1 /* $NetBSD: x86emu.c,v 1.3 2007/12/13 16:41:59 joerg Exp $ */ 2 3 /**************************************************************************** 4 * 5 * Realmode X86 Emulator Library 6 * 7 * Copyright (C) 1996-1999 SciTech Software, Inc. 8 * Copyright (C) David Mosberger-Tang 9 * Copyright (C) 1999 Egbert Eich 10 * Copyright (C) 2007 Joerg Sonnenberger 11 * 12 * ======================================================================== 13 * 14 * Permission to use, copy, modify, distribute, and sell this software and 15 * its documentation for any purpose is hereby granted without fee, 16 * provided that the above copyright notice appear in all copies and that 17 * both that copyright notice and this permission notice appear in 18 * supporting documentation, and that the name of the authors not be used 19 * in advertising or publicity pertaining to distribution of the software 20 * without specific, written prior permission. The authors makes no 21 * representations about the suitability of this software for any purpose. 22 * It is provided "as is" without express or implied warranty. 23 * 24 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 25 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 26 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 27 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 28 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 29 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 30 * PERFORMANCE OF THIS SOFTWARE. 31 * 32 ****************************************************************************/ 33 34 #ifndef _KERNEL 35 #include <stdbool.h> 36 #endif 37 38 #include <x86emu/x86emu.h> 39 #include <x86emu/x86emu_regs.h> 40 41 static void x86emu_intr_raise (struct X86EMU *, uint8_t type); 42 43 static void X86EMU_exec_one_byte(struct X86EMU *); 44 static void X86EMU_exec_two_byte(struct X86EMU *); 45 46 static void fetch_decode_modrm (struct X86EMU *); 47 static uint8_t fetch_byte_imm (struct X86EMU *); 48 static uint16_t fetch_word_imm (struct X86EMU *); 49 static uint32_t fetch_long_imm (struct X86EMU *); 50 static uint8_t fetch_data_byte (struct X86EMU *, uint32_t offset); 51 static uint8_t fetch_byte (struct X86EMU *, uint segment, uint32_t offset); 52 static uint16_t fetch_data_word (struct X86EMU *, uint32_t offset); 53 static uint16_t fetch_word (struct X86EMU *, uint32_t segment, uint32_t offset); 54 static uint32_t fetch_data_long (struct X86EMU *, uint32_t offset); 55 static uint32_t fetch_long (struct X86EMU *, uint32_t segment, uint32_t offset); 56 static void store_data_byte (struct X86EMU *, uint32_t offset, uint8_t val); 57 static void store_byte (struct X86EMU *, uint32_t segment, uint32_t offset, uint8_t val); 58 static void store_data_word (struct X86EMU *, uint32_t offset, uint16_t val); 59 static void store_word (struct X86EMU *, uint32_t segment, uint32_t offset, uint16_t val); 60 static void store_data_long (struct X86EMU *, uint32_t offset, uint32_t val); 61 static void store_long (struct X86EMU *, uint32_t segment, uint32_t offset, uint32_t val); 62 static uint8_t* decode_rl_byte_register(struct X86EMU *); 63 static uint16_t* decode_rl_word_register(struct X86EMU *); 64 static uint32_t* decode_rl_long_register(struct X86EMU *); 65 static uint8_t* decode_rh_byte_register(struct X86EMU *); 66 static uint16_t* decode_rh_word_register(struct X86EMU *); 67 static uint32_t* decode_rh_long_register(struct X86EMU *); 68 static uint16_t* decode_rh_seg_register(struct X86EMU *); 69 static uint32_t decode_rl_address(struct X86EMU *); 70 71 static uint8_t decode_and_fetch_byte(struct X86EMU *); 72 static uint16_t decode_and_fetch_word(struct X86EMU *); 73 static uint32_t decode_and_fetch_long(struct X86EMU *); 74 75 static uint8_t decode_and_fetch_byte_imm8(struct X86EMU *, uint8_t *); 76 static uint16_t decode_and_fetch_word_imm8(struct X86EMU *, uint8_t *); 77 static uint32_t decode_and_fetch_long_imm8(struct X86EMU *, uint8_t *); 78 79 static uint16_t decode_and_fetch_word_disp(struct X86EMU *, int16_t); 80 static uint32_t decode_and_fetch_long_disp(struct X86EMU *, int16_t); 81 82 static void write_back_byte(struct X86EMU *, uint8_t); 83 static void write_back_word(struct X86EMU *, uint16_t); 84 static void write_back_long(struct X86EMU *, uint32_t); 85 86 static uint16_t aaa_word (struct X86EMU *, uint16_t d); 87 static uint16_t aas_word (struct X86EMU *, uint16_t d); 88 static uint16_t aad_word (struct X86EMU *, uint16_t d); 89 static uint16_t aam_word (struct X86EMU *, uint8_t d); 90 static uint8_t adc_byte (struct X86EMU *, uint8_t d, uint8_t s); 91 static uint16_t adc_word (struct X86EMU *, uint16_t d, uint16_t s); 92 static uint32_t adc_long (struct X86EMU *, uint32_t d, uint32_t s); 93 static uint8_t add_byte (struct X86EMU *, uint8_t d, uint8_t s); 94 static uint16_t add_word (struct X86EMU *, uint16_t d, uint16_t s); 95 static uint32_t add_long (struct X86EMU *, uint32_t d, uint32_t s); 96 static uint8_t and_byte (struct X86EMU *, uint8_t d, uint8_t s); 97 static uint16_t and_word (struct X86EMU *, uint16_t d, uint16_t s); 98 static uint32_t and_long (struct X86EMU *, uint32_t d, uint32_t s); 99 static uint8_t cmp_byte (struct X86EMU *, uint8_t d, uint8_t s); 100 static uint16_t cmp_word (struct X86EMU *, uint16_t d, uint16_t s); 101 static uint32_t cmp_long (struct X86EMU *, uint32_t d, uint32_t s); 102 static void cmp_byte_no_return (struct X86EMU *, uint8_t d, uint8_t s); 103 static void cmp_word_no_return (struct X86EMU *, uint16_t d, uint16_t s); 104 static void cmp_long_no_return (struct X86EMU *, uint32_t d, uint32_t s); 105 static uint8_t daa_byte (struct X86EMU *, uint8_t d); 106 static uint8_t das_byte (struct X86EMU *, uint8_t d); 107 static uint8_t dec_byte (struct X86EMU *, uint8_t d); 108 static uint16_t dec_word (struct X86EMU *, uint16_t d); 109 static uint32_t dec_long (struct X86EMU *, uint32_t d); 110 static uint8_t inc_byte (struct X86EMU *, uint8_t d); 111 static uint16_t inc_word (struct X86EMU *, uint16_t d); 112 static uint32_t inc_long (struct X86EMU *, uint32_t d); 113 static uint8_t or_byte (struct X86EMU *, uint8_t d, uint8_t s); 114 static uint16_t or_word (struct X86EMU *, uint16_t d, uint16_t s); 115 static uint32_t or_long (struct X86EMU *, uint32_t d, uint32_t s); 116 static uint8_t neg_byte (struct X86EMU *, uint8_t s); 117 static uint16_t neg_word (struct X86EMU *, uint16_t s); 118 static uint32_t neg_long (struct X86EMU *, uint32_t s); 119 static uint8_t rcl_byte (struct X86EMU *, uint8_t d, uint8_t s); 120 static uint16_t rcl_word (struct X86EMU *, uint16_t d, uint8_t s); 121 static uint32_t rcl_long (struct X86EMU *, uint32_t d, uint8_t s); 122 static uint8_t rcr_byte (struct X86EMU *, uint8_t d, uint8_t s); 123 static uint16_t rcr_word (struct X86EMU *, uint16_t d, uint8_t s); 124 static uint32_t rcr_long (struct X86EMU *, uint32_t d, uint8_t s); 125 static uint8_t rol_byte (struct X86EMU *, uint8_t d, uint8_t s); 126 static uint16_t rol_word (struct X86EMU *, uint16_t d, uint8_t s); 127 static uint32_t rol_long (struct X86EMU *, uint32_t d, uint8_t s); 128 static uint8_t ror_byte (struct X86EMU *, uint8_t d, uint8_t s); 129 static uint16_t ror_word (struct X86EMU *, uint16_t d, uint8_t s); 130 static uint32_t ror_long (struct X86EMU *, uint32_t d, uint8_t s); 131 static uint8_t shl_byte (struct X86EMU *, uint8_t d, uint8_t s); 132 static uint16_t shl_word (struct X86EMU *, uint16_t d, uint8_t s); 133 static uint32_t shl_long (struct X86EMU *, uint32_t d, uint8_t s); 134 static uint8_t shr_byte (struct X86EMU *, uint8_t d, uint8_t s); 135 static uint16_t shr_word (struct X86EMU *, uint16_t d, uint8_t s); 136 static uint32_t shr_long (struct X86EMU *, uint32_t d, uint8_t s); 137 static uint8_t sar_byte (struct X86EMU *, uint8_t d, uint8_t s); 138 static uint16_t sar_word (struct X86EMU *, uint16_t d, uint8_t s); 139 static uint32_t sar_long (struct X86EMU *, uint32_t d, uint8_t s); 140 static uint16_t shld_word (struct X86EMU *, uint16_t d, uint16_t fill, uint8_t s); 141 static uint32_t shld_long (struct X86EMU *, uint32_t d, uint32_t fill, uint8_t s); 142 static uint16_t shrd_word (struct X86EMU *, uint16_t d, uint16_t fill, uint8_t s); 143 static uint32_t shrd_long (struct X86EMU *, uint32_t d, uint32_t fill, uint8_t s); 144 static uint8_t sbb_byte (struct X86EMU *, uint8_t d, uint8_t s); 145 static uint16_t sbb_word (struct X86EMU *, uint16_t d, uint16_t s); 146 static uint32_t sbb_long (struct X86EMU *, uint32_t d, uint32_t s); 147 static uint8_t sub_byte (struct X86EMU *, uint8_t d, uint8_t s); 148 static uint16_t sub_word (struct X86EMU *, uint16_t d, uint16_t s); 149 static uint32_t sub_long (struct X86EMU *, uint32_t d, uint32_t s); 150 static void test_byte (struct X86EMU *, uint8_t d, uint8_t s); 151 static void test_word (struct X86EMU *, uint16_t d, uint16_t s); 152 static void test_long (struct X86EMU *, uint32_t d, uint32_t s); 153 static uint8_t xor_byte (struct X86EMU *, uint8_t d, uint8_t s); 154 static uint16_t xor_word (struct X86EMU *, uint16_t d, uint16_t s); 155 static uint32_t xor_long (struct X86EMU *, uint32_t d, uint32_t s); 156 static void imul_byte (struct X86EMU *, uint8_t s); 157 static void imul_word (struct X86EMU *, uint16_t s); 158 static void imul_long (struct X86EMU *, uint32_t s); 159 static void mul_byte (struct X86EMU *, uint8_t s); 160 static void mul_word (struct X86EMU *, uint16_t s); 161 static void mul_long (struct X86EMU *, uint32_t s); 162 static void idiv_byte (struct X86EMU *, uint8_t s); 163 static void idiv_word (struct X86EMU *, uint16_t s); 164 static void idiv_long (struct X86EMU *, uint32_t s); 165 static void div_byte (struct X86EMU *, uint8_t s); 166 static void div_word (struct X86EMU *, uint16_t s); 167 static void div_long (struct X86EMU *, uint32_t s); 168 static void ins (struct X86EMU *, int size); 169 static void outs (struct X86EMU *, int size); 170 static void push_word (struct X86EMU *, uint16_t w); 171 static void push_long (struct X86EMU *, uint32_t w); 172 static uint16_t pop_word (struct X86EMU *); 173 static uint32_t pop_long (struct X86EMU *); 174 175 /**************************************************************************** 176 REMARKS: 177 Handles any pending asychronous interrupts. 178 ****************************************************************************/ 179 static void 180 x86emu_intr_dispatch(struct X86EMU *emu, uint8_t intno) 181 { 182 if (emu->_X86EMU_intrTab[intno]) { 183 (*emu->_X86EMU_intrTab[intno]) (emu, intno); 184 } else { 185 push_word(emu, (uint16_t) emu->x86.R_FLG); 186 CLEAR_FLAG(F_IF); 187 CLEAR_FLAG(F_TF); 188 push_word(emu, emu->x86.R_CS); 189 emu->x86.R_CS = fetch_word(emu, 0, intno * 4 + 2); 190 push_word(emu, emu->x86.R_IP); 191 emu->x86.R_IP = fetch_word(emu, 0, intno * 4); 192 } 193 } 194 195 static void 196 x86emu_intr_handle(struct X86EMU *emu) 197 { 198 uint8_t intno; 199 200 if (emu->x86.intr & INTR_SYNCH) { 201 intno = emu->x86.intno; 202 emu->x86.intr = 0; 203 x86emu_intr_dispatch(emu, intno); 204 } 205 } 206 /**************************************************************************** 207 PARAMETERS: 208 intrnum - Interrupt number to raise 209 210 REMARKS: 211 Raise the specified interrupt to be handled before the execution of the 212 next instruction. 213 ****************************************************************************/ 214 void 215 x86emu_intr_raise(struct X86EMU *emu, uint8_t intrnum) 216 { 217 emu->x86.intno = intrnum; 218 emu->x86.intr |= INTR_SYNCH; 219 } 220 /**************************************************************************** 221 REMARKS: 222 Main execution loop for the emulator. We return from here when the system 223 halts, which is normally caused by a stack fault when we return from the 224 original real mode call. 225 ****************************************************************************/ 226 void 227 X86EMU_exec(struct X86EMU *emu) 228 { 229 emu->x86.intr = 0; 230 231 #ifdef _KERNEL 232 if (setjmp(&emu->exec_state)) 233 return; 234 #else 235 if (setjmp(emu->exec_state)) 236 return; 237 #endif 238 239 for (;;) { 240 if (emu->x86.intr) { 241 if (((emu->x86.intr & INTR_SYNCH) && (emu->x86.intno == 0 || emu->x86.intno == 2)) || 242 !ACCESS_FLAG(F_IF)) { 243 x86emu_intr_handle(emu); 244 } 245 } 246 X86EMU_exec_one_byte(emu); 247 ++emu->cur_cycles; 248 } 249 } 250 251 void 252 X86EMU_exec_call(struct X86EMU *emu, uint16_t seg, uint16_t off) 253 { 254 push_word(emu, 0); 255 push_word(emu, 0); 256 emu->x86.R_CS = seg; 257 emu->x86.R_IP = off; 258 259 X86EMU_exec(emu); 260 } 261 262 void 263 X86EMU_exec_intr(struct X86EMU *emu, uint8_t intr) 264 { 265 push_word(emu, emu->x86.R_FLG); 266 CLEAR_FLAG(F_IF); 267 CLEAR_FLAG(F_TF); 268 push_word(emu, 0); 269 push_word(emu, 0); 270 emu->x86.R_CS = (*emu->emu_rdw)(emu, intr * 4 + 2); 271 emu->x86.R_IP = (*emu->emu_rdw)(emu, intr * 4); 272 emu->x86.intr = 0; 273 274 X86EMU_exec(emu); 275 } 276 /**************************************************************************** 277 REMARKS: 278 Halts the system by setting the halted system flag. 279 ****************************************************************************/ 280 void 281 X86EMU_halt_sys(struct X86EMU *emu) 282 { 283 #ifdef _KERNEL 284 longjmp(&emu->exec_state); 285 #else 286 longjmp(emu->exec_state, 1); 287 #endif 288 } 289 /**************************************************************************** 290 PARAMETERS: 291 mod - Mod value from decoded byte 292 regh - Reg h value from decoded byte 293 regl - Reg l value from decoded byte 294 295 REMARKS: 296 Raise the specified interrupt to be handled before the execution of the 297 next instruction. 298 299 NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline! 300 ****************************************************************************/ 301 static void 302 fetch_decode_modrm(struct X86EMU *emu) 303 { 304 int fetched; 305 306 fetched = fetch_byte_imm(emu); 307 emu->cur_mod = (fetched >> 6) & 0x03; 308 emu->cur_rh = (fetched >> 3) & 0x07; 309 emu->cur_rl = (fetched >> 0) & 0x07; 310 } 311 /**************************************************************************** 312 RETURNS: 313 Immediate byte value read from instruction queue 314 315 REMARKS: 316 This function returns the immediate byte from the instruction queue, and 317 moves the instruction pointer to the next value. 318 319 NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline! 320 ****************************************************************************/ 321 static uint8_t 322 fetch_byte_imm(struct X86EMU *emu) 323 { 324 uint8_t fetched; 325 326 fetched = fetch_byte(emu, emu->x86.R_CS, emu->x86.R_IP); 327 emu->x86.R_IP++; 328 return fetched; 329 } 330 /**************************************************************************** 331 RETURNS: 332 Immediate word value read from instruction queue 333 334 REMARKS: 335 This function returns the immediate byte from the instruction queue, and 336 moves the instruction pointer to the next value. 337 338 NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline! 339 ****************************************************************************/ 340 static uint16_t 341 fetch_word_imm(struct X86EMU *emu) 342 { 343 uint16_t fetched; 344 345 fetched = fetch_word(emu, emu->x86.R_CS, emu->x86.R_IP); 346 emu->x86.R_IP += 2; 347 return fetched; 348 } 349 /**************************************************************************** 350 RETURNS: 351 Immediate lone value read from instruction queue 352 353 REMARKS: 354 This function returns the immediate byte from the instruction queue, and 355 moves the instruction pointer to the next value. 356 357 NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline! 358 ****************************************************************************/ 359 static uint32_t 360 fetch_long_imm(struct X86EMU *emu) 361 { 362 uint32_t fetched; 363 364 fetched = fetch_long(emu, emu->x86.R_CS, emu->x86.R_IP); 365 emu->x86.R_IP += 4; 366 return fetched; 367 } 368 /**************************************************************************** 369 RETURNS: 370 Value of the default data segment 371 372 REMARKS: 373 Inline function that returns the default data segment for the current 374 instruction. 375 376 On the x86 processor, the default segment is not always DS if there is 377 no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to 378 addresses relative to SS (ie: on the stack). So, at the minimum, all 379 decodings of addressing modes would have to set/clear a bit describing 380 whether the access is relative to DS or SS. That is the function of the 381 cpu-state-varible emu->x86.mode. There are several potential states: 382 383 repe prefix seen (handled elsewhere) 384 repne prefix seen (ditto) 385 386 cs segment override 387 ds segment override 388 es segment override 389 fs segment override 390 gs segment override 391 ss segment override 392 393 ds/ss select (in absense of override) 394 395 Each of the above 7 items are handled with a bit in the mode field. 396 ****************************************************************************/ 397 static uint32_t 398 get_data_segment(struct X86EMU *emu) 399 { 400 switch (emu->x86.mode & SYSMODE_SEGMASK) { 401 case 0: /* default case: use ds register */ 402 case SYSMODE_SEGOVR_DS: 403 case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS: 404 return emu->x86.R_DS; 405 case SYSMODE_SEG_DS_SS:/* non-overridden, use ss register */ 406 return emu->x86.R_SS; 407 case SYSMODE_SEGOVR_CS: 408 case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS: 409 return emu->x86.R_CS; 410 case SYSMODE_SEGOVR_ES: 411 case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS: 412 return emu->x86.R_ES; 413 case SYSMODE_SEGOVR_FS: 414 case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS: 415 return emu->x86.R_FS; 416 case SYSMODE_SEGOVR_GS: 417 case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS: 418 return emu->x86.R_GS; 419 case SYSMODE_SEGOVR_SS: 420 case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS: 421 return emu->x86.R_SS; 422 } 423 X86EMU_halt_sys(emu); 424 } 425 /**************************************************************************** 426 PARAMETERS: 427 offset - Offset to load data from 428 429 RETURNS: 430 Byte value read from the absolute memory location. 431 432 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 433 ****************************************************************************/ 434 static uint8_t 435 fetch_data_byte(struct X86EMU *emu, uint32_t offset) 436 { 437 return fetch_byte(emu, get_data_segment(emu), offset); 438 } 439 /**************************************************************************** 440 PARAMETERS: 441 offset - Offset to load data from 442 443 RETURNS: 444 Word value read from the absolute memory location. 445 446 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 447 ****************************************************************************/ 448 static uint16_t 449 fetch_data_word(struct X86EMU *emu, uint32_t offset) 450 { 451 return fetch_word(emu, get_data_segment(emu), offset); 452 } 453 /**************************************************************************** 454 PARAMETERS: 455 offset - Offset to load data from 456 457 RETURNS: 458 Long value read from the absolute memory location. 459 460 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 461 ****************************************************************************/ 462 static uint32_t 463 fetch_data_long(struct X86EMU *emu, uint32_t offset) 464 { 465 return fetch_long(emu, get_data_segment(emu), offset); 466 } 467 /**************************************************************************** 468 PARAMETERS: 469 segment - Segment to load data from 470 offset - Offset to load data from 471 472 RETURNS: 473 Byte value read from the absolute memory location. 474 475 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 476 ****************************************************************************/ 477 static uint8_t 478 fetch_byte(struct X86EMU *emu, uint32_t segment, uint32_t offset) 479 { 480 return (*emu->emu_rdb) (emu, ((uint32_t) segment << 4) + offset); 481 } 482 /**************************************************************************** 483 PARAMETERS: 484 segment - Segment to load data from 485 offset - Offset to load data from 486 487 RETURNS: 488 Word value read from the absolute memory location. 489 490 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 491 ****************************************************************************/ 492 static uint16_t 493 fetch_word(struct X86EMU *emu, uint32_t segment, uint32_t offset) 494 { 495 return (*emu->emu_rdw) (emu, ((uint32_t) segment << 4) + offset); 496 } 497 /**************************************************************************** 498 PARAMETERS: 499 segment - Segment to load data from 500 offset - Offset to load data from 501 502 RETURNS: 503 Long value read from the absolute memory location. 504 505 NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 506 ****************************************************************************/ 507 static uint32_t 508 fetch_long(struct X86EMU *emu, uint32_t segment, uint32_t offset) 509 { 510 return (*emu->emu_rdl) (emu, ((uint32_t) segment << 4) + offset); 511 } 512 /**************************************************************************** 513 PARAMETERS: 514 offset - Offset to store data at 515 val - Value to store 516 517 REMARKS: 518 Writes a word value to an segmented memory location. The segment used is 519 the current 'default' segment, which may have been overridden. 520 521 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 522 ****************************************************************************/ 523 static void 524 store_data_byte(struct X86EMU *emu, uint32_t offset, uint8_t val) 525 { 526 store_byte(emu, get_data_segment(emu), offset, val); 527 } 528 /**************************************************************************** 529 PARAMETERS: 530 offset - Offset to store data at 531 val - Value to store 532 533 REMARKS: 534 Writes a word value to an segmented memory location. The segment used is 535 the current 'default' segment, which may have been overridden. 536 537 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 538 ****************************************************************************/ 539 static void 540 store_data_word(struct X86EMU *emu, uint32_t offset, uint16_t val) 541 { 542 store_word(emu, get_data_segment(emu), offset, val); 543 } 544 /**************************************************************************** 545 PARAMETERS: 546 offset - Offset to store data at 547 val - Value to store 548 549 REMARKS: 550 Writes a long value to an segmented memory location. The segment used is 551 the current 'default' segment, which may have been overridden. 552 553 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 554 ****************************************************************************/ 555 static void 556 store_data_long(struct X86EMU *emu, uint32_t offset, uint32_t val) 557 { 558 store_long(emu, get_data_segment(emu), offset, val); 559 } 560 /**************************************************************************** 561 PARAMETERS: 562 segment - Segment to store data at 563 offset - Offset to store data at 564 val - Value to store 565 566 REMARKS: 567 Writes a byte value to an absolute memory location. 568 569 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 570 ****************************************************************************/ 571 static void 572 store_byte(struct X86EMU *emu, uint32_t segment, uint32_t offset, uint8_t val) 573 { 574 (*emu->emu_wrb) (emu, ((uint32_t) segment << 4) + offset, val); 575 } 576 /**************************************************************************** 577 PARAMETERS: 578 segment - Segment to store data at 579 offset - Offset to store data at 580 val - Value to store 581 582 REMARKS: 583 Writes a word value to an absolute memory location. 584 585 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 586 ****************************************************************************/ 587 static void 588 store_word(struct X86EMU *emu, uint32_t segment, uint32_t offset, uint16_t val) 589 { 590 (*emu->emu_wrw) (emu, ((uint32_t) segment << 4) + offset, val); 591 } 592 /**************************************************************************** 593 PARAMETERS: 594 segment - Segment to store data at 595 offset - Offset to store data at 596 val - Value to store 597 598 REMARKS: 599 Writes a long value to an absolute memory location. 600 601 NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 602 ****************************************************************************/ 603 static void 604 store_long(struct X86EMU *emu, uint32_t segment, uint32_t offset, uint32_t val) 605 { 606 (*emu->emu_wrl) (emu, ((uint32_t) segment << 4) + offset, val); 607 } 608 /**************************************************************************** 609 PARAMETERS: 610 reg - Register to decode 611 612 RETURNS: 613 Pointer to the appropriate register 614 615 REMARKS: 616 Return a pointer to the register given by the R/RM field of the 617 modrm byte, for byte operands. Also enables the decoding of instructions. 618 ****************************************************************************/ 619 static uint8_t * 620 decode_rm_byte_register(struct X86EMU *emu, int reg) 621 { 622 switch (reg) { 623 case 0: 624 return &emu->x86.R_AL; 625 case 1: 626 return &emu->x86.R_CL; 627 case 2: 628 return &emu->x86.R_DL; 629 case 3: 630 return &emu->x86.R_BL; 631 case 4: 632 return &emu->x86.R_AH; 633 case 5: 634 return &emu->x86.R_CH; 635 case 6: 636 return &emu->x86.R_DH; 637 case 7: 638 return &emu->x86.R_BH; 639 default: 640 X86EMU_halt_sys(emu); 641 } 642 } 643 644 static uint8_t * 645 decode_rl_byte_register(struct X86EMU *emu) 646 { 647 return decode_rm_byte_register(emu, emu->cur_rl); 648 } 649 650 static uint8_t * 651 decode_rh_byte_register(struct X86EMU *emu) 652 { 653 return decode_rm_byte_register(emu, emu->cur_rh); 654 } 655 /**************************************************************************** 656 PARAMETERS: 657 reg - Register to decode 658 659 RETURNS: 660 Pointer to the appropriate register 661 662 REMARKS: 663 Return a pointer to the register given by the R/RM field of the 664 modrm byte, for word operands. Also enables the decoding of instructions. 665 ****************************************************************************/ 666 static uint16_t * 667 decode_rm_word_register(struct X86EMU *emu, int reg) 668 { 669 switch (reg) { 670 case 0: 671 return &emu->x86.R_AX; 672 case 1: 673 return &emu->x86.R_CX; 674 case 2: 675 return &emu->x86.R_DX; 676 case 3: 677 return &emu->x86.R_BX; 678 case 4: 679 return &emu->x86.R_SP; 680 case 5: 681 return &emu->x86.R_BP; 682 case 6: 683 return &emu->x86.R_SI; 684 case 7: 685 return &emu->x86.R_DI; 686 default: 687 X86EMU_halt_sys(emu); 688 } 689 } 690 691 static uint16_t * 692 decode_rl_word_register(struct X86EMU *emu) 693 { 694 return decode_rm_word_register(emu, emu->cur_rl); 695 } 696 697 static uint16_t * 698 decode_rh_word_register(struct X86EMU *emu) 699 { 700 return decode_rm_word_register(emu, emu->cur_rh); 701 } 702 /**************************************************************************** 703 PARAMETERS: 704 reg - Register to decode 705 706 RETURNS: 707 Pointer to the appropriate register 708 709 REMARKS: 710 Return a pointer to the register given by the R/RM field of the 711 modrm byte, for dword operands. Also enables the decoding of instructions. 712 ****************************************************************************/ 713 static uint32_t * 714 decode_rm_long_register(struct X86EMU *emu, int reg) 715 { 716 switch (reg) { 717 case 0: 718 return &emu->x86.R_EAX; 719 case 1: 720 return &emu->x86.R_ECX; 721 case 2: 722 return &emu->x86.R_EDX; 723 case 3: 724 return &emu->x86.R_EBX; 725 case 4: 726 return &emu->x86.R_ESP; 727 case 5: 728 return &emu->x86.R_EBP; 729 case 6: 730 return &emu->x86.R_ESI; 731 case 7: 732 return &emu->x86.R_EDI; 733 default: 734 X86EMU_halt_sys(emu); 735 } 736 } 737 738 static uint32_t * 739 decode_rl_long_register(struct X86EMU *emu) 740 { 741 return decode_rm_long_register(emu, emu->cur_rl); 742 } 743 744 static uint32_t * 745 decode_rh_long_register(struct X86EMU *emu) 746 { 747 return decode_rm_long_register(emu, emu->cur_rh); 748 } 749 750 /**************************************************************************** 751 PARAMETERS: 752 reg - Register to decode 753 754 RETURNS: 755 Pointer to the appropriate register 756 757 REMARKS: 758 Return a pointer to the register given by the R/RM field of the 759 modrm byte, for word operands, modified from above for the weirdo 760 special case of segreg operands. Also enables the decoding of instructions. 761 ****************************************************************************/ 762 static uint16_t * 763 decode_rh_seg_register(struct X86EMU *emu) 764 { 765 switch (emu->cur_rh) { 766 case 0: 767 return &emu->x86.R_ES; 768 case 1: 769 return &emu->x86.R_CS; 770 case 2: 771 return &emu->x86.R_SS; 772 case 3: 773 return &emu->x86.R_DS; 774 case 4: 775 return &emu->x86.R_FS; 776 case 5: 777 return &emu->x86.R_GS; 778 default: 779 X86EMU_halt_sys(emu); 780 } 781 } 782 /* 783 * 784 * return offset from the SIB Byte 785 */ 786 static uint32_t 787 decode_sib_address(struct X86EMU *emu, int sib, int mod) 788 { 789 uint32_t base = 0, i = 0, scale = 1; 790 791 switch (sib & 0x07) { 792 case 0: 793 base = emu->x86.R_EAX; 794 break; 795 case 1: 796 base = emu->x86.R_ECX; 797 break; 798 case 2: 799 base = emu->x86.R_EDX; 800 break; 801 case 3: 802 base = emu->x86.R_EBX; 803 break; 804 case 4: 805 base = emu->x86.R_ESP; 806 emu->x86.mode |= SYSMODE_SEG_DS_SS; 807 break; 808 case 5: 809 if (mod == 0) { 810 base = fetch_long_imm(emu); 811 } else { 812 base = emu->x86.R_ESP; 813 emu->x86.mode |= SYSMODE_SEG_DS_SS; 814 } 815 break; 816 case 6: 817 base = emu->x86.R_ESI; 818 break; 819 case 7: 820 base = emu->x86.R_EDI; 821 break; 822 } 823 switch ((sib >> 3) & 0x07) { 824 case 0: 825 i = emu->x86.R_EAX; 826 break; 827 case 1: 828 i = emu->x86.R_ECX; 829 break; 830 case 2: 831 i = emu->x86.R_EDX; 832 break; 833 case 3: 834 i = emu->x86.R_EBX; 835 break; 836 case 4: 837 i = 0; 838 break; 839 case 5: 840 i = emu->x86.R_EBP; 841 break; 842 case 6: 843 i = emu->x86.R_ESI; 844 break; 845 case 7: 846 i = emu->x86.R_EDI; 847 break; 848 } 849 scale = 1 << ((sib >> 6) & 0x03); 850 return base + (i * scale); 851 } 852 /**************************************************************************** 853 PARAMETERS: 854 rm - RM value to decode 855 856 RETURNS: 857 Offset in memory for the address decoding 858 859 REMARKS: 860 Return the offset given by mod=00, mod=01 or mod=10 addressing. 861 Also enables the decoding of instructions. 862 ****************************************************************************/ 863 static uint32_t 864 decode_rl_address(struct X86EMU *emu) 865 { 866 if (emu->x86.mode & SYSMODE_PREFIX_ADDR) { 867 uint32_t offset, sib; 868 /* 32-bit addressing */ 869 switch (emu->cur_rl) { 870 case 0: 871 offset = emu->x86.R_EAX; 872 break; 873 case 1: 874 offset = emu->x86.R_ECX; 875 break; 876 case 2: 877 offset = emu->x86.R_EDX; 878 break; 879 case 3: 880 offset = emu->x86.R_EBX; 881 break; 882 case 4: 883 sib = fetch_byte_imm(emu); 884 offset = decode_sib_address(emu, sib, 0); 885 break; 886 case 5: 887 if (emu->cur_mod == 0) 888 offset = fetch_long_imm(emu); 889 else 890 offset = emu->x86.R_EBP; 891 break; 892 case 6: 893 offset = emu->x86.R_ESI; 894 break; 895 case 7: 896 offset = emu->x86.R_EDI; 897 break; 898 default: 899 X86EMU_halt_sys(emu); 900 } 901 if (emu->cur_mod == 1) 902 offset += (int8_t)fetch_byte_imm(emu); 903 else if (emu->cur_mod == 2) 904 offset += fetch_long_imm(emu); 905 return offset; 906 } else { 907 uint16_t offset; 908 909 /* 16-bit addressing */ 910 switch (emu->cur_rl) { 911 case 0: 912 offset = emu->x86.R_BX + emu->x86.R_SI; 913 break; 914 case 1: 915 offset = emu->x86.R_BX + emu->x86.R_DI; 916 break; 917 case 2: 918 emu->x86.mode |= SYSMODE_SEG_DS_SS; 919 offset = emu->x86.R_BP + emu->x86.R_SI; 920 break; 921 case 3: 922 emu->x86.mode |= SYSMODE_SEG_DS_SS; 923 offset = emu->x86.R_BP + emu->x86.R_DI; 924 break; 925 case 4: 926 offset = emu->x86.R_SI; 927 break; 928 case 5: 929 offset = emu->x86.R_DI; 930 break; 931 case 6: 932 if (emu->cur_mod == 0) 933 offset = fetch_word_imm(emu); 934 else 935 offset = emu->x86.R_BP; 936 break; 937 case 7: 938 offset = emu->x86.R_BX; 939 break; 940 default: 941 X86EMU_halt_sys(emu); 942 } 943 if (emu->cur_mod == 1) 944 offset += (int8_t)fetch_byte_imm(emu); 945 else if (emu->cur_mod == 2) 946 offset += fetch_word_imm(emu); 947 return offset; 948 } 949 } 950 951 static uint8_t 952 decode_and_fetch_byte(struct X86EMU *emu) 953 { 954 if (emu->cur_mod != 3) { 955 emu->cur_offset = decode_rl_address(emu); 956 return fetch_data_byte(emu, emu->cur_offset); 957 } else { 958 return *decode_rl_byte_register(emu); 959 } 960 } 961 962 static uint16_t 963 decode_and_fetch_word_disp(struct X86EMU *emu, int16_t disp) 964 { 965 if (emu->cur_mod != 3) { 966 /* TODO: A20 gate emulation */ 967 emu->cur_offset = decode_rl_address(emu) + disp; 968 if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0) 969 emu->cur_offset &= 0xffff; 970 return fetch_data_word(emu, emu->cur_offset); 971 } else { 972 return *decode_rl_word_register(emu); 973 } 974 } 975 976 static uint32_t 977 decode_and_fetch_long_disp(struct X86EMU *emu, int16_t disp) 978 { 979 if (emu->cur_mod != 3) { 980 /* TODO: A20 gate emulation */ 981 emu->cur_offset = decode_rl_address(emu) + disp; 982 if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0) 983 emu->cur_offset &= 0xffff; 984 return fetch_data_long(emu, emu->cur_offset); 985 } else { 986 return *decode_rl_long_register(emu); 987 } 988 } 989 990 uint16_t 991 decode_and_fetch_word(struct X86EMU *emu) 992 { 993 return decode_and_fetch_word_disp(emu, 0); 994 } 995 996 uint32_t 997 decode_and_fetch_long(struct X86EMU *emu) 998 { 999 return decode_and_fetch_long_disp(emu, 0); 1000 } 1001 1002 uint8_t 1003 decode_and_fetch_byte_imm8(struct X86EMU *emu, uint8_t *imm) 1004 { 1005 if (emu->cur_mod != 3) { 1006 emu->cur_offset = decode_rl_address(emu); 1007 *imm = fetch_byte_imm(emu); 1008 return fetch_data_byte(emu, emu->cur_offset); 1009 } else { 1010 *imm = fetch_byte_imm(emu); 1011 return *decode_rl_byte_register(emu); 1012 } 1013 } 1014 1015 static uint16_t 1016 decode_and_fetch_word_imm8(struct X86EMU *emu, uint8_t *imm) 1017 { 1018 if (emu->cur_mod != 3) { 1019 emu->cur_offset = decode_rl_address(emu); 1020 *imm = fetch_byte_imm(emu); 1021 return fetch_data_word(emu, emu->cur_offset); 1022 } else { 1023 *imm = fetch_byte_imm(emu); 1024 return *decode_rl_word_register(emu); 1025 } 1026 } 1027 1028 static uint32_t 1029 decode_and_fetch_long_imm8(struct X86EMU *emu, uint8_t *imm) 1030 { 1031 if (emu->cur_mod != 3) { 1032 emu->cur_offset = decode_rl_address(emu); 1033 *imm = fetch_byte_imm(emu); 1034 return fetch_data_long(emu, emu->cur_offset); 1035 } else { 1036 *imm = fetch_byte_imm(emu); 1037 return *decode_rl_long_register(emu); 1038 } 1039 } 1040 1041 static void 1042 write_back_byte(struct X86EMU *emu, uint8_t val) 1043 { 1044 if (emu->cur_mod != 3) 1045 store_data_byte(emu, emu->cur_offset, val); 1046 else 1047 *decode_rl_byte_register(emu) = val; 1048 } 1049 1050 static void 1051 write_back_word(struct X86EMU *emu, uint16_t val) 1052 { 1053 if (emu->cur_mod != 3) 1054 store_data_word(emu, emu->cur_offset, val); 1055 else 1056 *decode_rl_word_register(emu) = val; 1057 } 1058 1059 static void 1060 write_back_long(struct X86EMU *emu, uint32_t val) 1061 { 1062 if (emu->cur_mod != 3) 1063 store_data_long(emu, emu->cur_offset, val); 1064 else 1065 *decode_rl_long_register(emu) = val; 1066 } 1067 1068 static void 1069 common_inc_word_long(struct X86EMU *emu, union X86EMU_register *reg) 1070 { 1071 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1072 reg->I32_reg.e_reg = inc_long(emu, reg->I32_reg.e_reg); 1073 else 1074 reg->I16_reg.x_reg = inc_word(emu, reg->I16_reg.x_reg); 1075 } 1076 1077 static void 1078 common_dec_word_long(struct X86EMU *emu, union X86EMU_register *reg) 1079 { 1080 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1081 reg->I32_reg.e_reg = dec_long(emu, reg->I32_reg.e_reg); 1082 else 1083 reg->I16_reg.x_reg = dec_word(emu, reg->I16_reg.x_reg); 1084 } 1085 1086 static void 1087 common_binop_byte_rm_r(struct X86EMU *emu, uint8_t (*binop)(struct X86EMU *, uint8_t, uint8_t)) 1088 { 1089 uint32_t destoffset; 1090 uint8_t *destreg, srcval; 1091 uint8_t destval; 1092 1093 fetch_decode_modrm(emu); 1094 srcval = *decode_rh_byte_register(emu); 1095 if (emu->cur_mod != 3) { 1096 destoffset = decode_rl_address(emu); 1097 destval = fetch_data_byte(emu, destoffset); 1098 destval = (*binop)(emu, destval, srcval); 1099 store_data_byte(emu, destoffset, destval); 1100 } else { 1101 destreg = decode_rl_byte_register(emu); 1102 *destreg = (*binop)(emu, *destreg, srcval); 1103 } 1104 } 1105 1106 static void 1107 common_binop_ns_byte_rm_r(struct X86EMU *emu, void (*binop)(struct X86EMU *, uint8_t, uint8_t)) 1108 { 1109 uint32_t destoffset; 1110 uint8_t destval, srcval; 1111 1112 fetch_decode_modrm(emu); 1113 srcval = *decode_rh_byte_register(emu); 1114 if (emu->cur_mod != 3) { 1115 destoffset = decode_rl_address(emu); 1116 destval = fetch_data_byte(emu, destoffset); 1117 } else { 1118 destval = *decode_rl_byte_register(emu); 1119 } 1120 (*binop)(emu, destval, srcval); 1121 } 1122 1123 static void 1124 common_binop_word_rm_r(struct X86EMU *emu, uint16_t (*binop)(struct X86EMU *, uint16_t, uint16_t)) 1125 { 1126 uint32_t destoffset; 1127 uint16_t destval, *destreg, srcval; 1128 1129 fetch_decode_modrm(emu); 1130 srcval = *decode_rh_word_register(emu); 1131 if (emu->cur_mod != 3) { 1132 destoffset = decode_rl_address(emu); 1133 destval = fetch_data_word(emu, destoffset); 1134 destval = (*binop)(emu, destval, srcval); 1135 store_data_word(emu, destoffset, destval); 1136 } else { 1137 destreg = decode_rl_word_register(emu); 1138 *destreg = (*binop)(emu, *destreg, srcval); 1139 } 1140 } 1141 1142 static void 1143 common_binop_byte_r_rm(struct X86EMU *emu, uint8_t (*binop)(struct X86EMU *, uint8_t, uint8_t)) 1144 { 1145 uint8_t *destreg, srcval; 1146 uint32_t srcoffset; 1147 1148 fetch_decode_modrm(emu); 1149 destreg = decode_rh_byte_register(emu); 1150 if (emu->cur_mod != 3) { 1151 srcoffset = decode_rl_address(emu); 1152 srcval = fetch_data_byte(emu, srcoffset); 1153 } else { 1154 srcval = *decode_rl_byte_register(emu); 1155 } 1156 *destreg = (*binop)(emu, *destreg, srcval); 1157 } 1158 1159 static void 1160 common_binop_long_rm_r(struct X86EMU *emu, uint32_t (*binop)(struct X86EMU *, uint32_t, uint32_t)) 1161 { 1162 uint32_t destoffset; 1163 uint32_t destval, *destreg, srcval; 1164 1165 fetch_decode_modrm(emu); 1166 srcval = *decode_rh_long_register(emu); 1167 if (emu->cur_mod != 3) { 1168 destoffset = decode_rl_address(emu); 1169 destval = fetch_data_long(emu, destoffset); 1170 destval = (*binop)(emu, destval, srcval); 1171 store_data_long(emu, destoffset, destval); 1172 } else { 1173 destreg = decode_rl_long_register(emu); 1174 *destreg = (*binop)(emu, *destreg, srcval); 1175 } 1176 } 1177 1178 static void 1179 common_binop_word_long_rm_r(struct X86EMU *emu, 1180 uint16_t (*binop16)(struct X86EMU *, uint16_t, uint16_t), uint32_t (*binop32)(struct X86EMU *, uint32_t, uint32_t)) 1181 { 1182 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1183 common_binop_long_rm_r(emu, binop32); 1184 else 1185 common_binop_word_rm_r(emu, binop16); 1186 } 1187 1188 static void 1189 common_binop_ns_word_rm_r(struct X86EMU *emu, void (*binop)(struct X86EMU *, uint16_t, uint16_t)) 1190 { 1191 uint32_t destoffset; 1192 uint16_t destval, srcval; 1193 1194 fetch_decode_modrm(emu); 1195 srcval = *decode_rh_word_register(emu); 1196 if (emu->cur_mod != 3) { 1197 destoffset = decode_rl_address(emu); 1198 destval = fetch_data_word(emu, destoffset); 1199 } else { 1200 destval = *decode_rl_word_register(emu); 1201 } 1202 (*binop)(emu, destval, srcval); 1203 } 1204 1205 1206 static void 1207 common_binop_ns_long_rm_r(struct X86EMU *emu, void (*binop)(struct X86EMU *, uint32_t, uint32_t)) 1208 { 1209 uint32_t destoffset; 1210 uint32_t destval, srcval; 1211 1212 fetch_decode_modrm(emu); 1213 srcval = *decode_rh_long_register(emu); 1214 if (emu->cur_mod != 3) { 1215 destoffset = decode_rl_address(emu); 1216 destval = fetch_data_long(emu, destoffset); 1217 } else { 1218 destval = *decode_rl_long_register(emu); 1219 } 1220 (*binop)(emu, destval, srcval); 1221 } 1222 1223 static void 1224 common_binop_ns_word_long_rm_r(struct X86EMU *emu, 1225 void (*binop16)(struct X86EMU *, uint16_t, uint16_t), void (*binop32)(struct X86EMU *, uint32_t, uint32_t)) 1226 { 1227 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1228 common_binop_ns_long_rm_r(emu, binop32); 1229 else 1230 common_binop_ns_word_rm_r(emu, binop16); 1231 } 1232 1233 static void 1234 common_binop_long_r_rm(struct X86EMU *emu, uint32_t (*binop)(struct X86EMU *, uint32_t, uint32_t)) 1235 { 1236 uint32_t srcoffset; 1237 uint32_t *destreg, srcval; 1238 1239 fetch_decode_modrm(emu); 1240 destreg = decode_rh_long_register(emu); 1241 if (emu->cur_mod != 3) { 1242 srcoffset = decode_rl_address(emu); 1243 srcval = fetch_data_long(emu, srcoffset); 1244 } else { 1245 srcval = *decode_rl_long_register(emu); 1246 } 1247 *destreg = (*binop)(emu, *destreg, srcval); 1248 } 1249 1250 static void 1251 common_binop_word_r_rm(struct X86EMU *emu, uint16_t (*binop)(struct X86EMU *, uint16_t, uint16_t)) 1252 { 1253 uint32_t srcoffset; 1254 uint16_t *destreg, srcval; 1255 1256 fetch_decode_modrm(emu); 1257 destreg = decode_rh_word_register(emu); 1258 if (emu->cur_mod != 3) { 1259 srcoffset = decode_rl_address(emu); 1260 srcval = fetch_data_word(emu, srcoffset); 1261 } else { 1262 srcval = *decode_rl_word_register(emu); 1263 } 1264 *destreg = (*binop)(emu, *destreg, srcval); 1265 } 1266 1267 static void 1268 common_binop_word_long_r_rm(struct X86EMU *emu, 1269 uint16_t (*binop16)(struct X86EMU *, uint16_t, uint16_t), uint32_t (*binop32)(struct X86EMU *, uint32_t, uint32_t)) 1270 { 1271 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1272 common_binop_long_r_rm(emu, binop32); 1273 else 1274 common_binop_word_r_rm(emu, binop16); 1275 } 1276 1277 static void 1278 common_binop_byte_imm(struct X86EMU *emu, uint8_t (*binop)(struct X86EMU *, uint8_t, uint8_t)) 1279 { 1280 uint8_t srcval; 1281 1282 srcval = fetch_byte_imm(emu); 1283 emu->x86.R_AL = (*binop)(emu, emu->x86.R_AL, srcval); 1284 } 1285 1286 static void 1287 common_binop_word_long_imm(struct X86EMU *emu, 1288 uint16_t (*binop16)(struct X86EMU *, uint16_t, uint16_t), uint32_t (*binop32)(struct X86EMU *, uint32_t, uint32_t)) 1289 { 1290 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1291 uint32_t srcval; 1292 1293 srcval = fetch_long_imm(emu); 1294 emu->x86.R_EAX = (*binop32)(emu, emu->x86.R_EAX, srcval); 1295 } else { 1296 uint16_t srcval; 1297 1298 srcval = fetch_word_imm(emu); 1299 emu->x86.R_AX = (*binop16)(emu, emu->x86.R_AX, srcval); 1300 } 1301 } 1302 1303 static void 1304 common_push_word_long(struct X86EMU *emu, union X86EMU_register *reg) 1305 { 1306 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1307 push_long(emu, reg->I32_reg.e_reg); 1308 else 1309 push_word(emu, reg->I16_reg.x_reg); 1310 } 1311 1312 static void 1313 common_pop_word_long(struct X86EMU *emu, union X86EMU_register *reg) 1314 { 1315 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1316 reg->I32_reg.e_reg = pop_long(emu); 1317 else 1318 reg->I16_reg.x_reg = pop_word(emu); 1319 } 1320 1321 static void 1322 common_imul_long_IMM(struct X86EMU *emu, bool byte_imm) 1323 { 1324 uint32_t srcoffset; 1325 uint32_t *destreg, srcval; 1326 int32_t imm; 1327 uint64_t res; 1328 1329 fetch_decode_modrm(emu); 1330 destreg = decode_rh_long_register(emu); 1331 if (emu->cur_mod != 3) { 1332 srcoffset = decode_rl_address(emu); 1333 srcval = fetch_data_long(emu, srcoffset); 1334 } else { 1335 srcval = *decode_rl_long_register(emu); 1336 } 1337 1338 if (byte_imm) 1339 imm = (int8_t)fetch_byte_imm(emu); 1340 else 1341 imm = fetch_long_imm(emu); 1342 res = (int32_t)srcval * imm; 1343 1344 if (res > 0xffffffff) { 1345 SET_FLAG(F_CF); 1346 SET_FLAG(F_OF); 1347 } else { 1348 CLEAR_FLAG(F_CF); 1349 CLEAR_FLAG(F_OF); 1350 } 1351 *destreg = (uint32_t)res; 1352 } 1353 1354 static void 1355 common_imul_word_IMM(struct X86EMU *emu, bool byte_imm) 1356 { 1357 uint32_t srcoffset; 1358 uint16_t *destreg, srcval; 1359 int16_t imm; 1360 uint32_t res; 1361 1362 fetch_decode_modrm(emu); 1363 destreg = decode_rh_word_register(emu); 1364 if (emu->cur_mod != 3) { 1365 srcoffset = decode_rl_address(emu); 1366 srcval = fetch_data_word(emu, srcoffset); 1367 } else { 1368 srcval = *decode_rl_word_register(emu); 1369 } 1370 1371 if (byte_imm) 1372 imm = (int8_t)fetch_byte_imm(emu); 1373 else 1374 imm = fetch_word_imm(emu); 1375 res = (int16_t)srcval * imm; 1376 1377 if (res > 0xffff) { 1378 SET_FLAG(F_CF); 1379 SET_FLAG(F_OF); 1380 } else { 1381 CLEAR_FLAG(F_CF); 1382 CLEAR_FLAG(F_OF); 1383 } 1384 *destreg = (uint16_t) res; 1385 } 1386 1387 static void 1388 common_imul_imm(struct X86EMU *emu, bool byte_imm) 1389 { 1390 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1391 common_imul_long_IMM(emu, byte_imm); 1392 else 1393 common_imul_word_IMM(emu, byte_imm); 1394 } 1395 1396 static void 1397 common_jmp_near(struct X86EMU *emu, bool cond) 1398 { 1399 int8_t offset; 1400 uint16_t target; 1401 1402 offset = (int8_t) fetch_byte_imm(emu); 1403 target = (uint16_t) (emu->x86.R_IP + (int16_t) offset); 1404 if (cond) 1405 emu->x86.R_IP = target; 1406 } 1407 1408 static void 1409 common_load_far_pointer(struct X86EMU *emu, uint16_t *seg) 1410 { 1411 uint16_t *dstreg; 1412 uint32_t srcoffset; 1413 1414 fetch_decode_modrm(emu); 1415 if (emu->cur_mod == 3) 1416 X86EMU_halt_sys(emu); 1417 1418 dstreg = decode_rh_word_register(emu); 1419 srcoffset = decode_rl_address(emu); 1420 *dstreg = fetch_data_word(emu, srcoffset); 1421 *seg = fetch_data_word(emu, srcoffset + 2); 1422 } 1423 1424 /*----------------------------- Implementation ----------------------------*/ 1425 /**************************************************************************** 1426 REMARKS: 1427 Handles opcode 0x3a 1428 ****************************************************************************/ 1429 static void 1430 x86emuOp_cmp_byte_R_RM(struct X86EMU *emu) 1431 { 1432 uint8_t *destreg, srcval; 1433 1434 fetch_decode_modrm(emu); 1435 destreg = decode_rh_byte_register(emu); 1436 srcval = decode_and_fetch_byte(emu); 1437 cmp_byte(emu, *destreg, srcval); 1438 } 1439 /**************************************************************************** 1440 REMARKS: 1441 Handles opcode 0x3b 1442 ****************************************************************************/ 1443 static void 1444 x86emuOp32_cmp_word_R_RM(struct X86EMU *emu) 1445 { 1446 uint32_t srcval, *destreg; 1447 1448 fetch_decode_modrm(emu); 1449 destreg = decode_rh_long_register(emu); 1450 srcval = decode_and_fetch_long(emu); 1451 cmp_long(emu, *destreg, srcval); 1452 } 1453 1454 static void 1455 x86emuOp16_cmp_word_R_RM(struct X86EMU *emu) 1456 { 1457 uint16_t srcval, *destreg; 1458 1459 fetch_decode_modrm(emu); 1460 destreg = decode_rh_word_register(emu); 1461 srcval = decode_and_fetch_word(emu); 1462 cmp_word(emu, *destreg, srcval); 1463 } 1464 1465 static void 1466 x86emuOp_cmp_word_R_RM(struct X86EMU *emu) 1467 { 1468 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1469 x86emuOp32_cmp_word_R_RM(emu); 1470 else 1471 x86emuOp16_cmp_word_R_RM(emu); 1472 } 1473 /**************************************************************************** 1474 REMARKS: 1475 Handles opcode 0x3c 1476 ****************************************************************************/ 1477 static void 1478 x86emuOp_cmp_byte_AL_IMM(struct X86EMU *emu) 1479 { 1480 uint8_t srcval; 1481 1482 srcval = fetch_byte_imm(emu); 1483 cmp_byte(emu, emu->x86.R_AL, srcval); 1484 } 1485 /**************************************************************************** 1486 REMARKS: 1487 Handles opcode 0x3d 1488 ****************************************************************************/ 1489 static void 1490 x86emuOp32_cmp_word_AX_IMM(struct X86EMU *emu) 1491 { 1492 uint32_t srcval; 1493 1494 srcval = fetch_long_imm(emu); 1495 cmp_long(emu, emu->x86.R_EAX, srcval); 1496 } 1497 1498 static void 1499 x86emuOp16_cmp_word_AX_IMM(struct X86EMU *emu) 1500 { 1501 uint16_t srcval; 1502 1503 srcval = fetch_word_imm(emu); 1504 cmp_word(emu, emu->x86.R_AX, srcval); 1505 } 1506 1507 static void 1508 x86emuOp_cmp_word_AX_IMM(struct X86EMU *emu) 1509 { 1510 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1511 x86emuOp32_cmp_word_AX_IMM(emu); 1512 else 1513 x86emuOp16_cmp_word_AX_IMM(emu); 1514 } 1515 /**************************************************************************** 1516 REMARKS: 1517 Handles opcode 0x60 1518 ****************************************************************************/ 1519 static void 1520 x86emuOp_push_all(struct X86EMU *emu) 1521 { 1522 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1523 uint32_t old_sp = emu->x86.R_ESP; 1524 1525 push_long(emu, emu->x86.R_EAX); 1526 push_long(emu, emu->x86.R_ECX); 1527 push_long(emu, emu->x86.R_EDX); 1528 push_long(emu, emu->x86.R_EBX); 1529 push_long(emu, old_sp); 1530 push_long(emu, emu->x86.R_EBP); 1531 push_long(emu, emu->x86.R_ESI); 1532 push_long(emu, emu->x86.R_EDI); 1533 } else { 1534 uint16_t old_sp = emu->x86.R_SP; 1535 1536 push_word(emu, emu->x86.R_AX); 1537 push_word(emu, emu->x86.R_CX); 1538 push_word(emu, emu->x86.R_DX); 1539 push_word(emu, emu->x86.R_BX); 1540 push_word(emu, old_sp); 1541 push_word(emu, emu->x86.R_BP); 1542 push_word(emu, emu->x86.R_SI); 1543 push_word(emu, emu->x86.R_DI); 1544 } 1545 } 1546 /**************************************************************************** 1547 REMARKS: 1548 Handles opcode 0x61 1549 ****************************************************************************/ 1550 static void 1551 x86emuOp_pop_all(struct X86EMU *emu) 1552 { 1553 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1554 emu->x86.R_EDI = pop_long(emu); 1555 emu->x86.R_ESI = pop_long(emu); 1556 emu->x86.R_EBP = pop_long(emu); 1557 emu->x86.R_ESP += 4; /* skip ESP */ 1558 emu->x86.R_EBX = pop_long(emu); 1559 emu->x86.R_EDX = pop_long(emu); 1560 emu->x86.R_ECX = pop_long(emu); 1561 emu->x86.R_EAX = pop_long(emu); 1562 } else { 1563 emu->x86.R_DI = pop_word(emu); 1564 emu->x86.R_SI = pop_word(emu); 1565 emu->x86.R_BP = pop_word(emu); 1566 emu->x86.R_SP += 2;/* skip SP */ 1567 emu->x86.R_BX = pop_word(emu); 1568 emu->x86.R_DX = pop_word(emu); 1569 emu->x86.R_CX = pop_word(emu); 1570 emu->x86.R_AX = pop_word(emu); 1571 } 1572 } 1573 /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */ 1574 /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */ 1575 1576 /**************************************************************************** 1577 REMARKS: 1578 Handles opcode 0x68 1579 ****************************************************************************/ 1580 static void 1581 x86emuOp_push_word_IMM(struct X86EMU *emu) 1582 { 1583 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1584 uint32_t imm; 1585 1586 imm = fetch_long_imm(emu); 1587 push_long(emu, imm); 1588 } else { 1589 uint16_t imm; 1590 1591 imm = fetch_word_imm(emu); 1592 push_word(emu, imm); 1593 } 1594 } 1595 /**************************************************************************** 1596 REMARKS: 1597 Handles opcode 0x6a 1598 ****************************************************************************/ 1599 static void 1600 x86emuOp_push_byte_IMM(struct X86EMU *emu) 1601 { 1602 int16_t imm; 1603 1604 imm = (int8_t) fetch_byte_imm(emu); 1605 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1606 push_long(emu, (int32_t) imm); 1607 } else { 1608 push_word(emu, imm); 1609 } 1610 } 1611 /**************************************************************************** 1612 REMARKS: 1613 Handles opcode 0x6c 1614 ****************************************************************************/ 1615 /**************************************************************************** 1616 REMARKS: 1617 Handles opcode 0x6d 1618 ****************************************************************************/ 1619 static void 1620 x86emuOp_ins_word(struct X86EMU *emu) 1621 { 1622 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1623 ins(emu, 4); 1624 } else { 1625 ins(emu, 2); 1626 } 1627 } 1628 /**************************************************************************** 1629 REMARKS: 1630 Handles opcode 0x6f 1631 ****************************************************************************/ 1632 static void 1633 x86emuOp_outs_word(struct X86EMU *emu) 1634 { 1635 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1636 outs(emu, 4); 1637 } else { 1638 outs(emu, 2); 1639 } 1640 } 1641 /**************************************************************************** 1642 REMARKS: 1643 Handles opcode 0x7c 1644 ****************************************************************************/ 1645 static void 1646 x86emuOp_jump_near_L(struct X86EMU *emu) 1647 { 1648 bool sf, of; 1649 1650 sf = ACCESS_FLAG(F_SF) != 0; 1651 of = ACCESS_FLAG(F_OF) != 0; 1652 1653 common_jmp_near(emu, sf != of); 1654 } 1655 /**************************************************************************** 1656 REMARKS: 1657 Handles opcode 0x7d 1658 ****************************************************************************/ 1659 static void 1660 x86emuOp_jump_near_NL(struct X86EMU *emu) 1661 { 1662 bool sf, of; 1663 1664 sf = ACCESS_FLAG(F_SF) != 0; 1665 of = ACCESS_FLAG(F_OF) != 0; 1666 1667 common_jmp_near(emu, sf == of); 1668 } 1669 /**************************************************************************** 1670 REMARKS: 1671 Handles opcode 0x7e 1672 ****************************************************************************/ 1673 static void 1674 x86emuOp_jump_near_LE(struct X86EMU *emu) 1675 { 1676 bool sf, of; 1677 1678 sf = ACCESS_FLAG(F_SF) != 0; 1679 of = ACCESS_FLAG(F_OF) != 0; 1680 1681 common_jmp_near(emu, sf != of || ACCESS_FLAG(F_ZF)); 1682 } 1683 /**************************************************************************** 1684 REMARKS: 1685 Handles opcode 0x7f 1686 ****************************************************************************/ 1687 static void 1688 x86emuOp_jump_near_NLE(struct X86EMU *emu) 1689 { 1690 bool sf, of; 1691 1692 sf = ACCESS_FLAG(F_SF) != 0; 1693 of = ACCESS_FLAG(F_OF) != 0; 1694 1695 common_jmp_near(emu, sf == of && !ACCESS_FLAG(F_ZF)); 1696 } 1697 1698 static 1699 uint8_t(*const opc80_byte_operation[]) (struct X86EMU *, uint8_t d, uint8_t s) = 1700 { 1701 add_byte, /* 00 */ 1702 or_byte, /* 01 */ 1703 adc_byte, /* 02 */ 1704 sbb_byte, /* 03 */ 1705 and_byte, /* 04 */ 1706 sub_byte, /* 05 */ 1707 xor_byte, /* 06 */ 1708 cmp_byte, /* 07 */ 1709 }; 1710 /**************************************************************************** 1711 REMARKS: 1712 Handles opcode 0x80 1713 ****************************************************************************/ 1714 static void 1715 x86emuOp_opc80_byte_RM_IMM(struct X86EMU *emu) 1716 { 1717 uint8_t imm, destval; 1718 1719 /* 1720 * Weirdo special case instruction format. Part of the opcode 1721 * held below in "RH". Doubly nested case would result, except 1722 * that the decoded instruction 1723 */ 1724 fetch_decode_modrm(emu); 1725 destval = decode_and_fetch_byte(emu); 1726 imm = fetch_byte_imm(emu); 1727 destval = (*opc80_byte_operation[emu->cur_rh]) (emu, destval, imm); 1728 if (emu->cur_rh != 7) 1729 write_back_byte(emu, destval); 1730 } 1731 1732 static 1733 uint16_t(* const opc81_word_operation[]) (struct X86EMU *, uint16_t d, uint16_t s) = 1734 { 1735 add_word, /* 00 */ 1736 or_word, /* 01 */ 1737 adc_word, /* 02 */ 1738 sbb_word, /* 03 */ 1739 and_word, /* 04 */ 1740 sub_word, /* 05 */ 1741 xor_word, /* 06 */ 1742 cmp_word, /* 07 */ 1743 }; 1744 1745 static 1746 uint32_t(* const opc81_long_operation[]) (struct X86EMU *, uint32_t d, uint32_t s) = 1747 { 1748 add_long, /* 00 */ 1749 or_long, /* 01 */ 1750 adc_long, /* 02 */ 1751 sbb_long, /* 03 */ 1752 and_long, /* 04 */ 1753 sub_long, /* 05 */ 1754 xor_long, /* 06 */ 1755 cmp_long, /* 07 */ 1756 }; 1757 /**************************************************************************** 1758 REMARKS: 1759 Handles opcode 0x81 1760 ****************************************************************************/ 1761 static void 1762 x86emuOp32_opc81_word_RM_IMM(struct X86EMU *emu) 1763 { 1764 uint32_t destval, imm; 1765 1766 /* 1767 * Weirdo special case instruction format. Part of the opcode 1768 * held below in "RH". Doubly nested case would result, except 1769 * that the decoded instruction 1770 */ 1771 fetch_decode_modrm(emu); 1772 destval = decode_and_fetch_long(emu); 1773 imm = fetch_long_imm(emu); 1774 destval = (*opc81_long_operation[emu->cur_rh]) (emu, destval, imm); 1775 if (emu->cur_rh != 7) 1776 write_back_long(emu, destval); 1777 } 1778 1779 static void 1780 x86emuOp16_opc81_word_RM_IMM(struct X86EMU *emu) 1781 { 1782 uint16_t destval, imm; 1783 1784 /* 1785 * Weirdo special case instruction format. Part of the opcode 1786 * held below in "RH". Doubly nested case would result, except 1787 * that the decoded instruction 1788 */ 1789 fetch_decode_modrm(emu); 1790 destval = decode_and_fetch_word(emu); 1791 imm = fetch_word_imm(emu); 1792 destval = (*opc81_word_operation[emu->cur_rh]) (emu, destval, imm); 1793 if (emu->cur_rh != 7) 1794 write_back_word(emu, destval); 1795 } 1796 1797 static void 1798 x86emuOp_opc81_word_RM_IMM(struct X86EMU *emu) 1799 { 1800 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1801 x86emuOp32_opc81_word_RM_IMM(emu); 1802 else 1803 x86emuOp16_opc81_word_RM_IMM(emu); 1804 } 1805 1806 static 1807 uint8_t(* const opc82_byte_operation[]) (struct X86EMU *, uint8_t s, uint8_t d) = 1808 { 1809 add_byte, /* 00 */ 1810 or_byte, /* 01 *//* YYY UNUSED ???? */ 1811 adc_byte, /* 02 */ 1812 sbb_byte, /* 03 */ 1813 and_byte, /* 04 *//* YYY UNUSED ???? */ 1814 sub_byte, /* 05 */ 1815 xor_byte, /* 06 *//* YYY UNUSED ???? */ 1816 cmp_byte, /* 07 */ 1817 }; 1818 /**************************************************************************** 1819 REMARKS: 1820 Handles opcode 0x82 1821 ****************************************************************************/ 1822 static void 1823 x86emuOp_opc82_byte_RM_IMM(struct X86EMU *emu) 1824 { 1825 uint8_t imm, destval; 1826 1827 /* 1828 * Weirdo special case instruction format. Part of the opcode 1829 * held below in "RH". Doubly nested case would result, except 1830 * that the decoded instruction Similar to opcode 81, except that 1831 * the immediate byte is sign extended to a word length. 1832 */ 1833 fetch_decode_modrm(emu); 1834 destval = decode_and_fetch_byte(emu); 1835 imm = fetch_byte_imm(emu); 1836 destval = (*opc82_byte_operation[emu->cur_rh]) (emu, destval, imm); 1837 if (emu->cur_rh != 7) 1838 write_back_byte(emu, destval); 1839 } 1840 1841 static 1842 uint16_t(* const opc83_word_operation[]) (struct X86EMU *, uint16_t s, uint16_t d) = 1843 { 1844 add_word, /* 00 */ 1845 or_word, /* 01 *//* YYY UNUSED ???? */ 1846 adc_word, /* 02 */ 1847 sbb_word, /* 03 */ 1848 and_word, /* 04 *//* YYY UNUSED ???? */ 1849 sub_word, /* 05 */ 1850 xor_word, /* 06 *//* YYY UNUSED ???? */ 1851 cmp_word, /* 07 */ 1852 }; 1853 1854 static 1855 uint32_t(* const opc83_long_operation[]) (struct X86EMU *, uint32_t s, uint32_t d) = 1856 { 1857 add_long, /* 00 */ 1858 or_long, /* 01 *//* YYY UNUSED ???? */ 1859 adc_long, /* 02 */ 1860 sbb_long, /* 03 */ 1861 and_long, /* 04 *//* YYY UNUSED ???? */ 1862 sub_long, /* 05 */ 1863 xor_long, /* 06 *//* YYY UNUSED ???? */ 1864 cmp_long, /* 07 */ 1865 }; 1866 /**************************************************************************** 1867 REMARKS: 1868 Handles opcode 0x83 1869 ****************************************************************************/ 1870 static void 1871 x86emuOp32_opc83_word_RM_IMM(struct X86EMU *emu) 1872 { 1873 uint32_t destval, imm; 1874 1875 fetch_decode_modrm(emu); 1876 destval = decode_and_fetch_long(emu); 1877 imm = (int8_t) fetch_byte_imm(emu); 1878 destval = (*opc83_long_operation[emu->cur_rh]) (emu, destval, imm); 1879 if (emu->cur_rh != 7) 1880 write_back_long(emu, destval); 1881 } 1882 1883 static void 1884 x86emuOp16_opc83_word_RM_IMM(struct X86EMU *emu) 1885 { 1886 uint16_t destval, imm; 1887 1888 fetch_decode_modrm(emu); 1889 destval = decode_and_fetch_word(emu); 1890 imm = (int8_t) fetch_byte_imm(emu); 1891 destval = (*opc83_word_operation[emu->cur_rh]) (emu, destval, imm); 1892 if (emu->cur_rh != 7) 1893 write_back_word(emu, destval); 1894 } 1895 1896 static void 1897 x86emuOp_opc83_word_RM_IMM(struct X86EMU *emu) 1898 { 1899 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1900 x86emuOp32_opc83_word_RM_IMM(emu); 1901 else 1902 x86emuOp16_opc83_word_RM_IMM(emu); 1903 } 1904 /**************************************************************************** 1905 REMARKS: 1906 Handles opcode 0x86 1907 ****************************************************************************/ 1908 static void 1909 x86emuOp_xchg_byte_RM_R(struct X86EMU *emu) 1910 { 1911 uint8_t *srcreg, destval, tmp; 1912 1913 fetch_decode_modrm(emu); 1914 destval = decode_and_fetch_byte(emu); 1915 srcreg = decode_rh_byte_register(emu); 1916 tmp = destval; 1917 destval = *srcreg; 1918 *srcreg = tmp; 1919 write_back_byte(emu, destval); 1920 } 1921 /**************************************************************************** 1922 REMARKS: 1923 Handles opcode 0x87 1924 ****************************************************************************/ 1925 static void 1926 x86emuOp32_xchg_word_RM_R(struct X86EMU *emu) 1927 { 1928 uint32_t *srcreg, destval, tmp; 1929 1930 fetch_decode_modrm(emu); 1931 destval = decode_and_fetch_long(emu); 1932 srcreg = decode_rh_long_register(emu); 1933 tmp = destval; 1934 destval = *srcreg; 1935 *srcreg = tmp; 1936 write_back_long(emu, destval); 1937 } 1938 1939 static void 1940 x86emuOp16_xchg_word_RM_R(struct X86EMU *emu) 1941 { 1942 uint16_t *srcreg, destval, tmp; 1943 1944 fetch_decode_modrm(emu); 1945 destval = decode_and_fetch_word(emu); 1946 srcreg = decode_rh_word_register(emu); 1947 tmp = destval; 1948 destval = *srcreg; 1949 *srcreg = tmp; 1950 write_back_word(emu, destval); 1951 } 1952 1953 static void 1954 x86emuOp_xchg_word_RM_R(struct X86EMU *emu) 1955 { 1956 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1957 x86emuOp32_xchg_word_RM_R(emu); 1958 else 1959 x86emuOp16_xchg_word_RM_R(emu); 1960 } 1961 /**************************************************************************** 1962 REMARKS: 1963 Handles opcode 0x88 1964 ****************************************************************************/ 1965 static void 1966 x86emuOp_mov_byte_RM_R(struct X86EMU *emu) 1967 { 1968 uint8_t *destreg, *srcreg; 1969 uint32_t destoffset; 1970 1971 fetch_decode_modrm(emu); 1972 srcreg = decode_rh_byte_register(emu); 1973 if (emu->cur_mod != 3) { 1974 destoffset = decode_rl_address(emu); 1975 store_data_byte(emu, destoffset, *srcreg); 1976 } else { 1977 destreg = decode_rl_byte_register(emu); 1978 *destreg = *srcreg; 1979 } 1980 } 1981 /**************************************************************************** 1982 REMARKS: 1983 Handles opcode 0x89 1984 ****************************************************************************/ 1985 static void 1986 x86emuOp32_mov_word_RM_R(struct X86EMU *emu) 1987 { 1988 uint32_t destoffset; 1989 uint32_t *destreg, srcval; 1990 1991 fetch_decode_modrm(emu); 1992 srcval = *decode_rh_long_register(emu); 1993 if (emu->cur_mod != 3) { 1994 destoffset = decode_rl_address(emu); 1995 store_data_long(emu, destoffset, srcval); 1996 } else { 1997 destreg = decode_rl_long_register(emu); 1998 *destreg = srcval; 1999 } 2000 } 2001 2002 static void 2003 x86emuOp16_mov_word_RM_R(struct X86EMU *emu) 2004 { 2005 uint32_t destoffset; 2006 uint16_t *destreg, srcval; 2007 2008 fetch_decode_modrm(emu); 2009 srcval = *decode_rh_word_register(emu); 2010 if (emu->cur_mod != 3) { 2011 destoffset = decode_rl_address(emu); 2012 store_data_word(emu, destoffset, srcval); 2013 } else { 2014 destreg = decode_rl_word_register(emu); 2015 *destreg = srcval; 2016 } 2017 } 2018 2019 static void 2020 x86emuOp_mov_word_RM_R(struct X86EMU *emu) 2021 { 2022 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2023 x86emuOp32_mov_word_RM_R(emu); 2024 else 2025 x86emuOp16_mov_word_RM_R(emu); 2026 } 2027 /**************************************************************************** 2028 REMARKS: 2029 Handles opcode 0x8a 2030 ****************************************************************************/ 2031 static void 2032 x86emuOp_mov_byte_R_RM(struct X86EMU *emu) 2033 { 2034 uint8_t *destreg; 2035 2036 fetch_decode_modrm(emu); 2037 destreg = decode_rh_byte_register(emu); 2038 *destreg = decode_and_fetch_byte(emu); 2039 } 2040 /**************************************************************************** 2041 REMARKS: 2042 Handles opcode 0x8b 2043 ****************************************************************************/ 2044 static void 2045 x86emuOp_mov_word_R_RM(struct X86EMU *emu) 2046 { 2047 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2048 uint32_t *destreg; 2049 2050 fetch_decode_modrm(emu); 2051 destreg = decode_rh_long_register(emu); 2052 *destreg = decode_and_fetch_long(emu); 2053 } else { 2054 uint16_t *destreg; 2055 2056 fetch_decode_modrm(emu); 2057 destreg = decode_rh_word_register(emu); 2058 *destreg = decode_and_fetch_word(emu); 2059 } 2060 } 2061 /**************************************************************************** 2062 REMARKS: 2063 Handles opcode 0x8c 2064 ****************************************************************************/ 2065 static void 2066 x86emuOp_mov_word_RM_SR(struct X86EMU *emu) 2067 { 2068 uint16_t *destreg, srcval; 2069 uint32_t destoffset; 2070 2071 fetch_decode_modrm(emu); 2072 srcval = *decode_rh_seg_register(emu); 2073 if (emu->cur_mod != 3) { 2074 destoffset = decode_rl_address(emu); 2075 store_data_word(emu, destoffset, srcval); 2076 } else { 2077 destreg = decode_rl_word_register(emu); 2078 *destreg = srcval; 2079 } 2080 } 2081 /**************************************************************************** 2082 REMARKS: 2083 Handles opcode 0x8d 2084 ****************************************************************************/ 2085 static void 2086 x86emuOp_lea_word_R_M(struct X86EMU *emu) 2087 { 2088 uint16_t *srcreg; 2089 uint32_t destoffset; 2090 2091 /* 2092 * TODO: Need to handle address size prefix! 2093 * 2094 * lea eax,[eax+ebx*2] ?? 2095 */ 2096 fetch_decode_modrm(emu); 2097 if (emu->cur_mod == 3) 2098 X86EMU_halt_sys(emu); 2099 2100 srcreg = decode_rh_word_register(emu); 2101 destoffset = decode_rl_address(emu); 2102 *srcreg = (uint16_t) destoffset; 2103 } 2104 /**************************************************************************** 2105 REMARKS: 2106 Handles opcode 0x8e 2107 ****************************************************************************/ 2108 static void 2109 x86emuOp_mov_word_SR_RM(struct X86EMU *emu) 2110 { 2111 uint16_t *destreg; 2112 2113 fetch_decode_modrm(emu); 2114 destreg = decode_rh_seg_register(emu); 2115 *destreg = decode_and_fetch_word(emu); 2116 /* 2117 * Clean up, and reset all the R_xSP pointers to the correct 2118 * locations. This is about 3x too much overhead (doing all the 2119 * segreg ptrs when only one is needed, but this instruction 2120 * *cannot* be that common, and this isn't too much work anyway. 2121 */ 2122 } 2123 /**************************************************************************** 2124 REMARKS: 2125 Handles opcode 0x8f 2126 ****************************************************************************/ 2127 static void 2128 x86emuOp32_pop_RM(struct X86EMU *emu) 2129 { 2130 uint32_t destoffset; 2131 uint32_t destval, *destreg; 2132 2133 fetch_decode_modrm(emu); 2134 if (emu->cur_mod != 3) { 2135 destoffset = decode_rl_address(emu); 2136 destval = pop_long(emu); 2137 store_data_long(emu, destoffset, destval); 2138 } else { 2139 destreg = decode_rl_long_register(emu); 2140 *destreg = pop_long(emu); 2141 } 2142 } 2143 2144 static void 2145 x86emuOp16_pop_RM(struct X86EMU *emu) 2146 { 2147 uint32_t destoffset; 2148 uint16_t destval, *destreg; 2149 2150 fetch_decode_modrm(emu); 2151 if (emu->cur_mod != 3) { 2152 destoffset = decode_rl_address(emu); 2153 destval = pop_word(emu); 2154 store_data_word(emu, destoffset, destval); 2155 } else { 2156 destreg = decode_rl_word_register(emu); 2157 *destreg = pop_word(emu); 2158 } 2159 } 2160 2161 static void 2162 x86emuOp_pop_RM(struct X86EMU *emu) 2163 { 2164 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2165 x86emuOp32_pop_RM(emu); 2166 else 2167 x86emuOp16_pop_RM(emu); 2168 } 2169 /**************************************************************************** 2170 REMARKS: 2171 Handles opcode 0x91 2172 ****************************************************************************/ 2173 static void 2174 x86emuOp_xchg_word_AX_CX(struct X86EMU *emu) 2175 { 2176 uint32_t tmp; 2177 2178 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2179 tmp = emu->x86.R_EAX; 2180 emu->x86.R_EAX = emu->x86.R_ECX; 2181 emu->x86.R_ECX = tmp; 2182 } else { 2183 tmp = emu->x86.R_AX; 2184 emu->x86.R_AX = emu->x86.R_CX; 2185 emu->x86.R_CX = (uint16_t) tmp; 2186 } 2187 } 2188 /**************************************************************************** 2189 REMARKS: 2190 Handles opcode 0x92 2191 ****************************************************************************/ 2192 static void 2193 x86emuOp_xchg_word_AX_DX(struct X86EMU *emu) 2194 { 2195 uint32_t tmp; 2196 2197 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2198 tmp = emu->x86.R_EAX; 2199 emu->x86.R_EAX = emu->x86.R_EDX; 2200 emu->x86.R_EDX = tmp; 2201 } else { 2202 tmp = emu->x86.R_AX; 2203 emu->x86.R_AX = emu->x86.R_DX; 2204 emu->x86.R_DX = (uint16_t) tmp; 2205 } 2206 } 2207 /**************************************************************************** 2208 REMARKS: 2209 Handles opcode 0x93 2210 ****************************************************************************/ 2211 static void 2212 x86emuOp_xchg_word_AX_BX(struct X86EMU *emu) 2213 { 2214 uint32_t tmp; 2215 2216 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2217 tmp = emu->x86.R_EAX; 2218 emu->x86.R_EAX = emu->x86.R_EBX; 2219 emu->x86.R_EBX = tmp; 2220 } else { 2221 tmp = emu->x86.R_AX; 2222 emu->x86.R_AX = emu->x86.R_BX; 2223 emu->x86.R_BX = (uint16_t) tmp; 2224 } 2225 } 2226 /**************************************************************************** 2227 REMARKS: 2228 Handles opcode 0x94 2229 ****************************************************************************/ 2230 static void 2231 x86emuOp_xchg_word_AX_SP(struct X86EMU *emu) 2232 { 2233 uint32_t tmp; 2234 2235 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2236 tmp = emu->x86.R_EAX; 2237 emu->x86.R_EAX = emu->x86.R_ESP; 2238 emu->x86.R_ESP = tmp; 2239 } else { 2240 tmp = emu->x86.R_AX; 2241 emu->x86.R_AX = emu->x86.R_SP; 2242 emu->x86.R_SP = (uint16_t) tmp; 2243 } 2244 } 2245 /**************************************************************************** 2246 REMARKS: 2247 Handles opcode 0x95 2248 ****************************************************************************/ 2249 static void 2250 x86emuOp_xchg_word_AX_BP(struct X86EMU *emu) 2251 { 2252 uint32_t tmp; 2253 2254 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2255 tmp = emu->x86.R_EAX; 2256 emu->x86.R_EAX = emu->x86.R_EBP; 2257 emu->x86.R_EBP = tmp; 2258 } else { 2259 tmp = emu->x86.R_AX; 2260 emu->x86.R_AX = emu->x86.R_BP; 2261 emu->x86.R_BP = (uint16_t) tmp; 2262 } 2263 } 2264 /**************************************************************************** 2265 REMARKS: 2266 Handles opcode 0x96 2267 ****************************************************************************/ 2268 static void 2269 x86emuOp_xchg_word_AX_SI(struct X86EMU *emu) 2270 { 2271 uint32_t tmp; 2272 2273 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2274 tmp = emu->x86.R_EAX; 2275 emu->x86.R_EAX = emu->x86.R_ESI; 2276 emu->x86.R_ESI = tmp; 2277 } else { 2278 tmp = emu->x86.R_AX; 2279 emu->x86.R_AX = emu->x86.R_SI; 2280 emu->x86.R_SI = (uint16_t) tmp; 2281 } 2282 } 2283 /**************************************************************************** 2284 REMARKS: 2285 Handles opcode 0x97 2286 ****************************************************************************/ 2287 static void 2288 x86emuOp_xchg_word_AX_DI(struct X86EMU *emu) 2289 { 2290 uint32_t tmp; 2291 2292 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2293 tmp = emu->x86.R_EAX; 2294 emu->x86.R_EAX = emu->x86.R_EDI; 2295 emu->x86.R_EDI = tmp; 2296 } else { 2297 tmp = emu->x86.R_AX; 2298 emu->x86.R_AX = emu->x86.R_DI; 2299 emu->x86.R_DI = (uint16_t) tmp; 2300 } 2301 } 2302 /**************************************************************************** 2303 REMARKS: 2304 Handles opcode 0x98 2305 ****************************************************************************/ 2306 static void 2307 x86emuOp_cbw(struct X86EMU *emu) 2308 { 2309 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2310 if (emu->x86.R_AX & 0x8000) { 2311 emu->x86.R_EAX |= 0xffff0000; 2312 } else { 2313 emu->x86.R_EAX &= 0x0000ffff; 2314 } 2315 } else { 2316 if (emu->x86.R_AL & 0x80) { 2317 emu->x86.R_AH = 0xff; 2318 } else { 2319 emu->x86.R_AH = 0x0; 2320 } 2321 } 2322 } 2323 /**************************************************************************** 2324 REMARKS: 2325 Handles opcode 0x99 2326 ****************************************************************************/ 2327 static void 2328 x86emuOp_cwd(struct X86EMU *emu) 2329 { 2330 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2331 if (emu->x86.R_EAX & 0x80000000) { 2332 emu->x86.R_EDX = 0xffffffff; 2333 } else { 2334 emu->x86.R_EDX = 0x0; 2335 } 2336 } else { 2337 if (emu->x86.R_AX & 0x8000) { 2338 emu->x86.R_DX = 0xffff; 2339 } else { 2340 emu->x86.R_DX = 0x0; 2341 } 2342 } 2343 } 2344 /**************************************************************************** 2345 REMARKS: 2346 Handles opcode 0x9a 2347 ****************************************************************************/ 2348 static void 2349 x86emuOp_call_far_IMM(struct X86EMU *emu) 2350 { 2351 uint16_t farseg, faroff; 2352 2353 faroff = fetch_word_imm(emu); 2354 farseg = fetch_word_imm(emu); 2355 /* XXX 2356 * 2357 * Hooked interrupt vectors calling into our "BIOS" will cause problems 2358 * unless all intersegment stuff is checked for BIOS access. Check 2359 * needed here. For moment, let it alone. */ 2360 push_word(emu, emu->x86.R_CS); 2361 emu->x86.R_CS = farseg; 2362 push_word(emu, emu->x86.R_IP); 2363 emu->x86.R_IP = faroff; 2364 } 2365 /**************************************************************************** 2366 REMARKS: 2367 Handles opcode 0x9c 2368 ****************************************************************************/ 2369 static void 2370 x86emuOp_pushf_word(struct X86EMU *emu) 2371 { 2372 uint32_t flags; 2373 2374 /* clear out *all* bits not representing flags, and turn on real bits */ 2375 flags = (emu->x86.R_EFLG & F_MSK) | F_ALWAYS_ON; 2376 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2377 push_long(emu, flags); 2378 } else { 2379 push_word(emu, (uint16_t) flags); 2380 } 2381 } 2382 /**************************************************************************** 2383 REMARKS: 2384 Handles opcode 0x9d 2385 ****************************************************************************/ 2386 static void 2387 x86emuOp_popf_word(struct X86EMU *emu) 2388 { 2389 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2390 emu->x86.R_EFLG = pop_long(emu); 2391 } else { 2392 emu->x86.R_FLG = pop_word(emu); 2393 } 2394 } 2395 /**************************************************************************** 2396 REMARKS: 2397 Handles opcode 0x9e 2398 ****************************************************************************/ 2399 static void 2400 x86emuOp_sahf(struct X86EMU *emu) 2401 { 2402 /* clear the lower bits of the flag register */ 2403 emu->x86.R_FLG &= 0xffffff00; 2404 /* or in the AH register into the flags register */ 2405 emu->x86.R_FLG |= emu->x86.R_AH; 2406 } 2407 /**************************************************************************** 2408 REMARKS: 2409 Handles opcode 0x9f 2410 ****************************************************************************/ 2411 static void 2412 x86emuOp_lahf(struct X86EMU *emu) 2413 { 2414 emu->x86.R_AH = (uint8_t) (emu->x86.R_FLG & 0xff); 2415 /* undocumented TC++ behavior??? Nope. It's documented, but you have 2416 * too look real hard to notice it. */ 2417 emu->x86.R_AH |= 0x2; 2418 } 2419 /**************************************************************************** 2420 REMARKS: 2421 Handles opcode 0xa0 2422 ****************************************************************************/ 2423 static void 2424 x86emuOp_mov_AL_M_IMM(struct X86EMU *emu) 2425 { 2426 uint16_t offset; 2427 2428 offset = fetch_word_imm(emu); 2429 emu->x86.R_AL = fetch_data_byte(emu, offset); 2430 } 2431 /**************************************************************************** 2432 REMARKS: 2433 Handles opcode 0xa1 2434 ****************************************************************************/ 2435 static void 2436 x86emuOp_mov_AX_M_IMM(struct X86EMU *emu) 2437 { 2438 uint16_t offset; 2439 2440 offset = fetch_word_imm(emu); 2441 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2442 emu->x86.R_EAX = fetch_data_long(emu, offset); 2443 } else { 2444 emu->x86.R_AX = fetch_data_word(emu, offset); 2445 } 2446 } 2447 /**************************************************************************** 2448 REMARKS: 2449 Handles opcode 0xa2 2450 ****************************************************************************/ 2451 static void 2452 x86emuOp_mov_M_AL_IMM(struct X86EMU *emu) 2453 { 2454 uint16_t offset; 2455 2456 offset = fetch_word_imm(emu); 2457 store_data_byte(emu, offset, emu->x86.R_AL); 2458 } 2459 /**************************************************************************** 2460 REMARKS: 2461 Handles opcode 0xa3 2462 ****************************************************************************/ 2463 static void 2464 x86emuOp_mov_M_AX_IMM(struct X86EMU *emu) 2465 { 2466 uint16_t offset; 2467 2468 offset = fetch_word_imm(emu); 2469 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2470 store_data_long(emu, offset, emu->x86.R_EAX); 2471 } else { 2472 store_data_word(emu, offset, emu->x86.R_AX); 2473 } 2474 } 2475 /**************************************************************************** 2476 REMARKS: 2477 Handles opcode 0xa4 2478 ****************************************************************************/ 2479 static void 2480 x86emuOp_movs_byte(struct X86EMU *emu) 2481 { 2482 uint8_t val; 2483 uint32_t count; 2484 int inc; 2485 2486 if (ACCESS_FLAG(F_DF)) /* down */ 2487 inc = -1; 2488 else 2489 inc = 1; 2490 count = 1; 2491 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2492 /* dont care whether REPE or REPNE */ 2493 /* move them until CX is ZERO. */ 2494 count = emu->x86.R_CX; 2495 emu->x86.R_CX = 0; 2496 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2497 } 2498 while (count--) { 2499 val = fetch_data_byte(emu, emu->x86.R_SI); 2500 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, val); 2501 emu->x86.R_SI += inc; 2502 emu->x86.R_DI += inc; 2503 } 2504 } 2505 /**************************************************************************** 2506 REMARKS: 2507 Handles opcode 0xa5 2508 ****************************************************************************/ 2509 static void 2510 x86emuOp_movs_word(struct X86EMU *emu) 2511 { 2512 uint32_t val; 2513 int inc; 2514 uint32_t count; 2515 2516 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2517 inc = 4; 2518 else 2519 inc = 2; 2520 2521 if (ACCESS_FLAG(F_DF)) /* down */ 2522 inc = -inc; 2523 2524 count = 1; 2525 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2526 /* dont care whether REPE or REPNE */ 2527 /* move them until CX is ZERO. */ 2528 count = emu->x86.R_CX; 2529 emu->x86.R_CX = 0; 2530 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2531 } 2532 while (count--) { 2533 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2534 val = fetch_data_long(emu, emu->x86.R_SI); 2535 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, val); 2536 } else { 2537 val = fetch_data_word(emu, emu->x86.R_SI); 2538 store_word(emu, emu->x86.R_ES, emu->x86.R_DI, (uint16_t) val); 2539 } 2540 emu->x86.R_SI += inc; 2541 emu->x86.R_DI += inc; 2542 } 2543 } 2544 /**************************************************************************** 2545 REMARKS: 2546 Handles opcode 0xa6 2547 ****************************************************************************/ 2548 static void 2549 x86emuOp_cmps_byte(struct X86EMU *emu) 2550 { 2551 int8_t val1, val2; 2552 int inc; 2553 2554 if (ACCESS_FLAG(F_DF)) /* down */ 2555 inc = -1; 2556 else 2557 inc = 1; 2558 2559 if (emu->x86.mode & SYSMODE_PREFIX_REPE) { 2560 /* REPE */ 2561 /* move them until CX is ZERO. */ 2562 while (emu->x86.R_CX != 0) { 2563 val1 = fetch_data_byte(emu, emu->x86.R_SI); 2564 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2565 cmp_byte(emu, val1, val2); 2566 emu->x86.R_CX -= 1; 2567 emu->x86.R_SI += inc; 2568 emu->x86.R_DI += inc; 2569 if (ACCESS_FLAG(F_ZF) == 0) 2570 break; 2571 } 2572 emu->x86.mode &= ~SYSMODE_PREFIX_REPE; 2573 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) { 2574 /* REPNE */ 2575 /* move them until CX is ZERO. */ 2576 while (emu->x86.R_CX != 0) { 2577 val1 = fetch_data_byte(emu, emu->x86.R_SI); 2578 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2579 cmp_byte(emu, val1, val2); 2580 emu->x86.R_CX -= 1; 2581 emu->x86.R_SI += inc; 2582 emu->x86.R_DI += inc; 2583 if (ACCESS_FLAG(F_ZF)) 2584 break; /* zero flag set means equal */ 2585 } 2586 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE; 2587 } else { 2588 val1 = fetch_data_byte(emu, emu->x86.R_SI); 2589 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2590 cmp_byte(emu, val1, val2); 2591 emu->x86.R_SI += inc; 2592 emu->x86.R_DI += inc; 2593 } 2594 } 2595 /**************************************************************************** 2596 REMARKS: 2597 Handles opcode 0xa7 2598 ****************************************************************************/ 2599 static void 2600 x86emuOp_cmps_word(struct X86EMU *emu) 2601 { 2602 uint32_t val1, val2; 2603 int inc; 2604 2605 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2606 if (ACCESS_FLAG(F_DF)) /* down */ 2607 inc = -4; 2608 else 2609 inc = 4; 2610 } else { 2611 if (ACCESS_FLAG(F_DF)) /* down */ 2612 inc = -2; 2613 else 2614 inc = 2; 2615 } 2616 if (emu->x86.mode & SYSMODE_PREFIX_REPE) { 2617 /* REPE */ 2618 /* move them until CX is ZERO. */ 2619 while (emu->x86.R_CX != 0) { 2620 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2621 val1 = fetch_data_long(emu, emu->x86.R_SI); 2622 val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2623 cmp_long(emu, val1, val2); 2624 } else { 2625 val1 = fetch_data_word(emu, emu->x86.R_SI); 2626 val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2627 cmp_word(emu, (uint16_t) val1, (uint16_t) val2); 2628 } 2629 emu->x86.R_CX -= 1; 2630 emu->x86.R_SI += inc; 2631 emu->x86.R_DI += inc; 2632 if (ACCESS_FLAG(F_ZF) == 0) 2633 break; 2634 } 2635 emu->x86.mode &= ~SYSMODE_PREFIX_REPE; 2636 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) { 2637 /* REPNE */ 2638 /* move them until CX is ZERO. */ 2639 while (emu->x86.R_CX != 0) { 2640 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2641 val1 = fetch_data_long(emu, emu->x86.R_SI); 2642 val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2643 cmp_long(emu, val1, val2); 2644 } else { 2645 val1 = fetch_data_word(emu, emu->x86.R_SI); 2646 val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2647 cmp_word(emu, (uint16_t) val1, (uint16_t) val2); 2648 } 2649 emu->x86.R_CX -= 1; 2650 emu->x86.R_SI += inc; 2651 emu->x86.R_DI += inc; 2652 if (ACCESS_FLAG(F_ZF)) 2653 break; /* zero flag set means equal */ 2654 } 2655 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE; 2656 } else { 2657 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2658 val1 = fetch_data_long(emu, emu->x86.R_SI); 2659 val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2660 cmp_long(emu, val1, val2); 2661 } else { 2662 val1 = fetch_data_word(emu, emu->x86.R_SI); 2663 val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2664 cmp_word(emu, (uint16_t) val1, (uint16_t) val2); 2665 } 2666 emu->x86.R_SI += inc; 2667 emu->x86.R_DI += inc; 2668 } 2669 } 2670 /**************************************************************************** 2671 REMARKS: 2672 Handles opcode 0xa9 2673 ****************************************************************************/ 2674 static void 2675 x86emuOp_test_AX_IMM(struct X86EMU *emu) 2676 { 2677 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2678 test_long(emu, emu->x86.R_EAX, fetch_long_imm(emu)); 2679 } else { 2680 test_word(emu, emu->x86.R_AX, fetch_word_imm(emu)); 2681 } 2682 } 2683 /**************************************************************************** 2684 REMARKS: 2685 Handles opcode 0xaa 2686 ****************************************************************************/ 2687 static void 2688 x86emuOp_stos_byte(struct X86EMU *emu) 2689 { 2690 int inc; 2691 2692 if (ACCESS_FLAG(F_DF)) /* down */ 2693 inc = -1; 2694 else 2695 inc = 1; 2696 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2697 /* dont care whether REPE or REPNE */ 2698 /* move them until CX is ZERO. */ 2699 while (emu->x86.R_CX != 0) { 2700 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL); 2701 emu->x86.R_CX -= 1; 2702 emu->x86.R_DI += inc; 2703 } 2704 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2705 } else { 2706 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL); 2707 emu->x86.R_DI += inc; 2708 } 2709 } 2710 /**************************************************************************** 2711 REMARKS: 2712 Handles opcode 0xab 2713 ****************************************************************************/ 2714 static void 2715 x86emuOp_stos_word(struct X86EMU *emu) 2716 { 2717 int inc; 2718 uint32_t count; 2719 2720 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2721 inc = 4; 2722 else 2723 inc = 2; 2724 2725 if (ACCESS_FLAG(F_DF)) /* down */ 2726 inc = -inc; 2727 2728 count = 1; 2729 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2730 /* dont care whether REPE or REPNE */ 2731 /* move them until CX is ZERO. */ 2732 count = emu->x86.R_CX; 2733 emu->x86.R_CX = 0; 2734 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2735 } 2736 while (count--) { 2737 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2738 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_EAX); 2739 } else { 2740 store_word(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AX); 2741 } 2742 emu->x86.R_DI += inc; 2743 } 2744 } 2745 /**************************************************************************** 2746 REMARKS: 2747 Handles opcode 0xac 2748 ****************************************************************************/ 2749 static void 2750 x86emuOp_lods_byte(struct X86EMU *emu) 2751 { 2752 int inc; 2753 2754 if (ACCESS_FLAG(F_DF)) /* down */ 2755 inc = -1; 2756 else 2757 inc = 1; 2758 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2759 /* dont care whether REPE or REPNE */ 2760 /* move them until CX is ZERO. */ 2761 while (emu->x86.R_CX != 0) { 2762 emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI); 2763 emu->x86.R_CX -= 1; 2764 emu->x86.R_SI += inc; 2765 } 2766 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2767 } else { 2768 emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI); 2769 emu->x86.R_SI += inc; 2770 } 2771 } 2772 /**************************************************************************** 2773 REMARKS: 2774 Handles opcode 0xad 2775 ****************************************************************************/ 2776 static void 2777 x86emuOp_lods_word(struct X86EMU *emu) 2778 { 2779 int inc; 2780 uint32_t count; 2781 2782 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2783 inc = 4; 2784 else 2785 inc = 2; 2786 2787 if (ACCESS_FLAG(F_DF)) /* down */ 2788 inc = -inc; 2789 2790 count = 1; 2791 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2792 /* dont care whether REPE or REPNE */ 2793 /* move them until CX is ZERO. */ 2794 count = emu->x86.R_CX; 2795 emu->x86.R_CX = 0; 2796 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2797 } 2798 while (count--) { 2799 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2800 emu->x86.R_EAX = fetch_data_long(emu, emu->x86.R_SI); 2801 } else { 2802 emu->x86.R_AX = fetch_data_word(emu, emu->x86.R_SI); 2803 } 2804 emu->x86.R_SI += inc; 2805 } 2806 } 2807 /**************************************************************************** 2808 REMARKS: 2809 Handles opcode 0xae 2810 ****************************************************************************/ 2811 static void 2812 x86emuOp_scas_byte(struct X86EMU *emu) 2813 { 2814 int8_t val2; 2815 int inc; 2816 2817 if (ACCESS_FLAG(F_DF)) /* down */ 2818 inc = -1; 2819 else 2820 inc = 1; 2821 if (emu->x86.mode & SYSMODE_PREFIX_REPE) { 2822 /* REPE */ 2823 /* move them until CX is ZERO. */ 2824 while (emu->x86.R_CX != 0) { 2825 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2826 cmp_byte(emu, emu->x86.R_AL, val2); 2827 emu->x86.R_CX -= 1; 2828 emu->x86.R_DI += inc; 2829 if (ACCESS_FLAG(F_ZF) == 0) 2830 break; 2831 } 2832 emu->x86.mode &= ~SYSMODE_PREFIX_REPE; 2833 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) { 2834 /* REPNE */ 2835 /* move them until CX is ZERO. */ 2836 while (emu->x86.R_CX != 0) { 2837 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2838 cmp_byte(emu, emu->x86.R_AL, val2); 2839 emu->x86.R_CX -= 1; 2840 emu->x86.R_DI += inc; 2841 if (ACCESS_FLAG(F_ZF)) 2842 break; /* zero flag set means equal */ 2843 } 2844 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE; 2845 } else { 2846 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2847 cmp_byte(emu, emu->x86.R_AL, val2); 2848 emu->x86.R_DI += inc; 2849 } 2850 } 2851 /**************************************************************************** 2852 REMARKS: 2853 Handles opcode 0xaf 2854 ****************************************************************************/ 2855 static void 2856 x86emuOp_scas_word(struct X86EMU *emu) 2857 { 2858 int inc; 2859 uint32_t val; 2860 2861 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2862 inc = 4; 2863 else 2864 inc = 2; 2865 2866 if (ACCESS_FLAG(F_DF)) /* down */ 2867 inc = -inc; 2868 2869 if (emu->x86.mode & SYSMODE_PREFIX_REPE) { 2870 /* REPE */ 2871 /* move them until CX is ZERO. */ 2872 while (emu->x86.R_CX != 0) { 2873 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2874 val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2875 cmp_long(emu, emu->x86.R_EAX, val); 2876 } else { 2877 val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2878 cmp_word(emu, emu->x86.R_AX, (uint16_t) val); 2879 } 2880 emu->x86.R_CX -= 1; 2881 emu->x86.R_DI += inc; 2882 if (ACCESS_FLAG(F_ZF) == 0) 2883 break; 2884 } 2885 emu->x86.mode &= ~SYSMODE_PREFIX_REPE; 2886 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) { 2887 /* REPNE */ 2888 /* move them until CX is ZERO. */ 2889 while (emu->x86.R_CX != 0) { 2890 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2891 val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2892 cmp_long(emu, emu->x86.R_EAX, val); 2893 } else { 2894 val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2895 cmp_word(emu, emu->x86.R_AX, (uint16_t) val); 2896 } 2897 emu->x86.R_CX -= 1; 2898 emu->x86.R_DI += inc; 2899 if (ACCESS_FLAG(F_ZF)) 2900 break; /* zero flag set means equal */ 2901 } 2902 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE; 2903 } else { 2904 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2905 val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2906 cmp_long(emu, emu->x86.R_EAX, val); 2907 } else { 2908 val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2909 cmp_word(emu, emu->x86.R_AX, (uint16_t) val); 2910 } 2911 emu->x86.R_DI += inc; 2912 } 2913 } 2914 /**************************************************************************** 2915 REMARKS: 2916 Handles opcode 0xb8 2917 ****************************************************************************/ 2918 static void 2919 x86emuOp_mov_word_AX_IMM(struct X86EMU *emu) 2920 { 2921 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2922 emu->x86.R_EAX = fetch_long_imm(emu); 2923 else 2924 emu->x86.R_AX = fetch_word_imm(emu); 2925 } 2926 /**************************************************************************** 2927 REMARKS: 2928 Handles opcode 0xb9 2929 ****************************************************************************/ 2930 static void 2931 x86emuOp_mov_word_CX_IMM(struct X86EMU *emu) 2932 { 2933 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2934 emu->x86.R_ECX = fetch_long_imm(emu); 2935 else 2936 emu->x86.R_CX = fetch_word_imm(emu); 2937 } 2938 /**************************************************************************** 2939 REMARKS: 2940 Handles opcode 0xba 2941 ****************************************************************************/ 2942 static void 2943 x86emuOp_mov_word_DX_IMM(struct X86EMU *emu) 2944 { 2945 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2946 emu->x86.R_EDX = fetch_long_imm(emu); 2947 else 2948 emu->x86.R_DX = fetch_word_imm(emu); 2949 } 2950 /**************************************************************************** 2951 REMARKS: 2952 Handles opcode 0xbb 2953 ****************************************************************************/ 2954 static void 2955 x86emuOp_mov_word_BX_IMM(struct X86EMU *emu) 2956 { 2957 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2958 emu->x86.R_EBX = fetch_long_imm(emu); 2959 else 2960 emu->x86.R_BX = fetch_word_imm(emu); 2961 } 2962 /**************************************************************************** 2963 REMARKS: 2964 Handles opcode 0xbc 2965 ****************************************************************************/ 2966 static void 2967 x86emuOp_mov_word_SP_IMM(struct X86EMU *emu) 2968 { 2969 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2970 emu->x86.R_ESP = fetch_long_imm(emu); 2971 else 2972 emu->x86.R_SP = fetch_word_imm(emu); 2973 } 2974 /**************************************************************************** 2975 REMARKS: 2976 Handles opcode 0xbd 2977 ****************************************************************************/ 2978 static void 2979 x86emuOp_mov_word_BP_IMM(struct X86EMU *emu) 2980 { 2981 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2982 emu->x86.R_EBP = fetch_long_imm(emu); 2983 else 2984 emu->x86.R_BP = fetch_word_imm(emu); 2985 } 2986 /**************************************************************************** 2987 REMARKS: 2988 Handles opcode 0xbe 2989 ****************************************************************************/ 2990 static void 2991 x86emuOp_mov_word_SI_IMM(struct X86EMU *emu) 2992 { 2993 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2994 emu->x86.R_ESI = fetch_long_imm(emu); 2995 else 2996 emu->x86.R_SI = fetch_word_imm(emu); 2997 } 2998 /**************************************************************************** 2999 REMARKS: 3000 Handles opcode 0xbf 3001 ****************************************************************************/ 3002 static void 3003 x86emuOp_mov_word_DI_IMM(struct X86EMU *emu) 3004 { 3005 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3006 emu->x86.R_EDI = fetch_long_imm(emu); 3007 else 3008 emu->x86.R_DI = fetch_word_imm(emu); 3009 } 3010 /* used by opcodes c0, d0, and d2. */ 3011 static 3012 uint8_t(* const opcD0_byte_operation[]) (struct X86EMU *, uint8_t d, uint8_t s) = 3013 { 3014 rol_byte, 3015 ror_byte, 3016 rcl_byte, 3017 rcr_byte, 3018 shl_byte, 3019 shr_byte, 3020 shl_byte, /* sal_byte === shl_byte by definition */ 3021 sar_byte, 3022 }; 3023 /**************************************************************************** 3024 REMARKS: 3025 Handles opcode 0xc0 3026 ****************************************************************************/ 3027 static void 3028 x86emuOp_opcC0_byte_RM_MEM(struct X86EMU *emu) 3029 { 3030 uint8_t destval, amt; 3031 3032 /* 3033 * Yet another weirdo special case instruction format. Part of 3034 * the opcode held below in "RH". Doubly nested case would 3035 * result, except that the decoded instruction 3036 */ 3037 fetch_decode_modrm(emu); 3038 /* know operation, decode the mod byte to find the addressing mode. */ 3039 destval = decode_and_fetch_byte_imm8(emu, &amt); 3040 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, amt); 3041 write_back_byte(emu, destval); 3042 } 3043 /* used by opcodes c1, d1, and d3. */ 3044 static 3045 uint16_t(* const opcD1_word_operation[]) (struct X86EMU *, uint16_t s, uint8_t d) = 3046 { 3047 rol_word, 3048 ror_word, 3049 rcl_word, 3050 rcr_word, 3051 shl_word, 3052 shr_word, 3053 shl_word, /* sal_byte === shl_byte by definition */ 3054 sar_word, 3055 }; 3056 /* used by opcodes c1, d1, and d3. */ 3057 static 3058 uint32_t(* const opcD1_long_operation[]) (struct X86EMU *, uint32_t s, uint8_t d) = 3059 { 3060 rol_long, 3061 ror_long, 3062 rcl_long, 3063 rcr_long, 3064 shl_long, 3065 shr_long, 3066 shl_long, /* sal_byte === shl_byte by definition */ 3067 sar_long, 3068 }; 3069 /**************************************************************************** 3070 REMARKS: 3071 Handles opcode 0xc1 3072 ****************************************************************************/ 3073 static void 3074 x86emuOp_opcC1_word_RM_MEM(struct X86EMU *emu) 3075 { 3076 uint8_t amt; 3077 3078 /* 3079 * Yet another weirdo special case instruction format. Part of 3080 * the opcode held below in "RH". Doubly nested case would 3081 * result, except that the decoded instruction 3082 */ 3083 fetch_decode_modrm(emu); 3084 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3085 uint32_t destval; 3086 3087 destval = decode_and_fetch_long_imm8(emu, &amt); 3088 destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, amt); 3089 write_back_long(emu, destval); 3090 } else { 3091 uint16_t destval; 3092 3093 destval = decode_and_fetch_word_imm8(emu, &amt); 3094 destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, amt); 3095 write_back_word(emu, destval); 3096 } 3097 } 3098 /**************************************************************************** 3099 REMARKS: 3100 Handles opcode 0xc2 3101 ****************************************************************************/ 3102 static void 3103 x86emuOp_ret_near_IMM(struct X86EMU *emu) 3104 { 3105 uint16_t imm; 3106 3107 imm = fetch_word_imm(emu); 3108 emu->x86.R_IP = pop_word(emu); 3109 emu->x86.R_SP += imm; 3110 } 3111 /**************************************************************************** 3112 REMARKS: 3113 Handles opcode 0xc6 3114 ****************************************************************************/ 3115 static void 3116 x86emuOp_mov_byte_RM_IMM(struct X86EMU *emu) 3117 { 3118 uint8_t *destreg; 3119 uint32_t destoffset; 3120 uint8_t imm; 3121 3122 fetch_decode_modrm(emu); 3123 if (emu->cur_rh != 0) 3124 X86EMU_halt_sys(emu); 3125 if (emu->cur_mod != 3) { 3126 destoffset = decode_rl_address(emu); 3127 imm = fetch_byte_imm(emu); 3128 store_data_byte(emu, destoffset, imm); 3129 } else { 3130 destreg = decode_rl_byte_register(emu); 3131 imm = fetch_byte_imm(emu); 3132 *destreg = imm; 3133 } 3134 } 3135 /**************************************************************************** 3136 REMARKS: 3137 Handles opcode 0xc7 3138 ****************************************************************************/ 3139 static void 3140 x86emuOp32_mov_word_RM_IMM(struct X86EMU *emu) 3141 { 3142 uint32_t destoffset; 3143 uint32_t imm, *destreg; 3144 3145 fetch_decode_modrm(emu); 3146 if (emu->cur_rh != 0) 3147 X86EMU_halt_sys(emu); 3148 3149 if (emu->cur_mod != 3) { 3150 destoffset = decode_rl_address(emu); 3151 imm = fetch_long_imm(emu); 3152 store_data_long(emu, destoffset, imm); 3153 } else { 3154 destreg = decode_rl_long_register(emu); 3155 imm = fetch_long_imm(emu); 3156 *destreg = imm; 3157 } 3158 } 3159 3160 static void 3161 x86emuOp16_mov_word_RM_IMM(struct X86EMU *emu) 3162 { 3163 uint32_t destoffset; 3164 uint16_t imm, *destreg; 3165 3166 fetch_decode_modrm(emu); 3167 if (emu->cur_rh != 0) 3168 X86EMU_halt_sys(emu); 3169 3170 if (emu->cur_mod != 3) { 3171 destoffset = decode_rl_address(emu); 3172 imm = fetch_word_imm(emu); 3173 store_data_word(emu, destoffset, imm); 3174 } else { 3175 destreg = decode_rl_word_register(emu); 3176 imm = fetch_word_imm(emu); 3177 *destreg = imm; 3178 } 3179 } 3180 3181 static void 3182 x86emuOp_mov_word_RM_IMM(struct X86EMU *emu) 3183 { 3184 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3185 x86emuOp32_mov_word_RM_IMM(emu); 3186 else 3187 x86emuOp16_mov_word_RM_IMM(emu); 3188 } 3189 /**************************************************************************** 3190 REMARKS: 3191 Handles opcode 0xc8 3192 ****************************************************************************/ 3193 static void 3194 x86emuOp_enter(struct X86EMU *emu) 3195 { 3196 uint16_t local, frame_pointer; 3197 uint8_t nesting; 3198 int i; 3199 3200 local = fetch_word_imm(emu); 3201 nesting = fetch_byte_imm(emu); 3202 push_word(emu, emu->x86.R_BP); 3203 frame_pointer = emu->x86.R_SP; 3204 if (nesting > 0) { 3205 for (i = 1; i < nesting; i++) { 3206 emu->x86.R_BP -= 2; 3207 push_word(emu, fetch_word(emu, emu->x86.R_SS, emu->x86.R_BP)); 3208 } 3209 push_word(emu, frame_pointer); 3210 } 3211 emu->x86.R_BP = frame_pointer; 3212 emu->x86.R_SP = (uint16_t) (emu->x86.R_SP - local); 3213 } 3214 /**************************************************************************** 3215 REMARKS: 3216 Handles opcode 0xc9 3217 ****************************************************************************/ 3218 static void 3219 x86emuOp_leave(struct X86EMU *emu) 3220 { 3221 emu->x86.R_SP = emu->x86.R_BP; 3222 emu->x86.R_BP = pop_word(emu); 3223 } 3224 /**************************************************************************** 3225 REMARKS: 3226 Handles opcode 0xca 3227 ****************************************************************************/ 3228 static void 3229 x86emuOp_ret_far_IMM(struct X86EMU *emu) 3230 { 3231 uint16_t imm; 3232 3233 imm = fetch_word_imm(emu); 3234 emu->x86.R_IP = pop_word(emu); 3235 emu->x86.R_CS = pop_word(emu); 3236 emu->x86.R_SP += imm; 3237 } 3238 /**************************************************************************** 3239 REMARKS: 3240 Handles opcode 0xcb 3241 ****************************************************************************/ 3242 static void 3243 x86emuOp_ret_far(struct X86EMU *emu) 3244 { 3245 emu->x86.R_IP = pop_word(emu); 3246 emu->x86.R_CS = pop_word(emu); 3247 } 3248 /**************************************************************************** 3249 REMARKS: 3250 Handles opcode 0xcc 3251 ****************************************************************************/ 3252 static void 3253 x86emuOp_int3(struct X86EMU *emu) 3254 { 3255 x86emu_intr_dispatch(emu, 3); 3256 } 3257 /**************************************************************************** 3258 REMARKS: 3259 Handles opcode 0xcd 3260 ****************************************************************************/ 3261 static void 3262 x86emuOp_int_IMM(struct X86EMU *emu) 3263 { 3264 uint8_t intnum; 3265 3266 intnum = fetch_byte_imm(emu); 3267 x86emu_intr_dispatch(emu, intnum); 3268 } 3269 /**************************************************************************** 3270 REMARKS: 3271 Handles opcode 0xce 3272 ****************************************************************************/ 3273 static void 3274 x86emuOp_into(struct X86EMU *emu) 3275 { 3276 if (ACCESS_FLAG(F_OF)) 3277 x86emu_intr_dispatch(emu, 4); 3278 } 3279 /**************************************************************************** 3280 REMARKS: 3281 Handles opcode 0xcf 3282 ****************************************************************************/ 3283 static void 3284 x86emuOp_iret(struct X86EMU *emu) 3285 { 3286 emu->x86.R_IP = pop_word(emu); 3287 emu->x86.R_CS = pop_word(emu); 3288 emu->x86.R_FLG = pop_word(emu); 3289 } 3290 /**************************************************************************** 3291 REMARKS: 3292 Handles opcode 0xd0 3293 ****************************************************************************/ 3294 static void 3295 x86emuOp_opcD0_byte_RM_1(struct X86EMU *emu) 3296 { 3297 uint8_t destval; 3298 3299 fetch_decode_modrm(emu); 3300 destval = decode_and_fetch_byte(emu); 3301 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, 1); 3302 write_back_byte(emu, destval); 3303 } 3304 /**************************************************************************** 3305 REMARKS: 3306 Handles opcode 0xd1 3307 ****************************************************************************/ 3308 static void 3309 x86emuOp_opcD1_word_RM_1(struct X86EMU *emu) 3310 { 3311 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3312 uint32_t destval; 3313 3314 fetch_decode_modrm(emu); 3315 destval = decode_and_fetch_long(emu); 3316 destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, 1); 3317 write_back_long(emu, destval); 3318 } else { 3319 uint16_t destval; 3320 3321 fetch_decode_modrm(emu); 3322 destval = decode_and_fetch_word(emu); 3323 destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, 1); 3324 write_back_word(emu, destval); 3325 } 3326 } 3327 /**************************************************************************** 3328 REMARKS: 3329 Handles opcode 0xd2 3330 ****************************************************************************/ 3331 static void 3332 x86emuOp_opcD2_byte_RM_CL(struct X86EMU *emu) 3333 { 3334 uint8_t destval; 3335 3336 fetch_decode_modrm(emu); 3337 destval = decode_and_fetch_byte(emu); 3338 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL); 3339 write_back_byte(emu, destval); 3340 } 3341 /**************************************************************************** 3342 REMARKS: 3343 Handles opcode 0xd3 3344 ****************************************************************************/ 3345 static void 3346 x86emuOp_opcD3_word_RM_CL(struct X86EMU *emu) 3347 { 3348 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3349 uint32_t destval; 3350 3351 fetch_decode_modrm(emu); 3352 destval = decode_and_fetch_long(emu); 3353 destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL); 3354 write_back_long(emu, destval); 3355 } else { 3356 uint16_t destval; 3357 3358 fetch_decode_modrm(emu); 3359 destval = decode_and_fetch_word(emu); 3360 destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL); 3361 write_back_word(emu, destval); 3362 } 3363 } 3364 /**************************************************************************** 3365 REMARKS: 3366 Handles opcode 0xd4 3367 ****************************************************************************/ 3368 static void 3369 x86emuOp_aam(struct X86EMU *emu) 3370 { 3371 uint8_t a; 3372 3373 a = fetch_byte_imm(emu); /* this is a stupid encoding. */ 3374 if (a != 10) { 3375 /* fix: add base decoding aam_word(uint8_t val, int base a) */ 3376 X86EMU_halt_sys(emu); 3377 } 3378 /* note the type change here --- returning AL and AH in AX. */ 3379 emu->x86.R_AX = aam_word(emu, emu->x86.R_AL); 3380 } 3381 /**************************************************************************** 3382 REMARKS: 3383 Handles opcode 0xd5 3384 ****************************************************************************/ 3385 static void 3386 x86emuOp_aad(struct X86EMU *emu) 3387 { 3388 uint8_t a; 3389 3390 a = fetch_byte_imm(emu); 3391 if (a != 10) { 3392 /* fix: add base decoding aad_word(uint16_t val, int base a) */ 3393 X86EMU_halt_sys(emu); 3394 } 3395 emu->x86.R_AX = aad_word(emu, emu->x86.R_AX); 3396 } 3397 /* opcode 0xd6 ILLEGAL OPCODE */ 3398 3399 /**************************************************************************** 3400 REMARKS: 3401 Handles opcode 0xd7 3402 ****************************************************************************/ 3403 static void 3404 x86emuOp_xlat(struct X86EMU *emu) 3405 { 3406 uint16_t addr; 3407 3408 addr = (uint16_t) (emu->x86.R_BX + (uint8_t) emu->x86.R_AL); 3409 emu->x86.R_AL = fetch_data_byte(emu, addr); 3410 } 3411 3412 /* opcode=0xd8 */ 3413 static void 3414 x86emuOp_esc_coprocess_d8(struct X86EMU *emu) 3415 { 3416 } 3417 /* opcode=0xd9 */ 3418 static void 3419 x86emuOp_esc_coprocess_d9(struct X86EMU *emu) 3420 { 3421 fetch_decode_modrm(emu); 3422 if (emu->cur_mod != 3) 3423 decode_rl_address(emu); 3424 } 3425 /* opcode=0xda */ 3426 static void 3427 x86emuOp_esc_coprocess_da(struct X86EMU *emu) 3428 { 3429 fetch_decode_modrm(emu); 3430 if (emu->cur_mod != 3) 3431 decode_rl_address(emu); 3432 } 3433 /* opcode=0xdb */ 3434 static void 3435 x86emuOp_esc_coprocess_db(struct X86EMU *emu) 3436 { 3437 fetch_decode_modrm(emu); 3438 if (emu->cur_mod != 3) 3439 decode_rl_address(emu); 3440 } 3441 /* opcode=0xdc */ 3442 static void 3443 x86emuOp_esc_coprocess_dc(struct X86EMU *emu) 3444 { 3445 fetch_decode_modrm(emu); 3446 if (emu->cur_mod != 3) 3447 decode_rl_address(emu); 3448 } 3449 /* opcode=0xdd */ 3450 static void 3451 x86emuOp_esc_coprocess_dd(struct X86EMU *emu) 3452 { 3453 fetch_decode_modrm(emu); 3454 if (emu->cur_mod != 3) 3455 decode_rl_address(emu); 3456 } 3457 /* opcode=0xde */ 3458 static void 3459 x86emuOp_esc_coprocess_de(struct X86EMU *emu) 3460 { 3461 fetch_decode_modrm(emu); 3462 if (emu->cur_mod != 3) 3463 decode_rl_address(emu); 3464 } 3465 /* opcode=0xdf */ 3466 static void 3467 x86emuOp_esc_coprocess_df(struct X86EMU *emu) 3468 { 3469 fetch_decode_modrm(emu); 3470 if (emu->cur_mod != 3) 3471 decode_rl_address(emu); 3472 } 3473 3474 /**************************************************************************** 3475 REMARKS: 3476 Handles opcode 0xe0 3477 ****************************************************************************/ 3478 static void 3479 x86emuOp_loopne(struct X86EMU *emu) 3480 { 3481 int16_t ip; 3482 3483 ip = (int8_t) fetch_byte_imm(emu); 3484 ip += (int16_t) emu->x86.R_IP; 3485 emu->x86.R_CX -= 1; 3486 if (emu->x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */ 3487 emu->x86.R_IP = ip; 3488 } 3489 /**************************************************************************** 3490 REMARKS: 3491 Handles opcode 0xe1 3492 ****************************************************************************/ 3493 static void 3494 x86emuOp_loope(struct X86EMU *emu) 3495 { 3496 int16_t ip; 3497 3498 ip = (int8_t) fetch_byte_imm(emu); 3499 ip += (int16_t) emu->x86.R_IP; 3500 emu->x86.R_CX -= 1; 3501 if (emu->x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */ 3502 emu->x86.R_IP = ip; 3503 } 3504 /**************************************************************************** 3505 REMARKS: 3506 Handles opcode 0xe2 3507 ****************************************************************************/ 3508 static void 3509 x86emuOp_loop(struct X86EMU *emu) 3510 { 3511 int16_t ip; 3512 3513 ip = (int8_t) fetch_byte_imm(emu); 3514 ip += (int16_t) emu->x86.R_IP; 3515 emu->x86.R_CX -= 1; 3516 if (emu->x86.R_CX != 0) 3517 emu->x86.R_IP = ip; 3518 } 3519 /**************************************************************************** 3520 REMARKS: 3521 Handles opcode 0xe3 3522 ****************************************************************************/ 3523 static void 3524 x86emuOp_jcxz(struct X86EMU *emu) 3525 { 3526 uint16_t target; 3527 int8_t offset; 3528 3529 /* jump to byte offset if overflow flag is set */ 3530 offset = (int8_t) fetch_byte_imm(emu); 3531 target = (uint16_t) (emu->x86.R_IP + offset); 3532 if (emu->x86.R_CX == 0) 3533 emu->x86.R_IP = target; 3534 } 3535 /**************************************************************************** 3536 REMARKS: 3537 Handles opcode 0xe4 3538 ****************************************************************************/ 3539 static void 3540 x86emuOp_in_byte_AL_IMM(struct X86EMU *emu) 3541 { 3542 uint8_t port; 3543 3544 port = (uint8_t) fetch_byte_imm(emu); 3545 emu->x86.R_AL = (*emu->emu_inb) (emu, port); 3546 } 3547 /**************************************************************************** 3548 REMARKS: 3549 Handles opcode 0xe5 3550 ****************************************************************************/ 3551 static void 3552 x86emuOp_in_word_AX_IMM(struct X86EMU *emu) 3553 { 3554 uint8_t port; 3555 3556 port = (uint8_t) fetch_byte_imm(emu); 3557 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3558 emu->x86.R_EAX = (*emu->emu_inl) (emu, port); 3559 } else { 3560 emu->x86.R_AX = (*emu->emu_inw) (emu, port); 3561 } 3562 } 3563 /**************************************************************************** 3564 REMARKS: 3565 Handles opcode 0xe6 3566 ****************************************************************************/ 3567 static void 3568 x86emuOp_out_byte_IMM_AL(struct X86EMU *emu) 3569 { 3570 uint8_t port; 3571 3572 port = (uint8_t) fetch_byte_imm(emu); 3573 (*emu->emu_outb) (emu, port, emu->x86.R_AL); 3574 } 3575 /**************************************************************************** 3576 REMARKS: 3577 Handles opcode 0xe7 3578 ****************************************************************************/ 3579 static void 3580 x86emuOp_out_word_IMM_AX(struct X86EMU *emu) 3581 { 3582 uint8_t port; 3583 3584 port = (uint8_t) fetch_byte_imm(emu); 3585 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3586 (*emu->emu_outl) (emu, port, emu->x86.R_EAX); 3587 } else { 3588 (*emu->emu_outw) (emu, port, emu->x86.R_AX); 3589 } 3590 } 3591 /**************************************************************************** 3592 REMARKS: 3593 Handles opcode 0xe8 3594 ****************************************************************************/ 3595 static void 3596 x86emuOp_call_near_IMM(struct X86EMU *emu) 3597 { 3598 int16_t ip; 3599 3600 ip = (int16_t) fetch_word_imm(emu); 3601 ip += (int16_t) emu->x86.R_IP; /* CHECK SIGN */ 3602 push_word(emu, emu->x86.R_IP); 3603 emu->x86.R_IP = ip; 3604 } 3605 /**************************************************************************** 3606 REMARKS: 3607 Handles opcode 0xe9 3608 ****************************************************************************/ 3609 static void 3610 x86emuOp_jump_near_IMM(struct X86EMU *emu) 3611 { 3612 int ip; 3613 3614 ip = (int16_t) fetch_word_imm(emu); 3615 ip += (int16_t) emu->x86.R_IP; 3616 emu->x86.R_IP = (uint16_t) ip; 3617 } 3618 /**************************************************************************** 3619 REMARKS: 3620 Handles opcode 0xea 3621 ****************************************************************************/ 3622 static void 3623 x86emuOp_jump_far_IMM(struct X86EMU *emu) 3624 { 3625 uint16_t cs, ip; 3626 3627 ip = fetch_word_imm(emu); 3628 cs = fetch_word_imm(emu); 3629 emu->x86.R_IP = ip; 3630 emu->x86.R_CS = cs; 3631 } 3632 /**************************************************************************** 3633 REMARKS: 3634 Handles opcode 0xeb 3635 ****************************************************************************/ 3636 static void 3637 x86emuOp_jump_byte_IMM(struct X86EMU *emu) 3638 { 3639 uint16_t target; 3640 int8_t offset; 3641 3642 offset = (int8_t) fetch_byte_imm(emu); 3643 target = (uint16_t) (emu->x86.R_IP + offset); 3644 emu->x86.R_IP = target; 3645 } 3646 /**************************************************************************** 3647 REMARKS: 3648 Handles opcode 0xec 3649 ****************************************************************************/ 3650 static void 3651 x86emuOp_in_byte_AL_DX(struct X86EMU *emu) 3652 { 3653 emu->x86.R_AL = (*emu->emu_inb) (emu, emu->x86.R_DX); 3654 } 3655 /**************************************************************************** 3656 REMARKS: 3657 Handles opcode 0xed 3658 ****************************************************************************/ 3659 static void 3660 x86emuOp_in_word_AX_DX(struct X86EMU *emu) 3661 { 3662 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3663 emu->x86.R_EAX = (*emu->emu_inl) (emu, emu->x86.R_DX); 3664 } else { 3665 emu->x86.R_AX = (*emu->emu_inw) (emu, emu->x86.R_DX); 3666 } 3667 } 3668 /**************************************************************************** 3669 REMARKS: 3670 Handles opcode 0xee 3671 ****************************************************************************/ 3672 static void 3673 x86emuOp_out_byte_DX_AL(struct X86EMU *emu) 3674 { 3675 (*emu->emu_outb) (emu, emu->x86.R_DX, emu->x86.R_AL); 3676 } 3677 /**************************************************************************** 3678 REMARKS: 3679 Handles opcode 0xef 3680 ****************************************************************************/ 3681 static void 3682 x86emuOp_out_word_DX_AX(struct X86EMU *emu) 3683 { 3684 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3685 (*emu->emu_outl) (emu, emu->x86.R_DX, emu->x86.R_EAX); 3686 } else { 3687 (*emu->emu_outw) (emu, emu->x86.R_DX, emu->x86.R_AX); 3688 } 3689 } 3690 /**************************************************************************** 3691 REMARKS: 3692 Handles opcode 0xf0 3693 ****************************************************************************/ 3694 static void 3695 x86emuOp_lock(struct X86EMU *emu) 3696 { 3697 } 3698 /*opcode 0xf1 ILLEGAL OPERATION */ 3699 3700 /**************************************************************************** 3701 REMARKS: 3702 Handles opcode 0xf5 3703 ****************************************************************************/ 3704 static void 3705 x86emuOp_cmc(struct X86EMU *emu) 3706 { 3707 if (ACCESS_FLAG(F_CF)) 3708 CLEAR_FLAG(F_CF); 3709 else 3710 SET_FLAG(F_CF); 3711 } 3712 /**************************************************************************** 3713 REMARKS: 3714 Handles opcode 0xf6 3715 ****************************************************************************/ 3716 static void 3717 x86emuOp_opcF6_byte_RM(struct X86EMU *emu) 3718 { 3719 uint8_t destval, srcval; 3720 3721 /* long, drawn out code follows. Double switch for a total of 32 3722 * cases. */ 3723 fetch_decode_modrm(emu); 3724 if (emu->cur_rh == 1) 3725 X86EMU_halt_sys(emu); 3726 3727 if (emu->cur_rh == 0) { 3728 destval = decode_and_fetch_byte_imm8(emu, &srcval); 3729 test_byte(emu, destval, srcval); 3730 return; 3731 } 3732 destval = decode_and_fetch_byte(emu); 3733 switch (emu->cur_rh) { 3734 case 2: 3735 destval = ~destval; 3736 write_back_byte(emu, destval); 3737 break; 3738 case 3: 3739 destval = neg_byte(emu, destval); 3740 write_back_byte(emu, destval); 3741 break; 3742 case 4: 3743 mul_byte(emu, destval); 3744 break; 3745 case 5: 3746 imul_byte(emu, destval); 3747 break; 3748 case 6: 3749 div_byte(emu, destval); 3750 break; 3751 case 7: 3752 idiv_byte(emu, destval); 3753 break; 3754 } 3755 } 3756 /**************************************************************************** 3757 REMARKS: 3758 Handles opcode 0xf7 3759 ****************************************************************************/ 3760 static void 3761 x86emuOp32_opcF7_word_RM(struct X86EMU *emu) 3762 { 3763 uint32_t destval, srcval; 3764 3765 /* long, drawn out code follows. Double switch for a total of 32 3766 * cases. */ 3767 fetch_decode_modrm(emu); 3768 if (emu->cur_rh == 1) 3769 X86EMU_halt_sys(emu); 3770 3771 if (emu->cur_rh == 0) { 3772 if (emu->cur_mod != 3) { 3773 uint32_t destoffset; 3774 3775 destoffset = decode_rl_address(emu); 3776 srcval = fetch_long_imm(emu); 3777 destval = fetch_data_long(emu, destoffset); 3778 } else { 3779 srcval = fetch_long_imm(emu); 3780 destval = *decode_rl_long_register(emu); 3781 } 3782 test_long(emu, destval, srcval); 3783 return; 3784 } 3785 destval = decode_and_fetch_long(emu); 3786 switch (emu->cur_rh) { 3787 case 2: 3788 destval = ~destval; 3789 write_back_long(emu, destval); 3790 break; 3791 case 3: 3792 destval = neg_long(emu, destval); 3793 write_back_long(emu, destval); 3794 break; 3795 case 4: 3796 mul_long(emu, destval); 3797 break; 3798 case 5: 3799 imul_long(emu, destval); 3800 break; 3801 case 6: 3802 div_long(emu, destval); 3803 break; 3804 case 7: 3805 idiv_long(emu, destval); 3806 break; 3807 } 3808 } 3809 static void 3810 x86emuOp16_opcF7_word_RM(struct X86EMU *emu) 3811 { 3812 uint16_t destval, srcval; 3813 3814 /* long, drawn out code follows. Double switch for a total of 32 3815 * cases. */ 3816 fetch_decode_modrm(emu); 3817 if (emu->cur_rh == 1) 3818 X86EMU_halt_sys(emu); 3819 3820 if (emu->cur_rh == 0) { 3821 if (emu->cur_mod != 3) { 3822 uint32_t destoffset; 3823 3824 destoffset = decode_rl_address(emu); 3825 srcval = fetch_word_imm(emu); 3826 destval = fetch_data_word(emu, destoffset); 3827 } else { 3828 srcval = fetch_word_imm(emu); 3829 destval = *decode_rl_word_register(emu); 3830 } 3831 test_word(emu, destval, srcval); 3832 return; 3833 } 3834 destval = decode_and_fetch_word(emu); 3835 switch (emu->cur_rh) { 3836 case 2: 3837 destval = ~destval; 3838 write_back_word(emu, destval); 3839 break; 3840 case 3: 3841 destval = neg_word(emu, destval); 3842 write_back_word(emu, destval); 3843 break; 3844 case 4: 3845 mul_word(emu, destval); 3846 break; 3847 case 5: 3848 imul_word(emu, destval); 3849 break; 3850 case 6: 3851 div_word(emu, destval); 3852 break; 3853 case 7: 3854 idiv_word(emu, destval); 3855 break; 3856 } 3857 } 3858 static void 3859 x86emuOp_opcF7_word_RM(struct X86EMU *emu) 3860 { 3861 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3862 x86emuOp32_opcF7_word_RM(emu); 3863 else 3864 x86emuOp16_opcF7_word_RM(emu); 3865 } 3866 /**************************************************************************** 3867 REMARKS: 3868 Handles opcode 0xfe 3869 ****************************************************************************/ 3870 static void 3871 x86emuOp_opcFE_byte_RM(struct X86EMU *emu) 3872 { 3873 uint8_t destval; 3874 uint32_t destoffset; 3875 uint8_t *destreg; 3876 3877 /* Yet another special case instruction. */ 3878 fetch_decode_modrm(emu); 3879 if (emu->cur_mod != 3) { 3880 destoffset = decode_rl_address(emu); 3881 switch (emu->cur_rh) { 3882 case 0: /* inc word ptr ... */ 3883 destval = fetch_data_byte(emu, destoffset); 3884 destval = inc_byte(emu, destval); 3885 store_data_byte(emu, destoffset, destval); 3886 break; 3887 case 1: /* dec word ptr ... */ 3888 destval = fetch_data_byte(emu, destoffset); 3889 destval = dec_byte(emu, destval); 3890 store_data_byte(emu, destoffset, destval); 3891 break; 3892 } 3893 } else { 3894 destreg = decode_rl_byte_register(emu); 3895 switch (emu->cur_rh) { 3896 case 0: 3897 *destreg = inc_byte(emu, *destreg); 3898 break; 3899 case 1: 3900 *destreg = dec_byte(emu, *destreg); 3901 break; 3902 } 3903 } 3904 } 3905 /**************************************************************************** 3906 REMARKS: 3907 Handles opcode 0xff 3908 ****************************************************************************/ 3909 static void 3910 x86emuOp32_opcFF_word_RM(struct X86EMU *emu) 3911 { 3912 uint32_t destoffset = 0; 3913 uint32_t destval, *destreg; 3914 3915 if (emu->cur_mod != 3) { 3916 destoffset = decode_rl_address(emu); 3917 destval = fetch_data_long(emu, destoffset); 3918 switch (emu->cur_rh) { 3919 case 0: /* inc word ptr ... */ 3920 destval = inc_long(emu, destval); 3921 store_data_long(emu, destoffset, destval); 3922 break; 3923 case 1: /* dec word ptr ... */ 3924 destval = dec_long(emu, destval); 3925 store_data_long(emu, destoffset, destval); 3926 break; 3927 case 6: /* push word ptr ... */ 3928 push_long(emu, destval); 3929 break; 3930 } 3931 } else { 3932 destreg = decode_rl_long_register(emu); 3933 switch (emu->cur_rh) { 3934 case 0: 3935 *destreg = inc_long(emu, *destreg); 3936 break; 3937 case 1: 3938 *destreg = dec_long(emu, *destreg); 3939 break; 3940 case 6: 3941 push_long(emu, *destreg); 3942 break; 3943 } 3944 } 3945 } 3946 3947 static void 3948 x86emuOp16_opcFF_word_RM(struct X86EMU *emu) 3949 { 3950 uint32_t destoffset = 0; 3951 uint16_t *destreg; 3952 uint16_t destval; 3953 3954 if (emu->cur_mod != 3) { 3955 destoffset = decode_rl_address(emu); 3956 destval = fetch_data_word(emu, destoffset); 3957 switch (emu->cur_rh) { 3958 case 0: 3959 destval = inc_word(emu, destval); 3960 store_data_word(emu, destoffset, destval); 3961 break; 3962 case 1: /* dec word ptr ... */ 3963 destval = dec_word(emu, destval); 3964 store_data_word(emu, destoffset, destval); 3965 break; 3966 case 6: /* push word ptr ... */ 3967 push_word(emu, destval); 3968 break; 3969 } 3970 } else { 3971 destreg = decode_rl_word_register(emu); 3972 switch (emu->cur_rh) { 3973 case 0: 3974 *destreg = inc_word(emu, *destreg); 3975 break; 3976 case 1: 3977 *destreg = dec_word(emu, *destreg); 3978 break; 3979 case 6: 3980 push_word(emu, *destreg); 3981 break; 3982 } 3983 } 3984 } 3985 3986 static void 3987 x86emuOp_opcFF_word_RM(struct X86EMU *emu) 3988 { 3989 uint32_t destoffset = 0; 3990 uint16_t destval, destval2; 3991 3992 /* Yet another special case instruction. */ 3993 fetch_decode_modrm(emu); 3994 if ((emu->cur_mod == 3 && (emu->cur_rh == 3 || emu->cur_rh == 5)) || emu->cur_rh == 7) 3995 X86EMU_halt_sys(emu); 3996 if (emu->cur_rh == 0 || emu->cur_rh == 1 || emu->cur_rh == 6) { 3997 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3998 x86emuOp32_opcFF_word_RM(emu); 3999 else 4000 x86emuOp16_opcFF_word_RM(emu); 4001 return; 4002 } 4003 4004 if (emu->cur_mod != 3) { 4005 destoffset = decode_rl_address(emu); 4006 destval = fetch_data_word(emu, destoffset); 4007 switch (emu->cur_rh) { 4008 case 3: /* call far ptr ... */ 4009 destval2 = fetch_data_word(emu, destoffset + 2); 4010 push_word(emu, emu->x86.R_CS); 4011 emu->x86.R_CS = destval2; 4012 push_word(emu, emu->x86.R_IP); 4013 emu->x86.R_IP = destval; 4014 break; 4015 case 5: /* jmp far ptr ... */ 4016 destval2 = fetch_data_word(emu, destoffset + 2); 4017 emu->x86.R_IP = destval; 4018 emu->x86.R_CS = destval2; 4019 break; 4020 } 4021 } else { 4022 destval = *decode_rl_word_register(emu); 4023 } 4024 4025 switch (emu->cur_rh) { 4026 case 2: /* call word ptr */ 4027 push_word(emu, emu->x86.R_IP); 4028 emu->x86.R_IP = destval; 4029 break; 4030 case 4: /* jmp */ 4031 emu->x86.R_IP = destval; 4032 break; 4033 } 4034 } 4035 /*************************************************************************** 4036 * Single byte operation code table: 4037 **************************************************************************/ 4038 static void 4039 X86EMU_exec_one_byte(struct X86EMU * emu) 4040 { 4041 uint8_t op1; 4042 4043 op1 = fetch_byte_imm(emu); 4044 4045 switch (op1) { 4046 case 0x00: 4047 common_binop_byte_rm_r(emu, add_byte); 4048 break; 4049 case 0x01: 4050 common_binop_word_long_rm_r(emu, add_word, add_long); 4051 break; 4052 case 0x02: 4053 common_binop_byte_r_rm(emu, add_byte); 4054 break; 4055 case 0x03: 4056 common_binop_word_long_r_rm(emu, add_word, add_long); 4057 break; 4058 case 0x04: 4059 common_binop_byte_imm(emu, add_byte); 4060 break; 4061 case 0x05: 4062 common_binop_word_long_imm(emu, add_word, add_long); 4063 break; 4064 case 0x06: 4065 push_word(emu, emu->x86.R_ES); 4066 break; 4067 case 0x07: 4068 emu->x86.R_ES = pop_word(emu); 4069 break; 4070 4071 case 0x08: 4072 common_binop_byte_rm_r(emu, or_byte); 4073 break; 4074 case 0x09: 4075 common_binop_word_long_rm_r(emu, or_word, or_long); 4076 break; 4077 case 0x0a: 4078 common_binop_byte_r_rm(emu, or_byte); 4079 break; 4080 case 0x0b: 4081 common_binop_word_long_r_rm(emu, or_word, or_long); 4082 break; 4083 case 0x0c: 4084 common_binop_byte_imm(emu, or_byte); 4085 break; 4086 case 0x0d: 4087 common_binop_word_long_imm(emu, or_word, or_long); 4088 break; 4089 case 0x0e: 4090 push_word(emu, emu->x86.R_CS); 4091 break; 4092 case 0x0f: 4093 X86EMU_exec_two_byte(emu); 4094 break; 4095 4096 case 0x10: 4097 common_binop_byte_rm_r(emu, adc_byte); 4098 break; 4099 case 0x11: 4100 common_binop_word_long_rm_r(emu, adc_word, adc_long); 4101 break; 4102 case 0x12: 4103 common_binop_byte_r_rm(emu, adc_byte); 4104 break; 4105 case 0x13: 4106 common_binop_word_long_r_rm(emu, adc_word, adc_long); 4107 break; 4108 case 0x14: 4109 common_binop_byte_imm(emu, adc_byte); 4110 break; 4111 case 0x15: 4112 common_binop_word_long_imm(emu, adc_word, adc_long); 4113 break; 4114 case 0x16: 4115 push_word(emu, emu->x86.R_SS); 4116 break; 4117 case 0x17: 4118 emu->x86.R_SS = pop_word(emu); 4119 break; 4120 4121 case 0x18: 4122 common_binop_byte_rm_r(emu, sbb_byte); 4123 break; 4124 case 0x19: 4125 common_binop_word_long_rm_r(emu, sbb_word, sbb_long); 4126 break; 4127 case 0x1a: 4128 common_binop_byte_r_rm(emu, sbb_byte); 4129 break; 4130 case 0x1b: 4131 common_binop_word_long_r_rm(emu, sbb_word, sbb_long); 4132 break; 4133 case 0x1c: 4134 common_binop_byte_imm(emu, sbb_byte); 4135 break; 4136 case 0x1d: 4137 common_binop_word_long_imm(emu, sbb_word, sbb_long); 4138 break; 4139 case 0x1e: 4140 push_word(emu, emu->x86.R_DS); 4141 break; 4142 case 0x1f: 4143 emu->x86.R_DS = pop_word(emu); 4144 break; 4145 4146 case 0x20: 4147 common_binop_byte_rm_r(emu, and_byte); 4148 break; 4149 case 0x21: 4150 common_binop_word_long_rm_r(emu, and_word, and_long); 4151 break; 4152 case 0x22: 4153 common_binop_byte_r_rm(emu, and_byte); 4154 break; 4155 case 0x23: 4156 common_binop_word_long_r_rm(emu, and_word, and_long); 4157 break; 4158 case 0x24: 4159 common_binop_byte_imm(emu, and_byte); 4160 break; 4161 case 0x25: 4162 common_binop_word_long_imm(emu, and_word, and_long); 4163 break; 4164 case 0x26: 4165 emu->x86.mode |= SYSMODE_SEGOVR_ES; 4166 break; 4167 case 0x27: 4168 emu->x86.R_AL = daa_byte(emu, emu->x86.R_AL); 4169 break; 4170 4171 case 0x28: 4172 common_binop_byte_rm_r(emu, sub_byte); 4173 break; 4174 case 0x29: 4175 common_binop_word_long_rm_r(emu, sub_word, sub_long); 4176 break; 4177 case 0x2a: 4178 common_binop_byte_r_rm(emu, sub_byte); 4179 break; 4180 case 0x2b: 4181 common_binop_word_long_r_rm(emu, sub_word, sub_long); 4182 break; 4183 case 0x2c: 4184 common_binop_byte_imm(emu, sub_byte); 4185 break; 4186 case 0x2d: 4187 common_binop_word_long_imm(emu, sub_word, sub_long); 4188 break; 4189 case 0x2e: 4190 emu->x86.mode |= SYSMODE_SEGOVR_CS; 4191 break; 4192 case 0x2f: 4193 emu->x86.R_AL = das_byte(emu, emu->x86.R_AL); 4194 break; 4195 4196 case 0x30: 4197 common_binop_byte_rm_r(emu, xor_byte); 4198 break; 4199 case 0x31: 4200 common_binop_word_long_rm_r(emu, xor_word, xor_long); 4201 break; 4202 case 0x32: 4203 common_binop_byte_r_rm(emu, xor_byte); 4204 break; 4205 case 0x33: 4206 common_binop_word_long_r_rm(emu, xor_word, xor_long); 4207 break; 4208 case 0x34: 4209 common_binop_byte_imm(emu, xor_byte); 4210 break; 4211 case 0x35: 4212 common_binop_word_long_imm(emu, xor_word, xor_long); 4213 break; 4214 case 0x36: 4215 emu->x86.mode |= SYSMODE_SEGOVR_SS; 4216 break; 4217 case 0x37: 4218 emu->x86.R_AX = aaa_word(emu, emu->x86.R_AX); 4219 break; 4220 4221 case 0x38: 4222 common_binop_ns_byte_rm_r(emu, cmp_byte_no_return); 4223 break; 4224 case 0x39: 4225 common_binop_ns_word_long_rm_r(emu, cmp_word_no_return, 4226 cmp_long_no_return); 4227 break; 4228 case 0x3a: 4229 x86emuOp_cmp_byte_R_RM(emu); 4230 break; 4231 case 0x3b: 4232 x86emuOp_cmp_word_R_RM(emu); 4233 break; 4234 case 0x3c: 4235 x86emuOp_cmp_byte_AL_IMM(emu); 4236 break; 4237 case 0x3d: 4238 x86emuOp_cmp_word_AX_IMM(emu); 4239 break; 4240 case 0x3e: 4241 emu->x86.mode |= SYSMODE_SEGOVR_DS; 4242 break; 4243 case 0x3f: 4244 emu->x86.R_AX = aas_word(emu, emu->x86.R_AX); 4245 break; 4246 4247 case 0x40: 4248 common_inc_word_long(emu, &emu->x86.register_a); 4249 break; 4250 case 0x41: 4251 common_inc_word_long(emu, &emu->x86.register_c); 4252 break; 4253 case 0x42: 4254 common_inc_word_long(emu, &emu->x86.register_d); 4255 break; 4256 case 0x43: 4257 common_inc_word_long(emu, &emu->x86.register_b); 4258 break; 4259 case 0x44: 4260 common_inc_word_long(emu, &emu->x86.register_sp); 4261 break; 4262 case 0x45: 4263 common_inc_word_long(emu, &emu->x86.register_bp); 4264 break; 4265 case 0x46: 4266 common_inc_word_long(emu, &emu->x86.register_si); 4267 break; 4268 case 0x47: 4269 common_inc_word_long(emu, &emu->x86.register_di); 4270 break; 4271 4272 case 0x48: 4273 common_dec_word_long(emu, &emu->x86.register_a); 4274 break; 4275 case 0x49: 4276 common_dec_word_long(emu, &emu->x86.register_c); 4277 break; 4278 case 0x4a: 4279 common_dec_word_long(emu, &emu->x86.register_d); 4280 break; 4281 case 0x4b: 4282 common_dec_word_long(emu, &emu->x86.register_b); 4283 break; 4284 case 0x4c: 4285 common_dec_word_long(emu, &emu->x86.register_sp); 4286 break; 4287 case 0x4d: 4288 common_dec_word_long(emu, &emu->x86.register_bp); 4289 break; 4290 case 0x4e: 4291 common_dec_word_long(emu, &emu->x86.register_si); 4292 break; 4293 case 0x4f: 4294 common_dec_word_long(emu, &emu->x86.register_di); 4295 break; 4296 4297 case 0x50: 4298 common_push_word_long(emu, &emu->x86.register_a); 4299 break; 4300 case 0x51: 4301 common_push_word_long(emu, &emu->x86.register_c); 4302 break; 4303 case 0x52: 4304 common_push_word_long(emu, &emu->x86.register_d); 4305 break; 4306 case 0x53: 4307 common_push_word_long(emu, &emu->x86.register_b); 4308 break; 4309 case 0x54: 4310 common_push_word_long(emu, &emu->x86.register_sp); 4311 break; 4312 case 0x55: 4313 common_push_word_long(emu, &emu->x86.register_bp); 4314 break; 4315 case 0x56: 4316 common_push_word_long(emu, &emu->x86.register_si); 4317 break; 4318 case 0x57: 4319 common_push_word_long(emu, &emu->x86.register_di); 4320 break; 4321 4322 case 0x58: 4323 common_pop_word_long(emu, &emu->x86.register_a); 4324 break; 4325 case 0x59: 4326 common_pop_word_long(emu, &emu->x86.register_c); 4327 break; 4328 case 0x5a: 4329 common_pop_word_long(emu, &emu->x86.register_d); 4330 break; 4331 case 0x5b: 4332 common_pop_word_long(emu, &emu->x86.register_b); 4333 break; 4334 case 0x5c: 4335 common_pop_word_long(emu, &emu->x86.register_sp); 4336 break; 4337 case 0x5d: 4338 common_pop_word_long(emu, &emu->x86.register_bp); 4339 break; 4340 case 0x5e: 4341 common_pop_word_long(emu, &emu->x86.register_si); 4342 break; 4343 case 0x5f: 4344 common_pop_word_long(emu, &emu->x86.register_di); 4345 break; 4346 4347 case 0x60: 4348 x86emuOp_push_all(emu); 4349 break; 4350 case 0x61: 4351 x86emuOp_pop_all(emu); 4352 break; 4353 /* 0x62 bound */ 4354 /* 0x63 arpl */ 4355 case 0x64: 4356 emu->x86.mode |= SYSMODE_SEGOVR_FS; 4357 break; 4358 case 0x65: 4359 emu->x86.mode |= SYSMODE_SEGOVR_GS; 4360 break; 4361 case 0x66: 4362 emu->x86.mode |= SYSMODE_PREFIX_DATA; 4363 break; 4364 case 0x67: 4365 emu->x86.mode |= SYSMODE_PREFIX_ADDR; 4366 break; 4367 4368 case 0x68: 4369 x86emuOp_push_word_IMM(emu); 4370 break; 4371 case 0x69: 4372 common_imul_imm(emu, false); 4373 break; 4374 case 0x6a: 4375 x86emuOp_push_byte_IMM(emu); 4376 break; 4377 case 0x6b: 4378 common_imul_imm(emu, true); 4379 break; 4380 case 0x6c: 4381 ins(emu, 1); 4382 break; 4383 case 0x6d: 4384 x86emuOp_ins_word(emu); 4385 break; 4386 case 0x6e: 4387 outs(emu, 1); 4388 break; 4389 case 0x6f: 4390 x86emuOp_outs_word(emu); 4391 break; 4392 4393 case 0x70: 4394 common_jmp_near(emu, ACCESS_FLAG(F_OF)); 4395 break; 4396 case 0x71: 4397 common_jmp_near(emu, !ACCESS_FLAG(F_OF)); 4398 break; 4399 case 0x72: 4400 common_jmp_near(emu, ACCESS_FLAG(F_CF)); 4401 break; 4402 case 0x73: 4403 common_jmp_near(emu, !ACCESS_FLAG(F_CF)); 4404 break; 4405 case 0x74: 4406 common_jmp_near(emu, ACCESS_FLAG(F_ZF)); 4407 break; 4408 case 0x75: 4409 common_jmp_near(emu, !ACCESS_FLAG(F_ZF)); 4410 break; 4411 case 0x76: 4412 common_jmp_near(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); 4413 break; 4414 case 0x77: 4415 common_jmp_near(emu, !ACCESS_FLAG(F_CF) && !ACCESS_FLAG(F_ZF)); 4416 break; 4417 4418 case 0x78: 4419 common_jmp_near(emu, ACCESS_FLAG(F_SF)); 4420 break; 4421 case 0x79: 4422 common_jmp_near(emu, !ACCESS_FLAG(F_SF)); 4423 break; 4424 case 0x7a: 4425 common_jmp_near(emu, ACCESS_FLAG(F_PF)); 4426 break; 4427 case 0x7b: 4428 common_jmp_near(emu, !ACCESS_FLAG(F_PF)); 4429 break; 4430 case 0x7c: 4431 x86emuOp_jump_near_L(emu); 4432 break; 4433 case 0x7d: 4434 x86emuOp_jump_near_NL(emu); 4435 break; 4436 case 0x7e: 4437 x86emuOp_jump_near_LE(emu); 4438 break; 4439 case 0x7f: 4440 x86emuOp_jump_near_NLE(emu); 4441 break; 4442 4443 case 0x80: 4444 x86emuOp_opc80_byte_RM_IMM(emu); 4445 break; 4446 case 0x81: 4447 x86emuOp_opc81_word_RM_IMM(emu); 4448 break; 4449 case 0x82: 4450 x86emuOp_opc82_byte_RM_IMM(emu); 4451 break; 4452 case 0x83: 4453 x86emuOp_opc83_word_RM_IMM(emu); 4454 break; 4455 case 0x84: 4456 common_binop_ns_byte_rm_r(emu, test_byte); 4457 break; 4458 case 0x85: 4459 common_binop_ns_word_long_rm_r(emu, test_word, test_long); 4460 break; 4461 case 0x86: 4462 x86emuOp_xchg_byte_RM_R(emu); 4463 break; 4464 case 0x87: 4465 x86emuOp_xchg_word_RM_R(emu); 4466 break; 4467 4468 case 0x88: 4469 x86emuOp_mov_byte_RM_R(emu); 4470 break; 4471 case 0x89: 4472 x86emuOp_mov_word_RM_R(emu); 4473 break; 4474 case 0x8a: 4475 x86emuOp_mov_byte_R_RM(emu); 4476 break; 4477 case 0x8b: 4478 x86emuOp_mov_word_R_RM(emu); 4479 break; 4480 case 0x8c: 4481 x86emuOp_mov_word_RM_SR(emu); 4482 break; 4483 case 0x8d: 4484 x86emuOp_lea_word_R_M(emu); 4485 break; 4486 case 0x8e: 4487 x86emuOp_mov_word_SR_RM(emu); 4488 break; 4489 case 0x8f: 4490 x86emuOp_pop_RM(emu); 4491 break; 4492 4493 case 0x90: 4494 /* nop */ 4495 break; 4496 case 0x91: 4497 x86emuOp_xchg_word_AX_CX(emu); 4498 break; 4499 case 0x92: 4500 x86emuOp_xchg_word_AX_DX(emu); 4501 break; 4502 case 0x93: 4503 x86emuOp_xchg_word_AX_BX(emu); 4504 break; 4505 case 0x94: 4506 x86emuOp_xchg_word_AX_SP(emu); 4507 break; 4508 case 0x95: 4509 x86emuOp_xchg_word_AX_BP(emu); 4510 break; 4511 case 0x96: 4512 x86emuOp_xchg_word_AX_SI(emu); 4513 break; 4514 case 0x97: 4515 x86emuOp_xchg_word_AX_DI(emu); 4516 break; 4517 4518 case 0x98: 4519 x86emuOp_cbw(emu); 4520 break; 4521 case 0x99: 4522 x86emuOp_cwd(emu); 4523 break; 4524 case 0x9a: 4525 x86emuOp_call_far_IMM(emu); 4526 break; 4527 case 0x9b: 4528 /* wait */ 4529 break; 4530 case 0x9c: 4531 x86emuOp_pushf_word(emu); 4532 break; 4533 case 0x9d: 4534 x86emuOp_popf_word(emu); 4535 break; 4536 case 0x9e: 4537 x86emuOp_sahf(emu); 4538 break; 4539 case 0x9f: 4540 x86emuOp_lahf(emu); 4541 break; 4542 4543 case 0xa0: 4544 x86emuOp_mov_AL_M_IMM(emu); 4545 break; 4546 case 0xa1: 4547 x86emuOp_mov_AX_M_IMM(emu); 4548 break; 4549 case 0xa2: 4550 x86emuOp_mov_M_AL_IMM(emu); 4551 break; 4552 case 0xa3: 4553 x86emuOp_mov_M_AX_IMM(emu); 4554 break; 4555 case 0xa4: 4556 x86emuOp_movs_byte(emu); 4557 break; 4558 case 0xa5: 4559 x86emuOp_movs_word(emu); 4560 break; 4561 case 0xa6: 4562 x86emuOp_cmps_byte(emu); 4563 break; 4564 case 0xa7: 4565 x86emuOp_cmps_word(emu); 4566 break; 4567 4568 case 0xa8: 4569 test_byte(emu, emu->x86.R_AL, fetch_byte_imm(emu)); 4570 break; 4571 case 0xa9: 4572 x86emuOp_test_AX_IMM(emu); 4573 break; 4574 case 0xaa: 4575 x86emuOp_stos_byte(emu); 4576 break; 4577 case 0xab: 4578 x86emuOp_stos_word(emu); 4579 break; 4580 case 0xac: 4581 x86emuOp_lods_byte(emu); 4582 break; 4583 case 0xad: 4584 x86emuOp_lods_word(emu); 4585 break; 4586 case 0xae: 4587 x86emuOp_scas_byte(emu); 4588 break; 4589 case 0xaf: 4590 x86emuOp_scas_word(emu); 4591 break; 4592 4593 case 0xb0: 4594 emu->x86.R_AL = fetch_byte_imm(emu); 4595 break; 4596 case 0xb1: 4597 emu->x86.R_CL = fetch_byte_imm(emu); 4598 break; 4599 case 0xb2: 4600 emu->x86.R_DL = fetch_byte_imm(emu); 4601 break; 4602 case 0xb3: 4603 emu->x86.R_BL = fetch_byte_imm(emu); 4604 break; 4605 case 0xb4: 4606 emu->x86.R_AH = fetch_byte_imm(emu); 4607 break; 4608 case 0xb5: 4609 emu->x86.R_CH = fetch_byte_imm(emu); 4610 break; 4611 case 0xb6: 4612 emu->x86.R_DH = fetch_byte_imm(emu); 4613 break; 4614 case 0xb7: 4615 emu->x86.R_BH = fetch_byte_imm(emu); 4616 break; 4617 4618 case 0xb8: 4619 x86emuOp_mov_word_AX_IMM(emu); 4620 break; 4621 case 0xb9: 4622 x86emuOp_mov_word_CX_IMM(emu); 4623 break; 4624 case 0xba: 4625 x86emuOp_mov_word_DX_IMM(emu); 4626 break; 4627 case 0xbb: 4628 x86emuOp_mov_word_BX_IMM(emu); 4629 break; 4630 case 0xbc: 4631 x86emuOp_mov_word_SP_IMM(emu); 4632 break; 4633 case 0xbd: 4634 x86emuOp_mov_word_BP_IMM(emu); 4635 break; 4636 case 0xbe: 4637 x86emuOp_mov_word_SI_IMM(emu); 4638 break; 4639 case 0xbf: 4640 x86emuOp_mov_word_DI_IMM(emu); 4641 break; 4642 4643 case 0xc0: 4644 x86emuOp_opcC0_byte_RM_MEM(emu); 4645 break; 4646 case 0xc1: 4647 x86emuOp_opcC1_word_RM_MEM(emu); 4648 break; 4649 case 0xc2: 4650 x86emuOp_ret_near_IMM(emu); 4651 break; 4652 case 0xc3: 4653 emu->x86.R_IP = pop_word(emu); 4654 break; 4655 case 0xc4: 4656 common_load_far_pointer(emu, &emu->x86.R_ES); 4657 break; 4658 case 0xc5: 4659 common_load_far_pointer(emu, &emu->x86.R_DS); 4660 break; 4661 case 0xc6: 4662 x86emuOp_mov_byte_RM_IMM(emu); 4663 break; 4664 case 0xc7: 4665 x86emuOp_mov_word_RM_IMM(emu); 4666 break; 4667 case 0xc8: 4668 x86emuOp_enter(emu); 4669 break; 4670 case 0xc9: 4671 x86emuOp_leave(emu); 4672 break; 4673 case 0xca: 4674 x86emuOp_ret_far_IMM(emu); 4675 break; 4676 case 0xcb: 4677 x86emuOp_ret_far(emu); 4678 break; 4679 case 0xcc: 4680 x86emuOp_int3(emu); 4681 break; 4682 case 0xcd: 4683 x86emuOp_int_IMM(emu); 4684 break; 4685 case 0xce: 4686 x86emuOp_into(emu); 4687 break; 4688 case 0xcf: 4689 x86emuOp_iret(emu); 4690 break; 4691 4692 case 0xd0: 4693 x86emuOp_opcD0_byte_RM_1(emu); 4694 break; 4695 case 0xd1: 4696 x86emuOp_opcD1_word_RM_1(emu); 4697 break; 4698 case 0xd2: 4699 x86emuOp_opcD2_byte_RM_CL(emu); 4700 break; 4701 case 0xd3: 4702 x86emuOp_opcD3_word_RM_CL(emu); 4703 break; 4704 case 0xd4: 4705 x86emuOp_aam(emu); 4706 break; 4707 case 0xd5: 4708 x86emuOp_aad(emu); 4709 break; 4710 /* 0xd6 Undocumented SETALC instruction */ 4711 case 0xd7: 4712 x86emuOp_xlat(emu); 4713 break; 4714 case 0xd8: 4715 x86emuOp_esc_coprocess_d8(emu); 4716 break; 4717 case 0xd9: 4718 x86emuOp_esc_coprocess_d9(emu); 4719 break; 4720 case 0xda: 4721 x86emuOp_esc_coprocess_da(emu); 4722 break; 4723 case 0xdb: 4724 x86emuOp_esc_coprocess_db(emu); 4725 break; 4726 case 0xdc: 4727 x86emuOp_esc_coprocess_dc(emu); 4728 break; 4729 case 0xdd: 4730 x86emuOp_esc_coprocess_dd(emu); 4731 break; 4732 case 0xde: 4733 x86emuOp_esc_coprocess_de(emu); 4734 break; 4735 case 0xdf: 4736 x86emuOp_esc_coprocess_df(emu); 4737 break; 4738 4739 case 0xe0: 4740 x86emuOp_loopne(emu); 4741 break; 4742 case 0xe1: 4743 x86emuOp_loope(emu); 4744 break; 4745 case 0xe2: 4746 x86emuOp_loop(emu); 4747 break; 4748 case 0xe3: 4749 x86emuOp_jcxz(emu); 4750 break; 4751 case 0xe4: 4752 x86emuOp_in_byte_AL_IMM(emu); 4753 break; 4754 case 0xe5: 4755 x86emuOp_in_word_AX_IMM(emu); 4756 break; 4757 case 0xe6: 4758 x86emuOp_out_byte_IMM_AL(emu); 4759 break; 4760 case 0xe7: 4761 x86emuOp_out_word_IMM_AX(emu); 4762 break; 4763 4764 case 0xe8: 4765 x86emuOp_call_near_IMM(emu); 4766 break; 4767 case 0xe9: 4768 x86emuOp_jump_near_IMM(emu); 4769 break; 4770 case 0xea: 4771 x86emuOp_jump_far_IMM(emu); 4772 break; 4773 case 0xeb: 4774 x86emuOp_jump_byte_IMM(emu); 4775 break; 4776 case 0xec: 4777 x86emuOp_in_byte_AL_DX(emu); 4778 break; 4779 case 0xed: 4780 x86emuOp_in_word_AX_DX(emu); 4781 break; 4782 case 0xee: 4783 x86emuOp_out_byte_DX_AL(emu); 4784 break; 4785 case 0xef: 4786 x86emuOp_out_word_DX_AX(emu); 4787 break; 4788 4789 case 0xf0: 4790 x86emuOp_lock(emu); 4791 break; 4792 case 0xf2: 4793 emu->x86.mode |= SYSMODE_PREFIX_REPNE; 4794 break; 4795 case 0xf3: 4796 emu->x86.mode |= SYSMODE_PREFIX_REPE; 4797 break; 4798 case 0xf4: 4799 X86EMU_halt_sys(emu); 4800 break; 4801 case 0xf5: 4802 x86emuOp_cmc(emu); 4803 break; 4804 case 0xf6: 4805 x86emuOp_opcF6_byte_RM(emu); 4806 break; 4807 case 0xf7: 4808 x86emuOp_opcF7_word_RM(emu); 4809 break; 4810 4811 case 0xf8: 4812 CLEAR_FLAG(F_CF); 4813 break; 4814 case 0xf9: 4815 SET_FLAG(F_CF); 4816 break; 4817 case 0xfa: 4818 CLEAR_FLAG(F_IF); 4819 break; 4820 case 0xfb: 4821 SET_FLAG(F_IF); 4822 break; 4823 case 0xfc: 4824 CLEAR_FLAG(F_DF); 4825 break; 4826 case 0xfd: 4827 SET_FLAG(F_DF); 4828 break; 4829 case 0xfe: 4830 x86emuOp_opcFE_byte_RM(emu); 4831 break; 4832 case 0xff: 4833 x86emuOp_opcFF_word_RM(emu); 4834 break; 4835 default: 4836 X86EMU_halt_sys(emu); 4837 break; 4838 } 4839 if (op1 != 0x26 && op1 != 0x2e && op1 != 0x36 && op1 != 0x3e && 4840 (op1 | 3) != 0x67) 4841 emu->x86.mode &= ~SYSMODE_CLRMASK; 4842 } 4843 4844 static void 4845 common_jmp_long(struct X86EMU *emu, bool cond) 4846 { 4847 int16_t target; 4848 4849 target = (int16_t) fetch_word_imm(emu); 4850 target += (int16_t) emu->x86.R_IP; 4851 if (cond) 4852 emu->x86.R_IP = (uint16_t) target; 4853 } 4854 4855 static void 4856 common_set_byte(struct X86EMU *emu, bool cond) 4857 { 4858 uint32_t destoffset; 4859 uint8_t *destreg, destval; 4860 4861 fetch_decode_modrm(emu); 4862 destval = cond ? 0x01 : 0x00; 4863 if (emu->cur_mod != 3) { 4864 destoffset = decode_rl_address(emu); 4865 store_data_byte(emu, destoffset, destval); 4866 } else { 4867 destreg = decode_rl_byte_register(emu); 4868 *destreg = destval; 4869 } 4870 } 4871 4872 static void 4873 common_bitstring32(struct X86EMU *emu, int op) 4874 { 4875 int bit; 4876 uint32_t srcval, *shiftreg, mask; 4877 4878 fetch_decode_modrm(emu); 4879 shiftreg = decode_rh_long_register(emu); 4880 srcval = decode_and_fetch_long_disp(emu, (int16_t) *shiftreg >> 5); 4881 bit = *shiftreg & 0x1F; 4882 mask = 0x1 << bit; 4883 CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 4884 4885 switch (op) { 4886 case 0: 4887 break; 4888 case 1: 4889 write_back_long(emu, srcval | mask); 4890 break; 4891 case 2: 4892 write_back_long(emu, srcval & ~mask); 4893 break; 4894 case 3: 4895 write_back_long(emu, srcval ^ mask); 4896 break; 4897 } 4898 } 4899 4900 static void 4901 common_bitstring16(struct X86EMU *emu, int op) 4902 { 4903 int bit; 4904 uint16_t srcval, *shiftreg, mask; 4905 4906 fetch_decode_modrm(emu); 4907 shiftreg = decode_rh_word_register(emu); 4908 srcval = decode_and_fetch_word_disp(emu, (int16_t) *shiftreg >> 4); 4909 bit = *shiftreg & 0xF; 4910 mask = 0x1 << bit; 4911 CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 4912 4913 switch (op) { 4914 case 0: 4915 break; 4916 case 1: 4917 write_back_word(emu, srcval | mask); 4918 break; 4919 case 2: 4920 write_back_word(emu, srcval & ~mask); 4921 break; 4922 case 3: 4923 write_back_word(emu, srcval ^ mask); 4924 break; 4925 } 4926 } 4927 4928 static void 4929 common_bitstring(struct X86EMU *emu, int op) 4930 { 4931 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 4932 common_bitstring32(emu, op); 4933 else 4934 common_bitstring16(emu, op); 4935 } 4936 4937 static void 4938 common_bitsearch32(struct X86EMU *emu, int diff) 4939 { 4940 uint32_t srcval, *dstreg; 4941 4942 fetch_decode_modrm(emu); 4943 dstreg = decode_rh_long_register(emu); 4944 srcval = decode_and_fetch_long(emu); 4945 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 4946 for (*dstreg = 0; *dstreg < 32; *dstreg += diff) { 4947 if ((srcval >> *dstreg) & 1) 4948 break; 4949 } 4950 } 4951 4952 static void 4953 common_bitsearch16(struct X86EMU *emu, int diff) 4954 { 4955 uint16_t srcval, *dstreg; 4956 4957 fetch_decode_modrm(emu); 4958 dstreg = decode_rh_word_register(emu); 4959 srcval = decode_and_fetch_word(emu); 4960 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 4961 for (*dstreg = 0; *dstreg < 16; *dstreg += diff) { 4962 if ((srcval >> *dstreg) & 1) 4963 break; 4964 } 4965 } 4966 4967 static void 4968 common_bitsearch(struct X86EMU *emu, int diff) 4969 { 4970 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 4971 common_bitsearch32(emu, diff); 4972 else 4973 common_bitsearch16(emu, diff); 4974 } 4975 4976 static void 4977 common_shift32(struct X86EMU *emu, bool shift_left, bool use_cl) 4978 { 4979 uint8_t shift; 4980 uint32_t destval, *shiftreg; 4981 4982 fetch_decode_modrm(emu); 4983 shiftreg = decode_rh_long_register(emu); 4984 if (use_cl) { 4985 destval = decode_and_fetch_long(emu); 4986 shift = emu->x86.R_CL; 4987 } else { 4988 destval = decode_and_fetch_long_imm8(emu, &shift); 4989 } 4990 if (shift_left) 4991 destval = shld_long(emu, destval, *shiftreg, shift); 4992 else 4993 destval = shrd_long(emu, destval, *shiftreg, shift); 4994 write_back_long(emu, destval); 4995 } 4996 4997 static void 4998 common_shift16(struct X86EMU *emu, bool shift_left, bool use_cl) 4999 { 5000 uint8_t shift; 5001 uint16_t destval, *shiftreg; 5002 5003 fetch_decode_modrm(emu); 5004 shiftreg = decode_rh_word_register(emu); 5005 if (use_cl) { 5006 destval = decode_and_fetch_word(emu); 5007 shift = emu->x86.R_CL; 5008 } else { 5009 destval = decode_and_fetch_word_imm8(emu, &shift); 5010 } 5011 if (shift_left) 5012 destval = shld_word(emu, destval, *shiftreg, shift); 5013 else 5014 destval = shrd_word(emu, destval, *shiftreg, shift); 5015 write_back_word(emu, destval); 5016 } 5017 5018 static void 5019 common_shift(struct X86EMU *emu, bool shift_left, bool use_cl) 5020 { 5021 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5022 common_shift32(emu, shift_left, use_cl); 5023 else 5024 common_shift16(emu, shift_left, use_cl); 5025 } 5026 5027 /*----------------------------- Implementation ----------------------------*/ 5028 #define xorl(a,b) ((a) && !(b)) || (!(a) && (b)) 5029 5030 /**************************************************************************** 5031 REMARKS: 5032 Handles opcode 0x0f,0x31 5033 ****************************************************************************/ 5034 static void 5035 x86emuOp2_rdtsc(struct X86EMU *emu) 5036 { 5037 emu->x86.R_EAX = emu->cur_cycles & 0xffffffff; 5038 emu->x86.R_EDX = emu->cur_cycles >> 32; 5039 } 5040 /**************************************************************************** 5041 REMARKS: 5042 Handles opcode 0x0f,0xa0 5043 ****************************************************************************/ 5044 static void 5045 x86emuOp2_push_FS(struct X86EMU *emu) 5046 { 5047 push_word(emu, emu->x86.R_FS); 5048 } 5049 /**************************************************************************** 5050 REMARKS: 5051 Handles opcode 0x0f,0xa1 5052 ****************************************************************************/ 5053 static void 5054 x86emuOp2_pop_FS(struct X86EMU *emu) 5055 { 5056 emu->x86.R_FS = pop_word(emu); 5057 } 5058 /**************************************************************************** 5059 REMARKS: 5060 Handles opcode 0x0f,0xa3 5061 ****************************************************************************/ 5062 static void 5063 x86emuOp2_bt_R(struct X86EMU *emu) 5064 { 5065 common_bitstring(emu, 0); 5066 } 5067 /**************************************************************************** 5068 REMARKS: 5069 Handles opcode 0x0f,0xa4 5070 ****************************************************************************/ 5071 static void 5072 x86emuOp2_shld_IMM(struct X86EMU *emu) 5073 { 5074 common_shift(emu, true, false); 5075 } 5076 /**************************************************************************** 5077 REMARKS: 5078 Handles opcode 0x0f,0xa5 5079 ****************************************************************************/ 5080 static void 5081 x86emuOp2_shld_CL(struct X86EMU *emu) 5082 { 5083 common_shift(emu, true, true); 5084 } 5085 /**************************************************************************** 5086 REMARKS: 5087 Handles opcode 0x0f,0xa8 5088 ****************************************************************************/ 5089 static void 5090 x86emuOp2_push_GS(struct X86EMU *emu) 5091 { 5092 push_word(emu, emu->x86.R_GS); 5093 } 5094 /**************************************************************************** 5095 REMARKS: 5096 Handles opcode 0x0f,0xa9 5097 ****************************************************************************/ 5098 static void 5099 x86emuOp2_pop_GS(struct X86EMU *emu) 5100 { 5101 emu->x86.R_GS = pop_word(emu); 5102 } 5103 /**************************************************************************** 5104 REMARKS: 5105 Handles opcode 0x0f,0xab 5106 ****************************************************************************/ 5107 static void 5108 x86emuOp2_bts_R(struct X86EMU *emu) 5109 { 5110 common_bitstring(emu, 1); 5111 } 5112 /**************************************************************************** 5113 REMARKS: 5114 Handles opcode 0x0f,0xac 5115 ****************************************************************************/ 5116 static void 5117 x86emuOp2_shrd_IMM(struct X86EMU *emu) 5118 { 5119 common_shift(emu, false, false); 5120 } 5121 /**************************************************************************** 5122 REMARKS: 5123 Handles opcode 0x0f,0xad 5124 ****************************************************************************/ 5125 static void 5126 x86emuOp2_shrd_CL(struct X86EMU *emu) 5127 { 5128 common_shift(emu, false, true); 5129 } 5130 /**************************************************************************** 5131 REMARKS: 5132 Handles opcode 0x0f,0xaf 5133 ****************************************************************************/ 5134 static void 5135 x86emuOp2_32_imul_R_RM(struct X86EMU *emu) 5136 { 5137 uint32_t *destreg, srcval; 5138 uint64_t res; 5139 5140 fetch_decode_modrm(emu); 5141 destreg = decode_rh_long_register(emu); 5142 srcval = decode_and_fetch_long(emu); 5143 res = (int32_t) *destreg * (int32_t)srcval; 5144 if (res > 0xffffffff) { 5145 SET_FLAG(F_CF); 5146 SET_FLAG(F_OF); 5147 } else { 5148 CLEAR_FLAG(F_CF); 5149 CLEAR_FLAG(F_OF); 5150 } 5151 *destreg = (uint32_t) res; 5152 } 5153 5154 static void 5155 x86emuOp2_16_imul_R_RM(struct X86EMU *emu) 5156 { 5157 uint16_t *destreg, srcval; 5158 uint32_t res; 5159 5160 fetch_decode_modrm(emu); 5161 destreg = decode_rh_word_register(emu); 5162 srcval = decode_and_fetch_word(emu); 5163 res = (int16_t) * destreg * (int16_t)srcval; 5164 if (res > 0xFFFF) { 5165 SET_FLAG(F_CF); 5166 SET_FLAG(F_OF); 5167 } else { 5168 CLEAR_FLAG(F_CF); 5169 CLEAR_FLAG(F_OF); 5170 } 5171 *destreg = (uint16_t) res; 5172 } 5173 5174 static void 5175 x86emuOp2_imul_R_RM(struct X86EMU *emu) 5176 { 5177 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5178 x86emuOp2_32_imul_R_RM(emu); 5179 else 5180 x86emuOp2_16_imul_R_RM(emu); 5181 } 5182 /**************************************************************************** 5183 REMARKS: 5184 Handles opcode 0x0f,0xb2 5185 ****************************************************************************/ 5186 static void 5187 x86emuOp2_lss_R_IMM(struct X86EMU *emu) 5188 { 5189 common_load_far_pointer(emu, &emu->x86.R_SS); 5190 } 5191 /**************************************************************************** 5192 REMARKS: 5193 Handles opcode 0x0f,0xb3 5194 ****************************************************************************/ 5195 static void 5196 x86emuOp2_btr_R(struct X86EMU *emu) 5197 { 5198 common_bitstring(emu, 2); 5199 } 5200 /**************************************************************************** 5201 REMARKS: 5202 Handles opcode 0x0f,0xb4 5203 ****************************************************************************/ 5204 static void 5205 x86emuOp2_lfs_R_IMM(struct X86EMU *emu) 5206 { 5207 common_load_far_pointer(emu, &emu->x86.R_FS); 5208 } 5209 /**************************************************************************** 5210 REMARKS: 5211 Handles opcode 0x0f,0xb5 5212 ****************************************************************************/ 5213 static void 5214 x86emuOp2_lgs_R_IMM(struct X86EMU *emu) 5215 { 5216 common_load_far_pointer(emu, &emu->x86.R_GS); 5217 } 5218 /**************************************************************************** 5219 REMARKS: 5220 Handles opcode 0x0f,0xb6 5221 ****************************************************************************/ 5222 static void 5223 x86emuOp2_32_movzx_byte_R_RM(struct X86EMU *emu) 5224 { 5225 uint32_t *destreg; 5226 5227 fetch_decode_modrm(emu); 5228 destreg = decode_rh_long_register(emu); 5229 *destreg = decode_and_fetch_byte(emu); 5230 } 5231 5232 static void 5233 x86emuOp2_16_movzx_byte_R_RM(struct X86EMU *emu) 5234 { 5235 uint16_t *destreg; 5236 5237 fetch_decode_modrm(emu); 5238 destreg = decode_rh_word_register(emu); 5239 *destreg = decode_and_fetch_byte(emu); 5240 } 5241 5242 static void 5243 x86emuOp2_movzx_byte_R_RM(struct X86EMU *emu) 5244 { 5245 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5246 x86emuOp2_32_movzx_byte_R_RM(emu); 5247 else 5248 x86emuOp2_16_movzx_byte_R_RM(emu); 5249 } 5250 /**************************************************************************** 5251 REMARKS: 5252 Handles opcode 0x0f,0xb7 5253 ****************************************************************************/ 5254 static void 5255 x86emuOp2_movzx_word_R_RM(struct X86EMU *emu) 5256 { 5257 uint32_t *destreg; 5258 5259 fetch_decode_modrm(emu); 5260 destreg = decode_rh_long_register(emu); 5261 *destreg = decode_and_fetch_word(emu); 5262 } 5263 /**************************************************************************** 5264 REMARKS: 5265 Handles opcode 0x0f,0xba 5266 ****************************************************************************/ 5267 static void 5268 x86emuOp2_32_btX_I(struct X86EMU *emu) 5269 { 5270 int bit; 5271 uint32_t srcval, mask; 5272 uint8_t shift; 5273 5274 fetch_decode_modrm(emu); 5275 if (emu->cur_rh < 4) 5276 X86EMU_halt_sys(emu); 5277 5278 srcval = decode_and_fetch_long_imm8(emu, &shift); 5279 bit = shift & 0x1F; 5280 mask = (0x1 << bit); 5281 5282 switch (emu->cur_rh) { 5283 case 5: 5284 write_back_long(emu, srcval | mask); 5285 break; 5286 case 6: 5287 write_back_long(emu, srcval & ~mask); 5288 break; 5289 case 7: 5290 write_back_long(emu, srcval ^ mask); 5291 break; 5292 } 5293 CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 5294 } 5295 5296 static void 5297 x86emuOp2_16_btX_I(struct X86EMU *emu) 5298 { 5299 int bit; 5300 5301 uint16_t srcval, mask; 5302 uint8_t shift; 5303 5304 fetch_decode_modrm(emu); 5305 if (emu->cur_rh < 4) 5306 X86EMU_halt_sys(emu); 5307 5308 srcval = decode_and_fetch_word_imm8(emu, &shift); 5309 bit = shift & 0xF; 5310 mask = (0x1 << bit); 5311 switch (emu->cur_rh) { 5312 case 5: 5313 write_back_word(emu, srcval | mask); 5314 break; 5315 case 6: 5316 write_back_word(emu, srcval & ~mask); 5317 break; 5318 case 7: 5319 write_back_word(emu, srcval ^ mask); 5320 break; 5321 } 5322 CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 5323 } 5324 5325 static void 5326 x86emuOp2_btX_I(struct X86EMU *emu) 5327 { 5328 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5329 x86emuOp2_32_btX_I(emu); 5330 else 5331 x86emuOp2_16_btX_I(emu); 5332 } 5333 /**************************************************************************** 5334 REMARKS: 5335 Handles opcode 0x0f,0xbb 5336 ****************************************************************************/ 5337 static void 5338 x86emuOp2_btc_R(struct X86EMU *emu) 5339 { 5340 common_bitstring(emu, 3); 5341 } 5342 /**************************************************************************** 5343 REMARKS: 5344 Handles opcode 0x0f,0xbc 5345 ****************************************************************************/ 5346 static void 5347 x86emuOp2_bsf(struct X86EMU *emu) 5348 { 5349 common_bitsearch(emu, +1); 5350 } 5351 /**************************************************************************** 5352 REMARKS: 5353 Handles opcode 0x0f,0xbd 5354 ****************************************************************************/ 5355 static void 5356 x86emuOp2_bsr(struct X86EMU *emu) 5357 { 5358 common_bitsearch(emu, -1); 5359 } 5360 /**************************************************************************** 5361 REMARKS: 5362 Handles opcode 0x0f,0xbe 5363 ****************************************************************************/ 5364 static void 5365 x86emuOp2_32_movsx_byte_R_RM(struct X86EMU *emu) 5366 { 5367 uint32_t *destreg; 5368 5369 destreg = decode_rh_long_register(emu); 5370 *destreg = (int32_t)(int8_t)decode_and_fetch_byte(emu); 5371 } 5372 5373 static void 5374 x86emuOp2_16_movsx_byte_R_RM(struct X86EMU *emu) 5375 { 5376 uint16_t *destreg; 5377 5378 fetch_decode_modrm(emu); 5379 destreg = decode_rh_word_register(emu); 5380 *destreg = (int16_t)(int8_t)decode_and_fetch_byte(emu); 5381 } 5382 5383 static void 5384 x86emuOp2_movsx_byte_R_RM(struct X86EMU *emu) 5385 { 5386 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5387 x86emuOp2_32_movsx_byte_R_RM(emu); 5388 else 5389 x86emuOp2_16_movsx_byte_R_RM(emu); 5390 } 5391 /**************************************************************************** 5392 REMARKS: 5393 Handles opcode 0x0f,0xbf 5394 ****************************************************************************/ 5395 static void 5396 x86emuOp2_movsx_word_R_RM(struct X86EMU *emu) 5397 { 5398 uint32_t *destreg; 5399 5400 fetch_decode_modrm(emu); 5401 destreg = decode_rh_long_register(emu); 5402 *destreg = (int32_t)(int16_t)decode_and_fetch_word(emu); 5403 } 5404 5405 static void 5406 X86EMU_exec_two_byte(struct X86EMU * emu) 5407 { 5408 uint8_t op2; 5409 5410 op2 = fetch_byte_imm(emu); 5411 5412 switch (op2) { 5413 /* 0x00 Group F (ring 0 PM) */ 5414 /* 0x01 Group G (ring 0 PM) */ 5415 /* 0x02 lar (ring 0 PM) */ 5416 /* 0x03 lsl (ring 0 PM) */ 5417 /* 0x05 loadall (undocumented) */ 5418 /* 0x06 clts (ring 0 PM) */ 5419 /* 0x07 loadall (undocumented) */ 5420 /* 0x08 invd (ring 0 PM) */ 5421 /* 0x09 wbinvd (ring 0 PM) */ 5422 5423 /* 0x20 mov reg32(op2); break;creg (ring 0 PM) */ 5424 /* 0x21 mov reg32(op2); break;dreg (ring 0 PM) */ 5425 /* 0x22 mov creg(op2); break;reg32 (ring 0 PM) */ 5426 /* 0x23 mov dreg(op2); break;reg32 (ring 0 PM) */ 5427 /* 0x24 mov reg32(op2); break;treg (ring 0 PM) */ 5428 /* 0x26 mov treg(op2); break;reg32 (ring 0 PM) */ 5429 5430 case 0x31: 5431 x86emuOp2_rdtsc(emu); 5432 break; 5433 5434 case 0x80: 5435 common_jmp_long(emu, ACCESS_FLAG(F_OF)); 5436 break; 5437 case 0x81: 5438 common_jmp_long(emu, !ACCESS_FLAG(F_OF)); 5439 break; 5440 case 0x82: 5441 common_jmp_long(emu, ACCESS_FLAG(F_CF)); 5442 break; 5443 case 0x83: 5444 common_jmp_long(emu, !ACCESS_FLAG(F_CF)); 5445 break; 5446 case 0x84: 5447 common_jmp_long(emu, ACCESS_FLAG(F_ZF)); 5448 break; 5449 case 0x85: 5450 common_jmp_long(emu, !ACCESS_FLAG(F_ZF)); 5451 break; 5452 case 0x86: 5453 common_jmp_long(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); 5454 break; 5455 case 0x87: 5456 common_jmp_long(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))); 5457 break; 5458 case 0x88: 5459 common_jmp_long(emu, ACCESS_FLAG(F_SF)); 5460 break; 5461 case 0x89: 5462 common_jmp_long(emu, !ACCESS_FLAG(F_SF)); 5463 break; 5464 case 0x8a: 5465 common_jmp_long(emu, ACCESS_FLAG(F_PF)); 5466 break; 5467 case 0x8b: 5468 common_jmp_long(emu, !ACCESS_FLAG(F_PF)); 5469 break; 5470 case 0x8c: 5471 common_jmp_long(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))); 5472 break; 5473 case 0x8d: 5474 common_jmp_long(emu, !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)))); 5475 break; 5476 case 0x8e: 5477 common_jmp_long(emu, 5478 (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF))); 5479 break; 5480 case 0x8f: 5481 common_jmp_long(emu, 5482 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF))); 5483 break; 5484 5485 case 0x90: 5486 common_set_byte(emu, ACCESS_FLAG(F_OF)); 5487 break; 5488 case 0x91: 5489 common_set_byte(emu, !ACCESS_FLAG(F_OF)); 5490 break; 5491 case 0x92: 5492 common_set_byte(emu, ACCESS_FLAG(F_CF)); 5493 break; 5494 case 0x93: 5495 common_set_byte(emu, !ACCESS_FLAG(F_CF)); 5496 break; 5497 case 0x94: 5498 common_set_byte(emu, ACCESS_FLAG(F_ZF)); 5499 break; 5500 case 0x95: 5501 common_set_byte(emu, !ACCESS_FLAG(F_ZF)); 5502 break; 5503 case 0x96: 5504 common_set_byte(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); 5505 break; 5506 case 0x97: 5507 common_set_byte(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))); 5508 break; 5509 case 0x98: 5510 common_set_byte(emu, ACCESS_FLAG(F_SF)); 5511 break; 5512 case 0x99: 5513 common_set_byte(emu, !ACCESS_FLAG(F_SF)); 5514 break; 5515 case 0x9a: 5516 common_set_byte(emu, ACCESS_FLAG(F_PF)); 5517 break; 5518 case 0x9b: 5519 common_set_byte(emu, !ACCESS_FLAG(F_PF)); 5520 break; 5521 case 0x9c: 5522 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))); 5523 break; 5524 case 0x9d: 5525 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))); 5526 break; 5527 case 0x9e: 5528 common_set_byte(emu, 5529 (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || 5530 ACCESS_FLAG(F_ZF))); 5531 break; 5532 case 0x9f: 5533 common_set_byte(emu, 5534 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || 5535 ACCESS_FLAG(F_ZF))); 5536 break; 5537 5538 case 0xa0: 5539 x86emuOp2_push_FS(emu); 5540 break; 5541 case 0xa1: 5542 x86emuOp2_pop_FS(emu); 5543 break; 5544 case 0xa3: 5545 x86emuOp2_bt_R(emu); 5546 break; 5547 case 0xa4: 5548 x86emuOp2_shld_IMM(emu); 5549 break; 5550 case 0xa5: 5551 x86emuOp2_shld_CL(emu); 5552 break; 5553 case 0xa8: 5554 x86emuOp2_push_GS(emu); 5555 break; 5556 case 0xa9: 5557 x86emuOp2_pop_GS(emu); 5558 break; 5559 case 0xab: 5560 x86emuOp2_bts_R(emu); 5561 break; 5562 case 0xac: 5563 x86emuOp2_shrd_IMM(emu); 5564 break; 5565 case 0xad: 5566 x86emuOp2_shrd_CL(emu); 5567 break; 5568 case 0xaf: 5569 x86emuOp2_imul_R_RM(emu); 5570 break; 5571 5572 /* 0xb0 TODO: cmpxchg */ 5573 /* 0xb1 TODO: cmpxchg */ 5574 case 0xb2: 5575 x86emuOp2_lss_R_IMM(emu); 5576 break; 5577 case 0xb3: 5578 x86emuOp2_btr_R(emu); 5579 break; 5580 case 0xb4: 5581 x86emuOp2_lfs_R_IMM(emu); 5582 break; 5583 case 0xb5: 5584 x86emuOp2_lgs_R_IMM(emu); 5585 break; 5586 case 0xb6: 5587 x86emuOp2_movzx_byte_R_RM(emu); 5588 break; 5589 case 0xb7: 5590 x86emuOp2_movzx_word_R_RM(emu); 5591 break; 5592 case 0xba: 5593 x86emuOp2_btX_I(emu); 5594 break; 5595 case 0xbb: 5596 x86emuOp2_btc_R(emu); 5597 break; 5598 case 0xbc: 5599 x86emuOp2_bsf(emu); 5600 break; 5601 case 0xbd: 5602 x86emuOp2_bsr(emu); 5603 break; 5604 case 0xbe: 5605 x86emuOp2_movsx_byte_R_RM(emu); 5606 break; 5607 case 0xbf: 5608 x86emuOp2_movsx_word_R_RM(emu); 5609 break; 5610 5611 /* 0xc0 TODO: xadd */ 5612 /* 0xc1 TODO: xadd */ 5613 /* 0xc8 TODO: bswap */ 5614 /* 0xc9 TODO: bswap */ 5615 /* 0xca TODO: bswap */ 5616 /* 0xcb TODO: bswap */ 5617 /* 0xcc TODO: bswap */ 5618 /* 0xcd TODO: bswap */ 5619 /* 0xce TODO: bswap */ 5620 /* 0xcf TODO: bswap */ 5621 5622 default: 5623 X86EMU_halt_sys(emu); 5624 break; 5625 } 5626 } 5627 5628 /* 5629 * Carry Chain Calculation 5630 * 5631 * This represents a somewhat expensive calculation which is 5632 * apparently required to emulate the setting of the OF and AF flag. 5633 * The latter is not so important, but the former is. The overflow 5634 * flag is the XOR of the top two bits of the carry chain for an 5635 * addition (similar for subtraction). Since we do not want to 5636 * simulate the addition in a bitwise manner, we try to calculate the 5637 * carry chain given the two operands and the result. 5638 * 5639 * So, given the following table, which represents the addition of two 5640 * bits, we can derive a formula for the carry chain. 5641 * 5642 * a b cin r cout 5643 * 0 0 0 0 0 5644 * 0 0 1 1 0 5645 * 0 1 0 1 0 5646 * 0 1 1 0 1 5647 * 1 0 0 1 0 5648 * 1 0 1 0 1 5649 * 1 1 0 0 1 5650 * 1 1 1 1 1 5651 * 5652 * Construction of table for cout: 5653 * 5654 * ab 5655 * r \ 00 01 11 10 5656 * |------------------ 5657 * 0 | 0 1 1 1 5658 * 1 | 0 0 1 0 5659 * 5660 * By inspection, one gets: cc = ab + r'(a + b) 5661 * 5662 * That represents alot of operations, but NO CHOICE.... 5663 * 5664 * Borrow Chain Calculation. 5665 * 5666 * The following table represents the subtraction of two bits, from 5667 * which we can derive a formula for the borrow chain. 5668 * 5669 * a b bin r bout 5670 * 0 0 0 0 0 5671 * 0 0 1 1 1 5672 * 0 1 0 1 1 5673 * 0 1 1 0 1 5674 * 1 0 0 1 0 5675 * 1 0 1 0 0 5676 * 1 1 0 0 0 5677 * 1 1 1 1 1 5678 * 5679 * Construction of table for cout: 5680 * 5681 * ab 5682 * r \ 00 01 11 10 5683 * |------------------ 5684 * 0 | 0 1 0 0 5685 * 1 | 1 1 1 0 5686 * 5687 * By inspection, one gets: bc = a'b + r(a' + b) 5688 * 5689 ****************************************************************************/ 5690 5691 /*------------------------- Global Variables ------------------------------*/ 5692 5693 static uint32_t x86emu_parity_tab[8] = 5694 { 5695 0x96696996, 5696 0x69969669, 5697 0x69969669, 5698 0x96696996, 5699 0x69969669, 5700 0x96696996, 5701 0x96696996, 5702 0x69969669, 5703 }; 5704 #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0) 5705 #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1) 5706 5707 /**************************************************************************** 5708 REMARKS: 5709 Implements the AAA instruction and side effects. 5710 ****************************************************************************/ 5711 static uint16_t 5712 aaa_word(struct X86EMU *emu, uint16_t d) 5713 { 5714 uint16_t res; 5715 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { 5716 d += 0x6; 5717 d += 0x100; 5718 SET_FLAG(F_AF); 5719 SET_FLAG(F_CF); 5720 } else { 5721 CLEAR_FLAG(F_CF); 5722 CLEAR_FLAG(F_AF); 5723 } 5724 res = (uint16_t) (d & 0xFF0F); 5725 CLEAR_FLAG(F_SF); 5726 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 5727 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5728 return res; 5729 } 5730 /**************************************************************************** 5731 REMARKS: 5732 Implements the AAA instruction and side effects. 5733 ****************************************************************************/ 5734 static uint16_t 5735 aas_word(struct X86EMU *emu, uint16_t d) 5736 { 5737 uint16_t res; 5738 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { 5739 d -= 0x6; 5740 d -= 0x100; 5741 SET_FLAG(F_AF); 5742 SET_FLAG(F_CF); 5743 } else { 5744 CLEAR_FLAG(F_CF); 5745 CLEAR_FLAG(F_AF); 5746 } 5747 res = (uint16_t) (d & 0xFF0F); 5748 CLEAR_FLAG(F_SF); 5749 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 5750 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5751 return res; 5752 } 5753 /**************************************************************************** 5754 REMARKS: 5755 Implements the AAD instruction and side effects. 5756 ****************************************************************************/ 5757 static uint16_t 5758 aad_word(struct X86EMU *emu, uint16_t d) 5759 { 5760 uint16_t l; 5761 uint8_t hb, lb; 5762 5763 hb = (uint8_t) ((d >> 8) & 0xff); 5764 lb = (uint8_t) ((d & 0xff)); 5765 l = (uint16_t) ((lb + 10 * hb) & 0xFF); 5766 5767 CLEAR_FLAG(F_CF); 5768 CLEAR_FLAG(F_AF); 5769 CLEAR_FLAG(F_OF); 5770 CONDITIONAL_SET_FLAG(l & 0x80, F_SF); 5771 CONDITIONAL_SET_FLAG(l == 0, F_ZF); 5772 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF); 5773 return l; 5774 } 5775 /**************************************************************************** 5776 REMARKS: 5777 Implements the AAM instruction and side effects. 5778 ****************************************************************************/ 5779 static uint16_t 5780 aam_word(struct X86EMU *emu, uint8_t d) 5781 { 5782 uint16_t h, l; 5783 5784 h = (uint16_t) (d / 10); 5785 l = (uint16_t) (d % 10); 5786 l |= (uint16_t) (h << 8); 5787 5788 CLEAR_FLAG(F_CF); 5789 CLEAR_FLAG(F_AF); 5790 CLEAR_FLAG(F_OF); 5791 CONDITIONAL_SET_FLAG(l & 0x80, F_SF); 5792 CONDITIONAL_SET_FLAG(l == 0, F_ZF); 5793 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF); 5794 return l; 5795 } 5796 /**************************************************************************** 5797 REMARKS: 5798 Implements the ADC instruction and side effects. 5799 ****************************************************************************/ 5800 static uint8_t 5801 adc_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 5802 { 5803 uint32_t res; /* all operands in native machine order */ 5804 uint32_t cc; 5805 5806 if (ACCESS_FLAG(F_CF)) 5807 res = 1 + d + s; 5808 else 5809 res = d + s; 5810 5811 CONDITIONAL_SET_FLAG(res & 0x100, F_CF); 5812 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 5813 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 5814 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5815 5816 /* calculate the carry chain SEE NOTE AT TOP. */ 5817 cc = (s & d) | ((~res) & (s | d)); 5818 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 5819 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 5820 return (uint8_t) res; 5821 } 5822 /**************************************************************************** 5823 REMARKS: 5824 Implements the ADC instruction and side effects. 5825 ****************************************************************************/ 5826 static uint16_t 5827 adc_word(struct X86EMU *emu, uint16_t d, uint16_t s) 5828 { 5829 uint32_t res; /* all operands in native machine order */ 5830 uint32_t cc; 5831 5832 if (ACCESS_FLAG(F_CF)) 5833 res = 1 + d + s; 5834 else 5835 res = d + s; 5836 5837 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF); 5838 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 5839 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 5840 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5841 5842 /* calculate the carry chain SEE NOTE AT TOP. */ 5843 cc = (s & d) | ((~res) & (s | d)); 5844 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 5845 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 5846 return (uint16_t) res; 5847 } 5848 /**************************************************************************** 5849 REMARKS: 5850 Implements the ADC instruction and side effects. 5851 ****************************************************************************/ 5852 static uint32_t 5853 adc_long(struct X86EMU *emu, uint32_t d, uint32_t s) 5854 { 5855 uint32_t lo; /* all operands in native machine order */ 5856 uint32_t hi; 5857 uint32_t res; 5858 uint32_t cc; 5859 5860 if (ACCESS_FLAG(F_CF)) { 5861 lo = 1 + (d & 0xFFFF) + (s & 0xFFFF); 5862 res = 1 + d + s; 5863 } else { 5864 lo = (d & 0xFFFF) + (s & 0xFFFF); 5865 res = d + s; 5866 } 5867 hi = (lo >> 16) + (d >> 16) + (s >> 16); 5868 5869 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF); 5870 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 5871 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 5872 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5873 5874 /* calculate the carry chain SEE NOTE AT TOP. */ 5875 cc = (s & d) | ((~res) & (s | d)); 5876 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 5877 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 5878 return res; 5879 } 5880 /**************************************************************************** 5881 REMARKS: 5882 Implements the ADD instruction and side effects. 5883 ****************************************************************************/ 5884 static uint8_t 5885 add_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 5886 { 5887 uint32_t res; /* all operands in native machine order */ 5888 uint32_t cc; 5889 5890 res = d + s; 5891 CONDITIONAL_SET_FLAG(res & 0x100, F_CF); 5892 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 5893 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 5894 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5895 5896 /* calculate the carry chain SEE NOTE AT TOP. */ 5897 cc = (s & d) | ((~res) & (s | d)); 5898 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 5899 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 5900 return (uint8_t) res; 5901 } 5902 /**************************************************************************** 5903 REMARKS: 5904 Implements the ADD instruction and side effects. 5905 ****************************************************************************/ 5906 static uint16_t 5907 add_word(struct X86EMU *emu, uint16_t d, uint16_t s) 5908 { 5909 uint32_t res; /* all operands in native machine order */ 5910 uint32_t cc; 5911 5912 res = d + s; 5913 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF); 5914 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 5915 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 5916 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5917 5918 /* calculate the carry chain SEE NOTE AT TOP. */ 5919 cc = (s & d) | ((~res) & (s | d)); 5920 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 5921 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 5922 return (uint16_t) res; 5923 } 5924 /**************************************************************************** 5925 REMARKS: 5926 Implements the ADD instruction and side effects. 5927 ****************************************************************************/ 5928 static uint32_t 5929 add_long(struct X86EMU *emu, uint32_t d, uint32_t s) 5930 { 5931 uint32_t lo; /* all operands in native machine order */ 5932 uint32_t hi; 5933 uint32_t res; 5934 uint32_t cc; 5935 5936 lo = (d & 0xFFFF) + (s & 0xFFFF); 5937 res = d + s; 5938 hi = (lo >> 16) + (d >> 16) + (s >> 16); 5939 5940 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF); 5941 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 5942 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 5943 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5944 5945 /* calculate the carry chain SEE NOTE AT TOP. */ 5946 cc = (s & d) | ((~res) & (s | d)); 5947 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 5948 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 5949 5950 return res; 5951 } 5952 /**************************************************************************** 5953 REMARKS: 5954 Implements the AND instruction and side effects. 5955 ****************************************************************************/ 5956 static uint8_t 5957 and_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 5958 { 5959 uint8_t res; /* all operands in native machine order */ 5960 5961 res = d & s; 5962 5963 /* set the flags */ 5964 CLEAR_FLAG(F_OF); 5965 CLEAR_FLAG(F_CF); 5966 CLEAR_FLAG(F_AF); 5967 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 5968 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 5969 CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 5970 return res; 5971 } 5972 /**************************************************************************** 5973 REMARKS: 5974 Implements the AND instruction and side effects. 5975 ****************************************************************************/ 5976 static uint16_t 5977 and_word(struct X86EMU *emu, uint16_t d, uint16_t s) 5978 { 5979 uint16_t res; /* all operands in native machine order */ 5980 5981 res = d & s; 5982 5983 /* set the flags */ 5984 CLEAR_FLAG(F_OF); 5985 CLEAR_FLAG(F_CF); 5986 CLEAR_FLAG(F_AF); 5987 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 5988 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 5989 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5990 return res; 5991 } 5992 /**************************************************************************** 5993 REMARKS: 5994 Implements the AND instruction and side effects. 5995 ****************************************************************************/ 5996 static uint32_t 5997 and_long(struct X86EMU *emu, uint32_t d, uint32_t s) 5998 { 5999 uint32_t res; /* all operands in native machine order */ 6000 6001 res = d & s; 6002 6003 /* set the flags */ 6004 CLEAR_FLAG(F_OF); 6005 CLEAR_FLAG(F_CF); 6006 CLEAR_FLAG(F_AF); 6007 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6008 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6009 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6010 return res; 6011 } 6012 /**************************************************************************** 6013 REMARKS: 6014 Implements the CMP instruction and side effects. 6015 ****************************************************************************/ 6016 static uint8_t 6017 cmp_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6018 { 6019 uint32_t res; /* all operands in native machine order */ 6020 uint32_t bc; 6021 6022 res = d - s; 6023 CLEAR_FLAG(F_CF); 6024 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6025 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6026 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6027 6028 /* calculate the borrow chain. See note at top */ 6029 bc = (res & (~d | s)) | (~d & s); 6030 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); 6031 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 6032 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6033 return d; 6034 } 6035 6036 static void 6037 cmp_byte_no_return(struct X86EMU *emu, uint8_t d, uint8_t s) 6038 { 6039 cmp_byte(emu, d, s); 6040 } 6041 /**************************************************************************** 6042 REMARKS: 6043 Implements the CMP instruction and side effects. 6044 ****************************************************************************/ 6045 static uint16_t 6046 cmp_word(struct X86EMU *emu, uint16_t d, uint16_t s) 6047 { 6048 uint32_t res; /* all operands in native machine order */ 6049 uint32_t bc; 6050 6051 res = d - s; 6052 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6053 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6054 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6055 6056 /* calculate the borrow chain. See note at top */ 6057 bc = (res & (~d | s)) | (~d & s); 6058 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 6059 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 6060 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6061 return d; 6062 } 6063 6064 static void 6065 cmp_word_no_return(struct X86EMU *emu, uint16_t d, uint16_t s) 6066 { 6067 cmp_word(emu, d, s); 6068 } 6069 /**************************************************************************** 6070 REMARKS: 6071 Implements the CMP instruction and side effects. 6072 ****************************************************************************/ 6073 static uint32_t 6074 cmp_long(struct X86EMU *emu, uint32_t d, uint32_t s) 6075 { 6076 uint32_t res; /* all operands in native machine order */ 6077 uint32_t bc; 6078 6079 res = d - s; 6080 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6081 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6082 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6083 6084 /* calculate the borrow chain. See note at top */ 6085 bc = (res & (~d | s)) | (~d & s); 6086 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 6087 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 6088 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6089 return d; 6090 } 6091 6092 static void 6093 cmp_long_no_return(struct X86EMU *emu, uint32_t d, uint32_t s) 6094 { 6095 cmp_long(emu, d, s); 6096 } 6097 /**************************************************************************** 6098 REMARKS: 6099 Implements the DAA instruction and side effects. 6100 ****************************************************************************/ 6101 static uint8_t 6102 daa_byte(struct X86EMU *emu, uint8_t d) 6103 { 6104 uint32_t res = d; 6105 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) { 6106 res += 6; 6107 SET_FLAG(F_AF); 6108 } 6109 if (res > 0x9F || ACCESS_FLAG(F_CF)) { 6110 res += 0x60; 6111 SET_FLAG(F_CF); 6112 } 6113 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6114 CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF); 6115 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6116 return (uint8_t) res; 6117 } 6118 /**************************************************************************** 6119 REMARKS: 6120 Implements the DAS instruction and side effects. 6121 ****************************************************************************/ 6122 static uint8_t 6123 das_byte(struct X86EMU *emu, uint8_t d) 6124 { 6125 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) { 6126 d -= 6; 6127 SET_FLAG(F_AF); 6128 } 6129 if (d > 0x9F || ACCESS_FLAG(F_CF)) { 6130 d -= 0x60; 6131 SET_FLAG(F_CF); 6132 } 6133 CONDITIONAL_SET_FLAG(d & 0x80, F_SF); 6134 CONDITIONAL_SET_FLAG(d == 0, F_ZF); 6135 CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF); 6136 return d; 6137 } 6138 /**************************************************************************** 6139 REMARKS: 6140 Implements the DEC instruction and side effects. 6141 ****************************************************************************/ 6142 static uint8_t 6143 dec_byte(struct X86EMU *emu, uint8_t d) 6144 { 6145 uint32_t res; /* all operands in native machine order */ 6146 uint32_t bc; 6147 6148 res = d - 1; 6149 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6150 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6151 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6152 6153 /* calculate the borrow chain. See note at top */ 6154 /* based on sub_byte, uses s==1. */ 6155 bc = (res & (~d | 1)) | (~d & 1); 6156 /* carry flag unchanged */ 6157 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 6158 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6159 return (uint8_t) res; 6160 } 6161 /**************************************************************************** 6162 REMARKS: 6163 Implements the DEC instruction and side effects. 6164 ****************************************************************************/ 6165 static uint16_t 6166 dec_word(struct X86EMU *emu, uint16_t d) 6167 { 6168 uint32_t res; /* all operands in native machine order */ 6169 uint32_t bc; 6170 6171 res = d - 1; 6172 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6173 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6174 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6175 6176 /* calculate the borrow chain. See note at top */ 6177 /* based on the sub_byte routine, with s==1 */ 6178 bc = (res & (~d | 1)) | (~d & 1); 6179 /* carry flag unchanged */ 6180 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 6181 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6182 return (uint16_t) res; 6183 } 6184 /**************************************************************************** 6185 REMARKS: 6186 Implements the DEC instruction and side effects. 6187 ****************************************************************************/ 6188 static uint32_t 6189 dec_long(struct X86EMU *emu, uint32_t d) 6190 { 6191 uint32_t res; /* all operands in native machine order */ 6192 uint32_t bc; 6193 6194 res = d - 1; 6195 6196 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6197 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6198 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6199 6200 /* calculate the borrow chain. See note at top */ 6201 bc = (res & (~d | 1)) | (~d & 1); 6202 /* carry flag unchanged */ 6203 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 6204 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6205 return res; 6206 } 6207 /**************************************************************************** 6208 REMARKS: 6209 Implements the INC instruction and side effects. 6210 ****************************************************************************/ 6211 static uint8_t 6212 inc_byte(struct X86EMU *emu, uint8_t d) 6213 { 6214 uint32_t res; /* all operands in native machine order */ 6215 uint32_t cc; 6216 6217 res = d + 1; 6218 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6219 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6220 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6221 6222 /* calculate the carry chain SEE NOTE AT TOP. */ 6223 cc = ((1 & d) | (~res)) & (1 | d); 6224 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 6225 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6226 return (uint8_t) res; 6227 } 6228 /**************************************************************************** 6229 REMARKS: 6230 Implements the INC instruction and side effects. 6231 ****************************************************************************/ 6232 static uint16_t 6233 inc_word(struct X86EMU *emu, uint16_t d) 6234 { 6235 uint32_t res; /* all operands in native machine order */ 6236 uint32_t cc; 6237 6238 res = d + 1; 6239 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6240 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6241 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6242 6243 /* calculate the carry chain SEE NOTE AT TOP. */ 6244 cc = (1 & d) | ((~res) & (1 | d)); 6245 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 6246 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6247 return (uint16_t) res; 6248 } 6249 /**************************************************************************** 6250 REMARKS: 6251 Implements the INC instruction and side effects. 6252 ****************************************************************************/ 6253 static uint32_t 6254 inc_long(struct X86EMU *emu, uint32_t d) 6255 { 6256 uint32_t res; /* all operands in native machine order */ 6257 uint32_t cc; 6258 6259 res = d + 1; 6260 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6261 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6262 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6263 6264 /* calculate the carry chain SEE NOTE AT TOP. */ 6265 cc = (1 & d) | ((~res) & (1 | d)); 6266 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 6267 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6268 return res; 6269 } 6270 /**************************************************************************** 6271 REMARKS: 6272 Implements the OR instruction and side effects. 6273 ****************************************************************************/ 6274 static uint8_t 6275 or_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6276 { 6277 uint8_t res; /* all operands in native machine order */ 6278 6279 res = d | s; 6280 CLEAR_FLAG(F_OF); 6281 CLEAR_FLAG(F_CF); 6282 CLEAR_FLAG(F_AF); 6283 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6284 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6285 CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 6286 return res; 6287 } 6288 /**************************************************************************** 6289 REMARKS: 6290 Implements the OR instruction and side effects. 6291 ****************************************************************************/ 6292 static uint16_t 6293 or_word(struct X86EMU *emu, uint16_t d, uint16_t s) 6294 { 6295 uint16_t res; /* all operands in native machine order */ 6296 6297 res = d | s; 6298 /* set the carry flag to be bit 8 */ 6299 CLEAR_FLAG(F_OF); 6300 CLEAR_FLAG(F_CF); 6301 CLEAR_FLAG(F_AF); 6302 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6303 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6304 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6305 return res; 6306 } 6307 /**************************************************************************** 6308 REMARKS: 6309 Implements the OR instruction and side effects. 6310 ****************************************************************************/ 6311 static uint32_t 6312 or_long(struct X86EMU *emu, uint32_t d, uint32_t s) 6313 { 6314 uint32_t res; /* all operands in native machine order */ 6315 6316 res = d | s; 6317 6318 /* set the carry flag to be bit 8 */ 6319 CLEAR_FLAG(F_OF); 6320 CLEAR_FLAG(F_CF); 6321 CLEAR_FLAG(F_AF); 6322 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6323 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6324 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6325 return res; 6326 } 6327 /**************************************************************************** 6328 REMARKS: 6329 Implements the OR instruction and side effects. 6330 ****************************************************************************/ 6331 static uint8_t 6332 neg_byte(struct X86EMU *emu, uint8_t s) 6333 { 6334 uint8_t res; 6335 uint8_t bc; 6336 6337 CONDITIONAL_SET_FLAG(s != 0, F_CF); 6338 res = (uint8_t) - s; 6339 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6340 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6341 CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 6342 /* calculate the borrow chain --- modified such that d=0. 6343 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for 6344 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and 6345 * res&0xfff... == res. Similarly ~d&s == s. So the simplified 6346 * result is: */ 6347 bc = res | s; 6348 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 6349 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6350 return res; 6351 } 6352 /**************************************************************************** 6353 REMARKS: 6354 Implements the OR instruction and side effects. 6355 ****************************************************************************/ 6356 static uint16_t 6357 neg_word(struct X86EMU *emu, uint16_t s) 6358 { 6359 uint16_t res; 6360 uint16_t bc; 6361 6362 CONDITIONAL_SET_FLAG(s != 0, F_CF); 6363 res = (uint16_t) - s; 6364 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6365 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6366 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6367 6368 /* calculate the borrow chain --- modified such that d=0. 6369 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for 6370 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and 6371 * res&0xfff... == res. Similarly ~d&s == s. So the simplified 6372 * result is: */ 6373 bc = res | s; 6374 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 6375 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6376 return res; 6377 } 6378 /**************************************************************************** 6379 REMARKS: 6380 Implements the OR instruction and side effects. 6381 ****************************************************************************/ 6382 static uint32_t 6383 neg_long(struct X86EMU *emu, uint32_t s) 6384 { 6385 uint32_t res; 6386 uint32_t bc; 6387 6388 CONDITIONAL_SET_FLAG(s != 0, F_CF); 6389 res = (uint32_t) - s; 6390 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6391 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6392 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6393 6394 /* calculate the borrow chain --- modified such that d=0. 6395 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for 6396 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and 6397 * res&0xfff... == res. Similarly ~d&s == s. So the simplified 6398 * result is: */ 6399 bc = res | s; 6400 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 6401 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6402 return res; 6403 } 6404 /**************************************************************************** 6405 REMARKS: 6406 Implements the RCL instruction and side effects. 6407 ****************************************************************************/ 6408 static uint8_t 6409 rcl_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6410 { 6411 unsigned int res, cnt, mask, cf; 6412 6413 /* s is the rotate distance. It varies from 0 - 8. */ 6414 /* have 6415 * 6416 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 6417 * 6418 * want to rotate through the carry by "s" bits. We could loop, but 6419 * that's inefficient. So the width is 9, and we split into three 6420 * parts: 6421 * 6422 * The new carry flag (was B_n) the stuff in B_n-1 .. B_0 the stuff in 6423 * B_7 .. B_n+1 6424 * 6425 * The new rotate is done mod 9, and given this, for a rotation of n bits 6426 * (mod 9) the new carry flag is then located n bits from the MSB. 6427 * The low part is then shifted up cnt bits, and the high part is or'd 6428 * in. Using CAPS for new values, and lowercase for the original 6429 * values, this can be expressed as: 6430 * 6431 * IF n > 0 1) CF <- b_(8-n) 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 6432 * 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */ 6433 res = d; 6434 if ((cnt = s % 9) != 0) { 6435 /* extract the new CARRY FLAG. */ 6436 /* CF <- b_(8-n) */ 6437 cf = (d >> (8 - cnt)) & 0x1; 6438 6439 /* get the low stuff which rotated into the range B_7 .. B_cnt */ 6440 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */ 6441 /* note that the right hand side done by the mask */ 6442 res = (d << cnt) & 0xff; 6443 6444 /* now the high stuff which rotated around into the positions 6445 * B_cnt-2 .. B_0 */ 6446 /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */ 6447 /* shift it downward, 7-(n-2) = 9-n positions. and mask off 6448 * the result before or'ing in. */ 6449 mask = (1 << (cnt - 1)) - 1; 6450 res |= (d >> (9 - cnt)) & mask; 6451 6452 /* if the carry flag was set, or it in. */ 6453 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6454 /* B_(n-1) <- cf */ 6455 res |= 1 << (cnt - 1); 6456 } 6457 /* set the new carry flag, based on the variable "cf" */ 6458 CONDITIONAL_SET_FLAG(cf, F_CF); 6459 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and 6460 * the most significant bit. Blecck. */ 6461 /* parenthesized this expression since it appears to be 6462 * causing OF to be misset */ 6463 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)), 6464 F_OF); 6465 6466 } 6467 return (uint8_t) res; 6468 } 6469 /**************************************************************************** 6470 REMARKS: 6471 Implements the RCL instruction and side effects. 6472 ****************************************************************************/ 6473 static uint16_t 6474 rcl_word(struct X86EMU *emu, uint16_t d, uint8_t s) 6475 { 6476 unsigned int res, cnt, mask, cf; 6477 6478 res = d; 6479 if ((cnt = s % 17) != 0) { 6480 cf = (d >> (16 - cnt)) & 0x1; 6481 res = (d << cnt) & 0xffff; 6482 mask = (1 << (cnt - 1)) - 1; 6483 res |= (d >> (17 - cnt)) & mask; 6484 if (ACCESS_FLAG(F_CF)) { 6485 res |= 1 << (cnt - 1); 6486 } 6487 CONDITIONAL_SET_FLAG(cf, F_CF); 6488 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)), 6489 F_OF); 6490 } 6491 return (uint16_t) res; 6492 } 6493 /**************************************************************************** 6494 REMARKS: 6495 Implements the RCL instruction and side effects. 6496 ****************************************************************************/ 6497 static uint32_t 6498 rcl_long(struct X86EMU *emu, uint32_t d, uint8_t s) 6499 { 6500 uint32_t res, cnt, mask, cf; 6501 6502 res = d; 6503 if ((cnt = s % 33) != 0) { 6504 cf = (d >> (32 - cnt)) & 0x1; 6505 res = (d << cnt) & 0xffffffff; 6506 mask = (1 << (cnt - 1)) - 1; 6507 res |= (d >> (33 - cnt)) & mask; 6508 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6509 res |= 1 << (cnt - 1); 6510 } 6511 CONDITIONAL_SET_FLAG(cf, F_CF); 6512 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)), 6513 F_OF); 6514 } 6515 return res; 6516 } 6517 /**************************************************************************** 6518 REMARKS: 6519 Implements the RCR instruction and side effects. 6520 ****************************************************************************/ 6521 static uint8_t 6522 rcr_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6523 { 6524 uint32_t res, cnt; 6525 uint32_t mask, cf, ocf = 0; 6526 6527 /* rotate right through carry */ 6528 /* s is the rotate distance. It varies from 0 - 8. d is the byte 6529 * object rotated. 6530 * 6531 * have 6532 * 6533 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 6534 * 6535 * The new rotate is done mod 9, and given this, for a rotation of n bits 6536 * (mod 9) the new carry flag is then located n bits from the LSB. 6537 * The low part is then shifted up cnt bits, and the high part is or'd 6538 * in. Using CAPS for new values, and lowercase for the original 6539 * values, this can be expressed as: 6540 * 6541 * IF n > 0 1) CF <- b_(n-1) 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 6542 * 3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */ 6543 res = d; 6544 if ((cnt = s % 9) != 0) { 6545 /* extract the new CARRY FLAG. */ 6546 /* CF <- b_(n-1) */ 6547 if (cnt == 1) { 6548 cf = d & 0x1; 6549 /* note hackery here. Access_flag(..) evaluates to 6550 * either 0 if flag not set non-zero if flag is set. 6551 * doing access_flag(..) != 0 casts that into either 6552 * 0..1 in any representation of the flags register 6553 * (i.e. packed bit array or unpacked.) */ 6554 ocf = ACCESS_FLAG(F_CF) != 0; 6555 } else 6556 cf = (d >> (cnt - 1)) & 0x1; 6557 6558 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */ 6559 /* note that the right hand side done by the mask This is 6560 * effectively done by shifting the object to the right. The 6561 * result must be masked, in case the object came in and was 6562 * treated as a negative number. Needed??? */ 6563 6564 mask = (1 << (8 - cnt)) - 1; 6565 res = (d >> cnt) & mask; 6566 6567 /* now the high stuff which rotated around into the positions 6568 * B_cnt-2 .. B_0 */ 6569 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */ 6570 /* shift it downward, 7-(n-2) = 9-n positions. and mask off 6571 * the result before or'ing in. */ 6572 res |= (d << (9 - cnt)); 6573 6574 /* if the carry flag was set, or it in. */ 6575 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6576 /* B_(8-n) <- cf */ 6577 res |= 1 << (8 - cnt); 6578 } 6579 /* set the new carry flag, based on the variable "cf" */ 6580 CONDITIONAL_SET_FLAG(cf, F_CF); 6581 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and 6582 * the most significant bit. Blecck. */ 6583 /* parenthesized... */ 6584 if (cnt == 1) { 6585 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)), 6586 F_OF); 6587 } 6588 } 6589 return (uint8_t) res; 6590 } 6591 /**************************************************************************** 6592 REMARKS: 6593 Implements the RCR instruction and side effects. 6594 ****************************************************************************/ 6595 static uint16_t 6596 rcr_word(struct X86EMU *emu, uint16_t d, uint8_t s) 6597 { 6598 uint32_t res, cnt; 6599 uint32_t mask, cf, ocf = 0; 6600 6601 /* rotate right through carry */ 6602 res = d; 6603 if ((cnt = s % 17) != 0) { 6604 if (cnt == 1) { 6605 cf = d & 0x1; 6606 ocf = ACCESS_FLAG(F_CF) != 0; 6607 } else 6608 cf = (d >> (cnt - 1)) & 0x1; 6609 mask = (1 << (16 - cnt)) - 1; 6610 res = (d >> cnt) & mask; 6611 res |= (d << (17 - cnt)); 6612 if (ACCESS_FLAG(F_CF)) { 6613 res |= 1 << (16 - cnt); 6614 } 6615 CONDITIONAL_SET_FLAG(cf, F_CF); 6616 if (cnt == 1) { 6617 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)), 6618 F_OF); 6619 } 6620 } 6621 return (uint16_t) res; 6622 } 6623 /**************************************************************************** 6624 REMARKS: 6625 Implements the RCR instruction and side effects. 6626 ****************************************************************************/ 6627 static uint32_t 6628 rcr_long(struct X86EMU *emu, uint32_t d, uint8_t s) 6629 { 6630 uint32_t res, cnt; 6631 uint32_t mask, cf, ocf = 0; 6632 6633 /* rotate right through carry */ 6634 res = d; 6635 if ((cnt = s % 33) != 0) { 6636 if (cnt == 1) { 6637 cf = d & 0x1; 6638 ocf = ACCESS_FLAG(F_CF) != 0; 6639 } else 6640 cf = (d >> (cnt - 1)) & 0x1; 6641 mask = (1 << (32 - cnt)) - 1; 6642 res = (d >> cnt) & mask; 6643 if (cnt != 1) 6644 res |= (d << (33 - cnt)); 6645 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6646 res |= 1 << (32 - cnt); 6647 } 6648 CONDITIONAL_SET_FLAG(cf, F_CF); 6649 if (cnt == 1) { 6650 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)), 6651 F_OF); 6652 } 6653 } 6654 return res; 6655 } 6656 /**************************************************************************** 6657 REMARKS: 6658 Implements the ROL instruction and side effects. 6659 ****************************************************************************/ 6660 static uint8_t 6661 rol_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6662 { 6663 unsigned int res, cnt, mask; 6664 6665 /* rotate left */ 6666 /* s is the rotate distance. It varies from 0 - 8. d is the byte 6667 * object rotated. 6668 * 6669 * have 6670 * 6671 * CF B_7 ... B_0 6672 * 6673 * The new rotate is done mod 8. Much simpler than the "rcl" or "rcr" 6674 * operations. 6675 * 6676 * IF n > 0 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) 2) B_(n-1) .. 6677 * B_(0) <- b_(7) .. b_(8-n) */ 6678 res = d; 6679 if ((cnt = s % 8) != 0) { 6680 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */ 6681 res = (d << cnt); 6682 6683 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */ 6684 mask = (1 << cnt) - 1; 6685 res |= (d >> (8 - cnt)) & mask; 6686 6687 /* set the new carry flag, Note that it is the low order bit 6688 * of the result!!! */ 6689 CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6690 /* OVERFLOW is set *IFF* s==1, then it is the xor of CF and 6691 * the most significant bit. Blecck. */ 6692 CONDITIONAL_SET_FLAG(s == 1 && 6693 XOR2((res & 0x1) + ((res >> 6) & 0x2)), 6694 F_OF); 6695 } if (s != 0) { 6696 /* set the new carry flag, Note that it is the low order bit 6697 * of the result!!! */ 6698 CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6699 } 6700 return (uint8_t) res; 6701 } 6702 /**************************************************************************** 6703 REMARKS: 6704 Implements the ROL instruction and side effects. 6705 ****************************************************************************/ 6706 static uint16_t 6707 rol_word(struct X86EMU *emu, uint16_t d, uint8_t s) 6708 { 6709 unsigned int res, cnt, mask; 6710 6711 res = d; 6712 if ((cnt = s % 16) != 0) { 6713 res = (d << cnt); 6714 mask = (1 << cnt) - 1; 6715 res |= (d >> (16 - cnt)) & mask; 6716 CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6717 CONDITIONAL_SET_FLAG(s == 1 && 6718 XOR2((res & 0x1) + ((res >> 14) & 0x2)), 6719 F_OF); 6720 } if (s != 0) { 6721 /* set the new carry flag, Note that it is the low order bit 6722 * of the result!!! */ 6723 CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6724 } 6725 return (uint16_t) res; 6726 } 6727 /**************************************************************************** 6728 REMARKS: 6729 Implements the ROL instruction and side effects. 6730 ****************************************************************************/ 6731 static uint32_t 6732 rol_long(struct X86EMU *emu, uint32_t d, uint8_t s) 6733 { 6734 uint32_t res, cnt, mask; 6735 6736 res = d; 6737 if ((cnt = s % 32) != 0) { 6738 res = (d << cnt); 6739 mask = (1 << cnt) - 1; 6740 res |= (d >> (32 - cnt)) & mask; 6741 CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6742 CONDITIONAL_SET_FLAG(s == 1 && 6743 XOR2((res & 0x1) + ((res >> 30) & 0x2)), 6744 F_OF); 6745 } if (s != 0) { 6746 /* set the new carry flag, Note that it is the low order bit 6747 * of the result!!! */ 6748 CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6749 } 6750 return res; 6751 } 6752 /**************************************************************************** 6753 REMARKS: 6754 Implements the ROR instruction and side effects. 6755 ****************************************************************************/ 6756 static uint8_t 6757 ror_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6758 { 6759 unsigned int res, cnt, mask; 6760 6761 /* rotate right */ 6762 /* s is the rotate distance. It varies from 0 - 8. d is the byte 6763 * object rotated. 6764 * 6765 * have 6766 * 6767 * B_7 ... B_0 6768 * 6769 * The rotate is done mod 8. 6770 * 6771 * IF n > 0 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 2) B_(7) .. 6772 * B_(8-n) <- b_(n-1) .. b_(0) */ 6773 res = d; 6774 if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */ 6775 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */ 6776 res = (d << (8 - cnt)); 6777 6778 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */ 6779 mask = (1 << (8 - cnt)) - 1; 6780 res |= (d >> (cnt)) & mask; 6781 6782 /* set the new carry flag, Note that it is the low order bit 6783 * of the result!!! */ 6784 CONDITIONAL_SET_FLAG(res & 0x80, F_CF); 6785 /* OVERFLOW is set *IFF* s==1, then it is the xor of the two 6786 * most significant bits. Blecck. */ 6787 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF); 6788 } else if (s != 0) { 6789 /* set the new carry flag, Note that it is the low order bit 6790 * of the result!!! */ 6791 CONDITIONAL_SET_FLAG(res & 0x80, F_CF); 6792 } 6793 return (uint8_t) res; 6794 } 6795 /**************************************************************************** 6796 REMARKS: 6797 Implements the ROR instruction and side effects. 6798 ****************************************************************************/ 6799 static uint16_t 6800 ror_word(struct X86EMU *emu, uint16_t d, uint8_t s) 6801 { 6802 unsigned int res, cnt, mask; 6803 6804 res = d; 6805 if ((cnt = s % 16) != 0) { 6806 res = (d << (16 - cnt)); 6807 mask = (1 << (16 - cnt)) - 1; 6808 res |= (d >> (cnt)) & mask; 6809 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF); 6810 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF); 6811 } else if (s != 0) { 6812 /* set the new carry flag, Note that it is the low order bit 6813 * of the result!!! */ 6814 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF); 6815 } 6816 return (uint16_t) res; 6817 } 6818 /**************************************************************************** 6819 REMARKS: 6820 Implements the ROR instruction and side effects. 6821 ****************************************************************************/ 6822 static uint32_t 6823 ror_long(struct X86EMU *emu, uint32_t d, uint8_t s) 6824 { 6825 uint32_t res, cnt, mask; 6826 6827 res = d; 6828 if ((cnt = s % 32) != 0) { 6829 res = (d << (32 - cnt)); 6830 mask = (1 << (32 - cnt)) - 1; 6831 res |= (d >> (cnt)) & mask; 6832 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF); 6833 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF); 6834 } else if (s != 0) { 6835 /* set the new carry flag, Note that it is the low order bit 6836 * of the result!!! */ 6837 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF); 6838 } 6839 return res; 6840 } 6841 /**************************************************************************** 6842 REMARKS: 6843 Implements the SHL instruction and side effects. 6844 ****************************************************************************/ 6845 static uint8_t 6846 shl_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6847 { 6848 unsigned int cnt, res, cf; 6849 6850 if (s < 8) { 6851 cnt = s % 8; 6852 6853 /* last bit shifted out goes into carry flag */ 6854 if (cnt > 0) { 6855 res = d << cnt; 6856 cf = d & (1 << (8 - cnt)); 6857 CONDITIONAL_SET_FLAG(cf, F_CF); 6858 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6859 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6860 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6861 } else { 6862 res = (uint8_t) d; 6863 } 6864 6865 if (cnt == 1) { 6866 /* Needs simplification. */ 6867 CONDITIONAL_SET_FLAG( 6868 (((res & 0x80) == 0x80) ^ 6869 (ACCESS_FLAG(F_CF) != 0)), 6870 /* was (emu->x86.R_FLG&F_CF)==F_CF)), */ 6871 F_OF); 6872 } else { 6873 CLEAR_FLAG(F_OF); 6874 } 6875 } else { 6876 res = 0; 6877 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF); 6878 CLEAR_FLAG(F_OF); 6879 CLEAR_FLAG(F_SF); 6880 SET_FLAG(F_PF); 6881 SET_FLAG(F_ZF); 6882 } 6883 return (uint8_t) res; 6884 } 6885 /**************************************************************************** 6886 REMARKS: 6887 Implements the SHL instruction and side effects. 6888 ****************************************************************************/ 6889 static uint16_t 6890 shl_word(struct X86EMU *emu, uint16_t d, uint8_t s) 6891 { 6892 unsigned int cnt, res, cf; 6893 6894 if (s < 16) { 6895 cnt = s % 16; 6896 if (cnt > 0) { 6897 res = d << cnt; 6898 cf = d & (1 << (16 - cnt)); 6899 CONDITIONAL_SET_FLAG(cf, F_CF); 6900 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6901 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6902 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6903 } else { 6904 res = (uint16_t) d; 6905 } 6906 6907 if (cnt == 1) { 6908 CONDITIONAL_SET_FLAG( 6909 (((res & 0x8000) == 0x8000) ^ 6910 (ACCESS_FLAG(F_CF) != 0)), 6911 F_OF); 6912 } else { 6913 CLEAR_FLAG(F_OF); 6914 } 6915 } else { 6916 res = 0; 6917 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF); 6918 CLEAR_FLAG(F_OF); 6919 CLEAR_FLAG(F_SF); 6920 SET_FLAG(F_PF); 6921 SET_FLAG(F_ZF); 6922 } 6923 return (uint16_t) res; 6924 } 6925 /**************************************************************************** 6926 REMARKS: 6927 Implements the SHL instruction and side effects. 6928 ****************************************************************************/ 6929 static uint32_t 6930 shl_long(struct X86EMU *emu, uint32_t d, uint8_t s) 6931 { 6932 unsigned int cnt, res, cf; 6933 6934 if (s < 32) { 6935 cnt = s % 32; 6936 if (cnt > 0) { 6937 res = d << cnt; 6938 cf = d & (1 << (32 - cnt)); 6939 CONDITIONAL_SET_FLAG(cf, F_CF); 6940 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6941 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6942 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6943 } else { 6944 res = d; 6945 } 6946 if (cnt == 1) { 6947 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^ 6948 (ACCESS_FLAG(F_CF) != 0)), F_OF); 6949 } else { 6950 CLEAR_FLAG(F_OF); 6951 } 6952 } else { 6953 res = 0; 6954 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF); 6955 CLEAR_FLAG(F_OF); 6956 CLEAR_FLAG(F_SF); 6957 SET_FLAG(F_PF); 6958 SET_FLAG(F_ZF); 6959 } 6960 return res; 6961 } 6962 /**************************************************************************** 6963 REMARKS: 6964 Implements the SHR instruction and side effects. 6965 ****************************************************************************/ 6966 static uint8_t 6967 shr_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6968 { 6969 unsigned int cnt, res, cf; 6970 6971 if (s < 8) { 6972 cnt = s % 8; 6973 if (cnt > 0) { 6974 cf = d & (1 << (cnt - 1)); 6975 res = d >> cnt; 6976 CONDITIONAL_SET_FLAG(cf, F_CF); 6977 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6978 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6979 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6980 } else { 6981 res = (uint8_t) d; 6982 } 6983 6984 if (cnt == 1) { 6985 CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF); 6986 } else { 6987 CLEAR_FLAG(F_OF); 6988 } 6989 } else { 6990 res = 0; 6991 CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF); 6992 CLEAR_FLAG(F_OF); 6993 CLEAR_FLAG(F_SF); 6994 SET_FLAG(F_PF); 6995 SET_FLAG(F_ZF); 6996 } 6997 return (uint8_t) res; 6998 } 6999 /**************************************************************************** 7000 REMARKS: 7001 Implements the SHR instruction and side effects. 7002 ****************************************************************************/ 7003 static uint16_t 7004 shr_word(struct X86EMU *emu, uint16_t d, uint8_t s) 7005 { 7006 unsigned int cnt, res, cf; 7007 7008 if (s < 16) { 7009 cnt = s % 16; 7010 if (cnt > 0) { 7011 cf = d & (1 << (cnt - 1)); 7012 res = d >> cnt; 7013 CONDITIONAL_SET_FLAG(cf, F_CF); 7014 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7015 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7016 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7017 } else { 7018 res = d; 7019 } 7020 7021 if (cnt == 1) { 7022 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF); 7023 } else { 7024 CLEAR_FLAG(F_OF); 7025 } 7026 } else { 7027 res = 0; 7028 CLEAR_FLAG(F_CF); 7029 CLEAR_FLAG(F_OF); 7030 SET_FLAG(F_ZF); 7031 CLEAR_FLAG(F_SF); 7032 CLEAR_FLAG(F_PF); 7033 } 7034 return (uint16_t) res; 7035 } 7036 /**************************************************************************** 7037 REMARKS: 7038 Implements the SHR instruction and side effects. 7039 ****************************************************************************/ 7040 static uint32_t 7041 shr_long(struct X86EMU *emu, uint32_t d, uint8_t s) 7042 { 7043 unsigned int cnt, res, cf; 7044 7045 if (s < 32) { 7046 cnt = s % 32; 7047 if (cnt > 0) { 7048 cf = d & (1 << (cnt - 1)); 7049 res = d >> cnt; 7050 CONDITIONAL_SET_FLAG(cf, F_CF); 7051 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7052 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7053 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7054 } else { 7055 res = d; 7056 } 7057 if (cnt == 1) { 7058 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF); 7059 } else { 7060 CLEAR_FLAG(F_OF); 7061 } 7062 } else { 7063 res = 0; 7064 CLEAR_FLAG(F_CF); 7065 CLEAR_FLAG(F_OF); 7066 SET_FLAG(F_ZF); 7067 CLEAR_FLAG(F_SF); 7068 CLEAR_FLAG(F_PF); 7069 } 7070 return res; 7071 } 7072 /**************************************************************************** 7073 REMARKS: 7074 Implements the SAR instruction and side effects. 7075 ****************************************************************************/ 7076 static uint8_t 7077 sar_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 7078 { 7079 unsigned int cnt, res, cf, mask, sf; 7080 7081 res = d; 7082 sf = d & 0x80; 7083 cnt = s % 8; 7084 if (cnt > 0 && cnt < 8) { 7085 mask = (1 << (8 - cnt)) - 1; 7086 cf = d & (1 << (cnt - 1)); 7087 res = (d >> cnt) & mask; 7088 CONDITIONAL_SET_FLAG(cf, F_CF); 7089 if (sf) { 7090 res |= ~mask; 7091 } 7092 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7093 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7094 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7095 } else if (cnt >= 8) { 7096 if (sf) { 7097 res = 0xff; 7098 SET_FLAG(F_CF); 7099 CLEAR_FLAG(F_ZF); 7100 SET_FLAG(F_SF); 7101 SET_FLAG(F_PF); 7102 } else { 7103 res = 0; 7104 CLEAR_FLAG(F_CF); 7105 SET_FLAG(F_ZF); 7106 CLEAR_FLAG(F_SF); 7107 CLEAR_FLAG(F_PF); 7108 } 7109 } 7110 return (uint8_t) res; 7111 } 7112 /**************************************************************************** 7113 REMARKS: 7114 Implements the SAR instruction and side effects. 7115 ****************************************************************************/ 7116 static uint16_t 7117 sar_word(struct X86EMU *emu, uint16_t d, uint8_t s) 7118 { 7119 unsigned int cnt, res, cf, mask, sf; 7120 7121 sf = d & 0x8000; 7122 cnt = s % 16; 7123 res = d; 7124 if (cnt > 0 && cnt < 16) { 7125 mask = (1 << (16 - cnt)) - 1; 7126 cf = d & (1 << (cnt - 1)); 7127 res = (d >> cnt) & mask; 7128 CONDITIONAL_SET_FLAG(cf, F_CF); 7129 if (sf) { 7130 res |= ~mask; 7131 } 7132 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7133 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7134 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7135 } else if (cnt >= 16) { 7136 if (sf) { 7137 res = 0xffff; 7138 SET_FLAG(F_CF); 7139 CLEAR_FLAG(F_ZF); 7140 SET_FLAG(F_SF); 7141 SET_FLAG(F_PF); 7142 } else { 7143 res = 0; 7144 CLEAR_FLAG(F_CF); 7145 SET_FLAG(F_ZF); 7146 CLEAR_FLAG(F_SF); 7147 CLEAR_FLAG(F_PF); 7148 } 7149 } 7150 return (uint16_t) res; 7151 } 7152 /**************************************************************************** 7153 REMARKS: 7154 Implements the SAR instruction and side effects. 7155 ****************************************************************************/ 7156 static uint32_t 7157 sar_long(struct X86EMU *emu, uint32_t d, uint8_t s) 7158 { 7159 uint32_t cnt, res, cf, mask, sf; 7160 7161 sf = d & 0x80000000; 7162 cnt = s % 32; 7163 res = d; 7164 if (cnt > 0 && cnt < 32) { 7165 mask = (1 << (32 - cnt)) - 1; 7166 cf = d & (1 << (cnt - 1)); 7167 res = (d >> cnt) & mask; 7168 CONDITIONAL_SET_FLAG(cf, F_CF); 7169 if (sf) { 7170 res |= ~mask; 7171 } 7172 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7173 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7174 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7175 } else if (cnt >= 32) { 7176 if (sf) { 7177 res = 0xffffffff; 7178 SET_FLAG(F_CF); 7179 CLEAR_FLAG(F_ZF); 7180 SET_FLAG(F_SF); 7181 SET_FLAG(F_PF); 7182 } else { 7183 res = 0; 7184 CLEAR_FLAG(F_CF); 7185 SET_FLAG(F_ZF); 7186 CLEAR_FLAG(F_SF); 7187 CLEAR_FLAG(F_PF); 7188 } 7189 } 7190 return res; 7191 } 7192 /**************************************************************************** 7193 REMARKS: 7194 Implements the SHLD instruction and side effects. 7195 ****************************************************************************/ 7196 static uint16_t 7197 shld_word(struct X86EMU *emu, uint16_t d, uint16_t fill, uint8_t s) 7198 { 7199 unsigned int cnt, res, cf; 7200 7201 if (s < 16) { 7202 cnt = s % 16; 7203 if (cnt > 0) { 7204 res = (d << cnt) | (fill >> (16 - cnt)); 7205 cf = d & (1 << (16 - cnt)); 7206 CONDITIONAL_SET_FLAG(cf, F_CF); 7207 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7208 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7209 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7210 } else { 7211 res = d; 7212 } 7213 if (cnt == 1) { 7214 CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^ 7215 (ACCESS_FLAG(F_CF) != 0)), F_OF); 7216 } else { 7217 CLEAR_FLAG(F_OF); 7218 } 7219 } else { 7220 res = 0; 7221 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF); 7222 CLEAR_FLAG(F_OF); 7223 CLEAR_FLAG(F_SF); 7224 SET_FLAG(F_PF); 7225 SET_FLAG(F_ZF); 7226 } 7227 return (uint16_t) res; 7228 } 7229 /**************************************************************************** 7230 REMARKS: 7231 Implements the SHLD instruction and side effects. 7232 ****************************************************************************/ 7233 static uint32_t 7234 shld_long(struct X86EMU *emu, uint32_t d, uint32_t fill, uint8_t s) 7235 { 7236 unsigned int cnt, res, cf; 7237 7238 if (s < 32) { 7239 cnt = s % 32; 7240 if (cnt > 0) { 7241 res = (d << cnt) | (fill >> (32 - cnt)); 7242 cf = d & (1 << (32 - cnt)); 7243 CONDITIONAL_SET_FLAG(cf, F_CF); 7244 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7245 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7246 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7247 } else { 7248 res = d; 7249 } 7250 if (cnt == 1) { 7251 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^ 7252 (ACCESS_FLAG(F_CF) != 0)), F_OF); 7253 } else { 7254 CLEAR_FLAG(F_OF); 7255 } 7256 } else { 7257 res = 0; 7258 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF); 7259 CLEAR_FLAG(F_OF); 7260 CLEAR_FLAG(F_SF); 7261 SET_FLAG(F_PF); 7262 SET_FLAG(F_ZF); 7263 } 7264 return res; 7265 } 7266 /**************************************************************************** 7267 REMARKS: 7268 Implements the SHRD instruction and side effects. 7269 ****************************************************************************/ 7270 static uint16_t 7271 shrd_word(struct X86EMU *emu, uint16_t d, uint16_t fill, uint8_t s) 7272 { 7273 unsigned int cnt, res, cf; 7274 7275 if (s < 16) { 7276 cnt = s % 16; 7277 if (cnt > 0) { 7278 cf = d & (1 << (cnt - 1)); 7279 res = (d >> cnt) | (fill << (16 - cnt)); 7280 CONDITIONAL_SET_FLAG(cf, F_CF); 7281 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7282 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7283 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7284 } else { 7285 res = d; 7286 } 7287 7288 if (cnt == 1) { 7289 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF); 7290 } else { 7291 CLEAR_FLAG(F_OF); 7292 } 7293 } else { 7294 res = 0; 7295 CLEAR_FLAG(F_CF); 7296 CLEAR_FLAG(F_OF); 7297 SET_FLAG(F_ZF); 7298 CLEAR_FLAG(F_SF); 7299 CLEAR_FLAG(F_PF); 7300 } 7301 return (uint16_t) res; 7302 } 7303 /**************************************************************************** 7304 REMARKS: 7305 Implements the SHRD instruction and side effects. 7306 ****************************************************************************/ 7307 static uint32_t 7308 shrd_long(struct X86EMU *emu, uint32_t d, uint32_t fill, uint8_t s) 7309 { 7310 unsigned int cnt, res, cf; 7311 7312 if (s < 32) { 7313 cnt = s % 32; 7314 if (cnt > 0) { 7315 cf = d & (1 << (cnt - 1)); 7316 res = (d >> cnt) | (fill << (32 - cnt)); 7317 CONDITIONAL_SET_FLAG(cf, F_CF); 7318 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7319 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7320 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7321 } else { 7322 res = d; 7323 } 7324 if (cnt == 1) { 7325 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF); 7326 } else { 7327 CLEAR_FLAG(F_OF); 7328 } 7329 } else { 7330 res = 0; 7331 CLEAR_FLAG(F_CF); 7332 CLEAR_FLAG(F_OF); 7333 SET_FLAG(F_ZF); 7334 CLEAR_FLAG(F_SF); 7335 CLEAR_FLAG(F_PF); 7336 } 7337 return res; 7338 } 7339 /**************************************************************************** 7340 REMARKS: 7341 Implements the SBB instruction and side effects. 7342 ****************************************************************************/ 7343 static uint8_t 7344 sbb_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 7345 { 7346 uint32_t res; /* all operands in native machine order */ 7347 uint32_t bc; 7348 7349 if (ACCESS_FLAG(F_CF)) 7350 res = d - s - 1; 7351 else 7352 res = d - s; 7353 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7354 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7355 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7356 7357 /* calculate the borrow chain. See note at top */ 7358 bc = (res & (~d | s)) | (~d & s); 7359 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); 7360 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 7361 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7362 return (uint8_t) res; 7363 } 7364 /**************************************************************************** 7365 REMARKS: 7366 Implements the SBB instruction and side effects. 7367 ****************************************************************************/ 7368 static uint16_t 7369 sbb_word(struct X86EMU *emu, uint16_t d, uint16_t s) 7370 { 7371 uint32_t res; /* all operands in native machine order */ 7372 uint32_t bc; 7373 7374 if (ACCESS_FLAG(F_CF)) 7375 res = d - s - 1; 7376 else 7377 res = d - s; 7378 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7379 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7380 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7381 7382 /* calculate the borrow chain. See note at top */ 7383 bc = (res & (~d | s)) | (~d & s); 7384 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 7385 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 7386 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7387 return (uint16_t) res; 7388 } 7389 /**************************************************************************** 7390 REMARKS: 7391 Implements the SBB instruction and side effects. 7392 ****************************************************************************/ 7393 static uint32_t 7394 sbb_long(struct X86EMU *emu, uint32_t d, uint32_t s) 7395 { 7396 uint32_t res; /* all operands in native machine order */ 7397 uint32_t bc; 7398 7399 if (ACCESS_FLAG(F_CF)) 7400 res = d - s - 1; 7401 else 7402 res = d - s; 7403 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7404 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7405 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7406 7407 /* calculate the borrow chain. See note at top */ 7408 bc = (res & (~d | s)) | (~d & s); 7409 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 7410 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 7411 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7412 return res; 7413 } 7414 /**************************************************************************** 7415 REMARKS: 7416 Implements the SUB instruction and side effects. 7417 ****************************************************************************/ 7418 static uint8_t 7419 sub_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 7420 { 7421 uint32_t res; /* all operands in native machine order */ 7422 uint32_t bc; 7423 7424 res = d - s; 7425 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7426 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7427 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7428 7429 /* calculate the borrow chain. See note at top */ 7430 bc = (res & (~d | s)) | (~d & s); 7431 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); 7432 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 7433 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7434 return (uint8_t) res; 7435 } 7436 /**************************************************************************** 7437 REMARKS: 7438 Implements the SUB instruction and side effects. 7439 ****************************************************************************/ 7440 static uint16_t 7441 sub_word(struct X86EMU *emu, uint16_t d, uint16_t s) 7442 { 7443 uint32_t res; /* all operands in native machine order */ 7444 uint32_t bc; 7445 7446 res = d - s; 7447 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7448 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7449 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7450 7451 /* calculate the borrow chain. See note at top */ 7452 bc = (res & (~d | s)) | (~d & s); 7453 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 7454 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 7455 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7456 return (uint16_t) res; 7457 } 7458 /**************************************************************************** 7459 REMARKS: 7460 Implements the SUB instruction and side effects. 7461 ****************************************************************************/ 7462 static uint32_t 7463 sub_long(struct X86EMU *emu, uint32_t d, uint32_t s) 7464 { 7465 uint32_t res; /* all operands in native machine order */ 7466 uint32_t bc; 7467 7468 res = d - s; 7469 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7470 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7471 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7472 7473 /* calculate the borrow chain. See note at top */ 7474 bc = (res & (~d | s)) | (~d & s); 7475 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 7476 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 7477 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7478 return res; 7479 } 7480 /**************************************************************************** 7481 REMARKS: 7482 Implements the TEST instruction and side effects. 7483 ****************************************************************************/ 7484 static void 7485 test_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 7486 { 7487 uint32_t res; /* all operands in native machine order */ 7488 7489 res = d & s; 7490 7491 CLEAR_FLAG(F_OF); 7492 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7493 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7494 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7495 /* AF == dont care */ 7496 CLEAR_FLAG(F_CF); 7497 } 7498 /**************************************************************************** 7499 REMARKS: 7500 Implements the TEST instruction and side effects. 7501 ****************************************************************************/ 7502 static void 7503 test_word(struct X86EMU *emu, uint16_t d, uint16_t s) 7504 { 7505 uint32_t res; /* all operands in native machine order */ 7506 7507 res = d & s; 7508 7509 CLEAR_FLAG(F_OF); 7510 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7511 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7512 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7513 /* AF == dont care */ 7514 CLEAR_FLAG(F_CF); 7515 } 7516 /**************************************************************************** 7517 REMARKS: 7518 Implements the TEST instruction and side effects. 7519 ****************************************************************************/ 7520 static void 7521 test_long(struct X86EMU *emu, uint32_t d, uint32_t s) 7522 { 7523 uint32_t res; /* all operands in native machine order */ 7524 7525 res = d & s; 7526 7527 CLEAR_FLAG(F_OF); 7528 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7529 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7530 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7531 /* AF == dont care */ 7532 CLEAR_FLAG(F_CF); 7533 } 7534 /**************************************************************************** 7535 REMARKS: 7536 Implements the XOR instruction and side effects. 7537 ****************************************************************************/ 7538 static uint8_t 7539 xor_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 7540 { 7541 uint8_t res; /* all operands in native machine order */ 7542 7543 res = d ^ s; 7544 CLEAR_FLAG(F_OF); 7545 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7546 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7547 CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 7548 CLEAR_FLAG(F_CF); 7549 CLEAR_FLAG(F_AF); 7550 return res; 7551 } 7552 /**************************************************************************** 7553 REMARKS: 7554 Implements the XOR instruction and side effects. 7555 ****************************************************************************/ 7556 static uint16_t 7557 xor_word(struct X86EMU *emu, uint16_t d, uint16_t s) 7558 { 7559 uint16_t res; /* all operands in native machine order */ 7560 7561 res = d ^ s; 7562 CLEAR_FLAG(F_OF); 7563 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7564 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7565 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7566 CLEAR_FLAG(F_CF); 7567 CLEAR_FLAG(F_AF); 7568 return res; 7569 } 7570 /**************************************************************************** 7571 REMARKS: 7572 Implements the XOR instruction and side effects. 7573 ****************************************************************************/ 7574 static uint32_t 7575 xor_long(struct X86EMU *emu, uint32_t d, uint32_t s) 7576 { 7577 uint32_t res; /* all operands in native machine order */ 7578 7579 res = d ^ s; 7580 CLEAR_FLAG(F_OF); 7581 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7582 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7583 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7584 CLEAR_FLAG(F_CF); 7585 CLEAR_FLAG(F_AF); 7586 return res; 7587 } 7588 /**************************************************************************** 7589 REMARKS: 7590 Implements the IMUL instruction and side effects. 7591 ****************************************************************************/ 7592 static void 7593 imul_byte(struct X86EMU *emu, uint8_t s) 7594 { 7595 int16_t res = (int16_t) ((int8_t) emu->x86.R_AL * (int8_t) s); 7596 7597 emu->x86.R_AX = res; 7598 if (((emu->x86.R_AL & 0x80) == 0 && emu->x86.R_AH == 0x00) || 7599 ((emu->x86.R_AL & 0x80) != 0 && emu->x86.R_AH == 0xFF)) { 7600 CLEAR_FLAG(F_CF); 7601 CLEAR_FLAG(F_OF); 7602 } else { 7603 SET_FLAG(F_CF); 7604 SET_FLAG(F_OF); 7605 } 7606 } 7607 /**************************************************************************** 7608 REMARKS: 7609 Implements the IMUL instruction and side effects. 7610 ****************************************************************************/ 7611 static void 7612 imul_word(struct X86EMU *emu, uint16_t s) 7613 { 7614 int32_t res = (int16_t) emu->x86.R_AX * (int16_t) s; 7615 7616 emu->x86.R_AX = (uint16_t) res; 7617 emu->x86.R_DX = (uint16_t) (res >> 16); 7618 if (((emu->x86.R_AX & 0x8000) == 0 && emu->x86.R_DX == 0x00) || 7619 ((emu->x86.R_AX & 0x8000) != 0 && emu->x86.R_DX == 0xFF)) { 7620 CLEAR_FLAG(F_CF); 7621 CLEAR_FLAG(F_OF); 7622 } else { 7623 SET_FLAG(F_CF); 7624 SET_FLAG(F_OF); 7625 } 7626 } 7627 /**************************************************************************** 7628 REMARKS: 7629 Implements the IMUL instruction and side effects. 7630 ****************************************************************************/ 7631 static void 7632 imul_long(struct X86EMU *emu, uint32_t s) 7633 { 7634 int64_t res; 7635 7636 res = (int64_t)(int32_t)emu->x86.R_EAX * (int32_t)s; 7637 emu->x86.R_EAX = (uint32_t)res; 7638 emu->x86.R_EDX = ((uint64_t)res) >> 32; 7639 if (((emu->x86.R_EAX & 0x80000000) == 0 && emu->x86.R_EDX == 0x00) || 7640 ((emu->x86.R_EAX & 0x80000000) != 0 && emu->x86.R_EDX == 0xFF)) { 7641 CLEAR_FLAG(F_CF); 7642 CLEAR_FLAG(F_OF); 7643 } else { 7644 SET_FLAG(F_CF); 7645 SET_FLAG(F_OF); 7646 } 7647 } 7648 /**************************************************************************** 7649 REMARKS: 7650 Implements the MUL instruction and side effects. 7651 ****************************************************************************/ 7652 static void 7653 mul_byte(struct X86EMU *emu, uint8_t s) 7654 { 7655 uint16_t res = (uint16_t) (emu->x86.R_AL * s); 7656 7657 emu->x86.R_AX = res; 7658 if (emu->x86.R_AH == 0) { 7659 CLEAR_FLAG(F_CF); 7660 CLEAR_FLAG(F_OF); 7661 } else { 7662 SET_FLAG(F_CF); 7663 SET_FLAG(F_OF); 7664 } 7665 } 7666 /**************************************************************************** 7667 REMARKS: 7668 Implements the MUL instruction and side effects. 7669 ****************************************************************************/ 7670 static void 7671 mul_word(struct X86EMU *emu, uint16_t s) 7672 { 7673 uint32_t res = emu->x86.R_AX * s; 7674 7675 emu->x86.R_AX = (uint16_t) res; 7676 emu->x86.R_DX = (uint16_t) (res >> 16); 7677 if (emu->x86.R_DX == 0) { 7678 CLEAR_FLAG(F_CF); 7679 CLEAR_FLAG(F_OF); 7680 } else { 7681 SET_FLAG(F_CF); 7682 SET_FLAG(F_OF); 7683 } 7684 } 7685 /**************************************************************************** 7686 REMARKS: 7687 Implements the MUL instruction and side effects. 7688 ****************************************************************************/ 7689 static void 7690 mul_long(struct X86EMU *emu, uint32_t s) 7691 { 7692 uint64_t res = (uint64_t) emu->x86.R_EAX * s; 7693 7694 emu->x86.R_EAX = (uint32_t) res; 7695 emu->x86.R_EDX = (uint32_t) (res >> 32); 7696 7697 if (emu->x86.R_EDX == 0) { 7698 CLEAR_FLAG(F_CF); 7699 CLEAR_FLAG(F_OF); 7700 } else { 7701 SET_FLAG(F_CF); 7702 SET_FLAG(F_OF); 7703 } 7704 } 7705 /**************************************************************************** 7706 REMARKS: 7707 Implements the IDIV instruction and side effects. 7708 ****************************************************************************/ 7709 static void 7710 idiv_byte(struct X86EMU *emu, uint8_t s) 7711 { 7712 int32_t dvd, div, mod; 7713 7714 dvd = (int16_t) emu->x86.R_AX; 7715 if (s == 0) { 7716 x86emu_intr_raise(emu, 0); 7717 return; 7718 } 7719 div = dvd / (int8_t) s; 7720 mod = dvd % (int8_t) s; 7721 if (div > 0x7f || div < -0x7f) { 7722 x86emu_intr_raise(emu, 0); 7723 return; 7724 } 7725 emu->x86.R_AL = (int8_t) div; 7726 emu->x86.R_AH = (int8_t) mod; 7727 } 7728 /**************************************************************************** 7729 REMARKS: 7730 Implements the IDIV instruction and side effects. 7731 ****************************************************************************/ 7732 static void 7733 idiv_word(struct X86EMU *emu, uint16_t s) 7734 { 7735 int32_t dvd, div, mod; 7736 7737 dvd = (((int32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX; 7738 if (s == 0) { 7739 x86emu_intr_raise(emu, 0); 7740 return; 7741 } 7742 div = dvd / (int16_t) s; 7743 mod = dvd % (int16_t) s; 7744 if (div > 0x7fff || div < -0x7fff) { 7745 x86emu_intr_raise(emu, 0); 7746 return; 7747 } 7748 CLEAR_FLAG(F_CF); 7749 CLEAR_FLAG(F_SF); 7750 CONDITIONAL_SET_FLAG(div == 0, F_ZF); 7751 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 7752 7753 emu->x86.R_AX = (uint16_t) div; 7754 emu->x86.R_DX = (uint16_t) mod; 7755 } 7756 /**************************************************************************** 7757 REMARKS: 7758 Implements the IDIV instruction and side effects. 7759 ****************************************************************************/ 7760 static void 7761 idiv_long(struct X86EMU *emu, uint32_t s) 7762 { 7763 int64_t dvd, div, mod; 7764 7765 dvd = (((int64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX; 7766 if (s == 0) { 7767 x86emu_intr_raise(emu, 0); 7768 return; 7769 } 7770 div = dvd / (int32_t) s; 7771 mod = dvd % (int32_t) s; 7772 if (div > 0x7fffffff || div < -0x7fffffff) { 7773 x86emu_intr_raise(emu, 0); 7774 return; 7775 } 7776 CLEAR_FLAG(F_CF); 7777 CLEAR_FLAG(F_AF); 7778 CLEAR_FLAG(F_SF); 7779 SET_FLAG(F_ZF); 7780 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 7781 7782 emu->x86.R_EAX = (uint32_t) div; 7783 emu->x86.R_EDX = (uint32_t) mod; 7784 } 7785 /**************************************************************************** 7786 REMARKS: 7787 Implements the DIV instruction and side effects. 7788 ****************************************************************************/ 7789 static void 7790 div_byte(struct X86EMU *emu, uint8_t s) 7791 { 7792 uint32_t dvd, div, mod; 7793 7794 dvd = emu->x86.R_AX; 7795 if (s == 0) { 7796 x86emu_intr_raise(emu, 0); 7797 return; 7798 } 7799 div = dvd / (uint8_t) s; 7800 mod = dvd % (uint8_t) s; 7801 if (div > 0xff) { 7802 x86emu_intr_raise(emu, 0); 7803 return; 7804 } 7805 emu->x86.R_AL = (uint8_t) div; 7806 emu->x86.R_AH = (uint8_t) mod; 7807 } 7808 /**************************************************************************** 7809 REMARKS: 7810 Implements the DIV instruction and side effects. 7811 ****************************************************************************/ 7812 static void 7813 div_word(struct X86EMU *emu, uint16_t s) 7814 { 7815 uint32_t dvd, div, mod; 7816 7817 dvd = (((uint32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX; 7818 if (s == 0) { 7819 x86emu_intr_raise(emu, 0); 7820 return; 7821 } 7822 div = dvd / (uint16_t) s; 7823 mod = dvd % (uint16_t) s; 7824 if (div > 0xffff) { 7825 x86emu_intr_raise(emu, 0); 7826 return; 7827 } 7828 CLEAR_FLAG(F_CF); 7829 CLEAR_FLAG(F_SF); 7830 CONDITIONAL_SET_FLAG(div == 0, F_ZF); 7831 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 7832 7833 emu->x86.R_AX = (uint16_t) div; 7834 emu->x86.R_DX = (uint16_t) mod; 7835 } 7836 /**************************************************************************** 7837 REMARKS: 7838 Implements the DIV instruction and side effects. 7839 ****************************************************************************/ 7840 static void 7841 div_long(struct X86EMU *emu, uint32_t s) 7842 { 7843 uint64_t dvd, div, mod; 7844 7845 dvd = (((uint64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX; 7846 if (s == 0) { 7847 x86emu_intr_raise(emu, 0); 7848 return; 7849 } 7850 div = dvd / (uint32_t) s; 7851 mod = dvd % (uint32_t) s; 7852 if (div > 0xffffffff) { 7853 x86emu_intr_raise(emu, 0); 7854 return; 7855 } 7856 CLEAR_FLAG(F_CF); 7857 CLEAR_FLAG(F_AF); 7858 CLEAR_FLAG(F_SF); 7859 SET_FLAG(F_ZF); 7860 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 7861 7862 emu->x86.R_EAX = (uint32_t) div; 7863 emu->x86.R_EDX = (uint32_t) mod; 7864 } 7865 /**************************************************************************** 7866 REMARKS: 7867 Implements the IN string instruction and side effects. 7868 ****************************************************************************/ 7869 static void 7870 ins(struct X86EMU *emu, int size) 7871 { 7872 int inc = size; 7873 7874 if (ACCESS_FLAG(F_DF)) { 7875 inc = -size; 7876 } 7877 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 7878 /* dont care whether REPE or REPNE */ 7879 /* in until CX is ZERO. */ 7880 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ? 7881 emu->x86.R_ECX : emu->x86.R_CX); 7882 switch (size) { 7883 case 1: 7884 while (count--) { 7885 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, 7886 (*emu->emu_inb) (emu, emu->x86.R_DX)); 7887 emu->x86.R_DI += inc; 7888 } 7889 break; 7890 7891 case 2: 7892 while (count--) { 7893 store_word(emu, emu->x86.R_ES, emu->x86.R_DI, 7894 (*emu->emu_inw) (emu, emu->x86.R_DX)); 7895 emu->x86.R_DI += inc; 7896 } 7897 break; 7898 case 4: 7899 while (count--) { 7900 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, 7901 (*emu->emu_inl) (emu, emu->x86.R_DX)); 7902 emu->x86.R_DI += inc; 7903 break; 7904 } 7905 } 7906 emu->x86.R_CX = 0; 7907 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 7908 emu->x86.R_ECX = 0; 7909 } 7910 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 7911 } else { 7912 switch (size) { 7913 case 1: 7914 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, 7915 (*emu->emu_inb) (emu, emu->x86.R_DX)); 7916 break; 7917 case 2: 7918 store_word(emu, emu->x86.R_ES, emu->x86.R_DI, 7919 (*emu->emu_inw) (emu, emu->x86.R_DX)); 7920 break; 7921 case 4: 7922 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, 7923 (*emu->emu_inl) (emu, emu->x86.R_DX)); 7924 break; 7925 } 7926 emu->x86.R_DI += inc; 7927 } 7928 } 7929 /**************************************************************************** 7930 REMARKS: 7931 Implements the OUT string instruction and side effects. 7932 ****************************************************************************/ 7933 static void 7934 outs(struct X86EMU *emu, int size) 7935 { 7936 int inc = size; 7937 7938 if (ACCESS_FLAG(F_DF)) { 7939 inc = -size; 7940 } 7941 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 7942 /* dont care whether REPE or REPNE */ 7943 /* out until CX is ZERO. */ 7944 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ? 7945 emu->x86.R_ECX : emu->x86.R_CX); 7946 switch (size) { 7947 case 1: 7948 while (count--) { 7949 (*emu->emu_outb) (emu, emu->x86.R_DX, 7950 fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI)); 7951 emu->x86.R_SI += inc; 7952 } 7953 break; 7954 7955 case 2: 7956 while (count--) { 7957 (*emu->emu_outw) (emu, emu->x86.R_DX, 7958 fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI)); 7959 emu->x86.R_SI += inc; 7960 } 7961 break; 7962 case 4: 7963 while (count--) { 7964 (*emu->emu_outl) (emu, emu->x86.R_DX, 7965 fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI)); 7966 emu->x86.R_SI += inc; 7967 break; 7968 } 7969 } 7970 emu->x86.R_CX = 0; 7971 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 7972 emu->x86.R_ECX = 0; 7973 } 7974 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 7975 } else { 7976 switch (size) { 7977 case 1: 7978 (*emu->emu_outb) (emu, emu->x86.R_DX, 7979 fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI)); 7980 break; 7981 case 2: 7982 (*emu->emu_outw) (emu, emu->x86.R_DX, 7983 fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI)); 7984 break; 7985 case 4: 7986 (*emu->emu_outl) (emu, emu->x86.R_DX, 7987 fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI)); 7988 break; 7989 } 7990 emu->x86.R_SI += inc; 7991 } 7992 } 7993 /**************************************************************************** 7994 REMARKS: 7995 Pushes a word onto the stack. 7996 7997 NOTE: Do not inline this, as (*emu->emu_wrX) is already inline! 7998 ****************************************************************************/ 7999 static void 8000 push_word(struct X86EMU *emu, uint16_t w) 8001 { 8002 emu->x86.R_SP -= 2; 8003 store_word(emu, emu->x86.R_SS, emu->x86.R_SP, w); 8004 } 8005 /**************************************************************************** 8006 REMARKS: 8007 Pushes a long onto the stack. 8008 8009 NOTE: Do not inline this, as (*emu->emu_wrX) is already inline! 8010 ****************************************************************************/ 8011 static void 8012 push_long(struct X86EMU *emu, uint32_t w) 8013 { 8014 emu->x86.R_SP -= 4; 8015 store_long(emu, emu->x86.R_SS, emu->x86.R_SP, w); 8016 } 8017 /**************************************************************************** 8018 REMARKS: 8019 Pops a word from the stack. 8020 8021 NOTE: Do not inline this, as (*emu->emu_rdX) is already inline! 8022 ****************************************************************************/ 8023 static uint16_t 8024 pop_word(struct X86EMU *emu) 8025 { 8026 uint16_t res; 8027 8028 res = fetch_word(emu, emu->x86.R_SS, emu->x86.R_SP); 8029 emu->x86.R_SP += 2; 8030 return res; 8031 } 8032 /**************************************************************************** 8033 REMARKS: 8034 Pops a long from the stack. 8035 8036 NOTE: Do not inline this, as (*emu->emu_rdX) is already inline! 8037 ****************************************************************************/ 8038 static uint32_t 8039 pop_long(struct X86EMU *emu) 8040 { 8041 uint32_t res; 8042 8043 res = fetch_long(emu, emu->x86.R_SS, emu->x86.R_SP); 8044 emu->x86.R_SP += 4; 8045 return res; 8046 } 8047