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