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