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