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