1 /**************************************************************************** 2 * Realmode X86 Emulator Library 3 * 4 * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. 5 * Jason Jin <Jason.jin@freescale.com> 6 * 7 * Copyright (C) 1991-2004 SciTech Software, Inc. 8 * Copyright (C) David Mosberger-Tang 9 * Copyright (C) 1999 Egbert Eich 10 * 11 * ======================================================================== 12 * 13 * Permission to use, copy, modify, distribute, and sell this software and 14 * its documentation for any purpose is hereby granted without fee, 15 * provided that the above copyright notice appear in all copies and that 16 * both that copyright notice and this permission notice appear in 17 * supporting documentation, and that the name of the authors not be used 18 * in advertising or publicity pertaining to distribution of the software 19 * without specific, written prior permission. The authors makes no 20 * representations about the suitability of this software for any purpose. 21 * It is provided "as is" without express or implied warranty. 22 * 23 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 24 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 25 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 26 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 27 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 28 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 29 * PERFORMANCE OF THIS SOFTWARE. 30 * 31 * ======================================================================== 32 * 33 * Language: ANSI C 34 * Environment: Any 35 * Developer: Kendall Bennett 36 * 37 * Description: This file includes subroutines to implement the decoding 38 * and emulation of all the x86 processor instructions. 39 * 40 * There are approximately 250 subroutines in here, which correspond 41 * to the 256 byte-"opcodes" found on the 8086. The table which 42 * dispatches this is found in the files optab.[ch]. 43 * 44 * Each opcode proc has a comment preceeding it which gives it's table 45 * address. Several opcodes are missing (undefined) in the table. 46 * 47 * Each proc includes information for decoding (DECODE_PRINTF and 48 * DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc 49 * functions (START_OF_INSTR, END_OF_INSTR). 50 * 51 * Many of the procedures are *VERY* similar in coding. This has 52 * allowed for a very large amount of code to be generated in a fairly 53 * short amount of time (i.e. cut, paste, and modify). The result is 54 * that much of the code below could have been folded into subroutines 55 * for a large reduction in size of this file. The downside would be 56 * that there would be a penalty in execution speed. The file could 57 * also have been *MUCH* larger by inlining certain functions which 58 * were called. This could have resulted even faster execution. The 59 * prime directive I used to decide whether to inline the code or to 60 * modularize it, was basically: 1) no unnecessary subroutine calls, 61 * 2) no routines more than about 200 lines in size, and 3) modularize 62 * any code that I might not get right the first time. The fetch_* 63 * subroutines fall into the latter category. The The decode_* fall 64 * into the second category. The coding of the "switch(mod){ .... }" 65 * in many of the subroutines below falls into the first category. 66 * Especially, the coding of {add,and,or,sub,...}_{byte,word} 67 * subroutines are an especially glaring case of the third guideline. 68 * Since so much of the code is cloned from other modules (compare 69 * opcode #00 to opcode #01), making the basic operations subroutine 70 * calls is especially important; otherwise mistakes in coding an 71 * "add" would represent a nightmare in maintenance. 72 * 73 * Jason ported this file to u-boot. place all the function pointer in 74 * the got2 sector. Removed some opcode. 75 * 76 ****************************************************************************/ 77 78 #include "x86emu/x86emui.h" 79 /*----------------------------- Implementation ----------------------------*/ 80 81 /* constant arrays to do several instructions in just one function */ 82 83 #ifdef DEBUG 84 static char *x86emu_GenOpName[8] = { 85 "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"}; 86 #endif 87 88 /* used by several opcodes */ 89 static u8 (*genop_byte_operation[])(u8 d, u8 s) __attribute__ ((section(".got2"))) = 90 { 91 add_byte, /* 00 */ 92 or_byte, /* 01 */ 93 adc_byte, /* 02 */ 94 sbb_byte, /* 03 */ 95 and_byte, /* 04 */ 96 sub_byte, /* 05 */ 97 xor_byte, /* 06 */ 98 cmp_byte, /* 07 */ 99 }; 100 101 static u16 (*genop_word_operation[])(u16 d, u16 s) __attribute__ ((section(".got2"))) = 102 { 103 add_word, /*00 */ 104 or_word, /*01 */ 105 adc_word, /*02 */ 106 sbb_word, /*03 */ 107 and_word, /*04 */ 108 sub_word, /*05 */ 109 xor_word, /*06 */ 110 cmp_word, /*07 */ 111 }; 112 113 static u32 (*genop_long_operation[])(u32 d, u32 s) __attribute__ ((section(".got2"))) = 114 { 115 add_long, /*00 */ 116 or_long, /*01 */ 117 adc_long, /*02 */ 118 sbb_long, /*03 */ 119 and_long, /*04 */ 120 sub_long, /*05 */ 121 xor_long, /*06 */ 122 cmp_long, /*07 */ 123 }; 124 125 /* used by opcodes 80, c0, d0, and d2. */ 126 static u8(*opcD0_byte_operation[])(u8 d, u8 s) __attribute__ ((section(".got2"))) = 127 { 128 rol_byte, 129 ror_byte, 130 rcl_byte, 131 rcr_byte, 132 shl_byte, 133 shr_byte, 134 shl_byte, /* sal_byte === shl_byte by definition */ 135 sar_byte, 136 }; 137 138 /* used by opcodes c1, d1, and d3. */ 139 static u16(*opcD1_word_operation[])(u16 s, u8 d) __attribute__ ((section(".got2"))) = 140 { 141 rol_word, 142 ror_word, 143 rcl_word, 144 rcr_word, 145 shl_word, 146 shr_word, 147 shl_word, /* sal_byte === shl_byte by definition */ 148 sar_word, 149 }; 150 151 /* used by opcodes c1, d1, and d3. */ 152 static u32 (*opcD1_long_operation[])(u32 s, u8 d) __attribute__ ((section(".got2"))) = 153 { 154 rol_long, 155 ror_long, 156 rcl_long, 157 rcr_long, 158 shl_long, 159 shr_long, 160 shl_long, /* sal_byte === shl_byte by definition */ 161 sar_long, 162 }; 163 164 #ifdef DEBUG 165 166 static char *opF6_names[8] = 167 { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" }; 168 169 #endif 170 171 /**************************************************************************** 172 PARAMETERS: 173 op1 - Instruction op code 174 175 REMARKS: 176 Handles illegal opcodes. 177 ****************************************************************************/ 178 void x86emuOp_illegal_op( 179 u8 op1) 180 { 181 START_OF_INSTR(); 182 if (M.x86.R_SP != 0) { 183 DECODE_PRINTF("ILLEGAL X86 OPCODE\n"); 184 TRACE_REGS(); 185 DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n", 186 M.x86.R_CS, M.x86.R_IP-1,op1)); 187 HALT_SYS(); 188 } 189 else { 190 /* If we get here, it means the stack pointer is back to zero 191 * so we are just returning from an emulator service call 192 * so therte is no need to display an error message. We trap 193 * the emulator with an 0xF1 opcode to finish the service 194 * call. 195 */ 196 X86EMU_halt_sys(); 197 } 198 END_OF_INSTR(); 199 } 200 201 /**************************************************************************** 202 REMARKS: 203 Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38 204 ****************************************************************************/ 205 void x86emuOp_genop_byte_RM_R(u8 op1) 206 { 207 int mod, rl, rh; 208 uint destoffset; 209 u8 *destreg, *srcreg; 210 u8 destval; 211 212 op1 = (op1 >> 3) & 0x7; 213 214 START_OF_INSTR(); 215 DECODE_PRINTF(x86emu_GenOpName[op1]); 216 DECODE_PRINTF("\t"); 217 FETCH_DECODE_MODRM(mod, rh, rl); 218 if(mod<3) 219 { destoffset = decode_rmXX_address(mod,rl); 220 DECODE_PRINTF(","); 221 destval = fetch_data_byte(destoffset); 222 srcreg = DECODE_RM_BYTE_REGISTER(rh); 223 DECODE_PRINTF("\n"); 224 TRACE_AND_STEP(); 225 destval = genop_byte_operation[op1](destval, *srcreg); 226 store_data_byte(destoffset, destval); 227 } 228 else 229 { /* register to register */ 230 destreg = DECODE_RM_BYTE_REGISTER(rl); 231 DECODE_PRINTF(","); 232 srcreg = DECODE_RM_BYTE_REGISTER(rh); 233 DECODE_PRINTF("\n"); 234 TRACE_AND_STEP(); 235 *destreg = genop_byte_operation[op1](*destreg, *srcreg); 236 } 237 DECODE_CLEAR_SEGOVR(); 238 END_OF_INSTR(); 239 } 240 241 /**************************************************************************** 242 REMARKS: 243 Handles opcodes 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39 244 ****************************************************************************/ 245 void x86emuOp_genop_word_RM_R(u8 op1) 246 { 247 int mod, rl, rh; 248 uint destoffset; 249 250 op1 = (op1 >> 3) & 0x7; 251 252 START_OF_INSTR(); 253 DECODE_PRINTF(x86emu_GenOpName[op1]); 254 DECODE_PRINTF("\t"); 255 FETCH_DECODE_MODRM(mod, rh, rl); 256 257 if(mod<3) { 258 destoffset = decode_rmXX_address(mod,rl); 259 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 260 u32 destval; 261 u32 *srcreg; 262 263 DECODE_PRINTF(","); 264 destval = fetch_data_long(destoffset); 265 srcreg = DECODE_RM_LONG_REGISTER(rh); 266 DECODE_PRINTF("\n"); 267 TRACE_AND_STEP(); 268 destval = genop_long_operation[op1](destval, *srcreg); 269 store_data_long(destoffset, destval); 270 } else { 271 u16 destval; 272 u16 *srcreg; 273 274 DECODE_PRINTF(","); 275 destval = fetch_data_word(destoffset); 276 srcreg = DECODE_RM_WORD_REGISTER(rh); 277 DECODE_PRINTF("\n"); 278 TRACE_AND_STEP(); 279 destval = genop_word_operation[op1](destval, *srcreg); 280 store_data_word(destoffset, destval); 281 } 282 } else { /* register to register */ 283 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 284 u32 *destreg,*srcreg; 285 286 destreg = DECODE_RM_LONG_REGISTER(rl); 287 DECODE_PRINTF(","); 288 srcreg = DECODE_RM_LONG_REGISTER(rh); 289 DECODE_PRINTF("\n"); 290 TRACE_AND_STEP(); 291 *destreg = genop_long_operation[op1](*destreg, *srcreg); 292 } else { 293 u16 *destreg,*srcreg; 294 295 destreg = DECODE_RM_WORD_REGISTER(rl); 296 DECODE_PRINTF(","); 297 srcreg = DECODE_RM_WORD_REGISTER(rh); 298 DECODE_PRINTF("\n"); 299 TRACE_AND_STEP(); 300 *destreg = genop_word_operation[op1](*destreg, *srcreg); 301 } 302 } 303 DECODE_CLEAR_SEGOVR(); 304 END_OF_INSTR(); 305 } 306 307 /**************************************************************************** 308 REMARKS: 309 Handles opcodes 0x02, 0x0a, 0x12, 0x1a, 0x22, 0x2a, 0x32, 0x3a 310 ****************************************************************************/ 311 void x86emuOp_genop_byte_R_RM(u8 op1) 312 { 313 int mod, rl, rh; 314 u8 *destreg, *srcreg; 315 uint srcoffset; 316 u8 srcval; 317 318 op1 = (op1 >> 3) & 0x7; 319 320 START_OF_INSTR(); 321 DECODE_PRINTF(x86emu_GenOpName[op1]); 322 DECODE_PRINTF("\t"); 323 FETCH_DECODE_MODRM(mod, rh, rl); 324 if (mod < 3) { 325 destreg = DECODE_RM_BYTE_REGISTER(rh); 326 DECODE_PRINTF(","); 327 srcoffset = decode_rmXX_address(mod,rl); 328 srcval = fetch_data_byte(srcoffset); 329 } else { /* register to register */ 330 destreg = DECODE_RM_BYTE_REGISTER(rh); 331 DECODE_PRINTF(","); 332 srcreg = DECODE_RM_BYTE_REGISTER(rl); 333 srcval = *srcreg; 334 } 335 DECODE_PRINTF("\n"); 336 TRACE_AND_STEP(); 337 *destreg = genop_byte_operation[op1](*destreg, srcval); 338 339 DECODE_CLEAR_SEGOVR(); 340 END_OF_INSTR(); 341 } 342 343 /**************************************************************************** 344 REMARKS: 345 Handles opcodes 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3b 346 ****************************************************************************/ 347 void x86emuOp_genop_word_R_RM(u8 op1) 348 { 349 int mod, rl, rh; 350 uint srcoffset; 351 u32 *destreg32, srcval; 352 u16 *destreg; 353 354 op1 = (op1 >> 3) & 0x7; 355 356 START_OF_INSTR(); 357 DECODE_PRINTF(x86emu_GenOpName[op1]); 358 DECODE_PRINTF("\t"); 359 FETCH_DECODE_MODRM(mod, rh, rl); 360 if (mod < 3) { 361 srcoffset = decode_rmXX_address(mod,rl); 362 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 363 destreg32 = DECODE_RM_LONG_REGISTER(rh); 364 DECODE_PRINTF(","); 365 srcval = fetch_data_long(srcoffset); 366 DECODE_PRINTF("\n"); 367 TRACE_AND_STEP(); 368 *destreg32 = genop_long_operation[op1](*destreg32, srcval); 369 } else { 370 destreg = DECODE_RM_WORD_REGISTER(rh); 371 DECODE_PRINTF(","); 372 srcval = fetch_data_word(srcoffset); 373 DECODE_PRINTF("\n"); 374 TRACE_AND_STEP(); 375 *destreg = genop_word_operation[op1](*destreg, srcval); 376 } 377 } else { /* register to register */ 378 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 379 u32 *srcreg; 380 destreg32 = DECODE_RM_LONG_REGISTER(rh); 381 DECODE_PRINTF(","); 382 srcreg = DECODE_RM_LONG_REGISTER(rl); 383 DECODE_PRINTF("\n"); 384 TRACE_AND_STEP(); 385 *destreg32 = genop_long_operation[op1](*destreg32, *srcreg); 386 } else { 387 u16 *srcreg; 388 destreg = DECODE_RM_WORD_REGISTER(rh); 389 DECODE_PRINTF(","); 390 srcreg = DECODE_RM_WORD_REGISTER(rl); 391 DECODE_PRINTF("\n"); 392 TRACE_AND_STEP(); 393 *destreg = genop_word_operation[op1](*destreg, *srcreg); 394 } 395 } 396 DECODE_CLEAR_SEGOVR(); 397 END_OF_INSTR(); 398 } 399 400 /**************************************************************************** 401 REMARKS: 402 Handles opcodes 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c 403 ****************************************************************************/ 404 void x86emuOp_genop_byte_AL_IMM(u8 op1) 405 { 406 u8 srcval; 407 408 op1 = (op1 >> 3) & 0x7; 409 410 START_OF_INSTR(); 411 DECODE_PRINTF(x86emu_GenOpName[op1]); 412 DECODE_PRINTF("\tAL,"); 413 srcval = fetch_byte_imm(); 414 DECODE_PRINTF2("%x\n", srcval); 415 TRACE_AND_STEP(); 416 M.x86.R_AL = genop_byte_operation[op1](M.x86.R_AL, srcval); 417 DECODE_CLEAR_SEGOVR(); 418 END_OF_INSTR(); 419 } 420 421 /**************************************************************************** 422 REMARKS: 423 Handles opcodes 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x35, 0x3d 424 ****************************************************************************/ 425 void x86emuOp_genop_word_AX_IMM(u8 op1) 426 { 427 u32 srcval; 428 429 op1 = (op1 >> 3) & 0x7; 430 431 START_OF_INSTR(); 432 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 433 DECODE_PRINTF(x86emu_GenOpName[op1]); 434 DECODE_PRINTF("\tEAX,"); 435 srcval = fetch_long_imm(); 436 } else { 437 DECODE_PRINTF(x86emu_GenOpName[op1]); 438 DECODE_PRINTF("\tAX,"); 439 srcval = fetch_word_imm(); 440 } 441 DECODE_PRINTF2("%x\n", srcval); 442 TRACE_AND_STEP(); 443 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 444 M.x86.R_EAX = genop_long_operation[op1](M.x86.R_EAX, srcval); 445 } else { 446 M.x86.R_AX = genop_word_operation[op1](M.x86.R_AX, (u16)srcval); 447 } 448 DECODE_CLEAR_SEGOVR(); 449 END_OF_INSTR(); 450 } 451 452 /**************************************************************************** 453 REMARKS: 454 Handles opcode 0x06 455 ****************************************************************************/ 456 void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1)) 457 { 458 START_OF_INSTR(); 459 DECODE_PRINTF("PUSH\tES\n"); 460 TRACE_AND_STEP(); 461 push_word(M.x86.R_ES); 462 DECODE_CLEAR_SEGOVR(); 463 END_OF_INSTR(); 464 } 465 466 /**************************************************************************** 467 REMARKS: 468 Handles opcode 0x07 469 ****************************************************************************/ 470 void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1)) 471 { 472 START_OF_INSTR(); 473 DECODE_PRINTF("POP\tES\n"); 474 TRACE_AND_STEP(); 475 M.x86.R_ES = pop_word(); 476 DECODE_CLEAR_SEGOVR(); 477 END_OF_INSTR(); 478 } 479 480 /**************************************************************************** 481 REMARKS: 482 Handles opcode 0x0e 483 ****************************************************************************/ 484 void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1)) 485 { 486 START_OF_INSTR(); 487 DECODE_PRINTF("PUSH\tCS\n"); 488 TRACE_AND_STEP(); 489 push_word(M.x86.R_CS); 490 DECODE_CLEAR_SEGOVR(); 491 END_OF_INSTR(); 492 } 493 494 /**************************************************************************** 495 REMARKS: 496 Handles opcode 0x0f. Escape for two-byte opcode (286 or better) 497 ****************************************************************************/ 498 void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1)) 499 { 500 u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++)); 501 INC_DECODED_INST_LEN(1); 502 (*x86emu_optab2[op2])(op2); 503 } 504 505 /**************************************************************************** 506 REMARKS: 507 Handles opcode 0x16 508 ****************************************************************************/ 509 void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1)) 510 { 511 START_OF_INSTR(); 512 DECODE_PRINTF("PUSH\tSS\n"); 513 TRACE_AND_STEP(); 514 push_word(M.x86.R_SS); 515 DECODE_CLEAR_SEGOVR(); 516 END_OF_INSTR(); 517 } 518 519 /**************************************************************************** 520 REMARKS: 521 Handles opcode 0x17 522 ****************************************************************************/ 523 void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1)) 524 { 525 START_OF_INSTR(); 526 DECODE_PRINTF("POP\tSS\n"); 527 TRACE_AND_STEP(); 528 M.x86.R_SS = pop_word(); 529 DECODE_CLEAR_SEGOVR(); 530 END_OF_INSTR(); 531 } 532 533 /**************************************************************************** 534 REMARKS: 535 Handles opcode 0x1e 536 ****************************************************************************/ 537 void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1)) 538 { 539 START_OF_INSTR(); 540 DECODE_PRINTF("PUSH\tDS\n"); 541 TRACE_AND_STEP(); 542 push_word(M.x86.R_DS); 543 DECODE_CLEAR_SEGOVR(); 544 END_OF_INSTR(); 545 } 546 547 /**************************************************************************** 548 REMARKS: 549 Handles opcode 0x1f 550 ****************************************************************************/ 551 void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1)) 552 { 553 START_OF_INSTR(); 554 DECODE_PRINTF("POP\tDS\n"); 555 TRACE_AND_STEP(); 556 M.x86.R_DS = pop_word(); 557 DECODE_CLEAR_SEGOVR(); 558 END_OF_INSTR(); 559 } 560 561 /**************************************************************************** 562 REMARKS: 563 Handles opcode 0x26 564 ****************************************************************************/ 565 void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1)) 566 { 567 START_OF_INSTR(); 568 DECODE_PRINTF("ES:\n"); 569 TRACE_AND_STEP(); 570 M.x86.mode |= SYSMODE_SEGOVR_ES; 571 /* 572 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4 573 * opcode subroutines we do not want to do this. 574 */ 575 END_OF_INSTR(); 576 } 577 578 /**************************************************************************** 579 REMARKS: 580 Handles opcode 0x27 581 ****************************************************************************/ 582 void x86emuOp_daa(u8 X86EMU_UNUSED(op1)) 583 { 584 START_OF_INSTR(); 585 DECODE_PRINTF("DAA\n"); 586 TRACE_AND_STEP(); 587 M.x86.R_AL = daa_byte(M.x86.R_AL); 588 DECODE_CLEAR_SEGOVR(); 589 END_OF_INSTR(); 590 } 591 592 /**************************************************************************** 593 REMARKS: 594 Handles opcode 0x2e 595 ****************************************************************************/ 596 void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1)) 597 { 598 START_OF_INSTR(); 599 DECODE_PRINTF("CS:\n"); 600 TRACE_AND_STEP(); 601 M.x86.mode |= SYSMODE_SEGOVR_CS; 602 /* note no DECODE_CLEAR_SEGOVR here. */ 603 END_OF_INSTR(); 604 } 605 606 /**************************************************************************** 607 REMARKS: 608 Handles opcode 0x2f 609 ****************************************************************************/ 610 void x86emuOp_das(u8 X86EMU_UNUSED(op1)) 611 { 612 START_OF_INSTR(); 613 DECODE_PRINTF("DAS\n"); 614 TRACE_AND_STEP(); 615 M.x86.R_AL = das_byte(M.x86.R_AL); 616 DECODE_CLEAR_SEGOVR(); 617 END_OF_INSTR(); 618 } 619 620 /**************************************************************************** 621 REMARKS: 622 Handles opcode 0x36 623 ****************************************************************************/ 624 void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1)) 625 { 626 START_OF_INSTR(); 627 DECODE_PRINTF("SS:\n"); 628 TRACE_AND_STEP(); 629 M.x86.mode |= SYSMODE_SEGOVR_SS; 630 /* no DECODE_CLEAR_SEGOVR ! */ 631 END_OF_INSTR(); 632 } 633 634 /**************************************************************************** 635 REMARKS: 636 Handles opcode 0x37 637 ****************************************************************************/ 638 void x86emuOp_aaa(u8 X86EMU_UNUSED(op1)) 639 { 640 START_OF_INSTR(); 641 DECODE_PRINTF("AAA\n"); 642 TRACE_AND_STEP(); 643 M.x86.R_AX = aaa_word(M.x86.R_AX); 644 DECODE_CLEAR_SEGOVR(); 645 END_OF_INSTR(); 646 } 647 648 /**************************************************************************** 649 REMARKS: 650 Handles opcode 0x3e 651 ****************************************************************************/ 652 void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1)) 653 { 654 START_OF_INSTR(); 655 DECODE_PRINTF("DS:\n"); 656 TRACE_AND_STEP(); 657 M.x86.mode |= SYSMODE_SEGOVR_DS; 658 /* NO DECODE_CLEAR_SEGOVR! */ 659 END_OF_INSTR(); 660 } 661 662 /**************************************************************************** 663 REMARKS: 664 Handles opcode 0x3f 665 ****************************************************************************/ 666 void x86emuOp_aas(u8 X86EMU_UNUSED(op1)) 667 { 668 START_OF_INSTR(); 669 DECODE_PRINTF("AAS\n"); 670 TRACE_AND_STEP(); 671 M.x86.R_AX = aas_word(M.x86.R_AX); 672 DECODE_CLEAR_SEGOVR(); 673 END_OF_INSTR(); 674 } 675 676 /**************************************************************************** 677 REMARKS: 678 Handles opcode 0x40 - 0x47 679 ****************************************************************************/ 680 void x86emuOp_inc_register(u8 op1) 681 { 682 START_OF_INSTR(); 683 op1 &= 0x7; 684 DECODE_PRINTF("INC\t"); 685 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 686 u32 *reg; 687 reg = DECODE_RM_LONG_REGISTER(op1); 688 DECODE_PRINTF("\n"); 689 TRACE_AND_STEP(); 690 *reg = inc_long(*reg); 691 } else { 692 u16 *reg; 693 reg = DECODE_RM_WORD_REGISTER(op1); 694 DECODE_PRINTF("\n"); 695 TRACE_AND_STEP(); 696 *reg = inc_word(*reg); 697 } 698 DECODE_CLEAR_SEGOVR(); 699 END_OF_INSTR(); 700 } 701 702 /**************************************************************************** 703 REMARKS: 704 Handles opcode 0x48 - 0x4F 705 ****************************************************************************/ 706 void x86emuOp_dec_register(u8 op1) 707 { 708 START_OF_INSTR(); 709 op1 &= 0x7; 710 DECODE_PRINTF("DEC\t"); 711 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 712 u32 *reg; 713 reg = DECODE_RM_LONG_REGISTER(op1); 714 DECODE_PRINTF("\n"); 715 TRACE_AND_STEP(); 716 *reg = dec_long(*reg); 717 } else { 718 u16 *reg; 719 reg = DECODE_RM_WORD_REGISTER(op1); 720 DECODE_PRINTF("\n"); 721 TRACE_AND_STEP(); 722 *reg = dec_word(*reg); 723 } 724 DECODE_CLEAR_SEGOVR(); 725 END_OF_INSTR(); 726 } 727 728 /**************************************************************************** 729 REMARKS: 730 Handles opcode 0x50 - 0x57 731 ****************************************************************************/ 732 void x86emuOp_push_register(u8 op1) 733 { 734 START_OF_INSTR(); 735 op1 &= 0x7; 736 DECODE_PRINTF("PUSH\t"); 737 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 738 u32 *reg; 739 reg = DECODE_RM_LONG_REGISTER(op1); 740 DECODE_PRINTF("\n"); 741 TRACE_AND_STEP(); 742 push_long(*reg); 743 } else { 744 u16 *reg; 745 reg = DECODE_RM_WORD_REGISTER(op1); 746 DECODE_PRINTF("\n"); 747 TRACE_AND_STEP(); 748 push_word(*reg); 749 } 750 DECODE_CLEAR_SEGOVR(); 751 END_OF_INSTR(); 752 } 753 754 /**************************************************************************** 755 REMARKS: 756 Handles opcode 0x58 - 0x5F 757 ****************************************************************************/ 758 void x86emuOp_pop_register(u8 op1) 759 { 760 START_OF_INSTR(); 761 op1 &= 0x7; 762 DECODE_PRINTF("POP\t"); 763 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 764 u32 *reg; 765 reg = DECODE_RM_LONG_REGISTER(op1); 766 DECODE_PRINTF("\n"); 767 TRACE_AND_STEP(); 768 *reg = pop_long(); 769 } else { 770 u16 *reg; 771 reg = DECODE_RM_WORD_REGISTER(op1); 772 DECODE_PRINTF("\n"); 773 TRACE_AND_STEP(); 774 *reg = pop_word(); 775 } 776 DECODE_CLEAR_SEGOVR(); 777 END_OF_INSTR(); 778 } 779 780 /**************************************************************************** 781 REMARKS: 782 Handles opcode 0x60 783 ****************************************************************************/ 784 void x86emuOp_push_all(u8 X86EMU_UNUSED(op1)) 785 { 786 START_OF_INSTR(); 787 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 788 DECODE_PRINTF("PUSHAD\n"); 789 } else { 790 DECODE_PRINTF("PUSHA\n"); 791 } 792 TRACE_AND_STEP(); 793 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 794 u32 old_sp = M.x86.R_ESP; 795 796 push_long(M.x86.R_EAX); 797 push_long(M.x86.R_ECX); 798 push_long(M.x86.R_EDX); 799 push_long(M.x86.R_EBX); 800 push_long(old_sp); 801 push_long(M.x86.R_EBP); 802 push_long(M.x86.R_ESI); 803 push_long(M.x86.R_EDI); 804 } else { 805 u16 old_sp = M.x86.R_SP; 806 807 push_word(M.x86.R_AX); 808 push_word(M.x86.R_CX); 809 push_word(M.x86.R_DX); 810 push_word(M.x86.R_BX); 811 push_word(old_sp); 812 push_word(M.x86.R_BP); 813 push_word(M.x86.R_SI); 814 push_word(M.x86.R_DI); 815 } 816 DECODE_CLEAR_SEGOVR(); 817 END_OF_INSTR(); 818 } 819 820 /**************************************************************************** 821 REMARKS: 822 Handles opcode 0x61 823 ****************************************************************************/ 824 void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1)) 825 { 826 START_OF_INSTR(); 827 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 828 DECODE_PRINTF("POPAD\n"); 829 } else { 830 DECODE_PRINTF("POPA\n"); 831 } 832 TRACE_AND_STEP(); 833 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 834 M.x86.R_EDI = pop_long(); 835 M.x86.R_ESI = pop_long(); 836 M.x86.R_EBP = pop_long(); 837 M.x86.R_ESP += 4; /* skip ESP */ 838 M.x86.R_EBX = pop_long(); 839 M.x86.R_EDX = pop_long(); 840 M.x86.R_ECX = pop_long(); 841 M.x86.R_EAX = pop_long(); 842 } else { 843 M.x86.R_DI = pop_word(); 844 M.x86.R_SI = pop_word(); 845 M.x86.R_BP = pop_word(); 846 M.x86.R_SP += 2; /* skip SP */ 847 M.x86.R_BX = pop_word(); 848 M.x86.R_DX = pop_word(); 849 M.x86.R_CX = pop_word(); 850 M.x86.R_AX = pop_word(); 851 } 852 DECODE_CLEAR_SEGOVR(); 853 END_OF_INSTR(); 854 } 855 856 /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */ 857 /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */ 858 859 /**************************************************************************** 860 REMARKS: 861 Handles opcode 0x64 862 ****************************************************************************/ 863 void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1)) 864 { 865 START_OF_INSTR(); 866 DECODE_PRINTF("FS:\n"); 867 TRACE_AND_STEP(); 868 M.x86.mode |= SYSMODE_SEGOVR_FS; 869 /* 870 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4 871 * opcode subroutines we do not want to do this. 872 */ 873 END_OF_INSTR(); 874 } 875 876 /**************************************************************************** 877 REMARKS: 878 Handles opcode 0x65 879 ****************************************************************************/ 880 void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1)) 881 { 882 START_OF_INSTR(); 883 DECODE_PRINTF("GS:\n"); 884 TRACE_AND_STEP(); 885 M.x86.mode |= SYSMODE_SEGOVR_GS; 886 /* 887 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4 888 * opcode subroutines we do not want to do this. 889 */ 890 END_OF_INSTR(); 891 } 892 893 /**************************************************************************** 894 REMARKS: 895 Handles opcode 0x66 - prefix for 32-bit register 896 ****************************************************************************/ 897 void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1)) 898 { 899 START_OF_INSTR(); 900 DECODE_PRINTF("DATA:\n"); 901 TRACE_AND_STEP(); 902 M.x86.mode |= SYSMODE_PREFIX_DATA; 903 /* note no DECODE_CLEAR_SEGOVR here. */ 904 END_OF_INSTR(); 905 } 906 907 /**************************************************************************** 908 REMARKS: 909 Handles opcode 0x67 - prefix for 32-bit address 910 ****************************************************************************/ 911 void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1)) 912 { 913 START_OF_INSTR(); 914 DECODE_PRINTF("ADDR:\n"); 915 TRACE_AND_STEP(); 916 M.x86.mode |= SYSMODE_PREFIX_ADDR; 917 /* note no DECODE_CLEAR_SEGOVR here. */ 918 END_OF_INSTR(); 919 } 920 921 /**************************************************************************** 922 REMARKS: 923 Handles opcode 0x68 924 ****************************************************************************/ 925 void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1)) 926 { 927 u32 imm; 928 929 START_OF_INSTR(); 930 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 931 imm = fetch_long_imm(); 932 } else { 933 imm = fetch_word_imm(); 934 } 935 DECODE_PRINTF2("PUSH\t%x\n", imm); 936 TRACE_AND_STEP(); 937 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 938 push_long(imm); 939 } else { 940 push_word((u16)imm); 941 } 942 DECODE_CLEAR_SEGOVR(); 943 END_OF_INSTR(); 944 } 945 946 /**************************************************************************** 947 REMARKS: 948 Handles opcode 0x69 949 ****************************************************************************/ 950 void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1)) 951 { 952 int mod, rl, rh; 953 uint srcoffset; 954 955 START_OF_INSTR(); 956 DECODE_PRINTF("IMUL\t"); 957 FETCH_DECODE_MODRM(mod, rh, rl); 958 if (mod < 3) { 959 srcoffset = decode_rmXX_address(mod, rl); 960 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 961 u32 *destreg; 962 u32 srcval; 963 u32 res_lo,res_hi; 964 s32 imm; 965 966 destreg = DECODE_RM_LONG_REGISTER(rh); 967 DECODE_PRINTF(","); 968 srcval = fetch_data_long(srcoffset); 969 imm = fetch_long_imm(); 970 DECODE_PRINTF2(",%d\n", (s32)imm); 971 TRACE_AND_STEP(); 972 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm); 973 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) || 974 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) { 975 CLEAR_FLAG(F_CF); 976 CLEAR_FLAG(F_OF); 977 } else { 978 SET_FLAG(F_CF); 979 SET_FLAG(F_OF); 980 } 981 *destreg = (u32)res_lo; 982 } else { 983 u16 *destreg; 984 u16 srcval; 985 u32 res; 986 s16 imm; 987 988 destreg = DECODE_RM_WORD_REGISTER(rh); 989 DECODE_PRINTF(","); 990 srcval = fetch_data_word(srcoffset); 991 imm = fetch_word_imm(); 992 DECODE_PRINTF2(",%d\n", (s32)imm); 993 TRACE_AND_STEP(); 994 res = (s16)srcval * (s16)imm; 995 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) || 996 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) { 997 CLEAR_FLAG(F_CF); 998 CLEAR_FLAG(F_OF); 999 } else { 1000 SET_FLAG(F_CF); 1001 SET_FLAG(F_OF); 1002 } 1003 *destreg = (u16)res; 1004 } 1005 } else { /* register to register */ 1006 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1007 u32 *destreg,*srcreg; 1008 u32 res_lo,res_hi; 1009 s32 imm; 1010 1011 destreg = DECODE_RM_LONG_REGISTER(rh); 1012 DECODE_PRINTF(","); 1013 srcreg = DECODE_RM_LONG_REGISTER(rl); 1014 imm = fetch_long_imm(); 1015 DECODE_PRINTF2(",%d\n", (s32)imm); 1016 TRACE_AND_STEP(); 1017 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm); 1018 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) || 1019 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) { 1020 CLEAR_FLAG(F_CF); 1021 CLEAR_FLAG(F_OF); 1022 } else { 1023 SET_FLAG(F_CF); 1024 SET_FLAG(F_OF); 1025 } 1026 *destreg = (u32)res_lo; 1027 } else { 1028 u16 *destreg,*srcreg; 1029 u32 res; 1030 s16 imm; 1031 1032 destreg = DECODE_RM_WORD_REGISTER(rh); 1033 DECODE_PRINTF(","); 1034 srcreg = DECODE_RM_WORD_REGISTER(rl); 1035 imm = fetch_word_imm(); 1036 DECODE_PRINTF2(",%d\n", (s32)imm); 1037 res = (s16)*srcreg * (s16)imm; 1038 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) || 1039 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) { 1040 CLEAR_FLAG(F_CF); 1041 CLEAR_FLAG(F_OF); 1042 } else { 1043 SET_FLAG(F_CF); 1044 SET_FLAG(F_OF); 1045 } 1046 *destreg = (u16)res; 1047 } 1048 } 1049 DECODE_CLEAR_SEGOVR(); 1050 END_OF_INSTR(); 1051 } 1052 1053 /**************************************************************************** 1054 REMARKS: 1055 Handles opcode 0x6a 1056 ****************************************************************************/ 1057 void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1)) 1058 { 1059 s16 imm; 1060 1061 START_OF_INSTR(); 1062 imm = (s8)fetch_byte_imm(); 1063 DECODE_PRINTF2("PUSH\t%d\n", imm); 1064 TRACE_AND_STEP(); 1065 push_word(imm); 1066 DECODE_CLEAR_SEGOVR(); 1067 END_OF_INSTR(); 1068 } 1069 1070 /**************************************************************************** 1071 REMARKS: 1072 Handles opcode 0x6b 1073 ****************************************************************************/ 1074 void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1)) 1075 { 1076 int mod, rl, rh; 1077 uint srcoffset; 1078 s8 imm; 1079 1080 START_OF_INSTR(); 1081 DECODE_PRINTF("IMUL\t"); 1082 FETCH_DECODE_MODRM(mod, rh, rl); 1083 if (mod < 3) { 1084 srcoffset = decode_rmXX_address(mod, rl); 1085 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1086 u32 *destreg; 1087 u32 srcval; 1088 u32 res_lo,res_hi; 1089 1090 destreg = DECODE_RM_LONG_REGISTER(rh); 1091 DECODE_PRINTF(","); 1092 srcval = fetch_data_long(srcoffset); 1093 imm = fetch_byte_imm(); 1094 DECODE_PRINTF2(",%d\n", (s32)imm); 1095 TRACE_AND_STEP(); 1096 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm); 1097 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) || 1098 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) { 1099 CLEAR_FLAG(F_CF); 1100 CLEAR_FLAG(F_OF); 1101 } else { 1102 SET_FLAG(F_CF); 1103 SET_FLAG(F_OF); 1104 } 1105 *destreg = (u32)res_lo; 1106 } else { 1107 u16 *destreg; 1108 u16 srcval; 1109 u32 res; 1110 1111 destreg = DECODE_RM_WORD_REGISTER(rh); 1112 DECODE_PRINTF(","); 1113 srcval = fetch_data_word(srcoffset); 1114 imm = fetch_byte_imm(); 1115 DECODE_PRINTF2(",%d\n", (s32)imm); 1116 TRACE_AND_STEP(); 1117 res = (s16)srcval * (s16)imm; 1118 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) || 1119 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) { 1120 CLEAR_FLAG(F_CF); 1121 CLEAR_FLAG(F_OF); 1122 } else { 1123 SET_FLAG(F_CF); 1124 SET_FLAG(F_OF); 1125 } 1126 *destreg = (u16)res; 1127 } 1128 } else { /* register to register */ 1129 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1130 u32 *destreg,*srcreg; 1131 u32 res_lo,res_hi; 1132 1133 destreg = DECODE_RM_LONG_REGISTER(rh); 1134 DECODE_PRINTF(","); 1135 srcreg = DECODE_RM_LONG_REGISTER(rl); 1136 imm = fetch_byte_imm(); 1137 DECODE_PRINTF2(",%d\n", (s32)imm); 1138 TRACE_AND_STEP(); 1139 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm); 1140 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) || 1141 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) { 1142 CLEAR_FLAG(F_CF); 1143 CLEAR_FLAG(F_OF); 1144 } else { 1145 SET_FLAG(F_CF); 1146 SET_FLAG(F_OF); 1147 } 1148 *destreg = (u32)res_lo; 1149 } else { 1150 u16 *destreg,*srcreg; 1151 u32 res; 1152 1153 destreg = DECODE_RM_WORD_REGISTER(rh); 1154 DECODE_PRINTF(","); 1155 srcreg = DECODE_RM_WORD_REGISTER(rl); 1156 imm = fetch_byte_imm(); 1157 DECODE_PRINTF2(",%d\n", (s32)imm); 1158 TRACE_AND_STEP(); 1159 res = (s16)*srcreg * (s16)imm; 1160 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) || 1161 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) { 1162 CLEAR_FLAG(F_CF); 1163 CLEAR_FLAG(F_OF); 1164 } else { 1165 SET_FLAG(F_CF); 1166 SET_FLAG(F_OF); 1167 } 1168 *destreg = (u16)res; 1169 } 1170 } 1171 DECODE_CLEAR_SEGOVR(); 1172 END_OF_INSTR(); 1173 } 1174 1175 /**************************************************************************** 1176 REMARKS: 1177 Handles opcode 0x6c 1178 ****************************************************************************/ 1179 void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1)) 1180 { 1181 START_OF_INSTR(); 1182 DECODE_PRINTF("INSB\n"); 1183 ins(1); 1184 TRACE_AND_STEP(); 1185 DECODE_CLEAR_SEGOVR(); 1186 END_OF_INSTR(); 1187 } 1188 1189 /**************************************************************************** 1190 REMARKS: 1191 Handles opcode 0x6d 1192 ****************************************************************************/ 1193 void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1)) 1194 { 1195 START_OF_INSTR(); 1196 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1197 DECODE_PRINTF("INSD\n"); 1198 ins(4); 1199 } else { 1200 DECODE_PRINTF("INSW\n"); 1201 ins(2); 1202 } 1203 TRACE_AND_STEP(); 1204 DECODE_CLEAR_SEGOVR(); 1205 END_OF_INSTR(); 1206 } 1207 1208 /**************************************************************************** 1209 REMARKS: 1210 Handles opcode 0x6e 1211 ****************************************************************************/ 1212 void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1)) 1213 { 1214 START_OF_INSTR(); 1215 DECODE_PRINTF("OUTSB\n"); 1216 outs(1); 1217 TRACE_AND_STEP(); 1218 DECODE_CLEAR_SEGOVR(); 1219 END_OF_INSTR(); 1220 } 1221 1222 /**************************************************************************** 1223 REMARKS: 1224 Handles opcode 0x6f 1225 ****************************************************************************/ 1226 void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1)) 1227 { 1228 START_OF_INSTR(); 1229 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1230 DECODE_PRINTF("OUTSD\n"); 1231 outs(4); 1232 } else { 1233 DECODE_PRINTF("OUTSW\n"); 1234 outs(2); 1235 } 1236 TRACE_AND_STEP(); 1237 DECODE_CLEAR_SEGOVR(); 1238 END_OF_INSTR(); 1239 } 1240 1241 /**************************************************************************** 1242 REMARKS: 1243 Handles opcode 0x70 - 0x7F 1244 ****************************************************************************/ 1245 int x86emu_check_jump_condition(u8 op); 1246 1247 void x86emuOp_jump_near_cond(u8 op1) 1248 { 1249 s8 offset; 1250 u16 target; 1251 int cond; 1252 1253 /* jump to byte offset if overflow flag is set */ 1254 START_OF_INSTR(); 1255 cond = x86emu_check_jump_condition(op1 & 0xF); 1256 offset = (s8)fetch_byte_imm(); 1257 target = (u16)(M.x86.R_IP + (s16)offset); 1258 DECODE_PRINTF2("%x\n", target); 1259 TRACE_AND_STEP(); 1260 if (cond) 1261 M.x86.R_IP = target; 1262 DECODE_CLEAR_SEGOVR(); 1263 END_OF_INSTR(); 1264 } 1265 1266 /**************************************************************************** 1267 REMARKS: 1268 Handles opcode 0x80 1269 ****************************************************************************/ 1270 void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1)) 1271 { 1272 int mod, rl, rh; 1273 u8 *destreg; 1274 uint destoffset; 1275 u8 imm; 1276 u8 destval; 1277 1278 /* 1279 * Weirdo special case instruction format. Part of the opcode 1280 * held below in "RH". Doubly nested case would result, except 1281 * that the decoded instruction 1282 */ 1283 START_OF_INSTR(); 1284 FETCH_DECODE_MODRM(mod, rh, rl); 1285 #ifdef DEBUG 1286 if (DEBUG_DECODE()) { 1287 /* XXX DECODE_PRINTF may be changed to something more 1288 general, so that it is important to leave the strings 1289 in the same format, even though the result is that the 1290 above test is done twice. */ 1291 1292 switch (rh) { 1293 case 0: 1294 DECODE_PRINTF("ADD\t"); 1295 break; 1296 case 1: 1297 DECODE_PRINTF("OR\t"); 1298 break; 1299 case 2: 1300 DECODE_PRINTF("ADC\t"); 1301 break; 1302 case 3: 1303 DECODE_PRINTF("SBB\t"); 1304 break; 1305 case 4: 1306 DECODE_PRINTF("AND\t"); 1307 break; 1308 case 5: 1309 DECODE_PRINTF("SUB\t"); 1310 break; 1311 case 6: 1312 DECODE_PRINTF("XOR\t"); 1313 break; 1314 case 7: 1315 DECODE_PRINTF("CMP\t"); 1316 break; 1317 } 1318 } 1319 #endif 1320 /* know operation, decode the mod byte to find the addressing 1321 mode. */ 1322 if (mod < 3) { 1323 DECODE_PRINTF("BYTE PTR "); 1324 destoffset = decode_rmXX_address(mod, rl); 1325 DECODE_PRINTF(","); 1326 destval = fetch_data_byte(destoffset); 1327 imm = fetch_byte_imm(); 1328 DECODE_PRINTF2("%x\n", imm); 1329 TRACE_AND_STEP(); 1330 destval = (*genop_byte_operation[rh]) (destval, imm); 1331 if (rh != 7) 1332 store_data_byte(destoffset, destval); 1333 } else { /* register to register */ 1334 destreg = DECODE_RM_BYTE_REGISTER(rl); 1335 DECODE_PRINTF(","); 1336 imm = fetch_byte_imm(); 1337 DECODE_PRINTF2("%x\n", imm); 1338 TRACE_AND_STEP(); 1339 destval = (*genop_byte_operation[rh]) (*destreg, imm); 1340 if (rh != 7) 1341 *destreg = destval; 1342 } 1343 DECODE_CLEAR_SEGOVR(); 1344 END_OF_INSTR(); 1345 } 1346 1347 /**************************************************************************** 1348 REMARKS: 1349 Handles opcode 0x81 1350 ****************************************************************************/ 1351 void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1)) 1352 { 1353 int mod, rl, rh; 1354 uint destoffset; 1355 1356 /* 1357 * Weirdo special case instruction format. Part of the opcode 1358 * held below in "RH". Doubly nested case would result, except 1359 * that the decoded instruction 1360 */ 1361 START_OF_INSTR(); 1362 FETCH_DECODE_MODRM(mod, rh, rl); 1363 #ifdef DEBUG 1364 if (DEBUG_DECODE()) { 1365 /* XXX DECODE_PRINTF may be changed to something more 1366 general, so that it is important to leave the strings 1367 in the same format, even though the result is that the 1368 above test is done twice. */ 1369 1370 switch (rh) { 1371 case 0: 1372 DECODE_PRINTF("ADD\t"); 1373 break; 1374 case 1: 1375 DECODE_PRINTF("OR\t"); 1376 break; 1377 case 2: 1378 DECODE_PRINTF("ADC\t"); 1379 break; 1380 case 3: 1381 DECODE_PRINTF("SBB\t"); 1382 break; 1383 case 4: 1384 DECODE_PRINTF("AND\t"); 1385 break; 1386 case 5: 1387 DECODE_PRINTF("SUB\t"); 1388 break; 1389 case 6: 1390 DECODE_PRINTF("XOR\t"); 1391 break; 1392 case 7: 1393 DECODE_PRINTF("CMP\t"); 1394 break; 1395 } 1396 } 1397 #endif 1398 /* 1399 * Know operation, decode the mod byte to find the addressing 1400 * mode. 1401 */ 1402 if (mod < 3) { 1403 DECODE_PRINTF("DWORD PTR "); 1404 destoffset = decode_rmXX_address(mod, rl); 1405 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1406 u32 destval,imm; 1407 1408 DECODE_PRINTF(","); 1409 destval = fetch_data_long(destoffset); 1410 imm = fetch_long_imm(); 1411 DECODE_PRINTF2("%x\n", imm); 1412 TRACE_AND_STEP(); 1413 destval = (*genop_long_operation[rh]) (destval, imm); 1414 if (rh != 7) 1415 store_data_long(destoffset, destval); 1416 } else { 1417 u16 destval,imm; 1418 1419 DECODE_PRINTF(","); 1420 destval = fetch_data_word(destoffset); 1421 imm = fetch_word_imm(); 1422 DECODE_PRINTF2("%x\n", imm); 1423 TRACE_AND_STEP(); 1424 destval = (*genop_word_operation[rh]) (destval, imm); 1425 if (rh != 7) 1426 store_data_word(destoffset, destval); 1427 } 1428 } else { /* register to register */ 1429 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1430 u32 *destreg; 1431 u32 destval,imm; 1432 1433 destreg = DECODE_RM_LONG_REGISTER(rl); 1434 DECODE_PRINTF(","); 1435 imm = fetch_long_imm(); 1436 DECODE_PRINTF2("%x\n", imm); 1437 TRACE_AND_STEP(); 1438 destval = (*genop_long_operation[rh]) (*destreg, imm); 1439 if (rh != 7) 1440 *destreg = destval; 1441 } else { 1442 u16 *destreg; 1443 u16 destval,imm; 1444 1445 destreg = DECODE_RM_WORD_REGISTER(rl); 1446 DECODE_PRINTF(","); 1447 imm = fetch_word_imm(); 1448 DECODE_PRINTF2("%x\n", imm); 1449 TRACE_AND_STEP(); 1450 destval = (*genop_word_operation[rh]) (*destreg, imm); 1451 if (rh != 7) 1452 *destreg = destval; 1453 } 1454 } 1455 DECODE_CLEAR_SEGOVR(); 1456 END_OF_INSTR(); 1457 } 1458 1459 /**************************************************************************** 1460 REMARKS: 1461 Handles opcode 0x82 1462 ****************************************************************************/ 1463 void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1)) 1464 { 1465 int mod, rl, rh; 1466 u8 *destreg; 1467 uint destoffset; 1468 u8 imm; 1469 u8 destval; 1470 1471 /* 1472 * Weirdo special case instruction format. Part of the opcode 1473 * held below in "RH". Doubly nested case would result, except 1474 * that the decoded instruction Similar to opcode 81, except that 1475 * the immediate byte is sign extended to a word length. 1476 */ 1477 START_OF_INSTR(); 1478 FETCH_DECODE_MODRM(mod, rh, rl); 1479 #ifdef DEBUG 1480 if (DEBUG_DECODE()) { 1481 /* XXX DECODE_PRINTF may be changed to something more 1482 general, so that it is important to leave the strings 1483 in the same format, even though the result is that the 1484 above test is done twice. */ 1485 switch (rh) { 1486 case 0: 1487 DECODE_PRINTF("ADD\t"); 1488 break; 1489 case 1: 1490 DECODE_PRINTF("OR\t"); 1491 break; 1492 case 2: 1493 DECODE_PRINTF("ADC\t"); 1494 break; 1495 case 3: 1496 DECODE_PRINTF("SBB\t"); 1497 break; 1498 case 4: 1499 DECODE_PRINTF("AND\t"); 1500 break; 1501 case 5: 1502 DECODE_PRINTF("SUB\t"); 1503 break; 1504 case 6: 1505 DECODE_PRINTF("XOR\t"); 1506 break; 1507 case 7: 1508 DECODE_PRINTF("CMP\t"); 1509 break; 1510 } 1511 } 1512 #endif 1513 /* know operation, decode the mod byte to find the addressing 1514 mode. */ 1515 if (mod < 3) { 1516 DECODE_PRINTF("BYTE PTR "); 1517 destoffset = decode_rmXX_address(mod, rl); 1518 destval = fetch_data_byte(destoffset); 1519 imm = fetch_byte_imm(); 1520 DECODE_PRINTF2(",%x\n", imm); 1521 TRACE_AND_STEP(); 1522 destval = (*genop_byte_operation[rh]) (destval, imm); 1523 if (rh != 7) 1524 store_data_byte(destoffset, destval); 1525 } else { /* register to register */ 1526 destreg = DECODE_RM_BYTE_REGISTER(rl); 1527 imm = fetch_byte_imm(); 1528 DECODE_PRINTF2(",%x\n", imm); 1529 TRACE_AND_STEP(); 1530 destval = (*genop_byte_operation[rh]) (*destreg, imm); 1531 if (rh != 7) 1532 *destreg = destval; 1533 } 1534 DECODE_CLEAR_SEGOVR(); 1535 END_OF_INSTR(); 1536 } 1537 1538 /**************************************************************************** 1539 REMARKS: 1540 Handles opcode 0x83 1541 ****************************************************************************/ 1542 void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1)) 1543 { 1544 int mod, rl, rh; 1545 uint destoffset; 1546 1547 /* 1548 * Weirdo special case instruction format. Part of the opcode 1549 * held below in "RH". Doubly nested case would result, except 1550 * that the decoded instruction Similar to opcode 81, except that 1551 * the immediate byte is sign extended to a word length. 1552 */ 1553 START_OF_INSTR(); 1554 FETCH_DECODE_MODRM(mod, rh, rl); 1555 #ifdef DEBUG 1556 if (DEBUG_DECODE()) { 1557 /* XXX DECODE_PRINTF may be changed to something more 1558 general, so that it is important to leave the strings 1559 in the same format, even though the result is that the 1560 above test is done twice. */ 1561 switch (rh) { 1562 case 0: 1563 DECODE_PRINTF("ADD\t"); 1564 break; 1565 case 1: 1566 DECODE_PRINTF("OR\t"); 1567 break; 1568 case 2: 1569 DECODE_PRINTF("ADC\t"); 1570 break; 1571 case 3: 1572 DECODE_PRINTF("SBB\t"); 1573 break; 1574 case 4: 1575 DECODE_PRINTF("AND\t"); 1576 break; 1577 case 5: 1578 DECODE_PRINTF("SUB\t"); 1579 break; 1580 case 6: 1581 DECODE_PRINTF("XOR\t"); 1582 break; 1583 case 7: 1584 DECODE_PRINTF("CMP\t"); 1585 break; 1586 } 1587 } 1588 #endif 1589 /* know operation, decode the mod byte to find the addressing 1590 mode. */ 1591 if (mod < 3) { 1592 DECODE_PRINTF("DWORD PTR "); 1593 destoffset = decode_rmXX_address(mod,rl); 1594 1595 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1596 u32 destval,imm; 1597 1598 destval = fetch_data_long(destoffset); 1599 imm = (s8) fetch_byte_imm(); 1600 DECODE_PRINTF2(",%x\n", imm); 1601 TRACE_AND_STEP(); 1602 destval = (*genop_long_operation[rh]) (destval, imm); 1603 if (rh != 7) 1604 store_data_long(destoffset, destval); 1605 } else { 1606 u16 destval,imm; 1607 1608 destval = fetch_data_word(destoffset); 1609 imm = (s8) fetch_byte_imm(); 1610 DECODE_PRINTF2(",%x\n", imm); 1611 TRACE_AND_STEP(); 1612 destval = (*genop_word_operation[rh]) (destval, imm); 1613 if (rh != 7) 1614 store_data_word(destoffset, destval); 1615 } 1616 } else { /* register to register */ 1617 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1618 u32 *destreg; 1619 u32 destval,imm; 1620 1621 destreg = DECODE_RM_LONG_REGISTER(rl); 1622 imm = (s8) fetch_byte_imm(); 1623 DECODE_PRINTF2(",%x\n", imm); 1624 TRACE_AND_STEP(); 1625 destval = (*genop_long_operation[rh]) (*destreg, imm); 1626 if (rh != 7) 1627 *destreg = destval; 1628 } else { 1629 u16 *destreg; 1630 u16 destval,imm; 1631 1632 destreg = DECODE_RM_WORD_REGISTER(rl); 1633 imm = (s8) fetch_byte_imm(); 1634 DECODE_PRINTF2(",%x\n", imm); 1635 TRACE_AND_STEP(); 1636 destval = (*genop_word_operation[rh]) (*destreg, imm); 1637 if (rh != 7) 1638 *destreg = destval; 1639 } 1640 } 1641 DECODE_CLEAR_SEGOVR(); 1642 END_OF_INSTR(); 1643 } 1644 1645 /**************************************************************************** 1646 REMARKS: 1647 Handles opcode 0x84 1648 ****************************************************************************/ 1649 void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1)) 1650 { 1651 int mod, rl, rh; 1652 u8 *destreg, *srcreg; 1653 uint destoffset; 1654 u8 destval; 1655 1656 START_OF_INSTR(); 1657 DECODE_PRINTF("TEST\t"); 1658 FETCH_DECODE_MODRM(mod, rh, rl); 1659 if (mod < 3) { 1660 destoffset = decode_rmXX_address(mod, rl); 1661 DECODE_PRINTF(","); 1662 destval = fetch_data_byte(destoffset); 1663 srcreg = DECODE_RM_BYTE_REGISTER(rh); 1664 DECODE_PRINTF("\n"); 1665 TRACE_AND_STEP(); 1666 test_byte(destval, *srcreg); 1667 } else { /* register to register */ 1668 destreg = DECODE_RM_BYTE_REGISTER(rl); 1669 DECODE_PRINTF(","); 1670 srcreg = DECODE_RM_BYTE_REGISTER(rh); 1671 DECODE_PRINTF("\n"); 1672 TRACE_AND_STEP(); 1673 test_byte(*destreg, *srcreg); 1674 } 1675 DECODE_CLEAR_SEGOVR(); 1676 END_OF_INSTR(); 1677 } 1678 1679 /**************************************************************************** 1680 REMARKS: 1681 Handles opcode 0x85 1682 ****************************************************************************/ 1683 void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1)) 1684 { 1685 int mod, rl, rh; 1686 uint destoffset; 1687 1688 START_OF_INSTR(); 1689 DECODE_PRINTF("TEST\t"); 1690 FETCH_DECODE_MODRM(mod, rh, rl); 1691 if (mod < 3) { 1692 destoffset = decode_rmXX_address(mod, rl); 1693 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1694 u32 destval; 1695 u32 *srcreg; 1696 1697 DECODE_PRINTF(","); 1698 destval = fetch_data_long(destoffset); 1699 srcreg = DECODE_RM_LONG_REGISTER(rh); 1700 DECODE_PRINTF("\n"); 1701 TRACE_AND_STEP(); 1702 test_long(destval, *srcreg); 1703 } else { 1704 u16 destval; 1705 u16 *srcreg; 1706 1707 DECODE_PRINTF(","); 1708 destval = fetch_data_word(destoffset); 1709 srcreg = DECODE_RM_WORD_REGISTER(rh); 1710 DECODE_PRINTF("\n"); 1711 TRACE_AND_STEP(); 1712 test_word(destval, *srcreg); 1713 } 1714 } else { /* register to register */ 1715 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1716 u32 *destreg,*srcreg; 1717 1718 destreg = DECODE_RM_LONG_REGISTER(rl); 1719 DECODE_PRINTF(","); 1720 srcreg = DECODE_RM_LONG_REGISTER(rh); 1721 DECODE_PRINTF("\n"); 1722 TRACE_AND_STEP(); 1723 test_long(*destreg, *srcreg); 1724 } else { 1725 u16 *destreg,*srcreg; 1726 1727 destreg = DECODE_RM_WORD_REGISTER(rl); 1728 DECODE_PRINTF(","); 1729 srcreg = DECODE_RM_WORD_REGISTER(rh); 1730 DECODE_PRINTF("\n"); 1731 TRACE_AND_STEP(); 1732 test_word(*destreg, *srcreg); 1733 } 1734 } 1735 DECODE_CLEAR_SEGOVR(); 1736 END_OF_INSTR(); 1737 } 1738 1739 /**************************************************************************** 1740 REMARKS: 1741 Handles opcode 0x86 1742 ****************************************************************************/ 1743 void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1)) 1744 { 1745 int mod, rl, rh; 1746 u8 *destreg, *srcreg; 1747 uint destoffset; 1748 u8 destval; 1749 u8 tmp; 1750 1751 START_OF_INSTR(); 1752 DECODE_PRINTF("XCHG\t"); 1753 FETCH_DECODE_MODRM(mod, rh, rl); 1754 if (mod < 3) { 1755 destoffset = decode_rmXX_address(mod, rl); 1756 DECODE_PRINTF(","); 1757 destval = fetch_data_byte(destoffset); 1758 srcreg = DECODE_RM_BYTE_REGISTER(rh); 1759 DECODE_PRINTF("\n"); 1760 TRACE_AND_STEP(); 1761 tmp = *srcreg; 1762 *srcreg = destval; 1763 destval = tmp; 1764 store_data_byte(destoffset, destval); 1765 } else { /* register to register */ 1766 destreg = DECODE_RM_BYTE_REGISTER(rl); 1767 DECODE_PRINTF(","); 1768 srcreg = DECODE_RM_BYTE_REGISTER(rh); 1769 DECODE_PRINTF("\n"); 1770 TRACE_AND_STEP(); 1771 tmp = *srcreg; 1772 *srcreg = *destreg; 1773 *destreg = tmp; 1774 } 1775 DECODE_CLEAR_SEGOVR(); 1776 END_OF_INSTR(); 1777 } 1778 1779 /**************************************************************************** 1780 REMARKS: 1781 Handles opcode 0x87 1782 ****************************************************************************/ 1783 void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1)) 1784 { 1785 int mod, rl, rh; 1786 uint destoffset; 1787 1788 START_OF_INSTR(); 1789 DECODE_PRINTF("XCHG\t"); 1790 FETCH_DECODE_MODRM(mod, rh, rl); 1791 if (mod < 3) { 1792 destoffset = decode_rmXX_address(mod, rl); 1793 DECODE_PRINTF(","); 1794 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1795 u32 *srcreg; 1796 u32 destval,tmp; 1797 1798 destval = fetch_data_long(destoffset); 1799 srcreg = DECODE_RM_LONG_REGISTER(rh); 1800 DECODE_PRINTF("\n"); 1801 TRACE_AND_STEP(); 1802 tmp = *srcreg; 1803 *srcreg = destval; 1804 destval = tmp; 1805 store_data_long(destoffset, destval); 1806 } else { 1807 u16 *srcreg; 1808 u16 destval,tmp; 1809 1810 destval = fetch_data_word(destoffset); 1811 srcreg = DECODE_RM_WORD_REGISTER(rh); 1812 DECODE_PRINTF("\n"); 1813 TRACE_AND_STEP(); 1814 tmp = *srcreg; 1815 *srcreg = destval; 1816 destval = tmp; 1817 store_data_word(destoffset, destval); 1818 } 1819 } else { /* register to register */ 1820 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1821 u32 *destreg,*srcreg; 1822 u32 tmp; 1823 1824 destreg = DECODE_RM_LONG_REGISTER(rl); 1825 DECODE_PRINTF(","); 1826 srcreg = DECODE_RM_LONG_REGISTER(rh); 1827 DECODE_PRINTF("\n"); 1828 TRACE_AND_STEP(); 1829 tmp = *srcreg; 1830 *srcreg = *destreg; 1831 *destreg = tmp; 1832 } else { 1833 u16 *destreg,*srcreg; 1834 u16 tmp; 1835 1836 destreg = DECODE_RM_WORD_REGISTER(rl); 1837 DECODE_PRINTF(","); 1838 srcreg = DECODE_RM_WORD_REGISTER(rh); 1839 DECODE_PRINTF("\n"); 1840 TRACE_AND_STEP(); 1841 tmp = *srcreg; 1842 *srcreg = *destreg; 1843 *destreg = tmp; 1844 } 1845 } 1846 DECODE_CLEAR_SEGOVR(); 1847 END_OF_INSTR(); 1848 } 1849 1850 /**************************************************************************** 1851 REMARKS: 1852 Handles opcode 0x88 1853 ****************************************************************************/ 1854 void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1)) 1855 { 1856 int mod, rl, rh; 1857 u8 *destreg, *srcreg; 1858 uint destoffset; 1859 1860 START_OF_INSTR(); 1861 DECODE_PRINTF("MOV\t"); 1862 FETCH_DECODE_MODRM(mod, rh, rl); 1863 if (mod < 3) { 1864 destoffset = decode_rmXX_address(mod, rl); 1865 DECODE_PRINTF(","); 1866 srcreg = DECODE_RM_BYTE_REGISTER(rh); 1867 DECODE_PRINTF("\n"); 1868 TRACE_AND_STEP(); 1869 store_data_byte(destoffset, *srcreg); 1870 } else { /* register to register */ 1871 destreg = DECODE_RM_BYTE_REGISTER(rl); 1872 DECODE_PRINTF(","); 1873 srcreg = DECODE_RM_BYTE_REGISTER(rh); 1874 DECODE_PRINTF("\n"); 1875 TRACE_AND_STEP(); 1876 *destreg = *srcreg; 1877 } 1878 DECODE_CLEAR_SEGOVR(); 1879 END_OF_INSTR(); 1880 } 1881 1882 /**************************************************************************** 1883 REMARKS: 1884 Handles opcode 0x89 1885 ****************************************************************************/ 1886 void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1)) 1887 { 1888 int mod, rl, rh; 1889 uint destoffset; 1890 1891 START_OF_INSTR(); 1892 DECODE_PRINTF("MOV\t"); 1893 FETCH_DECODE_MODRM(mod, rh, rl); 1894 if (mod < 3) { 1895 destoffset = decode_rmXX_address(mod, rl); 1896 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1897 u32 *srcreg; 1898 1899 DECODE_PRINTF(","); 1900 srcreg = DECODE_RM_LONG_REGISTER(rh); 1901 DECODE_PRINTF("\n"); 1902 TRACE_AND_STEP(); 1903 store_data_long(destoffset, *srcreg); 1904 } else { 1905 u16 *srcreg; 1906 1907 DECODE_PRINTF(","); 1908 srcreg = DECODE_RM_WORD_REGISTER(rh); 1909 DECODE_PRINTF("\n"); 1910 TRACE_AND_STEP(); 1911 store_data_word(destoffset, *srcreg); 1912 } 1913 } else { /* register to register */ 1914 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1915 u32 *destreg,*srcreg; 1916 1917 destreg = DECODE_RM_LONG_REGISTER(rl); 1918 DECODE_PRINTF(","); 1919 srcreg = DECODE_RM_LONG_REGISTER(rh); 1920 DECODE_PRINTF("\n"); 1921 TRACE_AND_STEP(); 1922 *destreg = *srcreg; 1923 } else { 1924 u16 *destreg,*srcreg; 1925 1926 destreg = DECODE_RM_WORD_REGISTER(rl); 1927 DECODE_PRINTF(","); 1928 srcreg = DECODE_RM_WORD_REGISTER(rh); 1929 DECODE_PRINTF("\n"); 1930 TRACE_AND_STEP(); 1931 *destreg = *srcreg; 1932 } 1933 } 1934 DECODE_CLEAR_SEGOVR(); 1935 END_OF_INSTR(); 1936 } 1937 1938 /**************************************************************************** 1939 REMARKS: 1940 Handles opcode 0x8a 1941 ****************************************************************************/ 1942 void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1)) 1943 { 1944 int mod, rl, rh; 1945 u8 *destreg, *srcreg; 1946 uint srcoffset; 1947 u8 srcval; 1948 1949 START_OF_INSTR(); 1950 DECODE_PRINTF("MOV\t"); 1951 FETCH_DECODE_MODRM(mod, rh, rl); 1952 if (mod < 3) { 1953 destreg = DECODE_RM_BYTE_REGISTER(rh); 1954 DECODE_PRINTF(","); 1955 srcoffset = decode_rmXX_address(mod, rl); 1956 srcval = fetch_data_byte(srcoffset); 1957 DECODE_PRINTF("\n"); 1958 TRACE_AND_STEP(); 1959 *destreg = srcval; 1960 } else { /* register to register */ 1961 destreg = DECODE_RM_BYTE_REGISTER(rh); 1962 DECODE_PRINTF(","); 1963 srcreg = DECODE_RM_BYTE_REGISTER(rl); 1964 DECODE_PRINTF("\n"); 1965 TRACE_AND_STEP(); 1966 *destreg = *srcreg; 1967 } 1968 DECODE_CLEAR_SEGOVR(); 1969 END_OF_INSTR(); 1970 } 1971 1972 /**************************************************************************** 1973 REMARKS: 1974 Handles opcode 0x8b 1975 ****************************************************************************/ 1976 void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1)) 1977 { 1978 int mod, rl, rh; 1979 uint srcoffset; 1980 1981 START_OF_INSTR(); 1982 DECODE_PRINTF("MOV\t"); 1983 FETCH_DECODE_MODRM(mod, rh, rl); 1984 if (mod < 3) { 1985 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1986 u32 *destreg; 1987 u32 srcval; 1988 1989 destreg = DECODE_RM_LONG_REGISTER(rh); 1990 DECODE_PRINTF(","); 1991 srcoffset = decode_rmXX_address(mod, rl); 1992 srcval = fetch_data_long(srcoffset); 1993 DECODE_PRINTF("\n"); 1994 TRACE_AND_STEP(); 1995 *destreg = srcval; 1996 } else { 1997 u16 *destreg; 1998 u16 srcval; 1999 2000 destreg = DECODE_RM_WORD_REGISTER(rh); 2001 DECODE_PRINTF(","); 2002 srcoffset = decode_rmXX_address(mod, rl); 2003 srcval = fetch_data_word(srcoffset); 2004 DECODE_PRINTF("\n"); 2005 TRACE_AND_STEP(); 2006 *destreg = srcval; 2007 } 2008 } else { /* register to register */ 2009 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2010 u32 *destreg, *srcreg; 2011 2012 destreg = DECODE_RM_LONG_REGISTER(rh); 2013 DECODE_PRINTF(","); 2014 srcreg = DECODE_RM_LONG_REGISTER(rl); 2015 DECODE_PRINTF("\n"); 2016 TRACE_AND_STEP(); 2017 *destreg = *srcreg; 2018 } else { 2019 u16 *destreg, *srcreg; 2020 2021 destreg = DECODE_RM_WORD_REGISTER(rh); 2022 DECODE_PRINTF(","); 2023 srcreg = DECODE_RM_WORD_REGISTER(rl); 2024 DECODE_PRINTF("\n"); 2025 TRACE_AND_STEP(); 2026 *destreg = *srcreg; 2027 } 2028 } 2029 DECODE_CLEAR_SEGOVR(); 2030 END_OF_INSTR(); 2031 } 2032 2033 /**************************************************************************** 2034 REMARKS: 2035 Handles opcode 0x8c 2036 ****************************************************************************/ 2037 void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1)) 2038 { 2039 int mod, rl, rh; 2040 u16 *destreg, *srcreg; 2041 uint destoffset; 2042 u16 destval; 2043 2044 START_OF_INSTR(); 2045 DECODE_PRINTF("MOV\t"); 2046 FETCH_DECODE_MODRM(mod, rh, rl); 2047 if (mod < 3) { 2048 destoffset = decode_rmXX_address(mod, rl); 2049 DECODE_PRINTF(","); 2050 srcreg = decode_rm_seg_register(rh); 2051 DECODE_PRINTF("\n"); 2052 TRACE_AND_STEP(); 2053 destval = *srcreg; 2054 store_data_word(destoffset, destval); 2055 } else { /* register to register */ 2056 destreg = DECODE_RM_WORD_REGISTER(rl); 2057 DECODE_PRINTF(","); 2058 srcreg = decode_rm_seg_register(rh); 2059 DECODE_PRINTF("\n"); 2060 TRACE_AND_STEP(); 2061 *destreg = *srcreg; 2062 } 2063 DECODE_CLEAR_SEGOVR(); 2064 END_OF_INSTR(); 2065 } 2066 2067 /**************************************************************************** 2068 REMARKS: 2069 Handles opcode 0x8d 2070 ****************************************************************************/ 2071 void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1)) 2072 { 2073 int mod, rl, rh; 2074 u16 *srcreg; 2075 uint destoffset; 2076 2077 /* 2078 * TODO: Need to handle address size prefix! 2079 * 2080 * lea eax,[eax+ebx*2] ?? 2081 */ 2082 2083 START_OF_INSTR(); 2084 DECODE_PRINTF("LEA\t"); 2085 FETCH_DECODE_MODRM(mod, rh, rl); 2086 if (mod < 3) { 2087 srcreg = DECODE_RM_WORD_REGISTER(rh); 2088 DECODE_PRINTF(","); 2089 destoffset = decode_rmXX_address(mod, rl); 2090 DECODE_PRINTF("\n"); 2091 TRACE_AND_STEP(); 2092 *srcreg = (u16)destoffset; 2093 } 2094 /* } else { undefined. Do nothing. } */ 2095 DECODE_CLEAR_SEGOVR(); 2096 END_OF_INSTR(); 2097 } 2098 2099 /**************************************************************************** 2100 REMARKS: 2101 Handles opcode 0x8e 2102 ****************************************************************************/ 2103 void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1)) 2104 { 2105 int mod, rl, rh; 2106 u16 *destreg, *srcreg; 2107 uint srcoffset; 2108 u16 srcval; 2109 2110 START_OF_INSTR(); 2111 DECODE_PRINTF("MOV\t"); 2112 FETCH_DECODE_MODRM(mod, rh, rl); 2113 if (mod < 3) { 2114 destreg = decode_rm_seg_register(rh); 2115 DECODE_PRINTF(","); 2116 srcoffset = decode_rmXX_address(mod, rl); 2117 srcval = fetch_data_word(srcoffset); 2118 DECODE_PRINTF("\n"); 2119 TRACE_AND_STEP(); 2120 *destreg = srcval; 2121 } else { /* register to register */ 2122 destreg = decode_rm_seg_register(rh); 2123 DECODE_PRINTF(","); 2124 srcreg = DECODE_RM_WORD_REGISTER(rl); 2125 DECODE_PRINTF("\n"); 2126 TRACE_AND_STEP(); 2127 *destreg = *srcreg; 2128 } 2129 /* 2130 * Clean up, and reset all the R_xSP pointers to the correct 2131 * locations. This is about 3x too much overhead (doing all the 2132 * segreg ptrs when only one is needed, but this instruction 2133 * *cannot* be that common, and this isn't too much work anyway. 2134 */ 2135 DECODE_CLEAR_SEGOVR(); 2136 END_OF_INSTR(); 2137 } 2138 2139 /**************************************************************************** 2140 REMARKS: 2141 Handles opcode 0x8f 2142 ****************************************************************************/ 2143 void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1)) 2144 { 2145 int mod, rl, rh; 2146 uint destoffset; 2147 2148 START_OF_INSTR(); 2149 DECODE_PRINTF("POP\t"); 2150 FETCH_DECODE_MODRM(mod, rh, rl); 2151 if (rh != 0) { 2152 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n"); 2153 HALT_SYS(); 2154 } 2155 if (mod < 3) { 2156 destoffset = decode_rmXX_address(mod, rl); 2157 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2158 u32 destval; 2159 2160 DECODE_PRINTF("\n"); 2161 TRACE_AND_STEP(); 2162 destval = pop_long(); 2163 store_data_long(destoffset, destval); 2164 } else { 2165 u16 destval; 2166 2167 DECODE_PRINTF("\n"); 2168 TRACE_AND_STEP(); 2169 destval = pop_word(); 2170 store_data_word(destoffset, destval); 2171 } 2172 } else { /* register to register */ 2173 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2174 u32 *destreg; 2175 2176 destreg = DECODE_RM_LONG_REGISTER(rl); 2177 DECODE_PRINTF("\n"); 2178 TRACE_AND_STEP(); 2179 *destreg = pop_long(); 2180 } else { 2181 u16 *destreg; 2182 2183 destreg = DECODE_RM_WORD_REGISTER(rl); 2184 DECODE_PRINTF("\n"); 2185 TRACE_AND_STEP(); 2186 *destreg = pop_word(); 2187 } 2188 } 2189 DECODE_CLEAR_SEGOVR(); 2190 END_OF_INSTR(); 2191 } 2192 2193 /**************************************************************************** 2194 REMARKS: 2195 Handles opcode 0x90 2196 ****************************************************************************/ 2197 void x86emuOp_nop(u8 X86EMU_UNUSED(op1)) 2198 { 2199 START_OF_INSTR(); 2200 DECODE_PRINTF("NOP\n"); 2201 TRACE_AND_STEP(); 2202 DECODE_CLEAR_SEGOVR(); 2203 END_OF_INSTR(); 2204 } 2205 2206 /**************************************************************************** 2207 REMARKS: 2208 Handles opcode 0x91-0x97 2209 ****************************************************************************/ 2210 void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1)) 2211 { 2212 u32 tmp; 2213 2214 op1 &= 0x7; 2215 2216 START_OF_INSTR(); 2217 2218 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2219 u32 *reg32; 2220 DECODE_PRINTF("XCHG\tEAX,"); 2221 reg32 = DECODE_RM_LONG_REGISTER(op1); 2222 DECODE_PRINTF("\n"); 2223 TRACE_AND_STEP(); 2224 tmp = M.x86.R_EAX; 2225 M.x86.R_EAX = *reg32; 2226 *reg32 = tmp; 2227 } else { 2228 u16 *reg16; 2229 DECODE_PRINTF("XCHG\tAX,"); 2230 reg16 = DECODE_RM_WORD_REGISTER(op1); 2231 DECODE_PRINTF("\n"); 2232 TRACE_AND_STEP(); 2233 tmp = M.x86.R_AX; 2234 M.x86.R_EAX = *reg16; 2235 *reg16 = (u16)tmp; 2236 } 2237 DECODE_CLEAR_SEGOVR(); 2238 END_OF_INSTR(); 2239 } 2240 2241 /**************************************************************************** 2242 REMARKS: 2243 Handles opcode 0x98 2244 ****************************************************************************/ 2245 void x86emuOp_cbw(u8 X86EMU_UNUSED(op1)) 2246 { 2247 START_OF_INSTR(); 2248 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2249 DECODE_PRINTF("CWDE\n"); 2250 } else { 2251 DECODE_PRINTF("CBW\n"); 2252 } 2253 TRACE_AND_STEP(); 2254 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2255 if (M.x86.R_AX & 0x8000) { 2256 M.x86.R_EAX |= 0xffff0000; 2257 } else { 2258 M.x86.R_EAX &= 0x0000ffff; 2259 } 2260 } else { 2261 if (M.x86.R_AL & 0x80) { 2262 M.x86.R_AH = 0xff; 2263 } else { 2264 M.x86.R_AH = 0x0; 2265 } 2266 } 2267 DECODE_CLEAR_SEGOVR(); 2268 END_OF_INSTR(); 2269 } 2270 2271 /**************************************************************************** 2272 REMARKS: 2273 Handles opcode 0x99 2274 ****************************************************************************/ 2275 void x86emuOp_cwd(u8 X86EMU_UNUSED(op1)) 2276 { 2277 START_OF_INSTR(); 2278 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2279 DECODE_PRINTF("CDQ\n"); 2280 } else { 2281 DECODE_PRINTF("CWD\n"); 2282 } 2283 DECODE_PRINTF("CWD\n"); 2284 TRACE_AND_STEP(); 2285 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2286 if (M.x86.R_EAX & 0x80000000) { 2287 M.x86.R_EDX = 0xffffffff; 2288 } else { 2289 M.x86.R_EDX = 0x0; 2290 } 2291 } else { 2292 if (M.x86.R_AX & 0x8000) { 2293 M.x86.R_DX = 0xffff; 2294 } else { 2295 M.x86.R_DX = 0x0; 2296 } 2297 } 2298 DECODE_CLEAR_SEGOVR(); 2299 END_OF_INSTR(); 2300 } 2301 2302 /**************************************************************************** 2303 REMARKS: 2304 Handles opcode 0x9a 2305 ****************************************************************************/ 2306 void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1)) 2307 { 2308 u16 farseg, faroff; 2309 2310 START_OF_INSTR(); 2311 DECODE_PRINTF("CALL\t"); 2312 faroff = fetch_word_imm(); 2313 farseg = fetch_word_imm(); 2314 DECODE_PRINTF2("%04x:", farseg); 2315 DECODE_PRINTF2("%04x\n", faroff); 2316 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR "); 2317 2318 /* XXX 2319 * 2320 * Hooked interrupt vectors calling into our "BIOS" will cause 2321 * problems unless all intersegment stuff is checked for BIOS 2322 * access. Check needed here. For moment, let it alone. 2323 */ 2324 TRACE_AND_STEP(); 2325 push_word(M.x86.R_CS); 2326 M.x86.R_CS = farseg; 2327 push_word(M.x86.R_IP); 2328 M.x86.R_IP = faroff; 2329 DECODE_CLEAR_SEGOVR(); 2330 END_OF_INSTR(); 2331 } 2332 2333 /**************************************************************************** 2334 REMARKS: 2335 Handles opcode 0x9b 2336 ****************************************************************************/ 2337 void x86emuOp_wait(u8 X86EMU_UNUSED(op1)) 2338 { 2339 START_OF_INSTR(); 2340 DECODE_PRINTF("WAIT"); 2341 TRACE_AND_STEP(); 2342 /* NADA. */ 2343 DECODE_CLEAR_SEGOVR(); 2344 END_OF_INSTR(); 2345 } 2346 2347 /**************************************************************************** 2348 REMARKS: 2349 Handles opcode 0x9c 2350 ****************************************************************************/ 2351 void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1)) 2352 { 2353 u32 flags; 2354 2355 START_OF_INSTR(); 2356 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2357 DECODE_PRINTF("PUSHFD\n"); 2358 } else { 2359 DECODE_PRINTF("PUSHF\n"); 2360 } 2361 TRACE_AND_STEP(); 2362 2363 /* clear out *all* bits not representing flags, and turn on real bits */ 2364 flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON; 2365 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2366 push_long(flags); 2367 } else { 2368 push_word((u16)flags); 2369 } 2370 DECODE_CLEAR_SEGOVR(); 2371 END_OF_INSTR(); 2372 } 2373 2374 /**************************************************************************** 2375 REMARKS: 2376 Handles opcode 0x9d 2377 ****************************************************************************/ 2378 void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1)) 2379 { 2380 START_OF_INSTR(); 2381 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2382 DECODE_PRINTF("POPFD\n"); 2383 } else { 2384 DECODE_PRINTF("POPF\n"); 2385 } 2386 TRACE_AND_STEP(); 2387 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2388 M.x86.R_EFLG = pop_long(); 2389 } else { 2390 M.x86.R_FLG = pop_word(); 2391 } 2392 DECODE_CLEAR_SEGOVR(); 2393 END_OF_INSTR(); 2394 } 2395 2396 /**************************************************************************** 2397 REMARKS: 2398 Handles opcode 0x9e 2399 ****************************************************************************/ 2400 void x86emuOp_sahf(u8 X86EMU_UNUSED(op1)) 2401 { 2402 START_OF_INSTR(); 2403 DECODE_PRINTF("SAHF\n"); 2404 TRACE_AND_STEP(); 2405 /* clear the lower bits of the flag register */ 2406 M.x86.R_FLG &= 0xffffff00; 2407 /* or in the AH register into the flags register */ 2408 M.x86.R_FLG |= M.x86.R_AH; 2409 DECODE_CLEAR_SEGOVR(); 2410 END_OF_INSTR(); 2411 } 2412 2413 /**************************************************************************** 2414 REMARKS: 2415 Handles opcode 0x9f 2416 ****************************************************************************/ 2417 void x86emuOp_lahf(u8 X86EMU_UNUSED(op1)) 2418 { 2419 START_OF_INSTR(); 2420 DECODE_PRINTF("LAHF\n"); 2421 TRACE_AND_STEP(); 2422 M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff); 2423 /*undocumented TC++ behavior??? Nope. It's documented, but 2424 you have too look real hard to notice it. */ 2425 M.x86.R_AH |= 0x2; 2426 DECODE_CLEAR_SEGOVR(); 2427 END_OF_INSTR(); 2428 } 2429 2430 /**************************************************************************** 2431 REMARKS: 2432 Handles opcode 0xa0 2433 ****************************************************************************/ 2434 void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1)) 2435 { 2436 u16 offset; 2437 2438 START_OF_INSTR(); 2439 DECODE_PRINTF("MOV\tAL,"); 2440 offset = fetch_word_imm(); 2441 DECODE_PRINTF2("[%04x]\n", offset); 2442 TRACE_AND_STEP(); 2443 M.x86.R_AL = fetch_data_byte(offset); 2444 DECODE_CLEAR_SEGOVR(); 2445 END_OF_INSTR(); 2446 } 2447 2448 /**************************************************************************** 2449 REMARKS: 2450 Handles opcode 0xa1 2451 ****************************************************************************/ 2452 void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1)) 2453 { 2454 u16 offset; 2455 2456 START_OF_INSTR(); 2457 offset = fetch_word_imm(); 2458 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2459 DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset); 2460 } else { 2461 DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset); 2462 } 2463 TRACE_AND_STEP(); 2464 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2465 M.x86.R_EAX = fetch_data_long(offset); 2466 } else { 2467 M.x86.R_AX = fetch_data_word(offset); 2468 } 2469 DECODE_CLEAR_SEGOVR(); 2470 END_OF_INSTR(); 2471 } 2472 2473 /**************************************************************************** 2474 REMARKS: 2475 Handles opcode 0xa2 2476 ****************************************************************************/ 2477 void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1)) 2478 { 2479 u16 offset; 2480 2481 START_OF_INSTR(); 2482 DECODE_PRINTF("MOV\t"); 2483 offset = fetch_word_imm(); 2484 DECODE_PRINTF2("[%04x],AL\n", offset); 2485 TRACE_AND_STEP(); 2486 store_data_byte(offset, M.x86.R_AL); 2487 DECODE_CLEAR_SEGOVR(); 2488 END_OF_INSTR(); 2489 } 2490 2491 /**************************************************************************** 2492 REMARKS: 2493 Handles opcode 0xa3 2494 ****************************************************************************/ 2495 void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1)) 2496 { 2497 u16 offset; 2498 2499 START_OF_INSTR(); 2500 offset = fetch_word_imm(); 2501 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2502 DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset); 2503 } else { 2504 DECODE_PRINTF2("MOV\t[%04x],AX\n", offset); 2505 } 2506 TRACE_AND_STEP(); 2507 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2508 store_data_long(offset, M.x86.R_EAX); 2509 } else { 2510 store_data_word(offset, M.x86.R_AX); 2511 } 2512 DECODE_CLEAR_SEGOVR(); 2513 END_OF_INSTR(); 2514 } 2515 2516 /**************************************************************************** 2517 REMARKS: 2518 Handles opcode 0xa4 2519 ****************************************************************************/ 2520 void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1)) 2521 { 2522 u8 val; 2523 u32 count; 2524 int inc; 2525 2526 START_OF_INSTR(); 2527 DECODE_PRINTF("MOVS\tBYTE\n"); 2528 if (ACCESS_FLAG(F_DF)) /* down */ 2529 inc = -1; 2530 else 2531 inc = 1; 2532 TRACE_AND_STEP(); 2533 count = 1; 2534 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2535 /* dont care whether REPE or REPNE */ 2536 /* move them until CX is ZERO. */ 2537 count = M.x86.R_CX; 2538 M.x86.R_CX = 0; 2539 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2540 } 2541 while (count--) { 2542 val = fetch_data_byte(M.x86.R_SI); 2543 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val); 2544 M.x86.R_SI += inc; 2545 M.x86.R_DI += inc; 2546 } 2547 DECODE_CLEAR_SEGOVR(); 2548 END_OF_INSTR(); 2549 } 2550 2551 /**************************************************************************** 2552 REMARKS: 2553 Handles opcode 0xa5 2554 ****************************************************************************/ 2555 void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1)) 2556 { 2557 u32 val; 2558 int inc; 2559 u32 count; 2560 2561 START_OF_INSTR(); 2562 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2563 DECODE_PRINTF("MOVS\tDWORD\n"); 2564 if (ACCESS_FLAG(F_DF)) /* down */ 2565 inc = -4; 2566 else 2567 inc = 4; 2568 } else { 2569 DECODE_PRINTF("MOVS\tWORD\n"); 2570 if (ACCESS_FLAG(F_DF)) /* down */ 2571 inc = -2; 2572 else 2573 inc = 2; 2574 } 2575 TRACE_AND_STEP(); 2576 count = 1; 2577 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2578 /* dont care whether REPE or REPNE */ 2579 /* move them until CX is ZERO. */ 2580 count = M.x86.R_CX; 2581 M.x86.R_CX = 0; 2582 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2583 } 2584 while (count--) { 2585 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2586 val = fetch_data_long(M.x86.R_SI); 2587 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val); 2588 } else { 2589 val = fetch_data_word(M.x86.R_SI); 2590 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val); 2591 } 2592 M.x86.R_SI += inc; 2593 M.x86.R_DI += inc; 2594 } 2595 DECODE_CLEAR_SEGOVR(); 2596 END_OF_INSTR(); 2597 } 2598 2599 /**************************************************************************** 2600 REMARKS: 2601 Handles opcode 0xa6 2602 ****************************************************************************/ 2603 void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1)) 2604 { 2605 s8 val1, val2; 2606 int inc; 2607 2608 START_OF_INSTR(); 2609 DECODE_PRINTF("CMPS\tBYTE\n"); 2610 TRACE_AND_STEP(); 2611 if (ACCESS_FLAG(F_DF)) /* down */ 2612 inc = -1; 2613 else 2614 inc = 1; 2615 2616 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2617 /* REPE */ 2618 /* move them until CX is ZERO. */ 2619 while (M.x86.R_CX != 0) { 2620 val1 = fetch_data_byte(M.x86.R_SI); 2621 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); 2622 cmp_byte(val1, val2); 2623 M.x86.R_CX -= 1; 2624 M.x86.R_SI += inc; 2625 M.x86.R_DI += inc; 2626 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break; 2627 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break; 2628 } 2629 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2630 } else { 2631 val1 = fetch_data_byte(M.x86.R_SI); 2632 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); 2633 cmp_byte(val1, val2); 2634 M.x86.R_SI += inc; 2635 M.x86.R_DI += inc; 2636 } 2637 DECODE_CLEAR_SEGOVR(); 2638 END_OF_INSTR(); 2639 } 2640 2641 /**************************************************************************** 2642 REMARKS: 2643 Handles opcode 0xa7 2644 ****************************************************************************/ 2645 void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1)) 2646 { 2647 u32 val1,val2; 2648 int inc; 2649 2650 START_OF_INSTR(); 2651 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2652 DECODE_PRINTF("CMPS\tDWORD\n"); 2653 inc = 4; 2654 } else { 2655 DECODE_PRINTF("CMPS\tWORD\n"); 2656 inc = 2; 2657 } 2658 if (ACCESS_FLAG(F_DF)) /* down */ 2659 inc = -inc; 2660 2661 TRACE_AND_STEP(); 2662 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2663 /* REPE */ 2664 /* move them until CX is ZERO. */ 2665 while (M.x86.R_CX != 0) { 2666 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2667 val1 = fetch_data_long(M.x86.R_SI); 2668 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); 2669 cmp_long(val1, val2); 2670 } else { 2671 val1 = fetch_data_word(M.x86.R_SI); 2672 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); 2673 cmp_word((u16)val1, (u16)val2); 2674 } 2675 M.x86.R_CX -= 1; 2676 M.x86.R_SI += inc; 2677 M.x86.R_DI += inc; 2678 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break; 2679 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break; 2680 } 2681 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2682 } else { 2683 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2684 val1 = fetch_data_long(M.x86.R_SI); 2685 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); 2686 cmp_long(val1, val2); 2687 } else { 2688 val1 = fetch_data_word(M.x86.R_SI); 2689 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); 2690 cmp_word((u16)val1, (u16)val2); 2691 } 2692 M.x86.R_SI += inc; 2693 M.x86.R_DI += inc; 2694 } 2695 DECODE_CLEAR_SEGOVR(); 2696 END_OF_INSTR(); 2697 } 2698 2699 /**************************************************************************** 2700 REMARKS: 2701 Handles opcode 0xa8 2702 ****************************************************************************/ 2703 void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1)) 2704 { 2705 int imm; 2706 2707 START_OF_INSTR(); 2708 DECODE_PRINTF("TEST\tAL,"); 2709 imm = fetch_byte_imm(); 2710 DECODE_PRINTF2("%04x\n", imm); 2711 TRACE_AND_STEP(); 2712 test_byte(M.x86.R_AL, (u8)imm); 2713 DECODE_CLEAR_SEGOVR(); 2714 END_OF_INSTR(); 2715 } 2716 2717 /**************************************************************************** 2718 REMARKS: 2719 Handles opcode 0xa9 2720 ****************************************************************************/ 2721 void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1)) 2722 { 2723 u32 srcval; 2724 2725 START_OF_INSTR(); 2726 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2727 DECODE_PRINTF("TEST\tEAX,"); 2728 srcval = fetch_long_imm(); 2729 } else { 2730 DECODE_PRINTF("TEST\tAX,"); 2731 srcval = fetch_word_imm(); 2732 } 2733 DECODE_PRINTF2("%x\n", srcval); 2734 TRACE_AND_STEP(); 2735 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2736 test_long(M.x86.R_EAX, srcval); 2737 } else { 2738 test_word(M.x86.R_AX, (u16)srcval); 2739 } 2740 DECODE_CLEAR_SEGOVR(); 2741 END_OF_INSTR(); 2742 } 2743 2744 /**************************************************************************** 2745 REMARKS: 2746 Handles opcode 0xaa 2747 ****************************************************************************/ 2748 void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1)) 2749 { 2750 int inc; 2751 2752 START_OF_INSTR(); 2753 DECODE_PRINTF("STOS\tBYTE\n"); 2754 if (ACCESS_FLAG(F_DF)) /* down */ 2755 inc = -1; 2756 else 2757 inc = 1; 2758 TRACE_AND_STEP(); 2759 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2760 /* dont care whether REPE or REPNE */ 2761 /* move them until CX is ZERO. */ 2762 while (M.x86.R_CX != 0) { 2763 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL); 2764 M.x86.R_CX -= 1; 2765 M.x86.R_DI += inc; 2766 } 2767 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2768 } else { 2769 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL); 2770 M.x86.R_DI += inc; 2771 } 2772 DECODE_CLEAR_SEGOVR(); 2773 END_OF_INSTR(); 2774 } 2775 2776 /**************************************************************************** 2777 REMARKS: 2778 Handles opcode 0xab 2779 ****************************************************************************/ 2780 void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1)) 2781 { 2782 int inc; 2783 u32 count; 2784 2785 START_OF_INSTR(); 2786 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2787 DECODE_PRINTF("STOS\tDWORD\n"); 2788 if (ACCESS_FLAG(F_DF)) /* down */ 2789 inc = -4; 2790 else 2791 inc = 4; 2792 } else { 2793 DECODE_PRINTF("STOS\tWORD\n"); 2794 if (ACCESS_FLAG(F_DF)) /* down */ 2795 inc = -2; 2796 else 2797 inc = 2; 2798 } 2799 TRACE_AND_STEP(); 2800 count = 1; 2801 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2802 /* dont care whether REPE or REPNE */ 2803 /* move them until CX is ZERO. */ 2804 count = M.x86.R_CX; 2805 M.x86.R_CX = 0; 2806 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2807 } 2808 while (count--) { 2809 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2810 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX); 2811 } else { 2812 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX); 2813 } 2814 M.x86.R_DI += inc; 2815 } 2816 DECODE_CLEAR_SEGOVR(); 2817 END_OF_INSTR(); 2818 } 2819 2820 /**************************************************************************** 2821 REMARKS: 2822 Handles opcode 0xac 2823 ****************************************************************************/ 2824 void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1)) 2825 { 2826 int inc; 2827 2828 START_OF_INSTR(); 2829 DECODE_PRINTF("LODS\tBYTE\n"); 2830 TRACE_AND_STEP(); 2831 if (ACCESS_FLAG(F_DF)) /* down */ 2832 inc = -1; 2833 else 2834 inc = 1; 2835 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2836 /* dont care whether REPE or REPNE */ 2837 /* move them until CX is ZERO. */ 2838 while (M.x86.R_CX != 0) { 2839 M.x86.R_AL = fetch_data_byte(M.x86.R_SI); 2840 M.x86.R_CX -= 1; 2841 M.x86.R_SI += inc; 2842 } 2843 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2844 } else { 2845 M.x86.R_AL = fetch_data_byte(M.x86.R_SI); 2846 M.x86.R_SI += inc; 2847 } 2848 DECODE_CLEAR_SEGOVR(); 2849 END_OF_INSTR(); 2850 } 2851 2852 /**************************************************************************** 2853 REMARKS: 2854 Handles opcode 0xad 2855 ****************************************************************************/ 2856 void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1)) 2857 { 2858 int inc; 2859 u32 count; 2860 2861 START_OF_INSTR(); 2862 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2863 DECODE_PRINTF("LODS\tDWORD\n"); 2864 if (ACCESS_FLAG(F_DF)) /* down */ 2865 inc = -4; 2866 else 2867 inc = 4; 2868 } else { 2869 DECODE_PRINTF("LODS\tWORD\n"); 2870 if (ACCESS_FLAG(F_DF)) /* down */ 2871 inc = -2; 2872 else 2873 inc = 2; 2874 } 2875 TRACE_AND_STEP(); 2876 count = 1; 2877 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2878 /* dont care whether REPE or REPNE */ 2879 /* move them until CX is ZERO. */ 2880 count = M.x86.R_CX; 2881 M.x86.R_CX = 0; 2882 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2883 } 2884 while (count--) { 2885 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2886 M.x86.R_EAX = fetch_data_long(M.x86.R_SI); 2887 } else { 2888 M.x86.R_AX = fetch_data_word(M.x86.R_SI); 2889 } 2890 M.x86.R_SI += inc; 2891 } 2892 DECODE_CLEAR_SEGOVR(); 2893 END_OF_INSTR(); 2894 } 2895 2896 /**************************************************************************** 2897 REMARKS: 2898 Handles opcode 0xae 2899 ****************************************************************************/ 2900 void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1)) 2901 { 2902 s8 val2; 2903 int inc; 2904 2905 START_OF_INSTR(); 2906 DECODE_PRINTF("SCAS\tBYTE\n"); 2907 TRACE_AND_STEP(); 2908 if (ACCESS_FLAG(F_DF)) /* down */ 2909 inc = -1; 2910 else 2911 inc = 1; 2912 if (M.x86.mode & SYSMODE_PREFIX_REPE) { 2913 /* REPE */ 2914 /* move them until CX is ZERO. */ 2915 while (M.x86.R_CX != 0) { 2916 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); 2917 cmp_byte(M.x86.R_AL, val2); 2918 M.x86.R_CX -= 1; 2919 M.x86.R_DI += inc; 2920 if (ACCESS_FLAG(F_ZF) == 0) 2921 break; 2922 } 2923 M.x86.mode &= ~SYSMODE_PREFIX_REPE; 2924 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) { 2925 /* REPNE */ 2926 /* move them until CX is ZERO. */ 2927 while (M.x86.R_CX != 0) { 2928 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); 2929 cmp_byte(M.x86.R_AL, val2); 2930 M.x86.R_CX -= 1; 2931 M.x86.R_DI += inc; 2932 if (ACCESS_FLAG(F_ZF)) 2933 break; /* zero flag set means equal */ 2934 } 2935 M.x86.mode &= ~SYSMODE_PREFIX_REPNE; 2936 } else { 2937 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); 2938 cmp_byte(M.x86.R_AL, val2); 2939 M.x86.R_DI += inc; 2940 } 2941 DECODE_CLEAR_SEGOVR(); 2942 END_OF_INSTR(); 2943 } 2944 2945 /**************************************************************************** 2946 REMARKS: 2947 Handles opcode 0xaf 2948 ****************************************************************************/ 2949 void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1)) 2950 { 2951 int inc; 2952 u32 val; 2953 2954 START_OF_INSTR(); 2955 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2956 DECODE_PRINTF("SCAS\tDWORD\n"); 2957 if (ACCESS_FLAG(F_DF)) /* down */ 2958 inc = -4; 2959 else 2960 inc = 4; 2961 } else { 2962 DECODE_PRINTF("SCAS\tWORD\n"); 2963 if (ACCESS_FLAG(F_DF)) /* down */ 2964 inc = -2; 2965 else 2966 inc = 2; 2967 } 2968 TRACE_AND_STEP(); 2969 if (M.x86.mode & SYSMODE_PREFIX_REPE) { 2970 /* REPE */ 2971 /* move them until CX is ZERO. */ 2972 while (M.x86.R_CX != 0) { 2973 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2974 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); 2975 cmp_long(M.x86.R_EAX, val); 2976 } else { 2977 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); 2978 cmp_word(M.x86.R_AX, (u16)val); 2979 } 2980 M.x86.R_CX -= 1; 2981 M.x86.R_DI += inc; 2982 if (ACCESS_FLAG(F_ZF) == 0) 2983 break; 2984 } 2985 M.x86.mode &= ~SYSMODE_PREFIX_REPE; 2986 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) { 2987 /* REPNE */ 2988 /* move them until CX is ZERO. */ 2989 while (M.x86.R_CX != 0) { 2990 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2991 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); 2992 cmp_long(M.x86.R_EAX, val); 2993 } else { 2994 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); 2995 cmp_word(M.x86.R_AX, (u16)val); 2996 } 2997 M.x86.R_CX -= 1; 2998 M.x86.R_DI += inc; 2999 if (ACCESS_FLAG(F_ZF)) 3000 break; /* zero flag set means equal */ 3001 } 3002 M.x86.mode &= ~SYSMODE_PREFIX_REPNE; 3003 } else { 3004 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 3005 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); 3006 cmp_long(M.x86.R_EAX, val); 3007 } else { 3008 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); 3009 cmp_word(M.x86.R_AX, (u16)val); 3010 } 3011 M.x86.R_DI += inc; 3012 } 3013 DECODE_CLEAR_SEGOVR(); 3014 END_OF_INSTR(); 3015 } 3016 3017 /**************************************************************************** 3018 REMARKS: 3019 Handles opcode 0xb0 - 0xb7 3020 ****************************************************************************/ 3021 void x86emuOp_mov_byte_register_IMM(u8 op1) 3022 { 3023 u8 imm, *ptr; 3024 3025 START_OF_INSTR(); 3026 DECODE_PRINTF("MOV\t"); 3027 ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7); 3028 DECODE_PRINTF(","); 3029 imm = fetch_byte_imm(); 3030 DECODE_PRINTF2("%x\n", imm); 3031 TRACE_AND_STEP(); 3032 *ptr = imm; 3033 DECODE_CLEAR_SEGOVR(); 3034 END_OF_INSTR(); 3035 } 3036 3037 /**************************************************************************** 3038 REMARKS: 3039 Handles opcode 0xb8 - 0xbf 3040 ****************************************************************************/ 3041 void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1)) 3042 { 3043 u32 srcval; 3044 3045 op1 &= 0x7; 3046 3047 START_OF_INSTR(); 3048 DECODE_PRINTF("MOV\t"); 3049 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 3050 u32 *reg32; 3051 reg32 = DECODE_RM_LONG_REGISTER(op1); 3052 srcval = fetch_long_imm(); 3053 DECODE_PRINTF2(",%x\n", srcval); 3054 TRACE_AND_STEP(); 3055 *reg32 = srcval; 3056 } else { 3057 u16 *reg16; 3058 reg16 = DECODE_RM_WORD_REGISTER(op1); 3059 srcval = fetch_word_imm(); 3060 DECODE_PRINTF2(",%x\n", srcval); 3061 TRACE_AND_STEP(); 3062 *reg16 = (u16)srcval; 3063 } 3064 DECODE_CLEAR_SEGOVR(); 3065 END_OF_INSTR(); 3066 } 3067 3068 /**************************************************************************** 3069 REMARKS: 3070 Handles opcode 0xc0 3071 ****************************************************************************/ 3072 void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1)) 3073 { 3074 int mod, rl, rh; 3075 u8 *destreg; 3076 uint destoffset; 3077 u8 destval; 3078 u8 amt; 3079 3080 /* 3081 * Yet another weirdo special case instruction format. Part of 3082 * the opcode held below in "RH". Doubly nested case would 3083 * result, except that the decoded instruction 3084 */ 3085 START_OF_INSTR(); 3086 FETCH_DECODE_MODRM(mod, rh, rl); 3087 #ifdef DEBUG 3088 if (DEBUG_DECODE()) { 3089 /* XXX DECODE_PRINTF may be changed to something more 3090 general, so that it is important to leave the strings 3091 in the same format, even though the result is that the 3092 above test is done twice. */ 3093 3094 switch (rh) { 3095 case 0: 3096 DECODE_PRINTF("ROL\t"); 3097 break; 3098 case 1: 3099 DECODE_PRINTF("ROR\t"); 3100 break; 3101 case 2: 3102 DECODE_PRINTF("RCL\t"); 3103 break; 3104 case 3: 3105 DECODE_PRINTF("RCR\t"); 3106 break; 3107 case 4: 3108 DECODE_PRINTF("SHL\t"); 3109 break; 3110 case 5: 3111 DECODE_PRINTF("SHR\t"); 3112 break; 3113 case 6: 3114 DECODE_PRINTF("SAL\t"); 3115 break; 3116 case 7: 3117 DECODE_PRINTF("SAR\t"); 3118 break; 3119 } 3120 } 3121 #endif 3122 /* know operation, decode the mod byte to find the addressing 3123 mode. */ 3124 if (mod < 3) { 3125 DECODE_PRINTF("BYTE PTR "); 3126 destoffset = decode_rmXX_address(mod, rl); 3127 amt = fetch_byte_imm(); 3128 DECODE_PRINTF2(",%x\n", amt); 3129 destval = fetch_data_byte(destoffset); 3130 TRACE_AND_STEP(); 3131 destval = (*opcD0_byte_operation[rh]) (destval, amt); 3132 store_data_byte(destoffset, destval); 3133 } else { /* register to register */ 3134 destreg = DECODE_RM_BYTE_REGISTER(rl); 3135 amt = fetch_byte_imm(); 3136 DECODE_PRINTF2(",%x\n", amt); 3137 TRACE_AND_STEP(); 3138 destval = (*opcD0_byte_operation[rh]) (*destreg, amt); 3139 *destreg = destval; 3140 } 3141 DECODE_CLEAR_SEGOVR(); 3142 END_OF_INSTR(); 3143 } 3144 3145 /**************************************************************************** 3146 REMARKS: 3147 Handles opcode 0xc1 3148 ****************************************************************************/ 3149 void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1)) 3150 { 3151 int mod, rl, rh; 3152 uint destoffset; 3153 u8 amt; 3154 3155 /* 3156 * Yet another weirdo special case instruction format. Part of 3157 * the opcode held below in "RH". Doubly nested case would 3158 * result, except that the decoded instruction 3159 */ 3160 START_OF_INSTR(); 3161 FETCH_DECODE_MODRM(mod, rh, rl); 3162 #ifdef DEBUG 3163 if (DEBUG_DECODE()) { 3164 /* XXX DECODE_PRINTF may be changed to something more 3165 general, so that it is important to leave the strings 3166 in the same format, even though the result is that the 3167 above test is done twice. */ 3168 3169 switch (rh) { 3170 case 0: 3171 DECODE_PRINTF("ROL\t"); 3172 break; 3173 case 1: 3174 DECODE_PRINTF("ROR\t"); 3175 break; 3176 case 2: 3177 DECODE_PRINTF("RCL\t"); 3178 break; 3179 case 3: 3180 DECODE_PRINTF("RCR\t"); 3181 break; 3182 case 4: 3183 DECODE_PRINTF("SHL\t"); 3184 break; 3185 case 5: 3186 DECODE_PRINTF("SHR\t"); 3187 break; 3188 case 6: 3189 DECODE_PRINTF("SAL\t"); 3190 break; 3191 case 7: 3192 DECODE_PRINTF("SAR\t"); 3193 break; 3194 } 3195 } 3196 #endif 3197 /* know operation, decode the mod byte to find the addressing 3198 mode. */ 3199 if (mod < 3) { 3200 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 3201 u32 destval; 3202 3203 DECODE_PRINTF("DWORD PTR "); 3204 destoffset = decode_rmXX_address(mod, rl); 3205 amt = fetch_byte_imm(); 3206 DECODE_PRINTF2(",%x\n", amt); 3207 destval = fetch_data_long(destoffset); 3208 TRACE_AND_STEP(); 3209 destval = (*opcD1_long_operation[rh]) (destval, amt); 3210 store_data_long(destoffset, destval); 3211 } else { 3212 u16 destval; 3213 3214 DECODE_PRINTF("WORD PTR "); 3215 destoffset = decode_rmXX_address(mod, rl); 3216 amt = fetch_byte_imm(); 3217 DECODE_PRINTF2(",%x\n", amt); 3218 destval = fetch_data_word(destoffset); 3219 TRACE_AND_STEP(); 3220 destval = (*opcD1_word_operation[rh]) (destval, amt); 3221 store_data_word(destoffset, destval); 3222 } 3223 } else { /* register to register */ 3224 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 3225 u32 *destreg; 3226 3227 destreg = DECODE_RM_LONG_REGISTER(rl); 3228 amt = fetch_byte_imm(); 3229 DECODE_PRINTF2(",%x\n", amt); 3230 TRACE_AND_STEP(); 3231 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt); 3232 } else { 3233 u16 *destreg; 3234 3235 destreg = DECODE_RM_WORD_REGISTER(rl); 3236 amt = fetch_byte_imm(); 3237 DECODE_PRINTF2(",%x\n", amt); 3238 TRACE_AND_STEP(); 3239 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt); 3240 } 3241 } 3242 DECODE_CLEAR_SEGOVR(); 3243 END_OF_INSTR(); 3244 } 3245 3246 /**************************************************************************** 3247 REMARKS: 3248 Handles opcode 0xc2 3249 ****************************************************************************/ 3250 void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1)) 3251 { 3252 u16 imm; 3253 3254 START_OF_INSTR(); 3255 DECODE_PRINTF("RET\t"); 3256 imm = fetch_word_imm(); 3257 DECODE_PRINTF2("%x\n", imm); 3258 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip); 3259 TRACE_AND_STEP(); 3260 M.x86.R_IP = pop_word(); 3261 M.x86.R_SP += imm; 3262 DECODE_CLEAR_SEGOVR(); 3263 END_OF_INSTR(); 3264 } 3265 3266 /**************************************************************************** 3267 REMARKS: 3268 Handles opcode 0xc3 3269 ****************************************************************************/ 3270 void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1)) 3271 { 3272 START_OF_INSTR(); 3273 DECODE_PRINTF("RET\n"); 3274 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip); 3275 TRACE_AND_STEP(); 3276 M.x86.R_IP = pop_word(); 3277 DECODE_CLEAR_SEGOVR(); 3278 END_OF_INSTR(); 3279 } 3280 3281 /**************************************************************************** 3282 REMARKS: 3283 Handles opcode 0xc4 3284 ****************************************************************************/ 3285 void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1)) 3286 { 3287 int mod, rh, rl; 3288 u16 *dstreg; 3289 uint srcoffset; 3290 3291 START_OF_INSTR(); 3292 DECODE_PRINTF("LES\t"); 3293 FETCH_DECODE_MODRM(mod, rh, rl); 3294 if (mod < 3) { 3295 dstreg = DECODE_RM_WORD_REGISTER(rh); 3296 DECODE_PRINTF(","); 3297 srcoffset = decode_rmXX_address(mod, rl); 3298 DECODE_PRINTF("\n"); 3299 TRACE_AND_STEP(); 3300 *dstreg = fetch_data_word(srcoffset); 3301 M.x86.R_ES = fetch_data_word(srcoffset + 2); 3302 } 3303 /* else UNDEFINED! register to register */ 3304 3305 DECODE_CLEAR_SEGOVR(); 3306 END_OF_INSTR(); 3307 } 3308 3309 /**************************************************************************** 3310 REMARKS: 3311 Handles opcode 0xc5 3312 ****************************************************************************/ 3313 void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1)) 3314 { 3315 int mod, rh, rl; 3316 u16 *dstreg; 3317 uint srcoffset; 3318 3319 START_OF_INSTR(); 3320 DECODE_PRINTF("LDS\t"); 3321 FETCH_DECODE_MODRM(mod, rh, rl); 3322 if (mod < 3) { 3323 dstreg = DECODE_RM_WORD_REGISTER(rh); 3324 DECODE_PRINTF(","); 3325 srcoffset = decode_rmXX_address(mod, rl); 3326 DECODE_PRINTF("\n"); 3327 TRACE_AND_STEP(); 3328 *dstreg = fetch_data_word(srcoffset); 3329 M.x86.R_DS = fetch_data_word(srcoffset + 2); 3330 } 3331 /* else UNDEFINED! */ 3332 DECODE_CLEAR_SEGOVR(); 3333 END_OF_INSTR(); 3334 } 3335 3336 /**************************************************************************** 3337 REMARKS: 3338 Handles opcode 0xc6 3339 ****************************************************************************/ 3340 void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1)) 3341 { 3342 int mod, rl, rh; 3343 u8 *destreg; 3344 uint destoffset; 3345 u8 imm; 3346 3347 START_OF_INSTR(); 3348 DECODE_PRINTF("MOV\t"); 3349 FETCH_DECODE_MODRM(mod, rh, rl); 3350 if (rh != 0) { 3351 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n"); 3352 HALT_SYS(); 3353 } 3354 if (mod < 3) { 3355 DECODE_PRINTF("BYTE PTR "); 3356 destoffset = decode_rmXX_address(mod, rl); 3357 imm = fetch_byte_imm(); 3358 DECODE_PRINTF2(",%2x\n", imm); 3359 TRACE_AND_STEP(); 3360 store_data_byte(destoffset, imm); 3361 } else { /* register to register */ 3362 destreg = DECODE_RM_BYTE_REGISTER(rl); 3363 imm = fetch_byte_imm(); 3364 DECODE_PRINTF2(",%2x\n", imm); 3365 TRACE_AND_STEP(); 3366 *destreg = imm; 3367 } 3368 DECODE_CLEAR_SEGOVR(); 3369 END_OF_INSTR(); 3370 } 3371 3372 /**************************************************************************** 3373 REMARKS: 3374 Handles opcode 0xc7 3375 ****************************************************************************/ 3376 void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1)) 3377 { 3378 int mod, rl, rh; 3379 uint destoffset; 3380 3381 START_OF_INSTR(); 3382 DECODE_PRINTF("MOV\t"); 3383 FETCH_DECODE_MODRM(mod, rh, rl); 3384 if (rh != 0) { 3385 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n"); 3386 HALT_SYS(); 3387 } 3388 if (mod < 3) { 3389 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 3390 u32 imm; 3391 3392 DECODE_PRINTF("DWORD PTR "); 3393 destoffset = decode_rmXX_address(mod, rl); 3394 imm = fetch_long_imm(); 3395 DECODE_PRINTF2(",%x\n", imm); 3396 TRACE_AND_STEP(); 3397 store_data_long(destoffset, imm); 3398 } else { 3399 u16 imm; 3400 3401 DECODE_PRINTF("WORD PTR "); 3402 destoffset = decode_rmXX_address(mod, rl); 3403 imm = fetch_word_imm(); 3404 DECODE_PRINTF2(",%x\n", imm); 3405 TRACE_AND_STEP(); 3406 store_data_word(destoffset, imm); 3407 } 3408 } else { /* register to register */ 3409 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 3410 u32 *destreg; 3411 u32 imm; 3412 3413 destreg = DECODE_RM_LONG_REGISTER(rl); 3414 imm = fetch_long_imm(); 3415 DECODE_PRINTF2(",%x\n", imm); 3416 TRACE_AND_STEP(); 3417 *destreg = imm; 3418 } else { 3419 u16 *destreg; 3420 u16 imm; 3421 3422 destreg = DECODE_RM_WORD_REGISTER(rl); 3423 imm = fetch_word_imm(); 3424 DECODE_PRINTF2(",%x\n", imm); 3425 TRACE_AND_STEP(); 3426 *destreg = imm; 3427 } 3428 } 3429 DECODE_CLEAR_SEGOVR(); 3430 END_OF_INSTR(); 3431 } 3432 3433 /**************************************************************************** 3434 REMARKS: 3435 Handles opcode 0xc8 3436 ****************************************************************************/ 3437 void x86emuOp_enter(u8 X86EMU_UNUSED(op1)) 3438 { 3439 u16 local,frame_pointer; 3440 u8 nesting; 3441 int i; 3442 3443 START_OF_INSTR(); 3444 local = fetch_word_imm(); 3445 nesting = fetch_byte_imm(); 3446 DECODE_PRINTF2("ENTER %x\n", local); 3447 DECODE_PRINTF2(",%x\n", nesting); 3448 TRACE_AND_STEP(); 3449 push_word(M.x86.R_BP); 3450 frame_pointer = M.x86.R_SP; 3451 if (nesting > 0) { 3452 for (i = 1; i < nesting; i++) { 3453 M.x86.R_BP -= 2; 3454 push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP)); 3455 } 3456 push_word(frame_pointer); 3457 } 3458 M.x86.R_BP = frame_pointer; 3459 M.x86.R_SP = (u16)(M.x86.R_SP - local); 3460 DECODE_CLEAR_SEGOVR(); 3461 END_OF_INSTR(); 3462 } 3463 3464 /**************************************************************************** 3465 REMARKS: 3466 Handles opcode 0xc9 3467 ****************************************************************************/ 3468 void x86emuOp_leave(u8 X86EMU_UNUSED(op1)) 3469 { 3470 START_OF_INSTR(); 3471 DECODE_PRINTF("LEAVE\n"); 3472 TRACE_AND_STEP(); 3473 M.x86.R_SP = M.x86.R_BP; 3474 M.x86.R_BP = pop_word(); 3475 DECODE_CLEAR_SEGOVR(); 3476 END_OF_INSTR(); 3477 } 3478 3479 /**************************************************************************** 3480 REMARKS: 3481 Handles opcode 0xca 3482 ****************************************************************************/ 3483 void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1)) 3484 { 3485 u16 imm; 3486 3487 START_OF_INSTR(); 3488 DECODE_PRINTF("RETF\t"); 3489 imm = fetch_word_imm(); 3490 DECODE_PRINTF2("%x\n", imm); 3491 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip); 3492 TRACE_AND_STEP(); 3493 M.x86.R_IP = pop_word(); 3494 M.x86.R_CS = pop_word(); 3495 M.x86.R_SP += imm; 3496 DECODE_CLEAR_SEGOVR(); 3497 END_OF_INSTR(); 3498 } 3499 3500 /**************************************************************************** 3501 REMARKS: 3502 Handles opcode 0xcb 3503 ****************************************************************************/ 3504 void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1)) 3505 { 3506 START_OF_INSTR(); 3507 DECODE_PRINTF("RETF\n"); 3508 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip); 3509 TRACE_AND_STEP(); 3510 M.x86.R_IP = pop_word(); 3511 M.x86.R_CS = pop_word(); 3512 DECODE_CLEAR_SEGOVR(); 3513 END_OF_INSTR(); 3514 } 3515 3516 /**************************************************************************** 3517 REMARKS: 3518 Handles opcode 0xcc 3519 ****************************************************************************/ 3520 void x86emuOp_int3(u8 X86EMU_UNUSED(op1)) 3521 { 3522 u16 tmp; 3523 3524 START_OF_INSTR(); 3525 DECODE_PRINTF("INT 3\n"); 3526 tmp = (u16) mem_access_word(3 * 4 + 2); 3527 /* access the segment register */ 3528 TRACE_AND_STEP(); 3529 if (_X86EMU_intrTab[3]) { 3530 (*_X86EMU_intrTab[3])(3); 3531 } else { 3532 push_word((u16)M.x86.R_FLG); 3533 CLEAR_FLAG(F_IF); 3534 CLEAR_FLAG(F_TF); 3535 push_word(M.x86.R_CS); 3536 M.x86.R_CS = mem_access_word(3 * 4 + 2); 3537 push_word(M.x86.R_IP); 3538 M.x86.R_IP = mem_access_word(3 * 4); 3539 } 3540 DECODE_CLEAR_SEGOVR(); 3541 END_OF_INSTR(); 3542 } 3543 3544 /**************************************************************************** 3545 REMARKS: 3546 Handles opcode 0xcd 3547 ****************************************************************************/ 3548 void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1)) 3549 { 3550 u16 tmp; 3551 u8 intnum; 3552 3553 START_OF_INSTR(); 3554 DECODE_PRINTF("INT\t"); 3555 intnum = fetch_byte_imm(); 3556 DECODE_PRINTF2("%x\n", intnum); 3557 tmp = mem_access_word(intnum * 4 + 2); 3558 TRACE_AND_STEP(); 3559 if (_X86EMU_intrTab[intnum]) { 3560 (*_X86EMU_intrTab[intnum])(intnum); 3561 } else { 3562 push_word((u16)M.x86.R_FLG); 3563 CLEAR_FLAG(F_IF); 3564 CLEAR_FLAG(F_TF); 3565 push_word(M.x86.R_CS); 3566 M.x86.R_CS = mem_access_word(intnum * 4 + 2); 3567 push_word(M.x86.R_IP); 3568 M.x86.R_IP = mem_access_word(intnum * 4); 3569 } 3570 DECODE_CLEAR_SEGOVR(); 3571 END_OF_INSTR(); 3572 } 3573 3574 /**************************************************************************** 3575 REMARKS: 3576 Handles opcode 0xce 3577 ****************************************************************************/ 3578 void x86emuOp_into(u8 X86EMU_UNUSED(op1)) 3579 { 3580 u16 tmp; 3581 3582 START_OF_INSTR(); 3583 DECODE_PRINTF("INTO\n"); 3584 TRACE_AND_STEP(); 3585 if (ACCESS_FLAG(F_OF)) { 3586 tmp = mem_access_word(4 * 4 + 2); 3587 if (_X86EMU_intrTab[4]) { 3588 (*_X86EMU_intrTab[4])(4); 3589 } else { 3590 push_word((u16)M.x86.R_FLG); 3591 CLEAR_FLAG(F_IF); 3592 CLEAR_FLAG(F_TF); 3593 push_word(M.x86.R_CS); 3594 M.x86.R_CS = mem_access_word(4 * 4 + 2); 3595 push_word(M.x86.R_IP); 3596 M.x86.R_IP = mem_access_word(4 * 4); 3597 } 3598 } 3599 DECODE_CLEAR_SEGOVR(); 3600 END_OF_INSTR(); 3601 } 3602 3603 /**************************************************************************** 3604 REMARKS: 3605 Handles opcode 0xcf 3606 ****************************************************************************/ 3607 void x86emuOp_iret(u8 X86EMU_UNUSED(op1)) 3608 { 3609 START_OF_INSTR(); 3610 DECODE_PRINTF("IRET\n"); 3611 3612 TRACE_AND_STEP(); 3613 3614 M.x86.R_IP = pop_word(); 3615 M.x86.R_CS = pop_word(); 3616 M.x86.R_FLG = pop_word(); 3617 DECODE_CLEAR_SEGOVR(); 3618 END_OF_INSTR(); 3619 } 3620 3621 /**************************************************************************** 3622 REMARKS: 3623 Handles opcode 0xd0 3624 ****************************************************************************/ 3625 void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1)) 3626 { 3627 int mod, rl, rh; 3628 u8 *destreg; 3629 uint destoffset; 3630 u8 destval; 3631 3632 /* 3633 * Yet another weirdo special case instruction format. Part of 3634 * the opcode held below in "RH". Doubly nested case would 3635 * result, except that the decoded instruction 3636 */ 3637 START_OF_INSTR(); 3638 FETCH_DECODE_MODRM(mod, rh, rl); 3639 #ifdef DEBUG 3640 if (DEBUG_DECODE()) { 3641 /* XXX DECODE_PRINTF may be changed to something more 3642 general, so that it is important to leave the strings 3643 in the same format, even though the result is that the 3644 above test is done twice. */ 3645 switch (rh) { 3646 case 0: 3647 DECODE_PRINTF("ROL\t"); 3648 break; 3649 case 1: 3650 DECODE_PRINTF("ROR\t"); 3651 break; 3652 case 2: 3653 DECODE_PRINTF("RCL\t"); 3654 break; 3655 case 3: 3656 DECODE_PRINTF("RCR\t"); 3657 break; 3658 case 4: 3659 DECODE_PRINTF("SHL\t"); 3660 break; 3661 case 5: 3662 DECODE_PRINTF("SHR\t"); 3663 break; 3664 case 6: 3665 DECODE_PRINTF("SAL\t"); 3666 break; 3667 case 7: 3668 DECODE_PRINTF("SAR\t"); 3669 break; 3670 } 3671 } 3672 #endif 3673 /* know operation, decode the mod byte to find the addressing 3674 mode. */ 3675 if (mod < 3) { 3676 DECODE_PRINTF("BYTE PTR "); 3677 destoffset = decode_rmXX_address(mod, rl); 3678 DECODE_PRINTF(",1\n"); 3679 destval = fetch_data_byte(destoffset); 3680 TRACE_AND_STEP(); 3681 destval = (*opcD0_byte_operation[rh]) (destval, 1); 3682 store_data_byte(destoffset, destval); 3683 } else { /* register to register */ 3684 destreg = DECODE_RM_BYTE_REGISTER(rl); 3685 DECODE_PRINTF(",1\n"); 3686 TRACE_AND_STEP(); 3687 destval = (*opcD0_byte_operation[rh]) (*destreg, 1); 3688 *destreg = destval; 3689 } 3690 DECODE_CLEAR_SEGOVR(); 3691 END_OF_INSTR(); 3692 } 3693 3694 /**************************************************************************** 3695 REMARKS: 3696 Handles opcode 0xd1 3697 ****************************************************************************/ 3698 void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1)) 3699 { 3700 int mod, rl, rh; 3701 uint destoffset; 3702 3703 /* 3704 * Yet another weirdo special case instruction format. Part of 3705 * the opcode held below in "RH". Doubly nested case would 3706 * result, except that the decoded instruction 3707 */ 3708 START_OF_INSTR(); 3709 FETCH_DECODE_MODRM(mod, rh, rl); 3710 #ifdef DEBUG 3711 if (DEBUG_DECODE()) { 3712 /* XXX DECODE_PRINTF may be changed to something more 3713 general, so that it is important to leave the strings 3714 in the same format, even though the result is that the 3715 above test is done twice. */ 3716 switch (rh) { 3717 case 0: 3718 DECODE_PRINTF("ROL\t"); 3719 break; 3720 case 1: 3721 DECODE_PRINTF("ROR\t"); 3722 break; 3723 case 2: 3724 DECODE_PRINTF("RCL\t"); 3725 break; 3726 case 3: 3727 DECODE_PRINTF("RCR\t"); 3728 break; 3729 case 4: 3730 DECODE_PRINTF("SHL\t"); 3731 break; 3732 case 5: 3733 DECODE_PRINTF("SHR\t"); 3734 break; 3735 case 6: 3736 DECODE_PRINTF("SAL\t"); 3737 break; 3738 case 7: 3739 DECODE_PRINTF("SAR\t"); 3740 break; 3741 } 3742 } 3743 #endif 3744 /* know operation, decode the mod byte to find the addressing 3745 mode. */ 3746 if (mod < 3) { 3747 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 3748 u32 destval; 3749 3750 DECODE_PRINTF("DWORD PTR "); 3751 destoffset = decode_rmXX_address(mod, rl); 3752 DECODE_PRINTF(",1\n"); 3753 destval = fetch_data_long(destoffset); 3754 TRACE_AND_STEP(); 3755 destval = (*opcD1_long_operation[rh]) (destval, 1); 3756 store_data_long(destoffset, destval); 3757 } else { 3758 u16 destval; 3759 3760 DECODE_PRINTF("WORD PTR "); 3761 destoffset = decode_rmXX_address(mod, rl); 3762 DECODE_PRINTF(",1\n"); 3763 destval = fetch_data_word(destoffset); 3764 TRACE_AND_STEP(); 3765 destval = (*opcD1_word_operation[rh]) (destval, 1); 3766 store_data_word(destoffset, destval); 3767 } 3768 } else { /* register to register */ 3769 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 3770 u32 destval; 3771 u32 *destreg; 3772 3773 destreg = DECODE_RM_LONG_REGISTER(rl); 3774 DECODE_PRINTF(",1\n"); 3775 TRACE_AND_STEP(); 3776 destval = (*opcD1_long_operation[rh]) (*destreg, 1); 3777 *destreg = destval; 3778 } else { 3779 u16 destval; 3780 u16 *destreg; 3781 3782 destreg = DECODE_RM_WORD_REGISTER(rl); 3783 DECODE_PRINTF(",1\n"); 3784 TRACE_AND_STEP(); 3785 destval = (*opcD1_word_operation[rh]) (*destreg, 1); 3786 *destreg = destval; 3787 } 3788 } 3789 DECODE_CLEAR_SEGOVR(); 3790 END_OF_INSTR(); 3791 } 3792 3793 /**************************************************************************** 3794 REMARKS: 3795 Handles opcode 0xd2 3796 ****************************************************************************/ 3797 void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1)) 3798 { 3799 int mod, rl, rh; 3800 u8 *destreg; 3801 uint destoffset; 3802 u8 destval; 3803 u8 amt; 3804 3805 /* 3806 * Yet another weirdo special case instruction format. Part of 3807 * the opcode held below in "RH". Doubly nested case would 3808 * result, except that the decoded instruction 3809 */ 3810 START_OF_INSTR(); 3811 FETCH_DECODE_MODRM(mod, rh, rl); 3812 #ifdef DEBUG 3813 if (DEBUG_DECODE()) { 3814 /* XXX DECODE_PRINTF may be changed to something more 3815 general, so that it is important to leave the strings 3816 in the same format, even though the result is that the 3817 above test is done twice. */ 3818 switch (rh) { 3819 case 0: 3820 DECODE_PRINTF("ROL\t"); 3821 break; 3822 case 1: 3823 DECODE_PRINTF("ROR\t"); 3824 break; 3825 case 2: 3826 DECODE_PRINTF("RCL\t"); 3827 break; 3828 case 3: 3829 DECODE_PRINTF("RCR\t"); 3830 break; 3831 case 4: 3832 DECODE_PRINTF("SHL\t"); 3833 break; 3834 case 5: 3835 DECODE_PRINTF("SHR\t"); 3836 break; 3837 case 6: 3838 DECODE_PRINTF("SAL\t"); 3839 break; 3840 case 7: 3841 DECODE_PRINTF("SAR\t"); 3842 break; 3843 } 3844 } 3845 #endif 3846 /* know operation, decode the mod byte to find the addressing 3847 mode. */ 3848 amt = M.x86.R_CL; 3849 if (mod < 3) { 3850 DECODE_PRINTF("BYTE PTR "); 3851 destoffset = decode_rmXX_address(mod, rl); 3852 DECODE_PRINTF(",CL\n"); 3853 destval = fetch_data_byte(destoffset); 3854 TRACE_AND_STEP(); 3855 destval = (*opcD0_byte_operation[rh]) (destval, amt); 3856 store_data_byte(destoffset, destval); 3857 } else { /* register to register */ 3858 destreg = DECODE_RM_BYTE_REGISTER(rl); 3859 DECODE_PRINTF(",CL\n"); 3860 TRACE_AND_STEP(); 3861 destval = (*opcD0_byte_operation[rh]) (*destreg, amt); 3862 *destreg = destval; 3863 } 3864 DECODE_CLEAR_SEGOVR(); 3865 END_OF_INSTR(); 3866 } 3867 3868 /**************************************************************************** 3869 REMARKS: 3870 Handles opcode 0xd3 3871 ****************************************************************************/ 3872 void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1)) 3873 { 3874 int mod, rl, rh; 3875 uint destoffset; 3876 u8 amt; 3877 3878 /* 3879 * Yet another weirdo special case instruction format. Part of 3880 * the opcode held below in "RH". Doubly nested case would 3881 * result, except that the decoded instruction 3882 */ 3883 START_OF_INSTR(); 3884 FETCH_DECODE_MODRM(mod, rh, rl); 3885 #ifdef DEBUG 3886 if (DEBUG_DECODE()) { 3887 /* XXX DECODE_PRINTF may be changed to something more 3888 general, so that it is important to leave the strings 3889 in the same format, even though the result is that the 3890 above test is done twice. */ 3891 switch (rh) { 3892 case 0: 3893 DECODE_PRINTF("ROL\t"); 3894 break; 3895 case 1: 3896 DECODE_PRINTF("ROR\t"); 3897 break; 3898 case 2: 3899 DECODE_PRINTF("RCL\t"); 3900 break; 3901 case 3: 3902 DECODE_PRINTF("RCR\t"); 3903 break; 3904 case 4: 3905 DECODE_PRINTF("SHL\t"); 3906 break; 3907 case 5: 3908 DECODE_PRINTF("SHR\t"); 3909 break; 3910 case 6: 3911 DECODE_PRINTF("SAL\t"); 3912 break; 3913 case 7: 3914 DECODE_PRINTF("SAR\t"); 3915 break; 3916 } 3917 } 3918 #endif 3919 /* know operation, decode the mod byte to find the addressing 3920 mode. */ 3921 amt = M.x86.R_CL; 3922 if (mod < 3) { 3923 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 3924 u32 destval; 3925 3926 DECODE_PRINTF("DWORD PTR "); 3927 destoffset = decode_rmXX_address(mod, rl); 3928 DECODE_PRINTF(",CL\n"); 3929 destval = fetch_data_long(destoffset); 3930 TRACE_AND_STEP(); 3931 destval = (*opcD1_long_operation[rh]) (destval, amt); 3932 store_data_long(destoffset, destval); 3933 } else { 3934 u16 destval; 3935 3936 DECODE_PRINTF("WORD PTR "); 3937 destoffset = decode_rmXX_address(mod, rl); 3938 DECODE_PRINTF(",CL\n"); 3939 destval = fetch_data_word(destoffset); 3940 TRACE_AND_STEP(); 3941 destval = (*opcD1_word_operation[rh]) (destval, amt); 3942 store_data_word(destoffset, destval); 3943 } 3944 } else { /* register to register */ 3945 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 3946 u32 *destreg; 3947 3948 destreg = DECODE_RM_LONG_REGISTER(rl); 3949 DECODE_PRINTF(",CL\n"); 3950 TRACE_AND_STEP(); 3951 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt); 3952 } else { 3953 u16 *destreg; 3954 3955 destreg = DECODE_RM_WORD_REGISTER(rl); 3956 DECODE_PRINTF(",CL\n"); 3957 TRACE_AND_STEP(); 3958 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt); 3959 } 3960 } 3961 DECODE_CLEAR_SEGOVR(); 3962 END_OF_INSTR(); 3963 } 3964 3965 /**************************************************************************** 3966 REMARKS: 3967 Handles opcode 0xd4 3968 ****************************************************************************/ 3969 void x86emuOp_aam(u8 X86EMU_UNUSED(op1)) 3970 { 3971 u8 a; 3972 3973 START_OF_INSTR(); 3974 DECODE_PRINTF("AAM\n"); 3975 a = fetch_byte_imm(); /* this is a stupid encoding. */ 3976 if (a != 10) { 3977 DECODE_PRINTF("ERROR DECODING AAM\n"); 3978 TRACE_REGS(); 3979 HALT_SYS(); 3980 } 3981 TRACE_AND_STEP(); 3982 /* note the type change here --- returning AL and AH in AX. */ 3983 M.x86.R_AX = aam_word(M.x86.R_AL); 3984 DECODE_CLEAR_SEGOVR(); 3985 END_OF_INSTR(); 3986 } 3987 3988 /**************************************************************************** 3989 REMARKS: 3990 Handles opcode 0xd5 3991 ****************************************************************************/ 3992 void x86emuOp_aad(u8 X86EMU_UNUSED(op1)) 3993 { 3994 u8 a; 3995 3996 START_OF_INSTR(); 3997 DECODE_PRINTF("AAD\n"); 3998 a = fetch_byte_imm(); 3999 TRACE_AND_STEP(); 4000 M.x86.R_AX = aad_word(M.x86.R_AX); 4001 DECODE_CLEAR_SEGOVR(); 4002 END_OF_INSTR(); 4003 } 4004 4005 /* opcode 0xd6 ILLEGAL OPCODE */ 4006 4007 /**************************************************************************** 4008 REMARKS: 4009 Handles opcode 0xd7 4010 ****************************************************************************/ 4011 void x86emuOp_xlat(u8 X86EMU_UNUSED(op1)) 4012 { 4013 u16 addr; 4014 4015 START_OF_INSTR(); 4016 DECODE_PRINTF("XLAT\n"); 4017 TRACE_AND_STEP(); 4018 addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL); 4019 M.x86.R_AL = fetch_data_byte(addr); 4020 DECODE_CLEAR_SEGOVR(); 4021 END_OF_INSTR(); 4022 } 4023 4024 /* instuctions D8 .. DF are in i87_ops.c */ 4025 4026 /**************************************************************************** 4027 REMARKS: 4028 Handles opcode 0xe0 4029 ****************************************************************************/ 4030 void x86emuOp_loopne(u8 X86EMU_UNUSED(op1)) 4031 { 4032 s16 ip; 4033 4034 START_OF_INSTR(); 4035 DECODE_PRINTF("LOOPNE\t"); 4036 ip = (s8) fetch_byte_imm(); 4037 ip += (s16) M.x86.R_IP; 4038 DECODE_PRINTF2("%04x\n", ip); 4039 TRACE_AND_STEP(); 4040 M.x86.R_CX -= 1; 4041 if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */ 4042 M.x86.R_IP = ip; 4043 DECODE_CLEAR_SEGOVR(); 4044 END_OF_INSTR(); 4045 } 4046 4047 /**************************************************************************** 4048 REMARKS: 4049 Handles opcode 0xe1 4050 ****************************************************************************/ 4051 void x86emuOp_loope(u8 X86EMU_UNUSED(op1)) 4052 { 4053 s16 ip; 4054 4055 START_OF_INSTR(); 4056 DECODE_PRINTF("LOOPE\t"); 4057 ip = (s8) fetch_byte_imm(); 4058 ip += (s16) M.x86.R_IP; 4059 DECODE_PRINTF2("%04x\n", ip); 4060 TRACE_AND_STEP(); 4061 M.x86.R_CX -= 1; 4062 if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */ 4063 M.x86.R_IP = ip; 4064 DECODE_CLEAR_SEGOVR(); 4065 END_OF_INSTR(); 4066 } 4067 4068 /**************************************************************************** 4069 REMARKS: 4070 Handles opcode 0xe2 4071 ****************************************************************************/ 4072 void x86emuOp_loop(u8 X86EMU_UNUSED(op1)) 4073 { 4074 s16 ip; 4075 4076 START_OF_INSTR(); 4077 DECODE_PRINTF("LOOP\t"); 4078 ip = (s8) fetch_byte_imm(); 4079 ip += (s16) M.x86.R_IP; 4080 DECODE_PRINTF2("%04x\n", ip); 4081 TRACE_AND_STEP(); 4082 M.x86.R_CX -= 1; 4083 if (M.x86.R_CX != 0) 4084 M.x86.R_IP = ip; 4085 DECODE_CLEAR_SEGOVR(); 4086 END_OF_INSTR(); 4087 } 4088 4089 /**************************************************************************** 4090 REMARKS: 4091 Handles opcode 0xe3 4092 ****************************************************************************/ 4093 void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1)) 4094 { 4095 u16 target; 4096 s8 offset; 4097 4098 /* jump to byte offset if overflow flag is set */ 4099 START_OF_INSTR(); 4100 DECODE_PRINTF("JCXZ\t"); 4101 offset = (s8)fetch_byte_imm(); 4102 target = (u16)(M.x86.R_IP + offset); 4103 DECODE_PRINTF2("%x\n", target); 4104 TRACE_AND_STEP(); 4105 if (M.x86.R_CX == 0) 4106 M.x86.R_IP = target; 4107 DECODE_CLEAR_SEGOVR(); 4108 END_OF_INSTR(); 4109 } 4110 4111 /**************************************************************************** 4112 REMARKS: 4113 Handles opcode 0xe4 4114 ****************************************************************************/ 4115 void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) 4116 { 4117 u8 port; 4118 4119 START_OF_INSTR(); 4120 DECODE_PRINTF("IN\t"); 4121 port = (u8) fetch_byte_imm(); 4122 DECODE_PRINTF2("%x,AL\n", port); 4123 TRACE_AND_STEP(); 4124 M.x86.R_AL = (*sys_inb)(port); 4125 DECODE_CLEAR_SEGOVR(); 4126 END_OF_INSTR(); 4127 } 4128 4129 /**************************************************************************** 4130 REMARKS: 4131 Handles opcode 0xe5 4132 ****************************************************************************/ 4133 void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1)) 4134 { 4135 u8 port; 4136 4137 START_OF_INSTR(); 4138 DECODE_PRINTF("IN\t"); 4139 port = (u8) fetch_byte_imm(); 4140 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4141 DECODE_PRINTF2("EAX,%x\n", port); 4142 } else { 4143 DECODE_PRINTF2("AX,%x\n", port); 4144 } 4145 TRACE_AND_STEP(); 4146 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4147 M.x86.R_EAX = (*sys_inl)(port); 4148 } else { 4149 M.x86.R_AX = (*sys_inw)(port); 4150 } 4151 DECODE_CLEAR_SEGOVR(); 4152 END_OF_INSTR(); 4153 } 4154 4155 /**************************************************************************** 4156 REMARKS: 4157 Handles opcode 0xe6 4158 ****************************************************************************/ 4159 void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1)) 4160 { 4161 u8 port; 4162 4163 START_OF_INSTR(); 4164 DECODE_PRINTF("OUT\t"); 4165 port = (u8) fetch_byte_imm(); 4166 DECODE_PRINTF2("%x,AL\n", port); 4167 TRACE_AND_STEP(); 4168 (*sys_outb)(port, M.x86.R_AL); 4169 DECODE_CLEAR_SEGOVR(); 4170 END_OF_INSTR(); 4171 } 4172 4173 /**************************************************************************** 4174 REMARKS: 4175 Handles opcode 0xe7 4176 ****************************************************************************/ 4177 void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1)) 4178 { 4179 u8 port; 4180 4181 START_OF_INSTR(); 4182 DECODE_PRINTF("OUT\t"); 4183 port = (u8) fetch_byte_imm(); 4184 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4185 DECODE_PRINTF2("%x,EAX\n", port); 4186 } else { 4187 DECODE_PRINTF2("%x,AX\n", port); 4188 } 4189 TRACE_AND_STEP(); 4190 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4191 (*sys_outl)(port, M.x86.R_EAX); 4192 } else { 4193 (*sys_outw)(port, M.x86.R_AX); 4194 } 4195 DECODE_CLEAR_SEGOVR(); 4196 END_OF_INSTR(); 4197 } 4198 4199 /**************************************************************************** 4200 REMARKS: 4201 Handles opcode 0xe8 4202 ****************************************************************************/ 4203 void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1)) 4204 { 4205 s16 ip; 4206 4207 START_OF_INSTR(); 4208 DECODE_PRINTF("CALL\t"); 4209 ip = (s16) fetch_word_imm(); 4210 ip += (s16) M.x86.R_IP; /* CHECK SIGN */ 4211 DECODE_PRINTF2("%04x\n", ip); 4212 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, ""); 4213 TRACE_AND_STEP(); 4214 push_word(M.x86.R_IP); 4215 M.x86.R_IP = ip; 4216 DECODE_CLEAR_SEGOVR(); 4217 END_OF_INSTR(); 4218 } 4219 4220 /**************************************************************************** 4221 REMARKS: 4222 Handles opcode 0xe9 4223 ****************************************************************************/ 4224 void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1)) 4225 { 4226 int ip; 4227 4228 START_OF_INSTR(); 4229 DECODE_PRINTF("JMP\t"); 4230 ip = (s16)fetch_word_imm(); 4231 ip += (s16)M.x86.R_IP; 4232 DECODE_PRINTF2("%04x\n", ip); 4233 TRACE_AND_STEP(); 4234 M.x86.R_IP = (u16)ip; 4235 DECODE_CLEAR_SEGOVR(); 4236 END_OF_INSTR(); 4237 } 4238 4239 /**************************************************************************** 4240 REMARKS: 4241 Handles opcode 0xea 4242 ****************************************************************************/ 4243 void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1)) 4244 { 4245 u16 cs, ip; 4246 4247 START_OF_INSTR(); 4248 DECODE_PRINTF("JMP\tFAR "); 4249 ip = fetch_word_imm(); 4250 cs = fetch_word_imm(); 4251 DECODE_PRINTF2("%04x:", cs); 4252 DECODE_PRINTF2("%04x\n", ip); 4253 TRACE_AND_STEP(); 4254 M.x86.R_IP = ip; 4255 M.x86.R_CS = cs; 4256 DECODE_CLEAR_SEGOVR(); 4257 END_OF_INSTR(); 4258 } 4259 4260 /**************************************************************************** 4261 REMARKS: 4262 Handles opcode 0xeb 4263 ****************************************************************************/ 4264 void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1)) 4265 { 4266 u16 target; 4267 s8 offset; 4268 4269 START_OF_INSTR(); 4270 DECODE_PRINTF("JMP\t"); 4271 offset = (s8)fetch_byte_imm(); 4272 target = (u16)(M.x86.R_IP + offset); 4273 DECODE_PRINTF2("%x\n", target); 4274 TRACE_AND_STEP(); 4275 M.x86.R_IP = target; 4276 DECODE_CLEAR_SEGOVR(); 4277 END_OF_INSTR(); 4278 } 4279 4280 /**************************************************************************** 4281 REMARKS: 4282 Handles opcode 0xec 4283 ****************************************************************************/ 4284 void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1)) 4285 { 4286 START_OF_INSTR(); 4287 DECODE_PRINTF("IN\tAL,DX\n"); 4288 TRACE_AND_STEP(); 4289 M.x86.R_AL = (*sys_inb)(M.x86.R_DX); 4290 DECODE_CLEAR_SEGOVR(); 4291 END_OF_INSTR(); 4292 } 4293 4294 /**************************************************************************** 4295 REMARKS: 4296 Handles opcode 0xed 4297 ****************************************************************************/ 4298 void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1)) 4299 { 4300 START_OF_INSTR(); 4301 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4302 DECODE_PRINTF("IN\tEAX,DX\n"); 4303 } else { 4304 DECODE_PRINTF("IN\tAX,DX\n"); 4305 } 4306 TRACE_AND_STEP(); 4307 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4308 M.x86.R_EAX = (*sys_inl)(M.x86.R_DX); 4309 } else { 4310 M.x86.R_AX = (*sys_inw)(M.x86.R_DX); 4311 } 4312 DECODE_CLEAR_SEGOVR(); 4313 END_OF_INSTR(); 4314 } 4315 4316 /**************************************************************************** 4317 REMARKS: 4318 Handles opcode 0xee 4319 ****************************************************************************/ 4320 void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1)) 4321 { 4322 START_OF_INSTR(); 4323 DECODE_PRINTF("OUT\tDX,AL\n"); 4324 TRACE_AND_STEP(); 4325 (*sys_outb)(M.x86.R_DX, M.x86.R_AL); 4326 DECODE_CLEAR_SEGOVR(); 4327 END_OF_INSTR(); 4328 } 4329 4330 /**************************************************************************** 4331 REMARKS: 4332 Handles opcode 0xef 4333 ****************************************************************************/ 4334 void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1)) 4335 { 4336 START_OF_INSTR(); 4337 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4338 DECODE_PRINTF("OUT\tDX,EAX\n"); 4339 } else { 4340 DECODE_PRINTF("OUT\tDX,AX\n"); 4341 } 4342 TRACE_AND_STEP(); 4343 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4344 (*sys_outl)(M.x86.R_DX, M.x86.R_EAX); 4345 } else { 4346 (*sys_outw)(M.x86.R_DX, M.x86.R_AX); 4347 } 4348 DECODE_CLEAR_SEGOVR(); 4349 END_OF_INSTR(); 4350 } 4351 4352 /**************************************************************************** 4353 REMARKS: 4354 Handles opcode 0xf0 4355 ****************************************************************************/ 4356 void x86emuOp_lock(u8 X86EMU_UNUSED(op1)) 4357 { 4358 START_OF_INSTR(); 4359 DECODE_PRINTF("LOCK:\n"); 4360 TRACE_AND_STEP(); 4361 DECODE_CLEAR_SEGOVR(); 4362 END_OF_INSTR(); 4363 } 4364 4365 /*opcode 0xf1 ILLEGAL OPERATION */ 4366 4367 /**************************************************************************** 4368 REMARKS: 4369 Handles opcode 0xf2 4370 ****************************************************************************/ 4371 void x86emuOp_repne(u8 X86EMU_UNUSED(op1)) 4372 { 4373 START_OF_INSTR(); 4374 DECODE_PRINTF("REPNE\n"); 4375 TRACE_AND_STEP(); 4376 M.x86.mode |= SYSMODE_PREFIX_REPNE; 4377 DECODE_CLEAR_SEGOVR(); 4378 END_OF_INSTR(); 4379 } 4380 4381 /**************************************************************************** 4382 REMARKS: 4383 Handles opcode 0xf3 4384 ****************************************************************************/ 4385 void x86emuOp_repe(u8 X86EMU_UNUSED(op1)) 4386 { 4387 START_OF_INSTR(); 4388 DECODE_PRINTF("REPE\n"); 4389 TRACE_AND_STEP(); 4390 M.x86.mode |= SYSMODE_PREFIX_REPE; 4391 DECODE_CLEAR_SEGOVR(); 4392 END_OF_INSTR(); 4393 } 4394 4395 /**************************************************************************** 4396 REMARKS: 4397 Handles opcode 0xf4 4398 ****************************************************************************/ 4399 void x86emuOp_halt(u8 X86EMU_UNUSED(op1)) 4400 { 4401 START_OF_INSTR(); 4402 DECODE_PRINTF("HALT\n"); 4403 TRACE_AND_STEP(); 4404 HALT_SYS(); 4405 DECODE_CLEAR_SEGOVR(); 4406 END_OF_INSTR(); 4407 } 4408 4409 /**************************************************************************** 4410 REMARKS: 4411 Handles opcode 0xf5 4412 ****************************************************************************/ 4413 void x86emuOp_cmc(u8 X86EMU_UNUSED(op1)) 4414 { 4415 /* complement the carry flag. */ 4416 START_OF_INSTR(); 4417 DECODE_PRINTF("CMC\n"); 4418 TRACE_AND_STEP(); 4419 TOGGLE_FLAG(F_CF); 4420 DECODE_CLEAR_SEGOVR(); 4421 END_OF_INSTR(); 4422 } 4423 4424 /**************************************************************************** 4425 REMARKS: 4426 Handles opcode 0xf6 4427 ****************************************************************************/ 4428 void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1)) 4429 { 4430 int mod, rl, rh; 4431 u8 *destreg; 4432 uint destoffset; 4433 u8 destval, srcval; 4434 4435 /* long, drawn out code follows. Double switch for a total 4436 of 32 cases. */ 4437 START_OF_INSTR(); 4438 FETCH_DECODE_MODRM(mod, rh, rl); 4439 DECODE_PRINTF(opF6_names[rh]); 4440 if (mod < 3) { 4441 DECODE_PRINTF("BYTE PTR "); 4442 destoffset = decode_rmXX_address(mod, rl); 4443 destval = fetch_data_byte(destoffset); 4444 4445 switch (rh) { 4446 case 0: /* test byte imm */ 4447 DECODE_PRINTF(","); 4448 srcval = fetch_byte_imm(); 4449 DECODE_PRINTF2("%02x\n", srcval); 4450 TRACE_AND_STEP(); 4451 test_byte(destval, srcval); 4452 break; 4453 case 1: 4454 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); 4455 HALT_SYS(); 4456 break; 4457 case 2: 4458 DECODE_PRINTF("\n"); 4459 TRACE_AND_STEP(); 4460 destval = not_byte(destval); 4461 store_data_byte(destoffset, destval); 4462 break; 4463 case 3: 4464 DECODE_PRINTF("\n"); 4465 TRACE_AND_STEP(); 4466 destval = neg_byte(destval); 4467 store_data_byte(destoffset, destval); 4468 break; 4469 case 4: 4470 DECODE_PRINTF("\n"); 4471 TRACE_AND_STEP(); 4472 mul_byte(destval); 4473 break; 4474 case 5: 4475 DECODE_PRINTF("\n"); 4476 TRACE_AND_STEP(); 4477 imul_byte(destval); 4478 break; 4479 case 6: 4480 DECODE_PRINTF("\n"); 4481 TRACE_AND_STEP(); 4482 div_byte(destval); 4483 break; 4484 default: 4485 DECODE_PRINTF("\n"); 4486 TRACE_AND_STEP(); 4487 idiv_byte(destval); 4488 break; 4489 } 4490 } else { /* mod=11 */ 4491 destreg = DECODE_RM_BYTE_REGISTER(rl); 4492 switch (rh) { 4493 case 0: /* test byte imm */ 4494 DECODE_PRINTF(","); 4495 srcval = fetch_byte_imm(); 4496 DECODE_PRINTF2("%02x\n", srcval); 4497 TRACE_AND_STEP(); 4498 test_byte(*destreg, srcval); 4499 break; 4500 case 1: 4501 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); 4502 HALT_SYS(); 4503 break; 4504 case 2: 4505 DECODE_PRINTF("\n"); 4506 TRACE_AND_STEP(); 4507 *destreg = not_byte(*destreg); 4508 break; 4509 case 3: 4510 DECODE_PRINTF("\n"); 4511 TRACE_AND_STEP(); 4512 *destreg = neg_byte(*destreg); 4513 break; 4514 case 4: 4515 DECODE_PRINTF("\n"); 4516 TRACE_AND_STEP(); 4517 mul_byte(*destreg); /*!!! */ 4518 break; 4519 case 5: 4520 DECODE_PRINTF("\n"); 4521 TRACE_AND_STEP(); 4522 imul_byte(*destreg); 4523 break; 4524 case 6: 4525 DECODE_PRINTF("\n"); 4526 TRACE_AND_STEP(); 4527 div_byte(*destreg); 4528 break; 4529 default: 4530 DECODE_PRINTF("\n"); 4531 TRACE_AND_STEP(); 4532 idiv_byte(*destreg); 4533 break; 4534 } 4535 } 4536 DECODE_CLEAR_SEGOVR(); 4537 END_OF_INSTR(); 4538 } 4539 4540 /**************************************************************************** 4541 REMARKS: 4542 Handles opcode 0xf7 4543 ****************************************************************************/ 4544 void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1)) 4545 { 4546 int mod, rl, rh; 4547 uint destoffset; 4548 4549 START_OF_INSTR(); 4550 FETCH_DECODE_MODRM(mod, rh, rl); 4551 DECODE_PRINTF(opF6_names[rh]); 4552 if (mod < 3) { 4553 4554 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4555 u32 destval, srcval; 4556 4557 DECODE_PRINTF("DWORD PTR "); 4558 destoffset = decode_rmXX_address(mod, rl); 4559 destval = fetch_data_long(destoffset); 4560 4561 switch (rh) { 4562 case 0: 4563 DECODE_PRINTF(","); 4564 srcval = fetch_long_imm(); 4565 DECODE_PRINTF2("%x\n", srcval); 4566 TRACE_AND_STEP(); 4567 test_long(destval, srcval); 4568 break; 4569 case 1: 4570 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n"); 4571 HALT_SYS(); 4572 break; 4573 case 2: 4574 DECODE_PRINTF("\n"); 4575 TRACE_AND_STEP(); 4576 destval = not_long(destval); 4577 store_data_long(destoffset, destval); 4578 break; 4579 case 3: 4580 DECODE_PRINTF("\n"); 4581 TRACE_AND_STEP(); 4582 destval = neg_long(destval); 4583 store_data_long(destoffset, destval); 4584 break; 4585 case 4: 4586 DECODE_PRINTF("\n"); 4587 TRACE_AND_STEP(); 4588 mul_long(destval); 4589 break; 4590 case 5: 4591 DECODE_PRINTF("\n"); 4592 TRACE_AND_STEP(); 4593 imul_long(destval); 4594 break; 4595 case 6: 4596 DECODE_PRINTF("\n"); 4597 TRACE_AND_STEP(); 4598 div_long(destval); 4599 break; 4600 case 7: 4601 DECODE_PRINTF("\n"); 4602 TRACE_AND_STEP(); 4603 idiv_long(destval); 4604 break; 4605 } 4606 } else { 4607 u16 destval, srcval; 4608 4609 DECODE_PRINTF("WORD PTR "); 4610 destoffset = decode_rmXX_address(mod, rl); 4611 destval = fetch_data_word(destoffset); 4612 4613 switch (rh) { 4614 case 0: /* test word imm */ 4615 DECODE_PRINTF(","); 4616 srcval = fetch_word_imm(); 4617 DECODE_PRINTF2("%x\n", srcval); 4618 TRACE_AND_STEP(); 4619 test_word(destval, srcval); 4620 break; 4621 case 1: 4622 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n"); 4623 HALT_SYS(); 4624 break; 4625 case 2: 4626 DECODE_PRINTF("\n"); 4627 TRACE_AND_STEP(); 4628 destval = not_word(destval); 4629 store_data_word(destoffset, destval); 4630 break; 4631 case 3: 4632 DECODE_PRINTF("\n"); 4633 TRACE_AND_STEP(); 4634 destval = neg_word(destval); 4635 store_data_word(destoffset, destval); 4636 break; 4637 case 4: 4638 DECODE_PRINTF("\n"); 4639 TRACE_AND_STEP(); 4640 mul_word(destval); 4641 break; 4642 case 5: 4643 DECODE_PRINTF("\n"); 4644 TRACE_AND_STEP(); 4645 imul_word(destval); 4646 break; 4647 case 6: 4648 DECODE_PRINTF("\n"); 4649 TRACE_AND_STEP(); 4650 div_word(destval); 4651 break; 4652 case 7: 4653 DECODE_PRINTF("\n"); 4654 TRACE_AND_STEP(); 4655 idiv_word(destval); 4656 break; 4657 } 4658 } 4659 4660 } else { /* mod=11 */ 4661 4662 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4663 u32 *destreg; 4664 u32 srcval; 4665 4666 destreg = DECODE_RM_LONG_REGISTER(rl); 4667 4668 switch (rh) { 4669 case 0: /* test word imm */ 4670 DECODE_PRINTF(","); 4671 srcval = fetch_long_imm(); 4672 DECODE_PRINTF2("%x\n", srcval); 4673 TRACE_AND_STEP(); 4674 test_long(*destreg, srcval); 4675 break; 4676 case 1: 4677 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); 4678 HALT_SYS(); 4679 break; 4680 case 2: 4681 DECODE_PRINTF("\n"); 4682 TRACE_AND_STEP(); 4683 *destreg = not_long(*destreg); 4684 break; 4685 case 3: 4686 DECODE_PRINTF("\n"); 4687 TRACE_AND_STEP(); 4688 *destreg = neg_long(*destreg); 4689 break; 4690 case 4: 4691 DECODE_PRINTF("\n"); 4692 TRACE_AND_STEP(); 4693 mul_long(*destreg); /*!!! */ 4694 break; 4695 case 5: 4696 DECODE_PRINTF("\n"); 4697 TRACE_AND_STEP(); 4698 imul_long(*destreg); 4699 break; 4700 case 6: 4701 DECODE_PRINTF("\n"); 4702 TRACE_AND_STEP(); 4703 div_long(*destreg); 4704 break; 4705 case 7: 4706 DECODE_PRINTF("\n"); 4707 TRACE_AND_STEP(); 4708 idiv_long(*destreg); 4709 break; 4710 } 4711 } else { 4712 u16 *destreg; 4713 u16 srcval; 4714 4715 destreg = DECODE_RM_WORD_REGISTER(rl); 4716 4717 switch (rh) { 4718 case 0: /* test word imm */ 4719 DECODE_PRINTF(","); 4720 srcval = fetch_word_imm(); 4721 DECODE_PRINTF2("%x\n", srcval); 4722 TRACE_AND_STEP(); 4723 test_word(*destreg, srcval); 4724 break; 4725 case 1: 4726 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); 4727 HALT_SYS(); 4728 break; 4729 case 2: 4730 DECODE_PRINTF("\n"); 4731 TRACE_AND_STEP(); 4732 *destreg = not_word(*destreg); 4733 break; 4734 case 3: 4735 DECODE_PRINTF("\n"); 4736 TRACE_AND_STEP(); 4737 *destreg = neg_word(*destreg); 4738 break; 4739 case 4: 4740 DECODE_PRINTF("\n"); 4741 TRACE_AND_STEP(); 4742 mul_word(*destreg); /*!!! */ 4743 break; 4744 case 5: 4745 DECODE_PRINTF("\n"); 4746 TRACE_AND_STEP(); 4747 imul_word(*destreg); 4748 break; 4749 case 6: 4750 DECODE_PRINTF("\n"); 4751 TRACE_AND_STEP(); 4752 div_word(*destreg); 4753 break; 4754 case 7: 4755 DECODE_PRINTF("\n"); 4756 TRACE_AND_STEP(); 4757 idiv_word(*destreg); 4758 break; 4759 } 4760 } 4761 } 4762 DECODE_CLEAR_SEGOVR(); 4763 END_OF_INSTR(); 4764 } 4765 4766 /**************************************************************************** 4767 REMARKS: 4768 Handles opcode 0xf8 4769 ****************************************************************************/ 4770 void x86emuOp_clc(u8 X86EMU_UNUSED(op1)) 4771 { 4772 /* clear the carry flag. */ 4773 START_OF_INSTR(); 4774 DECODE_PRINTF("CLC\n"); 4775 TRACE_AND_STEP(); 4776 CLEAR_FLAG(F_CF); 4777 DECODE_CLEAR_SEGOVR(); 4778 END_OF_INSTR(); 4779 } 4780 4781 /**************************************************************************** 4782 REMARKS: 4783 Handles opcode 0xf9 4784 ****************************************************************************/ 4785 void x86emuOp_stc(u8 X86EMU_UNUSED(op1)) 4786 { 4787 /* set the carry flag. */ 4788 START_OF_INSTR(); 4789 DECODE_PRINTF("STC\n"); 4790 TRACE_AND_STEP(); 4791 SET_FLAG(F_CF); 4792 DECODE_CLEAR_SEGOVR(); 4793 END_OF_INSTR(); 4794 } 4795 4796 /**************************************************************************** 4797 REMARKS: 4798 Handles opcode 0xfa 4799 ****************************************************************************/ 4800 void x86emuOp_cli(u8 X86EMU_UNUSED(op1)) 4801 { 4802 /* clear interrupts. */ 4803 START_OF_INSTR(); 4804 DECODE_PRINTF("CLI\n"); 4805 TRACE_AND_STEP(); 4806 CLEAR_FLAG(F_IF); 4807 DECODE_CLEAR_SEGOVR(); 4808 END_OF_INSTR(); 4809 } 4810 4811 /**************************************************************************** 4812 REMARKS: 4813 Handles opcode 0xfb 4814 ****************************************************************************/ 4815 void x86emuOp_sti(u8 X86EMU_UNUSED(op1)) 4816 { 4817 /* enable interrupts. */ 4818 START_OF_INSTR(); 4819 DECODE_PRINTF("STI\n"); 4820 TRACE_AND_STEP(); 4821 SET_FLAG(F_IF); 4822 DECODE_CLEAR_SEGOVR(); 4823 END_OF_INSTR(); 4824 } 4825 4826 /**************************************************************************** 4827 REMARKS: 4828 Handles opcode 0xfc 4829 ****************************************************************************/ 4830 void x86emuOp_cld(u8 X86EMU_UNUSED(op1)) 4831 { 4832 /* clear interrupts. */ 4833 START_OF_INSTR(); 4834 DECODE_PRINTF("CLD\n"); 4835 TRACE_AND_STEP(); 4836 CLEAR_FLAG(F_DF); 4837 DECODE_CLEAR_SEGOVR(); 4838 END_OF_INSTR(); 4839 } 4840 4841 /**************************************************************************** 4842 REMARKS: 4843 Handles opcode 0xfd 4844 ****************************************************************************/ 4845 void x86emuOp_std(u8 X86EMU_UNUSED(op1)) 4846 { 4847 /* clear interrupts. */ 4848 START_OF_INSTR(); 4849 DECODE_PRINTF("STD\n"); 4850 TRACE_AND_STEP(); 4851 SET_FLAG(F_DF); 4852 DECODE_CLEAR_SEGOVR(); 4853 END_OF_INSTR(); 4854 } 4855 4856 /**************************************************************************** 4857 REMARKS: 4858 Handles opcode 0xfe 4859 ****************************************************************************/ 4860 void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1)) 4861 { 4862 int mod, rh, rl; 4863 u8 destval; 4864 uint destoffset; 4865 u8 *destreg; 4866 4867 /* Yet another special case instruction. */ 4868 START_OF_INSTR(); 4869 FETCH_DECODE_MODRM(mod, rh, rl); 4870 #ifdef DEBUG 4871 if (DEBUG_DECODE()) { 4872 /* XXX DECODE_PRINTF may be changed to something more 4873 general, so that it is important to leave the strings 4874 in the same format, even though the result is that the 4875 above test is done twice. */ 4876 4877 switch (rh) { 4878 case 0: 4879 DECODE_PRINTF("INC\t"); 4880 break; 4881 case 1: 4882 DECODE_PRINTF("DEC\t"); 4883 break; 4884 case 2: 4885 case 3: 4886 case 4: 4887 case 5: 4888 case 6: 4889 case 7: 4890 DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod); 4891 HALT_SYS(); 4892 break; 4893 } 4894 } 4895 #endif 4896 if (mod < 3) { 4897 DECODE_PRINTF("BYTE PTR "); 4898 destoffset = decode_rmXX_address(mod, rl); 4899 DECODE_PRINTF("\n"); 4900 destval = fetch_data_byte(destoffset); 4901 TRACE_AND_STEP(); 4902 if (rh == 0) 4903 destval = inc_byte(destval); 4904 else 4905 destval = dec_byte(destval); 4906 store_data_byte(destoffset, destval); 4907 } else { 4908 destreg = DECODE_RM_BYTE_REGISTER(rl); 4909 DECODE_PRINTF("\n"); 4910 TRACE_AND_STEP(); 4911 if (rh == 0) 4912 *destreg = inc_byte(*destreg); 4913 else 4914 *destreg = dec_byte(*destreg); 4915 } 4916 DECODE_CLEAR_SEGOVR(); 4917 END_OF_INSTR(); 4918 } 4919 4920 /**************************************************************************** 4921 REMARKS: 4922 Handles opcode 0xff 4923 ****************************************************************************/ 4924 void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1)) 4925 { 4926 int mod, rh, rl; 4927 uint destoffset = 0; 4928 u16 *destreg; 4929 u16 destval,destval2; 4930 4931 /* Yet another special case instruction. */ 4932 START_OF_INSTR(); 4933 FETCH_DECODE_MODRM(mod, rh, rl); 4934 #ifdef DEBUG 4935 if (DEBUG_DECODE()) { 4936 /* XXX DECODE_PRINTF may be changed to something more 4937 general, so that it is important to leave the strings 4938 in the same format, even though the result is that the 4939 above test is done twice. */ 4940 4941 switch (rh) { 4942 case 0: 4943 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4944 DECODE_PRINTF("INC\tDWORD PTR "); 4945 } else { 4946 DECODE_PRINTF("INC\tWORD PTR "); 4947 } 4948 break; 4949 case 1: 4950 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4951 DECODE_PRINTF("DEC\tDWORD PTR "); 4952 } else { 4953 DECODE_PRINTF("DEC\tWORD PTR "); 4954 } 4955 break; 4956 case 2: 4957 DECODE_PRINTF("CALL\t "); 4958 break; 4959 case 3: 4960 DECODE_PRINTF("CALL\tFAR "); 4961 break; 4962 case 4: 4963 DECODE_PRINTF("JMP\t"); 4964 break; 4965 case 5: 4966 DECODE_PRINTF("JMP\tFAR "); 4967 break; 4968 case 6: 4969 DECODE_PRINTF("PUSH\t"); 4970 break; 4971 case 7: 4972 DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t"); 4973 HALT_SYS(); 4974 break; 4975 } 4976 } 4977 #endif 4978 if (mod < 3) { 4979 destoffset = decode_rmXX_address(mod, rl); 4980 DECODE_PRINTF("\n"); 4981 switch (rh) { 4982 case 0: /* inc word ptr ... */ 4983 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4984 u32 destval; 4985 4986 destval = fetch_data_long(destoffset); 4987 TRACE_AND_STEP(); 4988 destval = inc_long(destval); 4989 store_data_long(destoffset, destval); 4990 } else { 4991 u16 destval; 4992 4993 destval = fetch_data_word(destoffset); 4994 TRACE_AND_STEP(); 4995 destval = inc_word(destval); 4996 store_data_word(destoffset, destval); 4997 } 4998 break; 4999 case 1: /* dec word ptr ... */ 5000 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 5001 u32 destval; 5002 5003 destval = fetch_data_long(destoffset); 5004 TRACE_AND_STEP(); 5005 destval = dec_long(destval); 5006 store_data_long(destoffset, destval); 5007 } else { 5008 u16 destval; 5009 5010 destval = fetch_data_word(destoffset); 5011 TRACE_AND_STEP(); 5012 destval = dec_word(destval); 5013 store_data_word(destoffset, destval); 5014 } 5015 break; 5016 case 2: /* call word ptr ... */ 5017 destval = fetch_data_word(destoffset); 5018 TRACE_AND_STEP(); 5019 push_word(M.x86.R_IP); 5020 M.x86.R_IP = destval; 5021 break; 5022 case 3: /* call far ptr ... */ 5023 destval = fetch_data_word(destoffset); 5024 destval2 = fetch_data_word(destoffset + 2); 5025 TRACE_AND_STEP(); 5026 push_word(M.x86.R_CS); 5027 M.x86.R_CS = destval2; 5028 push_word(M.x86.R_IP); 5029 M.x86.R_IP = destval; 5030 break; 5031 case 4: /* jmp word ptr ... */ 5032 destval = fetch_data_word(destoffset); 5033 TRACE_AND_STEP(); 5034 M.x86.R_IP = destval; 5035 break; 5036 case 5: /* jmp far ptr ... */ 5037 destval = fetch_data_word(destoffset); 5038 destval2 = fetch_data_word(destoffset + 2); 5039 TRACE_AND_STEP(); 5040 M.x86.R_IP = destval; 5041 M.x86.R_CS = destval2; 5042 break; 5043 case 6: /* push word ptr ... */ 5044 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 5045 u32 destval; 5046 5047 destval = fetch_data_long(destoffset); 5048 TRACE_AND_STEP(); 5049 push_long(destval); 5050 } else { 5051 u16 destval; 5052 5053 destval = fetch_data_word(destoffset); 5054 TRACE_AND_STEP(); 5055 push_word(destval); 5056 } 5057 break; 5058 } 5059 } else { 5060 switch (rh) { 5061 case 0: 5062 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 5063 u32 *destreg; 5064 5065 destreg = DECODE_RM_LONG_REGISTER(rl); 5066 DECODE_PRINTF("\n"); 5067 TRACE_AND_STEP(); 5068 *destreg = inc_long(*destreg); 5069 } else { 5070 u16 *destreg; 5071 5072 destreg = DECODE_RM_WORD_REGISTER(rl); 5073 DECODE_PRINTF("\n"); 5074 TRACE_AND_STEP(); 5075 *destreg = inc_word(*destreg); 5076 } 5077 break; 5078 case 1: 5079 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 5080 u32 *destreg; 5081 5082 destreg = DECODE_RM_LONG_REGISTER(rl); 5083 DECODE_PRINTF("\n"); 5084 TRACE_AND_STEP(); 5085 *destreg = dec_long(*destreg); 5086 } else { 5087 u16 *destreg; 5088 5089 destreg = DECODE_RM_WORD_REGISTER(rl); 5090 DECODE_PRINTF("\n"); 5091 TRACE_AND_STEP(); 5092 *destreg = dec_word(*destreg); 5093 } 5094 break; 5095 case 2: /* call word ptr ... */ 5096 destreg = DECODE_RM_WORD_REGISTER(rl); 5097 DECODE_PRINTF("\n"); 5098 TRACE_AND_STEP(); 5099 push_word(M.x86.R_IP); 5100 M.x86.R_IP = *destreg; 5101 break; 5102 case 3: /* jmp far ptr ... */ 5103 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n"); 5104 TRACE_AND_STEP(); 5105 HALT_SYS(); 5106 break; 5107 5108 case 4: /* jmp ... */ 5109 destreg = DECODE_RM_WORD_REGISTER(rl); 5110 DECODE_PRINTF("\n"); 5111 TRACE_AND_STEP(); 5112 M.x86.R_IP = (u16) (*destreg); 5113 break; 5114 case 5: /* jmp far ptr ... */ 5115 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n"); 5116 TRACE_AND_STEP(); 5117 HALT_SYS(); 5118 break; 5119 case 6: 5120 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 5121 u32 *destreg; 5122 5123 destreg = DECODE_RM_LONG_REGISTER(rl); 5124 DECODE_PRINTF("\n"); 5125 TRACE_AND_STEP(); 5126 push_long(*destreg); 5127 } else { 5128 u16 *destreg; 5129 5130 destreg = DECODE_RM_WORD_REGISTER(rl); 5131 DECODE_PRINTF("\n"); 5132 TRACE_AND_STEP(); 5133 push_word(*destreg); 5134 } 5135 break; 5136 } 5137 } 5138 DECODE_CLEAR_SEGOVR(); 5139 END_OF_INSTR(); 5140 } 5141 5142 /*************************************************************************** 5143 * Single byte operation code table: 5144 **************************************************************************/ 5145 void (*x86emu_optab[256])(u8) __attribute__ ((section(".got2"))) = 5146 { 5147 /* 0x00 */ x86emuOp_genop_byte_RM_R, 5148 /* 0x01 */ x86emuOp_genop_word_RM_R, 5149 /* 0x02 */ x86emuOp_genop_byte_R_RM, 5150 /* 0x03 */ x86emuOp_genop_word_R_RM, 5151 /* 0x04 */ x86emuOp_genop_byte_AL_IMM, 5152 /* 0x05 */ x86emuOp_genop_word_AX_IMM, 5153 /* 0x06 */ x86emuOp_push_ES, 5154 /* 0x07 */ x86emuOp_pop_ES, 5155 5156 /* 0x08 */ x86emuOp_genop_byte_RM_R, 5157 /* 0x09 */ x86emuOp_genop_word_RM_R, 5158 /* 0x0a */ x86emuOp_genop_byte_R_RM, 5159 /* 0x0b */ x86emuOp_genop_word_R_RM, 5160 /* 0x0c */ x86emuOp_genop_byte_AL_IMM, 5161 /* 0x0d */ x86emuOp_genop_word_AX_IMM, 5162 /* 0x0e */ x86emuOp_push_CS, 5163 /* 0x0f */ x86emuOp_two_byte, 5164 5165 /* 0x10 */ x86emuOp_genop_byte_RM_R, 5166 /* 0x11 */ x86emuOp_genop_word_RM_R, 5167 /* 0x12 */ x86emuOp_genop_byte_R_RM, 5168 /* 0x13 */ x86emuOp_genop_word_R_RM, 5169 /* 0x14 */ x86emuOp_genop_byte_AL_IMM, 5170 /* 0x15 */ x86emuOp_genop_word_AX_IMM, 5171 /* 0x16 */ x86emuOp_push_SS, 5172 /* 0x17 */ x86emuOp_pop_SS, 5173 5174 /* 0x18 */ x86emuOp_genop_byte_RM_R, 5175 /* 0x19 */ x86emuOp_genop_word_RM_R, 5176 /* 0x1a */ x86emuOp_genop_byte_R_RM, 5177 /* 0x1b */ x86emuOp_genop_word_R_RM, 5178 /* 0x1c */ x86emuOp_genop_byte_AL_IMM, 5179 /* 0x1d */ x86emuOp_genop_word_AX_IMM, 5180 /* 0x1e */ x86emuOp_push_DS, 5181 /* 0x1f */ x86emuOp_pop_DS, 5182 5183 /* 0x20 */ x86emuOp_genop_byte_RM_R, 5184 /* 0x21 */ x86emuOp_genop_word_RM_R, 5185 /* 0x22 */ x86emuOp_genop_byte_R_RM, 5186 /* 0x23 */ x86emuOp_genop_word_R_RM, 5187 /* 0x24 */ x86emuOp_genop_byte_AL_IMM, 5188 /* 0x25 */ x86emuOp_genop_word_AX_IMM, 5189 /* 0x26 */ x86emuOp_segovr_ES, 5190 /* 0x27 */ x86emuOp_daa, 5191 5192 /* 0x28 */ x86emuOp_genop_byte_RM_R, 5193 /* 0x29 */ x86emuOp_genop_word_RM_R, 5194 /* 0x2a */ x86emuOp_genop_byte_R_RM, 5195 /* 0x2b */ x86emuOp_genop_word_R_RM, 5196 /* 0x2c */ x86emuOp_genop_byte_AL_IMM, 5197 /* 0x2d */ x86emuOp_genop_word_AX_IMM, 5198 /* 0x2e */ x86emuOp_segovr_CS, 5199 /* 0x2f */ x86emuOp_das, 5200 5201 /* 0x30 */ x86emuOp_genop_byte_RM_R, 5202 /* 0x31 */ x86emuOp_genop_word_RM_R, 5203 /* 0x32 */ x86emuOp_genop_byte_R_RM, 5204 /* 0x33 */ x86emuOp_genop_word_R_RM, 5205 /* 0x34 */ x86emuOp_genop_byte_AL_IMM, 5206 /* 0x35 */ x86emuOp_genop_word_AX_IMM, 5207 /* 0x36 */ x86emuOp_segovr_SS, 5208 /* 0x37 */ x86emuOp_aaa, 5209 5210 /* 0x38 */ x86emuOp_genop_byte_RM_R, 5211 /* 0x39 */ x86emuOp_genop_word_RM_R, 5212 /* 0x3a */ x86emuOp_genop_byte_R_RM, 5213 /* 0x3b */ x86emuOp_genop_word_R_RM, 5214 /* 0x3c */ x86emuOp_genop_byte_AL_IMM, 5215 /* 0x3d */ x86emuOp_genop_word_AX_IMM, 5216 /* 0x3e */ x86emuOp_segovr_DS, 5217 /* 0x3f */ x86emuOp_aas, 5218 5219 /* 0x40 */ x86emuOp_inc_register, 5220 /* 0x41 */ x86emuOp_inc_register, 5221 /* 0x42 */ x86emuOp_inc_register, 5222 /* 0x43 */ x86emuOp_inc_register, 5223 /* 0x44 */ x86emuOp_inc_register, 5224 /* 0x45 */ x86emuOp_inc_register, 5225 /* 0x46 */ x86emuOp_inc_register, 5226 /* 0x47 */ x86emuOp_inc_register, 5227 5228 /* 0x48 */ x86emuOp_dec_register, 5229 /* 0x49 */ x86emuOp_dec_register, 5230 /* 0x4a */ x86emuOp_dec_register, 5231 /* 0x4b */ x86emuOp_dec_register, 5232 /* 0x4c */ x86emuOp_dec_register, 5233 /* 0x4d */ x86emuOp_dec_register, 5234 /* 0x4e */ x86emuOp_dec_register, 5235 /* 0x4f */ x86emuOp_dec_register, 5236 5237 /* 0x50 */ x86emuOp_push_register, 5238 /* 0x51 */ x86emuOp_push_register, 5239 /* 0x52 */ x86emuOp_push_register, 5240 /* 0x53 */ x86emuOp_push_register, 5241 /* 0x54 */ x86emuOp_push_register, 5242 /* 0x55 */ x86emuOp_push_register, 5243 /* 0x56 */ x86emuOp_push_register, 5244 /* 0x57 */ x86emuOp_push_register, 5245 5246 /* 0x58 */ x86emuOp_pop_register, 5247 /* 0x59 */ x86emuOp_pop_register, 5248 /* 0x5a */ x86emuOp_pop_register, 5249 /* 0x5b */ x86emuOp_pop_register, 5250 /* 0x5c */ x86emuOp_pop_register, 5251 /* 0x5d */ x86emuOp_pop_register, 5252 /* 0x5e */ x86emuOp_pop_register, 5253 /* 0x5f */ x86emuOp_pop_register, 5254 5255 /* 0x60 */ x86emuOp_push_all, 5256 /* 0x61 */ x86emuOp_pop_all, 5257 /* 0x62 */ x86emuOp_illegal_op, /* bound */ 5258 /* 0x63 */ x86emuOp_illegal_op, /* arpl */ 5259 /* 0x64 */ x86emuOp_segovr_FS, 5260 /* 0x65 */ x86emuOp_segovr_GS, 5261 /* 0x66 */ x86emuOp_prefix_data, 5262 /* 0x67 */ x86emuOp_prefix_addr, 5263 5264 /* 0x68 */ x86emuOp_push_word_IMM, 5265 /* 0x69 */ x86emuOp_imul_word_IMM, 5266 /* 0x6a */ x86emuOp_push_byte_IMM, 5267 /* 0x6b */ x86emuOp_imul_byte_IMM, 5268 /* 0x6c */ x86emuOp_ins_byte, 5269 /* 0x6d */ x86emuOp_ins_word, 5270 /* 0x6e */ x86emuOp_outs_byte, 5271 /* 0x6f */ x86emuOp_outs_word, 5272 5273 /* 0x70 */ x86emuOp_jump_near_cond, 5274 /* 0x71 */ x86emuOp_jump_near_cond, 5275 /* 0x72 */ x86emuOp_jump_near_cond, 5276 /* 0x73 */ x86emuOp_jump_near_cond, 5277 /* 0x74 */ x86emuOp_jump_near_cond, 5278 /* 0x75 */ x86emuOp_jump_near_cond, 5279 /* 0x76 */ x86emuOp_jump_near_cond, 5280 /* 0x77 */ x86emuOp_jump_near_cond, 5281 5282 /* 0x78 */ x86emuOp_jump_near_cond, 5283 /* 0x79 */ x86emuOp_jump_near_cond, 5284 /* 0x7a */ x86emuOp_jump_near_cond, 5285 /* 0x7b */ x86emuOp_jump_near_cond, 5286 /* 0x7c */ x86emuOp_jump_near_cond, 5287 /* 0x7d */ x86emuOp_jump_near_cond, 5288 /* 0x7e */ x86emuOp_jump_near_cond, 5289 /* 0x7f */ x86emuOp_jump_near_cond, 5290 5291 /* 0x80 */ x86emuOp_opc80_byte_RM_IMM, 5292 /* 0x81 */ x86emuOp_opc81_word_RM_IMM, 5293 /* 0x82 */ x86emuOp_opc82_byte_RM_IMM, 5294 /* 0x83 */ x86emuOp_opc83_word_RM_IMM, 5295 /* 0x84 */ x86emuOp_test_byte_RM_R, 5296 /* 0x85 */ x86emuOp_test_word_RM_R, 5297 /* 0x86 */ x86emuOp_xchg_byte_RM_R, 5298 /* 0x87 */ x86emuOp_xchg_word_RM_R, 5299 5300 /* 0x88 */ x86emuOp_mov_byte_RM_R, 5301 /* 0x89 */ x86emuOp_mov_word_RM_R, 5302 /* 0x8a */ x86emuOp_mov_byte_R_RM, 5303 /* 0x8b */ x86emuOp_mov_word_R_RM, 5304 /* 0x8c */ x86emuOp_mov_word_RM_SR, 5305 /* 0x8d */ x86emuOp_lea_word_R_M, 5306 /* 0x8e */ x86emuOp_mov_word_SR_RM, 5307 /* 0x8f */ x86emuOp_pop_RM, 5308 5309 /* 0x90 */ x86emuOp_nop, 5310 /* 0x91 */ x86emuOp_xchg_word_AX_register, 5311 /* 0x92 */ x86emuOp_xchg_word_AX_register, 5312 /* 0x93 */ x86emuOp_xchg_word_AX_register, 5313 /* 0x94 */ x86emuOp_xchg_word_AX_register, 5314 /* 0x95 */ x86emuOp_xchg_word_AX_register, 5315 /* 0x96 */ x86emuOp_xchg_word_AX_register, 5316 /* 0x97 */ x86emuOp_xchg_word_AX_register, 5317 5318 /* 0x98 */ x86emuOp_cbw, 5319 /* 0x99 */ x86emuOp_cwd, 5320 /* 0x9a */ x86emuOp_call_far_IMM, 5321 /* 0x9b */ x86emuOp_wait, 5322 /* 0x9c */ x86emuOp_pushf_word, 5323 /* 0x9d */ x86emuOp_popf_word, 5324 /* 0x9e */ x86emuOp_sahf, 5325 /* 0x9f */ x86emuOp_lahf, 5326 5327 /* 0xa0 */ x86emuOp_mov_AL_M_IMM, 5328 /* 0xa1 */ x86emuOp_mov_AX_M_IMM, 5329 /* 0xa2 */ x86emuOp_mov_M_AL_IMM, 5330 /* 0xa3 */ x86emuOp_mov_M_AX_IMM, 5331 /* 0xa4 */ x86emuOp_movs_byte, 5332 /* 0xa5 */ x86emuOp_movs_word, 5333 /* 0xa6 */ x86emuOp_cmps_byte, 5334 /* 0xa7 */ x86emuOp_cmps_word, 5335 /* 0xa8 */ x86emuOp_test_AL_IMM, 5336 /* 0xa9 */ x86emuOp_test_AX_IMM, 5337 /* 0xaa */ x86emuOp_stos_byte, 5338 /* 0xab */ x86emuOp_stos_word, 5339 /* 0xac */ x86emuOp_lods_byte, 5340 /* 0xad */ x86emuOp_lods_word, 5341 /* 0xac */ x86emuOp_scas_byte, 5342 /* 0xad */ x86emuOp_scas_word, 5343 5344 /* 0xb0 */ x86emuOp_mov_byte_register_IMM, 5345 /* 0xb1 */ x86emuOp_mov_byte_register_IMM, 5346 /* 0xb2 */ x86emuOp_mov_byte_register_IMM, 5347 /* 0xb3 */ x86emuOp_mov_byte_register_IMM, 5348 /* 0xb4 */ x86emuOp_mov_byte_register_IMM, 5349 /* 0xb5 */ x86emuOp_mov_byte_register_IMM, 5350 /* 0xb6 */ x86emuOp_mov_byte_register_IMM, 5351 /* 0xb7 */ x86emuOp_mov_byte_register_IMM, 5352 5353 /* 0xb8 */ x86emuOp_mov_word_register_IMM, 5354 /* 0xb9 */ x86emuOp_mov_word_register_IMM, 5355 /* 0xba */ x86emuOp_mov_word_register_IMM, 5356 /* 0xbb */ x86emuOp_mov_word_register_IMM, 5357 /* 0xbc */ x86emuOp_mov_word_register_IMM, 5358 /* 0xbd */ x86emuOp_mov_word_register_IMM, 5359 /* 0xbe */ x86emuOp_mov_word_register_IMM, 5360 /* 0xbf */ x86emuOp_mov_word_register_IMM, 5361 5362 /* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM, 5363 /* 0xc1 */ x86emuOp_opcC1_word_RM_MEM, 5364 /* 0xc2 */ x86emuOp_ret_near_IMM, 5365 /* 0xc3 */ x86emuOp_ret_near, 5366 /* 0xc4 */ x86emuOp_les_R_IMM, 5367 /* 0xc5 */ x86emuOp_lds_R_IMM, 5368 /* 0xc6 */ x86emuOp_mov_byte_RM_IMM, 5369 /* 0xc7 */ x86emuOp_mov_word_RM_IMM, 5370 /* 0xc8 */ x86emuOp_enter, 5371 /* 0xc9 */ x86emuOp_leave, 5372 /* 0xca */ x86emuOp_ret_far_IMM, 5373 /* 0xcb */ x86emuOp_ret_far, 5374 /* 0xcc */ x86emuOp_int3, 5375 /* 0xcd */ x86emuOp_int_IMM, 5376 /* 0xce */ x86emuOp_into, 5377 /* 0xcf */ x86emuOp_iret, 5378 5379 /* 0xd0 */ x86emuOp_opcD0_byte_RM_1, 5380 /* 0xd1 */ x86emuOp_opcD1_word_RM_1, 5381 /* 0xd2 */ x86emuOp_opcD2_byte_RM_CL, 5382 /* 0xd3 */ x86emuOp_opcD3_word_RM_CL, 5383 /* 0xd4 */ x86emuOp_aam, 5384 /* 0xd5 */ x86emuOp_aad, 5385 /* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */ 5386 /* 0xd7 */ x86emuOp_xlat, 5387 /* 0xd8 */ NULL, /*x86emuOp_esc_coprocess_d8,*/ 5388 /* 0xd9 */ NULL, /*x86emuOp_esc_coprocess_d9,*/ 5389 /* 0xda */ NULL, /*x86emuOp_esc_coprocess_da,*/ 5390 /* 0xdb */ NULL, /*x86emuOp_esc_coprocess_db,*/ 5391 /* 0xdc */ NULL, /*x86emuOp_esc_coprocess_dc,*/ 5392 /* 0xdd */ NULL, /*x86emuOp_esc_coprocess_dd,*/ 5393 /* 0xde */ NULL, /*x86emuOp_esc_coprocess_de,*/ 5394 /* 0xdf */ NULL, /*x86emuOp_esc_coprocess_df,*/ 5395 5396 /* 0xe0 */ x86emuOp_loopne, 5397 /* 0xe1 */ x86emuOp_loope, 5398 /* 0xe2 */ x86emuOp_loop, 5399 /* 0xe3 */ x86emuOp_jcxz, 5400 /* 0xe4 */ x86emuOp_in_byte_AL_IMM, 5401 /* 0xe5 */ x86emuOp_in_word_AX_IMM, 5402 /* 0xe6 */ x86emuOp_out_byte_IMM_AL, 5403 /* 0xe7 */ x86emuOp_out_word_IMM_AX, 5404 5405 /* 0xe8 */ x86emuOp_call_near_IMM, 5406 /* 0xe9 */ x86emuOp_jump_near_IMM, 5407 /* 0xea */ x86emuOp_jump_far_IMM, 5408 /* 0xeb */ x86emuOp_jump_byte_IMM, 5409 /* 0xec */ x86emuOp_in_byte_AL_DX, 5410 /* 0xed */ x86emuOp_in_word_AX_DX, 5411 /* 0xee */ x86emuOp_out_byte_DX_AL, 5412 /* 0xef */ x86emuOp_out_word_DX_AX, 5413 5414 /* 0xf0 */ x86emuOp_lock, 5415 /* 0xf1 */ x86emuOp_illegal_op, 5416 /* 0xf2 */ x86emuOp_repne, 5417 /* 0xf3 */ x86emuOp_repe, 5418 /* 0xf4 */ x86emuOp_halt, 5419 /* 0xf5 */ x86emuOp_cmc, 5420 /* 0xf6 */ x86emuOp_opcF6_byte_RM, 5421 /* 0xf7 */ x86emuOp_opcF7_word_RM, 5422 5423 /* 0xf8 */ x86emuOp_clc, 5424 /* 0xf9 */ x86emuOp_stc, 5425 /* 0xfa */ x86emuOp_cli, 5426 /* 0xfb */ x86emuOp_sti, 5427 /* 0xfc */ x86emuOp_cld, 5428 /* 0xfd */ x86emuOp_std, 5429 /* 0xfe */ x86emuOp_opcFE_byte_RM, 5430 /* 0xff */ x86emuOp_opcFF_word_RM, 5431 }; 5432