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