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