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