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