1 /* $NetBSD: x86emu.c,v 1.5 2008/10/27 00:20:22 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,0xa1 5061 ****************************************************************************/ 5062 #if defined(__i386__) || defined(__amd64__) 5063 static void 5064 hw_cpuid(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) 5065 { 5066 __asm__ __volatile__("cpuid" 5067 : "=a" (*a), "=b" (*b), 5068 "=c" (*c), "=d" (*d) 5069 : "a" (*a), "c" (*c) 5070 : "cc"); 5071 } 5072 #endif 5073 static void 5074 x86emuOp2_cpuid(struct X86EMU *emu) 5075 { 5076 #if defined(__i386__) || defined(__amd64__) 5077 hw_cpuid(&emu->x86.R_EAX, &emu->x86.R_EBX, &emu->x86.R_ECX, 5078 &emu->x86.R_EDX); 5079 #endif 5080 switch (emu->x86.R_EAX) { 5081 case 0: 5082 emu->x86.R_EAX = 1; 5083 #if !defined(__i386__) && !defined(__amd64__) 5084 /* "GenuineIntel" */ 5085 emu->x86.R_EBX = 0x756e6547; 5086 emu->x86.R_EDX = 0x49656e69; 5087 emu->x86.R_ECX = 0x6c65746e; 5088 #endif 5089 break; 5090 case 1: 5091 #if !defined(__i386__) && !defined(__amd64__) 5092 emu->x86.R_EAX = 0x00000480; 5093 emu->x86.R_EBX = emu->x86.R_ECX = 0; 5094 emu->x86.R_EDX = 0x00000002; 5095 #else 5096 emu->x86.R_EDX &= 0x00000012; 5097 #endif 5098 break; 5099 default: 5100 emu->x86.R_EAX = emu->x86.R_EBX = emu->x86.R_ECX = 5101 emu->x86.R_EDX = 0; 5102 break; 5103 } 5104 } 5105 /**************************************************************************** 5106 REMARKS: 5107 Handles opcode 0x0f,0xa3 5108 ****************************************************************************/ 5109 static void 5110 x86emuOp2_bt_R(struct X86EMU *emu) 5111 { 5112 common_bitstring(emu, 0); 5113 } 5114 /**************************************************************************** 5115 REMARKS: 5116 Handles opcode 0x0f,0xa4 5117 ****************************************************************************/ 5118 static void 5119 x86emuOp2_shld_IMM(struct X86EMU *emu) 5120 { 5121 common_shift(emu, true, false); 5122 } 5123 /**************************************************************************** 5124 REMARKS: 5125 Handles opcode 0x0f,0xa5 5126 ****************************************************************************/ 5127 static void 5128 x86emuOp2_shld_CL(struct X86EMU *emu) 5129 { 5130 common_shift(emu, true, true); 5131 } 5132 /**************************************************************************** 5133 REMARKS: 5134 Handles opcode 0x0f,0xa8 5135 ****************************************************************************/ 5136 static void 5137 x86emuOp2_push_GS(struct X86EMU *emu) 5138 { 5139 push_word(emu, emu->x86.R_GS); 5140 } 5141 /**************************************************************************** 5142 REMARKS: 5143 Handles opcode 0x0f,0xa9 5144 ****************************************************************************/ 5145 static void 5146 x86emuOp2_pop_GS(struct X86EMU *emu) 5147 { 5148 emu->x86.R_GS = pop_word(emu); 5149 } 5150 /**************************************************************************** 5151 REMARKS: 5152 Handles opcode 0x0f,0xab 5153 ****************************************************************************/ 5154 static void 5155 x86emuOp2_bts_R(struct X86EMU *emu) 5156 { 5157 common_bitstring(emu, 1); 5158 } 5159 /**************************************************************************** 5160 REMARKS: 5161 Handles opcode 0x0f,0xac 5162 ****************************************************************************/ 5163 static void 5164 x86emuOp2_shrd_IMM(struct X86EMU *emu) 5165 { 5166 common_shift(emu, false, false); 5167 } 5168 /**************************************************************************** 5169 REMARKS: 5170 Handles opcode 0x0f,0xad 5171 ****************************************************************************/ 5172 static void 5173 x86emuOp2_shrd_CL(struct X86EMU *emu) 5174 { 5175 common_shift(emu, false, true); 5176 } 5177 /**************************************************************************** 5178 REMARKS: 5179 Handles opcode 0x0f,0xaf 5180 ****************************************************************************/ 5181 static void 5182 x86emuOp2_32_imul_R_RM(struct X86EMU *emu) 5183 { 5184 uint32_t *destreg, srcval; 5185 uint64_t res; 5186 5187 fetch_decode_modrm(emu); 5188 destreg = decode_rh_long_register(emu); 5189 srcval = decode_and_fetch_long(emu); 5190 res = (int32_t) *destreg * (int32_t)srcval; 5191 if (res > 0xffffffff) { 5192 SET_FLAG(F_CF); 5193 SET_FLAG(F_OF); 5194 } else { 5195 CLEAR_FLAG(F_CF); 5196 CLEAR_FLAG(F_OF); 5197 } 5198 *destreg = (uint32_t) res; 5199 } 5200 5201 static void 5202 x86emuOp2_16_imul_R_RM(struct X86EMU *emu) 5203 { 5204 uint16_t *destreg, srcval; 5205 uint32_t res; 5206 5207 fetch_decode_modrm(emu); 5208 destreg = decode_rh_word_register(emu); 5209 srcval = decode_and_fetch_word(emu); 5210 res = (int16_t) * destreg * (int16_t)srcval; 5211 if (res > 0xFFFF) { 5212 SET_FLAG(F_CF); 5213 SET_FLAG(F_OF); 5214 } else { 5215 CLEAR_FLAG(F_CF); 5216 CLEAR_FLAG(F_OF); 5217 } 5218 *destreg = (uint16_t) res; 5219 } 5220 5221 static void 5222 x86emuOp2_imul_R_RM(struct X86EMU *emu) 5223 { 5224 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5225 x86emuOp2_32_imul_R_RM(emu); 5226 else 5227 x86emuOp2_16_imul_R_RM(emu); 5228 } 5229 /**************************************************************************** 5230 REMARKS: 5231 Handles opcode 0x0f,0xb2 5232 ****************************************************************************/ 5233 static void 5234 x86emuOp2_lss_R_IMM(struct X86EMU *emu) 5235 { 5236 common_load_far_pointer(emu, &emu->x86.R_SS); 5237 } 5238 /**************************************************************************** 5239 REMARKS: 5240 Handles opcode 0x0f,0xb3 5241 ****************************************************************************/ 5242 static void 5243 x86emuOp2_btr_R(struct X86EMU *emu) 5244 { 5245 common_bitstring(emu, 2); 5246 } 5247 /**************************************************************************** 5248 REMARKS: 5249 Handles opcode 0x0f,0xb4 5250 ****************************************************************************/ 5251 static void 5252 x86emuOp2_lfs_R_IMM(struct X86EMU *emu) 5253 { 5254 common_load_far_pointer(emu, &emu->x86.R_FS); 5255 } 5256 /**************************************************************************** 5257 REMARKS: 5258 Handles opcode 0x0f,0xb5 5259 ****************************************************************************/ 5260 static void 5261 x86emuOp2_lgs_R_IMM(struct X86EMU *emu) 5262 { 5263 common_load_far_pointer(emu, &emu->x86.R_GS); 5264 } 5265 /**************************************************************************** 5266 REMARKS: 5267 Handles opcode 0x0f,0xb6 5268 ****************************************************************************/ 5269 static void 5270 x86emuOp2_32_movzx_byte_R_RM(struct X86EMU *emu) 5271 { 5272 uint32_t *destreg; 5273 5274 fetch_decode_modrm(emu); 5275 destreg = decode_rh_long_register(emu); 5276 *destreg = decode_and_fetch_byte(emu); 5277 } 5278 5279 static void 5280 x86emuOp2_16_movzx_byte_R_RM(struct X86EMU *emu) 5281 { 5282 uint16_t *destreg; 5283 5284 fetch_decode_modrm(emu); 5285 destreg = decode_rh_word_register(emu); 5286 *destreg = decode_and_fetch_byte(emu); 5287 } 5288 5289 static void 5290 x86emuOp2_movzx_byte_R_RM(struct X86EMU *emu) 5291 { 5292 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5293 x86emuOp2_32_movzx_byte_R_RM(emu); 5294 else 5295 x86emuOp2_16_movzx_byte_R_RM(emu); 5296 } 5297 /**************************************************************************** 5298 REMARKS: 5299 Handles opcode 0x0f,0xb7 5300 ****************************************************************************/ 5301 static void 5302 x86emuOp2_movzx_word_R_RM(struct X86EMU *emu) 5303 { 5304 uint32_t *destreg; 5305 5306 fetch_decode_modrm(emu); 5307 destreg = decode_rh_long_register(emu); 5308 *destreg = decode_and_fetch_word(emu); 5309 } 5310 /**************************************************************************** 5311 REMARKS: 5312 Handles opcode 0x0f,0xba 5313 ****************************************************************************/ 5314 static void 5315 x86emuOp2_32_btX_I(struct X86EMU *emu) 5316 { 5317 int bit; 5318 uint32_t srcval, mask; 5319 uint8_t shift; 5320 5321 fetch_decode_modrm(emu); 5322 if (emu->cur_rh < 4) 5323 X86EMU_halt_sys(emu); 5324 5325 srcval = decode_and_fetch_long_imm8(emu, &shift); 5326 bit = shift & 0x1F; 5327 mask = (0x1 << bit); 5328 5329 switch (emu->cur_rh) { 5330 case 5: 5331 write_back_long(emu, srcval | mask); 5332 break; 5333 case 6: 5334 write_back_long(emu, srcval & ~mask); 5335 break; 5336 case 7: 5337 write_back_long(emu, srcval ^ mask); 5338 break; 5339 } 5340 CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 5341 } 5342 5343 static void 5344 x86emuOp2_16_btX_I(struct X86EMU *emu) 5345 { 5346 int bit; 5347 5348 uint16_t srcval, mask; 5349 uint8_t shift; 5350 5351 fetch_decode_modrm(emu); 5352 if (emu->cur_rh < 4) 5353 X86EMU_halt_sys(emu); 5354 5355 srcval = decode_and_fetch_word_imm8(emu, &shift); 5356 bit = shift & 0xF; 5357 mask = (0x1 << bit); 5358 switch (emu->cur_rh) { 5359 case 5: 5360 write_back_word(emu, srcval | mask); 5361 break; 5362 case 6: 5363 write_back_word(emu, srcval & ~mask); 5364 break; 5365 case 7: 5366 write_back_word(emu, srcval ^ mask); 5367 break; 5368 } 5369 CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 5370 } 5371 5372 static void 5373 x86emuOp2_btX_I(struct X86EMU *emu) 5374 { 5375 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5376 x86emuOp2_32_btX_I(emu); 5377 else 5378 x86emuOp2_16_btX_I(emu); 5379 } 5380 /**************************************************************************** 5381 REMARKS: 5382 Handles opcode 0x0f,0xbb 5383 ****************************************************************************/ 5384 static void 5385 x86emuOp2_btc_R(struct X86EMU *emu) 5386 { 5387 common_bitstring(emu, 3); 5388 } 5389 /**************************************************************************** 5390 REMARKS: 5391 Handles opcode 0x0f,0xbc 5392 ****************************************************************************/ 5393 static void 5394 x86emuOp2_bsf(struct X86EMU *emu) 5395 { 5396 common_bitsearch(emu, +1); 5397 } 5398 /**************************************************************************** 5399 REMARKS: 5400 Handles opcode 0x0f,0xbd 5401 ****************************************************************************/ 5402 static void 5403 x86emuOp2_bsr(struct X86EMU *emu) 5404 { 5405 common_bitsearch(emu, -1); 5406 } 5407 /**************************************************************************** 5408 REMARKS: 5409 Handles opcode 0x0f,0xbe 5410 ****************************************************************************/ 5411 static void 5412 x86emuOp2_32_movsx_byte_R_RM(struct X86EMU *emu) 5413 { 5414 uint32_t *destreg; 5415 5416 destreg = decode_rh_long_register(emu); 5417 *destreg = (int32_t)(int8_t)decode_and_fetch_byte(emu); 5418 } 5419 5420 static void 5421 x86emuOp2_16_movsx_byte_R_RM(struct X86EMU *emu) 5422 { 5423 uint16_t *destreg; 5424 5425 fetch_decode_modrm(emu); 5426 destreg = decode_rh_word_register(emu); 5427 *destreg = (int16_t)(int8_t)decode_and_fetch_byte(emu); 5428 } 5429 5430 static void 5431 x86emuOp2_movsx_byte_R_RM(struct X86EMU *emu) 5432 { 5433 if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5434 x86emuOp2_32_movsx_byte_R_RM(emu); 5435 else 5436 x86emuOp2_16_movsx_byte_R_RM(emu); 5437 } 5438 /**************************************************************************** 5439 REMARKS: 5440 Handles opcode 0x0f,0xbf 5441 ****************************************************************************/ 5442 static void 5443 x86emuOp2_movsx_word_R_RM(struct X86EMU *emu) 5444 { 5445 uint32_t *destreg; 5446 5447 fetch_decode_modrm(emu); 5448 destreg = decode_rh_long_register(emu); 5449 *destreg = (int32_t)(int16_t)decode_and_fetch_word(emu); 5450 } 5451 5452 static void 5453 X86EMU_exec_two_byte(struct X86EMU * emu) 5454 { 5455 uint8_t op2; 5456 5457 op2 = fetch_byte_imm(emu); 5458 5459 switch (op2) { 5460 /* 0x00 Group F (ring 0 PM) */ 5461 /* 0x01 Group G (ring 0 PM) */ 5462 /* 0x02 lar (ring 0 PM) */ 5463 /* 0x03 lsl (ring 0 PM) */ 5464 /* 0x05 loadall (undocumented) */ 5465 /* 0x06 clts (ring 0 PM) */ 5466 /* 0x07 loadall (undocumented) */ 5467 /* 0x08 invd (ring 0 PM) */ 5468 /* 0x09 wbinvd (ring 0 PM) */ 5469 5470 /* 0x20 mov reg32(op2); break;creg (ring 0 PM) */ 5471 /* 0x21 mov reg32(op2); break;dreg (ring 0 PM) */ 5472 /* 0x22 mov creg(op2); break;reg32 (ring 0 PM) */ 5473 /* 0x23 mov dreg(op2); break;reg32 (ring 0 PM) */ 5474 /* 0x24 mov reg32(op2); break;treg (ring 0 PM) */ 5475 /* 0x26 mov treg(op2); break;reg32 (ring 0 PM) */ 5476 5477 case 0x31: 5478 x86emuOp2_rdtsc(emu); 5479 break; 5480 5481 case 0x80: 5482 common_jmp_long(emu, ACCESS_FLAG(F_OF)); 5483 break; 5484 case 0x81: 5485 common_jmp_long(emu, !ACCESS_FLAG(F_OF)); 5486 break; 5487 case 0x82: 5488 common_jmp_long(emu, ACCESS_FLAG(F_CF)); 5489 break; 5490 case 0x83: 5491 common_jmp_long(emu, !ACCESS_FLAG(F_CF)); 5492 break; 5493 case 0x84: 5494 common_jmp_long(emu, ACCESS_FLAG(F_ZF)); 5495 break; 5496 case 0x85: 5497 common_jmp_long(emu, !ACCESS_FLAG(F_ZF)); 5498 break; 5499 case 0x86: 5500 common_jmp_long(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); 5501 break; 5502 case 0x87: 5503 common_jmp_long(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))); 5504 break; 5505 case 0x88: 5506 common_jmp_long(emu, ACCESS_FLAG(F_SF)); 5507 break; 5508 case 0x89: 5509 common_jmp_long(emu, !ACCESS_FLAG(F_SF)); 5510 break; 5511 case 0x8a: 5512 common_jmp_long(emu, ACCESS_FLAG(F_PF)); 5513 break; 5514 case 0x8b: 5515 common_jmp_long(emu, !ACCESS_FLAG(F_PF)); 5516 break; 5517 case 0x8c: 5518 common_jmp_long(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))); 5519 break; 5520 case 0x8d: 5521 common_jmp_long(emu, !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)))); 5522 break; 5523 case 0x8e: 5524 common_jmp_long(emu, 5525 (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF))); 5526 break; 5527 case 0x8f: 5528 common_jmp_long(emu, 5529 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF))); 5530 break; 5531 5532 case 0x90: 5533 common_set_byte(emu, ACCESS_FLAG(F_OF)); 5534 break; 5535 case 0x91: 5536 common_set_byte(emu, !ACCESS_FLAG(F_OF)); 5537 break; 5538 case 0x92: 5539 common_set_byte(emu, ACCESS_FLAG(F_CF)); 5540 break; 5541 case 0x93: 5542 common_set_byte(emu, !ACCESS_FLAG(F_CF)); 5543 break; 5544 case 0x94: 5545 common_set_byte(emu, ACCESS_FLAG(F_ZF)); 5546 break; 5547 case 0x95: 5548 common_set_byte(emu, !ACCESS_FLAG(F_ZF)); 5549 break; 5550 case 0x96: 5551 common_set_byte(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); 5552 break; 5553 case 0x97: 5554 common_set_byte(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))); 5555 break; 5556 case 0x98: 5557 common_set_byte(emu, ACCESS_FLAG(F_SF)); 5558 break; 5559 case 0x99: 5560 common_set_byte(emu, !ACCESS_FLAG(F_SF)); 5561 break; 5562 case 0x9a: 5563 common_set_byte(emu, ACCESS_FLAG(F_PF)); 5564 break; 5565 case 0x9b: 5566 common_set_byte(emu, !ACCESS_FLAG(F_PF)); 5567 break; 5568 case 0x9c: 5569 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))); 5570 break; 5571 case 0x9d: 5572 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))); 5573 break; 5574 case 0x9e: 5575 common_set_byte(emu, 5576 (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || 5577 ACCESS_FLAG(F_ZF))); 5578 break; 5579 case 0x9f: 5580 common_set_byte(emu, 5581 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || 5582 ACCESS_FLAG(F_ZF))); 5583 break; 5584 5585 case 0xa0: 5586 x86emuOp2_push_FS(emu); 5587 break; 5588 case 0xa1: 5589 x86emuOp2_pop_FS(emu); 5590 break; 5591 case 0xa2: 5592 x86emuOp2_cpuid(emu); 5593 break; 5594 case 0xa3: 5595 x86emuOp2_bt_R(emu); 5596 break; 5597 case 0xa4: 5598 x86emuOp2_shld_IMM(emu); 5599 break; 5600 case 0xa5: 5601 x86emuOp2_shld_CL(emu); 5602 break; 5603 case 0xa8: 5604 x86emuOp2_push_GS(emu); 5605 break; 5606 case 0xa9: 5607 x86emuOp2_pop_GS(emu); 5608 break; 5609 case 0xab: 5610 x86emuOp2_bts_R(emu); 5611 break; 5612 case 0xac: 5613 x86emuOp2_shrd_IMM(emu); 5614 break; 5615 case 0xad: 5616 x86emuOp2_shrd_CL(emu); 5617 break; 5618 case 0xaf: 5619 x86emuOp2_imul_R_RM(emu); 5620 break; 5621 5622 /* 0xb0 TODO: cmpxchg */ 5623 /* 0xb1 TODO: cmpxchg */ 5624 case 0xb2: 5625 x86emuOp2_lss_R_IMM(emu); 5626 break; 5627 case 0xb3: 5628 x86emuOp2_btr_R(emu); 5629 break; 5630 case 0xb4: 5631 x86emuOp2_lfs_R_IMM(emu); 5632 break; 5633 case 0xb5: 5634 x86emuOp2_lgs_R_IMM(emu); 5635 break; 5636 case 0xb6: 5637 x86emuOp2_movzx_byte_R_RM(emu); 5638 break; 5639 case 0xb7: 5640 x86emuOp2_movzx_word_R_RM(emu); 5641 break; 5642 case 0xba: 5643 x86emuOp2_btX_I(emu); 5644 break; 5645 case 0xbb: 5646 x86emuOp2_btc_R(emu); 5647 break; 5648 case 0xbc: 5649 x86emuOp2_bsf(emu); 5650 break; 5651 case 0xbd: 5652 x86emuOp2_bsr(emu); 5653 break; 5654 case 0xbe: 5655 x86emuOp2_movsx_byte_R_RM(emu); 5656 break; 5657 case 0xbf: 5658 x86emuOp2_movsx_word_R_RM(emu); 5659 break; 5660 5661 /* 0xc0 TODO: xadd */ 5662 /* 0xc1 TODO: xadd */ 5663 /* 0xc8 TODO: bswap */ 5664 /* 0xc9 TODO: bswap */ 5665 /* 0xca TODO: bswap */ 5666 /* 0xcb TODO: bswap */ 5667 /* 0xcc TODO: bswap */ 5668 /* 0xcd TODO: bswap */ 5669 /* 0xce TODO: bswap */ 5670 /* 0xcf TODO: bswap */ 5671 5672 default: 5673 X86EMU_halt_sys(emu); 5674 break; 5675 } 5676 } 5677 5678 /* 5679 * Carry Chain Calculation 5680 * 5681 * This represents a somewhat expensive calculation which is 5682 * apparently required to emulate the setting of the OF and AF flag. 5683 * The latter is not so important, but the former is. The overflow 5684 * flag is the XOR of the top two bits of the carry chain for an 5685 * addition (similar for subtraction). Since we do not want to 5686 * simulate the addition in a bitwise manner, we try to calculate the 5687 * carry chain given the two operands and the result. 5688 * 5689 * So, given the following table, which represents the addition of two 5690 * bits, we can derive a formula for the carry chain. 5691 * 5692 * a b cin r cout 5693 * 0 0 0 0 0 5694 * 0 0 1 1 0 5695 * 0 1 0 1 0 5696 * 0 1 1 0 1 5697 * 1 0 0 1 0 5698 * 1 0 1 0 1 5699 * 1 1 0 0 1 5700 * 1 1 1 1 1 5701 * 5702 * Construction of table for cout: 5703 * 5704 * ab 5705 * r \ 00 01 11 10 5706 * |------------------ 5707 * 0 | 0 1 1 1 5708 * 1 | 0 0 1 0 5709 * 5710 * By inspection, one gets: cc = ab + r'(a + b) 5711 * 5712 * That represents alot of operations, but NO CHOICE.... 5713 * 5714 * Borrow Chain Calculation. 5715 * 5716 * The following table represents the subtraction of two bits, from 5717 * which we can derive a formula for the borrow chain. 5718 * 5719 * a b bin r bout 5720 * 0 0 0 0 0 5721 * 0 0 1 1 1 5722 * 0 1 0 1 1 5723 * 0 1 1 0 1 5724 * 1 0 0 1 0 5725 * 1 0 1 0 0 5726 * 1 1 0 0 0 5727 * 1 1 1 1 1 5728 * 5729 * Construction of table for cout: 5730 * 5731 * ab 5732 * r \ 00 01 11 10 5733 * |------------------ 5734 * 0 | 0 1 0 0 5735 * 1 | 1 1 1 0 5736 * 5737 * By inspection, one gets: bc = a'b + r(a' + b) 5738 * 5739 ****************************************************************************/ 5740 5741 /*------------------------- Global Variables ------------------------------*/ 5742 5743 static uint32_t x86emu_parity_tab[8] = 5744 { 5745 0x96696996, 5746 0x69969669, 5747 0x69969669, 5748 0x96696996, 5749 0x69969669, 5750 0x96696996, 5751 0x96696996, 5752 0x69969669, 5753 }; 5754 #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0) 5755 #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1) 5756 5757 /**************************************************************************** 5758 REMARKS: 5759 Implements the AAA instruction and side effects. 5760 ****************************************************************************/ 5761 static uint16_t 5762 aaa_word(struct X86EMU *emu, uint16_t d) 5763 { 5764 uint16_t res; 5765 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { 5766 d += 0x6; 5767 d += 0x100; 5768 SET_FLAG(F_AF); 5769 SET_FLAG(F_CF); 5770 } else { 5771 CLEAR_FLAG(F_CF); 5772 CLEAR_FLAG(F_AF); 5773 } 5774 res = (uint16_t) (d & 0xFF0F); 5775 CLEAR_FLAG(F_SF); 5776 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 5777 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5778 return res; 5779 } 5780 /**************************************************************************** 5781 REMARKS: 5782 Implements the AAA instruction and side effects. 5783 ****************************************************************************/ 5784 static uint16_t 5785 aas_word(struct X86EMU *emu, uint16_t d) 5786 { 5787 uint16_t res; 5788 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { 5789 d -= 0x6; 5790 d -= 0x100; 5791 SET_FLAG(F_AF); 5792 SET_FLAG(F_CF); 5793 } else { 5794 CLEAR_FLAG(F_CF); 5795 CLEAR_FLAG(F_AF); 5796 } 5797 res = (uint16_t) (d & 0xFF0F); 5798 CLEAR_FLAG(F_SF); 5799 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 5800 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5801 return res; 5802 } 5803 /**************************************************************************** 5804 REMARKS: 5805 Implements the AAD instruction and side effects. 5806 ****************************************************************************/ 5807 static uint16_t 5808 aad_word(struct X86EMU *emu, uint16_t d) 5809 { 5810 uint16_t l; 5811 uint8_t hb, lb; 5812 5813 hb = (uint8_t) ((d >> 8) & 0xff); 5814 lb = (uint8_t) ((d & 0xff)); 5815 l = (uint16_t) ((lb + 10 * hb) & 0xFF); 5816 5817 CLEAR_FLAG(F_CF); 5818 CLEAR_FLAG(F_AF); 5819 CLEAR_FLAG(F_OF); 5820 CONDITIONAL_SET_FLAG(l & 0x80, F_SF); 5821 CONDITIONAL_SET_FLAG(l == 0, F_ZF); 5822 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF); 5823 return l; 5824 } 5825 /**************************************************************************** 5826 REMARKS: 5827 Implements the AAM instruction and side effects. 5828 ****************************************************************************/ 5829 static uint16_t 5830 aam_word(struct X86EMU *emu, uint8_t d) 5831 { 5832 uint16_t h, l; 5833 5834 h = (uint16_t) (d / 10); 5835 l = (uint16_t) (d % 10); 5836 l |= (uint16_t) (h << 8); 5837 5838 CLEAR_FLAG(F_CF); 5839 CLEAR_FLAG(F_AF); 5840 CLEAR_FLAG(F_OF); 5841 CONDITIONAL_SET_FLAG(l & 0x80, F_SF); 5842 CONDITIONAL_SET_FLAG(l == 0, F_ZF); 5843 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF); 5844 return l; 5845 } 5846 /**************************************************************************** 5847 REMARKS: 5848 Implements the ADC instruction and side effects. 5849 ****************************************************************************/ 5850 static uint8_t 5851 adc_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 5852 { 5853 uint32_t res; /* all operands in native machine order */ 5854 uint32_t cc; 5855 5856 if (ACCESS_FLAG(F_CF)) 5857 res = 1 + d + s; 5858 else 5859 res = d + s; 5860 5861 CONDITIONAL_SET_FLAG(res & 0x100, F_CF); 5862 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 5863 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 5864 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5865 5866 /* calculate the carry chain SEE NOTE AT TOP. */ 5867 cc = (s & d) | ((~res) & (s | d)); 5868 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 5869 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 5870 return (uint8_t) res; 5871 } 5872 /**************************************************************************** 5873 REMARKS: 5874 Implements the ADC instruction and side effects. 5875 ****************************************************************************/ 5876 static uint16_t 5877 adc_word(struct X86EMU *emu, uint16_t d, uint16_t s) 5878 { 5879 uint32_t res; /* all operands in native machine order */ 5880 uint32_t cc; 5881 5882 if (ACCESS_FLAG(F_CF)) 5883 res = 1 + d + s; 5884 else 5885 res = d + s; 5886 5887 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF); 5888 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 5889 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 5890 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5891 5892 /* calculate the carry chain SEE NOTE AT TOP. */ 5893 cc = (s & d) | ((~res) & (s | d)); 5894 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 5895 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 5896 return (uint16_t) res; 5897 } 5898 /**************************************************************************** 5899 REMARKS: 5900 Implements the ADC instruction and side effects. 5901 ****************************************************************************/ 5902 static uint32_t 5903 adc_long(struct X86EMU *emu, uint32_t d, uint32_t s) 5904 { 5905 uint32_t lo; /* all operands in native machine order */ 5906 uint32_t hi; 5907 uint32_t res; 5908 uint32_t cc; 5909 5910 if (ACCESS_FLAG(F_CF)) { 5911 lo = 1 + (d & 0xFFFF) + (s & 0xFFFF); 5912 res = 1 + d + s; 5913 } else { 5914 lo = (d & 0xFFFF) + (s & 0xFFFF); 5915 res = d + s; 5916 } 5917 hi = (lo >> 16) + (d >> 16) + (s >> 16); 5918 5919 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF); 5920 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 5921 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 5922 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5923 5924 /* calculate the carry chain SEE NOTE AT TOP. */ 5925 cc = (s & d) | ((~res) & (s | d)); 5926 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 5927 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 5928 return res; 5929 } 5930 /**************************************************************************** 5931 REMARKS: 5932 Implements the ADD instruction and side effects. 5933 ****************************************************************************/ 5934 static uint8_t 5935 add_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 5936 { 5937 uint32_t res; /* all operands in native machine order */ 5938 uint32_t cc; 5939 5940 res = d + s; 5941 CONDITIONAL_SET_FLAG(res & 0x100, F_CF); 5942 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 5943 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 5944 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5945 5946 /* calculate the carry chain SEE NOTE AT TOP. */ 5947 cc = (s & d) | ((~res) & (s | d)); 5948 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 5949 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 5950 return (uint8_t) res; 5951 } 5952 /**************************************************************************** 5953 REMARKS: 5954 Implements the ADD instruction and side effects. 5955 ****************************************************************************/ 5956 static uint16_t 5957 add_word(struct X86EMU *emu, uint16_t d, uint16_t s) 5958 { 5959 uint32_t res; /* all operands in native machine order */ 5960 uint32_t cc; 5961 5962 res = d + s; 5963 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF); 5964 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 5965 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 5966 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5967 5968 /* calculate the carry chain SEE NOTE AT TOP. */ 5969 cc = (s & d) | ((~res) & (s | d)); 5970 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 5971 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 5972 return (uint16_t) res; 5973 } 5974 /**************************************************************************** 5975 REMARKS: 5976 Implements the ADD instruction and side effects. 5977 ****************************************************************************/ 5978 static uint32_t 5979 add_long(struct X86EMU *emu, uint32_t d, uint32_t s) 5980 { 5981 uint32_t lo; /* all operands in native machine order */ 5982 uint32_t hi; 5983 uint32_t res; 5984 uint32_t cc; 5985 5986 lo = (d & 0xFFFF) + (s & 0xFFFF); 5987 res = d + s; 5988 hi = (lo >> 16) + (d >> 16) + (s >> 16); 5989 5990 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF); 5991 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 5992 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 5993 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5994 5995 /* calculate the carry chain SEE NOTE AT TOP. */ 5996 cc = (s & d) | ((~res) & (s | d)); 5997 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 5998 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 5999 6000 return res; 6001 } 6002 /**************************************************************************** 6003 REMARKS: 6004 Implements the AND instruction and side effects. 6005 ****************************************************************************/ 6006 static uint8_t 6007 and_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6008 { 6009 uint8_t res; /* all operands in native machine order */ 6010 6011 res = d & s; 6012 6013 /* set the flags */ 6014 CLEAR_FLAG(F_OF); 6015 CLEAR_FLAG(F_CF); 6016 CLEAR_FLAG(F_AF); 6017 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6018 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6019 CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 6020 return res; 6021 } 6022 /**************************************************************************** 6023 REMARKS: 6024 Implements the AND instruction and side effects. 6025 ****************************************************************************/ 6026 static uint16_t 6027 and_word(struct X86EMU *emu, uint16_t d, uint16_t s) 6028 { 6029 uint16_t res; /* all operands in native machine order */ 6030 6031 res = d & s; 6032 6033 /* set the flags */ 6034 CLEAR_FLAG(F_OF); 6035 CLEAR_FLAG(F_CF); 6036 CLEAR_FLAG(F_AF); 6037 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6038 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6039 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6040 return res; 6041 } 6042 /**************************************************************************** 6043 REMARKS: 6044 Implements the AND instruction and side effects. 6045 ****************************************************************************/ 6046 static uint32_t 6047 and_long(struct X86EMU *emu, uint32_t d, uint32_t s) 6048 { 6049 uint32_t res; /* all operands in native machine order */ 6050 6051 res = d & s; 6052 6053 /* set the flags */ 6054 CLEAR_FLAG(F_OF); 6055 CLEAR_FLAG(F_CF); 6056 CLEAR_FLAG(F_AF); 6057 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6058 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6059 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6060 return res; 6061 } 6062 /**************************************************************************** 6063 REMARKS: 6064 Implements the CMP instruction and side effects. 6065 ****************************************************************************/ 6066 static uint8_t 6067 cmp_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6068 { 6069 uint32_t res; /* all operands in native machine order */ 6070 uint32_t bc; 6071 6072 res = d - s; 6073 CLEAR_FLAG(F_CF); 6074 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6075 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6076 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6077 6078 /* calculate the borrow chain. See note at top */ 6079 bc = (res & (~d | s)) | (~d & s); 6080 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); 6081 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 6082 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6083 return d; 6084 } 6085 6086 static void 6087 cmp_byte_no_return(struct X86EMU *emu, uint8_t d, uint8_t s) 6088 { 6089 cmp_byte(emu, d, s); 6090 } 6091 /**************************************************************************** 6092 REMARKS: 6093 Implements the CMP instruction and side effects. 6094 ****************************************************************************/ 6095 static uint16_t 6096 cmp_word(struct X86EMU *emu, uint16_t d, uint16_t s) 6097 { 6098 uint32_t res; /* all operands in native machine order */ 6099 uint32_t bc; 6100 6101 res = d - s; 6102 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6103 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6104 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6105 6106 /* calculate the borrow chain. See note at top */ 6107 bc = (res & (~d | s)) | (~d & s); 6108 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 6109 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 6110 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6111 return d; 6112 } 6113 6114 static void 6115 cmp_word_no_return(struct X86EMU *emu, uint16_t d, uint16_t s) 6116 { 6117 cmp_word(emu, d, s); 6118 } 6119 /**************************************************************************** 6120 REMARKS: 6121 Implements the CMP instruction and side effects. 6122 ****************************************************************************/ 6123 static uint32_t 6124 cmp_long(struct X86EMU *emu, uint32_t d, uint32_t s) 6125 { 6126 uint32_t res; /* all operands in native machine order */ 6127 uint32_t bc; 6128 6129 res = d - s; 6130 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6131 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6132 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6133 6134 /* calculate the borrow chain. See note at top */ 6135 bc = (res & (~d | s)) | (~d & s); 6136 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 6137 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 6138 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6139 return d; 6140 } 6141 6142 static void 6143 cmp_long_no_return(struct X86EMU *emu, uint32_t d, uint32_t s) 6144 { 6145 cmp_long(emu, d, s); 6146 } 6147 /**************************************************************************** 6148 REMARKS: 6149 Implements the DAA instruction and side effects. 6150 ****************************************************************************/ 6151 static uint8_t 6152 daa_byte(struct X86EMU *emu, uint8_t d) 6153 { 6154 uint32_t res = d; 6155 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) { 6156 res += 6; 6157 SET_FLAG(F_AF); 6158 } 6159 if (res > 0x9F || ACCESS_FLAG(F_CF)) { 6160 res += 0x60; 6161 SET_FLAG(F_CF); 6162 } 6163 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6164 CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF); 6165 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6166 return (uint8_t) res; 6167 } 6168 /**************************************************************************** 6169 REMARKS: 6170 Implements the DAS instruction and side effects. 6171 ****************************************************************************/ 6172 static uint8_t 6173 das_byte(struct X86EMU *emu, uint8_t d) 6174 { 6175 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) { 6176 d -= 6; 6177 SET_FLAG(F_AF); 6178 } 6179 if (d > 0x9F || ACCESS_FLAG(F_CF)) { 6180 d -= 0x60; 6181 SET_FLAG(F_CF); 6182 } 6183 CONDITIONAL_SET_FLAG(d & 0x80, F_SF); 6184 CONDITIONAL_SET_FLAG(d == 0, F_ZF); 6185 CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF); 6186 return d; 6187 } 6188 /**************************************************************************** 6189 REMARKS: 6190 Implements the DEC instruction and side effects. 6191 ****************************************************************************/ 6192 static uint8_t 6193 dec_byte(struct X86EMU *emu, uint8_t d) 6194 { 6195 uint32_t res; /* all operands in native machine order */ 6196 uint32_t bc; 6197 6198 res = d - 1; 6199 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6200 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6201 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6202 6203 /* calculate the borrow chain. See note at top */ 6204 /* based on sub_byte, uses s==1. */ 6205 bc = (res & (~d | 1)) | (~d & 1); 6206 /* carry flag unchanged */ 6207 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 6208 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6209 return (uint8_t) res; 6210 } 6211 /**************************************************************************** 6212 REMARKS: 6213 Implements the DEC instruction and side effects. 6214 ****************************************************************************/ 6215 static uint16_t 6216 dec_word(struct X86EMU *emu, uint16_t d) 6217 { 6218 uint32_t res; /* all operands in native machine order */ 6219 uint32_t bc; 6220 6221 res = d - 1; 6222 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6223 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6224 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6225 6226 /* calculate the borrow chain. See note at top */ 6227 /* based on the sub_byte routine, with s==1 */ 6228 bc = (res & (~d | 1)) | (~d & 1); 6229 /* carry flag unchanged */ 6230 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 6231 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6232 return (uint16_t) res; 6233 } 6234 /**************************************************************************** 6235 REMARKS: 6236 Implements the DEC instruction and side effects. 6237 ****************************************************************************/ 6238 static uint32_t 6239 dec_long(struct X86EMU *emu, uint32_t d) 6240 { 6241 uint32_t res; /* all operands in native machine order */ 6242 uint32_t bc; 6243 6244 res = d - 1; 6245 6246 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6247 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6248 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6249 6250 /* calculate the borrow chain. See note at top */ 6251 bc = (res & (~d | 1)) | (~d & 1); 6252 /* carry flag unchanged */ 6253 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 6254 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6255 return res; 6256 } 6257 /**************************************************************************** 6258 REMARKS: 6259 Implements the INC instruction and side effects. 6260 ****************************************************************************/ 6261 static uint8_t 6262 inc_byte(struct X86EMU *emu, uint8_t d) 6263 { 6264 uint32_t res; /* all operands in native machine order */ 6265 uint32_t cc; 6266 6267 res = d + 1; 6268 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6269 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6270 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6271 6272 /* calculate the carry chain SEE NOTE AT TOP. */ 6273 cc = ((1 & d) | (~res)) & (1 | d); 6274 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 6275 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6276 return (uint8_t) res; 6277 } 6278 /**************************************************************************** 6279 REMARKS: 6280 Implements the INC instruction and side effects. 6281 ****************************************************************************/ 6282 static uint16_t 6283 inc_word(struct X86EMU *emu, uint16_t d) 6284 { 6285 uint32_t res; /* all operands in native machine order */ 6286 uint32_t cc; 6287 6288 res = d + 1; 6289 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6290 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6291 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6292 6293 /* calculate the carry chain SEE NOTE AT TOP. */ 6294 cc = (1 & d) | ((~res) & (1 | d)); 6295 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 6296 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6297 return (uint16_t) res; 6298 } 6299 /**************************************************************************** 6300 REMARKS: 6301 Implements the INC instruction and side effects. 6302 ****************************************************************************/ 6303 static uint32_t 6304 inc_long(struct X86EMU *emu, uint32_t d) 6305 { 6306 uint32_t res; /* all operands in native machine order */ 6307 uint32_t cc; 6308 6309 res = d + 1; 6310 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6311 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6312 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6313 6314 /* calculate the carry chain SEE NOTE AT TOP. */ 6315 cc = (1 & d) | ((~res) & (1 | d)); 6316 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 6317 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6318 return res; 6319 } 6320 /**************************************************************************** 6321 REMARKS: 6322 Implements the OR instruction and side effects. 6323 ****************************************************************************/ 6324 static uint8_t 6325 or_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6326 { 6327 uint8_t res; /* all operands in native machine order */ 6328 6329 res = d | s; 6330 CLEAR_FLAG(F_OF); 6331 CLEAR_FLAG(F_CF); 6332 CLEAR_FLAG(F_AF); 6333 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6334 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6335 CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 6336 return res; 6337 } 6338 /**************************************************************************** 6339 REMARKS: 6340 Implements the OR instruction and side effects. 6341 ****************************************************************************/ 6342 static uint16_t 6343 or_word(struct X86EMU *emu, uint16_t d, uint16_t s) 6344 { 6345 uint16_t res; /* all operands in native machine order */ 6346 6347 res = d | s; 6348 /* set the carry flag to be bit 8 */ 6349 CLEAR_FLAG(F_OF); 6350 CLEAR_FLAG(F_CF); 6351 CLEAR_FLAG(F_AF); 6352 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6353 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6354 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6355 return res; 6356 } 6357 /**************************************************************************** 6358 REMARKS: 6359 Implements the OR instruction and side effects. 6360 ****************************************************************************/ 6361 static uint32_t 6362 or_long(struct X86EMU *emu, uint32_t d, uint32_t s) 6363 { 6364 uint32_t res; /* all operands in native machine order */ 6365 6366 res = d | s; 6367 6368 /* set the carry flag to be bit 8 */ 6369 CLEAR_FLAG(F_OF); 6370 CLEAR_FLAG(F_CF); 6371 CLEAR_FLAG(F_AF); 6372 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6373 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6374 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6375 return res; 6376 } 6377 /**************************************************************************** 6378 REMARKS: 6379 Implements the OR instruction and side effects. 6380 ****************************************************************************/ 6381 static uint8_t 6382 neg_byte(struct X86EMU *emu, uint8_t s) 6383 { 6384 uint8_t res; 6385 uint8_t bc; 6386 6387 CONDITIONAL_SET_FLAG(s != 0, F_CF); 6388 res = (uint8_t) - s; 6389 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6390 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6391 CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 6392 /* calculate the borrow chain --- modified such that d=0. 6393 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for 6394 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and 6395 * res&0xfff... == res. Similarly ~d&s == s. So the simplified 6396 * result is: */ 6397 bc = res | s; 6398 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 6399 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6400 return res; 6401 } 6402 /**************************************************************************** 6403 REMARKS: 6404 Implements the OR instruction and side effects. 6405 ****************************************************************************/ 6406 static uint16_t 6407 neg_word(struct X86EMU *emu, uint16_t s) 6408 { 6409 uint16_t res; 6410 uint16_t bc; 6411 6412 CONDITIONAL_SET_FLAG(s != 0, F_CF); 6413 res = (uint16_t) - s; 6414 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6415 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6416 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6417 6418 /* calculate the borrow chain --- modified such that d=0. 6419 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for 6420 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and 6421 * res&0xfff... == res. Similarly ~d&s == s. So the simplified 6422 * result is: */ 6423 bc = res | s; 6424 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 6425 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6426 return res; 6427 } 6428 /**************************************************************************** 6429 REMARKS: 6430 Implements the OR instruction and side effects. 6431 ****************************************************************************/ 6432 static uint32_t 6433 neg_long(struct X86EMU *emu, uint32_t s) 6434 { 6435 uint32_t res; 6436 uint32_t bc; 6437 6438 CONDITIONAL_SET_FLAG(s != 0, F_CF); 6439 res = (uint32_t) - s; 6440 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6441 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6442 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6443 6444 /* calculate the borrow chain --- modified such that d=0. 6445 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for 6446 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and 6447 * res&0xfff... == res. Similarly ~d&s == s. So the simplified 6448 * result is: */ 6449 bc = res | s; 6450 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 6451 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6452 return res; 6453 } 6454 /**************************************************************************** 6455 REMARKS: 6456 Implements the RCL instruction and side effects. 6457 ****************************************************************************/ 6458 static uint8_t 6459 rcl_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6460 { 6461 unsigned int res, cnt, mask, cf; 6462 6463 /* s is the rotate distance. It varies from 0 - 8. */ 6464 /* have 6465 * 6466 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 6467 * 6468 * want to rotate through the carry by "s" bits. We could loop, but 6469 * that's inefficient. So the width is 9, and we split into three 6470 * parts: 6471 * 6472 * The new carry flag (was B_n) the stuff in B_n-1 .. B_0 the stuff in 6473 * B_7 .. B_n+1 6474 * 6475 * The new rotate is done mod 9, and given this, for a rotation of n bits 6476 * (mod 9) the new carry flag is then located n bits from the MSB. 6477 * The low part is then shifted up cnt bits, and the high part is or'd 6478 * in. Using CAPS for new values, and lowercase for the original 6479 * values, this can be expressed as: 6480 * 6481 * IF n > 0 1) CF <- b_(8-n) 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 6482 * 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */ 6483 res = d; 6484 if ((cnt = s % 9) != 0) { 6485 /* extract the new CARRY FLAG. */ 6486 /* CF <- b_(8-n) */ 6487 cf = (d >> (8 - cnt)) & 0x1; 6488 6489 /* get the low stuff which rotated into the range B_7 .. B_cnt */ 6490 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */ 6491 /* note that the right hand side done by the mask */ 6492 res = (d << cnt) & 0xff; 6493 6494 /* now the high stuff which rotated around into the positions 6495 * B_cnt-2 .. B_0 */ 6496 /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */ 6497 /* shift it downward, 7-(n-2) = 9-n positions. and mask off 6498 * the result before or'ing in. */ 6499 mask = (1 << (cnt - 1)) - 1; 6500 res |= (d >> (9 - cnt)) & mask; 6501 6502 /* if the carry flag was set, or it in. */ 6503 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6504 /* B_(n-1) <- cf */ 6505 res |= 1 << (cnt - 1); 6506 } 6507 /* set the new carry flag, based on the variable "cf" */ 6508 CONDITIONAL_SET_FLAG(cf, F_CF); 6509 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and 6510 * the most significant bit. Blecck. */ 6511 /* parenthesized this expression since it appears to be 6512 * causing OF to be misset */ 6513 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)), 6514 F_OF); 6515 6516 } 6517 return (uint8_t) res; 6518 } 6519 /**************************************************************************** 6520 REMARKS: 6521 Implements the RCL instruction and side effects. 6522 ****************************************************************************/ 6523 static uint16_t 6524 rcl_word(struct X86EMU *emu, uint16_t d, uint8_t s) 6525 { 6526 unsigned int res, cnt, mask, cf; 6527 6528 res = d; 6529 if ((cnt = s % 17) != 0) { 6530 cf = (d >> (16 - cnt)) & 0x1; 6531 res = (d << cnt) & 0xffff; 6532 mask = (1 << (cnt - 1)) - 1; 6533 res |= (d >> (17 - cnt)) & mask; 6534 if (ACCESS_FLAG(F_CF)) { 6535 res |= 1 << (cnt - 1); 6536 } 6537 CONDITIONAL_SET_FLAG(cf, F_CF); 6538 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)), 6539 F_OF); 6540 } 6541 return (uint16_t) res; 6542 } 6543 /**************************************************************************** 6544 REMARKS: 6545 Implements the RCL instruction and side effects. 6546 ****************************************************************************/ 6547 static uint32_t 6548 rcl_long(struct X86EMU *emu, uint32_t d, uint8_t s) 6549 { 6550 uint32_t res, cnt, mask, cf; 6551 6552 res = d; 6553 if ((cnt = s % 33) != 0) { 6554 cf = (d >> (32 - cnt)) & 0x1; 6555 res = (d << cnt) & 0xffffffff; 6556 mask = (1 << (cnt - 1)) - 1; 6557 res |= (d >> (33 - cnt)) & mask; 6558 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6559 res |= 1 << (cnt - 1); 6560 } 6561 CONDITIONAL_SET_FLAG(cf, F_CF); 6562 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)), 6563 F_OF); 6564 } 6565 return res; 6566 } 6567 /**************************************************************************** 6568 REMARKS: 6569 Implements the RCR instruction and side effects. 6570 ****************************************************************************/ 6571 static uint8_t 6572 rcr_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6573 { 6574 uint32_t res, cnt; 6575 uint32_t mask, cf, ocf = 0; 6576 6577 /* rotate right through carry */ 6578 /* s is the rotate distance. It varies from 0 - 8. d is the byte 6579 * object rotated. 6580 * 6581 * have 6582 * 6583 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 6584 * 6585 * The new rotate is done mod 9, and given this, for a rotation of n bits 6586 * (mod 9) the new carry flag is then located n bits from the LSB. 6587 * The low part is then shifted up cnt bits, and the high part is or'd 6588 * in. Using CAPS for new values, and lowercase for the original 6589 * values, this can be expressed as: 6590 * 6591 * IF n > 0 1) CF <- b_(n-1) 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 6592 * 3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */ 6593 res = d; 6594 if ((cnt = s % 9) != 0) { 6595 /* extract the new CARRY FLAG. */ 6596 /* CF <- b_(n-1) */ 6597 if (cnt == 1) { 6598 cf = d & 0x1; 6599 /* note hackery here. Access_flag(..) evaluates to 6600 * either 0 if flag not set non-zero if flag is set. 6601 * doing access_flag(..) != 0 casts that into either 6602 * 0..1 in any representation of the flags register 6603 * (i.e. packed bit array or unpacked.) */ 6604 ocf = ACCESS_FLAG(F_CF) != 0; 6605 } else 6606 cf = (d >> (cnt - 1)) & 0x1; 6607 6608 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */ 6609 /* note that the right hand side done by the mask This is 6610 * effectively done by shifting the object to the right. The 6611 * result must be masked, in case the object came in and was 6612 * treated as a negative number. Needed??? */ 6613 6614 mask = (1 << (8 - cnt)) - 1; 6615 res = (d >> cnt) & mask; 6616 6617 /* now the high stuff which rotated around into the positions 6618 * B_cnt-2 .. B_0 */ 6619 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */ 6620 /* shift it downward, 7-(n-2) = 9-n positions. and mask off 6621 * the result before or'ing in. */ 6622 res |= (d << (9 - cnt)); 6623 6624 /* if the carry flag was set, or it in. */ 6625 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6626 /* B_(8-n) <- cf */ 6627 res |= 1 << (8 - cnt); 6628 } 6629 /* set the new carry flag, based on the variable "cf" */ 6630 CONDITIONAL_SET_FLAG(cf, F_CF); 6631 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and 6632 * the most significant bit. Blecck. */ 6633 /* parenthesized... */ 6634 if (cnt == 1) { 6635 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)), 6636 F_OF); 6637 } 6638 } 6639 return (uint8_t) res; 6640 } 6641 /**************************************************************************** 6642 REMARKS: 6643 Implements the RCR instruction and side effects. 6644 ****************************************************************************/ 6645 static uint16_t 6646 rcr_word(struct X86EMU *emu, uint16_t d, uint8_t s) 6647 { 6648 uint32_t res, cnt; 6649 uint32_t mask, cf, ocf = 0; 6650 6651 /* rotate right through carry */ 6652 res = d; 6653 if ((cnt = s % 17) != 0) { 6654 if (cnt == 1) { 6655 cf = d & 0x1; 6656 ocf = ACCESS_FLAG(F_CF) != 0; 6657 } else 6658 cf = (d >> (cnt - 1)) & 0x1; 6659 mask = (1 << (16 - cnt)) - 1; 6660 res = (d >> cnt) & mask; 6661 res |= (d << (17 - cnt)); 6662 if (ACCESS_FLAG(F_CF)) { 6663 res |= 1 << (16 - cnt); 6664 } 6665 CONDITIONAL_SET_FLAG(cf, F_CF); 6666 if (cnt == 1) { 6667 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)), 6668 F_OF); 6669 } 6670 } 6671 return (uint16_t) res; 6672 } 6673 /**************************************************************************** 6674 REMARKS: 6675 Implements the RCR instruction and side effects. 6676 ****************************************************************************/ 6677 static uint32_t 6678 rcr_long(struct X86EMU *emu, uint32_t d, uint8_t s) 6679 { 6680 uint32_t res, cnt; 6681 uint32_t mask, cf, ocf = 0; 6682 6683 /* rotate right through carry */ 6684 res = d; 6685 if ((cnt = s % 33) != 0) { 6686 if (cnt == 1) { 6687 cf = d & 0x1; 6688 ocf = ACCESS_FLAG(F_CF) != 0; 6689 } else 6690 cf = (d >> (cnt - 1)) & 0x1; 6691 mask = (1 << (32 - cnt)) - 1; 6692 res = (d >> cnt) & mask; 6693 if (cnt != 1) 6694 res |= (d << (33 - cnt)); 6695 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6696 res |= 1 << (32 - cnt); 6697 } 6698 CONDITIONAL_SET_FLAG(cf, F_CF); 6699 if (cnt == 1) { 6700 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)), 6701 F_OF); 6702 } 6703 } 6704 return res; 6705 } 6706 /**************************************************************************** 6707 REMARKS: 6708 Implements the ROL instruction and side effects. 6709 ****************************************************************************/ 6710 static uint8_t 6711 rol_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6712 { 6713 unsigned int res, cnt, mask; 6714 6715 /* rotate left */ 6716 /* s is the rotate distance. It varies from 0 - 8. d is the byte 6717 * object rotated. 6718 * 6719 * have 6720 * 6721 * CF B_7 ... B_0 6722 * 6723 * The new rotate is done mod 8. Much simpler than the "rcl" or "rcr" 6724 * operations. 6725 * 6726 * IF n > 0 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) 2) B_(n-1) .. 6727 * B_(0) <- b_(7) .. b_(8-n) */ 6728 res = d; 6729 if ((cnt = s % 8) != 0) { 6730 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */ 6731 res = (d << cnt); 6732 6733 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */ 6734 mask = (1 << cnt) - 1; 6735 res |= (d >> (8 - cnt)) & mask; 6736 6737 /* set the new carry flag, Note that it is the low order bit 6738 * of the result!!! */ 6739 CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6740 /* OVERFLOW is set *IFF* s==1, then it is the xor of CF and 6741 * the most significant bit. Blecck. */ 6742 CONDITIONAL_SET_FLAG(s == 1 && 6743 XOR2((res & 0x1) + ((res >> 6) & 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 (uint8_t) res; 6751 } 6752 /**************************************************************************** 6753 REMARKS: 6754 Implements the ROL instruction and side effects. 6755 ****************************************************************************/ 6756 static uint16_t 6757 rol_word(struct X86EMU *emu, uint16_t d, uint8_t s) 6758 { 6759 unsigned int res, cnt, mask; 6760 6761 res = d; 6762 if ((cnt = s % 16) != 0) { 6763 res = (d << cnt); 6764 mask = (1 << cnt) - 1; 6765 res |= (d >> (16 - cnt)) & mask; 6766 CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6767 CONDITIONAL_SET_FLAG(s == 1 && 6768 XOR2((res & 0x1) + ((res >> 14) & 0x2)), 6769 F_OF); 6770 } if (s != 0) { 6771 /* set the new carry flag, Note that it is the low order bit 6772 * of the result!!! */ 6773 CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6774 } 6775 return (uint16_t) res; 6776 } 6777 /**************************************************************************** 6778 REMARKS: 6779 Implements the ROL instruction and side effects. 6780 ****************************************************************************/ 6781 static uint32_t 6782 rol_long(struct X86EMU *emu, uint32_t d, uint8_t s) 6783 { 6784 uint32_t res, cnt, mask; 6785 6786 res = d; 6787 if ((cnt = s % 32) != 0) { 6788 res = (d << cnt); 6789 mask = (1 << cnt) - 1; 6790 res |= (d >> (32 - cnt)) & mask; 6791 CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6792 CONDITIONAL_SET_FLAG(s == 1 && 6793 XOR2((res & 0x1) + ((res >> 30) & 0x2)), 6794 F_OF); 6795 } if (s != 0) { 6796 /* set the new carry flag, Note that it is the low order bit 6797 * of the result!!! */ 6798 CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6799 } 6800 return res; 6801 } 6802 /**************************************************************************** 6803 REMARKS: 6804 Implements the ROR instruction and side effects. 6805 ****************************************************************************/ 6806 static uint8_t 6807 ror_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6808 { 6809 unsigned int res, cnt, mask; 6810 6811 /* rotate right */ 6812 /* s is the rotate distance. It varies from 0 - 8. d is the byte 6813 * object rotated. 6814 * 6815 * have 6816 * 6817 * B_7 ... B_0 6818 * 6819 * The rotate is done mod 8. 6820 * 6821 * IF n > 0 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 2) B_(7) .. 6822 * B_(8-n) <- b_(n-1) .. b_(0) */ 6823 res = d; 6824 if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */ 6825 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */ 6826 res = (d << (8 - cnt)); 6827 6828 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */ 6829 mask = (1 << (8 - cnt)) - 1; 6830 res |= (d >> (cnt)) & mask; 6831 6832 /* set the new carry flag, Note that it is the low order bit 6833 * of the result!!! */ 6834 CONDITIONAL_SET_FLAG(res & 0x80, F_CF); 6835 /* OVERFLOW is set *IFF* s==1, then it is the xor of the two 6836 * most significant bits. Blecck. */ 6837 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF); 6838 } else if (s != 0) { 6839 /* set the new carry flag, Note that it is the low order bit 6840 * of the result!!! */ 6841 CONDITIONAL_SET_FLAG(res & 0x80, F_CF); 6842 } 6843 return (uint8_t) res; 6844 } 6845 /**************************************************************************** 6846 REMARKS: 6847 Implements the ROR instruction and side effects. 6848 ****************************************************************************/ 6849 static uint16_t 6850 ror_word(struct X86EMU *emu, uint16_t d, uint8_t s) 6851 { 6852 unsigned int res, cnt, mask; 6853 6854 res = d; 6855 if ((cnt = s % 16) != 0) { 6856 res = (d << (16 - cnt)); 6857 mask = (1 << (16 - cnt)) - 1; 6858 res |= (d >> (cnt)) & mask; 6859 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF); 6860 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF); 6861 } else if (s != 0) { 6862 /* set the new carry flag, Note that it is the low order bit 6863 * of the result!!! */ 6864 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF); 6865 } 6866 return (uint16_t) res; 6867 } 6868 /**************************************************************************** 6869 REMARKS: 6870 Implements the ROR instruction and side effects. 6871 ****************************************************************************/ 6872 static uint32_t 6873 ror_long(struct X86EMU *emu, uint32_t d, uint8_t s) 6874 { 6875 uint32_t res, cnt, mask; 6876 6877 res = d; 6878 if ((cnt = s % 32) != 0) { 6879 res = (d << (32 - cnt)); 6880 mask = (1 << (32 - cnt)) - 1; 6881 res |= (d >> (cnt)) & mask; 6882 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF); 6883 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF); 6884 } else if (s != 0) { 6885 /* set the new carry flag, Note that it is the low order bit 6886 * of the result!!! */ 6887 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF); 6888 } 6889 return res; 6890 } 6891 /**************************************************************************** 6892 REMARKS: 6893 Implements the SHL instruction and side effects. 6894 ****************************************************************************/ 6895 static uint8_t 6896 shl_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6897 { 6898 unsigned int cnt, res, cf; 6899 6900 if (s < 8) { 6901 cnt = s % 8; 6902 6903 /* last bit shifted out goes into carry flag */ 6904 if (cnt > 0) { 6905 res = d << cnt; 6906 cf = d & (1 << (8 - cnt)); 6907 CONDITIONAL_SET_FLAG(cf, F_CF); 6908 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6909 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6910 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6911 } else { 6912 res = (uint8_t) d; 6913 } 6914 6915 if (cnt == 1) { 6916 /* Needs simplification. */ 6917 CONDITIONAL_SET_FLAG( 6918 (((res & 0x80) == 0x80) ^ 6919 (ACCESS_FLAG(F_CF) != 0)), 6920 /* was (emu->x86.R_FLG&F_CF)==F_CF)), */ 6921 F_OF); 6922 } else { 6923 CLEAR_FLAG(F_OF); 6924 } 6925 } else { 6926 res = 0; 6927 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF); 6928 CLEAR_FLAG(F_OF); 6929 CLEAR_FLAG(F_SF); 6930 SET_FLAG(F_PF); 6931 SET_FLAG(F_ZF); 6932 } 6933 return (uint8_t) res; 6934 } 6935 /**************************************************************************** 6936 REMARKS: 6937 Implements the SHL instruction and side effects. 6938 ****************************************************************************/ 6939 static uint16_t 6940 shl_word(struct X86EMU *emu, uint16_t d, uint8_t s) 6941 { 6942 unsigned int cnt, res, cf; 6943 6944 if (s < 16) { 6945 cnt = s % 16; 6946 if (cnt > 0) { 6947 res = d << cnt; 6948 cf = d & (1 << (16 - cnt)); 6949 CONDITIONAL_SET_FLAG(cf, F_CF); 6950 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6951 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6952 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6953 } else { 6954 res = (uint16_t) d; 6955 } 6956 6957 if (cnt == 1) { 6958 CONDITIONAL_SET_FLAG( 6959 (((res & 0x8000) == 0x8000) ^ 6960 (ACCESS_FLAG(F_CF) != 0)), 6961 F_OF); 6962 } else { 6963 CLEAR_FLAG(F_OF); 6964 } 6965 } else { 6966 res = 0; 6967 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF); 6968 CLEAR_FLAG(F_OF); 6969 CLEAR_FLAG(F_SF); 6970 SET_FLAG(F_PF); 6971 SET_FLAG(F_ZF); 6972 } 6973 return (uint16_t) res; 6974 } 6975 /**************************************************************************** 6976 REMARKS: 6977 Implements the SHL instruction and side effects. 6978 ****************************************************************************/ 6979 static uint32_t 6980 shl_long(struct X86EMU *emu, uint32_t d, uint8_t s) 6981 { 6982 unsigned int cnt, res, cf; 6983 6984 if (s < 32) { 6985 cnt = s % 32; 6986 if (cnt > 0) { 6987 res = d << cnt; 6988 cf = d & (1 << (32 - cnt)); 6989 CONDITIONAL_SET_FLAG(cf, F_CF); 6990 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6991 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6992 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6993 } else { 6994 res = d; 6995 } 6996 if (cnt == 1) { 6997 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^ 6998 (ACCESS_FLAG(F_CF) != 0)), F_OF); 6999 } else { 7000 CLEAR_FLAG(F_OF); 7001 } 7002 } else { 7003 res = 0; 7004 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF); 7005 CLEAR_FLAG(F_OF); 7006 CLEAR_FLAG(F_SF); 7007 SET_FLAG(F_PF); 7008 SET_FLAG(F_ZF); 7009 } 7010 return res; 7011 } 7012 /**************************************************************************** 7013 REMARKS: 7014 Implements the SHR instruction and side effects. 7015 ****************************************************************************/ 7016 static uint8_t 7017 shr_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 7018 { 7019 unsigned int cnt, res, cf; 7020 7021 if (s < 8) { 7022 cnt = s % 8; 7023 if (cnt > 0) { 7024 cf = d & (1 << (cnt - 1)); 7025 res = d >> cnt; 7026 CONDITIONAL_SET_FLAG(cf, F_CF); 7027 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7028 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7029 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7030 } else { 7031 res = (uint8_t) d; 7032 } 7033 7034 if (cnt == 1) { 7035 CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF); 7036 } else { 7037 CLEAR_FLAG(F_OF); 7038 } 7039 } else { 7040 res = 0; 7041 CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF); 7042 CLEAR_FLAG(F_OF); 7043 CLEAR_FLAG(F_SF); 7044 SET_FLAG(F_PF); 7045 SET_FLAG(F_ZF); 7046 } 7047 return (uint8_t) res; 7048 } 7049 /**************************************************************************** 7050 REMARKS: 7051 Implements the SHR instruction and side effects. 7052 ****************************************************************************/ 7053 static uint16_t 7054 shr_word(struct X86EMU *emu, uint16_t d, uint8_t s) 7055 { 7056 unsigned int cnt, res, cf; 7057 7058 if (s < 16) { 7059 cnt = s % 16; 7060 if (cnt > 0) { 7061 cf = d & (1 << (cnt - 1)); 7062 res = d >> cnt; 7063 CONDITIONAL_SET_FLAG(cf, F_CF); 7064 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7065 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7066 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7067 } else { 7068 res = d; 7069 } 7070 7071 if (cnt == 1) { 7072 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF); 7073 } else { 7074 CLEAR_FLAG(F_OF); 7075 } 7076 } else { 7077 res = 0; 7078 CLEAR_FLAG(F_CF); 7079 CLEAR_FLAG(F_OF); 7080 SET_FLAG(F_ZF); 7081 CLEAR_FLAG(F_SF); 7082 CLEAR_FLAG(F_PF); 7083 } 7084 return (uint16_t) res; 7085 } 7086 /**************************************************************************** 7087 REMARKS: 7088 Implements the SHR instruction and side effects. 7089 ****************************************************************************/ 7090 static uint32_t 7091 shr_long(struct X86EMU *emu, uint32_t d, uint8_t s) 7092 { 7093 unsigned int cnt, res, cf; 7094 7095 if (s < 32) { 7096 cnt = s % 32; 7097 if (cnt > 0) { 7098 cf = d & (1 << (cnt - 1)); 7099 res = d >> cnt; 7100 CONDITIONAL_SET_FLAG(cf, F_CF); 7101 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7102 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7103 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7104 } else { 7105 res = d; 7106 } 7107 if (cnt == 1) { 7108 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF); 7109 } else { 7110 CLEAR_FLAG(F_OF); 7111 } 7112 } else { 7113 res = 0; 7114 CLEAR_FLAG(F_CF); 7115 CLEAR_FLAG(F_OF); 7116 SET_FLAG(F_ZF); 7117 CLEAR_FLAG(F_SF); 7118 CLEAR_FLAG(F_PF); 7119 } 7120 return res; 7121 } 7122 /**************************************************************************** 7123 REMARKS: 7124 Implements the SAR instruction and side effects. 7125 ****************************************************************************/ 7126 static uint8_t 7127 sar_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 7128 { 7129 unsigned int cnt, res, cf, mask, sf; 7130 7131 res = d; 7132 sf = d & 0x80; 7133 cnt = s % 8; 7134 if (cnt > 0 && cnt < 8) { 7135 mask = (1 << (8 - cnt)) - 1; 7136 cf = d & (1 << (cnt - 1)); 7137 res = (d >> cnt) & mask; 7138 CONDITIONAL_SET_FLAG(cf, F_CF); 7139 if (sf) { 7140 res |= ~mask; 7141 } 7142 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7143 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7144 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7145 } else if (cnt >= 8) { 7146 if (sf) { 7147 res = 0xff; 7148 SET_FLAG(F_CF); 7149 CLEAR_FLAG(F_ZF); 7150 SET_FLAG(F_SF); 7151 SET_FLAG(F_PF); 7152 } else { 7153 res = 0; 7154 CLEAR_FLAG(F_CF); 7155 SET_FLAG(F_ZF); 7156 CLEAR_FLAG(F_SF); 7157 CLEAR_FLAG(F_PF); 7158 } 7159 } 7160 return (uint8_t) res; 7161 } 7162 /**************************************************************************** 7163 REMARKS: 7164 Implements the SAR instruction and side effects. 7165 ****************************************************************************/ 7166 static uint16_t 7167 sar_word(struct X86EMU *emu, uint16_t d, uint8_t s) 7168 { 7169 unsigned int cnt, res, cf, mask, sf; 7170 7171 sf = d & 0x8000; 7172 cnt = s % 16; 7173 res = d; 7174 if (cnt > 0 && cnt < 16) { 7175 mask = (1 << (16 - cnt)) - 1; 7176 cf = d & (1 << (cnt - 1)); 7177 res = (d >> cnt) & mask; 7178 CONDITIONAL_SET_FLAG(cf, F_CF); 7179 if (sf) { 7180 res |= ~mask; 7181 } 7182 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7183 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7184 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7185 } else if (cnt >= 16) { 7186 if (sf) { 7187 res = 0xffff; 7188 SET_FLAG(F_CF); 7189 CLEAR_FLAG(F_ZF); 7190 SET_FLAG(F_SF); 7191 SET_FLAG(F_PF); 7192 } else { 7193 res = 0; 7194 CLEAR_FLAG(F_CF); 7195 SET_FLAG(F_ZF); 7196 CLEAR_FLAG(F_SF); 7197 CLEAR_FLAG(F_PF); 7198 } 7199 } 7200 return (uint16_t) res; 7201 } 7202 /**************************************************************************** 7203 REMARKS: 7204 Implements the SAR instruction and side effects. 7205 ****************************************************************************/ 7206 static uint32_t 7207 sar_long(struct X86EMU *emu, uint32_t d, uint8_t s) 7208 { 7209 uint32_t cnt, res, cf, mask, sf; 7210 7211 sf = d & 0x80000000; 7212 cnt = s % 32; 7213 res = d; 7214 if (cnt > 0 && cnt < 32) { 7215 mask = (1 << (32 - cnt)) - 1; 7216 cf = d & (1 << (cnt - 1)); 7217 res = (d >> cnt) & mask; 7218 CONDITIONAL_SET_FLAG(cf, F_CF); 7219 if (sf) { 7220 res |= ~mask; 7221 } 7222 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7223 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7224 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7225 } else if (cnt >= 32) { 7226 if (sf) { 7227 res = 0xffffffff; 7228 SET_FLAG(F_CF); 7229 CLEAR_FLAG(F_ZF); 7230 SET_FLAG(F_SF); 7231 SET_FLAG(F_PF); 7232 } else { 7233 res = 0; 7234 CLEAR_FLAG(F_CF); 7235 SET_FLAG(F_ZF); 7236 CLEAR_FLAG(F_SF); 7237 CLEAR_FLAG(F_PF); 7238 } 7239 } 7240 return res; 7241 } 7242 /**************************************************************************** 7243 REMARKS: 7244 Implements the SHLD instruction and side effects. 7245 ****************************************************************************/ 7246 static uint16_t 7247 shld_word(struct X86EMU *emu, uint16_t d, uint16_t fill, uint8_t s) 7248 { 7249 unsigned int cnt, res, cf; 7250 7251 if (s < 16) { 7252 cnt = s % 16; 7253 if (cnt > 0) { 7254 res = (d << cnt) | (fill >> (16 - cnt)); 7255 cf = d & (1 << (16 - cnt)); 7256 CONDITIONAL_SET_FLAG(cf, F_CF); 7257 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7258 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7259 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7260 } else { 7261 res = d; 7262 } 7263 if (cnt == 1) { 7264 CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^ 7265 (ACCESS_FLAG(F_CF) != 0)), F_OF); 7266 } else { 7267 CLEAR_FLAG(F_OF); 7268 } 7269 } else { 7270 res = 0; 7271 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF); 7272 CLEAR_FLAG(F_OF); 7273 CLEAR_FLAG(F_SF); 7274 SET_FLAG(F_PF); 7275 SET_FLAG(F_ZF); 7276 } 7277 return (uint16_t) res; 7278 } 7279 /**************************************************************************** 7280 REMARKS: 7281 Implements the SHLD instruction and side effects. 7282 ****************************************************************************/ 7283 static uint32_t 7284 shld_long(struct X86EMU *emu, uint32_t d, uint32_t fill, uint8_t s) 7285 { 7286 unsigned int cnt, res, cf; 7287 7288 if (s < 32) { 7289 cnt = s % 32; 7290 if (cnt > 0) { 7291 res = (d << cnt) | (fill >> (32 - cnt)); 7292 cf = d & (1 << (32 - cnt)); 7293 CONDITIONAL_SET_FLAG(cf, F_CF); 7294 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7295 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7296 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7297 } else { 7298 res = d; 7299 } 7300 if (cnt == 1) { 7301 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^ 7302 (ACCESS_FLAG(F_CF) != 0)), F_OF); 7303 } else { 7304 CLEAR_FLAG(F_OF); 7305 } 7306 } else { 7307 res = 0; 7308 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF); 7309 CLEAR_FLAG(F_OF); 7310 CLEAR_FLAG(F_SF); 7311 SET_FLAG(F_PF); 7312 SET_FLAG(F_ZF); 7313 } 7314 return res; 7315 } 7316 /**************************************************************************** 7317 REMARKS: 7318 Implements the SHRD instruction and side effects. 7319 ****************************************************************************/ 7320 static uint16_t 7321 shrd_word(struct X86EMU *emu, uint16_t d, uint16_t fill, uint8_t s) 7322 { 7323 unsigned int cnt, res, cf; 7324 7325 if (s < 16) { 7326 cnt = s % 16; 7327 if (cnt > 0) { 7328 cf = d & (1 << (cnt - 1)); 7329 res = (d >> cnt) | (fill << (16 - cnt)); 7330 CONDITIONAL_SET_FLAG(cf, F_CF); 7331 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7332 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7333 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7334 } else { 7335 res = d; 7336 } 7337 7338 if (cnt == 1) { 7339 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF); 7340 } else { 7341 CLEAR_FLAG(F_OF); 7342 } 7343 } else { 7344 res = 0; 7345 CLEAR_FLAG(F_CF); 7346 CLEAR_FLAG(F_OF); 7347 SET_FLAG(F_ZF); 7348 CLEAR_FLAG(F_SF); 7349 CLEAR_FLAG(F_PF); 7350 } 7351 return (uint16_t) res; 7352 } 7353 /**************************************************************************** 7354 REMARKS: 7355 Implements the SHRD instruction and side effects. 7356 ****************************************************************************/ 7357 static uint32_t 7358 shrd_long(struct X86EMU *emu, uint32_t d, uint32_t fill, uint8_t s) 7359 { 7360 unsigned int cnt, res, cf; 7361 7362 if (s < 32) { 7363 cnt = s % 32; 7364 if (cnt > 0) { 7365 cf = d & (1 << (cnt - 1)); 7366 res = (d >> cnt) | (fill << (32 - cnt)); 7367 CONDITIONAL_SET_FLAG(cf, F_CF); 7368 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7369 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7370 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7371 } else { 7372 res = d; 7373 } 7374 if (cnt == 1) { 7375 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF); 7376 } else { 7377 CLEAR_FLAG(F_OF); 7378 } 7379 } else { 7380 res = 0; 7381 CLEAR_FLAG(F_CF); 7382 CLEAR_FLAG(F_OF); 7383 SET_FLAG(F_ZF); 7384 CLEAR_FLAG(F_SF); 7385 CLEAR_FLAG(F_PF); 7386 } 7387 return res; 7388 } 7389 /**************************************************************************** 7390 REMARKS: 7391 Implements the SBB instruction and side effects. 7392 ****************************************************************************/ 7393 static uint8_t 7394 sbb_byte(struct X86EMU *emu, uint8_t d, uint8_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 & 0x80, F_SF); 7404 CONDITIONAL_SET_FLAG((res & 0xff) == 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 & 0x80, F_CF); 7410 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 7411 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7412 return (uint8_t) res; 7413 } 7414 /**************************************************************************** 7415 REMARKS: 7416 Implements the SBB instruction and side effects. 7417 ****************************************************************************/ 7418 static uint16_t 7419 sbb_word(struct X86EMU *emu, uint16_t d, uint16_t s) 7420 { 7421 uint32_t res; /* all operands in native machine order */ 7422 uint32_t bc; 7423 7424 if (ACCESS_FLAG(F_CF)) 7425 res = d - s - 1; 7426 else 7427 res = d - s; 7428 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7429 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7430 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7431 7432 /* calculate the borrow chain. See note at top */ 7433 bc = (res & (~d | s)) | (~d & s); 7434 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 7435 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 7436 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7437 return (uint16_t) res; 7438 } 7439 /**************************************************************************** 7440 REMARKS: 7441 Implements the SBB instruction and side effects. 7442 ****************************************************************************/ 7443 static uint32_t 7444 sbb_long(struct X86EMU *emu, uint32_t d, uint32_t s) 7445 { 7446 uint32_t res; /* all operands in native machine order */ 7447 uint32_t bc; 7448 7449 if (ACCESS_FLAG(F_CF)) 7450 res = d - s - 1; 7451 else 7452 res = d - s; 7453 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7454 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7455 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7456 7457 /* calculate the borrow chain. See note at top */ 7458 bc = (res & (~d | s)) | (~d & s); 7459 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 7460 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 7461 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7462 return res; 7463 } 7464 /**************************************************************************** 7465 REMARKS: 7466 Implements the SUB instruction and side effects. 7467 ****************************************************************************/ 7468 static uint8_t 7469 sub_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 7470 { 7471 uint32_t res; /* all operands in native machine order */ 7472 uint32_t bc; 7473 7474 res = d - s; 7475 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7476 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7477 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7478 7479 /* calculate the borrow chain. See note at top */ 7480 bc = (res & (~d | s)) | (~d & s); 7481 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); 7482 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 7483 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7484 return (uint8_t) res; 7485 } 7486 /**************************************************************************** 7487 REMARKS: 7488 Implements the SUB instruction and side effects. 7489 ****************************************************************************/ 7490 static uint16_t 7491 sub_word(struct X86EMU *emu, uint16_t d, uint16_t s) 7492 { 7493 uint32_t res; /* all operands in native machine order */ 7494 uint32_t bc; 7495 7496 res = d - s; 7497 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7498 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7499 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7500 7501 /* calculate the borrow chain. See note at top */ 7502 bc = (res & (~d | s)) | (~d & s); 7503 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 7504 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 7505 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7506 return (uint16_t) res; 7507 } 7508 /**************************************************************************** 7509 REMARKS: 7510 Implements the SUB instruction and side effects. 7511 ****************************************************************************/ 7512 static uint32_t 7513 sub_long(struct X86EMU *emu, uint32_t d, uint32_t s) 7514 { 7515 uint32_t res; /* all operands in native machine order */ 7516 uint32_t bc; 7517 7518 res = d - s; 7519 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7520 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7521 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7522 7523 /* calculate the borrow chain. See note at top */ 7524 bc = (res & (~d | s)) | (~d & s); 7525 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 7526 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 7527 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7528 return res; 7529 } 7530 /**************************************************************************** 7531 REMARKS: 7532 Implements the TEST instruction and side effects. 7533 ****************************************************************************/ 7534 static void 7535 test_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 7536 { 7537 uint32_t res; /* all operands in native machine order */ 7538 7539 res = d & s; 7540 7541 CLEAR_FLAG(F_OF); 7542 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7543 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7544 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7545 /* AF == dont care */ 7546 CLEAR_FLAG(F_CF); 7547 } 7548 /**************************************************************************** 7549 REMARKS: 7550 Implements the TEST instruction and side effects. 7551 ****************************************************************************/ 7552 static void 7553 test_word(struct X86EMU *emu, uint16_t d, uint16_t s) 7554 { 7555 uint32_t res; /* all operands in native machine order */ 7556 7557 res = d & s; 7558 7559 CLEAR_FLAG(F_OF); 7560 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7561 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7562 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7563 /* AF == dont care */ 7564 CLEAR_FLAG(F_CF); 7565 } 7566 /**************************************************************************** 7567 REMARKS: 7568 Implements the TEST instruction and side effects. 7569 ****************************************************************************/ 7570 static void 7571 test_long(struct X86EMU *emu, uint32_t d, uint32_t s) 7572 { 7573 uint32_t res; /* all operands in native machine order */ 7574 7575 res = d & s; 7576 7577 CLEAR_FLAG(F_OF); 7578 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7579 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7580 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7581 /* AF == dont care */ 7582 CLEAR_FLAG(F_CF); 7583 } 7584 /**************************************************************************** 7585 REMARKS: 7586 Implements the XOR instruction and side effects. 7587 ****************************************************************************/ 7588 static uint8_t 7589 xor_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 7590 { 7591 uint8_t res; /* all operands in native machine order */ 7592 7593 res = d ^ s; 7594 CLEAR_FLAG(F_OF); 7595 CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7596 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7597 CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 7598 CLEAR_FLAG(F_CF); 7599 CLEAR_FLAG(F_AF); 7600 return res; 7601 } 7602 /**************************************************************************** 7603 REMARKS: 7604 Implements the XOR instruction and side effects. 7605 ****************************************************************************/ 7606 static uint16_t 7607 xor_word(struct X86EMU *emu, uint16_t d, uint16_t s) 7608 { 7609 uint16_t res; /* all operands in native machine order */ 7610 7611 res = d ^ s; 7612 CLEAR_FLAG(F_OF); 7613 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7614 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7615 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7616 CLEAR_FLAG(F_CF); 7617 CLEAR_FLAG(F_AF); 7618 return res; 7619 } 7620 /**************************************************************************** 7621 REMARKS: 7622 Implements the XOR instruction and side effects. 7623 ****************************************************************************/ 7624 static uint32_t 7625 xor_long(struct X86EMU *emu, uint32_t d, uint32_t s) 7626 { 7627 uint32_t res; /* all operands in native machine order */ 7628 7629 res = d ^ s; 7630 CLEAR_FLAG(F_OF); 7631 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7632 CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7633 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7634 CLEAR_FLAG(F_CF); 7635 CLEAR_FLAG(F_AF); 7636 return res; 7637 } 7638 /**************************************************************************** 7639 REMARKS: 7640 Implements the IMUL instruction and side effects. 7641 ****************************************************************************/ 7642 static void 7643 imul_byte(struct X86EMU *emu, uint8_t s) 7644 { 7645 int16_t res = (int16_t) ((int8_t) emu->x86.R_AL * (int8_t) s); 7646 7647 emu->x86.R_AX = res; 7648 if (((emu->x86.R_AL & 0x80) == 0 && emu->x86.R_AH == 0x00) || 7649 ((emu->x86.R_AL & 0x80) != 0 && emu->x86.R_AH == 0xFF)) { 7650 CLEAR_FLAG(F_CF); 7651 CLEAR_FLAG(F_OF); 7652 } else { 7653 SET_FLAG(F_CF); 7654 SET_FLAG(F_OF); 7655 } 7656 } 7657 /**************************************************************************** 7658 REMARKS: 7659 Implements the IMUL instruction and side effects. 7660 ****************************************************************************/ 7661 static void 7662 imul_word(struct X86EMU *emu, uint16_t s) 7663 { 7664 int32_t res = (int16_t) emu->x86.R_AX * (int16_t) s; 7665 7666 emu->x86.R_AX = (uint16_t) res; 7667 emu->x86.R_DX = (uint16_t) (res >> 16); 7668 if (((emu->x86.R_AX & 0x8000) == 0 && emu->x86.R_DX == 0x00) || 7669 ((emu->x86.R_AX & 0x8000) != 0 && emu->x86.R_DX == 0xFF)) { 7670 CLEAR_FLAG(F_CF); 7671 CLEAR_FLAG(F_OF); 7672 } else { 7673 SET_FLAG(F_CF); 7674 SET_FLAG(F_OF); 7675 } 7676 } 7677 /**************************************************************************** 7678 REMARKS: 7679 Implements the IMUL instruction and side effects. 7680 ****************************************************************************/ 7681 static void 7682 imul_long(struct X86EMU *emu, uint32_t s) 7683 { 7684 int64_t res; 7685 7686 res = (int64_t)(int32_t)emu->x86.R_EAX * (int32_t)s; 7687 emu->x86.R_EAX = (uint32_t)res; 7688 emu->x86.R_EDX = ((uint64_t)res) >> 32; 7689 if (((emu->x86.R_EAX & 0x80000000) == 0 && emu->x86.R_EDX == 0x00) || 7690 ((emu->x86.R_EAX & 0x80000000) != 0 && emu->x86.R_EDX == 0xFF)) { 7691 CLEAR_FLAG(F_CF); 7692 CLEAR_FLAG(F_OF); 7693 } else { 7694 SET_FLAG(F_CF); 7695 SET_FLAG(F_OF); 7696 } 7697 } 7698 /**************************************************************************** 7699 REMARKS: 7700 Implements the MUL instruction and side effects. 7701 ****************************************************************************/ 7702 static void 7703 mul_byte(struct X86EMU *emu, uint8_t s) 7704 { 7705 uint16_t res = (uint16_t) (emu->x86.R_AL * s); 7706 7707 emu->x86.R_AX = res; 7708 if (emu->x86.R_AH == 0) { 7709 CLEAR_FLAG(F_CF); 7710 CLEAR_FLAG(F_OF); 7711 } else { 7712 SET_FLAG(F_CF); 7713 SET_FLAG(F_OF); 7714 } 7715 } 7716 /**************************************************************************** 7717 REMARKS: 7718 Implements the MUL instruction and side effects. 7719 ****************************************************************************/ 7720 static void 7721 mul_word(struct X86EMU *emu, uint16_t s) 7722 { 7723 uint32_t res = emu->x86.R_AX * s; 7724 7725 emu->x86.R_AX = (uint16_t) res; 7726 emu->x86.R_DX = (uint16_t) (res >> 16); 7727 if (emu->x86.R_DX == 0) { 7728 CLEAR_FLAG(F_CF); 7729 CLEAR_FLAG(F_OF); 7730 } else { 7731 SET_FLAG(F_CF); 7732 SET_FLAG(F_OF); 7733 } 7734 } 7735 /**************************************************************************** 7736 REMARKS: 7737 Implements the MUL instruction and side effects. 7738 ****************************************************************************/ 7739 static void 7740 mul_long(struct X86EMU *emu, uint32_t s) 7741 { 7742 uint64_t res = (uint64_t) emu->x86.R_EAX * s; 7743 7744 emu->x86.R_EAX = (uint32_t) res; 7745 emu->x86.R_EDX = (uint32_t) (res >> 32); 7746 7747 if (emu->x86.R_EDX == 0) { 7748 CLEAR_FLAG(F_CF); 7749 CLEAR_FLAG(F_OF); 7750 } else { 7751 SET_FLAG(F_CF); 7752 SET_FLAG(F_OF); 7753 } 7754 } 7755 /**************************************************************************** 7756 REMARKS: 7757 Implements the IDIV instruction and side effects. 7758 ****************************************************************************/ 7759 static void 7760 idiv_byte(struct X86EMU *emu, uint8_t s) 7761 { 7762 int32_t dvd, div, mod; 7763 7764 dvd = (int16_t) emu->x86.R_AX; 7765 if (s == 0) { 7766 x86emu_intr_raise(emu, 8); 7767 return; 7768 } 7769 div = dvd / (int8_t) s; 7770 mod = dvd % (int8_t) s; 7771 if (div > 0x7f || div < -0x7f) { 7772 x86emu_intr_raise(emu, 8); 7773 return; 7774 } 7775 emu->x86.R_AL = (int8_t) div; 7776 emu->x86.R_AH = (int8_t) mod; 7777 } 7778 /**************************************************************************** 7779 REMARKS: 7780 Implements the IDIV instruction and side effects. 7781 ****************************************************************************/ 7782 static void 7783 idiv_word(struct X86EMU *emu, uint16_t s) 7784 { 7785 int32_t dvd, div, mod; 7786 7787 dvd = (((int32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX; 7788 if (s == 0) { 7789 x86emu_intr_raise(emu, 8); 7790 return; 7791 } 7792 div = dvd / (int16_t) s; 7793 mod = dvd % (int16_t) s; 7794 if (div > 0x7fff || div < -0x7fff) { 7795 x86emu_intr_raise(emu, 8); 7796 return; 7797 } 7798 CLEAR_FLAG(F_CF); 7799 CLEAR_FLAG(F_SF); 7800 CONDITIONAL_SET_FLAG(div == 0, F_ZF); 7801 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 7802 7803 emu->x86.R_AX = (uint16_t) div; 7804 emu->x86.R_DX = (uint16_t) mod; 7805 } 7806 /**************************************************************************** 7807 REMARKS: 7808 Implements the IDIV instruction and side effects. 7809 ****************************************************************************/ 7810 static void 7811 idiv_long(struct X86EMU *emu, uint32_t s) 7812 { 7813 int64_t dvd, div, mod; 7814 7815 dvd = (((int64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX; 7816 if (s == 0) { 7817 x86emu_intr_raise(emu, 8); 7818 return; 7819 } 7820 div = dvd / (int32_t) s; 7821 mod = dvd % (int32_t) s; 7822 if (div > 0x7fffffff || div < -0x7fffffff) { 7823 x86emu_intr_raise(emu, 8); 7824 return; 7825 } 7826 CLEAR_FLAG(F_CF); 7827 CLEAR_FLAG(F_AF); 7828 CLEAR_FLAG(F_SF); 7829 SET_FLAG(F_ZF); 7830 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 7831 7832 emu->x86.R_EAX = (uint32_t) div; 7833 emu->x86.R_EDX = (uint32_t) mod; 7834 } 7835 /**************************************************************************** 7836 REMARKS: 7837 Implements the DIV instruction and side effects. 7838 ****************************************************************************/ 7839 static void 7840 div_byte(struct X86EMU *emu, uint8_t s) 7841 { 7842 uint32_t dvd, div, mod; 7843 7844 dvd = emu->x86.R_AX; 7845 if (s == 0) { 7846 x86emu_intr_raise(emu, 8); 7847 return; 7848 } 7849 div = dvd / (uint8_t) s; 7850 mod = dvd % (uint8_t) s; 7851 if (div > 0xff) { 7852 x86emu_intr_raise(emu, 8); 7853 return; 7854 } 7855 emu->x86.R_AL = (uint8_t) div; 7856 emu->x86.R_AH = (uint8_t) mod; 7857 } 7858 /**************************************************************************** 7859 REMARKS: 7860 Implements the DIV instruction and side effects. 7861 ****************************************************************************/ 7862 static void 7863 div_word(struct X86EMU *emu, uint16_t s) 7864 { 7865 uint32_t dvd, div, mod; 7866 7867 dvd = (((uint32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX; 7868 if (s == 0) { 7869 x86emu_intr_raise(emu, 8); 7870 return; 7871 } 7872 div = dvd / (uint16_t) s; 7873 mod = dvd % (uint16_t) s; 7874 if (div > 0xffff) { 7875 x86emu_intr_raise(emu, 8); 7876 return; 7877 } 7878 CLEAR_FLAG(F_CF); 7879 CLEAR_FLAG(F_SF); 7880 CONDITIONAL_SET_FLAG(div == 0, F_ZF); 7881 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 7882 7883 emu->x86.R_AX = (uint16_t) div; 7884 emu->x86.R_DX = (uint16_t) mod; 7885 } 7886 /**************************************************************************** 7887 REMARKS: 7888 Implements the DIV instruction and side effects. 7889 ****************************************************************************/ 7890 static void 7891 div_long(struct X86EMU *emu, uint32_t s) 7892 { 7893 uint64_t dvd, div, mod; 7894 7895 dvd = (((uint64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX; 7896 if (s == 0) { 7897 x86emu_intr_raise(emu, 8); 7898 return; 7899 } 7900 div = dvd / (uint32_t) s; 7901 mod = dvd % (uint32_t) s; 7902 if (div > 0xffffffff) { 7903 x86emu_intr_raise(emu, 8); 7904 return; 7905 } 7906 CLEAR_FLAG(F_CF); 7907 CLEAR_FLAG(F_AF); 7908 CLEAR_FLAG(F_SF); 7909 SET_FLAG(F_ZF); 7910 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 7911 7912 emu->x86.R_EAX = (uint32_t) div; 7913 emu->x86.R_EDX = (uint32_t) mod; 7914 } 7915 /**************************************************************************** 7916 REMARKS: 7917 Implements the IN string instruction and side effects. 7918 ****************************************************************************/ 7919 static void 7920 ins(struct X86EMU *emu, int size) 7921 { 7922 int inc = size; 7923 7924 if (ACCESS_FLAG(F_DF)) { 7925 inc = -size; 7926 } 7927 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 7928 /* dont care whether REPE or REPNE */ 7929 /* in until CX is ZERO. */ 7930 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ? 7931 emu->x86.R_ECX : emu->x86.R_CX); 7932 switch (size) { 7933 case 1: 7934 while (count--) { 7935 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, 7936 (*emu->emu_inb) (emu, emu->x86.R_DX)); 7937 emu->x86.R_DI += inc; 7938 } 7939 break; 7940 7941 case 2: 7942 while (count--) { 7943 store_word(emu, emu->x86.R_ES, emu->x86.R_DI, 7944 (*emu->emu_inw) (emu, emu->x86.R_DX)); 7945 emu->x86.R_DI += inc; 7946 } 7947 break; 7948 case 4: 7949 while (count--) { 7950 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, 7951 (*emu->emu_inl) (emu, emu->x86.R_DX)); 7952 emu->x86.R_DI += inc; 7953 break; 7954 } 7955 } 7956 emu->x86.R_CX = 0; 7957 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 7958 emu->x86.R_ECX = 0; 7959 } 7960 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 7961 } else { 7962 switch (size) { 7963 case 1: 7964 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, 7965 (*emu->emu_inb) (emu, emu->x86.R_DX)); 7966 break; 7967 case 2: 7968 store_word(emu, emu->x86.R_ES, emu->x86.R_DI, 7969 (*emu->emu_inw) (emu, emu->x86.R_DX)); 7970 break; 7971 case 4: 7972 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, 7973 (*emu->emu_inl) (emu, emu->x86.R_DX)); 7974 break; 7975 } 7976 emu->x86.R_DI += inc; 7977 } 7978 } 7979 /**************************************************************************** 7980 REMARKS: 7981 Implements the OUT string instruction and side effects. 7982 ****************************************************************************/ 7983 static void 7984 outs(struct X86EMU *emu, int size) 7985 { 7986 int inc = size; 7987 7988 if (ACCESS_FLAG(F_DF)) { 7989 inc = -size; 7990 } 7991 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 7992 /* dont care whether REPE or REPNE */ 7993 /* out until CX is ZERO. */ 7994 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ? 7995 emu->x86.R_ECX : emu->x86.R_CX); 7996 switch (size) { 7997 case 1: 7998 while (count--) { 7999 (*emu->emu_outb) (emu, emu->x86.R_DX, 8000 fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI)); 8001 emu->x86.R_SI += inc; 8002 } 8003 break; 8004 8005 case 2: 8006 while (count--) { 8007 (*emu->emu_outw) (emu, emu->x86.R_DX, 8008 fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI)); 8009 emu->x86.R_SI += inc; 8010 } 8011 break; 8012 case 4: 8013 while (count--) { 8014 (*emu->emu_outl) (emu, emu->x86.R_DX, 8015 fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI)); 8016 emu->x86.R_SI += inc; 8017 break; 8018 } 8019 } 8020 emu->x86.R_CX = 0; 8021 if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 8022 emu->x86.R_ECX = 0; 8023 } 8024 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 8025 } else { 8026 switch (size) { 8027 case 1: 8028 (*emu->emu_outb) (emu, emu->x86.R_DX, 8029 fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI)); 8030 break; 8031 case 2: 8032 (*emu->emu_outw) (emu, emu->x86.R_DX, 8033 fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI)); 8034 break; 8035 case 4: 8036 (*emu->emu_outl) (emu, emu->x86.R_DX, 8037 fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI)); 8038 break; 8039 } 8040 emu->x86.R_SI += inc; 8041 } 8042 } 8043 /**************************************************************************** 8044 REMARKS: 8045 Pushes a word onto the stack. 8046 8047 NOTE: Do not inline this, as (*emu->emu_wrX) is already inline! 8048 ****************************************************************************/ 8049 static void 8050 push_word(struct X86EMU *emu, uint16_t w) 8051 { 8052 emu->x86.R_SP -= 2; 8053 store_word(emu, emu->x86.R_SS, emu->x86.R_SP, w); 8054 } 8055 /**************************************************************************** 8056 REMARKS: 8057 Pushes a long onto the stack. 8058 8059 NOTE: Do not inline this, as (*emu->emu_wrX) is already inline! 8060 ****************************************************************************/ 8061 static void 8062 push_long(struct X86EMU *emu, uint32_t w) 8063 { 8064 emu->x86.R_SP -= 4; 8065 store_long(emu, emu->x86.R_SS, emu->x86.R_SP, w); 8066 } 8067 /**************************************************************************** 8068 REMARKS: 8069 Pops a word from the stack. 8070 8071 NOTE: Do not inline this, as (*emu->emu_rdX) is already inline! 8072 ****************************************************************************/ 8073 static uint16_t 8074 pop_word(struct X86EMU *emu) 8075 { 8076 uint16_t res; 8077 8078 res = fetch_word(emu, emu->x86.R_SS, emu->x86.R_SP); 8079 emu->x86.R_SP += 2; 8080 return res; 8081 } 8082 /**************************************************************************** 8083 REMARKS: 8084 Pops a long from the stack. 8085 8086 NOTE: Do not inline this, as (*emu->emu_rdX) is already inline! 8087 ****************************************************************************/ 8088 static uint32_t 8089 pop_long(struct X86EMU *emu) 8090 { 8091 uint32_t res; 8092 8093 res = fetch_long(emu, emu->x86.R_SS, emu->x86.R_SP); 8094 emu->x86.R_SP += 4; 8095 return res; 8096 } 8097