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