1282050Sdelphij/* $OpenBSD: x86emu.c,v 1.9 2014/06/15 11:04:49 pirofti Exp $ */ 2197007Sdelphij/* $NetBSD: x86emu.c,v 1.7 2009/02/03 19:26:29 joerg Exp $ */ 3197007Sdelphij 4197007Sdelphij/* 5197007Sdelphij * 6197007Sdelphij * Realmode X86 Emulator Library 7197007Sdelphij * 8197007Sdelphij * Copyright (C) 1996-1999 SciTech Software, Inc. 9197007Sdelphij * Copyright (C) David Mosberger-Tang 10197007Sdelphij * Copyright (C) 1999 Egbert Eich 11197007Sdelphij * Copyright (C) 2007 Joerg Sonnenberger 12197007Sdelphij * 13197007Sdelphij * ======================================================================== 14197007Sdelphij * 15197007Sdelphij * Permission to use, copy, modify, distribute, and sell this software and 16197007Sdelphij * its documentation for any purpose is hereby granted without fee, 17197007Sdelphij * provided that the above copyright notice appear in all copies and that 18197007Sdelphij * both that copyright notice and this permission notice appear in 19197007Sdelphij * supporting documentation, and that the name of the authors not be used 20197007Sdelphij * in advertising or publicity pertaining to distribution of the software 21197007Sdelphij * without specific, written prior permission. The authors makes no 22197007Sdelphij * representations about the suitability of this software for any purpose. 23197007Sdelphij * It is provided "as is" without express or implied warranty. 24197007Sdelphij * 25197007Sdelphij * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 26197007Sdelphij * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 27197007Sdelphij * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 28197007Sdelphij * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 29197007Sdelphij * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 30197007Sdelphij * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 31197007Sdelphij * PERFORMANCE OF THIS SOFTWARE. 32197007Sdelphij * 33197007Sdelphij */ 34197007Sdelphij 35197386Sdelphij#include <sys/cdefs.h> 36197386Sdelphij__FBSDID("$FreeBSD$"); 37197386Sdelphij 38197019Sdelphij#include <contrib/x86emu/x86emu.h> 39197019Sdelphij#include <contrib/x86emu/x86emu_regs.h> 40197019Sdelphij 41197007Sdelphijstatic void x86emu_intr_raise (struct x86emu *, uint8_t type); 42197007Sdelphij 43197007Sdelphijstatic void x86emu_exec_one_byte(struct x86emu *); 44197007Sdelphijstatic void x86emu_exec_two_byte(struct x86emu *); 45197007Sdelphij 46197007Sdelphijstatic void fetch_decode_modrm (struct x86emu *); 47197007Sdelphijstatic uint8_t fetch_byte_imm (struct x86emu *); 48197007Sdelphijstatic uint16_t fetch_word_imm (struct x86emu *); 49197007Sdelphijstatic uint32_t fetch_long_imm (struct x86emu *); 50197007Sdelphijstatic uint8_t fetch_data_byte (struct x86emu *, uint32_t offset); 51197019Sdelphijstatic uint8_t fetch_byte (struct x86emu *, u_int segment, uint32_t offset); 52197007Sdelphijstatic uint16_t fetch_data_word (struct x86emu *, uint32_t offset); 53197007Sdelphijstatic uint16_t fetch_word (struct x86emu *, uint32_t segment, uint32_t offset); 54197007Sdelphijstatic uint32_t fetch_data_long (struct x86emu *, uint32_t offset); 55197007Sdelphijstatic uint32_t fetch_long (struct x86emu *, uint32_t segment, uint32_t offset); 56197007Sdelphijstatic void store_data_byte (struct x86emu *, uint32_t offset, uint8_t val); 57197007Sdelphijstatic void store_byte (struct x86emu *, uint32_t segment, uint32_t offset, uint8_t val); 58197007Sdelphijstatic void store_data_word (struct x86emu *, uint32_t offset, uint16_t val); 59197007Sdelphijstatic void store_word (struct x86emu *, uint32_t segment, uint32_t offset, uint16_t val); 60197007Sdelphijstatic void store_data_long (struct x86emu *, uint32_t offset, uint32_t val); 61197007Sdelphijstatic void store_long (struct x86emu *, uint32_t segment, uint32_t offset, uint32_t val); 62197007Sdelphijstatic uint8_t* decode_rl_byte_register(struct x86emu *); 63197007Sdelphijstatic uint16_t* decode_rl_word_register(struct x86emu *); 64197007Sdelphijstatic uint32_t* decode_rl_long_register(struct x86emu *); 65197007Sdelphijstatic uint8_t* decode_rh_byte_register(struct x86emu *); 66197007Sdelphijstatic uint16_t* decode_rh_word_register(struct x86emu *); 67197007Sdelphijstatic uint32_t* decode_rh_long_register(struct x86emu *); 68197007Sdelphijstatic uint16_t* decode_rh_seg_register(struct x86emu *); 69197007Sdelphijstatic uint32_t decode_rl_address(struct x86emu *); 70197007Sdelphij 71197007Sdelphijstatic uint8_t decode_and_fetch_byte(struct x86emu *); 72197007Sdelphijstatic uint16_t decode_and_fetch_word(struct x86emu *); 73197007Sdelphijstatic uint32_t decode_and_fetch_long(struct x86emu *); 74197007Sdelphij 75197007Sdelphijstatic uint8_t decode_and_fetch_byte_imm8(struct x86emu *, uint8_t *); 76197007Sdelphijstatic uint16_t decode_and_fetch_word_imm8(struct x86emu *, uint8_t *); 77197007Sdelphijstatic uint32_t decode_and_fetch_long_imm8(struct x86emu *, uint8_t *); 78197007Sdelphij 79197007Sdelphijstatic uint16_t decode_and_fetch_word_disp(struct x86emu *, int16_t); 80197007Sdelphijstatic uint32_t decode_and_fetch_long_disp(struct x86emu *, int16_t); 81197007Sdelphij 82197007Sdelphijstatic void write_back_byte(struct x86emu *, uint8_t); 83197007Sdelphijstatic void write_back_word(struct x86emu *, uint16_t); 84197007Sdelphijstatic void write_back_long(struct x86emu *, uint32_t); 85197007Sdelphij 86197007Sdelphijstatic uint16_t aaa_word (struct x86emu *, uint16_t d); 87197007Sdelphijstatic uint16_t aas_word (struct x86emu *, uint16_t d); 88197007Sdelphijstatic uint16_t aad_word (struct x86emu *, uint16_t d); 89197007Sdelphijstatic uint16_t aam_word (struct x86emu *, uint8_t d); 90197007Sdelphijstatic uint8_t adc_byte (struct x86emu *, uint8_t d, uint8_t s); 91197007Sdelphijstatic uint16_t adc_word (struct x86emu *, uint16_t d, uint16_t s); 92197007Sdelphijstatic uint32_t adc_long (struct x86emu *, uint32_t d, uint32_t s); 93197007Sdelphijstatic uint8_t add_byte (struct x86emu *, uint8_t d, uint8_t s); 94197007Sdelphijstatic uint16_t add_word (struct x86emu *, uint16_t d, uint16_t s); 95197007Sdelphijstatic uint32_t add_long (struct x86emu *, uint32_t d, uint32_t s); 96197007Sdelphijstatic uint8_t and_byte (struct x86emu *, uint8_t d, uint8_t s); 97197007Sdelphijstatic uint16_t and_word (struct x86emu *, uint16_t d, uint16_t s); 98197007Sdelphijstatic uint32_t and_long (struct x86emu *, uint32_t d, uint32_t s); 99197007Sdelphijstatic uint8_t cmp_byte (struct x86emu *, uint8_t d, uint8_t s); 100197007Sdelphijstatic uint16_t cmp_word (struct x86emu *, uint16_t d, uint16_t s); 101197007Sdelphijstatic uint32_t cmp_long (struct x86emu *, uint32_t d, uint32_t s); 102197007Sdelphijstatic void cmp_byte_no_return (struct x86emu *, uint8_t d, uint8_t s); 103197007Sdelphijstatic void cmp_word_no_return (struct x86emu *, uint16_t d, uint16_t s); 104197007Sdelphijstatic void cmp_long_no_return (struct x86emu *, uint32_t d, uint32_t s); 105197007Sdelphijstatic uint8_t daa_byte (struct x86emu *, uint8_t d); 106197007Sdelphijstatic uint8_t das_byte (struct x86emu *, uint8_t d); 107197007Sdelphijstatic uint8_t dec_byte (struct x86emu *, uint8_t d); 108197007Sdelphijstatic uint16_t dec_word (struct x86emu *, uint16_t d); 109197007Sdelphijstatic uint32_t dec_long (struct x86emu *, uint32_t d); 110197007Sdelphijstatic uint8_t inc_byte (struct x86emu *, uint8_t d); 111197007Sdelphijstatic uint16_t inc_word (struct x86emu *, uint16_t d); 112197007Sdelphijstatic uint32_t inc_long (struct x86emu *, uint32_t d); 113197007Sdelphijstatic uint8_t or_byte (struct x86emu *, uint8_t d, uint8_t s); 114197007Sdelphijstatic uint16_t or_word (struct x86emu *, uint16_t d, uint16_t s); 115197007Sdelphijstatic uint32_t or_long (struct x86emu *, uint32_t d, uint32_t s); 116197007Sdelphijstatic uint8_t neg_byte (struct x86emu *, uint8_t s); 117197007Sdelphijstatic uint16_t neg_word (struct x86emu *, uint16_t s); 118197007Sdelphijstatic uint32_t neg_long (struct x86emu *, uint32_t s); 119197007Sdelphijstatic uint8_t rcl_byte (struct x86emu *, uint8_t d, uint8_t s); 120197007Sdelphijstatic uint16_t rcl_word (struct x86emu *, uint16_t d, uint8_t s); 121197007Sdelphijstatic uint32_t rcl_long (struct x86emu *, uint32_t d, uint8_t s); 122197007Sdelphijstatic uint8_t rcr_byte (struct x86emu *, uint8_t d, uint8_t s); 123197007Sdelphijstatic uint16_t rcr_word (struct x86emu *, uint16_t d, uint8_t s); 124197007Sdelphijstatic uint32_t rcr_long (struct x86emu *, uint32_t d, uint8_t s); 125197007Sdelphijstatic uint8_t rol_byte (struct x86emu *, uint8_t d, uint8_t s); 126197007Sdelphijstatic uint16_t rol_word (struct x86emu *, uint16_t d, uint8_t s); 127197007Sdelphijstatic uint32_t rol_long (struct x86emu *, uint32_t d, uint8_t s); 128197007Sdelphijstatic uint8_t ror_byte (struct x86emu *, uint8_t d, uint8_t s); 129197007Sdelphijstatic uint16_t ror_word (struct x86emu *, uint16_t d, uint8_t s); 130197007Sdelphijstatic uint32_t ror_long (struct x86emu *, uint32_t d, uint8_t s); 131197007Sdelphijstatic uint8_t shl_byte (struct x86emu *, uint8_t d, uint8_t s); 132197007Sdelphijstatic uint16_t shl_word (struct x86emu *, uint16_t d, uint8_t s); 133197007Sdelphijstatic uint32_t shl_long (struct x86emu *, uint32_t d, uint8_t s); 134197007Sdelphijstatic uint8_t shr_byte (struct x86emu *, uint8_t d, uint8_t s); 135197007Sdelphijstatic uint16_t shr_word (struct x86emu *, uint16_t d, uint8_t s); 136197007Sdelphijstatic uint32_t shr_long (struct x86emu *, uint32_t d, uint8_t s); 137197007Sdelphijstatic uint8_t sar_byte (struct x86emu *, uint8_t d, uint8_t s); 138197007Sdelphijstatic uint16_t sar_word (struct x86emu *, uint16_t d, uint8_t s); 139197007Sdelphijstatic uint32_t sar_long (struct x86emu *, uint32_t d, uint8_t s); 140197007Sdelphijstatic uint16_t shld_word (struct x86emu *, uint16_t d, uint16_t fill, uint8_t s); 141197007Sdelphijstatic uint32_t shld_long (struct x86emu *, uint32_t d, uint32_t fill, uint8_t s); 142197007Sdelphijstatic uint16_t shrd_word (struct x86emu *, uint16_t d, uint16_t fill, uint8_t s); 143197007Sdelphijstatic uint32_t shrd_long (struct x86emu *, uint32_t d, uint32_t fill, uint8_t s); 144197007Sdelphijstatic uint8_t sbb_byte (struct x86emu *, uint8_t d, uint8_t s); 145197007Sdelphijstatic uint16_t sbb_word (struct x86emu *, uint16_t d, uint16_t s); 146197007Sdelphijstatic uint32_t sbb_long (struct x86emu *, uint32_t d, uint32_t s); 147197007Sdelphijstatic uint8_t sub_byte (struct x86emu *, uint8_t d, uint8_t s); 148197007Sdelphijstatic uint16_t sub_word (struct x86emu *, uint16_t d, uint16_t s); 149197007Sdelphijstatic uint32_t sub_long (struct x86emu *, uint32_t d, uint32_t s); 150197007Sdelphijstatic void test_byte (struct x86emu *, uint8_t d, uint8_t s); 151197007Sdelphijstatic void test_word (struct x86emu *, uint16_t d, uint16_t s); 152197007Sdelphijstatic void test_long (struct x86emu *, uint32_t d, uint32_t s); 153197007Sdelphijstatic uint8_t xor_byte (struct x86emu *, uint8_t d, uint8_t s); 154197007Sdelphijstatic uint16_t xor_word (struct x86emu *, uint16_t d, uint16_t s); 155197007Sdelphijstatic uint32_t xor_long (struct x86emu *, uint32_t d, uint32_t s); 156197007Sdelphijstatic void imul_byte (struct x86emu *, uint8_t s); 157197007Sdelphijstatic void imul_word (struct x86emu *, uint16_t s); 158197007Sdelphijstatic void imul_long (struct x86emu *, uint32_t s); 159197007Sdelphijstatic void mul_byte (struct x86emu *, uint8_t s); 160197007Sdelphijstatic void mul_word (struct x86emu *, uint16_t s); 161197007Sdelphijstatic void mul_long (struct x86emu *, uint32_t s); 162197007Sdelphijstatic void idiv_byte (struct x86emu *, uint8_t s); 163197007Sdelphijstatic void idiv_word (struct x86emu *, uint16_t s); 164197007Sdelphijstatic void idiv_long (struct x86emu *, uint32_t s); 165197007Sdelphijstatic void div_byte (struct x86emu *, uint8_t s); 166197007Sdelphijstatic void div_word (struct x86emu *, uint16_t s); 167197007Sdelphijstatic void div_long (struct x86emu *, uint32_t s); 168197007Sdelphijstatic void ins (struct x86emu *, int size); 169197007Sdelphijstatic void outs (struct x86emu *, int size); 170197007Sdelphijstatic void push_word (struct x86emu *, uint16_t w); 171197007Sdelphijstatic void push_long (struct x86emu *, uint32_t w); 172197007Sdelphijstatic uint16_t pop_word (struct x86emu *); 173197007Sdelphijstatic uint32_t pop_long (struct x86emu *); 174197007Sdelphij 175197007Sdelphij/* 176197007Sdelphij * REMARKS: 177197007Sdelphij * Handles any pending asychronous interrupts. 178197007Sdelphij */ 179197007Sdelphijstatic void 180197007Sdelphijx86emu_intr_dispatch(struct x86emu *emu, uint8_t intno) 181197007Sdelphij{ 182197007Sdelphij if (emu->_x86emu_intrTab[intno]) { 183197007Sdelphij (*emu->_x86emu_intrTab[intno]) (emu, intno); 184197007Sdelphij } else { 185197007Sdelphij push_word(emu, (uint16_t) emu->x86.R_FLG); 186197007Sdelphij CLEAR_FLAG(F_IF); 187197007Sdelphij CLEAR_FLAG(F_TF); 188197007Sdelphij push_word(emu, emu->x86.R_CS); 189197007Sdelphij emu->x86.R_CS = fetch_word(emu, 0, intno * 4 + 2); 190197007Sdelphij push_word(emu, emu->x86.R_IP); 191197007Sdelphij emu->x86.R_IP = fetch_word(emu, 0, intno * 4); 192197007Sdelphij } 193197007Sdelphij} 194197007Sdelphij 195197007Sdelphijstatic void 196197007Sdelphijx86emu_intr_handle(struct x86emu *emu) 197197007Sdelphij{ 198197007Sdelphij uint8_t intno; 199197007Sdelphij 200197007Sdelphij if (emu->x86.intr & INTR_SYNCH) { 201197007Sdelphij intno = emu->x86.intno; 202197007Sdelphij emu->x86.intr = 0; 203197007Sdelphij x86emu_intr_dispatch(emu, intno); 204197007Sdelphij } 205197007Sdelphij} 206197007Sdelphij 207197007Sdelphij/* 208197007Sdelphij * PARAMETERS: 209197007Sdelphij * intrnum - Interrupt number to raise 210197007Sdelphij * 211197007Sdelphij * REMARKS: 212197007Sdelphij * Raise the specified interrupt to be handled before the execution of the 213197007Sdelphij * next instruction. 214197007Sdelphij */ 215197007Sdelphijvoid 216197007Sdelphijx86emu_intr_raise(struct x86emu *emu, uint8_t intrnum) 217197007Sdelphij{ 218197007Sdelphij emu->x86.intno = intrnum; 219197007Sdelphij emu->x86.intr |= INTR_SYNCH; 220197007Sdelphij} 221197007Sdelphij 222197007Sdelphij/* 223197007Sdelphij * REMARKS: 224197007Sdelphij * Main execution loop for the emulator. We return from here when the system 225197007Sdelphij * halts, which is normally caused by a stack fault when we return from the 226197007Sdelphij * original real mode call. 227197007Sdelphij */ 228197007Sdelphijvoid 229197007Sdelphijx86emu_exec(struct x86emu *emu) 230197007Sdelphij{ 231197007Sdelphij emu->x86.intr = 0; 232197007Sdelphij 233197007Sdelphij if (setjmp(emu->exec_state)) 234197007Sdelphij return; 235197007Sdelphij 236197007Sdelphij for (;;) { 237197007Sdelphij if (emu->x86.intr) { 238204934Sdelphij if (((emu->x86.intr & INTR_SYNCH) && 239204934Sdelphij (emu->x86.intno == 0 || emu->x86.intno == 2)) || 240197007Sdelphij !ACCESS_FLAG(F_IF)) { 241197007Sdelphij x86emu_intr_handle(emu); 242197007Sdelphij } 243197007Sdelphij } 244197007Sdelphij if (emu->x86.R_CS == 0 && emu->x86.R_IP == 0) 245197007Sdelphij return; 246197007Sdelphij x86emu_exec_one_byte(emu); 247197007Sdelphij ++emu->cur_cycles; 248197007Sdelphij } 249197007Sdelphij} 250197007Sdelphij 251197007Sdelphijvoid 252197007Sdelphijx86emu_exec_call(struct x86emu *emu, uint16_t seg, uint16_t off) 253197007Sdelphij{ 254197007Sdelphij push_word(emu, 0); 255197007Sdelphij push_word(emu, 0); 256197007Sdelphij emu->x86.R_CS = seg; 257197007Sdelphij emu->x86.R_IP = off; 258197007Sdelphij 259197007Sdelphij x86emu_exec(emu); 260197007Sdelphij} 261197007Sdelphij 262197007Sdelphijvoid 263197007Sdelphijx86emu_exec_intr(struct x86emu *emu, uint8_t intr) 264197007Sdelphij{ 265197007Sdelphij push_word(emu, emu->x86.R_FLG); 266197007Sdelphij CLEAR_FLAG(F_IF); 267197007Sdelphij CLEAR_FLAG(F_TF); 268197007Sdelphij push_word(emu, 0); 269197007Sdelphij push_word(emu, 0); 270197007Sdelphij emu->x86.R_CS = (*emu->emu_rdw)(emu, intr * 4 + 2); 271197007Sdelphij emu->x86.R_IP = (*emu->emu_rdw)(emu, intr * 4); 272197007Sdelphij emu->x86.intr = 0; 273197007Sdelphij 274197007Sdelphij x86emu_exec(emu); 275197007Sdelphij} 276197007Sdelphij 277197007Sdelphij/* 278197007Sdelphij * REMARKS: 279197007Sdelphij * Halts the system by setting the halted system flag. 280197007Sdelphij */ 281197007Sdelphijvoid 282197007Sdelphijx86emu_halt_sys(struct x86emu *emu) 283197007Sdelphij{ 284197007Sdelphij longjmp(emu->exec_state, 1); 285197007Sdelphij} 286197007Sdelphij 287197007Sdelphij/* 288197007Sdelphij * PARAMETERS: 289197007Sdelphij * mod - Mod value from decoded byte 290197007Sdelphij * regh - Reg h value from decoded byte 291197007Sdelphij * regl - Reg l value from decoded byte 292197007Sdelphij * 293197007Sdelphij * REMARKS: 294197007Sdelphij * Raise the specified interrupt to be handled before the execution of the 295197007Sdelphij * next instruction. 296197007Sdelphij * 297197007Sdelphij * NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline! 298197007Sdelphij */ 299197007Sdelphijstatic void 300197007Sdelphijfetch_decode_modrm(struct x86emu *emu) 301197007Sdelphij{ 302197007Sdelphij int fetched; 303197007Sdelphij 304197007Sdelphij fetched = fetch_byte_imm(emu); 305197007Sdelphij emu->cur_mod = (fetched >> 6) & 0x03; 306197007Sdelphij emu->cur_rh = (fetched >> 3) & 0x07; 307197007Sdelphij emu->cur_rl = (fetched >> 0) & 0x07; 308197007Sdelphij} 309197007Sdelphij 310197007Sdelphij/* 311197007Sdelphij * RETURNS: 312197007Sdelphij * Immediate byte value read from instruction queue 313197007Sdelphij * 314197007Sdelphij * REMARKS: 315197007Sdelphij * This function returns the immediate byte from the instruction queue, and 316197007Sdelphij * moves the instruction pointer to the next value. 317197007Sdelphij * 318197007Sdelphij * NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline! 319197007Sdelphij */ 320197007Sdelphijstatic uint8_t 321197007Sdelphijfetch_byte_imm(struct x86emu *emu) 322197007Sdelphij{ 323197007Sdelphij uint8_t fetched; 324197007Sdelphij 325197007Sdelphij fetched = fetch_byte(emu, emu->x86.R_CS, emu->x86.R_IP); 326197007Sdelphij emu->x86.R_IP++; 327197007Sdelphij return fetched; 328197007Sdelphij} 329197007Sdelphij 330197007Sdelphij/* 331197007Sdelphij * RETURNS: 332197007Sdelphij * Immediate word value read from instruction queue 333197007Sdelphij * 334197007Sdelphij * REMARKS: 335197007Sdelphij * This function returns the immediate byte from the instruction queue, and 336197007Sdelphij * moves the instruction pointer to the next value. 337197007Sdelphij * 338197007Sdelphij * NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline! 339197007Sdelphij */ 340197007Sdelphijstatic uint16_t 341197007Sdelphijfetch_word_imm(struct x86emu *emu) 342197007Sdelphij{ 343197007Sdelphij uint16_t fetched; 344197007Sdelphij 345197007Sdelphij fetched = fetch_word(emu, emu->x86.R_CS, emu->x86.R_IP); 346197007Sdelphij emu->x86.R_IP += 2; 347197007Sdelphij return fetched; 348197007Sdelphij} 349197007Sdelphij 350197007Sdelphij/* 351197007Sdelphij * RETURNS: 352197007Sdelphij * Immediate lone value read from instruction queue 353197007Sdelphij * 354197007Sdelphij * REMARKS: 355197007Sdelphij * This function returns the immediate byte from the instruction queue, and 356197007Sdelphij * moves the instruction pointer to the next value. 357197007Sdelphij * 358197007Sdelphij * NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline! 359197007Sdelphij */ 360197007Sdelphijstatic uint32_t 361197007Sdelphijfetch_long_imm(struct x86emu *emu) 362197007Sdelphij{ 363197007Sdelphij uint32_t fetched; 364197007Sdelphij 365197007Sdelphij fetched = fetch_long(emu, emu->x86.R_CS, emu->x86.R_IP); 366197007Sdelphij emu->x86.R_IP += 4; 367197007Sdelphij return fetched; 368197007Sdelphij} 369197007Sdelphij 370197007Sdelphij/* 371197007Sdelphij * RETURNS: 372197007Sdelphij * Value of the default data segment 373197007Sdelphij * 374197007Sdelphij * REMARKS: 375197007Sdelphij * Inline function that returns the default data segment for the current 376197007Sdelphij * instruction. 377197007Sdelphij * 378197007Sdelphij * On the x86 processor, the default segment is not always DS if there is 379197007Sdelphij * no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to 380197007Sdelphij * addresses relative to SS (ie: on the stack). So, at the minimum, all 381197007Sdelphij * decodings of addressing modes would have to set/clear a bit describing 382197007Sdelphij * whether the access is relative to DS or SS. That is the function of the 383197007Sdelphij * cpu-state-varible emu->x86.mode. There are several potential states: 384197007Sdelphij * 385197007Sdelphij * repe prefix seen (handled elsewhere) 386197007Sdelphij * repne prefix seen (ditto) 387197007Sdelphij * 388197007Sdelphij * cs segment override 389197007Sdelphij * ds segment override 390197007Sdelphij * es segment override 391197007Sdelphij * fs segment override 392197007Sdelphij * gs segment override 393197007Sdelphij * ss segment override 394197007Sdelphij * 395197007Sdelphij * ds/ss select (in absense of override) 396197007Sdelphij * 397197007Sdelphij * Each of the above 7 items are handled with a bit in the mode field. 398197007Sdelphij */ 399197007Sdelphijstatic uint32_t 400197007Sdelphijget_data_segment(struct x86emu *emu) 401197007Sdelphij{ 402197007Sdelphij switch (emu->x86.mode & SYSMODE_SEGMASK) { 403197007Sdelphij case 0: /* default case: use ds register */ 404197007Sdelphij case SYSMODE_SEGOVR_DS: 405197007Sdelphij case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS: 406197007Sdelphij return emu->x86.R_DS; 407197007Sdelphij case SYSMODE_SEG_DS_SS:/* non-overridden, use ss register */ 408197007Sdelphij return emu->x86.R_SS; 409197007Sdelphij case SYSMODE_SEGOVR_CS: 410197007Sdelphij case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS: 411197007Sdelphij return emu->x86.R_CS; 412197007Sdelphij case SYSMODE_SEGOVR_ES: 413197007Sdelphij case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS: 414197007Sdelphij return emu->x86.R_ES; 415197007Sdelphij case SYSMODE_SEGOVR_FS: 416197007Sdelphij case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS: 417197007Sdelphij return emu->x86.R_FS; 418197007Sdelphij case SYSMODE_SEGOVR_GS: 419197007Sdelphij case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS: 420197007Sdelphij return emu->x86.R_GS; 421197007Sdelphij case SYSMODE_SEGOVR_SS: 422197007Sdelphij case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS: 423197007Sdelphij return emu->x86.R_SS; 424197007Sdelphij } 425197007Sdelphij x86emu_halt_sys(emu); 426197007Sdelphij} 427197007Sdelphij 428197007Sdelphij/* 429197007Sdelphij * PARAMETERS: 430197007Sdelphij * offset - Offset to load data from 431197007Sdelphij * 432197007Sdelphij * RETURNS: 433197007Sdelphij * Byte value read from the absolute memory location. 434197007Sdelphij * 435197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 436197007Sdelphij */ 437197007Sdelphijstatic uint8_t 438197007Sdelphijfetch_data_byte(struct x86emu *emu, uint32_t offset) 439197007Sdelphij{ 440197007Sdelphij return fetch_byte(emu, get_data_segment(emu), offset); 441197007Sdelphij} 442197007Sdelphij 443197007Sdelphij/* 444197007Sdelphij * PARAMETERS: 445197007Sdelphij * offset - Offset to load data from 446197007Sdelphij * 447197007Sdelphij * RETURNS: 448197007Sdelphij * Word value read from the absolute memory location. 449197007Sdelphij * 450197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 451197007Sdelphij */ 452197007Sdelphijstatic uint16_t 453197007Sdelphijfetch_data_word(struct x86emu *emu, uint32_t offset) 454197007Sdelphij{ 455197007Sdelphij return fetch_word(emu, get_data_segment(emu), offset); 456197007Sdelphij} 457197007Sdelphij 458197007Sdelphij/* 459197007Sdelphij * PARAMETERS: 460197007Sdelphij * offset - Offset to load data from 461197007Sdelphij * 462197007Sdelphij * RETURNS: 463197007Sdelphij * Long value read from the absolute memory location. 464197007Sdelphij * 465197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 466197007Sdelphij */ 467197007Sdelphijstatic uint32_t 468197007Sdelphijfetch_data_long(struct x86emu *emu, uint32_t offset) 469197007Sdelphij{ 470197007Sdelphij return fetch_long(emu, get_data_segment(emu), offset); 471197007Sdelphij} 472197007Sdelphij 473197007Sdelphij/* 474197007Sdelphij * PARAMETERS: 475197007Sdelphij * segment - Segment to load data from 476197007Sdelphij * offset - Offset to load data from 477197007Sdelphij * 478197007Sdelphij * RETURNS: 479197007Sdelphij * Byte value read from the absolute memory location. 480197007Sdelphij * 481197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 482197007Sdelphij */ 483197007Sdelphijstatic uint8_t 484197007Sdelphijfetch_byte(struct x86emu *emu, uint32_t segment, uint32_t offset) 485197007Sdelphij{ 486197007Sdelphij return (*emu->emu_rdb) (emu, ((uint32_t) segment << 4) + offset); 487197007Sdelphij} 488197007Sdelphij 489197007Sdelphij/* 490197007Sdelphij * PARAMETERS: 491197007Sdelphij * segment - Segment to load data from 492197007Sdelphij * offset - Offset to load data from 493197007Sdelphij * 494197007Sdelphij * RETURNS: 495197007Sdelphij * Word value read from the absolute memory location. 496197007Sdelphij * 497197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 498197007Sdelphij */ 499197007Sdelphijstatic uint16_t 500197007Sdelphijfetch_word(struct x86emu *emu, uint32_t segment, uint32_t offset) 501197007Sdelphij{ 502197007Sdelphij return (*emu->emu_rdw) (emu, ((uint32_t) segment << 4) + offset); 503197007Sdelphij} 504197007Sdelphij 505197007Sdelphij/* 506197007Sdelphij * PARAMETERS: 507197007Sdelphij * segment - Segment to load data from 508197007Sdelphij * offset - Offset to load data from 509197007Sdelphij * 510197007Sdelphij * RETURNS: 511197007Sdelphij * Long value read from the absolute memory location. 512197007Sdelphij * 513197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 514197007Sdelphij */ 515197007Sdelphijstatic uint32_t 516197007Sdelphijfetch_long(struct x86emu *emu, uint32_t segment, uint32_t offset) 517197007Sdelphij{ 518197007Sdelphij return (*emu->emu_rdl) (emu, ((uint32_t) segment << 4) + offset); 519197007Sdelphij} 520197007Sdelphij 521197007Sdelphij/* 522197007Sdelphij * PARAMETERS: 523197007Sdelphij * offset - Offset to store data at 524197007Sdelphij * val - Value to store 525197007Sdelphij * 526197007Sdelphij * REMARKS: 527197007Sdelphij * Writes a word value to an segmented memory location. The segment used is 528197007Sdelphij * the current 'default' segment, which may have been overridden. 529197007Sdelphij * 530197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 531197007Sdelphij */ 532197007Sdelphijstatic void 533197007Sdelphijstore_data_byte(struct x86emu *emu, uint32_t offset, uint8_t val) 534197007Sdelphij{ 535197007Sdelphij store_byte(emu, get_data_segment(emu), offset, val); 536197007Sdelphij} 537197007Sdelphij 538197007Sdelphij/* 539197007Sdelphij * PARAMETERS: 540197007Sdelphij * offset - Offset to store data at 541197007Sdelphij * val - Value to store 542197007Sdelphij * 543197007Sdelphij * REMARKS: 544197007Sdelphij * Writes a word value to an segmented memory location. The segment used is 545197007Sdelphij * the current 'default' segment, which may have been overridden. 546197007Sdelphij * 547197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 548197007Sdelphij */ 549197007Sdelphijstatic void 550197007Sdelphijstore_data_word(struct x86emu *emu, uint32_t offset, uint16_t val) 551197007Sdelphij{ 552197007Sdelphij store_word(emu, get_data_segment(emu), offset, val); 553197007Sdelphij} 554197007Sdelphij 555197007Sdelphij/* 556197007Sdelphij * PARAMETERS: 557197007Sdelphij * offset - Offset to store data at 558197007Sdelphij * val - Value to store 559197007Sdelphij * 560197007Sdelphij * REMARKS: 561197007Sdelphij * Writes a long value to an segmented memory location. The segment used is 562197007Sdelphij * the current 'default' segment, which may have been overridden. 563197007Sdelphij * 564197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 565197007Sdelphij */ 566197007Sdelphijstatic void 567197007Sdelphijstore_data_long(struct x86emu *emu, uint32_t offset, uint32_t val) 568197007Sdelphij{ 569197007Sdelphij store_long(emu, get_data_segment(emu), offset, val); 570197007Sdelphij} 571197007Sdelphij 572197007Sdelphij/* 573197007Sdelphij * PARAMETERS: 574197007Sdelphij * segment - Segment to store data at 575197007Sdelphij * offset - Offset to store data at 576197007Sdelphij * val - Value to store 577197007Sdelphij * 578197007Sdelphij * REMARKS: 579197007Sdelphij * Writes a byte value to an absolute memory location. 580197007Sdelphij * 581197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 582197007Sdelphij */ 583197007Sdelphijstatic void 584197007Sdelphijstore_byte(struct x86emu *emu, uint32_t segment, uint32_t offset, uint8_t val) 585197007Sdelphij{ 586197007Sdelphij (*emu->emu_wrb) (emu, ((uint32_t) segment << 4) + offset, val); 587197007Sdelphij} 588197007Sdelphij 589197007Sdelphij/* 590197007Sdelphij * PARAMETERS: 591197007Sdelphij * segment - Segment to store data at 592197007Sdelphij * offset - Offset to store data at 593197007Sdelphij * val - Value to store 594197007Sdelphij * 595197007Sdelphij * REMARKS: 596197007Sdelphij * Writes a word value to an absolute memory location. 597197007Sdelphij * 598197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 599197007Sdelphij */ 600197007Sdelphijstatic void 601197007Sdelphijstore_word(struct x86emu *emu, uint32_t segment, uint32_t offset, uint16_t val) 602197007Sdelphij{ 603197007Sdelphij (*emu->emu_wrw) (emu, ((uint32_t) segment << 4) + offset, val); 604197007Sdelphij} 605197007Sdelphij 606197007Sdelphij/* 607197007Sdelphij * PARAMETERS: 608197007Sdelphij * segment - Segment to store data at 609197007Sdelphij * offset - Offset to store data at 610197007Sdelphij * val - Value to store 611197007Sdelphij * 612197007Sdelphij * REMARKS: 613197007Sdelphij * Writes a long value to an absolute memory location. 614197007Sdelphij * 615197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 616197007Sdelphij */ 617197007Sdelphijstatic void 618197007Sdelphijstore_long(struct x86emu *emu, uint32_t segment, uint32_t offset, uint32_t val) 619197007Sdelphij{ 620197007Sdelphij (*emu->emu_wrl) (emu, ((uint32_t) segment << 4) + offset, val); 621197007Sdelphij} 622197007Sdelphij 623197007Sdelphij/* 624197007Sdelphij * PARAMETERS: 625197007Sdelphij * reg - Register to decode 626197007Sdelphij * 627197007Sdelphij * RETURNS: 628197007Sdelphij * Pointer to the appropriate register 629197007Sdelphij * 630197007Sdelphij * REMARKS: 631197007Sdelphij * Return a pointer to the register given by the R/RM field of the 632197007Sdelphij * modrm byte, for byte operands. Also enables the decoding of instructions. 633197007Sdelphij */ 634197007Sdelphijstatic uint8_t * 635197007Sdelphijdecode_rm_byte_register(struct x86emu *emu, int reg) 636197007Sdelphij{ 637197007Sdelphij switch (reg) { 638197007Sdelphij case 0: 639197007Sdelphij return &emu->x86.R_AL; 640197007Sdelphij case 1: 641197007Sdelphij return &emu->x86.R_CL; 642197007Sdelphij case 2: 643197007Sdelphij return &emu->x86.R_DL; 644197007Sdelphij case 3: 645197007Sdelphij return &emu->x86.R_BL; 646197007Sdelphij case 4: 647197007Sdelphij return &emu->x86.R_AH; 648197007Sdelphij case 5: 649197007Sdelphij return &emu->x86.R_CH; 650197007Sdelphij case 6: 651197007Sdelphij return &emu->x86.R_DH; 652197007Sdelphij case 7: 653197007Sdelphij return &emu->x86.R_BH; 654197007Sdelphij default: 655197007Sdelphij x86emu_halt_sys(emu); 656197007Sdelphij } 657197007Sdelphij} 658197007Sdelphij 659197007Sdelphijstatic uint8_t * 660197007Sdelphijdecode_rl_byte_register(struct x86emu *emu) 661197007Sdelphij{ 662197007Sdelphij return decode_rm_byte_register(emu, emu->cur_rl); 663197007Sdelphij} 664197007Sdelphij 665197007Sdelphijstatic uint8_t * 666197007Sdelphijdecode_rh_byte_register(struct x86emu *emu) 667197007Sdelphij{ 668197007Sdelphij return decode_rm_byte_register(emu, emu->cur_rh); 669197007Sdelphij} 670197007Sdelphij 671197007Sdelphij/* 672197007Sdelphij * PARAMETERS: 673197007Sdelphij * reg - Register to decode 674197007Sdelphij * 675197007Sdelphij * RETURNS: 676197007Sdelphij * Pointer to the appropriate register 677197007Sdelphij * 678197007Sdelphij * REMARKS: 679197007Sdelphij * Return a pointer to the register given by the R/RM field of the 680197007Sdelphij * modrm byte, for word operands. Also enables the decoding of instructions. 681197007Sdelphij */ 682197007Sdelphijstatic uint16_t * 683197007Sdelphijdecode_rm_word_register(struct x86emu *emu, int reg) 684197007Sdelphij{ 685197007Sdelphij switch (reg) { 686197007Sdelphij case 0: 687197007Sdelphij return &emu->x86.R_AX; 688197007Sdelphij case 1: 689197007Sdelphij return &emu->x86.R_CX; 690197007Sdelphij case 2: 691197007Sdelphij return &emu->x86.R_DX; 692197007Sdelphij case 3: 693197007Sdelphij return &emu->x86.R_BX; 694197007Sdelphij case 4: 695197007Sdelphij return &emu->x86.R_SP; 696197007Sdelphij case 5: 697197007Sdelphij return &emu->x86.R_BP; 698197007Sdelphij case 6: 699197007Sdelphij return &emu->x86.R_SI; 700197007Sdelphij case 7: 701197007Sdelphij return &emu->x86.R_DI; 702197007Sdelphij default: 703197007Sdelphij x86emu_halt_sys(emu); 704197007Sdelphij } 705197007Sdelphij} 706197007Sdelphij 707197007Sdelphijstatic uint16_t * 708197007Sdelphijdecode_rl_word_register(struct x86emu *emu) 709197007Sdelphij{ 710197007Sdelphij return decode_rm_word_register(emu, emu->cur_rl); 711197007Sdelphij} 712197007Sdelphij 713197007Sdelphijstatic uint16_t * 714197007Sdelphijdecode_rh_word_register(struct x86emu *emu) 715197007Sdelphij{ 716197007Sdelphij return decode_rm_word_register(emu, emu->cur_rh); 717197007Sdelphij} 718197007Sdelphij 719197007Sdelphij/* 720197007Sdelphij * PARAMETERS: 721197007Sdelphij * reg - Register to decode 722197007Sdelphij * 723197007Sdelphij * RETURNS: 724197007Sdelphij * Pointer to the appropriate register 725197007Sdelphij * 726197007Sdelphij * REMARKS: 727197007Sdelphij * Return a pointer to the register given by the R/RM field of the 728197007Sdelphij * modrm byte, for dword operands. Also enables the decoding of instructions. 729197007Sdelphij */ 730197007Sdelphijstatic uint32_t * 731197007Sdelphijdecode_rm_long_register(struct x86emu *emu, int reg) 732197007Sdelphij{ 733197007Sdelphij switch (reg) { 734197007Sdelphij case 0: 735197007Sdelphij return &emu->x86.R_EAX; 736197007Sdelphij case 1: 737197007Sdelphij return &emu->x86.R_ECX; 738197007Sdelphij case 2: 739197007Sdelphij return &emu->x86.R_EDX; 740197007Sdelphij case 3: 741197007Sdelphij return &emu->x86.R_EBX; 742197007Sdelphij case 4: 743197007Sdelphij return &emu->x86.R_ESP; 744197007Sdelphij case 5: 745197007Sdelphij return &emu->x86.R_EBP; 746197007Sdelphij case 6: 747197007Sdelphij return &emu->x86.R_ESI; 748197007Sdelphij case 7: 749197007Sdelphij return &emu->x86.R_EDI; 750197007Sdelphij default: 751197007Sdelphij x86emu_halt_sys(emu); 752197007Sdelphij } 753197007Sdelphij} 754197007Sdelphij 755197007Sdelphijstatic uint32_t * 756197007Sdelphijdecode_rl_long_register(struct x86emu *emu) 757197007Sdelphij{ 758197007Sdelphij return decode_rm_long_register(emu, emu->cur_rl); 759197007Sdelphij} 760197007Sdelphij 761197007Sdelphijstatic uint32_t * 762197007Sdelphijdecode_rh_long_register(struct x86emu *emu) 763197007Sdelphij{ 764197007Sdelphij return decode_rm_long_register(emu, emu->cur_rh); 765197007Sdelphij} 766197007Sdelphij 767197007Sdelphij 768197007Sdelphij/* 769197007Sdelphij * PARAMETERS: 770197007Sdelphij * reg - Register to decode 771197007Sdelphij * 772197007Sdelphij * RETURNS: 773197007Sdelphij * Pointer to the appropriate register 774197007Sdelphij * 775197007Sdelphij * REMARKS: 776197007Sdelphij * Return a pointer to the register given by the R/RM field of the 777197007Sdelphij * modrm byte, for word operands, modified from above for the weirdo 778197007Sdelphij * special case of segreg operands. Also enables the decoding of instructions. 779197007Sdelphij */ 780197007Sdelphijstatic uint16_t * 781197007Sdelphijdecode_rh_seg_register(struct x86emu *emu) 782197007Sdelphij{ 783197007Sdelphij switch (emu->cur_rh) { 784197007Sdelphij case 0: 785197007Sdelphij return &emu->x86.R_ES; 786197007Sdelphij case 1: 787197007Sdelphij return &emu->x86.R_CS; 788197007Sdelphij case 2: 789197007Sdelphij return &emu->x86.R_SS; 790197007Sdelphij case 3: 791197007Sdelphij return &emu->x86.R_DS; 792197007Sdelphij case 4: 793197007Sdelphij return &emu->x86.R_FS; 794197007Sdelphij case 5: 795197007Sdelphij return &emu->x86.R_GS; 796197007Sdelphij default: 797197007Sdelphij x86emu_halt_sys(emu); 798197007Sdelphij } 799197007Sdelphij} 800204934Sdelphij 801197007Sdelphij/* 802204934Sdelphij * Return offset from the SIB Byte. 803197007Sdelphij */ 804197007Sdelphijstatic uint32_t 805197007Sdelphijdecode_sib_address(struct x86emu *emu, int sib, int mod) 806197007Sdelphij{ 807197007Sdelphij uint32_t base = 0, i = 0, scale = 1; 808197007Sdelphij 809197007Sdelphij switch (sib & 0x07) { 810197007Sdelphij case 0: 811197007Sdelphij base = emu->x86.R_EAX; 812197007Sdelphij break; 813197007Sdelphij case 1: 814197007Sdelphij base = emu->x86.R_ECX; 815197007Sdelphij 816197007Sdelphij break; 817197007Sdelphij case 2: 818197007Sdelphij base = emu->x86.R_EDX; 819197007Sdelphij break; 820197007Sdelphij case 3: 821197007Sdelphij base = emu->x86.R_EBX; 822197007Sdelphij break; 823197007Sdelphij case 4: 824197007Sdelphij base = emu->x86.R_ESP; 825197007Sdelphij emu->x86.mode |= SYSMODE_SEG_DS_SS; 826197007Sdelphij break; 827197007Sdelphij case 5: 828197007Sdelphij if (mod == 0) { 829197007Sdelphij base = fetch_long_imm(emu); 830197007Sdelphij } else { 831197007Sdelphij base = emu->x86.R_EBP; 832197007Sdelphij emu->x86.mode |= SYSMODE_SEG_DS_SS; 833197007Sdelphij } 834197007Sdelphij break; 835197007Sdelphij case 6: 836197007Sdelphij base = emu->x86.R_ESI; 837197007Sdelphij break; 838197007Sdelphij case 7: 839197007Sdelphij base = emu->x86.R_EDI; 840197007Sdelphij break; 841197007Sdelphij } 842197007Sdelphij switch ((sib >> 3) & 0x07) { 843197007Sdelphij case 0: 844197007Sdelphij i = emu->x86.R_EAX; 845197007Sdelphij break; 846197007Sdelphij case 1: 847197007Sdelphij i = emu->x86.R_ECX; 848197007Sdelphij break; 849197007Sdelphij case 2: 850197007Sdelphij i = emu->x86.R_EDX; 851197007Sdelphij break; 852197007Sdelphij case 3: 853197007Sdelphij i = emu->x86.R_EBX; 854197007Sdelphij break; 855197007Sdelphij case 4: 856197007Sdelphij i = 0; 857197007Sdelphij break; 858197007Sdelphij case 5: 859197007Sdelphij i = emu->x86.R_EBP; 860197007Sdelphij break; 861197007Sdelphij case 6: 862197007Sdelphij i = emu->x86.R_ESI; 863197007Sdelphij break; 864197007Sdelphij case 7: 865197007Sdelphij i = emu->x86.R_EDI; 866197007Sdelphij break; 867197007Sdelphij } 868197007Sdelphij scale = 1 << ((sib >> 6) & 0x03); 869197007Sdelphij return base + (i * scale); 870197007Sdelphij} 871197007Sdelphij 872197007Sdelphij/* 873197007Sdelphij * PARAMETERS: 874197007Sdelphij * rm - RM value to decode 875197007Sdelphij * 876197007Sdelphij * RETURNS: 877197007Sdelphij * Offset in memory for the address decoding 878197007Sdelphij * 879197007Sdelphij * REMARKS: 880197007Sdelphij * Return the offset given by mod=00, mod=01 or mod=10 addressing. 881197007Sdelphij * Also enables the decoding of instructions. 882197007Sdelphij */ 883197007Sdelphijstatic uint32_t 884197007Sdelphijdecode_rl_address(struct x86emu *emu) 885197007Sdelphij{ 886197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_ADDR) { 887197007Sdelphij uint32_t offset, sib; 888197007Sdelphij /* 32-bit addressing */ 889197007Sdelphij switch (emu->cur_rl) { 890197007Sdelphij case 0: 891197007Sdelphij offset = emu->x86.R_EAX; 892197007Sdelphij break; 893197007Sdelphij case 1: 894197007Sdelphij offset = emu->x86.R_ECX; 895197007Sdelphij break; 896197007Sdelphij case 2: 897197007Sdelphij offset = emu->x86.R_EDX; 898197007Sdelphij break; 899197007Sdelphij case 3: 900197007Sdelphij offset = emu->x86.R_EBX; 901197007Sdelphij break; 902197007Sdelphij case 4: 903197007Sdelphij sib = fetch_byte_imm(emu); 904197007Sdelphij offset = decode_sib_address(emu, sib, 0); 905197007Sdelphij break; 906197007Sdelphij case 5: 907197007Sdelphij if (emu->cur_mod == 0) { 908197007Sdelphij offset = fetch_long_imm(emu); 909197007Sdelphij } else { 910197007Sdelphij emu->x86.mode |= SYSMODE_SEG_DS_SS; 911197007Sdelphij offset = emu->x86.R_EBP; 912197007Sdelphij } 913197007Sdelphij break; 914197007Sdelphij case 6: 915197007Sdelphij offset = emu->x86.R_ESI; 916197007Sdelphij break; 917197007Sdelphij case 7: 918197007Sdelphij offset = emu->x86.R_EDI; 919197007Sdelphij break; 920197007Sdelphij default: 921197007Sdelphij x86emu_halt_sys(emu); 922197007Sdelphij } 923197007Sdelphij if (emu->cur_mod == 1) 924197007Sdelphij offset += (int8_t)fetch_byte_imm(emu); 925197007Sdelphij else if (emu->cur_mod == 2) 926197007Sdelphij offset += fetch_long_imm(emu); 927197007Sdelphij return offset; 928197007Sdelphij } else { 929197007Sdelphij uint16_t offset; 930197007Sdelphij 931197007Sdelphij /* 16-bit addressing */ 932197007Sdelphij switch (emu->cur_rl) { 933197007Sdelphij case 0: 934197007Sdelphij offset = emu->x86.R_BX + emu->x86.R_SI; 935197007Sdelphij break; 936197007Sdelphij case 1: 937197007Sdelphij offset = emu->x86.R_BX + emu->x86.R_DI; 938197007Sdelphij break; 939197007Sdelphij case 2: 940197007Sdelphij emu->x86.mode |= SYSMODE_SEG_DS_SS; 941197007Sdelphij offset = emu->x86.R_BP + emu->x86.R_SI; 942197007Sdelphij break; 943197007Sdelphij case 3: 944197007Sdelphij emu->x86.mode |= SYSMODE_SEG_DS_SS; 945197007Sdelphij offset = emu->x86.R_BP + emu->x86.R_DI; 946197007Sdelphij break; 947197007Sdelphij case 4: 948197007Sdelphij offset = emu->x86.R_SI; 949197007Sdelphij break; 950197007Sdelphij case 5: 951197007Sdelphij offset = emu->x86.R_DI; 952197007Sdelphij break; 953197007Sdelphij case 6: 954197007Sdelphij if (emu->cur_mod == 0) { 955197007Sdelphij offset = fetch_word_imm(emu); 956197007Sdelphij } else { 957197007Sdelphij emu->x86.mode |= SYSMODE_SEG_DS_SS; 958197007Sdelphij offset = emu->x86.R_BP; 959197007Sdelphij } 960197007Sdelphij break; 961197007Sdelphij case 7: 962197007Sdelphij offset = emu->x86.R_BX; 963197007Sdelphij break; 964197007Sdelphij default: 965197007Sdelphij x86emu_halt_sys(emu); 966197007Sdelphij } 967197007Sdelphij if (emu->cur_mod == 1) 968197007Sdelphij offset += (int8_t)fetch_byte_imm(emu); 969197007Sdelphij else if (emu->cur_mod == 2) 970197007Sdelphij offset += fetch_word_imm(emu); 971197007Sdelphij return offset; 972197007Sdelphij } 973197007Sdelphij} 974197007Sdelphij 975197007Sdelphijstatic uint8_t 976197007Sdelphijdecode_and_fetch_byte(struct x86emu *emu) 977197007Sdelphij{ 978197007Sdelphij if (emu->cur_mod != 3) { 979197007Sdelphij emu->cur_offset = decode_rl_address(emu); 980197007Sdelphij return fetch_data_byte(emu, emu->cur_offset); 981197007Sdelphij } else { 982197007Sdelphij return *decode_rl_byte_register(emu); 983197007Sdelphij } 984197007Sdelphij} 985197007Sdelphij 986197007Sdelphijstatic uint16_t 987197007Sdelphijdecode_and_fetch_word_disp(struct x86emu *emu, int16_t disp) 988197007Sdelphij{ 989197007Sdelphij if (emu->cur_mod != 3) { 990197007Sdelphij /* TODO: A20 gate emulation */ 991197007Sdelphij emu->cur_offset = decode_rl_address(emu) + disp; 992197007Sdelphij if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0) 993197007Sdelphij emu->cur_offset &= 0xffff; 994197007Sdelphij return fetch_data_word(emu, emu->cur_offset); 995197007Sdelphij } else { 996197007Sdelphij return *decode_rl_word_register(emu); 997197007Sdelphij } 998197007Sdelphij} 999197007Sdelphij 1000197007Sdelphijstatic uint32_t 1001197007Sdelphijdecode_and_fetch_long_disp(struct x86emu *emu, int16_t disp) 1002197007Sdelphij{ 1003197007Sdelphij if (emu->cur_mod != 3) { 1004197007Sdelphij /* TODO: A20 gate emulation */ 1005197007Sdelphij emu->cur_offset = decode_rl_address(emu) + disp; 1006197007Sdelphij if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0) 1007197007Sdelphij emu->cur_offset &= 0xffff; 1008197007Sdelphij return fetch_data_long(emu, emu->cur_offset); 1009197007Sdelphij } else { 1010197007Sdelphij return *decode_rl_long_register(emu); 1011197007Sdelphij } 1012197007Sdelphij} 1013197007Sdelphij 1014197007Sdelphijuint16_t 1015197007Sdelphijdecode_and_fetch_word(struct x86emu *emu) 1016197007Sdelphij{ 1017197007Sdelphij return decode_and_fetch_word_disp(emu, 0); 1018197007Sdelphij} 1019197007Sdelphij 1020197007Sdelphijuint32_t 1021197007Sdelphijdecode_and_fetch_long(struct x86emu *emu) 1022197007Sdelphij{ 1023197007Sdelphij return decode_and_fetch_long_disp(emu, 0); 1024197007Sdelphij} 1025197007Sdelphij 1026197007Sdelphijuint8_t 1027197007Sdelphijdecode_and_fetch_byte_imm8(struct x86emu *emu, uint8_t *imm) 1028197007Sdelphij{ 1029197007Sdelphij if (emu->cur_mod != 3) { 1030197007Sdelphij emu->cur_offset = decode_rl_address(emu); 1031197007Sdelphij *imm = fetch_byte_imm(emu); 1032197007Sdelphij return fetch_data_byte(emu, emu->cur_offset); 1033197007Sdelphij } else { 1034197007Sdelphij *imm = fetch_byte_imm(emu); 1035197007Sdelphij return *decode_rl_byte_register(emu); 1036197007Sdelphij } 1037197007Sdelphij} 1038197007Sdelphij 1039197007Sdelphijstatic uint16_t 1040197007Sdelphijdecode_and_fetch_word_imm8(struct x86emu *emu, uint8_t *imm) 1041197007Sdelphij{ 1042197007Sdelphij if (emu->cur_mod != 3) { 1043197007Sdelphij emu->cur_offset = decode_rl_address(emu); 1044197007Sdelphij *imm = fetch_byte_imm(emu); 1045197007Sdelphij return fetch_data_word(emu, emu->cur_offset); 1046197007Sdelphij } else { 1047197007Sdelphij *imm = fetch_byte_imm(emu); 1048197007Sdelphij return *decode_rl_word_register(emu); 1049197007Sdelphij } 1050197007Sdelphij} 1051197007Sdelphij 1052197007Sdelphijstatic uint32_t 1053197007Sdelphijdecode_and_fetch_long_imm8(struct x86emu *emu, uint8_t *imm) 1054197007Sdelphij{ 1055197007Sdelphij if (emu->cur_mod != 3) { 1056197007Sdelphij emu->cur_offset = decode_rl_address(emu); 1057197007Sdelphij *imm = fetch_byte_imm(emu); 1058197007Sdelphij return fetch_data_long(emu, emu->cur_offset); 1059197007Sdelphij } else { 1060197007Sdelphij *imm = fetch_byte_imm(emu); 1061197007Sdelphij return *decode_rl_long_register(emu); 1062197007Sdelphij } 1063197007Sdelphij} 1064197007Sdelphij 1065197007Sdelphijstatic void 1066197007Sdelphijwrite_back_byte(struct x86emu *emu, uint8_t val) 1067197007Sdelphij{ 1068197007Sdelphij if (emu->cur_mod != 3) 1069197007Sdelphij store_data_byte(emu, emu->cur_offset, val); 1070197007Sdelphij else 1071197007Sdelphij *decode_rl_byte_register(emu) = val; 1072197007Sdelphij} 1073197007Sdelphij 1074197007Sdelphijstatic void 1075197007Sdelphijwrite_back_word(struct x86emu *emu, uint16_t val) 1076197007Sdelphij{ 1077197007Sdelphij if (emu->cur_mod != 3) 1078197007Sdelphij store_data_word(emu, emu->cur_offset, val); 1079197007Sdelphij else 1080197007Sdelphij *decode_rl_word_register(emu) = val; 1081197007Sdelphij} 1082197007Sdelphij 1083197007Sdelphijstatic void 1084197007Sdelphijwrite_back_long(struct x86emu *emu, uint32_t val) 1085197007Sdelphij{ 1086197007Sdelphij if (emu->cur_mod != 3) 1087197007Sdelphij store_data_long(emu, emu->cur_offset, val); 1088197007Sdelphij else 1089197007Sdelphij *decode_rl_long_register(emu) = val; 1090197007Sdelphij} 1091197007Sdelphij 1092197007Sdelphijstatic void 1093197007Sdelphijcommon_inc_word_long(struct x86emu *emu, union x86emu_register *reg) 1094197007Sdelphij{ 1095197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1096197007Sdelphij reg->I32_reg.e_reg = inc_long(emu, reg->I32_reg.e_reg); 1097197007Sdelphij else 1098197007Sdelphij reg->I16_reg.x_reg = inc_word(emu, reg->I16_reg.x_reg); 1099197007Sdelphij} 1100197007Sdelphij 1101197007Sdelphijstatic void 1102197007Sdelphijcommon_dec_word_long(struct x86emu *emu, union x86emu_register *reg) 1103197007Sdelphij{ 1104197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1105197007Sdelphij reg->I32_reg.e_reg = dec_long(emu, reg->I32_reg.e_reg); 1106197007Sdelphij else 1107197007Sdelphij reg->I16_reg.x_reg = dec_word(emu, reg->I16_reg.x_reg); 1108197007Sdelphij} 1109197007Sdelphij 1110197007Sdelphijstatic void 1111204934Sdelphijcommon_binop_byte_rm_r(struct x86emu *emu, 1112204934Sdelphij uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t)) 1113197007Sdelphij{ 1114197007Sdelphij uint32_t destoffset; 1115197007Sdelphij uint8_t *destreg, srcval; 1116197007Sdelphij uint8_t destval; 1117197007Sdelphij 1118197007Sdelphij fetch_decode_modrm(emu); 1119197007Sdelphij srcval = *decode_rh_byte_register(emu); 1120197007Sdelphij if (emu->cur_mod != 3) { 1121197007Sdelphij destoffset = decode_rl_address(emu); 1122197007Sdelphij destval = fetch_data_byte(emu, destoffset); 1123197007Sdelphij destval = (*binop)(emu, destval, srcval); 1124197007Sdelphij store_data_byte(emu, destoffset, destval); 1125197007Sdelphij } else { 1126197007Sdelphij destreg = decode_rl_byte_register(emu); 1127197007Sdelphij *destreg = (*binop)(emu, *destreg, srcval); 1128197007Sdelphij } 1129197007Sdelphij} 1130197007Sdelphij 1131197007Sdelphijstatic void 1132204934Sdelphijcommon_binop_ns_byte_rm_r(struct x86emu *emu, 1133204934Sdelphij void (*binop)(struct x86emu *, uint8_t, uint8_t)) 1134197007Sdelphij{ 1135197007Sdelphij uint32_t destoffset; 1136197007Sdelphij uint8_t destval, srcval; 1137197007Sdelphij 1138197007Sdelphij fetch_decode_modrm(emu); 1139197007Sdelphij srcval = *decode_rh_byte_register(emu); 1140197007Sdelphij if (emu->cur_mod != 3) { 1141197007Sdelphij destoffset = decode_rl_address(emu); 1142197007Sdelphij destval = fetch_data_byte(emu, destoffset); 1143197007Sdelphij } else { 1144197007Sdelphij destval = *decode_rl_byte_register(emu); 1145197007Sdelphij } 1146197007Sdelphij (*binop)(emu, destval, srcval); 1147197007Sdelphij} 1148197007Sdelphij 1149197007Sdelphijstatic void 1150204934Sdelphijcommon_binop_word_rm_r(struct x86emu *emu, 1151204934Sdelphij uint16_t (*binop)(struct x86emu *, uint16_t, uint16_t)) 1152197007Sdelphij{ 1153197007Sdelphij uint32_t destoffset; 1154197007Sdelphij uint16_t destval, *destreg, srcval; 1155197007Sdelphij 1156197007Sdelphij fetch_decode_modrm(emu); 1157197007Sdelphij srcval = *decode_rh_word_register(emu); 1158197007Sdelphij if (emu->cur_mod != 3) { 1159197007Sdelphij destoffset = decode_rl_address(emu); 1160197007Sdelphij destval = fetch_data_word(emu, destoffset); 1161197007Sdelphij destval = (*binop)(emu, destval, srcval); 1162197007Sdelphij store_data_word(emu, destoffset, destval); 1163197007Sdelphij } else { 1164197007Sdelphij destreg = decode_rl_word_register(emu); 1165197007Sdelphij *destreg = (*binop)(emu, *destreg, srcval); 1166197007Sdelphij } 1167197007Sdelphij} 1168197007Sdelphij 1169197007Sdelphijstatic void 1170204934Sdelphijcommon_binop_byte_r_rm(struct x86emu *emu, 1171204934Sdelphij uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t)) 1172197007Sdelphij{ 1173197007Sdelphij uint8_t *destreg, srcval; 1174197007Sdelphij uint32_t srcoffset; 1175197007Sdelphij 1176197007Sdelphij fetch_decode_modrm(emu); 1177197007Sdelphij destreg = decode_rh_byte_register(emu); 1178197007Sdelphij if (emu->cur_mod != 3) { 1179197007Sdelphij srcoffset = decode_rl_address(emu); 1180197007Sdelphij srcval = fetch_data_byte(emu, srcoffset); 1181197007Sdelphij } else { 1182197007Sdelphij srcval = *decode_rl_byte_register(emu); 1183197007Sdelphij } 1184197007Sdelphij *destreg = (*binop)(emu, *destreg, srcval); 1185197007Sdelphij} 1186197007Sdelphij 1187197007Sdelphijstatic void 1188204934Sdelphijcommon_binop_long_rm_r(struct x86emu *emu, 1189204934Sdelphij uint32_t (*binop)(struct x86emu *, uint32_t, uint32_t)) 1190197007Sdelphij{ 1191197007Sdelphij uint32_t destoffset; 1192197007Sdelphij uint32_t destval, *destreg, srcval; 1193197007Sdelphij 1194197007Sdelphij fetch_decode_modrm(emu); 1195197007Sdelphij srcval = *decode_rh_long_register(emu); 1196197007Sdelphij if (emu->cur_mod != 3) { 1197197007Sdelphij destoffset = decode_rl_address(emu); 1198197007Sdelphij destval = fetch_data_long(emu, destoffset); 1199197007Sdelphij destval = (*binop)(emu, destval, srcval); 1200197007Sdelphij store_data_long(emu, destoffset, destval); 1201197007Sdelphij } else { 1202197007Sdelphij destreg = decode_rl_long_register(emu); 1203197007Sdelphij *destreg = (*binop)(emu, *destreg, srcval); 1204197007Sdelphij } 1205197007Sdelphij} 1206197007Sdelphij 1207197007Sdelphijstatic void 1208197007Sdelphijcommon_binop_word_long_rm_r(struct x86emu *emu, 1209204934Sdelphij uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t), 1210204934Sdelphij uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t)) 1211197007Sdelphij{ 1212197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1213197007Sdelphij common_binop_long_rm_r(emu, binop32); 1214197007Sdelphij else 1215197007Sdelphij common_binop_word_rm_r(emu, binop16); 1216197007Sdelphij} 1217197007Sdelphij 1218197007Sdelphijstatic void 1219204934Sdelphijcommon_binop_ns_word_rm_r(struct x86emu *emu, 1220204934Sdelphij void (*binop)(struct x86emu *, uint16_t, uint16_t)) 1221197007Sdelphij{ 1222197007Sdelphij uint32_t destoffset; 1223197007Sdelphij uint16_t destval, srcval; 1224197007Sdelphij 1225197007Sdelphij fetch_decode_modrm(emu); 1226197007Sdelphij srcval = *decode_rh_word_register(emu); 1227197007Sdelphij if (emu->cur_mod != 3) { 1228197007Sdelphij destoffset = decode_rl_address(emu); 1229197007Sdelphij destval = fetch_data_word(emu, destoffset); 1230197007Sdelphij } else { 1231197007Sdelphij destval = *decode_rl_word_register(emu); 1232197007Sdelphij } 1233197007Sdelphij (*binop)(emu, destval, srcval); 1234197007Sdelphij} 1235197007Sdelphij 1236197007Sdelphij 1237197007Sdelphijstatic void 1238204934Sdelphijcommon_binop_ns_long_rm_r(struct x86emu *emu, 1239204934Sdelphij void (*binop)(struct x86emu *, uint32_t, uint32_t)) 1240197007Sdelphij{ 1241197007Sdelphij uint32_t destoffset; 1242197007Sdelphij uint32_t destval, srcval; 1243197007Sdelphij 1244197007Sdelphij fetch_decode_modrm(emu); 1245197007Sdelphij srcval = *decode_rh_long_register(emu); 1246197007Sdelphij if (emu->cur_mod != 3) { 1247197007Sdelphij destoffset = decode_rl_address(emu); 1248197007Sdelphij destval = fetch_data_long(emu, destoffset); 1249197007Sdelphij } else { 1250197007Sdelphij destval = *decode_rl_long_register(emu); 1251197007Sdelphij } 1252197007Sdelphij (*binop)(emu, destval, srcval); 1253197007Sdelphij} 1254197007Sdelphij 1255197007Sdelphijstatic void 1256197007Sdelphijcommon_binop_ns_word_long_rm_r(struct x86emu *emu, 1257204934Sdelphij void (*binop16)(struct x86emu *, uint16_t, uint16_t), 1258204934Sdelphij void (*binop32)(struct x86emu *, uint32_t, uint32_t)) 1259197007Sdelphij{ 1260197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1261197007Sdelphij common_binop_ns_long_rm_r(emu, binop32); 1262197007Sdelphij else 1263197007Sdelphij common_binop_ns_word_rm_r(emu, binop16); 1264197007Sdelphij} 1265197007Sdelphij 1266197007Sdelphijstatic void 1267204934Sdelphijcommon_binop_long_r_rm(struct x86emu *emu, 1268204934Sdelphij uint32_t (*binop)(struct x86emu *, uint32_t, uint32_t)) 1269197007Sdelphij{ 1270197007Sdelphij uint32_t srcoffset; 1271197007Sdelphij uint32_t *destreg, srcval; 1272197007Sdelphij 1273197007Sdelphij fetch_decode_modrm(emu); 1274197007Sdelphij destreg = decode_rh_long_register(emu); 1275197007Sdelphij if (emu->cur_mod != 3) { 1276197007Sdelphij srcoffset = decode_rl_address(emu); 1277197007Sdelphij srcval = fetch_data_long(emu, srcoffset); 1278197007Sdelphij } else { 1279197007Sdelphij srcval = *decode_rl_long_register(emu); 1280197007Sdelphij } 1281197007Sdelphij *destreg = (*binop)(emu, *destreg, srcval); 1282197007Sdelphij} 1283197007Sdelphij 1284197007Sdelphijstatic void 1285204934Sdelphijcommon_binop_word_r_rm(struct x86emu *emu, 1286204934Sdelphij uint16_t (*binop)(struct x86emu *, uint16_t, uint16_t)) 1287197007Sdelphij{ 1288197007Sdelphij uint32_t srcoffset; 1289197007Sdelphij uint16_t *destreg, srcval; 1290197007Sdelphij 1291197007Sdelphij fetch_decode_modrm(emu); 1292197007Sdelphij destreg = decode_rh_word_register(emu); 1293197007Sdelphij if (emu->cur_mod != 3) { 1294197007Sdelphij srcoffset = decode_rl_address(emu); 1295197007Sdelphij srcval = fetch_data_word(emu, srcoffset); 1296197007Sdelphij } else { 1297197007Sdelphij srcval = *decode_rl_word_register(emu); 1298197007Sdelphij } 1299197007Sdelphij *destreg = (*binop)(emu, *destreg, srcval); 1300197007Sdelphij} 1301197007Sdelphij 1302197007Sdelphijstatic void 1303197007Sdelphijcommon_binop_word_long_r_rm(struct x86emu *emu, 1304204934Sdelphij uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t), 1305204934Sdelphij uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t)) 1306197007Sdelphij{ 1307197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1308197007Sdelphij common_binop_long_r_rm(emu, binop32); 1309197007Sdelphij else 1310197007Sdelphij common_binop_word_r_rm(emu, binop16); 1311197007Sdelphij} 1312197007Sdelphij 1313197007Sdelphijstatic void 1314204934Sdelphijcommon_binop_byte_imm(struct x86emu *emu, 1315204934Sdelphij uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t)) 1316197007Sdelphij{ 1317197007Sdelphij uint8_t srcval; 1318197007Sdelphij 1319197007Sdelphij srcval = fetch_byte_imm(emu); 1320197007Sdelphij emu->x86.R_AL = (*binop)(emu, emu->x86.R_AL, srcval); 1321197007Sdelphij} 1322197007Sdelphij 1323197007Sdelphijstatic void 1324197007Sdelphijcommon_binop_word_long_imm(struct x86emu *emu, 1325204934Sdelphij uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t), 1326204934Sdelphij uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t)) 1327197007Sdelphij{ 1328197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1329197007Sdelphij uint32_t srcval; 1330197007Sdelphij 1331197007Sdelphij srcval = fetch_long_imm(emu); 1332197007Sdelphij emu->x86.R_EAX = (*binop32)(emu, emu->x86.R_EAX, srcval); 1333197007Sdelphij } else { 1334197007Sdelphij uint16_t srcval; 1335197007Sdelphij 1336197007Sdelphij srcval = fetch_word_imm(emu); 1337197007Sdelphij emu->x86.R_AX = (*binop16)(emu, emu->x86.R_AX, srcval); 1338197007Sdelphij } 1339197007Sdelphij} 1340197007Sdelphij 1341197007Sdelphijstatic void 1342197007Sdelphijcommon_push_word_long(struct x86emu *emu, union x86emu_register *reg) 1343197007Sdelphij{ 1344197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1345197007Sdelphij push_long(emu, reg->I32_reg.e_reg); 1346197007Sdelphij else 1347197007Sdelphij push_word(emu, reg->I16_reg.x_reg); 1348197007Sdelphij} 1349197007Sdelphij 1350197007Sdelphijstatic void 1351197007Sdelphijcommon_pop_word_long(struct x86emu *emu, union x86emu_register *reg) 1352197007Sdelphij{ 1353197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1354197007Sdelphij reg->I32_reg.e_reg = pop_long(emu); 1355197007Sdelphij else 1356197007Sdelphij reg->I16_reg.x_reg = pop_word(emu); 1357197007Sdelphij} 1358197007Sdelphij 1359197007Sdelphijstatic void 1360197007Sdelphijcommon_imul_long_IMM(struct x86emu *emu, int byte_imm) 1361197007Sdelphij{ 1362197007Sdelphij uint32_t srcoffset; 1363197007Sdelphij uint32_t *destreg, srcval; 1364197007Sdelphij int32_t imm; 1365197007Sdelphij uint64_t res; 1366197007Sdelphij 1367197007Sdelphij fetch_decode_modrm(emu); 1368197007Sdelphij destreg = decode_rh_long_register(emu); 1369197007Sdelphij if (emu->cur_mod != 3) { 1370197007Sdelphij srcoffset = decode_rl_address(emu); 1371197007Sdelphij srcval = fetch_data_long(emu, srcoffset); 1372197007Sdelphij } else { 1373197007Sdelphij srcval = *decode_rl_long_register(emu); 1374197007Sdelphij } 1375197007Sdelphij 1376197007Sdelphij if (byte_imm) 1377197007Sdelphij imm = (int8_t)fetch_byte_imm(emu); 1378197007Sdelphij else 1379197007Sdelphij imm = fetch_long_imm(emu); 1380197007Sdelphij res = (int32_t)srcval * imm; 1381197007Sdelphij 1382197007Sdelphij if (res > 0xffffffff) { 1383197007Sdelphij SET_FLAG(F_CF); 1384197007Sdelphij SET_FLAG(F_OF); 1385197007Sdelphij } else { 1386197007Sdelphij CLEAR_FLAG(F_CF); 1387197007Sdelphij CLEAR_FLAG(F_OF); 1388197007Sdelphij } 1389197007Sdelphij *destreg = (uint32_t)res; 1390197007Sdelphij} 1391197007Sdelphij 1392197007Sdelphijstatic void 1393197007Sdelphijcommon_imul_word_IMM(struct x86emu *emu, int byte_imm) 1394197007Sdelphij{ 1395197007Sdelphij uint32_t srcoffset; 1396197007Sdelphij uint16_t *destreg, srcval; 1397197007Sdelphij int16_t imm; 1398197007Sdelphij uint32_t res; 1399197007Sdelphij 1400197007Sdelphij fetch_decode_modrm(emu); 1401197007Sdelphij destreg = decode_rh_word_register(emu); 1402197007Sdelphij if (emu->cur_mod != 3) { 1403197007Sdelphij srcoffset = decode_rl_address(emu); 1404197007Sdelphij srcval = fetch_data_word(emu, srcoffset); 1405197007Sdelphij } else { 1406197007Sdelphij srcval = *decode_rl_word_register(emu); 1407197007Sdelphij } 1408197007Sdelphij 1409197007Sdelphij if (byte_imm) 1410197007Sdelphij imm = (int8_t)fetch_byte_imm(emu); 1411197007Sdelphij else 1412197007Sdelphij imm = fetch_word_imm(emu); 1413197007Sdelphij res = (int16_t)srcval * imm; 1414197007Sdelphij 1415197007Sdelphij if (res > 0xffff) { 1416197007Sdelphij SET_FLAG(F_CF); 1417197007Sdelphij SET_FLAG(F_OF); 1418197007Sdelphij } else { 1419197007Sdelphij CLEAR_FLAG(F_CF); 1420197007Sdelphij CLEAR_FLAG(F_OF); 1421197007Sdelphij } 1422197007Sdelphij *destreg = (uint16_t) res; 1423197007Sdelphij} 1424197007Sdelphij 1425197007Sdelphijstatic void 1426197007Sdelphijcommon_imul_imm(struct x86emu *emu, int byte_imm) 1427197007Sdelphij{ 1428197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1429197007Sdelphij common_imul_long_IMM(emu, byte_imm); 1430197007Sdelphij else 1431197007Sdelphij common_imul_word_IMM(emu, byte_imm); 1432197007Sdelphij} 1433197007Sdelphij 1434197007Sdelphijstatic void 1435197007Sdelphijcommon_jmp_near(struct x86emu *emu, int cond) 1436197007Sdelphij{ 1437197007Sdelphij int8_t offset; 1438197007Sdelphij uint16_t target; 1439197007Sdelphij 1440197007Sdelphij offset = (int8_t) fetch_byte_imm(emu); 1441197007Sdelphij target = (uint16_t) (emu->x86.R_IP + (int16_t) offset); 1442197007Sdelphij if (cond) 1443197007Sdelphij emu->x86.R_IP = target; 1444197007Sdelphij} 1445197007Sdelphij 1446197007Sdelphijstatic void 1447197007Sdelphijcommon_load_far_pointer(struct x86emu *emu, uint16_t *seg) 1448197007Sdelphij{ 1449197007Sdelphij uint16_t *dstreg; 1450197007Sdelphij uint32_t srcoffset; 1451197007Sdelphij 1452197007Sdelphij fetch_decode_modrm(emu); 1453197007Sdelphij if (emu->cur_mod == 3) 1454197007Sdelphij x86emu_halt_sys(emu); 1455197007Sdelphij 1456197007Sdelphij dstreg = decode_rh_word_register(emu); 1457197007Sdelphij srcoffset = decode_rl_address(emu); 1458197007Sdelphij *dstreg = fetch_data_word(emu, srcoffset); 1459197007Sdelphij *seg = fetch_data_word(emu, srcoffset + 2); 1460197007Sdelphij} 1461197007Sdelphij 1462197007Sdelphij/* Implementation */ 1463197007Sdelphij 1464197007Sdelphij/* 1465197007Sdelphij * REMARKS: 1466197007Sdelphij * Handles opcode 0x3a 1467197007Sdelphij */ 1468197007Sdelphijstatic void 1469197007Sdelphijx86emuOp_cmp_byte_R_RM(struct x86emu *emu) 1470197007Sdelphij{ 1471197007Sdelphij uint8_t *destreg, srcval; 1472197007Sdelphij 1473197007Sdelphij fetch_decode_modrm(emu); 1474197007Sdelphij destreg = decode_rh_byte_register(emu); 1475197007Sdelphij srcval = decode_and_fetch_byte(emu); 1476197007Sdelphij cmp_byte(emu, *destreg, srcval); 1477197007Sdelphij} 1478197007Sdelphij 1479197007Sdelphij/* 1480197007Sdelphij * REMARKS: 1481197007Sdelphij * 1482197007Sdelphij * Handles opcode 0x3b 1483197007Sdelphij */ 1484197007Sdelphijstatic void 1485197007Sdelphijx86emuOp32_cmp_word_R_RM(struct x86emu *emu) 1486197007Sdelphij{ 1487197007Sdelphij uint32_t srcval, *destreg; 1488197007Sdelphij 1489197007Sdelphij fetch_decode_modrm(emu); 1490197007Sdelphij destreg = decode_rh_long_register(emu); 1491197007Sdelphij srcval = decode_and_fetch_long(emu); 1492197007Sdelphij cmp_long(emu, *destreg, srcval); 1493197007Sdelphij} 1494197007Sdelphij 1495197007Sdelphijstatic void 1496197007Sdelphijx86emuOp16_cmp_word_R_RM(struct x86emu *emu) 1497197007Sdelphij{ 1498197007Sdelphij uint16_t srcval, *destreg; 1499197007Sdelphij 1500197007Sdelphij fetch_decode_modrm(emu); 1501197007Sdelphij destreg = decode_rh_word_register(emu); 1502197007Sdelphij srcval = decode_and_fetch_word(emu); 1503197007Sdelphij cmp_word(emu, *destreg, srcval); 1504197007Sdelphij} 1505197007Sdelphij 1506197007Sdelphijstatic void 1507197007Sdelphijx86emuOp_cmp_word_R_RM(struct x86emu *emu) 1508197007Sdelphij{ 1509197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1510197007Sdelphij x86emuOp32_cmp_word_R_RM(emu); 1511197007Sdelphij else 1512197007Sdelphij x86emuOp16_cmp_word_R_RM(emu); 1513197007Sdelphij} 1514197007Sdelphij 1515197007Sdelphij/* 1516197007Sdelphij * REMARKS: 1517197007Sdelphij * Handles opcode 0x3c 1518197007Sdelphij */ 1519197007Sdelphijstatic void 1520197007Sdelphijx86emuOp_cmp_byte_AL_IMM(struct x86emu *emu) 1521197007Sdelphij{ 1522197007Sdelphij uint8_t srcval; 1523197007Sdelphij 1524197007Sdelphij srcval = fetch_byte_imm(emu); 1525197007Sdelphij cmp_byte(emu, emu->x86.R_AL, srcval); 1526197007Sdelphij} 1527197007Sdelphij 1528197007Sdelphij/* 1529197007Sdelphij * REMARKS: 1530197007Sdelphij * Handles opcode 0x3d 1531197007Sdelphij */ 1532197007Sdelphijstatic void 1533197007Sdelphijx86emuOp32_cmp_word_AX_IMM(struct x86emu *emu) 1534197007Sdelphij{ 1535197007Sdelphij uint32_t srcval; 1536197007Sdelphij 1537197007Sdelphij srcval = fetch_long_imm(emu); 1538197007Sdelphij cmp_long(emu, emu->x86.R_EAX, srcval); 1539197007Sdelphij} 1540197007Sdelphij 1541197007Sdelphijstatic void 1542197007Sdelphijx86emuOp16_cmp_word_AX_IMM(struct x86emu *emu) 1543197007Sdelphij{ 1544197007Sdelphij uint16_t srcval; 1545197007Sdelphij 1546197007Sdelphij srcval = fetch_word_imm(emu); 1547197007Sdelphij cmp_word(emu, emu->x86.R_AX, srcval); 1548197007Sdelphij} 1549197007Sdelphij 1550197007Sdelphijstatic void 1551197007Sdelphijx86emuOp_cmp_word_AX_IMM(struct x86emu *emu) 1552197007Sdelphij{ 1553197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1554197007Sdelphij x86emuOp32_cmp_word_AX_IMM(emu); 1555197007Sdelphij else 1556197007Sdelphij x86emuOp16_cmp_word_AX_IMM(emu); 1557197007Sdelphij} 1558197007Sdelphij 1559197007Sdelphij/* 1560197007Sdelphij * REMARKS: 1561197007Sdelphij * Handles opcode 0x60 1562197007Sdelphij */ 1563197007Sdelphijstatic void 1564197007Sdelphijx86emuOp_push_all(struct x86emu *emu) 1565197007Sdelphij{ 1566197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1567197007Sdelphij uint32_t old_sp = emu->x86.R_ESP; 1568197007Sdelphij 1569197007Sdelphij push_long(emu, emu->x86.R_EAX); 1570197007Sdelphij push_long(emu, emu->x86.R_ECX); 1571197007Sdelphij push_long(emu, emu->x86.R_EDX); 1572197007Sdelphij push_long(emu, emu->x86.R_EBX); 1573197007Sdelphij push_long(emu, old_sp); 1574197007Sdelphij push_long(emu, emu->x86.R_EBP); 1575197007Sdelphij push_long(emu, emu->x86.R_ESI); 1576197007Sdelphij push_long(emu, emu->x86.R_EDI); 1577197007Sdelphij } else { 1578197007Sdelphij uint16_t old_sp = emu->x86.R_SP; 1579197007Sdelphij 1580197007Sdelphij push_word(emu, emu->x86.R_AX); 1581197007Sdelphij push_word(emu, emu->x86.R_CX); 1582197007Sdelphij push_word(emu, emu->x86.R_DX); 1583197007Sdelphij push_word(emu, emu->x86.R_BX); 1584197007Sdelphij push_word(emu, old_sp); 1585197007Sdelphij push_word(emu, emu->x86.R_BP); 1586197007Sdelphij push_word(emu, emu->x86.R_SI); 1587197007Sdelphij push_word(emu, emu->x86.R_DI); 1588197007Sdelphij } 1589197007Sdelphij} 1590197007Sdelphij 1591197007Sdelphij/* 1592197007Sdelphij * REMARKS: 1593197007Sdelphij * Handles opcode 0x61 1594197007Sdelphij */ 1595197007Sdelphijstatic void 1596197007Sdelphijx86emuOp_pop_all(struct x86emu *emu) 1597197007Sdelphij{ 1598197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1599197007Sdelphij emu->x86.R_EDI = pop_long(emu); 1600197007Sdelphij emu->x86.R_ESI = pop_long(emu); 1601197007Sdelphij emu->x86.R_EBP = pop_long(emu); 1602197007Sdelphij emu->x86.R_ESP += 4; /* skip ESP */ 1603197007Sdelphij emu->x86.R_EBX = pop_long(emu); 1604197007Sdelphij emu->x86.R_EDX = pop_long(emu); 1605197007Sdelphij emu->x86.R_ECX = pop_long(emu); 1606197007Sdelphij emu->x86.R_EAX = pop_long(emu); 1607197007Sdelphij } else { 1608197007Sdelphij emu->x86.R_DI = pop_word(emu); 1609197007Sdelphij emu->x86.R_SI = pop_word(emu); 1610197007Sdelphij emu->x86.R_BP = pop_word(emu); 1611197007Sdelphij emu->x86.R_SP += 2;/* skip SP */ 1612197007Sdelphij emu->x86.R_BX = pop_word(emu); 1613197007Sdelphij emu->x86.R_DX = pop_word(emu); 1614197007Sdelphij emu->x86.R_CX = pop_word(emu); 1615197007Sdelphij emu->x86.R_AX = pop_word(emu); 1616197007Sdelphij } 1617197007Sdelphij} 1618197007Sdelphij/*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */ 1619197007Sdelphij/*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */ 1620197007Sdelphij 1621197007Sdelphij 1622197007Sdelphij/* 1623197007Sdelphij * REMARKS: 1624197007Sdelphij * Handles opcode 0x68 1625197007Sdelphij */ 1626197007Sdelphijstatic void 1627197007Sdelphijx86emuOp_push_word_IMM(struct x86emu *emu) 1628197007Sdelphij{ 1629197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1630197007Sdelphij uint32_t imm; 1631197007Sdelphij 1632197007Sdelphij imm = fetch_long_imm(emu); 1633197007Sdelphij push_long(emu, imm); 1634197007Sdelphij } else { 1635197007Sdelphij uint16_t imm; 1636197007Sdelphij 1637197007Sdelphij imm = fetch_word_imm(emu); 1638197007Sdelphij push_word(emu, imm); 1639197007Sdelphij } 1640197007Sdelphij} 1641197007Sdelphij 1642197007Sdelphij/* 1643197007Sdelphij * REMARKS: 1644197007Sdelphij * Handles opcode 0x6a 1645197007Sdelphij */ 1646197007Sdelphijstatic void 1647197007Sdelphijx86emuOp_push_byte_IMM(struct x86emu *emu) 1648197007Sdelphij{ 1649197007Sdelphij int16_t imm; 1650197007Sdelphij 1651197007Sdelphij imm = (int8_t) fetch_byte_imm(emu); 1652197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1653197007Sdelphij push_long(emu, (int32_t) imm); 1654197007Sdelphij } else { 1655197007Sdelphij push_word(emu, imm); 1656197007Sdelphij } 1657197007Sdelphij} 1658197007Sdelphij 1659197007Sdelphij/* 1660197007Sdelphij * REMARKS: 1661197007Sdelphij * Handles opcode 0x6c and 0x6d 1662197007Sdelphij */ 1663197007Sdelphijstatic void 1664197007Sdelphijx86emuOp_ins_word(struct x86emu *emu) 1665197007Sdelphij{ 1666197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1667197007Sdelphij ins(emu, 4); 1668197007Sdelphij } else { 1669197007Sdelphij ins(emu, 2); 1670197007Sdelphij } 1671197007Sdelphij} 1672197007Sdelphij 1673197007Sdelphij/* 1674197007Sdelphij * REMARKS: 1675197007Sdelphij * Handles opcode 0x6f 1676197007Sdelphij */ 1677197007Sdelphijstatic void 1678197007Sdelphijx86emuOp_outs_word(struct x86emu *emu) 1679197007Sdelphij{ 1680197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1681197007Sdelphij outs(emu, 4); 1682197007Sdelphij } else { 1683197007Sdelphij outs(emu, 2); 1684197007Sdelphij } 1685197007Sdelphij} 1686197007Sdelphij 1687197007Sdelphij/* 1688197007Sdelphij * REMARKS: 1689197007Sdelphij * Handles opcode 0x7c 1690197007Sdelphij */ 1691197007Sdelphijstatic void 1692197007Sdelphijx86emuOp_jump_near_L(struct x86emu *emu) 1693197007Sdelphij{ 1694197007Sdelphij int sf, of; 1695197007Sdelphij 1696197007Sdelphij sf = ACCESS_FLAG(F_SF) != 0; 1697197007Sdelphij of = ACCESS_FLAG(F_OF) != 0; 1698197007Sdelphij 1699197007Sdelphij common_jmp_near(emu, sf != of); 1700197007Sdelphij} 1701197007Sdelphij 1702197007Sdelphij/* 1703197007Sdelphij * REMARKS: 1704197007Sdelphij * Handles opcode 0x7d 1705197007Sdelphij */ 1706197007Sdelphijstatic void 1707197007Sdelphijx86emuOp_jump_near_NL(struct x86emu *emu) 1708197007Sdelphij{ 1709197007Sdelphij int sf, of; 1710197007Sdelphij 1711197007Sdelphij sf = ACCESS_FLAG(F_SF) != 0; 1712197007Sdelphij of = ACCESS_FLAG(F_OF) != 0; 1713197007Sdelphij 1714197007Sdelphij common_jmp_near(emu, sf == of); 1715197007Sdelphij} 1716197007Sdelphij 1717197007Sdelphij/* 1718197007Sdelphij * REMARKS: 1719197007Sdelphij * Handles opcode 0x7e 1720197007Sdelphij */ 1721197007Sdelphijstatic void 1722197007Sdelphijx86emuOp_jump_near_LE(struct x86emu *emu) 1723197007Sdelphij{ 1724197007Sdelphij int sf, of; 1725197007Sdelphij 1726197007Sdelphij sf = ACCESS_FLAG(F_SF) != 0; 1727197007Sdelphij of = ACCESS_FLAG(F_OF) != 0; 1728197007Sdelphij 1729197007Sdelphij common_jmp_near(emu, sf != of || ACCESS_FLAG(F_ZF)); 1730197007Sdelphij} 1731197007Sdelphij 1732197007Sdelphij/* 1733197007Sdelphij * REMARKS: 1734197007Sdelphij * Handles opcode 0x7f 1735197007Sdelphij */ 1736197007Sdelphijstatic void 1737197007Sdelphijx86emuOp_jump_near_NLE(struct x86emu *emu) 1738197007Sdelphij{ 1739197007Sdelphij int sf, of; 1740197007Sdelphij 1741197007Sdelphij sf = ACCESS_FLAG(F_SF) != 0; 1742197007Sdelphij of = ACCESS_FLAG(F_OF) != 0; 1743197007Sdelphij 1744197007Sdelphij common_jmp_near(emu, sf == of && !ACCESS_FLAG(F_ZF)); 1745197007Sdelphij} 1746197007Sdelphij 1747197007Sdelphijstatic 1748197007Sdelphijuint8_t(*const opc80_byte_operation[]) (struct x86emu *, uint8_t d, uint8_t s) = 1749197007Sdelphij{ 1750197007Sdelphij add_byte, /* 00 */ 1751197007Sdelphij or_byte, /* 01 */ 1752197007Sdelphij adc_byte, /* 02 */ 1753197007Sdelphij sbb_byte, /* 03 */ 1754197007Sdelphij and_byte, /* 04 */ 1755197007Sdelphij sub_byte, /* 05 */ 1756197007Sdelphij xor_byte, /* 06 */ 1757197007Sdelphij cmp_byte, /* 07 */ 1758197007Sdelphij}; 1759197007Sdelphij 1760197007Sdelphij/* 1761197007Sdelphij * REMARKS: 1762197007Sdelphij * Handles opcode 0x80 1763197007Sdelphij */ 1764197007Sdelphijstatic void 1765197007Sdelphijx86emuOp_opc80_byte_RM_IMM(struct x86emu *emu) 1766197007Sdelphij{ 1767197007Sdelphij uint8_t imm, destval; 1768197007Sdelphij 1769197007Sdelphij /* 1770197007Sdelphij * Weirdo special case instruction format. Part of the opcode 1771197007Sdelphij * held below in "RH". Doubly nested case would result, except 1772197007Sdelphij * that the decoded instruction 1773197007Sdelphij */ 1774197007Sdelphij fetch_decode_modrm(emu); 1775197007Sdelphij destval = decode_and_fetch_byte(emu); 1776197007Sdelphij imm = fetch_byte_imm(emu); 1777197007Sdelphij destval = (*opc80_byte_operation[emu->cur_rh]) (emu, destval, imm); 1778197007Sdelphij if (emu->cur_rh != 7) 1779197007Sdelphij write_back_byte(emu, destval); 1780197007Sdelphij} 1781197007Sdelphij 1782197007Sdelphijstatic 1783204934Sdelphijuint16_t(* const opc81_word_operation[]) 1784204934Sdelphij (struct x86emu *, uint16_t d, uint16_t s) = 1785197007Sdelphij{ 1786197007Sdelphij add_word, /* 00 */ 1787197007Sdelphij or_word, /* 01 */ 1788197007Sdelphij adc_word, /* 02 */ 1789197007Sdelphij sbb_word, /* 03 */ 1790197007Sdelphij and_word, /* 04 */ 1791197007Sdelphij sub_word, /* 05 */ 1792197007Sdelphij xor_word, /* 06 */ 1793197007Sdelphij cmp_word, /* 07 */ 1794197007Sdelphij}; 1795197007Sdelphij 1796197007Sdelphijstatic 1797204934Sdelphijuint32_t(* const opc81_long_operation[]) 1798204934Sdelphij (struct x86emu *, uint32_t d, uint32_t s) = 1799197007Sdelphij{ 1800197007Sdelphij add_long, /* 00 */ 1801197007Sdelphij or_long, /* 01 */ 1802197007Sdelphij adc_long, /* 02 */ 1803197007Sdelphij sbb_long, /* 03 */ 1804197007Sdelphij and_long, /* 04 */ 1805197007Sdelphij sub_long, /* 05 */ 1806197007Sdelphij xor_long, /* 06 */ 1807197007Sdelphij cmp_long, /* 07 */ 1808197007Sdelphij}; 1809197007Sdelphij 1810197007Sdelphij/* 1811197007Sdelphij * REMARKS: 1812197007Sdelphij * Handles opcode 0x81 1813197007Sdelphij */ 1814197007Sdelphijstatic void 1815197007Sdelphijx86emuOp32_opc81_word_RM_IMM(struct x86emu *emu) 1816197007Sdelphij{ 1817197007Sdelphij uint32_t destval, imm; 1818197007Sdelphij 1819197007Sdelphij /* 1820197007Sdelphij * Weirdo special case instruction format. Part of the opcode 1821197007Sdelphij * held below in "RH". Doubly nested case would result, except 1822197007Sdelphij * that the decoded instruction 1823197007Sdelphij */ 1824197007Sdelphij fetch_decode_modrm(emu); 1825197007Sdelphij destval = decode_and_fetch_long(emu); 1826197007Sdelphij imm = fetch_long_imm(emu); 1827197007Sdelphij destval = (*opc81_long_operation[emu->cur_rh]) (emu, destval, imm); 1828197007Sdelphij if (emu->cur_rh != 7) 1829197007Sdelphij write_back_long(emu, destval); 1830197007Sdelphij} 1831197007Sdelphij 1832197007Sdelphijstatic void 1833197007Sdelphijx86emuOp16_opc81_word_RM_IMM(struct x86emu *emu) 1834197007Sdelphij{ 1835197007Sdelphij uint16_t destval, imm; 1836197007Sdelphij 1837197007Sdelphij /* 1838197007Sdelphij * Weirdo special case instruction format. Part of the opcode 1839197007Sdelphij * held below in "RH". Doubly nested case would result, except 1840197007Sdelphij * that the decoded instruction 1841197007Sdelphij */ 1842197007Sdelphij fetch_decode_modrm(emu); 1843197007Sdelphij destval = decode_and_fetch_word(emu); 1844197007Sdelphij imm = fetch_word_imm(emu); 1845197007Sdelphij destval = (*opc81_word_operation[emu->cur_rh]) (emu, destval, imm); 1846197007Sdelphij if (emu->cur_rh != 7) 1847197007Sdelphij write_back_word(emu, destval); 1848197007Sdelphij} 1849197007Sdelphij 1850197007Sdelphijstatic void 1851197007Sdelphijx86emuOp_opc81_word_RM_IMM(struct x86emu *emu) 1852197007Sdelphij{ 1853197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1854197007Sdelphij x86emuOp32_opc81_word_RM_IMM(emu); 1855197007Sdelphij else 1856197007Sdelphij x86emuOp16_opc81_word_RM_IMM(emu); 1857197007Sdelphij} 1858197007Sdelphij 1859197007Sdelphijstatic 1860204934Sdelphijuint8_t(* const opc82_byte_operation[]) 1861204934Sdelphij (struct x86emu *, uint8_t s, uint8_t d) = 1862197007Sdelphij{ 1863197007Sdelphij add_byte, /* 00 */ 1864197007Sdelphij or_byte, /* 01 *//* YYY UNUSED ???? */ 1865197007Sdelphij adc_byte, /* 02 */ 1866197007Sdelphij sbb_byte, /* 03 */ 1867197007Sdelphij and_byte, /* 04 *//* YYY UNUSED ???? */ 1868197007Sdelphij sub_byte, /* 05 */ 1869197007Sdelphij xor_byte, /* 06 *//* YYY UNUSED ???? */ 1870197007Sdelphij cmp_byte, /* 07 */ 1871197007Sdelphij}; 1872197007Sdelphij 1873197007Sdelphij/* 1874197007Sdelphij * REMARKS: 1875197007Sdelphij * Handles opcode 0x82 1876197007Sdelphij */ 1877197007Sdelphijstatic void 1878197007Sdelphijx86emuOp_opc82_byte_RM_IMM(struct x86emu *emu) 1879197007Sdelphij{ 1880197007Sdelphij uint8_t imm, destval; 1881197007Sdelphij 1882197007Sdelphij /* 1883197007Sdelphij * Weirdo special case instruction format. Part of the opcode 1884197007Sdelphij * held below in "RH". Doubly nested case would result, except 1885197007Sdelphij * that the decoded instruction Similar to opcode 81, except that 1886197007Sdelphij * the immediate byte is sign extended to a word length. 1887197007Sdelphij */ 1888197007Sdelphij fetch_decode_modrm(emu); 1889197007Sdelphij destval = decode_and_fetch_byte(emu); 1890197007Sdelphij imm = fetch_byte_imm(emu); 1891197007Sdelphij destval = (*opc82_byte_operation[emu->cur_rh]) (emu, destval, imm); 1892197007Sdelphij if (emu->cur_rh != 7) 1893197007Sdelphij write_back_byte(emu, destval); 1894197007Sdelphij} 1895197007Sdelphij 1896197007Sdelphijstatic 1897204934Sdelphijuint16_t(* const opc83_word_operation[]) 1898204934Sdelphij (struct x86emu *, uint16_t s, uint16_t d) = 1899197007Sdelphij{ 1900197007Sdelphij add_word, /* 00 */ 1901197007Sdelphij or_word, /* 01 *//* YYY UNUSED ???? */ 1902197007Sdelphij adc_word, /* 02 */ 1903197007Sdelphij sbb_word, /* 03 */ 1904197007Sdelphij and_word, /* 04 *//* YYY UNUSED ???? */ 1905197007Sdelphij sub_word, /* 05 */ 1906197007Sdelphij xor_word, /* 06 *//* YYY UNUSED ???? */ 1907197007Sdelphij cmp_word, /* 07 */ 1908197007Sdelphij}; 1909197007Sdelphij 1910197007Sdelphijstatic 1911204934Sdelphijuint32_t(* const opc83_long_operation[]) 1912204934Sdelphij (struct x86emu *, uint32_t s, uint32_t d) = 1913197007Sdelphij{ 1914197007Sdelphij add_long, /* 00 */ 1915197007Sdelphij or_long, /* 01 *//* YYY UNUSED ???? */ 1916197007Sdelphij adc_long, /* 02 */ 1917197007Sdelphij sbb_long, /* 03 */ 1918197007Sdelphij and_long, /* 04 *//* YYY UNUSED ???? */ 1919197007Sdelphij sub_long, /* 05 */ 1920197007Sdelphij xor_long, /* 06 *//* YYY UNUSED ???? */ 1921197007Sdelphij cmp_long, /* 07 */ 1922197007Sdelphij}; 1923197007Sdelphij 1924197007Sdelphij/* 1925197007Sdelphij * REMARKS: 1926197007Sdelphij * Handles opcode 0x83 1927197007Sdelphij */ 1928197007Sdelphijstatic void 1929197007Sdelphijx86emuOp32_opc83_word_RM_IMM(struct x86emu *emu) 1930197007Sdelphij{ 1931197007Sdelphij uint32_t destval, imm; 1932197007Sdelphij 1933197007Sdelphij fetch_decode_modrm(emu); 1934197007Sdelphij destval = decode_and_fetch_long(emu); 1935197007Sdelphij imm = (int8_t) fetch_byte_imm(emu); 1936197007Sdelphij destval = (*opc83_long_operation[emu->cur_rh]) (emu, destval, imm); 1937197007Sdelphij if (emu->cur_rh != 7) 1938197007Sdelphij write_back_long(emu, destval); 1939197007Sdelphij} 1940197007Sdelphij 1941197007Sdelphijstatic void 1942197007Sdelphijx86emuOp16_opc83_word_RM_IMM(struct x86emu *emu) 1943197007Sdelphij{ 1944197007Sdelphij uint16_t destval, imm; 1945197007Sdelphij 1946197007Sdelphij fetch_decode_modrm(emu); 1947197007Sdelphij destval = decode_and_fetch_word(emu); 1948197007Sdelphij imm = (int8_t) fetch_byte_imm(emu); 1949197007Sdelphij destval = (*opc83_word_operation[emu->cur_rh]) (emu, destval, imm); 1950197007Sdelphij if (emu->cur_rh != 7) 1951197007Sdelphij write_back_word(emu, destval); 1952197007Sdelphij} 1953197007Sdelphij 1954197007Sdelphijstatic void 1955197007Sdelphijx86emuOp_opc83_word_RM_IMM(struct x86emu *emu) 1956197007Sdelphij{ 1957197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1958197007Sdelphij x86emuOp32_opc83_word_RM_IMM(emu); 1959197007Sdelphij else 1960197007Sdelphij x86emuOp16_opc83_word_RM_IMM(emu); 1961197007Sdelphij} 1962197007Sdelphij 1963197007Sdelphij/* 1964197007Sdelphij * REMARKS: 1965197007Sdelphij * Handles opcode 0x86 1966197007Sdelphij */ 1967197007Sdelphijstatic void 1968197007Sdelphijx86emuOp_xchg_byte_RM_R(struct x86emu *emu) 1969197007Sdelphij{ 1970197007Sdelphij uint8_t *srcreg, destval, tmp; 1971197007Sdelphij 1972197007Sdelphij fetch_decode_modrm(emu); 1973197007Sdelphij destval = decode_and_fetch_byte(emu); 1974197007Sdelphij srcreg = decode_rh_byte_register(emu); 1975197007Sdelphij tmp = destval; 1976197007Sdelphij destval = *srcreg; 1977197007Sdelphij *srcreg = tmp; 1978197007Sdelphij write_back_byte(emu, destval); 1979197007Sdelphij} 1980197007Sdelphij 1981197007Sdelphij/* 1982197007Sdelphij * REMARKS: 1983197007Sdelphij * Handles opcode 0x87 1984197007Sdelphij */ 1985197007Sdelphijstatic void 1986197007Sdelphijx86emuOp32_xchg_word_RM_R(struct x86emu *emu) 1987197007Sdelphij{ 1988197007Sdelphij uint32_t *srcreg, destval, tmp; 1989197007Sdelphij 1990197007Sdelphij fetch_decode_modrm(emu); 1991197007Sdelphij destval = decode_and_fetch_long(emu); 1992197007Sdelphij srcreg = decode_rh_long_register(emu); 1993197007Sdelphij tmp = destval; 1994197007Sdelphij destval = *srcreg; 1995197007Sdelphij *srcreg = tmp; 1996197007Sdelphij write_back_long(emu, destval); 1997197007Sdelphij} 1998197007Sdelphij 1999197007Sdelphijstatic void 2000197007Sdelphijx86emuOp16_xchg_word_RM_R(struct x86emu *emu) 2001197007Sdelphij{ 2002197007Sdelphij uint16_t *srcreg, destval, tmp; 2003197007Sdelphij 2004197007Sdelphij fetch_decode_modrm(emu); 2005197007Sdelphij destval = decode_and_fetch_word(emu); 2006197007Sdelphij srcreg = decode_rh_word_register(emu); 2007197007Sdelphij tmp = destval; 2008197007Sdelphij destval = *srcreg; 2009197007Sdelphij *srcreg = tmp; 2010197007Sdelphij write_back_word(emu, destval); 2011197007Sdelphij} 2012197007Sdelphij 2013197007Sdelphijstatic void 2014197007Sdelphijx86emuOp_xchg_word_RM_R(struct x86emu *emu) 2015197007Sdelphij{ 2016197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2017197007Sdelphij x86emuOp32_xchg_word_RM_R(emu); 2018197007Sdelphij else 2019197007Sdelphij x86emuOp16_xchg_word_RM_R(emu); 2020197007Sdelphij} 2021197007Sdelphij 2022197007Sdelphij/* 2023197007Sdelphij * REMARKS: 2024197007Sdelphij * Handles opcode 0x88 2025197007Sdelphij */ 2026197007Sdelphijstatic void 2027197007Sdelphijx86emuOp_mov_byte_RM_R(struct x86emu *emu) 2028197007Sdelphij{ 2029197007Sdelphij uint8_t *destreg, *srcreg; 2030197007Sdelphij uint32_t destoffset; 2031197007Sdelphij 2032197007Sdelphij fetch_decode_modrm(emu); 2033197007Sdelphij srcreg = decode_rh_byte_register(emu); 2034197007Sdelphij if (emu->cur_mod != 3) { 2035197007Sdelphij destoffset = decode_rl_address(emu); 2036197007Sdelphij store_data_byte(emu, destoffset, *srcreg); 2037197007Sdelphij } else { 2038197007Sdelphij destreg = decode_rl_byte_register(emu); 2039197007Sdelphij *destreg = *srcreg; 2040197007Sdelphij } 2041197007Sdelphij} 2042197007Sdelphij 2043197007Sdelphij/* 2044197007Sdelphij * REMARKS: 2045197007Sdelphij * Handles opcode 0x89 2046197007Sdelphij */ 2047197007Sdelphijstatic void 2048197007Sdelphijx86emuOp32_mov_word_RM_R(struct x86emu *emu) 2049197007Sdelphij{ 2050197007Sdelphij uint32_t destoffset; 2051197007Sdelphij uint32_t *destreg, srcval; 2052197007Sdelphij 2053197007Sdelphij fetch_decode_modrm(emu); 2054197007Sdelphij srcval = *decode_rh_long_register(emu); 2055197007Sdelphij if (emu->cur_mod != 3) { 2056197007Sdelphij destoffset = decode_rl_address(emu); 2057197007Sdelphij store_data_long(emu, destoffset, srcval); 2058197007Sdelphij } else { 2059197007Sdelphij destreg = decode_rl_long_register(emu); 2060197007Sdelphij *destreg = srcval; 2061197007Sdelphij } 2062197007Sdelphij} 2063197007Sdelphij 2064197007Sdelphijstatic void 2065197007Sdelphijx86emuOp16_mov_word_RM_R(struct x86emu *emu) 2066197007Sdelphij{ 2067197007Sdelphij uint32_t destoffset; 2068197007Sdelphij uint16_t *destreg, srcval; 2069197007Sdelphij 2070197007Sdelphij fetch_decode_modrm(emu); 2071197007Sdelphij srcval = *decode_rh_word_register(emu); 2072197007Sdelphij if (emu->cur_mod != 3) { 2073197007Sdelphij destoffset = decode_rl_address(emu); 2074197007Sdelphij store_data_word(emu, destoffset, srcval); 2075197007Sdelphij } else { 2076197007Sdelphij destreg = decode_rl_word_register(emu); 2077197007Sdelphij *destreg = srcval; 2078197007Sdelphij } 2079197007Sdelphij} 2080197007Sdelphij 2081197007Sdelphijstatic void 2082197007Sdelphijx86emuOp_mov_word_RM_R(struct x86emu *emu) 2083197007Sdelphij{ 2084197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2085197007Sdelphij x86emuOp32_mov_word_RM_R(emu); 2086197007Sdelphij else 2087197007Sdelphij x86emuOp16_mov_word_RM_R(emu); 2088197007Sdelphij} 2089197007Sdelphij 2090197007Sdelphij/* 2091197007Sdelphij * REMARKS: 2092197007Sdelphij * Handles opcode 0x8a 2093197007Sdelphij */ 2094197007Sdelphijstatic void 2095197007Sdelphijx86emuOp_mov_byte_R_RM(struct x86emu *emu) 2096197007Sdelphij{ 2097197007Sdelphij uint8_t *destreg; 2098197007Sdelphij 2099197007Sdelphij fetch_decode_modrm(emu); 2100197007Sdelphij destreg = decode_rh_byte_register(emu); 2101197007Sdelphij *destreg = decode_and_fetch_byte(emu); 2102197007Sdelphij} 2103197007Sdelphij 2104197007Sdelphij/* 2105197007Sdelphij * REMARKS: 2106197007Sdelphij * Handles opcode 0x8b 2107197007Sdelphij */ 2108197007Sdelphijstatic void 2109197007Sdelphijx86emuOp_mov_word_R_RM(struct x86emu *emu) 2110197007Sdelphij{ 2111197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2112197007Sdelphij uint32_t *destreg; 2113197007Sdelphij 2114197007Sdelphij fetch_decode_modrm(emu); 2115197007Sdelphij destreg = decode_rh_long_register(emu); 2116197007Sdelphij *destreg = decode_and_fetch_long(emu); 2117197007Sdelphij } else { 2118197007Sdelphij uint16_t *destreg; 2119197007Sdelphij 2120197007Sdelphij fetch_decode_modrm(emu); 2121197007Sdelphij destreg = decode_rh_word_register(emu); 2122197007Sdelphij *destreg = decode_and_fetch_word(emu); 2123197007Sdelphij } 2124197007Sdelphij} 2125197007Sdelphij 2126197007Sdelphij/* 2127197007Sdelphij * REMARKS: 2128197007Sdelphij * Handles opcode 0x8c 2129197007Sdelphij */ 2130197007Sdelphijstatic void 2131197007Sdelphijx86emuOp_mov_word_RM_SR(struct x86emu *emu) 2132197007Sdelphij{ 2133197007Sdelphij uint16_t *destreg, srcval; 2134197007Sdelphij uint32_t destoffset; 2135197007Sdelphij 2136197007Sdelphij fetch_decode_modrm(emu); 2137197007Sdelphij srcval = *decode_rh_seg_register(emu); 2138197007Sdelphij if (emu->cur_mod != 3) { 2139197007Sdelphij destoffset = decode_rl_address(emu); 2140197007Sdelphij store_data_word(emu, destoffset, srcval); 2141197007Sdelphij } else { 2142197007Sdelphij destreg = decode_rl_word_register(emu); 2143197007Sdelphij *destreg = srcval; 2144197007Sdelphij } 2145197007Sdelphij} 2146197007Sdelphij 2147197007Sdelphij/* 2148197007Sdelphij * REMARKS: 2149197007Sdelphij * Handles opcode 0x8d 2150197007Sdelphij */ 2151197007Sdelphijstatic void 2152197007Sdelphijx86emuOp_lea_word_R_M(struct x86emu *emu) 2153197007Sdelphij{ 2154197007Sdelphij uint32_t destoffset; 2155197007Sdelphij 2156197007Sdelphij fetch_decode_modrm(emu); 2157197007Sdelphij if (emu->cur_mod == 3) 2158197007Sdelphij x86emu_halt_sys(emu); 2159197007Sdelphij 2160197007Sdelphij destoffset = decode_rl_address(emu); 2161268100Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_ADDR) { 2162268100Sdelphij uint32_t *srcreg; 2163268100Sdelphij 2164268100Sdelphij srcreg = decode_rh_long_register(emu); 2165268100Sdelphij *srcreg = (uint32_t) destoffset; 2166268100Sdelphij } else { 2167268100Sdelphij uint16_t *srcreg; 2168268100Sdelphij 2169268100Sdelphij srcreg = decode_rh_word_register(emu); 2170268100Sdelphij *srcreg = (uint16_t) destoffset; 2171268100Sdelphij } 2172197007Sdelphij} 2173197007Sdelphij 2174197007Sdelphij/* 2175197007Sdelphij * REMARKS: 2176197007Sdelphij * Handles opcode 0x8e 2177197007Sdelphij */ 2178197007Sdelphijstatic void 2179197007Sdelphijx86emuOp_mov_word_SR_RM(struct x86emu *emu) 2180197007Sdelphij{ 2181197007Sdelphij uint16_t *destreg; 2182197007Sdelphij 2183197007Sdelphij fetch_decode_modrm(emu); 2184197007Sdelphij destreg = decode_rh_seg_register(emu); 2185197007Sdelphij *destreg = decode_and_fetch_word(emu); 2186197007Sdelphij /* 2187197007Sdelphij * Clean up, and reset all the R_xSP pointers to the correct 2188197007Sdelphij * locations. This is about 3x too much overhead (doing all the 2189197007Sdelphij * segreg ptrs when only one is needed, but this instruction 2190197007Sdelphij * *cannot* be that common, and this isn't too much work anyway. 2191197007Sdelphij */ 2192197007Sdelphij} 2193197007Sdelphij 2194197007Sdelphij/* 2195197007Sdelphij * REMARKS: 2196197007Sdelphij * Handles opcode 0x8f 2197197007Sdelphij */ 2198197007Sdelphijstatic void 2199197007Sdelphijx86emuOp32_pop_RM(struct x86emu *emu) 2200197007Sdelphij{ 2201197007Sdelphij uint32_t destoffset; 2202197007Sdelphij uint32_t destval, *destreg; 2203197007Sdelphij 2204197007Sdelphij fetch_decode_modrm(emu); 2205197007Sdelphij if (emu->cur_mod != 3) { 2206197007Sdelphij destoffset = decode_rl_address(emu); 2207197007Sdelphij destval = pop_long(emu); 2208197007Sdelphij store_data_long(emu, destoffset, destval); 2209197007Sdelphij } else { 2210197007Sdelphij destreg = decode_rl_long_register(emu); 2211197007Sdelphij *destreg = pop_long(emu); 2212197007Sdelphij } 2213197007Sdelphij} 2214197007Sdelphij 2215197007Sdelphijstatic void 2216197007Sdelphijx86emuOp16_pop_RM(struct x86emu *emu) 2217197007Sdelphij{ 2218197007Sdelphij uint32_t destoffset; 2219197007Sdelphij uint16_t destval, *destreg; 2220197007Sdelphij 2221197007Sdelphij fetch_decode_modrm(emu); 2222197007Sdelphij if (emu->cur_mod != 3) { 2223197007Sdelphij destoffset = decode_rl_address(emu); 2224197007Sdelphij destval = pop_word(emu); 2225197007Sdelphij store_data_word(emu, destoffset, destval); 2226197007Sdelphij } else { 2227197007Sdelphij destreg = decode_rl_word_register(emu); 2228197007Sdelphij *destreg = pop_word(emu); 2229197007Sdelphij } 2230197007Sdelphij} 2231197007Sdelphij 2232197007Sdelphijstatic void 2233197007Sdelphijx86emuOp_pop_RM(struct x86emu *emu) 2234197007Sdelphij{ 2235197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2236197007Sdelphij x86emuOp32_pop_RM(emu); 2237197007Sdelphij else 2238197007Sdelphij x86emuOp16_pop_RM(emu); 2239197007Sdelphij} 2240197007Sdelphij 2241197007Sdelphij/* 2242197007Sdelphij * REMARKS: 2243197007Sdelphij * Handles opcode 0x91 2244197007Sdelphij */ 2245197007Sdelphijstatic void 2246197007Sdelphijx86emuOp_xchg_word_AX_CX(struct x86emu *emu) 2247197007Sdelphij{ 2248197007Sdelphij uint32_t tmp; 2249197007Sdelphij 2250197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2251197007Sdelphij tmp = emu->x86.R_EAX; 2252197007Sdelphij emu->x86.R_EAX = emu->x86.R_ECX; 2253197007Sdelphij emu->x86.R_ECX = tmp; 2254197007Sdelphij } else { 2255197007Sdelphij tmp = emu->x86.R_AX; 2256197007Sdelphij emu->x86.R_AX = emu->x86.R_CX; 2257197007Sdelphij emu->x86.R_CX = (uint16_t) tmp; 2258197007Sdelphij } 2259197007Sdelphij} 2260197007Sdelphij 2261197007Sdelphij/* 2262197007Sdelphij * REMARKS: 2263197007Sdelphij * Handles opcode 0x92 2264197007Sdelphij */ 2265197007Sdelphijstatic void 2266197007Sdelphijx86emuOp_xchg_word_AX_DX(struct x86emu *emu) 2267197007Sdelphij{ 2268197007Sdelphij uint32_t tmp; 2269197007Sdelphij 2270197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2271197007Sdelphij tmp = emu->x86.R_EAX; 2272197007Sdelphij emu->x86.R_EAX = emu->x86.R_EDX; 2273197007Sdelphij emu->x86.R_EDX = tmp; 2274197007Sdelphij } else { 2275197007Sdelphij tmp = emu->x86.R_AX; 2276197007Sdelphij emu->x86.R_AX = emu->x86.R_DX; 2277197007Sdelphij emu->x86.R_DX = (uint16_t) tmp; 2278197007Sdelphij } 2279197007Sdelphij} 2280197007Sdelphij 2281197007Sdelphij/* 2282197007Sdelphij * REMARKS: 2283197007Sdelphij * Handles opcode 0x93 2284197007Sdelphij */ 2285197007Sdelphijstatic void 2286197007Sdelphijx86emuOp_xchg_word_AX_BX(struct x86emu *emu) 2287197007Sdelphij{ 2288197007Sdelphij uint32_t tmp; 2289197007Sdelphij 2290197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2291197007Sdelphij tmp = emu->x86.R_EAX; 2292197007Sdelphij emu->x86.R_EAX = emu->x86.R_EBX; 2293197007Sdelphij emu->x86.R_EBX = tmp; 2294197007Sdelphij } else { 2295197007Sdelphij tmp = emu->x86.R_AX; 2296197007Sdelphij emu->x86.R_AX = emu->x86.R_BX; 2297197007Sdelphij emu->x86.R_BX = (uint16_t) tmp; 2298197007Sdelphij } 2299197007Sdelphij} 2300197007Sdelphij 2301197007Sdelphij/* 2302197007Sdelphij * REMARKS: 2303197007Sdelphij * Handles opcode 0x94 2304197007Sdelphij */ 2305197007Sdelphijstatic void 2306197007Sdelphijx86emuOp_xchg_word_AX_SP(struct x86emu *emu) 2307197007Sdelphij{ 2308197007Sdelphij uint32_t tmp; 2309197007Sdelphij 2310197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2311197007Sdelphij tmp = emu->x86.R_EAX; 2312197007Sdelphij emu->x86.R_EAX = emu->x86.R_ESP; 2313197007Sdelphij emu->x86.R_ESP = tmp; 2314197007Sdelphij } else { 2315197007Sdelphij tmp = emu->x86.R_AX; 2316197007Sdelphij emu->x86.R_AX = emu->x86.R_SP; 2317197007Sdelphij emu->x86.R_SP = (uint16_t) tmp; 2318197007Sdelphij } 2319197007Sdelphij} 2320197007Sdelphij 2321197007Sdelphij/* 2322197007Sdelphij * REMARKS: 2323197007Sdelphij * Handles opcode 0x95 2324197007Sdelphij */ 2325197007Sdelphijstatic void 2326197007Sdelphijx86emuOp_xchg_word_AX_BP(struct x86emu *emu) 2327197007Sdelphij{ 2328197007Sdelphij uint32_t tmp; 2329197007Sdelphij 2330197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2331197007Sdelphij tmp = emu->x86.R_EAX; 2332197007Sdelphij emu->x86.R_EAX = emu->x86.R_EBP; 2333197007Sdelphij emu->x86.R_EBP = tmp; 2334197007Sdelphij } else { 2335197007Sdelphij tmp = emu->x86.R_AX; 2336197007Sdelphij emu->x86.R_AX = emu->x86.R_BP; 2337197007Sdelphij emu->x86.R_BP = (uint16_t) tmp; 2338197007Sdelphij } 2339197007Sdelphij} 2340197007Sdelphij 2341197007Sdelphij/* 2342197007Sdelphij * REMARKS: 2343197007Sdelphij * Handles opcode 0x96 2344197007Sdelphij */ 2345197007Sdelphijstatic void 2346197007Sdelphijx86emuOp_xchg_word_AX_SI(struct x86emu *emu) 2347197007Sdelphij{ 2348197007Sdelphij uint32_t tmp; 2349197007Sdelphij 2350197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2351197007Sdelphij tmp = emu->x86.R_EAX; 2352197007Sdelphij emu->x86.R_EAX = emu->x86.R_ESI; 2353197007Sdelphij emu->x86.R_ESI = tmp; 2354197007Sdelphij } else { 2355197007Sdelphij tmp = emu->x86.R_AX; 2356197007Sdelphij emu->x86.R_AX = emu->x86.R_SI; 2357197007Sdelphij emu->x86.R_SI = (uint16_t) tmp; 2358197007Sdelphij } 2359197007Sdelphij} 2360197007Sdelphij 2361197007Sdelphij/* 2362197007Sdelphij * REMARKS: 2363197007Sdelphij * Handles opcode 0x97 2364197007Sdelphij */ 2365197007Sdelphijstatic void 2366197007Sdelphijx86emuOp_xchg_word_AX_DI(struct x86emu *emu) 2367197007Sdelphij{ 2368197007Sdelphij uint32_t tmp; 2369197007Sdelphij 2370197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2371197007Sdelphij tmp = emu->x86.R_EAX; 2372197007Sdelphij emu->x86.R_EAX = emu->x86.R_EDI; 2373197007Sdelphij emu->x86.R_EDI = tmp; 2374197007Sdelphij } else { 2375197007Sdelphij tmp = emu->x86.R_AX; 2376197007Sdelphij emu->x86.R_AX = emu->x86.R_DI; 2377197007Sdelphij emu->x86.R_DI = (uint16_t) tmp; 2378197007Sdelphij } 2379197007Sdelphij} 2380197007Sdelphij 2381197007Sdelphij/* 2382197007Sdelphij * REMARKS: 2383197007Sdelphij * Handles opcode 0x98 2384197007Sdelphij */ 2385197007Sdelphijstatic void 2386197007Sdelphijx86emuOp_cbw(struct x86emu *emu) 2387197007Sdelphij{ 2388197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2389197007Sdelphij if (emu->x86.R_AX & 0x8000) { 2390197007Sdelphij emu->x86.R_EAX |= 0xffff0000; 2391197007Sdelphij } else { 2392197007Sdelphij emu->x86.R_EAX &= 0x0000ffff; 2393197007Sdelphij } 2394197007Sdelphij } else { 2395197007Sdelphij if (emu->x86.R_AL & 0x80) { 2396197007Sdelphij emu->x86.R_AH = 0xff; 2397197007Sdelphij } else { 2398197007Sdelphij emu->x86.R_AH = 0x0; 2399197007Sdelphij } 2400197007Sdelphij } 2401197007Sdelphij} 2402197007Sdelphij 2403197007Sdelphij/* 2404197007Sdelphij * REMARKS: 2405197007Sdelphij * Handles opcode 0x99 2406197007Sdelphij */ 2407197007Sdelphijstatic void 2408197007Sdelphijx86emuOp_cwd(struct x86emu *emu) 2409197007Sdelphij{ 2410197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2411197007Sdelphij if (emu->x86.R_EAX & 0x80000000) { 2412197007Sdelphij emu->x86.R_EDX = 0xffffffff; 2413197007Sdelphij } else { 2414197007Sdelphij emu->x86.R_EDX = 0x0; 2415197007Sdelphij } 2416197007Sdelphij } else { 2417197007Sdelphij if (emu->x86.R_AX & 0x8000) { 2418197007Sdelphij emu->x86.R_DX = 0xffff; 2419197007Sdelphij } else { 2420197007Sdelphij emu->x86.R_DX = 0x0; 2421197007Sdelphij } 2422197007Sdelphij } 2423197007Sdelphij} 2424197007Sdelphij 2425197007Sdelphij/* 2426197007Sdelphij * REMARKS: 2427197007Sdelphij * Handles opcode 0x9a 2428197007Sdelphij */ 2429197007Sdelphijstatic void 2430197007Sdelphijx86emuOp_call_far_IMM(struct x86emu *emu) 2431197007Sdelphij{ 2432197007Sdelphij uint16_t farseg, faroff; 2433197007Sdelphij 2434197007Sdelphij faroff = fetch_word_imm(emu); 2435197007Sdelphij farseg = fetch_word_imm(emu); 2436197007Sdelphij /* XXX 2437197007Sdelphij * 2438197007Sdelphij * Hooked interrupt vectors calling into our "BIOS" will cause problems 2439197007Sdelphij * unless all intersegment stuff is checked for BIOS access. Check 2440197007Sdelphij * needed here. For moment, let it alone. */ 2441197007Sdelphij push_word(emu, emu->x86.R_CS); 2442197007Sdelphij emu->x86.R_CS = farseg; 2443197007Sdelphij push_word(emu, emu->x86.R_IP); 2444197007Sdelphij emu->x86.R_IP = faroff; 2445197007Sdelphij} 2446197007Sdelphij 2447197007Sdelphij/* 2448197007Sdelphij * REMARKS: 2449197007Sdelphij * Handles opcode 0x9c 2450197007Sdelphij */ 2451197007Sdelphijstatic void 2452197007Sdelphijx86emuOp_pushf_word(struct x86emu *emu) 2453197007Sdelphij{ 2454197007Sdelphij uint32_t flags; 2455197007Sdelphij 2456197007Sdelphij /* clear out *all* bits not representing flags, and turn on real bits */ 2457197007Sdelphij flags = (emu->x86.R_EFLG & F_MSK) | F_ALWAYS_ON; 2458197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2459197007Sdelphij push_long(emu, flags); 2460197007Sdelphij } else { 2461197007Sdelphij push_word(emu, (uint16_t) flags); 2462197007Sdelphij } 2463197007Sdelphij} 2464197007Sdelphij 2465197007Sdelphij/* 2466197007Sdelphij * REMARKS: 2467197007Sdelphij * Handles opcode 0x9d 2468197007Sdelphij */ 2469197007Sdelphijstatic void 2470197007Sdelphijx86emuOp_popf_word(struct x86emu *emu) 2471197007Sdelphij{ 2472197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2473197007Sdelphij emu->x86.R_EFLG = pop_long(emu); 2474197007Sdelphij } else { 2475197007Sdelphij emu->x86.R_FLG = pop_word(emu); 2476197007Sdelphij } 2477197007Sdelphij} 2478197007Sdelphij 2479197007Sdelphij/* 2480197007Sdelphij * REMARKS: 2481197007Sdelphij * Handles opcode 0x9e 2482197007Sdelphij */ 2483197007Sdelphijstatic void 2484197007Sdelphijx86emuOp_sahf(struct x86emu *emu) 2485197007Sdelphij{ 2486197007Sdelphij /* clear the lower bits of the flag register */ 2487197007Sdelphij emu->x86.R_FLG &= 0xffffff00; 2488197007Sdelphij /* or in the AH register into the flags register */ 2489197007Sdelphij emu->x86.R_FLG |= emu->x86.R_AH; 2490197007Sdelphij} 2491197007Sdelphij 2492197007Sdelphij/* 2493197007Sdelphij * REMARKS: 2494197007Sdelphij * Handles opcode 0x9f 2495197007Sdelphij */ 2496197007Sdelphijstatic void 2497197007Sdelphijx86emuOp_lahf(struct x86emu *emu) 2498197007Sdelphij{ 2499197007Sdelphij emu->x86.R_AH = (uint8_t) (emu->x86.R_FLG & 0xff); 2500197007Sdelphij /* undocumented TC++ behavior??? Nope. It's documented, but you have 2501197007Sdelphij * too look real hard to notice it. */ 2502197007Sdelphij emu->x86.R_AH |= 0x2; 2503197007Sdelphij} 2504197007Sdelphij 2505197007Sdelphij/* 2506197007Sdelphij * REMARKS: 2507197007Sdelphij * Handles opcode 0xa0 2508197007Sdelphij */ 2509197007Sdelphijstatic void 2510197007Sdelphijx86emuOp_mov_AL_M_IMM(struct x86emu *emu) 2511197007Sdelphij{ 2512197007Sdelphij uint16_t offset; 2513197007Sdelphij 2514197007Sdelphij offset = fetch_word_imm(emu); 2515197007Sdelphij emu->x86.R_AL = fetch_data_byte(emu, offset); 2516197007Sdelphij} 2517197007Sdelphij 2518197007Sdelphij/* 2519197007Sdelphij * REMARKS: 2520197007Sdelphij * Handles opcode 0xa1 2521197007Sdelphij */ 2522197007Sdelphijstatic void 2523197007Sdelphijx86emuOp_mov_AX_M_IMM(struct x86emu *emu) 2524197007Sdelphij{ 2525197007Sdelphij uint16_t offset; 2526197007Sdelphij 2527197007Sdelphij offset = fetch_word_imm(emu); 2528197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2529197007Sdelphij emu->x86.R_EAX = fetch_data_long(emu, offset); 2530197007Sdelphij } else { 2531197007Sdelphij emu->x86.R_AX = fetch_data_word(emu, offset); 2532197007Sdelphij } 2533197007Sdelphij} 2534197007Sdelphij 2535197007Sdelphij/* 2536197007Sdelphij * REMARKS: 2537197007Sdelphij * Handles opcode 0xa2 2538197007Sdelphij */ 2539197007Sdelphijstatic void 2540197007Sdelphijx86emuOp_mov_M_AL_IMM(struct x86emu *emu) 2541197007Sdelphij{ 2542197007Sdelphij uint16_t offset; 2543197007Sdelphij 2544197007Sdelphij offset = fetch_word_imm(emu); 2545197007Sdelphij store_data_byte(emu, offset, emu->x86.R_AL); 2546197007Sdelphij} 2547197007Sdelphij 2548197007Sdelphij/* 2549197007Sdelphij * REMARKS: 2550197007Sdelphij * Handles opcode 0xa3 2551197007Sdelphij */ 2552197007Sdelphijstatic void 2553197007Sdelphijx86emuOp_mov_M_AX_IMM(struct x86emu *emu) 2554197007Sdelphij{ 2555197007Sdelphij uint16_t offset; 2556197007Sdelphij 2557197007Sdelphij offset = fetch_word_imm(emu); 2558197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2559197007Sdelphij store_data_long(emu, offset, emu->x86.R_EAX); 2560197007Sdelphij } else { 2561197007Sdelphij store_data_word(emu, offset, emu->x86.R_AX); 2562197007Sdelphij } 2563197007Sdelphij} 2564197007Sdelphij 2565197007Sdelphij/* 2566197007Sdelphij * REMARKS: 2567197007Sdelphij * Handles opcode 0xa4 2568197007Sdelphij */ 2569197007Sdelphijstatic void 2570197007Sdelphijx86emuOp_movs_byte(struct x86emu *emu) 2571197007Sdelphij{ 2572197007Sdelphij uint8_t val; 2573197007Sdelphij uint32_t count; 2574197007Sdelphij int inc; 2575197007Sdelphij 2576197007Sdelphij if (ACCESS_FLAG(F_DF)) /* down */ 2577197007Sdelphij inc = -1; 2578197007Sdelphij else 2579197007Sdelphij inc = 1; 2580197007Sdelphij count = 1; 2581197007Sdelphij if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2582197007Sdelphij /* dont care whether REPE or REPNE */ 2583197007Sdelphij /* move them until CX is ZERO. */ 2584197007Sdelphij count = emu->x86.R_CX; 2585197007Sdelphij emu->x86.R_CX = 0; 2586197007Sdelphij emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2587197007Sdelphij } 2588197007Sdelphij while (count--) { 2589197007Sdelphij val = fetch_data_byte(emu, emu->x86.R_SI); 2590197007Sdelphij store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, val); 2591197007Sdelphij emu->x86.R_SI += inc; 2592197007Sdelphij emu->x86.R_DI += inc; 2593197007Sdelphij } 2594197007Sdelphij} 2595197007Sdelphij 2596197007Sdelphij/* 2597197007Sdelphij * REMARKS: 2598197007Sdelphij * Handles opcode 0xa5 2599197007Sdelphij */ 2600197007Sdelphijstatic void 2601197007Sdelphijx86emuOp_movs_word(struct x86emu *emu) 2602197007Sdelphij{ 2603197007Sdelphij uint32_t val; 2604197007Sdelphij int inc; 2605197007Sdelphij uint32_t count; 2606197007Sdelphij 2607197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2608197007Sdelphij inc = 4; 2609197007Sdelphij else 2610197007Sdelphij inc = 2; 2611197007Sdelphij 2612197007Sdelphij if (ACCESS_FLAG(F_DF)) /* down */ 2613197007Sdelphij inc = -inc; 2614197007Sdelphij 2615197007Sdelphij count = 1; 2616197007Sdelphij if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2617197007Sdelphij /* dont care whether REPE or REPNE */ 2618197007Sdelphij /* move them until CX is ZERO. */ 2619197007Sdelphij count = emu->x86.R_CX; 2620197007Sdelphij emu->x86.R_CX = 0; 2621197007Sdelphij emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2622197007Sdelphij } 2623197007Sdelphij while (count--) { 2624197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2625197007Sdelphij val = fetch_data_long(emu, emu->x86.R_SI); 2626197007Sdelphij store_long(emu, emu->x86.R_ES, emu->x86.R_DI, val); 2627197007Sdelphij } else { 2628197007Sdelphij val = fetch_data_word(emu, emu->x86.R_SI); 2629204934Sdelphij store_word(emu, emu->x86.R_ES, emu->x86.R_DI, 2630204934Sdelphij (uint16_t) val); 2631197007Sdelphij } 2632197007Sdelphij emu->x86.R_SI += inc; 2633197007Sdelphij emu->x86.R_DI += inc; 2634197007Sdelphij } 2635197007Sdelphij} 2636197007Sdelphij 2637197007Sdelphij/* 2638197007Sdelphij * REMARKS: 2639197007Sdelphij * Handles opcode 0xa6 2640197007Sdelphij */ 2641197007Sdelphijstatic void 2642197007Sdelphijx86emuOp_cmps_byte(struct x86emu *emu) 2643197007Sdelphij{ 2644197007Sdelphij int8_t val1, val2; 2645197007Sdelphij int inc; 2646197007Sdelphij 2647197007Sdelphij if (ACCESS_FLAG(F_DF)) /* down */ 2648197007Sdelphij inc = -1; 2649197007Sdelphij else 2650197007Sdelphij inc = 1; 2651197007Sdelphij 2652197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_REPE) { 2653197007Sdelphij /* REPE */ 2654197007Sdelphij /* move them until CX is ZERO. */ 2655197007Sdelphij while (emu->x86.R_CX != 0) { 2656197007Sdelphij val1 = fetch_data_byte(emu, emu->x86.R_SI); 2657197007Sdelphij val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2658197007Sdelphij cmp_byte(emu, val1, val2); 2659197007Sdelphij emu->x86.R_CX -= 1; 2660197007Sdelphij emu->x86.R_SI += inc; 2661197007Sdelphij emu->x86.R_DI += inc; 2662197007Sdelphij if (ACCESS_FLAG(F_ZF) == 0) 2663197007Sdelphij break; 2664197007Sdelphij } 2665197007Sdelphij emu->x86.mode &= ~SYSMODE_PREFIX_REPE; 2666197007Sdelphij } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) { 2667197007Sdelphij /* REPNE */ 2668197007Sdelphij /* move them until CX is ZERO. */ 2669197007Sdelphij while (emu->x86.R_CX != 0) { 2670197007Sdelphij val1 = fetch_data_byte(emu, emu->x86.R_SI); 2671197007Sdelphij val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2672197007Sdelphij cmp_byte(emu, val1, val2); 2673197007Sdelphij emu->x86.R_CX -= 1; 2674197007Sdelphij emu->x86.R_SI += inc; 2675197007Sdelphij emu->x86.R_DI += inc; 2676197007Sdelphij if (ACCESS_FLAG(F_ZF)) 2677197007Sdelphij break; /* zero flag set means equal */ 2678197007Sdelphij } 2679197007Sdelphij emu->x86.mode &= ~SYSMODE_PREFIX_REPNE; 2680197007Sdelphij } else { 2681197007Sdelphij val1 = fetch_data_byte(emu, emu->x86.R_SI); 2682197007Sdelphij val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2683197007Sdelphij cmp_byte(emu, val1, val2); 2684197007Sdelphij emu->x86.R_SI += inc; 2685197007Sdelphij emu->x86.R_DI += inc; 2686197007Sdelphij } 2687197007Sdelphij} 2688197007Sdelphij 2689197007Sdelphij/* 2690197007Sdelphij * REMARKS: 2691197007Sdelphij * Handles opcode 0xa7 2692197007Sdelphij */ 2693197007Sdelphijstatic void 2694197007Sdelphijx86emuOp_cmps_word(struct x86emu *emu) 2695197007Sdelphij{ 2696197007Sdelphij uint32_t val1, val2; 2697197007Sdelphij int inc; 2698197007Sdelphij 2699197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2700197007Sdelphij if (ACCESS_FLAG(F_DF)) /* down */ 2701197007Sdelphij inc = -4; 2702197007Sdelphij else 2703197007Sdelphij inc = 4; 2704197007Sdelphij } else { 2705197007Sdelphij if (ACCESS_FLAG(F_DF)) /* down */ 2706197007Sdelphij inc = -2; 2707197007Sdelphij else 2708197007Sdelphij inc = 2; 2709197007Sdelphij } 2710197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_REPE) { 2711197007Sdelphij /* REPE */ 2712197007Sdelphij /* move them until CX is ZERO. */ 2713197007Sdelphij while (emu->x86.R_CX != 0) { 2714197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2715197007Sdelphij val1 = fetch_data_long(emu, emu->x86.R_SI); 2716204934Sdelphij val2 = fetch_long(emu, emu->x86.R_ES, 2717204934Sdelphij emu->x86.R_DI); 2718197007Sdelphij cmp_long(emu, val1, val2); 2719197007Sdelphij } else { 2720197007Sdelphij val1 = fetch_data_word(emu, emu->x86.R_SI); 2721204934Sdelphij val2 = fetch_word(emu, emu->x86.R_ES, 2722204934Sdelphij emu->x86.R_DI); 2723197007Sdelphij cmp_word(emu, (uint16_t) val1, (uint16_t) val2); 2724197007Sdelphij } 2725197007Sdelphij emu->x86.R_CX -= 1; 2726197007Sdelphij emu->x86.R_SI += inc; 2727197007Sdelphij emu->x86.R_DI += inc; 2728197007Sdelphij if (ACCESS_FLAG(F_ZF) == 0) 2729197007Sdelphij break; 2730197007Sdelphij } 2731197007Sdelphij emu->x86.mode &= ~SYSMODE_PREFIX_REPE; 2732197007Sdelphij } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) { 2733197007Sdelphij /* REPNE */ 2734197007Sdelphij /* move them until CX is ZERO. */ 2735197007Sdelphij while (emu->x86.R_CX != 0) { 2736197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2737197007Sdelphij val1 = fetch_data_long(emu, emu->x86.R_SI); 2738204934Sdelphij val2 = fetch_long(emu, emu->x86.R_ES, 2739204934Sdelphij emu->x86.R_DI); 2740197007Sdelphij cmp_long(emu, val1, val2); 2741197007Sdelphij } else { 2742197007Sdelphij val1 = fetch_data_word(emu, emu->x86.R_SI); 2743204934Sdelphij val2 = fetch_word(emu, emu->x86.R_ES, 2744204934Sdelphij emu->x86.R_DI); 2745197007Sdelphij cmp_word(emu, (uint16_t) val1, (uint16_t) val2); 2746197007Sdelphij } 2747197007Sdelphij emu->x86.R_CX -= 1; 2748197007Sdelphij emu->x86.R_SI += inc; 2749197007Sdelphij emu->x86.R_DI += inc; 2750197007Sdelphij if (ACCESS_FLAG(F_ZF)) 2751197007Sdelphij break; /* zero flag set means equal */ 2752197007Sdelphij } 2753197007Sdelphij emu->x86.mode &= ~SYSMODE_PREFIX_REPNE; 2754197007Sdelphij } else { 2755197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2756197007Sdelphij val1 = fetch_data_long(emu, emu->x86.R_SI); 2757197007Sdelphij val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2758197007Sdelphij cmp_long(emu, val1, val2); 2759197007Sdelphij } else { 2760197007Sdelphij val1 = fetch_data_word(emu, emu->x86.R_SI); 2761197007Sdelphij val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2762197007Sdelphij cmp_word(emu, (uint16_t) val1, (uint16_t) val2); 2763197007Sdelphij } 2764197007Sdelphij emu->x86.R_SI += inc; 2765197007Sdelphij emu->x86.R_DI += inc; 2766197007Sdelphij } 2767197007Sdelphij} 2768197007Sdelphij 2769197007Sdelphij/* 2770197007Sdelphij * REMARKS: 2771197007Sdelphij * Handles opcode 0xa9 2772197007Sdelphij */ 2773197007Sdelphijstatic void 2774197007Sdelphijx86emuOp_test_AX_IMM(struct x86emu *emu) 2775197007Sdelphij{ 2776197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2777197007Sdelphij test_long(emu, emu->x86.R_EAX, fetch_long_imm(emu)); 2778197007Sdelphij } else { 2779197007Sdelphij test_word(emu, emu->x86.R_AX, fetch_word_imm(emu)); 2780197007Sdelphij } 2781197007Sdelphij} 2782197007Sdelphij 2783197007Sdelphij/* 2784197007Sdelphij * REMARKS: 2785197007Sdelphij * Handles opcode 0xaa 2786197007Sdelphij */ 2787197007Sdelphijstatic void 2788197007Sdelphijx86emuOp_stos_byte(struct x86emu *emu) 2789197007Sdelphij{ 2790197007Sdelphij int inc; 2791197007Sdelphij 2792197007Sdelphij if (ACCESS_FLAG(F_DF)) /* down */ 2793197007Sdelphij inc = -1; 2794197007Sdelphij else 2795197007Sdelphij inc = 1; 2796197007Sdelphij if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2797197007Sdelphij /* dont care whether REPE or REPNE */ 2798197007Sdelphij /* move them until CX is ZERO. */ 2799197007Sdelphij while (emu->x86.R_CX != 0) { 2800204934Sdelphij store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, 2801204934Sdelphij emu->x86.R_AL); 2802197007Sdelphij emu->x86.R_CX -= 1; 2803197007Sdelphij emu->x86.R_DI += inc; 2804197007Sdelphij } 2805197007Sdelphij emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2806197007Sdelphij } else { 2807197007Sdelphij store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL); 2808197007Sdelphij emu->x86.R_DI += inc; 2809197007Sdelphij } 2810197007Sdelphij} 2811197007Sdelphij 2812197007Sdelphij/* 2813197007Sdelphij * REMARKS: 2814197007Sdelphij * Handles opcode 0xab 2815197007Sdelphij */ 2816197007Sdelphijstatic void 2817197007Sdelphijx86emuOp_stos_word(struct x86emu *emu) 2818197007Sdelphij{ 2819197007Sdelphij int inc; 2820197007Sdelphij uint32_t count; 2821197007Sdelphij 2822197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2823197007Sdelphij inc = 4; 2824197007Sdelphij else 2825197007Sdelphij inc = 2; 2826197007Sdelphij 2827197007Sdelphij if (ACCESS_FLAG(F_DF)) /* down */ 2828197007Sdelphij inc = -inc; 2829197007Sdelphij 2830197007Sdelphij count = 1; 2831197007Sdelphij if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2832197007Sdelphij /* dont care whether REPE or REPNE */ 2833197007Sdelphij /* move them until CX is ZERO. */ 2834197007Sdelphij count = emu->x86.R_CX; 2835197007Sdelphij emu->x86.R_CX = 0; 2836197007Sdelphij emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2837197007Sdelphij } 2838197007Sdelphij while (count--) { 2839197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2840204934Sdelphij store_long(emu, emu->x86.R_ES, emu->x86.R_DI, 2841204934Sdelphij emu->x86.R_EAX); 2842197007Sdelphij } else { 2843204934Sdelphij store_word(emu, emu->x86.R_ES, emu->x86.R_DI, 2844204934Sdelphij emu->x86.R_AX); 2845197007Sdelphij } 2846197007Sdelphij emu->x86.R_DI += inc; 2847197007Sdelphij } 2848197007Sdelphij} 2849197007Sdelphij 2850197007Sdelphij/* 2851197007Sdelphij * REMARKS: 2852197007Sdelphij * Handles opcode 0xac 2853197007Sdelphij */ 2854197007Sdelphijstatic void 2855197007Sdelphijx86emuOp_lods_byte(struct x86emu *emu) 2856197007Sdelphij{ 2857197007Sdelphij int inc; 2858197007Sdelphij 2859197007Sdelphij if (ACCESS_FLAG(F_DF)) /* down */ 2860197007Sdelphij inc = -1; 2861197007Sdelphij else 2862197007Sdelphij inc = 1; 2863197007Sdelphij if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2864197007Sdelphij /* dont care whether REPE or REPNE */ 2865197007Sdelphij /* move them until CX is ZERO. */ 2866197007Sdelphij while (emu->x86.R_CX != 0) { 2867197007Sdelphij emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI); 2868197007Sdelphij emu->x86.R_CX -= 1; 2869197007Sdelphij emu->x86.R_SI += inc; 2870197007Sdelphij } 2871197007Sdelphij emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2872197007Sdelphij } else { 2873197007Sdelphij emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI); 2874197007Sdelphij emu->x86.R_SI += inc; 2875197007Sdelphij } 2876197007Sdelphij} 2877197007Sdelphij 2878197007Sdelphij/* 2879197007Sdelphij * REMARKS: 2880197007Sdelphij * Handles opcode 0xad 2881197007Sdelphij */ 2882197007Sdelphijstatic void 2883197007Sdelphijx86emuOp_lods_word(struct x86emu *emu) 2884197007Sdelphij{ 2885197007Sdelphij int inc; 2886197007Sdelphij uint32_t count; 2887197007Sdelphij 2888197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2889197007Sdelphij inc = 4; 2890197007Sdelphij else 2891197007Sdelphij inc = 2; 2892197007Sdelphij 2893197007Sdelphij if (ACCESS_FLAG(F_DF)) /* down */ 2894197007Sdelphij inc = -inc; 2895197007Sdelphij 2896197007Sdelphij count = 1; 2897197007Sdelphij if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2898197007Sdelphij /* dont care whether REPE or REPNE */ 2899197007Sdelphij /* move them until CX is ZERO. */ 2900197007Sdelphij count = emu->x86.R_CX; 2901197007Sdelphij emu->x86.R_CX = 0; 2902197007Sdelphij emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2903197007Sdelphij } 2904197007Sdelphij while (count--) { 2905197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2906197007Sdelphij emu->x86.R_EAX = fetch_data_long(emu, emu->x86.R_SI); 2907197007Sdelphij } else { 2908197007Sdelphij emu->x86.R_AX = fetch_data_word(emu, emu->x86.R_SI); 2909197007Sdelphij } 2910197007Sdelphij emu->x86.R_SI += inc; 2911197007Sdelphij } 2912197007Sdelphij} 2913197007Sdelphij 2914197007Sdelphij/* 2915197007Sdelphij * REMARKS: 2916197007Sdelphij * Handles opcode 0xae 2917197007Sdelphij */ 2918197007Sdelphijstatic void 2919197007Sdelphijx86emuOp_scas_byte(struct x86emu *emu) 2920197007Sdelphij{ 2921197007Sdelphij int8_t val2; 2922197007Sdelphij int inc; 2923197007Sdelphij 2924197007Sdelphij if (ACCESS_FLAG(F_DF)) /* down */ 2925197007Sdelphij inc = -1; 2926197007Sdelphij else 2927197007Sdelphij inc = 1; 2928197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_REPE) { 2929197007Sdelphij /* REPE */ 2930197007Sdelphij /* move them until CX is ZERO. */ 2931197007Sdelphij while (emu->x86.R_CX != 0) { 2932197007Sdelphij val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2933197007Sdelphij cmp_byte(emu, emu->x86.R_AL, val2); 2934197007Sdelphij emu->x86.R_CX -= 1; 2935197007Sdelphij emu->x86.R_DI += inc; 2936197007Sdelphij if (ACCESS_FLAG(F_ZF) == 0) 2937197007Sdelphij break; 2938197007Sdelphij } 2939197007Sdelphij emu->x86.mode &= ~SYSMODE_PREFIX_REPE; 2940197007Sdelphij } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) { 2941197007Sdelphij /* REPNE */ 2942197007Sdelphij /* move them until CX is ZERO. */ 2943197007Sdelphij while (emu->x86.R_CX != 0) { 2944197007Sdelphij val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2945197007Sdelphij cmp_byte(emu, emu->x86.R_AL, val2); 2946197007Sdelphij emu->x86.R_CX -= 1; 2947197007Sdelphij emu->x86.R_DI += inc; 2948197007Sdelphij if (ACCESS_FLAG(F_ZF)) 2949197007Sdelphij break; /* zero flag set means equal */ 2950197007Sdelphij } 2951197007Sdelphij emu->x86.mode &= ~SYSMODE_PREFIX_REPNE; 2952197007Sdelphij } else { 2953197007Sdelphij val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2954197007Sdelphij cmp_byte(emu, emu->x86.R_AL, val2); 2955197007Sdelphij emu->x86.R_DI += inc; 2956197007Sdelphij } 2957197007Sdelphij} 2958197007Sdelphij 2959197007Sdelphij/* 2960197007Sdelphij * REMARKS: 2961197007Sdelphij * Handles opcode 0xaf 2962197007Sdelphij */ 2963197007Sdelphijstatic void 2964197007Sdelphijx86emuOp_scas_word(struct x86emu *emu) 2965197007Sdelphij{ 2966197007Sdelphij int inc; 2967197007Sdelphij uint32_t val; 2968197007Sdelphij 2969197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2970197007Sdelphij inc = 4; 2971197007Sdelphij else 2972197007Sdelphij inc = 2; 2973197007Sdelphij 2974197007Sdelphij if (ACCESS_FLAG(F_DF)) /* down */ 2975197007Sdelphij inc = -inc; 2976197007Sdelphij 2977197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_REPE) { 2978197007Sdelphij /* REPE */ 2979197007Sdelphij /* move them until CX is ZERO. */ 2980197007Sdelphij while (emu->x86.R_CX != 0) { 2981197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2982204934Sdelphij val = fetch_long(emu, emu->x86.R_ES, 2983204934Sdelphij emu->x86.R_DI); 2984197007Sdelphij cmp_long(emu, emu->x86.R_EAX, val); 2985197007Sdelphij } else { 2986204934Sdelphij val = fetch_word(emu, emu->x86.R_ES, 2987204934Sdelphij emu->x86.R_DI); 2988197007Sdelphij cmp_word(emu, emu->x86.R_AX, (uint16_t) val); 2989197007Sdelphij } 2990197007Sdelphij emu->x86.R_CX -= 1; 2991197007Sdelphij emu->x86.R_DI += inc; 2992197007Sdelphij if (ACCESS_FLAG(F_ZF) == 0) 2993197007Sdelphij break; 2994197007Sdelphij } 2995197007Sdelphij emu->x86.mode &= ~SYSMODE_PREFIX_REPE; 2996197007Sdelphij } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) { 2997197007Sdelphij /* REPNE */ 2998197007Sdelphij /* move them until CX is ZERO. */ 2999197007Sdelphij while (emu->x86.R_CX != 0) { 3000197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3001204934Sdelphij val = fetch_long(emu, emu->x86.R_ES, 3002204934Sdelphij emu->x86.R_DI); 3003197007Sdelphij cmp_long(emu, emu->x86.R_EAX, val); 3004197007Sdelphij } else { 3005204934Sdelphij val = fetch_word(emu, emu->x86.R_ES, 3006204934Sdelphij emu->x86.R_DI); 3007197007Sdelphij cmp_word(emu, emu->x86.R_AX, (uint16_t) val); 3008197007Sdelphij } 3009197007Sdelphij emu->x86.R_CX -= 1; 3010197007Sdelphij emu->x86.R_DI += inc; 3011197007Sdelphij if (ACCESS_FLAG(F_ZF)) 3012197007Sdelphij break; /* zero flag set means equal */ 3013197007Sdelphij } 3014197007Sdelphij emu->x86.mode &= ~SYSMODE_PREFIX_REPNE; 3015197007Sdelphij } else { 3016197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3017197007Sdelphij val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 3018197007Sdelphij cmp_long(emu, emu->x86.R_EAX, val); 3019197007Sdelphij } else { 3020197007Sdelphij val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 3021197007Sdelphij cmp_word(emu, emu->x86.R_AX, (uint16_t) val); 3022197007Sdelphij } 3023197007Sdelphij emu->x86.R_DI += inc; 3024197007Sdelphij } 3025197007Sdelphij} 3026197007Sdelphij 3027197007Sdelphij/* 3028197007Sdelphij * REMARKS: 3029197007Sdelphij * Handles opcode 0xb8 3030197007Sdelphij */ 3031197007Sdelphijstatic void 3032197007Sdelphijx86emuOp_mov_word_AX_IMM(struct x86emu *emu) 3033197007Sdelphij{ 3034197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3035197007Sdelphij emu->x86.R_EAX = fetch_long_imm(emu); 3036197007Sdelphij else 3037197007Sdelphij emu->x86.R_AX = fetch_word_imm(emu); 3038197007Sdelphij} 3039197007Sdelphij 3040197007Sdelphij/* 3041197007Sdelphij * REMARKS: 3042197007Sdelphij * Handles opcode 0xb9 3043197007Sdelphij */ 3044197007Sdelphijstatic void 3045197007Sdelphijx86emuOp_mov_word_CX_IMM(struct x86emu *emu) 3046197007Sdelphij{ 3047197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3048197007Sdelphij emu->x86.R_ECX = fetch_long_imm(emu); 3049197007Sdelphij else 3050197007Sdelphij emu->x86.R_CX = fetch_word_imm(emu); 3051197007Sdelphij} 3052197007Sdelphij 3053197007Sdelphij/* 3054197007Sdelphij * REMARKS: 3055197007Sdelphij * Handles opcode 0xba 3056197007Sdelphij */ 3057197007Sdelphijstatic void 3058197007Sdelphijx86emuOp_mov_word_DX_IMM(struct x86emu *emu) 3059197007Sdelphij{ 3060197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3061197007Sdelphij emu->x86.R_EDX = fetch_long_imm(emu); 3062197007Sdelphij else 3063197007Sdelphij emu->x86.R_DX = fetch_word_imm(emu); 3064197007Sdelphij} 3065197007Sdelphij 3066197007Sdelphij/* 3067197007Sdelphij * REMARKS: 3068197007Sdelphij * Handles opcode 0xbb 3069197007Sdelphij */ 3070197007Sdelphijstatic void 3071197007Sdelphijx86emuOp_mov_word_BX_IMM(struct x86emu *emu) 3072197007Sdelphij{ 3073197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3074197007Sdelphij emu->x86.R_EBX = fetch_long_imm(emu); 3075197007Sdelphij else 3076197007Sdelphij emu->x86.R_BX = fetch_word_imm(emu); 3077197007Sdelphij} 3078197007Sdelphij 3079197007Sdelphij/* 3080197007Sdelphij * REMARKS: 3081197007Sdelphij * Handles opcode 0xbc 3082197007Sdelphij */ 3083197007Sdelphijstatic void 3084197007Sdelphijx86emuOp_mov_word_SP_IMM(struct x86emu *emu) 3085197007Sdelphij{ 3086197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3087197007Sdelphij emu->x86.R_ESP = fetch_long_imm(emu); 3088197007Sdelphij else 3089197007Sdelphij emu->x86.R_SP = fetch_word_imm(emu); 3090197007Sdelphij} 3091197007Sdelphij 3092197007Sdelphij/* 3093197007Sdelphij * REMARKS: 3094197007Sdelphij * Handles opcode 0xbd 3095197007Sdelphij */ 3096197007Sdelphijstatic void 3097197007Sdelphijx86emuOp_mov_word_BP_IMM(struct x86emu *emu) 3098197007Sdelphij{ 3099197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3100197007Sdelphij emu->x86.R_EBP = fetch_long_imm(emu); 3101197007Sdelphij else 3102197007Sdelphij emu->x86.R_BP = fetch_word_imm(emu); 3103197007Sdelphij} 3104197007Sdelphij 3105197007Sdelphij/* 3106197007Sdelphij * REMARKS: 3107197007Sdelphij * Handles opcode 0xbe 3108197007Sdelphij */ 3109197007Sdelphijstatic void 3110197007Sdelphijx86emuOp_mov_word_SI_IMM(struct x86emu *emu) 3111197007Sdelphij{ 3112197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3113197007Sdelphij emu->x86.R_ESI = fetch_long_imm(emu); 3114197007Sdelphij else 3115197007Sdelphij emu->x86.R_SI = fetch_word_imm(emu); 3116197007Sdelphij} 3117197007Sdelphij 3118197007Sdelphij/* 3119197007Sdelphij * REMARKS: 3120197007Sdelphij * Handles opcode 0xbf 3121197007Sdelphij */ 3122197007Sdelphijstatic void 3123197007Sdelphijx86emuOp_mov_word_DI_IMM(struct x86emu *emu) 3124197007Sdelphij{ 3125197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3126197007Sdelphij emu->x86.R_EDI = fetch_long_imm(emu); 3127197007Sdelphij else 3128197007Sdelphij emu->x86.R_DI = fetch_word_imm(emu); 3129197007Sdelphij} 3130197007Sdelphij/* used by opcodes c0, d0, and d2. */ 3131197007Sdelphijstatic 3132204934Sdelphijuint8_t(* const opcD0_byte_operation[]) 3133204934Sdelphij (struct x86emu *, uint8_t d, uint8_t s) = 3134197007Sdelphij{ 3135197007Sdelphij rol_byte, 3136197007Sdelphij ror_byte, 3137197007Sdelphij rcl_byte, 3138197007Sdelphij rcr_byte, 3139197007Sdelphij shl_byte, 3140197007Sdelphij shr_byte, 3141197007Sdelphij shl_byte, /* sal_byte === shl_byte by definition */ 3142197007Sdelphij sar_byte, 3143197007Sdelphij}; 3144197007Sdelphij 3145197007Sdelphij/* 3146197007Sdelphij * REMARKS: 3147197007Sdelphij * Handles opcode 0xc0 3148197007Sdelphij */ 3149197007Sdelphijstatic void 3150197007Sdelphijx86emuOp_opcC0_byte_RM_MEM(struct x86emu *emu) 3151197007Sdelphij{ 3152197007Sdelphij uint8_t destval, amt; 3153197007Sdelphij 3154197007Sdelphij /* 3155197007Sdelphij * Yet another weirdo special case instruction format. Part of 3156197007Sdelphij * the opcode held below in "RH". Doubly nested case would 3157197007Sdelphij * result, except that the decoded instruction 3158197007Sdelphij */ 3159197007Sdelphij fetch_decode_modrm(emu); 3160197007Sdelphij /* know operation, decode the mod byte to find the addressing mode. */ 3161197007Sdelphij destval = decode_and_fetch_byte_imm8(emu, &amt); 3162197007Sdelphij destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, amt); 3163197007Sdelphij write_back_byte(emu, destval); 3164197007Sdelphij} 3165197007Sdelphij/* used by opcodes c1, d1, and d3. */ 3166197007Sdelphijstatic 3167204934Sdelphijuint16_t(* const opcD1_word_operation[]) 3168204934Sdelphij (struct x86emu *, uint16_t s, uint8_t d) = 3169197007Sdelphij{ 3170197007Sdelphij rol_word, 3171197007Sdelphij ror_word, 3172197007Sdelphij rcl_word, 3173197007Sdelphij rcr_word, 3174197007Sdelphij shl_word, 3175197007Sdelphij shr_word, 3176197007Sdelphij shl_word, /* sal_byte === shl_byte by definition */ 3177197007Sdelphij sar_word, 3178197007Sdelphij}; 3179197007Sdelphij/* used by opcodes c1, d1, and d3. */ 3180197007Sdelphijstatic 3181204934Sdelphijuint32_t(* const opcD1_long_operation[]) 3182204934Sdelphij (struct x86emu *, uint32_t s, uint8_t d) = 3183197007Sdelphij{ 3184197007Sdelphij rol_long, 3185197007Sdelphij ror_long, 3186197007Sdelphij rcl_long, 3187197007Sdelphij rcr_long, 3188197007Sdelphij shl_long, 3189197007Sdelphij shr_long, 3190197007Sdelphij shl_long, /* sal_byte === shl_byte by definition */ 3191197007Sdelphij sar_long, 3192197007Sdelphij}; 3193197007Sdelphij 3194197007Sdelphij/* 3195197007Sdelphij * REMARKS: 3196197007Sdelphij * Handles opcode 0xc1 3197197007Sdelphij */ 3198197007Sdelphijstatic void 3199197007Sdelphijx86emuOp_opcC1_word_RM_MEM(struct x86emu *emu) 3200197007Sdelphij{ 3201197007Sdelphij uint8_t amt; 3202197007Sdelphij 3203197007Sdelphij /* 3204197007Sdelphij * Yet another weirdo special case instruction format. Part of 3205197007Sdelphij * the opcode held below in "RH". Doubly nested case would 3206197007Sdelphij * result, except that the decoded instruction 3207197007Sdelphij */ 3208197007Sdelphij fetch_decode_modrm(emu); 3209197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3210197007Sdelphij uint32_t destval; 3211197007Sdelphij 3212197007Sdelphij destval = decode_and_fetch_long_imm8(emu, &amt); 3213204934Sdelphij destval = (*opcD1_long_operation[emu->cur_rh]) 3214204934Sdelphij (emu, destval, amt); 3215197007Sdelphij write_back_long(emu, destval); 3216197007Sdelphij } else { 3217197007Sdelphij uint16_t destval; 3218197007Sdelphij 3219197007Sdelphij destval = decode_and_fetch_word_imm8(emu, &amt); 3220204934Sdelphij destval = (*opcD1_word_operation[emu->cur_rh]) 3221204934Sdelphij (emu, destval, amt); 3222197007Sdelphij write_back_word(emu, destval); 3223197007Sdelphij } 3224197007Sdelphij} 3225197007Sdelphij 3226197007Sdelphij/* 3227197007Sdelphij * REMARKS: 3228197007Sdelphij * Handles opcode 0xc2 3229197007Sdelphij */ 3230197007Sdelphijstatic void 3231197007Sdelphijx86emuOp_ret_near_IMM(struct x86emu *emu) 3232197007Sdelphij{ 3233197007Sdelphij uint16_t imm; 3234197007Sdelphij 3235197007Sdelphij imm = fetch_word_imm(emu); 3236197007Sdelphij emu->x86.R_IP = pop_word(emu); 3237197007Sdelphij emu->x86.R_SP += imm; 3238197007Sdelphij} 3239197007Sdelphij 3240197007Sdelphij/* 3241197007Sdelphij * REMARKS: 3242197007Sdelphij * Handles opcode 0xc6 3243197007Sdelphij */ 3244197007Sdelphijstatic void 3245197007Sdelphijx86emuOp_mov_byte_RM_IMM(struct x86emu *emu) 3246197007Sdelphij{ 3247197007Sdelphij uint8_t *destreg; 3248197007Sdelphij uint32_t destoffset; 3249197007Sdelphij uint8_t imm; 3250197007Sdelphij 3251197007Sdelphij fetch_decode_modrm(emu); 3252197007Sdelphij if (emu->cur_rh != 0) 3253197007Sdelphij x86emu_halt_sys(emu); 3254197007Sdelphij if (emu->cur_mod != 3) { 3255197007Sdelphij destoffset = decode_rl_address(emu); 3256197007Sdelphij imm = fetch_byte_imm(emu); 3257197007Sdelphij store_data_byte(emu, destoffset, imm); 3258197007Sdelphij } else { 3259197007Sdelphij destreg = decode_rl_byte_register(emu); 3260197007Sdelphij imm = fetch_byte_imm(emu); 3261197007Sdelphij *destreg = imm; 3262197007Sdelphij } 3263197007Sdelphij} 3264197007Sdelphij 3265197007Sdelphij/* 3266197007Sdelphij * REMARKS: 3267197007Sdelphij * Handles opcode 0xc7 3268197007Sdelphij */ 3269197007Sdelphijstatic void 3270197007Sdelphijx86emuOp32_mov_word_RM_IMM(struct x86emu *emu) 3271197007Sdelphij{ 3272197007Sdelphij uint32_t destoffset; 3273197007Sdelphij uint32_t imm, *destreg; 3274197007Sdelphij 3275197007Sdelphij fetch_decode_modrm(emu); 3276197007Sdelphij if (emu->cur_rh != 0) 3277197007Sdelphij x86emu_halt_sys(emu); 3278197007Sdelphij 3279197007Sdelphij if (emu->cur_mod != 3) { 3280197007Sdelphij destoffset = decode_rl_address(emu); 3281197007Sdelphij imm = fetch_long_imm(emu); 3282197007Sdelphij store_data_long(emu, destoffset, imm); 3283197007Sdelphij } else { 3284197007Sdelphij destreg = decode_rl_long_register(emu); 3285197007Sdelphij imm = fetch_long_imm(emu); 3286197007Sdelphij *destreg = imm; 3287197007Sdelphij } 3288197007Sdelphij} 3289197007Sdelphij 3290197007Sdelphijstatic void 3291197007Sdelphijx86emuOp16_mov_word_RM_IMM(struct x86emu *emu) 3292197007Sdelphij{ 3293197007Sdelphij uint32_t destoffset; 3294197007Sdelphij uint16_t imm, *destreg; 3295197007Sdelphij 3296197007Sdelphij fetch_decode_modrm(emu); 3297197007Sdelphij if (emu->cur_rh != 0) 3298197007Sdelphij x86emu_halt_sys(emu); 3299197007Sdelphij 3300197007Sdelphij if (emu->cur_mod != 3) { 3301197007Sdelphij destoffset = decode_rl_address(emu); 3302197007Sdelphij imm = fetch_word_imm(emu); 3303197007Sdelphij store_data_word(emu, destoffset, imm); 3304197007Sdelphij } else { 3305197007Sdelphij destreg = decode_rl_word_register(emu); 3306197007Sdelphij imm = fetch_word_imm(emu); 3307197007Sdelphij *destreg = imm; 3308197007Sdelphij } 3309197007Sdelphij} 3310197007Sdelphij 3311197007Sdelphijstatic void 3312197007Sdelphijx86emuOp_mov_word_RM_IMM(struct x86emu *emu) 3313197007Sdelphij{ 3314197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3315197007Sdelphij x86emuOp32_mov_word_RM_IMM(emu); 3316197007Sdelphij else 3317197007Sdelphij x86emuOp16_mov_word_RM_IMM(emu); 3318197007Sdelphij} 3319197007Sdelphij 3320197007Sdelphij/* 3321197007Sdelphij * REMARKS: 3322197007Sdelphij * Handles opcode 0xc8 3323197007Sdelphij */ 3324197007Sdelphijstatic void 3325197007Sdelphijx86emuOp_enter(struct x86emu *emu) 3326197007Sdelphij{ 3327197007Sdelphij uint16_t local, frame_pointer; 3328197007Sdelphij uint8_t nesting; 3329197007Sdelphij int i; 3330197007Sdelphij 3331197007Sdelphij local = fetch_word_imm(emu); 3332197007Sdelphij nesting = fetch_byte_imm(emu); 3333197007Sdelphij push_word(emu, emu->x86.R_BP); 3334197007Sdelphij frame_pointer = emu->x86.R_SP; 3335197007Sdelphij if (nesting > 0) { 3336197007Sdelphij for (i = 1; i < nesting; i++) { 3337197007Sdelphij emu->x86.R_BP -= 2; 3338204934Sdelphij push_word(emu, fetch_word(emu, emu->x86.R_SS, 3339204934Sdelphij emu->x86.R_BP)); 3340197007Sdelphij } 3341197007Sdelphij push_word(emu, frame_pointer); 3342197007Sdelphij } 3343197007Sdelphij emu->x86.R_BP = frame_pointer; 3344197007Sdelphij emu->x86.R_SP = (uint16_t) (emu->x86.R_SP - local); 3345197007Sdelphij} 3346197007Sdelphij 3347197007Sdelphij/* 3348197007Sdelphij * REMARKS: 3349197007Sdelphij * Handles opcode 0xc9 3350197007Sdelphij */ 3351197007Sdelphijstatic void 3352197007Sdelphijx86emuOp_leave(struct x86emu *emu) 3353197007Sdelphij{ 3354197007Sdelphij emu->x86.R_SP = emu->x86.R_BP; 3355197007Sdelphij emu->x86.R_BP = pop_word(emu); 3356197007Sdelphij} 3357197007Sdelphij 3358197007Sdelphij/* 3359197007Sdelphij * REMARKS: 3360197007Sdelphij * Handles opcode 0xca 3361197007Sdelphij */ 3362197007Sdelphijstatic void 3363197007Sdelphijx86emuOp_ret_far_IMM(struct x86emu *emu) 3364197007Sdelphij{ 3365197007Sdelphij uint16_t imm; 3366197007Sdelphij 3367197007Sdelphij imm = fetch_word_imm(emu); 3368197007Sdelphij emu->x86.R_IP = pop_word(emu); 3369197007Sdelphij emu->x86.R_CS = pop_word(emu); 3370197007Sdelphij emu->x86.R_SP += imm; 3371197007Sdelphij} 3372197007Sdelphij 3373197007Sdelphij/* 3374197007Sdelphij * REMARKS: 3375197007Sdelphij * Handles opcode 0xcb 3376197007Sdelphij */ 3377197007Sdelphijstatic void 3378197007Sdelphijx86emuOp_ret_far(struct x86emu *emu) 3379197007Sdelphij{ 3380197007Sdelphij emu->x86.R_IP = pop_word(emu); 3381197007Sdelphij emu->x86.R_CS = pop_word(emu); 3382197007Sdelphij} 3383197007Sdelphij 3384197007Sdelphij/* 3385197007Sdelphij * REMARKS: 3386197007Sdelphij * Handles opcode 0xcc 3387197007Sdelphij */ 3388197007Sdelphijstatic void 3389197007Sdelphijx86emuOp_int3(struct x86emu *emu) 3390197007Sdelphij{ 3391197007Sdelphij x86emu_intr_dispatch(emu, 3); 3392197007Sdelphij} 3393197007Sdelphij 3394197007Sdelphij/* 3395197007Sdelphij * REMARKS: 3396197007Sdelphij * Handles opcode 0xcd 3397197007Sdelphij */ 3398197007Sdelphijstatic void 3399197007Sdelphijx86emuOp_int_IMM(struct x86emu *emu) 3400197007Sdelphij{ 3401197007Sdelphij uint8_t intnum; 3402197007Sdelphij 3403197007Sdelphij intnum = fetch_byte_imm(emu); 3404197007Sdelphij x86emu_intr_dispatch(emu, intnum); 3405197007Sdelphij} 3406197007Sdelphij 3407197007Sdelphij/* 3408197007Sdelphij * REMARKS: 3409197007Sdelphij * Handles opcode 0xce 3410197007Sdelphij */ 3411197007Sdelphijstatic void 3412197007Sdelphijx86emuOp_into(struct x86emu *emu) 3413197007Sdelphij{ 3414197007Sdelphij if (ACCESS_FLAG(F_OF)) 3415197007Sdelphij x86emu_intr_dispatch(emu, 4); 3416197007Sdelphij} 3417197007Sdelphij 3418197007Sdelphij/* 3419197007Sdelphij * REMARKS: 3420197007Sdelphij * Handles opcode 0xcf 3421197007Sdelphij */ 3422197007Sdelphijstatic void 3423197007Sdelphijx86emuOp_iret(struct x86emu *emu) 3424197007Sdelphij{ 3425197007Sdelphij emu->x86.R_IP = pop_word(emu); 3426197007Sdelphij emu->x86.R_CS = pop_word(emu); 3427197007Sdelphij emu->x86.R_FLG = pop_word(emu); 3428197007Sdelphij} 3429197007Sdelphij 3430197007Sdelphij/* 3431197007Sdelphij * REMARKS: 3432197007Sdelphij * Handles opcode 0xd0 3433197007Sdelphij */ 3434197007Sdelphijstatic void 3435197007Sdelphijx86emuOp_opcD0_byte_RM_1(struct x86emu *emu) 3436197007Sdelphij{ 3437197007Sdelphij uint8_t destval; 3438197007Sdelphij 3439197007Sdelphij fetch_decode_modrm(emu); 3440197007Sdelphij destval = decode_and_fetch_byte(emu); 3441197007Sdelphij destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, 1); 3442197007Sdelphij write_back_byte(emu, destval); 3443197007Sdelphij} 3444197007Sdelphij 3445197007Sdelphij/* 3446197007Sdelphij * REMARKS: 3447197007Sdelphij * Handles opcode 0xd1 3448197007Sdelphij */ 3449197007Sdelphijstatic void 3450197007Sdelphijx86emuOp_opcD1_word_RM_1(struct x86emu *emu) 3451197007Sdelphij{ 3452197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3453197007Sdelphij uint32_t destval; 3454197007Sdelphij 3455197007Sdelphij fetch_decode_modrm(emu); 3456197007Sdelphij destval = decode_and_fetch_long(emu); 3457204934Sdelphij destval = (*opcD1_long_operation[emu->cur_rh])(emu, destval, 1); 3458197007Sdelphij write_back_long(emu, destval); 3459197007Sdelphij } else { 3460197007Sdelphij uint16_t destval; 3461197007Sdelphij 3462197007Sdelphij fetch_decode_modrm(emu); 3463197007Sdelphij destval = decode_and_fetch_word(emu); 3464204934Sdelphij destval = (*opcD1_word_operation[emu->cur_rh])(emu, destval, 1); 3465197007Sdelphij write_back_word(emu, destval); 3466197007Sdelphij } 3467197007Sdelphij} 3468197007Sdelphij 3469197007Sdelphij/* 3470197007Sdelphij * REMARKS: 3471197007Sdelphij * Handles opcode 0xd2 3472197007Sdelphij */ 3473197007Sdelphijstatic void 3474197007Sdelphijx86emuOp_opcD2_byte_RM_CL(struct x86emu *emu) 3475197007Sdelphij{ 3476197007Sdelphij uint8_t destval; 3477197007Sdelphij 3478197007Sdelphij fetch_decode_modrm(emu); 3479197007Sdelphij destval = decode_and_fetch_byte(emu); 3480204934Sdelphij destval = (*opcD0_byte_operation[emu->cur_rh]) 3481204934Sdelphij (emu, destval, emu->x86.R_CL); 3482197007Sdelphij write_back_byte(emu, destval); 3483197007Sdelphij} 3484197007Sdelphij 3485197007Sdelphij/* 3486197007Sdelphij * REMARKS: 3487197007Sdelphij * Handles opcode 0xd3 3488197007Sdelphij */ 3489197007Sdelphijstatic void 3490197007Sdelphijx86emuOp_opcD3_word_RM_CL(struct x86emu *emu) 3491197007Sdelphij{ 3492197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3493197007Sdelphij uint32_t destval; 3494197007Sdelphij 3495197007Sdelphij fetch_decode_modrm(emu); 3496197007Sdelphij destval = decode_and_fetch_long(emu); 3497204934Sdelphij destval = (*opcD1_long_operation[emu->cur_rh]) 3498204934Sdelphij (emu, destval, emu->x86.R_CL); 3499197007Sdelphij write_back_long(emu, destval); 3500197007Sdelphij } else { 3501197007Sdelphij uint16_t destval; 3502197007Sdelphij 3503197007Sdelphij fetch_decode_modrm(emu); 3504197007Sdelphij destval = decode_and_fetch_word(emu); 3505204934Sdelphij destval = (*opcD1_word_operation[emu->cur_rh]) 3506204934Sdelphij (emu, destval, emu->x86.R_CL); 3507197007Sdelphij write_back_word(emu, destval); 3508197007Sdelphij } 3509197007Sdelphij} 3510197007Sdelphij 3511197007Sdelphij/* 3512197007Sdelphij * REMARKS: 3513197007Sdelphij * Handles opcode 0xd4 3514197007Sdelphij */ 3515197007Sdelphijstatic void 3516197007Sdelphijx86emuOp_aam(struct x86emu *emu) 3517197007Sdelphij{ 3518197007Sdelphij uint8_t a; 3519197007Sdelphij 3520197007Sdelphij a = fetch_byte_imm(emu); /* this is a stupid encoding. */ 3521197007Sdelphij if (a != 10) { 3522197007Sdelphij /* fix: add base decoding aam_word(uint8_t val, int base a) */ 3523197007Sdelphij x86emu_halt_sys(emu); 3524197007Sdelphij } 3525197007Sdelphij /* note the type change here --- returning AL and AH in AX. */ 3526197007Sdelphij emu->x86.R_AX = aam_word(emu, emu->x86.R_AL); 3527197007Sdelphij} 3528197007Sdelphij 3529197007Sdelphij/* 3530197007Sdelphij * REMARKS: 3531197007Sdelphij * Handles opcode 0xd5 3532197007Sdelphij */ 3533197007Sdelphijstatic void 3534197007Sdelphijx86emuOp_aad(struct x86emu *emu) 3535197007Sdelphij{ 3536197007Sdelphij uint8_t a; 3537197007Sdelphij 3538197007Sdelphij a = fetch_byte_imm(emu); 3539197007Sdelphij if (a != 10) { 3540197007Sdelphij /* fix: add base decoding aad_word(uint16_t val, int base a) */ 3541197007Sdelphij x86emu_halt_sys(emu); 3542197007Sdelphij } 3543197007Sdelphij emu->x86.R_AX = aad_word(emu, emu->x86.R_AX); 3544197007Sdelphij} 3545197007Sdelphij/* opcode 0xd6 ILLEGAL OPCODE */ 3546197007Sdelphij 3547197007Sdelphij 3548197007Sdelphij/* 3549197007Sdelphij * REMARKS: 3550197007Sdelphij * Handles opcode 0xd7 3551197007Sdelphij */ 3552197007Sdelphijstatic void 3553197007Sdelphijx86emuOp_xlat(struct x86emu *emu) 3554197007Sdelphij{ 3555197007Sdelphij uint16_t addr; 3556197007Sdelphij 3557197007Sdelphij addr = (uint16_t) (emu->x86.R_BX + (uint8_t) emu->x86.R_AL); 3558197007Sdelphij emu->x86.R_AL = fetch_data_byte(emu, addr); 3559197007Sdelphij} 3560197007Sdelphij 3561197007Sdelphij/* opcode=0xd8 */ 3562197007Sdelphijstatic void 3563197007Sdelphijx86emuOp_esc_coprocess_d8(struct x86emu *emu) 3564197007Sdelphij{ 3565197007Sdelphij} 3566197007Sdelphij/* opcode=0xd9 */ 3567197007Sdelphijstatic void 3568197007Sdelphijx86emuOp_esc_coprocess_d9(struct x86emu *emu) 3569197007Sdelphij{ 3570197007Sdelphij fetch_decode_modrm(emu); 3571197007Sdelphij if (emu->cur_mod != 3) 3572197007Sdelphij decode_rl_address(emu); 3573197007Sdelphij} 3574197007Sdelphij/* opcode=0xda */ 3575197007Sdelphijstatic void 3576197007Sdelphijx86emuOp_esc_coprocess_da(struct x86emu *emu) 3577197007Sdelphij{ 3578197007Sdelphij fetch_decode_modrm(emu); 3579197007Sdelphij if (emu->cur_mod != 3) 3580197007Sdelphij decode_rl_address(emu); 3581197007Sdelphij} 3582197007Sdelphij/* opcode=0xdb */ 3583197007Sdelphijstatic void 3584197007Sdelphijx86emuOp_esc_coprocess_db(struct x86emu *emu) 3585197007Sdelphij{ 3586197007Sdelphij fetch_decode_modrm(emu); 3587197007Sdelphij if (emu->cur_mod != 3) 3588197007Sdelphij decode_rl_address(emu); 3589197007Sdelphij} 3590197007Sdelphij/* opcode=0xdc */ 3591197007Sdelphijstatic void 3592197007Sdelphijx86emuOp_esc_coprocess_dc(struct x86emu *emu) 3593197007Sdelphij{ 3594197007Sdelphij fetch_decode_modrm(emu); 3595197007Sdelphij if (emu->cur_mod != 3) 3596197007Sdelphij decode_rl_address(emu); 3597197007Sdelphij} 3598197007Sdelphij/* opcode=0xdd */ 3599197007Sdelphijstatic void 3600197007Sdelphijx86emuOp_esc_coprocess_dd(struct x86emu *emu) 3601197007Sdelphij{ 3602197007Sdelphij fetch_decode_modrm(emu); 3603197007Sdelphij if (emu->cur_mod != 3) 3604197007Sdelphij decode_rl_address(emu); 3605197007Sdelphij} 3606197007Sdelphij/* opcode=0xde */ 3607197007Sdelphijstatic void 3608197007Sdelphijx86emuOp_esc_coprocess_de(struct x86emu *emu) 3609197007Sdelphij{ 3610197007Sdelphij fetch_decode_modrm(emu); 3611197007Sdelphij if (emu->cur_mod != 3) 3612197007Sdelphij decode_rl_address(emu); 3613197007Sdelphij} 3614197007Sdelphij/* opcode=0xdf */ 3615197007Sdelphijstatic void 3616197007Sdelphijx86emuOp_esc_coprocess_df(struct x86emu *emu) 3617197007Sdelphij{ 3618197007Sdelphij fetch_decode_modrm(emu); 3619197007Sdelphij if (emu->cur_mod != 3) 3620197007Sdelphij decode_rl_address(emu); 3621197007Sdelphij} 3622197007Sdelphij 3623197007Sdelphij 3624197007Sdelphij/* 3625197007Sdelphij * REMARKS: 3626197007Sdelphij * Handles opcode 0xe0 3627197007Sdelphij */ 3628197007Sdelphijstatic void 3629197007Sdelphijx86emuOp_loopne(struct x86emu *emu) 3630197007Sdelphij{ 3631197007Sdelphij int16_t ip; 3632197007Sdelphij 3633197007Sdelphij ip = (int8_t) fetch_byte_imm(emu); 3634197007Sdelphij ip += (int16_t) emu->x86.R_IP; 3635197007Sdelphij emu->x86.R_CX -= 1; 3636197007Sdelphij if (emu->x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */ 3637197007Sdelphij emu->x86.R_IP = ip; 3638197007Sdelphij} 3639197007Sdelphij 3640197007Sdelphij/* 3641197007Sdelphij * REMARKS: 3642197007Sdelphij * Handles opcode 0xe1 3643197007Sdelphij */ 3644197007Sdelphijstatic void 3645197007Sdelphijx86emuOp_loope(struct x86emu *emu) 3646197007Sdelphij{ 3647197007Sdelphij int16_t ip; 3648197007Sdelphij 3649197007Sdelphij ip = (int8_t) fetch_byte_imm(emu); 3650197007Sdelphij ip += (int16_t) emu->x86.R_IP; 3651197007Sdelphij emu->x86.R_CX -= 1; 3652197007Sdelphij if (emu->x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */ 3653197007Sdelphij emu->x86.R_IP = ip; 3654197007Sdelphij} 3655197007Sdelphij 3656197007Sdelphij/* 3657197007Sdelphij * REMARKS: 3658197007Sdelphij * Handles opcode 0xe2 3659197007Sdelphij */ 3660197007Sdelphijstatic void 3661197007Sdelphijx86emuOp_loop(struct x86emu *emu) 3662197007Sdelphij{ 3663197007Sdelphij int16_t ip; 3664197007Sdelphij 3665197007Sdelphij ip = (int8_t) fetch_byte_imm(emu); 3666197007Sdelphij ip += (int16_t) emu->x86.R_IP; 3667197007Sdelphij emu->x86.R_CX -= 1; 3668197007Sdelphij if (emu->x86.R_CX != 0) 3669197007Sdelphij emu->x86.R_IP = ip; 3670197007Sdelphij} 3671197007Sdelphij 3672197007Sdelphij/* 3673197007Sdelphij * REMARKS: 3674197007Sdelphij * Handles opcode 0xe3 3675197007Sdelphij */ 3676197007Sdelphijstatic void 3677197007Sdelphijx86emuOp_jcxz(struct x86emu *emu) 3678197007Sdelphij{ 3679197007Sdelphij uint16_t target; 3680197007Sdelphij int8_t offset; 3681197007Sdelphij 3682197007Sdelphij /* jump to byte offset if overflow flag is set */ 3683197007Sdelphij offset = (int8_t) fetch_byte_imm(emu); 3684197007Sdelphij target = (uint16_t) (emu->x86.R_IP + offset); 3685197007Sdelphij if (emu->x86.R_CX == 0) 3686197007Sdelphij emu->x86.R_IP = target; 3687197007Sdelphij} 3688197007Sdelphij 3689197007Sdelphij/* 3690197007Sdelphij * REMARKS: 3691197007Sdelphij * Handles opcode 0xe4 3692197007Sdelphij */ 3693197007Sdelphijstatic void 3694197007Sdelphijx86emuOp_in_byte_AL_IMM(struct x86emu *emu) 3695197007Sdelphij{ 3696197007Sdelphij uint8_t port; 3697197007Sdelphij 3698197007Sdelphij port = (uint8_t) fetch_byte_imm(emu); 3699197007Sdelphij emu->x86.R_AL = (*emu->emu_inb) (emu, port); 3700197007Sdelphij} 3701197007Sdelphij 3702197007Sdelphij/* 3703197007Sdelphij * REMARKS: 3704197007Sdelphij * Handles opcode 0xe5 3705197007Sdelphij */ 3706197007Sdelphijstatic void 3707197007Sdelphijx86emuOp_in_word_AX_IMM(struct x86emu *emu) 3708197007Sdelphij{ 3709197007Sdelphij uint8_t port; 3710197007Sdelphij 3711197007Sdelphij port = (uint8_t) fetch_byte_imm(emu); 3712197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3713197007Sdelphij emu->x86.R_EAX = (*emu->emu_inl) (emu, port); 3714197007Sdelphij } else { 3715197007Sdelphij emu->x86.R_AX = (*emu->emu_inw) (emu, port); 3716197007Sdelphij } 3717197007Sdelphij} 3718197007Sdelphij 3719197007Sdelphij/* 3720197007Sdelphij * REMARKS: 3721197007Sdelphij * Handles opcode 0xe6 3722197007Sdelphij */ 3723197007Sdelphijstatic void 3724197007Sdelphijx86emuOp_out_byte_IMM_AL(struct x86emu *emu) 3725197007Sdelphij{ 3726197007Sdelphij uint8_t port; 3727197007Sdelphij 3728197007Sdelphij port = (uint8_t) fetch_byte_imm(emu); 3729197007Sdelphij (*emu->emu_outb) (emu, port, emu->x86.R_AL); 3730197007Sdelphij} 3731197007Sdelphij 3732197007Sdelphij/* 3733197007Sdelphij * REMARKS: 3734197007Sdelphij * Handles opcode 0xe7 3735197007Sdelphij */ 3736197007Sdelphijstatic void 3737197007Sdelphijx86emuOp_out_word_IMM_AX(struct x86emu *emu) 3738197007Sdelphij{ 3739197007Sdelphij uint8_t port; 3740197007Sdelphij 3741197007Sdelphij port = (uint8_t) fetch_byte_imm(emu); 3742197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3743197007Sdelphij (*emu->emu_outl) (emu, port, emu->x86.R_EAX); 3744197007Sdelphij } else { 3745197007Sdelphij (*emu->emu_outw) (emu, port, emu->x86.R_AX); 3746197007Sdelphij } 3747197007Sdelphij} 3748197007Sdelphij 3749197007Sdelphij/* 3750197007Sdelphij * REMARKS: 3751197007Sdelphij * Handles opcode 0xe8 3752197007Sdelphij */ 3753197007Sdelphijstatic void 3754197007Sdelphijx86emuOp_call_near_IMM(struct x86emu *emu) 3755197007Sdelphij{ 3756268100Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3757268100Sdelphij int32_t ip; 3758268100Sdelphij ip = (int32_t) fetch_long_imm(emu); 3759268100Sdelphij ip += (int32_t) emu->x86.R_EIP; 3760268100Sdelphij push_long(emu, emu->x86.R_EIP); 3761268100Sdelphij emu->x86.R_EIP = ip; 3762268100Sdelphij } else { 3763268100Sdelphij int16_t ip; 3764268100Sdelphij ip = (int16_t) fetch_word_imm(emu); 3765268100Sdelphij ip += (int16_t) emu->x86.R_IP; /* CHECK SIGN */ 3766268100Sdelphij push_word(emu, emu->x86.R_IP); 3767268100Sdelphij emu->x86.R_IP = ip; 3768268100Sdelphij } 3769197007Sdelphij} 3770197007Sdelphij 3771197007Sdelphij/* 3772197007Sdelphij * REMARKS: 3773197007Sdelphij * Handles opcode 0xe9 3774197007Sdelphij */ 3775197007Sdelphijstatic void 3776197007Sdelphijx86emuOp_jump_near_IMM(struct x86emu *emu) 3777197007Sdelphij{ 3778197007Sdelphij int ip; 3779197007Sdelphij 3780197007Sdelphij ip = (int16_t) fetch_word_imm(emu); 3781197007Sdelphij ip += (int16_t) emu->x86.R_IP; 3782197007Sdelphij emu->x86.R_IP = (uint16_t) ip; 3783197007Sdelphij} 3784197007Sdelphij 3785197007Sdelphij/* 3786197007Sdelphij * REMARKS: 3787197007Sdelphij * Handles opcode 0xea 3788197007Sdelphij */ 3789197007Sdelphijstatic void 3790197007Sdelphijx86emuOp_jump_far_IMM(struct x86emu *emu) 3791197007Sdelphij{ 3792197007Sdelphij uint16_t cs, ip; 3793197007Sdelphij 3794197007Sdelphij ip = fetch_word_imm(emu); 3795197007Sdelphij cs = fetch_word_imm(emu); 3796197007Sdelphij emu->x86.R_IP = ip; 3797197007Sdelphij emu->x86.R_CS = cs; 3798197007Sdelphij} 3799197007Sdelphij 3800197007Sdelphij/* 3801197007Sdelphij * REMARKS: 3802197007Sdelphij * Handles opcode 0xeb 3803197007Sdelphij */ 3804197007Sdelphijstatic void 3805197007Sdelphijx86emuOp_jump_byte_IMM(struct x86emu *emu) 3806197007Sdelphij{ 3807197007Sdelphij uint16_t target; 3808197007Sdelphij int8_t offset; 3809197007Sdelphij 3810197007Sdelphij offset = (int8_t) fetch_byte_imm(emu); 3811197007Sdelphij target = (uint16_t) (emu->x86.R_IP + offset); 3812197007Sdelphij emu->x86.R_IP = target; 3813197007Sdelphij} 3814197007Sdelphij 3815197007Sdelphij/* 3816197007Sdelphij * REMARKS: 3817197007Sdelphij * Handles opcode 0xec 3818197007Sdelphij */ 3819197007Sdelphijstatic void 3820197007Sdelphijx86emuOp_in_byte_AL_DX(struct x86emu *emu) 3821197007Sdelphij{ 3822197007Sdelphij emu->x86.R_AL = (*emu->emu_inb) (emu, emu->x86.R_DX); 3823197007Sdelphij} 3824197007Sdelphij 3825197007Sdelphij/* 3826197007Sdelphij * REMARKS: 3827197007Sdelphij * Handles opcode 0xed 3828197007Sdelphij */ 3829197007Sdelphijstatic void 3830197007Sdelphijx86emuOp_in_word_AX_DX(struct x86emu *emu) 3831197007Sdelphij{ 3832197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3833197007Sdelphij emu->x86.R_EAX = (*emu->emu_inl) (emu, emu->x86.R_DX); 3834197007Sdelphij } else { 3835197007Sdelphij emu->x86.R_AX = (*emu->emu_inw) (emu, emu->x86.R_DX); 3836197007Sdelphij } 3837197007Sdelphij} 3838197007Sdelphij 3839197007Sdelphij/* 3840197007Sdelphij * REMARKS: 3841197007Sdelphij * Handles opcode 0xee 3842197007Sdelphij */ 3843197007Sdelphijstatic void 3844197007Sdelphijx86emuOp_out_byte_DX_AL(struct x86emu *emu) 3845197007Sdelphij{ 3846197007Sdelphij (*emu->emu_outb) (emu, emu->x86.R_DX, emu->x86.R_AL); 3847197007Sdelphij} 3848197007Sdelphij 3849197007Sdelphij/* 3850197007Sdelphij * REMARKS: 3851197007Sdelphij * Handles opcode 0xef 3852197007Sdelphij */ 3853197007Sdelphijstatic void 3854197007Sdelphijx86emuOp_out_word_DX_AX(struct x86emu *emu) 3855197007Sdelphij{ 3856197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3857197007Sdelphij (*emu->emu_outl) (emu, emu->x86.R_DX, emu->x86.R_EAX); 3858197007Sdelphij } else { 3859197007Sdelphij (*emu->emu_outw) (emu, emu->x86.R_DX, emu->x86.R_AX); 3860197007Sdelphij } 3861197007Sdelphij} 3862197007Sdelphij 3863197007Sdelphij/* 3864197007Sdelphij * REMARKS: 3865197007Sdelphij * Handles opcode 0xf0 3866197007Sdelphij */ 3867197007Sdelphijstatic void 3868197007Sdelphijx86emuOp_lock(struct x86emu *emu) 3869197007Sdelphij{ 3870197007Sdelphij} 3871197007Sdelphij/*opcode 0xf1 ILLEGAL OPERATION */ 3872197007Sdelphij 3873197007Sdelphij 3874197007Sdelphij/* 3875197007Sdelphij * REMARKS: 3876197007Sdelphij * Handles opcode 0xf5 3877197007Sdelphij */ 3878197007Sdelphijstatic void 3879197007Sdelphijx86emuOp_cmc(struct x86emu *emu) 3880197007Sdelphij{ 3881197007Sdelphij if (ACCESS_FLAG(F_CF)) 3882197007Sdelphij CLEAR_FLAG(F_CF); 3883197007Sdelphij else 3884197007Sdelphij SET_FLAG(F_CF); 3885197007Sdelphij} 3886197007Sdelphij 3887197007Sdelphij/* 3888197007Sdelphij * REMARKS: 3889197007Sdelphij * Handles opcode 0xf6 3890197007Sdelphij */ 3891197007Sdelphijstatic void 3892197007Sdelphijx86emuOp_opcF6_byte_RM(struct x86emu *emu) 3893197007Sdelphij{ 3894197007Sdelphij uint8_t destval, srcval; 3895197007Sdelphij 3896197007Sdelphij /* long, drawn out code follows. Double switch for a total of 32 3897197007Sdelphij * cases. */ 3898197007Sdelphij fetch_decode_modrm(emu); 3899197007Sdelphij if (emu->cur_rh == 1) 3900197007Sdelphij x86emu_halt_sys(emu); 3901197007Sdelphij 3902197007Sdelphij if (emu->cur_rh == 0) { 3903197007Sdelphij destval = decode_and_fetch_byte_imm8(emu, &srcval); 3904197007Sdelphij test_byte(emu, destval, srcval); 3905197007Sdelphij return; 3906197007Sdelphij } 3907197007Sdelphij destval = decode_and_fetch_byte(emu); 3908197007Sdelphij switch (emu->cur_rh) { 3909197007Sdelphij case 2: 3910197007Sdelphij destval = ~destval; 3911197007Sdelphij write_back_byte(emu, destval); 3912197007Sdelphij break; 3913197007Sdelphij case 3: 3914197007Sdelphij destval = neg_byte(emu, destval); 3915197007Sdelphij write_back_byte(emu, destval); 3916197007Sdelphij break; 3917197007Sdelphij case 4: 3918197007Sdelphij mul_byte(emu, destval); 3919197007Sdelphij break; 3920197007Sdelphij case 5: 3921197007Sdelphij imul_byte(emu, destval); 3922197007Sdelphij break; 3923197007Sdelphij case 6: 3924197007Sdelphij div_byte(emu, destval); 3925197007Sdelphij break; 3926197007Sdelphij case 7: 3927197007Sdelphij idiv_byte(emu, destval); 3928197007Sdelphij break; 3929197007Sdelphij } 3930197007Sdelphij} 3931197007Sdelphij 3932197007Sdelphij/* 3933197007Sdelphij * REMARKS: 3934197007Sdelphij * Handles opcode 0xf7 3935197007Sdelphij */ 3936197007Sdelphijstatic void 3937197007Sdelphijx86emuOp32_opcF7_word_RM(struct x86emu *emu) 3938197007Sdelphij{ 3939197007Sdelphij uint32_t destval, srcval; 3940197007Sdelphij 3941197007Sdelphij /* long, drawn out code follows. Double switch for a total of 32 3942197007Sdelphij * cases. */ 3943197007Sdelphij fetch_decode_modrm(emu); 3944197007Sdelphij if (emu->cur_rh == 1) 3945197007Sdelphij x86emu_halt_sys(emu); 3946197007Sdelphij 3947197007Sdelphij if (emu->cur_rh == 0) { 3948197007Sdelphij if (emu->cur_mod != 3) { 3949197007Sdelphij uint32_t destoffset; 3950197007Sdelphij 3951197007Sdelphij destoffset = decode_rl_address(emu); 3952197007Sdelphij srcval = fetch_long_imm(emu); 3953197007Sdelphij destval = fetch_data_long(emu, destoffset); 3954197007Sdelphij } else { 3955197007Sdelphij srcval = fetch_long_imm(emu); 3956197007Sdelphij destval = *decode_rl_long_register(emu); 3957197007Sdelphij } 3958197007Sdelphij test_long(emu, destval, srcval); 3959197007Sdelphij return; 3960197007Sdelphij } 3961197007Sdelphij destval = decode_and_fetch_long(emu); 3962197007Sdelphij switch (emu->cur_rh) { 3963197007Sdelphij case 2: 3964197007Sdelphij destval = ~destval; 3965197007Sdelphij write_back_long(emu, destval); 3966197007Sdelphij break; 3967197007Sdelphij case 3: 3968197007Sdelphij destval = neg_long(emu, destval); 3969197007Sdelphij write_back_long(emu, destval); 3970197007Sdelphij break; 3971197007Sdelphij case 4: 3972197007Sdelphij mul_long(emu, destval); 3973197007Sdelphij break; 3974197007Sdelphij case 5: 3975197007Sdelphij imul_long(emu, destval); 3976197007Sdelphij break; 3977197007Sdelphij case 6: 3978197007Sdelphij div_long(emu, destval); 3979197007Sdelphij break; 3980197007Sdelphij case 7: 3981197007Sdelphij idiv_long(emu, destval); 3982197007Sdelphij break; 3983197007Sdelphij } 3984197007Sdelphij} 3985197007Sdelphijstatic void 3986197007Sdelphijx86emuOp16_opcF7_word_RM(struct x86emu *emu) 3987197007Sdelphij{ 3988197007Sdelphij uint16_t destval, srcval; 3989197007Sdelphij 3990197007Sdelphij /* long, drawn out code follows. Double switch for a total of 32 3991197007Sdelphij * cases. */ 3992197007Sdelphij fetch_decode_modrm(emu); 3993197007Sdelphij if (emu->cur_rh == 1) 3994197007Sdelphij x86emu_halt_sys(emu); 3995197007Sdelphij 3996197007Sdelphij if (emu->cur_rh == 0) { 3997197007Sdelphij if (emu->cur_mod != 3) { 3998197007Sdelphij uint32_t destoffset; 3999197007Sdelphij 4000197007Sdelphij destoffset = decode_rl_address(emu); 4001197007Sdelphij srcval = fetch_word_imm(emu); 4002197007Sdelphij destval = fetch_data_word(emu, destoffset); 4003197007Sdelphij } else { 4004197007Sdelphij srcval = fetch_word_imm(emu); 4005197007Sdelphij destval = *decode_rl_word_register(emu); 4006197007Sdelphij } 4007197007Sdelphij test_word(emu, destval, srcval); 4008197007Sdelphij return; 4009197007Sdelphij } 4010197007Sdelphij destval = decode_and_fetch_word(emu); 4011197007Sdelphij switch (emu->cur_rh) { 4012197007Sdelphij case 2: 4013197007Sdelphij destval = ~destval; 4014197007Sdelphij write_back_word(emu, destval); 4015197007Sdelphij break; 4016197007Sdelphij case 3: 4017197007Sdelphij destval = neg_word(emu, destval); 4018197007Sdelphij write_back_word(emu, destval); 4019197007Sdelphij break; 4020197007Sdelphij case 4: 4021197007Sdelphij mul_word(emu, destval); 4022197007Sdelphij break; 4023197007Sdelphij case 5: 4024197007Sdelphij imul_word(emu, destval); 4025197007Sdelphij break; 4026197007Sdelphij case 6: 4027197007Sdelphij div_word(emu, destval); 4028197007Sdelphij break; 4029197007Sdelphij case 7: 4030197007Sdelphij idiv_word(emu, destval); 4031197007Sdelphij break; 4032197007Sdelphij } 4033197007Sdelphij} 4034197007Sdelphijstatic void 4035197007Sdelphijx86emuOp_opcF7_word_RM(struct x86emu *emu) 4036197007Sdelphij{ 4037197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 4038197007Sdelphij x86emuOp32_opcF7_word_RM(emu); 4039197007Sdelphij else 4040197007Sdelphij x86emuOp16_opcF7_word_RM(emu); 4041197007Sdelphij} 4042197007Sdelphij 4043197007Sdelphij/* 4044197007Sdelphij * REMARKS: 4045197007Sdelphij * Handles opcode 0xfe 4046197007Sdelphij */ 4047197007Sdelphijstatic void 4048197007Sdelphijx86emuOp_opcFE_byte_RM(struct x86emu *emu) 4049197007Sdelphij{ 4050197007Sdelphij uint8_t destval; 4051197007Sdelphij uint32_t destoffset; 4052197007Sdelphij uint8_t *destreg; 4053197007Sdelphij 4054197007Sdelphij /* Yet another special case instruction. */ 4055197007Sdelphij fetch_decode_modrm(emu); 4056197007Sdelphij if (emu->cur_mod != 3) { 4057197007Sdelphij destoffset = decode_rl_address(emu); 4058197007Sdelphij switch (emu->cur_rh) { 4059197007Sdelphij case 0: /* inc word ptr ... */ 4060197007Sdelphij destval = fetch_data_byte(emu, destoffset); 4061197007Sdelphij destval = inc_byte(emu, destval); 4062197007Sdelphij store_data_byte(emu, destoffset, destval); 4063197007Sdelphij break; 4064197007Sdelphij case 1: /* dec word ptr ... */ 4065197007Sdelphij destval = fetch_data_byte(emu, destoffset); 4066197007Sdelphij destval = dec_byte(emu, destval); 4067197007Sdelphij store_data_byte(emu, destoffset, destval); 4068197007Sdelphij break; 4069197007Sdelphij } 4070197007Sdelphij } else { 4071197007Sdelphij destreg = decode_rl_byte_register(emu); 4072197007Sdelphij switch (emu->cur_rh) { 4073197007Sdelphij case 0: 4074197007Sdelphij *destreg = inc_byte(emu, *destreg); 4075197007Sdelphij break; 4076197007Sdelphij case 1: 4077197007Sdelphij *destreg = dec_byte(emu, *destreg); 4078197007Sdelphij break; 4079197007Sdelphij } 4080197007Sdelphij } 4081197007Sdelphij} 4082197007Sdelphij 4083197007Sdelphij/* 4084197007Sdelphij * REMARKS: 4085197007Sdelphij * Handles opcode 0xff 4086197007Sdelphij */ 4087197007Sdelphijstatic void 4088197007Sdelphijx86emuOp32_opcFF_word_RM(struct x86emu *emu) 4089197007Sdelphij{ 4090197007Sdelphij uint32_t destoffset = 0; 4091197007Sdelphij uint32_t destval, *destreg; 4092197007Sdelphij 4093197007Sdelphij if (emu->cur_mod != 3) { 4094197007Sdelphij destoffset = decode_rl_address(emu); 4095197007Sdelphij destval = fetch_data_long(emu, destoffset); 4096197007Sdelphij switch (emu->cur_rh) { 4097197007Sdelphij case 0: /* inc word ptr ... */ 4098197007Sdelphij destval = inc_long(emu, destval); 4099197007Sdelphij store_data_long(emu, destoffset, destval); 4100197007Sdelphij break; 4101197007Sdelphij case 1: /* dec word ptr ... */ 4102197007Sdelphij destval = dec_long(emu, destval); 4103197007Sdelphij store_data_long(emu, destoffset, destval); 4104197007Sdelphij break; 4105197007Sdelphij case 6: /* push word ptr ... */ 4106197007Sdelphij push_long(emu, destval); 4107197007Sdelphij break; 4108197007Sdelphij } 4109197007Sdelphij } else { 4110197007Sdelphij destreg = decode_rl_long_register(emu); 4111197007Sdelphij switch (emu->cur_rh) { 4112197007Sdelphij case 0: 4113197007Sdelphij *destreg = inc_long(emu, *destreg); 4114197007Sdelphij break; 4115197007Sdelphij case 1: 4116197007Sdelphij *destreg = dec_long(emu, *destreg); 4117197007Sdelphij break; 4118197007Sdelphij case 6: 4119197007Sdelphij push_long(emu, *destreg); 4120197007Sdelphij break; 4121197007Sdelphij } 4122197007Sdelphij } 4123197007Sdelphij} 4124197007Sdelphij 4125197007Sdelphijstatic void 4126197007Sdelphijx86emuOp16_opcFF_word_RM(struct x86emu *emu) 4127197007Sdelphij{ 4128197007Sdelphij uint32_t destoffset = 0; 4129197007Sdelphij uint16_t *destreg; 4130197007Sdelphij uint16_t destval; 4131197007Sdelphij 4132197007Sdelphij if (emu->cur_mod != 3) { 4133197007Sdelphij destoffset = decode_rl_address(emu); 4134197007Sdelphij destval = fetch_data_word(emu, destoffset); 4135197007Sdelphij switch (emu->cur_rh) { 4136197007Sdelphij case 0: 4137197007Sdelphij destval = inc_word(emu, destval); 4138197007Sdelphij store_data_word(emu, destoffset, destval); 4139197007Sdelphij break; 4140197007Sdelphij case 1: /* dec word ptr ... */ 4141197007Sdelphij destval = dec_word(emu, destval); 4142197007Sdelphij store_data_word(emu, destoffset, destval); 4143197007Sdelphij break; 4144197007Sdelphij case 6: /* push word ptr ... */ 4145197007Sdelphij push_word(emu, destval); 4146197007Sdelphij break; 4147197007Sdelphij } 4148197007Sdelphij } else { 4149197007Sdelphij destreg = decode_rl_word_register(emu); 4150197007Sdelphij switch (emu->cur_rh) { 4151197007Sdelphij case 0: 4152197007Sdelphij *destreg = inc_word(emu, *destreg); 4153197007Sdelphij break; 4154197007Sdelphij case 1: 4155197007Sdelphij *destreg = dec_word(emu, *destreg); 4156197007Sdelphij break; 4157197007Sdelphij case 6: 4158197007Sdelphij push_word(emu, *destreg); 4159197007Sdelphij break; 4160197007Sdelphij } 4161197007Sdelphij } 4162197007Sdelphij} 4163197007Sdelphij 4164197007Sdelphijstatic void 4165197007Sdelphijx86emuOp_opcFF_word_RM(struct x86emu *emu) 4166197007Sdelphij{ 4167197007Sdelphij uint32_t destoffset = 0; 4168197007Sdelphij uint16_t destval, destval2; 4169197007Sdelphij 4170197007Sdelphij /* Yet another special case instruction. */ 4171197007Sdelphij fetch_decode_modrm(emu); 4172204934Sdelphij if ((emu->cur_mod == 3 && (emu->cur_rh == 3 || emu->cur_rh == 5)) || 4173204934Sdelphij emu->cur_rh == 7) 4174197007Sdelphij x86emu_halt_sys(emu); 4175197007Sdelphij if (emu->cur_rh == 0 || emu->cur_rh == 1 || emu->cur_rh == 6) { 4176197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 4177197007Sdelphij x86emuOp32_opcFF_word_RM(emu); 4178197007Sdelphij else 4179197007Sdelphij x86emuOp16_opcFF_word_RM(emu); 4180197007Sdelphij return; 4181197007Sdelphij } 4182197007Sdelphij 4183197007Sdelphij if (emu->cur_mod != 3) { 4184197007Sdelphij destoffset = decode_rl_address(emu); 4185197007Sdelphij destval = fetch_data_word(emu, destoffset); 4186197007Sdelphij switch (emu->cur_rh) { 4187197007Sdelphij case 3: /* call far ptr ... */ 4188197007Sdelphij destval2 = fetch_data_word(emu, destoffset + 2); 4189197007Sdelphij push_word(emu, emu->x86.R_CS); 4190197007Sdelphij emu->x86.R_CS = destval2; 4191197007Sdelphij push_word(emu, emu->x86.R_IP); 4192197007Sdelphij emu->x86.R_IP = destval; 4193197007Sdelphij break; 4194197007Sdelphij case 5: /* jmp far ptr ... */ 4195197007Sdelphij destval2 = fetch_data_word(emu, destoffset + 2); 4196197007Sdelphij emu->x86.R_IP = destval; 4197197007Sdelphij emu->x86.R_CS = destval2; 4198197007Sdelphij break; 4199197007Sdelphij } 4200197007Sdelphij } else { 4201197007Sdelphij destval = *decode_rl_word_register(emu); 4202197007Sdelphij } 4203197007Sdelphij 4204197007Sdelphij switch (emu->cur_rh) { 4205197007Sdelphij case 2: /* call word ptr */ 4206197007Sdelphij push_word(emu, emu->x86.R_IP); 4207197007Sdelphij emu->x86.R_IP = destval; 4208197007Sdelphij break; 4209197007Sdelphij case 4: /* jmp */ 4210197007Sdelphij emu->x86.R_IP = destval; 4211197007Sdelphij break; 4212197007Sdelphij } 4213197007Sdelphij} 4214197007Sdelphij 4215197007Sdelphij/* 4216197007Sdelphij * * Single byte operation code table: 4217197007Sdelphij */ 4218197007Sdelphijstatic void 4219197007Sdelphijx86emu_exec_one_byte(struct x86emu * emu) 4220197007Sdelphij{ 4221197007Sdelphij uint8_t op1; 4222197007Sdelphij 4223197007Sdelphij op1 = fetch_byte_imm(emu); 4224197007Sdelphij 4225197007Sdelphij switch (op1) { 4226197007Sdelphij case 0x00: 4227197007Sdelphij common_binop_byte_rm_r(emu, add_byte); 4228197007Sdelphij break; 4229197007Sdelphij case 0x01: 4230197007Sdelphij common_binop_word_long_rm_r(emu, add_word, add_long); 4231197007Sdelphij break; 4232197007Sdelphij case 0x02: 4233197007Sdelphij common_binop_byte_r_rm(emu, add_byte); 4234197007Sdelphij break; 4235197007Sdelphij case 0x03: 4236197007Sdelphij common_binop_word_long_r_rm(emu, add_word, add_long); 4237197007Sdelphij break; 4238197007Sdelphij case 0x04: 4239197007Sdelphij common_binop_byte_imm(emu, add_byte); 4240197007Sdelphij break; 4241197007Sdelphij case 0x05: 4242197007Sdelphij common_binop_word_long_imm(emu, add_word, add_long); 4243197007Sdelphij break; 4244197007Sdelphij case 0x06: 4245197007Sdelphij push_word(emu, emu->x86.R_ES); 4246197007Sdelphij break; 4247197007Sdelphij case 0x07: 4248197007Sdelphij emu->x86.R_ES = pop_word(emu); 4249197007Sdelphij break; 4250197007Sdelphij 4251197007Sdelphij case 0x08: 4252197007Sdelphij common_binop_byte_rm_r(emu, or_byte); 4253197007Sdelphij break; 4254197007Sdelphij case 0x09: 4255197007Sdelphij common_binop_word_long_rm_r(emu, or_word, or_long); 4256197007Sdelphij break; 4257197007Sdelphij case 0x0a: 4258197007Sdelphij common_binop_byte_r_rm(emu, or_byte); 4259197007Sdelphij break; 4260197007Sdelphij case 0x0b: 4261197007Sdelphij common_binop_word_long_r_rm(emu, or_word, or_long); 4262197007Sdelphij break; 4263197007Sdelphij case 0x0c: 4264197007Sdelphij common_binop_byte_imm(emu, or_byte); 4265197007Sdelphij break; 4266197007Sdelphij case 0x0d: 4267197007Sdelphij common_binop_word_long_imm(emu, or_word, or_long); 4268197007Sdelphij break; 4269197007Sdelphij case 0x0e: 4270197007Sdelphij push_word(emu, emu->x86.R_CS); 4271197007Sdelphij break; 4272197007Sdelphij case 0x0f: 4273197007Sdelphij x86emu_exec_two_byte(emu); 4274197007Sdelphij break; 4275197007Sdelphij 4276197007Sdelphij case 0x10: 4277197007Sdelphij common_binop_byte_rm_r(emu, adc_byte); 4278197007Sdelphij break; 4279197007Sdelphij case 0x11: 4280197007Sdelphij common_binop_word_long_rm_r(emu, adc_word, adc_long); 4281197007Sdelphij break; 4282197007Sdelphij case 0x12: 4283197007Sdelphij common_binop_byte_r_rm(emu, adc_byte); 4284197007Sdelphij break; 4285197007Sdelphij case 0x13: 4286197007Sdelphij common_binop_word_long_r_rm(emu, adc_word, adc_long); 4287197007Sdelphij break; 4288197007Sdelphij case 0x14: 4289197007Sdelphij common_binop_byte_imm(emu, adc_byte); 4290197007Sdelphij break; 4291197007Sdelphij case 0x15: 4292197007Sdelphij common_binop_word_long_imm(emu, adc_word, adc_long); 4293197007Sdelphij break; 4294197007Sdelphij case 0x16: 4295197007Sdelphij push_word(emu, emu->x86.R_SS); 4296197007Sdelphij break; 4297197007Sdelphij case 0x17: 4298197007Sdelphij emu->x86.R_SS = pop_word(emu); 4299197007Sdelphij break; 4300197007Sdelphij 4301197007Sdelphij case 0x18: 4302197007Sdelphij common_binop_byte_rm_r(emu, sbb_byte); 4303197007Sdelphij break; 4304197007Sdelphij case 0x19: 4305197007Sdelphij common_binop_word_long_rm_r(emu, sbb_word, sbb_long); 4306197007Sdelphij break; 4307197007Sdelphij case 0x1a: 4308197007Sdelphij common_binop_byte_r_rm(emu, sbb_byte); 4309197007Sdelphij break; 4310197007Sdelphij case 0x1b: 4311197007Sdelphij common_binop_word_long_r_rm(emu, sbb_word, sbb_long); 4312197007Sdelphij break; 4313197007Sdelphij case 0x1c: 4314197007Sdelphij common_binop_byte_imm(emu, sbb_byte); 4315197007Sdelphij break; 4316197007Sdelphij case 0x1d: 4317197007Sdelphij common_binop_word_long_imm(emu, sbb_word, sbb_long); 4318197007Sdelphij break; 4319197007Sdelphij case 0x1e: 4320197007Sdelphij push_word(emu, emu->x86.R_DS); 4321197007Sdelphij break; 4322197007Sdelphij case 0x1f: 4323197007Sdelphij emu->x86.R_DS = pop_word(emu); 4324197007Sdelphij break; 4325197007Sdelphij 4326197007Sdelphij case 0x20: 4327197007Sdelphij common_binop_byte_rm_r(emu, and_byte); 4328197007Sdelphij break; 4329197007Sdelphij case 0x21: 4330197007Sdelphij common_binop_word_long_rm_r(emu, and_word, and_long); 4331197007Sdelphij break; 4332197007Sdelphij case 0x22: 4333197007Sdelphij common_binop_byte_r_rm(emu, and_byte); 4334197007Sdelphij break; 4335197007Sdelphij case 0x23: 4336197007Sdelphij common_binop_word_long_r_rm(emu, and_word, and_long); 4337197007Sdelphij break; 4338197007Sdelphij case 0x24: 4339197007Sdelphij common_binop_byte_imm(emu, and_byte); 4340197007Sdelphij break; 4341197007Sdelphij case 0x25: 4342197007Sdelphij common_binop_word_long_imm(emu, and_word, and_long); 4343197007Sdelphij break; 4344197007Sdelphij case 0x26: 4345197007Sdelphij emu->x86.mode |= SYSMODE_SEGOVR_ES; 4346197007Sdelphij break; 4347197007Sdelphij case 0x27: 4348197007Sdelphij emu->x86.R_AL = daa_byte(emu, emu->x86.R_AL); 4349197007Sdelphij break; 4350197007Sdelphij 4351197007Sdelphij case 0x28: 4352197007Sdelphij common_binop_byte_rm_r(emu, sub_byte); 4353197007Sdelphij break; 4354197007Sdelphij case 0x29: 4355197007Sdelphij common_binop_word_long_rm_r(emu, sub_word, sub_long); 4356197007Sdelphij break; 4357197007Sdelphij case 0x2a: 4358197007Sdelphij common_binop_byte_r_rm(emu, sub_byte); 4359197007Sdelphij break; 4360197007Sdelphij case 0x2b: 4361197007Sdelphij common_binop_word_long_r_rm(emu, sub_word, sub_long); 4362197007Sdelphij break; 4363197007Sdelphij case 0x2c: 4364197007Sdelphij common_binop_byte_imm(emu, sub_byte); 4365197007Sdelphij break; 4366197007Sdelphij case 0x2d: 4367197007Sdelphij common_binop_word_long_imm(emu, sub_word, sub_long); 4368197007Sdelphij break; 4369197007Sdelphij case 0x2e: 4370197007Sdelphij emu->x86.mode |= SYSMODE_SEGOVR_CS; 4371197007Sdelphij break; 4372197007Sdelphij case 0x2f: 4373197007Sdelphij emu->x86.R_AL = das_byte(emu, emu->x86.R_AL); 4374197007Sdelphij break; 4375197007Sdelphij 4376197007Sdelphij case 0x30: 4377197007Sdelphij common_binop_byte_rm_r(emu, xor_byte); 4378197007Sdelphij break; 4379197007Sdelphij case 0x31: 4380197007Sdelphij common_binop_word_long_rm_r(emu, xor_word, xor_long); 4381197007Sdelphij break; 4382197007Sdelphij case 0x32: 4383197007Sdelphij common_binop_byte_r_rm(emu, xor_byte); 4384197007Sdelphij break; 4385197007Sdelphij case 0x33: 4386197007Sdelphij common_binop_word_long_r_rm(emu, xor_word, xor_long); 4387197007Sdelphij break; 4388197007Sdelphij case 0x34: 4389197007Sdelphij common_binop_byte_imm(emu, xor_byte); 4390197007Sdelphij break; 4391197007Sdelphij case 0x35: 4392197007Sdelphij common_binop_word_long_imm(emu, xor_word, xor_long); 4393197007Sdelphij break; 4394197007Sdelphij case 0x36: 4395197007Sdelphij emu->x86.mode |= SYSMODE_SEGOVR_SS; 4396197007Sdelphij break; 4397197007Sdelphij case 0x37: 4398197007Sdelphij emu->x86.R_AX = aaa_word(emu, emu->x86.R_AX); 4399197007Sdelphij break; 4400197007Sdelphij 4401197007Sdelphij case 0x38: 4402197007Sdelphij common_binop_ns_byte_rm_r(emu, cmp_byte_no_return); 4403197007Sdelphij break; 4404197007Sdelphij case 0x39: 4405197007Sdelphij common_binop_ns_word_long_rm_r(emu, cmp_word_no_return, 4406197007Sdelphij cmp_long_no_return); 4407197007Sdelphij break; 4408197007Sdelphij case 0x3a: 4409197007Sdelphij x86emuOp_cmp_byte_R_RM(emu); 4410197007Sdelphij break; 4411197007Sdelphij case 0x3b: 4412197007Sdelphij x86emuOp_cmp_word_R_RM(emu); 4413197007Sdelphij break; 4414197007Sdelphij case 0x3c: 4415197007Sdelphij x86emuOp_cmp_byte_AL_IMM(emu); 4416197007Sdelphij break; 4417197007Sdelphij case 0x3d: 4418197007Sdelphij x86emuOp_cmp_word_AX_IMM(emu); 4419197007Sdelphij break; 4420197007Sdelphij case 0x3e: 4421197007Sdelphij emu->x86.mode |= SYSMODE_SEGOVR_DS; 4422197007Sdelphij break; 4423197007Sdelphij case 0x3f: 4424197007Sdelphij emu->x86.R_AX = aas_word(emu, emu->x86.R_AX); 4425197007Sdelphij break; 4426197007Sdelphij 4427197007Sdelphij case 0x40: 4428197007Sdelphij common_inc_word_long(emu, &emu->x86.register_a); 4429197007Sdelphij break; 4430197007Sdelphij case 0x41: 4431197007Sdelphij common_inc_word_long(emu, &emu->x86.register_c); 4432197007Sdelphij break; 4433197007Sdelphij case 0x42: 4434197007Sdelphij common_inc_word_long(emu, &emu->x86.register_d); 4435197007Sdelphij break; 4436197007Sdelphij case 0x43: 4437197007Sdelphij common_inc_word_long(emu, &emu->x86.register_b); 4438197007Sdelphij break; 4439197007Sdelphij case 0x44: 4440197007Sdelphij common_inc_word_long(emu, &emu->x86.register_sp); 4441197007Sdelphij break; 4442197007Sdelphij case 0x45: 4443197007Sdelphij common_inc_word_long(emu, &emu->x86.register_bp); 4444197007Sdelphij break; 4445197007Sdelphij case 0x46: 4446197007Sdelphij common_inc_word_long(emu, &emu->x86.register_si); 4447197007Sdelphij break; 4448197007Sdelphij case 0x47: 4449197007Sdelphij common_inc_word_long(emu, &emu->x86.register_di); 4450197007Sdelphij break; 4451197007Sdelphij 4452197007Sdelphij case 0x48: 4453197007Sdelphij common_dec_word_long(emu, &emu->x86.register_a); 4454197007Sdelphij break; 4455197007Sdelphij case 0x49: 4456197007Sdelphij common_dec_word_long(emu, &emu->x86.register_c); 4457197007Sdelphij break; 4458197007Sdelphij case 0x4a: 4459197007Sdelphij common_dec_word_long(emu, &emu->x86.register_d); 4460197007Sdelphij break; 4461197007Sdelphij case 0x4b: 4462197007Sdelphij common_dec_word_long(emu, &emu->x86.register_b); 4463197007Sdelphij break; 4464197007Sdelphij case 0x4c: 4465197007Sdelphij common_dec_word_long(emu, &emu->x86.register_sp); 4466197007Sdelphij break; 4467197007Sdelphij case 0x4d: 4468197007Sdelphij common_dec_word_long(emu, &emu->x86.register_bp); 4469197007Sdelphij break; 4470197007Sdelphij case 0x4e: 4471197007Sdelphij common_dec_word_long(emu, &emu->x86.register_si); 4472197007Sdelphij break; 4473197007Sdelphij case 0x4f: 4474197007Sdelphij common_dec_word_long(emu, &emu->x86.register_di); 4475197007Sdelphij break; 4476197007Sdelphij 4477197007Sdelphij case 0x50: 4478197007Sdelphij common_push_word_long(emu, &emu->x86.register_a); 4479197007Sdelphij break; 4480197007Sdelphij case 0x51: 4481197007Sdelphij common_push_word_long(emu, &emu->x86.register_c); 4482197007Sdelphij break; 4483197007Sdelphij case 0x52: 4484197007Sdelphij common_push_word_long(emu, &emu->x86.register_d); 4485197007Sdelphij break; 4486197007Sdelphij case 0x53: 4487197007Sdelphij common_push_word_long(emu, &emu->x86.register_b); 4488197007Sdelphij break; 4489197007Sdelphij case 0x54: 4490197007Sdelphij common_push_word_long(emu, &emu->x86.register_sp); 4491197007Sdelphij break; 4492197007Sdelphij case 0x55: 4493197007Sdelphij common_push_word_long(emu, &emu->x86.register_bp); 4494197007Sdelphij break; 4495197007Sdelphij case 0x56: 4496197007Sdelphij common_push_word_long(emu, &emu->x86.register_si); 4497197007Sdelphij break; 4498197007Sdelphij case 0x57: 4499197007Sdelphij common_push_word_long(emu, &emu->x86.register_di); 4500197007Sdelphij break; 4501197007Sdelphij 4502197007Sdelphij case 0x58: 4503197007Sdelphij common_pop_word_long(emu, &emu->x86.register_a); 4504197007Sdelphij break; 4505197007Sdelphij case 0x59: 4506197007Sdelphij common_pop_word_long(emu, &emu->x86.register_c); 4507197007Sdelphij break; 4508197007Sdelphij case 0x5a: 4509197007Sdelphij common_pop_word_long(emu, &emu->x86.register_d); 4510197007Sdelphij break; 4511197007Sdelphij case 0x5b: 4512197007Sdelphij common_pop_word_long(emu, &emu->x86.register_b); 4513197007Sdelphij break; 4514197007Sdelphij case 0x5c: 4515197007Sdelphij common_pop_word_long(emu, &emu->x86.register_sp); 4516197007Sdelphij break; 4517197007Sdelphij case 0x5d: 4518197007Sdelphij common_pop_word_long(emu, &emu->x86.register_bp); 4519197007Sdelphij break; 4520197007Sdelphij case 0x5e: 4521197007Sdelphij common_pop_word_long(emu, &emu->x86.register_si); 4522197007Sdelphij break; 4523197007Sdelphij case 0x5f: 4524197007Sdelphij common_pop_word_long(emu, &emu->x86.register_di); 4525197007Sdelphij break; 4526197007Sdelphij 4527197007Sdelphij case 0x60: 4528197007Sdelphij x86emuOp_push_all(emu); 4529197007Sdelphij break; 4530197007Sdelphij case 0x61: 4531197007Sdelphij x86emuOp_pop_all(emu); 4532197007Sdelphij break; 4533197007Sdelphij /* 0x62 bound */ 4534197007Sdelphij /* 0x63 arpl */ 4535197007Sdelphij case 0x64: 4536197007Sdelphij emu->x86.mode |= SYSMODE_SEGOVR_FS; 4537197007Sdelphij break; 4538197007Sdelphij case 0x65: 4539197007Sdelphij emu->x86.mode |= SYSMODE_SEGOVR_GS; 4540197007Sdelphij break; 4541197007Sdelphij case 0x66: 4542197007Sdelphij emu->x86.mode |= SYSMODE_PREFIX_DATA; 4543197007Sdelphij break; 4544197007Sdelphij case 0x67: 4545197007Sdelphij emu->x86.mode |= SYSMODE_PREFIX_ADDR; 4546197007Sdelphij break; 4547197007Sdelphij 4548197007Sdelphij case 0x68: 4549197007Sdelphij x86emuOp_push_word_IMM(emu); 4550197007Sdelphij break; 4551197007Sdelphij case 0x69: 4552197007Sdelphij common_imul_imm(emu, 0); 4553197007Sdelphij break; 4554197007Sdelphij case 0x6a: 4555197007Sdelphij x86emuOp_push_byte_IMM(emu); 4556197007Sdelphij break; 4557197007Sdelphij case 0x6b: 4558197007Sdelphij common_imul_imm(emu, 1); 4559197007Sdelphij break; 4560197007Sdelphij case 0x6c: 4561197007Sdelphij ins(emu, 1); 4562197007Sdelphij break; 4563197007Sdelphij case 0x6d: 4564197007Sdelphij x86emuOp_ins_word(emu); 4565197007Sdelphij break; 4566197007Sdelphij case 0x6e: 4567197007Sdelphij outs(emu, 1); 4568197007Sdelphij break; 4569197007Sdelphij case 0x6f: 4570197007Sdelphij x86emuOp_outs_word(emu); 4571197007Sdelphij break; 4572197007Sdelphij 4573197007Sdelphij case 0x70: 4574197007Sdelphij common_jmp_near(emu, ACCESS_FLAG(F_OF)); 4575197007Sdelphij break; 4576197007Sdelphij case 0x71: 4577197007Sdelphij common_jmp_near(emu, !ACCESS_FLAG(F_OF)); 4578197007Sdelphij break; 4579197007Sdelphij case 0x72: 4580197007Sdelphij common_jmp_near(emu, ACCESS_FLAG(F_CF)); 4581197007Sdelphij break; 4582197007Sdelphij case 0x73: 4583197007Sdelphij common_jmp_near(emu, !ACCESS_FLAG(F_CF)); 4584197007Sdelphij break; 4585197007Sdelphij case 0x74: 4586197007Sdelphij common_jmp_near(emu, ACCESS_FLAG(F_ZF)); 4587197007Sdelphij break; 4588197007Sdelphij case 0x75: 4589197007Sdelphij common_jmp_near(emu, !ACCESS_FLAG(F_ZF)); 4590197007Sdelphij break; 4591197007Sdelphij case 0x76: 4592197007Sdelphij common_jmp_near(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); 4593197007Sdelphij break; 4594197007Sdelphij case 0x77: 4595197007Sdelphij common_jmp_near(emu, !ACCESS_FLAG(F_CF) && !ACCESS_FLAG(F_ZF)); 4596197007Sdelphij break; 4597197007Sdelphij 4598197007Sdelphij case 0x78: 4599197007Sdelphij common_jmp_near(emu, ACCESS_FLAG(F_SF)); 4600197007Sdelphij break; 4601197007Sdelphij case 0x79: 4602197007Sdelphij common_jmp_near(emu, !ACCESS_FLAG(F_SF)); 4603197007Sdelphij break; 4604197007Sdelphij case 0x7a: 4605197007Sdelphij common_jmp_near(emu, ACCESS_FLAG(F_PF)); 4606197007Sdelphij break; 4607197007Sdelphij case 0x7b: 4608197007Sdelphij common_jmp_near(emu, !ACCESS_FLAG(F_PF)); 4609197007Sdelphij break; 4610197007Sdelphij case 0x7c: 4611197007Sdelphij x86emuOp_jump_near_L(emu); 4612197007Sdelphij break; 4613197007Sdelphij case 0x7d: 4614197007Sdelphij x86emuOp_jump_near_NL(emu); 4615197007Sdelphij break; 4616197007Sdelphij case 0x7e: 4617197007Sdelphij x86emuOp_jump_near_LE(emu); 4618197007Sdelphij break; 4619197007Sdelphij case 0x7f: 4620197007Sdelphij x86emuOp_jump_near_NLE(emu); 4621197007Sdelphij break; 4622197007Sdelphij 4623197007Sdelphij case 0x80: 4624197007Sdelphij x86emuOp_opc80_byte_RM_IMM(emu); 4625197007Sdelphij break; 4626197007Sdelphij case 0x81: 4627197007Sdelphij x86emuOp_opc81_word_RM_IMM(emu); 4628197007Sdelphij break; 4629197007Sdelphij case 0x82: 4630197007Sdelphij x86emuOp_opc82_byte_RM_IMM(emu); 4631197007Sdelphij break; 4632197007Sdelphij case 0x83: 4633197007Sdelphij x86emuOp_opc83_word_RM_IMM(emu); 4634197007Sdelphij break; 4635197007Sdelphij case 0x84: 4636197007Sdelphij common_binop_ns_byte_rm_r(emu, test_byte); 4637197007Sdelphij break; 4638197007Sdelphij case 0x85: 4639197007Sdelphij common_binop_ns_word_long_rm_r(emu, test_word, test_long); 4640197007Sdelphij break; 4641197007Sdelphij case 0x86: 4642197007Sdelphij x86emuOp_xchg_byte_RM_R(emu); 4643197007Sdelphij break; 4644197007Sdelphij case 0x87: 4645197007Sdelphij x86emuOp_xchg_word_RM_R(emu); 4646197007Sdelphij break; 4647197007Sdelphij 4648197007Sdelphij case 0x88: 4649197007Sdelphij x86emuOp_mov_byte_RM_R(emu); 4650197007Sdelphij break; 4651197007Sdelphij case 0x89: 4652197007Sdelphij x86emuOp_mov_word_RM_R(emu); 4653197007Sdelphij break; 4654197007Sdelphij case 0x8a: 4655197007Sdelphij x86emuOp_mov_byte_R_RM(emu); 4656197007Sdelphij break; 4657197007Sdelphij case 0x8b: 4658197007Sdelphij x86emuOp_mov_word_R_RM(emu); 4659197007Sdelphij break; 4660197007Sdelphij case 0x8c: 4661197007Sdelphij x86emuOp_mov_word_RM_SR(emu); 4662197007Sdelphij break; 4663197007Sdelphij case 0x8d: 4664197007Sdelphij x86emuOp_lea_word_R_M(emu); 4665197007Sdelphij break; 4666197007Sdelphij case 0x8e: 4667197007Sdelphij x86emuOp_mov_word_SR_RM(emu); 4668197007Sdelphij break; 4669197007Sdelphij case 0x8f: 4670197007Sdelphij x86emuOp_pop_RM(emu); 4671197007Sdelphij break; 4672197007Sdelphij 4673197007Sdelphij case 0x90: 4674197007Sdelphij /* nop */ 4675197007Sdelphij break; 4676197007Sdelphij case 0x91: 4677197007Sdelphij x86emuOp_xchg_word_AX_CX(emu); 4678197007Sdelphij break; 4679197007Sdelphij case 0x92: 4680197007Sdelphij x86emuOp_xchg_word_AX_DX(emu); 4681197007Sdelphij break; 4682197007Sdelphij case 0x93: 4683197007Sdelphij x86emuOp_xchg_word_AX_BX(emu); 4684197007Sdelphij break; 4685197007Sdelphij case 0x94: 4686197007Sdelphij x86emuOp_xchg_word_AX_SP(emu); 4687197007Sdelphij break; 4688197007Sdelphij case 0x95: 4689197007Sdelphij x86emuOp_xchg_word_AX_BP(emu); 4690197007Sdelphij break; 4691197007Sdelphij case 0x96: 4692197007Sdelphij x86emuOp_xchg_word_AX_SI(emu); 4693197007Sdelphij break; 4694197007Sdelphij case 0x97: 4695197007Sdelphij x86emuOp_xchg_word_AX_DI(emu); 4696197007Sdelphij break; 4697197007Sdelphij 4698197007Sdelphij case 0x98: 4699197007Sdelphij x86emuOp_cbw(emu); 4700197007Sdelphij break; 4701197007Sdelphij case 0x99: 4702197007Sdelphij x86emuOp_cwd(emu); 4703197007Sdelphij break; 4704197007Sdelphij case 0x9a: 4705197007Sdelphij x86emuOp_call_far_IMM(emu); 4706197007Sdelphij break; 4707197007Sdelphij case 0x9b: 4708197007Sdelphij /* wait */ 4709197007Sdelphij break; 4710197007Sdelphij case 0x9c: 4711197007Sdelphij x86emuOp_pushf_word(emu); 4712197007Sdelphij break; 4713197007Sdelphij case 0x9d: 4714197007Sdelphij x86emuOp_popf_word(emu); 4715197007Sdelphij break; 4716197007Sdelphij case 0x9e: 4717197007Sdelphij x86emuOp_sahf(emu); 4718197007Sdelphij break; 4719197007Sdelphij case 0x9f: 4720197007Sdelphij x86emuOp_lahf(emu); 4721197007Sdelphij break; 4722197007Sdelphij 4723197007Sdelphij case 0xa0: 4724197007Sdelphij x86emuOp_mov_AL_M_IMM(emu); 4725197007Sdelphij break; 4726197007Sdelphij case 0xa1: 4727197007Sdelphij x86emuOp_mov_AX_M_IMM(emu); 4728197007Sdelphij break; 4729197007Sdelphij case 0xa2: 4730197007Sdelphij x86emuOp_mov_M_AL_IMM(emu); 4731197007Sdelphij break; 4732197007Sdelphij case 0xa3: 4733197007Sdelphij x86emuOp_mov_M_AX_IMM(emu); 4734197007Sdelphij break; 4735197007Sdelphij case 0xa4: 4736197007Sdelphij x86emuOp_movs_byte(emu); 4737197007Sdelphij break; 4738197007Sdelphij case 0xa5: 4739197007Sdelphij x86emuOp_movs_word(emu); 4740197007Sdelphij break; 4741197007Sdelphij case 0xa6: 4742197007Sdelphij x86emuOp_cmps_byte(emu); 4743197007Sdelphij break; 4744197007Sdelphij case 0xa7: 4745197007Sdelphij x86emuOp_cmps_word(emu); 4746197007Sdelphij break; 4747197007Sdelphij 4748197007Sdelphij case 0xa8: 4749197007Sdelphij test_byte(emu, emu->x86.R_AL, fetch_byte_imm(emu)); 4750197007Sdelphij break; 4751197007Sdelphij case 0xa9: 4752197007Sdelphij x86emuOp_test_AX_IMM(emu); 4753197007Sdelphij break; 4754197007Sdelphij case 0xaa: 4755197007Sdelphij x86emuOp_stos_byte(emu); 4756197007Sdelphij break; 4757197007Sdelphij case 0xab: 4758197007Sdelphij x86emuOp_stos_word(emu); 4759197007Sdelphij break; 4760197007Sdelphij case 0xac: 4761197007Sdelphij x86emuOp_lods_byte(emu); 4762197007Sdelphij break; 4763197007Sdelphij case 0xad: 4764197007Sdelphij x86emuOp_lods_word(emu); 4765197007Sdelphij break; 4766197007Sdelphij case 0xae: 4767197007Sdelphij x86emuOp_scas_byte(emu); 4768197007Sdelphij break; 4769197007Sdelphij case 0xaf: 4770197007Sdelphij x86emuOp_scas_word(emu); 4771197007Sdelphij break; 4772197007Sdelphij 4773197007Sdelphij case 0xb0: 4774197007Sdelphij emu->x86.R_AL = fetch_byte_imm(emu); 4775197007Sdelphij break; 4776197007Sdelphij case 0xb1: 4777197007Sdelphij emu->x86.R_CL = fetch_byte_imm(emu); 4778197007Sdelphij break; 4779197007Sdelphij case 0xb2: 4780197007Sdelphij emu->x86.R_DL = fetch_byte_imm(emu); 4781197007Sdelphij break; 4782197007Sdelphij case 0xb3: 4783197007Sdelphij emu->x86.R_BL = fetch_byte_imm(emu); 4784197007Sdelphij break; 4785197007Sdelphij case 0xb4: 4786197007Sdelphij emu->x86.R_AH = fetch_byte_imm(emu); 4787197007Sdelphij break; 4788197007Sdelphij case 0xb5: 4789197007Sdelphij emu->x86.R_CH = fetch_byte_imm(emu); 4790197007Sdelphij break; 4791197007Sdelphij case 0xb6: 4792197007Sdelphij emu->x86.R_DH = fetch_byte_imm(emu); 4793197007Sdelphij break; 4794197007Sdelphij case 0xb7: 4795197007Sdelphij emu->x86.R_BH = fetch_byte_imm(emu); 4796197007Sdelphij break; 4797197007Sdelphij 4798197007Sdelphij case 0xb8: 4799197007Sdelphij x86emuOp_mov_word_AX_IMM(emu); 4800197007Sdelphij break; 4801197007Sdelphij case 0xb9: 4802197007Sdelphij x86emuOp_mov_word_CX_IMM(emu); 4803197007Sdelphij break; 4804197007Sdelphij case 0xba: 4805197007Sdelphij x86emuOp_mov_word_DX_IMM(emu); 4806197007Sdelphij break; 4807197007Sdelphij case 0xbb: 4808197007Sdelphij x86emuOp_mov_word_BX_IMM(emu); 4809197007Sdelphij break; 4810197007Sdelphij case 0xbc: 4811197007Sdelphij 4812197007Sdelphij x86emuOp_mov_word_SP_IMM(emu); 4813197007Sdelphij break; 4814197007Sdelphij case 0xbd: 4815197007Sdelphij x86emuOp_mov_word_BP_IMM(emu); 4816197007Sdelphij break; 4817197007Sdelphij case 0xbe: 4818197007Sdelphij x86emuOp_mov_word_SI_IMM(emu); 4819197007Sdelphij break; 4820197007Sdelphij case 0xbf: 4821197007Sdelphij x86emuOp_mov_word_DI_IMM(emu); 4822197007Sdelphij break; 4823197007Sdelphij 4824197007Sdelphij case 0xc0: 4825197007Sdelphij x86emuOp_opcC0_byte_RM_MEM(emu); 4826197007Sdelphij break; 4827197007Sdelphij case 0xc1: 4828197007Sdelphij x86emuOp_opcC1_word_RM_MEM(emu); 4829197007Sdelphij break; 4830197007Sdelphij case 0xc2: 4831197007Sdelphij x86emuOp_ret_near_IMM(emu); 4832197007Sdelphij break; 4833197007Sdelphij case 0xc3: 4834197007Sdelphij emu->x86.R_IP = pop_word(emu); 4835197007Sdelphij break; 4836197007Sdelphij case 0xc4: 4837197007Sdelphij common_load_far_pointer(emu, &emu->x86.R_ES); 4838197007Sdelphij break; 4839197007Sdelphij case 0xc5: 4840197007Sdelphij common_load_far_pointer(emu, &emu->x86.R_DS); 4841197007Sdelphij break; 4842197007Sdelphij case 0xc6: 4843197007Sdelphij x86emuOp_mov_byte_RM_IMM(emu); 4844197007Sdelphij break; 4845197007Sdelphij case 0xc7: 4846197007Sdelphij x86emuOp_mov_word_RM_IMM(emu); 4847197007Sdelphij break; 4848197007Sdelphij case 0xc8: 4849197007Sdelphij x86emuOp_enter(emu); 4850197007Sdelphij break; 4851197007Sdelphij case 0xc9: 4852197007Sdelphij x86emuOp_leave(emu); 4853197007Sdelphij break; 4854197007Sdelphij case 0xca: 4855197007Sdelphij x86emuOp_ret_far_IMM(emu); 4856197007Sdelphij break; 4857197007Sdelphij case 0xcb: 4858197007Sdelphij x86emuOp_ret_far(emu); 4859197007Sdelphij break; 4860197007Sdelphij case 0xcc: 4861197007Sdelphij x86emuOp_int3(emu); 4862197007Sdelphij break; 4863197007Sdelphij case 0xcd: 4864197007Sdelphij x86emuOp_int_IMM(emu); 4865197007Sdelphij break; 4866197007Sdelphij case 0xce: 4867197007Sdelphij x86emuOp_into(emu); 4868197007Sdelphij break; 4869197007Sdelphij case 0xcf: 4870197007Sdelphij x86emuOp_iret(emu); 4871197007Sdelphij break; 4872197007Sdelphij 4873197007Sdelphij case 0xd0: 4874197007Sdelphij x86emuOp_opcD0_byte_RM_1(emu); 4875197007Sdelphij break; 4876197007Sdelphij case 0xd1: 4877197007Sdelphij x86emuOp_opcD1_word_RM_1(emu); 4878197007Sdelphij break; 4879197007Sdelphij case 0xd2: 4880197007Sdelphij x86emuOp_opcD2_byte_RM_CL(emu); 4881197007Sdelphij break; 4882197007Sdelphij case 0xd3: 4883197007Sdelphij x86emuOp_opcD3_word_RM_CL(emu); 4884197007Sdelphij break; 4885197007Sdelphij case 0xd4: 4886197007Sdelphij x86emuOp_aam(emu); 4887197007Sdelphij break; 4888197007Sdelphij case 0xd5: 4889197007Sdelphij x86emuOp_aad(emu); 4890197007Sdelphij break; 4891197007Sdelphij /* 0xd6 Undocumented SETALC instruction */ 4892197007Sdelphij case 0xd7: 4893197007Sdelphij x86emuOp_xlat(emu); 4894197007Sdelphij break; 4895197007Sdelphij case 0xd8: 4896197007Sdelphij x86emuOp_esc_coprocess_d8(emu); 4897197007Sdelphij break; 4898197007Sdelphij case 0xd9: 4899197007Sdelphij x86emuOp_esc_coprocess_d9(emu); 4900197007Sdelphij break; 4901197007Sdelphij case 0xda: 4902197007Sdelphij x86emuOp_esc_coprocess_da(emu); 4903197007Sdelphij break; 4904197007Sdelphij case 0xdb: 4905197007Sdelphij x86emuOp_esc_coprocess_db(emu); 4906197007Sdelphij break; 4907197007Sdelphij case 0xdc: 4908197007Sdelphij x86emuOp_esc_coprocess_dc(emu); 4909197007Sdelphij break; 4910197007Sdelphij case 0xdd: 4911197007Sdelphij x86emuOp_esc_coprocess_dd(emu); 4912197007Sdelphij break; 4913197007Sdelphij case 0xde: 4914197007Sdelphij x86emuOp_esc_coprocess_de(emu); 4915197007Sdelphij break; 4916197007Sdelphij case 0xdf: 4917197007Sdelphij x86emuOp_esc_coprocess_df(emu); 4918197007Sdelphij break; 4919197007Sdelphij 4920197007Sdelphij case 0xe0: 4921197007Sdelphij x86emuOp_loopne(emu); 4922197007Sdelphij break; 4923197007Sdelphij case 0xe1: 4924197007Sdelphij x86emuOp_loope(emu); 4925197007Sdelphij break; 4926197007Sdelphij case 0xe2: 4927197007Sdelphij x86emuOp_loop(emu); 4928197007Sdelphij break; 4929197007Sdelphij case 0xe3: 4930197007Sdelphij x86emuOp_jcxz(emu); 4931197007Sdelphij break; 4932197007Sdelphij case 0xe4: 4933197007Sdelphij x86emuOp_in_byte_AL_IMM(emu); 4934197007Sdelphij break; 4935197007Sdelphij case 0xe5: 4936197007Sdelphij x86emuOp_in_word_AX_IMM(emu); 4937197007Sdelphij break; 4938197007Sdelphij case 0xe6: 4939197007Sdelphij x86emuOp_out_byte_IMM_AL(emu); 4940197007Sdelphij break; 4941197007Sdelphij case 0xe7: 4942197007Sdelphij x86emuOp_out_word_IMM_AX(emu); 4943197007Sdelphij break; 4944197007Sdelphij 4945197007Sdelphij case 0xe8: 4946197007Sdelphij x86emuOp_call_near_IMM(emu); 4947197007Sdelphij break; 4948197007Sdelphij case 0xe9: 4949197007Sdelphij x86emuOp_jump_near_IMM(emu); 4950197007Sdelphij break; 4951197007Sdelphij case 0xea: 4952197007Sdelphij x86emuOp_jump_far_IMM(emu); 4953197007Sdelphij break; 4954197007Sdelphij case 0xeb: 4955197007Sdelphij x86emuOp_jump_byte_IMM(emu); 4956197007Sdelphij break; 4957197007Sdelphij case 0xec: 4958197007Sdelphij x86emuOp_in_byte_AL_DX(emu); 4959197007Sdelphij break; 4960197007Sdelphij case 0xed: 4961197007Sdelphij x86emuOp_in_word_AX_DX(emu); 4962197007Sdelphij break; 4963197007Sdelphij case 0xee: 4964197007Sdelphij x86emuOp_out_byte_DX_AL(emu); 4965197007Sdelphij break; 4966197007Sdelphij case 0xef: 4967197007Sdelphij x86emuOp_out_word_DX_AX(emu); 4968197007Sdelphij break; 4969197007Sdelphij 4970197007Sdelphij case 0xf0: 4971197007Sdelphij x86emuOp_lock(emu); 4972197007Sdelphij break; 4973197007Sdelphij case 0xf2: 4974197007Sdelphij emu->x86.mode |= SYSMODE_PREFIX_REPNE; 4975197007Sdelphij break; 4976197007Sdelphij case 0xf3: 4977197007Sdelphij emu->x86.mode |= SYSMODE_PREFIX_REPE; 4978197007Sdelphij break; 4979197007Sdelphij case 0xf4: 4980197007Sdelphij x86emu_halt_sys(emu); 4981197007Sdelphij break; 4982197007Sdelphij case 0xf5: 4983197007Sdelphij x86emuOp_cmc(emu); 4984197007Sdelphij break; 4985197007Sdelphij case 0xf6: 4986197007Sdelphij x86emuOp_opcF6_byte_RM(emu); 4987197007Sdelphij break; 4988197007Sdelphij case 0xf7: 4989197007Sdelphij x86emuOp_opcF7_word_RM(emu); 4990197007Sdelphij break; 4991197007Sdelphij 4992197007Sdelphij case 0xf8: 4993197007Sdelphij CLEAR_FLAG(F_CF); 4994197007Sdelphij break; 4995197007Sdelphij case 0xf9: 4996197007Sdelphij SET_FLAG(F_CF); 4997197007Sdelphij break; 4998197007Sdelphij case 0xfa: 4999197007Sdelphij CLEAR_FLAG(F_IF); 5000197007Sdelphij break; 5001197007Sdelphij case 0xfb: 5002197007Sdelphij SET_FLAG(F_IF); 5003197007Sdelphij break; 5004197007Sdelphij case 0xfc: 5005197007Sdelphij CLEAR_FLAG(F_DF); 5006197007Sdelphij break; 5007197007Sdelphij case 0xfd: 5008197007Sdelphij SET_FLAG(F_DF); 5009197007Sdelphij break; 5010197007Sdelphij case 0xfe: 5011197007Sdelphij x86emuOp_opcFE_byte_RM(emu); 5012197007Sdelphij break; 5013197007Sdelphij case 0xff: 5014197007Sdelphij x86emuOp_opcFF_word_RM(emu); 5015197007Sdelphij break; 5016197007Sdelphij default: 5017197007Sdelphij x86emu_halt_sys(emu); 5018197007Sdelphij break; 5019197007Sdelphij } 5020197007Sdelphij if (op1 != 0x26 && op1 != 0x2e && op1 != 0x36 && op1 != 0x3e && 5021197007Sdelphij (op1 | 3) != 0x67) 5022197007Sdelphij emu->x86.mode &= ~SYSMODE_CLRMASK; 5023197007Sdelphij} 5024197007Sdelphij 5025197007Sdelphijstatic void 5026197007Sdelphijcommon_jmp_long(struct x86emu *emu, int cond) 5027197007Sdelphij{ 5028197007Sdelphij int16_t target; 5029197007Sdelphij 5030197007Sdelphij target = (int16_t) fetch_word_imm(emu); 5031197007Sdelphij target += (int16_t) emu->x86.R_IP; 5032197007Sdelphij if (cond) 5033197007Sdelphij emu->x86.R_IP = (uint16_t) target; 5034197007Sdelphij} 5035197007Sdelphij 5036197007Sdelphijstatic void 5037197007Sdelphijcommon_set_byte(struct x86emu *emu, int cond) 5038197007Sdelphij{ 5039197007Sdelphij uint32_t destoffset; 5040197007Sdelphij uint8_t *destreg, destval; 5041197007Sdelphij 5042197007Sdelphij fetch_decode_modrm(emu); 5043197007Sdelphij destval = cond ? 0x01 : 0x00; 5044197007Sdelphij if (emu->cur_mod != 3) { 5045197007Sdelphij destoffset = decode_rl_address(emu); 5046197007Sdelphij store_data_byte(emu, destoffset, destval); 5047197007Sdelphij } else { 5048197007Sdelphij destreg = decode_rl_byte_register(emu); 5049197007Sdelphij *destreg = destval; 5050197007Sdelphij } 5051197007Sdelphij} 5052197007Sdelphij 5053197007Sdelphijstatic void 5054197007Sdelphijcommon_bitstring32(struct x86emu *emu, int op) 5055197007Sdelphij{ 5056197007Sdelphij int bit; 5057197007Sdelphij uint32_t srcval, *shiftreg, mask; 5058197007Sdelphij 5059197007Sdelphij fetch_decode_modrm(emu); 5060197007Sdelphij shiftreg = decode_rh_long_register(emu); 5061197007Sdelphij srcval = decode_and_fetch_long_disp(emu, (int16_t) *shiftreg >> 5); 5062197007Sdelphij bit = *shiftreg & 0x1F; 5063197007Sdelphij mask = 0x1 << bit; 5064197007Sdelphij CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 5065197007Sdelphij 5066197007Sdelphij switch (op) { 5067197007Sdelphij case 0: 5068197007Sdelphij break; 5069197007Sdelphij case 1: 5070197007Sdelphij write_back_long(emu, srcval | mask); 5071197007Sdelphij break; 5072197007Sdelphij case 2: 5073197007Sdelphij write_back_long(emu, srcval & ~mask); 5074197007Sdelphij break; 5075197007Sdelphij case 3: 5076197007Sdelphij write_back_long(emu, srcval ^ mask); 5077197007Sdelphij break; 5078197007Sdelphij } 5079197007Sdelphij} 5080197007Sdelphij 5081197007Sdelphijstatic void 5082197007Sdelphijcommon_bitstring16(struct x86emu *emu, int op) 5083197007Sdelphij{ 5084197007Sdelphij int bit; 5085197007Sdelphij uint16_t srcval, *shiftreg, mask; 5086197007Sdelphij 5087197007Sdelphij fetch_decode_modrm(emu); 5088197007Sdelphij shiftreg = decode_rh_word_register(emu); 5089197007Sdelphij srcval = decode_and_fetch_word_disp(emu, (int16_t) *shiftreg >> 4); 5090197007Sdelphij bit = *shiftreg & 0xF; 5091197007Sdelphij mask = 0x1 << bit; 5092197007Sdelphij CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 5093197007Sdelphij 5094197007Sdelphij switch (op) { 5095197007Sdelphij case 0: 5096197007Sdelphij break; 5097197007Sdelphij case 1: 5098197007Sdelphij write_back_word(emu, srcval | mask); 5099197007Sdelphij break; 5100197007Sdelphij case 2: 5101197007Sdelphij write_back_word(emu, srcval & ~mask); 5102197007Sdelphij break; 5103197007Sdelphij case 3: 5104197007Sdelphij write_back_word(emu, srcval ^ mask); 5105197007Sdelphij break; 5106197007Sdelphij } 5107197007Sdelphij} 5108197007Sdelphij 5109197007Sdelphijstatic void 5110197007Sdelphijcommon_bitstring(struct x86emu *emu, int op) 5111197007Sdelphij{ 5112197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5113197007Sdelphij common_bitstring32(emu, op); 5114197007Sdelphij else 5115197007Sdelphij common_bitstring16(emu, op); 5116197007Sdelphij} 5117197007Sdelphij 5118197007Sdelphijstatic void 5119197007Sdelphijcommon_bitsearch32(struct x86emu *emu, int diff) 5120197007Sdelphij{ 5121197007Sdelphij uint32_t srcval, *dstreg; 5122197007Sdelphij 5123197007Sdelphij fetch_decode_modrm(emu); 5124197007Sdelphij dstreg = decode_rh_long_register(emu); 5125197007Sdelphij srcval = decode_and_fetch_long(emu); 5126197007Sdelphij CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 5127197007Sdelphij for (*dstreg = 0; *dstreg < 32; *dstreg += diff) { 5128197007Sdelphij if ((srcval >> *dstreg) & 1) 5129197007Sdelphij break; 5130197007Sdelphij } 5131197007Sdelphij} 5132197007Sdelphij 5133197007Sdelphijstatic void 5134197007Sdelphijcommon_bitsearch16(struct x86emu *emu, int diff) 5135197007Sdelphij{ 5136197007Sdelphij uint16_t srcval, *dstreg; 5137197007Sdelphij 5138197007Sdelphij fetch_decode_modrm(emu); 5139197007Sdelphij dstreg = decode_rh_word_register(emu); 5140197007Sdelphij srcval = decode_and_fetch_word(emu); 5141197007Sdelphij CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 5142197007Sdelphij for (*dstreg = 0; *dstreg < 16; *dstreg += diff) { 5143197007Sdelphij if ((srcval >> *dstreg) & 1) 5144197007Sdelphij break; 5145197007Sdelphij } 5146197007Sdelphij} 5147197007Sdelphij 5148197007Sdelphijstatic void 5149197007Sdelphijcommon_bitsearch(struct x86emu *emu, int diff) 5150197007Sdelphij{ 5151197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5152197007Sdelphij common_bitsearch32(emu, diff); 5153197007Sdelphij else 5154197007Sdelphij common_bitsearch16(emu, diff); 5155197007Sdelphij} 5156197007Sdelphij 5157197007Sdelphijstatic void 5158197007Sdelphijcommon_shift32(struct x86emu *emu, int shift_left, int use_cl) 5159197007Sdelphij{ 5160197007Sdelphij uint8_t shift; 5161197007Sdelphij uint32_t destval, *shiftreg; 5162197007Sdelphij 5163197007Sdelphij fetch_decode_modrm(emu); 5164197007Sdelphij shiftreg = decode_rh_long_register(emu); 5165197007Sdelphij if (use_cl) { 5166197007Sdelphij destval = decode_and_fetch_long(emu); 5167197007Sdelphij shift = emu->x86.R_CL; 5168197007Sdelphij } else { 5169197007Sdelphij destval = decode_and_fetch_long_imm8(emu, &shift); 5170197007Sdelphij } 5171197007Sdelphij if (shift_left) 5172197007Sdelphij destval = shld_long(emu, destval, *shiftreg, shift); 5173197007Sdelphij else 5174197007Sdelphij destval = shrd_long(emu, destval, *shiftreg, shift); 5175197007Sdelphij write_back_long(emu, destval); 5176197007Sdelphij} 5177197007Sdelphij 5178197007Sdelphijstatic void 5179197007Sdelphijcommon_shift16(struct x86emu *emu, int shift_left, int use_cl) 5180197007Sdelphij{ 5181197007Sdelphij uint8_t shift; 5182197007Sdelphij uint16_t destval, *shiftreg; 5183197007Sdelphij 5184197007Sdelphij fetch_decode_modrm(emu); 5185197007Sdelphij shiftreg = decode_rh_word_register(emu); 5186197007Sdelphij if (use_cl) { 5187197007Sdelphij destval = decode_and_fetch_word(emu); 5188197007Sdelphij shift = emu->x86.R_CL; 5189197007Sdelphij } else { 5190197007Sdelphij destval = decode_and_fetch_word_imm8(emu, &shift); 5191197007Sdelphij } 5192197007Sdelphij if (shift_left) 5193197007Sdelphij destval = shld_word(emu, destval, *shiftreg, shift); 5194197007Sdelphij else 5195197007Sdelphij destval = shrd_word(emu, destval, *shiftreg, shift); 5196197007Sdelphij write_back_word(emu, destval); 5197197007Sdelphij} 5198197007Sdelphij 5199197007Sdelphijstatic void 5200197007Sdelphijcommon_shift(struct x86emu *emu, int shift_left, int use_cl) 5201197007Sdelphij{ 5202197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5203197007Sdelphij common_shift32(emu, shift_left, use_cl); 5204197007Sdelphij else 5205197007Sdelphij common_shift16(emu, shift_left, use_cl); 5206197007Sdelphij} 5207197007Sdelphij 5208204934Sdelphij/* 5209204934Sdelphij * Implementation 5210204934Sdelphij */ 5211197007Sdelphij#define xorl(a,b) ((a) && !(b)) || (!(a) && (b)) 5212197007Sdelphij 5213197007Sdelphij 5214197007Sdelphij/* 5215197007Sdelphij * REMARKS: 5216197007Sdelphij * Handles opcode 0x0f,0x31 5217197007Sdelphij */ 5218197007Sdelphijstatic void 5219197007Sdelphijx86emuOp2_rdtsc(struct x86emu *emu) 5220197007Sdelphij{ 5221197007Sdelphij emu->x86.R_EAX = emu->cur_cycles & 0xffffffff; 5222197007Sdelphij emu->x86.R_EDX = emu->cur_cycles >> 32; 5223197007Sdelphij} 5224197007Sdelphij 5225197007Sdelphij/* 5226197007Sdelphij * REMARKS: 5227197007Sdelphij * Handles opcode 0x0f,0xa0 5228197007Sdelphij */ 5229197007Sdelphijstatic void 5230197007Sdelphijx86emuOp2_push_FS(struct x86emu *emu) 5231197007Sdelphij{ 5232197007Sdelphij push_word(emu, emu->x86.R_FS); 5233197007Sdelphij} 5234197007Sdelphij 5235197007Sdelphij/* 5236197007Sdelphij * REMARKS: 5237197007Sdelphij * Handles opcode 0x0f,0xa1 5238197007Sdelphij */ 5239197007Sdelphijstatic void 5240197007Sdelphijx86emuOp2_pop_FS(struct x86emu *emu) 5241197007Sdelphij{ 5242197007Sdelphij emu->x86.R_FS = pop_word(emu); 5243197007Sdelphij} 5244197007Sdelphij 5245197007Sdelphij/* 5246197007Sdelphij * REMARKS: 5247197007Sdelphij * Handles opcode 0x0f,0xa1 5248197007Sdelphij */ 5249197007Sdelphij#if defined(__i386__) || defined(__amd64__) 5250197007Sdelphijstatic void 5251197007Sdelphijhw_cpuid(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) 5252197007Sdelphij{ 5253282050Sdelphij __asm__ volatile("cpuid" 5254197007Sdelphij : "=a" (*a), "=b" (*b), 5255197007Sdelphij "=c" (*c), "=d" (*d) 5256197007Sdelphij : "a" (*a), "c" (*c) 5257197007Sdelphij : "cc"); 5258197007Sdelphij} 5259197007Sdelphij#endif 5260197007Sdelphijstatic void 5261197007Sdelphijx86emuOp2_cpuid(struct x86emu *emu) 5262197007Sdelphij{ 5263197007Sdelphij#if defined(__i386__) || defined(__amd64__) 5264197007Sdelphij hw_cpuid(&emu->x86.R_EAX, &emu->x86.R_EBX, &emu->x86.R_ECX, 5265197007Sdelphij &emu->x86.R_EDX); 5266197007Sdelphij#endif 5267197007Sdelphij switch (emu->x86.R_EAX) { 5268197007Sdelphij case 0: 5269197007Sdelphij emu->x86.R_EAX = 1; 5270197007Sdelphij#if !defined(__i386__) && !defined(__amd64__) 5271197007Sdelphij /* "GenuineIntel" */ 5272197007Sdelphij emu->x86.R_EBX = 0x756e6547; 5273197007Sdelphij emu->x86.R_EDX = 0x49656e69; 5274197007Sdelphij emu->x86.R_ECX = 0x6c65746e; 5275197007Sdelphij#endif 5276197007Sdelphij break; 5277197007Sdelphij case 1: 5278197007Sdelphij#if !defined(__i386__) && !defined(__amd64__) 5279197007Sdelphij emu->x86.R_EAX = 0x00000480; 5280197007Sdelphij emu->x86.R_EBX = emu->x86.R_ECX = 0; 5281197007Sdelphij emu->x86.R_EDX = 0x00000002; 5282197007Sdelphij#else 5283197007Sdelphij emu->x86.R_EDX &= 0x00000012; 5284197007Sdelphij#endif 5285197007Sdelphij break; 5286197007Sdelphij default: 5287197007Sdelphij emu->x86.R_EAX = emu->x86.R_EBX = emu->x86.R_ECX = 5288197007Sdelphij emu->x86.R_EDX = 0; 5289197007Sdelphij break; 5290197007Sdelphij } 5291197007Sdelphij} 5292197007Sdelphij 5293197007Sdelphij/* 5294197007Sdelphij * REMARKS: 5295197007Sdelphij * Handles opcode 0x0f,0xa3 5296197007Sdelphij */ 5297197007Sdelphijstatic void 5298197007Sdelphijx86emuOp2_bt_R(struct x86emu *emu) 5299197007Sdelphij{ 5300197007Sdelphij common_bitstring(emu, 0); 5301197007Sdelphij} 5302197007Sdelphij 5303197007Sdelphij/* 5304197007Sdelphij * REMARKS: 5305197007Sdelphij * Handles opcode 0x0f,0xa4 5306197007Sdelphij */ 5307197007Sdelphijstatic void 5308197007Sdelphijx86emuOp2_shld_IMM(struct x86emu *emu) 5309197007Sdelphij{ 5310197007Sdelphij common_shift(emu, 1, 0); 5311197007Sdelphij} 5312197007Sdelphij 5313197007Sdelphij/* 5314197007Sdelphij * REMARKS: 5315197007Sdelphij * Handles opcode 0x0f,0xa5 5316197007Sdelphij */ 5317197007Sdelphijstatic void 5318197007Sdelphijx86emuOp2_shld_CL(struct x86emu *emu) 5319197007Sdelphij{ 5320197007Sdelphij common_shift(emu, 1, 1); 5321197007Sdelphij} 5322197007Sdelphij 5323197007Sdelphij/* 5324197007Sdelphij * REMARKS: 5325197007Sdelphij * Handles opcode 0x0f,0xa8 5326197007Sdelphij */ 5327197007Sdelphijstatic void 5328197007Sdelphijx86emuOp2_push_GS(struct x86emu *emu) 5329197007Sdelphij{ 5330197007Sdelphij push_word(emu, emu->x86.R_GS); 5331197007Sdelphij} 5332197007Sdelphij 5333197007Sdelphij/* 5334197007Sdelphij * REMARKS: 5335197007Sdelphij * Handles opcode 0x0f,0xa9 5336197007Sdelphij */ 5337197007Sdelphijstatic void 5338197007Sdelphijx86emuOp2_pop_GS(struct x86emu *emu) 5339197007Sdelphij{ 5340197007Sdelphij emu->x86.R_GS = pop_word(emu); 5341197007Sdelphij} 5342197007Sdelphij 5343197007Sdelphij/* 5344197007Sdelphij * REMARKS: 5345197007Sdelphij * Handles opcode 0x0f,0xab 5346197007Sdelphij */ 5347197007Sdelphijstatic void 5348197007Sdelphijx86emuOp2_bts_R(struct x86emu *emu) 5349197007Sdelphij{ 5350197007Sdelphij common_bitstring(emu, 1); 5351197007Sdelphij} 5352197007Sdelphij 5353197007Sdelphij/* 5354197007Sdelphij * REMARKS: 5355197007Sdelphij * Handles opcode 0x0f,0xac 5356197007Sdelphij */ 5357197007Sdelphijstatic void 5358197007Sdelphijx86emuOp2_shrd_IMM(struct x86emu *emu) 5359197007Sdelphij{ 5360197007Sdelphij common_shift(emu, 0, 0); 5361197007Sdelphij} 5362197007Sdelphij 5363197007Sdelphij/* 5364197007Sdelphij * REMARKS: 5365197007Sdelphij * Handles opcode 0x0f,0xad 5366197007Sdelphij */ 5367197007Sdelphijstatic void 5368197007Sdelphijx86emuOp2_shrd_CL(struct x86emu *emu) 5369197007Sdelphij{ 5370197007Sdelphij common_shift(emu, 0, 1); 5371197007Sdelphij} 5372197007Sdelphij 5373197007Sdelphij/* 5374197007Sdelphij * REMARKS: 5375197007Sdelphij * Handles opcode 0x0f,0xaf 5376197007Sdelphij */ 5377197007Sdelphijstatic void 5378197007Sdelphijx86emuOp2_32_imul_R_RM(struct x86emu *emu) 5379197007Sdelphij{ 5380197007Sdelphij uint32_t *destreg, srcval; 5381197007Sdelphij uint64_t res; 5382197007Sdelphij 5383197007Sdelphij fetch_decode_modrm(emu); 5384197007Sdelphij destreg = decode_rh_long_register(emu); 5385197007Sdelphij srcval = decode_and_fetch_long(emu); 5386197007Sdelphij res = (int32_t) *destreg * (int32_t)srcval; 5387197007Sdelphij if (res > 0xffffffff) { 5388197007Sdelphij SET_FLAG(F_CF); 5389197007Sdelphij SET_FLAG(F_OF); 5390197007Sdelphij } else { 5391197007Sdelphij CLEAR_FLAG(F_CF); 5392197007Sdelphij CLEAR_FLAG(F_OF); 5393197007Sdelphij } 5394197007Sdelphij *destreg = (uint32_t) res; 5395197007Sdelphij} 5396197007Sdelphij 5397197007Sdelphijstatic void 5398197007Sdelphijx86emuOp2_16_imul_R_RM(struct x86emu *emu) 5399197007Sdelphij{ 5400197007Sdelphij uint16_t *destreg, srcval; 5401197007Sdelphij uint32_t res; 5402197007Sdelphij 5403197007Sdelphij fetch_decode_modrm(emu); 5404197007Sdelphij destreg = decode_rh_word_register(emu); 5405197007Sdelphij srcval = decode_and_fetch_word(emu); 5406197007Sdelphij res = (int16_t) * destreg * (int16_t)srcval; 5407197007Sdelphij if (res > 0xFFFF) { 5408197007Sdelphij SET_FLAG(F_CF); 5409197007Sdelphij SET_FLAG(F_OF); 5410197007Sdelphij } else { 5411197007Sdelphij CLEAR_FLAG(F_CF); 5412197007Sdelphij CLEAR_FLAG(F_OF); 5413197007Sdelphij } 5414197007Sdelphij *destreg = (uint16_t) res; 5415197007Sdelphij} 5416197007Sdelphij 5417197007Sdelphijstatic void 5418197007Sdelphijx86emuOp2_imul_R_RM(struct x86emu *emu) 5419197007Sdelphij{ 5420197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5421197007Sdelphij x86emuOp2_32_imul_R_RM(emu); 5422197007Sdelphij else 5423197007Sdelphij x86emuOp2_16_imul_R_RM(emu); 5424197007Sdelphij} 5425197007Sdelphij 5426197007Sdelphij/* 5427197007Sdelphij * REMARKS: 5428197007Sdelphij * Handles opcode 0x0f,0xb2 5429197007Sdelphij */ 5430197007Sdelphijstatic void 5431197007Sdelphijx86emuOp2_lss_R_IMM(struct x86emu *emu) 5432197007Sdelphij{ 5433197007Sdelphij common_load_far_pointer(emu, &emu->x86.R_SS); 5434197007Sdelphij} 5435197007Sdelphij 5436197007Sdelphij/* 5437197007Sdelphij * REMARKS: 5438197007Sdelphij * Handles opcode 0x0f,0xb3 5439197007Sdelphij */ 5440197007Sdelphijstatic void 5441197007Sdelphijx86emuOp2_btr_R(struct x86emu *emu) 5442197007Sdelphij{ 5443197007Sdelphij common_bitstring(emu, 2); 5444197007Sdelphij} 5445197007Sdelphij 5446197007Sdelphij/* 5447197007Sdelphij * REMARKS: 5448197007Sdelphij * Handles opcode 0x0f,0xb4 5449197007Sdelphij */ 5450197007Sdelphijstatic void 5451197007Sdelphijx86emuOp2_lfs_R_IMM(struct x86emu *emu) 5452197007Sdelphij{ 5453197007Sdelphij common_load_far_pointer(emu, &emu->x86.R_FS); 5454197007Sdelphij} 5455197007Sdelphij 5456197007Sdelphij/* 5457197007Sdelphij * REMARKS: 5458197007Sdelphij * Handles opcode 0x0f,0xb5 5459197007Sdelphij */ 5460197007Sdelphijstatic void 5461197007Sdelphijx86emuOp2_lgs_R_IMM(struct x86emu *emu) 5462197007Sdelphij{ 5463197007Sdelphij common_load_far_pointer(emu, &emu->x86.R_GS); 5464197007Sdelphij} 5465197007Sdelphij 5466197007Sdelphij/* 5467197007Sdelphij * REMARKS: 5468197007Sdelphij * Handles opcode 0x0f,0xb6 5469197007Sdelphij */ 5470197007Sdelphijstatic void 5471197007Sdelphijx86emuOp2_32_movzx_byte_R_RM(struct x86emu *emu) 5472197007Sdelphij{ 5473197007Sdelphij uint32_t *destreg; 5474197007Sdelphij 5475197007Sdelphij fetch_decode_modrm(emu); 5476197007Sdelphij destreg = decode_rh_long_register(emu); 5477197007Sdelphij *destreg = decode_and_fetch_byte(emu); 5478197007Sdelphij} 5479197007Sdelphij 5480197007Sdelphijstatic void 5481197007Sdelphijx86emuOp2_16_movzx_byte_R_RM(struct x86emu *emu) 5482197007Sdelphij{ 5483197007Sdelphij uint16_t *destreg; 5484197007Sdelphij 5485197007Sdelphij fetch_decode_modrm(emu); 5486197007Sdelphij destreg = decode_rh_word_register(emu); 5487197007Sdelphij *destreg = decode_and_fetch_byte(emu); 5488197007Sdelphij} 5489197007Sdelphij 5490197007Sdelphijstatic void 5491197007Sdelphijx86emuOp2_movzx_byte_R_RM(struct x86emu *emu) 5492197007Sdelphij{ 5493197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5494197007Sdelphij x86emuOp2_32_movzx_byte_R_RM(emu); 5495197007Sdelphij else 5496197007Sdelphij x86emuOp2_16_movzx_byte_R_RM(emu); 5497197007Sdelphij} 5498197007Sdelphij 5499197007Sdelphij/* 5500197007Sdelphij * REMARKS: 5501197007Sdelphij * Handles opcode 0x0f,0xb7 5502197007Sdelphij */ 5503197007Sdelphijstatic void 5504197007Sdelphijx86emuOp2_movzx_word_R_RM(struct x86emu *emu) 5505197007Sdelphij{ 5506197007Sdelphij uint32_t *destreg; 5507197007Sdelphij 5508197007Sdelphij fetch_decode_modrm(emu); 5509197007Sdelphij destreg = decode_rh_long_register(emu); 5510197007Sdelphij *destreg = decode_and_fetch_word(emu); 5511197007Sdelphij} 5512197007Sdelphij 5513197007Sdelphij/* 5514197007Sdelphij * REMARKS: 5515197007Sdelphij * Handles opcode 0x0f,0xba 5516197007Sdelphij */ 5517197007Sdelphijstatic void 5518197007Sdelphijx86emuOp2_32_btX_I(struct x86emu *emu) 5519197007Sdelphij{ 5520197007Sdelphij int bit; 5521197007Sdelphij uint32_t srcval, mask; 5522197007Sdelphij uint8_t shift; 5523197007Sdelphij 5524197007Sdelphij fetch_decode_modrm(emu); 5525197007Sdelphij if (emu->cur_rh < 4) 5526197007Sdelphij x86emu_halt_sys(emu); 5527197007Sdelphij 5528197007Sdelphij srcval = decode_and_fetch_long_imm8(emu, &shift); 5529197007Sdelphij bit = shift & 0x1F; 5530197007Sdelphij mask = (0x1 << bit); 5531197007Sdelphij 5532197007Sdelphij switch (emu->cur_rh) { 5533197007Sdelphij case 5: 5534197007Sdelphij write_back_long(emu, srcval | mask); 5535197007Sdelphij break; 5536197007Sdelphij case 6: 5537197007Sdelphij write_back_long(emu, srcval & ~mask); 5538197007Sdelphij break; 5539197007Sdelphij case 7: 5540197007Sdelphij write_back_long(emu, srcval ^ mask); 5541197007Sdelphij break; 5542197007Sdelphij } 5543197007Sdelphij CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 5544197007Sdelphij} 5545197007Sdelphij 5546197007Sdelphijstatic void 5547197007Sdelphijx86emuOp2_16_btX_I(struct x86emu *emu) 5548197007Sdelphij{ 5549197007Sdelphij int bit; 5550197007Sdelphij 5551197007Sdelphij uint16_t srcval, mask; 5552197007Sdelphij uint8_t shift; 5553197007Sdelphij 5554197007Sdelphij fetch_decode_modrm(emu); 5555197007Sdelphij if (emu->cur_rh < 4) 5556197007Sdelphij x86emu_halt_sys(emu); 5557197007Sdelphij 5558197007Sdelphij srcval = decode_and_fetch_word_imm8(emu, &shift); 5559197007Sdelphij bit = shift & 0xF; 5560197007Sdelphij mask = (0x1 << bit); 5561197007Sdelphij switch (emu->cur_rh) { 5562197007Sdelphij case 5: 5563197007Sdelphij write_back_word(emu, srcval | mask); 5564197007Sdelphij break; 5565197007Sdelphij case 6: 5566197007Sdelphij write_back_word(emu, srcval & ~mask); 5567197007Sdelphij break; 5568197007Sdelphij case 7: 5569197007Sdelphij write_back_word(emu, srcval ^ mask); 5570197007Sdelphij break; 5571197007Sdelphij } 5572197007Sdelphij CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 5573197007Sdelphij} 5574197007Sdelphij 5575197007Sdelphijstatic void 5576197007Sdelphijx86emuOp2_btX_I(struct x86emu *emu) 5577197007Sdelphij{ 5578197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5579197007Sdelphij x86emuOp2_32_btX_I(emu); 5580197007Sdelphij else 5581197007Sdelphij x86emuOp2_16_btX_I(emu); 5582197007Sdelphij} 5583197007Sdelphij 5584197007Sdelphij/* 5585197007Sdelphij * REMARKS: 5586197007Sdelphij * Handles opcode 0x0f,0xbb 5587197007Sdelphij */ 5588197007Sdelphijstatic void 5589197007Sdelphijx86emuOp2_btc_R(struct x86emu *emu) 5590197007Sdelphij{ 5591197007Sdelphij common_bitstring(emu, 3); 5592197007Sdelphij} 5593197007Sdelphij 5594197007Sdelphij/* 5595197007Sdelphij * REMARKS: 5596197007Sdelphij * Handles opcode 0x0f,0xbc 5597197007Sdelphij */ 5598197007Sdelphijstatic void 5599197007Sdelphijx86emuOp2_bsf(struct x86emu *emu) 5600197007Sdelphij{ 5601197007Sdelphij common_bitsearch(emu, +1); 5602197007Sdelphij} 5603197007Sdelphij 5604197007Sdelphij/* 5605197007Sdelphij * REMARKS: 5606197007Sdelphij * Handles opcode 0x0f,0xbd 5607197007Sdelphij */ 5608197007Sdelphijstatic void 5609197007Sdelphijx86emuOp2_bsr(struct x86emu *emu) 5610197007Sdelphij{ 5611197007Sdelphij common_bitsearch(emu, -1); 5612197007Sdelphij} 5613197007Sdelphij 5614197007Sdelphij/* 5615197007Sdelphij * REMARKS: 5616197007Sdelphij * Handles opcode 0x0f,0xbe 5617197007Sdelphij */ 5618197007Sdelphijstatic void 5619197007Sdelphijx86emuOp2_32_movsx_byte_R_RM(struct x86emu *emu) 5620197007Sdelphij{ 5621197007Sdelphij uint32_t *destreg; 5622197007Sdelphij 5623268100Sdelphij fetch_decode_modrm(emu); 5624197007Sdelphij destreg = decode_rh_long_register(emu); 5625197007Sdelphij *destreg = (int32_t)(int8_t)decode_and_fetch_byte(emu); 5626197007Sdelphij} 5627197007Sdelphij 5628197007Sdelphijstatic void 5629197007Sdelphijx86emuOp2_16_movsx_byte_R_RM(struct x86emu *emu) 5630197007Sdelphij{ 5631197007Sdelphij uint16_t *destreg; 5632197007Sdelphij 5633197007Sdelphij fetch_decode_modrm(emu); 5634197007Sdelphij destreg = decode_rh_word_register(emu); 5635197007Sdelphij *destreg = (int16_t)(int8_t)decode_and_fetch_byte(emu); 5636197007Sdelphij} 5637197007Sdelphij 5638197007Sdelphijstatic void 5639197007Sdelphijx86emuOp2_movsx_byte_R_RM(struct x86emu *emu) 5640197007Sdelphij{ 5641197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5642197007Sdelphij x86emuOp2_32_movsx_byte_R_RM(emu); 5643197007Sdelphij else 5644197007Sdelphij x86emuOp2_16_movsx_byte_R_RM(emu); 5645197007Sdelphij} 5646197007Sdelphij 5647197007Sdelphij/* 5648197007Sdelphij * REMARKS: 5649197007Sdelphij * Handles opcode 0x0f,0xbf 5650197007Sdelphij */ 5651197007Sdelphijstatic void 5652197007Sdelphijx86emuOp2_movsx_word_R_RM(struct x86emu *emu) 5653197007Sdelphij{ 5654197007Sdelphij uint32_t *destreg; 5655197007Sdelphij 5656197007Sdelphij fetch_decode_modrm(emu); 5657197007Sdelphij destreg = decode_rh_long_register(emu); 5658197007Sdelphij *destreg = (int32_t)(int16_t)decode_and_fetch_word(emu); 5659197007Sdelphij} 5660197007Sdelphij 5661197007Sdelphijstatic void 5662197007Sdelphijx86emu_exec_two_byte(struct x86emu * emu) 5663197007Sdelphij{ 5664197007Sdelphij uint8_t op2; 5665197007Sdelphij 5666197007Sdelphij op2 = fetch_byte_imm(emu); 5667197007Sdelphij 5668197007Sdelphij switch (op2) { 5669197007Sdelphij /* 0x00 Group F (ring 0 PM) */ 5670197007Sdelphij /* 0x01 Group G (ring 0 PM) */ 5671197007Sdelphij /* 0x02 lar (ring 0 PM) */ 5672197007Sdelphij /* 0x03 lsl (ring 0 PM) */ 5673197007Sdelphij /* 0x05 loadall (undocumented) */ 5674197007Sdelphij /* 0x06 clts (ring 0 PM) */ 5675197007Sdelphij /* 0x07 loadall (undocumented) */ 5676197007Sdelphij /* 0x08 invd (ring 0 PM) */ 5677197007Sdelphij /* 0x09 wbinvd (ring 0 PM) */ 5678197007Sdelphij 5679197007Sdelphij /* 0x20 mov reg32(op2); break;creg (ring 0 PM) */ 5680197007Sdelphij /* 0x21 mov reg32(op2); break;dreg (ring 0 PM) */ 5681197007Sdelphij /* 0x22 mov creg(op2); break;reg32 (ring 0 PM) */ 5682197007Sdelphij /* 0x23 mov dreg(op2); break;reg32 (ring 0 PM) */ 5683197007Sdelphij /* 0x24 mov reg32(op2); break;treg (ring 0 PM) */ 5684197007Sdelphij /* 0x26 mov treg(op2); break;reg32 (ring 0 PM) */ 5685197007Sdelphij 5686197007Sdelphij case 0x31: 5687197007Sdelphij x86emuOp2_rdtsc(emu); 5688197007Sdelphij break; 5689197007Sdelphij 5690197007Sdelphij case 0x80: 5691197007Sdelphij common_jmp_long(emu, ACCESS_FLAG(F_OF)); 5692197007Sdelphij break; 5693197007Sdelphij case 0x81: 5694197007Sdelphij common_jmp_long(emu, !ACCESS_FLAG(F_OF)); 5695197007Sdelphij break; 5696197007Sdelphij case 0x82: 5697197007Sdelphij common_jmp_long(emu, ACCESS_FLAG(F_CF)); 5698197007Sdelphij break; 5699197007Sdelphij case 0x83: 5700197007Sdelphij common_jmp_long(emu, !ACCESS_FLAG(F_CF)); 5701197007Sdelphij break; 5702197007Sdelphij case 0x84: 5703197007Sdelphij common_jmp_long(emu, ACCESS_FLAG(F_ZF)); 5704197007Sdelphij break; 5705197007Sdelphij case 0x85: 5706197007Sdelphij common_jmp_long(emu, !ACCESS_FLAG(F_ZF)); 5707197007Sdelphij break; 5708197007Sdelphij case 0x86: 5709197007Sdelphij common_jmp_long(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); 5710197007Sdelphij break; 5711197007Sdelphij case 0x87: 5712197007Sdelphij common_jmp_long(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))); 5713197007Sdelphij break; 5714197007Sdelphij case 0x88: 5715197007Sdelphij common_jmp_long(emu, ACCESS_FLAG(F_SF)); 5716197007Sdelphij break; 5717197007Sdelphij case 0x89: 5718197007Sdelphij common_jmp_long(emu, !ACCESS_FLAG(F_SF)); 5719197007Sdelphij break; 5720197007Sdelphij case 0x8a: 5721197007Sdelphij common_jmp_long(emu, ACCESS_FLAG(F_PF)); 5722197007Sdelphij break; 5723197007Sdelphij case 0x8b: 5724197007Sdelphij common_jmp_long(emu, !ACCESS_FLAG(F_PF)); 5725197007Sdelphij break; 5726197007Sdelphij case 0x8c: 5727204934Sdelphij common_jmp_long(emu, xorl(ACCESS_FLAG(F_SF), 5728204934Sdelphij ACCESS_FLAG(F_OF))); 5729197007Sdelphij break; 5730197007Sdelphij case 0x8d: 5731204934Sdelphij common_jmp_long(emu, !(xorl(ACCESS_FLAG(F_SF), 5732204934Sdelphij ACCESS_FLAG(F_OF)))); 5733197007Sdelphij break; 5734197007Sdelphij case 0x8e: 5735204934Sdelphij common_jmp_long(emu, (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) 5736204934Sdelphij || ACCESS_FLAG(F_ZF))); 5737197007Sdelphij break; 5738197007Sdelphij case 0x8f: 5739204934Sdelphij common_jmp_long(emu, 5740204934Sdelphij !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || 5741204934Sdelphij ACCESS_FLAG(F_ZF))); 5742197007Sdelphij break; 5743197007Sdelphij 5744197007Sdelphij case 0x90: 5745197007Sdelphij common_set_byte(emu, ACCESS_FLAG(F_OF)); 5746197007Sdelphij break; 5747197007Sdelphij case 0x91: 5748197007Sdelphij common_set_byte(emu, !ACCESS_FLAG(F_OF)); 5749197007Sdelphij break; 5750197007Sdelphij case 0x92: 5751197007Sdelphij common_set_byte(emu, ACCESS_FLAG(F_CF)); 5752197007Sdelphij break; 5753197007Sdelphij case 0x93: 5754197007Sdelphij common_set_byte(emu, !ACCESS_FLAG(F_CF)); 5755197007Sdelphij break; 5756197007Sdelphij case 0x94: 5757197007Sdelphij common_set_byte(emu, ACCESS_FLAG(F_ZF)); 5758197007Sdelphij break; 5759197007Sdelphij case 0x95: 5760197007Sdelphij common_set_byte(emu, !ACCESS_FLAG(F_ZF)); 5761197007Sdelphij break; 5762197007Sdelphij case 0x96: 5763197007Sdelphij common_set_byte(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); 5764197007Sdelphij break; 5765197007Sdelphij case 0x97: 5766197007Sdelphij common_set_byte(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))); 5767197007Sdelphij break; 5768197007Sdelphij case 0x98: 5769197007Sdelphij common_set_byte(emu, ACCESS_FLAG(F_SF)); 5770197007Sdelphij break; 5771197007Sdelphij case 0x99: 5772197007Sdelphij common_set_byte(emu, !ACCESS_FLAG(F_SF)); 5773197007Sdelphij break; 5774197007Sdelphij case 0x9a: 5775197007Sdelphij common_set_byte(emu, ACCESS_FLAG(F_PF)); 5776197007Sdelphij break; 5777197007Sdelphij case 0x9b: 5778197007Sdelphij common_set_byte(emu, !ACCESS_FLAG(F_PF)); 5779197007Sdelphij break; 5780197007Sdelphij case 0x9c: 5781204934Sdelphij common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), 5782204934Sdelphij ACCESS_FLAG(F_OF))); 5783197007Sdelphij break; 5784197007Sdelphij case 0x9d: 5785204934Sdelphij common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), 5786204934Sdelphij ACCESS_FLAG(F_OF))); 5787197007Sdelphij break; 5788197007Sdelphij case 0x9e: 5789197007Sdelphij common_set_byte(emu, 5790197007Sdelphij (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || 5791197007Sdelphij ACCESS_FLAG(F_ZF))); 5792197007Sdelphij break; 5793197007Sdelphij case 0x9f: 5794197007Sdelphij common_set_byte(emu, 5795197007Sdelphij !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || 5796197007Sdelphij ACCESS_FLAG(F_ZF))); 5797197007Sdelphij break; 5798197007Sdelphij 5799197007Sdelphij case 0xa0: 5800197007Sdelphij x86emuOp2_push_FS(emu); 5801197007Sdelphij break; 5802197007Sdelphij case 0xa1: 5803197007Sdelphij x86emuOp2_pop_FS(emu); 5804197007Sdelphij break; 5805197007Sdelphij case 0xa2: 5806197007Sdelphij x86emuOp2_cpuid(emu); 5807197007Sdelphij break; 5808197007Sdelphij case 0xa3: 5809197007Sdelphij x86emuOp2_bt_R(emu); 5810197007Sdelphij break; 5811197007Sdelphij case 0xa4: 5812197007Sdelphij x86emuOp2_shld_IMM(emu); 5813197007Sdelphij break; 5814197007Sdelphij case 0xa5: 5815197007Sdelphij x86emuOp2_shld_CL(emu); 5816197007Sdelphij break; 5817197007Sdelphij case 0xa8: 5818197007Sdelphij x86emuOp2_push_GS(emu); 5819197007Sdelphij break; 5820197007Sdelphij case 0xa9: 5821197007Sdelphij x86emuOp2_pop_GS(emu); 5822197007Sdelphij break; 5823197007Sdelphij case 0xab: 5824197007Sdelphij x86emuOp2_bts_R(emu); 5825197007Sdelphij break; 5826197007Sdelphij case 0xac: 5827197007Sdelphij x86emuOp2_shrd_IMM(emu); 5828197007Sdelphij break; 5829197007Sdelphij case 0xad: 5830197007Sdelphij x86emuOp2_shrd_CL(emu); 5831197007Sdelphij break; 5832197007Sdelphij case 0xaf: 5833197007Sdelphij x86emuOp2_imul_R_RM(emu); 5834197007Sdelphij break; 5835197007Sdelphij 5836197007Sdelphij /* 0xb0 TODO: cmpxchg */ 5837197007Sdelphij /* 0xb1 TODO: cmpxchg */ 5838197007Sdelphij case 0xb2: 5839197007Sdelphij x86emuOp2_lss_R_IMM(emu); 5840197007Sdelphij break; 5841197007Sdelphij case 0xb3: 5842197007Sdelphij x86emuOp2_btr_R(emu); 5843197007Sdelphij break; 5844197007Sdelphij case 0xb4: 5845197007Sdelphij x86emuOp2_lfs_R_IMM(emu); 5846197007Sdelphij break; 5847197007Sdelphij case 0xb5: 5848197007Sdelphij x86emuOp2_lgs_R_IMM(emu); 5849197007Sdelphij break; 5850197007Sdelphij case 0xb6: 5851197007Sdelphij x86emuOp2_movzx_byte_R_RM(emu); 5852197007Sdelphij break; 5853197007Sdelphij case 0xb7: 5854197007Sdelphij x86emuOp2_movzx_word_R_RM(emu); 5855197007Sdelphij break; 5856197007Sdelphij case 0xba: 5857197007Sdelphij x86emuOp2_btX_I(emu); 5858197007Sdelphij break; 5859197007Sdelphij case 0xbb: 5860197007Sdelphij x86emuOp2_btc_R(emu); 5861197007Sdelphij break; 5862197007Sdelphij case 0xbc: 5863197007Sdelphij x86emuOp2_bsf(emu); 5864197007Sdelphij break; 5865197007Sdelphij case 0xbd: 5866197007Sdelphij x86emuOp2_bsr(emu); 5867197007Sdelphij break; 5868197007Sdelphij case 0xbe: 5869197007Sdelphij x86emuOp2_movsx_byte_R_RM(emu); 5870197007Sdelphij break; 5871197007Sdelphij case 0xbf: 5872197007Sdelphij x86emuOp2_movsx_word_R_RM(emu); 5873197007Sdelphij break; 5874197007Sdelphij 5875197007Sdelphij /* 0xc0 TODO: xadd */ 5876197007Sdelphij /* 0xc1 TODO: xadd */ 5877197007Sdelphij /* 0xc8 TODO: bswap */ 5878197007Sdelphij /* 0xc9 TODO: bswap */ 5879197007Sdelphij /* 0xca TODO: bswap */ 5880197007Sdelphij /* 0xcb TODO: bswap */ 5881197007Sdelphij /* 0xcc TODO: bswap */ 5882197007Sdelphij /* 0xcd TODO: bswap */ 5883197007Sdelphij /* 0xce TODO: bswap */ 5884197007Sdelphij /* 0xcf TODO: bswap */ 5885197007Sdelphij 5886197007Sdelphij default: 5887197007Sdelphij x86emu_halt_sys(emu); 5888197007Sdelphij break; 5889197007Sdelphij } 5890197007Sdelphij} 5891197007Sdelphij 5892197007Sdelphij/* 5893204934Sdelphij * Carry Chain Calculation 5894204934Sdelphij * 5895204934Sdelphij * This represents a somewhat expensive calculation which is 5896204934Sdelphij * apparently required to emulate the setting of the OF and AF flag. 5897204934Sdelphij * The latter is not so important, but the former is. The overflow 5898204934Sdelphij * flag is the XOR of the top two bits of the carry chain for an 5899204934Sdelphij * addition (similar for subtraction). Since we do not want to 5900204934Sdelphij * simulate the addition in a bitwise manner, we try to calculate the 5901204934Sdelphij * carry chain given the two operands and the result. 5902204934Sdelphij * 5903204934Sdelphij * So, given the following table, which represents the addition of two 5904204934Sdelphij * bits, we can derive a formula for the carry chain. 5905204934Sdelphij * 5906204934Sdelphij * a b cin r cout 5907204934Sdelphij * 0 0 0 0 0 5908204934Sdelphij * 0 0 1 1 0 5909204934Sdelphij * 0 1 0 1 0 5910204934Sdelphij * 0 1 1 0 1 5911204934Sdelphij * 1 0 0 1 0 5912204934Sdelphij * 1 0 1 0 1 5913204934Sdelphij * 1 1 0 0 1 5914204934Sdelphij * 1 1 1 1 1 5915204934Sdelphij * 5916204934Sdelphij * Construction of table for cout: 5917204934Sdelphij * 5918204934Sdelphij * ab 5919204934Sdelphij * r \ 00 01 11 10 5920204934Sdelphij * |------------------ 5921204934Sdelphij * 0 | 0 1 1 1 5922204934Sdelphij * 1 | 0 0 1 0 5923204934Sdelphij * 5924204934Sdelphij * By inspection, one gets: cc = ab + r'(a + b) 5925204934Sdelphij * 5926204934Sdelphij * That represents alot of operations, but NO CHOICE.... 5927204934Sdelphij * 5928204934Sdelphij * Borrow Chain Calculation. 5929204934Sdelphij * 5930204934Sdelphij * The following table represents the subtraction of two bits, from 5931204934Sdelphij * which we can derive a formula for the borrow chain. 5932204934Sdelphij * 5933204934Sdelphij * a b bin r bout 5934204934Sdelphij * 0 0 0 0 0 5935204934Sdelphij * 0 0 1 1 1 5936204934Sdelphij * 0 1 0 1 1 5937204934Sdelphij * 0 1 1 0 1 5938204934Sdelphij * 1 0 0 1 0 5939204934Sdelphij * 1 0 1 0 0 5940204934Sdelphij * 1 1 0 0 0 5941204934Sdelphij * 1 1 1 1 1 5942204934Sdelphij * 5943204934Sdelphij * Construction of table for cout: 5944204934Sdelphij * 5945204934Sdelphij * ab 5946204934Sdelphij * r \ 00 01 11 10 5947204934Sdelphij * |------------------ 5948204934Sdelphij * 0 | 0 1 0 0 5949204934Sdelphij * 1 | 1 1 1 0 5950204934Sdelphij * 5951204934Sdelphij * By inspection, one gets: bc = a'b + r(a' + b) 5952204934Sdelphij * 5953197007Sdelphij */ 5954197007Sdelphij 5955204934Sdelphij/* 5956204934Sdelphij * Global Variables 5957204934Sdelphij */ 5958197007Sdelphij 5959197007Sdelphijstatic uint32_t x86emu_parity_tab[8] = 5960197007Sdelphij{ 5961197007Sdelphij 0x96696996, 5962197007Sdelphij 0x69969669, 5963197007Sdelphij 0x69969669, 5964197007Sdelphij 0x96696996, 5965197007Sdelphij 0x69969669, 5966197007Sdelphij 0x96696996, 5967197007Sdelphij 0x96696996, 5968197007Sdelphij 0x69969669, 5969197007Sdelphij}; 5970197007Sdelphij#define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0) 5971197007Sdelphij#define XOR2(x) (((x) ^ ((x)>>1)) & 0x1) 5972197007Sdelphij 5973197007Sdelphij 5974197007Sdelphij/* 5975197007Sdelphij * REMARKS: 5976197007Sdelphij * Implements the AAA instruction and side effects. 5977197007Sdelphij */ 5978197007Sdelphijstatic uint16_t 5979197007Sdelphijaaa_word(struct x86emu *emu, uint16_t d) 5980197007Sdelphij{ 5981197007Sdelphij uint16_t res; 5982197007Sdelphij if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { 5983197007Sdelphij d += 0x6; 5984197007Sdelphij d += 0x100; 5985197007Sdelphij SET_FLAG(F_AF); 5986197007Sdelphij SET_FLAG(F_CF); 5987197007Sdelphij } else { 5988197007Sdelphij CLEAR_FLAG(F_CF); 5989197007Sdelphij CLEAR_FLAG(F_AF); 5990197007Sdelphij } 5991197007Sdelphij res = (uint16_t) (d & 0xFF0F); 5992197007Sdelphij CLEAR_FLAG(F_SF); 5993197007Sdelphij CONDITIONAL_SET_FLAG(res == 0, F_ZF); 5994197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5995197007Sdelphij return res; 5996197007Sdelphij} 5997197007Sdelphij 5998197007Sdelphij/* 5999197007Sdelphij * REMARKS: 6000197007Sdelphij * Implements the AAA instruction and side effects. 6001197007Sdelphij */ 6002197007Sdelphijstatic uint16_t 6003197007Sdelphijaas_word(struct x86emu *emu, uint16_t d) 6004197007Sdelphij{ 6005197007Sdelphij uint16_t res; 6006197007Sdelphij if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { 6007197007Sdelphij d -= 0x6; 6008197007Sdelphij d -= 0x100; 6009197007Sdelphij SET_FLAG(F_AF); 6010197007Sdelphij SET_FLAG(F_CF); 6011197007Sdelphij } else { 6012197007Sdelphij CLEAR_FLAG(F_CF); 6013197007Sdelphij CLEAR_FLAG(F_AF); 6014197007Sdelphij } 6015197007Sdelphij res = (uint16_t) (d & 0xFF0F); 6016197007Sdelphij CLEAR_FLAG(F_SF); 6017197007Sdelphij CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6018197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6019197007Sdelphij return res; 6020197007Sdelphij} 6021197007Sdelphij 6022197007Sdelphij/* 6023197007Sdelphij * REMARKS: 6024197007Sdelphij * Implements the AAD instruction and side effects. 6025197007Sdelphij */ 6026197007Sdelphijstatic uint16_t 6027197007Sdelphijaad_word(struct x86emu *emu, uint16_t d) 6028197007Sdelphij{ 6029197007Sdelphij uint16_t l; 6030197007Sdelphij uint8_t hb, lb; 6031197007Sdelphij 6032197007Sdelphij hb = (uint8_t) ((d >> 8) & 0xff); 6033197007Sdelphij lb = (uint8_t) ((d & 0xff)); 6034197007Sdelphij l = (uint16_t) ((lb + 10 * hb) & 0xFF); 6035197007Sdelphij 6036197007Sdelphij CLEAR_FLAG(F_CF); 6037197007Sdelphij CLEAR_FLAG(F_AF); 6038197007Sdelphij CLEAR_FLAG(F_OF); 6039197007Sdelphij CONDITIONAL_SET_FLAG(l & 0x80, F_SF); 6040197007Sdelphij CONDITIONAL_SET_FLAG(l == 0, F_ZF); 6041197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF); 6042197007Sdelphij return l; 6043197007Sdelphij} 6044197007Sdelphij 6045197007Sdelphij/* 6046197007Sdelphij * REMARKS: 6047197007Sdelphij * Implements the AAM instruction and side effects. 6048197007Sdelphij */ 6049197007Sdelphijstatic uint16_t 6050197007Sdelphijaam_word(struct x86emu *emu, uint8_t d) 6051197007Sdelphij{ 6052197007Sdelphij uint16_t h, l; 6053197007Sdelphij 6054197007Sdelphij h = (uint16_t) (d / 10); 6055197007Sdelphij l = (uint16_t) (d % 10); 6056197007Sdelphij l |= (uint16_t) (h << 8); 6057197007Sdelphij 6058197007Sdelphij CLEAR_FLAG(F_CF); 6059197007Sdelphij CLEAR_FLAG(F_AF); 6060197007Sdelphij CLEAR_FLAG(F_OF); 6061197007Sdelphij CONDITIONAL_SET_FLAG(l & 0x80, F_SF); 6062197007Sdelphij CONDITIONAL_SET_FLAG(l == 0, F_ZF); 6063197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF); 6064197007Sdelphij return l; 6065197007Sdelphij} 6066197007Sdelphij 6067197007Sdelphij/* 6068197007Sdelphij * REMARKS: 6069197007Sdelphij * Implements the ADC instruction and side effects. 6070197007Sdelphij */ 6071197007Sdelphijstatic uint8_t 6072197007Sdelphijadc_byte(struct x86emu *emu, uint8_t d, uint8_t s) 6073197007Sdelphij{ 6074197007Sdelphij uint32_t res; /* all operands in native machine order */ 6075197007Sdelphij uint32_t cc; 6076197007Sdelphij 6077197007Sdelphij if (ACCESS_FLAG(F_CF)) 6078197007Sdelphij res = 1 + d + s; 6079197007Sdelphij else 6080197007Sdelphij res = d + s; 6081197007Sdelphij 6082197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x100, F_CF); 6083197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6084197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6085197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6086197007Sdelphij 6087197007Sdelphij /* calculate the carry chain SEE NOTE AT TOP. */ 6088197007Sdelphij cc = (s & d) | ((~res) & (s | d)); 6089197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 6090197007Sdelphij CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6091197007Sdelphij return (uint8_t) res; 6092197007Sdelphij} 6093197007Sdelphij 6094197007Sdelphij/* 6095197007Sdelphij * REMARKS: 6096197007Sdelphij * Implements the ADC instruction and side effects. 6097197007Sdelphij */ 6098197007Sdelphijstatic uint16_t 6099197007Sdelphijadc_word(struct x86emu *emu, uint16_t d, uint16_t s) 6100197007Sdelphij{ 6101197007Sdelphij uint32_t res; /* all operands in native machine order */ 6102197007Sdelphij uint32_t cc; 6103197007Sdelphij 6104197007Sdelphij if (ACCESS_FLAG(F_CF)) 6105197007Sdelphij res = 1 + d + s; 6106197007Sdelphij else 6107197007Sdelphij res = d + s; 6108197007Sdelphij 6109197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x10000, F_CF); 6110197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6111197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6112197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6113197007Sdelphij 6114197007Sdelphij /* calculate the carry chain SEE NOTE AT TOP. */ 6115197007Sdelphij cc = (s & d) | ((~res) & (s | d)); 6116197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 6117197007Sdelphij CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6118197007Sdelphij return (uint16_t) res; 6119197007Sdelphij} 6120197007Sdelphij 6121197007Sdelphij/* 6122197007Sdelphij * REMARKS: 6123197007Sdelphij * Implements the ADC instruction and side effects. 6124197007Sdelphij */ 6125197007Sdelphijstatic uint32_t 6126197007Sdelphijadc_long(struct x86emu *emu, uint32_t d, uint32_t s) 6127197007Sdelphij{ 6128197007Sdelphij uint32_t lo; /* all operands in native machine order */ 6129197007Sdelphij uint32_t hi; 6130197007Sdelphij uint32_t res; 6131197007Sdelphij uint32_t cc; 6132197007Sdelphij 6133197007Sdelphij if (ACCESS_FLAG(F_CF)) { 6134197007Sdelphij lo = 1 + (d & 0xFFFF) + (s & 0xFFFF); 6135197007Sdelphij res = 1 + d + s; 6136197007Sdelphij } else { 6137197007Sdelphij lo = (d & 0xFFFF) + (s & 0xFFFF); 6138197007Sdelphij res = d + s; 6139197007Sdelphij } 6140197007Sdelphij hi = (lo >> 16) + (d >> 16) + (s >> 16); 6141197007Sdelphij 6142197007Sdelphij CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF); 6143197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6144197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6145197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6146197007Sdelphij 6147197007Sdelphij /* calculate the carry chain SEE NOTE AT TOP. */ 6148197007Sdelphij cc = (s & d) | ((~res) & (s | d)); 6149197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 6150197007Sdelphij CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6151197007Sdelphij return res; 6152197007Sdelphij} 6153197007Sdelphij 6154197007Sdelphij/* 6155197007Sdelphij * REMARKS: 6156197007Sdelphij * Implements the ADD instruction and side effects. 6157197007Sdelphij */ 6158197007Sdelphijstatic uint8_t 6159197007Sdelphijadd_byte(struct x86emu *emu, uint8_t d, uint8_t s) 6160197007Sdelphij{ 6161197007Sdelphij uint32_t res; /* all operands in native machine order */ 6162197007Sdelphij uint32_t cc; 6163197007Sdelphij 6164197007Sdelphij res = d + s; 6165197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x100, F_CF); 6166197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6167197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6168197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6169197007Sdelphij 6170197007Sdelphij /* calculate the carry chain SEE NOTE AT TOP. */ 6171197007Sdelphij cc = (s & d) | ((~res) & (s | d)); 6172197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 6173197007Sdelphij CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6174197007Sdelphij return (uint8_t) res; 6175197007Sdelphij} 6176197007Sdelphij 6177197007Sdelphij/* 6178197007Sdelphij * REMARKS: 6179197007Sdelphij * Implements the ADD instruction and side effects. 6180197007Sdelphij */ 6181197007Sdelphijstatic uint16_t 6182197007Sdelphijadd_word(struct x86emu *emu, uint16_t d, uint16_t s) 6183197007Sdelphij{ 6184197007Sdelphij uint32_t res; /* all operands in native machine order */ 6185197007Sdelphij uint32_t cc; 6186197007Sdelphij 6187197007Sdelphij res = d + s; 6188197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x10000, F_CF); 6189197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6190197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6191197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6192197007Sdelphij 6193197007Sdelphij /* calculate the carry chain SEE NOTE AT TOP. */ 6194197007Sdelphij cc = (s & d) | ((~res) & (s | d)); 6195197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 6196197007Sdelphij CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6197197007Sdelphij return (uint16_t) res; 6198197007Sdelphij} 6199197007Sdelphij 6200197007Sdelphij/* 6201197007Sdelphij * REMARKS: 6202197007Sdelphij * Implements the ADD instruction and side effects. 6203197007Sdelphij */ 6204197007Sdelphijstatic uint32_t 6205197007Sdelphijadd_long(struct x86emu *emu, uint32_t d, uint32_t s) 6206197007Sdelphij{ 6207197007Sdelphij uint32_t lo; /* all operands in native machine order */ 6208197007Sdelphij uint32_t hi; 6209197007Sdelphij uint32_t res; 6210197007Sdelphij uint32_t cc; 6211197007Sdelphij 6212197007Sdelphij lo = (d & 0xFFFF) + (s & 0xFFFF); 6213197007Sdelphij res = d + s; 6214197007Sdelphij hi = (lo >> 16) + (d >> 16) + (s >> 16); 6215197007Sdelphij 6216197007Sdelphij CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF); 6217197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6218197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6219197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6220197007Sdelphij 6221197007Sdelphij /* calculate the carry chain SEE NOTE AT TOP. */ 6222197007Sdelphij cc = (s & d) | ((~res) & (s | d)); 6223197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 6224197007Sdelphij CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6225197007Sdelphij 6226197007Sdelphij return res; 6227197007Sdelphij} 6228197007Sdelphij 6229197007Sdelphij/* 6230197007Sdelphij * REMARKS: 6231197007Sdelphij * Implements the AND instruction and side effects. 6232197007Sdelphij */ 6233197007Sdelphijstatic uint8_t 6234197007Sdelphijand_byte(struct x86emu *emu, uint8_t d, uint8_t s) 6235197007Sdelphij{ 6236197007Sdelphij uint8_t res; /* all operands in native machine order */ 6237197007Sdelphij 6238197007Sdelphij res = d & s; 6239197007Sdelphij 6240197007Sdelphij /* set the flags */ 6241197007Sdelphij CLEAR_FLAG(F_OF); 6242197007Sdelphij CLEAR_FLAG(F_CF); 6243197007Sdelphij CLEAR_FLAG(F_AF); 6244197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6245197007Sdelphij CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6246197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 6247197007Sdelphij return res; 6248197007Sdelphij} 6249197007Sdelphij 6250197007Sdelphij/* 6251197007Sdelphij * REMARKS: 6252197007Sdelphij * Implements the AND instruction and side effects. 6253197007Sdelphij */ 6254197007Sdelphijstatic uint16_t 6255197007Sdelphijand_word(struct x86emu *emu, uint16_t d, uint16_t s) 6256197007Sdelphij{ 6257197007Sdelphij uint16_t res; /* all operands in native machine order */ 6258197007Sdelphij 6259197007Sdelphij res = d & s; 6260197007Sdelphij 6261197007Sdelphij /* set the flags */ 6262197007Sdelphij CLEAR_FLAG(F_OF); 6263197007Sdelphij CLEAR_FLAG(F_CF); 6264197007Sdelphij CLEAR_FLAG(F_AF); 6265197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6266197007Sdelphij CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6267197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6268197007Sdelphij return res; 6269197007Sdelphij} 6270197007Sdelphij 6271197007Sdelphij/* 6272197007Sdelphij * REMARKS: 6273197007Sdelphij * Implements the AND instruction and side effects. 6274197007Sdelphij */ 6275197007Sdelphijstatic uint32_t 6276197007Sdelphijand_long(struct x86emu *emu, uint32_t d, uint32_t s) 6277197007Sdelphij{ 6278197007Sdelphij uint32_t res; /* all operands in native machine order */ 6279197007Sdelphij 6280197007Sdelphij res = d & s; 6281197007Sdelphij 6282197007Sdelphij /* set the flags */ 6283197007Sdelphij CLEAR_FLAG(F_OF); 6284197007Sdelphij CLEAR_FLAG(F_CF); 6285197007Sdelphij CLEAR_FLAG(F_AF); 6286197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6287197007Sdelphij CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6288197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6289197007Sdelphij return res; 6290197007Sdelphij} 6291197007Sdelphij 6292197007Sdelphij/* 6293197007Sdelphij * REMARKS: 6294197007Sdelphij * Implements the CMP instruction and side effects. 6295197007Sdelphij */ 6296197007Sdelphijstatic uint8_t 6297197007Sdelphijcmp_byte(struct x86emu *emu, uint8_t d, uint8_t s) 6298197007Sdelphij{ 6299197007Sdelphij uint32_t res; /* all operands in native machine order */ 6300197007Sdelphij uint32_t bc; 6301197007Sdelphij 6302197007Sdelphij res = d - s; 6303197007Sdelphij CLEAR_FLAG(F_CF); 6304197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6305197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6306197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6307197007Sdelphij 6308197007Sdelphij /* calculate the borrow chain. See note at top */ 6309197007Sdelphij bc = (res & (~d | s)) | (~d & s); 6310197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); 6311197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 6312197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6313197007Sdelphij return d; 6314197007Sdelphij} 6315197007Sdelphij 6316197007Sdelphijstatic void 6317197007Sdelphijcmp_byte_no_return(struct x86emu *emu, uint8_t d, uint8_t s) 6318197007Sdelphij{ 6319197007Sdelphij cmp_byte(emu, d, s); 6320197007Sdelphij} 6321197007Sdelphij 6322197007Sdelphij/* 6323197007Sdelphij * REMARKS: 6324197007Sdelphij * Implements the CMP instruction and side effects. 6325197007Sdelphij */ 6326197007Sdelphijstatic uint16_t 6327197007Sdelphijcmp_word(struct x86emu *emu, uint16_t d, uint16_t s) 6328197007Sdelphij{ 6329197007Sdelphij uint32_t res; /* all operands in native machine order */ 6330197007Sdelphij uint32_t bc; 6331197007Sdelphij 6332197007Sdelphij res = d - s; 6333197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6334197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6335197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6336197007Sdelphij 6337197007Sdelphij /* calculate the borrow chain. See note at top */ 6338197007Sdelphij bc = (res & (~d | s)) | (~d & s); 6339197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 6340197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 6341197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6342197007Sdelphij return d; 6343197007Sdelphij} 6344197007Sdelphij 6345197007Sdelphijstatic void 6346197007Sdelphijcmp_word_no_return(struct x86emu *emu, uint16_t d, uint16_t s) 6347197007Sdelphij{ 6348197007Sdelphij cmp_word(emu, d, s); 6349197007Sdelphij} 6350197007Sdelphij 6351197007Sdelphij/* 6352197007Sdelphij * REMARKS: 6353197007Sdelphij * Implements the CMP instruction and side effects. 6354197007Sdelphij */ 6355197007Sdelphijstatic uint32_t 6356197007Sdelphijcmp_long(struct x86emu *emu, uint32_t d, uint32_t s) 6357197007Sdelphij{ 6358197007Sdelphij uint32_t res; /* all operands in native machine order */ 6359197007Sdelphij uint32_t bc; 6360197007Sdelphij 6361197007Sdelphij res = d - s; 6362197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6363197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6364197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6365197007Sdelphij 6366197007Sdelphij /* calculate the borrow chain. See note at top */ 6367197007Sdelphij bc = (res & (~d | s)) | (~d & s); 6368197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 6369197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 6370197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6371197007Sdelphij return d; 6372197007Sdelphij} 6373197007Sdelphij 6374197007Sdelphijstatic void 6375197007Sdelphijcmp_long_no_return(struct x86emu *emu, uint32_t d, uint32_t s) 6376197007Sdelphij{ 6377197007Sdelphij cmp_long(emu, d, s); 6378197007Sdelphij} 6379197007Sdelphij 6380197007Sdelphij/* 6381197007Sdelphij * REMARKS: 6382197007Sdelphij * Implements the DAA instruction and side effects. 6383197007Sdelphij */ 6384197007Sdelphijstatic uint8_t 6385197007Sdelphijdaa_byte(struct x86emu *emu, uint8_t d) 6386197007Sdelphij{ 6387197007Sdelphij uint32_t res = d; 6388197007Sdelphij if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) { 6389197007Sdelphij res += 6; 6390197007Sdelphij SET_FLAG(F_AF); 6391197007Sdelphij } 6392197007Sdelphij if (res > 0x9F || ACCESS_FLAG(F_CF)) { 6393197007Sdelphij res += 0x60; 6394197007Sdelphij SET_FLAG(F_CF); 6395197007Sdelphij } 6396197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6397197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF); 6398197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6399197007Sdelphij return (uint8_t) res; 6400197007Sdelphij} 6401197007Sdelphij 6402197007Sdelphij/* 6403197007Sdelphij * REMARKS: 6404197007Sdelphij * Implements the DAS instruction and side effects. 6405197007Sdelphij */ 6406197007Sdelphijstatic uint8_t 6407197007Sdelphijdas_byte(struct x86emu *emu, uint8_t d) 6408197007Sdelphij{ 6409197007Sdelphij if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) { 6410197007Sdelphij d -= 6; 6411197007Sdelphij SET_FLAG(F_AF); 6412197007Sdelphij } 6413197007Sdelphij if (d > 0x9F || ACCESS_FLAG(F_CF)) { 6414197007Sdelphij d -= 0x60; 6415197007Sdelphij SET_FLAG(F_CF); 6416197007Sdelphij } 6417197007Sdelphij CONDITIONAL_SET_FLAG(d & 0x80, F_SF); 6418197007Sdelphij CONDITIONAL_SET_FLAG(d == 0, F_ZF); 6419197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF); 6420197007Sdelphij return d; 6421197007Sdelphij} 6422197007Sdelphij 6423197007Sdelphij/* 6424197007Sdelphij * REMARKS: 6425197007Sdelphij * Implements the DEC instruction and side effects. 6426197007Sdelphij */ 6427197007Sdelphijstatic uint8_t 6428197007Sdelphijdec_byte(struct x86emu *emu, uint8_t d) 6429197007Sdelphij{ 6430197007Sdelphij uint32_t res; /* all operands in native machine order */ 6431197007Sdelphij uint32_t bc; 6432197007Sdelphij 6433197007Sdelphij res = d - 1; 6434197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6435197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6436197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6437197007Sdelphij 6438197007Sdelphij /* calculate the borrow chain. See note at top */ 6439197007Sdelphij /* based on sub_byte, uses s==1. */ 6440197007Sdelphij bc = (res & (~d | 1)) | (~d & 1); 6441197007Sdelphij /* carry flag unchanged */ 6442197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 6443197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6444197007Sdelphij return (uint8_t) res; 6445197007Sdelphij} 6446197007Sdelphij 6447197007Sdelphij/* 6448197007Sdelphij * REMARKS: 6449197007Sdelphij * Implements the DEC instruction and side effects. 6450197007Sdelphij */ 6451197007Sdelphijstatic uint16_t 6452197007Sdelphijdec_word(struct x86emu *emu, uint16_t d) 6453197007Sdelphij{ 6454197007Sdelphij uint32_t res; /* all operands in native machine order */ 6455197007Sdelphij uint32_t bc; 6456197007Sdelphij 6457197007Sdelphij res = d - 1; 6458197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6459197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6460197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6461197007Sdelphij 6462197007Sdelphij /* calculate the borrow chain. See note at top */ 6463197007Sdelphij /* based on the sub_byte routine, with s==1 */ 6464197007Sdelphij bc = (res & (~d | 1)) | (~d & 1); 6465197007Sdelphij /* carry flag unchanged */ 6466197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 6467197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6468197007Sdelphij return (uint16_t) res; 6469197007Sdelphij} 6470197007Sdelphij 6471197007Sdelphij/* 6472197007Sdelphij * REMARKS: 6473197007Sdelphij * Implements the DEC instruction and side effects. 6474197007Sdelphij */ 6475197007Sdelphijstatic uint32_t 6476197007Sdelphijdec_long(struct x86emu *emu, uint32_t d) 6477197007Sdelphij{ 6478197007Sdelphij uint32_t res; /* all operands in native machine order */ 6479197007Sdelphij uint32_t bc; 6480197007Sdelphij 6481197007Sdelphij res = d - 1; 6482197007Sdelphij 6483197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6484197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6485197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6486197007Sdelphij 6487197007Sdelphij /* calculate the borrow chain. See note at top */ 6488197007Sdelphij bc = (res & (~d | 1)) | (~d & 1); 6489197007Sdelphij /* carry flag unchanged */ 6490197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 6491197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6492197007Sdelphij return res; 6493197007Sdelphij} 6494197007Sdelphij 6495197007Sdelphij/* 6496197007Sdelphij * REMARKS: 6497197007Sdelphij * Implements the INC instruction and side effects. 6498197007Sdelphij */ 6499197007Sdelphijstatic uint8_t 6500197007Sdelphijinc_byte(struct x86emu *emu, uint8_t d) 6501197007Sdelphij{ 6502197007Sdelphij uint32_t res; /* all operands in native machine order */ 6503197007Sdelphij uint32_t cc; 6504197007Sdelphij 6505197007Sdelphij res = d + 1; 6506197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6507197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6508197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6509197007Sdelphij 6510197007Sdelphij /* calculate the carry chain SEE NOTE AT TOP. */ 6511197007Sdelphij cc = ((1 & d) | (~res)) & (1 | d); 6512197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 6513197007Sdelphij CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6514197007Sdelphij return (uint8_t) res; 6515197007Sdelphij} 6516197007Sdelphij 6517197007Sdelphij/* 6518197007Sdelphij * REMARKS: 6519197007Sdelphij * Implements the INC instruction and side effects. 6520197007Sdelphij */ 6521197007Sdelphijstatic uint16_t 6522197007Sdelphijinc_word(struct x86emu *emu, uint16_t d) 6523197007Sdelphij{ 6524197007Sdelphij uint32_t res; /* all operands in native machine order */ 6525197007Sdelphij uint32_t cc; 6526197007Sdelphij 6527197007Sdelphij res = d + 1; 6528197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6529197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6530197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6531197007Sdelphij 6532197007Sdelphij /* calculate the carry chain SEE NOTE AT TOP. */ 6533197007Sdelphij cc = (1 & d) | ((~res) & (1 | d)); 6534197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 6535197007Sdelphij CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6536197007Sdelphij return (uint16_t) res; 6537197007Sdelphij} 6538197007Sdelphij 6539197007Sdelphij/* 6540197007Sdelphij * REMARKS: 6541197007Sdelphij * Implements the INC instruction and side effects. 6542197007Sdelphij */ 6543197007Sdelphijstatic uint32_t 6544197007Sdelphijinc_long(struct x86emu *emu, uint32_t d) 6545197007Sdelphij{ 6546197007Sdelphij uint32_t res; /* all operands in native machine order */ 6547197007Sdelphij uint32_t cc; 6548197007Sdelphij 6549197007Sdelphij res = d + 1; 6550197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6551197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6552197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6553197007Sdelphij 6554197007Sdelphij /* calculate the carry chain SEE NOTE AT TOP. */ 6555197007Sdelphij cc = (1 & d) | ((~res) & (1 | d)); 6556197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 6557197007Sdelphij CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6558197007Sdelphij return res; 6559197007Sdelphij} 6560197007Sdelphij 6561197007Sdelphij/* 6562197007Sdelphij * REMARKS: 6563197007Sdelphij * Implements the OR instruction and side effects. 6564197007Sdelphij */ 6565197007Sdelphijstatic uint8_t 6566197007Sdelphijor_byte(struct x86emu *emu, uint8_t d, uint8_t s) 6567197007Sdelphij{ 6568197007Sdelphij uint8_t res; /* all operands in native machine order */ 6569197007Sdelphij 6570197007Sdelphij res = d | s; 6571197007Sdelphij CLEAR_FLAG(F_OF); 6572197007Sdelphij CLEAR_FLAG(F_CF); 6573197007Sdelphij CLEAR_FLAG(F_AF); 6574197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6575197007Sdelphij CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6576197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 6577197007Sdelphij return res; 6578197007Sdelphij} 6579197007Sdelphij 6580197007Sdelphij/* 6581197007Sdelphij * REMARKS: 6582197007Sdelphij * Implements the OR instruction and side effects. 6583197007Sdelphij */ 6584197007Sdelphijstatic uint16_t 6585197007Sdelphijor_word(struct x86emu *emu, uint16_t d, uint16_t s) 6586197007Sdelphij{ 6587197007Sdelphij uint16_t res; /* all operands in native machine order */ 6588197007Sdelphij 6589197007Sdelphij res = d | s; 6590197007Sdelphij /* set the carry flag to be bit 8 */ 6591197007Sdelphij CLEAR_FLAG(F_OF); 6592197007Sdelphij CLEAR_FLAG(F_CF); 6593197007Sdelphij CLEAR_FLAG(F_AF); 6594197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6595197007Sdelphij CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6596197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6597197007Sdelphij return res; 6598197007Sdelphij} 6599197007Sdelphij 6600197007Sdelphij/* 6601197007Sdelphij * REMARKS: 6602197007Sdelphij * Implements the OR instruction and side effects. 6603197007Sdelphij */ 6604197007Sdelphijstatic uint32_t 6605197007Sdelphijor_long(struct x86emu *emu, uint32_t d, uint32_t s) 6606197007Sdelphij{ 6607197007Sdelphij uint32_t res; /* all operands in native machine order */ 6608197007Sdelphij 6609197007Sdelphij res = d | s; 6610197007Sdelphij 6611197007Sdelphij /* set the carry flag to be bit 8 */ 6612197007Sdelphij CLEAR_FLAG(F_OF); 6613197007Sdelphij CLEAR_FLAG(F_CF); 6614197007Sdelphij CLEAR_FLAG(F_AF); 6615197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6616197007Sdelphij CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6617197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6618197007Sdelphij return res; 6619197007Sdelphij} 6620197007Sdelphij 6621197007Sdelphij/* 6622197007Sdelphij * REMARKS: 6623197007Sdelphij * Implements the OR instruction and side effects. 6624197007Sdelphij */ 6625197007Sdelphijstatic uint8_t 6626197007Sdelphijneg_byte(struct x86emu *emu, uint8_t s) 6627197007Sdelphij{ 6628197007Sdelphij uint8_t res; 6629197007Sdelphij uint8_t bc; 6630197007Sdelphij 6631197007Sdelphij CONDITIONAL_SET_FLAG(s != 0, F_CF); 6632197007Sdelphij res = (uint8_t) - s; 6633197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6634197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6635197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 6636197007Sdelphij /* calculate the borrow chain --- modified such that d=0. 6637197007Sdelphij * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for 6638197007Sdelphij * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and 6639197007Sdelphij * res&0xfff... == res. Similarly ~d&s == s. So the simplified 6640197007Sdelphij * result is: */ 6641197007Sdelphij bc = res | s; 6642197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 6643197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6644197007Sdelphij return res; 6645197007Sdelphij} 6646197007Sdelphij 6647197007Sdelphij/* 6648197007Sdelphij * REMARKS: 6649197007Sdelphij * Implements the OR instruction and side effects. 6650197007Sdelphij */ 6651197007Sdelphijstatic uint16_t 6652197007Sdelphijneg_word(struct x86emu *emu, uint16_t s) 6653197007Sdelphij{ 6654197007Sdelphij uint16_t res; 6655197007Sdelphij uint16_t bc; 6656197007Sdelphij 6657197007Sdelphij CONDITIONAL_SET_FLAG(s != 0, F_CF); 6658197007Sdelphij res = (uint16_t) - s; 6659197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6660197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6661197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6662197007Sdelphij 6663197007Sdelphij /* calculate the borrow chain --- modified such that d=0. 6664197007Sdelphij * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for 6665197007Sdelphij * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and 6666197007Sdelphij * res&0xfff... == res. Similarly ~d&s == s. So the simplified 6667197007Sdelphij * result is: */ 6668197007Sdelphij bc = res | s; 6669197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 6670197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6671197007Sdelphij return res; 6672197007Sdelphij} 6673197007Sdelphij 6674197007Sdelphij/* 6675197007Sdelphij * REMARKS: 6676197007Sdelphij * Implements the OR instruction and side effects. 6677197007Sdelphij */ 6678197007Sdelphijstatic uint32_t 6679197007Sdelphijneg_long(struct x86emu *emu, uint32_t s) 6680197007Sdelphij{ 6681197007Sdelphij uint32_t res; 6682197007Sdelphij uint32_t bc; 6683197007Sdelphij 6684197007Sdelphij CONDITIONAL_SET_FLAG(s != 0, F_CF); 6685197007Sdelphij res = (uint32_t) - s; 6686197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6687197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6688197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6689197007Sdelphij 6690197007Sdelphij /* calculate the borrow chain --- modified such that d=0. 6691197007Sdelphij * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for 6692197007Sdelphij * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and 6693197007Sdelphij * res&0xfff... == res. Similarly ~d&s == s. So the simplified 6694197007Sdelphij * result is: */ 6695197007Sdelphij bc = res | s; 6696197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 6697197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6698197007Sdelphij return res; 6699197007Sdelphij} 6700197007Sdelphij 6701197007Sdelphij/* 6702197007Sdelphij * REMARKS: 6703197007Sdelphij * Implements the RCL instruction and side effects. 6704197007Sdelphij */ 6705197007Sdelphijstatic uint8_t 6706197007Sdelphijrcl_byte(struct x86emu *emu, uint8_t d, uint8_t s) 6707197007Sdelphij{ 6708197007Sdelphij unsigned int res, cnt, mask, cf; 6709197007Sdelphij 6710197007Sdelphij /* s is the rotate distance. It varies from 0 - 8. */ 6711197007Sdelphij /* have 6712197007Sdelphij * 6713197007Sdelphij * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 6714197007Sdelphij * 6715197007Sdelphij * want to rotate through the carry by "s" bits. We could loop, but 6716197007Sdelphij * that's inefficient. So the width is 9, and we split into three 6717197007Sdelphij * parts: 6718197007Sdelphij * 6719204934Sdelphij * The new carry flag (was B_n) the stuff in B_n-1 .. B_0 the stuff 6720204934Sdelphij * in B_7 .. B_n+1 6721197007Sdelphij * 6722204934Sdelphij * The new rotate is done mod 9, and given this, for a rotation of n 6723204934Sdelphij * bits (mod 9) the new carry flag is then located n bits from the MSB. 6724197007Sdelphij * The low part is then shifted up cnt bits, and the high part is or'd 6725197007Sdelphij * in. Using CAPS for new values, and lowercase for the original 6726197007Sdelphij * values, this can be expressed as: 6727197007Sdelphij * 6728197007Sdelphij * IF n > 0 1) CF <- b_(8-n) 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 6729204934Sdelphij * 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) 6730204934Sdelphij */ 6731197007Sdelphij res = d; 6732197007Sdelphij if ((cnt = s % 9) != 0) { 6733197007Sdelphij /* extract the new CARRY FLAG. */ 6734197007Sdelphij /* CF <- b_(8-n) */ 6735197007Sdelphij cf = (d >> (8 - cnt)) & 0x1; 6736197007Sdelphij 6737204934Sdelphij /* 6738204934Sdelphij * Get the low stuff which rotated into the range B_7 .. B_cnt 6739204934Sdelphij * B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 6740204934Sdelphij * note that the right hand side done by the mask. 6741204934Sdelphij */ 6742197007Sdelphij res = (d << cnt) & 0xff; 6743197007Sdelphij 6744204934Sdelphij /* 6745204934Sdelphij * now the high stuff which rotated around into the positions 6746204934Sdelphij * B_cnt-2 .. B_0 6747204934Sdelphij * B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) 6748204934Sdelphij * shift it downward, 7-(n-2) = 9-n positions. and mask off 6749204934Sdelphij * the result before or'ing in. 6750204934Sdelphij */ 6751197007Sdelphij mask = (1 << (cnt - 1)) - 1; 6752197007Sdelphij res |= (d >> (9 - cnt)) & mask; 6753197007Sdelphij 6754197007Sdelphij /* if the carry flag was set, or it in. */ 6755197007Sdelphij if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6756197007Sdelphij /* B_(n-1) <- cf */ 6757197007Sdelphij res |= 1 << (cnt - 1); 6758197007Sdelphij } 6759197007Sdelphij /* set the new carry flag, based on the variable "cf" */ 6760197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 6761197007Sdelphij /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and 6762197007Sdelphij * the most significant bit. Blecck. */ 6763197007Sdelphij /* parenthesized this expression since it appears to be 6764197007Sdelphij * causing OF to be misset */ 6765197007Sdelphij CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)), 6766197007Sdelphij F_OF); 6767197007Sdelphij 6768197007Sdelphij } 6769197007Sdelphij return (uint8_t) res; 6770197007Sdelphij} 6771197007Sdelphij 6772197007Sdelphij/* 6773197007Sdelphij * REMARKS: 6774197007Sdelphij * Implements the RCL instruction and side effects. 6775197007Sdelphij */ 6776197007Sdelphijstatic uint16_t 6777197007Sdelphijrcl_word(struct x86emu *emu, uint16_t d, uint8_t s) 6778197007Sdelphij{ 6779197007Sdelphij unsigned int res, cnt, mask, cf; 6780197007Sdelphij 6781197007Sdelphij res = d; 6782197007Sdelphij if ((cnt = s % 17) != 0) { 6783197007Sdelphij cf = (d >> (16 - cnt)) & 0x1; 6784197007Sdelphij res = (d << cnt) & 0xffff; 6785197007Sdelphij mask = (1 << (cnt - 1)) - 1; 6786197007Sdelphij res |= (d >> (17 - cnt)) & mask; 6787197007Sdelphij if (ACCESS_FLAG(F_CF)) { 6788197007Sdelphij res |= 1 << (cnt - 1); 6789197007Sdelphij } 6790197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 6791197007Sdelphij CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)), 6792197007Sdelphij F_OF); 6793197007Sdelphij } 6794197007Sdelphij return (uint16_t) res; 6795197007Sdelphij} 6796197007Sdelphij 6797197007Sdelphij/* 6798197007Sdelphij * REMARKS: 6799197007Sdelphij * Implements the RCL instruction and side effects. 6800197007Sdelphij */ 6801197007Sdelphijstatic uint32_t 6802197007Sdelphijrcl_long(struct x86emu *emu, uint32_t d, uint8_t s) 6803197007Sdelphij{ 6804197007Sdelphij uint32_t res, cnt, mask, cf; 6805197007Sdelphij 6806197007Sdelphij res = d; 6807197007Sdelphij if ((cnt = s % 33) != 0) { 6808197007Sdelphij cf = (d >> (32 - cnt)) & 0x1; 6809197007Sdelphij res = (d << cnt) & 0xffffffff; 6810197007Sdelphij mask = (1 << (cnt - 1)) - 1; 6811197007Sdelphij res |= (d >> (33 - cnt)) & mask; 6812197007Sdelphij if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6813197007Sdelphij res |= 1 << (cnt - 1); 6814197007Sdelphij } 6815197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 6816197007Sdelphij CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)), 6817197007Sdelphij F_OF); 6818197007Sdelphij } 6819197007Sdelphij return res; 6820197007Sdelphij} 6821197007Sdelphij 6822197007Sdelphij/* 6823197007Sdelphij * REMARKS: 6824197007Sdelphij * Implements the RCR instruction and side effects. 6825197007Sdelphij */ 6826197007Sdelphijstatic uint8_t 6827197007Sdelphijrcr_byte(struct x86emu *emu, uint8_t d, uint8_t s) 6828197007Sdelphij{ 6829197007Sdelphij uint32_t res, cnt; 6830197007Sdelphij uint32_t mask, cf, ocf = 0; 6831197007Sdelphij 6832197007Sdelphij /* rotate right through carry */ 6833197007Sdelphij /* s is the rotate distance. It varies from 0 - 8. d is the byte 6834197007Sdelphij * object rotated. 6835197007Sdelphij * 6836197007Sdelphij * have 6837197007Sdelphij * 6838197007Sdelphij * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 6839197007Sdelphij * 6840204934Sdelphij * The new rotate is done mod 9, and given this, for a rotation of n 6841204934Sdelphij * bits (mod 9) the new carry flag is then located n bits from the LSB. 6842197007Sdelphij * The low part is then shifted up cnt bits, and the high part is or'd 6843197007Sdelphij * in. Using CAPS for new values, and lowercase for the original 6844197007Sdelphij * values, this can be expressed as: 6845197007Sdelphij * 6846204934Sdelphij * IF n > 0 6847204934Sdelphij * 1) CF <- b_(n-1) 6848204934Sdelphij * 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 6849204934Sdelphij * 3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) 6850204934Sdelphij */ 6851197007Sdelphij res = d; 6852197007Sdelphij if ((cnt = s % 9) != 0) { 6853197007Sdelphij /* extract the new CARRY FLAG. */ 6854197007Sdelphij /* CF <- b_(n-1) */ 6855197007Sdelphij if (cnt == 1) { 6856197007Sdelphij cf = d & 0x1; 6857197007Sdelphij /* note hackery here. Access_flag(..) evaluates to 6858197007Sdelphij * either 0 if flag not set non-zero if flag is set. 6859197007Sdelphij * doing access_flag(..) != 0 casts that into either 6860197007Sdelphij * 0..1 in any representation of the flags register 6861197007Sdelphij * (i.e. packed bit array or unpacked.) */ 6862197007Sdelphij ocf = ACCESS_FLAG(F_CF) != 0; 6863197007Sdelphij } else 6864197007Sdelphij cf = (d >> (cnt - 1)) & 0x1; 6865197007Sdelphij 6866197007Sdelphij /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */ 6867197007Sdelphij /* note that the right hand side done by the mask This is 6868197007Sdelphij * effectively done by shifting the object to the right. The 6869197007Sdelphij * result must be masked, in case the object came in and was 6870197007Sdelphij * treated as a negative number. Needed??? */ 6871197007Sdelphij 6872197007Sdelphij mask = (1 << (8 - cnt)) - 1; 6873197007Sdelphij res = (d >> cnt) & mask; 6874197007Sdelphij 6875197007Sdelphij /* now the high stuff which rotated around into the positions 6876197007Sdelphij * B_cnt-2 .. B_0 */ 6877197007Sdelphij /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */ 6878197007Sdelphij /* shift it downward, 7-(n-2) = 9-n positions. and mask off 6879197007Sdelphij * the result before or'ing in. */ 6880197007Sdelphij res |= (d << (9 - cnt)); 6881197007Sdelphij 6882197007Sdelphij /* if the carry flag was set, or it in. */ 6883197007Sdelphij if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6884197007Sdelphij /* B_(8-n) <- cf */ 6885197007Sdelphij res |= 1 << (8 - cnt); 6886197007Sdelphij } 6887197007Sdelphij /* set the new carry flag, based on the variable "cf" */ 6888197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 6889197007Sdelphij /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and 6890197007Sdelphij * the most significant bit. Blecck. */ 6891197007Sdelphij /* parenthesized... */ 6892197007Sdelphij if (cnt == 1) { 6893197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)), 6894197007Sdelphij F_OF); 6895197007Sdelphij } 6896197007Sdelphij } 6897197007Sdelphij return (uint8_t) res; 6898197007Sdelphij} 6899197007Sdelphij 6900197007Sdelphij/* 6901197007Sdelphij * REMARKS: 6902197007Sdelphij * Implements the RCR instruction and side effects. 6903197007Sdelphij */ 6904197007Sdelphijstatic uint16_t 6905197007Sdelphijrcr_word(struct x86emu *emu, uint16_t d, uint8_t s) 6906197007Sdelphij{ 6907197007Sdelphij uint32_t res, cnt; 6908197007Sdelphij uint32_t mask, cf, ocf = 0; 6909197007Sdelphij 6910197007Sdelphij /* rotate right through carry */ 6911197007Sdelphij res = d; 6912197007Sdelphij if ((cnt = s % 17) != 0) { 6913197007Sdelphij if (cnt == 1) { 6914197007Sdelphij cf = d & 0x1; 6915197007Sdelphij ocf = ACCESS_FLAG(F_CF) != 0; 6916197007Sdelphij } else 6917197007Sdelphij cf = (d >> (cnt - 1)) & 0x1; 6918197007Sdelphij mask = (1 << (16 - cnt)) - 1; 6919197007Sdelphij res = (d >> cnt) & mask; 6920197007Sdelphij res |= (d << (17 - cnt)); 6921197007Sdelphij if (ACCESS_FLAG(F_CF)) { 6922197007Sdelphij res |= 1 << (16 - cnt); 6923197007Sdelphij } 6924197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 6925197007Sdelphij if (cnt == 1) { 6926197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)), 6927197007Sdelphij F_OF); 6928197007Sdelphij } 6929197007Sdelphij } 6930197007Sdelphij return (uint16_t) res; 6931197007Sdelphij} 6932197007Sdelphij 6933197007Sdelphij/* 6934197007Sdelphij * REMARKS: 6935197007Sdelphij * Implements the RCR instruction and side effects. 6936197007Sdelphij */ 6937197007Sdelphijstatic uint32_t 6938197007Sdelphijrcr_long(struct x86emu *emu, uint32_t d, uint8_t s) 6939197007Sdelphij{ 6940197007Sdelphij uint32_t res, cnt; 6941197007Sdelphij uint32_t mask, cf, ocf = 0; 6942197007Sdelphij 6943197007Sdelphij /* rotate right through carry */ 6944197007Sdelphij res = d; 6945197007Sdelphij if ((cnt = s % 33) != 0) { 6946197007Sdelphij if (cnt == 1) { 6947197007Sdelphij cf = d & 0x1; 6948197007Sdelphij ocf = ACCESS_FLAG(F_CF) != 0; 6949197007Sdelphij } else 6950197007Sdelphij cf = (d >> (cnt - 1)) & 0x1; 6951197007Sdelphij mask = (1 << (32 - cnt)) - 1; 6952197007Sdelphij res = (d >> cnt) & mask; 6953197007Sdelphij if (cnt != 1) 6954197007Sdelphij res |= (d << (33 - cnt)); 6955197007Sdelphij if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6956197007Sdelphij res |= 1 << (32 - cnt); 6957197007Sdelphij } 6958197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 6959197007Sdelphij if (cnt == 1) { 6960197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)), 6961197007Sdelphij F_OF); 6962197007Sdelphij } 6963197007Sdelphij } 6964197007Sdelphij return res; 6965197007Sdelphij} 6966197007Sdelphij 6967197007Sdelphij/* 6968197007Sdelphij * REMARKS: 6969197007Sdelphij * Implements the ROL instruction and side effects. 6970197007Sdelphij */ 6971197007Sdelphijstatic uint8_t 6972197007Sdelphijrol_byte(struct x86emu *emu, uint8_t d, uint8_t s) 6973197007Sdelphij{ 6974197007Sdelphij unsigned int res, cnt, mask; 6975197007Sdelphij 6976197007Sdelphij /* rotate left */ 6977197007Sdelphij /* s is the rotate distance. It varies from 0 - 8. d is the byte 6978197007Sdelphij * object rotated. 6979197007Sdelphij * 6980197007Sdelphij * have 6981197007Sdelphij * 6982197007Sdelphij * CF B_7 ... B_0 6983197007Sdelphij * 6984197007Sdelphij * The new rotate is done mod 8. Much simpler than the "rcl" or "rcr" 6985197007Sdelphij * operations. 6986197007Sdelphij * 6987197007Sdelphij * IF n > 0 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) 2) B_(n-1) .. 6988197007Sdelphij * B_(0) <- b_(7) .. b_(8-n) */ 6989197007Sdelphij res = d; 6990197007Sdelphij if ((cnt = s % 8) != 0) { 6991197007Sdelphij /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */ 6992197007Sdelphij res = (d << cnt); 6993197007Sdelphij 6994197007Sdelphij /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */ 6995197007Sdelphij mask = (1 << cnt) - 1; 6996197007Sdelphij res |= (d >> (8 - cnt)) & mask; 6997197007Sdelphij 6998197007Sdelphij /* set the new carry flag, Note that it is the low order bit 6999197007Sdelphij * of the result!!! */ 7000197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 7001197007Sdelphij /* OVERFLOW is set *IFF* s==1, then it is the xor of CF and 7002197007Sdelphij * the most significant bit. Blecck. */ 7003197007Sdelphij CONDITIONAL_SET_FLAG(s == 1 && 7004197007Sdelphij XOR2((res & 0x1) + ((res >> 6) & 0x2)), 7005197007Sdelphij F_OF); 7006197007Sdelphij } if (s != 0) { 7007197007Sdelphij /* set the new carry flag, Note that it is the low order bit 7008197007Sdelphij * of the result!!! */ 7009197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 7010197007Sdelphij } 7011197007Sdelphij return (uint8_t) res; 7012197007Sdelphij} 7013197007Sdelphij 7014197007Sdelphij/* 7015197007Sdelphij * REMARKS: 7016197007Sdelphij * Implements the ROL instruction and side effects. 7017197007Sdelphij */ 7018197007Sdelphijstatic uint16_t 7019197007Sdelphijrol_word(struct x86emu *emu, uint16_t d, uint8_t s) 7020197007Sdelphij{ 7021197007Sdelphij unsigned int res, cnt, mask; 7022197007Sdelphij 7023197007Sdelphij res = d; 7024197007Sdelphij if ((cnt = s % 16) != 0) { 7025197007Sdelphij res = (d << cnt); 7026197007Sdelphij mask = (1 << cnt) - 1; 7027197007Sdelphij res |= (d >> (16 - cnt)) & mask; 7028197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 7029197007Sdelphij CONDITIONAL_SET_FLAG(s == 1 && 7030197007Sdelphij XOR2((res & 0x1) + ((res >> 14) & 0x2)), 7031197007Sdelphij F_OF); 7032197007Sdelphij } if (s != 0) { 7033197007Sdelphij /* set the new carry flag, Note that it is the low order bit 7034197007Sdelphij * of the result!!! */ 7035197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 7036197007Sdelphij } 7037197007Sdelphij return (uint16_t) res; 7038197007Sdelphij} 7039197007Sdelphij 7040197007Sdelphij/* 7041197007Sdelphij * REMARKS: 7042197007Sdelphij * Implements the ROL instruction and side effects. 7043197007Sdelphij */ 7044197007Sdelphijstatic uint32_t 7045197007Sdelphijrol_long(struct x86emu *emu, uint32_t d, uint8_t s) 7046197007Sdelphij{ 7047197007Sdelphij uint32_t res, cnt, mask; 7048197007Sdelphij 7049197007Sdelphij res = d; 7050197007Sdelphij if ((cnt = s % 32) != 0) { 7051197007Sdelphij res = (d << cnt); 7052197007Sdelphij mask = (1 << cnt) - 1; 7053197007Sdelphij res |= (d >> (32 - cnt)) & mask; 7054197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 7055197007Sdelphij CONDITIONAL_SET_FLAG(s == 1 && 7056197007Sdelphij XOR2((res & 0x1) + ((res >> 30) & 0x2)), 7057197007Sdelphij F_OF); 7058197007Sdelphij } if (s != 0) { 7059197007Sdelphij /* set the new carry flag, Note that it is the low order bit 7060197007Sdelphij * of the result!!! */ 7061197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 7062197007Sdelphij } 7063197007Sdelphij return res; 7064197007Sdelphij} 7065197007Sdelphij 7066197007Sdelphij/* 7067197007Sdelphij * REMARKS: 7068197007Sdelphij * Implements the ROR instruction and side effects. 7069197007Sdelphij */ 7070197007Sdelphijstatic uint8_t 7071197007Sdelphijror_byte(struct x86emu *emu, uint8_t d, uint8_t s) 7072197007Sdelphij{ 7073197007Sdelphij unsigned int res, cnt, mask; 7074197007Sdelphij 7075197007Sdelphij /* rotate right */ 7076197007Sdelphij /* s is the rotate distance. It varies from 0 - 8. d is the byte 7077197007Sdelphij * object rotated. 7078197007Sdelphij * 7079197007Sdelphij * have 7080197007Sdelphij * 7081197007Sdelphij * B_7 ... B_0 7082197007Sdelphij * 7083197007Sdelphij * The rotate is done mod 8. 7084197007Sdelphij * 7085197007Sdelphij * IF n > 0 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 2) B_(7) .. 7086197007Sdelphij * B_(8-n) <- b_(n-1) .. b_(0) */ 7087197007Sdelphij res = d; 7088197007Sdelphij if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */ 7089197007Sdelphij /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */ 7090197007Sdelphij res = (d << (8 - cnt)); 7091197007Sdelphij 7092197007Sdelphij /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */ 7093197007Sdelphij mask = (1 << (8 - cnt)) - 1; 7094197007Sdelphij res |= (d >> (cnt)) & mask; 7095197007Sdelphij 7096197007Sdelphij /* set the new carry flag, Note that it is the low order bit 7097197007Sdelphij * of the result!!! */ 7098197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_CF); 7099197007Sdelphij /* OVERFLOW is set *IFF* s==1, then it is the xor of the two 7100197007Sdelphij * most significant bits. Blecck. */ 7101197007Sdelphij CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF); 7102197007Sdelphij } else if (s != 0) { 7103197007Sdelphij /* set the new carry flag, Note that it is the low order bit 7104197007Sdelphij * of the result!!! */ 7105197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_CF); 7106197007Sdelphij } 7107197007Sdelphij return (uint8_t) res; 7108197007Sdelphij} 7109197007Sdelphij 7110197007Sdelphij/* 7111197007Sdelphij * REMARKS: 7112197007Sdelphij * Implements the ROR instruction and side effects. 7113197007Sdelphij */ 7114197007Sdelphijstatic uint16_t 7115197007Sdelphijror_word(struct x86emu *emu, uint16_t d, uint8_t s) 7116197007Sdelphij{ 7117197007Sdelphij unsigned int res, cnt, mask; 7118197007Sdelphij 7119197007Sdelphij res = d; 7120197007Sdelphij if ((cnt = s % 16) != 0) { 7121197007Sdelphij res = (d << (16 - cnt)); 7122197007Sdelphij mask = (1 << (16 - cnt)) - 1; 7123197007Sdelphij res |= (d >> (cnt)) & mask; 7124197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_CF); 7125197007Sdelphij CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF); 7126197007Sdelphij } else if (s != 0) { 7127197007Sdelphij /* set the new carry flag, Note that it is the low order bit 7128197007Sdelphij * of the result!!! */ 7129197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_CF); 7130197007Sdelphij } 7131197007Sdelphij return (uint16_t) res; 7132197007Sdelphij} 7133197007Sdelphij 7134197007Sdelphij/* 7135197007Sdelphij * REMARKS: 7136197007Sdelphij * Implements the ROR instruction and side effects. 7137197007Sdelphij */ 7138197007Sdelphijstatic uint32_t 7139197007Sdelphijror_long(struct x86emu *emu, uint32_t d, uint8_t s) 7140197007Sdelphij{ 7141197007Sdelphij uint32_t res, cnt, mask; 7142197007Sdelphij 7143197007Sdelphij res = d; 7144197007Sdelphij if ((cnt = s % 32) != 0) { 7145197007Sdelphij res = (d << (32 - cnt)); 7146197007Sdelphij mask = (1 << (32 - cnt)) - 1; 7147197007Sdelphij res |= (d >> (cnt)) & mask; 7148197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF); 7149197007Sdelphij CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF); 7150197007Sdelphij } else if (s != 0) { 7151197007Sdelphij /* set the new carry flag, Note that it is the low order bit 7152197007Sdelphij * of the result!!! */ 7153197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF); 7154197007Sdelphij } 7155197007Sdelphij return res; 7156197007Sdelphij} 7157197007Sdelphij 7158197007Sdelphij/* 7159197007Sdelphij * REMARKS: 7160197007Sdelphij * Implements the SHL instruction and side effects. 7161197007Sdelphij */ 7162197007Sdelphijstatic uint8_t 7163197007Sdelphijshl_byte(struct x86emu *emu, uint8_t d, uint8_t s) 7164197007Sdelphij{ 7165197007Sdelphij unsigned int cnt, res, cf; 7166197007Sdelphij 7167197007Sdelphij if (s < 8) { 7168197007Sdelphij cnt = s % 8; 7169197007Sdelphij 7170197007Sdelphij /* last bit shifted out goes into carry flag */ 7171197007Sdelphij if (cnt > 0) { 7172197007Sdelphij res = d << cnt; 7173197007Sdelphij cf = d & (1 << (8 - cnt)); 7174197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 7175197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7176197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7177197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7178197007Sdelphij } else { 7179197007Sdelphij res = (uint8_t) d; 7180197007Sdelphij } 7181197007Sdelphij 7182197007Sdelphij if (cnt == 1) { 7183197007Sdelphij /* Needs simplification. */ 7184197007Sdelphij CONDITIONAL_SET_FLAG( 7185197007Sdelphij (((res & 0x80) == 0x80) ^ 7186197007Sdelphij (ACCESS_FLAG(F_CF) != 0)), 7187197007Sdelphij /* was (emu->x86.R_FLG&F_CF)==F_CF)), */ 7188197007Sdelphij F_OF); 7189197007Sdelphij } else { 7190197007Sdelphij CLEAR_FLAG(F_OF); 7191197007Sdelphij } 7192197007Sdelphij } else { 7193197007Sdelphij res = 0; 7194197007Sdelphij CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF); 7195197007Sdelphij CLEAR_FLAG(F_OF); 7196197007Sdelphij CLEAR_FLAG(F_SF); 7197197007Sdelphij SET_FLAG(F_PF); 7198197007Sdelphij SET_FLAG(F_ZF); 7199197007Sdelphij } 7200197007Sdelphij return (uint8_t) res; 7201197007Sdelphij} 7202197007Sdelphij 7203197007Sdelphij/* 7204197007Sdelphij * REMARKS: 7205197007Sdelphij * Implements the SHL instruction and side effects. 7206197007Sdelphij */ 7207197007Sdelphijstatic uint16_t 7208197007Sdelphijshl_word(struct x86emu *emu, uint16_t d, uint8_t s) 7209197007Sdelphij{ 7210197007Sdelphij unsigned int cnt, res, cf; 7211197007Sdelphij 7212197007Sdelphij if (s < 16) { 7213197007Sdelphij cnt = s % 16; 7214197007Sdelphij if (cnt > 0) { 7215197007Sdelphij res = d << cnt; 7216197007Sdelphij cf = d & (1 << (16 - cnt)); 7217197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 7218197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7219197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7220197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7221197007Sdelphij } else { 7222197007Sdelphij res = (uint16_t) d; 7223197007Sdelphij } 7224197007Sdelphij 7225197007Sdelphij if (cnt == 1) { 7226197007Sdelphij CONDITIONAL_SET_FLAG( 7227197007Sdelphij (((res & 0x8000) == 0x8000) ^ 7228197007Sdelphij (ACCESS_FLAG(F_CF) != 0)), 7229197007Sdelphij F_OF); 7230197007Sdelphij } else { 7231197007Sdelphij CLEAR_FLAG(F_OF); 7232197007Sdelphij } 7233197007Sdelphij } else { 7234197007Sdelphij res = 0; 7235197007Sdelphij CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF); 7236197007Sdelphij CLEAR_FLAG(F_OF); 7237197007Sdelphij CLEAR_FLAG(F_SF); 7238197007Sdelphij SET_FLAG(F_PF); 7239197007Sdelphij SET_FLAG(F_ZF); 7240197007Sdelphij } 7241197007Sdelphij return (uint16_t) res; 7242197007Sdelphij} 7243197007Sdelphij 7244197007Sdelphij/* 7245197007Sdelphij * REMARKS: 7246197007Sdelphij * Implements the SHL instruction and side effects. 7247197007Sdelphij */ 7248197007Sdelphijstatic uint32_t 7249197007Sdelphijshl_long(struct x86emu *emu, uint32_t d, uint8_t s) 7250197007Sdelphij{ 7251197007Sdelphij unsigned int cnt, res, cf; 7252197007Sdelphij 7253197007Sdelphij if (s < 32) { 7254197007Sdelphij cnt = s % 32; 7255197007Sdelphij if (cnt > 0) { 7256197007Sdelphij res = d << cnt; 7257197007Sdelphij cf = d & (1 << (32 - cnt)); 7258197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 7259197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7260197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7261197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7262197007Sdelphij } else { 7263197007Sdelphij res = d; 7264197007Sdelphij } 7265197007Sdelphij if (cnt == 1) { 7266204934Sdelphij CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) 7267204934Sdelphij ^ (ACCESS_FLAG(F_CF) != 0)), F_OF); 7268197007Sdelphij } else { 7269197007Sdelphij CLEAR_FLAG(F_OF); 7270197007Sdelphij } 7271197007Sdelphij } else { 7272197007Sdelphij res = 0; 7273197007Sdelphij CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF); 7274197007Sdelphij CLEAR_FLAG(F_OF); 7275197007Sdelphij CLEAR_FLAG(F_SF); 7276197007Sdelphij SET_FLAG(F_PF); 7277197007Sdelphij SET_FLAG(F_ZF); 7278197007Sdelphij } 7279197007Sdelphij return res; 7280197007Sdelphij} 7281197007Sdelphij 7282197007Sdelphij/* 7283197007Sdelphij * REMARKS: 7284197007Sdelphij * Implements the SHR instruction and side effects. 7285197007Sdelphij */ 7286197007Sdelphijstatic uint8_t 7287197007Sdelphijshr_byte(struct x86emu *emu, uint8_t d, uint8_t s) 7288197007Sdelphij{ 7289197007Sdelphij unsigned int cnt, res, cf; 7290197007Sdelphij 7291197007Sdelphij if (s < 8) { 7292197007Sdelphij cnt = s % 8; 7293197007Sdelphij if (cnt > 0) { 7294197007Sdelphij cf = d & (1 << (cnt - 1)); 7295197007Sdelphij res = d >> cnt; 7296197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 7297197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7298197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7299197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7300197007Sdelphij } else { 7301197007Sdelphij res = (uint8_t) d; 7302197007Sdelphij } 7303197007Sdelphij 7304197007Sdelphij if (cnt == 1) { 7305197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF); 7306197007Sdelphij } else { 7307197007Sdelphij CLEAR_FLAG(F_OF); 7308197007Sdelphij } 7309197007Sdelphij } else { 7310197007Sdelphij res = 0; 7311197007Sdelphij CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF); 7312197007Sdelphij CLEAR_FLAG(F_OF); 7313197007Sdelphij CLEAR_FLAG(F_SF); 7314197007Sdelphij SET_FLAG(F_PF); 7315197007Sdelphij SET_FLAG(F_ZF); 7316197007Sdelphij } 7317197007Sdelphij return (uint8_t) res; 7318197007Sdelphij} 7319197007Sdelphij 7320197007Sdelphij/* 7321197007Sdelphij * REMARKS: 7322197007Sdelphij * Implements the SHR instruction and side effects. 7323197007Sdelphij */ 7324197007Sdelphijstatic uint16_t 7325197007Sdelphijshr_word(struct x86emu *emu, uint16_t d, uint8_t s) 7326197007Sdelphij{ 7327197007Sdelphij unsigned int cnt, res, cf; 7328197007Sdelphij 7329197007Sdelphij if (s < 16) { 7330197007Sdelphij cnt = s % 16; 7331197007Sdelphij if (cnt > 0) { 7332197007Sdelphij cf = d & (1 << (cnt - 1)); 7333197007Sdelphij res = d >> cnt; 7334197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 7335197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7336197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7337197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7338197007Sdelphij } else { 7339197007Sdelphij res = d; 7340197007Sdelphij } 7341197007Sdelphij 7342197007Sdelphij if (cnt == 1) { 7343197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF); 7344197007Sdelphij } else { 7345197007Sdelphij CLEAR_FLAG(F_OF); 7346197007Sdelphij } 7347197007Sdelphij } else { 7348197007Sdelphij res = 0; 7349197007Sdelphij CLEAR_FLAG(F_CF); 7350197007Sdelphij CLEAR_FLAG(F_OF); 7351197007Sdelphij SET_FLAG(F_ZF); 7352197007Sdelphij CLEAR_FLAG(F_SF); 7353197007Sdelphij CLEAR_FLAG(F_PF); 7354197007Sdelphij } 7355197007Sdelphij return (uint16_t) res; 7356197007Sdelphij} 7357197007Sdelphij 7358197007Sdelphij/* 7359197007Sdelphij * REMARKS: 7360197007Sdelphij * Implements the SHR instruction and side effects. 7361197007Sdelphij */ 7362197007Sdelphijstatic uint32_t 7363197007Sdelphijshr_long(struct x86emu *emu, uint32_t d, uint8_t s) 7364197007Sdelphij{ 7365197007Sdelphij unsigned int cnt, res, cf; 7366197007Sdelphij 7367197007Sdelphij if (s < 32) { 7368197007Sdelphij cnt = s % 32; 7369197007Sdelphij if (cnt > 0) { 7370197007Sdelphij cf = d & (1 << (cnt - 1)); 7371197007Sdelphij res = d >> cnt; 7372197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 7373197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7374197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7375197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7376197007Sdelphij } else { 7377197007Sdelphij res = d; 7378197007Sdelphij } 7379197007Sdelphij if (cnt == 1) { 7380197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF); 7381197007Sdelphij } else { 7382197007Sdelphij CLEAR_FLAG(F_OF); 7383197007Sdelphij } 7384197007Sdelphij } else { 7385197007Sdelphij res = 0; 7386197007Sdelphij CLEAR_FLAG(F_CF); 7387197007Sdelphij CLEAR_FLAG(F_OF); 7388197007Sdelphij SET_FLAG(F_ZF); 7389197007Sdelphij CLEAR_FLAG(F_SF); 7390197007Sdelphij CLEAR_FLAG(F_PF); 7391197007Sdelphij } 7392197007Sdelphij return res; 7393197007Sdelphij} 7394197007Sdelphij 7395197007Sdelphij/* 7396197007Sdelphij * REMARKS: 7397197007Sdelphij * Implements the SAR instruction and side effects. 7398197007Sdelphij */ 7399197007Sdelphijstatic uint8_t 7400197007Sdelphijsar_byte(struct x86emu *emu, uint8_t d, uint8_t s) 7401197007Sdelphij{ 7402197007Sdelphij unsigned int cnt, res, cf, mask, sf; 7403197007Sdelphij 7404197007Sdelphij res = d; 7405197007Sdelphij sf = d & 0x80; 7406197007Sdelphij cnt = s % 8; 7407197007Sdelphij if (cnt > 0 && cnt < 8) { 7408197007Sdelphij mask = (1 << (8 - cnt)) - 1; 7409197007Sdelphij cf = d & (1 << (cnt - 1)); 7410197007Sdelphij res = (d >> cnt) & mask; 7411197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 7412197007Sdelphij if (sf) { 7413197007Sdelphij res |= ~mask; 7414197007Sdelphij } 7415197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7416197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7417197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7418197007Sdelphij } else if (cnt >= 8) { 7419197007Sdelphij if (sf) { 7420197007Sdelphij res = 0xff; 7421197007Sdelphij SET_FLAG(F_CF); 7422197007Sdelphij CLEAR_FLAG(F_ZF); 7423197007Sdelphij SET_FLAG(F_SF); 7424197007Sdelphij SET_FLAG(F_PF); 7425197007Sdelphij } else { 7426197007Sdelphij res = 0; 7427197007Sdelphij CLEAR_FLAG(F_CF); 7428197007Sdelphij SET_FLAG(F_ZF); 7429197007Sdelphij CLEAR_FLAG(F_SF); 7430197007Sdelphij CLEAR_FLAG(F_PF); 7431197007Sdelphij } 7432197007Sdelphij } 7433197007Sdelphij return (uint8_t) res; 7434197007Sdelphij} 7435197007Sdelphij 7436197007Sdelphij/* 7437197007Sdelphij * REMARKS: 7438197007Sdelphij * Implements the SAR instruction and side effects. 7439197007Sdelphij */ 7440197007Sdelphijstatic uint16_t 7441197007Sdelphijsar_word(struct x86emu *emu, uint16_t d, uint8_t s) 7442197007Sdelphij{ 7443197007Sdelphij unsigned int cnt, res, cf, mask, sf; 7444197007Sdelphij 7445197007Sdelphij sf = d & 0x8000; 7446197007Sdelphij cnt = s % 16; 7447197007Sdelphij res = d; 7448197007Sdelphij if (cnt > 0 && cnt < 16) { 7449197007Sdelphij mask = (1 << (16 - cnt)) - 1; 7450197007Sdelphij cf = d & (1 << (cnt - 1)); 7451197007Sdelphij res = (d >> cnt) & mask; 7452197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 7453197007Sdelphij if (sf) { 7454197007Sdelphij res |= ~mask; 7455197007Sdelphij } 7456197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7457197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7458197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7459197007Sdelphij } else if (cnt >= 16) { 7460197007Sdelphij if (sf) { 7461197007Sdelphij res = 0xffff; 7462197007Sdelphij SET_FLAG(F_CF); 7463197007Sdelphij CLEAR_FLAG(F_ZF); 7464197007Sdelphij SET_FLAG(F_SF); 7465197007Sdelphij SET_FLAG(F_PF); 7466197007Sdelphij } else { 7467197007Sdelphij res = 0; 7468197007Sdelphij CLEAR_FLAG(F_CF); 7469197007Sdelphij SET_FLAG(F_ZF); 7470197007Sdelphij CLEAR_FLAG(F_SF); 7471197007Sdelphij CLEAR_FLAG(F_PF); 7472197007Sdelphij } 7473197007Sdelphij } 7474197007Sdelphij return (uint16_t) res; 7475197007Sdelphij} 7476197007Sdelphij 7477197007Sdelphij/* 7478197007Sdelphij * REMARKS: 7479197007Sdelphij * Implements the SAR instruction and side effects. 7480197007Sdelphij */ 7481197007Sdelphijstatic uint32_t 7482197007Sdelphijsar_long(struct x86emu *emu, uint32_t d, uint8_t s) 7483197007Sdelphij{ 7484197007Sdelphij uint32_t cnt, res, cf, mask, sf; 7485197007Sdelphij 7486197007Sdelphij sf = d & 0x80000000; 7487197007Sdelphij cnt = s % 32; 7488197007Sdelphij res = d; 7489197007Sdelphij if (cnt > 0 && cnt < 32) { 7490197007Sdelphij mask = (1 << (32 - cnt)) - 1; 7491197007Sdelphij cf = d & (1 << (cnt - 1)); 7492197007Sdelphij res = (d >> cnt) & mask; 7493197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 7494197007Sdelphij if (sf) { 7495197007Sdelphij res |= ~mask; 7496197007Sdelphij } 7497197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7498197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7499197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7500197007Sdelphij } else if (cnt >= 32) { 7501197007Sdelphij if (sf) { 7502197007Sdelphij res = 0xffffffff; 7503197007Sdelphij SET_FLAG(F_CF); 7504197007Sdelphij CLEAR_FLAG(F_ZF); 7505197007Sdelphij SET_FLAG(F_SF); 7506197007Sdelphij SET_FLAG(F_PF); 7507197007Sdelphij } else { 7508197007Sdelphij res = 0; 7509197007Sdelphij CLEAR_FLAG(F_CF); 7510197007Sdelphij SET_FLAG(F_ZF); 7511197007Sdelphij CLEAR_FLAG(F_SF); 7512197007Sdelphij CLEAR_FLAG(F_PF); 7513197007Sdelphij } 7514197007Sdelphij } 7515197007Sdelphij return res; 7516197007Sdelphij} 7517197007Sdelphij 7518197007Sdelphij/* 7519197007Sdelphij * REMARKS: 7520197007Sdelphij * Implements the SHLD instruction and side effects. 7521197007Sdelphij */ 7522197007Sdelphijstatic uint16_t 7523197007Sdelphijshld_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s) 7524197007Sdelphij{ 7525197007Sdelphij unsigned int cnt, res, cf; 7526197007Sdelphij 7527197007Sdelphij if (s < 16) { 7528197007Sdelphij cnt = s % 16; 7529197007Sdelphij if (cnt > 0) { 7530197007Sdelphij res = (d << cnt) | (fill >> (16 - cnt)); 7531197007Sdelphij cf = d & (1 << (16 - cnt)); 7532197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 7533197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7534197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7535197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7536197007Sdelphij } else { 7537197007Sdelphij res = d; 7538197007Sdelphij } 7539197007Sdelphij if (cnt == 1) { 7540197007Sdelphij CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^ 7541197007Sdelphij (ACCESS_FLAG(F_CF) != 0)), F_OF); 7542197007Sdelphij } else { 7543197007Sdelphij CLEAR_FLAG(F_OF); 7544197007Sdelphij } 7545197007Sdelphij } else { 7546197007Sdelphij res = 0; 7547197007Sdelphij CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF); 7548197007Sdelphij CLEAR_FLAG(F_OF); 7549197007Sdelphij CLEAR_FLAG(F_SF); 7550197007Sdelphij SET_FLAG(F_PF); 7551197007Sdelphij SET_FLAG(F_ZF); 7552197007Sdelphij } 7553197007Sdelphij return (uint16_t) res; 7554197007Sdelphij} 7555197007Sdelphij 7556197007Sdelphij/* 7557197007Sdelphij * REMARKS: 7558197007Sdelphij * Implements the SHLD instruction and side effects. 7559197007Sdelphij */ 7560197007Sdelphijstatic uint32_t 7561197007Sdelphijshld_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s) 7562197007Sdelphij{ 7563197007Sdelphij unsigned int cnt, res, cf; 7564197007Sdelphij 7565197007Sdelphij if (s < 32) { 7566197007Sdelphij cnt = s % 32; 7567197007Sdelphij if (cnt > 0) { 7568197007Sdelphij res = (d << cnt) | (fill >> (32 - cnt)); 7569197007Sdelphij cf = d & (1 << (32 - cnt)); 7570197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 7571197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7572197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7573197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7574197007Sdelphij } else { 7575197007Sdelphij res = d; 7576197007Sdelphij } 7577197007Sdelphij if (cnt == 1) { 7578204934Sdelphij CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) 7579204934Sdelphij ^ (ACCESS_FLAG(F_CF) != 0)), F_OF); 7580197007Sdelphij } else { 7581197007Sdelphij CLEAR_FLAG(F_OF); 7582197007Sdelphij } 7583197007Sdelphij } else { 7584197007Sdelphij res = 0; 7585197007Sdelphij CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF); 7586197007Sdelphij CLEAR_FLAG(F_OF); 7587197007Sdelphij CLEAR_FLAG(F_SF); 7588197007Sdelphij SET_FLAG(F_PF); 7589197007Sdelphij SET_FLAG(F_ZF); 7590197007Sdelphij } 7591197007Sdelphij return res; 7592197007Sdelphij} 7593197007Sdelphij 7594197007Sdelphij/* 7595197007Sdelphij * REMARKS: 7596197007Sdelphij * Implements the SHRD instruction and side effects. 7597197007Sdelphij */ 7598197007Sdelphijstatic uint16_t 7599197007Sdelphijshrd_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s) 7600197007Sdelphij{ 7601197007Sdelphij unsigned int cnt, res, cf; 7602197007Sdelphij 7603197007Sdelphij if (s < 16) { 7604197007Sdelphij cnt = s % 16; 7605197007Sdelphij if (cnt > 0) { 7606197007Sdelphij cf = d & (1 << (cnt - 1)); 7607197007Sdelphij res = (d >> cnt) | (fill << (16 - cnt)); 7608197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 7609197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7610197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7611197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7612197007Sdelphij } else { 7613197007Sdelphij res = d; 7614197007Sdelphij } 7615197007Sdelphij 7616197007Sdelphij if (cnt == 1) { 7617197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF); 7618197007Sdelphij } else { 7619197007Sdelphij CLEAR_FLAG(F_OF); 7620197007Sdelphij } 7621197007Sdelphij } else { 7622197007Sdelphij res = 0; 7623197007Sdelphij CLEAR_FLAG(F_CF); 7624197007Sdelphij CLEAR_FLAG(F_OF); 7625197007Sdelphij SET_FLAG(F_ZF); 7626197007Sdelphij CLEAR_FLAG(F_SF); 7627197007Sdelphij CLEAR_FLAG(F_PF); 7628197007Sdelphij } 7629197007Sdelphij return (uint16_t) res; 7630197007Sdelphij} 7631197007Sdelphij 7632197007Sdelphij/* 7633197007Sdelphij * REMARKS: 7634197007Sdelphij * Implements the SHRD instruction and side effects. 7635197007Sdelphij */ 7636197007Sdelphijstatic uint32_t 7637197007Sdelphijshrd_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s) 7638197007Sdelphij{ 7639197007Sdelphij unsigned int cnt, res, cf; 7640197007Sdelphij 7641197007Sdelphij if (s < 32) { 7642197007Sdelphij cnt = s % 32; 7643197007Sdelphij if (cnt > 0) { 7644197007Sdelphij cf = d & (1 << (cnt - 1)); 7645197007Sdelphij res = (d >> cnt) | (fill << (32 - cnt)); 7646197007Sdelphij CONDITIONAL_SET_FLAG(cf, F_CF); 7647197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7648197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7649197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7650197007Sdelphij } else { 7651197007Sdelphij res = d; 7652197007Sdelphij } 7653197007Sdelphij if (cnt == 1) { 7654197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF); 7655197007Sdelphij } else { 7656197007Sdelphij CLEAR_FLAG(F_OF); 7657197007Sdelphij } 7658197007Sdelphij } else { 7659197007Sdelphij res = 0; 7660197007Sdelphij CLEAR_FLAG(F_CF); 7661197007Sdelphij CLEAR_FLAG(F_OF); 7662197007Sdelphij SET_FLAG(F_ZF); 7663197007Sdelphij CLEAR_FLAG(F_SF); 7664197007Sdelphij CLEAR_FLAG(F_PF); 7665197007Sdelphij } 7666197007Sdelphij return res; 7667197007Sdelphij} 7668197007Sdelphij 7669197007Sdelphij/* 7670197007Sdelphij * REMARKS: 7671197007Sdelphij * Implements the SBB instruction and side effects. 7672197007Sdelphij */ 7673197007Sdelphijstatic uint8_t 7674197007Sdelphijsbb_byte(struct x86emu *emu, uint8_t d, uint8_t s) 7675197007Sdelphij{ 7676197007Sdelphij uint32_t res; /* all operands in native machine order */ 7677197007Sdelphij uint32_t bc; 7678197007Sdelphij 7679197007Sdelphij if (ACCESS_FLAG(F_CF)) 7680197007Sdelphij res = d - s - 1; 7681197007Sdelphij else 7682197007Sdelphij res = d - s; 7683197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7684197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7685197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7686197007Sdelphij 7687197007Sdelphij /* calculate the borrow chain. See note at top */ 7688197007Sdelphij bc = (res & (~d | s)) | (~d & s); 7689197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); 7690197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 7691197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7692197007Sdelphij return (uint8_t) res; 7693197007Sdelphij} 7694197007Sdelphij 7695197007Sdelphij/* 7696197007Sdelphij * REMARKS: 7697197007Sdelphij * Implements the SBB instruction and side effects. 7698197007Sdelphij */ 7699197007Sdelphijstatic uint16_t 7700197007Sdelphijsbb_word(struct x86emu *emu, uint16_t d, uint16_t s) 7701197007Sdelphij{ 7702197007Sdelphij uint32_t res; /* all operands in native machine order */ 7703197007Sdelphij uint32_t bc; 7704197007Sdelphij 7705197007Sdelphij if (ACCESS_FLAG(F_CF)) 7706197007Sdelphij res = d - s - 1; 7707197007Sdelphij else 7708197007Sdelphij res = d - s; 7709197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7710197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7711197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7712197007Sdelphij 7713197007Sdelphij /* calculate the borrow chain. See note at top */ 7714197007Sdelphij bc = (res & (~d | s)) | (~d & s); 7715197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 7716197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 7717197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7718197007Sdelphij return (uint16_t) res; 7719197007Sdelphij} 7720197007Sdelphij 7721197007Sdelphij/* 7722197007Sdelphij * REMARKS: 7723197007Sdelphij * Implements the SBB instruction and side effects. 7724197007Sdelphij */ 7725197007Sdelphijstatic uint32_t 7726197007Sdelphijsbb_long(struct x86emu *emu, uint32_t d, uint32_t s) 7727197007Sdelphij{ 7728197007Sdelphij uint32_t res; /* all operands in native machine order */ 7729197007Sdelphij uint32_t bc; 7730197007Sdelphij 7731197007Sdelphij if (ACCESS_FLAG(F_CF)) 7732197007Sdelphij res = d - s - 1; 7733197007Sdelphij else 7734197007Sdelphij res = d - s; 7735197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7736197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7737197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7738197007Sdelphij 7739197007Sdelphij /* calculate the borrow chain. See note at top */ 7740197007Sdelphij bc = (res & (~d | s)) | (~d & s); 7741197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 7742197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 7743197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7744197007Sdelphij return res; 7745197007Sdelphij} 7746197007Sdelphij 7747197007Sdelphij/* 7748197007Sdelphij * REMARKS: 7749197007Sdelphij * Implements the SUB instruction and side effects. 7750197007Sdelphij */ 7751197007Sdelphijstatic uint8_t 7752197007Sdelphijsub_byte(struct x86emu *emu, uint8_t d, uint8_t s) 7753197007Sdelphij{ 7754197007Sdelphij uint32_t res; /* all operands in native machine order */ 7755197007Sdelphij uint32_t bc; 7756197007Sdelphij 7757197007Sdelphij res = d - s; 7758197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7759197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7760197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7761197007Sdelphij 7762197007Sdelphij /* calculate the borrow chain. See note at top */ 7763197007Sdelphij bc = (res & (~d | s)) | (~d & s); 7764197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); 7765197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 7766197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7767197007Sdelphij return (uint8_t) res; 7768197007Sdelphij} 7769197007Sdelphij 7770197007Sdelphij/* 7771197007Sdelphij * REMARKS: 7772197007Sdelphij * Implements the SUB instruction and side effects. 7773197007Sdelphij */ 7774197007Sdelphijstatic uint16_t 7775197007Sdelphijsub_word(struct x86emu *emu, uint16_t d, uint16_t s) 7776197007Sdelphij{ 7777197007Sdelphij uint32_t res; /* all operands in native machine order */ 7778197007Sdelphij uint32_t bc; 7779197007Sdelphij 7780197007Sdelphij res = d - s; 7781197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7782197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7783197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7784197007Sdelphij 7785197007Sdelphij /* calculate the borrow chain. See note at top */ 7786197007Sdelphij bc = (res & (~d | s)) | (~d & s); 7787197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 7788197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 7789197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7790197007Sdelphij return (uint16_t) res; 7791197007Sdelphij} 7792197007Sdelphij 7793197007Sdelphij/* 7794197007Sdelphij * REMARKS: 7795197007Sdelphij * Implements the SUB instruction and side effects. 7796197007Sdelphij */ 7797197007Sdelphijstatic uint32_t 7798197007Sdelphijsub_long(struct x86emu *emu, uint32_t d, uint32_t s) 7799197007Sdelphij{ 7800197007Sdelphij uint32_t res; /* all operands in native machine order */ 7801197007Sdelphij uint32_t bc; 7802197007Sdelphij 7803197007Sdelphij res = d - s; 7804197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7805197007Sdelphij CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7806197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7807197007Sdelphij 7808197007Sdelphij /* calculate the borrow chain. See note at top */ 7809197007Sdelphij bc = (res & (~d | s)) | (~d & s); 7810197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 7811197007Sdelphij CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 7812197007Sdelphij CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7813197007Sdelphij return res; 7814197007Sdelphij} 7815197007Sdelphij 7816197007Sdelphij/* 7817197007Sdelphij * REMARKS: 7818197007Sdelphij * Implements the TEST instruction and side effects. 7819197007Sdelphij */ 7820197007Sdelphijstatic void 7821197007Sdelphijtest_byte(struct x86emu *emu, uint8_t d, uint8_t s) 7822197007Sdelphij{ 7823197007Sdelphij uint32_t res; /* all operands in native machine order */ 7824197007Sdelphij 7825197007Sdelphij res = d & s; 7826197007Sdelphij 7827197007Sdelphij CLEAR_FLAG(F_OF); 7828197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7829197007Sdelphij CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7830197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7831197007Sdelphij /* AF == dont care */ 7832197007Sdelphij CLEAR_FLAG(F_CF); 7833197007Sdelphij} 7834197007Sdelphij 7835197007Sdelphij/* 7836197007Sdelphij * REMARKS: 7837197007Sdelphij * Implements the TEST instruction and side effects. 7838197007Sdelphij */ 7839197007Sdelphijstatic void 7840197007Sdelphijtest_word(struct x86emu *emu, uint16_t d, uint16_t s) 7841197007Sdelphij{ 7842197007Sdelphij uint32_t res; /* all operands in native machine order */ 7843197007Sdelphij 7844197007Sdelphij res = d & s; 7845197007Sdelphij 7846197007Sdelphij CLEAR_FLAG(F_OF); 7847197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7848197007Sdelphij CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7849197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7850197007Sdelphij /* AF == dont care */ 7851197007Sdelphij CLEAR_FLAG(F_CF); 7852197007Sdelphij} 7853197007Sdelphij 7854197007Sdelphij/* 7855197007Sdelphij * REMARKS: 7856197007Sdelphij * Implements the TEST instruction and side effects. 7857197007Sdelphij */ 7858197007Sdelphijstatic void 7859197007Sdelphijtest_long(struct x86emu *emu, uint32_t d, uint32_t s) 7860197007Sdelphij{ 7861197007Sdelphij uint32_t res; /* all operands in native machine order */ 7862197007Sdelphij 7863197007Sdelphij res = d & s; 7864197007Sdelphij 7865197007Sdelphij CLEAR_FLAG(F_OF); 7866197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7867197007Sdelphij CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7868197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7869197007Sdelphij /* AF == dont care */ 7870197007Sdelphij CLEAR_FLAG(F_CF); 7871197007Sdelphij} 7872197007Sdelphij 7873197007Sdelphij/* 7874197007Sdelphij * REMARKS: 7875197007Sdelphij * Implements the XOR instruction and side effects. 7876197007Sdelphij */ 7877197007Sdelphijstatic uint8_t 7878197007Sdelphijxor_byte(struct x86emu *emu, uint8_t d, uint8_t s) 7879197007Sdelphij{ 7880197007Sdelphij uint8_t res; /* all operands in native machine order */ 7881197007Sdelphij 7882197007Sdelphij res = d ^ s; 7883197007Sdelphij CLEAR_FLAG(F_OF); 7884197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7885197007Sdelphij CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7886197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 7887197007Sdelphij CLEAR_FLAG(F_CF); 7888197007Sdelphij CLEAR_FLAG(F_AF); 7889197007Sdelphij return res; 7890197007Sdelphij} 7891197007Sdelphij 7892197007Sdelphij/* 7893197007Sdelphij * REMARKS: 7894197007Sdelphij * Implements the XOR instruction and side effects. 7895197007Sdelphij */ 7896197007Sdelphijstatic uint16_t 7897197007Sdelphijxor_word(struct x86emu *emu, uint16_t d, uint16_t s) 7898197007Sdelphij{ 7899197007Sdelphij uint16_t res; /* all operands in native machine order */ 7900197007Sdelphij 7901197007Sdelphij res = d ^ s; 7902197007Sdelphij CLEAR_FLAG(F_OF); 7903197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7904197007Sdelphij CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7905197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7906197007Sdelphij CLEAR_FLAG(F_CF); 7907197007Sdelphij CLEAR_FLAG(F_AF); 7908197007Sdelphij return res; 7909197007Sdelphij} 7910197007Sdelphij 7911197007Sdelphij/* 7912197007Sdelphij * REMARKS: 7913197007Sdelphij * Implements the XOR instruction and side effects. 7914197007Sdelphij */ 7915197007Sdelphijstatic uint32_t 7916197007Sdelphijxor_long(struct x86emu *emu, uint32_t d, uint32_t s) 7917197007Sdelphij{ 7918197007Sdelphij uint32_t res; /* all operands in native machine order */ 7919197007Sdelphij 7920197007Sdelphij res = d ^ s; 7921197007Sdelphij CLEAR_FLAG(F_OF); 7922197007Sdelphij CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7923197007Sdelphij CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7924197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7925197007Sdelphij CLEAR_FLAG(F_CF); 7926197007Sdelphij CLEAR_FLAG(F_AF); 7927197007Sdelphij return res; 7928197007Sdelphij} 7929197007Sdelphij 7930197007Sdelphij/* 7931197007Sdelphij * REMARKS: 7932197007Sdelphij * Implements the IMUL instruction and side effects. 7933197007Sdelphij */ 7934197007Sdelphijstatic void 7935197007Sdelphijimul_byte(struct x86emu *emu, uint8_t s) 7936197007Sdelphij{ 7937197007Sdelphij int16_t res = (int16_t) ((int8_t) emu->x86.R_AL * (int8_t) s); 7938197007Sdelphij 7939197007Sdelphij emu->x86.R_AX = res; 7940197007Sdelphij if (((emu->x86.R_AL & 0x80) == 0 && emu->x86.R_AH == 0x00) || 7941197007Sdelphij ((emu->x86.R_AL & 0x80) != 0 && emu->x86.R_AH == 0xFF)) { 7942197007Sdelphij CLEAR_FLAG(F_CF); 7943197007Sdelphij CLEAR_FLAG(F_OF); 7944197007Sdelphij } else { 7945197007Sdelphij SET_FLAG(F_CF); 7946197007Sdelphij SET_FLAG(F_OF); 7947197007Sdelphij } 7948197007Sdelphij} 7949197007Sdelphij 7950197007Sdelphij/* 7951197007Sdelphij * REMARKS: 7952197007Sdelphij * Implements the IMUL instruction and side effects. 7953197007Sdelphij */ 7954197007Sdelphijstatic void 7955197007Sdelphijimul_word(struct x86emu *emu, uint16_t s) 7956197007Sdelphij{ 7957197007Sdelphij int32_t res = (int16_t) emu->x86.R_AX * (int16_t) s; 7958197007Sdelphij 7959197007Sdelphij emu->x86.R_AX = (uint16_t) res; 7960197007Sdelphij emu->x86.R_DX = (uint16_t) (res >> 16); 7961197007Sdelphij if (((emu->x86.R_AX & 0x8000) == 0 && emu->x86.R_DX == 0x00) || 7962197007Sdelphij ((emu->x86.R_AX & 0x8000) != 0 && emu->x86.R_DX == 0xFF)) { 7963197007Sdelphij CLEAR_FLAG(F_CF); 7964197007Sdelphij CLEAR_FLAG(F_OF); 7965197007Sdelphij } else { 7966197007Sdelphij SET_FLAG(F_CF); 7967197007Sdelphij SET_FLAG(F_OF); 7968197007Sdelphij } 7969197007Sdelphij} 7970197007Sdelphij 7971197007Sdelphij/* 7972197007Sdelphij * REMARKS: 7973197007Sdelphij * Implements the IMUL instruction and side effects. 7974197007Sdelphij */ 7975197007Sdelphijstatic void 7976197007Sdelphijimul_long(struct x86emu *emu, uint32_t s) 7977197007Sdelphij{ 7978197007Sdelphij int64_t res; 7979197007Sdelphij 7980197007Sdelphij res = (int64_t)(int32_t)emu->x86.R_EAX * (int32_t)s; 7981197007Sdelphij emu->x86.R_EAX = (uint32_t)res; 7982197007Sdelphij emu->x86.R_EDX = ((uint64_t)res) >> 32; 7983197007Sdelphij if (((emu->x86.R_EAX & 0x80000000) == 0 && emu->x86.R_EDX == 0x00) || 7984197007Sdelphij ((emu->x86.R_EAX & 0x80000000) != 0 && emu->x86.R_EDX == 0xFF)) { 7985197007Sdelphij CLEAR_FLAG(F_CF); 7986197007Sdelphij CLEAR_FLAG(F_OF); 7987197007Sdelphij } else { 7988197007Sdelphij SET_FLAG(F_CF); 7989197007Sdelphij SET_FLAG(F_OF); 7990197007Sdelphij } 7991197007Sdelphij} 7992197007Sdelphij 7993197007Sdelphij/* 7994197007Sdelphij * REMARKS: 7995197007Sdelphij * Implements the MUL instruction and side effects. 7996197007Sdelphij */ 7997197007Sdelphijstatic void 7998197007Sdelphijmul_byte(struct x86emu *emu, uint8_t s) 7999197007Sdelphij{ 8000197007Sdelphij uint16_t res = (uint16_t) (emu->x86.R_AL * s); 8001197007Sdelphij 8002197007Sdelphij emu->x86.R_AX = res; 8003197007Sdelphij if (emu->x86.R_AH == 0) { 8004197007Sdelphij CLEAR_FLAG(F_CF); 8005197007Sdelphij CLEAR_FLAG(F_OF); 8006197007Sdelphij } else { 8007197007Sdelphij SET_FLAG(F_CF); 8008197007Sdelphij SET_FLAG(F_OF); 8009197007Sdelphij } 8010197007Sdelphij} 8011197007Sdelphij 8012197007Sdelphij/* 8013197007Sdelphij * REMARKS: 8014197007Sdelphij * Implements the MUL instruction and side effects. 8015197007Sdelphij */ 8016197007Sdelphijstatic void 8017197007Sdelphijmul_word(struct x86emu *emu, uint16_t s) 8018197007Sdelphij{ 8019197007Sdelphij uint32_t res = emu->x86.R_AX * s; 8020197007Sdelphij 8021197007Sdelphij emu->x86.R_AX = (uint16_t) res; 8022197007Sdelphij emu->x86.R_DX = (uint16_t) (res >> 16); 8023197007Sdelphij if (emu->x86.R_DX == 0) { 8024197007Sdelphij CLEAR_FLAG(F_CF); 8025197007Sdelphij CLEAR_FLAG(F_OF); 8026197007Sdelphij } else { 8027197007Sdelphij SET_FLAG(F_CF); 8028197007Sdelphij SET_FLAG(F_OF); 8029197007Sdelphij } 8030197007Sdelphij} 8031197007Sdelphij 8032197007Sdelphij/* 8033197007Sdelphij * REMARKS: 8034197007Sdelphij * Implements the MUL instruction and side effects. 8035197007Sdelphij */ 8036197007Sdelphijstatic void 8037197007Sdelphijmul_long(struct x86emu *emu, uint32_t s) 8038197007Sdelphij{ 8039197007Sdelphij uint64_t res = (uint64_t) emu->x86.R_EAX * s; 8040197007Sdelphij 8041197007Sdelphij emu->x86.R_EAX = (uint32_t) res; 8042197007Sdelphij emu->x86.R_EDX = (uint32_t) (res >> 32); 8043197007Sdelphij 8044197007Sdelphij if (emu->x86.R_EDX == 0) { 8045197007Sdelphij CLEAR_FLAG(F_CF); 8046197007Sdelphij CLEAR_FLAG(F_OF); 8047197007Sdelphij } else { 8048197007Sdelphij SET_FLAG(F_CF); 8049197007Sdelphij SET_FLAG(F_OF); 8050197007Sdelphij } 8051197007Sdelphij} 8052197007Sdelphij 8053197007Sdelphij/* 8054197007Sdelphij * REMARKS: 8055197007Sdelphij * Implements the IDIV instruction and side effects. 8056197007Sdelphij */ 8057197007Sdelphijstatic void 8058197007Sdelphijidiv_byte(struct x86emu *emu, uint8_t s) 8059197007Sdelphij{ 8060197007Sdelphij int32_t dvd, div, mod; 8061197007Sdelphij 8062197007Sdelphij dvd = (int16_t) emu->x86.R_AX; 8063197007Sdelphij if (s == 0) { 8064197007Sdelphij x86emu_intr_raise(emu, 8); 8065197007Sdelphij return; 8066197007Sdelphij } 8067197007Sdelphij div = dvd / (int8_t) s; 8068197007Sdelphij mod = dvd % (int8_t) s; 8069197007Sdelphij if (div > 0x7f || div < -0x7f) { 8070197007Sdelphij x86emu_intr_raise(emu, 8); 8071197007Sdelphij return; 8072197007Sdelphij } 8073197007Sdelphij emu->x86.R_AL = (int8_t) div; 8074197007Sdelphij emu->x86.R_AH = (int8_t) mod; 8075197007Sdelphij} 8076197007Sdelphij 8077197007Sdelphij/* 8078197007Sdelphij * REMARKS: 8079197007Sdelphij * Implements the IDIV instruction and side effects. 8080197007Sdelphij */ 8081197007Sdelphijstatic void 8082197007Sdelphijidiv_word(struct x86emu *emu, uint16_t s) 8083197007Sdelphij{ 8084197007Sdelphij int32_t dvd, div, mod; 8085197007Sdelphij 8086197007Sdelphij dvd = (((int32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX; 8087197007Sdelphij if (s == 0) { 8088197007Sdelphij x86emu_intr_raise(emu, 8); 8089197007Sdelphij return; 8090197007Sdelphij } 8091197007Sdelphij div = dvd / (int16_t) s; 8092197007Sdelphij mod = dvd % (int16_t) s; 8093197007Sdelphij if (div > 0x7fff || div < -0x7fff) { 8094197007Sdelphij x86emu_intr_raise(emu, 8); 8095197007Sdelphij return; 8096197007Sdelphij } 8097197007Sdelphij CLEAR_FLAG(F_CF); 8098197007Sdelphij CLEAR_FLAG(F_SF); 8099197007Sdelphij CONDITIONAL_SET_FLAG(div == 0, F_ZF); 8100197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 8101197007Sdelphij 8102197007Sdelphij emu->x86.R_AX = (uint16_t) div; 8103197007Sdelphij emu->x86.R_DX = (uint16_t) mod; 8104197007Sdelphij} 8105197007Sdelphij 8106197007Sdelphij/* 8107197007Sdelphij * REMARKS: 8108197007Sdelphij * Implements the IDIV instruction and side effects. 8109197007Sdelphij */ 8110197007Sdelphijstatic void 8111197007Sdelphijidiv_long(struct x86emu *emu, uint32_t s) 8112197007Sdelphij{ 8113197007Sdelphij int64_t dvd, div, mod; 8114197007Sdelphij 8115197007Sdelphij dvd = (((int64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX; 8116197007Sdelphij if (s == 0) { 8117197007Sdelphij x86emu_intr_raise(emu, 8); 8118197007Sdelphij return; 8119197007Sdelphij } 8120197007Sdelphij div = dvd / (int32_t) s; 8121197007Sdelphij mod = dvd % (int32_t) s; 8122197007Sdelphij if (div > 0x7fffffff || div < -0x7fffffff) { 8123197007Sdelphij x86emu_intr_raise(emu, 8); 8124197007Sdelphij return; 8125197007Sdelphij } 8126197007Sdelphij CLEAR_FLAG(F_CF); 8127197007Sdelphij CLEAR_FLAG(F_AF); 8128197007Sdelphij CLEAR_FLAG(F_SF); 8129197007Sdelphij SET_FLAG(F_ZF); 8130197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 8131197007Sdelphij 8132197007Sdelphij emu->x86.R_EAX = (uint32_t) div; 8133197007Sdelphij emu->x86.R_EDX = (uint32_t) mod; 8134197007Sdelphij} 8135197007Sdelphij 8136197007Sdelphij/* 8137197007Sdelphij * REMARKS: 8138197007Sdelphij * Implements the DIV instruction and side effects. 8139197007Sdelphij */ 8140197007Sdelphijstatic void 8141197007Sdelphijdiv_byte(struct x86emu *emu, uint8_t s) 8142197007Sdelphij{ 8143197007Sdelphij uint32_t dvd, div, mod; 8144197007Sdelphij 8145197007Sdelphij dvd = emu->x86.R_AX; 8146197007Sdelphij if (s == 0) { 8147197007Sdelphij x86emu_intr_raise(emu, 8); 8148197007Sdelphij return; 8149197007Sdelphij } 8150197007Sdelphij div = dvd / (uint8_t) s; 8151197007Sdelphij mod = dvd % (uint8_t) s; 8152197007Sdelphij if (div > 0xff) { 8153197007Sdelphij x86emu_intr_raise(emu, 8); 8154197007Sdelphij return; 8155197007Sdelphij } 8156197007Sdelphij emu->x86.R_AL = (uint8_t) div; 8157197007Sdelphij emu->x86.R_AH = (uint8_t) mod; 8158197007Sdelphij} 8159197007Sdelphij 8160197007Sdelphij/* 8161197007Sdelphij * REMARKS: 8162197007Sdelphij * Implements the DIV instruction and side effects. 8163197007Sdelphij */ 8164197007Sdelphijstatic void 8165197007Sdelphijdiv_word(struct x86emu *emu, uint16_t s) 8166197007Sdelphij{ 8167197007Sdelphij uint32_t dvd, div, mod; 8168197007Sdelphij 8169197007Sdelphij dvd = (((uint32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX; 8170197007Sdelphij if (s == 0) { 8171197007Sdelphij x86emu_intr_raise(emu, 8); 8172197007Sdelphij return; 8173197007Sdelphij } 8174197007Sdelphij div = dvd / (uint16_t) s; 8175197007Sdelphij mod = dvd % (uint16_t) s; 8176197007Sdelphij if (div > 0xffff) { 8177197007Sdelphij x86emu_intr_raise(emu, 8); 8178197007Sdelphij return; 8179197007Sdelphij } 8180197007Sdelphij CLEAR_FLAG(F_CF); 8181197007Sdelphij CLEAR_FLAG(F_SF); 8182197007Sdelphij CONDITIONAL_SET_FLAG(div == 0, F_ZF); 8183197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 8184197007Sdelphij 8185197007Sdelphij emu->x86.R_AX = (uint16_t) div; 8186197007Sdelphij emu->x86.R_DX = (uint16_t) mod; 8187197007Sdelphij} 8188197007Sdelphij 8189197007Sdelphij/* 8190197007Sdelphij * REMARKS: 8191197007Sdelphij * Implements the DIV instruction and side effects. 8192197007Sdelphij */ 8193197007Sdelphijstatic void 8194197007Sdelphijdiv_long(struct x86emu *emu, uint32_t s) 8195197007Sdelphij{ 8196197007Sdelphij uint64_t dvd, div, mod; 8197197007Sdelphij 8198197007Sdelphij dvd = (((uint64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX; 8199197007Sdelphij if (s == 0) { 8200197007Sdelphij x86emu_intr_raise(emu, 8); 8201197007Sdelphij return; 8202197007Sdelphij } 8203197007Sdelphij div = dvd / (uint32_t) s; 8204197007Sdelphij mod = dvd % (uint32_t) s; 8205197007Sdelphij if (div > 0xffffffff) { 8206197007Sdelphij x86emu_intr_raise(emu, 8); 8207197007Sdelphij return; 8208197007Sdelphij } 8209197007Sdelphij CLEAR_FLAG(F_CF); 8210197007Sdelphij CLEAR_FLAG(F_AF); 8211197007Sdelphij CLEAR_FLAG(F_SF); 8212197007Sdelphij SET_FLAG(F_ZF); 8213197007Sdelphij CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 8214197007Sdelphij 8215197007Sdelphij emu->x86.R_EAX = (uint32_t) div; 8216197007Sdelphij emu->x86.R_EDX = (uint32_t) mod; 8217197007Sdelphij} 8218197007Sdelphij 8219197007Sdelphij/* 8220197007Sdelphij * REMARKS: 8221197007Sdelphij * Implements the IN string instruction and side effects. 8222197007Sdelphij */ 8223197007Sdelphijstatic void 8224197007Sdelphijins(struct x86emu *emu, int size) 8225197007Sdelphij{ 8226197007Sdelphij int inc = size; 8227197007Sdelphij 8228197007Sdelphij if (ACCESS_FLAG(F_DF)) { 8229197007Sdelphij inc = -size; 8230197007Sdelphij } 8231197007Sdelphij if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 8232197007Sdelphij /* dont care whether REPE or REPNE */ 8233197007Sdelphij /* in until CX is ZERO. */ 8234197007Sdelphij uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ? 8235197007Sdelphij emu->x86.R_ECX : emu->x86.R_CX); 8236197007Sdelphij switch (size) { 8237197007Sdelphij case 1: 8238197007Sdelphij while (count--) { 8239197007Sdelphij store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, 8240197007Sdelphij (*emu->emu_inb) (emu, emu->x86.R_DX)); 8241197007Sdelphij emu->x86.R_DI += inc; 8242197007Sdelphij } 8243197007Sdelphij break; 8244197007Sdelphij 8245197007Sdelphij case 2: 8246197007Sdelphij while (count--) { 8247197007Sdelphij store_word(emu, emu->x86.R_ES, emu->x86.R_DI, 8248197007Sdelphij (*emu->emu_inw) (emu, emu->x86.R_DX)); 8249197007Sdelphij emu->x86.R_DI += inc; 8250197007Sdelphij } 8251197007Sdelphij break; 8252197007Sdelphij case 4: 8253197007Sdelphij while (count--) { 8254197007Sdelphij store_long(emu, emu->x86.R_ES, emu->x86.R_DI, 8255197007Sdelphij (*emu->emu_inl) (emu, emu->x86.R_DX)); 8256197007Sdelphij emu->x86.R_DI += inc; 8257197007Sdelphij break; 8258197007Sdelphij } 8259197007Sdelphij } 8260197007Sdelphij emu->x86.R_CX = 0; 8261197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 8262197007Sdelphij emu->x86.R_ECX = 0; 8263197007Sdelphij } 8264197007Sdelphij emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 8265197007Sdelphij } else { 8266197007Sdelphij switch (size) { 8267197007Sdelphij case 1: 8268197007Sdelphij store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, 8269197007Sdelphij (*emu->emu_inb) (emu, emu->x86.R_DX)); 8270197007Sdelphij break; 8271197007Sdelphij case 2: 8272197007Sdelphij store_word(emu, emu->x86.R_ES, emu->x86.R_DI, 8273197007Sdelphij (*emu->emu_inw) (emu, emu->x86.R_DX)); 8274197007Sdelphij break; 8275197007Sdelphij case 4: 8276197007Sdelphij store_long(emu, emu->x86.R_ES, emu->x86.R_DI, 8277197007Sdelphij (*emu->emu_inl) (emu, emu->x86.R_DX)); 8278197007Sdelphij break; 8279197007Sdelphij } 8280197007Sdelphij emu->x86.R_DI += inc; 8281197007Sdelphij } 8282197007Sdelphij} 8283197007Sdelphij 8284197007Sdelphij/* 8285197007Sdelphij * REMARKS: 8286197007Sdelphij * Implements the OUT string instruction and side effects. 8287197007Sdelphij */ 8288197007Sdelphijstatic void 8289197007Sdelphijouts(struct x86emu *emu, int size) 8290197007Sdelphij{ 8291197007Sdelphij int inc = size; 8292197007Sdelphij 8293197007Sdelphij if (ACCESS_FLAG(F_DF)) { 8294197007Sdelphij inc = -size; 8295197007Sdelphij } 8296197007Sdelphij if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 8297197007Sdelphij /* dont care whether REPE or REPNE */ 8298197007Sdelphij /* out until CX is ZERO. */ 8299197007Sdelphij uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ? 8300197007Sdelphij emu->x86.R_ECX : emu->x86.R_CX); 8301197007Sdelphij switch (size) { 8302197007Sdelphij case 1: 8303197007Sdelphij while (count--) { 8304197007Sdelphij (*emu->emu_outb) (emu, emu->x86.R_DX, 8305204934Sdelphij fetch_byte(emu, emu->x86.R_ES, 8306204934Sdelphij emu->x86.R_SI)); 8307197007Sdelphij emu->x86.R_SI += inc; 8308197007Sdelphij } 8309197007Sdelphij break; 8310197007Sdelphij 8311197007Sdelphij case 2: 8312197007Sdelphij while (count--) { 8313197007Sdelphij (*emu->emu_outw) (emu, emu->x86.R_DX, 8314204934Sdelphij fetch_word(emu, emu->x86.R_ES, 8315204934Sdelphij emu->x86.R_SI)); 8316197007Sdelphij emu->x86.R_SI += inc; 8317197007Sdelphij } 8318197007Sdelphij break; 8319197007Sdelphij case 4: 8320197007Sdelphij while (count--) { 8321197007Sdelphij (*emu->emu_outl) (emu, emu->x86.R_DX, 8322204934Sdelphij fetch_long(emu, emu->x86.R_ES, 8323204934Sdelphij emu->x86.R_SI)); 8324197007Sdelphij emu->x86.R_SI += inc; 8325197007Sdelphij break; 8326197007Sdelphij } 8327197007Sdelphij } 8328197007Sdelphij emu->x86.R_CX = 0; 8329197007Sdelphij if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 8330197007Sdelphij emu->x86.R_ECX = 0; 8331197007Sdelphij } 8332197007Sdelphij emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 8333197007Sdelphij } else { 8334197007Sdelphij switch (size) { 8335197007Sdelphij case 1: 8336197007Sdelphij (*emu->emu_outb) (emu, emu->x86.R_DX, 8337197007Sdelphij fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI)); 8338197007Sdelphij break; 8339197007Sdelphij case 2: 8340197007Sdelphij (*emu->emu_outw) (emu, emu->x86.R_DX, 8341197007Sdelphij fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI)); 8342197007Sdelphij break; 8343197007Sdelphij case 4: 8344197007Sdelphij (*emu->emu_outl) (emu, emu->x86.R_DX, 8345197007Sdelphij fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI)); 8346197007Sdelphij break; 8347197007Sdelphij } 8348197007Sdelphij emu->x86.R_SI += inc; 8349197007Sdelphij } 8350197007Sdelphij} 8351197007Sdelphij 8352197007Sdelphij/* 8353197007Sdelphij * REMARKS: 8354197007Sdelphij * Pushes a word onto the stack. 8355197007Sdelphij * 8356197007Sdelphij * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline! 8357197007Sdelphij */ 8358197007Sdelphijstatic void 8359197007Sdelphijpush_word(struct x86emu *emu, uint16_t w) 8360197007Sdelphij{ 8361197007Sdelphij emu->x86.R_SP -= 2; 8362197007Sdelphij store_word(emu, emu->x86.R_SS, emu->x86.R_SP, w); 8363197007Sdelphij} 8364197007Sdelphij 8365197007Sdelphij/* 8366197007Sdelphij * REMARKS: 8367197007Sdelphij * Pushes a long onto the stack. 8368197007Sdelphij * 8369197007Sdelphij * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline! 8370197007Sdelphij */ 8371197007Sdelphijstatic void 8372197007Sdelphijpush_long(struct x86emu *emu, uint32_t w) 8373197007Sdelphij{ 8374197007Sdelphij emu->x86.R_SP -= 4; 8375197007Sdelphij store_long(emu, emu->x86.R_SS, emu->x86.R_SP, w); 8376197007Sdelphij} 8377197007Sdelphij 8378197007Sdelphij/* 8379197007Sdelphij * REMARKS: 8380197007Sdelphij * Pops a word from the stack. 8381197007Sdelphij * 8382197007Sdelphij * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline! 8383197007Sdelphij */ 8384197007Sdelphijstatic uint16_t 8385197007Sdelphijpop_word(struct x86emu *emu) 8386197007Sdelphij{ 8387197007Sdelphij uint16_t res; 8388197007Sdelphij 8389197007Sdelphij res = fetch_word(emu, emu->x86.R_SS, emu->x86.R_SP); 8390197007Sdelphij emu->x86.R_SP += 2; 8391197007Sdelphij return res; 8392197007Sdelphij} 8393197007Sdelphij 8394197007Sdelphij/* 8395197007Sdelphij * REMARKS: 8396197007Sdelphij * Pops a long from the stack. 8397197007Sdelphij * 8398197007Sdelphij * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline! 8399197007Sdelphij */ 8400197007Sdelphijstatic uint32_t 8401197007Sdelphijpop_long(struct x86emu *emu) 8402197007Sdelphij{ 8403197007Sdelphij uint32_t res; 8404197007Sdelphij 8405197007Sdelphij res = fetch_long(emu, emu->x86.R_SS, emu->x86.R_SP); 8406197007Sdelphij emu->x86.R_SP += 4; 8407197007Sdelphij return res; 8408197007Sdelphij} 8409