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