x86emu.c revision 197009
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 38static void x86emu_intr_raise (struct x86emu *, uint8_t type); 39 40static void x86emu_exec_one_byte(struct x86emu *); 41static void x86emu_exec_two_byte(struct x86emu *); 42 43static void fetch_decode_modrm (struct x86emu *); 44static uint8_t fetch_byte_imm (struct x86emu *); 45static uint16_t fetch_word_imm (struct x86emu *); 46static uint32_t fetch_long_imm (struct x86emu *); 47static uint8_t fetch_data_byte (struct x86emu *, uint32_t offset); 48static uint8_t fetch_byte (struct x86emu *, uint segment, uint32_t offset); 49static uint16_t fetch_data_word (struct x86emu *, uint32_t offset); 50static uint16_t fetch_word (struct x86emu *, uint32_t segment, uint32_t offset); 51static uint32_t fetch_data_long (struct x86emu *, uint32_t offset); 52static uint32_t fetch_long (struct x86emu *, uint32_t segment, uint32_t offset); 53static void store_data_byte (struct x86emu *, uint32_t offset, uint8_t val); 54static void store_byte (struct x86emu *, uint32_t segment, uint32_t offset, uint8_t val); 55static void store_data_word (struct x86emu *, uint32_t offset, uint16_t val); 56static void store_word (struct x86emu *, uint32_t segment, uint32_t offset, uint16_t val); 57static void store_data_long (struct x86emu *, uint32_t offset, uint32_t val); 58static void store_long (struct x86emu *, uint32_t segment, uint32_t offset, uint32_t val); 59static uint8_t* decode_rl_byte_register(struct x86emu *); 60static uint16_t* decode_rl_word_register(struct x86emu *); 61static uint32_t* decode_rl_long_register(struct x86emu *); 62static uint8_t* decode_rh_byte_register(struct x86emu *); 63static uint16_t* decode_rh_word_register(struct x86emu *); 64static uint32_t* decode_rh_long_register(struct x86emu *); 65static uint16_t* decode_rh_seg_register(struct x86emu *); 66static uint32_t decode_rl_address(struct x86emu *); 67 68static uint8_t decode_and_fetch_byte(struct x86emu *); 69static uint16_t decode_and_fetch_word(struct x86emu *); 70static uint32_t decode_and_fetch_long(struct x86emu *); 71 72static uint8_t decode_and_fetch_byte_imm8(struct x86emu *, uint8_t *); 73static uint16_t decode_and_fetch_word_imm8(struct x86emu *, uint8_t *); 74static uint32_t decode_and_fetch_long_imm8(struct x86emu *, uint8_t *); 75 76static uint16_t decode_and_fetch_word_disp(struct x86emu *, int16_t); 77static uint32_t decode_and_fetch_long_disp(struct x86emu *, int16_t); 78 79static void write_back_byte(struct x86emu *, uint8_t); 80static void write_back_word(struct x86emu *, uint16_t); 81static void write_back_long(struct x86emu *, uint32_t); 82 83static uint16_t aaa_word (struct x86emu *, uint16_t d); 84static uint16_t aas_word (struct x86emu *, uint16_t d); 85static uint16_t aad_word (struct x86emu *, uint16_t d); 86static uint16_t aam_word (struct x86emu *, uint8_t d); 87static uint8_t adc_byte (struct x86emu *, uint8_t d, uint8_t s); 88static uint16_t adc_word (struct x86emu *, uint16_t d, uint16_t s); 89static uint32_t adc_long (struct x86emu *, uint32_t d, uint32_t s); 90static uint8_t add_byte (struct x86emu *, uint8_t d, uint8_t s); 91static uint16_t add_word (struct x86emu *, uint16_t d, uint16_t s); 92static uint32_t add_long (struct x86emu *, uint32_t d, uint32_t s); 93static uint8_t and_byte (struct x86emu *, uint8_t d, uint8_t s); 94static uint16_t and_word (struct x86emu *, uint16_t d, uint16_t s); 95static uint32_t and_long (struct x86emu *, uint32_t d, uint32_t s); 96static uint8_t cmp_byte (struct x86emu *, uint8_t d, uint8_t s); 97static uint16_t cmp_word (struct x86emu *, uint16_t d, uint16_t s); 98static uint32_t cmp_long (struct x86emu *, uint32_t d, uint32_t s); 99static void cmp_byte_no_return (struct x86emu *, uint8_t d, uint8_t s); 100static void cmp_word_no_return (struct x86emu *, uint16_t d, uint16_t s); 101static void cmp_long_no_return (struct x86emu *, uint32_t d, uint32_t s); 102static uint8_t daa_byte (struct x86emu *, uint8_t d); 103static uint8_t das_byte (struct x86emu *, uint8_t d); 104static uint8_t dec_byte (struct x86emu *, uint8_t d); 105static uint16_t dec_word (struct x86emu *, uint16_t d); 106static uint32_t dec_long (struct x86emu *, uint32_t d); 107static uint8_t inc_byte (struct x86emu *, uint8_t d); 108static uint16_t inc_word (struct x86emu *, uint16_t d); 109static uint32_t inc_long (struct x86emu *, uint32_t d); 110static uint8_t or_byte (struct x86emu *, uint8_t d, uint8_t s); 111static uint16_t or_word (struct x86emu *, uint16_t d, uint16_t s); 112static uint32_t or_long (struct x86emu *, uint32_t d, uint32_t s); 113static uint8_t neg_byte (struct x86emu *, uint8_t s); 114static uint16_t neg_word (struct x86emu *, uint16_t s); 115static uint32_t neg_long (struct x86emu *, uint32_t s); 116static uint8_t rcl_byte (struct x86emu *, uint8_t d, uint8_t s); 117static uint16_t rcl_word (struct x86emu *, uint16_t d, uint8_t s); 118static uint32_t rcl_long (struct x86emu *, uint32_t d, uint8_t s); 119static uint8_t rcr_byte (struct x86emu *, uint8_t d, uint8_t s); 120static uint16_t rcr_word (struct x86emu *, uint16_t d, uint8_t s); 121static uint32_t rcr_long (struct x86emu *, uint32_t d, uint8_t s); 122static uint8_t rol_byte (struct x86emu *, uint8_t d, uint8_t s); 123static uint16_t rol_word (struct x86emu *, uint16_t d, uint8_t s); 124static uint32_t rol_long (struct x86emu *, uint32_t d, uint8_t s); 125static uint8_t ror_byte (struct x86emu *, uint8_t d, uint8_t s); 126static uint16_t ror_word (struct x86emu *, uint16_t d, uint8_t s); 127static uint32_t ror_long (struct x86emu *, uint32_t d, uint8_t s); 128static uint8_t shl_byte (struct x86emu *, uint8_t d, uint8_t s); 129static uint16_t shl_word (struct x86emu *, uint16_t d, uint8_t s); 130static uint32_t shl_long (struct x86emu *, uint32_t d, uint8_t s); 131static uint8_t shr_byte (struct x86emu *, uint8_t d, uint8_t s); 132static uint16_t shr_word (struct x86emu *, uint16_t d, uint8_t s); 133static uint32_t shr_long (struct x86emu *, uint32_t d, uint8_t s); 134static uint8_t sar_byte (struct x86emu *, uint8_t d, uint8_t s); 135static uint16_t sar_word (struct x86emu *, uint16_t d, uint8_t s); 136static uint32_t sar_long (struct x86emu *, uint32_t d, uint8_t s); 137static uint16_t shld_word (struct x86emu *, uint16_t d, uint16_t fill, uint8_t s); 138static uint32_t shld_long (struct x86emu *, uint32_t d, uint32_t fill, uint8_t s); 139static uint16_t shrd_word (struct x86emu *, uint16_t d, uint16_t fill, uint8_t s); 140static uint32_t shrd_long (struct x86emu *, uint32_t d, uint32_t fill, uint8_t s); 141static uint8_t sbb_byte (struct x86emu *, uint8_t d, uint8_t s); 142static uint16_t sbb_word (struct x86emu *, uint16_t d, uint16_t s); 143static uint32_t sbb_long (struct x86emu *, uint32_t d, uint32_t s); 144static uint8_t sub_byte (struct x86emu *, uint8_t d, uint8_t s); 145static uint16_t sub_word (struct x86emu *, uint16_t d, uint16_t s); 146static uint32_t sub_long (struct x86emu *, uint32_t d, uint32_t s); 147static void test_byte (struct x86emu *, uint8_t d, uint8_t s); 148static void test_word (struct x86emu *, uint16_t d, uint16_t s); 149static void test_long (struct x86emu *, uint32_t d, uint32_t s); 150static uint8_t xor_byte (struct x86emu *, uint8_t d, uint8_t s); 151static uint16_t xor_word (struct x86emu *, uint16_t d, uint16_t s); 152static uint32_t xor_long (struct x86emu *, uint32_t d, uint32_t s); 153static void imul_byte (struct x86emu *, uint8_t s); 154static void imul_word (struct x86emu *, uint16_t s); 155static void imul_long (struct x86emu *, uint32_t s); 156static void mul_byte (struct x86emu *, uint8_t s); 157static void mul_word (struct x86emu *, uint16_t s); 158static void mul_long (struct x86emu *, uint32_t s); 159static void idiv_byte (struct x86emu *, uint8_t s); 160static void idiv_word (struct x86emu *, uint16_t s); 161static void idiv_long (struct x86emu *, uint32_t s); 162static void div_byte (struct x86emu *, uint8_t s); 163static void div_word (struct x86emu *, uint16_t s); 164static void div_long (struct x86emu *, uint32_t s); 165static void ins (struct x86emu *, int size); 166static void outs (struct x86emu *, int size); 167static void push_word (struct x86emu *, uint16_t w); 168static void push_long (struct x86emu *, uint32_t w); 169static uint16_t pop_word (struct x86emu *); 170static uint32_t pop_long (struct x86emu *); 171 172/* 173 * REMARKS: 174 * Handles any pending asychronous interrupts. 175 */ 176static void 177x86emu_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 192static void 193x86emu_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 */ 212void 213x86emu_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 */ 225void 226x86emu_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 252void 253x86emu_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 263void 264x86emu_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 */ 282void 283x86emu_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 */ 304static void 305fetch_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 */ 325static uint8_t 326fetch_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 */ 345static uint16_t 346fetch_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 */ 365static uint32_t 366fetch_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 */ 404static uint32_t 405get_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 */ 442static uint8_t 443fetch_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 */ 457static uint16_t 458fetch_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 */ 472static uint32_t 473fetch_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 */ 488static uint8_t 489fetch_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 */ 504static uint16_t 505fetch_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 */ 520static uint32_t 521fetch_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 */ 537static void 538store_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 */ 554static void 555store_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 */ 571static void 572store_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 */ 588static void 589store_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 */ 605static void 606store_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 */ 622static void 623store_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 */ 639static uint8_t * 640decode_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 664static uint8_t * 665decode_rl_byte_register(struct x86emu *emu) 666{ 667 return decode_rm_byte_register(emu, emu->cur_rl); 668} 669 670static uint8_t * 671decode_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 */ 687static uint16_t * 688decode_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 712static uint16_t * 713decode_rl_word_register(struct x86emu *emu) 714{ 715 return decode_rm_word_register(emu, emu->cur_rl); 716} 717 718static uint16_t * 719decode_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 */ 735static uint32_t * 736decode_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 760static uint32_t * 761decode_rl_long_register(struct x86emu *emu) 762{ 763 return decode_rm_long_register(emu, emu->cur_rl); 764} 765 766static uint32_t * 767decode_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 */ 785static uint16_t * 786decode_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 */ 809static uint32_t 810decode_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 */ 888static uint32_t 889decode_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 980static uint8_t 981decode_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 991static uint16_t 992decode_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 1005static uint32_t 1006decode_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 1019uint16_t 1020decode_and_fetch_word(struct x86emu *emu) 1021{ 1022 return decode_and_fetch_word_disp(emu, 0); 1023} 1024 1025uint32_t 1026decode_and_fetch_long(struct x86emu *emu) 1027{ 1028 return decode_and_fetch_long_disp(emu, 0); 1029} 1030 1031uint8_t 1032decode_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 1044static uint16_t 1045decode_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 1057static uint32_t 1058decode_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 1070static void 1071write_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 1079static void 1080write_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 1088static void 1089write_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 1097static void 1098common_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 1106static void 1107common_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 1115static void 1116common_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 1135static void 1136common_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 1152static void 1153common_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 1171static void 1172common_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 1188static void 1189common_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 1207static void 1208common_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 1217static void 1218common_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 1235static void 1236common_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 1252static void 1253common_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 1262static void 1263common_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 1279static void 1280common_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 1296static void 1297common_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 1306static void 1307common_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 1315static void 1316common_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 1332static void 1333common_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 1341static void 1342common_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 1350static void 1351common_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 1383static void 1384common_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 1416static void 1417common_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 1425static void 1426common_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 1437static void 1438common_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 */ 1459static void 1460x86emuOp_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 */ 1475static void 1476x86emuOp32_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 1486static void 1487x86emuOp16_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 1497static void 1498x86emuOp_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 */ 1510static void 1511x86emuOp_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 */ 1523static void 1524x86emuOp32_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 1532static void 1533x86emuOp16_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 1541static void 1542x86emuOp_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 */ 1554static void 1555x86emuOp_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 */ 1586static void 1587x86emuOp_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 */ 1617static void 1618x86emuOp_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 */ 1637static void 1638x86emuOp_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 */ 1654static void 1655x86emuOp_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 */ 1668static void 1669x86emuOp_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 */ 1682static void 1683x86emuOp_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 */ 1697static void 1698x86emuOp_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 */ 1712static void 1713x86emuOp_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 */ 1727static void 1728x86emuOp_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 1738static 1739uint8_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 */ 1755static void 1756x86emuOp_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 1773static 1774uint16_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 1786static 1787uint32_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 */ 1803static void 1804x86emuOp32_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 1821static void 1822x86emuOp16_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 1839static void 1840x86emuOp_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 1848static 1849uint8_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 */ 1865static void 1866x86emuOp_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 1884static 1885uint16_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 1897static 1898uint32_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 */ 1914static void 1915x86emuOp32_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 1927static void 1928x86emuOp16_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 1940static void 1941x86emuOp_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 */ 1953static void 1954x86emuOp_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 */ 1971static void 1972x86emuOp32_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 1985static void 1986x86emuOp16_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 1999static void 2000x86emuOp_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 */ 2012static void 2013x86emuOp_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 */ 2033static void 2034x86emuOp32_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 2050static void 2051x86emuOp16_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 2067static void 2068x86emuOp_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 */ 2080static void 2081x86emuOp_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 */ 2094static void 2095x86emuOp_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 */ 2116static void 2117x86emuOp_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 */ 2137static void 2138x86emuOp_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 */ 2161static void 2162x86emuOp_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 */ 2181static void 2182x86emuOp32_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 2198static void 2199x86emuOp16_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 2215static void 2216x86emuOp_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 */ 2228static void 2229x86emuOp_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 */ 2248static void 2249x86emuOp_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 */ 2268static void 2269x86emuOp_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 */ 2288static void 2289x86emuOp_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 */ 2308static void 2309x86emuOp_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 */ 2328static void 2329x86emuOp_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 */ 2348static void 2349x86emuOp_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 */ 2368static void 2369x86emuOp_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 */ 2390static void 2391x86emuOp_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 */ 2412static void 2413x86emuOp_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 */ 2434static void 2435x86emuOp_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 */ 2452static void 2453x86emuOp_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 */ 2466static void 2467x86emuOp_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 */ 2479static void 2480x86emuOp_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 */ 2492static void 2493x86emuOp_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 */ 2505static void 2506x86emuOp_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 */ 2522static void 2523x86emuOp_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 */ 2535static void 2536x86emuOp_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 */ 2552static void 2553x86emuOp_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 */ 2583static void 2584x86emuOp_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 */ 2623static void 2624x86emuOp_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 */ 2675static void 2676x86emuOp_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 */ 2751static void 2752x86emuOp_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 */ 2765static void 2766x86emuOp_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 */ 2793static void 2794x86emuOp_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 */ 2829static void 2830x86emuOp_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 */ 2857static void 2858x86emuOp_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 */ 2893static void 2894x86emuOp_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 */ 2938static void 2939x86emuOp_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 */ 3002static void 3003x86emuOp_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 */ 3015static void 3016x86emuOp_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 */ 3028static void 3029x86emuOp_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 */ 3041static void 3042x86emuOp_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 */ 3054static void 3055x86emuOp_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 */ 3067static void 3068x86emuOp_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 */ 3080static void 3081x86emuOp_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 */ 3093static void 3094x86emuOp_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. */ 3102static 3103uint8_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 */ 3119static void 3120x86emuOp_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. */ 3136static 3137uint16_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. */ 3149static 3150uint32_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 */ 3166static void 3167x86emuOp_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 */ 3196static void 3197x86emuOp_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 */ 3210static void 3211x86emuOp_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 */ 3235static void 3236x86emuOp32_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 3256static void 3257x86emuOp16_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 3277static void 3278x86emuOp_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 */ 3290static void 3291x86emuOp_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 */ 3316static void 3317x86emuOp_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 */ 3327static void 3328x86emuOp_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 */ 3342static void 3343x86emuOp_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 */ 3353static void 3354x86emuOp_int3(struct x86emu *emu) 3355{ 3356 x86emu_intr_dispatch(emu, 3); 3357} 3358 3359/* 3360 * REMARKS: 3361 * Handles opcode 0xcd 3362 */ 3363static void 3364x86emuOp_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 */ 3376static void 3377x86emuOp_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 */ 3387static void 3388x86emuOp_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 */ 3399static void 3400x86emuOp_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 */ 3414static void 3415x86emuOp_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 */ 3438static void 3439x86emuOp_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 */ 3453static void 3454x86emuOp_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 */ 3477static void 3478x86emuOp_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 */ 3495static void 3496x86emuOp_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 */ 3514static void 3515x86emuOp_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 */ 3524static void 3525x86emuOp_esc_coprocess_d8(struct x86emu *emu) 3526{ 3527} 3528/* opcode=0xd9 */ 3529static void 3530x86emuOp_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 */ 3537static void 3538x86emuOp_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 */ 3545static void 3546x86emuOp_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 */ 3553static void 3554x86emuOp_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 */ 3561static void 3562x86emuOp_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 */ 3569static void 3570x86emuOp_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 */ 3577static void 3578x86emuOp_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 */ 3590static void 3591x86emuOp_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 */ 3606static void 3607x86emuOp_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 */ 3622static void 3623x86emuOp_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 */ 3638static void 3639x86emuOp_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 */ 3655static void 3656x86emuOp_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 */ 3668static void 3669x86emuOp_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 */ 3685static void 3686x86emuOp_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 */ 3698static void 3699x86emuOp_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 */ 3715static void 3716x86emuOp_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 */ 3730static void 3731x86emuOp_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 */ 3744static void 3745x86emuOp_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 */ 3759static void 3760x86emuOp_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 */ 3774static void 3775x86emuOp_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 */ 3784static void 3785x86emuOp_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 */ 3798static void 3799x86emuOp_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 */ 3808static void 3809x86emuOp_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 */ 3822static void 3823x86emuOp_lock(struct x86emu *emu) 3824{ 3825} 3826/*opcode 0xf1 ILLEGAL OPERATION */ 3827 3828 3829/* 3830 * REMARKS: 3831 * Handles opcode 0xf5 3832 */ 3833static void 3834x86emuOp_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 */ 3846static void 3847x86emuOp_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 */ 3891static void 3892x86emuOp32_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} 3940static void 3941x86emuOp16_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} 3989static void 3990x86emuOp_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 */ 4002static void 4003x86emuOp_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 */ 4042static void 4043x86emuOp32_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 4080static void 4081x86emuOp16_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 4119static void 4120x86emuOp_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 */ 4172static void 4173x86emu_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 4979static void 4980common_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 4990static void 4991common_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 5007static void 5008common_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 5035static void 5036common_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 5063static void 5064common_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 5072static void 5073common_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 5087static void 5088common_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 5102static void 5103common_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 5111static void 5112common_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 5132static void 5133common_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 5153static void 5154common_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 */ 5170static void 5171x86emuOp2_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 */ 5181static void 5182x86emuOp2_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 */ 5191static void 5192x86emuOp2_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__) 5202static void 5203hw_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 5212static void 5213x86emuOp2_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 */ 5249static void 5250x86emuOp2_bt_R(struct x86emu *emu) 5251{ 5252 common_bitstring(emu, 0); 5253} 5254 5255/* 5256 * REMARKS: 5257 * Handles opcode 0x0f,0xa4 5258 */ 5259static void 5260x86emuOp2_shld_IMM(struct x86emu *emu) 5261{ 5262 common_shift(emu, 1, 0); 5263} 5264 5265/* 5266 * REMARKS: 5267 * Handles opcode 0x0f,0xa5 5268 */ 5269static void 5270x86emuOp2_shld_CL(struct x86emu *emu) 5271{ 5272 common_shift(emu, 1, 1); 5273} 5274 5275/* 5276 * REMARKS: 5277 * Handles opcode 0x0f,0xa8 5278 */ 5279static void 5280x86emuOp2_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 */ 5289static void 5290x86emuOp2_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 */ 5299static void 5300x86emuOp2_bts_R(struct x86emu *emu) 5301{ 5302 common_bitstring(emu, 1); 5303} 5304 5305/* 5306 * REMARKS: 5307 * Handles opcode 0x0f,0xac 5308 */ 5309static void 5310x86emuOp2_shrd_IMM(struct x86emu *emu) 5311{ 5312 common_shift(emu, 0, 0); 5313} 5314 5315/* 5316 * REMARKS: 5317 * Handles opcode 0x0f,0xad 5318 */ 5319static void 5320x86emuOp2_shrd_CL(struct x86emu *emu) 5321{ 5322 common_shift(emu, 0, 1); 5323} 5324 5325/* 5326 * REMARKS: 5327 * Handles opcode 0x0f,0xaf 5328 */ 5329static void 5330x86emuOp2_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 5349static void 5350x86emuOp2_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 5369static void 5370x86emuOp2_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 */ 5382static void 5383x86emuOp2_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 */ 5392static void 5393x86emuOp2_btr_R(struct x86emu *emu) 5394{ 5395 common_bitstring(emu, 2); 5396} 5397 5398/* 5399 * REMARKS: 5400 * Handles opcode 0x0f,0xb4 5401 */ 5402static void 5403x86emuOp2_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 */ 5412static void 5413x86emuOp2_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 */ 5422static void 5423x86emuOp2_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 5432static void 5433x86emuOp2_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 5442static void 5443x86emuOp2_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 */ 5455static void 5456x86emuOp2_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 */ 5469static void 5470x86emuOp2_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 5498static void 5499x86emuOp2_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 5527static void 5528x86emuOp2_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 */ 5540static void 5541x86emuOp2_btc_R(struct x86emu *emu) 5542{ 5543 common_bitstring(emu, 3); 5544} 5545 5546/* 5547 * REMARKS: 5548 * Handles opcode 0x0f,0xbc 5549 */ 5550static void 5551x86emuOp2_bsf(struct x86emu *emu) 5552{ 5553 common_bitsearch(emu, +1); 5554} 5555 5556/* 5557 * REMARKS: 5558 * Handles opcode 0x0f,0xbd 5559 */ 5560static void 5561x86emuOp2_bsr(struct x86emu *emu) 5562{ 5563 common_bitsearch(emu, -1); 5564} 5565 5566/* 5567 * REMARKS: 5568 * Handles opcode 0x0f,0xbe 5569 */ 5570static void 5571x86emuOp2_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 5579static void 5580x86emuOp2_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 5589static void 5590x86emuOp2_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 */ 5602static void 5603x86emuOp2_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 5612static void 5613x86emu_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 5903static 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 */ 5922static uint16_t 5923aaa_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 */ 5946static uint16_t 5947aas_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 */ 5970static uint16_t 5971aad_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 */ 5993static uint16_t 5994aam_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 */ 6015static uint8_t 6016adc_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 */ 6042static uint16_t 6043adc_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 */ 6069static uint32_t 6070adc_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 */ 6102static uint8_t 6103add_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 */ 6125static uint16_t 6126add_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 */ 6148static uint32_t 6149add_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 */ 6177static uint8_t 6178and_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 */ 6198static uint16_t 6199and_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 */ 6219static uint32_t 6220and_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 */ 6240static uint8_t 6241cmp_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 6260static void 6261cmp_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 */ 6270static uint16_t 6271cmp_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 6289static void 6290cmp_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 */ 6299static uint32_t 6300cmp_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 6318static void 6319cmp_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 */ 6328static uint8_t 6329daa_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 */ 6350static uint8_t 6351das_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 */ 6371static uint8_t 6372dec_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 */ 6395static uint16_t 6396dec_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 */ 6419static uint32_t 6420dec_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 */ 6443static uint8_t 6444inc_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 */ 6465static uint16_t 6466inc_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 */ 6487static uint32_t 6488inc_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 */ 6509static uint8_t 6510or_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 */ 6528static uint16_t 6529or_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 */ 6548static uint32_t 6549or_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 */ 6569static uint8_t 6570neg_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 */ 6595static uint16_t 6596neg_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 */ 6622static uint32_t 6623neg_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 */ 6649static uint8_t 6650rcl_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 */ 6715static uint16_t 6716rcl_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 */ 6740static uint32_t 6741rcl_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 */ 6765static uint8_t 6766rcr_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 */ 6840static uint16_t 6841rcr_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 */ 6873static uint32_t 6874rcr_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 */ 6907static uint8_t 6908rol_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 */ 6954static uint16_t 6955rol_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 */ 6980static uint32_t 6981rol_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 */ 7006static uint8_t 7007ror_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 */ 7050static uint16_t 7051ror_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 */ 7074static uint32_t 7075ror_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 */ 7098static uint8_t 7099shl_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 */ 7143static uint16_t 7144shl_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 */ 7184static uint32_t 7185shl_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 */ 7222static uint8_t 7223shr_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 */ 7260static uint16_t 7261shr_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 */ 7298static uint32_t 7299shr_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 */ 7335static uint8_t 7336sar_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 */ 7376static uint16_t 7377sar_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 */ 7417static uint32_t 7418sar_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 */ 7458static uint16_t 7459shld_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 */ 7496static uint32_t 7497shld_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 */ 7534static uint16_t 7535shrd_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 */ 7572static uint32_t 7573shrd_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 */ 7609static uint8_t 7610sbb_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 */ 7635static uint16_t 7636sbb_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 */ 7661static uint32_t 7662sbb_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 */ 7687static uint8_t 7688sub_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 */ 7710static uint16_t 7711sub_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 */ 7733static uint32_t 7734sub_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 */ 7756static void 7757test_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 */ 7775static void 7776test_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 */ 7794static void 7795test_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 */ 7813static uint8_t 7814xor_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 */ 7832static uint16_t 7833xor_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 */ 7851static uint32_t 7852xor_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 */ 7870static void 7871imul_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 */ 7890static void 7891imul_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 */ 7911static void 7912imul_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 */ 7933static void 7934mul_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 */ 7952static void 7953mul_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 */ 7972static void 7973mul_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 */ 7993static void 7994idiv_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 */ 8017static void 8018idiv_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 */ 8046static void 8047idiv_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 */ 8076static void 8077div_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 */ 8100static void 8101div_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 */ 8129static void 8130div_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 */ 8159static void 8160ins(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 */ 8224static void 8225outs(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 */ 8291static void 8292push_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 */ 8304static void 8305push_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 */ 8317static uint16_t 8318pop_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 */ 8333static uint32_t 8334pop_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