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