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