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 START_OF_INSTR(); 3522 DECODE_PRINTF("INT 3\n"); 3523 (void)mem_access_word(3 * 4 + 2); 3524 /* access the segment register */ 3525 TRACE_AND_STEP(); 3526 if (_X86EMU_intrTab[3]) { 3527 (*_X86EMU_intrTab[3])(3); 3528 } else { 3529 push_word((u16)M.x86.R_FLG); 3530 CLEAR_FLAG(F_IF); 3531 CLEAR_FLAG(F_TF); 3532 push_word(M.x86.R_CS); 3533 M.x86.R_CS = mem_access_word(3 * 4 + 2); 3534 push_word(M.x86.R_IP); 3535 M.x86.R_IP = mem_access_word(3 * 4); 3536 } 3537 DECODE_CLEAR_SEGOVR(); 3538 END_OF_INSTR(); 3539 } 3540 3541 /**************************************************************************** 3542 REMARKS: 3543 Handles opcode 0xcd 3544 ****************************************************************************/ 3545 void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1)) 3546 { 3547 u8 intnum; 3548 3549 START_OF_INSTR(); 3550 DECODE_PRINTF("INT\t"); 3551 intnum = fetch_byte_imm(); 3552 DECODE_PRINTF2("%x\n", intnum); 3553 (void)mem_access_word(intnum * 4 + 2); 3554 TRACE_AND_STEP(); 3555 if (_X86EMU_intrTab[intnum]) { 3556 (*_X86EMU_intrTab[intnum])(intnum); 3557 } else { 3558 push_word((u16)M.x86.R_FLG); 3559 CLEAR_FLAG(F_IF); 3560 CLEAR_FLAG(F_TF); 3561 push_word(M.x86.R_CS); 3562 M.x86.R_CS = mem_access_word(intnum * 4 + 2); 3563 push_word(M.x86.R_IP); 3564 M.x86.R_IP = mem_access_word(intnum * 4); 3565 } 3566 DECODE_CLEAR_SEGOVR(); 3567 END_OF_INSTR(); 3568 } 3569 3570 /**************************************************************************** 3571 REMARKS: 3572 Handles opcode 0xce 3573 ****************************************************************************/ 3574 void x86emuOp_into(u8 X86EMU_UNUSED(op1)) 3575 { 3576 START_OF_INSTR(); 3577 DECODE_PRINTF("INTO\n"); 3578 TRACE_AND_STEP(); 3579 if (ACCESS_FLAG(F_OF)) { 3580 (void)mem_access_word(4 * 4 + 2); 3581 if (_X86EMU_intrTab[4]) { 3582 (*_X86EMU_intrTab[4])(4); 3583 } else { 3584 push_word((u16)M.x86.R_FLG); 3585 CLEAR_FLAG(F_IF); 3586 CLEAR_FLAG(F_TF); 3587 push_word(M.x86.R_CS); 3588 M.x86.R_CS = mem_access_word(4 * 4 + 2); 3589 push_word(M.x86.R_IP); 3590 M.x86.R_IP = mem_access_word(4 * 4); 3591 } 3592 } 3593 DECODE_CLEAR_SEGOVR(); 3594 END_OF_INSTR(); 3595 } 3596 3597 /**************************************************************************** 3598 REMARKS: 3599 Handles opcode 0xcf 3600 ****************************************************************************/ 3601 void x86emuOp_iret(u8 X86EMU_UNUSED(op1)) 3602 { 3603 START_OF_INSTR(); 3604 DECODE_PRINTF("IRET\n"); 3605 3606 TRACE_AND_STEP(); 3607 3608 M.x86.R_IP = pop_word(); 3609 M.x86.R_CS = pop_word(); 3610 M.x86.R_FLG = pop_word(); 3611 DECODE_CLEAR_SEGOVR(); 3612 END_OF_INSTR(); 3613 } 3614 3615 /**************************************************************************** 3616 REMARKS: 3617 Handles opcode 0xd0 3618 ****************************************************************************/ 3619 void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1)) 3620 { 3621 int mod, rl, rh; 3622 u8 *destreg; 3623 uint destoffset; 3624 u8 destval; 3625 3626 /* 3627 * Yet another weirdo special case instruction format. Part of 3628 * the opcode held below in "RH". Doubly nested case would 3629 * result, except that the decoded instruction 3630 */ 3631 START_OF_INSTR(); 3632 FETCH_DECODE_MODRM(mod, rh, rl); 3633 #ifdef DEBUG 3634 if (DEBUG_DECODE()) { 3635 /* XXX DECODE_PRINTF may be changed to something more 3636 general, so that it is important to leave the strings 3637 in the same format, even though the result is that the 3638 above test is done twice. */ 3639 switch (rh) { 3640 case 0: 3641 DECODE_PRINTF("ROL\t"); 3642 break; 3643 case 1: 3644 DECODE_PRINTF("ROR\t"); 3645 break; 3646 case 2: 3647 DECODE_PRINTF("RCL\t"); 3648 break; 3649 case 3: 3650 DECODE_PRINTF("RCR\t"); 3651 break; 3652 case 4: 3653 DECODE_PRINTF("SHL\t"); 3654 break; 3655 case 5: 3656 DECODE_PRINTF("SHR\t"); 3657 break; 3658 case 6: 3659 DECODE_PRINTF("SAL\t"); 3660 break; 3661 case 7: 3662 DECODE_PRINTF("SAR\t"); 3663 break; 3664 } 3665 } 3666 #endif 3667 /* know operation, decode the mod byte to find the addressing 3668 mode. */ 3669 if (mod < 3) { 3670 DECODE_PRINTF("BYTE PTR "); 3671 destoffset = decode_rmXX_address(mod, rl); 3672 DECODE_PRINTF(",1\n"); 3673 destval = fetch_data_byte(destoffset); 3674 TRACE_AND_STEP(); 3675 destval = (*opcD0_byte_operation[rh]) (destval, 1); 3676 store_data_byte(destoffset, destval); 3677 } else { /* register to register */ 3678 destreg = DECODE_RM_BYTE_REGISTER(rl); 3679 DECODE_PRINTF(",1\n"); 3680 TRACE_AND_STEP(); 3681 destval = (*opcD0_byte_operation[rh]) (*destreg, 1); 3682 *destreg = destval; 3683 } 3684 DECODE_CLEAR_SEGOVR(); 3685 END_OF_INSTR(); 3686 } 3687 3688 /**************************************************************************** 3689 REMARKS: 3690 Handles opcode 0xd1 3691 ****************************************************************************/ 3692 void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1)) 3693 { 3694 int mod, rl, rh; 3695 uint destoffset; 3696 3697 /* 3698 * Yet another weirdo special case instruction format. Part of 3699 * the opcode held below in "RH". Doubly nested case would 3700 * result, except that the decoded instruction 3701 */ 3702 START_OF_INSTR(); 3703 FETCH_DECODE_MODRM(mod, rh, rl); 3704 #ifdef DEBUG 3705 if (DEBUG_DECODE()) { 3706 /* XXX DECODE_PRINTF may be changed to something more 3707 general, so that it is important to leave the strings 3708 in the same format, even though the result is that the 3709 above test is done twice. */ 3710 switch (rh) { 3711 case 0: 3712 DECODE_PRINTF("ROL\t"); 3713 break; 3714 case 1: 3715 DECODE_PRINTF("ROR\t"); 3716 break; 3717 case 2: 3718 DECODE_PRINTF("RCL\t"); 3719 break; 3720 case 3: 3721 DECODE_PRINTF("RCR\t"); 3722 break; 3723 case 4: 3724 DECODE_PRINTF("SHL\t"); 3725 break; 3726 case 5: 3727 DECODE_PRINTF("SHR\t"); 3728 break; 3729 case 6: 3730 DECODE_PRINTF("SAL\t"); 3731 break; 3732 case 7: 3733 DECODE_PRINTF("SAR\t"); 3734 break; 3735 } 3736 } 3737 #endif 3738 /* know operation, decode the mod byte to find the addressing 3739 mode. */ 3740 if (mod < 3) { 3741 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 3742 u32 destval; 3743 3744 DECODE_PRINTF("DWORD PTR "); 3745 destoffset = decode_rmXX_address(mod, rl); 3746 DECODE_PRINTF(",1\n"); 3747 destval = fetch_data_long(destoffset); 3748 TRACE_AND_STEP(); 3749 destval = (*opcD1_long_operation[rh]) (destval, 1); 3750 store_data_long(destoffset, destval); 3751 } else { 3752 u16 destval; 3753 3754 DECODE_PRINTF("WORD PTR "); 3755 destoffset = decode_rmXX_address(mod, rl); 3756 DECODE_PRINTF(",1\n"); 3757 destval = fetch_data_word(destoffset); 3758 TRACE_AND_STEP(); 3759 destval = (*opcD1_word_operation[rh]) (destval, 1); 3760 store_data_word(destoffset, destval); 3761 } 3762 } else { /* register to register */ 3763 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 3764 u32 destval; 3765 u32 *destreg; 3766 3767 destreg = DECODE_RM_LONG_REGISTER(rl); 3768 DECODE_PRINTF(",1\n"); 3769 TRACE_AND_STEP(); 3770 destval = (*opcD1_long_operation[rh]) (*destreg, 1); 3771 *destreg = destval; 3772 } else { 3773 u16 destval; 3774 u16 *destreg; 3775 3776 destreg = DECODE_RM_WORD_REGISTER(rl); 3777 DECODE_PRINTF(",1\n"); 3778 TRACE_AND_STEP(); 3779 destval = (*opcD1_word_operation[rh]) (*destreg, 1); 3780 *destreg = destval; 3781 } 3782 } 3783 DECODE_CLEAR_SEGOVR(); 3784 END_OF_INSTR(); 3785 } 3786 3787 /**************************************************************************** 3788 REMARKS: 3789 Handles opcode 0xd2 3790 ****************************************************************************/ 3791 void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1)) 3792 { 3793 int mod, rl, rh; 3794 u8 *destreg; 3795 uint destoffset; 3796 u8 destval; 3797 u8 amt; 3798 3799 /* 3800 * Yet another weirdo special case instruction format. Part of 3801 * the opcode held below in "RH". Doubly nested case would 3802 * result, except that the decoded instruction 3803 */ 3804 START_OF_INSTR(); 3805 FETCH_DECODE_MODRM(mod, rh, rl); 3806 #ifdef DEBUG 3807 if (DEBUG_DECODE()) { 3808 /* XXX DECODE_PRINTF may be changed to something more 3809 general, so that it is important to leave the strings 3810 in the same format, even though the result is that the 3811 above test is done twice. */ 3812 switch (rh) { 3813 case 0: 3814 DECODE_PRINTF("ROL\t"); 3815 break; 3816 case 1: 3817 DECODE_PRINTF("ROR\t"); 3818 break; 3819 case 2: 3820 DECODE_PRINTF("RCL\t"); 3821 break; 3822 case 3: 3823 DECODE_PRINTF("RCR\t"); 3824 break; 3825 case 4: 3826 DECODE_PRINTF("SHL\t"); 3827 break; 3828 case 5: 3829 DECODE_PRINTF("SHR\t"); 3830 break; 3831 case 6: 3832 DECODE_PRINTF("SAL\t"); 3833 break; 3834 case 7: 3835 DECODE_PRINTF("SAR\t"); 3836 break; 3837 } 3838 } 3839 #endif 3840 /* know operation, decode the mod byte to find the addressing 3841 mode. */ 3842 amt = M.x86.R_CL; 3843 if (mod < 3) { 3844 DECODE_PRINTF("BYTE PTR "); 3845 destoffset = decode_rmXX_address(mod, rl); 3846 DECODE_PRINTF(",CL\n"); 3847 destval = fetch_data_byte(destoffset); 3848 TRACE_AND_STEP(); 3849 destval = (*opcD0_byte_operation[rh]) (destval, amt); 3850 store_data_byte(destoffset, destval); 3851 } else { /* register to register */ 3852 destreg = DECODE_RM_BYTE_REGISTER(rl); 3853 DECODE_PRINTF(",CL\n"); 3854 TRACE_AND_STEP(); 3855 destval = (*opcD0_byte_operation[rh]) (*destreg, amt); 3856 *destreg = destval; 3857 } 3858 DECODE_CLEAR_SEGOVR(); 3859 END_OF_INSTR(); 3860 } 3861 3862 /**************************************************************************** 3863 REMARKS: 3864 Handles opcode 0xd3 3865 ****************************************************************************/ 3866 void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1)) 3867 { 3868 int mod, rl, rh; 3869 uint destoffset; 3870 u8 amt; 3871 3872 /* 3873 * Yet another weirdo special case instruction format. Part of 3874 * the opcode held below in "RH". Doubly nested case would 3875 * result, except that the decoded instruction 3876 */ 3877 START_OF_INSTR(); 3878 FETCH_DECODE_MODRM(mod, rh, rl); 3879 #ifdef DEBUG 3880 if (DEBUG_DECODE()) { 3881 /* XXX DECODE_PRINTF may be changed to something more 3882 general, so that it is important to leave the strings 3883 in the same format, even though the result is that the 3884 above test is done twice. */ 3885 switch (rh) { 3886 case 0: 3887 DECODE_PRINTF("ROL\t"); 3888 break; 3889 case 1: 3890 DECODE_PRINTF("ROR\t"); 3891 break; 3892 case 2: 3893 DECODE_PRINTF("RCL\t"); 3894 break; 3895 case 3: 3896 DECODE_PRINTF("RCR\t"); 3897 break; 3898 case 4: 3899 DECODE_PRINTF("SHL\t"); 3900 break; 3901 case 5: 3902 DECODE_PRINTF("SHR\t"); 3903 break; 3904 case 6: 3905 DECODE_PRINTF("SAL\t"); 3906 break; 3907 case 7: 3908 DECODE_PRINTF("SAR\t"); 3909 break; 3910 } 3911 } 3912 #endif 3913 /* know operation, decode the mod byte to find the addressing 3914 mode. */ 3915 amt = M.x86.R_CL; 3916 if (mod < 3) { 3917 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 3918 u32 destval; 3919 3920 DECODE_PRINTF("DWORD PTR "); 3921 destoffset = decode_rmXX_address(mod, rl); 3922 DECODE_PRINTF(",CL\n"); 3923 destval = fetch_data_long(destoffset); 3924 TRACE_AND_STEP(); 3925 destval = (*opcD1_long_operation[rh]) (destval, amt); 3926 store_data_long(destoffset, destval); 3927 } else { 3928 u16 destval; 3929 3930 DECODE_PRINTF("WORD PTR "); 3931 destoffset = decode_rmXX_address(mod, rl); 3932 DECODE_PRINTF(",CL\n"); 3933 destval = fetch_data_word(destoffset); 3934 TRACE_AND_STEP(); 3935 destval = (*opcD1_word_operation[rh]) (destval, amt); 3936 store_data_word(destoffset, destval); 3937 } 3938 } else { /* register to register */ 3939 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 3940 u32 *destreg; 3941 3942 destreg = DECODE_RM_LONG_REGISTER(rl); 3943 DECODE_PRINTF(",CL\n"); 3944 TRACE_AND_STEP(); 3945 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt); 3946 } else { 3947 u16 *destreg; 3948 3949 destreg = DECODE_RM_WORD_REGISTER(rl); 3950 DECODE_PRINTF(",CL\n"); 3951 TRACE_AND_STEP(); 3952 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt); 3953 } 3954 } 3955 DECODE_CLEAR_SEGOVR(); 3956 END_OF_INSTR(); 3957 } 3958 3959 /**************************************************************************** 3960 REMARKS: 3961 Handles opcode 0xd4 3962 ****************************************************************************/ 3963 void x86emuOp_aam(u8 X86EMU_UNUSED(op1)) 3964 { 3965 u8 a; 3966 3967 START_OF_INSTR(); 3968 DECODE_PRINTF("AAM\n"); 3969 a = fetch_byte_imm(); /* this is a stupid encoding. */ 3970 if (a != 10) { 3971 DECODE_PRINTF("ERROR DECODING AAM\n"); 3972 TRACE_REGS(); 3973 HALT_SYS(); 3974 } 3975 TRACE_AND_STEP(); 3976 /* note the type change here --- returning AL and AH in AX. */ 3977 M.x86.R_AX = aam_word(M.x86.R_AL); 3978 DECODE_CLEAR_SEGOVR(); 3979 END_OF_INSTR(); 3980 } 3981 3982 /**************************************************************************** 3983 REMARKS: 3984 Handles opcode 0xd5 3985 ****************************************************************************/ 3986 void x86emuOp_aad(u8 X86EMU_UNUSED(op1)) 3987 { 3988 START_OF_INSTR(); 3989 DECODE_PRINTF("AAD\n"); 3990 (void)fetch_byte_imm(); 3991 TRACE_AND_STEP(); 3992 M.x86.R_AX = aad_word(M.x86.R_AX); 3993 DECODE_CLEAR_SEGOVR(); 3994 END_OF_INSTR(); 3995 } 3996 3997 /* opcode 0xd6 ILLEGAL OPCODE */ 3998 3999 /**************************************************************************** 4000 REMARKS: 4001 Handles opcode 0xd7 4002 ****************************************************************************/ 4003 void x86emuOp_xlat(u8 X86EMU_UNUSED(op1)) 4004 { 4005 u16 addr; 4006 4007 START_OF_INSTR(); 4008 DECODE_PRINTF("XLAT\n"); 4009 TRACE_AND_STEP(); 4010 addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL); 4011 M.x86.R_AL = fetch_data_byte(addr); 4012 DECODE_CLEAR_SEGOVR(); 4013 END_OF_INSTR(); 4014 } 4015 4016 /* instuctions D8 .. DF are in i87_ops.c */ 4017 4018 /**************************************************************************** 4019 REMARKS: 4020 Handles opcode 0xe0 4021 ****************************************************************************/ 4022 void x86emuOp_loopne(u8 X86EMU_UNUSED(op1)) 4023 { 4024 s16 ip; 4025 4026 START_OF_INSTR(); 4027 DECODE_PRINTF("LOOPNE\t"); 4028 ip = (s8) fetch_byte_imm(); 4029 ip += (s16) M.x86.R_IP; 4030 DECODE_PRINTF2("%04x\n", ip); 4031 TRACE_AND_STEP(); 4032 M.x86.R_CX -= 1; 4033 if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */ 4034 M.x86.R_IP = ip; 4035 DECODE_CLEAR_SEGOVR(); 4036 END_OF_INSTR(); 4037 } 4038 4039 /**************************************************************************** 4040 REMARKS: 4041 Handles opcode 0xe1 4042 ****************************************************************************/ 4043 void x86emuOp_loope(u8 X86EMU_UNUSED(op1)) 4044 { 4045 s16 ip; 4046 4047 START_OF_INSTR(); 4048 DECODE_PRINTF("LOOPE\t"); 4049 ip = (s8) fetch_byte_imm(); 4050 ip += (s16) M.x86.R_IP; 4051 DECODE_PRINTF2("%04x\n", ip); 4052 TRACE_AND_STEP(); 4053 M.x86.R_CX -= 1; 4054 if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */ 4055 M.x86.R_IP = ip; 4056 DECODE_CLEAR_SEGOVR(); 4057 END_OF_INSTR(); 4058 } 4059 4060 /**************************************************************************** 4061 REMARKS: 4062 Handles opcode 0xe2 4063 ****************************************************************************/ 4064 void x86emuOp_loop(u8 X86EMU_UNUSED(op1)) 4065 { 4066 s16 ip; 4067 4068 START_OF_INSTR(); 4069 DECODE_PRINTF("LOOP\t"); 4070 ip = (s8) fetch_byte_imm(); 4071 ip += (s16) M.x86.R_IP; 4072 DECODE_PRINTF2("%04x\n", ip); 4073 TRACE_AND_STEP(); 4074 M.x86.R_CX -= 1; 4075 if (M.x86.R_CX != 0) 4076 M.x86.R_IP = ip; 4077 DECODE_CLEAR_SEGOVR(); 4078 END_OF_INSTR(); 4079 } 4080 4081 /**************************************************************************** 4082 REMARKS: 4083 Handles opcode 0xe3 4084 ****************************************************************************/ 4085 void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1)) 4086 { 4087 u16 target; 4088 s8 offset; 4089 4090 /* jump to byte offset if overflow flag is set */ 4091 START_OF_INSTR(); 4092 DECODE_PRINTF("JCXZ\t"); 4093 offset = (s8)fetch_byte_imm(); 4094 target = (u16)(M.x86.R_IP + offset); 4095 DECODE_PRINTF2("%x\n", target); 4096 TRACE_AND_STEP(); 4097 if (M.x86.R_CX == 0) 4098 M.x86.R_IP = target; 4099 DECODE_CLEAR_SEGOVR(); 4100 END_OF_INSTR(); 4101 } 4102 4103 /**************************************************************************** 4104 REMARKS: 4105 Handles opcode 0xe4 4106 ****************************************************************************/ 4107 void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) 4108 { 4109 u8 port; 4110 4111 START_OF_INSTR(); 4112 DECODE_PRINTF("IN\t"); 4113 port = (u8) fetch_byte_imm(); 4114 DECODE_PRINTF2("%x,AL\n", port); 4115 TRACE_AND_STEP(); 4116 M.x86.R_AL = (*sys_inb)(port); 4117 DECODE_CLEAR_SEGOVR(); 4118 END_OF_INSTR(); 4119 } 4120 4121 /**************************************************************************** 4122 REMARKS: 4123 Handles opcode 0xe5 4124 ****************************************************************************/ 4125 void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1)) 4126 { 4127 u8 port; 4128 4129 START_OF_INSTR(); 4130 DECODE_PRINTF("IN\t"); 4131 port = (u8) fetch_byte_imm(); 4132 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4133 DECODE_PRINTF2("EAX,%x\n", port); 4134 } else { 4135 DECODE_PRINTF2("AX,%x\n", port); 4136 } 4137 TRACE_AND_STEP(); 4138 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4139 M.x86.R_EAX = (*sys_inl)(port); 4140 } else { 4141 M.x86.R_AX = (*sys_inw)(port); 4142 } 4143 DECODE_CLEAR_SEGOVR(); 4144 END_OF_INSTR(); 4145 } 4146 4147 /**************************************************************************** 4148 REMARKS: 4149 Handles opcode 0xe6 4150 ****************************************************************************/ 4151 void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1)) 4152 { 4153 u8 port; 4154 4155 START_OF_INSTR(); 4156 DECODE_PRINTF("OUT\t"); 4157 port = (u8) fetch_byte_imm(); 4158 DECODE_PRINTF2("%x,AL\n", port); 4159 TRACE_AND_STEP(); 4160 (*sys_outb)(port, M.x86.R_AL); 4161 DECODE_CLEAR_SEGOVR(); 4162 END_OF_INSTR(); 4163 } 4164 4165 /**************************************************************************** 4166 REMARKS: 4167 Handles opcode 0xe7 4168 ****************************************************************************/ 4169 void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1)) 4170 { 4171 u8 port; 4172 4173 START_OF_INSTR(); 4174 DECODE_PRINTF("OUT\t"); 4175 port = (u8) fetch_byte_imm(); 4176 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4177 DECODE_PRINTF2("%x,EAX\n", port); 4178 } else { 4179 DECODE_PRINTF2("%x,AX\n", port); 4180 } 4181 TRACE_AND_STEP(); 4182 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4183 (*sys_outl)(port, M.x86.R_EAX); 4184 } else { 4185 (*sys_outw)(port, M.x86.R_AX); 4186 } 4187 DECODE_CLEAR_SEGOVR(); 4188 END_OF_INSTR(); 4189 } 4190 4191 /**************************************************************************** 4192 REMARKS: 4193 Handles opcode 0xe8 4194 ****************************************************************************/ 4195 void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1)) 4196 { 4197 s16 ip; 4198 4199 START_OF_INSTR(); 4200 DECODE_PRINTF("CALL\t"); 4201 ip = (s16) fetch_word_imm(); 4202 ip += (s16) M.x86.R_IP; /* CHECK SIGN */ 4203 DECODE_PRINTF2("%04x\n", ip); 4204 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, ""); 4205 TRACE_AND_STEP(); 4206 push_word(M.x86.R_IP); 4207 M.x86.R_IP = ip; 4208 DECODE_CLEAR_SEGOVR(); 4209 END_OF_INSTR(); 4210 } 4211 4212 /**************************************************************************** 4213 REMARKS: 4214 Handles opcode 0xe9 4215 ****************************************************************************/ 4216 void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1)) 4217 { 4218 int ip; 4219 4220 START_OF_INSTR(); 4221 DECODE_PRINTF("JMP\t"); 4222 ip = (s16)fetch_word_imm(); 4223 ip += (s16)M.x86.R_IP; 4224 DECODE_PRINTF2("%04x\n", ip); 4225 TRACE_AND_STEP(); 4226 M.x86.R_IP = (u16)ip; 4227 DECODE_CLEAR_SEGOVR(); 4228 END_OF_INSTR(); 4229 } 4230 4231 /**************************************************************************** 4232 REMARKS: 4233 Handles opcode 0xea 4234 ****************************************************************************/ 4235 void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1)) 4236 { 4237 u16 cs, ip; 4238 4239 START_OF_INSTR(); 4240 DECODE_PRINTF("JMP\tFAR "); 4241 ip = fetch_word_imm(); 4242 cs = fetch_word_imm(); 4243 DECODE_PRINTF2("%04x:", cs); 4244 DECODE_PRINTF2("%04x\n", ip); 4245 TRACE_AND_STEP(); 4246 M.x86.R_IP = ip; 4247 M.x86.R_CS = cs; 4248 DECODE_CLEAR_SEGOVR(); 4249 END_OF_INSTR(); 4250 } 4251 4252 /**************************************************************************** 4253 REMARKS: 4254 Handles opcode 0xeb 4255 ****************************************************************************/ 4256 void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1)) 4257 { 4258 u16 target; 4259 s8 offset; 4260 4261 START_OF_INSTR(); 4262 DECODE_PRINTF("JMP\t"); 4263 offset = (s8)fetch_byte_imm(); 4264 target = (u16)(M.x86.R_IP + offset); 4265 DECODE_PRINTF2("%x\n", target); 4266 TRACE_AND_STEP(); 4267 M.x86.R_IP = target; 4268 DECODE_CLEAR_SEGOVR(); 4269 END_OF_INSTR(); 4270 } 4271 4272 /**************************************************************************** 4273 REMARKS: 4274 Handles opcode 0xec 4275 ****************************************************************************/ 4276 void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1)) 4277 { 4278 START_OF_INSTR(); 4279 DECODE_PRINTF("IN\tAL,DX\n"); 4280 TRACE_AND_STEP(); 4281 M.x86.R_AL = (*sys_inb)(M.x86.R_DX); 4282 DECODE_CLEAR_SEGOVR(); 4283 END_OF_INSTR(); 4284 } 4285 4286 /**************************************************************************** 4287 REMARKS: 4288 Handles opcode 0xed 4289 ****************************************************************************/ 4290 void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1)) 4291 { 4292 START_OF_INSTR(); 4293 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4294 DECODE_PRINTF("IN\tEAX,DX\n"); 4295 } else { 4296 DECODE_PRINTF("IN\tAX,DX\n"); 4297 } 4298 TRACE_AND_STEP(); 4299 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4300 M.x86.R_EAX = (*sys_inl)(M.x86.R_DX); 4301 } else { 4302 M.x86.R_AX = (*sys_inw)(M.x86.R_DX); 4303 } 4304 DECODE_CLEAR_SEGOVR(); 4305 END_OF_INSTR(); 4306 } 4307 4308 /**************************************************************************** 4309 REMARKS: 4310 Handles opcode 0xee 4311 ****************************************************************************/ 4312 void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1)) 4313 { 4314 START_OF_INSTR(); 4315 DECODE_PRINTF("OUT\tDX,AL\n"); 4316 TRACE_AND_STEP(); 4317 (*sys_outb)(M.x86.R_DX, M.x86.R_AL); 4318 DECODE_CLEAR_SEGOVR(); 4319 END_OF_INSTR(); 4320 } 4321 4322 /**************************************************************************** 4323 REMARKS: 4324 Handles opcode 0xef 4325 ****************************************************************************/ 4326 void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1)) 4327 { 4328 START_OF_INSTR(); 4329 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4330 DECODE_PRINTF("OUT\tDX,EAX\n"); 4331 } else { 4332 DECODE_PRINTF("OUT\tDX,AX\n"); 4333 } 4334 TRACE_AND_STEP(); 4335 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4336 (*sys_outl)(M.x86.R_DX, M.x86.R_EAX); 4337 } else { 4338 (*sys_outw)(M.x86.R_DX, M.x86.R_AX); 4339 } 4340 DECODE_CLEAR_SEGOVR(); 4341 END_OF_INSTR(); 4342 } 4343 4344 /**************************************************************************** 4345 REMARKS: 4346 Handles opcode 0xf0 4347 ****************************************************************************/ 4348 void x86emuOp_lock(u8 X86EMU_UNUSED(op1)) 4349 { 4350 START_OF_INSTR(); 4351 DECODE_PRINTF("LOCK:\n"); 4352 TRACE_AND_STEP(); 4353 DECODE_CLEAR_SEGOVR(); 4354 END_OF_INSTR(); 4355 } 4356 4357 /*opcode 0xf1 ILLEGAL OPERATION */ 4358 4359 /**************************************************************************** 4360 REMARKS: 4361 Handles opcode 0xf2 4362 ****************************************************************************/ 4363 void x86emuOp_repne(u8 X86EMU_UNUSED(op1)) 4364 { 4365 START_OF_INSTR(); 4366 DECODE_PRINTF("REPNE\n"); 4367 TRACE_AND_STEP(); 4368 M.x86.mode |= SYSMODE_PREFIX_REPNE; 4369 DECODE_CLEAR_SEGOVR(); 4370 END_OF_INSTR(); 4371 } 4372 4373 /**************************************************************************** 4374 REMARKS: 4375 Handles opcode 0xf3 4376 ****************************************************************************/ 4377 void x86emuOp_repe(u8 X86EMU_UNUSED(op1)) 4378 { 4379 START_OF_INSTR(); 4380 DECODE_PRINTF("REPE\n"); 4381 TRACE_AND_STEP(); 4382 M.x86.mode |= SYSMODE_PREFIX_REPE; 4383 DECODE_CLEAR_SEGOVR(); 4384 END_OF_INSTR(); 4385 } 4386 4387 /**************************************************************************** 4388 REMARKS: 4389 Handles opcode 0xf4 4390 ****************************************************************************/ 4391 void x86emuOp_halt(u8 X86EMU_UNUSED(op1)) 4392 { 4393 START_OF_INSTR(); 4394 DECODE_PRINTF("HALT\n"); 4395 TRACE_AND_STEP(); 4396 HALT_SYS(); 4397 DECODE_CLEAR_SEGOVR(); 4398 END_OF_INSTR(); 4399 } 4400 4401 /**************************************************************************** 4402 REMARKS: 4403 Handles opcode 0xf5 4404 ****************************************************************************/ 4405 void x86emuOp_cmc(u8 X86EMU_UNUSED(op1)) 4406 { 4407 /* complement the carry flag. */ 4408 START_OF_INSTR(); 4409 DECODE_PRINTF("CMC\n"); 4410 TRACE_AND_STEP(); 4411 TOGGLE_FLAG(F_CF); 4412 DECODE_CLEAR_SEGOVR(); 4413 END_OF_INSTR(); 4414 } 4415 4416 /**************************************************************************** 4417 REMARKS: 4418 Handles opcode 0xf6 4419 ****************************************************************************/ 4420 void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1)) 4421 { 4422 int mod, rl, rh; 4423 u8 *destreg; 4424 uint destoffset; 4425 u8 destval, srcval; 4426 4427 /* long, drawn out code follows. Double switch for a total 4428 of 32 cases. */ 4429 START_OF_INSTR(); 4430 FETCH_DECODE_MODRM(mod, rh, rl); 4431 DECODE_PRINTF(opF6_names[rh]); 4432 if (mod < 3) { 4433 DECODE_PRINTF("BYTE PTR "); 4434 destoffset = decode_rmXX_address(mod, rl); 4435 destval = fetch_data_byte(destoffset); 4436 4437 switch (rh) { 4438 case 0: /* test byte imm */ 4439 DECODE_PRINTF(","); 4440 srcval = fetch_byte_imm(); 4441 DECODE_PRINTF2("%02x\n", srcval); 4442 TRACE_AND_STEP(); 4443 test_byte(destval, srcval); 4444 break; 4445 case 1: 4446 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); 4447 HALT_SYS(); 4448 break; 4449 case 2: 4450 DECODE_PRINTF("\n"); 4451 TRACE_AND_STEP(); 4452 destval = not_byte(destval); 4453 store_data_byte(destoffset, destval); 4454 break; 4455 case 3: 4456 DECODE_PRINTF("\n"); 4457 TRACE_AND_STEP(); 4458 destval = neg_byte(destval); 4459 store_data_byte(destoffset, destval); 4460 break; 4461 case 4: 4462 DECODE_PRINTF("\n"); 4463 TRACE_AND_STEP(); 4464 mul_byte(destval); 4465 break; 4466 case 5: 4467 DECODE_PRINTF("\n"); 4468 TRACE_AND_STEP(); 4469 imul_byte(destval); 4470 break; 4471 case 6: 4472 DECODE_PRINTF("\n"); 4473 TRACE_AND_STEP(); 4474 div_byte(destval); 4475 break; 4476 default: 4477 DECODE_PRINTF("\n"); 4478 TRACE_AND_STEP(); 4479 idiv_byte(destval); 4480 break; 4481 } 4482 } else { /* mod=11 */ 4483 destreg = DECODE_RM_BYTE_REGISTER(rl); 4484 switch (rh) { 4485 case 0: /* test byte imm */ 4486 DECODE_PRINTF(","); 4487 srcval = fetch_byte_imm(); 4488 DECODE_PRINTF2("%02x\n", srcval); 4489 TRACE_AND_STEP(); 4490 test_byte(*destreg, srcval); 4491 break; 4492 case 1: 4493 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); 4494 HALT_SYS(); 4495 break; 4496 case 2: 4497 DECODE_PRINTF("\n"); 4498 TRACE_AND_STEP(); 4499 *destreg = not_byte(*destreg); 4500 break; 4501 case 3: 4502 DECODE_PRINTF("\n"); 4503 TRACE_AND_STEP(); 4504 *destreg = neg_byte(*destreg); 4505 break; 4506 case 4: 4507 DECODE_PRINTF("\n"); 4508 TRACE_AND_STEP(); 4509 mul_byte(*destreg); /*!!! */ 4510 break; 4511 case 5: 4512 DECODE_PRINTF("\n"); 4513 TRACE_AND_STEP(); 4514 imul_byte(*destreg); 4515 break; 4516 case 6: 4517 DECODE_PRINTF("\n"); 4518 TRACE_AND_STEP(); 4519 div_byte(*destreg); 4520 break; 4521 default: 4522 DECODE_PRINTF("\n"); 4523 TRACE_AND_STEP(); 4524 idiv_byte(*destreg); 4525 break; 4526 } 4527 } 4528 DECODE_CLEAR_SEGOVR(); 4529 END_OF_INSTR(); 4530 } 4531 4532 /**************************************************************************** 4533 REMARKS: 4534 Handles opcode 0xf7 4535 ****************************************************************************/ 4536 void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1)) 4537 { 4538 int mod, rl, rh; 4539 uint destoffset; 4540 4541 START_OF_INSTR(); 4542 FETCH_DECODE_MODRM(mod, rh, rl); 4543 DECODE_PRINTF(opF6_names[rh]); 4544 if (mod < 3) { 4545 4546 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4547 u32 destval, srcval; 4548 4549 DECODE_PRINTF("DWORD PTR "); 4550 destoffset = decode_rmXX_address(mod, rl); 4551 destval = fetch_data_long(destoffset); 4552 4553 switch (rh) { 4554 case 0: 4555 DECODE_PRINTF(","); 4556 srcval = fetch_long_imm(); 4557 DECODE_PRINTF2("%x\n", srcval); 4558 TRACE_AND_STEP(); 4559 test_long(destval, srcval); 4560 break; 4561 case 1: 4562 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n"); 4563 HALT_SYS(); 4564 break; 4565 case 2: 4566 DECODE_PRINTF("\n"); 4567 TRACE_AND_STEP(); 4568 destval = not_long(destval); 4569 store_data_long(destoffset, destval); 4570 break; 4571 case 3: 4572 DECODE_PRINTF("\n"); 4573 TRACE_AND_STEP(); 4574 destval = neg_long(destval); 4575 store_data_long(destoffset, destval); 4576 break; 4577 case 4: 4578 DECODE_PRINTF("\n"); 4579 TRACE_AND_STEP(); 4580 mul_long(destval); 4581 break; 4582 case 5: 4583 DECODE_PRINTF("\n"); 4584 TRACE_AND_STEP(); 4585 imul_long(destval); 4586 break; 4587 case 6: 4588 DECODE_PRINTF("\n"); 4589 TRACE_AND_STEP(); 4590 div_long(destval); 4591 break; 4592 case 7: 4593 DECODE_PRINTF("\n"); 4594 TRACE_AND_STEP(); 4595 idiv_long(destval); 4596 break; 4597 } 4598 } else { 4599 u16 destval, srcval; 4600 4601 DECODE_PRINTF("WORD PTR "); 4602 destoffset = decode_rmXX_address(mod, rl); 4603 destval = fetch_data_word(destoffset); 4604 4605 switch (rh) { 4606 case 0: /* test word imm */ 4607 DECODE_PRINTF(","); 4608 srcval = fetch_word_imm(); 4609 DECODE_PRINTF2("%x\n", srcval); 4610 TRACE_AND_STEP(); 4611 test_word(destval, srcval); 4612 break; 4613 case 1: 4614 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n"); 4615 HALT_SYS(); 4616 break; 4617 case 2: 4618 DECODE_PRINTF("\n"); 4619 TRACE_AND_STEP(); 4620 destval = not_word(destval); 4621 store_data_word(destoffset, destval); 4622 break; 4623 case 3: 4624 DECODE_PRINTF("\n"); 4625 TRACE_AND_STEP(); 4626 destval = neg_word(destval); 4627 store_data_word(destoffset, destval); 4628 break; 4629 case 4: 4630 DECODE_PRINTF("\n"); 4631 TRACE_AND_STEP(); 4632 mul_word(destval); 4633 break; 4634 case 5: 4635 DECODE_PRINTF("\n"); 4636 TRACE_AND_STEP(); 4637 imul_word(destval); 4638 break; 4639 case 6: 4640 DECODE_PRINTF("\n"); 4641 TRACE_AND_STEP(); 4642 div_word(destval); 4643 break; 4644 case 7: 4645 DECODE_PRINTF("\n"); 4646 TRACE_AND_STEP(); 4647 idiv_word(destval); 4648 break; 4649 } 4650 } 4651 4652 } else { /* mod=11 */ 4653 4654 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4655 u32 *destreg; 4656 u32 srcval; 4657 4658 destreg = DECODE_RM_LONG_REGISTER(rl); 4659 4660 switch (rh) { 4661 case 0: /* test word imm */ 4662 DECODE_PRINTF(","); 4663 srcval = fetch_long_imm(); 4664 DECODE_PRINTF2("%x\n", srcval); 4665 TRACE_AND_STEP(); 4666 test_long(*destreg, srcval); 4667 break; 4668 case 1: 4669 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); 4670 HALT_SYS(); 4671 break; 4672 case 2: 4673 DECODE_PRINTF("\n"); 4674 TRACE_AND_STEP(); 4675 *destreg = not_long(*destreg); 4676 break; 4677 case 3: 4678 DECODE_PRINTF("\n"); 4679 TRACE_AND_STEP(); 4680 *destreg = neg_long(*destreg); 4681 break; 4682 case 4: 4683 DECODE_PRINTF("\n"); 4684 TRACE_AND_STEP(); 4685 mul_long(*destreg); /*!!! */ 4686 break; 4687 case 5: 4688 DECODE_PRINTF("\n"); 4689 TRACE_AND_STEP(); 4690 imul_long(*destreg); 4691 break; 4692 case 6: 4693 DECODE_PRINTF("\n"); 4694 TRACE_AND_STEP(); 4695 div_long(*destreg); 4696 break; 4697 case 7: 4698 DECODE_PRINTF("\n"); 4699 TRACE_AND_STEP(); 4700 idiv_long(*destreg); 4701 break; 4702 } 4703 } else { 4704 u16 *destreg; 4705 u16 srcval; 4706 4707 destreg = DECODE_RM_WORD_REGISTER(rl); 4708 4709 switch (rh) { 4710 case 0: /* test word imm */ 4711 DECODE_PRINTF(","); 4712 srcval = fetch_word_imm(); 4713 DECODE_PRINTF2("%x\n", srcval); 4714 TRACE_AND_STEP(); 4715 test_word(*destreg, srcval); 4716 break; 4717 case 1: 4718 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); 4719 HALT_SYS(); 4720 break; 4721 case 2: 4722 DECODE_PRINTF("\n"); 4723 TRACE_AND_STEP(); 4724 *destreg = not_word(*destreg); 4725 break; 4726 case 3: 4727 DECODE_PRINTF("\n"); 4728 TRACE_AND_STEP(); 4729 *destreg = neg_word(*destreg); 4730 break; 4731 case 4: 4732 DECODE_PRINTF("\n"); 4733 TRACE_AND_STEP(); 4734 mul_word(*destreg); /*!!! */ 4735 break; 4736 case 5: 4737 DECODE_PRINTF("\n"); 4738 TRACE_AND_STEP(); 4739 imul_word(*destreg); 4740 break; 4741 case 6: 4742 DECODE_PRINTF("\n"); 4743 TRACE_AND_STEP(); 4744 div_word(*destreg); 4745 break; 4746 case 7: 4747 DECODE_PRINTF("\n"); 4748 TRACE_AND_STEP(); 4749 idiv_word(*destreg); 4750 break; 4751 } 4752 } 4753 } 4754 DECODE_CLEAR_SEGOVR(); 4755 END_OF_INSTR(); 4756 } 4757 4758 /**************************************************************************** 4759 REMARKS: 4760 Handles opcode 0xf8 4761 ****************************************************************************/ 4762 void x86emuOp_clc(u8 X86EMU_UNUSED(op1)) 4763 { 4764 /* clear the carry flag. */ 4765 START_OF_INSTR(); 4766 DECODE_PRINTF("CLC\n"); 4767 TRACE_AND_STEP(); 4768 CLEAR_FLAG(F_CF); 4769 DECODE_CLEAR_SEGOVR(); 4770 END_OF_INSTR(); 4771 } 4772 4773 /**************************************************************************** 4774 REMARKS: 4775 Handles opcode 0xf9 4776 ****************************************************************************/ 4777 void x86emuOp_stc(u8 X86EMU_UNUSED(op1)) 4778 { 4779 /* set the carry flag. */ 4780 START_OF_INSTR(); 4781 DECODE_PRINTF("STC\n"); 4782 TRACE_AND_STEP(); 4783 SET_FLAG(F_CF); 4784 DECODE_CLEAR_SEGOVR(); 4785 END_OF_INSTR(); 4786 } 4787 4788 /**************************************************************************** 4789 REMARKS: 4790 Handles opcode 0xfa 4791 ****************************************************************************/ 4792 void x86emuOp_cli(u8 X86EMU_UNUSED(op1)) 4793 { 4794 /* clear interrupts. */ 4795 START_OF_INSTR(); 4796 DECODE_PRINTF("CLI\n"); 4797 TRACE_AND_STEP(); 4798 CLEAR_FLAG(F_IF); 4799 DECODE_CLEAR_SEGOVR(); 4800 END_OF_INSTR(); 4801 } 4802 4803 /**************************************************************************** 4804 REMARKS: 4805 Handles opcode 0xfb 4806 ****************************************************************************/ 4807 void x86emuOp_sti(u8 X86EMU_UNUSED(op1)) 4808 { 4809 /* enable interrupts. */ 4810 START_OF_INSTR(); 4811 DECODE_PRINTF("STI\n"); 4812 TRACE_AND_STEP(); 4813 SET_FLAG(F_IF); 4814 DECODE_CLEAR_SEGOVR(); 4815 END_OF_INSTR(); 4816 } 4817 4818 /**************************************************************************** 4819 REMARKS: 4820 Handles opcode 0xfc 4821 ****************************************************************************/ 4822 void x86emuOp_cld(u8 X86EMU_UNUSED(op1)) 4823 { 4824 /* clear interrupts. */ 4825 START_OF_INSTR(); 4826 DECODE_PRINTF("CLD\n"); 4827 TRACE_AND_STEP(); 4828 CLEAR_FLAG(F_DF); 4829 DECODE_CLEAR_SEGOVR(); 4830 END_OF_INSTR(); 4831 } 4832 4833 /**************************************************************************** 4834 REMARKS: 4835 Handles opcode 0xfd 4836 ****************************************************************************/ 4837 void x86emuOp_std(u8 X86EMU_UNUSED(op1)) 4838 { 4839 /* clear interrupts. */ 4840 START_OF_INSTR(); 4841 DECODE_PRINTF("STD\n"); 4842 TRACE_AND_STEP(); 4843 SET_FLAG(F_DF); 4844 DECODE_CLEAR_SEGOVR(); 4845 END_OF_INSTR(); 4846 } 4847 4848 /**************************************************************************** 4849 REMARKS: 4850 Handles opcode 0xfe 4851 ****************************************************************************/ 4852 void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1)) 4853 { 4854 int mod, rh, rl; 4855 u8 destval; 4856 uint destoffset; 4857 u8 *destreg; 4858 4859 /* Yet another special case instruction. */ 4860 START_OF_INSTR(); 4861 FETCH_DECODE_MODRM(mod, rh, rl); 4862 #ifdef DEBUG 4863 if (DEBUG_DECODE()) { 4864 /* XXX DECODE_PRINTF may be changed to something more 4865 general, so that it is important to leave the strings 4866 in the same format, even though the result is that the 4867 above test is done twice. */ 4868 4869 switch (rh) { 4870 case 0: 4871 DECODE_PRINTF("INC\t"); 4872 break; 4873 case 1: 4874 DECODE_PRINTF("DEC\t"); 4875 break; 4876 case 2: 4877 case 3: 4878 case 4: 4879 case 5: 4880 case 6: 4881 case 7: 4882 DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod); 4883 HALT_SYS(); 4884 break; 4885 } 4886 } 4887 #endif 4888 if (mod < 3) { 4889 DECODE_PRINTF("BYTE PTR "); 4890 destoffset = decode_rmXX_address(mod, rl); 4891 DECODE_PRINTF("\n"); 4892 destval = fetch_data_byte(destoffset); 4893 TRACE_AND_STEP(); 4894 if (rh == 0) 4895 destval = inc_byte(destval); 4896 else 4897 destval = dec_byte(destval); 4898 store_data_byte(destoffset, destval); 4899 } else { 4900 destreg = DECODE_RM_BYTE_REGISTER(rl); 4901 DECODE_PRINTF("\n"); 4902 TRACE_AND_STEP(); 4903 if (rh == 0) 4904 *destreg = inc_byte(*destreg); 4905 else 4906 *destreg = dec_byte(*destreg); 4907 } 4908 DECODE_CLEAR_SEGOVR(); 4909 END_OF_INSTR(); 4910 } 4911 4912 /**************************************************************************** 4913 REMARKS: 4914 Handles opcode 0xff 4915 ****************************************************************************/ 4916 void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1)) 4917 { 4918 int mod, rh, rl; 4919 uint destoffset = 0; 4920 u16 *destreg; 4921 u16 destval,destval2; 4922 4923 /* Yet another special case instruction. */ 4924 START_OF_INSTR(); 4925 FETCH_DECODE_MODRM(mod, rh, rl); 4926 #ifdef DEBUG 4927 if (DEBUG_DECODE()) { 4928 /* XXX DECODE_PRINTF may be changed to something more 4929 general, so that it is important to leave the strings 4930 in the same format, even though the result is that the 4931 above test is done twice. */ 4932 4933 switch (rh) { 4934 case 0: 4935 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4936 DECODE_PRINTF("INC\tDWORD PTR "); 4937 } else { 4938 DECODE_PRINTF("INC\tWORD PTR "); 4939 } 4940 break; 4941 case 1: 4942 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4943 DECODE_PRINTF("DEC\tDWORD PTR "); 4944 } else { 4945 DECODE_PRINTF("DEC\tWORD PTR "); 4946 } 4947 break; 4948 case 2: 4949 DECODE_PRINTF("CALL\t "); 4950 break; 4951 case 3: 4952 DECODE_PRINTF("CALL\tFAR "); 4953 break; 4954 case 4: 4955 DECODE_PRINTF("JMP\t"); 4956 break; 4957 case 5: 4958 DECODE_PRINTF("JMP\tFAR "); 4959 break; 4960 case 6: 4961 DECODE_PRINTF("PUSH\t"); 4962 break; 4963 case 7: 4964 DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t"); 4965 HALT_SYS(); 4966 break; 4967 } 4968 } 4969 #endif 4970 if (mod < 3) { 4971 destoffset = decode_rmXX_address(mod, rl); 4972 DECODE_PRINTF("\n"); 4973 switch (rh) { 4974 case 0: /* inc word ptr ... */ 4975 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4976 u32 destval; 4977 4978 destval = fetch_data_long(destoffset); 4979 TRACE_AND_STEP(); 4980 destval = inc_long(destval); 4981 store_data_long(destoffset, destval); 4982 } else { 4983 u16 destval; 4984 4985 destval = fetch_data_word(destoffset); 4986 TRACE_AND_STEP(); 4987 destval = inc_word(destval); 4988 store_data_word(destoffset, destval); 4989 } 4990 break; 4991 case 1: /* dec word ptr ... */ 4992 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 4993 u32 destval; 4994 4995 destval = fetch_data_long(destoffset); 4996 TRACE_AND_STEP(); 4997 destval = dec_long(destval); 4998 store_data_long(destoffset, destval); 4999 } else { 5000 u16 destval; 5001 5002 destval = fetch_data_word(destoffset); 5003 TRACE_AND_STEP(); 5004 destval = dec_word(destval); 5005 store_data_word(destoffset, destval); 5006 } 5007 break; 5008 case 2: /* call word ptr ... */ 5009 destval = fetch_data_word(destoffset); 5010 TRACE_AND_STEP(); 5011 push_word(M.x86.R_IP); 5012 M.x86.R_IP = destval; 5013 break; 5014 case 3: /* call far ptr ... */ 5015 destval = fetch_data_word(destoffset); 5016 destval2 = fetch_data_word(destoffset + 2); 5017 TRACE_AND_STEP(); 5018 push_word(M.x86.R_CS); 5019 M.x86.R_CS = destval2; 5020 push_word(M.x86.R_IP); 5021 M.x86.R_IP = destval; 5022 break; 5023 case 4: /* jmp word ptr ... */ 5024 destval = fetch_data_word(destoffset); 5025 TRACE_AND_STEP(); 5026 M.x86.R_IP = destval; 5027 break; 5028 case 5: /* jmp far ptr ... */ 5029 destval = fetch_data_word(destoffset); 5030 destval2 = fetch_data_word(destoffset + 2); 5031 TRACE_AND_STEP(); 5032 M.x86.R_IP = destval; 5033 M.x86.R_CS = destval2; 5034 break; 5035 case 6: /* push word ptr ... */ 5036 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 5037 u32 destval; 5038 5039 destval = fetch_data_long(destoffset); 5040 TRACE_AND_STEP(); 5041 push_long(destval); 5042 } else { 5043 u16 destval; 5044 5045 destval = fetch_data_word(destoffset); 5046 TRACE_AND_STEP(); 5047 push_word(destval); 5048 } 5049 break; 5050 } 5051 } else { 5052 switch (rh) { 5053 case 0: 5054 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 5055 u32 *destreg; 5056 5057 destreg = DECODE_RM_LONG_REGISTER(rl); 5058 DECODE_PRINTF("\n"); 5059 TRACE_AND_STEP(); 5060 *destreg = inc_long(*destreg); 5061 } else { 5062 u16 *destreg; 5063 5064 destreg = DECODE_RM_WORD_REGISTER(rl); 5065 DECODE_PRINTF("\n"); 5066 TRACE_AND_STEP(); 5067 *destreg = inc_word(*destreg); 5068 } 5069 break; 5070 case 1: 5071 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 5072 u32 *destreg; 5073 5074 destreg = DECODE_RM_LONG_REGISTER(rl); 5075 DECODE_PRINTF("\n"); 5076 TRACE_AND_STEP(); 5077 *destreg = dec_long(*destreg); 5078 } else { 5079 u16 *destreg; 5080 5081 destreg = DECODE_RM_WORD_REGISTER(rl); 5082 DECODE_PRINTF("\n"); 5083 TRACE_AND_STEP(); 5084 *destreg = dec_word(*destreg); 5085 } 5086 break; 5087 case 2: /* call word ptr ... */ 5088 destreg = DECODE_RM_WORD_REGISTER(rl); 5089 DECODE_PRINTF("\n"); 5090 TRACE_AND_STEP(); 5091 push_word(M.x86.R_IP); 5092 M.x86.R_IP = *destreg; 5093 break; 5094 case 3: /* jmp far ptr ... */ 5095 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n"); 5096 TRACE_AND_STEP(); 5097 HALT_SYS(); 5098 break; 5099 5100 case 4: /* jmp ... */ 5101 destreg = DECODE_RM_WORD_REGISTER(rl); 5102 DECODE_PRINTF("\n"); 5103 TRACE_AND_STEP(); 5104 M.x86.R_IP = (u16) (*destreg); 5105 break; 5106 case 5: /* jmp far ptr ... */ 5107 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n"); 5108 TRACE_AND_STEP(); 5109 HALT_SYS(); 5110 break; 5111 case 6: 5112 if (M.x86.mode & SYSMODE_PREFIX_DATA) { 5113 u32 *destreg; 5114 5115 destreg = DECODE_RM_LONG_REGISTER(rl); 5116 DECODE_PRINTF("\n"); 5117 TRACE_AND_STEP(); 5118 push_long(*destreg); 5119 } else { 5120 u16 *destreg; 5121 5122 destreg = DECODE_RM_WORD_REGISTER(rl); 5123 DECODE_PRINTF("\n"); 5124 TRACE_AND_STEP(); 5125 push_word(*destreg); 5126 } 5127 break; 5128 } 5129 } 5130 DECODE_CLEAR_SEGOVR(); 5131 END_OF_INSTR(); 5132 } 5133 5134 /*************************************************************************** 5135 * Single byte operation code table: 5136 **************************************************************************/ 5137 void (*x86emu_optab[256])(u8) = 5138 { 5139 /* 0x00 */ x86emuOp_genop_byte_RM_R, 5140 /* 0x01 */ x86emuOp_genop_word_RM_R, 5141 /* 0x02 */ x86emuOp_genop_byte_R_RM, 5142 /* 0x03 */ x86emuOp_genop_word_R_RM, 5143 /* 0x04 */ x86emuOp_genop_byte_AL_IMM, 5144 /* 0x05 */ x86emuOp_genop_word_AX_IMM, 5145 /* 0x06 */ x86emuOp_push_ES, 5146 /* 0x07 */ x86emuOp_pop_ES, 5147 5148 /* 0x08 */ x86emuOp_genop_byte_RM_R, 5149 /* 0x09 */ x86emuOp_genop_word_RM_R, 5150 /* 0x0a */ x86emuOp_genop_byte_R_RM, 5151 /* 0x0b */ x86emuOp_genop_word_R_RM, 5152 /* 0x0c */ x86emuOp_genop_byte_AL_IMM, 5153 /* 0x0d */ x86emuOp_genop_word_AX_IMM, 5154 /* 0x0e */ x86emuOp_push_CS, 5155 /* 0x0f */ x86emuOp_two_byte, 5156 5157 /* 0x10 */ x86emuOp_genop_byte_RM_R, 5158 /* 0x11 */ x86emuOp_genop_word_RM_R, 5159 /* 0x12 */ x86emuOp_genop_byte_R_RM, 5160 /* 0x13 */ x86emuOp_genop_word_R_RM, 5161 /* 0x14 */ x86emuOp_genop_byte_AL_IMM, 5162 /* 0x15 */ x86emuOp_genop_word_AX_IMM, 5163 /* 0x16 */ x86emuOp_push_SS, 5164 /* 0x17 */ x86emuOp_pop_SS, 5165 5166 /* 0x18 */ x86emuOp_genop_byte_RM_R, 5167 /* 0x19 */ x86emuOp_genop_word_RM_R, 5168 /* 0x1a */ x86emuOp_genop_byte_R_RM, 5169 /* 0x1b */ x86emuOp_genop_word_R_RM, 5170 /* 0x1c */ x86emuOp_genop_byte_AL_IMM, 5171 /* 0x1d */ x86emuOp_genop_word_AX_IMM, 5172 /* 0x1e */ x86emuOp_push_DS, 5173 /* 0x1f */ x86emuOp_pop_DS, 5174 5175 /* 0x20 */ x86emuOp_genop_byte_RM_R, 5176 /* 0x21 */ x86emuOp_genop_word_RM_R, 5177 /* 0x22 */ x86emuOp_genop_byte_R_RM, 5178 /* 0x23 */ x86emuOp_genop_word_R_RM, 5179 /* 0x24 */ x86emuOp_genop_byte_AL_IMM, 5180 /* 0x25 */ x86emuOp_genop_word_AX_IMM, 5181 /* 0x26 */ x86emuOp_segovr_ES, 5182 /* 0x27 */ x86emuOp_daa, 5183 5184 /* 0x28 */ x86emuOp_genop_byte_RM_R, 5185 /* 0x29 */ x86emuOp_genop_word_RM_R, 5186 /* 0x2a */ x86emuOp_genop_byte_R_RM, 5187 /* 0x2b */ x86emuOp_genop_word_R_RM, 5188 /* 0x2c */ x86emuOp_genop_byte_AL_IMM, 5189 /* 0x2d */ x86emuOp_genop_word_AX_IMM, 5190 /* 0x2e */ x86emuOp_segovr_CS, 5191 /* 0x2f */ x86emuOp_das, 5192 5193 /* 0x30 */ x86emuOp_genop_byte_RM_R, 5194 /* 0x31 */ x86emuOp_genop_word_RM_R, 5195 /* 0x32 */ x86emuOp_genop_byte_R_RM, 5196 /* 0x33 */ x86emuOp_genop_word_R_RM, 5197 /* 0x34 */ x86emuOp_genop_byte_AL_IMM, 5198 /* 0x35 */ x86emuOp_genop_word_AX_IMM, 5199 /* 0x36 */ x86emuOp_segovr_SS, 5200 /* 0x37 */ x86emuOp_aaa, 5201 5202 /* 0x38 */ x86emuOp_genop_byte_RM_R, 5203 /* 0x39 */ x86emuOp_genop_word_RM_R, 5204 /* 0x3a */ x86emuOp_genop_byte_R_RM, 5205 /* 0x3b */ x86emuOp_genop_word_R_RM, 5206 /* 0x3c */ x86emuOp_genop_byte_AL_IMM, 5207 /* 0x3d */ x86emuOp_genop_word_AX_IMM, 5208 /* 0x3e */ x86emuOp_segovr_DS, 5209 /* 0x3f */ x86emuOp_aas, 5210 5211 /* 0x40 */ x86emuOp_inc_register, 5212 /* 0x41 */ x86emuOp_inc_register, 5213 /* 0x42 */ x86emuOp_inc_register, 5214 /* 0x43 */ x86emuOp_inc_register, 5215 /* 0x44 */ x86emuOp_inc_register, 5216 /* 0x45 */ x86emuOp_inc_register, 5217 /* 0x46 */ x86emuOp_inc_register, 5218 /* 0x47 */ x86emuOp_inc_register, 5219 5220 /* 0x48 */ x86emuOp_dec_register, 5221 /* 0x49 */ x86emuOp_dec_register, 5222 /* 0x4a */ x86emuOp_dec_register, 5223 /* 0x4b */ x86emuOp_dec_register, 5224 /* 0x4c */ x86emuOp_dec_register, 5225 /* 0x4d */ x86emuOp_dec_register, 5226 /* 0x4e */ x86emuOp_dec_register, 5227 /* 0x4f */ x86emuOp_dec_register, 5228 5229 /* 0x50 */ x86emuOp_push_register, 5230 /* 0x51 */ x86emuOp_push_register, 5231 /* 0x52 */ x86emuOp_push_register, 5232 /* 0x53 */ x86emuOp_push_register, 5233 /* 0x54 */ x86emuOp_push_register, 5234 /* 0x55 */ x86emuOp_push_register, 5235 /* 0x56 */ x86emuOp_push_register, 5236 /* 0x57 */ x86emuOp_push_register, 5237 5238 /* 0x58 */ x86emuOp_pop_register, 5239 /* 0x59 */ x86emuOp_pop_register, 5240 /* 0x5a */ x86emuOp_pop_register, 5241 /* 0x5b */ x86emuOp_pop_register, 5242 /* 0x5c */ x86emuOp_pop_register, 5243 /* 0x5d */ x86emuOp_pop_register, 5244 /* 0x5e */ x86emuOp_pop_register, 5245 /* 0x5f */ x86emuOp_pop_register, 5246 5247 /* 0x60 */ x86emuOp_push_all, 5248 /* 0x61 */ x86emuOp_pop_all, 5249 /* 0x62 */ x86emuOp_illegal_op, /* bound */ 5250 /* 0x63 */ x86emuOp_illegal_op, /* arpl */ 5251 /* 0x64 */ x86emuOp_segovr_FS, 5252 /* 0x65 */ x86emuOp_segovr_GS, 5253 /* 0x66 */ x86emuOp_prefix_data, 5254 /* 0x67 */ x86emuOp_prefix_addr, 5255 5256 /* 0x68 */ x86emuOp_push_word_IMM, 5257 /* 0x69 */ x86emuOp_imul_word_IMM, 5258 /* 0x6a */ x86emuOp_push_byte_IMM, 5259 /* 0x6b */ x86emuOp_imul_byte_IMM, 5260 /* 0x6c */ x86emuOp_ins_byte, 5261 /* 0x6d */ x86emuOp_ins_word, 5262 /* 0x6e */ x86emuOp_outs_byte, 5263 /* 0x6f */ x86emuOp_outs_word, 5264 5265 /* 0x70 */ x86emuOp_jump_near_cond, 5266 /* 0x71 */ x86emuOp_jump_near_cond, 5267 /* 0x72 */ x86emuOp_jump_near_cond, 5268 /* 0x73 */ x86emuOp_jump_near_cond, 5269 /* 0x74 */ x86emuOp_jump_near_cond, 5270 /* 0x75 */ x86emuOp_jump_near_cond, 5271 /* 0x76 */ x86emuOp_jump_near_cond, 5272 /* 0x77 */ x86emuOp_jump_near_cond, 5273 5274 /* 0x78 */ x86emuOp_jump_near_cond, 5275 /* 0x79 */ x86emuOp_jump_near_cond, 5276 /* 0x7a */ x86emuOp_jump_near_cond, 5277 /* 0x7b */ x86emuOp_jump_near_cond, 5278 /* 0x7c */ x86emuOp_jump_near_cond, 5279 /* 0x7d */ x86emuOp_jump_near_cond, 5280 /* 0x7e */ x86emuOp_jump_near_cond, 5281 /* 0x7f */ x86emuOp_jump_near_cond, 5282 5283 /* 0x80 */ x86emuOp_opc80_byte_RM_IMM, 5284 /* 0x81 */ x86emuOp_opc81_word_RM_IMM, 5285 /* 0x82 */ x86emuOp_opc82_byte_RM_IMM, 5286 /* 0x83 */ x86emuOp_opc83_word_RM_IMM, 5287 /* 0x84 */ x86emuOp_test_byte_RM_R, 5288 /* 0x85 */ x86emuOp_test_word_RM_R, 5289 /* 0x86 */ x86emuOp_xchg_byte_RM_R, 5290 /* 0x87 */ x86emuOp_xchg_word_RM_R, 5291 5292 /* 0x88 */ x86emuOp_mov_byte_RM_R, 5293 /* 0x89 */ x86emuOp_mov_word_RM_R, 5294 /* 0x8a */ x86emuOp_mov_byte_R_RM, 5295 /* 0x8b */ x86emuOp_mov_word_R_RM, 5296 /* 0x8c */ x86emuOp_mov_word_RM_SR, 5297 /* 0x8d */ x86emuOp_lea_word_R_M, 5298 /* 0x8e */ x86emuOp_mov_word_SR_RM, 5299 /* 0x8f */ x86emuOp_pop_RM, 5300 5301 /* 0x90 */ x86emuOp_nop, 5302 /* 0x91 */ x86emuOp_xchg_word_AX_register, 5303 /* 0x92 */ x86emuOp_xchg_word_AX_register, 5304 /* 0x93 */ x86emuOp_xchg_word_AX_register, 5305 /* 0x94 */ x86emuOp_xchg_word_AX_register, 5306 /* 0x95 */ x86emuOp_xchg_word_AX_register, 5307 /* 0x96 */ x86emuOp_xchg_word_AX_register, 5308 /* 0x97 */ x86emuOp_xchg_word_AX_register, 5309 5310 /* 0x98 */ x86emuOp_cbw, 5311 /* 0x99 */ x86emuOp_cwd, 5312 /* 0x9a */ x86emuOp_call_far_IMM, 5313 /* 0x9b */ x86emuOp_wait, 5314 /* 0x9c */ x86emuOp_pushf_word, 5315 /* 0x9d */ x86emuOp_popf_word, 5316 /* 0x9e */ x86emuOp_sahf, 5317 /* 0x9f */ x86emuOp_lahf, 5318 5319 /* 0xa0 */ x86emuOp_mov_AL_M_IMM, 5320 /* 0xa1 */ x86emuOp_mov_AX_M_IMM, 5321 /* 0xa2 */ x86emuOp_mov_M_AL_IMM, 5322 /* 0xa3 */ x86emuOp_mov_M_AX_IMM, 5323 /* 0xa4 */ x86emuOp_movs_byte, 5324 /* 0xa5 */ x86emuOp_movs_word, 5325 /* 0xa6 */ x86emuOp_cmps_byte, 5326 /* 0xa7 */ x86emuOp_cmps_word, 5327 /* 0xa8 */ x86emuOp_test_AL_IMM, 5328 /* 0xa9 */ x86emuOp_test_AX_IMM, 5329 /* 0xaa */ x86emuOp_stos_byte, 5330 /* 0xab */ x86emuOp_stos_word, 5331 /* 0xac */ x86emuOp_lods_byte, 5332 /* 0xad */ x86emuOp_lods_word, 5333 /* 0xac */ x86emuOp_scas_byte, 5334 /* 0xad */ x86emuOp_scas_word, 5335 5336 /* 0xb0 */ x86emuOp_mov_byte_register_IMM, 5337 /* 0xb1 */ x86emuOp_mov_byte_register_IMM, 5338 /* 0xb2 */ x86emuOp_mov_byte_register_IMM, 5339 /* 0xb3 */ x86emuOp_mov_byte_register_IMM, 5340 /* 0xb4 */ x86emuOp_mov_byte_register_IMM, 5341 /* 0xb5 */ x86emuOp_mov_byte_register_IMM, 5342 /* 0xb6 */ x86emuOp_mov_byte_register_IMM, 5343 /* 0xb7 */ x86emuOp_mov_byte_register_IMM, 5344 5345 /* 0xb8 */ x86emuOp_mov_word_register_IMM, 5346 /* 0xb9 */ x86emuOp_mov_word_register_IMM, 5347 /* 0xba */ x86emuOp_mov_word_register_IMM, 5348 /* 0xbb */ x86emuOp_mov_word_register_IMM, 5349 /* 0xbc */ x86emuOp_mov_word_register_IMM, 5350 /* 0xbd */ x86emuOp_mov_word_register_IMM, 5351 /* 0xbe */ x86emuOp_mov_word_register_IMM, 5352 /* 0xbf */ x86emuOp_mov_word_register_IMM, 5353 5354 /* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM, 5355 /* 0xc1 */ x86emuOp_opcC1_word_RM_MEM, 5356 /* 0xc2 */ x86emuOp_ret_near_IMM, 5357 /* 0xc3 */ x86emuOp_ret_near, 5358 /* 0xc4 */ x86emuOp_les_R_IMM, 5359 /* 0xc5 */ x86emuOp_lds_R_IMM, 5360 /* 0xc6 */ x86emuOp_mov_byte_RM_IMM, 5361 /* 0xc7 */ x86emuOp_mov_word_RM_IMM, 5362 /* 0xc8 */ x86emuOp_enter, 5363 /* 0xc9 */ x86emuOp_leave, 5364 /* 0xca */ x86emuOp_ret_far_IMM, 5365 /* 0xcb */ x86emuOp_ret_far, 5366 /* 0xcc */ x86emuOp_int3, 5367 /* 0xcd */ x86emuOp_int_IMM, 5368 /* 0xce */ x86emuOp_into, 5369 /* 0xcf */ x86emuOp_iret, 5370 5371 /* 0xd0 */ x86emuOp_opcD0_byte_RM_1, 5372 /* 0xd1 */ x86emuOp_opcD1_word_RM_1, 5373 /* 0xd2 */ x86emuOp_opcD2_byte_RM_CL, 5374 /* 0xd3 */ x86emuOp_opcD3_word_RM_CL, 5375 /* 0xd4 */ x86emuOp_aam, 5376 /* 0xd5 */ x86emuOp_aad, 5377 /* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */ 5378 /* 0xd7 */ x86emuOp_xlat, 5379 /* 0xd8 */ NULL, /*x86emuOp_esc_coprocess_d8,*/ 5380 /* 0xd9 */ NULL, /*x86emuOp_esc_coprocess_d9,*/ 5381 /* 0xda */ NULL, /*x86emuOp_esc_coprocess_da,*/ 5382 /* 0xdb */ NULL, /*x86emuOp_esc_coprocess_db,*/ 5383 /* 0xdc */ NULL, /*x86emuOp_esc_coprocess_dc,*/ 5384 /* 0xdd */ NULL, /*x86emuOp_esc_coprocess_dd,*/ 5385 /* 0xde */ NULL, /*x86emuOp_esc_coprocess_de,*/ 5386 /* 0xdf */ NULL, /*x86emuOp_esc_coprocess_df,*/ 5387 5388 /* 0xe0 */ x86emuOp_loopne, 5389 /* 0xe1 */ x86emuOp_loope, 5390 /* 0xe2 */ x86emuOp_loop, 5391 /* 0xe3 */ x86emuOp_jcxz, 5392 /* 0xe4 */ x86emuOp_in_byte_AL_IMM, 5393 /* 0xe5 */ x86emuOp_in_word_AX_IMM, 5394 /* 0xe6 */ x86emuOp_out_byte_IMM_AL, 5395 /* 0xe7 */ x86emuOp_out_word_IMM_AX, 5396 5397 /* 0xe8 */ x86emuOp_call_near_IMM, 5398 /* 0xe9 */ x86emuOp_jump_near_IMM, 5399 /* 0xea */ x86emuOp_jump_far_IMM, 5400 /* 0xeb */ x86emuOp_jump_byte_IMM, 5401 /* 0xec */ x86emuOp_in_byte_AL_DX, 5402 /* 0xed */ x86emuOp_in_word_AX_DX, 5403 /* 0xee */ x86emuOp_out_byte_DX_AL, 5404 /* 0xef */ x86emuOp_out_word_DX_AX, 5405 5406 /* 0xf0 */ x86emuOp_lock, 5407 /* 0xf1 */ x86emuOp_illegal_op, 5408 /* 0xf2 */ x86emuOp_repne, 5409 /* 0xf3 */ x86emuOp_repe, 5410 /* 0xf4 */ x86emuOp_halt, 5411 /* 0xf5 */ x86emuOp_cmc, 5412 /* 0xf6 */ x86emuOp_opcF6_byte_RM, 5413 /* 0xf7 */ x86emuOp_opcF7_word_RM, 5414 5415 /* 0xf8 */ x86emuOp_clc, 5416 /* 0xf9 */ x86emuOp_stc, 5417 /* 0xfa */ x86emuOp_cli, 5418 /* 0xfb */ x86emuOp_sti, 5419 /* 0xfc */ x86emuOp_cld, 5420 /* 0xfd */ x86emuOp_std, 5421 /* 0xfe */ x86emuOp_opcFE_byte_RM, 5422 /* 0xff */ x86emuOp_opcFF_word_RM, 5423 }; 5424