1 /* $OpenBSD: x86emu.c,v 1.4 2009/06/18 14:19:21 pirofti Exp $ */ 2 /* $NetBSD: x86emu.c,v 1.7 2009/02/03 19:26:29 joerg Exp $ */ 3 4 /* 5 * 6 * Realmode X86 Emulator Library 7 * 8 * Copyright (C) 1996-1999 SciTech Software, Inc. 9 * Copyright (C) David Mosberger-Tang 10 * Copyright (C) 1999 Egbert Eich 11 * Copyright (C) 2007 Joerg Sonnenberger 12 * 13 * ======================================================================== 14 * 15 * Permission to use, copy, modify, distribute, and sell this software and 16 * its documentation for any purpose is hereby granted without fee, 17 * provided that the above copyright notice appear in all copies and that 18 * both that copyright notice and this permission notice appear in 19 * supporting documentation, and that the name of the authors not be used 20 * in advertising or publicity pertaining to distribution of the software 21 * without specific, written prior permission. The authors makes no 22 * representations about the suitability of this software for any purpose. 23 * It is provided "as is" without express or implied warranty. 24 * 25 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 26 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 27 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 28 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 29 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 30 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 31 * PERFORMANCE OF THIS SOFTWARE. 32 * 33 */ 34 35 #include <sys/cdefs.h> 36 __FBSDID("$FreeBSD$"); 37 38 #include <contrib/x86emu/x86emu.h> 39 #include <contrib/x86emu/x86emu_regs.h> 40 41 static void x86emu_intr_raise (struct x86emu *, uint8_t type); 42 43 static void x86emu_exec_one_byte(struct x86emu *); 44 static void x86emu_exec_two_byte(struct x86emu *); 45 46 static void fetch_decode_modrm (struct x86emu *); 47 static uint8_t fetch_byte_imm (struct x86emu *); 48 static uint16_t fetch_word_imm (struct x86emu *); 49 static uint32_t fetch_long_imm (struct x86emu *); 50 static uint8_t fetch_data_byte (struct x86emu *, uint32_t offset); 51 static uint8_t fetch_byte (struct x86emu *, u_int segment, uint32_t offset); 52 static uint16_t fetch_data_word (struct x86emu *, uint32_t offset); 53 static uint16_t fetch_word (struct x86emu *, uint32_t segment, uint32_t offset); 54 static uint32_t fetch_data_long (struct x86emu *, uint32_t offset); 55 static uint32_t fetch_long (struct x86emu *, uint32_t segment, uint32_t offset); 56 static void store_data_byte (struct x86emu *, uint32_t offset, uint8_t val); 57 static void store_byte (struct x86emu *, uint32_t segment, uint32_t offset, uint8_t val); 58 static void store_data_word (struct x86emu *, uint32_t offset, uint16_t val); 59 static void store_word (struct x86emu *, uint32_t segment, uint32_t offset, uint16_t val); 60 static void store_data_long (struct x86emu *, uint32_t offset, uint32_t val); 61 static void store_long (struct x86emu *, uint32_t segment, uint32_t offset, uint32_t val); 62 static uint8_t* decode_rl_byte_register(struct x86emu *); 63 static uint16_t* decode_rl_word_register(struct x86emu *); 64 static uint32_t* decode_rl_long_register(struct x86emu *); 65 static uint8_t* decode_rh_byte_register(struct x86emu *); 66 static uint16_t* decode_rh_word_register(struct x86emu *); 67 static uint32_t* decode_rh_long_register(struct x86emu *); 68 static uint16_t* decode_rh_seg_register(struct x86emu *); 69 static uint32_t decode_rl_address(struct x86emu *); 70 71 static uint8_t decode_and_fetch_byte(struct x86emu *); 72 static uint16_t decode_and_fetch_word(struct x86emu *); 73 static uint32_t decode_and_fetch_long(struct x86emu *); 74 75 static uint8_t decode_and_fetch_byte_imm8(struct x86emu *, uint8_t *); 76 static uint16_t decode_and_fetch_word_imm8(struct x86emu *, uint8_t *); 77 static uint32_t decode_and_fetch_long_imm8(struct x86emu *, uint8_t *); 78 79 static uint16_t decode_and_fetch_word_disp(struct x86emu *, int16_t); 80 static uint32_t decode_and_fetch_long_disp(struct x86emu *, int16_t); 81 82 static void write_back_byte(struct x86emu *, uint8_t); 83 static void write_back_word(struct x86emu *, uint16_t); 84 static void write_back_long(struct x86emu *, uint32_t); 85 86 static uint16_t aaa_word (struct x86emu *, uint16_t d); 87 static uint16_t aas_word (struct x86emu *, uint16_t d); 88 static uint16_t aad_word (struct x86emu *, uint16_t d); 89 static uint16_t aam_word (struct x86emu *, uint8_t d); 90 static uint8_t adc_byte (struct x86emu *, uint8_t d, uint8_t s); 91 static uint16_t adc_word (struct x86emu *, uint16_t d, uint16_t s); 92 static uint32_t adc_long (struct x86emu *, uint32_t d, uint32_t s); 93 static uint8_t add_byte (struct x86emu *, uint8_t d, uint8_t s); 94 static uint16_t add_word (struct x86emu *, uint16_t d, uint16_t s); 95 static uint32_t add_long (struct x86emu *, uint32_t d, uint32_t s); 96 static uint8_t and_byte (struct x86emu *, uint8_t d, uint8_t s); 97 static uint16_t and_word (struct x86emu *, uint16_t d, uint16_t s); 98 static uint32_t and_long (struct x86emu *, uint32_t d, uint32_t s); 99 static uint8_t cmp_byte (struct x86emu *, uint8_t d, uint8_t s); 100 static uint16_t cmp_word (struct x86emu *, uint16_t d, uint16_t s); 101 static uint32_t cmp_long (struct x86emu *, uint32_t d, uint32_t s); 102 static void cmp_byte_no_return (struct x86emu *, uint8_t d, uint8_t s); 103 static void cmp_word_no_return (struct x86emu *, uint16_t d, uint16_t s); 104 static void cmp_long_no_return (struct x86emu *, uint32_t d, uint32_t s); 105 static uint8_t daa_byte (struct x86emu *, uint8_t d); 106 static uint8_t das_byte (struct x86emu *, uint8_t d); 107 static uint8_t dec_byte (struct x86emu *, uint8_t d); 108 static uint16_t dec_word (struct x86emu *, uint16_t d); 109 static uint32_t dec_long (struct x86emu *, uint32_t d); 110 static uint8_t inc_byte (struct x86emu *, uint8_t d); 111 static uint16_t inc_word (struct x86emu *, uint16_t d); 112 static uint32_t inc_long (struct x86emu *, uint32_t d); 113 static uint8_t or_byte (struct x86emu *, uint8_t d, uint8_t s); 114 static uint16_t or_word (struct x86emu *, uint16_t d, uint16_t s); 115 static uint32_t or_long (struct x86emu *, uint32_t d, uint32_t s); 116 static uint8_t neg_byte (struct x86emu *, uint8_t s); 117 static uint16_t neg_word (struct x86emu *, uint16_t s); 118 static uint32_t neg_long (struct x86emu *, uint32_t s); 119 static uint8_t rcl_byte (struct x86emu *, uint8_t d, uint8_t s); 120 static uint16_t rcl_word (struct x86emu *, uint16_t d, uint8_t s); 121 static uint32_t rcl_long (struct x86emu *, uint32_t d, uint8_t s); 122 static uint8_t rcr_byte (struct x86emu *, uint8_t d, uint8_t s); 123 static uint16_t rcr_word (struct x86emu *, uint16_t d, uint8_t s); 124 static uint32_t rcr_long (struct x86emu *, uint32_t d, uint8_t s); 125 static uint8_t rol_byte (struct x86emu *, uint8_t d, uint8_t s); 126 static uint16_t rol_word (struct x86emu *, uint16_t d, uint8_t s); 127 static uint32_t rol_long (struct x86emu *, uint32_t d, uint8_t s); 128 static uint8_t ror_byte (struct x86emu *, uint8_t d, uint8_t s); 129 static uint16_t ror_word (struct x86emu *, uint16_t d, uint8_t s); 130 static uint32_t ror_long (struct x86emu *, uint32_t d, uint8_t s); 131 static uint8_t shl_byte (struct x86emu *, uint8_t d, uint8_t s); 132 static uint16_t shl_word (struct x86emu *, uint16_t d, uint8_t s); 133 static uint32_t shl_long (struct x86emu *, uint32_t d, uint8_t s); 134 static uint8_t shr_byte (struct x86emu *, uint8_t d, uint8_t s); 135 static uint16_t shr_word (struct x86emu *, uint16_t d, uint8_t s); 136 static uint32_t shr_long (struct x86emu *, uint32_t d, uint8_t s); 137 static uint8_t sar_byte (struct x86emu *, uint8_t d, uint8_t s); 138 static uint16_t sar_word (struct x86emu *, uint16_t d, uint8_t s); 139 static uint32_t sar_long (struct x86emu *, uint32_t d, uint8_t s); 140 static uint16_t shld_word (struct x86emu *, uint16_t d, uint16_t fill, uint8_t s); 141 static uint32_t shld_long (struct x86emu *, uint32_t d, uint32_t fill, uint8_t s); 142 static uint16_t shrd_word (struct x86emu *, uint16_t d, uint16_t fill, uint8_t s); 143 static uint32_t shrd_long (struct x86emu *, uint32_t d, uint32_t fill, uint8_t s); 144 static uint8_t sbb_byte (struct x86emu *, uint8_t d, uint8_t s); 145 static uint16_t sbb_word (struct x86emu *, uint16_t d, uint16_t s); 146 static uint32_t sbb_long (struct x86emu *, uint32_t d, uint32_t s); 147 static uint8_t sub_byte (struct x86emu *, uint8_t d, uint8_t s); 148 static uint16_t sub_word (struct x86emu *, uint16_t d, uint16_t s); 149 static uint32_t sub_long (struct x86emu *, uint32_t d, uint32_t s); 150 static void test_byte (struct x86emu *, uint8_t d, uint8_t s); 151 static void test_word (struct x86emu *, uint16_t d, uint16_t s); 152 static void test_long (struct x86emu *, uint32_t d, uint32_t s); 153 static uint8_t xor_byte (struct x86emu *, uint8_t d, uint8_t s); 154 static uint16_t xor_word (struct x86emu *, uint16_t d, uint16_t s); 155 static uint32_t xor_long (struct x86emu *, uint32_t d, uint32_t s); 156 static void imul_byte (struct x86emu *, uint8_t s); 157 static void imul_word (struct x86emu *, uint16_t s); 158 static void imul_long (struct x86emu *, uint32_t s); 159 static void mul_byte (struct x86emu *, uint8_t s); 160 static void mul_word (struct x86emu *, uint16_t s); 161 static void mul_long (struct x86emu *, uint32_t s); 162 static void idiv_byte (struct x86emu *, uint8_t s); 163 static void idiv_word (struct x86emu *, uint16_t s); 164 static void idiv_long (struct x86emu *, uint32_t s); 165 static void div_byte (struct x86emu *, uint8_t s); 166 static void div_word (struct x86emu *, uint16_t s); 167 static void div_long (struct x86emu *, uint32_t s); 168 static void ins (struct x86emu *, int size); 169 static void outs (struct x86emu *, int size); 170 static void push_word (struct x86emu *, uint16_t w); 171 static void push_long (struct x86emu *, uint32_t w); 172 static uint16_t pop_word (struct x86emu *); 173 static uint32_t pop_long (struct x86emu *); 174 175 /* 176 * REMARKS: 177 * Handles any pending asychronous interrupts. 178 */ 179 static void 180 x86emu_intr_dispatch(struct x86emu *emu, uint8_t intno) 181 { 182 if (emu->_x86emu_intrTab[intno]) { 183 (*emu->_x86emu_intrTab[intno]) (emu, intno); 184 } else { 185 push_word(emu, (uint16_t) emu->x86.R_FLG); 186 CLEAR_FLAG(F_IF); 187 CLEAR_FLAG(F_TF); 188 push_word(emu, emu->x86.R_CS); 189 emu->x86.R_CS = fetch_word(emu, 0, intno * 4 + 2); 190 push_word(emu, emu->x86.R_IP); 191 emu->x86.R_IP = fetch_word(emu, 0, intno * 4); 192 } 193 } 194 195 static void 196 x86emu_intr_handle(struct x86emu *emu) 197 { 198 uint8_t intno; 199 200 if (emu->x86.intr & INTR_SYNCH) { 201 intno = emu->x86.intno; 202 emu->x86.intr = 0; 203 x86emu_intr_dispatch(emu, intno); 204 } 205 } 206 207 /* 208 * PARAMETERS: 209 * intrnum - Interrupt number to raise 210 * 211 * REMARKS: 212 * Raise the specified interrupt to be handled before the execution of the 213 * next instruction. 214 */ 215 void 216 x86emu_intr_raise(struct x86emu *emu, uint8_t intrnum) 217 { 218 emu->x86.intno = intrnum; 219 emu->x86.intr |= INTR_SYNCH; 220 } 221 222 /* 223 * REMARKS: 224 * Main execution loop for the emulator. We return from here when the system 225 * halts, which is normally caused by a stack fault when we return from the 226 * original real mode call. 227 */ 228 void 229 x86emu_exec(struct x86emu *emu) 230 { 231 emu->x86.intr = 0; 232 233 if (setjmp(emu->exec_state)) 234 return; 235 236 for (;;) { 237 if (emu->x86.intr) { 238 if (((emu->x86.intr & INTR_SYNCH) && (emu->x86.intno == 0 || emu->x86.intno == 2)) || 239 !ACCESS_FLAG(F_IF)) { 240 x86emu_intr_handle(emu); 241 } 242 } 243 if (emu->x86.R_CS == 0 && emu->x86.R_IP == 0) 244 return; 245 x86emu_exec_one_byte(emu); 246 ++emu->cur_cycles; 247 } 248 } 249 250 void 251 x86emu_exec_call(struct x86emu *emu, uint16_t seg, uint16_t off) 252 { 253 push_word(emu, 0); 254 push_word(emu, 0); 255 emu->x86.R_CS = seg; 256 emu->x86.R_IP = off; 257 258 x86emu_exec(emu); 259 } 260 261 void 262 x86emu_exec_intr(struct x86emu *emu, uint8_t intr) 263 { 264 push_word(emu, emu->x86.R_FLG); 265 CLEAR_FLAG(F_IF); 266 CLEAR_FLAG(F_TF); 267 push_word(emu, 0); 268 push_word(emu, 0); 269 emu->x86.R_CS = (*emu->emu_rdw)(emu, intr * 4 + 2); 270 emu->x86.R_IP = (*emu->emu_rdw)(emu, intr * 4); 271 emu->x86.intr = 0; 272 273 x86emu_exec(emu); 274 } 275 276 /* 277 * REMARKS: 278 * Halts the system by setting the halted system flag. 279 */ 280 void 281 x86emu_halt_sys(struct x86emu *emu) 282 { 283 longjmp(emu->exec_state, 1); 284 } 285 286 /* 287 * PARAMETERS: 288 * mod - Mod value from decoded byte 289 * regh - Reg h value from decoded byte 290 * regl - Reg l value from decoded byte 291 * 292 * REMARKS: 293 * Raise the specified interrupt to be handled before the execution of the 294 * next instruction. 295 * 296 * NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline! 297 */ 298 static void 299 fetch_decode_modrm(struct x86emu *emu) 300 { 301 int fetched; 302 303 fetched = fetch_byte_imm(emu); 304 emu->cur_mod = (fetched >> 6) & 0x03; 305 emu->cur_rh = (fetched >> 3) & 0x07; 306 emu->cur_rl = (fetched >> 0) & 0x07; 307 } 308 309 /* 310 * RETURNS: 311 * Immediate byte value read from instruction queue 312 * 313 * REMARKS: 314 * This function returns the immediate byte from the instruction queue, and 315 * moves the instruction pointer to the next value. 316 * 317 * NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline! 318 */ 319 static uint8_t 320 fetch_byte_imm(struct x86emu *emu) 321 { 322 uint8_t fetched; 323 324 fetched = fetch_byte(emu, emu->x86.R_CS, emu->x86.R_IP); 325 emu->x86.R_IP++; 326 return fetched; 327 } 328 329 /* 330 * RETURNS: 331 * Immediate word value read from instruction queue 332 * 333 * REMARKS: 334 * This function returns the immediate byte from the instruction queue, and 335 * moves the instruction pointer to the next value. 336 * 337 * NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline! 338 */ 339 static uint16_t 340 fetch_word_imm(struct x86emu *emu) 341 { 342 uint16_t fetched; 343 344 fetched = fetch_word(emu, emu->x86.R_CS, emu->x86.R_IP); 345 emu->x86.R_IP += 2; 346 return fetched; 347 } 348 349 /* 350 * RETURNS: 351 * Immediate lone value read from instruction queue 352 * 353 * REMARKS: 354 * This function returns the immediate byte from the instruction queue, and 355 * moves the instruction pointer to the next value. 356 * 357 * NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline! 358 */ 359 static uint32_t 360 fetch_long_imm(struct x86emu *emu) 361 { 362 uint32_t fetched; 363 364 fetched = fetch_long(emu, emu->x86.R_CS, emu->x86.R_IP); 365 emu->x86.R_IP += 4; 366 return fetched; 367 } 368 369 /* 370 * RETURNS: 371 * Value of the default data segment 372 * 373 * REMARKS: 374 * Inline function that returns the default data segment for the current 375 * instruction. 376 * 377 * On the x86 processor, the default segment is not always DS if there is 378 * no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to 379 * addresses relative to SS (ie: on the stack). So, at the minimum, all 380 * decodings of addressing modes would have to set/clear a bit describing 381 * whether the access is relative to DS or SS. That is the function of the 382 * cpu-state-varible emu->x86.mode. There are several potential states: 383 * 384 * repe prefix seen (handled elsewhere) 385 * repne prefix seen (ditto) 386 * 387 * cs segment override 388 * ds segment override 389 * es segment override 390 * fs segment override 391 * gs segment override 392 * ss segment override 393 * 394 * ds/ss select (in absense of override) 395 * 396 * Each of the above 7 items are handled with a bit in the mode field. 397 */ 398 static uint32_t 399 get_data_segment(struct x86emu *emu) 400 { 401 switch (emu->x86.mode & SYSMODE_SEGMASK) { 402 case 0: /* default case: use ds register */ 403 case SYSMODE_SEGOVR_DS: 404 case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS: 405 return emu->x86.R_DS; 406 case SYSMODE_SEG_DS_SS:/* non-overridden, use ss register */ 407 return emu->x86.R_SS; 408 case SYSMODE_SEGOVR_CS: 409 case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS: 410 return emu->x86.R_CS; 411 case SYSMODE_SEGOVR_ES: 412 case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS: 413 return emu->x86.R_ES; 414 case SYSMODE_SEGOVR_FS: 415 case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS: 416 return emu->x86.R_FS; 417 case SYSMODE_SEGOVR_GS: 418 case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS: 419 return emu->x86.R_GS; 420 case SYSMODE_SEGOVR_SS: 421 case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS: 422 return emu->x86.R_SS; 423 } 424 x86emu_halt_sys(emu); 425 } 426 427 /* 428 * PARAMETERS: 429 * offset - Offset to load data from 430 * 431 * RETURNS: 432 * Byte value read from the absolute memory location. 433 * 434 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 435 */ 436 static uint8_t 437 fetch_data_byte(struct x86emu *emu, uint32_t offset) 438 { 439 return fetch_byte(emu, get_data_segment(emu), offset); 440 } 441 442 /* 443 * PARAMETERS: 444 * offset - Offset to load data from 445 * 446 * RETURNS: 447 * Word value read from the absolute memory location. 448 * 449 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 450 */ 451 static uint16_t 452 fetch_data_word(struct x86emu *emu, uint32_t offset) 453 { 454 return fetch_word(emu, get_data_segment(emu), offset); 455 } 456 457 /* 458 * PARAMETERS: 459 * offset - Offset to load data from 460 * 461 * RETURNS: 462 * Long value read from the absolute memory location. 463 * 464 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 465 */ 466 static uint32_t 467 fetch_data_long(struct x86emu *emu, uint32_t offset) 468 { 469 return fetch_long(emu, get_data_segment(emu), offset); 470 } 471 472 /* 473 * PARAMETERS: 474 * segment - Segment to load data from 475 * offset - Offset to load data from 476 * 477 * RETURNS: 478 * Byte value read from the absolute memory location. 479 * 480 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 481 */ 482 static uint8_t 483 fetch_byte(struct x86emu *emu, uint32_t segment, uint32_t offset) 484 { 485 return (*emu->emu_rdb) (emu, ((uint32_t) segment << 4) + offset); 486 } 487 488 /* 489 * PARAMETERS: 490 * segment - Segment to load data from 491 * offset - Offset to load data from 492 * 493 * RETURNS: 494 * Word value read from the absolute memory location. 495 * 496 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 497 */ 498 static uint16_t 499 fetch_word(struct x86emu *emu, uint32_t segment, uint32_t offset) 500 { 501 return (*emu->emu_rdw) (emu, ((uint32_t) segment << 4) + offset); 502 } 503 504 /* 505 * PARAMETERS: 506 * segment - Segment to load data from 507 * offset - Offset to load data from 508 * 509 * RETURNS: 510 * Long value read from the absolute memory location. 511 * 512 * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 513 */ 514 static uint32_t 515 fetch_long(struct x86emu *emu, uint32_t segment, uint32_t offset) 516 { 517 return (*emu->emu_rdl) (emu, ((uint32_t) segment << 4) + offset); 518 } 519 520 /* 521 * PARAMETERS: 522 * offset - Offset to store data at 523 * val - Value to store 524 * 525 * REMARKS: 526 * Writes a word value to an segmented memory location. The segment used is 527 * the current 'default' segment, which may have been overridden. 528 * 529 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 530 */ 531 static void 532 store_data_byte(struct x86emu *emu, uint32_t offset, uint8_t val) 533 { 534 store_byte(emu, get_data_segment(emu), offset, val); 535 } 536 537 /* 538 * PARAMETERS: 539 * offset - Offset to store data at 540 * val - Value to store 541 * 542 * REMARKS: 543 * Writes a word value to an segmented memory location. The segment used is 544 * the current 'default' segment, which may have been overridden. 545 * 546 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 547 */ 548 static void 549 store_data_word(struct x86emu *emu, uint32_t offset, uint16_t val) 550 { 551 store_word(emu, get_data_segment(emu), offset, val); 552 } 553 554 /* 555 * PARAMETERS: 556 * offset - Offset to store data at 557 * val - Value to store 558 * 559 * REMARKS: 560 * Writes a long value to an segmented memory location. The segment used is 561 * the current 'default' segment, which may have been overridden. 562 * 563 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 564 */ 565 static void 566 store_data_long(struct x86emu *emu, uint32_t offset, uint32_t val) 567 { 568 store_long(emu, get_data_segment(emu), offset, val); 569 } 570 571 /* 572 * PARAMETERS: 573 * segment - Segment to store data at 574 * offset - Offset to store data at 575 * val - Value to store 576 * 577 * REMARKS: 578 * Writes a byte value to an absolute memory location. 579 * 580 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 581 */ 582 static void 583 store_byte(struct x86emu *emu, uint32_t segment, uint32_t offset, uint8_t val) 584 { 585 (*emu->emu_wrb) (emu, ((uint32_t) segment << 4) + offset, val); 586 } 587 588 /* 589 * PARAMETERS: 590 * segment - Segment to store data at 591 * offset - Offset to store data at 592 * val - Value to store 593 * 594 * REMARKS: 595 * Writes a word value to an absolute memory location. 596 * 597 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 598 */ 599 static void 600 store_word(struct x86emu *emu, uint32_t segment, uint32_t offset, uint16_t val) 601 { 602 (*emu->emu_wrw) (emu, ((uint32_t) segment << 4) + offset, val); 603 } 604 605 /* 606 * PARAMETERS: 607 * segment - Segment to store data at 608 * offset - Offset to store data at 609 * val - Value to store 610 * 611 * REMARKS: 612 * Writes a long value to an absolute memory location. 613 * 614 * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 615 */ 616 static void 617 store_long(struct x86emu *emu, uint32_t segment, uint32_t offset, uint32_t val) 618 { 619 (*emu->emu_wrl) (emu, ((uint32_t) segment << 4) + offset, val); 620 } 621 622 /* 623 * PARAMETERS: 624 * reg - Register to decode 625 * 626 * RETURNS: 627 * Pointer to the appropriate register 628 * 629 * REMARKS: 630 * Return a pointer to the register given by the R/RM field of the 631 * modrm byte, for byte operands. Also enables the decoding of instructions. 632 */ 633 static uint8_t * 634 decode_rm_byte_register(struct x86emu *emu, int reg) 635 { 636 switch (reg) { 637 case 0: 638 return &emu->x86.R_AL; 639 case 1: 640 return &emu->x86.R_CL; 641 case 2: 642 return &emu->x86.R_DL; 643 case 3: 644 return &emu->x86.R_BL; 645 case 4: 646 return &emu->x86.R_AH; 647 case 5: 648 return &emu->x86.R_CH; 649 case 6: 650 return &emu->x86.R_DH; 651 case 7: 652 return &emu->x86.R_BH; 653 default: 654 x86emu_halt_sys(emu); 655 } 656 } 657 658 static uint8_t * 659 decode_rl_byte_register(struct x86emu *emu) 660 { 661 return decode_rm_byte_register(emu, emu->cur_rl); 662 } 663 664 static uint8_t * 665 decode_rh_byte_register(struct x86emu *emu) 666 { 667 return decode_rm_byte_register(emu, emu->cur_rh); 668 } 669 670 /* 671 * PARAMETERS: 672 * reg - Register to decode 673 * 674 * RETURNS: 675 * Pointer to the appropriate register 676 * 677 * REMARKS: 678 * Return a pointer to the register given by the R/RM field of the 679 * modrm byte, for word operands. Also enables the decoding of instructions. 680 */ 681 static uint16_t * 682 decode_rm_word_register(struct x86emu *emu, int reg) 683 { 684 switch (reg) { 685 case 0: 686 return &emu->x86.R_AX; 687 case 1: 688 return &emu->x86.R_CX; 689 case 2: 690 return &emu->x86.R_DX; 691 case 3: 692 return &emu->x86.R_BX; 693 case 4: 694 return &emu->x86.R_SP; 695 case 5: 696 return &emu->x86.R_BP; 697 case 6: 698 return &emu->x86.R_SI; 699 case 7: 700 return &emu->x86.R_DI; 701 default: 702 x86emu_halt_sys(emu); 703 } 704 } 705 706 static uint16_t * 707 decode_rl_word_register(struct x86emu *emu) 708 { 709 return decode_rm_word_register(emu, emu->cur_rl); 710 } 711 712 static uint16_t * 713 decode_rh_word_register(struct x86emu *emu) 714 { 715 return decode_rm_word_register(emu, emu->cur_rh); 716 } 717 718 /* 719 * PARAMETERS: 720 * reg - Register to decode 721 * 722 * RETURNS: 723 * Pointer to the appropriate register 724 * 725 * REMARKS: 726 * Return a pointer to the register given by the R/RM field of the 727 * modrm byte, for dword operands. Also enables the decoding of instructions. 728 */ 729 static uint32_t * 730 decode_rm_long_register(struct x86emu *emu, int reg) 731 { 732 switch (reg) { 733 case 0: 734 return &emu->x86.R_EAX; 735 case 1: 736 return &emu->x86.R_ECX; 737 case 2: 738 return &emu->x86.R_EDX; 739 case 3: 740 return &emu->x86.R_EBX; 741 case 4: 742 return &emu->x86.R_ESP; 743 case 5: 744 return &emu->x86.R_EBP; 745 case 6: 746 return &emu->x86.R_ESI; 747 case 7: 748 return &emu->x86.R_EDI; 749 default: 750 x86emu_halt_sys(emu); 751 } 752 } 753 754 static uint32_t * 755 decode_rl_long_register(struct x86emu *emu) 756 { 757 return decode_rm_long_register(emu, emu->cur_rl); 758 } 759 760 static uint32_t * 761 decode_rh_long_register(struct x86emu *emu) 762 { 763 return decode_rm_long_register(emu, emu->cur_rh); 764 } 765 766 767 /* 768 * PARAMETERS: 769 * reg - Register to decode 770 * 771 * RETURNS: 772 * Pointer to the appropriate register 773 * 774 * REMARKS: 775 * Return a pointer to the register given by the R/RM field of the 776 * modrm byte, for word operands, modified from above for the weirdo 777 * special case of segreg operands. Also enables the decoding of instructions. 778 */ 779 static uint16_t * 780 decode_rh_seg_register(struct x86emu *emu) 781 { 782 switch (emu->cur_rh) { 783 case 0: 784 return &emu->x86.R_ES; 785 case 1: 786 return &emu->x86.R_CS; 787 case 2: 788 return &emu->x86.R_SS; 789 case 3: 790 return &emu->x86.R_DS; 791 case 4: 792 return &emu->x86.R_FS; 793 case 5: 794 return &emu->x86.R_GS; 795 default: 796 x86emu_halt_sys(emu); 797 } 798 } 799 /* 800 * 801 * return offset from the SIB Byte 802 */ 803 static uint32_t 804 decode_sib_address(struct x86emu *emu, int sib, int mod) 805 { 806 uint32_t base = 0, i = 0, scale = 1; 807 808 switch (sib & 0x07) { 809 case 0: 810 base = emu->x86.R_EAX; 811 break; 812 case 1: 813 base = emu->x86.R_ECX; 814 815 break; 816 case 2: 817 base = emu->x86.R_EDX; 818 break; 819 case 3: 820 base = emu->x86.R_EBX; 821 break; 822 case 4: 823 base = emu->x86.R_ESP; 824 emu->x86.mode |= SYSMODE_SEG_DS_SS; 825 break; 826 case 5: 827 if (mod == 0) { 828 base = fetch_long_imm(emu); 829 } else { 830 base = emu->x86.R_EBP; 831 emu->x86.mode |= SYSMODE_SEG_DS_SS; 832 } 833 break; 834 case 6: 835 base = emu->x86.R_ESI; 836 break; 837 case 7: 838 base = emu->x86.R_EDI; 839 break; 840 } 841 switch ((sib >> 3) & 0x07) { 842 case 0: 843 i = emu->x86.R_EAX; 844 break; 845 case 1: 846 i = emu->x86.R_ECX; 847 break; 848 case 2: 849 i = emu->x86.R_EDX; 850 break; 851 case 3: 852 i = emu->x86.R_EBX; 853 break; 854 case 4: 855 i = 0; 856 break; 857 case 5: 858 i = emu->x86.R_EBP; 859 break; 860 case 6: 861 i = emu->x86.R_ESI; 862 break; 863 case 7: 864 i = emu->x86.R_EDI; 865 break; 866 } 867 scale = 1 << ((sib >> 6) & 0x03); 868 return base + (i * scale); 869 } 870 871 /* 872 * PARAMETERS: 873 * rm - RM value to decode 874 * 875 * RETURNS: 876 * Offset in memory for the address decoding 877 * 878 * REMARKS: 879 * Return the offset given by mod=00, mod=01 or mod=10 addressing. 880 * Also enables the decoding of instructions. 881 */ 882 static uint32_t 883 decode_rl_address(struct x86emu *emu) 884 { 885 if (emu->x86.mode & SYSMODE_PREFIX_ADDR) { 886 uint32_t offset, sib; 887 /* 32-bit addressing */ 888 switch (emu->cur_rl) { 889 case 0: 890 offset = emu->x86.R_EAX; 891 break; 892 case 1: 893 offset = emu->x86.R_ECX; 894 break; 895 case 2: 896 offset = emu->x86.R_EDX; 897 break; 898 case 3: 899 offset = emu->x86.R_EBX; 900 break; 901 case 4: 902 sib = fetch_byte_imm(emu); 903 offset = decode_sib_address(emu, sib, 0); 904 break; 905 case 5: 906 if (emu->cur_mod == 0) { 907 offset = fetch_long_imm(emu); 908 } else { 909 emu->x86.mode |= SYSMODE_SEG_DS_SS; 910 offset = emu->x86.R_EBP; 911 } 912 break; 913 case 6: 914 offset = emu->x86.R_ESI; 915 break; 916 case 7: 917 offset = emu->x86.R_EDI; 918 break; 919 default: 920 x86emu_halt_sys(emu); 921 } 922 if (emu->cur_mod == 1) 923 offset += (int8_t)fetch_byte_imm(emu); 924 else if (emu->cur_mod == 2) 925 offset += fetch_long_imm(emu); 926 return offset; 927 } else { 928 uint16_t offset; 929 930 /* 16-bit addressing */ 931 switch (emu->cur_rl) { 932 case 0: 933 offset = emu->x86.R_BX + emu->x86.R_SI; 934 break; 935 case 1: 936 offset = emu->x86.R_BX + emu->x86.R_DI; 937 break; 938 case 2: 939 emu->x86.mode |= SYSMODE_SEG_DS_SS; 940 offset = emu->x86.R_BP + emu->x86.R_SI; 941 break; 942 case 3: 943 emu->x86.mode |= SYSMODE_SEG_DS_SS; 944 offset = emu->x86.R_BP + emu->x86.R_DI; 945 break; 946 case 4: 947 offset = emu->x86.R_SI; 948 break; 949 case 5: 950 offset = emu->x86.R_DI; 951 break; 952 case 6: 953 if (emu->cur_mod == 0) { 954 offset = fetch_word_imm(emu); 955 } else { 956 emu->x86.mode |= SYSMODE_SEG_DS_SS; 957 offset = emu->x86.R_BP; 958 } 959 break; 960 case 7: 961 offset = emu->x86.R_BX; 962 break; 963 default: 964 x86emu_halt_sys(emu); 965 } 966 if (emu->cur_mod == 1) 967 offset += (int8_t)fetch_byte_imm(emu); 968 else if (emu->cur_mod == 2) 969 offset += fetch_word_imm(emu); 970 return offset; 971 } 972 } 973 974 static uint8_t 975 decode_and_fetch_byte(struct x86emu *emu) 976 { 977 if (emu->cur_mod != 3) { 978 emu->cur_offset = decode_rl_address(emu); 979 return fetch_data_byte(emu, emu->cur_offset); 980 } else { 981 return *decode_rl_byte_register(emu); 982 } 983 } 984 985 static uint16_t 986 decode_and_fetch_word_disp(struct x86emu *emu, int16_t disp) 987 { 988 if (emu->cur_mod != 3) { 989 /* TODO: A20 gate emulation */ 990 emu->cur_offset = decode_rl_address(emu) + disp; 991 if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0) 992 emu->cur_offset &= 0xffff; 993 return fetch_data_word(emu, emu->cur_offset); 994 } else { 995 return *decode_rl_word_register(emu); 996 } 997 } 998 999 static uint32_t 1000 decode_and_fetch_long_disp(struct x86emu *emu, int16_t disp) 1001 { 1002 if (emu->cur_mod != 3) { 1003 /* TODO: A20 gate emulation */ 1004 emu->cur_offset = decode_rl_address(emu) + disp; 1005 if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0) 1006 emu->cur_offset &= 0xffff; 1007 return fetch_data_long(emu, emu->cur_offset); 1008 } else { 1009 return *decode_rl_long_register(emu); 1010 } 1011 } 1012 1013 uint16_t 1014 decode_and_fetch_word(struct x86emu *emu) 1015 { 1016 return decode_and_fetch_word_disp(emu, 0); 1017 } 1018 1019 uint32_t 1020 decode_and_fetch_long(struct x86emu *emu) 1021 { 1022 return decode_and_fetch_long_disp(emu, 0); 1023 } 1024 1025 uint8_t 1026 decode_and_fetch_byte_imm8(struct x86emu *emu, uint8_t *imm) 1027 { 1028 if (emu->cur_mod != 3) { 1029 emu->cur_offset = decode_rl_address(emu); 1030 *imm = fetch_byte_imm(emu); 1031 return fetch_data_byte(emu, emu->cur_offset); 1032 } else { 1033 *imm = fetch_byte_imm(emu); 1034 return *decode_rl_byte_register(emu); 1035 } 1036 } 1037 1038 static uint16_t 1039 decode_and_fetch_word_imm8(struct x86emu *emu, uint8_t *imm) 1040 { 1041 if (emu->cur_mod != 3) { 1042 emu->cur_offset = decode_rl_address(emu); 1043 *imm = fetch_byte_imm(emu); 1044 return fetch_data_word(emu, emu->cur_offset); 1045 } else { 1046 *imm = fetch_byte_imm(emu); 1047 return *decode_rl_word_register(emu); 1048 } 1049 } 1050 1051 static uint32_t 1052 decode_and_fetch_long_imm8(struct x86emu *emu, uint8_t *imm) 1053 { 1054 if (emu->cur_mod != 3) { 1055 emu->cur_offset = decode_rl_address(emu); 1056 *imm = fetch_byte_imm(emu); 1057 return fetch_data_long(emu, emu->cur_offset); 1058 } else { 1059 *imm = fetch_byte_imm(emu); 1060 return *decode_rl_long_register(emu); 1061 } 1062 } 1063 1064 static void 1065 write_back_byte(struct x86emu *emu, uint8_t val) 1066 { 1067 if (emu->cur_mod != 3) 1068 store_data_byte(emu, emu->cur_offset, val); 1069 else 1070 *decode_rl_byte_register(emu) = val; 1071 } 1072 1073 static void 1074 write_back_word(struct x86emu *emu, uint16_t val) 1075 { 1076 if (emu->cur_mod != 3) 1077 store_data_word(emu, emu->cur_offset, val); 1078 else 1079 *decode_rl_word_register(emu) = val; 1080 } 1081 1082 static void 1083 write_back_long(struct x86emu *emu, uint32_t val) 1084 { 1085 if (emu->cur_mod != 3) 1086 store_data_long(emu, emu->cur_offset, val); 1087 else 1088 *decode_rl_long_register(emu) = val; 1089 } 1090 1091 static void 1092 common_inc_word_long(struct x86emu *emu, union x86emu_register *reg) 1093 { 1094 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1095 reg->I32_reg.e_reg = inc_long(emu, reg->I32_reg.e_reg); 1096 else 1097 reg->I16_reg.x_reg = inc_word(emu, reg->I16_reg.x_reg); 1098 } 1099 1100 static void 1101 common_dec_word_long(struct x86emu *emu, union x86emu_register *reg) 1102 { 1103 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1104 reg->I32_reg.e_reg = dec_long(emu, reg->I32_reg.e_reg); 1105 else 1106 reg->I16_reg.x_reg = dec_word(emu, reg->I16_reg.x_reg); 1107 } 1108 1109 static void 1110 common_binop_byte_rm_r(struct x86emu *emu, uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t)) 1111 { 1112 uint32_t destoffset; 1113 uint8_t *destreg, srcval; 1114 uint8_t destval; 1115 1116 fetch_decode_modrm(emu); 1117 srcval = *decode_rh_byte_register(emu); 1118 if (emu->cur_mod != 3) { 1119 destoffset = decode_rl_address(emu); 1120 destval = fetch_data_byte(emu, destoffset); 1121 destval = (*binop)(emu, destval, srcval); 1122 store_data_byte(emu, destoffset, destval); 1123 } else { 1124 destreg = decode_rl_byte_register(emu); 1125 *destreg = (*binop)(emu, *destreg, srcval); 1126 } 1127 } 1128 1129 static void 1130 common_binop_ns_byte_rm_r(struct x86emu *emu, void (*binop)(struct x86emu *, uint8_t, uint8_t)) 1131 { 1132 uint32_t destoffset; 1133 uint8_t destval, srcval; 1134 1135 fetch_decode_modrm(emu); 1136 srcval = *decode_rh_byte_register(emu); 1137 if (emu->cur_mod != 3) { 1138 destoffset = decode_rl_address(emu); 1139 destval = fetch_data_byte(emu, destoffset); 1140 } else { 1141 destval = *decode_rl_byte_register(emu); 1142 } 1143 (*binop)(emu, destval, srcval); 1144 } 1145 1146 static void 1147 common_binop_word_rm_r(struct x86emu *emu, uint16_t (*binop)(struct x86emu *, uint16_t, uint16_t)) 1148 { 1149 uint32_t destoffset; 1150 uint16_t destval, *destreg, srcval; 1151 1152 fetch_decode_modrm(emu); 1153 srcval = *decode_rh_word_register(emu); 1154 if (emu->cur_mod != 3) { 1155 destoffset = decode_rl_address(emu); 1156 destval = fetch_data_word(emu, destoffset); 1157 destval = (*binop)(emu, destval, srcval); 1158 store_data_word(emu, destoffset, destval); 1159 } else { 1160 destreg = decode_rl_word_register(emu); 1161 *destreg = (*binop)(emu, *destreg, srcval); 1162 } 1163 } 1164 1165 static void 1166 common_binop_byte_r_rm(struct x86emu *emu, uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t)) 1167 { 1168 uint8_t *destreg, srcval; 1169 uint32_t srcoffset; 1170 1171 fetch_decode_modrm(emu); 1172 destreg = decode_rh_byte_register(emu); 1173 if (emu->cur_mod != 3) { 1174 srcoffset = decode_rl_address(emu); 1175 srcval = fetch_data_byte(emu, srcoffset); 1176 } else { 1177 srcval = *decode_rl_byte_register(emu); 1178 } 1179 *destreg = (*binop)(emu, *destreg, srcval); 1180 } 1181 1182 static void 1183 common_binop_long_rm_r(struct x86emu *emu, uint32_t (*binop)(struct x86emu *, uint32_t, uint32_t)) 1184 { 1185 uint32_t destoffset; 1186 uint32_t destval, *destreg, srcval; 1187 1188 fetch_decode_modrm(emu); 1189 srcval = *decode_rh_long_register(emu); 1190 if (emu->cur_mod != 3) { 1191 destoffset = decode_rl_address(emu); 1192 destval = fetch_data_long(emu, destoffset); 1193 destval = (*binop)(emu, destval, srcval); 1194 store_data_long(emu, destoffset, destval); 1195 } else { 1196 destreg = decode_rl_long_register(emu); 1197 *destreg = (*binop)(emu, *destreg, srcval); 1198 } 1199 } 1200 1201 static void 1202 common_binop_word_long_rm_r(struct x86emu *emu, 1203 uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t), uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t)) 1204 { 1205 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1206 common_binop_long_rm_r(emu, binop32); 1207 else 1208 common_binop_word_rm_r(emu, binop16); 1209 } 1210 1211 static void 1212 common_binop_ns_word_rm_r(struct x86emu *emu, void (*binop)(struct x86emu *, uint16_t, uint16_t)) 1213 { 1214 uint32_t destoffset; 1215 uint16_t destval, srcval; 1216 1217 fetch_decode_modrm(emu); 1218 srcval = *decode_rh_word_register(emu); 1219 if (emu->cur_mod != 3) { 1220 destoffset = decode_rl_address(emu); 1221 destval = fetch_data_word(emu, destoffset); 1222 } else { 1223 destval = *decode_rl_word_register(emu); 1224 } 1225 (*binop)(emu, destval, srcval); 1226 } 1227 1228 1229 static void 1230 common_binop_ns_long_rm_r(struct x86emu *emu, void (*binop)(struct x86emu *, uint32_t, uint32_t)) 1231 { 1232 uint32_t destoffset; 1233 uint32_t destval, srcval; 1234 1235 fetch_decode_modrm(emu); 1236 srcval = *decode_rh_long_register(emu); 1237 if (emu->cur_mod != 3) { 1238 destoffset = decode_rl_address(emu); 1239 destval = fetch_data_long(emu, destoffset); 1240 } else { 1241 destval = *decode_rl_long_register(emu); 1242 } 1243 (*binop)(emu, destval, srcval); 1244 } 1245 1246 static void 1247 common_binop_ns_word_long_rm_r(struct x86emu *emu, 1248 void (*binop16)(struct x86emu *, uint16_t, uint16_t), void (*binop32)(struct x86emu *, uint32_t, uint32_t)) 1249 { 1250 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1251 common_binop_ns_long_rm_r(emu, binop32); 1252 else 1253 common_binop_ns_word_rm_r(emu, binop16); 1254 } 1255 1256 static void 1257 common_binop_long_r_rm(struct x86emu *emu, uint32_t (*binop)(struct x86emu *, uint32_t, uint32_t)) 1258 { 1259 uint32_t srcoffset; 1260 uint32_t *destreg, srcval; 1261 1262 fetch_decode_modrm(emu); 1263 destreg = decode_rh_long_register(emu); 1264 if (emu->cur_mod != 3) { 1265 srcoffset = decode_rl_address(emu); 1266 srcval = fetch_data_long(emu, srcoffset); 1267 } else { 1268 srcval = *decode_rl_long_register(emu); 1269 } 1270 *destreg = (*binop)(emu, *destreg, srcval); 1271 } 1272 1273 static void 1274 common_binop_word_r_rm(struct x86emu *emu, uint16_t (*binop)(struct x86emu *, uint16_t, uint16_t)) 1275 { 1276 uint32_t srcoffset; 1277 uint16_t *destreg, srcval; 1278 1279 fetch_decode_modrm(emu); 1280 destreg = decode_rh_word_register(emu); 1281 if (emu->cur_mod != 3) { 1282 srcoffset = decode_rl_address(emu); 1283 srcval = fetch_data_word(emu, srcoffset); 1284 } else { 1285 srcval = *decode_rl_word_register(emu); 1286 } 1287 *destreg = (*binop)(emu, *destreg, srcval); 1288 } 1289 1290 static void 1291 common_binop_word_long_r_rm(struct x86emu *emu, 1292 uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t), uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t)) 1293 { 1294 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1295 common_binop_long_r_rm(emu, binop32); 1296 else 1297 common_binop_word_r_rm(emu, binop16); 1298 } 1299 1300 static void 1301 common_binop_byte_imm(struct x86emu *emu, uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t)) 1302 { 1303 uint8_t srcval; 1304 1305 srcval = fetch_byte_imm(emu); 1306 emu->x86.R_AL = (*binop)(emu, emu->x86.R_AL, srcval); 1307 } 1308 1309 static void 1310 common_binop_word_long_imm(struct x86emu *emu, 1311 uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t), uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t)) 1312 { 1313 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1314 uint32_t srcval; 1315 1316 srcval = fetch_long_imm(emu); 1317 emu->x86.R_EAX = (*binop32)(emu, emu->x86.R_EAX, srcval); 1318 } else { 1319 uint16_t srcval; 1320 1321 srcval = fetch_word_imm(emu); 1322 emu->x86.R_AX = (*binop16)(emu, emu->x86.R_AX, srcval); 1323 } 1324 } 1325 1326 static void 1327 common_push_word_long(struct x86emu *emu, union x86emu_register *reg) 1328 { 1329 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1330 push_long(emu, reg->I32_reg.e_reg); 1331 else 1332 push_word(emu, reg->I16_reg.x_reg); 1333 } 1334 1335 static void 1336 common_pop_word_long(struct x86emu *emu, union x86emu_register *reg) 1337 { 1338 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1339 reg->I32_reg.e_reg = pop_long(emu); 1340 else 1341 reg->I16_reg.x_reg = pop_word(emu); 1342 } 1343 1344 static void 1345 common_imul_long_IMM(struct x86emu *emu, int byte_imm) 1346 { 1347 uint32_t srcoffset; 1348 uint32_t *destreg, srcval; 1349 int32_t imm; 1350 uint64_t res; 1351 1352 fetch_decode_modrm(emu); 1353 destreg = decode_rh_long_register(emu); 1354 if (emu->cur_mod != 3) { 1355 srcoffset = decode_rl_address(emu); 1356 srcval = fetch_data_long(emu, srcoffset); 1357 } else { 1358 srcval = *decode_rl_long_register(emu); 1359 } 1360 1361 if (byte_imm) 1362 imm = (int8_t)fetch_byte_imm(emu); 1363 else 1364 imm = fetch_long_imm(emu); 1365 res = (int32_t)srcval * imm; 1366 1367 if (res > 0xffffffff) { 1368 SET_FLAG(F_CF); 1369 SET_FLAG(F_OF); 1370 } else { 1371 CLEAR_FLAG(F_CF); 1372 CLEAR_FLAG(F_OF); 1373 } 1374 *destreg = (uint32_t)res; 1375 } 1376 1377 static void 1378 common_imul_word_IMM(struct x86emu *emu, int byte_imm) 1379 { 1380 uint32_t srcoffset; 1381 uint16_t *destreg, srcval; 1382 int16_t imm; 1383 uint32_t res; 1384 1385 fetch_decode_modrm(emu); 1386 destreg = decode_rh_word_register(emu); 1387 if (emu->cur_mod != 3) { 1388 srcoffset = decode_rl_address(emu); 1389 srcval = fetch_data_word(emu, srcoffset); 1390 } else { 1391 srcval = *decode_rl_word_register(emu); 1392 } 1393 1394 if (byte_imm) 1395 imm = (int8_t)fetch_byte_imm(emu); 1396 else 1397 imm = fetch_word_imm(emu); 1398 res = (int16_t)srcval * imm; 1399 1400 if (res > 0xffff) { 1401 SET_FLAG(F_CF); 1402 SET_FLAG(F_OF); 1403 } else { 1404 CLEAR_FLAG(F_CF); 1405 CLEAR_FLAG(F_OF); 1406 } 1407 *destreg = (uint16_t) res; 1408 } 1409 1410 static void 1411 common_imul_imm(struct x86emu *emu, int byte_imm) 1412 { 1413 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1414 common_imul_long_IMM(emu, byte_imm); 1415 else 1416 common_imul_word_IMM(emu, byte_imm); 1417 } 1418 1419 static void 1420 common_jmp_near(struct x86emu *emu, int cond) 1421 { 1422 int8_t offset; 1423 uint16_t target; 1424 1425 offset = (int8_t) fetch_byte_imm(emu); 1426 target = (uint16_t) (emu->x86.R_IP + (int16_t) offset); 1427 if (cond) 1428 emu->x86.R_IP = target; 1429 } 1430 1431 static void 1432 common_load_far_pointer(struct x86emu *emu, uint16_t *seg) 1433 { 1434 uint16_t *dstreg; 1435 uint32_t srcoffset; 1436 1437 fetch_decode_modrm(emu); 1438 if (emu->cur_mod == 3) 1439 x86emu_halt_sys(emu); 1440 1441 dstreg = decode_rh_word_register(emu); 1442 srcoffset = decode_rl_address(emu); 1443 *dstreg = fetch_data_word(emu, srcoffset); 1444 *seg = fetch_data_word(emu, srcoffset + 2); 1445 } 1446 1447 /* Implementation */ 1448 1449 /* 1450 * REMARKS: 1451 * Handles opcode 0x3a 1452 */ 1453 static void 1454 x86emuOp_cmp_byte_R_RM(struct x86emu *emu) 1455 { 1456 uint8_t *destreg, srcval; 1457 1458 fetch_decode_modrm(emu); 1459 destreg = decode_rh_byte_register(emu); 1460 srcval = decode_and_fetch_byte(emu); 1461 cmp_byte(emu, *destreg, srcval); 1462 } 1463 1464 /* 1465 * REMARKS: 1466 * 1467 * Handles opcode 0x3b 1468 */ 1469 static void 1470 x86emuOp32_cmp_word_R_RM(struct x86emu *emu) 1471 { 1472 uint32_t srcval, *destreg; 1473 1474 fetch_decode_modrm(emu); 1475 destreg = decode_rh_long_register(emu); 1476 srcval = decode_and_fetch_long(emu); 1477 cmp_long(emu, *destreg, srcval); 1478 } 1479 1480 static void 1481 x86emuOp16_cmp_word_R_RM(struct x86emu *emu) 1482 { 1483 uint16_t srcval, *destreg; 1484 1485 fetch_decode_modrm(emu); 1486 destreg = decode_rh_word_register(emu); 1487 srcval = decode_and_fetch_word(emu); 1488 cmp_word(emu, *destreg, srcval); 1489 } 1490 1491 static void 1492 x86emuOp_cmp_word_R_RM(struct x86emu *emu) 1493 { 1494 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1495 x86emuOp32_cmp_word_R_RM(emu); 1496 else 1497 x86emuOp16_cmp_word_R_RM(emu); 1498 } 1499 1500 /* 1501 * REMARKS: 1502 * Handles opcode 0x3c 1503 */ 1504 static void 1505 x86emuOp_cmp_byte_AL_IMM(struct x86emu *emu) 1506 { 1507 uint8_t srcval; 1508 1509 srcval = fetch_byte_imm(emu); 1510 cmp_byte(emu, emu->x86.R_AL, srcval); 1511 } 1512 1513 /* 1514 * REMARKS: 1515 * Handles opcode 0x3d 1516 */ 1517 static void 1518 x86emuOp32_cmp_word_AX_IMM(struct x86emu *emu) 1519 { 1520 uint32_t srcval; 1521 1522 srcval = fetch_long_imm(emu); 1523 cmp_long(emu, emu->x86.R_EAX, srcval); 1524 } 1525 1526 static void 1527 x86emuOp16_cmp_word_AX_IMM(struct x86emu *emu) 1528 { 1529 uint16_t srcval; 1530 1531 srcval = fetch_word_imm(emu); 1532 cmp_word(emu, emu->x86.R_AX, srcval); 1533 } 1534 1535 static void 1536 x86emuOp_cmp_word_AX_IMM(struct x86emu *emu) 1537 { 1538 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1539 x86emuOp32_cmp_word_AX_IMM(emu); 1540 else 1541 x86emuOp16_cmp_word_AX_IMM(emu); 1542 } 1543 1544 /* 1545 * REMARKS: 1546 * Handles opcode 0x60 1547 */ 1548 static void 1549 x86emuOp_push_all(struct x86emu *emu) 1550 { 1551 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1552 uint32_t old_sp = emu->x86.R_ESP; 1553 1554 push_long(emu, emu->x86.R_EAX); 1555 push_long(emu, emu->x86.R_ECX); 1556 push_long(emu, emu->x86.R_EDX); 1557 push_long(emu, emu->x86.R_EBX); 1558 push_long(emu, old_sp); 1559 push_long(emu, emu->x86.R_EBP); 1560 push_long(emu, emu->x86.R_ESI); 1561 push_long(emu, emu->x86.R_EDI); 1562 } else { 1563 uint16_t old_sp = emu->x86.R_SP; 1564 1565 push_word(emu, emu->x86.R_AX); 1566 push_word(emu, emu->x86.R_CX); 1567 push_word(emu, emu->x86.R_DX); 1568 push_word(emu, emu->x86.R_BX); 1569 push_word(emu, old_sp); 1570 push_word(emu, emu->x86.R_BP); 1571 push_word(emu, emu->x86.R_SI); 1572 push_word(emu, emu->x86.R_DI); 1573 } 1574 } 1575 1576 /* 1577 * REMARKS: 1578 * Handles opcode 0x61 1579 */ 1580 static void 1581 x86emuOp_pop_all(struct x86emu *emu) 1582 { 1583 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1584 emu->x86.R_EDI = pop_long(emu); 1585 emu->x86.R_ESI = pop_long(emu); 1586 emu->x86.R_EBP = pop_long(emu); 1587 emu->x86.R_ESP += 4; /* skip ESP */ 1588 emu->x86.R_EBX = pop_long(emu); 1589 emu->x86.R_EDX = pop_long(emu); 1590 emu->x86.R_ECX = pop_long(emu); 1591 emu->x86.R_EAX = pop_long(emu); 1592 } else { 1593 emu->x86.R_DI = pop_word(emu); 1594 emu->x86.R_SI = pop_word(emu); 1595 emu->x86.R_BP = pop_word(emu); 1596 emu->x86.R_SP += 2;/* skip SP */ 1597 emu->x86.R_BX = pop_word(emu); 1598 emu->x86.R_DX = pop_word(emu); 1599 emu->x86.R_CX = pop_word(emu); 1600 emu->x86.R_AX = pop_word(emu); 1601 } 1602 } 1603 /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */ 1604 /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */ 1605 1606 1607 /* 1608 * REMARKS: 1609 * Handles opcode 0x68 1610 */ 1611 static void 1612 x86emuOp_push_word_IMM(struct x86emu *emu) 1613 { 1614 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1615 uint32_t imm; 1616 1617 imm = fetch_long_imm(emu); 1618 push_long(emu, imm); 1619 } else { 1620 uint16_t imm; 1621 1622 imm = fetch_word_imm(emu); 1623 push_word(emu, imm); 1624 } 1625 } 1626 1627 /* 1628 * REMARKS: 1629 * Handles opcode 0x6a 1630 */ 1631 static void 1632 x86emuOp_push_byte_IMM(struct x86emu *emu) 1633 { 1634 int16_t imm; 1635 1636 imm = (int8_t) fetch_byte_imm(emu); 1637 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1638 push_long(emu, (int32_t) imm); 1639 } else { 1640 push_word(emu, imm); 1641 } 1642 } 1643 1644 /* 1645 * REMARKS: 1646 * Handles opcode 0x6c and 0x6d 1647 */ 1648 static void 1649 x86emuOp_ins_word(struct x86emu *emu) 1650 { 1651 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1652 ins(emu, 4); 1653 } else { 1654 ins(emu, 2); 1655 } 1656 } 1657 1658 /* 1659 * REMARKS: 1660 * Handles opcode 0x6f 1661 */ 1662 static void 1663 x86emuOp_outs_word(struct x86emu *emu) 1664 { 1665 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1666 outs(emu, 4); 1667 } else { 1668 outs(emu, 2); 1669 } 1670 } 1671 1672 /* 1673 * REMARKS: 1674 * Handles opcode 0x7c 1675 */ 1676 static void 1677 x86emuOp_jump_near_L(struct x86emu *emu) 1678 { 1679 int sf, of; 1680 1681 sf = ACCESS_FLAG(F_SF) != 0; 1682 of = ACCESS_FLAG(F_OF) != 0; 1683 1684 common_jmp_near(emu, sf != of); 1685 } 1686 1687 /* 1688 * REMARKS: 1689 * Handles opcode 0x7d 1690 */ 1691 static void 1692 x86emuOp_jump_near_NL(struct x86emu *emu) 1693 { 1694 int sf, of; 1695 1696 sf = ACCESS_FLAG(F_SF) != 0; 1697 of = ACCESS_FLAG(F_OF) != 0; 1698 1699 common_jmp_near(emu, sf == of); 1700 } 1701 1702 /* 1703 * REMARKS: 1704 * Handles opcode 0x7e 1705 */ 1706 static void 1707 x86emuOp_jump_near_LE(struct x86emu *emu) 1708 { 1709 int sf, of; 1710 1711 sf = ACCESS_FLAG(F_SF) != 0; 1712 of = ACCESS_FLAG(F_OF) != 0; 1713 1714 common_jmp_near(emu, sf != of || ACCESS_FLAG(F_ZF)); 1715 } 1716 1717 /* 1718 * REMARKS: 1719 * Handles opcode 0x7f 1720 */ 1721 static void 1722 x86emuOp_jump_near_NLE(struct x86emu *emu) 1723 { 1724 int sf, of; 1725 1726 sf = ACCESS_FLAG(F_SF) != 0; 1727 of = ACCESS_FLAG(F_OF) != 0; 1728 1729 common_jmp_near(emu, sf == of && !ACCESS_FLAG(F_ZF)); 1730 } 1731 1732 static 1733 uint8_t(*const opc80_byte_operation[]) (struct x86emu *, uint8_t d, uint8_t s) = 1734 { 1735 add_byte, /* 00 */ 1736 or_byte, /* 01 */ 1737 adc_byte, /* 02 */ 1738 sbb_byte, /* 03 */ 1739 and_byte, /* 04 */ 1740 sub_byte, /* 05 */ 1741 xor_byte, /* 06 */ 1742 cmp_byte, /* 07 */ 1743 }; 1744 1745 /* 1746 * REMARKS: 1747 * Handles opcode 0x80 1748 */ 1749 static void 1750 x86emuOp_opc80_byte_RM_IMM(struct x86emu *emu) 1751 { 1752 uint8_t imm, destval; 1753 1754 /* 1755 * Weirdo special case instruction format. Part of the opcode 1756 * held below in "RH". Doubly nested case would result, except 1757 * that the decoded instruction 1758 */ 1759 fetch_decode_modrm(emu); 1760 destval = decode_and_fetch_byte(emu); 1761 imm = fetch_byte_imm(emu); 1762 destval = (*opc80_byte_operation[emu->cur_rh]) (emu, destval, imm); 1763 if (emu->cur_rh != 7) 1764 write_back_byte(emu, destval); 1765 } 1766 1767 static 1768 uint16_t(* const opc81_word_operation[]) (struct x86emu *, uint16_t d, uint16_t s) = 1769 { 1770 add_word, /* 00 */ 1771 or_word, /* 01 */ 1772 adc_word, /* 02 */ 1773 sbb_word, /* 03 */ 1774 and_word, /* 04 */ 1775 sub_word, /* 05 */ 1776 xor_word, /* 06 */ 1777 cmp_word, /* 07 */ 1778 }; 1779 1780 static 1781 uint32_t(* const opc81_long_operation[]) (struct x86emu *, uint32_t d, uint32_t s) = 1782 { 1783 add_long, /* 00 */ 1784 or_long, /* 01 */ 1785 adc_long, /* 02 */ 1786 sbb_long, /* 03 */ 1787 and_long, /* 04 */ 1788 sub_long, /* 05 */ 1789 xor_long, /* 06 */ 1790 cmp_long, /* 07 */ 1791 }; 1792 1793 /* 1794 * REMARKS: 1795 * Handles opcode 0x81 1796 */ 1797 static void 1798 x86emuOp32_opc81_word_RM_IMM(struct x86emu *emu) 1799 { 1800 uint32_t destval, imm; 1801 1802 /* 1803 * Weirdo special case instruction format. Part of the opcode 1804 * held below in "RH". Doubly nested case would result, except 1805 * that the decoded instruction 1806 */ 1807 fetch_decode_modrm(emu); 1808 destval = decode_and_fetch_long(emu); 1809 imm = fetch_long_imm(emu); 1810 destval = (*opc81_long_operation[emu->cur_rh]) (emu, destval, imm); 1811 if (emu->cur_rh != 7) 1812 write_back_long(emu, destval); 1813 } 1814 1815 static void 1816 x86emuOp16_opc81_word_RM_IMM(struct x86emu *emu) 1817 { 1818 uint16_t destval, imm; 1819 1820 /* 1821 * Weirdo special case instruction format. Part of the opcode 1822 * held below in "RH". Doubly nested case would result, except 1823 * that the decoded instruction 1824 */ 1825 fetch_decode_modrm(emu); 1826 destval = decode_and_fetch_word(emu); 1827 imm = fetch_word_imm(emu); 1828 destval = (*opc81_word_operation[emu->cur_rh]) (emu, destval, imm); 1829 if (emu->cur_rh != 7) 1830 write_back_word(emu, destval); 1831 } 1832 1833 static void 1834 x86emuOp_opc81_word_RM_IMM(struct x86emu *emu) 1835 { 1836 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1837 x86emuOp32_opc81_word_RM_IMM(emu); 1838 else 1839 x86emuOp16_opc81_word_RM_IMM(emu); 1840 } 1841 1842 static 1843 uint8_t(* const opc82_byte_operation[]) (struct x86emu *, uint8_t s, uint8_t d) = 1844 { 1845 add_byte, /* 00 */ 1846 or_byte, /* 01 *//* YYY UNUSED ???? */ 1847 adc_byte, /* 02 */ 1848 sbb_byte, /* 03 */ 1849 and_byte, /* 04 *//* YYY UNUSED ???? */ 1850 sub_byte, /* 05 */ 1851 xor_byte, /* 06 *//* YYY UNUSED ???? */ 1852 cmp_byte, /* 07 */ 1853 }; 1854 1855 /* 1856 * REMARKS: 1857 * Handles opcode 0x82 1858 */ 1859 static void 1860 x86emuOp_opc82_byte_RM_IMM(struct x86emu *emu) 1861 { 1862 uint8_t imm, destval; 1863 1864 /* 1865 * Weirdo special case instruction format. Part of the opcode 1866 * held below in "RH". Doubly nested case would result, except 1867 * that the decoded instruction Similar to opcode 81, except that 1868 * the immediate byte is sign extended to a word length. 1869 */ 1870 fetch_decode_modrm(emu); 1871 destval = decode_and_fetch_byte(emu); 1872 imm = fetch_byte_imm(emu); 1873 destval = (*opc82_byte_operation[emu->cur_rh]) (emu, destval, imm); 1874 if (emu->cur_rh != 7) 1875 write_back_byte(emu, destval); 1876 } 1877 1878 static 1879 uint16_t(* const opc83_word_operation[]) (struct x86emu *, uint16_t s, uint16_t d) = 1880 { 1881 add_word, /* 00 */ 1882 or_word, /* 01 *//* YYY UNUSED ???? */ 1883 adc_word, /* 02 */ 1884 sbb_word, /* 03 */ 1885 and_word, /* 04 *//* YYY UNUSED ???? */ 1886 sub_word, /* 05 */ 1887 xor_word, /* 06 *//* YYY UNUSED ???? */ 1888 cmp_word, /* 07 */ 1889 }; 1890 1891 static 1892 uint32_t(* const opc83_long_operation[]) (struct x86emu *, uint32_t s, uint32_t d) = 1893 { 1894 add_long, /* 00 */ 1895 or_long, /* 01 *//* YYY UNUSED ???? */ 1896 adc_long, /* 02 */ 1897 sbb_long, /* 03 */ 1898 and_long, /* 04 *//* YYY UNUSED ???? */ 1899 sub_long, /* 05 */ 1900 xor_long, /* 06 *//* YYY UNUSED ???? */ 1901 cmp_long, /* 07 */ 1902 }; 1903 1904 /* 1905 * REMARKS: 1906 * Handles opcode 0x83 1907 */ 1908 static void 1909 x86emuOp32_opc83_word_RM_IMM(struct x86emu *emu) 1910 { 1911 uint32_t destval, imm; 1912 1913 fetch_decode_modrm(emu); 1914 destval = decode_and_fetch_long(emu); 1915 imm = (int8_t) fetch_byte_imm(emu); 1916 destval = (*opc83_long_operation[emu->cur_rh]) (emu, destval, imm); 1917 if (emu->cur_rh != 7) 1918 write_back_long(emu, destval); 1919 } 1920 1921 static void 1922 x86emuOp16_opc83_word_RM_IMM(struct x86emu *emu) 1923 { 1924 uint16_t destval, imm; 1925 1926 fetch_decode_modrm(emu); 1927 destval = decode_and_fetch_word(emu); 1928 imm = (int8_t) fetch_byte_imm(emu); 1929 destval = (*opc83_word_operation[emu->cur_rh]) (emu, destval, imm); 1930 if (emu->cur_rh != 7) 1931 write_back_word(emu, destval); 1932 } 1933 1934 static void 1935 x86emuOp_opc83_word_RM_IMM(struct x86emu *emu) 1936 { 1937 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1938 x86emuOp32_opc83_word_RM_IMM(emu); 1939 else 1940 x86emuOp16_opc83_word_RM_IMM(emu); 1941 } 1942 1943 /* 1944 * REMARKS: 1945 * Handles opcode 0x86 1946 */ 1947 static void 1948 x86emuOp_xchg_byte_RM_R(struct x86emu *emu) 1949 { 1950 uint8_t *srcreg, destval, tmp; 1951 1952 fetch_decode_modrm(emu); 1953 destval = decode_and_fetch_byte(emu); 1954 srcreg = decode_rh_byte_register(emu); 1955 tmp = destval; 1956 destval = *srcreg; 1957 *srcreg = tmp; 1958 write_back_byte(emu, destval); 1959 } 1960 1961 /* 1962 * REMARKS: 1963 * Handles opcode 0x87 1964 */ 1965 static void 1966 x86emuOp32_xchg_word_RM_R(struct x86emu *emu) 1967 { 1968 uint32_t *srcreg, destval, tmp; 1969 1970 fetch_decode_modrm(emu); 1971 destval = decode_and_fetch_long(emu); 1972 srcreg = decode_rh_long_register(emu); 1973 tmp = destval; 1974 destval = *srcreg; 1975 *srcreg = tmp; 1976 write_back_long(emu, destval); 1977 } 1978 1979 static void 1980 x86emuOp16_xchg_word_RM_R(struct x86emu *emu) 1981 { 1982 uint16_t *srcreg, destval, tmp; 1983 1984 fetch_decode_modrm(emu); 1985 destval = decode_and_fetch_word(emu); 1986 srcreg = decode_rh_word_register(emu); 1987 tmp = destval; 1988 destval = *srcreg; 1989 *srcreg = tmp; 1990 write_back_word(emu, destval); 1991 } 1992 1993 static void 1994 x86emuOp_xchg_word_RM_R(struct x86emu *emu) 1995 { 1996 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1997 x86emuOp32_xchg_word_RM_R(emu); 1998 else 1999 x86emuOp16_xchg_word_RM_R(emu); 2000 } 2001 2002 /* 2003 * REMARKS: 2004 * Handles opcode 0x88 2005 */ 2006 static void 2007 x86emuOp_mov_byte_RM_R(struct x86emu *emu) 2008 { 2009 uint8_t *destreg, *srcreg; 2010 uint32_t destoffset; 2011 2012 fetch_decode_modrm(emu); 2013 srcreg = decode_rh_byte_register(emu); 2014 if (emu->cur_mod != 3) { 2015 destoffset = decode_rl_address(emu); 2016 store_data_byte(emu, destoffset, *srcreg); 2017 } else { 2018 destreg = decode_rl_byte_register(emu); 2019 *destreg = *srcreg; 2020 } 2021 } 2022 2023 /* 2024 * REMARKS: 2025 * Handles opcode 0x89 2026 */ 2027 static void 2028 x86emuOp32_mov_word_RM_R(struct x86emu *emu) 2029 { 2030 uint32_t destoffset; 2031 uint32_t *destreg, srcval; 2032 2033 fetch_decode_modrm(emu); 2034 srcval = *decode_rh_long_register(emu); 2035 if (emu->cur_mod != 3) { 2036 destoffset = decode_rl_address(emu); 2037 store_data_long(emu, destoffset, srcval); 2038 } else { 2039 destreg = decode_rl_long_register(emu); 2040 *destreg = srcval; 2041 } 2042 } 2043 2044 static void 2045 x86emuOp16_mov_word_RM_R(struct x86emu *emu) 2046 { 2047 uint32_t destoffset; 2048 uint16_t *destreg, srcval; 2049 2050 fetch_decode_modrm(emu); 2051 srcval = *decode_rh_word_register(emu); 2052 if (emu->cur_mod != 3) { 2053 destoffset = decode_rl_address(emu); 2054 store_data_word(emu, destoffset, srcval); 2055 } else { 2056 destreg = decode_rl_word_register(emu); 2057 *destreg = srcval; 2058 } 2059 } 2060 2061 static void 2062 x86emuOp_mov_word_RM_R(struct x86emu *emu) 2063 { 2064 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2065 x86emuOp32_mov_word_RM_R(emu); 2066 else 2067 x86emuOp16_mov_word_RM_R(emu); 2068 } 2069 2070 /* 2071 * REMARKS: 2072 * Handles opcode 0x8a 2073 */ 2074 static void 2075 x86emuOp_mov_byte_R_RM(struct x86emu *emu) 2076 { 2077 uint8_t *destreg; 2078 2079 fetch_decode_modrm(emu); 2080 destreg = decode_rh_byte_register(emu); 2081 *destreg = decode_and_fetch_byte(emu); 2082 } 2083 2084 /* 2085 * REMARKS: 2086 * Handles opcode 0x8b 2087 */ 2088 static void 2089 x86emuOp_mov_word_R_RM(struct x86emu *emu) 2090 { 2091 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2092 uint32_t *destreg; 2093 2094 fetch_decode_modrm(emu); 2095 destreg = decode_rh_long_register(emu); 2096 *destreg = decode_and_fetch_long(emu); 2097 } else { 2098 uint16_t *destreg; 2099 2100 fetch_decode_modrm(emu); 2101 destreg = decode_rh_word_register(emu); 2102 *destreg = decode_and_fetch_word(emu); 2103 } 2104 } 2105 2106 /* 2107 * REMARKS: 2108 * Handles opcode 0x8c 2109 */ 2110 static void 2111 x86emuOp_mov_word_RM_SR(struct x86emu *emu) 2112 { 2113 uint16_t *destreg, srcval; 2114 uint32_t destoffset; 2115 2116 fetch_decode_modrm(emu); 2117 srcval = *decode_rh_seg_register(emu); 2118 if (emu->cur_mod != 3) { 2119 destoffset = decode_rl_address(emu); 2120 store_data_word(emu, destoffset, srcval); 2121 } else { 2122 destreg = decode_rl_word_register(emu); 2123 *destreg = srcval; 2124 } 2125 } 2126 2127 /* 2128 * REMARKS: 2129 * Handles opcode 0x8d 2130 */ 2131 static void 2132 x86emuOp_lea_word_R_M(struct x86emu *emu) 2133 { 2134 uint16_t *srcreg; 2135 uint32_t destoffset; 2136 2137 /* 2138 * TODO: Need to handle address size prefix! 2139 * 2140 * lea eax,[eax+ebx*2] ?? 2141 */ 2142 fetch_decode_modrm(emu); 2143 if (emu->cur_mod == 3) 2144 x86emu_halt_sys(emu); 2145 2146 srcreg = decode_rh_word_register(emu); 2147 destoffset = decode_rl_address(emu); 2148 *srcreg = (uint16_t) destoffset; 2149 } 2150 2151 /* 2152 * REMARKS: 2153 * Handles opcode 0x8e 2154 */ 2155 static void 2156 x86emuOp_mov_word_SR_RM(struct x86emu *emu) 2157 { 2158 uint16_t *destreg; 2159 2160 fetch_decode_modrm(emu); 2161 destreg = decode_rh_seg_register(emu); 2162 *destreg = decode_and_fetch_word(emu); 2163 /* 2164 * Clean up, and reset all the R_xSP pointers to the correct 2165 * locations. This is about 3x too much overhead (doing all the 2166 * segreg ptrs when only one is needed, but this instruction 2167 * *cannot* be that common, and this isn't too much work anyway. 2168 */ 2169 } 2170 2171 /* 2172 * REMARKS: 2173 * Handles opcode 0x8f 2174 */ 2175 static void 2176 x86emuOp32_pop_RM(struct x86emu *emu) 2177 { 2178 uint32_t destoffset; 2179 uint32_t destval, *destreg; 2180 2181 fetch_decode_modrm(emu); 2182 if (emu->cur_mod != 3) { 2183 destoffset = decode_rl_address(emu); 2184 destval = pop_long(emu); 2185 store_data_long(emu, destoffset, destval); 2186 } else { 2187 destreg = decode_rl_long_register(emu); 2188 *destreg = pop_long(emu); 2189 } 2190 } 2191 2192 static void 2193 x86emuOp16_pop_RM(struct x86emu *emu) 2194 { 2195 uint32_t destoffset; 2196 uint16_t destval, *destreg; 2197 2198 fetch_decode_modrm(emu); 2199 if (emu->cur_mod != 3) { 2200 destoffset = decode_rl_address(emu); 2201 destval = pop_word(emu); 2202 store_data_word(emu, destoffset, destval); 2203 } else { 2204 destreg = decode_rl_word_register(emu); 2205 *destreg = pop_word(emu); 2206 } 2207 } 2208 2209 static void 2210 x86emuOp_pop_RM(struct x86emu *emu) 2211 { 2212 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2213 x86emuOp32_pop_RM(emu); 2214 else 2215 x86emuOp16_pop_RM(emu); 2216 } 2217 2218 /* 2219 * REMARKS: 2220 * Handles opcode 0x91 2221 */ 2222 static void 2223 x86emuOp_xchg_word_AX_CX(struct x86emu *emu) 2224 { 2225 uint32_t tmp; 2226 2227 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2228 tmp = emu->x86.R_EAX; 2229 emu->x86.R_EAX = emu->x86.R_ECX; 2230 emu->x86.R_ECX = tmp; 2231 } else { 2232 tmp = emu->x86.R_AX; 2233 emu->x86.R_AX = emu->x86.R_CX; 2234 emu->x86.R_CX = (uint16_t) tmp; 2235 } 2236 } 2237 2238 /* 2239 * REMARKS: 2240 * Handles opcode 0x92 2241 */ 2242 static void 2243 x86emuOp_xchg_word_AX_DX(struct x86emu *emu) 2244 { 2245 uint32_t tmp; 2246 2247 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2248 tmp = emu->x86.R_EAX; 2249 emu->x86.R_EAX = emu->x86.R_EDX; 2250 emu->x86.R_EDX = tmp; 2251 } else { 2252 tmp = emu->x86.R_AX; 2253 emu->x86.R_AX = emu->x86.R_DX; 2254 emu->x86.R_DX = (uint16_t) tmp; 2255 } 2256 } 2257 2258 /* 2259 * REMARKS: 2260 * Handles opcode 0x93 2261 */ 2262 static void 2263 x86emuOp_xchg_word_AX_BX(struct x86emu *emu) 2264 { 2265 uint32_t tmp; 2266 2267 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2268 tmp = emu->x86.R_EAX; 2269 emu->x86.R_EAX = emu->x86.R_EBX; 2270 emu->x86.R_EBX = tmp; 2271 } else { 2272 tmp = emu->x86.R_AX; 2273 emu->x86.R_AX = emu->x86.R_BX; 2274 emu->x86.R_BX = (uint16_t) tmp; 2275 } 2276 } 2277 2278 /* 2279 * REMARKS: 2280 * Handles opcode 0x94 2281 */ 2282 static void 2283 x86emuOp_xchg_word_AX_SP(struct x86emu *emu) 2284 { 2285 uint32_t tmp; 2286 2287 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2288 tmp = emu->x86.R_EAX; 2289 emu->x86.R_EAX = emu->x86.R_ESP; 2290 emu->x86.R_ESP = tmp; 2291 } else { 2292 tmp = emu->x86.R_AX; 2293 emu->x86.R_AX = emu->x86.R_SP; 2294 emu->x86.R_SP = (uint16_t) tmp; 2295 } 2296 } 2297 2298 /* 2299 * REMARKS: 2300 * Handles opcode 0x95 2301 */ 2302 static void 2303 x86emuOp_xchg_word_AX_BP(struct x86emu *emu) 2304 { 2305 uint32_t tmp; 2306 2307 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2308 tmp = emu->x86.R_EAX; 2309 emu->x86.R_EAX = emu->x86.R_EBP; 2310 emu->x86.R_EBP = tmp; 2311 } else { 2312 tmp = emu->x86.R_AX; 2313 emu->x86.R_AX = emu->x86.R_BP; 2314 emu->x86.R_BP = (uint16_t) tmp; 2315 } 2316 } 2317 2318 /* 2319 * REMARKS: 2320 * Handles opcode 0x96 2321 */ 2322 static void 2323 x86emuOp_xchg_word_AX_SI(struct x86emu *emu) 2324 { 2325 uint32_t tmp; 2326 2327 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2328 tmp = emu->x86.R_EAX; 2329 emu->x86.R_EAX = emu->x86.R_ESI; 2330 emu->x86.R_ESI = tmp; 2331 } else { 2332 tmp = emu->x86.R_AX; 2333 emu->x86.R_AX = emu->x86.R_SI; 2334 emu->x86.R_SI = (uint16_t) tmp; 2335 } 2336 } 2337 2338 /* 2339 * REMARKS: 2340 * Handles opcode 0x97 2341 */ 2342 static void 2343 x86emuOp_xchg_word_AX_DI(struct x86emu *emu) 2344 { 2345 uint32_t tmp; 2346 2347 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2348 tmp = emu->x86.R_EAX; 2349 emu->x86.R_EAX = emu->x86.R_EDI; 2350 emu->x86.R_EDI = tmp; 2351 } else { 2352 tmp = emu->x86.R_AX; 2353 emu->x86.R_AX = emu->x86.R_DI; 2354 emu->x86.R_DI = (uint16_t) tmp; 2355 } 2356 } 2357 2358 /* 2359 * REMARKS: 2360 * Handles opcode 0x98 2361 */ 2362 static void 2363 x86emuOp_cbw(struct x86emu *emu) 2364 { 2365 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2366 if (emu->x86.R_AX & 0x8000) { 2367 emu->x86.R_EAX |= 0xffff0000; 2368 } else { 2369 emu->x86.R_EAX &= 0x0000ffff; 2370 } 2371 } else { 2372 if (emu->x86.R_AL & 0x80) { 2373 emu->x86.R_AH = 0xff; 2374 } else { 2375 emu->x86.R_AH = 0x0; 2376 } 2377 } 2378 } 2379 2380 /* 2381 * REMARKS: 2382 * Handles opcode 0x99 2383 */ 2384 static void 2385 x86emuOp_cwd(struct x86emu *emu) 2386 { 2387 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2388 if (emu->x86.R_EAX & 0x80000000) { 2389 emu->x86.R_EDX = 0xffffffff; 2390 } else { 2391 emu->x86.R_EDX = 0x0; 2392 } 2393 } else { 2394 if (emu->x86.R_AX & 0x8000) { 2395 emu->x86.R_DX = 0xffff; 2396 } else { 2397 emu->x86.R_DX = 0x0; 2398 } 2399 } 2400 } 2401 2402 /* 2403 * REMARKS: 2404 * Handles opcode 0x9a 2405 */ 2406 static void 2407 x86emuOp_call_far_IMM(struct x86emu *emu) 2408 { 2409 uint16_t farseg, faroff; 2410 2411 faroff = fetch_word_imm(emu); 2412 farseg = fetch_word_imm(emu); 2413 /* XXX 2414 * 2415 * Hooked interrupt vectors calling into our "BIOS" will cause problems 2416 * unless all intersegment stuff is checked for BIOS access. Check 2417 * needed here. For moment, let it alone. */ 2418 push_word(emu, emu->x86.R_CS); 2419 emu->x86.R_CS = farseg; 2420 push_word(emu, emu->x86.R_IP); 2421 emu->x86.R_IP = faroff; 2422 } 2423 2424 /* 2425 * REMARKS: 2426 * Handles opcode 0x9c 2427 */ 2428 static void 2429 x86emuOp_pushf_word(struct x86emu *emu) 2430 { 2431 uint32_t flags; 2432 2433 /* clear out *all* bits not representing flags, and turn on real bits */ 2434 flags = (emu->x86.R_EFLG & F_MSK) | F_ALWAYS_ON; 2435 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2436 push_long(emu, flags); 2437 } else { 2438 push_word(emu, (uint16_t) flags); 2439 } 2440 } 2441 2442 /* 2443 * REMARKS: 2444 * Handles opcode 0x9d 2445 */ 2446 static void 2447 x86emuOp_popf_word(struct x86emu *emu) 2448 { 2449 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2450 emu->x86.R_EFLG = pop_long(emu); 2451 } else { 2452 emu->x86.R_FLG = pop_word(emu); 2453 } 2454 } 2455 2456 /* 2457 * REMARKS: 2458 * Handles opcode 0x9e 2459 */ 2460 static void 2461 x86emuOp_sahf(struct x86emu *emu) 2462 { 2463 /* clear the lower bits of the flag register */ 2464 emu->x86.R_FLG &= 0xffffff00; 2465 /* or in the AH register into the flags register */ 2466 emu->x86.R_FLG |= emu->x86.R_AH; 2467 } 2468 2469 /* 2470 * REMARKS: 2471 * Handles opcode 0x9f 2472 */ 2473 static void 2474 x86emuOp_lahf(struct x86emu *emu) 2475 { 2476 emu->x86.R_AH = (uint8_t) (emu->x86.R_FLG & 0xff); 2477 /* undocumented TC++ behavior??? Nope. It's documented, but you have 2478 * too look real hard to notice it. */ 2479 emu->x86.R_AH |= 0x2; 2480 } 2481 2482 /* 2483 * REMARKS: 2484 * Handles opcode 0xa0 2485 */ 2486 static void 2487 x86emuOp_mov_AL_M_IMM(struct x86emu *emu) 2488 { 2489 uint16_t offset; 2490 2491 offset = fetch_word_imm(emu); 2492 emu->x86.R_AL = fetch_data_byte(emu, offset); 2493 } 2494 2495 /* 2496 * REMARKS: 2497 * Handles opcode 0xa1 2498 */ 2499 static void 2500 x86emuOp_mov_AX_M_IMM(struct x86emu *emu) 2501 { 2502 uint16_t offset; 2503 2504 offset = fetch_word_imm(emu); 2505 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2506 emu->x86.R_EAX = fetch_data_long(emu, offset); 2507 } else { 2508 emu->x86.R_AX = fetch_data_word(emu, offset); 2509 } 2510 } 2511 2512 /* 2513 * REMARKS: 2514 * Handles opcode 0xa2 2515 */ 2516 static void 2517 x86emuOp_mov_M_AL_IMM(struct x86emu *emu) 2518 { 2519 uint16_t offset; 2520 2521 offset = fetch_word_imm(emu); 2522 store_data_byte(emu, offset, emu->x86.R_AL); 2523 } 2524 2525 /* 2526 * REMARKS: 2527 * Handles opcode 0xa3 2528 */ 2529 static void 2530 x86emuOp_mov_M_AX_IMM(struct x86emu *emu) 2531 { 2532 uint16_t offset; 2533 2534 offset = fetch_word_imm(emu); 2535 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2536 store_data_long(emu, offset, emu->x86.R_EAX); 2537 } else { 2538 store_data_word(emu, offset, emu->x86.R_AX); 2539 } 2540 } 2541 2542 /* 2543 * REMARKS: 2544 * Handles opcode 0xa4 2545 */ 2546 static void 2547 x86emuOp_movs_byte(struct x86emu *emu) 2548 { 2549 uint8_t val; 2550 uint32_t count; 2551 int inc; 2552 2553 if (ACCESS_FLAG(F_DF)) /* down */ 2554 inc = -1; 2555 else 2556 inc = 1; 2557 count = 1; 2558 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2559 /* dont care whether REPE or REPNE */ 2560 /* move them until CX is ZERO. */ 2561 count = emu->x86.R_CX; 2562 emu->x86.R_CX = 0; 2563 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2564 } 2565 while (count--) { 2566 val = fetch_data_byte(emu, emu->x86.R_SI); 2567 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, val); 2568 emu->x86.R_SI += inc; 2569 emu->x86.R_DI += inc; 2570 } 2571 } 2572 2573 /* 2574 * REMARKS: 2575 * Handles opcode 0xa5 2576 */ 2577 static void 2578 x86emuOp_movs_word(struct x86emu *emu) 2579 { 2580 uint32_t val; 2581 int inc; 2582 uint32_t count; 2583 2584 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2585 inc = 4; 2586 else 2587 inc = 2; 2588 2589 if (ACCESS_FLAG(F_DF)) /* down */ 2590 inc = -inc; 2591 2592 count = 1; 2593 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2594 /* dont care whether REPE or REPNE */ 2595 /* move them until CX is ZERO. */ 2596 count = emu->x86.R_CX; 2597 emu->x86.R_CX = 0; 2598 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2599 } 2600 while (count--) { 2601 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2602 val = fetch_data_long(emu, emu->x86.R_SI); 2603 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, val); 2604 } else { 2605 val = fetch_data_word(emu, emu->x86.R_SI); 2606 store_word(emu, emu->x86.R_ES, emu->x86.R_DI, (uint16_t) val); 2607 } 2608 emu->x86.R_SI += inc; 2609 emu->x86.R_DI += inc; 2610 } 2611 } 2612 2613 /* 2614 * REMARKS: 2615 * Handles opcode 0xa6 2616 */ 2617 static void 2618 x86emuOp_cmps_byte(struct x86emu *emu) 2619 { 2620 int8_t val1, val2; 2621 int inc; 2622 2623 if (ACCESS_FLAG(F_DF)) /* down */ 2624 inc = -1; 2625 else 2626 inc = 1; 2627 2628 if (emu->x86.mode & SYSMODE_PREFIX_REPE) { 2629 /* REPE */ 2630 /* move them until CX is ZERO. */ 2631 while (emu->x86.R_CX != 0) { 2632 val1 = fetch_data_byte(emu, emu->x86.R_SI); 2633 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2634 cmp_byte(emu, val1, val2); 2635 emu->x86.R_CX -= 1; 2636 emu->x86.R_SI += inc; 2637 emu->x86.R_DI += inc; 2638 if (ACCESS_FLAG(F_ZF) == 0) 2639 break; 2640 } 2641 emu->x86.mode &= ~SYSMODE_PREFIX_REPE; 2642 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) { 2643 /* REPNE */ 2644 /* move them until CX is ZERO. */ 2645 while (emu->x86.R_CX != 0) { 2646 val1 = fetch_data_byte(emu, emu->x86.R_SI); 2647 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2648 cmp_byte(emu, val1, val2); 2649 emu->x86.R_CX -= 1; 2650 emu->x86.R_SI += inc; 2651 emu->x86.R_DI += inc; 2652 if (ACCESS_FLAG(F_ZF)) 2653 break; /* zero flag set means equal */ 2654 } 2655 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE; 2656 } else { 2657 val1 = fetch_data_byte(emu, emu->x86.R_SI); 2658 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2659 cmp_byte(emu, val1, val2); 2660 emu->x86.R_SI += inc; 2661 emu->x86.R_DI += inc; 2662 } 2663 } 2664 2665 /* 2666 * REMARKS: 2667 * Handles opcode 0xa7 2668 */ 2669 static void 2670 x86emuOp_cmps_word(struct x86emu *emu) 2671 { 2672 uint32_t val1, val2; 2673 int inc; 2674 2675 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2676 if (ACCESS_FLAG(F_DF)) /* down */ 2677 inc = -4; 2678 else 2679 inc = 4; 2680 } else { 2681 if (ACCESS_FLAG(F_DF)) /* down */ 2682 inc = -2; 2683 else 2684 inc = 2; 2685 } 2686 if (emu->x86.mode & SYSMODE_PREFIX_REPE) { 2687 /* REPE */ 2688 /* move them until CX is ZERO. */ 2689 while (emu->x86.R_CX != 0) { 2690 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2691 val1 = fetch_data_long(emu, emu->x86.R_SI); 2692 val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2693 cmp_long(emu, val1, val2); 2694 } else { 2695 val1 = fetch_data_word(emu, emu->x86.R_SI); 2696 val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2697 cmp_word(emu, (uint16_t) val1, (uint16_t) val2); 2698 } 2699 emu->x86.R_CX -= 1; 2700 emu->x86.R_SI += inc; 2701 emu->x86.R_DI += inc; 2702 if (ACCESS_FLAG(F_ZF) == 0) 2703 break; 2704 } 2705 emu->x86.mode &= ~SYSMODE_PREFIX_REPE; 2706 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) { 2707 /* REPNE */ 2708 /* move them until CX is ZERO. */ 2709 while (emu->x86.R_CX != 0) { 2710 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2711 val1 = fetch_data_long(emu, emu->x86.R_SI); 2712 val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2713 cmp_long(emu, val1, val2); 2714 } else { 2715 val1 = fetch_data_word(emu, emu->x86.R_SI); 2716 val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2717 cmp_word(emu, (uint16_t) val1, (uint16_t) val2); 2718 } 2719 emu->x86.R_CX -= 1; 2720 emu->x86.R_SI += inc; 2721 emu->x86.R_DI += inc; 2722 if (ACCESS_FLAG(F_ZF)) 2723 break; /* zero flag set means equal */ 2724 } 2725 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE; 2726 } else { 2727 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2728 val1 = fetch_data_long(emu, emu->x86.R_SI); 2729 val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2730 cmp_long(emu, val1, val2); 2731 } else { 2732 val1 = fetch_data_word(emu, emu->x86.R_SI); 2733 val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2734 cmp_word(emu, (uint16_t) val1, (uint16_t) val2); 2735 } 2736 emu->x86.R_SI += inc; 2737 emu->x86.R_DI += inc; 2738 } 2739 } 2740 2741 /* 2742 * REMARKS: 2743 * Handles opcode 0xa9 2744 */ 2745 static void 2746 x86emuOp_test_AX_IMM(struct x86emu *emu) 2747 { 2748 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2749 test_long(emu, emu->x86.R_EAX, fetch_long_imm(emu)); 2750 } else { 2751 test_word(emu, emu->x86.R_AX, fetch_word_imm(emu)); 2752 } 2753 } 2754 2755 /* 2756 * REMARKS: 2757 * Handles opcode 0xaa 2758 */ 2759 static void 2760 x86emuOp_stos_byte(struct x86emu *emu) 2761 { 2762 int inc; 2763 2764 if (ACCESS_FLAG(F_DF)) /* down */ 2765 inc = -1; 2766 else 2767 inc = 1; 2768 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2769 /* dont care whether REPE or REPNE */ 2770 /* move them until CX is ZERO. */ 2771 while (emu->x86.R_CX != 0) { 2772 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL); 2773 emu->x86.R_CX -= 1; 2774 emu->x86.R_DI += inc; 2775 } 2776 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2777 } else { 2778 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL); 2779 emu->x86.R_DI += inc; 2780 } 2781 } 2782 2783 /* 2784 * REMARKS: 2785 * Handles opcode 0xab 2786 */ 2787 static void 2788 x86emuOp_stos_word(struct x86emu *emu) 2789 { 2790 int inc; 2791 uint32_t count; 2792 2793 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2794 inc = 4; 2795 else 2796 inc = 2; 2797 2798 if (ACCESS_FLAG(F_DF)) /* down */ 2799 inc = -inc; 2800 2801 count = 1; 2802 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2803 /* dont care whether REPE or REPNE */ 2804 /* move them until CX is ZERO. */ 2805 count = emu->x86.R_CX; 2806 emu->x86.R_CX = 0; 2807 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2808 } 2809 while (count--) { 2810 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2811 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_EAX); 2812 } else { 2813 store_word(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AX); 2814 } 2815 emu->x86.R_DI += inc; 2816 } 2817 } 2818 2819 /* 2820 * REMARKS: 2821 * Handles opcode 0xac 2822 */ 2823 static void 2824 x86emuOp_lods_byte(struct x86emu *emu) 2825 { 2826 int inc; 2827 2828 if (ACCESS_FLAG(F_DF)) /* down */ 2829 inc = -1; 2830 else 2831 inc = 1; 2832 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2833 /* dont care whether REPE or REPNE */ 2834 /* move them until CX is ZERO. */ 2835 while (emu->x86.R_CX != 0) { 2836 emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI); 2837 emu->x86.R_CX -= 1; 2838 emu->x86.R_SI += inc; 2839 } 2840 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2841 } else { 2842 emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI); 2843 emu->x86.R_SI += inc; 2844 } 2845 } 2846 2847 /* 2848 * REMARKS: 2849 * Handles opcode 0xad 2850 */ 2851 static void 2852 x86emuOp_lods_word(struct x86emu *emu) 2853 { 2854 int inc; 2855 uint32_t count; 2856 2857 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2858 inc = 4; 2859 else 2860 inc = 2; 2861 2862 if (ACCESS_FLAG(F_DF)) /* down */ 2863 inc = -inc; 2864 2865 count = 1; 2866 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2867 /* dont care whether REPE or REPNE */ 2868 /* move them until CX is ZERO. */ 2869 count = emu->x86.R_CX; 2870 emu->x86.R_CX = 0; 2871 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2872 } 2873 while (count--) { 2874 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2875 emu->x86.R_EAX = fetch_data_long(emu, emu->x86.R_SI); 2876 } else { 2877 emu->x86.R_AX = fetch_data_word(emu, emu->x86.R_SI); 2878 } 2879 emu->x86.R_SI += inc; 2880 } 2881 } 2882 2883 /* 2884 * REMARKS: 2885 * Handles opcode 0xae 2886 */ 2887 static void 2888 x86emuOp_scas_byte(struct x86emu *emu) 2889 { 2890 int8_t val2; 2891 int inc; 2892 2893 if (ACCESS_FLAG(F_DF)) /* down */ 2894 inc = -1; 2895 else 2896 inc = 1; 2897 if (emu->x86.mode & SYSMODE_PREFIX_REPE) { 2898 /* REPE */ 2899 /* move them until CX is ZERO. */ 2900 while (emu->x86.R_CX != 0) { 2901 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2902 cmp_byte(emu, emu->x86.R_AL, val2); 2903 emu->x86.R_CX -= 1; 2904 emu->x86.R_DI += inc; 2905 if (ACCESS_FLAG(F_ZF) == 0) 2906 break; 2907 } 2908 emu->x86.mode &= ~SYSMODE_PREFIX_REPE; 2909 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) { 2910 /* REPNE */ 2911 /* move them until CX is ZERO. */ 2912 while (emu->x86.R_CX != 0) { 2913 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2914 cmp_byte(emu, emu->x86.R_AL, val2); 2915 emu->x86.R_CX -= 1; 2916 emu->x86.R_DI += inc; 2917 if (ACCESS_FLAG(F_ZF)) 2918 break; /* zero flag set means equal */ 2919 } 2920 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE; 2921 } else { 2922 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2923 cmp_byte(emu, emu->x86.R_AL, val2); 2924 emu->x86.R_DI += inc; 2925 } 2926 } 2927 2928 /* 2929 * REMARKS: 2930 * Handles opcode 0xaf 2931 */ 2932 static void 2933 x86emuOp_scas_word(struct x86emu *emu) 2934 { 2935 int inc; 2936 uint32_t val; 2937 2938 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2939 inc = 4; 2940 else 2941 inc = 2; 2942 2943 if (ACCESS_FLAG(F_DF)) /* down */ 2944 inc = -inc; 2945 2946 if (emu->x86.mode & SYSMODE_PREFIX_REPE) { 2947 /* REPE */ 2948 /* move them until CX is ZERO. */ 2949 while (emu->x86.R_CX != 0) { 2950 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2951 val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2952 cmp_long(emu, emu->x86.R_EAX, val); 2953 } else { 2954 val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2955 cmp_word(emu, emu->x86.R_AX, (uint16_t) val); 2956 } 2957 emu->x86.R_CX -= 1; 2958 emu->x86.R_DI += inc; 2959 if (ACCESS_FLAG(F_ZF) == 0) 2960 break; 2961 } 2962 emu->x86.mode &= ~SYSMODE_PREFIX_REPE; 2963 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) { 2964 /* REPNE */ 2965 /* move them until CX is ZERO. */ 2966 while (emu->x86.R_CX != 0) { 2967 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2968 val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2969 cmp_long(emu, emu->x86.R_EAX, val); 2970 } else { 2971 val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2972 cmp_word(emu, emu->x86.R_AX, (uint16_t) val); 2973 } 2974 emu->x86.R_CX -= 1; 2975 emu->x86.R_DI += inc; 2976 if (ACCESS_FLAG(F_ZF)) 2977 break; /* zero flag set means equal */ 2978 } 2979 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE; 2980 } else { 2981 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2982 val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2983 cmp_long(emu, emu->x86.R_EAX, val); 2984 } else { 2985 val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2986 cmp_word(emu, emu->x86.R_AX, (uint16_t) val); 2987 } 2988 emu->x86.R_DI += inc; 2989 } 2990 } 2991 2992 /* 2993 * REMARKS: 2994 * Handles opcode 0xb8 2995 */ 2996 static void 2997 x86emuOp_mov_word_AX_IMM(struct x86emu *emu) 2998 { 2999 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3000 emu->x86.R_EAX = fetch_long_imm(emu); 3001 else 3002 emu->x86.R_AX = fetch_word_imm(emu); 3003 } 3004 3005 /* 3006 * REMARKS: 3007 * Handles opcode 0xb9 3008 */ 3009 static void 3010 x86emuOp_mov_word_CX_IMM(struct x86emu *emu) 3011 { 3012 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3013 emu->x86.R_ECX = fetch_long_imm(emu); 3014 else 3015 emu->x86.R_CX = fetch_word_imm(emu); 3016 } 3017 3018 /* 3019 * REMARKS: 3020 * Handles opcode 0xba 3021 */ 3022 static void 3023 x86emuOp_mov_word_DX_IMM(struct x86emu *emu) 3024 { 3025 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3026 emu->x86.R_EDX = fetch_long_imm(emu); 3027 else 3028 emu->x86.R_DX = fetch_word_imm(emu); 3029 } 3030 3031 /* 3032 * REMARKS: 3033 * Handles opcode 0xbb 3034 */ 3035 static void 3036 x86emuOp_mov_word_BX_IMM(struct x86emu *emu) 3037 { 3038 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3039 emu->x86.R_EBX = fetch_long_imm(emu); 3040 else 3041 emu->x86.R_BX = fetch_word_imm(emu); 3042 } 3043 3044 /* 3045 * REMARKS: 3046 * Handles opcode 0xbc 3047 */ 3048 static void 3049 x86emuOp_mov_word_SP_IMM(struct x86emu *emu) 3050 { 3051 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3052 emu->x86.R_ESP = fetch_long_imm(emu); 3053 else 3054 emu->x86.R_SP = fetch_word_imm(emu); 3055 } 3056 3057 /* 3058 * REMARKS: 3059 * Handles opcode 0xbd 3060 */ 3061 static void 3062 x86emuOp_mov_word_BP_IMM(struct x86emu *emu) 3063 { 3064 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3065 emu->x86.R_EBP = fetch_long_imm(emu); 3066 else 3067 emu->x86.R_BP = fetch_word_imm(emu); 3068 } 3069 3070 /* 3071 * REMARKS: 3072 * Handles opcode 0xbe 3073 */ 3074 static void 3075 x86emuOp_mov_word_SI_IMM(struct x86emu *emu) 3076 { 3077 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3078 emu->x86.R_ESI = fetch_long_imm(emu); 3079 else 3080 emu->x86.R_SI = fetch_word_imm(emu); 3081 } 3082 3083 /* 3084 * REMARKS: 3085 * Handles opcode 0xbf 3086 */ 3087 static void 3088 x86emuOp_mov_word_DI_IMM(struct x86emu *emu) 3089 { 3090 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3091 emu->x86.R_EDI = fetch_long_imm(emu); 3092 else 3093 emu->x86.R_DI = fetch_word_imm(emu); 3094 } 3095 /* used by opcodes c0, d0, and d2. */ 3096 static 3097 uint8_t(* const opcD0_byte_operation[]) (struct x86emu *, uint8_t d, uint8_t s) = 3098 { 3099 rol_byte, 3100 ror_byte, 3101 rcl_byte, 3102 rcr_byte, 3103 shl_byte, 3104 shr_byte, 3105 shl_byte, /* sal_byte === shl_byte by definition */ 3106 sar_byte, 3107 }; 3108 3109 /* 3110 * REMARKS: 3111 * Handles opcode 0xc0 3112 */ 3113 static void 3114 x86emuOp_opcC0_byte_RM_MEM(struct x86emu *emu) 3115 { 3116 uint8_t destval, amt; 3117 3118 /* 3119 * Yet another weirdo special case instruction format. Part of 3120 * the opcode held below in "RH". Doubly nested case would 3121 * result, except that the decoded instruction 3122 */ 3123 fetch_decode_modrm(emu); 3124 /* know operation, decode the mod byte to find the addressing mode. */ 3125 destval = decode_and_fetch_byte_imm8(emu, &amt); 3126 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, amt); 3127 write_back_byte(emu, destval); 3128 } 3129 /* used by opcodes c1, d1, and d3. */ 3130 static 3131 uint16_t(* const opcD1_word_operation[]) (struct x86emu *, uint16_t s, uint8_t d) = 3132 { 3133 rol_word, 3134 ror_word, 3135 rcl_word, 3136 rcr_word, 3137 shl_word, 3138 shr_word, 3139 shl_word, /* sal_byte === shl_byte by definition */ 3140 sar_word, 3141 }; 3142 /* used by opcodes c1, d1, and d3. */ 3143 static 3144 uint32_t(* const opcD1_long_operation[]) (struct x86emu *, uint32_t s, uint8_t d) = 3145 { 3146 rol_long, 3147 ror_long, 3148 rcl_long, 3149 rcr_long, 3150 shl_long, 3151 shr_long, 3152 shl_long, /* sal_byte === shl_byte by definition */ 3153 sar_long, 3154 }; 3155 3156 /* 3157 * REMARKS: 3158 * Handles opcode 0xc1 3159 */ 3160 static void 3161 x86emuOp_opcC1_word_RM_MEM(struct x86emu *emu) 3162 { 3163 uint8_t amt; 3164 3165 /* 3166 * Yet another weirdo special case instruction format. Part of 3167 * the opcode held below in "RH". Doubly nested case would 3168 * result, except that the decoded instruction 3169 */ 3170 fetch_decode_modrm(emu); 3171 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3172 uint32_t destval; 3173 3174 destval = decode_and_fetch_long_imm8(emu, &amt); 3175 destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, amt); 3176 write_back_long(emu, destval); 3177 } else { 3178 uint16_t destval; 3179 3180 destval = decode_and_fetch_word_imm8(emu, &amt); 3181 destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, amt); 3182 write_back_word(emu, destval); 3183 } 3184 } 3185 3186 /* 3187 * REMARKS: 3188 * Handles opcode 0xc2 3189 */ 3190 static void 3191 x86emuOp_ret_near_IMM(struct x86emu *emu) 3192 { 3193 uint16_t imm; 3194 3195 imm = fetch_word_imm(emu); 3196 emu->x86.R_IP = pop_word(emu); 3197 emu->x86.R_SP += imm; 3198 } 3199 3200 /* 3201 * REMARKS: 3202 * Handles opcode 0xc6 3203 */ 3204 static void 3205 x86emuOp_mov_byte_RM_IMM(struct x86emu *emu) 3206 { 3207 uint8_t *destreg; 3208 uint32_t destoffset; 3209 uint8_t imm; 3210 3211 fetch_decode_modrm(emu); 3212 if (emu->cur_rh != 0) 3213 x86emu_halt_sys(emu); 3214 if (emu->cur_mod != 3) { 3215 destoffset = decode_rl_address(emu); 3216 imm = fetch_byte_imm(emu); 3217 store_data_byte(emu, destoffset, imm); 3218 } else { 3219 destreg = decode_rl_byte_register(emu); 3220 imm = fetch_byte_imm(emu); 3221 *destreg = imm; 3222 } 3223 } 3224 3225 /* 3226 * REMARKS: 3227 * Handles opcode 0xc7 3228 */ 3229 static void 3230 x86emuOp32_mov_word_RM_IMM(struct x86emu *emu) 3231 { 3232 uint32_t destoffset; 3233 uint32_t imm, *destreg; 3234 3235 fetch_decode_modrm(emu); 3236 if (emu->cur_rh != 0) 3237 x86emu_halt_sys(emu); 3238 3239 if (emu->cur_mod != 3) { 3240 destoffset = decode_rl_address(emu); 3241 imm = fetch_long_imm(emu); 3242 store_data_long(emu, destoffset, imm); 3243 } else { 3244 destreg = decode_rl_long_register(emu); 3245 imm = fetch_long_imm(emu); 3246 *destreg = imm; 3247 } 3248 } 3249 3250 static void 3251 x86emuOp16_mov_word_RM_IMM(struct x86emu *emu) 3252 { 3253 uint32_t destoffset; 3254 uint16_t imm, *destreg; 3255 3256 fetch_decode_modrm(emu); 3257 if (emu->cur_rh != 0) 3258 x86emu_halt_sys(emu); 3259 3260 if (emu->cur_mod != 3) { 3261 destoffset = decode_rl_address(emu); 3262 imm = fetch_word_imm(emu); 3263 store_data_word(emu, destoffset, imm); 3264 } else { 3265 destreg = decode_rl_word_register(emu); 3266 imm = fetch_word_imm(emu); 3267 *destreg = imm; 3268 } 3269 } 3270 3271 static void 3272 x86emuOp_mov_word_RM_IMM(struct x86emu *emu) 3273 { 3274 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3275 x86emuOp32_mov_word_RM_IMM(emu); 3276 else 3277 x86emuOp16_mov_word_RM_IMM(emu); 3278 } 3279 3280 /* 3281 * REMARKS: 3282 * Handles opcode 0xc8 3283 */ 3284 static void 3285 x86emuOp_enter(struct x86emu *emu) 3286 { 3287 uint16_t local, frame_pointer; 3288 uint8_t nesting; 3289 int i; 3290 3291 local = fetch_word_imm(emu); 3292 nesting = fetch_byte_imm(emu); 3293 push_word(emu, emu->x86.R_BP); 3294 frame_pointer = emu->x86.R_SP; 3295 if (nesting > 0) { 3296 for (i = 1; i < nesting; i++) { 3297 emu->x86.R_BP -= 2; 3298 push_word(emu, fetch_word(emu, emu->x86.R_SS, emu->x86.R_BP)); 3299 } 3300 push_word(emu, frame_pointer); 3301 } 3302 emu->x86.R_BP = frame_pointer; 3303 emu->x86.R_SP = (uint16_t) (emu->x86.R_SP - local); 3304 } 3305 3306 /* 3307 * REMARKS: 3308 * Handles opcode 0xc9 3309 */ 3310 static void 3311 x86emuOp_leave(struct x86emu *emu) 3312 { 3313 emu->x86.R_SP = emu->x86.R_BP; 3314 emu->x86.R_BP = pop_word(emu); 3315 } 3316 3317 /* 3318 * REMARKS: 3319 * Handles opcode 0xca 3320 */ 3321 static void 3322 x86emuOp_ret_far_IMM(struct x86emu *emu) 3323 { 3324 uint16_t imm; 3325 3326 imm = fetch_word_imm(emu); 3327 emu->x86.R_IP = pop_word(emu); 3328 emu->x86.R_CS = pop_word(emu); 3329 emu->x86.R_SP += imm; 3330 } 3331 3332 /* 3333 * REMARKS: 3334 * Handles opcode 0xcb 3335 */ 3336 static void 3337 x86emuOp_ret_far(struct x86emu *emu) 3338 { 3339 emu->x86.R_IP = pop_word(emu); 3340 emu->x86.R_CS = pop_word(emu); 3341 } 3342 3343 /* 3344 * REMARKS: 3345 * Handles opcode 0xcc 3346 */ 3347 static void 3348 x86emuOp_int3(struct x86emu *emu) 3349 { 3350 x86emu_intr_dispatch(emu, 3); 3351 } 3352 3353 /* 3354 * REMARKS: 3355 * Handles opcode 0xcd 3356 */ 3357 static void 3358 x86emuOp_int_IMM(struct x86emu *emu) 3359 { 3360 uint8_t intnum; 3361 3362 intnum = fetch_byte_imm(emu); 3363 x86emu_intr_dispatch(emu, intnum); 3364 } 3365 3366 /* 3367 * REMARKS: 3368 * Handles opcode 0xce 3369 */ 3370 static void 3371 x86emuOp_into(struct x86emu *emu) 3372 { 3373 if (ACCESS_FLAG(F_OF)) 3374 x86emu_intr_dispatch(emu, 4); 3375 } 3376 3377 /* 3378 * REMARKS: 3379 * Handles opcode 0xcf 3380 */ 3381 static void 3382 x86emuOp_iret(struct x86emu *emu) 3383 { 3384 emu->x86.R_IP = pop_word(emu); 3385 emu->x86.R_CS = pop_word(emu); 3386 emu->x86.R_FLG = pop_word(emu); 3387 } 3388 3389 /* 3390 * REMARKS: 3391 * Handles opcode 0xd0 3392 */ 3393 static void 3394 x86emuOp_opcD0_byte_RM_1(struct x86emu *emu) 3395 { 3396 uint8_t destval; 3397 3398 fetch_decode_modrm(emu); 3399 destval = decode_and_fetch_byte(emu); 3400 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, 1); 3401 write_back_byte(emu, destval); 3402 } 3403 3404 /* 3405 * REMARKS: 3406 * Handles opcode 0xd1 3407 */ 3408 static void 3409 x86emuOp_opcD1_word_RM_1(struct x86emu *emu) 3410 { 3411 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3412 uint32_t destval; 3413 3414 fetch_decode_modrm(emu); 3415 destval = decode_and_fetch_long(emu); 3416 destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, 1); 3417 write_back_long(emu, destval); 3418 } else { 3419 uint16_t destval; 3420 3421 fetch_decode_modrm(emu); 3422 destval = decode_and_fetch_word(emu); 3423 destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, 1); 3424 write_back_word(emu, destval); 3425 } 3426 } 3427 3428 /* 3429 * REMARKS: 3430 * Handles opcode 0xd2 3431 */ 3432 static void 3433 x86emuOp_opcD2_byte_RM_CL(struct x86emu *emu) 3434 { 3435 uint8_t destval; 3436 3437 fetch_decode_modrm(emu); 3438 destval = decode_and_fetch_byte(emu); 3439 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL); 3440 write_back_byte(emu, destval); 3441 } 3442 3443 /* 3444 * REMARKS: 3445 * Handles opcode 0xd3 3446 */ 3447 static void 3448 x86emuOp_opcD3_word_RM_CL(struct x86emu *emu) 3449 { 3450 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3451 uint32_t destval; 3452 3453 fetch_decode_modrm(emu); 3454 destval = decode_and_fetch_long(emu); 3455 destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL); 3456 write_back_long(emu, destval); 3457 } else { 3458 uint16_t destval; 3459 3460 fetch_decode_modrm(emu); 3461 destval = decode_and_fetch_word(emu); 3462 destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL); 3463 write_back_word(emu, destval); 3464 } 3465 } 3466 3467 /* 3468 * REMARKS: 3469 * Handles opcode 0xd4 3470 */ 3471 static void 3472 x86emuOp_aam(struct x86emu *emu) 3473 { 3474 uint8_t a; 3475 3476 a = fetch_byte_imm(emu); /* this is a stupid encoding. */ 3477 if (a != 10) { 3478 /* fix: add base decoding aam_word(uint8_t val, int base a) */ 3479 x86emu_halt_sys(emu); 3480 } 3481 /* note the type change here --- returning AL and AH in AX. */ 3482 emu->x86.R_AX = aam_word(emu, emu->x86.R_AL); 3483 } 3484 3485 /* 3486 * REMARKS: 3487 * Handles opcode 0xd5 3488 */ 3489 static void 3490 x86emuOp_aad(struct x86emu *emu) 3491 { 3492 uint8_t a; 3493 3494 a = fetch_byte_imm(emu); 3495 if (a != 10) { 3496 /* fix: add base decoding aad_word(uint16_t val, int base a) */ 3497 x86emu_halt_sys(emu); 3498 } 3499 emu->x86.R_AX = aad_word(emu, emu->x86.R_AX); 3500 } 3501 /* opcode 0xd6 ILLEGAL OPCODE */ 3502 3503 3504 /* 3505 * REMARKS: 3506 * Handles opcode 0xd7 3507 */ 3508 static void 3509 x86emuOp_xlat(struct x86emu *emu) 3510 { 3511 uint16_t addr; 3512 3513 addr = (uint16_t) (emu->x86.R_BX + (uint8_t) emu->x86.R_AL); 3514 emu->x86.R_AL = fetch_data_byte(emu, addr); 3515 } 3516 3517 /* opcode=0xd8 */ 3518 static void 3519 x86emuOp_esc_coprocess_d8(struct x86emu *emu) 3520 { 3521 } 3522 /* opcode=0xd9 */ 3523 static void 3524 x86emuOp_esc_coprocess_d9(struct x86emu *emu) 3525 { 3526 fetch_decode_modrm(emu); 3527 if (emu->cur_mod != 3) 3528 decode_rl_address(emu); 3529 } 3530 /* opcode=0xda */ 3531 static void 3532 x86emuOp_esc_coprocess_da(struct x86emu *emu) 3533 { 3534 fetch_decode_modrm(emu); 3535 if (emu->cur_mod != 3) 3536 decode_rl_address(emu); 3537 } 3538 /* opcode=0xdb */ 3539 static void 3540 x86emuOp_esc_coprocess_db(struct x86emu *emu) 3541 { 3542 fetch_decode_modrm(emu); 3543 if (emu->cur_mod != 3) 3544 decode_rl_address(emu); 3545 } 3546 /* opcode=0xdc */ 3547 static void 3548 x86emuOp_esc_coprocess_dc(struct x86emu *emu) 3549 { 3550 fetch_decode_modrm(emu); 3551 if (emu->cur_mod != 3) 3552 decode_rl_address(emu); 3553 } 3554 /* opcode=0xdd */ 3555 static void 3556 x86emuOp_esc_coprocess_dd(struct x86emu *emu) 3557 { 3558 fetch_decode_modrm(emu); 3559 if (emu->cur_mod != 3) 3560 decode_rl_address(emu); 3561 } 3562 /* opcode=0xde */ 3563 static void 3564 x86emuOp_esc_coprocess_de(struct x86emu *emu) 3565 { 3566 fetch_decode_modrm(emu); 3567 if (emu->cur_mod != 3) 3568 decode_rl_address(emu); 3569 } 3570 /* opcode=0xdf */ 3571 static void 3572 x86emuOp_esc_coprocess_df(struct x86emu *emu) 3573 { 3574 fetch_decode_modrm(emu); 3575 if (emu->cur_mod != 3) 3576 decode_rl_address(emu); 3577 } 3578 3579 3580 /* 3581 * REMARKS: 3582 * Handles opcode 0xe0 3583 */ 3584 static void 3585 x86emuOp_loopne(struct x86emu *emu) 3586 { 3587 int16_t ip; 3588 3589 ip = (int8_t) fetch_byte_imm(emu); 3590 ip += (int16_t) emu->x86.R_IP; 3591 emu->x86.R_CX -= 1; 3592 if (emu->x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */ 3593 emu->x86.R_IP = ip; 3594 } 3595 3596 /* 3597 * REMARKS: 3598 * Handles opcode 0xe1 3599 */ 3600 static void 3601 x86emuOp_loope(struct x86emu *emu) 3602 { 3603 int16_t ip; 3604 3605 ip = (int8_t) fetch_byte_imm(emu); 3606 ip += (int16_t) emu->x86.R_IP; 3607 emu->x86.R_CX -= 1; 3608 if (emu->x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */ 3609 emu->x86.R_IP = ip; 3610 } 3611 3612 /* 3613 * REMARKS: 3614 * Handles opcode 0xe2 3615 */ 3616 static void 3617 x86emuOp_loop(struct x86emu *emu) 3618 { 3619 int16_t ip; 3620 3621 ip = (int8_t) fetch_byte_imm(emu); 3622 ip += (int16_t) emu->x86.R_IP; 3623 emu->x86.R_CX -= 1; 3624 if (emu->x86.R_CX != 0) 3625 emu->x86.R_IP = ip; 3626 } 3627 3628 /* 3629 * REMARKS: 3630 * Handles opcode 0xe3 3631 */ 3632 static void 3633 x86emuOp_jcxz(struct x86emu *emu) 3634 { 3635 uint16_t target; 3636 int8_t offset; 3637 3638 /* jump to byte offset if overflow flag is set */ 3639 offset = (int8_t) fetch_byte_imm(emu); 3640 target = (uint16_t) (emu->x86.R_IP + offset); 3641 if (emu->x86.R_CX == 0) 3642 emu->x86.R_IP = target; 3643 } 3644 3645 /* 3646 * REMARKS: 3647 * Handles opcode 0xe4 3648 */ 3649 static void 3650 x86emuOp_in_byte_AL_IMM(struct x86emu *emu) 3651 { 3652 uint8_t port; 3653 3654 port = (uint8_t) fetch_byte_imm(emu); 3655 emu->x86.R_AL = (*emu->emu_inb) (emu, port); 3656 } 3657 3658 /* 3659 * REMARKS: 3660 * Handles opcode 0xe5 3661 */ 3662 static void 3663 x86emuOp_in_word_AX_IMM(struct x86emu *emu) 3664 { 3665 uint8_t port; 3666 3667 port = (uint8_t) fetch_byte_imm(emu); 3668 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3669 emu->x86.R_EAX = (*emu->emu_inl) (emu, port); 3670 } else { 3671 emu->x86.R_AX = (*emu->emu_inw) (emu, port); 3672 } 3673 } 3674 3675 /* 3676 * REMARKS: 3677 * Handles opcode 0xe6 3678 */ 3679 static void 3680 x86emuOp_out_byte_IMM_AL(struct x86emu *emu) 3681 { 3682 uint8_t port; 3683 3684 port = (uint8_t) fetch_byte_imm(emu); 3685 (*emu->emu_outb) (emu, port, emu->x86.R_AL); 3686 } 3687 3688 /* 3689 * REMARKS: 3690 * Handles opcode 0xe7 3691 */ 3692 static void 3693 x86emuOp_out_word_IMM_AX(struct x86emu *emu) 3694 { 3695 uint8_t port; 3696 3697 port = (uint8_t) fetch_byte_imm(emu); 3698 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3699 (*emu->emu_outl) (emu, port, emu->x86.R_EAX); 3700 } else { 3701 (*emu->emu_outw) (emu, port, emu->x86.R_AX); 3702 } 3703 } 3704 3705 /* 3706 * REMARKS: 3707 * Handles opcode 0xe8 3708 */ 3709 static void 3710 x86emuOp_call_near_IMM(struct x86emu *emu) 3711 { 3712 int16_t ip; 3713 3714 ip = (int16_t) fetch_word_imm(emu); 3715 ip += (int16_t) emu->x86.R_IP; /* CHECK SIGN */ 3716 push_word(emu, emu->x86.R_IP); 3717 emu->x86.R_IP = ip; 3718 } 3719 3720 /* 3721 * REMARKS: 3722 * Handles opcode 0xe9 3723 */ 3724 static void 3725 x86emuOp_jump_near_IMM(struct x86emu *emu) 3726 { 3727 int ip; 3728 3729 ip = (int16_t) fetch_word_imm(emu); 3730 ip += (int16_t) emu->x86.R_IP; 3731 emu->x86.R_IP = (uint16_t) ip; 3732 } 3733 3734 /* 3735 * REMARKS: 3736 * Handles opcode 0xea 3737 */ 3738 static void 3739 x86emuOp_jump_far_IMM(struct x86emu *emu) 3740 { 3741 uint16_t cs, ip; 3742 3743 ip = fetch_word_imm(emu); 3744 cs = fetch_word_imm(emu); 3745 emu->x86.R_IP = ip; 3746 emu->x86.R_CS = cs; 3747 } 3748 3749 /* 3750 * REMARKS: 3751 * Handles opcode 0xeb 3752 */ 3753 static void 3754 x86emuOp_jump_byte_IMM(struct x86emu *emu) 3755 { 3756 uint16_t target; 3757 int8_t offset; 3758 3759 offset = (int8_t) fetch_byte_imm(emu); 3760 target = (uint16_t) (emu->x86.R_IP + offset); 3761 emu->x86.R_IP = target; 3762 } 3763 3764 /* 3765 * REMARKS: 3766 * Handles opcode 0xec 3767 */ 3768 static void 3769 x86emuOp_in_byte_AL_DX(struct x86emu *emu) 3770 { 3771 emu->x86.R_AL = (*emu->emu_inb) (emu, emu->x86.R_DX); 3772 } 3773 3774 /* 3775 * REMARKS: 3776 * Handles opcode 0xed 3777 */ 3778 static void 3779 x86emuOp_in_word_AX_DX(struct x86emu *emu) 3780 { 3781 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3782 emu->x86.R_EAX = (*emu->emu_inl) (emu, emu->x86.R_DX); 3783 } else { 3784 emu->x86.R_AX = (*emu->emu_inw) (emu, emu->x86.R_DX); 3785 } 3786 } 3787 3788 /* 3789 * REMARKS: 3790 * Handles opcode 0xee 3791 */ 3792 static void 3793 x86emuOp_out_byte_DX_AL(struct x86emu *emu) 3794 { 3795 (*emu->emu_outb) (emu, emu->x86.R_DX, emu->x86.R_AL); 3796 } 3797 3798 /* 3799 * REMARKS: 3800 * Handles opcode 0xef 3801 */ 3802 static void 3803 x86emuOp_out_word_DX_AX(struct x86emu *emu) 3804 { 3805 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3806 (*emu->emu_outl) (emu, emu->x86.R_DX, emu->x86.R_EAX); 3807 } else { 3808 (*emu->emu_outw) (emu, emu->x86.R_DX, emu->x86.R_AX); 3809 } 3810 } 3811 3812 /* 3813 * REMARKS: 3814 * Handles opcode 0xf0 3815 */ 3816 static void 3817 x86emuOp_lock(struct x86emu *emu) 3818 { 3819 } 3820 /*opcode 0xf1 ILLEGAL OPERATION */ 3821 3822 3823 /* 3824 * REMARKS: 3825 * Handles opcode 0xf5 3826 */ 3827 static void 3828 x86emuOp_cmc(struct x86emu *emu) 3829 { 3830 if (ACCESS_FLAG(F_CF)) 3831 CLEAR_FLAG(F_CF); 3832 else 3833 SET_FLAG(F_CF); 3834 } 3835 3836 /* 3837 * REMARKS: 3838 * Handles opcode 0xf6 3839 */ 3840 static void 3841 x86emuOp_opcF6_byte_RM(struct x86emu *emu) 3842 { 3843 uint8_t destval, srcval; 3844 3845 /* long, drawn out code follows. Double switch for a total of 32 3846 * cases. */ 3847 fetch_decode_modrm(emu); 3848 if (emu->cur_rh == 1) 3849 x86emu_halt_sys(emu); 3850 3851 if (emu->cur_rh == 0) { 3852 destval = decode_and_fetch_byte_imm8(emu, &srcval); 3853 test_byte(emu, destval, srcval); 3854 return; 3855 } 3856 destval = decode_and_fetch_byte(emu); 3857 switch (emu->cur_rh) { 3858 case 2: 3859 destval = ~destval; 3860 write_back_byte(emu, destval); 3861 break; 3862 case 3: 3863 destval = neg_byte(emu, destval); 3864 write_back_byte(emu, destval); 3865 break; 3866 case 4: 3867 mul_byte(emu, destval); 3868 break; 3869 case 5: 3870 imul_byte(emu, destval); 3871 break; 3872 case 6: 3873 div_byte(emu, destval); 3874 break; 3875 case 7: 3876 idiv_byte(emu, destval); 3877 break; 3878 } 3879 } 3880 3881 /* 3882 * REMARKS: 3883 * Handles opcode 0xf7 3884 */ 3885 static void 3886 x86emuOp32_opcF7_word_RM(struct x86emu *emu) 3887 { 3888 uint32_t destval, srcval; 3889 3890 /* long, drawn out code follows. Double switch for a total of 32 3891 * cases. */ 3892 fetch_decode_modrm(emu); 3893 if (emu->cur_rh == 1) 3894 x86emu_halt_sys(emu); 3895 3896 if (emu->cur_rh == 0) { 3897 if (emu->cur_mod != 3) { 3898 uint32_t destoffset; 3899 3900 destoffset = decode_rl_address(emu); 3901 srcval = fetch_long_imm(emu); 3902 destval = fetch_data_long(emu, destoffset); 3903 } else { 3904 srcval = fetch_long_imm(emu); 3905 destval = *decode_rl_long_register(emu); 3906 } 3907 test_long(emu, destval, srcval); 3908 return; 3909 } 3910 destval = decode_and_fetch_long(emu); 3911 switch (emu->cur_rh) { 3912 case 2: 3913 destval = ~destval; 3914 write_back_long(emu, destval); 3915 break; 3916 case 3: 3917 destval = neg_long(emu, destval); 3918 write_back_long(emu, destval); 3919 break; 3920 case 4: 3921 mul_long(emu, destval); 3922 break; 3923 case 5: 3924 imul_long(emu, destval); 3925 break; 3926 case 6: 3927 div_long(emu, destval); 3928 break; 3929 case 7: 3930 idiv_long(emu, destval); 3931 break; 3932 } 3933 } 3934 static void 3935 x86emuOp16_opcF7_word_RM(struct x86emu *emu) 3936 { 3937 uint16_t destval, srcval; 3938 3939 /* long, drawn out code follows. Double switch for a total of 32 3940 * cases. */ 3941 fetch_decode_modrm(emu); 3942 if (emu->cur_rh == 1) 3943 x86emu_halt_sys(emu); 3944 3945 if (emu->cur_rh == 0) { 3946 if (emu->cur_mod != 3) { 3947 uint32_t destoffset; 3948 3949 destoffset = decode_rl_address(emu); 3950 srcval = fetch_word_imm(emu); 3951 destval = fetch_data_word(emu, destoffset); 3952 } else { 3953 srcval = fetch_word_imm(emu); 3954 destval = *decode_rl_word_register(emu); 3955 } 3956 test_word(emu, destval, srcval); 3957 return; 3958 } 3959 destval = decode_and_fetch_word(emu); 3960 switch (emu->cur_rh) { 3961 case 2: 3962 destval = ~destval; 3963 write_back_word(emu, destval); 3964 break; 3965 case 3: 3966 destval = neg_word(emu, destval); 3967 write_back_word(emu, destval); 3968 break; 3969 case 4: 3970 mul_word(emu, destval); 3971 break; 3972 case 5: 3973 imul_word(emu, destval); 3974 break; 3975 case 6: 3976 div_word(emu, destval); 3977 break; 3978 case 7: 3979 idiv_word(emu, destval); 3980 break; 3981 } 3982 } 3983 static void 3984 x86emuOp_opcF7_word_RM(struct x86emu *emu) 3985 { 3986 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3987 x86emuOp32_opcF7_word_RM(emu); 3988 else 3989 x86emuOp16_opcF7_word_RM(emu); 3990 } 3991 3992 /* 3993 * REMARKS: 3994 * Handles opcode 0xfe 3995 */ 3996 static void 3997 x86emuOp_opcFE_byte_RM(struct x86emu *emu) 3998 { 3999 uint8_t destval; 4000 uint32_t destoffset; 4001 uint8_t *destreg; 4002 4003 /* Yet another special case instruction. */ 4004 fetch_decode_modrm(emu); 4005 if (emu->cur_mod != 3) { 4006 destoffset = decode_rl_address(emu); 4007 switch (emu->cur_rh) { 4008 case 0: /* inc word ptr ... */ 4009 destval = fetch_data_byte(emu, destoffset); 4010 destval = inc_byte(emu, destval); 4011 store_data_byte(emu, destoffset, destval); 4012 break; 4013 case 1: /* dec word ptr ... */ 4014 destval = fetch_data_byte(emu, destoffset); 4015 destval = dec_byte(emu, destval); 4016 store_data_byte(emu, destoffset, destval); 4017 break; 4018 } 4019 } else { 4020 destreg = decode_rl_byte_register(emu); 4021 switch (emu->cur_rh) { 4022 case 0: 4023 *destreg = inc_byte(emu, *destreg); 4024 break; 4025 case 1: 4026 *destreg = dec_byte(emu, *destreg); 4027 break; 4028 } 4029 } 4030 } 4031 4032 /* 4033 * REMARKS: 4034 * Handles opcode 0xff 4035 */ 4036 static void 4037 x86emuOp32_opcFF_word_RM(struct x86emu *emu) 4038 { 4039 uint32_t destoffset = 0; 4040 uint32_t destval, *destreg; 4041 4042 if (emu->cur_mod != 3) { 4043 destoffset = decode_rl_address(emu); 4044 destval = fetch_data_long(emu, destoffset); 4045 switch (emu->cur_rh) { 4046 case 0: /* inc word ptr ... */ 4047 destval = inc_long(emu, destval); 4048 store_data_long(emu, destoffset, destval); 4049 break; 4050 case 1: /* dec word ptr ... */ 4051 destval = dec_long(emu, destval); 4052 store_data_long(emu, destoffset, destval); 4053 break; 4054 case 6: /* push word ptr ... */ 4055 push_long(emu, destval); 4056 break; 4057 } 4058 } else { 4059 destreg = decode_rl_long_register(emu); 4060 switch (emu->cur_rh) { 4061 case 0: 4062 *destreg = inc_long(emu, *destreg); 4063 break; 4064 case 1: 4065 *destreg = dec_long(emu, *destreg); 4066 break; 4067 case 6: 4068 push_long(emu, *destreg); 4069 break; 4070 } 4071 } 4072 } 4073 4074 static void 4075 x86emuOp16_opcFF_word_RM(struct x86emu *emu) 4076 { 4077 uint32_t destoffset = 0; 4078 uint16_t *destreg; 4079 uint16_t destval; 4080 4081 if (emu->cur_mod != 3) { 4082 destoffset = decode_rl_address(emu); 4083 destval = fetch_data_word(emu, destoffset); 4084 switch (emu->cur_rh) { 4085 case 0: 4086 destval = inc_word(emu, destval); 4087 store_data_word(emu, destoffset, destval); 4088 break; 4089 case 1: /* dec word ptr ... */ 4090 destval = dec_word(emu, destval); 4091 store_data_word(emu, destoffset, destval); 4092 break; 4093 case 6: /* push word ptr ... */ 4094 push_word(emu, destval); 4095 break; 4096 } 4097 } else { 4098 destreg = decode_rl_word_register(emu); 4099 switch (emu->cur_rh) { 4100 case 0: 4101 *destreg = inc_word(emu, *destreg); 4102 break; 4103 case 1: 4104 *destreg = dec_word(emu, *destreg); 4105 break; 4106 case 6: 4107 push_word(emu, *destreg); 4108 break; 4109 } 4110 } 4111 } 4112 4113 static void 4114 x86emuOp_opcFF_word_RM(struct x86emu *emu) 4115 { 4116 uint32_t destoffset = 0; 4117 uint16_t destval, destval2; 4118 4119 /* Yet another special case instruction. */ 4120 fetch_decode_modrm(emu); 4121 if ((emu->cur_mod == 3 && (emu->cur_rh == 3 || emu->cur_rh == 5)) || emu->cur_rh == 7) 4122 x86emu_halt_sys(emu); 4123 if (emu->cur_rh == 0 || emu->cur_rh == 1 || emu->cur_rh == 6) { 4124 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 4125 x86emuOp32_opcFF_word_RM(emu); 4126 else 4127 x86emuOp16_opcFF_word_RM(emu); 4128 return; 4129 } 4130 4131 if (emu->cur_mod != 3) { 4132 destoffset = decode_rl_address(emu); 4133 destval = fetch_data_word(emu, destoffset); 4134 switch (emu->cur_rh) { 4135 case 3: /* call far ptr ... */ 4136 destval2 = fetch_data_word(emu, destoffset + 2); 4137 push_word(emu, emu->x86.R_CS); 4138 emu->x86.R_CS = destval2; 4139 push_word(emu, emu->x86.R_IP); 4140 emu->x86.R_IP = destval; 4141 break; 4142 case 5: /* jmp far ptr ... */ 4143 destval2 = fetch_data_word(emu, destoffset + 2); 4144 emu->x86.R_IP = destval; 4145 emu->x86.R_CS = destval2; 4146 break; 4147 } 4148 } else { 4149 destval = *decode_rl_word_register(emu); 4150 } 4151 4152 switch (emu->cur_rh) { 4153 case 2: /* call word ptr */ 4154 push_word(emu, emu->x86.R_IP); 4155 emu->x86.R_IP = destval; 4156 break; 4157 case 4: /* jmp */ 4158 emu->x86.R_IP = destval; 4159 break; 4160 } 4161 } 4162 4163 /* 4164 * * Single byte operation code table: 4165 */ 4166 static void 4167 x86emu_exec_one_byte(struct x86emu * emu) 4168 { 4169 uint8_t op1; 4170 4171 op1 = fetch_byte_imm(emu); 4172 4173 switch (op1) { 4174 case 0x00: 4175 common_binop_byte_rm_r(emu, add_byte); 4176 break; 4177 case 0x01: 4178 common_binop_word_long_rm_r(emu, add_word, add_long); 4179 break; 4180 case 0x02: 4181 common_binop_byte_r_rm(emu, add_byte); 4182 break; 4183 case 0x03: 4184 common_binop_word_long_r_rm(emu, add_word, add_long); 4185 break; 4186 case 0x04: 4187 common_binop_byte_imm(emu, add_byte); 4188 break; 4189 case 0x05: 4190 common_binop_word_long_imm(emu, add_word, add_long); 4191 break; 4192 case 0x06: 4193 push_word(emu, emu->x86.R_ES); 4194 break; 4195 case 0x07: 4196 emu->x86.R_ES = pop_word(emu); 4197 break; 4198 4199 case 0x08: 4200 common_binop_byte_rm_r(emu, or_byte); 4201 break; 4202 case 0x09: 4203 common_binop_word_long_rm_r(emu, or_word, or_long); 4204 break; 4205 case 0x0a: 4206 common_binop_byte_r_rm(emu, or_byte); 4207 break; 4208 case 0x0b: 4209 common_binop_word_long_r_rm(emu, or_word, or_long); 4210 break; 4211 case 0x0c: 4212 common_binop_byte_imm(emu, or_byte); 4213 break; 4214 case 0x0d: 4215 common_binop_word_long_imm(emu, or_word, or_long); 4216 break; 4217 case 0x0e: 4218 push_word(emu, emu->x86.R_CS); 4219 break; 4220 case 0x0f: 4221 x86emu_exec_two_byte(emu); 4222 break; 4223 4224 case 0x10: 4225 common_binop_byte_rm_r(emu, adc_byte); 4226 break; 4227 case 0x11: 4228 common_binop_word_long_rm_r(emu, adc_word, adc_long); 4229 break; 4230 case 0x12: 4231 common_binop_byte_r_rm(emu, adc_byte); 4232 break; 4233 case 0x13: 4234 common_binop_word_long_r_rm(emu, adc_word, adc_long); 4235 break; 4236 case 0x14: 4237 common_binop_byte_imm(emu, adc_byte); 4238 break; 4239 case 0x15: 4240 common_binop_word_long_imm(emu, adc_word, adc_long); 4241 break; 4242 case 0x16: 4243 push_word(emu, emu->x86.R_SS); 4244 break; 4245 case 0x17: 4246 emu->x86.R_SS = pop_word(emu); 4247 break; 4248 4249 case 0x18: 4250 common_binop_byte_rm_r(emu, sbb_byte); 4251 break; 4252 case 0x19: 4253 common_binop_word_long_rm_r(emu, sbb_word, sbb_long); 4254 break; 4255 case 0x1a: 4256 common_binop_byte_r_rm(emu, sbb_byte); 4257 break; 4258 case 0x1b: 4259 common_binop_word_long_r_rm(emu, sbb_word, sbb_long); 4260 break; 4261 case 0x1c: 4262 common_binop_byte_imm(emu, sbb_byte); 4263 break; 4264 case 0x1d: 4265 common_binop_word_long_imm(emu, sbb_word, sbb_long); 4266 break; 4267 case 0x1e: 4268 push_word(emu, emu->x86.R_DS); 4269 break; 4270 case 0x1f: 4271 emu->x86.R_DS = pop_word(emu); 4272 break; 4273 4274 case 0x20: 4275 common_binop_byte_rm_r(emu, and_byte); 4276 break; 4277 case 0x21: 4278 common_binop_word_long_rm_r(emu, and_word, and_long); 4279 break; 4280 case 0x22: 4281 common_binop_byte_r_rm(emu, and_byte); 4282 break; 4283 case 0x23: 4284 common_binop_word_long_r_rm(emu, and_word, and_long); 4285 break; 4286 case 0x24: 4287 common_binop_byte_imm(emu, and_byte); 4288 break; 4289 case 0x25: 4290 common_binop_word_long_imm(emu, and_word, and_long); 4291 break; 4292 case 0x26: 4293 emu->x86.mode |= SYSMODE_SEGOVR_ES; 4294 break; 4295 case 0x27: 4296 emu->x86.R_AL = daa_byte(emu, emu->x86.R_AL); 4297 break; 4298 4299 case 0x28: 4300 common_binop_byte_rm_r(emu, sub_byte); 4301 break; 4302 case 0x29: 4303 common_binop_word_long_rm_r(emu, sub_word, sub_long); 4304 break; 4305 case 0x2a: 4306 common_binop_byte_r_rm(emu, sub_byte); 4307 break; 4308 case 0x2b: 4309 common_binop_word_long_r_rm(emu, sub_word, sub_long); 4310 break; 4311 case 0x2c: 4312 common_binop_byte_imm(emu, sub_byte); 4313 break; 4314 case 0x2d: 4315 common_binop_word_long_imm(emu, sub_word, sub_long); 4316 break; 4317 case 0x2e: 4318 emu->x86.mode |= SYSMODE_SEGOVR_CS; 4319 break; 4320 case 0x2f: 4321 emu->x86.R_AL = das_byte(emu, emu->x86.R_AL); 4322 break; 4323 4324 case 0x30: 4325 common_binop_byte_rm_r(emu, xor_byte); 4326 break; 4327 case 0x31: 4328 common_binop_word_long_rm_r(emu, xor_word, xor_long); 4329 break; 4330 case 0x32: 4331 common_binop_byte_r_rm(emu, xor_byte); 4332 break; 4333 case 0x33: 4334 common_binop_word_long_r_rm(emu, xor_word, xor_long); 4335 break; 4336 case 0x34: 4337 common_binop_byte_imm(emu, xor_byte); 4338 break; 4339 case 0x35: 4340 common_binop_word_long_imm(emu, xor_word, xor_long); 4341 break; 4342 case 0x36: 4343 emu->x86.mode |= SYSMODE_SEGOVR_SS; 4344 break; 4345 case 0x37: 4346 emu->x86.R_AX = aaa_word(emu, emu->x86.R_AX); 4347 break; 4348 4349 case 0x38: 4350 common_binop_ns_byte_rm_r(emu, cmp_byte_no_return); 4351 break; 4352 case 0x39: 4353 common_binop_ns_word_long_rm_r(emu, cmp_word_no_return, 4354 cmp_long_no_return); 4355 break; 4356 case 0x3a: 4357 x86emuOp_cmp_byte_R_RM(emu); 4358 break; 4359 case 0x3b: 4360 x86emuOp_cmp_word_R_RM(emu); 4361 break; 4362 case 0x3c: 4363 x86emuOp_cmp_byte_AL_IMM(emu); 4364 break; 4365 case 0x3d: 4366 x86emuOp_cmp_word_AX_IMM(emu); 4367 break; 4368 case 0x3e: 4369 emu->x86.mode |= SYSMODE_SEGOVR_DS; 4370 break; 4371 case 0x3f: 4372 emu->x86.R_AX = aas_word(emu, emu->x86.R_AX); 4373 break; 4374 4375 case 0x40: 4376 common_inc_word_long(emu, &emu->x86.register_a); 4377 break; 4378 case 0x41: 4379 common_inc_word_long(emu, &emu->x86.register_c); 4380 break; 4381 case 0x42: 4382 common_inc_word_long(emu, &emu->x86.register_d); 4383 break; 4384 case 0x43: 4385 common_inc_word_long(emu, &emu->x86.register_b); 4386 break; 4387 case 0x44: 4388 common_inc_word_long(emu, &emu->x86.register_sp); 4389 break; 4390 case 0x45: 4391 common_inc_word_long(emu, &emu->x86.register_bp); 4392 break; 4393 case 0x46: 4394 common_inc_word_long(emu, &emu->x86.register_si); 4395 break; 4396 case 0x47: 4397 common_inc_word_long(emu, &emu->x86.register_di); 4398 break; 4399 4400 case 0x48: 4401 common_dec_word_long(emu, &emu->x86.register_a); 4402 break; 4403 case 0x49: 4404 common_dec_word_long(emu, &emu->x86.register_c); 4405 break; 4406 case 0x4a: 4407 common_dec_word_long(emu, &emu->x86.register_d); 4408 break; 4409 case 0x4b: 4410 common_dec_word_long(emu, &emu->x86.register_b); 4411 break; 4412 case 0x4c: 4413 common_dec_word_long(emu, &emu->x86.register_sp); 4414 break; 4415 case 0x4d: 4416 common_dec_word_long(emu, &emu->x86.register_bp); 4417 break; 4418 case 0x4e: 4419 common_dec_word_long(emu, &emu->x86.register_si); 4420 break; 4421 case 0x4f: 4422 common_dec_word_long(emu, &emu->x86.register_di); 4423 break; 4424 4425 case 0x50: 4426 common_push_word_long(emu, &emu->x86.register_a); 4427 break; 4428 case 0x51: 4429 common_push_word_long(emu, &emu->x86.register_c); 4430 break; 4431 case 0x52: 4432 common_push_word_long(emu, &emu->x86.register_d); 4433 break; 4434 case 0x53: 4435 common_push_word_long(emu, &emu->x86.register_b); 4436 break; 4437 case 0x54: 4438 common_push_word_long(emu, &emu->x86.register_sp); 4439 break; 4440 case 0x55: 4441 common_push_word_long(emu, &emu->x86.register_bp); 4442 break; 4443 case 0x56: 4444 common_push_word_long(emu, &emu->x86.register_si); 4445 break; 4446 case 0x57: 4447 common_push_word_long(emu, &emu->x86.register_di); 4448 break; 4449 4450 case 0x58: 4451 common_pop_word_long(emu, &emu->x86.register_a); 4452 break; 4453 case 0x59: 4454 common_pop_word_long(emu, &emu->x86.register_c); 4455 break; 4456 case 0x5a: 4457 common_pop_word_long(emu, &emu->x86.register_d); 4458 break; 4459 case 0x5b: 4460 common_pop_word_long(emu, &emu->x86.register_b); 4461 break; 4462 case 0x5c: 4463 common_pop_word_long(emu, &emu->x86.register_sp); 4464 break; 4465 case 0x5d: 4466 common_pop_word_long(emu, &emu->x86.register_bp); 4467 break; 4468 case 0x5e: 4469 common_pop_word_long(emu, &emu->x86.register_si); 4470 break; 4471 case 0x5f: 4472 common_pop_word_long(emu, &emu->x86.register_di); 4473 break; 4474 4475 case 0x60: 4476 x86emuOp_push_all(emu); 4477 break; 4478 case 0x61: 4479 x86emuOp_pop_all(emu); 4480 break; 4481 /* 0x62 bound */ 4482 /* 0x63 arpl */ 4483 case 0x64: 4484 emu->x86.mode |= SYSMODE_SEGOVR_FS; 4485 break; 4486 case 0x65: 4487 emu->x86.mode |= SYSMODE_SEGOVR_GS; 4488 break; 4489 case 0x66: 4490 emu->x86.mode |= SYSMODE_PREFIX_DATA; 4491 break; 4492 case 0x67: 4493 emu->x86.mode |= SYSMODE_PREFIX_ADDR; 4494 break; 4495 4496 case 0x68: 4497 x86emuOp_push_word_IMM(emu); 4498 break; 4499 case 0x69: 4500 common_imul_imm(emu, 0); 4501 break; 4502 case 0x6a: 4503 x86emuOp_push_byte_IMM(emu); 4504 break; 4505 case 0x6b: 4506 common_imul_imm(emu, 1); 4507 break; 4508 case 0x6c: 4509 ins(emu, 1); 4510 break; 4511 case 0x6d: 4512 x86emuOp_ins_word(emu); 4513 break; 4514 case 0x6e: 4515 outs(emu, 1); 4516 break; 4517 case 0x6f: 4518 x86emuOp_outs_word(emu); 4519 break; 4520 4521 case 0x70: 4522 common_jmp_near(emu, ACCESS_FLAG(F_OF)); 4523 break; 4524 case 0x71: 4525 common_jmp_near(emu, !ACCESS_FLAG(F_OF)); 4526 break; 4527 case 0x72: 4528 common_jmp_near(emu, ACCESS_FLAG(F_CF)); 4529 break; 4530 case 0x73: 4531 common_jmp_near(emu, !ACCESS_FLAG(F_CF)); 4532 break; 4533 case 0x74: 4534 common_jmp_near(emu, ACCESS_FLAG(F_ZF)); 4535 break; 4536 case 0x75: 4537 common_jmp_near(emu, !ACCESS_FLAG(F_ZF)); 4538 break; 4539 case 0x76: 4540 common_jmp_near(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); 4541 break; 4542 case 0x77: 4543 common_jmp_near(emu, !ACCESS_FLAG(F_CF) && !ACCESS_FLAG(F_ZF)); 4544 break; 4545 4546 case 0x78: 4547 common_jmp_near(emu, ACCESS_FLAG(F_SF)); 4548 break; 4549 case 0x79: 4550 common_jmp_near(emu, !ACCESS_FLAG(F_SF)); 4551 break; 4552 case 0x7a: 4553 common_jmp_near(emu, ACCESS_FLAG(F_PF)); 4554 break; 4555 case 0x7b: 4556 common_jmp_near(emu, !ACCESS_FLAG(F_PF)); 4557 break; 4558 case 0x7c: 4559 x86emuOp_jump_near_L(emu); 4560 break; 4561 case 0x7d: 4562 x86emuOp_jump_near_NL(emu); 4563 break; 4564 case 0x7e: 4565 x86emuOp_jump_near_LE(emu); 4566 break; 4567 case 0x7f: 4568 x86emuOp_jump_near_NLE(emu); 4569 break; 4570 4571 case 0x80: 4572 x86emuOp_opc80_byte_RM_IMM(emu); 4573 break; 4574 case 0x81: 4575 x86emuOp_opc81_word_RM_IMM(emu); 4576 break; 4577 case 0x82: 4578 x86emuOp_opc82_byte_RM_IMM(emu); 4579 break; 4580 case 0x83: 4581 x86emuOp_opc83_word_RM_IMM(emu); 4582 break; 4583 case 0x84: 4584 common_binop_ns_byte_rm_r(emu, test_byte); 4585 break; 4586 case 0x85: 4587 common_binop_ns_word_long_rm_r(emu, test_word, test_long); 4588 break; 4589 case 0x86: 4590 x86emuOp_xchg_byte_RM_R(emu); 4591 break; 4592 case 0x87: 4593 x86emuOp_xchg_word_RM_R(emu); 4594 break; 4595 4596 case 0x88: 4597 x86emuOp_mov_byte_RM_R(emu); 4598 break; 4599 case 0x89: 4600 x86emuOp_mov_word_RM_R(emu); 4601 break; 4602 case 0x8a: 4603 x86emuOp_mov_byte_R_RM(emu); 4604 break; 4605 case 0x8b: 4606 x86emuOp_mov_word_R_RM(emu); 4607 break; 4608 case 0x8c: 4609 x86emuOp_mov_word_RM_SR(emu); 4610 break; 4611 case 0x8d: 4612 x86emuOp_lea_word_R_M(emu); 4613 break; 4614 case 0x8e: 4615 x86emuOp_mov_word_SR_RM(emu); 4616 break; 4617 case 0x8f: 4618 x86emuOp_pop_RM(emu); 4619 break; 4620 4621 case 0x90: 4622 /* nop */ 4623 break; 4624 case 0x91: 4625 x86emuOp_xchg_word_AX_CX(emu); 4626 break; 4627 case 0x92: 4628 x86emuOp_xchg_word_AX_DX(emu); 4629 break; 4630 case 0x93: 4631 x86emuOp_xchg_word_AX_BX(emu); 4632 break; 4633 case 0x94: 4634 x86emuOp_xchg_word_AX_SP(emu); 4635 break; 4636 case 0x95: 4637 x86emuOp_xchg_word_AX_BP(emu); 4638 break; 4639 case 0x96: 4640 x86emuOp_xchg_word_AX_SI(emu); 4641 break; 4642 case 0x97: 4643 x86emuOp_xchg_word_AX_DI(emu); 4644 break; 4645 4646 case 0x98: 4647 x86emuOp_cbw(emu); 4648 break; 4649 case 0x99: 4650 x86emuOp_cwd(emu); 4651 break; 4652 case 0x9a: 4653 x86emuOp_call_far_IMM(emu); 4654 break; 4655 case 0x9b: 4656 /* wait */ 4657 break; 4658 case 0x9c: 4659 x86emuOp_pushf_word(emu); 4660 break; 4661 case 0x9d: 4662 x86emuOp_popf_word(emu); 4663 break; 4664 case 0x9e: 4665 x86emuOp_sahf(emu); 4666 break; 4667 case 0x9f: 4668 x86emuOp_lahf(emu); 4669 break; 4670 4671 case 0xa0: 4672 x86emuOp_mov_AL_M_IMM(emu); 4673 break; 4674 case 0xa1: 4675 x86emuOp_mov_AX_M_IMM(emu); 4676 break; 4677 case 0xa2: 4678 x86emuOp_mov_M_AL_IMM(emu); 4679 break; 4680 case 0xa3: 4681 x86emuOp_mov_M_AX_IMM(emu); 4682 break; 4683 case 0xa4: 4684 x86emuOp_movs_byte(emu); 4685 break; 4686 case 0xa5: 4687 x86emuOp_movs_word(emu); 4688 break; 4689 case 0xa6: 4690 x86emuOp_cmps_byte(emu); 4691 break; 4692 case 0xa7: 4693 x86emuOp_cmps_word(emu); 4694 break; 4695 4696 case 0xa8: 4697 test_byte(emu, emu->x86.R_AL, fetch_byte_imm(emu)); 4698 break; 4699 case 0xa9: 4700 x86emuOp_test_AX_IMM(emu); 4701 break; 4702 case 0xaa: 4703 x86emuOp_stos_byte(emu); 4704 break; 4705 case 0xab: 4706 x86emuOp_stos_word(emu); 4707 break; 4708 case 0xac: 4709 x86emuOp_lods_byte(emu); 4710 break; 4711 case 0xad: 4712 x86emuOp_lods_word(emu); 4713 break; 4714 case 0xae: 4715 x86emuOp_scas_byte(emu); 4716 break; 4717 case 0xaf: 4718 x86emuOp_scas_word(emu); 4719 break; 4720 4721 case 0xb0: 4722 emu->x86.R_AL = fetch_byte_imm(emu); 4723 break; 4724 case 0xb1: 4725 emu->x86.R_CL = fetch_byte_imm(emu); 4726 break; 4727 case 0xb2: 4728 emu->x86.R_DL = fetch_byte_imm(emu); 4729 break; 4730 case 0xb3: 4731 emu->x86.R_BL = fetch_byte_imm(emu); 4732 break; 4733 case 0xb4: 4734 emu->x86.R_AH = fetch_byte_imm(emu); 4735 break; 4736 case 0xb5: 4737 emu->x86.R_CH = fetch_byte_imm(emu); 4738 break; 4739 case 0xb6: 4740 emu->x86.R_DH = fetch_byte_imm(emu); 4741 break; 4742 case 0xb7: 4743 emu->x86.R_BH = fetch_byte_imm(emu); 4744 break; 4745 4746 case 0xb8: 4747 x86emuOp_mov_word_AX_IMM(emu); 4748 break; 4749 case 0xb9: 4750 x86emuOp_mov_word_CX_IMM(emu); 4751 break; 4752 case 0xba: 4753 x86emuOp_mov_word_DX_IMM(emu); 4754 break; 4755 case 0xbb: 4756 x86emuOp_mov_word_BX_IMM(emu); 4757 break; 4758 case 0xbc: 4759 4760 x86emuOp_mov_word_SP_IMM(emu); 4761 break; 4762 case 0xbd: 4763 x86emuOp_mov_word_BP_IMM(emu); 4764 break; 4765 case 0xbe: 4766 x86emuOp_mov_word_SI_IMM(emu); 4767 break; 4768 case 0xbf: 4769 x86emuOp_mov_word_DI_IMM(emu); 4770 break; 4771 4772 case 0xc0: 4773 x86emuOp_opcC0_byte_RM_MEM(emu); 4774 break; 4775 case 0xc1: 4776 x86emuOp_opcC1_word_RM_MEM(emu); 4777 break; 4778 case 0xc2: 4779 x86emuOp_ret_near_IMM(emu); 4780 break; 4781 case 0xc3: 4782 emu->x86.R_IP = pop_word(emu); 4783 break; 4784 case 0xc4: 4785 common_load_far_pointer(emu, &emu->x86.R_ES); 4786 break; 4787 case 0xc5: 4788 common_load_far_pointer(emu, &emu->x86.R_DS); 4789 break; 4790 case 0xc6: 4791 x86emuOp_mov_byte_RM_IMM(emu); 4792 break; 4793 case 0xc7: 4794 x86emuOp_mov_word_RM_IMM(emu); 4795 break; 4796 case 0xc8: 4797 x86emuOp_enter(emu); 4798 break; 4799 case 0xc9: 4800 x86emuOp_leave(emu); 4801 break; 4802 case 0xca: 4803 x86emuOp_ret_far_IMM(emu); 4804 break; 4805 case 0xcb: 4806 x86emuOp_ret_far(emu); 4807 break; 4808 case 0xcc: 4809 x86emuOp_int3(emu); 4810 break; 4811 case 0xcd: 4812 x86emuOp_int_IMM(emu); 4813 break; 4814 case 0xce: 4815 x86emuOp_into(emu); 4816 break; 4817 case 0xcf: 4818 x86emuOp_iret(emu); 4819 break; 4820 4821 case 0xd0: 4822 x86emuOp_opcD0_byte_RM_1(emu); 4823 break; 4824 case 0xd1: 4825 x86emuOp_opcD1_word_RM_1(emu); 4826 break; 4827 case 0xd2: 4828 x86emuOp_opcD2_byte_RM_CL(emu); 4829 break; 4830 case 0xd3: 4831 x86emuOp_opcD3_word_RM_CL(emu); 4832 break; 4833 case 0xd4: 4834 x86emuOp_aam(emu); 4835 break; 4836 case 0xd5: 4837 x86emuOp_aad(emu); 4838 break; 4839 /* 0xd6 Undocumented SETALC instruction */ 4840 case 0xd7: 4841 x86emuOp_xlat(emu); 4842 break; 4843 case 0xd8: 4844 x86emuOp_esc_coprocess_d8(emu); 4845 break; 4846 case 0xd9: 4847 x86emuOp_esc_coprocess_d9(emu); 4848 break; 4849 case 0xda: 4850 x86emuOp_esc_coprocess_da(emu); 4851 break; 4852 case 0xdb: 4853 x86emuOp_esc_coprocess_db(emu); 4854 break; 4855 case 0xdc: 4856 x86emuOp_esc_coprocess_dc(emu); 4857 break; 4858 case 0xdd: 4859 x86emuOp_esc_coprocess_dd(emu); 4860 break; 4861 case 0xde: 4862 x86emuOp_esc_coprocess_de(emu); 4863 break; 4864 case 0xdf: 4865 x86emuOp_esc_coprocess_df(emu); 4866 break; 4867 4868 case 0xe0: 4869 x86emuOp_loopne(emu); 4870 break; 4871 case 0xe1: 4872 x86emuOp_loope(emu); 4873 break; 4874 case 0xe2: 4875 x86emuOp_loop(emu); 4876 break; 4877 case 0xe3: 4878 x86emuOp_jcxz(emu); 4879 break; 4880 case 0xe4: 4881 x86emuOp_in_byte_AL_IMM(emu); 4882 break; 4883 case 0xe5: 4884 x86emuOp_in_word_AX_IMM(emu); 4885 break; 4886 case 0xe6: 4887 x86emuOp_out_byte_IMM_AL(emu); 4888 break; 4889 case 0xe7: 4890 x86emuOp_out_word_IMM_AX(emu); 4891 break; 4892 4893 case 0xe8: 4894 x86emuOp_call_near_IMM(emu); 4895 break; 4896 case 0xe9: 4897 x86emuOp_jump_near_IMM(emu); 4898 break; 4899 case 0xea: 4900 x86emuOp_jump_far_IMM(emu); 4901 break; 4902 case 0xeb: 4903 x86emuOp_jump_byte_IMM(emu); 4904 break; 4905 case 0xec: 4906 x86emuOp_in_byte_AL_DX(emu); 4907 break; 4908 case 0xed: 4909 x86emuOp_in_word_AX_DX(emu); 4910 break; 4911 case 0xee: 4912 x86emuOp_out_byte_DX_AL(emu); 4913 break; 4914 case 0xef: 4915 x86emuOp_out_word_DX_AX(emu); 4916 break; 4917 4918 case 0xf0: 4919 x86emuOp_lock(emu); 4920 break; 4921 case 0xf2: 4922 emu->x86.mode |= SYSMODE_PREFIX_REPNE; 4923 break; 4924 case 0xf3: 4925 emu->x86.mode |= SYSMODE_PREFIX_REPE; 4926 break; 4927 case 0xf4: 4928 x86emu_halt_sys(emu); 4929 break; 4930 case 0xf5: 4931 x86emuOp_cmc(emu); 4932 break; 4933 case 0xf6: 4934 x86emuOp_opcF6_byte_RM(emu); 4935 break; 4936 case 0xf7: 4937 x86emuOp_opcF7_word_RM(emu); 4938 break; 4939 4940 case 0xf8: 4941 CLEAR_FLAG(F_CF); 4942 break; 4943 case 0xf9: 4944 SET_FLAG(F_CF); 4945 break; 4946 case 0xfa: 4947 CLEAR_FLAG(F_IF); 4948 break; 4949 case 0xfb: 4950 SET_FLAG(F_IF); 4951 break; 4952 case 0xfc: 4953 CLEAR_FLAG(F_DF); 4954 break; 4955 case 0xfd: 4956 SET_FLAG(F_DF); 4957 break; 4958 case 0xfe: 4959 x86emuOp_opcFE_byte_RM(emu); 4960 break; 4961 case 0xff: 4962 x86emuOp_opcFF_word_RM(emu); 4963 break; 4964 default: 4965 x86emu_halt_sys(emu); 4966 break; 4967 } 4968 if (op1 != 0x26 && op1 != 0x2e && op1 != 0x36 && op1 != 0x3e && 4969 (op1 | 3) != 0x67) 4970 emu->x86.mode &= ~SYSMODE_CLRMASK; 4971 } 4972 4973 static void 4974 common_jmp_long(struct x86emu *emu, int cond) 4975 { 4976 int16_t target; 4977 4978 target = (int16_t) fetch_word_imm(emu); 4979 target += (int16_t) emu->x86.R_IP; 4980 if (cond) 4981 emu->x86.R_IP = (uint16_t) target; 4982 } 4983 4984 static void 4985 common_set_byte(struct x86emu *emu, int cond) 4986 { 4987 uint32_t destoffset; 4988 uint8_t *destreg, destval; 4989 4990 fetch_decode_modrm(emu); 4991 destval = cond ? 0x01 : 0x00; 4992 if (emu->cur_mod != 3) { 4993 destoffset = decode_rl_address(emu); 4994 store_data_byte(emu, destoffset, destval); 4995 } else { 4996 destreg = decode_rl_byte_register(emu); 4997 *destreg = destval; 4998 } 4999 } 5000 5001 static void 5002 common_bitstring32(struct x86emu *emu, int op) 5003 { 5004 int bit; 5005 uint32_t srcval, *shiftreg, mask; 5006 5007 fetch_decode_modrm(emu); 5008 shiftreg = decode_rh_long_register(emu); 5009 srcval = decode_and_fetch_long_disp(emu, (int16_t) *shiftreg >> 5); 5010 bit = *shiftreg & 0x1F; 5011 mask = 0x1 << bit; 5012 CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 5013 5014 switch (op) { 5015 case 0: 5016 break; 5017 case 1: 5018 write_back_long(emu, srcval | mask); 5019 break; 5020 case 2: 5021 write_back_long(emu, srcval & ~mask); 5022 break; 5023 case 3: 5024 write_back_long(emu, srcval ^ mask); 5025 break; 5026 } 5027 } 5028 5029 static void 5030 common_bitstring16(struct x86emu *emu, int op) 5031 { 5032 int bit; 5033 uint16_t srcval, *shiftreg, mask; 5034 5035 fetch_decode_modrm(emu); 5036 shiftreg = decode_rh_word_register(emu); 5037 srcval = decode_and_fetch_word_disp(emu, (int16_t) *shiftreg >> 4); 5038 bit = *shiftreg & 0xF; 5039 mask = 0x1 << bit; 5040 CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 5041 5042 switch (op) { 5043 case 0: 5044 break; 5045 case 1: 5046 write_back_word(emu, srcval | mask); 5047 break; 5048 case 2: 5049 write_back_word(emu, srcval & ~mask); 5050 break; 5051 case 3: 5052 write_back_word(emu, srcval ^ mask); 5053 break; 5054 } 5055 } 5056 5057 static void 5058 common_bitstring(struct x86emu *emu, int op) 5059 { 5060 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5061 common_bitstring32(emu, op); 5062 else 5063 common_bitstring16(emu, op); 5064 } 5065 5066 static void 5067 common_bitsearch32(struct x86emu *emu, int diff) 5068 { 5069 uint32_t srcval, *dstreg; 5070 5071 fetch_decode_modrm(emu); 5072 dstreg = decode_rh_long_register(emu); 5073 srcval = decode_and_fetch_long(emu); 5074 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 5075 for (*dstreg = 0; *dstreg < 32; *dstreg += diff) { 5076 if ((srcval >> *dstreg) & 1) 5077 break; 5078 } 5079 } 5080 5081 static void 5082 common_bitsearch16(struct x86emu *emu, int diff) 5083 { 5084 uint16_t srcval, *dstreg; 5085 5086 fetch_decode_modrm(emu); 5087 dstreg = decode_rh_word_register(emu); 5088 srcval = decode_and_fetch_word(emu); 5089 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 5090 for (*dstreg = 0; *dstreg < 16; *dstreg += diff) { 5091 if ((srcval >> *dstreg) & 1) 5092 break; 5093 } 5094 } 5095 5096 static void 5097 common_bitsearch(struct x86emu *emu, int diff) 5098 { 5099 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5100 common_bitsearch32(emu, diff); 5101 else 5102 common_bitsearch16(emu, diff); 5103 } 5104 5105 static void 5106 common_shift32(struct x86emu *emu, int shift_left, int use_cl) 5107 { 5108 uint8_t shift; 5109 uint32_t destval, *shiftreg; 5110 5111 fetch_decode_modrm(emu); 5112 shiftreg = decode_rh_long_register(emu); 5113 if (use_cl) { 5114 destval = decode_and_fetch_long(emu); 5115 shift = emu->x86.R_CL; 5116 } else { 5117 destval = decode_and_fetch_long_imm8(emu, &shift); 5118 } 5119 if (shift_left) 5120 destval = shld_long(emu, destval, *shiftreg, shift); 5121 else 5122 destval = shrd_long(emu, destval, *shiftreg, shift); 5123 write_back_long(emu, destval); 5124 } 5125 5126 static void 5127 common_shift16(struct x86emu *emu, int shift_left, int use_cl) 5128 { 5129 uint8_t shift; 5130 uint16_t destval, *shiftreg; 5131 5132 fetch_decode_modrm(emu); 5133 shiftreg = decode_rh_word_register(emu); 5134 if (use_cl) { 5135 destval = decode_and_fetch_word(emu); 5136 shift = emu->x86.R_CL; 5137 } else { 5138 destval = decode_and_fetch_word_imm8(emu, &shift); 5139 } 5140 if (shift_left) 5141 destval = shld_word(emu, destval, *shiftreg, shift); 5142 else 5143 destval = shrd_word(emu, destval, *shiftreg, shift); 5144 write_back_word(emu, destval); 5145 } 5146 5147 static void 5148 common_shift(struct x86emu *emu, int shift_left, int use_cl) 5149 { 5150 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5151 common_shift32(emu, shift_left, use_cl); 5152 else 5153 common_shift16(emu, shift_left, use_cl); 5154 } 5155 5156 /*----------------------------- Implementation ----------------------------*/ 5157 #define xorl(a,b) ((a) && !(b)) || (!(a) && (b)) 5158 5159 5160 /* 5161 * REMARKS: 5162 * Handles opcode 0x0f,0x31 5163 */ 5164 static void 5165 x86emuOp2_rdtsc(struct x86emu *emu) 5166 { 5167 emu->x86.R_EAX = emu->cur_cycles & 0xffffffff; 5168 emu->x86.R_EDX = emu->cur_cycles >> 32; 5169 } 5170 5171 /* 5172 * REMARKS: 5173 * Handles opcode 0x0f,0xa0 5174 */ 5175 static void 5176 x86emuOp2_push_FS(struct x86emu *emu) 5177 { 5178 push_word(emu, emu->x86.R_FS); 5179 } 5180 5181 /* 5182 * REMARKS: 5183 * Handles opcode 0x0f,0xa1 5184 */ 5185 static void 5186 x86emuOp2_pop_FS(struct x86emu *emu) 5187 { 5188 emu->x86.R_FS = pop_word(emu); 5189 } 5190 5191 /* 5192 * REMARKS: 5193 * Handles opcode 0x0f,0xa1 5194 */ 5195 #if defined(__i386__) || defined(__amd64__) 5196 static void 5197 hw_cpuid(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) 5198 { 5199 __asm__ __volatile__("cpuid" 5200 : "=a" (*a), "=b" (*b), 5201 "=c" (*c), "=d" (*d) 5202 : "a" (*a), "c" (*c) 5203 : "cc"); 5204 } 5205 #endif 5206 static void 5207 x86emuOp2_cpuid(struct x86emu *emu) 5208 { 5209 #if defined(__i386__) || defined(__amd64__) 5210 hw_cpuid(&emu->x86.R_EAX, &emu->x86.R_EBX, &emu->x86.R_ECX, 5211 &emu->x86.R_EDX); 5212 #endif 5213 switch (emu->x86.R_EAX) { 5214 case 0: 5215 emu->x86.R_EAX = 1; 5216 #if !defined(__i386__) && !defined(__amd64__) 5217 /* "GenuineIntel" */ 5218 emu->x86.R_EBX = 0x756e6547; 5219 emu->x86.R_EDX = 0x49656e69; 5220 emu->x86.R_ECX = 0x6c65746e; 5221 #endif 5222 break; 5223 case 1: 5224 #if !defined(__i386__) && !defined(__amd64__) 5225 emu->x86.R_EAX = 0x00000480; 5226 emu->x86.R_EBX = emu->x86.R_ECX = 0; 5227 emu->x86.R_EDX = 0x00000002; 5228 #else 5229 emu->x86.R_EDX &= 0x00000012; 5230 #endif 5231 break; 5232 default: 5233 emu->x86.R_EAX = emu->x86.R_EBX = emu->x86.R_ECX = 5234 emu->x86.R_EDX = 0; 5235 break; 5236 } 5237 } 5238 5239 /* 5240 * REMARKS: 5241 * Handles opcode 0x0f,0xa3 5242 */ 5243 static void 5244 x86emuOp2_bt_R(struct x86emu *emu) 5245 { 5246 common_bitstring(emu, 0); 5247 } 5248 5249 /* 5250 * REMARKS: 5251 * Handles opcode 0x0f,0xa4 5252 */ 5253 static void 5254 x86emuOp2_shld_IMM(struct x86emu *emu) 5255 { 5256 common_shift(emu, 1, 0); 5257 } 5258 5259 /* 5260 * REMARKS: 5261 * Handles opcode 0x0f,0xa5 5262 */ 5263 static void 5264 x86emuOp2_shld_CL(struct x86emu *emu) 5265 { 5266 common_shift(emu, 1, 1); 5267 } 5268 5269 /* 5270 * REMARKS: 5271 * Handles opcode 0x0f,0xa8 5272 */ 5273 static void 5274 x86emuOp2_push_GS(struct x86emu *emu) 5275 { 5276 push_word(emu, emu->x86.R_GS); 5277 } 5278 5279 /* 5280 * REMARKS: 5281 * Handles opcode 0x0f,0xa9 5282 */ 5283 static void 5284 x86emuOp2_pop_GS(struct x86emu *emu) 5285 { 5286 emu->x86.R_GS = pop_word(emu); 5287 } 5288 5289 /* 5290 * REMARKS: 5291 * Handles opcode 0x0f,0xab 5292 */ 5293 static void 5294 x86emuOp2_bts_R(struct x86emu *emu) 5295 { 5296 common_bitstring(emu, 1); 5297 } 5298 5299 /* 5300 * REMARKS: 5301 * Handles opcode 0x0f,0xac 5302 */ 5303 static void 5304 x86emuOp2_shrd_IMM(struct x86emu *emu) 5305 { 5306 common_shift(emu, 0, 0); 5307 } 5308 5309 /* 5310 * REMARKS: 5311 * Handles opcode 0x0f,0xad 5312 */ 5313 static void 5314 x86emuOp2_shrd_CL(struct x86emu *emu) 5315 { 5316 common_shift(emu, 0, 1); 5317 } 5318 5319 /* 5320 * REMARKS: 5321 * Handles opcode 0x0f,0xaf 5322 */ 5323 static void 5324 x86emuOp2_32_imul_R_RM(struct x86emu *emu) 5325 { 5326 uint32_t *destreg, srcval; 5327 uint64_t res; 5328 5329 fetch_decode_modrm(emu); 5330 destreg = decode_rh_long_register(emu); 5331 srcval = decode_and_fetch_long(emu); 5332 res = (int32_t) *destreg * (int32_t)srcval; 5333 if (res > 0xffffffff) { 5334 SET_FLAG(F_CF); 5335 SET_FLAG(F_OF); 5336 } else { 5337 CLEAR_FLAG(F_CF); 5338 CLEAR_FLAG(F_OF); 5339 } 5340 *destreg = (uint32_t) res; 5341 } 5342 5343 static void 5344 x86emuOp2_16_imul_R_RM(struct x86emu *emu) 5345 { 5346 uint16_t *destreg, srcval; 5347 uint32_t res; 5348 5349 fetch_decode_modrm(emu); 5350 destreg = decode_rh_word_register(emu); 5351 srcval = decode_and_fetch_word(emu); 5352 res = (int16_t) * destreg * (int16_t)srcval; 5353 if (res > 0xFFFF) { 5354 SET_FLAG(F_CF); 5355 SET_FLAG(F_OF); 5356 } else { 5357 CLEAR_FLAG(F_CF); 5358 CLEAR_FLAG(F_OF); 5359 } 5360 *destreg = (uint16_t) res; 5361 } 5362 5363 static void 5364 x86emuOp2_imul_R_RM(struct x86emu *emu) 5365 { 5366 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5367 x86emuOp2_32_imul_R_RM(emu); 5368 else 5369 x86emuOp2_16_imul_R_RM(emu); 5370 } 5371 5372 /* 5373 * REMARKS: 5374 * Handles opcode 0x0f,0xb2 5375 */ 5376 static void 5377 x86emuOp2_lss_R_IMM(struct x86emu *emu) 5378 { 5379 common_load_far_pointer(emu, &emu->x86.R_SS); 5380 } 5381 5382 /* 5383 * REMARKS: 5384 * Handles opcode 0x0f,0xb3 5385 */ 5386 static void 5387 x86emuOp2_btr_R(struct x86emu *emu) 5388 { 5389 common_bitstring(emu, 2); 5390 } 5391 5392 /* 5393 * REMARKS: 5394 * Handles opcode 0x0f,0xb4 5395 */ 5396 static void 5397 x86emuOp2_lfs_R_IMM(struct x86emu *emu) 5398 { 5399 common_load_far_pointer(emu, &emu->x86.R_FS); 5400 } 5401 5402 /* 5403 * REMARKS: 5404 * Handles opcode 0x0f,0xb5 5405 */ 5406 static void 5407 x86emuOp2_lgs_R_IMM(struct x86emu *emu) 5408 { 5409 common_load_far_pointer(emu, &emu->x86.R_GS); 5410 } 5411 5412 /* 5413 * REMARKS: 5414 * Handles opcode 0x0f,0xb6 5415 */ 5416 static void 5417 x86emuOp2_32_movzx_byte_R_RM(struct x86emu *emu) 5418 { 5419 uint32_t *destreg; 5420 5421 fetch_decode_modrm(emu); 5422 destreg = decode_rh_long_register(emu); 5423 *destreg = decode_and_fetch_byte(emu); 5424 } 5425 5426 static void 5427 x86emuOp2_16_movzx_byte_R_RM(struct x86emu *emu) 5428 { 5429 uint16_t *destreg; 5430 5431 fetch_decode_modrm(emu); 5432 destreg = decode_rh_word_register(emu); 5433 *destreg = decode_and_fetch_byte(emu); 5434 } 5435 5436 static void 5437 x86emuOp2_movzx_byte_R_RM(struct x86emu *emu) 5438 { 5439 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5440 x86emuOp2_32_movzx_byte_R_RM(emu); 5441 else 5442 x86emuOp2_16_movzx_byte_R_RM(emu); 5443 } 5444 5445 /* 5446 * REMARKS: 5447 * Handles opcode 0x0f,0xb7 5448 */ 5449 static void 5450 x86emuOp2_movzx_word_R_RM(struct x86emu *emu) 5451 { 5452 uint32_t *destreg; 5453 5454 fetch_decode_modrm(emu); 5455 destreg = decode_rh_long_register(emu); 5456 *destreg = decode_and_fetch_word(emu); 5457 } 5458 5459 /* 5460 * REMARKS: 5461 * Handles opcode 0x0f,0xba 5462 */ 5463 static void 5464 x86emuOp2_32_btX_I(struct x86emu *emu) 5465 { 5466 int bit; 5467 uint32_t srcval, mask; 5468 uint8_t shift; 5469 5470 fetch_decode_modrm(emu); 5471 if (emu->cur_rh < 4) 5472 x86emu_halt_sys(emu); 5473 5474 srcval = decode_and_fetch_long_imm8(emu, &shift); 5475 bit = shift & 0x1F; 5476 mask = (0x1 << bit); 5477 5478 switch (emu->cur_rh) { 5479 case 5: 5480 write_back_long(emu, srcval | mask); 5481 break; 5482 case 6: 5483 write_back_long(emu, srcval & ~mask); 5484 break; 5485 case 7: 5486 write_back_long(emu, srcval ^ mask); 5487 break; 5488 } 5489 CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 5490 } 5491 5492 static void 5493 x86emuOp2_16_btX_I(struct x86emu *emu) 5494 { 5495 int bit; 5496 5497 uint16_t srcval, mask; 5498 uint8_t shift; 5499 5500 fetch_decode_modrm(emu); 5501 if (emu->cur_rh < 4) 5502 x86emu_halt_sys(emu); 5503 5504 srcval = decode_and_fetch_word_imm8(emu, &shift); 5505 bit = shift & 0xF; 5506 mask = (0x1 << bit); 5507 switch (emu->cur_rh) { 5508 case 5: 5509 write_back_word(emu, srcval | mask); 5510 break; 5511 case 6: 5512 write_back_word(emu, srcval & ~mask); 5513 break; 5514 case 7: 5515 write_back_word(emu, srcval ^ mask); 5516 break; 5517 } 5518 CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 5519 } 5520 5521 static void 5522 x86emuOp2_btX_I(struct x86emu *emu) 5523 { 5524 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5525 x86emuOp2_32_btX_I(emu); 5526 else 5527 x86emuOp2_16_btX_I(emu); 5528 } 5529 5530 /* 5531 * REMARKS: 5532 * Handles opcode 0x0f,0xbb 5533 */ 5534 static void 5535 x86emuOp2_btc_R(struct x86emu *emu) 5536 { 5537 common_bitstring(emu, 3); 5538 } 5539 5540 /* 5541 * REMARKS: 5542 * Handles opcode 0x0f,0xbc 5543 */ 5544 static void 5545 x86emuOp2_bsf(struct x86emu *emu) 5546 { 5547 common_bitsearch(emu, +1); 5548 } 5549 5550 /* 5551 * REMARKS: 5552 * Handles opcode 0x0f,0xbd 5553 */ 5554 static void 5555 x86emuOp2_bsr(struct x86emu *emu) 5556 { 5557 common_bitsearch(emu, -1); 5558 } 5559 5560 /* 5561 * REMARKS: 5562 * Handles opcode 0x0f,0xbe 5563 */ 5564 static void 5565 x86emuOp2_32_movsx_byte_R_RM(struct x86emu *emu) 5566 { 5567 uint32_t *destreg; 5568 5569 destreg = decode_rh_long_register(emu); 5570 *destreg = (int32_t)(int8_t)decode_and_fetch_byte(emu); 5571 } 5572 5573 static void 5574 x86emuOp2_16_movsx_byte_R_RM(struct x86emu *emu) 5575 { 5576 uint16_t *destreg; 5577 5578 fetch_decode_modrm(emu); 5579 destreg = decode_rh_word_register(emu); 5580 *destreg = (int16_t)(int8_t)decode_and_fetch_byte(emu); 5581 } 5582 5583 static void 5584 x86emuOp2_movsx_byte_R_RM(struct x86emu *emu) 5585 { 5586 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5587 x86emuOp2_32_movsx_byte_R_RM(emu); 5588 else 5589 x86emuOp2_16_movsx_byte_R_RM(emu); 5590 } 5591 5592 /* 5593 * REMARKS: 5594 * Handles opcode 0x0f,0xbf 5595 */ 5596 static void 5597 x86emuOp2_movsx_word_R_RM(struct x86emu *emu) 5598 { 5599 uint32_t *destreg; 5600 5601 fetch_decode_modrm(emu); 5602 destreg = decode_rh_long_register(emu); 5603 *destreg = (int32_t)(int16_t)decode_and_fetch_word(emu); 5604 } 5605 5606 static void 5607 x86emu_exec_two_byte(struct x86emu * emu) 5608 { 5609 uint8_t op2; 5610 5611 op2 = fetch_byte_imm(emu); 5612 5613 switch (op2) { 5614 /* 0x00 Group F (ring 0 PM) */ 5615 /* 0x01 Group G (ring 0 PM) */ 5616 /* 0x02 lar (ring 0 PM) */ 5617 /* 0x03 lsl (ring 0 PM) */ 5618 /* 0x05 loadall (undocumented) */ 5619 /* 0x06 clts (ring 0 PM) */ 5620 /* 0x07 loadall (undocumented) */ 5621 /* 0x08 invd (ring 0 PM) */ 5622 /* 0x09 wbinvd (ring 0 PM) */ 5623 5624 /* 0x20 mov reg32(op2); break;creg (ring 0 PM) */ 5625 /* 0x21 mov reg32(op2); break;dreg (ring 0 PM) */ 5626 /* 0x22 mov creg(op2); break;reg32 (ring 0 PM) */ 5627 /* 0x23 mov dreg(op2); break;reg32 (ring 0 PM) */ 5628 /* 0x24 mov reg32(op2); break;treg (ring 0 PM) */ 5629 /* 0x26 mov treg(op2); break;reg32 (ring 0 PM) */ 5630 5631 case 0x31: 5632 x86emuOp2_rdtsc(emu); 5633 break; 5634 5635 case 0x80: 5636 common_jmp_long(emu, ACCESS_FLAG(F_OF)); 5637 break; 5638 case 0x81: 5639 common_jmp_long(emu, !ACCESS_FLAG(F_OF)); 5640 break; 5641 case 0x82: 5642 common_jmp_long(emu, ACCESS_FLAG(F_CF)); 5643 break; 5644 case 0x83: 5645 common_jmp_long(emu, !ACCESS_FLAG(F_CF)); 5646 break; 5647 case 0x84: 5648 common_jmp_long(emu, ACCESS_FLAG(F_ZF)); 5649 break; 5650 case 0x85: 5651 common_jmp_long(emu, !ACCESS_FLAG(F_ZF)); 5652 break; 5653 case 0x86: 5654 common_jmp_long(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); 5655 break; 5656 case 0x87: 5657 common_jmp_long(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))); 5658 break; 5659 case 0x88: 5660 common_jmp_long(emu, ACCESS_FLAG(F_SF)); 5661 break; 5662 case 0x89: 5663 common_jmp_long(emu, !ACCESS_FLAG(F_SF)); 5664 break; 5665 case 0x8a: 5666 common_jmp_long(emu, ACCESS_FLAG(F_PF)); 5667 break; 5668 case 0x8b: 5669 common_jmp_long(emu, !ACCESS_FLAG(F_PF)); 5670 break; 5671 case 0x8c: 5672 common_jmp_long(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))); 5673 break; 5674 case 0x8d: 5675 common_jmp_long(emu, !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)))); 5676 break; 5677 case 0x8e: 5678 common_jmp_long(emu, 5679 (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF))); 5680 break; 5681 case 0x8f: 5682 common_jmp_long(emu, 5683 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF))); 5684 break; 5685 5686 case 0x90: 5687 common_set_byte(emu, ACCESS_FLAG(F_OF)); 5688 break; 5689 case 0x91: 5690 common_set_byte(emu, !ACCESS_FLAG(F_OF)); 5691 break; 5692 case 0x92: 5693 common_set_byte(emu, ACCESS_FLAG(F_CF)); 5694 break; 5695 case 0x93: 5696 common_set_byte(emu, !ACCESS_FLAG(F_CF)); 5697 break; 5698 case 0x94: 5699 common_set_byte(emu, ACCESS_FLAG(F_ZF)); 5700 break; 5701 case 0x95: 5702 common_set_byte(emu, !ACCESS_FLAG(F_ZF)); 5703 break; 5704 case 0x96: 5705 common_set_byte(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); 5706 break; 5707 case 0x97: 5708 common_set_byte(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))); 5709 break; 5710 case 0x98: 5711 common_set_byte(emu, ACCESS_FLAG(F_SF)); 5712 break; 5713 case 0x99: 5714 common_set_byte(emu, !ACCESS_FLAG(F_SF)); 5715 break; 5716 case 0x9a: 5717 common_set_byte(emu, ACCESS_FLAG(F_PF)); 5718 break; 5719 case 0x9b: 5720 common_set_byte(emu, !ACCESS_FLAG(F_PF)); 5721 break; 5722 case 0x9c: 5723 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))); 5724 break; 5725 case 0x9d: 5726 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))); 5727 break; 5728 case 0x9e: 5729 common_set_byte(emu, 5730 (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || 5731 ACCESS_FLAG(F_ZF))); 5732 break; 5733 case 0x9f: 5734 common_set_byte(emu, 5735 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || 5736 ACCESS_FLAG(F_ZF))); 5737 break; 5738 5739 case 0xa0: 5740 x86emuOp2_push_FS(emu); 5741 break; 5742 case 0xa1: 5743 x86emuOp2_pop_FS(emu); 5744 break; 5745 case 0xa2: 5746 x86emuOp2_cpuid(emu); 5747 break; 5748 case 0xa3: 5749 x86emuOp2_bt_R(emu); 5750 break; 5751 case 0xa4: 5752 x86emuOp2_shld_IMM(emu); 5753 break; 5754 case 0xa5: 5755 x86emuOp2_shld_CL(emu); 5756 break; 5757 case 0xa8: 5758 x86emuOp2_push_GS(emu); 5759 break; 5760 case 0xa9: 5761 x86emuOp2_pop_GS(emu); 5762 break; 5763 case 0xab: 5764 x86emuOp2_bts_R(emu); 5765 break; 5766 case 0xac: 5767 x86emuOp2_shrd_IMM(emu); 5768 break; 5769 case 0xad: 5770 x86emuOp2_shrd_CL(emu); 5771 break; 5772 case 0xaf: 5773 x86emuOp2_imul_R_RM(emu); 5774 break; 5775 5776 /* 0xb0 TODO: cmpxchg */ 5777 /* 0xb1 TODO: cmpxchg */ 5778 case 0xb2: 5779 x86emuOp2_lss_R_IMM(emu); 5780 break; 5781 case 0xb3: 5782 x86emuOp2_btr_R(emu); 5783 break; 5784 case 0xb4: 5785 x86emuOp2_lfs_R_IMM(emu); 5786 break; 5787 case 0xb5: 5788 x86emuOp2_lgs_R_IMM(emu); 5789 break; 5790 case 0xb6: 5791 x86emuOp2_movzx_byte_R_RM(emu); 5792 break; 5793 case 0xb7: 5794 x86emuOp2_movzx_word_R_RM(emu); 5795 break; 5796 case 0xba: 5797 x86emuOp2_btX_I(emu); 5798 break; 5799 case 0xbb: 5800 x86emuOp2_btc_R(emu); 5801 break; 5802 case 0xbc: 5803 x86emuOp2_bsf(emu); 5804 break; 5805 case 0xbd: 5806 x86emuOp2_bsr(emu); 5807 break; 5808 case 0xbe: 5809 x86emuOp2_movsx_byte_R_RM(emu); 5810 break; 5811 case 0xbf: 5812 x86emuOp2_movsx_word_R_RM(emu); 5813 break; 5814 5815 /* 0xc0 TODO: xadd */ 5816 /* 0xc1 TODO: xadd */ 5817 /* 0xc8 TODO: bswap */ 5818 /* 0xc9 TODO: bswap */ 5819 /* 0xca TODO: bswap */ 5820 /* 0xcb TODO: bswap */ 5821 /* 0xcc TODO: bswap */ 5822 /* 0xcd TODO: bswap */ 5823 /* 0xce TODO: bswap */ 5824 /* 0xcf TODO: bswap */ 5825 5826 default: 5827 x86emu_halt_sys(emu); 5828 break; 5829 } 5830 } 5831 5832 /* 5833 * Carry Chain Calculation 5834 * 5835 * This represents a somewhat expensive calculation which is 5836 * apparently required to emulate the setting of the OF and AF flag. 5837 * The latter is not so important, but the former is. The overflow 5838 * flag is the XOR of the top two bits of the carry chain for an 5839 * addition (similar for subtraction). Since we do not want to 5840 * simulate the addition in a bitwise manner, we try to calculate the 5841 * carry chain given the two operands and the result. 5842 * 5843 * So, given the following table, which represents the addition of two 5844 * bits, we can derive a formula for the carry chain. 5845 * 5846 * a b cin r cout 5847 * 0 0 0 0 0 5848 * 0 0 1 1 0 5849 * 0 1 0 1 0 5850 * 0 1 1 0 1 5851 * 1 0 0 1 0 5852 * 1 0 1 0 1 5853 * 1 1 0 0 1 5854 * 1 1 1 1 1 5855 * 5856 * Construction of table for cout: 5857 * 5858 * ab 5859 * r \ 00 01 11 10 5860 * |------------------ 5861 * 0 | 0 1 1 1 5862 * 1 | 0 0 1 0 5863 * 5864 * By inspection, one gets: cc = ab + r'(a + b) 5865 * 5866 * That represents alot of operations, but NO CHOICE.... 5867 * 5868 * Borrow Chain Calculation. 5869 * 5870 * The following table represents the subtraction of two bits, from 5871 * which we can derive a formula for the borrow chain. 5872 * 5873 * a b bin r bout 5874 * 0 0 0 0 0 5875 * 0 0 1 1 1 5876 * 0 1 0 1 1 5877 * 0 1 1 0 1 5878 * 1 0 0 1 0 5879 * 1 0 1 0 0 5880 * 1 1 0 0 0 5881 * 1 1 1 1 1 5882 * 5883 * Construction of table for cout: 5884 * 5885 * ab 5886 * r \ 00 01 11 10 5887 * |------------------ 5888 * 0 | 0 1 0 0 5889 * 1 | 1 1 1 0 5890 * 5891 * By inspection, one gets: bc = a'b + r(a' + b) 5892 * 5893 */ 5894 5895 /*------------------------- Global Variables ------------------------------*/ 5896 5897 static uint32_t x86emu_parity_tab[8] = 5898 { 5899 0x96696996, 5900 0x69969669, 5901 0x69969669, 5902 0x96696996, 5903 0x69969669, 5904 0x96696996, 5905 0x96696996, 5906 0x69969669, 5907 }; 5908 #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0) 5909 #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1) 5910 5911 5912 /* 5913 * REMARKS: 5914 * Implements the AAA instruction and side effects. 5915 */ 5916 static uint16_t 5917 aaa_word(struct x86emu *emu, uint16_t d) 5918 { 5919 uint16_t res; 5920 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { 5921 d += 0x6; 5922 d += 0x100; 5923 SET_FLAG(F_AF); 5924 SET_FLAG(F_CF); 5925 } else { 5926 CLEAR_FLAG(F_CF); 5927 CLEAR_FLAG(F_AF); 5928 } 5929 res = (uint16_t) (d & 0xFF0F); 5930 CLEAR_FLAG(F_SF); 5931 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 5932 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5933 return res; 5934 } 5935 5936 /* 5937 * REMARKS: 5938 * Implements the AAA instruction and side effects. 5939 */ 5940 static uint16_t 5941 aas_word(struct x86emu *emu, uint16_t d) 5942 { 5943 uint16_t res; 5944 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { 5945 d -= 0x6; 5946 d -= 0x100; 5947 SET_FLAG(F_AF); 5948 SET_FLAG(F_CF); 5949 } else { 5950 CLEAR_FLAG(F_CF); 5951 CLEAR_FLAG(F_AF); 5952 } 5953 res = (uint16_t) (d & 0xFF0F); 5954 CLEAR_FLAG(F_SF); 5955 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 5956 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5957 return res; 5958 } 5959 5960 /* 5961 * REMARKS: 5962 * Implements the AAD instruction and side effects. 5963 */ 5964 static uint16_t 5965 aad_word(struct x86emu *emu, uint16_t d) 5966 { 5967 uint16_t l; 5968 uint8_t hb, lb; 5969 5970 hb = (uint8_t) ((d >> 8) & 0xff); 5971 lb = (uint8_t) ((d & 0xff)); 5972 l = (uint16_t) ((lb + 10 * hb) & 0xFF); 5973 5974 CLEAR_FLAG(F_CF); 5975 CLEAR_FLAG(F_AF); 5976 CLEAR_FLAG(F_OF); 5977 CONDITIONAL_SET_FLAG(l & 0x80, F_SF); 5978 CONDITIONAL_SET_FLAG(l == 0, F_ZF); 5979 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF); 5980 return l; 5981 } 5982 5983 /* 5984 * REMARKS: 5985 * Implements the AAM instruction and side effects. 5986 */ 5987 static uint16_t 5988 aam_word(struct x86emu *emu, uint8_t d) 5989 { 5990 uint16_t h, l; 5991 5992 h = (uint16_t) (d / 10); 5993 l = (uint16_t) (d % 10); 5994 l |= (uint16_t) (h << 8); 5995 5996 CLEAR_FLAG(F_CF); 5997 CLEAR_FLAG(F_AF); 5998 CLEAR_FLAG(F_OF); 5999 CONDITIONAL_SET_FLAG(l & 0x80, F_SF); 6000 CONDITIONAL_SET_FLAG(l == 0, F_ZF); 6001 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF); 6002 return l; 6003 } 6004 6005 /* 6006 * REMARKS: 6007 * Implements the ADC instruction and side effects. 6008 */ 6009 static uint8_t 6010 adc_byte(struct x86emu *emu, uint8_t d, uint8_t s) 6011 { 6012 uint32_t res; /* all operands in native machine order */ 6013 uint32_t cc; 6014 6015 if (ACCESS_FLAG(F_CF)) 6016 res = 1 + d + s; 6017 else 6018 res = d + s; 6019 6020 CONDITIONAL_SET_FLAG(res & 0x100, F_CF); 6021 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6022 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6023 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6024 6025 /* calculate the carry chain SEE NOTE AT TOP. */ 6026 cc = (s & d) | ((~res) & (s | d)); 6027 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 6028 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6029 return (uint8_t) res; 6030 } 6031 6032 /* 6033 * REMARKS: 6034 * Implements the ADC instruction and side effects. 6035 */ 6036 static uint16_t 6037 adc_word(struct x86emu *emu, uint16_t d, uint16_t s) 6038 { 6039 uint32_t res; /* all operands in native machine order */ 6040 uint32_t cc; 6041 6042 if (ACCESS_FLAG(F_CF)) 6043 res = 1 + d + s; 6044 else 6045 res = d + s; 6046 6047 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF); 6048 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6049 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6050 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6051 6052 /* calculate the carry chain SEE NOTE AT TOP. */ 6053 cc = (s & d) | ((~res) & (s | d)); 6054 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 6055 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6056 return (uint16_t) res; 6057 } 6058 6059 /* 6060 * REMARKS: 6061 * Implements the ADC instruction and side effects. 6062 */ 6063 static uint32_t 6064 adc_long(struct x86emu *emu, uint32_t d, uint32_t s) 6065 { 6066 uint32_t lo; /* all operands in native machine order */ 6067 uint32_t hi; 6068 uint32_t res; 6069 uint32_t cc; 6070 6071 if (ACCESS_FLAG(F_CF)) { 6072 lo = 1 + (d & 0xFFFF) + (s & 0xFFFF); 6073 res = 1 + d + s; 6074 } else { 6075 lo = (d & 0xFFFF) + (s & 0xFFFF); 6076 res = d + s; 6077 } 6078 hi = (lo >> 16) + (d >> 16) + (s >> 16); 6079 6080 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF); 6081 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6082 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6083 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6084 6085 /* calculate the carry chain SEE NOTE AT TOP. */ 6086 cc = (s & d) | ((~res) & (s | d)); 6087 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 6088 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6089 return res; 6090 } 6091 6092 /* 6093 * REMARKS: 6094 * Implements the ADD instruction and side effects. 6095 */ 6096 static uint8_t 6097 add_byte(struct x86emu *emu, uint8_t d, uint8_t s) 6098 { 6099 uint32_t res; /* all operands in native machine order */ 6100 uint32_t cc; 6101 6102 res = d + s; 6103 CONDITIONAL_SET_FLAG(res & 0x100, F_CF); 6104 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6105 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6106 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6107 6108 /* calculate the carry chain SEE NOTE AT TOP. */ 6109 cc = (s & d) | ((~res) & (s | d)); 6110 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 6111 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6112 return (uint8_t) res; 6113 } 6114 6115 /* 6116 * REMARKS: 6117 * Implements the ADD instruction and side effects. 6118 */ 6119 static uint16_t 6120 add_word(struct x86emu *emu, uint16_t d, uint16_t s) 6121 { 6122 uint32_t res; /* all operands in native machine order */ 6123 uint32_t cc; 6124 6125 res = d + s; 6126 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF); 6127 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6128 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6129 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6130 6131 /* calculate the carry chain SEE NOTE AT TOP. */ 6132 cc = (s & d) | ((~res) & (s | d)); 6133 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 6134 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6135 return (uint16_t) res; 6136 } 6137 6138 /* 6139 * REMARKS: 6140 * Implements the ADD instruction and side effects. 6141 */ 6142 static uint32_t 6143 add_long(struct x86emu *emu, uint32_t d, uint32_t s) 6144 { 6145 uint32_t lo; /* all operands in native machine order */ 6146 uint32_t hi; 6147 uint32_t res; 6148 uint32_t cc; 6149 6150 lo = (d & 0xFFFF) + (s & 0xFFFF); 6151 res = d + s; 6152 hi = (lo >> 16) + (d >> 16) + (s >> 16); 6153 6154 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF); 6155 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6156 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6157 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6158 6159 /* calculate the carry chain SEE NOTE AT TOP. */ 6160 cc = (s & d) | ((~res) & (s | d)); 6161 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 6162 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6163 6164 return res; 6165 } 6166 6167 /* 6168 * REMARKS: 6169 * Implements the AND instruction and side effects. 6170 */ 6171 static uint8_t 6172 and_byte(struct x86emu *emu, uint8_t d, uint8_t s) 6173 { 6174 uint8_t res; /* all operands in native machine order */ 6175 6176 res = d & s; 6177 6178 /* set the flags */ 6179 CLEAR_FLAG(F_OF); 6180 CLEAR_FLAG(F_CF); 6181 CLEAR_FLAG(F_AF); 6182 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6183 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6184 CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 6185 return res; 6186 } 6187 6188 /* 6189 * REMARKS: 6190 * Implements the AND instruction and side effects. 6191 */ 6192 static uint16_t 6193 and_word(struct x86emu *emu, uint16_t d, uint16_t s) 6194 { 6195 uint16_t res; /* all operands in native machine order */ 6196 6197 res = d & s; 6198 6199 /* set the flags */ 6200 CLEAR_FLAG(F_OF); 6201 CLEAR_FLAG(F_CF); 6202 CLEAR_FLAG(F_AF); 6203 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6204 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6205 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6206 return res; 6207 } 6208 6209 /* 6210 * REMARKS: 6211 * Implements the AND instruction and side effects. 6212 */ 6213 static uint32_t 6214 and_long(struct x86emu *emu, uint32_t d, uint32_t s) 6215 { 6216 uint32_t res; /* all operands in native machine order */ 6217 6218 res = d & s; 6219 6220 /* set the flags */ 6221 CLEAR_FLAG(F_OF); 6222 CLEAR_FLAG(F_CF); 6223 CLEAR_FLAG(F_AF); 6224 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6225 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6226 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6227 return res; 6228 } 6229 6230 /* 6231 * REMARKS: 6232 * Implements the CMP instruction and side effects. 6233 */ 6234 static uint8_t 6235 cmp_byte(struct x86emu *emu, uint8_t d, uint8_t s) 6236 { 6237 uint32_t res; /* all operands in native machine order */ 6238 uint32_t bc; 6239 6240 res = d - s; 6241 CLEAR_FLAG(F_CF); 6242 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6243 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6244 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6245 6246 /* calculate the borrow chain. See note at top */ 6247 bc = (res & (~d | s)) | (~d & s); 6248 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); 6249 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 6250 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6251 return d; 6252 } 6253 6254 static void 6255 cmp_byte_no_return(struct x86emu *emu, uint8_t d, uint8_t s) 6256 { 6257 cmp_byte(emu, d, s); 6258 } 6259 6260 /* 6261 * REMARKS: 6262 * Implements the CMP instruction and side effects. 6263 */ 6264 static uint16_t 6265 cmp_word(struct x86emu *emu, uint16_t d, uint16_t s) 6266 { 6267 uint32_t res; /* all operands in native machine order */ 6268 uint32_t bc; 6269 6270 res = d - s; 6271 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6272 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6273 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6274 6275 /* calculate the borrow chain. See note at top */ 6276 bc = (res & (~d | s)) | (~d & s); 6277 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 6278 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 6279 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6280 return d; 6281 } 6282 6283 static void 6284 cmp_word_no_return(struct x86emu *emu, uint16_t d, uint16_t s) 6285 { 6286 cmp_word(emu, d, s); 6287 } 6288 6289 /* 6290 * REMARKS: 6291 * Implements the CMP instruction and side effects. 6292 */ 6293 static uint32_t 6294 cmp_long(struct x86emu *emu, uint32_t d, uint32_t s) 6295 { 6296 uint32_t res; /* all operands in native machine order */ 6297 uint32_t bc; 6298 6299 res = d - s; 6300 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6301 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6302 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6303 6304 /* calculate the borrow chain. See note at top */ 6305 bc = (res & (~d | s)) | (~d & s); 6306 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 6307 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 6308 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6309 return d; 6310 } 6311 6312 static void 6313 cmp_long_no_return(struct x86emu *emu, uint32_t d, uint32_t s) 6314 { 6315 cmp_long(emu, d, s); 6316 } 6317 6318 /* 6319 * REMARKS: 6320 * Implements the DAA instruction and side effects. 6321 */ 6322 static uint8_t 6323 daa_byte(struct x86emu *emu, uint8_t d) 6324 { 6325 uint32_t res = d; 6326 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) { 6327 res += 6; 6328 SET_FLAG(F_AF); 6329 } 6330 if (res > 0x9F || ACCESS_FLAG(F_CF)) { 6331 res += 0x60; 6332 SET_FLAG(F_CF); 6333 } 6334 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6335 CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF); 6336 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6337 return (uint8_t) res; 6338 } 6339 6340 /* 6341 * REMARKS: 6342 * Implements the DAS instruction and side effects. 6343 */ 6344 static uint8_t 6345 das_byte(struct x86emu *emu, uint8_t d) 6346 { 6347 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) { 6348 d -= 6; 6349 SET_FLAG(F_AF); 6350 } 6351 if (d > 0x9F || ACCESS_FLAG(F_CF)) { 6352 d -= 0x60; 6353 SET_FLAG(F_CF); 6354 } 6355 CONDITIONAL_SET_FLAG(d & 0x80, F_SF); 6356 CONDITIONAL_SET_FLAG(d == 0, F_ZF); 6357 CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF); 6358 return d; 6359 } 6360 6361 /* 6362 * REMARKS: 6363 * Implements the DEC instruction and side effects. 6364 */ 6365 static uint8_t 6366 dec_byte(struct x86emu *emu, uint8_t d) 6367 { 6368 uint32_t res; /* all operands in native machine order */ 6369 uint32_t bc; 6370 6371 res = d - 1; 6372 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6373 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6374 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6375 6376 /* calculate the borrow chain. See note at top */ 6377 /* based on sub_byte, uses s==1. */ 6378 bc = (res & (~d | 1)) | (~d & 1); 6379 /* carry flag unchanged */ 6380 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 6381 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6382 return (uint8_t) res; 6383 } 6384 6385 /* 6386 * REMARKS: 6387 * Implements the DEC instruction and side effects. 6388 */ 6389 static uint16_t 6390 dec_word(struct x86emu *emu, uint16_t d) 6391 { 6392 uint32_t res; /* all operands in native machine order */ 6393 uint32_t bc; 6394 6395 res = d - 1; 6396 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6397 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6398 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6399 6400 /* calculate the borrow chain. See note at top */ 6401 /* based on the sub_byte routine, with s==1 */ 6402 bc = (res & (~d | 1)) | (~d & 1); 6403 /* carry flag unchanged */ 6404 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 6405 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6406 return (uint16_t) res; 6407 } 6408 6409 /* 6410 * REMARKS: 6411 * Implements the DEC instruction and side effects. 6412 */ 6413 static uint32_t 6414 dec_long(struct x86emu *emu, uint32_t d) 6415 { 6416 uint32_t res; /* all operands in native machine order */ 6417 uint32_t bc; 6418 6419 res = d - 1; 6420 6421 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6422 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6423 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6424 6425 /* calculate the borrow chain. See note at top */ 6426 bc = (res & (~d | 1)) | (~d & 1); 6427 /* carry flag unchanged */ 6428 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 6429 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6430 return res; 6431 } 6432 6433 /* 6434 * REMARKS: 6435 * Implements the INC instruction and side effects. 6436 */ 6437 static uint8_t 6438 inc_byte(struct x86emu *emu, uint8_t d) 6439 { 6440 uint32_t res; /* all operands in native machine order */ 6441 uint32_t cc; 6442 6443 res = d + 1; 6444 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6445 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6446 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6447 6448 /* calculate the carry chain SEE NOTE AT TOP. */ 6449 cc = ((1 & d) | (~res)) & (1 | d); 6450 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 6451 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6452 return (uint8_t) res; 6453 } 6454 6455 /* 6456 * REMARKS: 6457 * Implements the INC instruction and side effects. 6458 */ 6459 static uint16_t 6460 inc_word(struct x86emu *emu, uint16_t d) 6461 { 6462 uint32_t res; /* all operands in native machine order */ 6463 uint32_t cc; 6464 6465 res = d + 1; 6466 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6467 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6468 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6469 6470 /* calculate the carry chain SEE NOTE AT TOP. */ 6471 cc = (1 & d) | ((~res) & (1 | d)); 6472 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 6473 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6474 return (uint16_t) res; 6475 } 6476 6477 /* 6478 * REMARKS: 6479 * Implements the INC instruction and side effects. 6480 */ 6481 static uint32_t 6482 inc_long(struct x86emu *emu, uint32_t d) 6483 { 6484 uint32_t res; /* all operands in native machine order */ 6485 uint32_t cc; 6486 6487 res = d + 1; 6488 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6489 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6490 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6491 6492 /* calculate the carry chain SEE NOTE AT TOP. */ 6493 cc = (1 & d) | ((~res) & (1 | d)); 6494 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 6495 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6496 return res; 6497 } 6498 6499 /* 6500 * REMARKS: 6501 * Implements the OR instruction and side effects. 6502 */ 6503 static uint8_t 6504 or_byte(struct x86emu *emu, uint8_t d, uint8_t s) 6505 { 6506 uint8_t res; /* all operands in native machine order */ 6507 6508 res = d | s; 6509 CLEAR_FLAG(F_OF); 6510 CLEAR_FLAG(F_CF); 6511 CLEAR_FLAG(F_AF); 6512 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6513 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6514 CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 6515 return res; 6516 } 6517 6518 /* 6519 * REMARKS: 6520 * Implements the OR instruction and side effects. 6521 */ 6522 static uint16_t 6523 or_word(struct x86emu *emu, uint16_t d, uint16_t s) 6524 { 6525 uint16_t res; /* all operands in native machine order */ 6526 6527 res = d | s; 6528 /* set the carry flag to be bit 8 */ 6529 CLEAR_FLAG(F_OF); 6530 CLEAR_FLAG(F_CF); 6531 CLEAR_FLAG(F_AF); 6532 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6533 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6534 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6535 return res; 6536 } 6537 6538 /* 6539 * REMARKS: 6540 * Implements the OR instruction and side effects. 6541 */ 6542 static uint32_t 6543 or_long(struct x86emu *emu, uint32_t d, uint32_t s) 6544 { 6545 uint32_t res; /* all operands in native machine order */ 6546 6547 res = d | s; 6548 6549 /* set the carry flag to be bit 8 */ 6550 CLEAR_FLAG(F_OF); 6551 CLEAR_FLAG(F_CF); 6552 CLEAR_FLAG(F_AF); 6553 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6554 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6555 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6556 return res; 6557 } 6558 6559 /* 6560 * REMARKS: 6561 * Implements the OR instruction and side effects. 6562 */ 6563 static uint8_t 6564 neg_byte(struct x86emu *emu, uint8_t s) 6565 { 6566 uint8_t res; 6567 uint8_t bc; 6568 6569 CONDITIONAL_SET_FLAG(s != 0, F_CF); 6570 res = (uint8_t) - s; 6571 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6572 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6573 CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 6574 /* calculate the borrow chain --- modified such that d=0. 6575 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for 6576 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and 6577 * res&0xfff... == res. Similarly ~d&s == s. So the simplified 6578 * result is: */ 6579 bc = res | s; 6580 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 6581 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6582 return res; 6583 } 6584 6585 /* 6586 * REMARKS: 6587 * Implements the OR instruction and side effects. 6588 */ 6589 static uint16_t 6590 neg_word(struct x86emu *emu, uint16_t s) 6591 { 6592 uint16_t res; 6593 uint16_t bc; 6594 6595 CONDITIONAL_SET_FLAG(s != 0, F_CF); 6596 res = (uint16_t) - s; 6597 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6598 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6599 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6600 6601 /* calculate the borrow chain --- modified such that d=0. 6602 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for 6603 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and 6604 * res&0xfff... == res. Similarly ~d&s == s. So the simplified 6605 * result is: */ 6606 bc = res | s; 6607 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 6608 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6609 return res; 6610 } 6611 6612 /* 6613 * REMARKS: 6614 * Implements the OR instruction and side effects. 6615 */ 6616 static uint32_t 6617 neg_long(struct x86emu *emu, uint32_t s) 6618 { 6619 uint32_t res; 6620 uint32_t bc; 6621 6622 CONDITIONAL_SET_FLAG(s != 0, F_CF); 6623 res = (uint32_t) - s; 6624 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6625 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6626 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6627 6628 /* calculate the borrow chain --- modified such that d=0. 6629 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for 6630 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and 6631 * res&0xfff... == res. Similarly ~d&s == s. So the simplified 6632 * result is: */ 6633 bc = res | s; 6634 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 6635 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6636 return res; 6637 } 6638 6639 /* 6640 * REMARKS: 6641 * Implements the RCL instruction and side effects. 6642 */ 6643 static uint8_t 6644 rcl_byte(struct x86emu *emu, uint8_t d, uint8_t s) 6645 { 6646 unsigned int res, cnt, mask, cf; 6647 6648 /* s is the rotate distance. It varies from 0 - 8. */ 6649 /* have 6650 * 6651 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 6652 * 6653 * want to rotate through the carry by "s" bits. We could loop, but 6654 * that's inefficient. So the width is 9, and we split into three 6655 * parts: 6656 * 6657 * The new carry flag (was B_n) the stuff in B_n-1 .. B_0 the stuff in 6658 * B_7 .. B_n+1 6659 * 6660 * The new rotate is done mod 9, and given this, for a rotation of n bits 6661 * (mod 9) the new carry flag is then located n bits from the MSB. 6662 * The low part is then shifted up cnt bits, and the high part is or'd 6663 * in. Using CAPS for new values, and lowercase for the original 6664 * values, this can be expressed as: 6665 * 6666 * IF n > 0 1) CF <- b_(8-n) 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 6667 * 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */ 6668 res = d; 6669 if ((cnt = s % 9) != 0) { 6670 /* extract the new CARRY FLAG. */ 6671 /* CF <- b_(8-n) */ 6672 cf = (d >> (8 - cnt)) & 0x1; 6673 6674 /* get the low stuff which rotated into the range B_7 .. B_cnt */ 6675 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */ 6676 /* note that the right hand side done by the mask */ 6677 res = (d << cnt) & 0xff; 6678 6679 /* now the high stuff which rotated around into the positions 6680 * B_cnt-2 .. B_0 */ 6681 /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */ 6682 /* shift it downward, 7-(n-2) = 9-n positions. and mask off 6683 * the result before or'ing in. */ 6684 mask = (1 << (cnt - 1)) - 1; 6685 res |= (d >> (9 - cnt)) & mask; 6686 6687 /* if the carry flag was set, or it in. */ 6688 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6689 /* B_(n-1) <- cf */ 6690 res |= 1 << (cnt - 1); 6691 } 6692 /* set the new carry flag, based on the variable "cf" */ 6693 CONDITIONAL_SET_FLAG(cf, F_CF); 6694 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and 6695 * the most significant bit. Blecck. */ 6696 /* parenthesized this expression since it appears to be 6697 * causing OF to be misset */ 6698 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)), 6699 F_OF); 6700 6701 } 6702 return (uint8_t) res; 6703 } 6704 6705 /* 6706 * REMARKS: 6707 * Implements the RCL instruction and side effects. 6708 */ 6709 static uint16_t 6710 rcl_word(struct x86emu *emu, uint16_t d, uint8_t s) 6711 { 6712 unsigned int res, cnt, mask, cf; 6713 6714 res = d; 6715 if ((cnt = s % 17) != 0) { 6716 cf = (d >> (16 - cnt)) & 0x1; 6717 res = (d << cnt) & 0xffff; 6718 mask = (1 << (cnt - 1)) - 1; 6719 res |= (d >> (17 - cnt)) & mask; 6720 if (ACCESS_FLAG(F_CF)) { 6721 res |= 1 << (cnt - 1); 6722 } 6723 CONDITIONAL_SET_FLAG(cf, F_CF); 6724 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)), 6725 F_OF); 6726 } 6727 return (uint16_t) res; 6728 } 6729 6730 /* 6731 * REMARKS: 6732 * Implements the RCL instruction and side effects. 6733 */ 6734 static uint32_t 6735 rcl_long(struct x86emu *emu, uint32_t d, uint8_t s) 6736 { 6737 uint32_t res, cnt, mask, cf; 6738 6739 res = d; 6740 if ((cnt = s % 33) != 0) { 6741 cf = (d >> (32 - cnt)) & 0x1; 6742 res = (d << cnt) & 0xffffffff; 6743 mask = (1 << (cnt - 1)) - 1; 6744 res |= (d >> (33 - cnt)) & mask; 6745 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6746 res |= 1 << (cnt - 1); 6747 } 6748 CONDITIONAL_SET_FLAG(cf, F_CF); 6749 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)), 6750 F_OF); 6751 } 6752 return res; 6753 } 6754 6755 /* 6756 * REMARKS: 6757 * Implements the RCR instruction and side effects. 6758 */ 6759 static uint8_t 6760 rcr_byte(struct x86emu *emu, uint8_t d, uint8_t s) 6761 { 6762 uint32_t res, cnt; 6763 uint32_t mask, cf, ocf = 0; 6764 6765 /* rotate right through carry */ 6766 /* s is the rotate distance. It varies from 0 - 8. d is the byte 6767 * object rotated. 6768 * 6769 * have 6770 * 6771 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 6772 * 6773 * The new rotate is done mod 9, and given this, for a rotation of n bits 6774 * (mod 9) the new carry flag is then located n bits from the LSB. 6775 * The low part is then shifted up cnt bits, and the high part is or'd 6776 * in. Using CAPS for new values, and lowercase for the original 6777 * values, this can be expressed as: 6778 * 6779 * IF n > 0 1) CF <- b_(n-1) 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 6780 * 3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */ 6781 res = d; 6782 if ((cnt = s % 9) != 0) { 6783 /* extract the new CARRY FLAG. */ 6784 /* CF <- b_(n-1) */ 6785 if (cnt == 1) { 6786 cf = d & 0x1; 6787 /* note hackery here. Access_flag(..) evaluates to 6788 * either 0 if flag not set non-zero if flag is set. 6789 * doing access_flag(..) != 0 casts that into either 6790 * 0..1 in any representation of the flags register 6791 * (i.e. packed bit array or unpacked.) */ 6792 ocf = ACCESS_FLAG(F_CF) != 0; 6793 } else 6794 cf = (d >> (cnt - 1)) & 0x1; 6795 6796 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */ 6797 /* note that the right hand side done by the mask This is 6798 * effectively done by shifting the object to the right. The 6799 * result must be masked, in case the object came in and was 6800 * treated as a negative number. Needed??? */ 6801 6802 mask = (1 << (8 - cnt)) - 1; 6803 res = (d >> cnt) & mask; 6804 6805 /* now the high stuff which rotated around into the positions 6806 * B_cnt-2 .. B_0 */ 6807 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */ 6808 /* shift it downward, 7-(n-2) = 9-n positions. and mask off 6809 * the result before or'ing in. */ 6810 res |= (d << (9 - cnt)); 6811 6812 /* if the carry flag was set, or it in. */ 6813 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6814 /* B_(8-n) <- cf */ 6815 res |= 1 << (8 - cnt); 6816 } 6817 /* set the new carry flag, based on the variable "cf" */ 6818 CONDITIONAL_SET_FLAG(cf, F_CF); 6819 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and 6820 * the most significant bit. Blecck. */ 6821 /* parenthesized... */ 6822 if (cnt == 1) { 6823 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)), 6824 F_OF); 6825 } 6826 } 6827 return (uint8_t) res; 6828 } 6829 6830 /* 6831 * REMARKS: 6832 * Implements the RCR instruction and side effects. 6833 */ 6834 static uint16_t 6835 rcr_word(struct x86emu *emu, uint16_t d, uint8_t s) 6836 { 6837 uint32_t res, cnt; 6838 uint32_t mask, cf, ocf = 0; 6839 6840 /* rotate right through carry */ 6841 res = d; 6842 if ((cnt = s % 17) != 0) { 6843 if (cnt == 1) { 6844 cf = d & 0x1; 6845 ocf = ACCESS_FLAG(F_CF) != 0; 6846 } else 6847 cf = (d >> (cnt - 1)) & 0x1; 6848 mask = (1 << (16 - cnt)) - 1; 6849 res = (d >> cnt) & mask; 6850 res |= (d << (17 - cnt)); 6851 if (ACCESS_FLAG(F_CF)) { 6852 res |= 1 << (16 - cnt); 6853 } 6854 CONDITIONAL_SET_FLAG(cf, F_CF); 6855 if (cnt == 1) { 6856 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)), 6857 F_OF); 6858 } 6859 } 6860 return (uint16_t) res; 6861 } 6862 6863 /* 6864 * REMARKS: 6865 * Implements the RCR instruction and side effects. 6866 */ 6867 static uint32_t 6868 rcr_long(struct x86emu *emu, uint32_t d, uint8_t s) 6869 { 6870 uint32_t res, cnt; 6871 uint32_t mask, cf, ocf = 0; 6872 6873 /* rotate right through carry */ 6874 res = d; 6875 if ((cnt = s % 33) != 0) { 6876 if (cnt == 1) { 6877 cf = d & 0x1; 6878 ocf = ACCESS_FLAG(F_CF) != 0; 6879 } else 6880 cf = (d >> (cnt - 1)) & 0x1; 6881 mask = (1 << (32 - cnt)) - 1; 6882 res = (d >> cnt) & mask; 6883 if (cnt != 1) 6884 res |= (d << (33 - cnt)); 6885 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6886 res |= 1 << (32 - cnt); 6887 } 6888 CONDITIONAL_SET_FLAG(cf, F_CF); 6889 if (cnt == 1) { 6890 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)), 6891 F_OF); 6892 } 6893 } 6894 return res; 6895 } 6896 6897 /* 6898 * REMARKS: 6899 * Implements the ROL instruction and side effects. 6900 */ 6901 static uint8_t 6902 rol_byte(struct x86emu *emu, uint8_t d, uint8_t s) 6903 { 6904 unsigned int res, cnt, mask; 6905 6906 /* rotate left */ 6907 /* s is the rotate distance. It varies from 0 - 8. d is the byte 6908 * object rotated. 6909 * 6910 * have 6911 * 6912 * CF B_7 ... B_0 6913 * 6914 * The new rotate is done mod 8. Much simpler than the "rcl" or "rcr" 6915 * operations. 6916 * 6917 * IF n > 0 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) 2) B_(n-1) .. 6918 * B_(0) <- b_(7) .. b_(8-n) */ 6919 res = d; 6920 if ((cnt = s % 8) != 0) { 6921 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */ 6922 res = (d << cnt); 6923 6924 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */ 6925 mask = (1 << cnt) - 1; 6926 res |= (d >> (8 - cnt)) & mask; 6927 6928 /* set the new carry flag, Note that it is the low order bit 6929 * of the result!!! */ 6930 CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6931 /* OVERFLOW is set *IFF* s==1, then it is the xor of CF and 6932 * the most significant bit. Blecck. */ 6933 CONDITIONAL_SET_FLAG(s == 1 && 6934 XOR2((res & 0x1) + ((res >> 6) & 0x2)), 6935 F_OF); 6936 } if (s != 0) { 6937 /* set the new carry flag, Note that it is the low order bit 6938 * of the result!!! */ 6939 CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6940 } 6941 return (uint8_t) res; 6942 } 6943 6944 /* 6945 * REMARKS: 6946 * Implements the ROL instruction and side effects. 6947 */ 6948 static uint16_t 6949 rol_word(struct x86emu *emu, uint16_t d, uint8_t s) 6950 { 6951 unsigned int res, cnt, mask; 6952 6953 res = d; 6954 if ((cnt = s % 16) != 0) { 6955 res = (d << cnt); 6956 mask = (1 << cnt) - 1; 6957 res |= (d >> (16 - cnt)) & mask; 6958 CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6959 CONDITIONAL_SET_FLAG(s == 1 && 6960 XOR2((res & 0x1) + ((res >> 14) & 0x2)), 6961 F_OF); 6962 } if (s != 0) { 6963 /* set the new carry flag, Note that it is the low order bit 6964 * of the result!!! */ 6965 CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6966 } 6967 return (uint16_t) res; 6968 } 6969 6970 /* 6971 * REMARKS: 6972 * Implements the ROL instruction and side effects. 6973 */ 6974 static uint32_t 6975 rol_long(struct x86emu *emu, uint32_t d, uint8_t s) 6976 { 6977 uint32_t res, cnt, mask; 6978 6979 res = d; 6980 if ((cnt = s % 32) != 0) { 6981 res = (d << cnt); 6982 mask = (1 << cnt) - 1; 6983 res |= (d >> (32 - cnt)) & mask; 6984 CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6985 CONDITIONAL_SET_FLAG(s == 1 && 6986 XOR2((res & 0x1) + ((res >> 30) & 0x2)), 6987 F_OF); 6988 } if (s != 0) { 6989 /* set the new carry flag, Note that it is the low order bit 6990 * of the result!!! */ 6991 CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6992 } 6993 return res; 6994 } 6995 6996 /* 6997 * REMARKS: 6998 * Implements the ROR instruction and side effects. 6999 */ 7000 static uint8_t 7001 ror_byte(struct x86emu *emu, uint8_t d, uint8_t s) 7002 { 7003 unsigned int res, cnt, mask; 7004 7005 /* rotate right */ 7006 /* s is the rotate distance. It varies from 0 - 8. d is the byte 7007 * object rotated. 7008 * 7009 * have 7010 * 7011 * B_7 ... B_0 7012 * 7013 * The rotate is done mod 8. 7014 * 7015 * IF n > 0 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 2) B_(7) .. 7016 * B_(8-n) <- b_(n-1) .. b_(0) */ 7017 res = d; 7018 if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */ 7019 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */ 7020 res = (d << (8 - cnt)); 7021 7022 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */ 7023 mask = (1 << (8 - cnt)) - 1; 7024 res |= (d >> (cnt)) & mask; 7025 7026 /* set the new carry flag, Note that it is the low order bit 7027 * of the result!!! */ 7028 CONDITIONAL_SET_FLAG(res & 0x80, F_CF); 7029 /* OVERFLOW is set *IFF* s==1, then it is the xor of the two 7030 * most significant bits. Blecck. */ 7031 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF); 7032 } else if (s != 0) { 7033 /* set the new carry flag, Note that it is the low order bit 7034 * of the result!!! */ 7035 CONDITIONAL_SET_FLAG(res & 0x80, F_CF); 7036 } 7037 return (uint8_t) res; 7038 } 7039 7040 /* 7041 * REMARKS: 7042 * Implements the ROR instruction and side effects. 7043 */ 7044 static uint16_t 7045 ror_word(struct x86emu *emu, uint16_t d, uint8_t s) 7046 { 7047 unsigned int res, cnt, mask; 7048 7049 res = d; 7050 if ((cnt = s % 16) != 0) { 7051 res = (d << (16 - cnt)); 7052 mask = (1 << (16 - cnt)) - 1; 7053 res |= (d >> (cnt)) & mask; 7054 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF); 7055 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF); 7056 } else if (s != 0) { 7057 /* set the new carry flag, Note that it is the low order bit 7058 * of the result!!! */ 7059 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF); 7060 } 7061 return (uint16_t) res; 7062 } 7063 7064 /* 7065 * REMARKS: 7066 * Implements the ROR instruction and side effects. 7067 */ 7068 static uint32_t 7069 ror_long(struct x86emu *emu, uint32_t d, uint8_t s) 7070 { 7071 uint32_t res, cnt, mask; 7072 7073 res = d; 7074 if ((cnt = s % 32) != 0) { 7075 res = (d << (32 - cnt)); 7076 mask = (1 << (32 - cnt)) - 1; 7077 res |= (d >> (cnt)) & mask; 7078 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF); 7079 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF); 7080 } else if (s != 0) { 7081 /* set the new carry flag, Note that it is the low order bit 7082 * of the result!!! */ 7083 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF); 7084 } 7085 return res; 7086 } 7087 7088 /* 7089 * REMARKS: 7090 * Implements the SHL instruction and side effects. 7091 */ 7092 static uint8_t 7093 shl_byte(struct x86emu *emu, uint8_t d, uint8_t s) 7094 { 7095 unsigned int cnt, res, cf; 7096 7097 if (s < 8) { 7098 cnt = s % 8; 7099 7100 /* last bit shifted out goes into carry flag */ 7101 if (cnt > 0) { 7102 res = d << cnt; 7103 cf = d & (1 << (8 - cnt)); 7104 CONDITIONAL_SET_FLAG(cf, F_CF); 7105 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7106 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7107 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7108 } else { 7109 res = (uint8_t) d; 7110 } 7111 7112 if (cnt == 1) { 7113 /* Needs simplification. */ 7114 CONDITIONAL_SET_FLAG( 7115 (((res & 0x80) == 0x80) ^ 7116 (ACCESS_FLAG(F_CF) != 0)), 7117 /* was (emu->x86.R_FLG&F_CF)==F_CF)), */ 7118 F_OF); 7119 } else { 7120 CLEAR_FLAG(F_OF); 7121 } 7122 } else { 7123 res = 0; 7124 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF); 7125 CLEAR_FLAG(F_OF); 7126 CLEAR_FLAG(F_SF); 7127 SET_FLAG(F_PF); 7128 SET_FLAG(F_ZF); 7129 } 7130 return (uint8_t) res; 7131 } 7132 7133 /* 7134 * REMARKS: 7135 * Implements the SHL instruction and side effects. 7136 */ 7137 static uint16_t 7138 shl_word(struct x86emu *emu, uint16_t d, uint8_t s) 7139 { 7140 unsigned int cnt, res, cf; 7141 7142 if (s < 16) { 7143 cnt = s % 16; 7144 if (cnt > 0) { 7145 res = d << cnt; 7146 cf = d & (1 << (16 - cnt)); 7147 CONDITIONAL_SET_FLAG(cf, F_CF); 7148 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7149 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7150 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7151 } else { 7152 res = (uint16_t) d; 7153 } 7154 7155 if (cnt == 1) { 7156 CONDITIONAL_SET_FLAG( 7157 (((res & 0x8000) == 0x8000) ^ 7158 (ACCESS_FLAG(F_CF) != 0)), 7159 F_OF); 7160 } else { 7161 CLEAR_FLAG(F_OF); 7162 } 7163 } else { 7164 res = 0; 7165 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF); 7166 CLEAR_FLAG(F_OF); 7167 CLEAR_FLAG(F_SF); 7168 SET_FLAG(F_PF); 7169 SET_FLAG(F_ZF); 7170 } 7171 return (uint16_t) res; 7172 } 7173 7174 /* 7175 * REMARKS: 7176 * Implements the SHL instruction and side effects. 7177 */ 7178 static uint32_t 7179 shl_long(struct x86emu *emu, uint32_t d, uint8_t s) 7180 { 7181 unsigned int cnt, res, cf; 7182 7183 if (s < 32) { 7184 cnt = s % 32; 7185 if (cnt > 0) { 7186 res = d << cnt; 7187 cf = d & (1 << (32 - cnt)); 7188 CONDITIONAL_SET_FLAG(cf, F_CF); 7189 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7190 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7191 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7192 } else { 7193 res = d; 7194 } 7195 if (cnt == 1) { 7196 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^ 7197 (ACCESS_FLAG(F_CF) != 0)), F_OF); 7198 } else { 7199 CLEAR_FLAG(F_OF); 7200 } 7201 } else { 7202 res = 0; 7203 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF); 7204 CLEAR_FLAG(F_OF); 7205 CLEAR_FLAG(F_SF); 7206 SET_FLAG(F_PF); 7207 SET_FLAG(F_ZF); 7208 } 7209 return res; 7210 } 7211 7212 /* 7213 * REMARKS: 7214 * Implements the SHR instruction and side effects. 7215 */ 7216 static uint8_t 7217 shr_byte(struct x86emu *emu, uint8_t d, uint8_t s) 7218 { 7219 unsigned int cnt, res, cf; 7220 7221 if (s < 8) { 7222 cnt = s % 8; 7223 if (cnt > 0) { 7224 cf = d & (1 << (cnt - 1)); 7225 res = d >> cnt; 7226 CONDITIONAL_SET_FLAG(cf, F_CF); 7227 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7228 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7229 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7230 } else { 7231 res = (uint8_t) d; 7232 } 7233 7234 if (cnt == 1) { 7235 CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF); 7236 } else { 7237 CLEAR_FLAG(F_OF); 7238 } 7239 } else { 7240 res = 0; 7241 CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF); 7242 CLEAR_FLAG(F_OF); 7243 CLEAR_FLAG(F_SF); 7244 SET_FLAG(F_PF); 7245 SET_FLAG(F_ZF); 7246 } 7247 return (uint8_t) res; 7248 } 7249 7250 /* 7251 * REMARKS: 7252 * Implements the SHR instruction and side effects. 7253 */ 7254 static uint16_t 7255 shr_word(struct x86emu *emu, uint16_t d, uint8_t s) 7256 { 7257 unsigned int cnt, res, cf; 7258 7259 if (s < 16) { 7260 cnt = s % 16; 7261 if (cnt > 0) { 7262 cf = d & (1 << (cnt - 1)); 7263 res = d >> cnt; 7264 CONDITIONAL_SET_FLAG(cf, F_CF); 7265 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7266 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7267 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7268 } else { 7269 res = d; 7270 } 7271 7272 if (cnt == 1) { 7273 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF); 7274 } else { 7275 CLEAR_FLAG(F_OF); 7276 } 7277 } else { 7278 res = 0; 7279 CLEAR_FLAG(F_CF); 7280 CLEAR_FLAG(F_OF); 7281 SET_FLAG(F_ZF); 7282 CLEAR_FLAG(F_SF); 7283 CLEAR_FLAG(F_PF); 7284 } 7285 return (uint16_t) res; 7286 } 7287 7288 /* 7289 * REMARKS: 7290 * Implements the SHR instruction and side effects. 7291 */ 7292 static uint32_t 7293 shr_long(struct x86emu *emu, uint32_t d, uint8_t s) 7294 { 7295 unsigned int cnt, res, cf; 7296 7297 if (s < 32) { 7298 cnt = s % 32; 7299 if (cnt > 0) { 7300 cf = d & (1 << (cnt - 1)); 7301 res = d >> cnt; 7302 CONDITIONAL_SET_FLAG(cf, F_CF); 7303 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7304 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7305 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7306 } else { 7307 res = d; 7308 } 7309 if (cnt == 1) { 7310 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF); 7311 } else { 7312 CLEAR_FLAG(F_OF); 7313 } 7314 } else { 7315 res = 0; 7316 CLEAR_FLAG(F_CF); 7317 CLEAR_FLAG(F_OF); 7318 SET_FLAG(F_ZF); 7319 CLEAR_FLAG(F_SF); 7320 CLEAR_FLAG(F_PF); 7321 } 7322 return res; 7323 } 7324 7325 /* 7326 * REMARKS: 7327 * Implements the SAR instruction and side effects. 7328 */ 7329 static uint8_t 7330 sar_byte(struct x86emu *emu, uint8_t d, uint8_t s) 7331 { 7332 unsigned int cnt, res, cf, mask, sf; 7333 7334 res = d; 7335 sf = d & 0x80; 7336 cnt = s % 8; 7337 if (cnt > 0 && cnt < 8) { 7338 mask = (1 << (8 - cnt)) - 1; 7339 cf = d & (1 << (cnt - 1)); 7340 res = (d >> cnt) & mask; 7341 CONDITIONAL_SET_FLAG(cf, F_CF); 7342 if (sf) { 7343 res |= ~mask; 7344 } 7345 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7346 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7347 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7348 } else if (cnt >= 8) { 7349 if (sf) { 7350 res = 0xff; 7351 SET_FLAG(F_CF); 7352 CLEAR_FLAG(F_ZF); 7353 SET_FLAG(F_SF); 7354 SET_FLAG(F_PF); 7355 } else { 7356 res = 0; 7357 CLEAR_FLAG(F_CF); 7358 SET_FLAG(F_ZF); 7359 CLEAR_FLAG(F_SF); 7360 CLEAR_FLAG(F_PF); 7361 } 7362 } 7363 return (uint8_t) res; 7364 } 7365 7366 /* 7367 * REMARKS: 7368 * Implements the SAR instruction and side effects. 7369 */ 7370 static uint16_t 7371 sar_word(struct x86emu *emu, uint16_t d, uint8_t s) 7372 { 7373 unsigned int cnt, res, cf, mask, sf; 7374 7375 sf = d & 0x8000; 7376 cnt = s % 16; 7377 res = d; 7378 if (cnt > 0 && cnt < 16) { 7379 mask = (1 << (16 - cnt)) - 1; 7380 cf = d & (1 << (cnt - 1)); 7381 res = (d >> cnt) & mask; 7382 CONDITIONAL_SET_FLAG(cf, F_CF); 7383 if (sf) { 7384 res |= ~mask; 7385 } 7386 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7387 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7388 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7389 } else if (cnt >= 16) { 7390 if (sf) { 7391 res = 0xffff; 7392 SET_FLAG(F_CF); 7393 CLEAR_FLAG(F_ZF); 7394 SET_FLAG(F_SF); 7395 SET_FLAG(F_PF); 7396 } else { 7397 res = 0; 7398 CLEAR_FLAG(F_CF); 7399 SET_FLAG(F_ZF); 7400 CLEAR_FLAG(F_SF); 7401 CLEAR_FLAG(F_PF); 7402 } 7403 } 7404 return (uint16_t) res; 7405 } 7406 7407 /* 7408 * REMARKS: 7409 * Implements the SAR instruction and side effects. 7410 */ 7411 static uint32_t 7412 sar_long(struct x86emu *emu, uint32_t d, uint8_t s) 7413 { 7414 uint32_t cnt, res, cf, mask, sf; 7415 7416 sf = d & 0x80000000; 7417 cnt = s % 32; 7418 res = d; 7419 if (cnt > 0 && cnt < 32) { 7420 mask = (1 << (32 - cnt)) - 1; 7421 cf = d & (1 << (cnt - 1)); 7422 res = (d >> cnt) & mask; 7423 CONDITIONAL_SET_FLAG(cf, F_CF); 7424 if (sf) { 7425 res |= ~mask; 7426 } 7427 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7428 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7429 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7430 } else if (cnt >= 32) { 7431 if (sf) { 7432 res = 0xffffffff; 7433 SET_FLAG(F_CF); 7434 CLEAR_FLAG(F_ZF); 7435 SET_FLAG(F_SF); 7436 SET_FLAG(F_PF); 7437 } else { 7438 res = 0; 7439 CLEAR_FLAG(F_CF); 7440 SET_FLAG(F_ZF); 7441 CLEAR_FLAG(F_SF); 7442 CLEAR_FLAG(F_PF); 7443 } 7444 } 7445 return res; 7446 } 7447 7448 /* 7449 * REMARKS: 7450 * Implements the SHLD instruction and side effects. 7451 */ 7452 static uint16_t 7453 shld_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s) 7454 { 7455 unsigned int cnt, res, cf; 7456 7457 if (s < 16) { 7458 cnt = s % 16; 7459 if (cnt > 0) { 7460 res = (d << cnt) | (fill >> (16 - cnt)); 7461 cf = d & (1 << (16 - cnt)); 7462 CONDITIONAL_SET_FLAG(cf, F_CF); 7463 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7464 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7465 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7466 } else { 7467 res = d; 7468 } 7469 if (cnt == 1) { 7470 CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^ 7471 (ACCESS_FLAG(F_CF) != 0)), F_OF); 7472 } else { 7473 CLEAR_FLAG(F_OF); 7474 } 7475 } else { 7476 res = 0; 7477 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF); 7478 CLEAR_FLAG(F_OF); 7479 CLEAR_FLAG(F_SF); 7480 SET_FLAG(F_PF); 7481 SET_FLAG(F_ZF); 7482 } 7483 return (uint16_t) res; 7484 } 7485 7486 /* 7487 * REMARKS: 7488 * Implements the SHLD instruction and side effects. 7489 */ 7490 static uint32_t 7491 shld_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s) 7492 { 7493 unsigned int cnt, res, cf; 7494 7495 if (s < 32) { 7496 cnt = s % 32; 7497 if (cnt > 0) { 7498 res = (d << cnt) | (fill >> (32 - cnt)); 7499 cf = d & (1 << (32 - cnt)); 7500 CONDITIONAL_SET_FLAG(cf, F_CF); 7501 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7502 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7503 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7504 } else { 7505 res = d; 7506 } 7507 if (cnt == 1) { 7508 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^ 7509 (ACCESS_FLAG(F_CF) != 0)), F_OF); 7510 } else { 7511 CLEAR_FLAG(F_OF); 7512 } 7513 } else { 7514 res = 0; 7515 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF); 7516 CLEAR_FLAG(F_OF); 7517 CLEAR_FLAG(F_SF); 7518 SET_FLAG(F_PF); 7519 SET_FLAG(F_ZF); 7520 } 7521 return res; 7522 } 7523 7524 /* 7525 * REMARKS: 7526 * Implements the SHRD instruction and side effects. 7527 */ 7528 static uint16_t 7529 shrd_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s) 7530 { 7531 unsigned int cnt, res, cf; 7532 7533 if (s < 16) { 7534 cnt = s % 16; 7535 if (cnt > 0) { 7536 cf = d & (1 << (cnt - 1)); 7537 res = (d >> cnt) | (fill << (16 - cnt)); 7538 CONDITIONAL_SET_FLAG(cf, F_CF); 7539 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7540 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7541 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7542 } else { 7543 res = d; 7544 } 7545 7546 if (cnt == 1) { 7547 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF); 7548 } else { 7549 CLEAR_FLAG(F_OF); 7550 } 7551 } else { 7552 res = 0; 7553 CLEAR_FLAG(F_CF); 7554 CLEAR_FLAG(F_OF); 7555 SET_FLAG(F_ZF); 7556 CLEAR_FLAG(F_SF); 7557 CLEAR_FLAG(F_PF); 7558 } 7559 return (uint16_t) res; 7560 } 7561 7562 /* 7563 * REMARKS: 7564 * Implements the SHRD instruction and side effects. 7565 */ 7566 static uint32_t 7567 shrd_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s) 7568 { 7569 unsigned int cnt, res, cf; 7570 7571 if (s < 32) { 7572 cnt = s % 32; 7573 if (cnt > 0) { 7574 cf = d & (1 << (cnt - 1)); 7575 res = (d >> cnt) | (fill << (32 - cnt)); 7576 CONDITIONAL_SET_FLAG(cf, F_CF); 7577 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7578 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7579 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7580 } else { 7581 res = d; 7582 } 7583 if (cnt == 1) { 7584 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF); 7585 } else { 7586 CLEAR_FLAG(F_OF); 7587 } 7588 } else { 7589 res = 0; 7590 CLEAR_FLAG(F_CF); 7591 CLEAR_FLAG(F_OF); 7592 SET_FLAG(F_ZF); 7593 CLEAR_FLAG(F_SF); 7594 CLEAR_FLAG(F_PF); 7595 } 7596 return res; 7597 } 7598 7599 /* 7600 * REMARKS: 7601 * Implements the SBB instruction and side effects. 7602 */ 7603 static uint8_t 7604 sbb_byte(struct x86emu *emu, uint8_t d, uint8_t s) 7605 { 7606 uint32_t res; /* all operands in native machine order */ 7607 uint32_t bc; 7608 7609 if (ACCESS_FLAG(F_CF)) 7610 res = d - s - 1; 7611 else 7612 res = d - s; 7613 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7614 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7615 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7616 7617 /* calculate the borrow chain. See note at top */ 7618 bc = (res & (~d | s)) | (~d & s); 7619 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); 7620 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 7621 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7622 return (uint8_t) res; 7623 } 7624 7625 /* 7626 * REMARKS: 7627 * Implements the SBB instruction and side effects. 7628 */ 7629 static uint16_t 7630 sbb_word(struct x86emu *emu, uint16_t d, uint16_t s) 7631 { 7632 uint32_t res; /* all operands in native machine order */ 7633 uint32_t bc; 7634 7635 if (ACCESS_FLAG(F_CF)) 7636 res = d - s - 1; 7637 else 7638 res = d - s; 7639 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7640 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7641 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7642 7643 /* calculate the borrow chain. See note at top */ 7644 bc = (res & (~d | s)) | (~d & s); 7645 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 7646 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 7647 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7648 return (uint16_t) res; 7649 } 7650 7651 /* 7652 * REMARKS: 7653 * Implements the SBB instruction and side effects. 7654 */ 7655 static uint32_t 7656 sbb_long(struct x86emu *emu, uint32_t d, uint32_t s) 7657 { 7658 uint32_t res; /* all operands in native machine order */ 7659 uint32_t bc; 7660 7661 if (ACCESS_FLAG(F_CF)) 7662 res = d - s - 1; 7663 else 7664 res = d - s; 7665 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7666 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7667 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7668 7669 /* calculate the borrow chain. See note at top */ 7670 bc = (res & (~d | s)) | (~d & s); 7671 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 7672 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 7673 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7674 return res; 7675 } 7676 7677 /* 7678 * REMARKS: 7679 * Implements the SUB instruction and side effects. 7680 */ 7681 static uint8_t 7682 sub_byte(struct x86emu *emu, uint8_t d, uint8_t s) 7683 { 7684 uint32_t res; /* all operands in native machine order */ 7685 uint32_t bc; 7686 7687 res = d - s; 7688 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7689 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7690 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7691 7692 /* calculate the borrow chain. See note at top */ 7693 bc = (res & (~d | s)) | (~d & s); 7694 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); 7695 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 7696 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7697 return (uint8_t) res; 7698 } 7699 7700 /* 7701 * REMARKS: 7702 * Implements the SUB instruction and side effects. 7703 */ 7704 static uint16_t 7705 sub_word(struct x86emu *emu, uint16_t d, uint16_t s) 7706 { 7707 uint32_t res; /* all operands in native machine order */ 7708 uint32_t bc; 7709 7710 res = d - s; 7711 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7712 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7713 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7714 7715 /* calculate the borrow chain. See note at top */ 7716 bc = (res & (~d | s)) | (~d & s); 7717 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 7718 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 7719 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7720 return (uint16_t) res; 7721 } 7722 7723 /* 7724 * REMARKS: 7725 * Implements the SUB instruction and side effects. 7726 */ 7727 static uint32_t 7728 sub_long(struct x86emu *emu, uint32_t d, uint32_t s) 7729 { 7730 uint32_t res; /* all operands in native machine order */ 7731 uint32_t bc; 7732 7733 res = d - s; 7734 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7735 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7736 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7737 7738 /* calculate the borrow chain. See note at top */ 7739 bc = (res & (~d | s)) | (~d & s); 7740 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 7741 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 7742 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7743 return res; 7744 } 7745 7746 /* 7747 * REMARKS: 7748 * Implements the TEST instruction and side effects. 7749 */ 7750 static void 7751 test_byte(struct x86emu *emu, uint8_t d, uint8_t s) 7752 { 7753 uint32_t res; /* all operands in native machine order */ 7754 7755 res = d & s; 7756 7757 CLEAR_FLAG(F_OF); 7758 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7759 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7760 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7761 /* AF == dont care */ 7762 CLEAR_FLAG(F_CF); 7763 } 7764 7765 /* 7766 * REMARKS: 7767 * Implements the TEST instruction and side effects. 7768 */ 7769 static void 7770 test_word(struct x86emu *emu, uint16_t d, uint16_t s) 7771 { 7772 uint32_t res; /* all operands in native machine order */ 7773 7774 res = d & s; 7775 7776 CLEAR_FLAG(F_OF); 7777 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7778 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7779 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7780 /* AF == dont care */ 7781 CLEAR_FLAG(F_CF); 7782 } 7783 7784 /* 7785 * REMARKS: 7786 * Implements the TEST instruction and side effects. 7787 */ 7788 static void 7789 test_long(struct x86emu *emu, uint32_t d, uint32_t s) 7790 { 7791 uint32_t res; /* all operands in native machine order */ 7792 7793 res = d & s; 7794 7795 CLEAR_FLAG(F_OF); 7796 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7797 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7798 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7799 /* AF == dont care */ 7800 CLEAR_FLAG(F_CF); 7801 } 7802 7803 /* 7804 * REMARKS: 7805 * Implements the XOR instruction and side effects. 7806 */ 7807 static uint8_t 7808 xor_byte(struct x86emu *emu, uint8_t d, uint8_t s) 7809 { 7810 uint8_t res; /* all operands in native machine order */ 7811 7812 res = d ^ s; 7813 CLEAR_FLAG(F_OF); 7814 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7815 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7816 CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 7817 CLEAR_FLAG(F_CF); 7818 CLEAR_FLAG(F_AF); 7819 return res; 7820 } 7821 7822 /* 7823 * REMARKS: 7824 * Implements the XOR instruction and side effects. 7825 */ 7826 static uint16_t 7827 xor_word(struct x86emu *emu, uint16_t d, uint16_t s) 7828 { 7829 uint16_t res; /* all operands in native machine order */ 7830 7831 res = d ^ s; 7832 CLEAR_FLAG(F_OF); 7833 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7834 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7835 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7836 CLEAR_FLAG(F_CF); 7837 CLEAR_FLAG(F_AF); 7838 return res; 7839 } 7840 7841 /* 7842 * REMARKS: 7843 * Implements the XOR instruction and side effects. 7844 */ 7845 static uint32_t 7846 xor_long(struct x86emu *emu, uint32_t d, uint32_t s) 7847 { 7848 uint32_t res; /* all operands in native machine order */ 7849 7850 res = d ^ s; 7851 CLEAR_FLAG(F_OF); 7852 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7853 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7854 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7855 CLEAR_FLAG(F_CF); 7856 CLEAR_FLAG(F_AF); 7857 return res; 7858 } 7859 7860 /* 7861 * REMARKS: 7862 * Implements the IMUL instruction and side effects. 7863 */ 7864 static void 7865 imul_byte(struct x86emu *emu, uint8_t s) 7866 { 7867 int16_t res = (int16_t) ((int8_t) emu->x86.R_AL * (int8_t) s); 7868 7869 emu->x86.R_AX = res; 7870 if (((emu->x86.R_AL & 0x80) == 0 && emu->x86.R_AH == 0x00) || 7871 ((emu->x86.R_AL & 0x80) != 0 && emu->x86.R_AH == 0xFF)) { 7872 CLEAR_FLAG(F_CF); 7873 CLEAR_FLAG(F_OF); 7874 } else { 7875 SET_FLAG(F_CF); 7876 SET_FLAG(F_OF); 7877 } 7878 } 7879 7880 /* 7881 * REMARKS: 7882 * Implements the IMUL instruction and side effects. 7883 */ 7884 static void 7885 imul_word(struct x86emu *emu, uint16_t s) 7886 { 7887 int32_t res = (int16_t) emu->x86.R_AX * (int16_t) s; 7888 7889 emu->x86.R_AX = (uint16_t) res; 7890 emu->x86.R_DX = (uint16_t) (res >> 16); 7891 if (((emu->x86.R_AX & 0x8000) == 0 && emu->x86.R_DX == 0x00) || 7892 ((emu->x86.R_AX & 0x8000) != 0 && emu->x86.R_DX == 0xFF)) { 7893 CLEAR_FLAG(F_CF); 7894 CLEAR_FLAG(F_OF); 7895 } else { 7896 SET_FLAG(F_CF); 7897 SET_FLAG(F_OF); 7898 } 7899 } 7900 7901 /* 7902 * REMARKS: 7903 * Implements the IMUL instruction and side effects. 7904 */ 7905 static void 7906 imul_long(struct x86emu *emu, uint32_t s) 7907 { 7908 int64_t res; 7909 7910 res = (int64_t)(int32_t)emu->x86.R_EAX * (int32_t)s; 7911 emu->x86.R_EAX = (uint32_t)res; 7912 emu->x86.R_EDX = ((uint64_t)res) >> 32; 7913 if (((emu->x86.R_EAX & 0x80000000) == 0 && emu->x86.R_EDX == 0x00) || 7914 ((emu->x86.R_EAX & 0x80000000) != 0 && emu->x86.R_EDX == 0xFF)) { 7915 CLEAR_FLAG(F_CF); 7916 CLEAR_FLAG(F_OF); 7917 } else { 7918 SET_FLAG(F_CF); 7919 SET_FLAG(F_OF); 7920 } 7921 } 7922 7923 /* 7924 * REMARKS: 7925 * Implements the MUL instruction and side effects. 7926 */ 7927 static void 7928 mul_byte(struct x86emu *emu, uint8_t s) 7929 { 7930 uint16_t res = (uint16_t) (emu->x86.R_AL * s); 7931 7932 emu->x86.R_AX = res; 7933 if (emu->x86.R_AH == 0) { 7934 CLEAR_FLAG(F_CF); 7935 CLEAR_FLAG(F_OF); 7936 } else { 7937 SET_FLAG(F_CF); 7938 SET_FLAG(F_OF); 7939 } 7940 } 7941 7942 /* 7943 * REMARKS: 7944 * Implements the MUL instruction and side effects. 7945 */ 7946 static void 7947 mul_word(struct x86emu *emu, uint16_t s) 7948 { 7949 uint32_t res = emu->x86.R_AX * s; 7950 7951 emu->x86.R_AX = (uint16_t) res; 7952 emu->x86.R_DX = (uint16_t) (res >> 16); 7953 if (emu->x86.R_DX == 0) { 7954 CLEAR_FLAG(F_CF); 7955 CLEAR_FLAG(F_OF); 7956 } else { 7957 SET_FLAG(F_CF); 7958 SET_FLAG(F_OF); 7959 } 7960 } 7961 7962 /* 7963 * REMARKS: 7964 * Implements the MUL instruction and side effects. 7965 */ 7966 static void 7967 mul_long(struct x86emu *emu, uint32_t s) 7968 { 7969 uint64_t res = (uint64_t) emu->x86.R_EAX * s; 7970 7971 emu->x86.R_EAX = (uint32_t) res; 7972 emu->x86.R_EDX = (uint32_t) (res >> 32); 7973 7974 if (emu->x86.R_EDX == 0) { 7975 CLEAR_FLAG(F_CF); 7976 CLEAR_FLAG(F_OF); 7977 } else { 7978 SET_FLAG(F_CF); 7979 SET_FLAG(F_OF); 7980 } 7981 } 7982 7983 /* 7984 * REMARKS: 7985 * Implements the IDIV instruction and side effects. 7986 */ 7987 static void 7988 idiv_byte(struct x86emu *emu, uint8_t s) 7989 { 7990 int32_t dvd, div, mod; 7991 7992 dvd = (int16_t) emu->x86.R_AX; 7993 if (s == 0) { 7994 x86emu_intr_raise(emu, 8); 7995 return; 7996 } 7997 div = dvd / (int8_t) s; 7998 mod = dvd % (int8_t) s; 7999 if (div > 0x7f || div < -0x7f) { 8000 x86emu_intr_raise(emu, 8); 8001 return; 8002 } 8003 emu->x86.R_AL = (int8_t) div; 8004 emu->x86.R_AH = (int8_t) mod; 8005 } 8006 8007 /* 8008 * REMARKS: 8009 * Implements the IDIV instruction and side effects. 8010 */ 8011 static void 8012 idiv_word(struct x86emu *emu, uint16_t s) 8013 { 8014 int32_t dvd, div, mod; 8015 8016 dvd = (((int32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX; 8017 if (s == 0) { 8018 x86emu_intr_raise(emu, 8); 8019 return; 8020 } 8021 div = dvd / (int16_t) s; 8022 mod = dvd % (int16_t) s; 8023 if (div > 0x7fff || div < -0x7fff) { 8024 x86emu_intr_raise(emu, 8); 8025 return; 8026 } 8027 CLEAR_FLAG(F_CF); 8028 CLEAR_FLAG(F_SF); 8029 CONDITIONAL_SET_FLAG(div == 0, F_ZF); 8030 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 8031 8032 emu->x86.R_AX = (uint16_t) div; 8033 emu->x86.R_DX = (uint16_t) mod; 8034 } 8035 8036 /* 8037 * REMARKS: 8038 * Implements the IDIV instruction and side effects. 8039 */ 8040 static void 8041 idiv_long(struct x86emu *emu, uint32_t s) 8042 { 8043 int64_t dvd, div, mod; 8044 8045 dvd = (((int64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX; 8046 if (s == 0) { 8047 x86emu_intr_raise(emu, 8); 8048 return; 8049 } 8050 div = dvd / (int32_t) s; 8051 mod = dvd % (int32_t) s; 8052 if (div > 0x7fffffff || div < -0x7fffffff) { 8053 x86emu_intr_raise(emu, 8); 8054 return; 8055 } 8056 CLEAR_FLAG(F_CF); 8057 CLEAR_FLAG(F_AF); 8058 CLEAR_FLAG(F_SF); 8059 SET_FLAG(F_ZF); 8060 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 8061 8062 emu->x86.R_EAX = (uint32_t) div; 8063 emu->x86.R_EDX = (uint32_t) mod; 8064 } 8065 8066 /* 8067 * REMARKS: 8068 * Implements the DIV instruction and side effects. 8069 */ 8070 static void 8071 div_byte(struct x86emu *emu, uint8_t s) 8072 { 8073 uint32_t dvd, div, mod; 8074 8075 dvd = emu->x86.R_AX; 8076 if (s == 0) { 8077 x86emu_intr_raise(emu, 8); 8078 return; 8079 } 8080 div = dvd / (uint8_t) s; 8081 mod = dvd % (uint8_t) s; 8082 if (div > 0xff) { 8083 x86emu_intr_raise(emu, 8); 8084 return; 8085 } 8086 emu->x86.R_AL = (uint8_t) div; 8087 emu->x86.R_AH = (uint8_t) mod; 8088 } 8089 8090 /* 8091 * REMARKS: 8092 * Implements the DIV instruction and side effects. 8093 */ 8094 static void 8095 div_word(struct x86emu *emu, uint16_t s) 8096 { 8097 uint32_t dvd, div, mod; 8098 8099 dvd = (((uint32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX; 8100 if (s == 0) { 8101 x86emu_intr_raise(emu, 8); 8102 return; 8103 } 8104 div = dvd / (uint16_t) s; 8105 mod = dvd % (uint16_t) s; 8106 if (div > 0xffff) { 8107 x86emu_intr_raise(emu, 8); 8108 return; 8109 } 8110 CLEAR_FLAG(F_CF); 8111 CLEAR_FLAG(F_SF); 8112 CONDITIONAL_SET_FLAG(div == 0, F_ZF); 8113 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 8114 8115 emu->x86.R_AX = (uint16_t) div; 8116 emu->x86.R_DX = (uint16_t) mod; 8117 } 8118 8119 /* 8120 * REMARKS: 8121 * Implements the DIV instruction and side effects. 8122 */ 8123 static void 8124 div_long(struct x86emu *emu, uint32_t s) 8125 { 8126 uint64_t dvd, div, mod; 8127 8128 dvd = (((uint64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX; 8129 if (s == 0) { 8130 x86emu_intr_raise(emu, 8); 8131 return; 8132 } 8133 div = dvd / (uint32_t) s; 8134 mod = dvd % (uint32_t) s; 8135 if (div > 0xffffffff) { 8136 x86emu_intr_raise(emu, 8); 8137 return; 8138 } 8139 CLEAR_FLAG(F_CF); 8140 CLEAR_FLAG(F_AF); 8141 CLEAR_FLAG(F_SF); 8142 SET_FLAG(F_ZF); 8143 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 8144 8145 emu->x86.R_EAX = (uint32_t) div; 8146 emu->x86.R_EDX = (uint32_t) mod; 8147 } 8148 8149 /* 8150 * REMARKS: 8151 * Implements the IN string instruction and side effects. 8152 */ 8153 static void 8154 ins(struct x86emu *emu, int size) 8155 { 8156 int inc = size; 8157 8158 if (ACCESS_FLAG(F_DF)) { 8159 inc = -size; 8160 } 8161 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 8162 /* dont care whether REPE or REPNE */ 8163 /* in until CX is ZERO. */ 8164 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ? 8165 emu->x86.R_ECX : emu->x86.R_CX); 8166 switch (size) { 8167 case 1: 8168 while (count--) { 8169 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, 8170 (*emu->emu_inb) (emu, emu->x86.R_DX)); 8171 emu->x86.R_DI += inc; 8172 } 8173 break; 8174 8175 case 2: 8176 while (count--) { 8177 store_word(emu, emu->x86.R_ES, emu->x86.R_DI, 8178 (*emu->emu_inw) (emu, emu->x86.R_DX)); 8179 emu->x86.R_DI += inc; 8180 } 8181 break; 8182 case 4: 8183 while (count--) { 8184 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, 8185 (*emu->emu_inl) (emu, emu->x86.R_DX)); 8186 emu->x86.R_DI += inc; 8187 break; 8188 } 8189 } 8190 emu->x86.R_CX = 0; 8191 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 8192 emu->x86.R_ECX = 0; 8193 } 8194 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 8195 } else { 8196 switch (size) { 8197 case 1: 8198 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, 8199 (*emu->emu_inb) (emu, emu->x86.R_DX)); 8200 break; 8201 case 2: 8202 store_word(emu, emu->x86.R_ES, emu->x86.R_DI, 8203 (*emu->emu_inw) (emu, emu->x86.R_DX)); 8204 break; 8205 case 4: 8206 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, 8207 (*emu->emu_inl) (emu, emu->x86.R_DX)); 8208 break; 8209 } 8210 emu->x86.R_DI += inc; 8211 } 8212 } 8213 8214 /* 8215 * REMARKS: 8216 * Implements the OUT string instruction and side effects. 8217 */ 8218 static void 8219 outs(struct x86emu *emu, int size) 8220 { 8221 int inc = size; 8222 8223 if (ACCESS_FLAG(F_DF)) { 8224 inc = -size; 8225 } 8226 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 8227 /* dont care whether REPE or REPNE */ 8228 /* out until CX is ZERO. */ 8229 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ? 8230 emu->x86.R_ECX : emu->x86.R_CX); 8231 switch (size) { 8232 case 1: 8233 while (count--) { 8234 (*emu->emu_outb) (emu, emu->x86.R_DX, 8235 fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI)); 8236 emu->x86.R_SI += inc; 8237 } 8238 break; 8239 8240 case 2: 8241 while (count--) { 8242 (*emu->emu_outw) (emu, emu->x86.R_DX, 8243 fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI)); 8244 emu->x86.R_SI += inc; 8245 } 8246 break; 8247 case 4: 8248 while (count--) { 8249 (*emu->emu_outl) (emu, emu->x86.R_DX, 8250 fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI)); 8251 emu->x86.R_SI += inc; 8252 break; 8253 } 8254 } 8255 emu->x86.R_CX = 0; 8256 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 8257 emu->x86.R_ECX = 0; 8258 } 8259 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 8260 } else { 8261 switch (size) { 8262 case 1: 8263 (*emu->emu_outb) (emu, emu->x86.R_DX, 8264 fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI)); 8265 break; 8266 case 2: 8267 (*emu->emu_outw) (emu, emu->x86.R_DX, 8268 fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI)); 8269 break; 8270 case 4: 8271 (*emu->emu_outl) (emu, emu->x86.R_DX, 8272 fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI)); 8273 break; 8274 } 8275 emu->x86.R_SI += inc; 8276 } 8277 } 8278 8279 /* 8280 * REMARKS: 8281 * Pushes a word onto the stack. 8282 * 8283 * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline! 8284 */ 8285 static void 8286 push_word(struct x86emu *emu, uint16_t w) 8287 { 8288 emu->x86.R_SP -= 2; 8289 store_word(emu, emu->x86.R_SS, emu->x86.R_SP, w); 8290 } 8291 8292 /* 8293 * REMARKS: 8294 * Pushes a long onto the stack. 8295 * 8296 * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline! 8297 */ 8298 static void 8299 push_long(struct x86emu *emu, uint32_t w) 8300 { 8301 emu->x86.R_SP -= 4; 8302 store_long(emu, emu->x86.R_SS, emu->x86.R_SP, w); 8303 } 8304 8305 /* 8306 * REMARKS: 8307 * Pops a word from the stack. 8308 * 8309 * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline! 8310 */ 8311 static uint16_t 8312 pop_word(struct x86emu *emu) 8313 { 8314 uint16_t res; 8315 8316 res = fetch_word(emu, emu->x86.R_SS, emu->x86.R_SP); 8317 emu->x86.R_SP += 2; 8318 return res; 8319 } 8320 8321 /* 8322 * REMARKS: 8323 * Pops a long from the stack. 8324 * 8325 * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline! 8326 */ 8327 static uint32_t 8328 pop_long(struct x86emu *emu) 8329 { 8330 uint32_t res; 8331 8332 res = fetch_long(emu, emu->x86.R_SS, emu->x86.R_SP); 8333 emu->x86.R_SP += 4; 8334 return res; 8335 } 8336