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