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