1 1.12 msaitoh 2 1.14 andvar /* $NetBSD: x86emu.c,v 1.14 2022/11/01 19:45:35 andvar Exp $ */ 3 1.1 joerg 4 1.1 joerg /**************************************************************************** 5 1.1 joerg * 6 1.1 joerg * Realmode X86 Emulator Library 7 1.1 joerg * 8 1.1 joerg * Copyright (C) 1996-1999 SciTech Software, Inc. 9 1.1 joerg * Copyright (C) David Mosberger-Tang 10 1.1 joerg * Copyright (C) 1999 Egbert Eich 11 1.1 joerg * Copyright (C) 2007 Joerg Sonnenberger 12 1.1 joerg * 13 1.1 joerg * ======================================================================== 14 1.1 joerg * 15 1.1 joerg * Permission to use, copy, modify, distribute, and sell this software and 16 1.1 joerg * its documentation for any purpose is hereby granted without fee, 17 1.1 joerg * provided that the above copyright notice appear in all copies and that 18 1.1 joerg * both that copyright notice and this permission notice appear in 19 1.1 joerg * supporting documentation, and that the name of the authors not be used 20 1.1 joerg * in advertising or publicity pertaining to distribution of the software 21 1.1 joerg * without specific, written prior permission. The authors makes no 22 1.1 joerg * representations about the suitability of this software for any purpose. 23 1.1 joerg * It is provided "as is" without express or implied warranty. 24 1.1 joerg * 25 1.1 joerg * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 26 1.1 joerg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 27 1.1 joerg * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 28 1.1 joerg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 29 1.1 joerg * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 30 1.1 joerg * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 31 1.1 joerg * PERFORMANCE OF THIS SOFTWARE. 32 1.1 joerg * 33 1.1 joerg ****************************************************************************/ 34 1.1 joerg 35 1.1 joerg #ifndef _KERNEL 36 1.1 joerg #include <stdbool.h> 37 1.1 joerg #endif 38 1.1 joerg 39 1.2 joerg #include <x86emu/x86emu.h> 40 1.2 joerg #include <x86emu/x86emu_regs.h> 41 1.1 joerg 42 1.1 joerg static void x86emu_intr_raise (struct X86EMU *, uint8_t type); 43 1.1 joerg 44 1.1 joerg static void X86EMU_exec_one_byte(struct X86EMU *); 45 1.1 joerg static void X86EMU_exec_two_byte(struct X86EMU *); 46 1.1 joerg 47 1.1 joerg static void fetch_decode_modrm (struct X86EMU *); 48 1.1 joerg static uint8_t fetch_byte_imm (struct X86EMU *); 49 1.1 joerg static uint16_t fetch_word_imm (struct X86EMU *); 50 1.1 joerg static uint32_t fetch_long_imm (struct X86EMU *); 51 1.1 joerg static uint8_t fetch_data_byte (struct X86EMU *, uint32_t offset); 52 1.1 joerg static uint8_t fetch_byte (struct X86EMU *, uint segment, uint32_t offset); 53 1.1 joerg static uint16_t fetch_data_word (struct X86EMU *, uint32_t offset); 54 1.1 joerg static uint16_t fetch_word (struct X86EMU *, uint32_t segment, uint32_t offset); 55 1.1 joerg static uint32_t fetch_data_long (struct X86EMU *, uint32_t offset); 56 1.1 joerg static uint32_t fetch_long (struct X86EMU *, uint32_t segment, uint32_t offset); 57 1.1 joerg static void store_data_byte (struct X86EMU *, uint32_t offset, uint8_t val); 58 1.1 joerg static void store_byte (struct X86EMU *, uint32_t segment, uint32_t offset, uint8_t val); 59 1.1 joerg static void store_data_word (struct X86EMU *, uint32_t offset, uint16_t val); 60 1.1 joerg static void store_word (struct X86EMU *, uint32_t segment, uint32_t offset, uint16_t val); 61 1.1 joerg static void store_data_long (struct X86EMU *, uint32_t offset, uint32_t val); 62 1.1 joerg static void store_long (struct X86EMU *, uint32_t segment, uint32_t offset, uint32_t val); 63 1.1 joerg static uint8_t* decode_rl_byte_register(struct X86EMU *); 64 1.1 joerg static uint16_t* decode_rl_word_register(struct X86EMU *); 65 1.1 joerg static uint32_t* decode_rl_long_register(struct X86EMU *); 66 1.1 joerg static uint8_t* decode_rh_byte_register(struct X86EMU *); 67 1.1 joerg static uint16_t* decode_rh_word_register(struct X86EMU *); 68 1.1 joerg static uint32_t* decode_rh_long_register(struct X86EMU *); 69 1.1 joerg static uint16_t* decode_rh_seg_register(struct X86EMU *); 70 1.1 joerg static uint32_t decode_rl_address(struct X86EMU *); 71 1.1 joerg 72 1.1 joerg static uint8_t decode_and_fetch_byte(struct X86EMU *); 73 1.1 joerg static uint16_t decode_and_fetch_word(struct X86EMU *); 74 1.1 joerg static uint32_t decode_and_fetch_long(struct X86EMU *); 75 1.1 joerg 76 1.1 joerg static uint8_t decode_and_fetch_byte_imm8(struct X86EMU *, uint8_t *); 77 1.1 joerg static uint16_t decode_and_fetch_word_imm8(struct X86EMU *, uint8_t *); 78 1.1 joerg static uint32_t decode_and_fetch_long_imm8(struct X86EMU *, uint8_t *); 79 1.1 joerg 80 1.1 joerg static uint16_t decode_and_fetch_word_disp(struct X86EMU *, int16_t); 81 1.1 joerg static uint32_t decode_and_fetch_long_disp(struct X86EMU *, int16_t); 82 1.1 joerg 83 1.1 joerg static void write_back_byte(struct X86EMU *, uint8_t); 84 1.1 joerg static void write_back_word(struct X86EMU *, uint16_t); 85 1.1 joerg static void write_back_long(struct X86EMU *, uint32_t); 86 1.1 joerg 87 1.1 joerg static uint16_t aaa_word (struct X86EMU *, uint16_t d); 88 1.1 joerg static uint16_t aas_word (struct X86EMU *, uint16_t d); 89 1.1 joerg static uint16_t aad_word (struct X86EMU *, uint16_t d); 90 1.1 joerg static uint16_t aam_word (struct X86EMU *, uint8_t d); 91 1.1 joerg static uint8_t adc_byte (struct X86EMU *, uint8_t d, uint8_t s); 92 1.1 joerg static uint16_t adc_word (struct X86EMU *, uint16_t d, uint16_t s); 93 1.1 joerg static uint32_t adc_long (struct X86EMU *, uint32_t d, uint32_t s); 94 1.1 joerg static uint8_t add_byte (struct X86EMU *, uint8_t d, uint8_t s); 95 1.1 joerg static uint16_t add_word (struct X86EMU *, uint16_t d, uint16_t s); 96 1.1 joerg static uint32_t add_long (struct X86EMU *, uint32_t d, uint32_t s); 97 1.1 joerg static uint8_t and_byte (struct X86EMU *, uint8_t d, uint8_t s); 98 1.1 joerg static uint16_t and_word (struct X86EMU *, uint16_t d, uint16_t s); 99 1.1 joerg static uint32_t and_long (struct X86EMU *, uint32_t d, uint32_t s); 100 1.1 joerg static uint8_t cmp_byte (struct X86EMU *, uint8_t d, uint8_t s); 101 1.1 joerg static uint16_t cmp_word (struct X86EMU *, uint16_t d, uint16_t s); 102 1.1 joerg static uint32_t cmp_long (struct X86EMU *, uint32_t d, uint32_t s); 103 1.1 joerg static void cmp_byte_no_return (struct X86EMU *, uint8_t d, uint8_t s); 104 1.1 joerg static void cmp_word_no_return (struct X86EMU *, uint16_t d, uint16_t s); 105 1.1 joerg static void cmp_long_no_return (struct X86EMU *, uint32_t d, uint32_t s); 106 1.1 joerg static uint8_t daa_byte (struct X86EMU *, uint8_t d); 107 1.1 joerg static uint8_t das_byte (struct X86EMU *, uint8_t d); 108 1.1 joerg static uint8_t dec_byte (struct X86EMU *, uint8_t d); 109 1.1 joerg static uint16_t dec_word (struct X86EMU *, uint16_t d); 110 1.1 joerg static uint32_t dec_long (struct X86EMU *, uint32_t d); 111 1.1 joerg static uint8_t inc_byte (struct X86EMU *, uint8_t d); 112 1.1 joerg static uint16_t inc_word (struct X86EMU *, uint16_t d); 113 1.1 joerg static uint32_t inc_long (struct X86EMU *, uint32_t d); 114 1.1 joerg static uint8_t or_byte (struct X86EMU *, uint8_t d, uint8_t s); 115 1.1 joerg static uint16_t or_word (struct X86EMU *, uint16_t d, uint16_t s); 116 1.1 joerg static uint32_t or_long (struct X86EMU *, uint32_t d, uint32_t s); 117 1.1 joerg static uint8_t neg_byte (struct X86EMU *, uint8_t s); 118 1.1 joerg static uint16_t neg_word (struct X86EMU *, uint16_t s); 119 1.1 joerg static uint32_t neg_long (struct X86EMU *, uint32_t s); 120 1.1 joerg static uint8_t rcl_byte (struct X86EMU *, uint8_t d, uint8_t s); 121 1.1 joerg static uint16_t rcl_word (struct X86EMU *, uint16_t d, uint8_t s); 122 1.1 joerg static uint32_t rcl_long (struct X86EMU *, uint32_t d, uint8_t s); 123 1.1 joerg static uint8_t rcr_byte (struct X86EMU *, uint8_t d, uint8_t s); 124 1.1 joerg static uint16_t rcr_word (struct X86EMU *, uint16_t d, uint8_t s); 125 1.1 joerg static uint32_t rcr_long (struct X86EMU *, uint32_t d, uint8_t s); 126 1.1 joerg static uint8_t rol_byte (struct X86EMU *, uint8_t d, uint8_t s); 127 1.1 joerg static uint16_t rol_word (struct X86EMU *, uint16_t d, uint8_t s); 128 1.1 joerg static uint32_t rol_long (struct X86EMU *, uint32_t d, uint8_t s); 129 1.1 joerg static uint8_t ror_byte (struct X86EMU *, uint8_t d, uint8_t s); 130 1.1 joerg static uint16_t ror_word (struct X86EMU *, uint16_t d, uint8_t s); 131 1.1 joerg static uint32_t ror_long (struct X86EMU *, uint32_t d, uint8_t s); 132 1.1 joerg static uint8_t shl_byte (struct X86EMU *, uint8_t d, uint8_t s); 133 1.1 joerg static uint16_t shl_word (struct X86EMU *, uint16_t d, uint8_t s); 134 1.1 joerg static uint32_t shl_long (struct X86EMU *, uint32_t d, uint8_t s); 135 1.1 joerg static uint8_t shr_byte (struct X86EMU *, uint8_t d, uint8_t s); 136 1.1 joerg static uint16_t shr_word (struct X86EMU *, uint16_t d, uint8_t s); 137 1.1 joerg static uint32_t shr_long (struct X86EMU *, uint32_t d, uint8_t s); 138 1.1 joerg static uint8_t sar_byte (struct X86EMU *, uint8_t d, uint8_t s); 139 1.1 joerg static uint16_t sar_word (struct X86EMU *, uint16_t d, uint8_t s); 140 1.1 joerg static uint32_t sar_long (struct X86EMU *, uint32_t d, uint8_t s); 141 1.1 joerg static uint16_t shld_word (struct X86EMU *, uint16_t d, uint16_t fill, uint8_t s); 142 1.1 joerg static uint32_t shld_long (struct X86EMU *, uint32_t d, uint32_t fill, uint8_t s); 143 1.1 joerg static uint16_t shrd_word (struct X86EMU *, uint16_t d, uint16_t fill, uint8_t s); 144 1.1 joerg static uint32_t shrd_long (struct X86EMU *, uint32_t d, uint32_t fill, uint8_t s); 145 1.1 joerg static uint8_t sbb_byte (struct X86EMU *, uint8_t d, uint8_t s); 146 1.1 joerg static uint16_t sbb_word (struct X86EMU *, uint16_t d, uint16_t s); 147 1.1 joerg static uint32_t sbb_long (struct X86EMU *, uint32_t d, uint32_t s); 148 1.1 joerg static uint8_t sub_byte (struct X86EMU *, uint8_t d, uint8_t s); 149 1.1 joerg static uint16_t sub_word (struct X86EMU *, uint16_t d, uint16_t s); 150 1.1 joerg static uint32_t sub_long (struct X86EMU *, uint32_t d, uint32_t s); 151 1.1 joerg static void test_byte (struct X86EMU *, uint8_t d, uint8_t s); 152 1.1 joerg static void test_word (struct X86EMU *, uint16_t d, uint16_t s); 153 1.1 joerg static void test_long (struct X86EMU *, uint32_t d, uint32_t s); 154 1.1 joerg static uint8_t xor_byte (struct X86EMU *, uint8_t d, uint8_t s); 155 1.1 joerg static uint16_t xor_word (struct X86EMU *, uint16_t d, uint16_t s); 156 1.1 joerg static uint32_t xor_long (struct X86EMU *, uint32_t d, uint32_t s); 157 1.1 joerg static void imul_byte (struct X86EMU *, uint8_t s); 158 1.1 joerg static void imul_word (struct X86EMU *, uint16_t s); 159 1.1 joerg static void imul_long (struct X86EMU *, uint32_t s); 160 1.1 joerg static void mul_byte (struct X86EMU *, uint8_t s); 161 1.1 joerg static void mul_word (struct X86EMU *, uint16_t s); 162 1.1 joerg static void mul_long (struct X86EMU *, uint32_t s); 163 1.1 joerg static void idiv_byte (struct X86EMU *, uint8_t s); 164 1.1 joerg static void idiv_word (struct X86EMU *, uint16_t s); 165 1.1 joerg static void idiv_long (struct X86EMU *, uint32_t s); 166 1.1 joerg static void div_byte (struct X86EMU *, uint8_t s); 167 1.1 joerg static void div_word (struct X86EMU *, uint16_t s); 168 1.1 joerg static void div_long (struct X86EMU *, uint32_t s); 169 1.1 joerg static void ins (struct X86EMU *, int size); 170 1.1 joerg static void outs (struct X86EMU *, int size); 171 1.1 joerg static void push_word (struct X86EMU *, uint16_t w); 172 1.1 joerg static void push_long (struct X86EMU *, uint32_t w); 173 1.1 joerg static uint16_t pop_word (struct X86EMU *); 174 1.1 joerg static uint32_t pop_long (struct X86EMU *); 175 1.1 joerg 176 1.1 joerg /**************************************************************************** 177 1.1 joerg REMARKS: 178 1.12 msaitoh Handles any pending asynchronous interrupts. 179 1.1 joerg ****************************************************************************/ 180 1.3 joerg static void 181 1.3 joerg x86emu_intr_dispatch(struct X86EMU *emu, uint8_t intno) 182 1.3 joerg { 183 1.3 joerg if (emu->_X86EMU_intrTab[intno]) { 184 1.3 joerg (*emu->_X86EMU_intrTab[intno]) (emu, intno); 185 1.3 joerg } else { 186 1.3 joerg push_word(emu, (uint16_t) emu->x86.R_FLG); 187 1.3 joerg CLEAR_FLAG(F_IF); 188 1.3 joerg CLEAR_FLAG(F_TF); 189 1.3 joerg push_word(emu, emu->x86.R_CS); 190 1.3 joerg emu->x86.R_CS = fetch_word(emu, 0, intno * 4 + 2); 191 1.3 joerg push_word(emu, emu->x86.R_IP); 192 1.3 joerg emu->x86.R_IP = fetch_word(emu, 0, intno * 4); 193 1.3 joerg } 194 1.3 joerg } 195 1.3 joerg 196 1.1 joerg static void 197 1.1 joerg x86emu_intr_handle(struct X86EMU *emu) 198 1.1 joerg { 199 1.1 joerg uint8_t intno; 200 1.1 joerg 201 1.1 joerg if (emu->x86.intr & INTR_SYNCH) { 202 1.1 joerg intno = emu->x86.intno; 203 1.3 joerg emu->x86.intr = 0; 204 1.3 joerg x86emu_intr_dispatch(emu, intno); 205 1.1 joerg } 206 1.1 joerg } 207 1.1 joerg /**************************************************************************** 208 1.1 joerg PARAMETERS: 209 1.1 joerg intrnum - Interrupt number to raise 210 1.1 joerg 211 1.1 joerg REMARKS: 212 1.1 joerg Raise the specified interrupt to be handled before the execution of the 213 1.1 joerg next instruction. 214 1.1 joerg ****************************************************************************/ 215 1.1 joerg void 216 1.1 joerg x86emu_intr_raise(struct X86EMU *emu, uint8_t intrnum) 217 1.1 joerg { 218 1.1 joerg emu->x86.intno = intrnum; 219 1.1 joerg emu->x86.intr |= INTR_SYNCH; 220 1.1 joerg } 221 1.1 joerg /**************************************************************************** 222 1.1 joerg REMARKS: 223 1.1 joerg Main execution loop for the emulator. We return from here when the system 224 1.1 joerg halts, which is normally caused by a stack fault when we return from the 225 1.1 joerg original real mode call. 226 1.1 joerg ****************************************************************************/ 227 1.1 joerg void 228 1.1 joerg X86EMU_exec(struct X86EMU *emu) 229 1.1 joerg { 230 1.1 joerg emu->x86.intr = 0; 231 1.1 joerg 232 1.1 joerg #ifdef _KERNEL 233 1.1 joerg if (setjmp(&emu->exec_state)) 234 1.1 joerg return; 235 1.1 joerg #else 236 1.1 joerg if (setjmp(emu->exec_state)) 237 1.1 joerg return; 238 1.1 joerg #endif 239 1.1 joerg 240 1.1 joerg for (;;) { 241 1.1 joerg if (emu->x86.intr) { 242 1.1 joerg if (((emu->x86.intr & INTR_SYNCH) && (emu->x86.intno == 0 || emu->x86.intno == 2)) || 243 1.1 joerg !ACCESS_FLAG(F_IF)) { 244 1.1 joerg x86emu_intr_handle(emu); 245 1.1 joerg } 246 1.1 joerg } 247 1.7 joerg if (emu->x86.R_CS == 0 && emu->x86.R_IP == 0) 248 1.7 joerg return; 249 1.1 joerg X86EMU_exec_one_byte(emu); 250 1.1 joerg ++emu->cur_cycles; 251 1.1 joerg } 252 1.1 joerg } 253 1.1 joerg 254 1.1 joerg void 255 1.1 joerg X86EMU_exec_call(struct X86EMU *emu, uint16_t seg, uint16_t off) 256 1.1 joerg { 257 1.1 joerg push_word(emu, 0); 258 1.1 joerg push_word(emu, 0); 259 1.1 joerg emu->x86.R_CS = seg; 260 1.1 joerg emu->x86.R_IP = off; 261 1.1 joerg 262 1.1 joerg X86EMU_exec(emu); 263 1.1 joerg } 264 1.1 joerg 265 1.1 joerg void 266 1.1 joerg X86EMU_exec_intr(struct X86EMU *emu, uint8_t intr) 267 1.1 joerg { 268 1.1 joerg push_word(emu, emu->x86.R_FLG); 269 1.1 joerg CLEAR_FLAG(F_IF); 270 1.1 joerg CLEAR_FLAG(F_TF); 271 1.1 joerg push_word(emu, 0); 272 1.1 joerg push_word(emu, 0); 273 1.1 joerg emu->x86.R_CS = (*emu->emu_rdw)(emu, intr * 4 + 2); 274 1.1 joerg emu->x86.R_IP = (*emu->emu_rdw)(emu, intr * 4); 275 1.1 joerg emu->x86.intr = 0; 276 1.1 joerg 277 1.1 joerg X86EMU_exec(emu); 278 1.1 joerg } 279 1.1 joerg /**************************************************************************** 280 1.1 joerg REMARKS: 281 1.1 joerg Halts the system by setting the halted system flag. 282 1.1 joerg ****************************************************************************/ 283 1.1 joerg void 284 1.1 joerg X86EMU_halt_sys(struct X86EMU *emu) 285 1.1 joerg { 286 1.1 joerg #ifdef _KERNEL 287 1.1 joerg longjmp(&emu->exec_state); 288 1.1 joerg #else 289 1.1 joerg longjmp(emu->exec_state, 1); 290 1.1 joerg #endif 291 1.1 joerg } 292 1.1 joerg /**************************************************************************** 293 1.1 joerg PARAMETERS: 294 1.1 joerg mod - Mod value from decoded byte 295 1.1 joerg regh - Reg h value from decoded byte 296 1.1 joerg regl - Reg l value from decoded byte 297 1.1 joerg 298 1.1 joerg REMARKS: 299 1.1 joerg Raise the specified interrupt to be handled before the execution of the 300 1.1 joerg next instruction. 301 1.1 joerg 302 1.1 joerg NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline! 303 1.1 joerg ****************************************************************************/ 304 1.1 joerg static void 305 1.1 joerg fetch_decode_modrm(struct X86EMU *emu) 306 1.1 joerg { 307 1.1 joerg int fetched; 308 1.1 joerg 309 1.1 joerg fetched = fetch_byte_imm(emu); 310 1.1 joerg emu->cur_mod = (fetched >> 6) & 0x03; 311 1.1 joerg emu->cur_rh = (fetched >> 3) & 0x07; 312 1.1 joerg emu->cur_rl = (fetched >> 0) & 0x07; 313 1.1 joerg } 314 1.1 joerg /**************************************************************************** 315 1.1 joerg RETURNS: 316 1.1 joerg Immediate byte value read from instruction queue 317 1.1 joerg 318 1.1 joerg REMARKS: 319 1.1 joerg This function returns the immediate byte from the instruction queue, and 320 1.1 joerg moves the instruction pointer to the next value. 321 1.1 joerg 322 1.1 joerg NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline! 323 1.1 joerg ****************************************************************************/ 324 1.1 joerg static uint8_t 325 1.1 joerg fetch_byte_imm(struct X86EMU *emu) 326 1.1 joerg { 327 1.1 joerg uint8_t fetched; 328 1.1 joerg 329 1.1 joerg fetched = fetch_byte(emu, emu->x86.R_CS, emu->x86.R_IP); 330 1.1 joerg emu->x86.R_IP++; 331 1.1 joerg return fetched; 332 1.1 joerg } 333 1.1 joerg /**************************************************************************** 334 1.1 joerg RETURNS: 335 1.1 joerg Immediate word value read from instruction queue 336 1.1 joerg 337 1.1 joerg REMARKS: 338 1.1 joerg This function returns the immediate byte from the instruction queue, and 339 1.1 joerg moves the instruction pointer to the next value. 340 1.1 joerg 341 1.1 joerg NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline! 342 1.1 joerg ****************************************************************************/ 343 1.1 joerg static uint16_t 344 1.1 joerg fetch_word_imm(struct X86EMU *emu) 345 1.1 joerg { 346 1.1 joerg uint16_t fetched; 347 1.1 joerg 348 1.1 joerg fetched = fetch_word(emu, emu->x86.R_CS, emu->x86.R_IP); 349 1.1 joerg emu->x86.R_IP += 2; 350 1.1 joerg return fetched; 351 1.1 joerg } 352 1.1 joerg /**************************************************************************** 353 1.1 joerg RETURNS: 354 1.1 joerg Immediate lone value read from instruction queue 355 1.1 joerg 356 1.1 joerg REMARKS: 357 1.1 joerg This function returns the immediate byte from the instruction queue, and 358 1.1 joerg moves the instruction pointer to the next value. 359 1.1 joerg 360 1.1 joerg NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline! 361 1.1 joerg ****************************************************************************/ 362 1.1 joerg static uint32_t 363 1.1 joerg fetch_long_imm(struct X86EMU *emu) 364 1.1 joerg { 365 1.1 joerg uint32_t fetched; 366 1.1 joerg 367 1.1 joerg fetched = fetch_long(emu, emu->x86.R_CS, emu->x86.R_IP); 368 1.1 joerg emu->x86.R_IP += 4; 369 1.1 joerg return fetched; 370 1.1 joerg } 371 1.1 joerg /**************************************************************************** 372 1.1 joerg RETURNS: 373 1.1 joerg Value of the default data segment 374 1.1 joerg 375 1.1 joerg REMARKS: 376 1.1 joerg Inline function that returns the default data segment for the current 377 1.1 joerg instruction. 378 1.1 joerg 379 1.1 joerg On the x86 processor, the default segment is not always DS if there is 380 1.1 joerg no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to 381 1.1 joerg addresses relative to SS (ie: on the stack). So, at the minimum, all 382 1.1 joerg decodings of addressing modes would have to set/clear a bit describing 383 1.1 joerg whether the access is relative to DS or SS. That is the function of the 384 1.14 andvar cpu-state-variable emu->x86.mode. There are several potential states: 385 1.1 joerg 386 1.1 joerg repe prefix seen (handled elsewhere) 387 1.1 joerg repne prefix seen (ditto) 388 1.1 joerg 389 1.1 joerg cs segment override 390 1.1 joerg ds segment override 391 1.1 joerg es segment override 392 1.1 joerg fs segment override 393 1.1 joerg gs segment override 394 1.1 joerg ss segment override 395 1.1 joerg 396 1.11 msaitoh ds/ss select (in absence of override) 397 1.1 joerg 398 1.1 joerg Each of the above 7 items are handled with a bit in the mode field. 399 1.1 joerg ****************************************************************************/ 400 1.1 joerg static uint32_t 401 1.1 joerg get_data_segment(struct X86EMU *emu) 402 1.1 joerg { 403 1.1 joerg switch (emu->x86.mode & SYSMODE_SEGMASK) { 404 1.1 joerg case 0: /* default case: use ds register */ 405 1.1 joerg case SYSMODE_SEGOVR_DS: 406 1.1 joerg case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS: 407 1.1 joerg return emu->x86.R_DS; 408 1.1 joerg case SYSMODE_SEG_DS_SS:/* non-overridden, use ss register */ 409 1.1 joerg return emu->x86.R_SS; 410 1.1 joerg case SYSMODE_SEGOVR_CS: 411 1.1 joerg case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS: 412 1.1 joerg return emu->x86.R_CS; 413 1.1 joerg case SYSMODE_SEGOVR_ES: 414 1.1 joerg case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS: 415 1.1 joerg return emu->x86.R_ES; 416 1.1 joerg case SYSMODE_SEGOVR_FS: 417 1.1 joerg case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS: 418 1.1 joerg return emu->x86.R_FS; 419 1.1 joerg case SYSMODE_SEGOVR_GS: 420 1.1 joerg case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS: 421 1.1 joerg return emu->x86.R_GS; 422 1.1 joerg case SYSMODE_SEGOVR_SS: 423 1.1 joerg case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS: 424 1.1 joerg return emu->x86.R_SS; 425 1.1 joerg } 426 1.1 joerg X86EMU_halt_sys(emu); 427 1.1 joerg } 428 1.1 joerg /**************************************************************************** 429 1.1 joerg PARAMETERS: 430 1.1 joerg offset - Offset to load data from 431 1.1 joerg 432 1.1 joerg RETURNS: 433 1.1 joerg Byte value read from the absolute memory location. 434 1.1 joerg 435 1.1 joerg NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 436 1.1 joerg ****************************************************************************/ 437 1.1 joerg static uint8_t 438 1.1 joerg fetch_data_byte(struct X86EMU *emu, uint32_t offset) 439 1.1 joerg { 440 1.1 joerg return fetch_byte(emu, get_data_segment(emu), offset); 441 1.1 joerg } 442 1.1 joerg /**************************************************************************** 443 1.1 joerg PARAMETERS: 444 1.1 joerg offset - Offset to load data from 445 1.1 joerg 446 1.1 joerg RETURNS: 447 1.1 joerg Word value read from the absolute memory location. 448 1.1 joerg 449 1.1 joerg NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 450 1.1 joerg ****************************************************************************/ 451 1.1 joerg static uint16_t 452 1.1 joerg fetch_data_word(struct X86EMU *emu, uint32_t offset) 453 1.1 joerg { 454 1.1 joerg return fetch_word(emu, get_data_segment(emu), offset); 455 1.1 joerg } 456 1.1 joerg /**************************************************************************** 457 1.1 joerg PARAMETERS: 458 1.1 joerg offset - Offset to load data from 459 1.1 joerg 460 1.1 joerg RETURNS: 461 1.1 joerg Long value read from the absolute memory location. 462 1.1 joerg 463 1.1 joerg NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 464 1.1 joerg ****************************************************************************/ 465 1.1 joerg static uint32_t 466 1.1 joerg fetch_data_long(struct X86EMU *emu, uint32_t offset) 467 1.1 joerg { 468 1.1 joerg return fetch_long(emu, get_data_segment(emu), offset); 469 1.1 joerg } 470 1.1 joerg /**************************************************************************** 471 1.1 joerg PARAMETERS: 472 1.1 joerg segment - Segment to load data from 473 1.1 joerg offset - Offset to load data from 474 1.1 joerg 475 1.1 joerg RETURNS: 476 1.1 joerg Byte value read from the absolute memory location. 477 1.1 joerg 478 1.1 joerg NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 479 1.1 joerg ****************************************************************************/ 480 1.1 joerg static uint8_t 481 1.1 joerg fetch_byte(struct X86EMU *emu, uint32_t segment, uint32_t offset) 482 1.1 joerg { 483 1.1 joerg return (*emu->emu_rdb) (emu, ((uint32_t) segment << 4) + offset); 484 1.1 joerg } 485 1.1 joerg /**************************************************************************** 486 1.1 joerg PARAMETERS: 487 1.1 joerg segment - Segment to load data from 488 1.1 joerg offset - Offset to load data from 489 1.1 joerg 490 1.1 joerg RETURNS: 491 1.1 joerg Word value read from the absolute memory location. 492 1.1 joerg 493 1.1 joerg NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 494 1.1 joerg ****************************************************************************/ 495 1.1 joerg static uint16_t 496 1.1 joerg fetch_word(struct X86EMU *emu, uint32_t segment, uint32_t offset) 497 1.1 joerg { 498 1.1 joerg return (*emu->emu_rdw) (emu, ((uint32_t) segment << 4) + offset); 499 1.1 joerg } 500 1.1 joerg /**************************************************************************** 501 1.1 joerg PARAMETERS: 502 1.1 joerg segment - Segment to load data from 503 1.1 joerg offset - Offset to load data from 504 1.1 joerg 505 1.1 joerg RETURNS: 506 1.1 joerg Long value read from the absolute memory location. 507 1.1 joerg 508 1.1 joerg NOTE: Do not inline this function as (*emu->emu_rdX) is already inline! 509 1.1 joerg ****************************************************************************/ 510 1.1 joerg static uint32_t 511 1.1 joerg fetch_long(struct X86EMU *emu, uint32_t segment, uint32_t offset) 512 1.1 joerg { 513 1.1 joerg return (*emu->emu_rdl) (emu, ((uint32_t) segment << 4) + offset); 514 1.1 joerg } 515 1.1 joerg /**************************************************************************** 516 1.1 joerg PARAMETERS: 517 1.1 joerg offset - Offset to store data at 518 1.1 joerg val - Value to store 519 1.1 joerg 520 1.1 joerg REMARKS: 521 1.1 joerg Writes a word value to an segmented memory location. The segment used is 522 1.1 joerg the current 'default' segment, which may have been overridden. 523 1.1 joerg 524 1.1 joerg NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 525 1.1 joerg ****************************************************************************/ 526 1.1 joerg static void 527 1.1 joerg store_data_byte(struct X86EMU *emu, uint32_t offset, uint8_t val) 528 1.1 joerg { 529 1.1 joerg store_byte(emu, get_data_segment(emu), offset, val); 530 1.1 joerg } 531 1.1 joerg /**************************************************************************** 532 1.1 joerg PARAMETERS: 533 1.1 joerg offset - Offset to store data at 534 1.1 joerg val - Value to store 535 1.1 joerg 536 1.1 joerg REMARKS: 537 1.1 joerg Writes a word value to an segmented memory location. The segment used is 538 1.1 joerg the current 'default' segment, which may have been overridden. 539 1.1 joerg 540 1.1 joerg NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 541 1.1 joerg ****************************************************************************/ 542 1.1 joerg static void 543 1.1 joerg store_data_word(struct X86EMU *emu, uint32_t offset, uint16_t val) 544 1.1 joerg { 545 1.1 joerg store_word(emu, get_data_segment(emu), offset, val); 546 1.1 joerg } 547 1.1 joerg /**************************************************************************** 548 1.1 joerg PARAMETERS: 549 1.1 joerg offset - Offset to store data at 550 1.1 joerg val - Value to store 551 1.1 joerg 552 1.1 joerg REMARKS: 553 1.1 joerg Writes a long value to an segmented memory location. The segment used is 554 1.1 joerg the current 'default' segment, which may have been overridden. 555 1.1 joerg 556 1.1 joerg NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 557 1.1 joerg ****************************************************************************/ 558 1.1 joerg static void 559 1.1 joerg store_data_long(struct X86EMU *emu, uint32_t offset, uint32_t val) 560 1.1 joerg { 561 1.1 joerg store_long(emu, get_data_segment(emu), offset, val); 562 1.1 joerg } 563 1.1 joerg /**************************************************************************** 564 1.1 joerg PARAMETERS: 565 1.1 joerg segment - Segment to store data at 566 1.1 joerg offset - Offset to store data at 567 1.1 joerg val - Value to store 568 1.1 joerg 569 1.1 joerg REMARKS: 570 1.1 joerg Writes a byte value to an absolute memory location. 571 1.1 joerg 572 1.1 joerg NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 573 1.1 joerg ****************************************************************************/ 574 1.1 joerg static void 575 1.1 joerg store_byte(struct X86EMU *emu, uint32_t segment, uint32_t offset, uint8_t val) 576 1.1 joerg { 577 1.1 joerg (*emu->emu_wrb) (emu, ((uint32_t) segment << 4) + offset, val); 578 1.1 joerg } 579 1.1 joerg /**************************************************************************** 580 1.1 joerg PARAMETERS: 581 1.1 joerg segment - Segment to store data at 582 1.1 joerg offset - Offset to store data at 583 1.1 joerg val - Value to store 584 1.1 joerg 585 1.1 joerg REMARKS: 586 1.1 joerg Writes a word value to an absolute memory location. 587 1.1 joerg 588 1.1 joerg NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 589 1.1 joerg ****************************************************************************/ 590 1.1 joerg static void 591 1.1 joerg store_word(struct X86EMU *emu, uint32_t segment, uint32_t offset, uint16_t val) 592 1.1 joerg { 593 1.1 joerg (*emu->emu_wrw) (emu, ((uint32_t) segment << 4) + offset, val); 594 1.1 joerg } 595 1.1 joerg /**************************************************************************** 596 1.1 joerg PARAMETERS: 597 1.1 joerg segment - Segment to store data at 598 1.1 joerg offset - Offset to store data at 599 1.1 joerg val - Value to store 600 1.1 joerg 601 1.1 joerg REMARKS: 602 1.1 joerg Writes a long value to an absolute memory location. 603 1.1 joerg 604 1.1 joerg NOTE: Do not inline this function as (*emu->emu_wrX) is already inline! 605 1.1 joerg ****************************************************************************/ 606 1.1 joerg static void 607 1.1 joerg store_long(struct X86EMU *emu, uint32_t segment, uint32_t offset, uint32_t val) 608 1.1 joerg { 609 1.1 joerg (*emu->emu_wrl) (emu, ((uint32_t) segment << 4) + offset, val); 610 1.1 joerg } 611 1.1 joerg /**************************************************************************** 612 1.1 joerg PARAMETERS: 613 1.1 joerg reg - Register to decode 614 1.1 joerg 615 1.1 joerg RETURNS: 616 1.1 joerg Pointer to the appropriate register 617 1.1 joerg 618 1.1 joerg REMARKS: 619 1.1 joerg Return a pointer to the register given by the R/RM field of the 620 1.1 joerg modrm byte, for byte operands. Also enables the decoding of instructions. 621 1.1 joerg ****************************************************************************/ 622 1.1 joerg static uint8_t * 623 1.1 joerg decode_rm_byte_register(struct X86EMU *emu, int reg) 624 1.1 joerg { 625 1.1 joerg switch (reg) { 626 1.1 joerg case 0: 627 1.1 joerg return &emu->x86.R_AL; 628 1.1 joerg case 1: 629 1.1 joerg return &emu->x86.R_CL; 630 1.1 joerg case 2: 631 1.1 joerg return &emu->x86.R_DL; 632 1.1 joerg case 3: 633 1.1 joerg return &emu->x86.R_BL; 634 1.1 joerg case 4: 635 1.1 joerg return &emu->x86.R_AH; 636 1.1 joerg case 5: 637 1.1 joerg return &emu->x86.R_CH; 638 1.1 joerg case 6: 639 1.1 joerg return &emu->x86.R_DH; 640 1.1 joerg case 7: 641 1.1 joerg return &emu->x86.R_BH; 642 1.1 joerg default: 643 1.1 joerg X86EMU_halt_sys(emu); 644 1.1 joerg } 645 1.1 joerg } 646 1.1 joerg 647 1.1 joerg static uint8_t * 648 1.1 joerg decode_rl_byte_register(struct X86EMU *emu) 649 1.1 joerg { 650 1.1 joerg return decode_rm_byte_register(emu, emu->cur_rl); 651 1.1 joerg } 652 1.1 joerg 653 1.1 joerg static uint8_t * 654 1.1 joerg decode_rh_byte_register(struct X86EMU *emu) 655 1.1 joerg { 656 1.1 joerg return decode_rm_byte_register(emu, emu->cur_rh); 657 1.1 joerg } 658 1.1 joerg /**************************************************************************** 659 1.1 joerg PARAMETERS: 660 1.1 joerg reg - Register to decode 661 1.1 joerg 662 1.1 joerg RETURNS: 663 1.1 joerg Pointer to the appropriate register 664 1.1 joerg 665 1.1 joerg REMARKS: 666 1.1 joerg Return a pointer to the register given by the R/RM field of the 667 1.1 joerg modrm byte, for word operands. Also enables the decoding of instructions. 668 1.1 joerg ****************************************************************************/ 669 1.1 joerg static uint16_t * 670 1.1 joerg decode_rm_word_register(struct X86EMU *emu, int reg) 671 1.1 joerg { 672 1.1 joerg switch (reg) { 673 1.1 joerg case 0: 674 1.1 joerg return &emu->x86.R_AX; 675 1.1 joerg case 1: 676 1.1 joerg return &emu->x86.R_CX; 677 1.1 joerg case 2: 678 1.1 joerg return &emu->x86.R_DX; 679 1.1 joerg case 3: 680 1.1 joerg return &emu->x86.R_BX; 681 1.1 joerg case 4: 682 1.1 joerg return &emu->x86.R_SP; 683 1.1 joerg case 5: 684 1.1 joerg return &emu->x86.R_BP; 685 1.1 joerg case 6: 686 1.1 joerg return &emu->x86.R_SI; 687 1.1 joerg case 7: 688 1.1 joerg return &emu->x86.R_DI; 689 1.1 joerg default: 690 1.1 joerg X86EMU_halt_sys(emu); 691 1.1 joerg } 692 1.1 joerg } 693 1.1 joerg 694 1.1 joerg static uint16_t * 695 1.1 joerg decode_rl_word_register(struct X86EMU *emu) 696 1.1 joerg { 697 1.1 joerg return decode_rm_word_register(emu, emu->cur_rl); 698 1.1 joerg } 699 1.1 joerg 700 1.1 joerg static uint16_t * 701 1.1 joerg decode_rh_word_register(struct X86EMU *emu) 702 1.1 joerg { 703 1.1 joerg return decode_rm_word_register(emu, emu->cur_rh); 704 1.1 joerg } 705 1.1 joerg /**************************************************************************** 706 1.1 joerg PARAMETERS: 707 1.1 joerg reg - Register to decode 708 1.1 joerg 709 1.1 joerg RETURNS: 710 1.1 joerg Pointer to the appropriate register 711 1.1 joerg 712 1.1 joerg REMARKS: 713 1.1 joerg Return a pointer to the register given by the R/RM field of the 714 1.1 joerg modrm byte, for dword operands. Also enables the decoding of instructions. 715 1.1 joerg ****************************************************************************/ 716 1.1 joerg static uint32_t * 717 1.1 joerg decode_rm_long_register(struct X86EMU *emu, int reg) 718 1.1 joerg { 719 1.1 joerg switch (reg) { 720 1.1 joerg case 0: 721 1.1 joerg return &emu->x86.R_EAX; 722 1.1 joerg case 1: 723 1.1 joerg return &emu->x86.R_ECX; 724 1.1 joerg case 2: 725 1.1 joerg return &emu->x86.R_EDX; 726 1.1 joerg case 3: 727 1.1 joerg return &emu->x86.R_EBX; 728 1.1 joerg case 4: 729 1.1 joerg return &emu->x86.R_ESP; 730 1.1 joerg case 5: 731 1.1 joerg return &emu->x86.R_EBP; 732 1.1 joerg case 6: 733 1.1 joerg return &emu->x86.R_ESI; 734 1.1 joerg case 7: 735 1.1 joerg return &emu->x86.R_EDI; 736 1.1 joerg default: 737 1.1 joerg X86EMU_halt_sys(emu); 738 1.1 joerg } 739 1.1 joerg } 740 1.1 joerg 741 1.1 joerg static uint32_t * 742 1.1 joerg decode_rl_long_register(struct X86EMU *emu) 743 1.1 joerg { 744 1.1 joerg return decode_rm_long_register(emu, emu->cur_rl); 745 1.1 joerg } 746 1.1 joerg 747 1.1 joerg static uint32_t * 748 1.1 joerg decode_rh_long_register(struct X86EMU *emu) 749 1.1 joerg { 750 1.1 joerg return decode_rm_long_register(emu, emu->cur_rh); 751 1.1 joerg } 752 1.1 joerg 753 1.1 joerg /**************************************************************************** 754 1.1 joerg PARAMETERS: 755 1.1 joerg reg - Register to decode 756 1.1 joerg 757 1.1 joerg RETURNS: 758 1.1 joerg Pointer to the appropriate register 759 1.1 joerg 760 1.1 joerg REMARKS: 761 1.1 joerg Return a pointer to the register given by the R/RM field of the 762 1.1 joerg modrm byte, for word operands, modified from above for the weirdo 763 1.1 joerg special case of segreg operands. Also enables the decoding of instructions. 764 1.1 joerg ****************************************************************************/ 765 1.1 joerg static uint16_t * 766 1.1 joerg decode_rh_seg_register(struct X86EMU *emu) 767 1.1 joerg { 768 1.1 joerg switch (emu->cur_rh) { 769 1.1 joerg case 0: 770 1.1 joerg return &emu->x86.R_ES; 771 1.1 joerg case 1: 772 1.1 joerg return &emu->x86.R_CS; 773 1.1 joerg case 2: 774 1.1 joerg return &emu->x86.R_SS; 775 1.1 joerg case 3: 776 1.1 joerg return &emu->x86.R_DS; 777 1.1 joerg case 4: 778 1.1 joerg return &emu->x86.R_FS; 779 1.1 joerg case 5: 780 1.1 joerg return &emu->x86.R_GS; 781 1.1 joerg default: 782 1.1 joerg X86EMU_halt_sys(emu); 783 1.1 joerg } 784 1.1 joerg } 785 1.1 joerg /* 786 1.1 joerg * 787 1.1 joerg * return offset from the SIB Byte 788 1.1 joerg */ 789 1.1 joerg static uint32_t 790 1.1 joerg decode_sib_address(struct X86EMU *emu, int sib, int mod) 791 1.1 joerg { 792 1.1 joerg uint32_t base = 0, i = 0, scale = 1; 793 1.1 joerg 794 1.1 joerg switch (sib & 0x07) { 795 1.1 joerg case 0: 796 1.1 joerg base = emu->x86.R_EAX; 797 1.1 joerg break; 798 1.1 joerg case 1: 799 1.1 joerg base = emu->x86.R_ECX; 800 1.1 joerg break; 801 1.1 joerg case 2: 802 1.1 joerg base = emu->x86.R_EDX; 803 1.1 joerg break; 804 1.1 joerg case 3: 805 1.1 joerg base = emu->x86.R_EBX; 806 1.1 joerg break; 807 1.1 joerg case 4: 808 1.1 joerg base = emu->x86.R_ESP; 809 1.1 joerg emu->x86.mode |= SYSMODE_SEG_DS_SS; 810 1.1 joerg break; 811 1.1 joerg case 5: 812 1.1 joerg if (mod == 0) { 813 1.1 joerg base = fetch_long_imm(emu); 814 1.1 joerg } else { 815 1.6 joerg base = emu->x86.R_EBP; 816 1.1 joerg emu->x86.mode |= SYSMODE_SEG_DS_SS; 817 1.1 joerg } 818 1.1 joerg break; 819 1.1 joerg case 6: 820 1.1 joerg base = emu->x86.R_ESI; 821 1.1 joerg break; 822 1.1 joerg case 7: 823 1.1 joerg base = emu->x86.R_EDI; 824 1.1 joerg break; 825 1.1 joerg } 826 1.1 joerg switch ((sib >> 3) & 0x07) { 827 1.1 joerg case 0: 828 1.1 joerg i = emu->x86.R_EAX; 829 1.1 joerg break; 830 1.1 joerg case 1: 831 1.1 joerg i = emu->x86.R_ECX; 832 1.1 joerg break; 833 1.1 joerg case 2: 834 1.1 joerg i = emu->x86.R_EDX; 835 1.1 joerg break; 836 1.1 joerg case 3: 837 1.1 joerg i = emu->x86.R_EBX; 838 1.1 joerg break; 839 1.1 joerg case 4: 840 1.1 joerg i = 0; 841 1.1 joerg break; 842 1.1 joerg case 5: 843 1.1 joerg i = emu->x86.R_EBP; 844 1.1 joerg break; 845 1.1 joerg case 6: 846 1.1 joerg i = emu->x86.R_ESI; 847 1.1 joerg break; 848 1.1 joerg case 7: 849 1.1 joerg i = emu->x86.R_EDI; 850 1.1 joerg break; 851 1.1 joerg } 852 1.1 joerg scale = 1 << ((sib >> 6) & 0x03); 853 1.1 joerg return base + (i * scale); 854 1.1 joerg } 855 1.1 joerg /**************************************************************************** 856 1.1 joerg PARAMETERS: 857 1.1 joerg rm - RM value to decode 858 1.1 joerg 859 1.1 joerg RETURNS: 860 1.1 joerg Offset in memory for the address decoding 861 1.1 joerg 862 1.1 joerg REMARKS: 863 1.1 joerg Return the offset given by mod=00, mod=01 or mod=10 addressing. 864 1.1 joerg Also enables the decoding of instructions. 865 1.1 joerg ****************************************************************************/ 866 1.1 joerg static uint32_t 867 1.1 joerg decode_rl_address(struct X86EMU *emu) 868 1.1 joerg { 869 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_ADDR) { 870 1.1 joerg uint32_t offset, sib; 871 1.1 joerg /* 32-bit addressing */ 872 1.1 joerg switch (emu->cur_rl) { 873 1.1 joerg case 0: 874 1.1 joerg offset = emu->x86.R_EAX; 875 1.1 joerg break; 876 1.1 joerg case 1: 877 1.1 joerg offset = emu->x86.R_ECX; 878 1.1 joerg break; 879 1.1 joerg case 2: 880 1.1 joerg offset = emu->x86.R_EDX; 881 1.1 joerg break; 882 1.1 joerg case 3: 883 1.1 joerg offset = emu->x86.R_EBX; 884 1.1 joerg break; 885 1.1 joerg case 4: 886 1.1 joerg sib = fetch_byte_imm(emu); 887 1.1 joerg offset = decode_sib_address(emu, sib, 0); 888 1.1 joerg break; 889 1.1 joerg case 5: 890 1.6 joerg if (emu->cur_mod == 0) { 891 1.1 joerg offset = fetch_long_imm(emu); 892 1.6 joerg } else { 893 1.6 joerg emu->x86.mode |= SYSMODE_SEG_DS_SS; 894 1.1 joerg offset = emu->x86.R_EBP; 895 1.6 joerg } 896 1.1 joerg break; 897 1.1 joerg case 6: 898 1.1 joerg offset = emu->x86.R_ESI; 899 1.1 joerg break; 900 1.1 joerg case 7: 901 1.1 joerg offset = emu->x86.R_EDI; 902 1.1 joerg break; 903 1.1 joerg default: 904 1.1 joerg X86EMU_halt_sys(emu); 905 1.1 joerg } 906 1.1 joerg if (emu->cur_mod == 1) 907 1.1 joerg offset += (int8_t)fetch_byte_imm(emu); 908 1.1 joerg else if (emu->cur_mod == 2) 909 1.1 joerg offset += fetch_long_imm(emu); 910 1.1 joerg return offset; 911 1.1 joerg } else { 912 1.1 joerg uint16_t offset; 913 1.1 joerg 914 1.1 joerg /* 16-bit addressing */ 915 1.1 joerg switch (emu->cur_rl) { 916 1.1 joerg case 0: 917 1.1 joerg offset = emu->x86.R_BX + emu->x86.R_SI; 918 1.1 joerg break; 919 1.1 joerg case 1: 920 1.1 joerg offset = emu->x86.R_BX + emu->x86.R_DI; 921 1.1 joerg break; 922 1.1 joerg case 2: 923 1.1 joerg emu->x86.mode |= SYSMODE_SEG_DS_SS; 924 1.1 joerg offset = emu->x86.R_BP + emu->x86.R_SI; 925 1.1 joerg break; 926 1.1 joerg case 3: 927 1.1 joerg emu->x86.mode |= SYSMODE_SEG_DS_SS; 928 1.1 joerg offset = emu->x86.R_BP + emu->x86.R_DI; 929 1.1 joerg break; 930 1.1 joerg case 4: 931 1.1 joerg offset = emu->x86.R_SI; 932 1.1 joerg break; 933 1.1 joerg case 5: 934 1.1 joerg offset = emu->x86.R_DI; 935 1.1 joerg break; 936 1.1 joerg case 6: 937 1.6 joerg if (emu->cur_mod == 0) { 938 1.1 joerg offset = fetch_word_imm(emu); 939 1.6 joerg } else { 940 1.6 joerg emu->x86.mode |= SYSMODE_SEG_DS_SS; 941 1.1 joerg offset = emu->x86.R_BP; 942 1.6 joerg } 943 1.1 joerg break; 944 1.1 joerg case 7: 945 1.1 joerg offset = emu->x86.R_BX; 946 1.1 joerg break; 947 1.1 joerg default: 948 1.1 joerg X86EMU_halt_sys(emu); 949 1.1 joerg } 950 1.1 joerg if (emu->cur_mod == 1) 951 1.1 joerg offset += (int8_t)fetch_byte_imm(emu); 952 1.1 joerg else if (emu->cur_mod == 2) 953 1.1 joerg offset += fetch_word_imm(emu); 954 1.1 joerg return offset; 955 1.1 joerg } 956 1.1 joerg } 957 1.1 joerg 958 1.1 joerg static uint8_t 959 1.1 joerg decode_and_fetch_byte(struct X86EMU *emu) 960 1.1 joerg { 961 1.1 joerg if (emu->cur_mod != 3) { 962 1.1 joerg emu->cur_offset = decode_rl_address(emu); 963 1.1 joerg return fetch_data_byte(emu, emu->cur_offset); 964 1.1 joerg } else { 965 1.1 joerg return *decode_rl_byte_register(emu); 966 1.1 joerg } 967 1.1 joerg } 968 1.1 joerg 969 1.1 joerg static uint16_t 970 1.1 joerg decode_and_fetch_word_disp(struct X86EMU *emu, int16_t disp) 971 1.1 joerg { 972 1.1 joerg if (emu->cur_mod != 3) { 973 1.1 joerg /* TODO: A20 gate emulation */ 974 1.1 joerg emu->cur_offset = decode_rl_address(emu) + disp; 975 1.1 joerg if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0) 976 1.1 joerg emu->cur_offset &= 0xffff; 977 1.1 joerg return fetch_data_word(emu, emu->cur_offset); 978 1.1 joerg } else { 979 1.1 joerg return *decode_rl_word_register(emu); 980 1.1 joerg } 981 1.1 joerg } 982 1.1 joerg 983 1.1 joerg static uint32_t 984 1.1 joerg decode_and_fetch_long_disp(struct X86EMU *emu, int16_t disp) 985 1.1 joerg { 986 1.1 joerg if (emu->cur_mod != 3) { 987 1.1 joerg /* TODO: A20 gate emulation */ 988 1.1 joerg emu->cur_offset = decode_rl_address(emu) + disp; 989 1.1 joerg if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0) 990 1.1 joerg emu->cur_offset &= 0xffff; 991 1.1 joerg return fetch_data_long(emu, emu->cur_offset); 992 1.1 joerg } else { 993 1.1 joerg return *decode_rl_long_register(emu); 994 1.1 joerg } 995 1.1 joerg } 996 1.1 joerg 997 1.1 joerg uint16_t 998 1.1 joerg decode_and_fetch_word(struct X86EMU *emu) 999 1.1 joerg { 1000 1.1 joerg return decode_and_fetch_word_disp(emu, 0); 1001 1.1 joerg } 1002 1.1 joerg 1003 1.1 joerg uint32_t 1004 1.1 joerg decode_and_fetch_long(struct X86EMU *emu) 1005 1.1 joerg { 1006 1.1 joerg return decode_and_fetch_long_disp(emu, 0); 1007 1.1 joerg } 1008 1.1 joerg 1009 1.1 joerg uint8_t 1010 1.1 joerg decode_and_fetch_byte_imm8(struct X86EMU *emu, uint8_t *imm) 1011 1.1 joerg { 1012 1.1 joerg if (emu->cur_mod != 3) { 1013 1.1 joerg emu->cur_offset = decode_rl_address(emu); 1014 1.1 joerg *imm = fetch_byte_imm(emu); 1015 1.1 joerg return fetch_data_byte(emu, emu->cur_offset); 1016 1.1 joerg } else { 1017 1.1 joerg *imm = fetch_byte_imm(emu); 1018 1.1 joerg return *decode_rl_byte_register(emu); 1019 1.1 joerg } 1020 1.1 joerg } 1021 1.1 joerg 1022 1.1 joerg static uint16_t 1023 1.1 joerg decode_and_fetch_word_imm8(struct X86EMU *emu, uint8_t *imm) 1024 1.1 joerg { 1025 1.1 joerg if (emu->cur_mod != 3) { 1026 1.1 joerg emu->cur_offset = decode_rl_address(emu); 1027 1.1 joerg *imm = fetch_byte_imm(emu); 1028 1.1 joerg return fetch_data_word(emu, emu->cur_offset); 1029 1.1 joerg } else { 1030 1.1 joerg *imm = fetch_byte_imm(emu); 1031 1.1 joerg return *decode_rl_word_register(emu); 1032 1.1 joerg } 1033 1.1 joerg } 1034 1.1 joerg 1035 1.1 joerg static uint32_t 1036 1.1 joerg decode_and_fetch_long_imm8(struct X86EMU *emu, uint8_t *imm) 1037 1.1 joerg { 1038 1.1 joerg if (emu->cur_mod != 3) { 1039 1.1 joerg emu->cur_offset = decode_rl_address(emu); 1040 1.1 joerg *imm = fetch_byte_imm(emu); 1041 1.1 joerg return fetch_data_long(emu, emu->cur_offset); 1042 1.1 joerg } else { 1043 1.1 joerg *imm = fetch_byte_imm(emu); 1044 1.1 joerg return *decode_rl_long_register(emu); 1045 1.1 joerg } 1046 1.1 joerg } 1047 1.1 joerg 1048 1.1 joerg static void 1049 1.1 joerg write_back_byte(struct X86EMU *emu, uint8_t val) 1050 1.1 joerg { 1051 1.1 joerg if (emu->cur_mod != 3) 1052 1.1 joerg store_data_byte(emu, emu->cur_offset, val); 1053 1.1 joerg else 1054 1.1 joerg *decode_rl_byte_register(emu) = val; 1055 1.1 joerg } 1056 1.1 joerg 1057 1.1 joerg static void 1058 1.1 joerg write_back_word(struct X86EMU *emu, uint16_t val) 1059 1.1 joerg { 1060 1.1 joerg if (emu->cur_mod != 3) 1061 1.1 joerg store_data_word(emu, emu->cur_offset, val); 1062 1.1 joerg else 1063 1.1 joerg *decode_rl_word_register(emu) = val; 1064 1.1 joerg } 1065 1.1 joerg 1066 1.1 joerg static void 1067 1.1 joerg write_back_long(struct X86EMU *emu, uint32_t val) 1068 1.1 joerg { 1069 1.1 joerg if (emu->cur_mod != 3) 1070 1.1 joerg store_data_long(emu, emu->cur_offset, val); 1071 1.1 joerg else 1072 1.1 joerg *decode_rl_long_register(emu) = val; 1073 1.1 joerg } 1074 1.1 joerg 1075 1.1 joerg static void 1076 1.1 joerg common_inc_word_long(struct X86EMU *emu, union X86EMU_register *reg) 1077 1.1 joerg { 1078 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1079 1.1 joerg reg->I32_reg.e_reg = inc_long(emu, reg->I32_reg.e_reg); 1080 1.1 joerg else 1081 1.1 joerg reg->I16_reg.x_reg = inc_word(emu, reg->I16_reg.x_reg); 1082 1.1 joerg } 1083 1.1 joerg 1084 1.1 joerg static void 1085 1.1 joerg common_dec_word_long(struct X86EMU *emu, union X86EMU_register *reg) 1086 1.1 joerg { 1087 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1088 1.1 joerg reg->I32_reg.e_reg = dec_long(emu, reg->I32_reg.e_reg); 1089 1.1 joerg else 1090 1.1 joerg reg->I16_reg.x_reg = dec_word(emu, reg->I16_reg.x_reg); 1091 1.1 joerg } 1092 1.1 joerg 1093 1.1 joerg static void 1094 1.1 joerg common_binop_byte_rm_r(struct X86EMU *emu, uint8_t (*binop)(struct X86EMU *, uint8_t, uint8_t)) 1095 1.1 joerg { 1096 1.1 joerg uint32_t destoffset; 1097 1.1 joerg uint8_t *destreg, srcval; 1098 1.1 joerg uint8_t destval; 1099 1.1 joerg 1100 1.1 joerg fetch_decode_modrm(emu); 1101 1.1 joerg srcval = *decode_rh_byte_register(emu); 1102 1.1 joerg if (emu->cur_mod != 3) { 1103 1.1 joerg destoffset = decode_rl_address(emu); 1104 1.1 joerg destval = fetch_data_byte(emu, destoffset); 1105 1.1 joerg destval = (*binop)(emu, destval, srcval); 1106 1.1 joerg store_data_byte(emu, destoffset, destval); 1107 1.1 joerg } else { 1108 1.1 joerg destreg = decode_rl_byte_register(emu); 1109 1.1 joerg *destreg = (*binop)(emu, *destreg, srcval); 1110 1.1 joerg } 1111 1.1 joerg } 1112 1.1 joerg 1113 1.1 joerg static void 1114 1.1 joerg common_binop_ns_byte_rm_r(struct X86EMU *emu, void (*binop)(struct X86EMU *, uint8_t, uint8_t)) 1115 1.1 joerg { 1116 1.1 joerg uint32_t destoffset; 1117 1.1 joerg uint8_t destval, srcval; 1118 1.1 joerg 1119 1.1 joerg fetch_decode_modrm(emu); 1120 1.1 joerg srcval = *decode_rh_byte_register(emu); 1121 1.1 joerg if (emu->cur_mod != 3) { 1122 1.1 joerg destoffset = decode_rl_address(emu); 1123 1.1 joerg destval = fetch_data_byte(emu, destoffset); 1124 1.1 joerg } else { 1125 1.1 joerg destval = *decode_rl_byte_register(emu); 1126 1.1 joerg } 1127 1.1 joerg (*binop)(emu, destval, srcval); 1128 1.1 joerg } 1129 1.1 joerg 1130 1.1 joerg static void 1131 1.1 joerg common_binop_word_rm_r(struct X86EMU *emu, uint16_t (*binop)(struct X86EMU *, uint16_t, uint16_t)) 1132 1.1 joerg { 1133 1.1 joerg uint32_t destoffset; 1134 1.1 joerg uint16_t destval, *destreg, srcval; 1135 1.1 joerg 1136 1.1 joerg fetch_decode_modrm(emu); 1137 1.1 joerg srcval = *decode_rh_word_register(emu); 1138 1.1 joerg if (emu->cur_mod != 3) { 1139 1.1 joerg destoffset = decode_rl_address(emu); 1140 1.1 joerg destval = fetch_data_word(emu, destoffset); 1141 1.1 joerg destval = (*binop)(emu, destval, srcval); 1142 1.1 joerg store_data_word(emu, destoffset, destval); 1143 1.1 joerg } else { 1144 1.1 joerg destreg = decode_rl_word_register(emu); 1145 1.1 joerg *destreg = (*binop)(emu, *destreg, srcval); 1146 1.1 joerg } 1147 1.1 joerg } 1148 1.1 joerg 1149 1.1 joerg static void 1150 1.1 joerg common_binop_byte_r_rm(struct X86EMU *emu, uint8_t (*binop)(struct X86EMU *, uint8_t, uint8_t)) 1151 1.1 joerg { 1152 1.1 joerg uint8_t *destreg, srcval; 1153 1.1 joerg uint32_t srcoffset; 1154 1.1 joerg 1155 1.1 joerg fetch_decode_modrm(emu); 1156 1.1 joerg destreg = decode_rh_byte_register(emu); 1157 1.1 joerg if (emu->cur_mod != 3) { 1158 1.1 joerg srcoffset = decode_rl_address(emu); 1159 1.1 joerg srcval = fetch_data_byte(emu, srcoffset); 1160 1.1 joerg } else { 1161 1.1 joerg srcval = *decode_rl_byte_register(emu); 1162 1.1 joerg } 1163 1.1 joerg *destreg = (*binop)(emu, *destreg, srcval); 1164 1.1 joerg } 1165 1.1 joerg 1166 1.1 joerg static void 1167 1.1 joerg common_binop_long_rm_r(struct X86EMU *emu, uint32_t (*binop)(struct X86EMU *, uint32_t, uint32_t)) 1168 1.1 joerg { 1169 1.1 joerg uint32_t destoffset; 1170 1.1 joerg uint32_t destval, *destreg, srcval; 1171 1.1 joerg 1172 1.1 joerg fetch_decode_modrm(emu); 1173 1.1 joerg srcval = *decode_rh_long_register(emu); 1174 1.1 joerg if (emu->cur_mod != 3) { 1175 1.1 joerg destoffset = decode_rl_address(emu); 1176 1.1 joerg destval = fetch_data_long(emu, destoffset); 1177 1.1 joerg destval = (*binop)(emu, destval, srcval); 1178 1.1 joerg store_data_long(emu, destoffset, destval); 1179 1.1 joerg } else { 1180 1.1 joerg destreg = decode_rl_long_register(emu); 1181 1.1 joerg *destreg = (*binop)(emu, *destreg, srcval); 1182 1.1 joerg } 1183 1.1 joerg } 1184 1.1 joerg 1185 1.1 joerg static void 1186 1.1 joerg common_binop_word_long_rm_r(struct X86EMU *emu, 1187 1.1 joerg uint16_t (*binop16)(struct X86EMU *, uint16_t, uint16_t), uint32_t (*binop32)(struct X86EMU *, uint32_t, uint32_t)) 1188 1.1 joerg { 1189 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1190 1.1 joerg common_binop_long_rm_r(emu, binop32); 1191 1.1 joerg else 1192 1.1 joerg common_binop_word_rm_r(emu, binop16); 1193 1.1 joerg } 1194 1.1 joerg 1195 1.1 joerg static void 1196 1.1 joerg common_binop_ns_word_rm_r(struct X86EMU *emu, void (*binop)(struct X86EMU *, uint16_t, uint16_t)) 1197 1.1 joerg { 1198 1.1 joerg uint32_t destoffset; 1199 1.1 joerg uint16_t destval, srcval; 1200 1.1 joerg 1201 1.1 joerg fetch_decode_modrm(emu); 1202 1.1 joerg srcval = *decode_rh_word_register(emu); 1203 1.1 joerg if (emu->cur_mod != 3) { 1204 1.1 joerg destoffset = decode_rl_address(emu); 1205 1.1 joerg destval = fetch_data_word(emu, destoffset); 1206 1.1 joerg } else { 1207 1.1 joerg destval = *decode_rl_word_register(emu); 1208 1.1 joerg } 1209 1.1 joerg (*binop)(emu, destval, srcval); 1210 1.1 joerg } 1211 1.1 joerg 1212 1.1 joerg 1213 1.1 joerg static void 1214 1.1 joerg common_binop_ns_long_rm_r(struct X86EMU *emu, void (*binop)(struct X86EMU *, uint32_t, uint32_t)) 1215 1.1 joerg { 1216 1.1 joerg uint32_t destoffset; 1217 1.1 joerg uint32_t destval, srcval; 1218 1.1 joerg 1219 1.1 joerg fetch_decode_modrm(emu); 1220 1.1 joerg srcval = *decode_rh_long_register(emu); 1221 1.1 joerg if (emu->cur_mod != 3) { 1222 1.1 joerg destoffset = decode_rl_address(emu); 1223 1.1 joerg destval = fetch_data_long(emu, destoffset); 1224 1.1 joerg } else { 1225 1.1 joerg destval = *decode_rl_long_register(emu); 1226 1.1 joerg } 1227 1.1 joerg (*binop)(emu, destval, srcval); 1228 1.1 joerg } 1229 1.1 joerg 1230 1.1 joerg static void 1231 1.1 joerg common_binop_ns_word_long_rm_r(struct X86EMU *emu, 1232 1.1 joerg void (*binop16)(struct X86EMU *, uint16_t, uint16_t), void (*binop32)(struct X86EMU *, uint32_t, uint32_t)) 1233 1.1 joerg { 1234 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1235 1.1 joerg common_binop_ns_long_rm_r(emu, binop32); 1236 1.1 joerg else 1237 1.1 joerg common_binop_ns_word_rm_r(emu, binop16); 1238 1.1 joerg } 1239 1.1 joerg 1240 1.1 joerg static void 1241 1.1 joerg common_binop_long_r_rm(struct X86EMU *emu, uint32_t (*binop)(struct X86EMU *, uint32_t, uint32_t)) 1242 1.1 joerg { 1243 1.1 joerg uint32_t srcoffset; 1244 1.1 joerg uint32_t *destreg, srcval; 1245 1.1 joerg 1246 1.1 joerg fetch_decode_modrm(emu); 1247 1.1 joerg destreg = decode_rh_long_register(emu); 1248 1.1 joerg if (emu->cur_mod != 3) { 1249 1.1 joerg srcoffset = decode_rl_address(emu); 1250 1.1 joerg srcval = fetch_data_long(emu, srcoffset); 1251 1.1 joerg } else { 1252 1.1 joerg srcval = *decode_rl_long_register(emu); 1253 1.1 joerg } 1254 1.1 joerg *destreg = (*binop)(emu, *destreg, srcval); 1255 1.1 joerg } 1256 1.1 joerg 1257 1.1 joerg static void 1258 1.1 joerg common_binop_word_r_rm(struct X86EMU *emu, uint16_t (*binop)(struct X86EMU *, uint16_t, uint16_t)) 1259 1.1 joerg { 1260 1.1 joerg uint32_t srcoffset; 1261 1.1 joerg uint16_t *destreg, srcval; 1262 1.1 joerg 1263 1.1 joerg fetch_decode_modrm(emu); 1264 1.1 joerg destreg = decode_rh_word_register(emu); 1265 1.1 joerg if (emu->cur_mod != 3) { 1266 1.1 joerg srcoffset = decode_rl_address(emu); 1267 1.1 joerg srcval = fetch_data_word(emu, srcoffset); 1268 1.1 joerg } else { 1269 1.1 joerg srcval = *decode_rl_word_register(emu); 1270 1.1 joerg } 1271 1.1 joerg *destreg = (*binop)(emu, *destreg, srcval); 1272 1.1 joerg } 1273 1.1 joerg 1274 1.1 joerg static void 1275 1.1 joerg common_binop_word_long_r_rm(struct X86EMU *emu, 1276 1.1 joerg uint16_t (*binop16)(struct X86EMU *, uint16_t, uint16_t), uint32_t (*binop32)(struct X86EMU *, uint32_t, uint32_t)) 1277 1.1 joerg { 1278 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1279 1.1 joerg common_binop_long_r_rm(emu, binop32); 1280 1.1 joerg else 1281 1.1 joerg common_binop_word_r_rm(emu, binop16); 1282 1.1 joerg } 1283 1.1 joerg 1284 1.1 joerg static void 1285 1.1 joerg common_binop_byte_imm(struct X86EMU *emu, uint8_t (*binop)(struct X86EMU *, uint8_t, uint8_t)) 1286 1.1 joerg { 1287 1.1 joerg uint8_t srcval; 1288 1.1 joerg 1289 1.1 joerg srcval = fetch_byte_imm(emu); 1290 1.1 joerg emu->x86.R_AL = (*binop)(emu, emu->x86.R_AL, srcval); 1291 1.1 joerg } 1292 1.1 joerg 1293 1.1 joerg static void 1294 1.1 joerg common_binop_word_long_imm(struct X86EMU *emu, 1295 1.1 joerg uint16_t (*binop16)(struct X86EMU *, uint16_t, uint16_t), uint32_t (*binop32)(struct X86EMU *, uint32_t, uint32_t)) 1296 1.1 joerg { 1297 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1298 1.1 joerg uint32_t srcval; 1299 1.1 joerg 1300 1.1 joerg srcval = fetch_long_imm(emu); 1301 1.1 joerg emu->x86.R_EAX = (*binop32)(emu, emu->x86.R_EAX, srcval); 1302 1.1 joerg } else { 1303 1.1 joerg uint16_t srcval; 1304 1.1 joerg 1305 1.1 joerg srcval = fetch_word_imm(emu); 1306 1.1 joerg emu->x86.R_AX = (*binop16)(emu, emu->x86.R_AX, srcval); 1307 1.1 joerg } 1308 1.1 joerg } 1309 1.1 joerg 1310 1.1 joerg static void 1311 1.1 joerg common_push_word_long(struct X86EMU *emu, union X86EMU_register *reg) 1312 1.1 joerg { 1313 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1314 1.1 joerg push_long(emu, reg->I32_reg.e_reg); 1315 1.1 joerg else 1316 1.1 joerg push_word(emu, reg->I16_reg.x_reg); 1317 1.1 joerg } 1318 1.1 joerg 1319 1.1 joerg static void 1320 1.1 joerg common_pop_word_long(struct X86EMU *emu, union X86EMU_register *reg) 1321 1.1 joerg { 1322 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1323 1.1 joerg reg->I32_reg.e_reg = pop_long(emu); 1324 1.1 joerg else 1325 1.1 joerg reg->I16_reg.x_reg = pop_word(emu); 1326 1.1 joerg } 1327 1.1 joerg 1328 1.1 joerg static void 1329 1.1 joerg common_imul_long_IMM(struct X86EMU *emu, bool byte_imm) 1330 1.1 joerg { 1331 1.1 joerg uint32_t srcoffset; 1332 1.1 joerg uint32_t *destreg, srcval; 1333 1.1 joerg int32_t imm; 1334 1.1 joerg uint64_t res; 1335 1.1 joerg 1336 1.1 joerg fetch_decode_modrm(emu); 1337 1.1 joerg destreg = decode_rh_long_register(emu); 1338 1.1 joerg if (emu->cur_mod != 3) { 1339 1.1 joerg srcoffset = decode_rl_address(emu); 1340 1.1 joerg srcval = fetch_data_long(emu, srcoffset); 1341 1.1 joerg } else { 1342 1.1 joerg srcval = *decode_rl_long_register(emu); 1343 1.1 joerg } 1344 1.1 joerg 1345 1.1 joerg if (byte_imm) 1346 1.1 joerg imm = (int8_t)fetch_byte_imm(emu); 1347 1.1 joerg else 1348 1.1 joerg imm = fetch_long_imm(emu); 1349 1.1 joerg res = (int32_t)srcval * imm; 1350 1.1 joerg 1351 1.1 joerg if (res > 0xffffffff) { 1352 1.1 joerg SET_FLAG(F_CF); 1353 1.1 joerg SET_FLAG(F_OF); 1354 1.1 joerg } else { 1355 1.1 joerg CLEAR_FLAG(F_CF); 1356 1.1 joerg CLEAR_FLAG(F_OF); 1357 1.1 joerg } 1358 1.1 joerg *destreg = (uint32_t)res; 1359 1.1 joerg } 1360 1.1 joerg 1361 1.1 joerg static void 1362 1.1 joerg common_imul_word_IMM(struct X86EMU *emu, bool byte_imm) 1363 1.1 joerg { 1364 1.1 joerg uint32_t srcoffset; 1365 1.1 joerg uint16_t *destreg, srcval; 1366 1.1 joerg int16_t imm; 1367 1.1 joerg uint32_t res; 1368 1.1 joerg 1369 1.1 joerg fetch_decode_modrm(emu); 1370 1.1 joerg destreg = decode_rh_word_register(emu); 1371 1.1 joerg if (emu->cur_mod != 3) { 1372 1.1 joerg srcoffset = decode_rl_address(emu); 1373 1.1 joerg srcval = fetch_data_word(emu, srcoffset); 1374 1.1 joerg } else { 1375 1.1 joerg srcval = *decode_rl_word_register(emu); 1376 1.1 joerg } 1377 1.1 joerg 1378 1.1 joerg if (byte_imm) 1379 1.1 joerg imm = (int8_t)fetch_byte_imm(emu); 1380 1.1 joerg else 1381 1.1 joerg imm = fetch_word_imm(emu); 1382 1.1 joerg res = (int16_t)srcval * imm; 1383 1.1 joerg 1384 1.1 joerg if (res > 0xffff) { 1385 1.1 joerg SET_FLAG(F_CF); 1386 1.1 joerg SET_FLAG(F_OF); 1387 1.1 joerg } else { 1388 1.1 joerg CLEAR_FLAG(F_CF); 1389 1.1 joerg CLEAR_FLAG(F_OF); 1390 1.1 joerg } 1391 1.1 joerg *destreg = (uint16_t) res; 1392 1.1 joerg } 1393 1.1 joerg 1394 1.1 joerg static void 1395 1.1 joerg common_imul_imm(struct X86EMU *emu, bool byte_imm) 1396 1.1 joerg { 1397 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1398 1.1 joerg common_imul_long_IMM(emu, byte_imm); 1399 1.1 joerg else 1400 1.1 joerg common_imul_word_IMM(emu, byte_imm); 1401 1.1 joerg } 1402 1.1 joerg 1403 1.1 joerg static void 1404 1.1 joerg common_jmp_near(struct X86EMU *emu, bool cond) 1405 1.1 joerg { 1406 1.1 joerg int8_t offset; 1407 1.1 joerg uint16_t target; 1408 1.1 joerg 1409 1.1 joerg offset = (int8_t) fetch_byte_imm(emu); 1410 1.1 joerg target = (uint16_t) (emu->x86.R_IP + (int16_t) offset); 1411 1.1 joerg if (cond) 1412 1.1 joerg emu->x86.R_IP = target; 1413 1.1 joerg } 1414 1.1 joerg 1415 1.1 joerg static void 1416 1.1 joerg common_load_far_pointer(struct X86EMU *emu, uint16_t *seg) 1417 1.1 joerg { 1418 1.1 joerg uint16_t *dstreg; 1419 1.1 joerg uint32_t srcoffset; 1420 1.1 joerg 1421 1.1 joerg fetch_decode_modrm(emu); 1422 1.1 joerg if (emu->cur_mod == 3) 1423 1.1 joerg X86EMU_halt_sys(emu); 1424 1.1 joerg 1425 1.1 joerg dstreg = decode_rh_word_register(emu); 1426 1.1 joerg srcoffset = decode_rl_address(emu); 1427 1.1 joerg *dstreg = fetch_data_word(emu, srcoffset); 1428 1.1 joerg *seg = fetch_data_word(emu, srcoffset + 2); 1429 1.1 joerg } 1430 1.1 joerg 1431 1.1 joerg /*----------------------------- Implementation ----------------------------*/ 1432 1.1 joerg /**************************************************************************** 1433 1.1 joerg REMARKS: 1434 1.1 joerg Handles opcode 0x3a 1435 1.1 joerg ****************************************************************************/ 1436 1.1 joerg static void 1437 1.1 joerg x86emuOp_cmp_byte_R_RM(struct X86EMU *emu) 1438 1.1 joerg { 1439 1.1 joerg uint8_t *destreg, srcval; 1440 1.1 joerg 1441 1.1 joerg fetch_decode_modrm(emu); 1442 1.1 joerg destreg = decode_rh_byte_register(emu); 1443 1.1 joerg srcval = decode_and_fetch_byte(emu); 1444 1.1 joerg cmp_byte(emu, *destreg, srcval); 1445 1.1 joerg } 1446 1.1 joerg /**************************************************************************** 1447 1.1 joerg REMARKS: 1448 1.1 joerg Handles opcode 0x3b 1449 1.1 joerg ****************************************************************************/ 1450 1.1 joerg static void 1451 1.1 joerg x86emuOp32_cmp_word_R_RM(struct X86EMU *emu) 1452 1.1 joerg { 1453 1.1 joerg uint32_t srcval, *destreg; 1454 1.1 joerg 1455 1.1 joerg fetch_decode_modrm(emu); 1456 1.1 joerg destreg = decode_rh_long_register(emu); 1457 1.1 joerg srcval = decode_and_fetch_long(emu); 1458 1.1 joerg cmp_long(emu, *destreg, srcval); 1459 1.1 joerg } 1460 1.1 joerg 1461 1.1 joerg static void 1462 1.1 joerg x86emuOp16_cmp_word_R_RM(struct X86EMU *emu) 1463 1.1 joerg { 1464 1.1 joerg uint16_t srcval, *destreg; 1465 1.1 joerg 1466 1.1 joerg fetch_decode_modrm(emu); 1467 1.1 joerg destreg = decode_rh_word_register(emu); 1468 1.1 joerg srcval = decode_and_fetch_word(emu); 1469 1.1 joerg cmp_word(emu, *destreg, srcval); 1470 1.1 joerg } 1471 1.1 joerg 1472 1.1 joerg static void 1473 1.1 joerg x86emuOp_cmp_word_R_RM(struct X86EMU *emu) 1474 1.1 joerg { 1475 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1476 1.1 joerg x86emuOp32_cmp_word_R_RM(emu); 1477 1.1 joerg else 1478 1.1 joerg x86emuOp16_cmp_word_R_RM(emu); 1479 1.1 joerg } 1480 1.1 joerg /**************************************************************************** 1481 1.1 joerg REMARKS: 1482 1.1 joerg Handles opcode 0x3c 1483 1.1 joerg ****************************************************************************/ 1484 1.1 joerg static void 1485 1.1 joerg x86emuOp_cmp_byte_AL_IMM(struct X86EMU *emu) 1486 1.1 joerg { 1487 1.1 joerg uint8_t srcval; 1488 1.1 joerg 1489 1.1 joerg srcval = fetch_byte_imm(emu); 1490 1.1 joerg cmp_byte(emu, emu->x86.R_AL, srcval); 1491 1.1 joerg } 1492 1.1 joerg /**************************************************************************** 1493 1.1 joerg REMARKS: 1494 1.1 joerg Handles opcode 0x3d 1495 1.1 joerg ****************************************************************************/ 1496 1.1 joerg static void 1497 1.1 joerg x86emuOp32_cmp_word_AX_IMM(struct X86EMU *emu) 1498 1.1 joerg { 1499 1.1 joerg uint32_t srcval; 1500 1.1 joerg 1501 1.1 joerg srcval = fetch_long_imm(emu); 1502 1.1 joerg cmp_long(emu, emu->x86.R_EAX, srcval); 1503 1.1 joerg } 1504 1.1 joerg 1505 1.1 joerg static void 1506 1.1 joerg x86emuOp16_cmp_word_AX_IMM(struct X86EMU *emu) 1507 1.1 joerg { 1508 1.1 joerg uint16_t srcval; 1509 1.1 joerg 1510 1.1 joerg srcval = fetch_word_imm(emu); 1511 1.1 joerg cmp_word(emu, emu->x86.R_AX, srcval); 1512 1.1 joerg } 1513 1.1 joerg 1514 1.1 joerg static void 1515 1.1 joerg x86emuOp_cmp_word_AX_IMM(struct X86EMU *emu) 1516 1.1 joerg { 1517 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1518 1.1 joerg x86emuOp32_cmp_word_AX_IMM(emu); 1519 1.1 joerg else 1520 1.1 joerg x86emuOp16_cmp_word_AX_IMM(emu); 1521 1.1 joerg } 1522 1.1 joerg /**************************************************************************** 1523 1.1 joerg REMARKS: 1524 1.1 joerg Handles opcode 0x60 1525 1.1 joerg ****************************************************************************/ 1526 1.1 joerg static void 1527 1.1 joerg x86emuOp_push_all(struct X86EMU *emu) 1528 1.1 joerg { 1529 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1530 1.1 joerg uint32_t old_sp = emu->x86.R_ESP; 1531 1.1 joerg 1532 1.1 joerg push_long(emu, emu->x86.R_EAX); 1533 1.1 joerg push_long(emu, emu->x86.R_ECX); 1534 1.1 joerg push_long(emu, emu->x86.R_EDX); 1535 1.1 joerg push_long(emu, emu->x86.R_EBX); 1536 1.1 joerg push_long(emu, old_sp); 1537 1.1 joerg push_long(emu, emu->x86.R_EBP); 1538 1.1 joerg push_long(emu, emu->x86.R_ESI); 1539 1.1 joerg push_long(emu, emu->x86.R_EDI); 1540 1.1 joerg } else { 1541 1.1 joerg uint16_t old_sp = emu->x86.R_SP; 1542 1.1 joerg 1543 1.1 joerg push_word(emu, emu->x86.R_AX); 1544 1.1 joerg push_word(emu, emu->x86.R_CX); 1545 1.1 joerg push_word(emu, emu->x86.R_DX); 1546 1.1 joerg push_word(emu, emu->x86.R_BX); 1547 1.1 joerg push_word(emu, old_sp); 1548 1.1 joerg push_word(emu, emu->x86.R_BP); 1549 1.1 joerg push_word(emu, emu->x86.R_SI); 1550 1.1 joerg push_word(emu, emu->x86.R_DI); 1551 1.1 joerg } 1552 1.1 joerg } 1553 1.1 joerg /**************************************************************************** 1554 1.1 joerg REMARKS: 1555 1.1 joerg Handles opcode 0x61 1556 1.1 joerg ****************************************************************************/ 1557 1.1 joerg static void 1558 1.1 joerg x86emuOp_pop_all(struct X86EMU *emu) 1559 1.1 joerg { 1560 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1561 1.1 joerg emu->x86.R_EDI = pop_long(emu); 1562 1.1 joerg emu->x86.R_ESI = pop_long(emu); 1563 1.1 joerg emu->x86.R_EBP = pop_long(emu); 1564 1.1 joerg emu->x86.R_ESP += 4; /* skip ESP */ 1565 1.1 joerg emu->x86.R_EBX = pop_long(emu); 1566 1.1 joerg emu->x86.R_EDX = pop_long(emu); 1567 1.1 joerg emu->x86.R_ECX = pop_long(emu); 1568 1.1 joerg emu->x86.R_EAX = pop_long(emu); 1569 1.1 joerg } else { 1570 1.1 joerg emu->x86.R_DI = pop_word(emu); 1571 1.1 joerg emu->x86.R_SI = pop_word(emu); 1572 1.1 joerg emu->x86.R_BP = pop_word(emu); 1573 1.1 joerg emu->x86.R_SP += 2;/* skip SP */ 1574 1.1 joerg emu->x86.R_BX = pop_word(emu); 1575 1.1 joerg emu->x86.R_DX = pop_word(emu); 1576 1.1 joerg emu->x86.R_CX = pop_word(emu); 1577 1.1 joerg emu->x86.R_AX = pop_word(emu); 1578 1.1 joerg } 1579 1.1 joerg } 1580 1.1 joerg /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */ 1581 1.1 joerg /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */ 1582 1.1 joerg 1583 1.1 joerg /**************************************************************************** 1584 1.1 joerg REMARKS: 1585 1.1 joerg Handles opcode 0x68 1586 1.1 joerg ****************************************************************************/ 1587 1.1 joerg static void 1588 1.1 joerg x86emuOp_push_word_IMM(struct X86EMU *emu) 1589 1.1 joerg { 1590 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1591 1.1 joerg uint32_t imm; 1592 1.1 joerg 1593 1.1 joerg imm = fetch_long_imm(emu); 1594 1.1 joerg push_long(emu, imm); 1595 1.1 joerg } else { 1596 1.1 joerg uint16_t imm; 1597 1.1 joerg 1598 1.1 joerg imm = fetch_word_imm(emu); 1599 1.1 joerg push_word(emu, imm); 1600 1.1 joerg } 1601 1.1 joerg } 1602 1.1 joerg /**************************************************************************** 1603 1.1 joerg REMARKS: 1604 1.1 joerg Handles opcode 0x6a 1605 1.1 joerg ****************************************************************************/ 1606 1.1 joerg static void 1607 1.1 joerg x86emuOp_push_byte_IMM(struct X86EMU *emu) 1608 1.1 joerg { 1609 1.1 joerg int16_t imm; 1610 1.1 joerg 1611 1.1 joerg imm = (int8_t) fetch_byte_imm(emu); 1612 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1613 1.1 joerg push_long(emu, (int32_t) imm); 1614 1.1 joerg } else { 1615 1.1 joerg push_word(emu, imm); 1616 1.1 joerg } 1617 1.1 joerg } 1618 1.1 joerg /**************************************************************************** 1619 1.1 joerg REMARKS: 1620 1.1 joerg Handles opcode 0x6c 1621 1.1 joerg ****************************************************************************/ 1622 1.1 joerg /**************************************************************************** 1623 1.1 joerg REMARKS: 1624 1.1 joerg Handles opcode 0x6d 1625 1.1 joerg ****************************************************************************/ 1626 1.1 joerg static void 1627 1.1 joerg x86emuOp_ins_word(struct X86EMU *emu) 1628 1.1 joerg { 1629 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1630 1.1 joerg ins(emu, 4); 1631 1.1 joerg } else { 1632 1.1 joerg ins(emu, 2); 1633 1.1 joerg } 1634 1.1 joerg } 1635 1.1 joerg /**************************************************************************** 1636 1.1 joerg REMARKS: 1637 1.1 joerg Handles opcode 0x6f 1638 1.1 joerg ****************************************************************************/ 1639 1.1 joerg static void 1640 1.1 joerg x86emuOp_outs_word(struct X86EMU *emu) 1641 1.1 joerg { 1642 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 1643 1.1 joerg outs(emu, 4); 1644 1.1 joerg } else { 1645 1.1 joerg outs(emu, 2); 1646 1.1 joerg } 1647 1.1 joerg } 1648 1.1 joerg /**************************************************************************** 1649 1.1 joerg REMARKS: 1650 1.1 joerg Handles opcode 0x7c 1651 1.1 joerg ****************************************************************************/ 1652 1.1 joerg static void 1653 1.1 joerg x86emuOp_jump_near_L(struct X86EMU *emu) 1654 1.1 joerg { 1655 1.1 joerg bool sf, of; 1656 1.1 joerg 1657 1.1 joerg sf = ACCESS_FLAG(F_SF) != 0; 1658 1.1 joerg of = ACCESS_FLAG(F_OF) != 0; 1659 1.1 joerg 1660 1.1 joerg common_jmp_near(emu, sf != of); 1661 1.1 joerg } 1662 1.1 joerg /**************************************************************************** 1663 1.1 joerg REMARKS: 1664 1.1 joerg Handles opcode 0x7d 1665 1.1 joerg ****************************************************************************/ 1666 1.1 joerg static void 1667 1.1 joerg x86emuOp_jump_near_NL(struct X86EMU *emu) 1668 1.1 joerg { 1669 1.1 joerg bool sf, of; 1670 1.1 joerg 1671 1.1 joerg sf = ACCESS_FLAG(F_SF) != 0; 1672 1.1 joerg of = ACCESS_FLAG(F_OF) != 0; 1673 1.1 joerg 1674 1.1 joerg common_jmp_near(emu, sf == of); 1675 1.1 joerg } 1676 1.1 joerg /**************************************************************************** 1677 1.1 joerg REMARKS: 1678 1.1 joerg Handles opcode 0x7e 1679 1.1 joerg ****************************************************************************/ 1680 1.1 joerg static void 1681 1.1 joerg x86emuOp_jump_near_LE(struct X86EMU *emu) 1682 1.1 joerg { 1683 1.1 joerg bool sf, of; 1684 1.1 joerg 1685 1.1 joerg sf = ACCESS_FLAG(F_SF) != 0; 1686 1.1 joerg of = ACCESS_FLAG(F_OF) != 0; 1687 1.1 joerg 1688 1.1 joerg common_jmp_near(emu, sf != of || ACCESS_FLAG(F_ZF)); 1689 1.1 joerg } 1690 1.1 joerg /**************************************************************************** 1691 1.1 joerg REMARKS: 1692 1.1 joerg Handles opcode 0x7f 1693 1.1 joerg ****************************************************************************/ 1694 1.1 joerg static void 1695 1.1 joerg x86emuOp_jump_near_NLE(struct X86EMU *emu) 1696 1.1 joerg { 1697 1.1 joerg bool sf, of; 1698 1.1 joerg 1699 1.1 joerg sf = ACCESS_FLAG(F_SF) != 0; 1700 1.1 joerg of = ACCESS_FLAG(F_OF) != 0; 1701 1.1 joerg 1702 1.1 joerg common_jmp_near(emu, sf == of && !ACCESS_FLAG(F_ZF)); 1703 1.1 joerg } 1704 1.1 joerg 1705 1.1 joerg static 1706 1.1 joerg uint8_t(*const opc80_byte_operation[]) (struct X86EMU *, uint8_t d, uint8_t s) = 1707 1.1 joerg { 1708 1.1 joerg add_byte, /* 00 */ 1709 1.1 joerg or_byte, /* 01 */ 1710 1.1 joerg adc_byte, /* 02 */ 1711 1.1 joerg sbb_byte, /* 03 */ 1712 1.1 joerg and_byte, /* 04 */ 1713 1.1 joerg sub_byte, /* 05 */ 1714 1.1 joerg xor_byte, /* 06 */ 1715 1.1 joerg cmp_byte, /* 07 */ 1716 1.1 joerg }; 1717 1.1 joerg /**************************************************************************** 1718 1.1 joerg REMARKS: 1719 1.1 joerg Handles opcode 0x80 1720 1.1 joerg ****************************************************************************/ 1721 1.1 joerg static void 1722 1.1 joerg x86emuOp_opc80_byte_RM_IMM(struct X86EMU *emu) 1723 1.1 joerg { 1724 1.1 joerg uint8_t imm, destval; 1725 1.1 joerg 1726 1.1 joerg /* 1727 1.1 joerg * Weirdo special case instruction format. Part of the opcode 1728 1.1 joerg * held below in "RH". Doubly nested case would result, except 1729 1.1 joerg * that the decoded instruction 1730 1.1 joerg */ 1731 1.1 joerg fetch_decode_modrm(emu); 1732 1.1 joerg destval = decode_and_fetch_byte(emu); 1733 1.1 joerg imm = fetch_byte_imm(emu); 1734 1.1 joerg destval = (*opc80_byte_operation[emu->cur_rh]) (emu, destval, imm); 1735 1.1 joerg if (emu->cur_rh != 7) 1736 1.1 joerg write_back_byte(emu, destval); 1737 1.1 joerg } 1738 1.1 joerg 1739 1.1 joerg static 1740 1.1 joerg uint16_t(* const opc81_word_operation[]) (struct X86EMU *, uint16_t d, uint16_t s) = 1741 1.1 joerg { 1742 1.1 joerg add_word, /* 00 */ 1743 1.1 joerg or_word, /* 01 */ 1744 1.1 joerg adc_word, /* 02 */ 1745 1.1 joerg sbb_word, /* 03 */ 1746 1.1 joerg and_word, /* 04 */ 1747 1.1 joerg sub_word, /* 05 */ 1748 1.1 joerg xor_word, /* 06 */ 1749 1.1 joerg cmp_word, /* 07 */ 1750 1.1 joerg }; 1751 1.1 joerg 1752 1.1 joerg static 1753 1.1 joerg uint32_t(* const opc81_long_operation[]) (struct X86EMU *, uint32_t d, uint32_t s) = 1754 1.1 joerg { 1755 1.1 joerg add_long, /* 00 */ 1756 1.1 joerg or_long, /* 01 */ 1757 1.1 joerg adc_long, /* 02 */ 1758 1.1 joerg sbb_long, /* 03 */ 1759 1.1 joerg and_long, /* 04 */ 1760 1.1 joerg sub_long, /* 05 */ 1761 1.1 joerg xor_long, /* 06 */ 1762 1.1 joerg cmp_long, /* 07 */ 1763 1.1 joerg }; 1764 1.1 joerg /**************************************************************************** 1765 1.1 joerg REMARKS: 1766 1.1 joerg Handles opcode 0x81 1767 1.1 joerg ****************************************************************************/ 1768 1.1 joerg static void 1769 1.1 joerg x86emuOp32_opc81_word_RM_IMM(struct X86EMU *emu) 1770 1.1 joerg { 1771 1.1 joerg uint32_t destval, imm; 1772 1.1 joerg 1773 1.1 joerg /* 1774 1.1 joerg * Weirdo special case instruction format. Part of the opcode 1775 1.1 joerg * held below in "RH". Doubly nested case would result, except 1776 1.1 joerg * that the decoded instruction 1777 1.1 joerg */ 1778 1.1 joerg fetch_decode_modrm(emu); 1779 1.1 joerg destval = decode_and_fetch_long(emu); 1780 1.1 joerg imm = fetch_long_imm(emu); 1781 1.1 joerg destval = (*opc81_long_operation[emu->cur_rh]) (emu, destval, imm); 1782 1.1 joerg if (emu->cur_rh != 7) 1783 1.1 joerg write_back_long(emu, destval); 1784 1.1 joerg } 1785 1.1 joerg 1786 1.1 joerg static void 1787 1.1 joerg x86emuOp16_opc81_word_RM_IMM(struct X86EMU *emu) 1788 1.1 joerg { 1789 1.1 joerg uint16_t destval, imm; 1790 1.1 joerg 1791 1.1 joerg /* 1792 1.1 joerg * Weirdo special case instruction format. Part of the opcode 1793 1.1 joerg * held below in "RH". Doubly nested case would result, except 1794 1.1 joerg * that the decoded instruction 1795 1.1 joerg */ 1796 1.1 joerg fetch_decode_modrm(emu); 1797 1.1 joerg destval = decode_and_fetch_word(emu); 1798 1.1 joerg imm = fetch_word_imm(emu); 1799 1.1 joerg destval = (*opc81_word_operation[emu->cur_rh]) (emu, destval, imm); 1800 1.1 joerg if (emu->cur_rh != 7) 1801 1.1 joerg write_back_word(emu, destval); 1802 1.1 joerg } 1803 1.1 joerg 1804 1.1 joerg static void 1805 1.1 joerg x86emuOp_opc81_word_RM_IMM(struct X86EMU *emu) 1806 1.1 joerg { 1807 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1808 1.1 joerg x86emuOp32_opc81_word_RM_IMM(emu); 1809 1.1 joerg else 1810 1.1 joerg x86emuOp16_opc81_word_RM_IMM(emu); 1811 1.1 joerg } 1812 1.1 joerg 1813 1.1 joerg static 1814 1.1 joerg uint8_t(* const opc82_byte_operation[]) (struct X86EMU *, uint8_t s, uint8_t d) = 1815 1.1 joerg { 1816 1.1 joerg add_byte, /* 00 */ 1817 1.1 joerg or_byte, /* 01 *//* YYY UNUSED ???? */ 1818 1.1 joerg adc_byte, /* 02 */ 1819 1.1 joerg sbb_byte, /* 03 */ 1820 1.1 joerg and_byte, /* 04 *//* YYY UNUSED ???? */ 1821 1.1 joerg sub_byte, /* 05 */ 1822 1.1 joerg xor_byte, /* 06 *//* YYY UNUSED ???? */ 1823 1.1 joerg cmp_byte, /* 07 */ 1824 1.1 joerg }; 1825 1.1 joerg /**************************************************************************** 1826 1.1 joerg REMARKS: 1827 1.1 joerg Handles opcode 0x82 1828 1.1 joerg ****************************************************************************/ 1829 1.1 joerg static void 1830 1.1 joerg x86emuOp_opc82_byte_RM_IMM(struct X86EMU *emu) 1831 1.1 joerg { 1832 1.1 joerg uint8_t imm, destval; 1833 1.1 joerg 1834 1.1 joerg /* 1835 1.1 joerg * Weirdo special case instruction format. Part of the opcode 1836 1.1 joerg * held below in "RH". Doubly nested case would result, except 1837 1.1 joerg * that the decoded instruction Similar to opcode 81, except that 1838 1.1 joerg * the immediate byte is sign extended to a word length. 1839 1.1 joerg */ 1840 1.1 joerg fetch_decode_modrm(emu); 1841 1.1 joerg destval = decode_and_fetch_byte(emu); 1842 1.1 joerg imm = fetch_byte_imm(emu); 1843 1.1 joerg destval = (*opc82_byte_operation[emu->cur_rh]) (emu, destval, imm); 1844 1.1 joerg if (emu->cur_rh != 7) 1845 1.1 joerg write_back_byte(emu, destval); 1846 1.1 joerg } 1847 1.1 joerg 1848 1.1 joerg static 1849 1.1 joerg uint16_t(* const opc83_word_operation[]) (struct X86EMU *, uint16_t s, uint16_t d) = 1850 1.1 joerg { 1851 1.1 joerg add_word, /* 00 */ 1852 1.1 joerg or_word, /* 01 *//* YYY UNUSED ???? */ 1853 1.1 joerg adc_word, /* 02 */ 1854 1.1 joerg sbb_word, /* 03 */ 1855 1.1 joerg and_word, /* 04 *//* YYY UNUSED ???? */ 1856 1.1 joerg sub_word, /* 05 */ 1857 1.1 joerg xor_word, /* 06 *//* YYY UNUSED ???? */ 1858 1.1 joerg cmp_word, /* 07 */ 1859 1.1 joerg }; 1860 1.1 joerg 1861 1.1 joerg static 1862 1.1 joerg uint32_t(* const opc83_long_operation[]) (struct X86EMU *, uint32_t s, uint32_t d) = 1863 1.1 joerg { 1864 1.1 joerg add_long, /* 00 */ 1865 1.1 joerg or_long, /* 01 *//* YYY UNUSED ???? */ 1866 1.1 joerg adc_long, /* 02 */ 1867 1.1 joerg sbb_long, /* 03 */ 1868 1.1 joerg and_long, /* 04 *//* YYY UNUSED ???? */ 1869 1.1 joerg sub_long, /* 05 */ 1870 1.1 joerg xor_long, /* 06 *//* YYY UNUSED ???? */ 1871 1.1 joerg cmp_long, /* 07 */ 1872 1.1 joerg }; 1873 1.1 joerg /**************************************************************************** 1874 1.1 joerg REMARKS: 1875 1.1 joerg Handles opcode 0x83 1876 1.1 joerg ****************************************************************************/ 1877 1.1 joerg static void 1878 1.1 joerg x86emuOp32_opc83_word_RM_IMM(struct X86EMU *emu) 1879 1.1 joerg { 1880 1.1 joerg uint32_t destval, imm; 1881 1.1 joerg 1882 1.1 joerg fetch_decode_modrm(emu); 1883 1.1 joerg destval = decode_and_fetch_long(emu); 1884 1.1 joerg imm = (int8_t) fetch_byte_imm(emu); 1885 1.1 joerg destval = (*opc83_long_operation[emu->cur_rh]) (emu, destval, imm); 1886 1.1 joerg if (emu->cur_rh != 7) 1887 1.1 joerg write_back_long(emu, destval); 1888 1.1 joerg } 1889 1.1 joerg 1890 1.1 joerg static void 1891 1.1 joerg x86emuOp16_opc83_word_RM_IMM(struct X86EMU *emu) 1892 1.1 joerg { 1893 1.1 joerg uint16_t destval, imm; 1894 1.1 joerg 1895 1.1 joerg fetch_decode_modrm(emu); 1896 1.1 joerg destval = decode_and_fetch_word(emu); 1897 1.1 joerg imm = (int8_t) fetch_byte_imm(emu); 1898 1.1 joerg destval = (*opc83_word_operation[emu->cur_rh]) (emu, destval, imm); 1899 1.1 joerg if (emu->cur_rh != 7) 1900 1.1 joerg write_back_word(emu, destval); 1901 1.1 joerg } 1902 1.1 joerg 1903 1.1 joerg static void 1904 1.1 joerg x86emuOp_opc83_word_RM_IMM(struct X86EMU *emu) 1905 1.1 joerg { 1906 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1907 1.1 joerg x86emuOp32_opc83_word_RM_IMM(emu); 1908 1.1 joerg else 1909 1.1 joerg x86emuOp16_opc83_word_RM_IMM(emu); 1910 1.1 joerg } 1911 1.1 joerg /**************************************************************************** 1912 1.1 joerg REMARKS: 1913 1.1 joerg Handles opcode 0x86 1914 1.1 joerg ****************************************************************************/ 1915 1.1 joerg static void 1916 1.1 joerg x86emuOp_xchg_byte_RM_R(struct X86EMU *emu) 1917 1.1 joerg { 1918 1.1 joerg uint8_t *srcreg, destval, tmp; 1919 1.1 joerg 1920 1.1 joerg fetch_decode_modrm(emu); 1921 1.1 joerg destval = decode_and_fetch_byte(emu); 1922 1.1 joerg srcreg = decode_rh_byte_register(emu); 1923 1.1 joerg tmp = destval; 1924 1.1 joerg destval = *srcreg; 1925 1.1 joerg *srcreg = tmp; 1926 1.1 joerg write_back_byte(emu, destval); 1927 1.1 joerg } 1928 1.1 joerg /**************************************************************************** 1929 1.1 joerg REMARKS: 1930 1.1 joerg Handles opcode 0x87 1931 1.1 joerg ****************************************************************************/ 1932 1.1 joerg static void 1933 1.1 joerg x86emuOp32_xchg_word_RM_R(struct X86EMU *emu) 1934 1.1 joerg { 1935 1.1 joerg uint32_t *srcreg, destval, tmp; 1936 1.1 joerg 1937 1.1 joerg fetch_decode_modrm(emu); 1938 1.1 joerg destval = decode_and_fetch_long(emu); 1939 1.1 joerg srcreg = decode_rh_long_register(emu); 1940 1.1 joerg tmp = destval; 1941 1.1 joerg destval = *srcreg; 1942 1.1 joerg *srcreg = tmp; 1943 1.1 joerg write_back_long(emu, destval); 1944 1.1 joerg } 1945 1.1 joerg 1946 1.1 joerg static void 1947 1.1 joerg x86emuOp16_xchg_word_RM_R(struct X86EMU *emu) 1948 1.1 joerg { 1949 1.1 joerg uint16_t *srcreg, destval, tmp; 1950 1.1 joerg 1951 1.1 joerg fetch_decode_modrm(emu); 1952 1.1 joerg destval = decode_and_fetch_word(emu); 1953 1.1 joerg srcreg = decode_rh_word_register(emu); 1954 1.1 joerg tmp = destval; 1955 1.1 joerg destval = *srcreg; 1956 1.1 joerg *srcreg = tmp; 1957 1.1 joerg write_back_word(emu, destval); 1958 1.1 joerg } 1959 1.1 joerg 1960 1.1 joerg static void 1961 1.1 joerg x86emuOp_xchg_word_RM_R(struct X86EMU *emu) 1962 1.1 joerg { 1963 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 1964 1.1 joerg x86emuOp32_xchg_word_RM_R(emu); 1965 1.1 joerg else 1966 1.1 joerg x86emuOp16_xchg_word_RM_R(emu); 1967 1.1 joerg } 1968 1.1 joerg /**************************************************************************** 1969 1.1 joerg REMARKS: 1970 1.1 joerg Handles opcode 0x88 1971 1.1 joerg ****************************************************************************/ 1972 1.1 joerg static void 1973 1.1 joerg x86emuOp_mov_byte_RM_R(struct X86EMU *emu) 1974 1.1 joerg { 1975 1.1 joerg uint8_t *destreg, *srcreg; 1976 1.1 joerg uint32_t destoffset; 1977 1.1 joerg 1978 1.1 joerg fetch_decode_modrm(emu); 1979 1.1 joerg srcreg = decode_rh_byte_register(emu); 1980 1.1 joerg if (emu->cur_mod != 3) { 1981 1.1 joerg destoffset = decode_rl_address(emu); 1982 1.1 joerg store_data_byte(emu, destoffset, *srcreg); 1983 1.1 joerg } else { 1984 1.1 joerg destreg = decode_rl_byte_register(emu); 1985 1.1 joerg *destreg = *srcreg; 1986 1.1 joerg } 1987 1.1 joerg } 1988 1.1 joerg /**************************************************************************** 1989 1.1 joerg REMARKS: 1990 1.1 joerg Handles opcode 0x89 1991 1.1 joerg ****************************************************************************/ 1992 1.1 joerg static void 1993 1.1 joerg x86emuOp32_mov_word_RM_R(struct X86EMU *emu) 1994 1.1 joerg { 1995 1.1 joerg uint32_t destoffset; 1996 1.1 joerg uint32_t *destreg, srcval; 1997 1.1 joerg 1998 1.1 joerg fetch_decode_modrm(emu); 1999 1.1 joerg srcval = *decode_rh_long_register(emu); 2000 1.1 joerg if (emu->cur_mod != 3) { 2001 1.1 joerg destoffset = decode_rl_address(emu); 2002 1.1 joerg store_data_long(emu, destoffset, srcval); 2003 1.1 joerg } else { 2004 1.1 joerg destreg = decode_rl_long_register(emu); 2005 1.1 joerg *destreg = srcval; 2006 1.1 joerg } 2007 1.1 joerg } 2008 1.1 joerg 2009 1.1 joerg static void 2010 1.1 joerg x86emuOp16_mov_word_RM_R(struct X86EMU *emu) 2011 1.1 joerg { 2012 1.1 joerg uint32_t destoffset; 2013 1.1 joerg uint16_t *destreg, srcval; 2014 1.1 joerg 2015 1.1 joerg fetch_decode_modrm(emu); 2016 1.1 joerg srcval = *decode_rh_word_register(emu); 2017 1.1 joerg if (emu->cur_mod != 3) { 2018 1.1 joerg destoffset = decode_rl_address(emu); 2019 1.1 joerg store_data_word(emu, destoffset, srcval); 2020 1.1 joerg } else { 2021 1.1 joerg destreg = decode_rl_word_register(emu); 2022 1.1 joerg *destreg = srcval; 2023 1.1 joerg } 2024 1.1 joerg } 2025 1.1 joerg 2026 1.1 joerg static void 2027 1.1 joerg x86emuOp_mov_word_RM_R(struct X86EMU *emu) 2028 1.1 joerg { 2029 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2030 1.1 joerg x86emuOp32_mov_word_RM_R(emu); 2031 1.1 joerg else 2032 1.1 joerg x86emuOp16_mov_word_RM_R(emu); 2033 1.1 joerg } 2034 1.1 joerg /**************************************************************************** 2035 1.1 joerg REMARKS: 2036 1.1 joerg Handles opcode 0x8a 2037 1.1 joerg ****************************************************************************/ 2038 1.1 joerg static void 2039 1.1 joerg x86emuOp_mov_byte_R_RM(struct X86EMU *emu) 2040 1.1 joerg { 2041 1.1 joerg uint8_t *destreg; 2042 1.1 joerg 2043 1.1 joerg fetch_decode_modrm(emu); 2044 1.1 joerg destreg = decode_rh_byte_register(emu); 2045 1.1 joerg *destreg = decode_and_fetch_byte(emu); 2046 1.1 joerg } 2047 1.1 joerg /**************************************************************************** 2048 1.1 joerg REMARKS: 2049 1.1 joerg Handles opcode 0x8b 2050 1.1 joerg ****************************************************************************/ 2051 1.1 joerg static void 2052 1.1 joerg x86emuOp_mov_word_R_RM(struct X86EMU *emu) 2053 1.1 joerg { 2054 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2055 1.1 joerg uint32_t *destreg; 2056 1.1 joerg 2057 1.1 joerg fetch_decode_modrm(emu); 2058 1.1 joerg destreg = decode_rh_long_register(emu); 2059 1.1 joerg *destreg = decode_and_fetch_long(emu); 2060 1.1 joerg } else { 2061 1.1 joerg uint16_t *destreg; 2062 1.1 joerg 2063 1.1 joerg fetch_decode_modrm(emu); 2064 1.1 joerg destreg = decode_rh_word_register(emu); 2065 1.1 joerg *destreg = decode_and_fetch_word(emu); 2066 1.1 joerg } 2067 1.1 joerg } 2068 1.1 joerg /**************************************************************************** 2069 1.1 joerg REMARKS: 2070 1.1 joerg Handles opcode 0x8c 2071 1.1 joerg ****************************************************************************/ 2072 1.1 joerg static void 2073 1.1 joerg x86emuOp_mov_word_RM_SR(struct X86EMU *emu) 2074 1.1 joerg { 2075 1.1 joerg uint16_t *destreg, srcval; 2076 1.1 joerg uint32_t destoffset; 2077 1.1 joerg 2078 1.1 joerg fetch_decode_modrm(emu); 2079 1.1 joerg srcval = *decode_rh_seg_register(emu); 2080 1.1 joerg if (emu->cur_mod != 3) { 2081 1.1 joerg destoffset = decode_rl_address(emu); 2082 1.1 joerg store_data_word(emu, destoffset, srcval); 2083 1.1 joerg } else { 2084 1.1 joerg destreg = decode_rl_word_register(emu); 2085 1.1 joerg *destreg = srcval; 2086 1.1 joerg } 2087 1.1 joerg } 2088 1.1 joerg /**************************************************************************** 2089 1.1 joerg REMARKS: 2090 1.1 joerg Handles opcode 0x8d 2091 1.1 joerg ****************************************************************************/ 2092 1.1 joerg static void 2093 1.1 joerg x86emuOp_lea_word_R_M(struct X86EMU *emu) 2094 1.1 joerg { 2095 1.1 joerg uint32_t destoffset; 2096 1.1 joerg 2097 1.1 joerg fetch_decode_modrm(emu); 2098 1.1 joerg if (emu->cur_mod == 3) 2099 1.1 joerg X86EMU_halt_sys(emu); 2100 1.1 joerg 2101 1.1 joerg destoffset = decode_rl_address(emu); 2102 1.9 joerg if (emu->x86.mode & SYSMODE_PREFIX_ADDR) { 2103 1.9 joerg uint32_t *srcreg; 2104 1.9 joerg 2105 1.9 joerg srcreg = decode_rh_long_register(emu); 2106 1.9 joerg *srcreg = (uint32_t) destoffset; 2107 1.9 joerg } else { 2108 1.9 joerg uint16_t *srcreg; 2109 1.9 joerg 2110 1.9 joerg srcreg = decode_rh_word_register(emu); 2111 1.9 joerg *srcreg = (uint16_t) destoffset; 2112 1.9 joerg } 2113 1.1 joerg } 2114 1.1 joerg /**************************************************************************** 2115 1.1 joerg REMARKS: 2116 1.1 joerg Handles opcode 0x8e 2117 1.1 joerg ****************************************************************************/ 2118 1.1 joerg static void 2119 1.1 joerg x86emuOp_mov_word_SR_RM(struct X86EMU *emu) 2120 1.1 joerg { 2121 1.1 joerg uint16_t *destreg; 2122 1.1 joerg 2123 1.1 joerg fetch_decode_modrm(emu); 2124 1.1 joerg destreg = decode_rh_seg_register(emu); 2125 1.1 joerg *destreg = decode_and_fetch_word(emu); 2126 1.1 joerg /* 2127 1.1 joerg * Clean up, and reset all the R_xSP pointers to the correct 2128 1.1 joerg * locations. This is about 3x too much overhead (doing all the 2129 1.1 joerg * segreg ptrs when only one is needed, but this instruction 2130 1.1 joerg * *cannot* be that common, and this isn't too much work anyway. 2131 1.1 joerg */ 2132 1.1 joerg } 2133 1.1 joerg /**************************************************************************** 2134 1.1 joerg REMARKS: 2135 1.1 joerg Handles opcode 0x8f 2136 1.1 joerg ****************************************************************************/ 2137 1.1 joerg static void 2138 1.1 joerg x86emuOp32_pop_RM(struct X86EMU *emu) 2139 1.1 joerg { 2140 1.1 joerg uint32_t destoffset; 2141 1.1 joerg uint32_t destval, *destreg; 2142 1.1 joerg 2143 1.1 joerg fetch_decode_modrm(emu); 2144 1.1 joerg if (emu->cur_mod != 3) { 2145 1.1 joerg destoffset = decode_rl_address(emu); 2146 1.1 joerg destval = pop_long(emu); 2147 1.1 joerg store_data_long(emu, destoffset, destval); 2148 1.1 joerg } else { 2149 1.1 joerg destreg = decode_rl_long_register(emu); 2150 1.1 joerg *destreg = pop_long(emu); 2151 1.1 joerg } 2152 1.1 joerg } 2153 1.1 joerg 2154 1.1 joerg static void 2155 1.1 joerg x86emuOp16_pop_RM(struct X86EMU *emu) 2156 1.1 joerg { 2157 1.1 joerg uint32_t destoffset; 2158 1.1 joerg uint16_t destval, *destreg; 2159 1.1 joerg 2160 1.1 joerg fetch_decode_modrm(emu); 2161 1.1 joerg if (emu->cur_mod != 3) { 2162 1.1 joerg destoffset = decode_rl_address(emu); 2163 1.1 joerg destval = pop_word(emu); 2164 1.1 joerg store_data_word(emu, destoffset, destval); 2165 1.1 joerg } else { 2166 1.1 joerg destreg = decode_rl_word_register(emu); 2167 1.1 joerg *destreg = pop_word(emu); 2168 1.1 joerg } 2169 1.1 joerg } 2170 1.1 joerg 2171 1.1 joerg static void 2172 1.1 joerg x86emuOp_pop_RM(struct X86EMU *emu) 2173 1.1 joerg { 2174 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2175 1.1 joerg x86emuOp32_pop_RM(emu); 2176 1.1 joerg else 2177 1.1 joerg x86emuOp16_pop_RM(emu); 2178 1.1 joerg } 2179 1.1 joerg /**************************************************************************** 2180 1.1 joerg REMARKS: 2181 1.1 joerg Handles opcode 0x91 2182 1.1 joerg ****************************************************************************/ 2183 1.1 joerg static void 2184 1.1 joerg x86emuOp_xchg_word_AX_CX(struct X86EMU *emu) 2185 1.1 joerg { 2186 1.1 joerg uint32_t tmp; 2187 1.1 joerg 2188 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2189 1.1 joerg tmp = emu->x86.R_EAX; 2190 1.1 joerg emu->x86.R_EAX = emu->x86.R_ECX; 2191 1.1 joerg emu->x86.R_ECX = tmp; 2192 1.1 joerg } else { 2193 1.1 joerg tmp = emu->x86.R_AX; 2194 1.1 joerg emu->x86.R_AX = emu->x86.R_CX; 2195 1.1 joerg emu->x86.R_CX = (uint16_t) tmp; 2196 1.1 joerg } 2197 1.1 joerg } 2198 1.1 joerg /**************************************************************************** 2199 1.1 joerg REMARKS: 2200 1.1 joerg Handles opcode 0x92 2201 1.1 joerg ****************************************************************************/ 2202 1.1 joerg static void 2203 1.1 joerg x86emuOp_xchg_word_AX_DX(struct X86EMU *emu) 2204 1.1 joerg { 2205 1.1 joerg uint32_t tmp; 2206 1.1 joerg 2207 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2208 1.1 joerg tmp = emu->x86.R_EAX; 2209 1.1 joerg emu->x86.R_EAX = emu->x86.R_EDX; 2210 1.1 joerg emu->x86.R_EDX = tmp; 2211 1.1 joerg } else { 2212 1.1 joerg tmp = emu->x86.R_AX; 2213 1.1 joerg emu->x86.R_AX = emu->x86.R_DX; 2214 1.1 joerg emu->x86.R_DX = (uint16_t) tmp; 2215 1.1 joerg } 2216 1.1 joerg } 2217 1.1 joerg /**************************************************************************** 2218 1.1 joerg REMARKS: 2219 1.1 joerg Handles opcode 0x93 2220 1.1 joerg ****************************************************************************/ 2221 1.1 joerg static void 2222 1.1 joerg x86emuOp_xchg_word_AX_BX(struct X86EMU *emu) 2223 1.1 joerg { 2224 1.1 joerg uint32_t tmp; 2225 1.1 joerg 2226 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2227 1.1 joerg tmp = emu->x86.R_EAX; 2228 1.1 joerg emu->x86.R_EAX = emu->x86.R_EBX; 2229 1.1 joerg emu->x86.R_EBX = tmp; 2230 1.1 joerg } else { 2231 1.1 joerg tmp = emu->x86.R_AX; 2232 1.1 joerg emu->x86.R_AX = emu->x86.R_BX; 2233 1.1 joerg emu->x86.R_BX = (uint16_t) tmp; 2234 1.1 joerg } 2235 1.1 joerg } 2236 1.1 joerg /**************************************************************************** 2237 1.1 joerg REMARKS: 2238 1.1 joerg Handles opcode 0x94 2239 1.1 joerg ****************************************************************************/ 2240 1.1 joerg static void 2241 1.1 joerg x86emuOp_xchg_word_AX_SP(struct X86EMU *emu) 2242 1.1 joerg { 2243 1.1 joerg uint32_t tmp; 2244 1.1 joerg 2245 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2246 1.1 joerg tmp = emu->x86.R_EAX; 2247 1.1 joerg emu->x86.R_EAX = emu->x86.R_ESP; 2248 1.1 joerg emu->x86.R_ESP = tmp; 2249 1.1 joerg } else { 2250 1.1 joerg tmp = emu->x86.R_AX; 2251 1.1 joerg emu->x86.R_AX = emu->x86.R_SP; 2252 1.1 joerg emu->x86.R_SP = (uint16_t) tmp; 2253 1.1 joerg } 2254 1.1 joerg } 2255 1.1 joerg /**************************************************************************** 2256 1.1 joerg REMARKS: 2257 1.1 joerg Handles opcode 0x95 2258 1.1 joerg ****************************************************************************/ 2259 1.1 joerg static void 2260 1.1 joerg x86emuOp_xchg_word_AX_BP(struct X86EMU *emu) 2261 1.1 joerg { 2262 1.1 joerg uint32_t tmp; 2263 1.1 joerg 2264 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2265 1.1 joerg tmp = emu->x86.R_EAX; 2266 1.1 joerg emu->x86.R_EAX = emu->x86.R_EBP; 2267 1.1 joerg emu->x86.R_EBP = tmp; 2268 1.1 joerg } else { 2269 1.1 joerg tmp = emu->x86.R_AX; 2270 1.1 joerg emu->x86.R_AX = emu->x86.R_BP; 2271 1.1 joerg emu->x86.R_BP = (uint16_t) tmp; 2272 1.1 joerg } 2273 1.1 joerg } 2274 1.1 joerg /**************************************************************************** 2275 1.1 joerg REMARKS: 2276 1.1 joerg Handles opcode 0x96 2277 1.1 joerg ****************************************************************************/ 2278 1.1 joerg static void 2279 1.1 joerg x86emuOp_xchg_word_AX_SI(struct X86EMU *emu) 2280 1.1 joerg { 2281 1.1 joerg uint32_t tmp; 2282 1.1 joerg 2283 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2284 1.1 joerg tmp = emu->x86.R_EAX; 2285 1.1 joerg emu->x86.R_EAX = emu->x86.R_ESI; 2286 1.1 joerg emu->x86.R_ESI = tmp; 2287 1.1 joerg } else { 2288 1.1 joerg tmp = emu->x86.R_AX; 2289 1.1 joerg emu->x86.R_AX = emu->x86.R_SI; 2290 1.1 joerg emu->x86.R_SI = (uint16_t) tmp; 2291 1.1 joerg } 2292 1.1 joerg } 2293 1.1 joerg /**************************************************************************** 2294 1.1 joerg REMARKS: 2295 1.1 joerg Handles opcode 0x97 2296 1.1 joerg ****************************************************************************/ 2297 1.1 joerg static void 2298 1.1 joerg x86emuOp_xchg_word_AX_DI(struct X86EMU *emu) 2299 1.1 joerg { 2300 1.1 joerg uint32_t tmp; 2301 1.1 joerg 2302 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2303 1.1 joerg tmp = emu->x86.R_EAX; 2304 1.1 joerg emu->x86.R_EAX = emu->x86.R_EDI; 2305 1.1 joerg emu->x86.R_EDI = tmp; 2306 1.1 joerg } else { 2307 1.1 joerg tmp = emu->x86.R_AX; 2308 1.1 joerg emu->x86.R_AX = emu->x86.R_DI; 2309 1.1 joerg emu->x86.R_DI = (uint16_t) tmp; 2310 1.1 joerg } 2311 1.1 joerg } 2312 1.1 joerg /**************************************************************************** 2313 1.1 joerg REMARKS: 2314 1.1 joerg Handles opcode 0x98 2315 1.1 joerg ****************************************************************************/ 2316 1.1 joerg static void 2317 1.1 joerg x86emuOp_cbw(struct X86EMU *emu) 2318 1.1 joerg { 2319 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2320 1.1 joerg if (emu->x86.R_AX & 0x8000) { 2321 1.1 joerg emu->x86.R_EAX |= 0xffff0000; 2322 1.1 joerg } else { 2323 1.1 joerg emu->x86.R_EAX &= 0x0000ffff; 2324 1.1 joerg } 2325 1.1 joerg } else { 2326 1.1 joerg if (emu->x86.R_AL & 0x80) { 2327 1.1 joerg emu->x86.R_AH = 0xff; 2328 1.1 joerg } else { 2329 1.1 joerg emu->x86.R_AH = 0x0; 2330 1.1 joerg } 2331 1.1 joerg } 2332 1.1 joerg } 2333 1.1 joerg /**************************************************************************** 2334 1.1 joerg REMARKS: 2335 1.1 joerg Handles opcode 0x99 2336 1.1 joerg ****************************************************************************/ 2337 1.1 joerg static void 2338 1.1 joerg x86emuOp_cwd(struct X86EMU *emu) 2339 1.1 joerg { 2340 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2341 1.1 joerg if (emu->x86.R_EAX & 0x80000000) { 2342 1.1 joerg emu->x86.R_EDX = 0xffffffff; 2343 1.1 joerg } else { 2344 1.1 joerg emu->x86.R_EDX = 0x0; 2345 1.1 joerg } 2346 1.1 joerg } else { 2347 1.1 joerg if (emu->x86.R_AX & 0x8000) { 2348 1.1 joerg emu->x86.R_DX = 0xffff; 2349 1.1 joerg } else { 2350 1.1 joerg emu->x86.R_DX = 0x0; 2351 1.1 joerg } 2352 1.1 joerg } 2353 1.1 joerg } 2354 1.1 joerg /**************************************************************************** 2355 1.1 joerg REMARKS: 2356 1.1 joerg Handles opcode 0x9a 2357 1.1 joerg ****************************************************************************/ 2358 1.1 joerg static void 2359 1.1 joerg x86emuOp_call_far_IMM(struct X86EMU *emu) 2360 1.1 joerg { 2361 1.1 joerg uint16_t farseg, faroff; 2362 1.1 joerg 2363 1.1 joerg faroff = fetch_word_imm(emu); 2364 1.1 joerg farseg = fetch_word_imm(emu); 2365 1.1 joerg /* XXX 2366 1.1 joerg * 2367 1.1 joerg * Hooked interrupt vectors calling into our "BIOS" will cause problems 2368 1.1 joerg * unless all intersegment stuff is checked for BIOS access. Check 2369 1.1 joerg * needed here. For moment, let it alone. */ 2370 1.1 joerg push_word(emu, emu->x86.R_CS); 2371 1.1 joerg emu->x86.R_CS = farseg; 2372 1.1 joerg push_word(emu, emu->x86.R_IP); 2373 1.1 joerg emu->x86.R_IP = faroff; 2374 1.1 joerg } 2375 1.1 joerg /**************************************************************************** 2376 1.1 joerg REMARKS: 2377 1.1 joerg Handles opcode 0x9c 2378 1.1 joerg ****************************************************************************/ 2379 1.1 joerg static void 2380 1.1 joerg x86emuOp_pushf_word(struct X86EMU *emu) 2381 1.1 joerg { 2382 1.1 joerg uint32_t flags; 2383 1.1 joerg 2384 1.1 joerg /* clear out *all* bits not representing flags, and turn on real bits */ 2385 1.1 joerg flags = (emu->x86.R_EFLG & F_MSK) | F_ALWAYS_ON; 2386 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2387 1.1 joerg push_long(emu, flags); 2388 1.1 joerg } else { 2389 1.1 joerg push_word(emu, (uint16_t) flags); 2390 1.1 joerg } 2391 1.1 joerg } 2392 1.1 joerg /**************************************************************************** 2393 1.1 joerg REMARKS: 2394 1.1 joerg Handles opcode 0x9d 2395 1.1 joerg ****************************************************************************/ 2396 1.1 joerg static void 2397 1.1 joerg x86emuOp_popf_word(struct X86EMU *emu) 2398 1.1 joerg { 2399 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2400 1.1 joerg emu->x86.R_EFLG = pop_long(emu); 2401 1.1 joerg } else { 2402 1.1 joerg emu->x86.R_FLG = pop_word(emu); 2403 1.1 joerg } 2404 1.1 joerg } 2405 1.1 joerg /**************************************************************************** 2406 1.1 joerg REMARKS: 2407 1.1 joerg Handles opcode 0x9e 2408 1.1 joerg ****************************************************************************/ 2409 1.1 joerg static void 2410 1.1 joerg x86emuOp_sahf(struct X86EMU *emu) 2411 1.1 joerg { 2412 1.1 joerg /* clear the lower bits of the flag register */ 2413 1.1 joerg emu->x86.R_FLG &= 0xffffff00; 2414 1.1 joerg /* or in the AH register into the flags register */ 2415 1.1 joerg emu->x86.R_FLG |= emu->x86.R_AH; 2416 1.1 joerg } 2417 1.1 joerg /**************************************************************************** 2418 1.1 joerg REMARKS: 2419 1.1 joerg Handles opcode 0x9f 2420 1.1 joerg ****************************************************************************/ 2421 1.1 joerg static void 2422 1.1 joerg x86emuOp_lahf(struct X86EMU *emu) 2423 1.1 joerg { 2424 1.1 joerg emu->x86.R_AH = (uint8_t) (emu->x86.R_FLG & 0xff); 2425 1.1 joerg /* undocumented TC++ behavior??? Nope. It's documented, but you have 2426 1.1 joerg * too look real hard to notice it. */ 2427 1.1 joerg emu->x86.R_AH |= 0x2; 2428 1.1 joerg } 2429 1.1 joerg /**************************************************************************** 2430 1.1 joerg REMARKS: 2431 1.1 joerg Handles opcode 0xa0 2432 1.1 joerg ****************************************************************************/ 2433 1.1 joerg static void 2434 1.1 joerg x86emuOp_mov_AL_M_IMM(struct X86EMU *emu) 2435 1.1 joerg { 2436 1.1 joerg uint16_t offset; 2437 1.1 joerg 2438 1.1 joerg offset = fetch_word_imm(emu); 2439 1.1 joerg emu->x86.R_AL = fetch_data_byte(emu, offset); 2440 1.1 joerg } 2441 1.1 joerg /**************************************************************************** 2442 1.1 joerg REMARKS: 2443 1.1 joerg Handles opcode 0xa1 2444 1.1 joerg ****************************************************************************/ 2445 1.1 joerg static void 2446 1.1 joerg x86emuOp_mov_AX_M_IMM(struct X86EMU *emu) 2447 1.1 joerg { 2448 1.1 joerg uint16_t offset; 2449 1.1 joerg 2450 1.1 joerg offset = fetch_word_imm(emu); 2451 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2452 1.1 joerg emu->x86.R_EAX = fetch_data_long(emu, offset); 2453 1.1 joerg } else { 2454 1.1 joerg emu->x86.R_AX = fetch_data_word(emu, offset); 2455 1.1 joerg } 2456 1.1 joerg } 2457 1.1 joerg /**************************************************************************** 2458 1.1 joerg REMARKS: 2459 1.1 joerg Handles opcode 0xa2 2460 1.1 joerg ****************************************************************************/ 2461 1.1 joerg static void 2462 1.1 joerg x86emuOp_mov_M_AL_IMM(struct X86EMU *emu) 2463 1.1 joerg { 2464 1.1 joerg uint16_t offset; 2465 1.1 joerg 2466 1.1 joerg offset = fetch_word_imm(emu); 2467 1.1 joerg store_data_byte(emu, offset, emu->x86.R_AL); 2468 1.1 joerg } 2469 1.1 joerg /**************************************************************************** 2470 1.1 joerg REMARKS: 2471 1.1 joerg Handles opcode 0xa3 2472 1.1 joerg ****************************************************************************/ 2473 1.1 joerg static void 2474 1.1 joerg x86emuOp_mov_M_AX_IMM(struct X86EMU *emu) 2475 1.1 joerg { 2476 1.1 joerg uint16_t offset; 2477 1.1 joerg 2478 1.1 joerg offset = fetch_word_imm(emu); 2479 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2480 1.1 joerg store_data_long(emu, offset, emu->x86.R_EAX); 2481 1.1 joerg } else { 2482 1.1 joerg store_data_word(emu, offset, emu->x86.R_AX); 2483 1.1 joerg } 2484 1.1 joerg } 2485 1.1 joerg /**************************************************************************** 2486 1.1 joerg REMARKS: 2487 1.1 joerg Handles opcode 0xa4 2488 1.1 joerg ****************************************************************************/ 2489 1.1 joerg static void 2490 1.1 joerg x86emuOp_movs_byte(struct X86EMU *emu) 2491 1.1 joerg { 2492 1.1 joerg uint8_t val; 2493 1.1 joerg uint32_t count; 2494 1.1 joerg int inc; 2495 1.1 joerg 2496 1.1 joerg if (ACCESS_FLAG(F_DF)) /* down */ 2497 1.1 joerg inc = -1; 2498 1.1 joerg else 2499 1.1 joerg inc = 1; 2500 1.1 joerg count = 1; 2501 1.1 joerg if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2502 1.1 joerg /* dont care whether REPE or REPNE */ 2503 1.1 joerg /* move them until CX is ZERO. */ 2504 1.1 joerg count = emu->x86.R_CX; 2505 1.1 joerg emu->x86.R_CX = 0; 2506 1.1 joerg emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2507 1.1 joerg } 2508 1.1 joerg while (count--) { 2509 1.1 joerg val = fetch_data_byte(emu, emu->x86.R_SI); 2510 1.1 joerg store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, val); 2511 1.1 joerg emu->x86.R_SI += inc; 2512 1.1 joerg emu->x86.R_DI += inc; 2513 1.1 joerg } 2514 1.1 joerg } 2515 1.1 joerg /**************************************************************************** 2516 1.1 joerg REMARKS: 2517 1.1 joerg Handles opcode 0xa5 2518 1.1 joerg ****************************************************************************/ 2519 1.1 joerg static void 2520 1.1 joerg x86emuOp_movs_word(struct X86EMU *emu) 2521 1.1 joerg { 2522 1.1 joerg uint32_t val; 2523 1.1 joerg int inc; 2524 1.1 joerg uint32_t count; 2525 1.1 joerg 2526 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2527 1.1 joerg inc = 4; 2528 1.1 joerg else 2529 1.1 joerg inc = 2; 2530 1.1 joerg 2531 1.1 joerg if (ACCESS_FLAG(F_DF)) /* down */ 2532 1.1 joerg inc = -inc; 2533 1.1 joerg 2534 1.1 joerg count = 1; 2535 1.1 joerg if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2536 1.1 joerg /* dont care whether REPE or REPNE */ 2537 1.1 joerg /* move them until CX is ZERO. */ 2538 1.1 joerg count = emu->x86.R_CX; 2539 1.1 joerg emu->x86.R_CX = 0; 2540 1.1 joerg emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2541 1.1 joerg } 2542 1.1 joerg while (count--) { 2543 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2544 1.1 joerg val = fetch_data_long(emu, emu->x86.R_SI); 2545 1.1 joerg store_long(emu, emu->x86.R_ES, emu->x86.R_DI, val); 2546 1.1 joerg } else { 2547 1.1 joerg val = fetch_data_word(emu, emu->x86.R_SI); 2548 1.1 joerg store_word(emu, emu->x86.R_ES, emu->x86.R_DI, (uint16_t) val); 2549 1.1 joerg } 2550 1.1 joerg emu->x86.R_SI += inc; 2551 1.1 joerg emu->x86.R_DI += inc; 2552 1.1 joerg } 2553 1.1 joerg } 2554 1.1 joerg /**************************************************************************** 2555 1.1 joerg REMARKS: 2556 1.1 joerg Handles opcode 0xa6 2557 1.1 joerg ****************************************************************************/ 2558 1.1 joerg static void 2559 1.1 joerg x86emuOp_cmps_byte(struct X86EMU *emu) 2560 1.1 joerg { 2561 1.1 joerg int8_t val1, val2; 2562 1.1 joerg int inc; 2563 1.1 joerg 2564 1.1 joerg if (ACCESS_FLAG(F_DF)) /* down */ 2565 1.1 joerg inc = -1; 2566 1.1 joerg else 2567 1.1 joerg inc = 1; 2568 1.1 joerg 2569 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_REPE) { 2570 1.1 joerg /* REPE */ 2571 1.1 joerg /* move them until CX is ZERO. */ 2572 1.1 joerg while (emu->x86.R_CX != 0) { 2573 1.1 joerg val1 = fetch_data_byte(emu, emu->x86.R_SI); 2574 1.1 joerg val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2575 1.1 joerg cmp_byte(emu, val1, val2); 2576 1.1 joerg emu->x86.R_CX -= 1; 2577 1.1 joerg emu->x86.R_SI += inc; 2578 1.1 joerg emu->x86.R_DI += inc; 2579 1.1 joerg if (ACCESS_FLAG(F_ZF) == 0) 2580 1.1 joerg break; 2581 1.1 joerg } 2582 1.1 joerg emu->x86.mode &= ~SYSMODE_PREFIX_REPE; 2583 1.1 joerg } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) { 2584 1.1 joerg /* REPNE */ 2585 1.1 joerg /* move them until CX is ZERO. */ 2586 1.1 joerg while (emu->x86.R_CX != 0) { 2587 1.1 joerg val1 = fetch_data_byte(emu, emu->x86.R_SI); 2588 1.1 joerg val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2589 1.1 joerg cmp_byte(emu, val1, val2); 2590 1.1 joerg emu->x86.R_CX -= 1; 2591 1.1 joerg emu->x86.R_SI += inc; 2592 1.1 joerg emu->x86.R_DI += inc; 2593 1.1 joerg if (ACCESS_FLAG(F_ZF)) 2594 1.1 joerg break; /* zero flag set means equal */ 2595 1.1 joerg } 2596 1.1 joerg emu->x86.mode &= ~SYSMODE_PREFIX_REPNE; 2597 1.1 joerg } else { 2598 1.1 joerg val1 = fetch_data_byte(emu, emu->x86.R_SI); 2599 1.1 joerg val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2600 1.1 joerg cmp_byte(emu, val1, val2); 2601 1.1 joerg emu->x86.R_SI += inc; 2602 1.1 joerg emu->x86.R_DI += inc; 2603 1.1 joerg } 2604 1.1 joerg } 2605 1.1 joerg /**************************************************************************** 2606 1.1 joerg REMARKS: 2607 1.1 joerg Handles opcode 0xa7 2608 1.1 joerg ****************************************************************************/ 2609 1.1 joerg static void 2610 1.1 joerg x86emuOp_cmps_word(struct X86EMU *emu) 2611 1.1 joerg { 2612 1.1 joerg uint32_t val1, val2; 2613 1.1 joerg int inc; 2614 1.1 joerg 2615 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2616 1.1 joerg if (ACCESS_FLAG(F_DF)) /* down */ 2617 1.1 joerg inc = -4; 2618 1.1 joerg else 2619 1.1 joerg inc = 4; 2620 1.1 joerg } else { 2621 1.1 joerg if (ACCESS_FLAG(F_DF)) /* down */ 2622 1.1 joerg inc = -2; 2623 1.1 joerg else 2624 1.1 joerg inc = 2; 2625 1.1 joerg } 2626 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_REPE) { 2627 1.1 joerg /* REPE */ 2628 1.1 joerg /* move them until CX is ZERO. */ 2629 1.1 joerg while (emu->x86.R_CX != 0) { 2630 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2631 1.1 joerg val1 = fetch_data_long(emu, emu->x86.R_SI); 2632 1.1 joerg val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2633 1.1 joerg cmp_long(emu, val1, val2); 2634 1.1 joerg } else { 2635 1.1 joerg val1 = fetch_data_word(emu, emu->x86.R_SI); 2636 1.1 joerg val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2637 1.1 joerg cmp_word(emu, (uint16_t) val1, (uint16_t) val2); 2638 1.1 joerg } 2639 1.1 joerg emu->x86.R_CX -= 1; 2640 1.1 joerg emu->x86.R_SI += inc; 2641 1.1 joerg emu->x86.R_DI += inc; 2642 1.1 joerg if (ACCESS_FLAG(F_ZF) == 0) 2643 1.1 joerg break; 2644 1.1 joerg } 2645 1.1 joerg emu->x86.mode &= ~SYSMODE_PREFIX_REPE; 2646 1.1 joerg } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) { 2647 1.1 joerg /* REPNE */ 2648 1.1 joerg /* move them until CX is ZERO. */ 2649 1.1 joerg while (emu->x86.R_CX != 0) { 2650 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2651 1.1 joerg val1 = fetch_data_long(emu, emu->x86.R_SI); 2652 1.1 joerg val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2653 1.1 joerg cmp_long(emu, val1, val2); 2654 1.1 joerg } else { 2655 1.1 joerg val1 = fetch_data_word(emu, emu->x86.R_SI); 2656 1.1 joerg val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2657 1.1 joerg cmp_word(emu, (uint16_t) val1, (uint16_t) val2); 2658 1.1 joerg } 2659 1.1 joerg emu->x86.R_CX -= 1; 2660 1.1 joerg emu->x86.R_SI += inc; 2661 1.1 joerg emu->x86.R_DI += inc; 2662 1.1 joerg if (ACCESS_FLAG(F_ZF)) 2663 1.1 joerg break; /* zero flag set means equal */ 2664 1.1 joerg } 2665 1.1 joerg emu->x86.mode &= ~SYSMODE_PREFIX_REPNE; 2666 1.1 joerg } else { 2667 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2668 1.1 joerg val1 = fetch_data_long(emu, emu->x86.R_SI); 2669 1.1 joerg val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2670 1.1 joerg cmp_long(emu, val1, val2); 2671 1.1 joerg } else { 2672 1.1 joerg val1 = fetch_data_word(emu, emu->x86.R_SI); 2673 1.1 joerg val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2674 1.1 joerg cmp_word(emu, (uint16_t) val1, (uint16_t) val2); 2675 1.1 joerg } 2676 1.1 joerg emu->x86.R_SI += inc; 2677 1.1 joerg emu->x86.R_DI += inc; 2678 1.1 joerg } 2679 1.1 joerg } 2680 1.1 joerg /**************************************************************************** 2681 1.1 joerg REMARKS: 2682 1.1 joerg Handles opcode 0xa9 2683 1.1 joerg ****************************************************************************/ 2684 1.1 joerg static void 2685 1.1 joerg x86emuOp_test_AX_IMM(struct X86EMU *emu) 2686 1.1 joerg { 2687 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2688 1.1 joerg test_long(emu, emu->x86.R_EAX, fetch_long_imm(emu)); 2689 1.1 joerg } else { 2690 1.1 joerg test_word(emu, emu->x86.R_AX, fetch_word_imm(emu)); 2691 1.1 joerg } 2692 1.1 joerg } 2693 1.1 joerg /**************************************************************************** 2694 1.1 joerg REMARKS: 2695 1.1 joerg Handles opcode 0xaa 2696 1.1 joerg ****************************************************************************/ 2697 1.1 joerg static void 2698 1.1 joerg x86emuOp_stos_byte(struct X86EMU *emu) 2699 1.1 joerg { 2700 1.1 joerg int inc; 2701 1.1 joerg 2702 1.1 joerg if (ACCESS_FLAG(F_DF)) /* down */ 2703 1.1 joerg inc = -1; 2704 1.1 joerg else 2705 1.1 joerg inc = 1; 2706 1.1 joerg if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2707 1.1 joerg /* dont care whether REPE or REPNE */ 2708 1.1 joerg /* move them until CX is ZERO. */ 2709 1.1 joerg while (emu->x86.R_CX != 0) { 2710 1.1 joerg store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL); 2711 1.1 joerg emu->x86.R_CX -= 1; 2712 1.1 joerg emu->x86.R_DI += inc; 2713 1.1 joerg } 2714 1.1 joerg emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2715 1.1 joerg } else { 2716 1.1 joerg store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL); 2717 1.1 joerg emu->x86.R_DI += inc; 2718 1.1 joerg } 2719 1.1 joerg } 2720 1.1 joerg /**************************************************************************** 2721 1.1 joerg REMARKS: 2722 1.1 joerg Handles opcode 0xab 2723 1.1 joerg ****************************************************************************/ 2724 1.1 joerg static void 2725 1.1 joerg x86emuOp_stos_word(struct X86EMU *emu) 2726 1.1 joerg { 2727 1.1 joerg int inc; 2728 1.1 joerg uint32_t count; 2729 1.1 joerg 2730 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2731 1.1 joerg inc = 4; 2732 1.1 joerg else 2733 1.1 joerg inc = 2; 2734 1.1 joerg 2735 1.1 joerg if (ACCESS_FLAG(F_DF)) /* down */ 2736 1.1 joerg inc = -inc; 2737 1.1 joerg 2738 1.1 joerg count = 1; 2739 1.1 joerg if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2740 1.1 joerg /* dont care whether REPE or REPNE */ 2741 1.1 joerg /* move them until CX is ZERO. */ 2742 1.1 joerg count = emu->x86.R_CX; 2743 1.1 joerg emu->x86.R_CX = 0; 2744 1.1 joerg emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2745 1.1 joerg } 2746 1.1 joerg while (count--) { 2747 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2748 1.1 joerg store_long(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_EAX); 2749 1.1 joerg } else { 2750 1.1 joerg store_word(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AX); 2751 1.1 joerg } 2752 1.1 joerg emu->x86.R_DI += inc; 2753 1.1 joerg } 2754 1.1 joerg } 2755 1.1 joerg /**************************************************************************** 2756 1.1 joerg REMARKS: 2757 1.1 joerg Handles opcode 0xac 2758 1.1 joerg ****************************************************************************/ 2759 1.1 joerg static void 2760 1.1 joerg x86emuOp_lods_byte(struct X86EMU *emu) 2761 1.1 joerg { 2762 1.1 joerg int inc; 2763 1.1 joerg 2764 1.1 joerg if (ACCESS_FLAG(F_DF)) /* down */ 2765 1.1 joerg inc = -1; 2766 1.1 joerg else 2767 1.1 joerg inc = 1; 2768 1.1 joerg if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2769 1.1 joerg /* dont care whether REPE or REPNE */ 2770 1.1 joerg /* move them until CX is ZERO. */ 2771 1.1 joerg while (emu->x86.R_CX != 0) { 2772 1.1 joerg emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI); 2773 1.1 joerg emu->x86.R_CX -= 1; 2774 1.1 joerg emu->x86.R_SI += inc; 2775 1.1 joerg } 2776 1.1 joerg emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2777 1.1 joerg } else { 2778 1.1 joerg emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI); 2779 1.1 joerg emu->x86.R_SI += inc; 2780 1.1 joerg } 2781 1.1 joerg } 2782 1.1 joerg /**************************************************************************** 2783 1.1 joerg REMARKS: 2784 1.1 joerg Handles opcode 0xad 2785 1.1 joerg ****************************************************************************/ 2786 1.1 joerg static void 2787 1.1 joerg x86emuOp_lods_word(struct X86EMU *emu) 2788 1.1 joerg { 2789 1.1 joerg int inc; 2790 1.1 joerg uint32_t count; 2791 1.1 joerg 2792 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2793 1.1 joerg inc = 4; 2794 1.1 joerg else 2795 1.1 joerg inc = 2; 2796 1.1 joerg 2797 1.1 joerg if (ACCESS_FLAG(F_DF)) /* down */ 2798 1.1 joerg inc = -inc; 2799 1.1 joerg 2800 1.1 joerg count = 1; 2801 1.1 joerg if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 2802 1.1 joerg /* dont care whether REPE or REPNE */ 2803 1.1 joerg /* move them until CX is ZERO. */ 2804 1.1 joerg count = emu->x86.R_CX; 2805 1.1 joerg emu->x86.R_CX = 0; 2806 1.1 joerg emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 2807 1.1 joerg } 2808 1.1 joerg while (count--) { 2809 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2810 1.1 joerg emu->x86.R_EAX = fetch_data_long(emu, emu->x86.R_SI); 2811 1.1 joerg } else { 2812 1.1 joerg emu->x86.R_AX = fetch_data_word(emu, emu->x86.R_SI); 2813 1.1 joerg } 2814 1.1 joerg emu->x86.R_SI += inc; 2815 1.1 joerg } 2816 1.1 joerg } 2817 1.1 joerg /**************************************************************************** 2818 1.1 joerg REMARKS: 2819 1.1 joerg Handles opcode 0xae 2820 1.1 joerg ****************************************************************************/ 2821 1.1 joerg static void 2822 1.1 joerg x86emuOp_scas_byte(struct X86EMU *emu) 2823 1.1 joerg { 2824 1.1 joerg int8_t val2; 2825 1.1 joerg int inc; 2826 1.1 joerg 2827 1.1 joerg if (ACCESS_FLAG(F_DF)) /* down */ 2828 1.1 joerg inc = -1; 2829 1.1 joerg else 2830 1.1 joerg inc = 1; 2831 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_REPE) { 2832 1.1 joerg /* REPE */ 2833 1.1 joerg /* move them until CX is ZERO. */ 2834 1.1 joerg while (emu->x86.R_CX != 0) { 2835 1.1 joerg val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2836 1.1 joerg cmp_byte(emu, emu->x86.R_AL, val2); 2837 1.1 joerg emu->x86.R_CX -= 1; 2838 1.1 joerg emu->x86.R_DI += inc; 2839 1.1 joerg if (ACCESS_FLAG(F_ZF) == 0) 2840 1.1 joerg break; 2841 1.1 joerg } 2842 1.1 joerg emu->x86.mode &= ~SYSMODE_PREFIX_REPE; 2843 1.1 joerg } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) { 2844 1.1 joerg /* REPNE */ 2845 1.1 joerg /* move them until CX is ZERO. */ 2846 1.1 joerg while (emu->x86.R_CX != 0) { 2847 1.1 joerg val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2848 1.1 joerg cmp_byte(emu, emu->x86.R_AL, val2); 2849 1.1 joerg emu->x86.R_CX -= 1; 2850 1.1 joerg emu->x86.R_DI += inc; 2851 1.1 joerg if (ACCESS_FLAG(F_ZF)) 2852 1.1 joerg break; /* zero flag set means equal */ 2853 1.1 joerg } 2854 1.1 joerg emu->x86.mode &= ~SYSMODE_PREFIX_REPNE; 2855 1.1 joerg } else { 2856 1.1 joerg val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI); 2857 1.1 joerg cmp_byte(emu, emu->x86.R_AL, val2); 2858 1.1 joerg emu->x86.R_DI += inc; 2859 1.1 joerg } 2860 1.1 joerg } 2861 1.1 joerg /**************************************************************************** 2862 1.1 joerg REMARKS: 2863 1.1 joerg Handles opcode 0xaf 2864 1.1 joerg ****************************************************************************/ 2865 1.1 joerg static void 2866 1.1 joerg x86emuOp_scas_word(struct X86EMU *emu) 2867 1.1 joerg { 2868 1.1 joerg int inc; 2869 1.1 joerg uint32_t val; 2870 1.1 joerg 2871 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2872 1.1 joerg inc = 4; 2873 1.1 joerg else 2874 1.1 joerg inc = 2; 2875 1.1 joerg 2876 1.1 joerg if (ACCESS_FLAG(F_DF)) /* down */ 2877 1.1 joerg inc = -inc; 2878 1.1 joerg 2879 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_REPE) { 2880 1.1 joerg /* REPE */ 2881 1.1 joerg /* move them until CX is ZERO. */ 2882 1.1 joerg while (emu->x86.R_CX != 0) { 2883 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2884 1.1 joerg val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2885 1.1 joerg cmp_long(emu, emu->x86.R_EAX, val); 2886 1.1 joerg } else { 2887 1.1 joerg val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2888 1.1 joerg cmp_word(emu, emu->x86.R_AX, (uint16_t) val); 2889 1.1 joerg } 2890 1.1 joerg emu->x86.R_CX -= 1; 2891 1.1 joerg emu->x86.R_DI += inc; 2892 1.1 joerg if (ACCESS_FLAG(F_ZF) == 0) 2893 1.1 joerg break; 2894 1.1 joerg } 2895 1.1 joerg emu->x86.mode &= ~SYSMODE_PREFIX_REPE; 2896 1.1 joerg } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) { 2897 1.1 joerg /* REPNE */ 2898 1.1 joerg /* move them until CX is ZERO. */ 2899 1.1 joerg while (emu->x86.R_CX != 0) { 2900 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2901 1.1 joerg val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2902 1.1 joerg cmp_long(emu, emu->x86.R_EAX, val); 2903 1.1 joerg } else { 2904 1.1 joerg val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2905 1.1 joerg cmp_word(emu, emu->x86.R_AX, (uint16_t) val); 2906 1.1 joerg } 2907 1.1 joerg emu->x86.R_CX -= 1; 2908 1.1 joerg emu->x86.R_DI += inc; 2909 1.1 joerg if (ACCESS_FLAG(F_ZF)) 2910 1.1 joerg break; /* zero flag set means equal */ 2911 1.1 joerg } 2912 1.1 joerg emu->x86.mode &= ~SYSMODE_PREFIX_REPNE; 2913 1.1 joerg } else { 2914 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 2915 1.1 joerg val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI); 2916 1.1 joerg cmp_long(emu, emu->x86.R_EAX, val); 2917 1.1 joerg } else { 2918 1.1 joerg val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI); 2919 1.1 joerg cmp_word(emu, emu->x86.R_AX, (uint16_t) val); 2920 1.1 joerg } 2921 1.1 joerg emu->x86.R_DI += inc; 2922 1.1 joerg } 2923 1.1 joerg } 2924 1.1 joerg /**************************************************************************** 2925 1.1 joerg REMARKS: 2926 1.1 joerg Handles opcode 0xb8 2927 1.1 joerg ****************************************************************************/ 2928 1.1 joerg static void 2929 1.1 joerg x86emuOp_mov_word_AX_IMM(struct X86EMU *emu) 2930 1.1 joerg { 2931 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2932 1.1 joerg emu->x86.R_EAX = fetch_long_imm(emu); 2933 1.1 joerg else 2934 1.1 joerg emu->x86.R_AX = fetch_word_imm(emu); 2935 1.1 joerg } 2936 1.1 joerg /**************************************************************************** 2937 1.1 joerg REMARKS: 2938 1.1 joerg Handles opcode 0xb9 2939 1.1 joerg ****************************************************************************/ 2940 1.1 joerg static void 2941 1.1 joerg x86emuOp_mov_word_CX_IMM(struct X86EMU *emu) 2942 1.1 joerg { 2943 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2944 1.1 joerg emu->x86.R_ECX = fetch_long_imm(emu); 2945 1.1 joerg else 2946 1.1 joerg emu->x86.R_CX = fetch_word_imm(emu); 2947 1.1 joerg } 2948 1.1 joerg /**************************************************************************** 2949 1.1 joerg REMARKS: 2950 1.1 joerg Handles opcode 0xba 2951 1.1 joerg ****************************************************************************/ 2952 1.1 joerg static void 2953 1.1 joerg x86emuOp_mov_word_DX_IMM(struct X86EMU *emu) 2954 1.1 joerg { 2955 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2956 1.1 joerg emu->x86.R_EDX = fetch_long_imm(emu); 2957 1.1 joerg else 2958 1.1 joerg emu->x86.R_DX = fetch_word_imm(emu); 2959 1.1 joerg } 2960 1.1 joerg /**************************************************************************** 2961 1.1 joerg REMARKS: 2962 1.1 joerg Handles opcode 0xbb 2963 1.1 joerg ****************************************************************************/ 2964 1.1 joerg static void 2965 1.1 joerg x86emuOp_mov_word_BX_IMM(struct X86EMU *emu) 2966 1.1 joerg { 2967 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2968 1.1 joerg emu->x86.R_EBX = fetch_long_imm(emu); 2969 1.1 joerg else 2970 1.1 joerg emu->x86.R_BX = fetch_word_imm(emu); 2971 1.1 joerg } 2972 1.1 joerg /**************************************************************************** 2973 1.1 joerg REMARKS: 2974 1.1 joerg Handles opcode 0xbc 2975 1.1 joerg ****************************************************************************/ 2976 1.1 joerg static void 2977 1.1 joerg x86emuOp_mov_word_SP_IMM(struct X86EMU *emu) 2978 1.1 joerg { 2979 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2980 1.1 joerg emu->x86.R_ESP = fetch_long_imm(emu); 2981 1.1 joerg else 2982 1.1 joerg emu->x86.R_SP = fetch_word_imm(emu); 2983 1.1 joerg } 2984 1.1 joerg /**************************************************************************** 2985 1.1 joerg REMARKS: 2986 1.1 joerg Handles opcode 0xbd 2987 1.1 joerg ****************************************************************************/ 2988 1.1 joerg static void 2989 1.1 joerg x86emuOp_mov_word_BP_IMM(struct X86EMU *emu) 2990 1.1 joerg { 2991 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 2992 1.1 joerg emu->x86.R_EBP = fetch_long_imm(emu); 2993 1.1 joerg else 2994 1.1 joerg emu->x86.R_BP = fetch_word_imm(emu); 2995 1.1 joerg } 2996 1.1 joerg /**************************************************************************** 2997 1.1 joerg REMARKS: 2998 1.1 joerg Handles opcode 0xbe 2999 1.1 joerg ****************************************************************************/ 3000 1.1 joerg static void 3001 1.1 joerg x86emuOp_mov_word_SI_IMM(struct X86EMU *emu) 3002 1.1 joerg { 3003 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3004 1.1 joerg emu->x86.R_ESI = fetch_long_imm(emu); 3005 1.1 joerg else 3006 1.1 joerg emu->x86.R_SI = fetch_word_imm(emu); 3007 1.1 joerg } 3008 1.1 joerg /**************************************************************************** 3009 1.1 joerg REMARKS: 3010 1.1 joerg Handles opcode 0xbf 3011 1.1 joerg ****************************************************************************/ 3012 1.1 joerg static void 3013 1.1 joerg x86emuOp_mov_word_DI_IMM(struct X86EMU *emu) 3014 1.1 joerg { 3015 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3016 1.1 joerg emu->x86.R_EDI = fetch_long_imm(emu); 3017 1.1 joerg else 3018 1.1 joerg emu->x86.R_DI = fetch_word_imm(emu); 3019 1.1 joerg } 3020 1.1 joerg /* used by opcodes c0, d0, and d2. */ 3021 1.1 joerg static 3022 1.1 joerg uint8_t(* const opcD0_byte_operation[]) (struct X86EMU *, uint8_t d, uint8_t s) = 3023 1.1 joerg { 3024 1.1 joerg rol_byte, 3025 1.1 joerg ror_byte, 3026 1.1 joerg rcl_byte, 3027 1.1 joerg rcr_byte, 3028 1.1 joerg shl_byte, 3029 1.1 joerg shr_byte, 3030 1.1 joerg shl_byte, /* sal_byte === shl_byte by definition */ 3031 1.1 joerg sar_byte, 3032 1.1 joerg }; 3033 1.1 joerg /**************************************************************************** 3034 1.1 joerg REMARKS: 3035 1.1 joerg Handles opcode 0xc0 3036 1.1 joerg ****************************************************************************/ 3037 1.1 joerg static void 3038 1.1 joerg x86emuOp_opcC0_byte_RM_MEM(struct X86EMU *emu) 3039 1.1 joerg { 3040 1.1 joerg uint8_t destval, amt; 3041 1.1 joerg 3042 1.1 joerg /* 3043 1.1 joerg * Yet another weirdo special case instruction format. Part of 3044 1.1 joerg * the opcode held below in "RH". Doubly nested case would 3045 1.1 joerg * result, except that the decoded instruction 3046 1.1 joerg */ 3047 1.1 joerg fetch_decode_modrm(emu); 3048 1.1 joerg /* know operation, decode the mod byte to find the addressing mode. */ 3049 1.1 joerg destval = decode_and_fetch_byte_imm8(emu, &amt); 3050 1.1 joerg destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, amt); 3051 1.1 joerg write_back_byte(emu, destval); 3052 1.1 joerg } 3053 1.1 joerg /* used by opcodes c1, d1, and d3. */ 3054 1.1 joerg static 3055 1.1 joerg uint16_t(* const opcD1_word_operation[]) (struct X86EMU *, uint16_t s, uint8_t d) = 3056 1.1 joerg { 3057 1.1 joerg rol_word, 3058 1.1 joerg ror_word, 3059 1.1 joerg rcl_word, 3060 1.1 joerg rcr_word, 3061 1.1 joerg shl_word, 3062 1.1 joerg shr_word, 3063 1.1 joerg shl_word, /* sal_byte === shl_byte by definition */ 3064 1.1 joerg sar_word, 3065 1.1 joerg }; 3066 1.1 joerg /* used by opcodes c1, d1, and d3. */ 3067 1.1 joerg static 3068 1.1 joerg uint32_t(* const opcD1_long_operation[]) (struct X86EMU *, uint32_t s, uint8_t d) = 3069 1.1 joerg { 3070 1.1 joerg rol_long, 3071 1.1 joerg ror_long, 3072 1.1 joerg rcl_long, 3073 1.1 joerg rcr_long, 3074 1.1 joerg shl_long, 3075 1.1 joerg shr_long, 3076 1.1 joerg shl_long, /* sal_byte === shl_byte by definition */ 3077 1.1 joerg sar_long, 3078 1.1 joerg }; 3079 1.1 joerg /**************************************************************************** 3080 1.1 joerg REMARKS: 3081 1.1 joerg Handles opcode 0xc1 3082 1.1 joerg ****************************************************************************/ 3083 1.1 joerg static void 3084 1.1 joerg x86emuOp_opcC1_word_RM_MEM(struct X86EMU *emu) 3085 1.1 joerg { 3086 1.1 joerg uint8_t amt; 3087 1.1 joerg 3088 1.1 joerg /* 3089 1.1 joerg * Yet another weirdo special case instruction format. Part of 3090 1.1 joerg * the opcode held below in "RH". Doubly nested case would 3091 1.1 joerg * result, except that the decoded instruction 3092 1.1 joerg */ 3093 1.1 joerg fetch_decode_modrm(emu); 3094 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3095 1.1 joerg uint32_t destval; 3096 1.1 joerg 3097 1.1 joerg destval = decode_and_fetch_long_imm8(emu, &amt); 3098 1.1 joerg destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, amt); 3099 1.1 joerg write_back_long(emu, destval); 3100 1.1 joerg } else { 3101 1.1 joerg uint16_t destval; 3102 1.1 joerg 3103 1.1 joerg destval = decode_and_fetch_word_imm8(emu, &amt); 3104 1.1 joerg destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, amt); 3105 1.1 joerg write_back_word(emu, destval); 3106 1.1 joerg } 3107 1.1 joerg } 3108 1.1 joerg /**************************************************************************** 3109 1.1 joerg REMARKS: 3110 1.1 joerg Handles opcode 0xc2 3111 1.1 joerg ****************************************************************************/ 3112 1.1 joerg static void 3113 1.1 joerg x86emuOp_ret_near_IMM(struct X86EMU *emu) 3114 1.1 joerg { 3115 1.1 joerg uint16_t imm; 3116 1.1 joerg 3117 1.1 joerg imm = fetch_word_imm(emu); 3118 1.1 joerg emu->x86.R_IP = pop_word(emu); 3119 1.1 joerg emu->x86.R_SP += imm; 3120 1.1 joerg } 3121 1.1 joerg /**************************************************************************** 3122 1.1 joerg REMARKS: 3123 1.1 joerg Handles opcode 0xc6 3124 1.1 joerg ****************************************************************************/ 3125 1.1 joerg static void 3126 1.1 joerg x86emuOp_mov_byte_RM_IMM(struct X86EMU *emu) 3127 1.1 joerg { 3128 1.1 joerg uint8_t *destreg; 3129 1.1 joerg uint32_t destoffset; 3130 1.1 joerg uint8_t imm; 3131 1.1 joerg 3132 1.1 joerg fetch_decode_modrm(emu); 3133 1.1 joerg if (emu->cur_rh != 0) 3134 1.1 joerg X86EMU_halt_sys(emu); 3135 1.1 joerg if (emu->cur_mod != 3) { 3136 1.1 joerg destoffset = decode_rl_address(emu); 3137 1.1 joerg imm = fetch_byte_imm(emu); 3138 1.1 joerg store_data_byte(emu, destoffset, imm); 3139 1.1 joerg } else { 3140 1.1 joerg destreg = decode_rl_byte_register(emu); 3141 1.1 joerg imm = fetch_byte_imm(emu); 3142 1.1 joerg *destreg = imm; 3143 1.1 joerg } 3144 1.1 joerg } 3145 1.1 joerg /**************************************************************************** 3146 1.1 joerg REMARKS: 3147 1.1 joerg Handles opcode 0xc7 3148 1.1 joerg ****************************************************************************/ 3149 1.1 joerg static void 3150 1.1 joerg x86emuOp32_mov_word_RM_IMM(struct X86EMU *emu) 3151 1.1 joerg { 3152 1.1 joerg uint32_t destoffset; 3153 1.1 joerg uint32_t imm, *destreg; 3154 1.1 joerg 3155 1.1 joerg fetch_decode_modrm(emu); 3156 1.1 joerg if (emu->cur_rh != 0) 3157 1.1 joerg X86EMU_halt_sys(emu); 3158 1.1 joerg 3159 1.1 joerg if (emu->cur_mod != 3) { 3160 1.1 joerg destoffset = decode_rl_address(emu); 3161 1.1 joerg imm = fetch_long_imm(emu); 3162 1.1 joerg store_data_long(emu, destoffset, imm); 3163 1.1 joerg } else { 3164 1.1 joerg destreg = decode_rl_long_register(emu); 3165 1.1 joerg imm = fetch_long_imm(emu); 3166 1.1 joerg *destreg = imm; 3167 1.1 joerg } 3168 1.1 joerg } 3169 1.1 joerg 3170 1.1 joerg static void 3171 1.1 joerg x86emuOp16_mov_word_RM_IMM(struct X86EMU *emu) 3172 1.1 joerg { 3173 1.1 joerg uint32_t destoffset; 3174 1.1 joerg uint16_t imm, *destreg; 3175 1.1 joerg 3176 1.1 joerg fetch_decode_modrm(emu); 3177 1.1 joerg if (emu->cur_rh != 0) 3178 1.1 joerg X86EMU_halt_sys(emu); 3179 1.1 joerg 3180 1.1 joerg if (emu->cur_mod != 3) { 3181 1.1 joerg destoffset = decode_rl_address(emu); 3182 1.1 joerg imm = fetch_word_imm(emu); 3183 1.1 joerg store_data_word(emu, destoffset, imm); 3184 1.1 joerg } else { 3185 1.1 joerg destreg = decode_rl_word_register(emu); 3186 1.1 joerg imm = fetch_word_imm(emu); 3187 1.1 joerg *destreg = imm; 3188 1.1 joerg } 3189 1.1 joerg } 3190 1.1 joerg 3191 1.1 joerg static void 3192 1.1 joerg x86emuOp_mov_word_RM_IMM(struct X86EMU *emu) 3193 1.1 joerg { 3194 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3195 1.1 joerg x86emuOp32_mov_word_RM_IMM(emu); 3196 1.1 joerg else 3197 1.1 joerg x86emuOp16_mov_word_RM_IMM(emu); 3198 1.1 joerg } 3199 1.1 joerg /**************************************************************************** 3200 1.1 joerg REMARKS: 3201 1.1 joerg Handles opcode 0xc8 3202 1.1 joerg ****************************************************************************/ 3203 1.1 joerg static void 3204 1.1 joerg x86emuOp_enter(struct X86EMU *emu) 3205 1.1 joerg { 3206 1.1 joerg uint16_t local, frame_pointer; 3207 1.1 joerg uint8_t nesting; 3208 1.1 joerg int i; 3209 1.1 joerg 3210 1.1 joerg local = fetch_word_imm(emu); 3211 1.1 joerg nesting = fetch_byte_imm(emu); 3212 1.1 joerg push_word(emu, emu->x86.R_BP); 3213 1.1 joerg frame_pointer = emu->x86.R_SP; 3214 1.1 joerg if (nesting > 0) { 3215 1.1 joerg for (i = 1; i < nesting; i++) { 3216 1.1 joerg emu->x86.R_BP -= 2; 3217 1.1 joerg push_word(emu, fetch_word(emu, emu->x86.R_SS, emu->x86.R_BP)); 3218 1.1 joerg } 3219 1.1 joerg push_word(emu, frame_pointer); 3220 1.1 joerg } 3221 1.1 joerg emu->x86.R_BP = frame_pointer; 3222 1.1 joerg emu->x86.R_SP = (uint16_t) (emu->x86.R_SP - local); 3223 1.1 joerg } 3224 1.1 joerg /**************************************************************************** 3225 1.1 joerg REMARKS: 3226 1.1 joerg Handles opcode 0xc9 3227 1.1 joerg ****************************************************************************/ 3228 1.1 joerg static void 3229 1.1 joerg x86emuOp_leave(struct X86EMU *emu) 3230 1.1 joerg { 3231 1.1 joerg emu->x86.R_SP = emu->x86.R_BP; 3232 1.1 joerg emu->x86.R_BP = pop_word(emu); 3233 1.1 joerg } 3234 1.1 joerg /**************************************************************************** 3235 1.1 joerg REMARKS: 3236 1.1 joerg Handles opcode 0xca 3237 1.1 joerg ****************************************************************************/ 3238 1.1 joerg static void 3239 1.1 joerg x86emuOp_ret_far_IMM(struct X86EMU *emu) 3240 1.1 joerg { 3241 1.1 joerg uint16_t imm; 3242 1.1 joerg 3243 1.1 joerg imm = fetch_word_imm(emu); 3244 1.1 joerg emu->x86.R_IP = pop_word(emu); 3245 1.1 joerg emu->x86.R_CS = pop_word(emu); 3246 1.1 joerg emu->x86.R_SP += imm; 3247 1.1 joerg } 3248 1.1 joerg /**************************************************************************** 3249 1.1 joerg REMARKS: 3250 1.1 joerg Handles opcode 0xcb 3251 1.1 joerg ****************************************************************************/ 3252 1.1 joerg static void 3253 1.1 joerg x86emuOp_ret_far(struct X86EMU *emu) 3254 1.1 joerg { 3255 1.1 joerg emu->x86.R_IP = pop_word(emu); 3256 1.1 joerg emu->x86.R_CS = pop_word(emu); 3257 1.1 joerg } 3258 1.1 joerg /**************************************************************************** 3259 1.1 joerg REMARKS: 3260 1.1 joerg Handles opcode 0xcc 3261 1.1 joerg ****************************************************************************/ 3262 1.1 joerg static void 3263 1.1 joerg x86emuOp_int3(struct X86EMU *emu) 3264 1.1 joerg { 3265 1.3 joerg x86emu_intr_dispatch(emu, 3); 3266 1.1 joerg } 3267 1.1 joerg /**************************************************************************** 3268 1.1 joerg REMARKS: 3269 1.1 joerg Handles opcode 0xcd 3270 1.1 joerg ****************************************************************************/ 3271 1.1 joerg static void 3272 1.1 joerg x86emuOp_int_IMM(struct X86EMU *emu) 3273 1.1 joerg { 3274 1.1 joerg uint8_t intnum; 3275 1.1 joerg 3276 1.1 joerg intnum = fetch_byte_imm(emu); 3277 1.3 joerg x86emu_intr_dispatch(emu, intnum); 3278 1.1 joerg } 3279 1.1 joerg /**************************************************************************** 3280 1.1 joerg REMARKS: 3281 1.1 joerg Handles opcode 0xce 3282 1.1 joerg ****************************************************************************/ 3283 1.1 joerg static void 3284 1.1 joerg x86emuOp_into(struct X86EMU *emu) 3285 1.1 joerg { 3286 1.3 joerg if (ACCESS_FLAG(F_OF)) 3287 1.3 joerg x86emu_intr_dispatch(emu, 4); 3288 1.1 joerg } 3289 1.1 joerg /**************************************************************************** 3290 1.1 joerg REMARKS: 3291 1.1 joerg Handles opcode 0xcf 3292 1.1 joerg ****************************************************************************/ 3293 1.1 joerg static void 3294 1.1 joerg x86emuOp_iret(struct X86EMU *emu) 3295 1.1 joerg { 3296 1.1 joerg emu->x86.R_IP = pop_word(emu); 3297 1.1 joerg emu->x86.R_CS = pop_word(emu); 3298 1.1 joerg emu->x86.R_FLG = pop_word(emu); 3299 1.1 joerg } 3300 1.1 joerg /**************************************************************************** 3301 1.1 joerg REMARKS: 3302 1.1 joerg Handles opcode 0xd0 3303 1.1 joerg ****************************************************************************/ 3304 1.1 joerg static void 3305 1.1 joerg x86emuOp_opcD0_byte_RM_1(struct X86EMU *emu) 3306 1.1 joerg { 3307 1.1 joerg uint8_t destval; 3308 1.1 joerg 3309 1.1 joerg fetch_decode_modrm(emu); 3310 1.1 joerg destval = decode_and_fetch_byte(emu); 3311 1.1 joerg destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, 1); 3312 1.1 joerg write_back_byte(emu, destval); 3313 1.1 joerg } 3314 1.1 joerg /**************************************************************************** 3315 1.1 joerg REMARKS: 3316 1.1 joerg Handles opcode 0xd1 3317 1.1 joerg ****************************************************************************/ 3318 1.1 joerg static void 3319 1.1 joerg x86emuOp_opcD1_word_RM_1(struct X86EMU *emu) 3320 1.1 joerg { 3321 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3322 1.1 joerg uint32_t destval; 3323 1.1 joerg 3324 1.1 joerg fetch_decode_modrm(emu); 3325 1.1 joerg destval = decode_and_fetch_long(emu); 3326 1.1 joerg destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, 1); 3327 1.1 joerg write_back_long(emu, destval); 3328 1.1 joerg } else { 3329 1.1 joerg uint16_t destval; 3330 1.1 joerg 3331 1.1 joerg fetch_decode_modrm(emu); 3332 1.1 joerg destval = decode_and_fetch_word(emu); 3333 1.1 joerg destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, 1); 3334 1.1 joerg write_back_word(emu, destval); 3335 1.1 joerg } 3336 1.1 joerg } 3337 1.1 joerg /**************************************************************************** 3338 1.1 joerg REMARKS: 3339 1.1 joerg Handles opcode 0xd2 3340 1.1 joerg ****************************************************************************/ 3341 1.1 joerg static void 3342 1.1 joerg x86emuOp_opcD2_byte_RM_CL(struct X86EMU *emu) 3343 1.1 joerg { 3344 1.1 joerg uint8_t destval; 3345 1.1 joerg 3346 1.1 joerg fetch_decode_modrm(emu); 3347 1.1 joerg destval = decode_and_fetch_byte(emu); 3348 1.1 joerg destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL); 3349 1.1 joerg write_back_byte(emu, destval); 3350 1.1 joerg } 3351 1.1 joerg /**************************************************************************** 3352 1.1 joerg REMARKS: 3353 1.1 joerg Handles opcode 0xd3 3354 1.1 joerg ****************************************************************************/ 3355 1.1 joerg static void 3356 1.1 joerg x86emuOp_opcD3_word_RM_CL(struct X86EMU *emu) 3357 1.1 joerg { 3358 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3359 1.1 joerg uint32_t destval; 3360 1.1 joerg 3361 1.1 joerg fetch_decode_modrm(emu); 3362 1.1 joerg destval = decode_and_fetch_long(emu); 3363 1.1 joerg destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL); 3364 1.1 joerg write_back_long(emu, destval); 3365 1.1 joerg } else { 3366 1.1 joerg uint16_t destval; 3367 1.1 joerg 3368 1.1 joerg fetch_decode_modrm(emu); 3369 1.1 joerg destval = decode_and_fetch_word(emu); 3370 1.1 joerg destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL); 3371 1.1 joerg write_back_word(emu, destval); 3372 1.1 joerg } 3373 1.1 joerg } 3374 1.1 joerg /**************************************************************************** 3375 1.1 joerg REMARKS: 3376 1.1 joerg Handles opcode 0xd4 3377 1.1 joerg ****************************************************************************/ 3378 1.1 joerg static void 3379 1.1 joerg x86emuOp_aam(struct X86EMU *emu) 3380 1.1 joerg { 3381 1.1 joerg uint8_t a; 3382 1.1 joerg 3383 1.1 joerg a = fetch_byte_imm(emu); /* this is a stupid encoding. */ 3384 1.1 joerg if (a != 10) { 3385 1.1 joerg /* fix: add base decoding aam_word(uint8_t val, int base a) */ 3386 1.1 joerg X86EMU_halt_sys(emu); 3387 1.1 joerg } 3388 1.1 joerg /* note the type change here --- returning AL and AH in AX. */ 3389 1.1 joerg emu->x86.R_AX = aam_word(emu, emu->x86.R_AL); 3390 1.1 joerg } 3391 1.1 joerg /**************************************************************************** 3392 1.1 joerg REMARKS: 3393 1.1 joerg Handles opcode 0xd5 3394 1.1 joerg ****************************************************************************/ 3395 1.1 joerg static void 3396 1.1 joerg x86emuOp_aad(struct X86EMU *emu) 3397 1.1 joerg { 3398 1.1 joerg uint8_t a; 3399 1.1 joerg 3400 1.1 joerg a = fetch_byte_imm(emu); 3401 1.1 joerg if (a != 10) { 3402 1.1 joerg /* fix: add base decoding aad_word(uint16_t val, int base a) */ 3403 1.1 joerg X86EMU_halt_sys(emu); 3404 1.1 joerg } 3405 1.1 joerg emu->x86.R_AX = aad_word(emu, emu->x86.R_AX); 3406 1.1 joerg } 3407 1.1 joerg /* opcode 0xd6 ILLEGAL OPCODE */ 3408 1.1 joerg 3409 1.1 joerg /**************************************************************************** 3410 1.1 joerg REMARKS: 3411 1.1 joerg Handles opcode 0xd7 3412 1.1 joerg ****************************************************************************/ 3413 1.1 joerg static void 3414 1.1 joerg x86emuOp_xlat(struct X86EMU *emu) 3415 1.1 joerg { 3416 1.1 joerg uint16_t addr; 3417 1.1 joerg 3418 1.1 joerg addr = (uint16_t) (emu->x86.R_BX + (uint8_t) emu->x86.R_AL); 3419 1.1 joerg emu->x86.R_AL = fetch_data_byte(emu, addr); 3420 1.1 joerg } 3421 1.1 joerg 3422 1.1 joerg /* opcode=0xd8 */ 3423 1.1 joerg static void 3424 1.1 joerg x86emuOp_esc_coprocess_d8(struct X86EMU *emu) 3425 1.1 joerg { 3426 1.1 joerg } 3427 1.1 joerg /* opcode=0xd9 */ 3428 1.1 joerg static void 3429 1.1 joerg x86emuOp_esc_coprocess_d9(struct X86EMU *emu) 3430 1.1 joerg { 3431 1.1 joerg fetch_decode_modrm(emu); 3432 1.1 joerg if (emu->cur_mod != 3) 3433 1.1 joerg decode_rl_address(emu); 3434 1.1 joerg } 3435 1.1 joerg /* opcode=0xda */ 3436 1.1 joerg static void 3437 1.1 joerg x86emuOp_esc_coprocess_da(struct X86EMU *emu) 3438 1.1 joerg { 3439 1.1 joerg fetch_decode_modrm(emu); 3440 1.1 joerg if (emu->cur_mod != 3) 3441 1.1 joerg decode_rl_address(emu); 3442 1.1 joerg } 3443 1.1 joerg /* opcode=0xdb */ 3444 1.1 joerg static void 3445 1.1 joerg x86emuOp_esc_coprocess_db(struct X86EMU *emu) 3446 1.1 joerg { 3447 1.1 joerg fetch_decode_modrm(emu); 3448 1.1 joerg if (emu->cur_mod != 3) 3449 1.1 joerg decode_rl_address(emu); 3450 1.1 joerg } 3451 1.1 joerg /* opcode=0xdc */ 3452 1.1 joerg static void 3453 1.1 joerg x86emuOp_esc_coprocess_dc(struct X86EMU *emu) 3454 1.1 joerg { 3455 1.1 joerg fetch_decode_modrm(emu); 3456 1.1 joerg if (emu->cur_mod != 3) 3457 1.1 joerg decode_rl_address(emu); 3458 1.1 joerg } 3459 1.1 joerg /* opcode=0xdd */ 3460 1.1 joerg static void 3461 1.1 joerg x86emuOp_esc_coprocess_dd(struct X86EMU *emu) 3462 1.1 joerg { 3463 1.1 joerg fetch_decode_modrm(emu); 3464 1.1 joerg if (emu->cur_mod != 3) 3465 1.1 joerg decode_rl_address(emu); 3466 1.1 joerg } 3467 1.1 joerg /* opcode=0xde */ 3468 1.1 joerg static void 3469 1.1 joerg x86emuOp_esc_coprocess_de(struct X86EMU *emu) 3470 1.1 joerg { 3471 1.1 joerg fetch_decode_modrm(emu); 3472 1.1 joerg if (emu->cur_mod != 3) 3473 1.1 joerg decode_rl_address(emu); 3474 1.1 joerg } 3475 1.1 joerg /* opcode=0xdf */ 3476 1.1 joerg static void 3477 1.1 joerg x86emuOp_esc_coprocess_df(struct X86EMU *emu) 3478 1.1 joerg { 3479 1.1 joerg fetch_decode_modrm(emu); 3480 1.1 joerg if (emu->cur_mod != 3) 3481 1.1 joerg decode_rl_address(emu); 3482 1.1 joerg } 3483 1.1 joerg 3484 1.1 joerg /**************************************************************************** 3485 1.1 joerg REMARKS: 3486 1.1 joerg Handles opcode 0xe0 3487 1.1 joerg ****************************************************************************/ 3488 1.1 joerg static void 3489 1.1 joerg x86emuOp_loopne(struct X86EMU *emu) 3490 1.1 joerg { 3491 1.1 joerg int16_t ip; 3492 1.1 joerg 3493 1.1 joerg ip = (int8_t) fetch_byte_imm(emu); 3494 1.1 joerg ip += (int16_t) emu->x86.R_IP; 3495 1.1 joerg emu->x86.R_CX -= 1; 3496 1.1 joerg if (emu->x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */ 3497 1.1 joerg emu->x86.R_IP = ip; 3498 1.1 joerg } 3499 1.1 joerg /**************************************************************************** 3500 1.1 joerg REMARKS: 3501 1.1 joerg Handles opcode 0xe1 3502 1.1 joerg ****************************************************************************/ 3503 1.1 joerg static void 3504 1.1 joerg x86emuOp_loope(struct X86EMU *emu) 3505 1.1 joerg { 3506 1.1 joerg int16_t ip; 3507 1.1 joerg 3508 1.1 joerg ip = (int8_t) fetch_byte_imm(emu); 3509 1.1 joerg ip += (int16_t) emu->x86.R_IP; 3510 1.1 joerg emu->x86.R_CX -= 1; 3511 1.1 joerg if (emu->x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */ 3512 1.1 joerg emu->x86.R_IP = ip; 3513 1.1 joerg } 3514 1.1 joerg /**************************************************************************** 3515 1.1 joerg REMARKS: 3516 1.1 joerg Handles opcode 0xe2 3517 1.1 joerg ****************************************************************************/ 3518 1.1 joerg static void 3519 1.1 joerg x86emuOp_loop(struct X86EMU *emu) 3520 1.1 joerg { 3521 1.1 joerg int16_t ip; 3522 1.1 joerg 3523 1.1 joerg ip = (int8_t) fetch_byte_imm(emu); 3524 1.1 joerg ip += (int16_t) emu->x86.R_IP; 3525 1.1 joerg emu->x86.R_CX -= 1; 3526 1.1 joerg if (emu->x86.R_CX != 0) 3527 1.1 joerg emu->x86.R_IP = ip; 3528 1.1 joerg } 3529 1.1 joerg /**************************************************************************** 3530 1.1 joerg REMARKS: 3531 1.1 joerg Handles opcode 0xe3 3532 1.1 joerg ****************************************************************************/ 3533 1.1 joerg static void 3534 1.1 joerg x86emuOp_jcxz(struct X86EMU *emu) 3535 1.1 joerg { 3536 1.1 joerg uint16_t target; 3537 1.1 joerg int8_t offset; 3538 1.1 joerg 3539 1.1 joerg /* jump to byte offset if overflow flag is set */ 3540 1.1 joerg offset = (int8_t) fetch_byte_imm(emu); 3541 1.1 joerg target = (uint16_t) (emu->x86.R_IP + offset); 3542 1.1 joerg if (emu->x86.R_CX == 0) 3543 1.1 joerg emu->x86.R_IP = target; 3544 1.1 joerg } 3545 1.1 joerg /**************************************************************************** 3546 1.1 joerg REMARKS: 3547 1.1 joerg Handles opcode 0xe4 3548 1.1 joerg ****************************************************************************/ 3549 1.1 joerg static void 3550 1.1 joerg x86emuOp_in_byte_AL_IMM(struct X86EMU *emu) 3551 1.1 joerg { 3552 1.1 joerg uint8_t port; 3553 1.1 joerg 3554 1.1 joerg port = (uint8_t) fetch_byte_imm(emu); 3555 1.1 joerg emu->x86.R_AL = (*emu->emu_inb) (emu, port); 3556 1.1 joerg } 3557 1.1 joerg /**************************************************************************** 3558 1.1 joerg REMARKS: 3559 1.1 joerg Handles opcode 0xe5 3560 1.1 joerg ****************************************************************************/ 3561 1.1 joerg static void 3562 1.1 joerg x86emuOp_in_word_AX_IMM(struct X86EMU *emu) 3563 1.1 joerg { 3564 1.1 joerg uint8_t port; 3565 1.1 joerg 3566 1.1 joerg port = (uint8_t) fetch_byte_imm(emu); 3567 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3568 1.1 joerg emu->x86.R_EAX = (*emu->emu_inl) (emu, port); 3569 1.1 joerg } else { 3570 1.1 joerg emu->x86.R_AX = (*emu->emu_inw) (emu, port); 3571 1.1 joerg } 3572 1.1 joerg } 3573 1.1 joerg /**************************************************************************** 3574 1.1 joerg REMARKS: 3575 1.1 joerg Handles opcode 0xe6 3576 1.1 joerg ****************************************************************************/ 3577 1.1 joerg static void 3578 1.1 joerg x86emuOp_out_byte_IMM_AL(struct X86EMU *emu) 3579 1.1 joerg { 3580 1.1 joerg uint8_t port; 3581 1.1 joerg 3582 1.1 joerg port = (uint8_t) fetch_byte_imm(emu); 3583 1.1 joerg (*emu->emu_outb) (emu, port, emu->x86.R_AL); 3584 1.1 joerg } 3585 1.1 joerg /**************************************************************************** 3586 1.1 joerg REMARKS: 3587 1.1 joerg Handles opcode 0xe7 3588 1.1 joerg ****************************************************************************/ 3589 1.1 joerg static void 3590 1.1 joerg x86emuOp_out_word_IMM_AX(struct X86EMU *emu) 3591 1.1 joerg { 3592 1.1 joerg uint8_t port; 3593 1.1 joerg 3594 1.1 joerg port = (uint8_t) fetch_byte_imm(emu); 3595 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3596 1.1 joerg (*emu->emu_outl) (emu, port, emu->x86.R_EAX); 3597 1.1 joerg } else { 3598 1.1 joerg (*emu->emu_outw) (emu, port, emu->x86.R_AX); 3599 1.1 joerg } 3600 1.1 joerg } 3601 1.1 joerg /**************************************************************************** 3602 1.1 joerg REMARKS: 3603 1.1 joerg Handles opcode 0xe8 3604 1.1 joerg ****************************************************************************/ 3605 1.1 joerg static void 3606 1.1 joerg x86emuOp_call_near_IMM(struct X86EMU *emu) 3607 1.1 joerg { 3608 1.10 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3609 1.10 joerg int32_t ip; 3610 1.10 joerg ip = (int32_t) fetch_long_imm(emu); 3611 1.10 joerg ip += (int32_t) emu->x86.R_EIP; 3612 1.10 joerg push_long(emu, emu->x86.R_EIP); 3613 1.10 joerg emu->x86.R_EIP = ip; 3614 1.10 joerg } else { 3615 1.10 joerg int16_t ip; 3616 1.10 joerg ip = (int16_t) fetch_word_imm(emu); 3617 1.10 joerg ip += (int16_t) emu->x86.R_IP; /* CHECK SIGN */ 3618 1.10 joerg push_word(emu, emu->x86.R_IP); 3619 1.10 joerg emu->x86.R_IP = ip; 3620 1.10 joerg } 3621 1.1 joerg } 3622 1.1 joerg /**************************************************************************** 3623 1.1 joerg REMARKS: 3624 1.1 joerg Handles opcode 0xe9 3625 1.1 joerg ****************************************************************************/ 3626 1.1 joerg static void 3627 1.1 joerg x86emuOp_jump_near_IMM(struct X86EMU *emu) 3628 1.1 joerg { 3629 1.1 joerg int ip; 3630 1.1 joerg 3631 1.1 joerg ip = (int16_t) fetch_word_imm(emu); 3632 1.1 joerg ip += (int16_t) emu->x86.R_IP; 3633 1.1 joerg emu->x86.R_IP = (uint16_t) ip; 3634 1.1 joerg } 3635 1.1 joerg /**************************************************************************** 3636 1.1 joerg REMARKS: 3637 1.1 joerg Handles opcode 0xea 3638 1.1 joerg ****************************************************************************/ 3639 1.1 joerg static void 3640 1.1 joerg x86emuOp_jump_far_IMM(struct X86EMU *emu) 3641 1.1 joerg { 3642 1.1 joerg uint16_t cs, ip; 3643 1.1 joerg 3644 1.1 joerg ip = fetch_word_imm(emu); 3645 1.1 joerg cs = fetch_word_imm(emu); 3646 1.1 joerg emu->x86.R_IP = ip; 3647 1.1 joerg emu->x86.R_CS = cs; 3648 1.1 joerg } 3649 1.1 joerg /**************************************************************************** 3650 1.1 joerg REMARKS: 3651 1.1 joerg Handles opcode 0xeb 3652 1.1 joerg ****************************************************************************/ 3653 1.1 joerg static void 3654 1.1 joerg x86emuOp_jump_byte_IMM(struct X86EMU *emu) 3655 1.1 joerg { 3656 1.1 joerg uint16_t target; 3657 1.1 joerg int8_t offset; 3658 1.1 joerg 3659 1.1 joerg offset = (int8_t) fetch_byte_imm(emu); 3660 1.1 joerg target = (uint16_t) (emu->x86.R_IP + offset); 3661 1.1 joerg emu->x86.R_IP = target; 3662 1.1 joerg } 3663 1.1 joerg /**************************************************************************** 3664 1.1 joerg REMARKS: 3665 1.1 joerg Handles opcode 0xec 3666 1.1 joerg ****************************************************************************/ 3667 1.1 joerg static void 3668 1.1 joerg x86emuOp_in_byte_AL_DX(struct X86EMU *emu) 3669 1.1 joerg { 3670 1.1 joerg emu->x86.R_AL = (*emu->emu_inb) (emu, emu->x86.R_DX); 3671 1.1 joerg } 3672 1.1 joerg /**************************************************************************** 3673 1.1 joerg REMARKS: 3674 1.1 joerg Handles opcode 0xed 3675 1.1 joerg ****************************************************************************/ 3676 1.1 joerg static void 3677 1.1 joerg x86emuOp_in_word_AX_DX(struct X86EMU *emu) 3678 1.1 joerg { 3679 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3680 1.1 joerg emu->x86.R_EAX = (*emu->emu_inl) (emu, emu->x86.R_DX); 3681 1.1 joerg } else { 3682 1.1 joerg emu->x86.R_AX = (*emu->emu_inw) (emu, emu->x86.R_DX); 3683 1.1 joerg } 3684 1.1 joerg } 3685 1.1 joerg /**************************************************************************** 3686 1.1 joerg REMARKS: 3687 1.1 joerg Handles opcode 0xee 3688 1.1 joerg ****************************************************************************/ 3689 1.1 joerg static void 3690 1.1 joerg x86emuOp_out_byte_DX_AL(struct X86EMU *emu) 3691 1.1 joerg { 3692 1.1 joerg (*emu->emu_outb) (emu, emu->x86.R_DX, emu->x86.R_AL); 3693 1.1 joerg } 3694 1.1 joerg /**************************************************************************** 3695 1.1 joerg REMARKS: 3696 1.1 joerg Handles opcode 0xef 3697 1.1 joerg ****************************************************************************/ 3698 1.1 joerg static void 3699 1.1 joerg x86emuOp_out_word_DX_AX(struct X86EMU *emu) 3700 1.1 joerg { 3701 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 3702 1.1 joerg (*emu->emu_outl) (emu, emu->x86.R_DX, emu->x86.R_EAX); 3703 1.1 joerg } else { 3704 1.1 joerg (*emu->emu_outw) (emu, emu->x86.R_DX, emu->x86.R_AX); 3705 1.1 joerg } 3706 1.1 joerg } 3707 1.1 joerg /**************************************************************************** 3708 1.1 joerg REMARKS: 3709 1.1 joerg Handles opcode 0xf0 3710 1.1 joerg ****************************************************************************/ 3711 1.1 joerg static void 3712 1.1 joerg x86emuOp_lock(struct X86EMU *emu) 3713 1.1 joerg { 3714 1.1 joerg } 3715 1.1 joerg /*opcode 0xf1 ILLEGAL OPERATION */ 3716 1.1 joerg 3717 1.1 joerg /**************************************************************************** 3718 1.1 joerg REMARKS: 3719 1.1 joerg Handles opcode 0xf5 3720 1.1 joerg ****************************************************************************/ 3721 1.1 joerg static void 3722 1.1 joerg x86emuOp_cmc(struct X86EMU *emu) 3723 1.1 joerg { 3724 1.1 joerg if (ACCESS_FLAG(F_CF)) 3725 1.1 joerg CLEAR_FLAG(F_CF); 3726 1.1 joerg else 3727 1.1 joerg SET_FLAG(F_CF); 3728 1.1 joerg } 3729 1.1 joerg /**************************************************************************** 3730 1.1 joerg REMARKS: 3731 1.1 joerg Handles opcode 0xf6 3732 1.1 joerg ****************************************************************************/ 3733 1.1 joerg static void 3734 1.1 joerg x86emuOp_opcF6_byte_RM(struct X86EMU *emu) 3735 1.1 joerg { 3736 1.1 joerg uint8_t destval, srcval; 3737 1.1 joerg 3738 1.1 joerg /* long, drawn out code follows. Double switch for a total of 32 3739 1.1 joerg * cases. */ 3740 1.1 joerg fetch_decode_modrm(emu); 3741 1.1 joerg if (emu->cur_rh == 1) 3742 1.1 joerg X86EMU_halt_sys(emu); 3743 1.1 joerg 3744 1.1 joerg if (emu->cur_rh == 0) { 3745 1.1 joerg destval = decode_and_fetch_byte_imm8(emu, &srcval); 3746 1.1 joerg test_byte(emu, destval, srcval); 3747 1.1 joerg return; 3748 1.1 joerg } 3749 1.1 joerg destval = decode_and_fetch_byte(emu); 3750 1.1 joerg switch (emu->cur_rh) { 3751 1.1 joerg case 2: 3752 1.1 joerg destval = ~destval; 3753 1.1 joerg write_back_byte(emu, destval); 3754 1.1 joerg break; 3755 1.1 joerg case 3: 3756 1.1 joerg destval = neg_byte(emu, destval); 3757 1.1 joerg write_back_byte(emu, destval); 3758 1.1 joerg break; 3759 1.1 joerg case 4: 3760 1.1 joerg mul_byte(emu, destval); 3761 1.1 joerg break; 3762 1.1 joerg case 5: 3763 1.1 joerg imul_byte(emu, destval); 3764 1.1 joerg break; 3765 1.1 joerg case 6: 3766 1.1 joerg div_byte(emu, destval); 3767 1.1 joerg break; 3768 1.1 joerg case 7: 3769 1.1 joerg idiv_byte(emu, destval); 3770 1.1 joerg break; 3771 1.1 joerg } 3772 1.1 joerg } 3773 1.1 joerg /**************************************************************************** 3774 1.1 joerg REMARKS: 3775 1.1 joerg Handles opcode 0xf7 3776 1.1 joerg ****************************************************************************/ 3777 1.1 joerg static void 3778 1.1 joerg x86emuOp32_opcF7_word_RM(struct X86EMU *emu) 3779 1.1 joerg { 3780 1.1 joerg uint32_t destval, srcval; 3781 1.1 joerg 3782 1.1 joerg /* long, drawn out code follows. Double switch for a total of 32 3783 1.1 joerg * cases. */ 3784 1.1 joerg fetch_decode_modrm(emu); 3785 1.1 joerg if (emu->cur_rh == 1) 3786 1.1 joerg X86EMU_halt_sys(emu); 3787 1.1 joerg 3788 1.1 joerg if (emu->cur_rh == 0) { 3789 1.1 joerg if (emu->cur_mod != 3) { 3790 1.1 joerg uint32_t destoffset; 3791 1.1 joerg 3792 1.1 joerg destoffset = decode_rl_address(emu); 3793 1.1 joerg srcval = fetch_long_imm(emu); 3794 1.1 joerg destval = fetch_data_long(emu, destoffset); 3795 1.1 joerg } else { 3796 1.1 joerg srcval = fetch_long_imm(emu); 3797 1.1 joerg destval = *decode_rl_long_register(emu); 3798 1.1 joerg } 3799 1.1 joerg test_long(emu, destval, srcval); 3800 1.1 joerg return; 3801 1.1 joerg } 3802 1.1 joerg destval = decode_and_fetch_long(emu); 3803 1.1 joerg switch (emu->cur_rh) { 3804 1.1 joerg case 2: 3805 1.1 joerg destval = ~destval; 3806 1.1 joerg write_back_long(emu, destval); 3807 1.1 joerg break; 3808 1.1 joerg case 3: 3809 1.1 joerg destval = neg_long(emu, destval); 3810 1.1 joerg write_back_long(emu, destval); 3811 1.1 joerg break; 3812 1.1 joerg case 4: 3813 1.1 joerg mul_long(emu, destval); 3814 1.1 joerg break; 3815 1.1 joerg case 5: 3816 1.1 joerg imul_long(emu, destval); 3817 1.1 joerg break; 3818 1.1 joerg case 6: 3819 1.1 joerg div_long(emu, destval); 3820 1.1 joerg break; 3821 1.1 joerg case 7: 3822 1.1 joerg idiv_long(emu, destval); 3823 1.1 joerg break; 3824 1.1 joerg } 3825 1.1 joerg } 3826 1.1 joerg static void 3827 1.1 joerg x86emuOp16_opcF7_word_RM(struct X86EMU *emu) 3828 1.1 joerg { 3829 1.1 joerg uint16_t destval, srcval; 3830 1.1 joerg 3831 1.1 joerg /* long, drawn out code follows. Double switch for a total of 32 3832 1.1 joerg * cases. */ 3833 1.1 joerg fetch_decode_modrm(emu); 3834 1.1 joerg if (emu->cur_rh == 1) 3835 1.1 joerg X86EMU_halt_sys(emu); 3836 1.1 joerg 3837 1.1 joerg if (emu->cur_rh == 0) { 3838 1.1 joerg if (emu->cur_mod != 3) { 3839 1.1 joerg uint32_t destoffset; 3840 1.1 joerg 3841 1.1 joerg destoffset = decode_rl_address(emu); 3842 1.1 joerg srcval = fetch_word_imm(emu); 3843 1.1 joerg destval = fetch_data_word(emu, destoffset); 3844 1.1 joerg } else { 3845 1.1 joerg srcval = fetch_word_imm(emu); 3846 1.1 joerg destval = *decode_rl_word_register(emu); 3847 1.1 joerg } 3848 1.1 joerg test_word(emu, destval, srcval); 3849 1.1 joerg return; 3850 1.1 joerg } 3851 1.1 joerg destval = decode_and_fetch_word(emu); 3852 1.1 joerg switch (emu->cur_rh) { 3853 1.1 joerg case 2: 3854 1.1 joerg destval = ~destval; 3855 1.1 joerg write_back_word(emu, destval); 3856 1.1 joerg break; 3857 1.1 joerg case 3: 3858 1.1 joerg destval = neg_word(emu, destval); 3859 1.1 joerg write_back_word(emu, destval); 3860 1.1 joerg break; 3861 1.1 joerg case 4: 3862 1.1 joerg mul_word(emu, destval); 3863 1.1 joerg break; 3864 1.1 joerg case 5: 3865 1.1 joerg imul_word(emu, destval); 3866 1.1 joerg break; 3867 1.1 joerg case 6: 3868 1.1 joerg div_word(emu, destval); 3869 1.1 joerg break; 3870 1.1 joerg case 7: 3871 1.1 joerg idiv_word(emu, destval); 3872 1.1 joerg break; 3873 1.1 joerg } 3874 1.1 joerg } 3875 1.1 joerg static void 3876 1.1 joerg x86emuOp_opcF7_word_RM(struct X86EMU *emu) 3877 1.1 joerg { 3878 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 3879 1.1 joerg x86emuOp32_opcF7_word_RM(emu); 3880 1.1 joerg else 3881 1.1 joerg x86emuOp16_opcF7_word_RM(emu); 3882 1.1 joerg } 3883 1.1 joerg /**************************************************************************** 3884 1.1 joerg REMARKS: 3885 1.1 joerg Handles opcode 0xfe 3886 1.1 joerg ****************************************************************************/ 3887 1.1 joerg static void 3888 1.1 joerg x86emuOp_opcFE_byte_RM(struct X86EMU *emu) 3889 1.1 joerg { 3890 1.1 joerg uint8_t destval; 3891 1.1 joerg uint32_t destoffset; 3892 1.1 joerg uint8_t *destreg; 3893 1.1 joerg 3894 1.1 joerg /* Yet another special case instruction. */ 3895 1.1 joerg fetch_decode_modrm(emu); 3896 1.1 joerg if (emu->cur_mod != 3) { 3897 1.1 joerg destoffset = decode_rl_address(emu); 3898 1.1 joerg switch (emu->cur_rh) { 3899 1.1 joerg case 0: /* inc word ptr ... */ 3900 1.1 joerg destval = fetch_data_byte(emu, destoffset); 3901 1.1 joerg destval = inc_byte(emu, destval); 3902 1.1 joerg store_data_byte(emu, destoffset, destval); 3903 1.1 joerg break; 3904 1.1 joerg case 1: /* dec word ptr ... */ 3905 1.1 joerg destval = fetch_data_byte(emu, destoffset); 3906 1.1 joerg destval = dec_byte(emu, destval); 3907 1.1 joerg store_data_byte(emu, destoffset, destval); 3908 1.1 joerg break; 3909 1.1 joerg } 3910 1.1 joerg } else { 3911 1.1 joerg destreg = decode_rl_byte_register(emu); 3912 1.1 joerg switch (emu->cur_rh) { 3913 1.1 joerg case 0: 3914 1.1 joerg *destreg = inc_byte(emu, *destreg); 3915 1.1 joerg break; 3916 1.1 joerg case 1: 3917 1.1 joerg *destreg = dec_byte(emu, *destreg); 3918 1.1 joerg break; 3919 1.1 joerg } 3920 1.1 joerg } 3921 1.1 joerg } 3922 1.1 joerg /**************************************************************************** 3923 1.1 joerg REMARKS: 3924 1.1 joerg Handles opcode 0xff 3925 1.1 joerg ****************************************************************************/ 3926 1.1 joerg static void 3927 1.1 joerg x86emuOp32_opcFF_word_RM(struct X86EMU *emu) 3928 1.1 joerg { 3929 1.1 joerg uint32_t destoffset = 0; 3930 1.1 joerg uint32_t destval, *destreg; 3931 1.1 joerg 3932 1.1 joerg if (emu->cur_mod != 3) { 3933 1.1 joerg destoffset = decode_rl_address(emu); 3934 1.1 joerg destval = fetch_data_long(emu, destoffset); 3935 1.1 joerg switch (emu->cur_rh) { 3936 1.1 joerg case 0: /* inc word ptr ... */ 3937 1.1 joerg destval = inc_long(emu, destval); 3938 1.1 joerg store_data_long(emu, destoffset, destval); 3939 1.1 joerg break; 3940 1.1 joerg case 1: /* dec word ptr ... */ 3941 1.1 joerg destval = dec_long(emu, destval); 3942 1.1 joerg store_data_long(emu, destoffset, destval); 3943 1.1 joerg break; 3944 1.1 joerg case 6: /* push word ptr ... */ 3945 1.1 joerg push_long(emu, destval); 3946 1.1 joerg break; 3947 1.1 joerg } 3948 1.1 joerg } else { 3949 1.1 joerg destreg = decode_rl_long_register(emu); 3950 1.1 joerg switch (emu->cur_rh) { 3951 1.1 joerg case 0: 3952 1.1 joerg *destreg = inc_long(emu, *destreg); 3953 1.1 joerg break; 3954 1.1 joerg case 1: 3955 1.1 joerg *destreg = dec_long(emu, *destreg); 3956 1.1 joerg break; 3957 1.1 joerg case 6: 3958 1.1 joerg push_long(emu, *destreg); 3959 1.1 joerg break; 3960 1.1 joerg } 3961 1.1 joerg } 3962 1.1 joerg } 3963 1.1 joerg 3964 1.1 joerg static void 3965 1.1 joerg x86emuOp16_opcFF_word_RM(struct X86EMU *emu) 3966 1.1 joerg { 3967 1.1 joerg uint32_t destoffset = 0; 3968 1.1 joerg uint16_t *destreg; 3969 1.1 joerg uint16_t destval; 3970 1.1 joerg 3971 1.1 joerg if (emu->cur_mod != 3) { 3972 1.1 joerg destoffset = decode_rl_address(emu); 3973 1.1 joerg destval = fetch_data_word(emu, destoffset); 3974 1.1 joerg switch (emu->cur_rh) { 3975 1.1 joerg case 0: 3976 1.1 joerg destval = inc_word(emu, destval); 3977 1.1 joerg store_data_word(emu, destoffset, destval); 3978 1.1 joerg break; 3979 1.1 joerg case 1: /* dec word ptr ... */ 3980 1.1 joerg destval = dec_word(emu, destval); 3981 1.1 joerg store_data_word(emu, destoffset, destval); 3982 1.1 joerg break; 3983 1.1 joerg case 6: /* push word ptr ... */ 3984 1.1 joerg push_word(emu, destval); 3985 1.1 joerg break; 3986 1.1 joerg } 3987 1.1 joerg } else { 3988 1.1 joerg destreg = decode_rl_word_register(emu); 3989 1.1 joerg switch (emu->cur_rh) { 3990 1.1 joerg case 0: 3991 1.1 joerg *destreg = inc_word(emu, *destreg); 3992 1.1 joerg break; 3993 1.1 joerg case 1: 3994 1.1 joerg *destreg = dec_word(emu, *destreg); 3995 1.1 joerg break; 3996 1.1 joerg case 6: 3997 1.1 joerg push_word(emu, *destreg); 3998 1.1 joerg break; 3999 1.1 joerg } 4000 1.1 joerg } 4001 1.1 joerg } 4002 1.1 joerg 4003 1.1 joerg static void 4004 1.1 joerg x86emuOp_opcFF_word_RM(struct X86EMU *emu) 4005 1.1 joerg { 4006 1.1 joerg uint32_t destoffset = 0; 4007 1.1 joerg uint16_t destval, destval2; 4008 1.1 joerg 4009 1.1 joerg /* Yet another special case instruction. */ 4010 1.1 joerg fetch_decode_modrm(emu); 4011 1.1 joerg if ((emu->cur_mod == 3 && (emu->cur_rh == 3 || emu->cur_rh == 5)) || emu->cur_rh == 7) 4012 1.1 joerg X86EMU_halt_sys(emu); 4013 1.1 joerg if (emu->cur_rh == 0 || emu->cur_rh == 1 || emu->cur_rh == 6) { 4014 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 4015 1.1 joerg x86emuOp32_opcFF_word_RM(emu); 4016 1.1 joerg else 4017 1.1 joerg x86emuOp16_opcFF_word_RM(emu); 4018 1.1 joerg return; 4019 1.1 joerg } 4020 1.1 joerg 4021 1.1 joerg if (emu->cur_mod != 3) { 4022 1.1 joerg destoffset = decode_rl_address(emu); 4023 1.1 joerg destval = fetch_data_word(emu, destoffset); 4024 1.1 joerg switch (emu->cur_rh) { 4025 1.1 joerg case 3: /* call far ptr ... */ 4026 1.1 joerg destval2 = fetch_data_word(emu, destoffset + 2); 4027 1.1 joerg push_word(emu, emu->x86.R_CS); 4028 1.1 joerg emu->x86.R_CS = destval2; 4029 1.1 joerg push_word(emu, emu->x86.R_IP); 4030 1.1 joerg emu->x86.R_IP = destval; 4031 1.1 joerg break; 4032 1.1 joerg case 5: /* jmp far ptr ... */ 4033 1.1 joerg destval2 = fetch_data_word(emu, destoffset + 2); 4034 1.1 joerg emu->x86.R_IP = destval; 4035 1.1 joerg emu->x86.R_CS = destval2; 4036 1.1 joerg break; 4037 1.1 joerg } 4038 1.1 joerg } else { 4039 1.1 joerg destval = *decode_rl_word_register(emu); 4040 1.1 joerg } 4041 1.1 joerg 4042 1.1 joerg switch (emu->cur_rh) { 4043 1.1 joerg case 2: /* call word ptr */ 4044 1.1 joerg push_word(emu, emu->x86.R_IP); 4045 1.1 joerg emu->x86.R_IP = destval; 4046 1.1 joerg break; 4047 1.1 joerg case 4: /* jmp */ 4048 1.1 joerg emu->x86.R_IP = destval; 4049 1.1 joerg break; 4050 1.1 joerg } 4051 1.1 joerg } 4052 1.1 joerg /*************************************************************************** 4053 1.1 joerg * Single byte operation code table: 4054 1.1 joerg **************************************************************************/ 4055 1.1 joerg static void 4056 1.1 joerg X86EMU_exec_one_byte(struct X86EMU * emu) 4057 1.1 joerg { 4058 1.1 joerg uint8_t op1; 4059 1.1 joerg 4060 1.1 joerg op1 = fetch_byte_imm(emu); 4061 1.1 joerg 4062 1.1 joerg switch (op1) { 4063 1.1 joerg case 0x00: 4064 1.1 joerg common_binop_byte_rm_r(emu, add_byte); 4065 1.1 joerg break; 4066 1.1 joerg case 0x01: 4067 1.1 joerg common_binop_word_long_rm_r(emu, add_word, add_long); 4068 1.1 joerg break; 4069 1.1 joerg case 0x02: 4070 1.1 joerg common_binop_byte_r_rm(emu, add_byte); 4071 1.1 joerg break; 4072 1.1 joerg case 0x03: 4073 1.1 joerg common_binop_word_long_r_rm(emu, add_word, add_long); 4074 1.1 joerg break; 4075 1.1 joerg case 0x04: 4076 1.1 joerg common_binop_byte_imm(emu, add_byte); 4077 1.1 joerg break; 4078 1.1 joerg case 0x05: 4079 1.1 joerg common_binop_word_long_imm(emu, add_word, add_long); 4080 1.1 joerg break; 4081 1.1 joerg case 0x06: 4082 1.1 joerg push_word(emu, emu->x86.R_ES); 4083 1.1 joerg break; 4084 1.1 joerg case 0x07: 4085 1.1 joerg emu->x86.R_ES = pop_word(emu); 4086 1.1 joerg break; 4087 1.1 joerg 4088 1.1 joerg case 0x08: 4089 1.1 joerg common_binop_byte_rm_r(emu, or_byte); 4090 1.1 joerg break; 4091 1.1 joerg case 0x09: 4092 1.1 joerg common_binop_word_long_rm_r(emu, or_word, or_long); 4093 1.1 joerg break; 4094 1.1 joerg case 0x0a: 4095 1.1 joerg common_binop_byte_r_rm(emu, or_byte); 4096 1.1 joerg break; 4097 1.1 joerg case 0x0b: 4098 1.1 joerg common_binop_word_long_r_rm(emu, or_word, or_long); 4099 1.1 joerg break; 4100 1.1 joerg case 0x0c: 4101 1.1 joerg common_binop_byte_imm(emu, or_byte); 4102 1.1 joerg break; 4103 1.1 joerg case 0x0d: 4104 1.1 joerg common_binop_word_long_imm(emu, or_word, or_long); 4105 1.1 joerg break; 4106 1.1 joerg case 0x0e: 4107 1.1 joerg push_word(emu, emu->x86.R_CS); 4108 1.1 joerg break; 4109 1.1 joerg case 0x0f: 4110 1.1 joerg X86EMU_exec_two_byte(emu); 4111 1.1 joerg break; 4112 1.1 joerg 4113 1.1 joerg case 0x10: 4114 1.1 joerg common_binop_byte_rm_r(emu, adc_byte); 4115 1.1 joerg break; 4116 1.1 joerg case 0x11: 4117 1.1 joerg common_binop_word_long_rm_r(emu, adc_word, adc_long); 4118 1.1 joerg break; 4119 1.1 joerg case 0x12: 4120 1.1 joerg common_binop_byte_r_rm(emu, adc_byte); 4121 1.1 joerg break; 4122 1.1 joerg case 0x13: 4123 1.1 joerg common_binop_word_long_r_rm(emu, adc_word, adc_long); 4124 1.1 joerg break; 4125 1.1 joerg case 0x14: 4126 1.1 joerg common_binop_byte_imm(emu, adc_byte); 4127 1.1 joerg break; 4128 1.1 joerg case 0x15: 4129 1.1 joerg common_binop_word_long_imm(emu, adc_word, adc_long); 4130 1.1 joerg break; 4131 1.1 joerg case 0x16: 4132 1.1 joerg push_word(emu, emu->x86.R_SS); 4133 1.1 joerg break; 4134 1.1 joerg case 0x17: 4135 1.1 joerg emu->x86.R_SS = pop_word(emu); 4136 1.1 joerg break; 4137 1.1 joerg 4138 1.1 joerg case 0x18: 4139 1.1 joerg common_binop_byte_rm_r(emu, sbb_byte); 4140 1.1 joerg break; 4141 1.1 joerg case 0x19: 4142 1.1 joerg common_binop_word_long_rm_r(emu, sbb_word, sbb_long); 4143 1.1 joerg break; 4144 1.1 joerg case 0x1a: 4145 1.1 joerg common_binop_byte_r_rm(emu, sbb_byte); 4146 1.1 joerg break; 4147 1.1 joerg case 0x1b: 4148 1.1 joerg common_binop_word_long_r_rm(emu, sbb_word, sbb_long); 4149 1.1 joerg break; 4150 1.1 joerg case 0x1c: 4151 1.1 joerg common_binop_byte_imm(emu, sbb_byte); 4152 1.1 joerg break; 4153 1.1 joerg case 0x1d: 4154 1.1 joerg common_binop_word_long_imm(emu, sbb_word, sbb_long); 4155 1.1 joerg break; 4156 1.1 joerg case 0x1e: 4157 1.1 joerg push_word(emu, emu->x86.R_DS); 4158 1.1 joerg break; 4159 1.1 joerg case 0x1f: 4160 1.1 joerg emu->x86.R_DS = pop_word(emu); 4161 1.1 joerg break; 4162 1.1 joerg 4163 1.1 joerg case 0x20: 4164 1.1 joerg common_binop_byte_rm_r(emu, and_byte); 4165 1.1 joerg break; 4166 1.1 joerg case 0x21: 4167 1.1 joerg common_binop_word_long_rm_r(emu, and_word, and_long); 4168 1.1 joerg break; 4169 1.1 joerg case 0x22: 4170 1.1 joerg common_binop_byte_r_rm(emu, and_byte); 4171 1.1 joerg break; 4172 1.1 joerg case 0x23: 4173 1.1 joerg common_binop_word_long_r_rm(emu, and_word, and_long); 4174 1.1 joerg break; 4175 1.1 joerg case 0x24: 4176 1.1 joerg common_binop_byte_imm(emu, and_byte); 4177 1.1 joerg break; 4178 1.1 joerg case 0x25: 4179 1.1 joerg common_binop_word_long_imm(emu, and_word, and_long); 4180 1.1 joerg break; 4181 1.1 joerg case 0x26: 4182 1.1 joerg emu->x86.mode |= SYSMODE_SEGOVR_ES; 4183 1.1 joerg break; 4184 1.1 joerg case 0x27: 4185 1.1 joerg emu->x86.R_AL = daa_byte(emu, emu->x86.R_AL); 4186 1.1 joerg break; 4187 1.1 joerg 4188 1.1 joerg case 0x28: 4189 1.1 joerg common_binop_byte_rm_r(emu, sub_byte); 4190 1.1 joerg break; 4191 1.1 joerg case 0x29: 4192 1.1 joerg common_binop_word_long_rm_r(emu, sub_word, sub_long); 4193 1.1 joerg break; 4194 1.1 joerg case 0x2a: 4195 1.1 joerg common_binop_byte_r_rm(emu, sub_byte); 4196 1.1 joerg break; 4197 1.1 joerg case 0x2b: 4198 1.1 joerg common_binop_word_long_r_rm(emu, sub_word, sub_long); 4199 1.1 joerg break; 4200 1.1 joerg case 0x2c: 4201 1.1 joerg common_binop_byte_imm(emu, sub_byte); 4202 1.1 joerg break; 4203 1.1 joerg case 0x2d: 4204 1.1 joerg common_binop_word_long_imm(emu, sub_word, sub_long); 4205 1.1 joerg break; 4206 1.1 joerg case 0x2e: 4207 1.1 joerg emu->x86.mode |= SYSMODE_SEGOVR_CS; 4208 1.1 joerg break; 4209 1.1 joerg case 0x2f: 4210 1.1 joerg emu->x86.R_AL = das_byte(emu, emu->x86.R_AL); 4211 1.1 joerg break; 4212 1.1 joerg 4213 1.1 joerg case 0x30: 4214 1.1 joerg common_binop_byte_rm_r(emu, xor_byte); 4215 1.1 joerg break; 4216 1.1 joerg case 0x31: 4217 1.1 joerg common_binop_word_long_rm_r(emu, xor_word, xor_long); 4218 1.1 joerg break; 4219 1.1 joerg case 0x32: 4220 1.1 joerg common_binop_byte_r_rm(emu, xor_byte); 4221 1.1 joerg break; 4222 1.1 joerg case 0x33: 4223 1.1 joerg common_binop_word_long_r_rm(emu, xor_word, xor_long); 4224 1.1 joerg break; 4225 1.1 joerg case 0x34: 4226 1.1 joerg common_binop_byte_imm(emu, xor_byte); 4227 1.1 joerg break; 4228 1.1 joerg case 0x35: 4229 1.1 joerg common_binop_word_long_imm(emu, xor_word, xor_long); 4230 1.1 joerg break; 4231 1.1 joerg case 0x36: 4232 1.1 joerg emu->x86.mode |= SYSMODE_SEGOVR_SS; 4233 1.1 joerg break; 4234 1.1 joerg case 0x37: 4235 1.1 joerg emu->x86.R_AX = aaa_word(emu, emu->x86.R_AX); 4236 1.1 joerg break; 4237 1.1 joerg 4238 1.1 joerg case 0x38: 4239 1.1 joerg common_binop_ns_byte_rm_r(emu, cmp_byte_no_return); 4240 1.1 joerg break; 4241 1.1 joerg case 0x39: 4242 1.1 joerg common_binop_ns_word_long_rm_r(emu, cmp_word_no_return, 4243 1.1 joerg cmp_long_no_return); 4244 1.1 joerg break; 4245 1.1 joerg case 0x3a: 4246 1.1 joerg x86emuOp_cmp_byte_R_RM(emu); 4247 1.1 joerg break; 4248 1.1 joerg case 0x3b: 4249 1.1 joerg x86emuOp_cmp_word_R_RM(emu); 4250 1.1 joerg break; 4251 1.1 joerg case 0x3c: 4252 1.1 joerg x86emuOp_cmp_byte_AL_IMM(emu); 4253 1.1 joerg break; 4254 1.1 joerg case 0x3d: 4255 1.1 joerg x86emuOp_cmp_word_AX_IMM(emu); 4256 1.1 joerg break; 4257 1.1 joerg case 0x3e: 4258 1.1 joerg emu->x86.mode |= SYSMODE_SEGOVR_DS; 4259 1.1 joerg break; 4260 1.1 joerg case 0x3f: 4261 1.1 joerg emu->x86.R_AX = aas_word(emu, emu->x86.R_AX); 4262 1.1 joerg break; 4263 1.1 joerg 4264 1.1 joerg case 0x40: 4265 1.1 joerg common_inc_word_long(emu, &emu->x86.register_a); 4266 1.1 joerg break; 4267 1.1 joerg case 0x41: 4268 1.1 joerg common_inc_word_long(emu, &emu->x86.register_c); 4269 1.1 joerg break; 4270 1.1 joerg case 0x42: 4271 1.1 joerg common_inc_word_long(emu, &emu->x86.register_d); 4272 1.1 joerg break; 4273 1.1 joerg case 0x43: 4274 1.1 joerg common_inc_word_long(emu, &emu->x86.register_b); 4275 1.1 joerg break; 4276 1.1 joerg case 0x44: 4277 1.1 joerg common_inc_word_long(emu, &emu->x86.register_sp); 4278 1.1 joerg break; 4279 1.1 joerg case 0x45: 4280 1.1 joerg common_inc_word_long(emu, &emu->x86.register_bp); 4281 1.1 joerg break; 4282 1.1 joerg case 0x46: 4283 1.1 joerg common_inc_word_long(emu, &emu->x86.register_si); 4284 1.1 joerg break; 4285 1.1 joerg case 0x47: 4286 1.1 joerg common_inc_word_long(emu, &emu->x86.register_di); 4287 1.1 joerg break; 4288 1.1 joerg 4289 1.1 joerg case 0x48: 4290 1.1 joerg common_dec_word_long(emu, &emu->x86.register_a); 4291 1.1 joerg break; 4292 1.1 joerg case 0x49: 4293 1.1 joerg common_dec_word_long(emu, &emu->x86.register_c); 4294 1.1 joerg break; 4295 1.1 joerg case 0x4a: 4296 1.1 joerg common_dec_word_long(emu, &emu->x86.register_d); 4297 1.1 joerg break; 4298 1.1 joerg case 0x4b: 4299 1.1 joerg common_dec_word_long(emu, &emu->x86.register_b); 4300 1.1 joerg break; 4301 1.1 joerg case 0x4c: 4302 1.1 joerg common_dec_word_long(emu, &emu->x86.register_sp); 4303 1.1 joerg break; 4304 1.1 joerg case 0x4d: 4305 1.1 joerg common_dec_word_long(emu, &emu->x86.register_bp); 4306 1.1 joerg break; 4307 1.1 joerg case 0x4e: 4308 1.1 joerg common_dec_word_long(emu, &emu->x86.register_si); 4309 1.1 joerg break; 4310 1.1 joerg case 0x4f: 4311 1.1 joerg common_dec_word_long(emu, &emu->x86.register_di); 4312 1.1 joerg break; 4313 1.1 joerg 4314 1.1 joerg case 0x50: 4315 1.1 joerg common_push_word_long(emu, &emu->x86.register_a); 4316 1.1 joerg break; 4317 1.1 joerg case 0x51: 4318 1.1 joerg common_push_word_long(emu, &emu->x86.register_c); 4319 1.1 joerg break; 4320 1.1 joerg case 0x52: 4321 1.1 joerg common_push_word_long(emu, &emu->x86.register_d); 4322 1.1 joerg break; 4323 1.1 joerg case 0x53: 4324 1.1 joerg common_push_word_long(emu, &emu->x86.register_b); 4325 1.1 joerg break; 4326 1.1 joerg case 0x54: 4327 1.1 joerg common_push_word_long(emu, &emu->x86.register_sp); 4328 1.1 joerg break; 4329 1.1 joerg case 0x55: 4330 1.1 joerg common_push_word_long(emu, &emu->x86.register_bp); 4331 1.1 joerg break; 4332 1.1 joerg case 0x56: 4333 1.1 joerg common_push_word_long(emu, &emu->x86.register_si); 4334 1.1 joerg break; 4335 1.1 joerg case 0x57: 4336 1.1 joerg common_push_word_long(emu, &emu->x86.register_di); 4337 1.1 joerg break; 4338 1.1 joerg 4339 1.1 joerg case 0x58: 4340 1.1 joerg common_pop_word_long(emu, &emu->x86.register_a); 4341 1.1 joerg break; 4342 1.1 joerg case 0x59: 4343 1.1 joerg common_pop_word_long(emu, &emu->x86.register_c); 4344 1.1 joerg break; 4345 1.1 joerg case 0x5a: 4346 1.1 joerg common_pop_word_long(emu, &emu->x86.register_d); 4347 1.1 joerg break; 4348 1.1 joerg case 0x5b: 4349 1.1 joerg common_pop_word_long(emu, &emu->x86.register_b); 4350 1.1 joerg break; 4351 1.1 joerg case 0x5c: 4352 1.1 joerg common_pop_word_long(emu, &emu->x86.register_sp); 4353 1.1 joerg break; 4354 1.1 joerg case 0x5d: 4355 1.1 joerg common_pop_word_long(emu, &emu->x86.register_bp); 4356 1.1 joerg break; 4357 1.1 joerg case 0x5e: 4358 1.1 joerg common_pop_word_long(emu, &emu->x86.register_si); 4359 1.1 joerg break; 4360 1.1 joerg case 0x5f: 4361 1.1 joerg common_pop_word_long(emu, &emu->x86.register_di); 4362 1.1 joerg break; 4363 1.1 joerg 4364 1.1 joerg case 0x60: 4365 1.1 joerg x86emuOp_push_all(emu); 4366 1.1 joerg break; 4367 1.1 joerg case 0x61: 4368 1.1 joerg x86emuOp_pop_all(emu); 4369 1.1 joerg break; 4370 1.1 joerg /* 0x62 bound */ 4371 1.1 joerg /* 0x63 arpl */ 4372 1.1 joerg case 0x64: 4373 1.1 joerg emu->x86.mode |= SYSMODE_SEGOVR_FS; 4374 1.1 joerg break; 4375 1.1 joerg case 0x65: 4376 1.1 joerg emu->x86.mode |= SYSMODE_SEGOVR_GS; 4377 1.1 joerg break; 4378 1.1 joerg case 0x66: 4379 1.1 joerg emu->x86.mode |= SYSMODE_PREFIX_DATA; 4380 1.1 joerg break; 4381 1.1 joerg case 0x67: 4382 1.1 joerg emu->x86.mode |= SYSMODE_PREFIX_ADDR; 4383 1.1 joerg break; 4384 1.1 joerg 4385 1.1 joerg case 0x68: 4386 1.1 joerg x86emuOp_push_word_IMM(emu); 4387 1.1 joerg break; 4388 1.1 joerg case 0x69: 4389 1.1 joerg common_imul_imm(emu, false); 4390 1.1 joerg break; 4391 1.1 joerg case 0x6a: 4392 1.1 joerg x86emuOp_push_byte_IMM(emu); 4393 1.1 joerg break; 4394 1.1 joerg case 0x6b: 4395 1.1 joerg common_imul_imm(emu, true); 4396 1.1 joerg break; 4397 1.1 joerg case 0x6c: 4398 1.1 joerg ins(emu, 1); 4399 1.1 joerg break; 4400 1.1 joerg case 0x6d: 4401 1.1 joerg x86emuOp_ins_word(emu); 4402 1.1 joerg break; 4403 1.1 joerg case 0x6e: 4404 1.1 joerg outs(emu, 1); 4405 1.1 joerg break; 4406 1.1 joerg case 0x6f: 4407 1.1 joerg x86emuOp_outs_word(emu); 4408 1.1 joerg break; 4409 1.1 joerg 4410 1.1 joerg case 0x70: 4411 1.1 joerg common_jmp_near(emu, ACCESS_FLAG(F_OF)); 4412 1.1 joerg break; 4413 1.1 joerg case 0x71: 4414 1.1 joerg common_jmp_near(emu, !ACCESS_FLAG(F_OF)); 4415 1.1 joerg break; 4416 1.1 joerg case 0x72: 4417 1.1 joerg common_jmp_near(emu, ACCESS_FLAG(F_CF)); 4418 1.1 joerg break; 4419 1.1 joerg case 0x73: 4420 1.1 joerg common_jmp_near(emu, !ACCESS_FLAG(F_CF)); 4421 1.1 joerg break; 4422 1.1 joerg case 0x74: 4423 1.1 joerg common_jmp_near(emu, ACCESS_FLAG(F_ZF)); 4424 1.1 joerg break; 4425 1.1 joerg case 0x75: 4426 1.1 joerg common_jmp_near(emu, !ACCESS_FLAG(F_ZF)); 4427 1.1 joerg break; 4428 1.1 joerg case 0x76: 4429 1.1 joerg common_jmp_near(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); 4430 1.1 joerg break; 4431 1.1 joerg case 0x77: 4432 1.1 joerg common_jmp_near(emu, !ACCESS_FLAG(F_CF) && !ACCESS_FLAG(F_ZF)); 4433 1.1 joerg break; 4434 1.1 joerg 4435 1.1 joerg case 0x78: 4436 1.1 joerg common_jmp_near(emu, ACCESS_FLAG(F_SF)); 4437 1.1 joerg break; 4438 1.1 joerg case 0x79: 4439 1.1 joerg common_jmp_near(emu, !ACCESS_FLAG(F_SF)); 4440 1.1 joerg break; 4441 1.1 joerg case 0x7a: 4442 1.1 joerg common_jmp_near(emu, ACCESS_FLAG(F_PF)); 4443 1.1 joerg break; 4444 1.1 joerg case 0x7b: 4445 1.1 joerg common_jmp_near(emu, !ACCESS_FLAG(F_PF)); 4446 1.1 joerg break; 4447 1.1 joerg case 0x7c: 4448 1.1 joerg x86emuOp_jump_near_L(emu); 4449 1.1 joerg break; 4450 1.1 joerg case 0x7d: 4451 1.1 joerg x86emuOp_jump_near_NL(emu); 4452 1.1 joerg break; 4453 1.1 joerg case 0x7e: 4454 1.1 joerg x86emuOp_jump_near_LE(emu); 4455 1.1 joerg break; 4456 1.1 joerg case 0x7f: 4457 1.1 joerg x86emuOp_jump_near_NLE(emu); 4458 1.1 joerg break; 4459 1.1 joerg 4460 1.1 joerg case 0x80: 4461 1.1 joerg x86emuOp_opc80_byte_RM_IMM(emu); 4462 1.1 joerg break; 4463 1.1 joerg case 0x81: 4464 1.1 joerg x86emuOp_opc81_word_RM_IMM(emu); 4465 1.1 joerg break; 4466 1.1 joerg case 0x82: 4467 1.1 joerg x86emuOp_opc82_byte_RM_IMM(emu); 4468 1.1 joerg break; 4469 1.1 joerg case 0x83: 4470 1.1 joerg x86emuOp_opc83_word_RM_IMM(emu); 4471 1.1 joerg break; 4472 1.1 joerg case 0x84: 4473 1.1 joerg common_binop_ns_byte_rm_r(emu, test_byte); 4474 1.1 joerg break; 4475 1.1 joerg case 0x85: 4476 1.1 joerg common_binop_ns_word_long_rm_r(emu, test_word, test_long); 4477 1.1 joerg break; 4478 1.1 joerg case 0x86: 4479 1.1 joerg x86emuOp_xchg_byte_RM_R(emu); 4480 1.1 joerg break; 4481 1.1 joerg case 0x87: 4482 1.1 joerg x86emuOp_xchg_word_RM_R(emu); 4483 1.1 joerg break; 4484 1.1 joerg 4485 1.1 joerg case 0x88: 4486 1.1 joerg x86emuOp_mov_byte_RM_R(emu); 4487 1.1 joerg break; 4488 1.1 joerg case 0x89: 4489 1.1 joerg x86emuOp_mov_word_RM_R(emu); 4490 1.1 joerg break; 4491 1.1 joerg case 0x8a: 4492 1.1 joerg x86emuOp_mov_byte_R_RM(emu); 4493 1.1 joerg break; 4494 1.1 joerg case 0x8b: 4495 1.1 joerg x86emuOp_mov_word_R_RM(emu); 4496 1.1 joerg break; 4497 1.1 joerg case 0x8c: 4498 1.1 joerg x86emuOp_mov_word_RM_SR(emu); 4499 1.1 joerg break; 4500 1.1 joerg case 0x8d: 4501 1.1 joerg x86emuOp_lea_word_R_M(emu); 4502 1.1 joerg break; 4503 1.1 joerg case 0x8e: 4504 1.1 joerg x86emuOp_mov_word_SR_RM(emu); 4505 1.1 joerg break; 4506 1.1 joerg case 0x8f: 4507 1.1 joerg x86emuOp_pop_RM(emu); 4508 1.1 joerg break; 4509 1.1 joerg 4510 1.1 joerg case 0x90: 4511 1.1 joerg /* nop */ 4512 1.1 joerg break; 4513 1.1 joerg case 0x91: 4514 1.1 joerg x86emuOp_xchg_word_AX_CX(emu); 4515 1.1 joerg break; 4516 1.1 joerg case 0x92: 4517 1.1 joerg x86emuOp_xchg_word_AX_DX(emu); 4518 1.1 joerg break; 4519 1.1 joerg case 0x93: 4520 1.1 joerg x86emuOp_xchg_word_AX_BX(emu); 4521 1.1 joerg break; 4522 1.1 joerg case 0x94: 4523 1.1 joerg x86emuOp_xchg_word_AX_SP(emu); 4524 1.1 joerg break; 4525 1.1 joerg case 0x95: 4526 1.1 joerg x86emuOp_xchg_word_AX_BP(emu); 4527 1.1 joerg break; 4528 1.1 joerg case 0x96: 4529 1.1 joerg x86emuOp_xchg_word_AX_SI(emu); 4530 1.1 joerg break; 4531 1.1 joerg case 0x97: 4532 1.1 joerg x86emuOp_xchg_word_AX_DI(emu); 4533 1.1 joerg break; 4534 1.1 joerg 4535 1.1 joerg case 0x98: 4536 1.1 joerg x86emuOp_cbw(emu); 4537 1.1 joerg break; 4538 1.1 joerg case 0x99: 4539 1.1 joerg x86emuOp_cwd(emu); 4540 1.1 joerg break; 4541 1.1 joerg case 0x9a: 4542 1.1 joerg x86emuOp_call_far_IMM(emu); 4543 1.1 joerg break; 4544 1.1 joerg case 0x9b: 4545 1.1 joerg /* wait */ 4546 1.1 joerg break; 4547 1.1 joerg case 0x9c: 4548 1.1 joerg x86emuOp_pushf_word(emu); 4549 1.1 joerg break; 4550 1.1 joerg case 0x9d: 4551 1.1 joerg x86emuOp_popf_word(emu); 4552 1.1 joerg break; 4553 1.1 joerg case 0x9e: 4554 1.1 joerg x86emuOp_sahf(emu); 4555 1.1 joerg break; 4556 1.1 joerg case 0x9f: 4557 1.1 joerg x86emuOp_lahf(emu); 4558 1.1 joerg break; 4559 1.1 joerg 4560 1.1 joerg case 0xa0: 4561 1.1 joerg x86emuOp_mov_AL_M_IMM(emu); 4562 1.1 joerg break; 4563 1.1 joerg case 0xa1: 4564 1.1 joerg x86emuOp_mov_AX_M_IMM(emu); 4565 1.1 joerg break; 4566 1.1 joerg case 0xa2: 4567 1.1 joerg x86emuOp_mov_M_AL_IMM(emu); 4568 1.1 joerg break; 4569 1.1 joerg case 0xa3: 4570 1.1 joerg x86emuOp_mov_M_AX_IMM(emu); 4571 1.1 joerg break; 4572 1.1 joerg case 0xa4: 4573 1.1 joerg x86emuOp_movs_byte(emu); 4574 1.1 joerg break; 4575 1.1 joerg case 0xa5: 4576 1.1 joerg x86emuOp_movs_word(emu); 4577 1.1 joerg break; 4578 1.1 joerg case 0xa6: 4579 1.1 joerg x86emuOp_cmps_byte(emu); 4580 1.1 joerg break; 4581 1.1 joerg case 0xa7: 4582 1.1 joerg x86emuOp_cmps_word(emu); 4583 1.1 joerg break; 4584 1.1 joerg 4585 1.1 joerg case 0xa8: 4586 1.1 joerg test_byte(emu, emu->x86.R_AL, fetch_byte_imm(emu)); 4587 1.1 joerg break; 4588 1.1 joerg case 0xa9: 4589 1.1 joerg x86emuOp_test_AX_IMM(emu); 4590 1.1 joerg break; 4591 1.1 joerg case 0xaa: 4592 1.1 joerg x86emuOp_stos_byte(emu); 4593 1.1 joerg break; 4594 1.1 joerg case 0xab: 4595 1.1 joerg x86emuOp_stos_word(emu); 4596 1.1 joerg break; 4597 1.1 joerg case 0xac: 4598 1.1 joerg x86emuOp_lods_byte(emu); 4599 1.1 joerg break; 4600 1.1 joerg case 0xad: 4601 1.1 joerg x86emuOp_lods_word(emu); 4602 1.1 joerg break; 4603 1.1 joerg case 0xae: 4604 1.1 joerg x86emuOp_scas_byte(emu); 4605 1.1 joerg break; 4606 1.1 joerg case 0xaf: 4607 1.1 joerg x86emuOp_scas_word(emu); 4608 1.1 joerg break; 4609 1.1 joerg 4610 1.1 joerg case 0xb0: 4611 1.1 joerg emu->x86.R_AL = fetch_byte_imm(emu); 4612 1.1 joerg break; 4613 1.1 joerg case 0xb1: 4614 1.1 joerg emu->x86.R_CL = fetch_byte_imm(emu); 4615 1.1 joerg break; 4616 1.1 joerg case 0xb2: 4617 1.1 joerg emu->x86.R_DL = fetch_byte_imm(emu); 4618 1.1 joerg break; 4619 1.1 joerg case 0xb3: 4620 1.1 joerg emu->x86.R_BL = fetch_byte_imm(emu); 4621 1.1 joerg break; 4622 1.1 joerg case 0xb4: 4623 1.1 joerg emu->x86.R_AH = fetch_byte_imm(emu); 4624 1.1 joerg break; 4625 1.1 joerg case 0xb5: 4626 1.1 joerg emu->x86.R_CH = fetch_byte_imm(emu); 4627 1.1 joerg break; 4628 1.1 joerg case 0xb6: 4629 1.1 joerg emu->x86.R_DH = fetch_byte_imm(emu); 4630 1.1 joerg break; 4631 1.1 joerg case 0xb7: 4632 1.1 joerg emu->x86.R_BH = fetch_byte_imm(emu); 4633 1.1 joerg break; 4634 1.1 joerg 4635 1.1 joerg case 0xb8: 4636 1.1 joerg x86emuOp_mov_word_AX_IMM(emu); 4637 1.1 joerg break; 4638 1.1 joerg case 0xb9: 4639 1.1 joerg x86emuOp_mov_word_CX_IMM(emu); 4640 1.1 joerg break; 4641 1.1 joerg case 0xba: 4642 1.1 joerg x86emuOp_mov_word_DX_IMM(emu); 4643 1.1 joerg break; 4644 1.1 joerg case 0xbb: 4645 1.1 joerg x86emuOp_mov_word_BX_IMM(emu); 4646 1.1 joerg break; 4647 1.1 joerg case 0xbc: 4648 1.1 joerg x86emuOp_mov_word_SP_IMM(emu); 4649 1.1 joerg break; 4650 1.1 joerg case 0xbd: 4651 1.1 joerg x86emuOp_mov_word_BP_IMM(emu); 4652 1.1 joerg break; 4653 1.1 joerg case 0xbe: 4654 1.1 joerg x86emuOp_mov_word_SI_IMM(emu); 4655 1.1 joerg break; 4656 1.1 joerg case 0xbf: 4657 1.1 joerg x86emuOp_mov_word_DI_IMM(emu); 4658 1.1 joerg break; 4659 1.1 joerg 4660 1.1 joerg case 0xc0: 4661 1.1 joerg x86emuOp_opcC0_byte_RM_MEM(emu); 4662 1.1 joerg break; 4663 1.1 joerg case 0xc1: 4664 1.1 joerg x86emuOp_opcC1_word_RM_MEM(emu); 4665 1.1 joerg break; 4666 1.1 joerg case 0xc2: 4667 1.1 joerg x86emuOp_ret_near_IMM(emu); 4668 1.1 joerg break; 4669 1.1 joerg case 0xc3: 4670 1.1 joerg emu->x86.R_IP = pop_word(emu); 4671 1.1 joerg break; 4672 1.1 joerg case 0xc4: 4673 1.1 joerg common_load_far_pointer(emu, &emu->x86.R_ES); 4674 1.1 joerg break; 4675 1.1 joerg case 0xc5: 4676 1.1 joerg common_load_far_pointer(emu, &emu->x86.R_DS); 4677 1.1 joerg break; 4678 1.1 joerg case 0xc6: 4679 1.1 joerg x86emuOp_mov_byte_RM_IMM(emu); 4680 1.1 joerg break; 4681 1.1 joerg case 0xc7: 4682 1.1 joerg x86emuOp_mov_word_RM_IMM(emu); 4683 1.1 joerg break; 4684 1.1 joerg case 0xc8: 4685 1.1 joerg x86emuOp_enter(emu); 4686 1.1 joerg break; 4687 1.1 joerg case 0xc9: 4688 1.1 joerg x86emuOp_leave(emu); 4689 1.1 joerg break; 4690 1.1 joerg case 0xca: 4691 1.1 joerg x86emuOp_ret_far_IMM(emu); 4692 1.1 joerg break; 4693 1.1 joerg case 0xcb: 4694 1.1 joerg x86emuOp_ret_far(emu); 4695 1.1 joerg break; 4696 1.1 joerg case 0xcc: 4697 1.1 joerg x86emuOp_int3(emu); 4698 1.1 joerg break; 4699 1.1 joerg case 0xcd: 4700 1.1 joerg x86emuOp_int_IMM(emu); 4701 1.1 joerg break; 4702 1.1 joerg case 0xce: 4703 1.1 joerg x86emuOp_into(emu); 4704 1.1 joerg break; 4705 1.1 joerg case 0xcf: 4706 1.1 joerg x86emuOp_iret(emu); 4707 1.1 joerg break; 4708 1.1 joerg 4709 1.1 joerg case 0xd0: 4710 1.1 joerg x86emuOp_opcD0_byte_RM_1(emu); 4711 1.1 joerg break; 4712 1.1 joerg case 0xd1: 4713 1.1 joerg x86emuOp_opcD1_word_RM_1(emu); 4714 1.1 joerg break; 4715 1.1 joerg case 0xd2: 4716 1.1 joerg x86emuOp_opcD2_byte_RM_CL(emu); 4717 1.1 joerg break; 4718 1.1 joerg case 0xd3: 4719 1.1 joerg x86emuOp_opcD3_word_RM_CL(emu); 4720 1.1 joerg break; 4721 1.1 joerg case 0xd4: 4722 1.1 joerg x86emuOp_aam(emu); 4723 1.1 joerg break; 4724 1.1 joerg case 0xd5: 4725 1.1 joerg x86emuOp_aad(emu); 4726 1.1 joerg break; 4727 1.1 joerg /* 0xd6 Undocumented SETALC instruction */ 4728 1.1 joerg case 0xd7: 4729 1.1 joerg x86emuOp_xlat(emu); 4730 1.1 joerg break; 4731 1.1 joerg case 0xd8: 4732 1.1 joerg x86emuOp_esc_coprocess_d8(emu); 4733 1.1 joerg break; 4734 1.1 joerg case 0xd9: 4735 1.1 joerg x86emuOp_esc_coprocess_d9(emu); 4736 1.1 joerg break; 4737 1.1 joerg case 0xda: 4738 1.1 joerg x86emuOp_esc_coprocess_da(emu); 4739 1.1 joerg break; 4740 1.1 joerg case 0xdb: 4741 1.1 joerg x86emuOp_esc_coprocess_db(emu); 4742 1.1 joerg break; 4743 1.1 joerg case 0xdc: 4744 1.1 joerg x86emuOp_esc_coprocess_dc(emu); 4745 1.1 joerg break; 4746 1.1 joerg case 0xdd: 4747 1.1 joerg x86emuOp_esc_coprocess_dd(emu); 4748 1.1 joerg break; 4749 1.1 joerg case 0xde: 4750 1.1 joerg x86emuOp_esc_coprocess_de(emu); 4751 1.1 joerg break; 4752 1.1 joerg case 0xdf: 4753 1.1 joerg x86emuOp_esc_coprocess_df(emu); 4754 1.1 joerg break; 4755 1.1 joerg 4756 1.1 joerg case 0xe0: 4757 1.1 joerg x86emuOp_loopne(emu); 4758 1.1 joerg break; 4759 1.1 joerg case 0xe1: 4760 1.1 joerg x86emuOp_loope(emu); 4761 1.1 joerg break; 4762 1.1 joerg case 0xe2: 4763 1.1 joerg x86emuOp_loop(emu); 4764 1.1 joerg break; 4765 1.1 joerg case 0xe3: 4766 1.1 joerg x86emuOp_jcxz(emu); 4767 1.1 joerg break; 4768 1.1 joerg case 0xe4: 4769 1.1 joerg x86emuOp_in_byte_AL_IMM(emu); 4770 1.1 joerg break; 4771 1.1 joerg case 0xe5: 4772 1.1 joerg x86emuOp_in_word_AX_IMM(emu); 4773 1.1 joerg break; 4774 1.1 joerg case 0xe6: 4775 1.1 joerg x86emuOp_out_byte_IMM_AL(emu); 4776 1.1 joerg break; 4777 1.1 joerg case 0xe7: 4778 1.1 joerg x86emuOp_out_word_IMM_AX(emu); 4779 1.1 joerg break; 4780 1.1 joerg 4781 1.1 joerg case 0xe8: 4782 1.1 joerg x86emuOp_call_near_IMM(emu); 4783 1.1 joerg break; 4784 1.1 joerg case 0xe9: 4785 1.1 joerg x86emuOp_jump_near_IMM(emu); 4786 1.1 joerg break; 4787 1.1 joerg case 0xea: 4788 1.1 joerg x86emuOp_jump_far_IMM(emu); 4789 1.1 joerg break; 4790 1.1 joerg case 0xeb: 4791 1.1 joerg x86emuOp_jump_byte_IMM(emu); 4792 1.1 joerg break; 4793 1.1 joerg case 0xec: 4794 1.1 joerg x86emuOp_in_byte_AL_DX(emu); 4795 1.1 joerg break; 4796 1.1 joerg case 0xed: 4797 1.1 joerg x86emuOp_in_word_AX_DX(emu); 4798 1.1 joerg break; 4799 1.1 joerg case 0xee: 4800 1.1 joerg x86emuOp_out_byte_DX_AL(emu); 4801 1.1 joerg break; 4802 1.1 joerg case 0xef: 4803 1.1 joerg x86emuOp_out_word_DX_AX(emu); 4804 1.1 joerg break; 4805 1.1 joerg 4806 1.1 joerg case 0xf0: 4807 1.1 joerg x86emuOp_lock(emu); 4808 1.1 joerg break; 4809 1.1 joerg case 0xf2: 4810 1.1 joerg emu->x86.mode |= SYSMODE_PREFIX_REPNE; 4811 1.1 joerg break; 4812 1.1 joerg case 0xf3: 4813 1.1 joerg emu->x86.mode |= SYSMODE_PREFIX_REPE; 4814 1.1 joerg break; 4815 1.1 joerg case 0xf4: 4816 1.1 joerg X86EMU_halt_sys(emu); 4817 1.1 joerg break; 4818 1.1 joerg case 0xf5: 4819 1.1 joerg x86emuOp_cmc(emu); 4820 1.1 joerg break; 4821 1.1 joerg case 0xf6: 4822 1.1 joerg x86emuOp_opcF6_byte_RM(emu); 4823 1.1 joerg break; 4824 1.1 joerg case 0xf7: 4825 1.1 joerg x86emuOp_opcF7_word_RM(emu); 4826 1.1 joerg break; 4827 1.1 joerg 4828 1.1 joerg case 0xf8: 4829 1.1 joerg CLEAR_FLAG(F_CF); 4830 1.1 joerg break; 4831 1.1 joerg case 0xf9: 4832 1.1 joerg SET_FLAG(F_CF); 4833 1.1 joerg break; 4834 1.1 joerg case 0xfa: 4835 1.1 joerg CLEAR_FLAG(F_IF); 4836 1.1 joerg break; 4837 1.1 joerg case 0xfb: 4838 1.1 joerg SET_FLAG(F_IF); 4839 1.1 joerg break; 4840 1.1 joerg case 0xfc: 4841 1.1 joerg CLEAR_FLAG(F_DF); 4842 1.1 joerg break; 4843 1.1 joerg case 0xfd: 4844 1.1 joerg SET_FLAG(F_DF); 4845 1.1 joerg break; 4846 1.1 joerg case 0xfe: 4847 1.1 joerg x86emuOp_opcFE_byte_RM(emu); 4848 1.1 joerg break; 4849 1.1 joerg case 0xff: 4850 1.1 joerg x86emuOp_opcFF_word_RM(emu); 4851 1.1 joerg break; 4852 1.1 joerg default: 4853 1.1 joerg X86EMU_halt_sys(emu); 4854 1.1 joerg break; 4855 1.1 joerg } 4856 1.1 joerg if (op1 != 0x26 && op1 != 0x2e && op1 != 0x36 && op1 != 0x3e && 4857 1.1 joerg (op1 | 3) != 0x67) 4858 1.1 joerg emu->x86.mode &= ~SYSMODE_CLRMASK; 4859 1.1 joerg } 4860 1.1 joerg 4861 1.1 joerg static void 4862 1.1 joerg common_jmp_long(struct X86EMU *emu, bool cond) 4863 1.1 joerg { 4864 1.1 joerg int16_t target; 4865 1.1 joerg 4866 1.1 joerg target = (int16_t) fetch_word_imm(emu); 4867 1.1 joerg target += (int16_t) emu->x86.R_IP; 4868 1.1 joerg if (cond) 4869 1.1 joerg emu->x86.R_IP = (uint16_t) target; 4870 1.1 joerg } 4871 1.1 joerg 4872 1.1 joerg static void 4873 1.1 joerg common_set_byte(struct X86EMU *emu, bool cond) 4874 1.1 joerg { 4875 1.1 joerg uint32_t destoffset; 4876 1.1 joerg uint8_t *destreg, destval; 4877 1.1 joerg 4878 1.1 joerg fetch_decode_modrm(emu); 4879 1.1 joerg destval = cond ? 0x01 : 0x00; 4880 1.1 joerg if (emu->cur_mod != 3) { 4881 1.1 joerg destoffset = decode_rl_address(emu); 4882 1.1 joerg store_data_byte(emu, destoffset, destval); 4883 1.1 joerg } else { 4884 1.1 joerg destreg = decode_rl_byte_register(emu); 4885 1.1 joerg *destreg = destval; 4886 1.1 joerg } 4887 1.1 joerg } 4888 1.1 joerg 4889 1.1 joerg static void 4890 1.1 joerg common_bitstring32(struct X86EMU *emu, int op) 4891 1.1 joerg { 4892 1.1 joerg int bit; 4893 1.1 joerg uint32_t srcval, *shiftreg, mask; 4894 1.1 joerg 4895 1.1 joerg fetch_decode_modrm(emu); 4896 1.1 joerg shiftreg = decode_rh_long_register(emu); 4897 1.1 joerg srcval = decode_and_fetch_long_disp(emu, (int16_t) *shiftreg >> 5); 4898 1.1 joerg bit = *shiftreg & 0x1F; 4899 1.1 joerg mask = 0x1 << bit; 4900 1.1 joerg CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 4901 1.1 joerg 4902 1.1 joerg switch (op) { 4903 1.1 joerg case 0: 4904 1.1 joerg break; 4905 1.1 joerg case 1: 4906 1.1 joerg write_back_long(emu, srcval | mask); 4907 1.1 joerg break; 4908 1.1 joerg case 2: 4909 1.1 joerg write_back_long(emu, srcval & ~mask); 4910 1.1 joerg break; 4911 1.1 joerg case 3: 4912 1.1 joerg write_back_long(emu, srcval ^ mask); 4913 1.1 joerg break; 4914 1.1 joerg } 4915 1.1 joerg } 4916 1.1 joerg 4917 1.1 joerg static void 4918 1.1 joerg common_bitstring16(struct X86EMU *emu, int op) 4919 1.1 joerg { 4920 1.1 joerg int bit; 4921 1.1 joerg uint16_t srcval, *shiftreg, mask; 4922 1.1 joerg 4923 1.1 joerg fetch_decode_modrm(emu); 4924 1.1 joerg shiftreg = decode_rh_word_register(emu); 4925 1.1 joerg srcval = decode_and_fetch_word_disp(emu, (int16_t) *shiftreg >> 4); 4926 1.1 joerg bit = *shiftreg & 0xF; 4927 1.1 joerg mask = 0x1 << bit; 4928 1.1 joerg CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 4929 1.1 joerg 4930 1.1 joerg switch (op) { 4931 1.1 joerg case 0: 4932 1.1 joerg break; 4933 1.1 joerg case 1: 4934 1.1 joerg write_back_word(emu, srcval | mask); 4935 1.1 joerg break; 4936 1.1 joerg case 2: 4937 1.1 joerg write_back_word(emu, srcval & ~mask); 4938 1.1 joerg break; 4939 1.1 joerg case 3: 4940 1.1 joerg write_back_word(emu, srcval ^ mask); 4941 1.1 joerg break; 4942 1.1 joerg } 4943 1.1 joerg } 4944 1.1 joerg 4945 1.1 joerg static void 4946 1.1 joerg common_bitstring(struct X86EMU *emu, int op) 4947 1.1 joerg { 4948 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 4949 1.1 joerg common_bitstring32(emu, op); 4950 1.1 joerg else 4951 1.1 joerg common_bitstring16(emu, op); 4952 1.1 joerg } 4953 1.1 joerg 4954 1.1 joerg static void 4955 1.1 joerg common_bitsearch32(struct X86EMU *emu, int diff) 4956 1.1 joerg { 4957 1.1 joerg uint32_t srcval, *dstreg; 4958 1.1 joerg 4959 1.1 joerg fetch_decode_modrm(emu); 4960 1.1 joerg dstreg = decode_rh_long_register(emu); 4961 1.1 joerg srcval = decode_and_fetch_long(emu); 4962 1.1 joerg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 4963 1.1 joerg for (*dstreg = 0; *dstreg < 32; *dstreg += diff) { 4964 1.1 joerg if ((srcval >> *dstreg) & 1) 4965 1.1 joerg break; 4966 1.1 joerg } 4967 1.1 joerg } 4968 1.1 joerg 4969 1.1 joerg static void 4970 1.1 joerg common_bitsearch16(struct X86EMU *emu, int diff) 4971 1.1 joerg { 4972 1.1 joerg uint16_t srcval, *dstreg; 4973 1.1 joerg 4974 1.1 joerg fetch_decode_modrm(emu); 4975 1.1 joerg dstreg = decode_rh_word_register(emu); 4976 1.1 joerg srcval = decode_and_fetch_word(emu); 4977 1.1 joerg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 4978 1.1 joerg for (*dstreg = 0; *dstreg < 16; *dstreg += diff) { 4979 1.1 joerg if ((srcval >> *dstreg) & 1) 4980 1.1 joerg break; 4981 1.1 joerg } 4982 1.1 joerg } 4983 1.1 joerg 4984 1.1 joerg static void 4985 1.1 joerg common_bitsearch(struct X86EMU *emu, int diff) 4986 1.1 joerg { 4987 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 4988 1.1 joerg common_bitsearch32(emu, diff); 4989 1.1 joerg else 4990 1.1 joerg common_bitsearch16(emu, diff); 4991 1.1 joerg } 4992 1.1 joerg 4993 1.1 joerg static void 4994 1.1 joerg common_shift32(struct X86EMU *emu, bool shift_left, bool use_cl) 4995 1.1 joerg { 4996 1.1 joerg uint8_t shift; 4997 1.1 joerg uint32_t destval, *shiftreg; 4998 1.1 joerg 4999 1.1 joerg fetch_decode_modrm(emu); 5000 1.1 joerg shiftreg = decode_rh_long_register(emu); 5001 1.1 joerg if (use_cl) { 5002 1.1 joerg destval = decode_and_fetch_long(emu); 5003 1.1 joerg shift = emu->x86.R_CL; 5004 1.1 joerg } else { 5005 1.1 joerg destval = decode_and_fetch_long_imm8(emu, &shift); 5006 1.1 joerg } 5007 1.1 joerg if (shift_left) 5008 1.1 joerg destval = shld_long(emu, destval, *shiftreg, shift); 5009 1.1 joerg else 5010 1.1 joerg destval = shrd_long(emu, destval, *shiftreg, shift); 5011 1.1 joerg write_back_long(emu, destval); 5012 1.1 joerg } 5013 1.1 joerg 5014 1.1 joerg static void 5015 1.1 joerg common_shift16(struct X86EMU *emu, bool shift_left, bool use_cl) 5016 1.1 joerg { 5017 1.1 joerg uint8_t shift; 5018 1.1 joerg uint16_t destval, *shiftreg; 5019 1.1 joerg 5020 1.1 joerg fetch_decode_modrm(emu); 5021 1.1 joerg shiftreg = decode_rh_word_register(emu); 5022 1.1 joerg if (use_cl) { 5023 1.1 joerg destval = decode_and_fetch_word(emu); 5024 1.1 joerg shift = emu->x86.R_CL; 5025 1.1 joerg } else { 5026 1.1 joerg destval = decode_and_fetch_word_imm8(emu, &shift); 5027 1.1 joerg } 5028 1.1 joerg if (shift_left) 5029 1.1 joerg destval = shld_word(emu, destval, *shiftreg, shift); 5030 1.1 joerg else 5031 1.1 joerg destval = shrd_word(emu, destval, *shiftreg, shift); 5032 1.1 joerg write_back_word(emu, destval); 5033 1.1 joerg } 5034 1.1 joerg 5035 1.1 joerg static void 5036 1.1 joerg common_shift(struct X86EMU *emu, bool shift_left, bool use_cl) 5037 1.1 joerg { 5038 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5039 1.1 joerg common_shift32(emu, shift_left, use_cl); 5040 1.1 joerg else 5041 1.1 joerg common_shift16(emu, shift_left, use_cl); 5042 1.1 joerg } 5043 1.1 joerg 5044 1.1 joerg /*----------------------------- Implementation ----------------------------*/ 5045 1.1 joerg #define xorl(a,b) ((a) && !(b)) || (!(a) && (b)) 5046 1.1 joerg 5047 1.1 joerg /**************************************************************************** 5048 1.1 joerg REMARKS: 5049 1.1 joerg Handles opcode 0x0f,0x31 5050 1.1 joerg ****************************************************************************/ 5051 1.1 joerg static void 5052 1.1 joerg x86emuOp2_rdtsc(struct X86EMU *emu) 5053 1.1 joerg { 5054 1.1 joerg emu->x86.R_EAX = emu->cur_cycles & 0xffffffff; 5055 1.1 joerg emu->x86.R_EDX = emu->cur_cycles >> 32; 5056 1.1 joerg } 5057 1.1 joerg /**************************************************************************** 5058 1.1 joerg REMARKS: 5059 1.1 joerg Handles opcode 0x0f,0xa0 5060 1.1 joerg ****************************************************************************/ 5061 1.1 joerg static void 5062 1.1 joerg x86emuOp2_push_FS(struct X86EMU *emu) 5063 1.1 joerg { 5064 1.1 joerg push_word(emu, emu->x86.R_FS); 5065 1.1 joerg } 5066 1.1 joerg /**************************************************************************** 5067 1.1 joerg REMARKS: 5068 1.1 joerg Handles opcode 0x0f,0xa1 5069 1.1 joerg ****************************************************************************/ 5070 1.1 joerg static void 5071 1.1 joerg x86emuOp2_pop_FS(struct X86EMU *emu) 5072 1.1 joerg { 5073 1.1 joerg emu->x86.R_FS = pop_word(emu); 5074 1.1 joerg } 5075 1.1 joerg /**************************************************************************** 5076 1.1 joerg REMARKS: 5077 1.4 jmcneill Handles opcode 0x0f,0xa1 5078 1.4 jmcneill ****************************************************************************/ 5079 1.4 jmcneill #if defined(__i386__) || defined(__amd64__) 5080 1.4 jmcneill static void 5081 1.4 jmcneill hw_cpuid(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) 5082 1.4 jmcneill { 5083 1.4 jmcneill __asm__ __volatile__("cpuid" 5084 1.4 jmcneill : "=a" (*a), "=b" (*b), 5085 1.4 jmcneill "=c" (*c), "=d" (*d) 5086 1.4 jmcneill : "a" (*a), "c" (*c) 5087 1.4 jmcneill : "cc"); 5088 1.4 jmcneill } 5089 1.4 jmcneill #endif 5090 1.4 jmcneill static void 5091 1.4 jmcneill x86emuOp2_cpuid(struct X86EMU *emu) 5092 1.4 jmcneill { 5093 1.4 jmcneill #if defined(__i386__) || defined(__amd64__) 5094 1.4 jmcneill hw_cpuid(&emu->x86.R_EAX, &emu->x86.R_EBX, &emu->x86.R_ECX, 5095 1.4 jmcneill &emu->x86.R_EDX); 5096 1.4 jmcneill #endif 5097 1.4 jmcneill switch (emu->x86.R_EAX) { 5098 1.4 jmcneill case 0: 5099 1.4 jmcneill emu->x86.R_EAX = 1; 5100 1.4 jmcneill #if !defined(__i386__) && !defined(__amd64__) 5101 1.4 jmcneill /* "GenuineIntel" */ 5102 1.4 jmcneill emu->x86.R_EBX = 0x756e6547; 5103 1.4 jmcneill emu->x86.R_EDX = 0x49656e69; 5104 1.4 jmcneill emu->x86.R_ECX = 0x6c65746e; 5105 1.4 jmcneill #endif 5106 1.4 jmcneill break; 5107 1.4 jmcneill case 1: 5108 1.4 jmcneill #if !defined(__i386__) && !defined(__amd64__) 5109 1.4 jmcneill emu->x86.R_EAX = 0x00000480; 5110 1.4 jmcneill emu->x86.R_EBX = emu->x86.R_ECX = 0; 5111 1.4 jmcneill emu->x86.R_EDX = 0x00000002; 5112 1.4 jmcneill #else 5113 1.4 jmcneill emu->x86.R_EDX &= 0x00000012; 5114 1.4 jmcneill #endif 5115 1.4 jmcneill break; 5116 1.4 jmcneill default: 5117 1.4 jmcneill emu->x86.R_EAX = emu->x86.R_EBX = emu->x86.R_ECX = 5118 1.4 jmcneill emu->x86.R_EDX = 0; 5119 1.4 jmcneill break; 5120 1.4 jmcneill } 5121 1.4 jmcneill } 5122 1.4 jmcneill /**************************************************************************** 5123 1.4 jmcneill REMARKS: 5124 1.1 joerg Handles opcode 0x0f,0xa3 5125 1.1 joerg ****************************************************************************/ 5126 1.1 joerg static void 5127 1.1 joerg x86emuOp2_bt_R(struct X86EMU *emu) 5128 1.1 joerg { 5129 1.1 joerg common_bitstring(emu, 0); 5130 1.1 joerg } 5131 1.1 joerg /**************************************************************************** 5132 1.1 joerg REMARKS: 5133 1.1 joerg Handles opcode 0x0f,0xa4 5134 1.1 joerg ****************************************************************************/ 5135 1.1 joerg static void 5136 1.1 joerg x86emuOp2_shld_IMM(struct X86EMU *emu) 5137 1.1 joerg { 5138 1.1 joerg common_shift(emu, true, false); 5139 1.1 joerg } 5140 1.1 joerg /**************************************************************************** 5141 1.1 joerg REMARKS: 5142 1.1 joerg Handles opcode 0x0f,0xa5 5143 1.1 joerg ****************************************************************************/ 5144 1.1 joerg static void 5145 1.1 joerg x86emuOp2_shld_CL(struct X86EMU *emu) 5146 1.1 joerg { 5147 1.1 joerg common_shift(emu, true, true); 5148 1.1 joerg } 5149 1.1 joerg /**************************************************************************** 5150 1.1 joerg REMARKS: 5151 1.1 joerg Handles opcode 0x0f,0xa8 5152 1.1 joerg ****************************************************************************/ 5153 1.1 joerg static void 5154 1.1 joerg x86emuOp2_push_GS(struct X86EMU *emu) 5155 1.1 joerg { 5156 1.1 joerg push_word(emu, emu->x86.R_GS); 5157 1.1 joerg } 5158 1.1 joerg /**************************************************************************** 5159 1.1 joerg REMARKS: 5160 1.1 joerg Handles opcode 0x0f,0xa9 5161 1.1 joerg ****************************************************************************/ 5162 1.1 joerg static void 5163 1.1 joerg x86emuOp2_pop_GS(struct X86EMU *emu) 5164 1.1 joerg { 5165 1.1 joerg emu->x86.R_GS = pop_word(emu); 5166 1.1 joerg } 5167 1.1 joerg /**************************************************************************** 5168 1.1 joerg REMARKS: 5169 1.1 joerg Handles opcode 0x0f,0xab 5170 1.1 joerg ****************************************************************************/ 5171 1.1 joerg static void 5172 1.1 joerg x86emuOp2_bts_R(struct X86EMU *emu) 5173 1.1 joerg { 5174 1.1 joerg common_bitstring(emu, 1); 5175 1.1 joerg } 5176 1.1 joerg /**************************************************************************** 5177 1.1 joerg REMARKS: 5178 1.1 joerg Handles opcode 0x0f,0xac 5179 1.1 joerg ****************************************************************************/ 5180 1.1 joerg static void 5181 1.1 joerg x86emuOp2_shrd_IMM(struct X86EMU *emu) 5182 1.1 joerg { 5183 1.1 joerg common_shift(emu, false, false); 5184 1.1 joerg } 5185 1.1 joerg /**************************************************************************** 5186 1.1 joerg REMARKS: 5187 1.1 joerg Handles opcode 0x0f,0xad 5188 1.1 joerg ****************************************************************************/ 5189 1.1 joerg static void 5190 1.1 joerg x86emuOp2_shrd_CL(struct X86EMU *emu) 5191 1.1 joerg { 5192 1.1 joerg common_shift(emu, false, true); 5193 1.1 joerg } 5194 1.1 joerg /**************************************************************************** 5195 1.1 joerg REMARKS: 5196 1.1 joerg Handles opcode 0x0f,0xaf 5197 1.1 joerg ****************************************************************************/ 5198 1.1 joerg static void 5199 1.1 joerg x86emuOp2_32_imul_R_RM(struct X86EMU *emu) 5200 1.1 joerg { 5201 1.1 joerg uint32_t *destreg, srcval; 5202 1.1 joerg uint64_t res; 5203 1.1 joerg 5204 1.1 joerg fetch_decode_modrm(emu); 5205 1.1 joerg destreg = decode_rh_long_register(emu); 5206 1.1 joerg srcval = decode_and_fetch_long(emu); 5207 1.1 joerg res = (int32_t) *destreg * (int32_t)srcval; 5208 1.1 joerg if (res > 0xffffffff) { 5209 1.1 joerg SET_FLAG(F_CF); 5210 1.1 joerg SET_FLAG(F_OF); 5211 1.1 joerg } else { 5212 1.1 joerg CLEAR_FLAG(F_CF); 5213 1.1 joerg CLEAR_FLAG(F_OF); 5214 1.1 joerg } 5215 1.1 joerg *destreg = (uint32_t) res; 5216 1.1 joerg } 5217 1.1 joerg 5218 1.1 joerg static void 5219 1.1 joerg x86emuOp2_16_imul_R_RM(struct X86EMU *emu) 5220 1.1 joerg { 5221 1.1 joerg uint16_t *destreg, srcval; 5222 1.1 joerg uint32_t res; 5223 1.1 joerg 5224 1.1 joerg fetch_decode_modrm(emu); 5225 1.1 joerg destreg = decode_rh_word_register(emu); 5226 1.1 joerg srcval = decode_and_fetch_word(emu); 5227 1.1 joerg res = (int16_t) * destreg * (int16_t)srcval; 5228 1.1 joerg if (res > 0xFFFF) { 5229 1.1 joerg SET_FLAG(F_CF); 5230 1.1 joerg SET_FLAG(F_OF); 5231 1.1 joerg } else { 5232 1.1 joerg CLEAR_FLAG(F_CF); 5233 1.1 joerg CLEAR_FLAG(F_OF); 5234 1.1 joerg } 5235 1.1 joerg *destreg = (uint16_t) res; 5236 1.1 joerg } 5237 1.1 joerg 5238 1.1 joerg static void 5239 1.1 joerg x86emuOp2_imul_R_RM(struct X86EMU *emu) 5240 1.1 joerg { 5241 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5242 1.1 joerg x86emuOp2_32_imul_R_RM(emu); 5243 1.1 joerg else 5244 1.1 joerg x86emuOp2_16_imul_R_RM(emu); 5245 1.1 joerg } 5246 1.1 joerg /**************************************************************************** 5247 1.1 joerg REMARKS: 5248 1.1 joerg Handles opcode 0x0f,0xb2 5249 1.1 joerg ****************************************************************************/ 5250 1.1 joerg static void 5251 1.1 joerg x86emuOp2_lss_R_IMM(struct X86EMU *emu) 5252 1.1 joerg { 5253 1.1 joerg common_load_far_pointer(emu, &emu->x86.R_SS); 5254 1.1 joerg } 5255 1.1 joerg /**************************************************************************** 5256 1.1 joerg REMARKS: 5257 1.1 joerg Handles opcode 0x0f,0xb3 5258 1.1 joerg ****************************************************************************/ 5259 1.1 joerg static void 5260 1.1 joerg x86emuOp2_btr_R(struct X86EMU *emu) 5261 1.1 joerg { 5262 1.1 joerg common_bitstring(emu, 2); 5263 1.1 joerg } 5264 1.1 joerg /**************************************************************************** 5265 1.1 joerg REMARKS: 5266 1.1 joerg Handles opcode 0x0f,0xb4 5267 1.1 joerg ****************************************************************************/ 5268 1.1 joerg static void 5269 1.1 joerg x86emuOp2_lfs_R_IMM(struct X86EMU *emu) 5270 1.1 joerg { 5271 1.1 joerg common_load_far_pointer(emu, &emu->x86.R_FS); 5272 1.1 joerg } 5273 1.1 joerg /**************************************************************************** 5274 1.1 joerg REMARKS: 5275 1.1 joerg Handles opcode 0x0f,0xb5 5276 1.1 joerg ****************************************************************************/ 5277 1.1 joerg static void 5278 1.1 joerg x86emuOp2_lgs_R_IMM(struct X86EMU *emu) 5279 1.1 joerg { 5280 1.1 joerg common_load_far_pointer(emu, &emu->x86.R_GS); 5281 1.1 joerg } 5282 1.1 joerg /**************************************************************************** 5283 1.1 joerg REMARKS: 5284 1.1 joerg Handles opcode 0x0f,0xb6 5285 1.1 joerg ****************************************************************************/ 5286 1.1 joerg static void 5287 1.1 joerg x86emuOp2_32_movzx_byte_R_RM(struct X86EMU *emu) 5288 1.1 joerg { 5289 1.1 joerg uint32_t *destreg; 5290 1.1 joerg 5291 1.1 joerg fetch_decode_modrm(emu); 5292 1.1 joerg destreg = decode_rh_long_register(emu); 5293 1.1 joerg *destreg = decode_and_fetch_byte(emu); 5294 1.1 joerg } 5295 1.1 joerg 5296 1.1 joerg static void 5297 1.1 joerg x86emuOp2_16_movzx_byte_R_RM(struct X86EMU *emu) 5298 1.1 joerg { 5299 1.1 joerg uint16_t *destreg; 5300 1.1 joerg 5301 1.1 joerg fetch_decode_modrm(emu); 5302 1.1 joerg destreg = decode_rh_word_register(emu); 5303 1.1 joerg *destreg = decode_and_fetch_byte(emu); 5304 1.1 joerg } 5305 1.1 joerg 5306 1.1 joerg static void 5307 1.1 joerg x86emuOp2_movzx_byte_R_RM(struct X86EMU *emu) 5308 1.1 joerg { 5309 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5310 1.1 joerg x86emuOp2_32_movzx_byte_R_RM(emu); 5311 1.1 joerg else 5312 1.1 joerg x86emuOp2_16_movzx_byte_R_RM(emu); 5313 1.1 joerg } 5314 1.1 joerg /**************************************************************************** 5315 1.1 joerg REMARKS: 5316 1.1 joerg Handles opcode 0x0f,0xb7 5317 1.1 joerg ****************************************************************************/ 5318 1.1 joerg static void 5319 1.1 joerg x86emuOp2_movzx_word_R_RM(struct X86EMU *emu) 5320 1.1 joerg { 5321 1.1 joerg uint32_t *destreg; 5322 1.1 joerg 5323 1.1 joerg fetch_decode_modrm(emu); 5324 1.1 joerg destreg = decode_rh_long_register(emu); 5325 1.1 joerg *destreg = decode_and_fetch_word(emu); 5326 1.1 joerg } 5327 1.1 joerg /**************************************************************************** 5328 1.1 joerg REMARKS: 5329 1.1 joerg Handles opcode 0x0f,0xba 5330 1.1 joerg ****************************************************************************/ 5331 1.1 joerg static void 5332 1.1 joerg x86emuOp2_32_btX_I(struct X86EMU *emu) 5333 1.1 joerg { 5334 1.1 joerg int bit; 5335 1.1 joerg uint32_t srcval, mask; 5336 1.1 joerg uint8_t shift; 5337 1.1 joerg 5338 1.1 joerg fetch_decode_modrm(emu); 5339 1.1 joerg if (emu->cur_rh < 4) 5340 1.1 joerg X86EMU_halt_sys(emu); 5341 1.1 joerg 5342 1.1 joerg srcval = decode_and_fetch_long_imm8(emu, &shift); 5343 1.1 joerg bit = shift & 0x1F; 5344 1.1 joerg mask = (0x1 << bit); 5345 1.1 joerg 5346 1.1 joerg switch (emu->cur_rh) { 5347 1.1 joerg case 5: 5348 1.1 joerg write_back_long(emu, srcval | mask); 5349 1.1 joerg break; 5350 1.1 joerg case 6: 5351 1.1 joerg write_back_long(emu, srcval & ~mask); 5352 1.1 joerg break; 5353 1.1 joerg case 7: 5354 1.1 joerg write_back_long(emu, srcval ^ mask); 5355 1.1 joerg break; 5356 1.1 joerg } 5357 1.1 joerg CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 5358 1.1 joerg } 5359 1.1 joerg 5360 1.1 joerg static void 5361 1.1 joerg x86emuOp2_16_btX_I(struct X86EMU *emu) 5362 1.1 joerg { 5363 1.1 joerg int bit; 5364 1.1 joerg 5365 1.1 joerg uint16_t srcval, mask; 5366 1.1 joerg uint8_t shift; 5367 1.1 joerg 5368 1.1 joerg fetch_decode_modrm(emu); 5369 1.1 joerg if (emu->cur_rh < 4) 5370 1.1 joerg X86EMU_halt_sys(emu); 5371 1.1 joerg 5372 1.1 joerg srcval = decode_and_fetch_word_imm8(emu, &shift); 5373 1.1 joerg bit = shift & 0xF; 5374 1.1 joerg mask = (0x1 << bit); 5375 1.1 joerg switch (emu->cur_rh) { 5376 1.1 joerg case 5: 5377 1.1 joerg write_back_word(emu, srcval | mask); 5378 1.1 joerg break; 5379 1.1 joerg case 6: 5380 1.1 joerg write_back_word(emu, srcval & ~mask); 5381 1.1 joerg break; 5382 1.1 joerg case 7: 5383 1.1 joerg write_back_word(emu, srcval ^ mask); 5384 1.1 joerg break; 5385 1.1 joerg } 5386 1.1 joerg CONDITIONAL_SET_FLAG(srcval & mask, F_CF); 5387 1.1 joerg } 5388 1.1 joerg 5389 1.1 joerg static void 5390 1.1 joerg x86emuOp2_btX_I(struct X86EMU *emu) 5391 1.1 joerg { 5392 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5393 1.1 joerg x86emuOp2_32_btX_I(emu); 5394 1.1 joerg else 5395 1.1 joerg x86emuOp2_16_btX_I(emu); 5396 1.1 joerg } 5397 1.1 joerg /**************************************************************************** 5398 1.1 joerg REMARKS: 5399 1.1 joerg Handles opcode 0x0f,0xbb 5400 1.1 joerg ****************************************************************************/ 5401 1.1 joerg static void 5402 1.1 joerg x86emuOp2_btc_R(struct X86EMU *emu) 5403 1.1 joerg { 5404 1.1 joerg common_bitstring(emu, 3); 5405 1.1 joerg } 5406 1.1 joerg /**************************************************************************** 5407 1.1 joerg REMARKS: 5408 1.1 joerg Handles opcode 0x0f,0xbc 5409 1.1 joerg ****************************************************************************/ 5410 1.1 joerg static void 5411 1.1 joerg x86emuOp2_bsf(struct X86EMU *emu) 5412 1.1 joerg { 5413 1.1 joerg common_bitsearch(emu, +1); 5414 1.1 joerg } 5415 1.1 joerg /**************************************************************************** 5416 1.1 joerg REMARKS: 5417 1.1 joerg Handles opcode 0x0f,0xbd 5418 1.1 joerg ****************************************************************************/ 5419 1.1 joerg static void 5420 1.1 joerg x86emuOp2_bsr(struct X86EMU *emu) 5421 1.1 joerg { 5422 1.1 joerg common_bitsearch(emu, -1); 5423 1.1 joerg } 5424 1.1 joerg /**************************************************************************** 5425 1.1 joerg REMARKS: 5426 1.1 joerg Handles opcode 0x0f,0xbe 5427 1.1 joerg ****************************************************************************/ 5428 1.1 joerg static void 5429 1.1 joerg x86emuOp2_32_movsx_byte_R_RM(struct X86EMU *emu) 5430 1.1 joerg { 5431 1.1 joerg uint32_t *destreg; 5432 1.1 joerg 5433 1.8 joerg fetch_decode_modrm(emu); 5434 1.1 joerg destreg = decode_rh_long_register(emu); 5435 1.1 joerg *destreg = (int32_t)(int8_t)decode_and_fetch_byte(emu); 5436 1.1 joerg } 5437 1.1 joerg 5438 1.1 joerg static void 5439 1.1 joerg x86emuOp2_16_movsx_byte_R_RM(struct X86EMU *emu) 5440 1.1 joerg { 5441 1.1 joerg uint16_t *destreg; 5442 1.1 joerg 5443 1.1 joerg fetch_decode_modrm(emu); 5444 1.1 joerg destreg = decode_rh_word_register(emu); 5445 1.1 joerg *destreg = (int16_t)(int8_t)decode_and_fetch_byte(emu); 5446 1.1 joerg } 5447 1.1 joerg 5448 1.1 joerg static void 5449 1.1 joerg x86emuOp2_movsx_byte_R_RM(struct X86EMU *emu) 5450 1.1 joerg { 5451 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) 5452 1.1 joerg x86emuOp2_32_movsx_byte_R_RM(emu); 5453 1.1 joerg else 5454 1.1 joerg x86emuOp2_16_movsx_byte_R_RM(emu); 5455 1.1 joerg } 5456 1.1 joerg /**************************************************************************** 5457 1.1 joerg REMARKS: 5458 1.1 joerg Handles opcode 0x0f,0xbf 5459 1.1 joerg ****************************************************************************/ 5460 1.1 joerg static void 5461 1.1 joerg x86emuOp2_movsx_word_R_RM(struct X86EMU *emu) 5462 1.1 joerg { 5463 1.1 joerg uint32_t *destreg; 5464 1.1 joerg 5465 1.1 joerg fetch_decode_modrm(emu); 5466 1.1 joerg destreg = decode_rh_long_register(emu); 5467 1.1 joerg *destreg = (int32_t)(int16_t)decode_and_fetch_word(emu); 5468 1.1 joerg } 5469 1.1 joerg 5470 1.1 joerg static void 5471 1.1 joerg X86EMU_exec_two_byte(struct X86EMU * emu) 5472 1.1 joerg { 5473 1.1 joerg uint8_t op2; 5474 1.1 joerg 5475 1.1 joerg op2 = fetch_byte_imm(emu); 5476 1.1 joerg 5477 1.1 joerg switch (op2) { 5478 1.1 joerg /* 0x00 Group F (ring 0 PM) */ 5479 1.1 joerg /* 0x01 Group G (ring 0 PM) */ 5480 1.1 joerg /* 0x02 lar (ring 0 PM) */ 5481 1.1 joerg /* 0x03 lsl (ring 0 PM) */ 5482 1.1 joerg /* 0x05 loadall (undocumented) */ 5483 1.1 joerg /* 0x06 clts (ring 0 PM) */ 5484 1.1 joerg /* 0x07 loadall (undocumented) */ 5485 1.1 joerg /* 0x08 invd (ring 0 PM) */ 5486 1.1 joerg /* 0x09 wbinvd (ring 0 PM) */ 5487 1.1 joerg 5488 1.1 joerg /* 0x20 mov reg32(op2); break;creg (ring 0 PM) */ 5489 1.1 joerg /* 0x21 mov reg32(op2); break;dreg (ring 0 PM) */ 5490 1.1 joerg /* 0x22 mov creg(op2); break;reg32 (ring 0 PM) */ 5491 1.1 joerg /* 0x23 mov dreg(op2); break;reg32 (ring 0 PM) */ 5492 1.1 joerg /* 0x24 mov reg32(op2); break;treg (ring 0 PM) */ 5493 1.1 joerg /* 0x26 mov treg(op2); break;reg32 (ring 0 PM) */ 5494 1.1 joerg 5495 1.1 joerg case 0x31: 5496 1.1 joerg x86emuOp2_rdtsc(emu); 5497 1.1 joerg break; 5498 1.1 joerg 5499 1.1 joerg case 0x80: 5500 1.1 joerg common_jmp_long(emu, ACCESS_FLAG(F_OF)); 5501 1.1 joerg break; 5502 1.1 joerg case 0x81: 5503 1.1 joerg common_jmp_long(emu, !ACCESS_FLAG(F_OF)); 5504 1.1 joerg break; 5505 1.1 joerg case 0x82: 5506 1.1 joerg common_jmp_long(emu, ACCESS_FLAG(F_CF)); 5507 1.1 joerg break; 5508 1.1 joerg case 0x83: 5509 1.1 joerg common_jmp_long(emu, !ACCESS_FLAG(F_CF)); 5510 1.1 joerg break; 5511 1.1 joerg case 0x84: 5512 1.1 joerg common_jmp_long(emu, ACCESS_FLAG(F_ZF)); 5513 1.1 joerg break; 5514 1.1 joerg case 0x85: 5515 1.1 joerg common_jmp_long(emu, !ACCESS_FLAG(F_ZF)); 5516 1.1 joerg break; 5517 1.1 joerg case 0x86: 5518 1.1 joerg common_jmp_long(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); 5519 1.1 joerg break; 5520 1.1 joerg case 0x87: 5521 1.1 joerg common_jmp_long(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))); 5522 1.1 joerg break; 5523 1.1 joerg case 0x88: 5524 1.1 joerg common_jmp_long(emu, ACCESS_FLAG(F_SF)); 5525 1.1 joerg break; 5526 1.1 joerg case 0x89: 5527 1.1 joerg common_jmp_long(emu, !ACCESS_FLAG(F_SF)); 5528 1.1 joerg break; 5529 1.1 joerg case 0x8a: 5530 1.1 joerg common_jmp_long(emu, ACCESS_FLAG(F_PF)); 5531 1.1 joerg break; 5532 1.1 joerg case 0x8b: 5533 1.1 joerg common_jmp_long(emu, !ACCESS_FLAG(F_PF)); 5534 1.1 joerg break; 5535 1.1 joerg case 0x8c: 5536 1.1 joerg common_jmp_long(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))); 5537 1.1 joerg break; 5538 1.1 joerg case 0x8d: 5539 1.1 joerg common_jmp_long(emu, !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)))); 5540 1.1 joerg break; 5541 1.1 joerg case 0x8e: 5542 1.1 joerg common_jmp_long(emu, 5543 1.1 joerg (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF))); 5544 1.1 joerg break; 5545 1.1 joerg case 0x8f: 5546 1.1 joerg common_jmp_long(emu, 5547 1.1 joerg !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF))); 5548 1.1 joerg break; 5549 1.1 joerg 5550 1.1 joerg case 0x90: 5551 1.1 joerg common_set_byte(emu, ACCESS_FLAG(F_OF)); 5552 1.1 joerg break; 5553 1.1 joerg case 0x91: 5554 1.1 joerg common_set_byte(emu, !ACCESS_FLAG(F_OF)); 5555 1.1 joerg break; 5556 1.1 joerg case 0x92: 5557 1.1 joerg common_set_byte(emu, ACCESS_FLAG(F_CF)); 5558 1.1 joerg break; 5559 1.1 joerg case 0x93: 5560 1.1 joerg common_set_byte(emu, !ACCESS_FLAG(F_CF)); 5561 1.1 joerg break; 5562 1.1 joerg case 0x94: 5563 1.1 joerg common_set_byte(emu, ACCESS_FLAG(F_ZF)); 5564 1.1 joerg break; 5565 1.1 joerg case 0x95: 5566 1.1 joerg common_set_byte(emu, !ACCESS_FLAG(F_ZF)); 5567 1.1 joerg break; 5568 1.1 joerg case 0x96: 5569 1.1 joerg common_set_byte(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); 5570 1.1 joerg break; 5571 1.1 joerg case 0x97: 5572 1.1 joerg common_set_byte(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))); 5573 1.1 joerg break; 5574 1.1 joerg case 0x98: 5575 1.1 joerg common_set_byte(emu, ACCESS_FLAG(F_SF)); 5576 1.1 joerg break; 5577 1.1 joerg case 0x99: 5578 1.1 joerg common_set_byte(emu, !ACCESS_FLAG(F_SF)); 5579 1.1 joerg break; 5580 1.1 joerg case 0x9a: 5581 1.1 joerg common_set_byte(emu, ACCESS_FLAG(F_PF)); 5582 1.1 joerg break; 5583 1.1 joerg case 0x9b: 5584 1.1 joerg common_set_byte(emu, !ACCESS_FLAG(F_PF)); 5585 1.1 joerg break; 5586 1.1 joerg case 0x9c: 5587 1.1 joerg common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))); 5588 1.1 joerg break; 5589 1.1 joerg case 0x9d: 5590 1.1 joerg common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))); 5591 1.1 joerg break; 5592 1.1 joerg case 0x9e: 5593 1.1 joerg common_set_byte(emu, 5594 1.1 joerg (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || 5595 1.1 joerg ACCESS_FLAG(F_ZF))); 5596 1.1 joerg break; 5597 1.1 joerg case 0x9f: 5598 1.1 joerg common_set_byte(emu, 5599 1.1 joerg !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || 5600 1.1 joerg ACCESS_FLAG(F_ZF))); 5601 1.1 joerg break; 5602 1.1 joerg 5603 1.1 joerg case 0xa0: 5604 1.1 joerg x86emuOp2_push_FS(emu); 5605 1.1 joerg break; 5606 1.1 joerg case 0xa1: 5607 1.1 joerg x86emuOp2_pop_FS(emu); 5608 1.1 joerg break; 5609 1.4 jmcneill case 0xa2: 5610 1.4 jmcneill x86emuOp2_cpuid(emu); 5611 1.4 jmcneill break; 5612 1.1 joerg case 0xa3: 5613 1.1 joerg x86emuOp2_bt_R(emu); 5614 1.1 joerg break; 5615 1.1 joerg case 0xa4: 5616 1.1 joerg x86emuOp2_shld_IMM(emu); 5617 1.1 joerg break; 5618 1.1 joerg case 0xa5: 5619 1.1 joerg x86emuOp2_shld_CL(emu); 5620 1.1 joerg break; 5621 1.1 joerg case 0xa8: 5622 1.1 joerg x86emuOp2_push_GS(emu); 5623 1.1 joerg break; 5624 1.1 joerg case 0xa9: 5625 1.1 joerg x86emuOp2_pop_GS(emu); 5626 1.1 joerg break; 5627 1.1 joerg case 0xab: 5628 1.1 joerg x86emuOp2_bts_R(emu); 5629 1.1 joerg break; 5630 1.1 joerg case 0xac: 5631 1.1 joerg x86emuOp2_shrd_IMM(emu); 5632 1.1 joerg break; 5633 1.1 joerg case 0xad: 5634 1.1 joerg x86emuOp2_shrd_CL(emu); 5635 1.1 joerg break; 5636 1.1 joerg case 0xaf: 5637 1.1 joerg x86emuOp2_imul_R_RM(emu); 5638 1.1 joerg break; 5639 1.1 joerg 5640 1.1 joerg /* 0xb0 TODO: cmpxchg */ 5641 1.1 joerg /* 0xb1 TODO: cmpxchg */ 5642 1.1 joerg case 0xb2: 5643 1.1 joerg x86emuOp2_lss_R_IMM(emu); 5644 1.1 joerg break; 5645 1.1 joerg case 0xb3: 5646 1.1 joerg x86emuOp2_btr_R(emu); 5647 1.1 joerg break; 5648 1.1 joerg case 0xb4: 5649 1.1 joerg x86emuOp2_lfs_R_IMM(emu); 5650 1.1 joerg break; 5651 1.1 joerg case 0xb5: 5652 1.1 joerg x86emuOp2_lgs_R_IMM(emu); 5653 1.1 joerg break; 5654 1.1 joerg case 0xb6: 5655 1.1 joerg x86emuOp2_movzx_byte_R_RM(emu); 5656 1.1 joerg break; 5657 1.1 joerg case 0xb7: 5658 1.1 joerg x86emuOp2_movzx_word_R_RM(emu); 5659 1.1 joerg break; 5660 1.1 joerg case 0xba: 5661 1.1 joerg x86emuOp2_btX_I(emu); 5662 1.1 joerg break; 5663 1.1 joerg case 0xbb: 5664 1.1 joerg x86emuOp2_btc_R(emu); 5665 1.1 joerg break; 5666 1.1 joerg case 0xbc: 5667 1.1 joerg x86emuOp2_bsf(emu); 5668 1.1 joerg break; 5669 1.1 joerg case 0xbd: 5670 1.1 joerg x86emuOp2_bsr(emu); 5671 1.1 joerg break; 5672 1.1 joerg case 0xbe: 5673 1.1 joerg x86emuOp2_movsx_byte_R_RM(emu); 5674 1.1 joerg break; 5675 1.1 joerg case 0xbf: 5676 1.1 joerg x86emuOp2_movsx_word_R_RM(emu); 5677 1.1 joerg break; 5678 1.1 joerg 5679 1.1 joerg /* 0xc0 TODO: xadd */ 5680 1.1 joerg /* 0xc1 TODO: xadd */ 5681 1.1 joerg /* 0xc8 TODO: bswap */ 5682 1.1 joerg /* 0xc9 TODO: bswap */ 5683 1.1 joerg /* 0xca TODO: bswap */ 5684 1.1 joerg /* 0xcb TODO: bswap */ 5685 1.1 joerg /* 0xcc TODO: bswap */ 5686 1.1 joerg /* 0xcd TODO: bswap */ 5687 1.1 joerg /* 0xce TODO: bswap */ 5688 1.1 joerg /* 0xcf TODO: bswap */ 5689 1.1 joerg 5690 1.1 joerg default: 5691 1.1 joerg X86EMU_halt_sys(emu); 5692 1.1 joerg break; 5693 1.1 joerg } 5694 1.1 joerg } 5695 1.1 joerg 5696 1.1 joerg /* 5697 1.1 joerg * Carry Chain Calculation 5698 1.1 joerg * 5699 1.1 joerg * This represents a somewhat expensive calculation which is 5700 1.1 joerg * apparently required to emulate the setting of the OF and AF flag. 5701 1.1 joerg * The latter is not so important, but the former is. The overflow 5702 1.1 joerg * flag is the XOR of the top two bits of the carry chain for an 5703 1.1 joerg * addition (similar for subtraction). Since we do not want to 5704 1.1 joerg * simulate the addition in a bitwise manner, we try to calculate the 5705 1.1 joerg * carry chain given the two operands and the result. 5706 1.1 joerg * 5707 1.1 joerg * So, given the following table, which represents the addition of two 5708 1.1 joerg * bits, we can derive a formula for the carry chain. 5709 1.1 joerg * 5710 1.1 joerg * a b cin r cout 5711 1.1 joerg * 0 0 0 0 0 5712 1.1 joerg * 0 0 1 1 0 5713 1.1 joerg * 0 1 0 1 0 5714 1.1 joerg * 0 1 1 0 1 5715 1.1 joerg * 1 0 0 1 0 5716 1.1 joerg * 1 0 1 0 1 5717 1.1 joerg * 1 1 0 0 1 5718 1.1 joerg * 1 1 1 1 1 5719 1.1 joerg * 5720 1.1 joerg * Construction of table for cout: 5721 1.1 joerg * 5722 1.1 joerg * ab 5723 1.1 joerg * r \ 00 01 11 10 5724 1.1 joerg * |------------------ 5725 1.1 joerg * 0 | 0 1 1 1 5726 1.1 joerg * 1 | 0 0 1 0 5727 1.1 joerg * 5728 1.1 joerg * By inspection, one gets: cc = ab + r'(a + b) 5729 1.1 joerg * 5730 1.1 joerg * That represents alot of operations, but NO CHOICE.... 5731 1.1 joerg * 5732 1.1 joerg * Borrow Chain Calculation. 5733 1.1 joerg * 5734 1.1 joerg * The following table represents the subtraction of two bits, from 5735 1.1 joerg * which we can derive a formula for the borrow chain. 5736 1.1 joerg * 5737 1.1 joerg * a b bin r bout 5738 1.1 joerg * 0 0 0 0 0 5739 1.1 joerg * 0 0 1 1 1 5740 1.1 joerg * 0 1 0 1 1 5741 1.1 joerg * 0 1 1 0 1 5742 1.1 joerg * 1 0 0 1 0 5743 1.1 joerg * 1 0 1 0 0 5744 1.1 joerg * 1 1 0 0 0 5745 1.1 joerg * 1 1 1 1 1 5746 1.1 joerg * 5747 1.1 joerg * Construction of table for cout: 5748 1.1 joerg * 5749 1.1 joerg * ab 5750 1.1 joerg * r \ 00 01 11 10 5751 1.1 joerg * |------------------ 5752 1.1 joerg * 0 | 0 1 0 0 5753 1.1 joerg * 1 | 1 1 1 0 5754 1.1 joerg * 5755 1.1 joerg * By inspection, one gets: bc = a'b + r(a' + b) 5756 1.1 joerg * 5757 1.1 joerg ****************************************************************************/ 5758 1.1 joerg 5759 1.1 joerg /*------------------------- Global Variables ------------------------------*/ 5760 1.1 joerg 5761 1.1 joerg static uint32_t x86emu_parity_tab[8] = 5762 1.1 joerg { 5763 1.1 joerg 0x96696996, 5764 1.1 joerg 0x69969669, 5765 1.1 joerg 0x69969669, 5766 1.1 joerg 0x96696996, 5767 1.1 joerg 0x69969669, 5768 1.1 joerg 0x96696996, 5769 1.1 joerg 0x96696996, 5770 1.1 joerg 0x69969669, 5771 1.1 joerg }; 5772 1.1 joerg #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0) 5773 1.1 joerg #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1) 5774 1.1 joerg 5775 1.1 joerg /**************************************************************************** 5776 1.1 joerg REMARKS: 5777 1.1 joerg Implements the AAA instruction and side effects. 5778 1.1 joerg ****************************************************************************/ 5779 1.1 joerg static uint16_t 5780 1.1 joerg aaa_word(struct X86EMU *emu, uint16_t d) 5781 1.1 joerg { 5782 1.1 joerg uint16_t res; 5783 1.1 joerg if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { 5784 1.1 joerg d += 0x6; 5785 1.1 joerg d += 0x100; 5786 1.1 joerg SET_FLAG(F_AF); 5787 1.1 joerg SET_FLAG(F_CF); 5788 1.1 joerg } else { 5789 1.1 joerg CLEAR_FLAG(F_CF); 5790 1.1 joerg CLEAR_FLAG(F_AF); 5791 1.1 joerg } 5792 1.1 joerg res = (uint16_t) (d & 0xFF0F); 5793 1.1 joerg CLEAR_FLAG(F_SF); 5794 1.1 joerg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 5795 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5796 1.1 joerg return res; 5797 1.1 joerg } 5798 1.1 joerg /**************************************************************************** 5799 1.1 joerg REMARKS: 5800 1.1 joerg Implements the AAA instruction and side effects. 5801 1.1 joerg ****************************************************************************/ 5802 1.1 joerg static uint16_t 5803 1.1 joerg aas_word(struct X86EMU *emu, uint16_t d) 5804 1.1 joerg { 5805 1.1 joerg uint16_t res; 5806 1.1 joerg if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { 5807 1.1 joerg d -= 0x6; 5808 1.1 joerg d -= 0x100; 5809 1.1 joerg SET_FLAG(F_AF); 5810 1.1 joerg SET_FLAG(F_CF); 5811 1.1 joerg } else { 5812 1.1 joerg CLEAR_FLAG(F_CF); 5813 1.1 joerg CLEAR_FLAG(F_AF); 5814 1.1 joerg } 5815 1.1 joerg res = (uint16_t) (d & 0xFF0F); 5816 1.1 joerg CLEAR_FLAG(F_SF); 5817 1.1 joerg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 5818 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5819 1.1 joerg return res; 5820 1.1 joerg } 5821 1.1 joerg /**************************************************************************** 5822 1.1 joerg REMARKS: 5823 1.1 joerg Implements the AAD instruction and side effects. 5824 1.1 joerg ****************************************************************************/ 5825 1.1 joerg static uint16_t 5826 1.1 joerg aad_word(struct X86EMU *emu, uint16_t d) 5827 1.1 joerg { 5828 1.1 joerg uint16_t l; 5829 1.1 joerg uint8_t hb, lb; 5830 1.1 joerg 5831 1.1 joerg hb = (uint8_t) ((d >> 8) & 0xff); 5832 1.1 joerg lb = (uint8_t) ((d & 0xff)); 5833 1.1 joerg l = (uint16_t) ((lb + 10 * hb) & 0xFF); 5834 1.1 joerg 5835 1.1 joerg CLEAR_FLAG(F_CF); 5836 1.1 joerg CLEAR_FLAG(F_AF); 5837 1.1 joerg CLEAR_FLAG(F_OF); 5838 1.1 joerg CONDITIONAL_SET_FLAG(l & 0x80, F_SF); 5839 1.1 joerg CONDITIONAL_SET_FLAG(l == 0, F_ZF); 5840 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF); 5841 1.1 joerg return l; 5842 1.1 joerg } 5843 1.1 joerg /**************************************************************************** 5844 1.1 joerg REMARKS: 5845 1.1 joerg Implements the AAM instruction and side effects. 5846 1.1 joerg ****************************************************************************/ 5847 1.1 joerg static uint16_t 5848 1.1 joerg aam_word(struct X86EMU *emu, uint8_t d) 5849 1.1 joerg { 5850 1.1 joerg uint16_t h, l; 5851 1.1 joerg 5852 1.1 joerg h = (uint16_t) (d / 10); 5853 1.1 joerg l = (uint16_t) (d % 10); 5854 1.1 joerg l |= (uint16_t) (h << 8); 5855 1.1 joerg 5856 1.1 joerg CLEAR_FLAG(F_CF); 5857 1.1 joerg CLEAR_FLAG(F_AF); 5858 1.1 joerg CLEAR_FLAG(F_OF); 5859 1.1 joerg CONDITIONAL_SET_FLAG(l & 0x80, F_SF); 5860 1.1 joerg CONDITIONAL_SET_FLAG(l == 0, F_ZF); 5861 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF); 5862 1.1 joerg return l; 5863 1.1 joerg } 5864 1.1 joerg /**************************************************************************** 5865 1.1 joerg REMARKS: 5866 1.1 joerg Implements the ADC instruction and side effects. 5867 1.1 joerg ****************************************************************************/ 5868 1.1 joerg static uint8_t 5869 1.1 joerg adc_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 5870 1.1 joerg { 5871 1.1 joerg uint32_t res; /* all operands in native machine order */ 5872 1.1 joerg uint32_t cc; 5873 1.1 joerg 5874 1.1 joerg if (ACCESS_FLAG(F_CF)) 5875 1.1 joerg res = 1 + d + s; 5876 1.1 joerg else 5877 1.1 joerg res = d + s; 5878 1.1 joerg 5879 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x100, F_CF); 5880 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 5881 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 5882 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5883 1.1 joerg 5884 1.1 joerg /* calculate the carry chain SEE NOTE AT TOP. */ 5885 1.1 joerg cc = (s & d) | ((~res) & (s | d)); 5886 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 5887 1.1 joerg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 5888 1.1 joerg return (uint8_t) res; 5889 1.1 joerg } 5890 1.1 joerg /**************************************************************************** 5891 1.1 joerg REMARKS: 5892 1.1 joerg Implements the ADC instruction and side effects. 5893 1.1 joerg ****************************************************************************/ 5894 1.1 joerg static uint16_t 5895 1.1 joerg adc_word(struct X86EMU *emu, uint16_t d, uint16_t s) 5896 1.1 joerg { 5897 1.1 joerg uint32_t res; /* all operands in native machine order */ 5898 1.1 joerg uint32_t cc; 5899 1.1 joerg 5900 1.1 joerg if (ACCESS_FLAG(F_CF)) 5901 1.1 joerg res = 1 + d + s; 5902 1.1 joerg else 5903 1.1 joerg res = d + s; 5904 1.1 joerg 5905 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x10000, F_CF); 5906 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 5907 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 5908 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5909 1.1 joerg 5910 1.1 joerg /* calculate the carry chain SEE NOTE AT TOP. */ 5911 1.1 joerg cc = (s & d) | ((~res) & (s | d)); 5912 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 5913 1.1 joerg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 5914 1.1 joerg return (uint16_t) res; 5915 1.1 joerg } 5916 1.1 joerg /**************************************************************************** 5917 1.1 joerg REMARKS: 5918 1.1 joerg Implements the ADC instruction and side effects. 5919 1.1 joerg ****************************************************************************/ 5920 1.1 joerg static uint32_t 5921 1.1 joerg adc_long(struct X86EMU *emu, uint32_t d, uint32_t s) 5922 1.1 joerg { 5923 1.1 joerg uint32_t lo; /* all operands in native machine order */ 5924 1.1 joerg uint32_t hi; 5925 1.1 joerg uint32_t res; 5926 1.1 joerg uint32_t cc; 5927 1.1 joerg 5928 1.1 joerg if (ACCESS_FLAG(F_CF)) { 5929 1.1 joerg lo = 1 + (d & 0xFFFF) + (s & 0xFFFF); 5930 1.1 joerg res = 1 + d + s; 5931 1.1 joerg } else { 5932 1.1 joerg lo = (d & 0xFFFF) + (s & 0xFFFF); 5933 1.1 joerg res = d + s; 5934 1.1 joerg } 5935 1.1 joerg hi = (lo >> 16) + (d >> 16) + (s >> 16); 5936 1.1 joerg 5937 1.1 joerg CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF); 5938 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 5939 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 5940 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5941 1.1 joerg 5942 1.1 joerg /* calculate the carry chain SEE NOTE AT TOP. */ 5943 1.1 joerg cc = (s & d) | ((~res) & (s | d)); 5944 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 5945 1.1 joerg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 5946 1.1 joerg return res; 5947 1.1 joerg } 5948 1.1 joerg /**************************************************************************** 5949 1.1 joerg REMARKS: 5950 1.1 joerg Implements the ADD instruction and side effects. 5951 1.1 joerg ****************************************************************************/ 5952 1.1 joerg static uint8_t 5953 1.1 joerg add_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 5954 1.1 joerg { 5955 1.1 joerg uint32_t res; /* all operands in native machine order */ 5956 1.1 joerg uint32_t cc; 5957 1.1 joerg 5958 1.1 joerg res = d + s; 5959 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x100, F_CF); 5960 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 5961 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 5962 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5963 1.1 joerg 5964 1.1 joerg /* calculate the carry chain SEE NOTE AT TOP. */ 5965 1.1 joerg cc = (s & d) | ((~res) & (s | d)); 5966 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 5967 1.1 joerg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 5968 1.1 joerg return (uint8_t) res; 5969 1.1 joerg } 5970 1.1 joerg /**************************************************************************** 5971 1.1 joerg REMARKS: 5972 1.1 joerg Implements the ADD instruction and side effects. 5973 1.1 joerg ****************************************************************************/ 5974 1.1 joerg static uint16_t 5975 1.1 joerg add_word(struct X86EMU *emu, uint16_t d, uint16_t s) 5976 1.1 joerg { 5977 1.1 joerg uint32_t res; /* all operands in native machine order */ 5978 1.1 joerg uint32_t cc; 5979 1.1 joerg 5980 1.1 joerg res = d + s; 5981 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x10000, F_CF); 5982 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 5983 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 5984 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 5985 1.1 joerg 5986 1.1 joerg /* calculate the carry chain SEE NOTE AT TOP. */ 5987 1.1 joerg cc = (s & d) | ((~res) & (s | d)); 5988 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 5989 1.1 joerg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 5990 1.1 joerg return (uint16_t) res; 5991 1.1 joerg } 5992 1.1 joerg /**************************************************************************** 5993 1.1 joerg REMARKS: 5994 1.1 joerg Implements the ADD instruction and side effects. 5995 1.1 joerg ****************************************************************************/ 5996 1.1 joerg static uint32_t 5997 1.1 joerg add_long(struct X86EMU *emu, uint32_t d, uint32_t s) 5998 1.1 joerg { 5999 1.1 joerg uint32_t lo; /* all operands in native machine order */ 6000 1.1 joerg uint32_t hi; 6001 1.1 joerg uint32_t res; 6002 1.1 joerg uint32_t cc; 6003 1.1 joerg 6004 1.1 joerg lo = (d & 0xFFFF) + (s & 0xFFFF); 6005 1.1 joerg res = d + s; 6006 1.1 joerg hi = (lo >> 16) + (d >> 16) + (s >> 16); 6007 1.1 joerg 6008 1.1 joerg CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF); 6009 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6010 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6011 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6012 1.1 joerg 6013 1.1 joerg /* calculate the carry chain SEE NOTE AT TOP. */ 6014 1.1 joerg cc = (s & d) | ((~res) & (s | d)); 6015 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 6016 1.1 joerg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6017 1.1 joerg 6018 1.1 joerg return res; 6019 1.1 joerg } 6020 1.1 joerg /**************************************************************************** 6021 1.1 joerg REMARKS: 6022 1.1 joerg Implements the AND instruction and side effects. 6023 1.1 joerg ****************************************************************************/ 6024 1.1 joerg static uint8_t 6025 1.1 joerg and_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6026 1.1 joerg { 6027 1.1 joerg uint8_t res; /* all operands in native machine order */ 6028 1.1 joerg 6029 1.1 joerg res = d & s; 6030 1.1 joerg 6031 1.1 joerg /* set the flags */ 6032 1.1 joerg CLEAR_FLAG(F_OF); 6033 1.1 joerg CLEAR_FLAG(F_CF); 6034 1.1 joerg CLEAR_FLAG(F_AF); 6035 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6036 1.1 joerg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6037 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 6038 1.1 joerg return res; 6039 1.1 joerg } 6040 1.1 joerg /**************************************************************************** 6041 1.1 joerg REMARKS: 6042 1.1 joerg Implements the AND instruction and side effects. 6043 1.1 joerg ****************************************************************************/ 6044 1.1 joerg static uint16_t 6045 1.1 joerg and_word(struct X86EMU *emu, uint16_t d, uint16_t s) 6046 1.1 joerg { 6047 1.1 joerg uint16_t res; /* all operands in native machine order */ 6048 1.1 joerg 6049 1.1 joerg res = d & s; 6050 1.1 joerg 6051 1.1 joerg /* set the flags */ 6052 1.1 joerg CLEAR_FLAG(F_OF); 6053 1.1 joerg CLEAR_FLAG(F_CF); 6054 1.1 joerg CLEAR_FLAG(F_AF); 6055 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6056 1.1 joerg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6057 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6058 1.1 joerg return res; 6059 1.1 joerg } 6060 1.1 joerg /**************************************************************************** 6061 1.1 joerg REMARKS: 6062 1.1 joerg Implements the AND instruction and side effects. 6063 1.1 joerg ****************************************************************************/ 6064 1.1 joerg static uint32_t 6065 1.1 joerg and_long(struct X86EMU *emu, uint32_t d, uint32_t s) 6066 1.1 joerg { 6067 1.1 joerg uint32_t res; /* all operands in native machine order */ 6068 1.1 joerg 6069 1.1 joerg res = d & s; 6070 1.1 joerg 6071 1.1 joerg /* set the flags */ 6072 1.1 joerg CLEAR_FLAG(F_OF); 6073 1.1 joerg CLEAR_FLAG(F_CF); 6074 1.1 joerg CLEAR_FLAG(F_AF); 6075 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6076 1.1 joerg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6077 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6078 1.1 joerg return res; 6079 1.1 joerg } 6080 1.1 joerg /**************************************************************************** 6081 1.1 joerg REMARKS: 6082 1.1 joerg Implements the CMP instruction and side effects. 6083 1.1 joerg ****************************************************************************/ 6084 1.1 joerg static uint8_t 6085 1.1 joerg cmp_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6086 1.1 joerg { 6087 1.1 joerg uint32_t res; /* all operands in native machine order */ 6088 1.1 joerg uint32_t bc; 6089 1.1 joerg 6090 1.1 joerg res = d - s; 6091 1.1 joerg CLEAR_FLAG(F_CF); 6092 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6093 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6094 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6095 1.1 joerg 6096 1.1 joerg /* calculate the borrow chain. See note at top */ 6097 1.1 joerg bc = (res & (~d | s)) | (~d & s); 6098 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); 6099 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 6100 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6101 1.1 joerg return d; 6102 1.1 joerg } 6103 1.1 joerg 6104 1.1 joerg static void 6105 1.1 joerg cmp_byte_no_return(struct X86EMU *emu, uint8_t d, uint8_t s) 6106 1.1 joerg { 6107 1.1 joerg cmp_byte(emu, d, s); 6108 1.1 joerg } 6109 1.1 joerg /**************************************************************************** 6110 1.1 joerg REMARKS: 6111 1.1 joerg Implements the CMP instruction and side effects. 6112 1.1 joerg ****************************************************************************/ 6113 1.1 joerg static uint16_t 6114 1.1 joerg cmp_word(struct X86EMU *emu, uint16_t d, uint16_t s) 6115 1.1 joerg { 6116 1.1 joerg uint32_t res; /* all operands in native machine order */ 6117 1.1 joerg uint32_t bc; 6118 1.1 joerg 6119 1.1 joerg res = d - s; 6120 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6121 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6122 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6123 1.1 joerg 6124 1.1 joerg /* calculate the borrow chain. See note at top */ 6125 1.1 joerg bc = (res & (~d | s)) | (~d & s); 6126 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 6127 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 6128 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6129 1.1 joerg return d; 6130 1.1 joerg } 6131 1.1 joerg 6132 1.1 joerg static void 6133 1.1 joerg cmp_word_no_return(struct X86EMU *emu, uint16_t d, uint16_t s) 6134 1.1 joerg { 6135 1.1 joerg cmp_word(emu, d, s); 6136 1.1 joerg } 6137 1.1 joerg /**************************************************************************** 6138 1.1 joerg REMARKS: 6139 1.1 joerg Implements the CMP instruction and side effects. 6140 1.1 joerg ****************************************************************************/ 6141 1.1 joerg static uint32_t 6142 1.1 joerg cmp_long(struct X86EMU *emu, uint32_t d, uint32_t s) 6143 1.1 joerg { 6144 1.1 joerg uint32_t res; /* all operands in native machine order */ 6145 1.1 joerg uint32_t bc; 6146 1.1 joerg 6147 1.1 joerg res = d - s; 6148 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6149 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6150 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6151 1.1 joerg 6152 1.1 joerg /* calculate the borrow chain. See note at top */ 6153 1.1 joerg bc = (res & (~d | s)) | (~d & s); 6154 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 6155 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 6156 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6157 1.1 joerg return d; 6158 1.1 joerg } 6159 1.1 joerg 6160 1.1 joerg static void 6161 1.1 joerg cmp_long_no_return(struct X86EMU *emu, uint32_t d, uint32_t s) 6162 1.1 joerg { 6163 1.1 joerg cmp_long(emu, d, s); 6164 1.1 joerg } 6165 1.1 joerg /**************************************************************************** 6166 1.1 joerg REMARKS: 6167 1.1 joerg Implements the DAA instruction and side effects. 6168 1.1 joerg ****************************************************************************/ 6169 1.1 joerg static uint8_t 6170 1.1 joerg daa_byte(struct X86EMU *emu, uint8_t d) 6171 1.1 joerg { 6172 1.1 joerg uint32_t res = d; 6173 1.1 joerg if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) { 6174 1.1 joerg res += 6; 6175 1.1 joerg SET_FLAG(F_AF); 6176 1.1 joerg } 6177 1.1 joerg if (res > 0x9F || ACCESS_FLAG(F_CF)) { 6178 1.1 joerg res += 0x60; 6179 1.1 joerg SET_FLAG(F_CF); 6180 1.1 joerg } 6181 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6182 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF); 6183 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6184 1.1 joerg return (uint8_t) res; 6185 1.1 joerg } 6186 1.1 joerg /**************************************************************************** 6187 1.1 joerg REMARKS: 6188 1.1 joerg Implements the DAS instruction and side effects. 6189 1.1 joerg ****************************************************************************/ 6190 1.1 joerg static uint8_t 6191 1.1 joerg das_byte(struct X86EMU *emu, uint8_t d) 6192 1.1 joerg { 6193 1.1 joerg if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) { 6194 1.1 joerg d -= 6; 6195 1.1 joerg SET_FLAG(F_AF); 6196 1.1 joerg } 6197 1.1 joerg if (d > 0x9F || ACCESS_FLAG(F_CF)) { 6198 1.1 joerg d -= 0x60; 6199 1.1 joerg SET_FLAG(F_CF); 6200 1.1 joerg } 6201 1.1 joerg CONDITIONAL_SET_FLAG(d & 0x80, F_SF); 6202 1.1 joerg CONDITIONAL_SET_FLAG(d == 0, F_ZF); 6203 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF); 6204 1.1 joerg return d; 6205 1.1 joerg } 6206 1.1 joerg /**************************************************************************** 6207 1.1 joerg REMARKS: 6208 1.1 joerg Implements the DEC instruction and side effects. 6209 1.1 joerg ****************************************************************************/ 6210 1.1 joerg static uint8_t 6211 1.1 joerg dec_byte(struct X86EMU *emu, uint8_t d) 6212 1.1 joerg { 6213 1.1 joerg uint32_t res; /* all operands in native machine order */ 6214 1.1 joerg uint32_t bc; 6215 1.1 joerg 6216 1.1 joerg res = d - 1; 6217 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6218 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6219 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6220 1.1 joerg 6221 1.1 joerg /* calculate the borrow chain. See note at top */ 6222 1.1 joerg /* based on sub_byte, uses s==1. */ 6223 1.1 joerg bc = (res & (~d | 1)) | (~d & 1); 6224 1.1 joerg /* carry flag unchanged */ 6225 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 6226 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6227 1.1 joerg return (uint8_t) res; 6228 1.1 joerg } 6229 1.1 joerg /**************************************************************************** 6230 1.1 joerg REMARKS: 6231 1.1 joerg Implements the DEC instruction and side effects. 6232 1.1 joerg ****************************************************************************/ 6233 1.1 joerg static uint16_t 6234 1.1 joerg dec_word(struct X86EMU *emu, uint16_t d) 6235 1.1 joerg { 6236 1.1 joerg uint32_t res; /* all operands in native machine order */ 6237 1.1 joerg uint32_t bc; 6238 1.1 joerg 6239 1.1 joerg res = d - 1; 6240 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6241 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6242 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6243 1.1 joerg 6244 1.1 joerg /* calculate the borrow chain. See note at top */ 6245 1.1 joerg /* based on the sub_byte routine, with s==1 */ 6246 1.1 joerg bc = (res & (~d | 1)) | (~d & 1); 6247 1.1 joerg /* carry flag unchanged */ 6248 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 6249 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6250 1.1 joerg return (uint16_t) res; 6251 1.1 joerg } 6252 1.1 joerg /**************************************************************************** 6253 1.1 joerg REMARKS: 6254 1.1 joerg Implements the DEC instruction and side effects. 6255 1.1 joerg ****************************************************************************/ 6256 1.1 joerg static uint32_t 6257 1.1 joerg dec_long(struct X86EMU *emu, uint32_t d) 6258 1.1 joerg { 6259 1.1 joerg uint32_t res; /* all operands in native machine order */ 6260 1.1 joerg uint32_t bc; 6261 1.1 joerg 6262 1.1 joerg res = d - 1; 6263 1.1 joerg 6264 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6265 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6266 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6267 1.1 joerg 6268 1.1 joerg /* calculate the borrow chain. See note at top */ 6269 1.1 joerg bc = (res & (~d | 1)) | (~d & 1); 6270 1.1 joerg /* carry flag unchanged */ 6271 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 6272 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6273 1.1 joerg return res; 6274 1.1 joerg } 6275 1.1 joerg /**************************************************************************** 6276 1.1 joerg REMARKS: 6277 1.1 joerg Implements the INC instruction and side effects. 6278 1.1 joerg ****************************************************************************/ 6279 1.1 joerg static uint8_t 6280 1.1 joerg inc_byte(struct X86EMU *emu, uint8_t d) 6281 1.1 joerg { 6282 1.1 joerg uint32_t res; /* all operands in native machine order */ 6283 1.1 joerg uint32_t cc; 6284 1.1 joerg 6285 1.1 joerg res = d + 1; 6286 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6287 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6288 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6289 1.1 joerg 6290 1.1 joerg /* calculate the carry chain SEE NOTE AT TOP. */ 6291 1.1 joerg cc = ((1 & d) | (~res)) & (1 | d); 6292 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); 6293 1.1 joerg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6294 1.1 joerg return (uint8_t) res; 6295 1.1 joerg } 6296 1.1 joerg /**************************************************************************** 6297 1.1 joerg REMARKS: 6298 1.1 joerg Implements the INC instruction and side effects. 6299 1.1 joerg ****************************************************************************/ 6300 1.1 joerg static uint16_t 6301 1.1 joerg inc_word(struct X86EMU *emu, uint16_t d) 6302 1.1 joerg { 6303 1.1 joerg uint32_t res; /* all operands in native machine order */ 6304 1.1 joerg uint32_t cc; 6305 1.1 joerg 6306 1.1 joerg res = d + 1; 6307 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6308 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6309 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6310 1.1 joerg 6311 1.1 joerg /* calculate the carry chain SEE NOTE AT TOP. */ 6312 1.1 joerg cc = (1 & d) | ((~res) & (1 | d)); 6313 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); 6314 1.1 joerg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6315 1.1 joerg return (uint16_t) res; 6316 1.1 joerg } 6317 1.1 joerg /**************************************************************************** 6318 1.1 joerg REMARKS: 6319 1.1 joerg Implements the INC instruction and side effects. 6320 1.1 joerg ****************************************************************************/ 6321 1.1 joerg static uint32_t 6322 1.1 joerg inc_long(struct X86EMU *emu, uint32_t d) 6323 1.1 joerg { 6324 1.1 joerg uint32_t res; /* all operands in native machine order */ 6325 1.1 joerg uint32_t cc; 6326 1.1 joerg 6327 1.1 joerg res = d + 1; 6328 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6329 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6330 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6331 1.1 joerg 6332 1.1 joerg /* calculate the carry chain SEE NOTE AT TOP. */ 6333 1.1 joerg cc = (1 & d) | ((~res) & (1 | d)); 6334 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); 6335 1.1 joerg CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); 6336 1.1 joerg return res; 6337 1.1 joerg } 6338 1.1 joerg /**************************************************************************** 6339 1.1 joerg REMARKS: 6340 1.1 joerg Implements the OR instruction and side effects. 6341 1.1 joerg ****************************************************************************/ 6342 1.1 joerg static uint8_t 6343 1.1 joerg or_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6344 1.1 joerg { 6345 1.1 joerg uint8_t res; /* all operands in native machine order */ 6346 1.1 joerg 6347 1.1 joerg res = d | s; 6348 1.1 joerg CLEAR_FLAG(F_OF); 6349 1.1 joerg CLEAR_FLAG(F_CF); 6350 1.1 joerg CLEAR_FLAG(F_AF); 6351 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6352 1.1 joerg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6353 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 6354 1.1 joerg return res; 6355 1.1 joerg } 6356 1.1 joerg /**************************************************************************** 6357 1.1 joerg REMARKS: 6358 1.1 joerg Implements the OR instruction and side effects. 6359 1.1 joerg ****************************************************************************/ 6360 1.1 joerg static uint16_t 6361 1.1 joerg or_word(struct X86EMU *emu, uint16_t d, uint16_t s) 6362 1.1 joerg { 6363 1.1 joerg uint16_t res; /* all operands in native machine order */ 6364 1.1 joerg 6365 1.1 joerg res = d | s; 6366 1.1 joerg /* set the carry flag to be bit 8 */ 6367 1.1 joerg CLEAR_FLAG(F_OF); 6368 1.1 joerg CLEAR_FLAG(F_CF); 6369 1.1 joerg CLEAR_FLAG(F_AF); 6370 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6371 1.1 joerg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6372 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6373 1.1 joerg return res; 6374 1.1 joerg } 6375 1.1 joerg /**************************************************************************** 6376 1.1 joerg REMARKS: 6377 1.1 joerg Implements the OR instruction and side effects. 6378 1.1 joerg ****************************************************************************/ 6379 1.1 joerg static uint32_t 6380 1.1 joerg or_long(struct X86EMU *emu, uint32_t d, uint32_t s) 6381 1.1 joerg { 6382 1.1 joerg uint32_t res; /* all operands in native machine order */ 6383 1.1 joerg 6384 1.1 joerg res = d | s; 6385 1.1 joerg 6386 1.1 joerg /* set the carry flag to be bit 8 */ 6387 1.1 joerg CLEAR_FLAG(F_OF); 6388 1.1 joerg CLEAR_FLAG(F_CF); 6389 1.1 joerg CLEAR_FLAG(F_AF); 6390 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6391 1.1 joerg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 6392 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6393 1.1 joerg return res; 6394 1.1 joerg } 6395 1.1 joerg /**************************************************************************** 6396 1.1 joerg REMARKS: 6397 1.1 joerg Implements the OR instruction and side effects. 6398 1.1 joerg ****************************************************************************/ 6399 1.1 joerg static uint8_t 6400 1.1 joerg neg_byte(struct X86EMU *emu, uint8_t s) 6401 1.1 joerg { 6402 1.1 joerg uint8_t res; 6403 1.1 joerg uint8_t bc; 6404 1.1 joerg 6405 1.1 joerg CONDITIONAL_SET_FLAG(s != 0, F_CF); 6406 1.1 joerg res = (uint8_t) - s; 6407 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6408 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6409 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 6410 1.1 joerg /* calculate the borrow chain --- modified such that d=0. 6411 1.13 andvar * substituting d=0 into bc= res&(~d|s)|(~d&s); (the one used for 6412 1.1 joerg * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and 6413 1.1 joerg * res&0xfff... == res. Similarly ~d&s == s. So the simplified 6414 1.1 joerg * result is: */ 6415 1.1 joerg bc = res | s; 6416 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 6417 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6418 1.1 joerg return res; 6419 1.1 joerg } 6420 1.1 joerg /**************************************************************************** 6421 1.1 joerg REMARKS: 6422 1.1 joerg Implements the OR instruction and side effects. 6423 1.1 joerg ****************************************************************************/ 6424 1.1 joerg static uint16_t 6425 1.1 joerg neg_word(struct X86EMU *emu, uint16_t s) 6426 1.1 joerg { 6427 1.1 joerg uint16_t res; 6428 1.1 joerg uint16_t bc; 6429 1.1 joerg 6430 1.1 joerg CONDITIONAL_SET_FLAG(s != 0, F_CF); 6431 1.1 joerg res = (uint16_t) - s; 6432 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6433 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6434 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6435 1.1 joerg 6436 1.1 joerg /* calculate the borrow chain --- modified such that d=0. 6437 1.13 andvar * substituting d=0 into bc= res&(~d|s)|(~d&s); (the one used for 6438 1.1 joerg * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and 6439 1.1 joerg * res&0xfff... == res. Similarly ~d&s == s. So the simplified 6440 1.1 joerg * result is: */ 6441 1.1 joerg bc = res | s; 6442 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 6443 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6444 1.1 joerg return res; 6445 1.1 joerg } 6446 1.1 joerg /**************************************************************************** 6447 1.1 joerg REMARKS: 6448 1.1 joerg Implements the OR instruction and side effects. 6449 1.1 joerg ****************************************************************************/ 6450 1.1 joerg static uint32_t 6451 1.1 joerg neg_long(struct X86EMU *emu, uint32_t s) 6452 1.1 joerg { 6453 1.1 joerg uint32_t res; 6454 1.1 joerg uint32_t bc; 6455 1.1 joerg 6456 1.1 joerg CONDITIONAL_SET_FLAG(s != 0, F_CF); 6457 1.1 joerg res = (uint32_t) - s; 6458 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 6459 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 6460 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6461 1.1 joerg 6462 1.1 joerg /* calculate the borrow chain --- modified such that d=0. 6463 1.13 andvar * substituting d=0 into bc= res&(~d|s)|(~d&s); (the one used for 6464 1.1 joerg * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and 6465 1.1 joerg * res&0xfff... == res. Similarly ~d&s == s. So the simplified 6466 1.1 joerg * result is: */ 6467 1.1 joerg bc = res | s; 6468 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 6469 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 6470 1.1 joerg return res; 6471 1.1 joerg } 6472 1.1 joerg /**************************************************************************** 6473 1.1 joerg REMARKS: 6474 1.1 joerg Implements the RCL instruction and side effects. 6475 1.1 joerg ****************************************************************************/ 6476 1.1 joerg static uint8_t 6477 1.1 joerg rcl_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6478 1.1 joerg { 6479 1.1 joerg unsigned int res, cnt, mask, cf; 6480 1.1 joerg 6481 1.1 joerg /* s is the rotate distance. It varies from 0 - 8. */ 6482 1.1 joerg /* have 6483 1.1 joerg * 6484 1.1 joerg * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 6485 1.1 joerg * 6486 1.1 joerg * want to rotate through the carry by "s" bits. We could loop, but 6487 1.1 joerg * that's inefficient. So the width is 9, and we split into three 6488 1.1 joerg * parts: 6489 1.1 joerg * 6490 1.1 joerg * The new carry flag (was B_n) the stuff in B_n-1 .. B_0 the stuff in 6491 1.1 joerg * B_7 .. B_n+1 6492 1.1 joerg * 6493 1.1 joerg * The new rotate is done mod 9, and given this, for a rotation of n bits 6494 1.1 joerg * (mod 9) the new carry flag is then located n bits from the MSB. 6495 1.1 joerg * The low part is then shifted up cnt bits, and the high part is or'd 6496 1.1 joerg * in. Using CAPS for new values, and lowercase for the original 6497 1.1 joerg * values, this can be expressed as: 6498 1.1 joerg * 6499 1.1 joerg * IF n > 0 1) CF <- b_(8-n) 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 6500 1.1 joerg * 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */ 6501 1.1 joerg res = d; 6502 1.1 joerg if ((cnt = s % 9) != 0) { 6503 1.1 joerg /* extract the new CARRY FLAG. */ 6504 1.1 joerg /* CF <- b_(8-n) */ 6505 1.1 joerg cf = (d >> (8 - cnt)) & 0x1; 6506 1.1 joerg 6507 1.1 joerg /* get the low stuff which rotated into the range B_7 .. B_cnt */ 6508 1.1 joerg /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */ 6509 1.1 joerg /* note that the right hand side done by the mask */ 6510 1.1 joerg res = (d << cnt) & 0xff; 6511 1.1 joerg 6512 1.1 joerg /* now the high stuff which rotated around into the positions 6513 1.1 joerg * B_cnt-2 .. B_0 */ 6514 1.1 joerg /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */ 6515 1.1 joerg /* shift it downward, 7-(n-2) = 9-n positions. and mask off 6516 1.1 joerg * the result before or'ing in. */ 6517 1.1 joerg mask = (1 << (cnt - 1)) - 1; 6518 1.1 joerg res |= (d >> (9 - cnt)) & mask; 6519 1.1 joerg 6520 1.1 joerg /* if the carry flag was set, or it in. */ 6521 1.1 joerg if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6522 1.1 joerg /* B_(n-1) <- cf */ 6523 1.1 joerg res |= 1 << (cnt - 1); 6524 1.1 joerg } 6525 1.1 joerg /* set the new carry flag, based on the variable "cf" */ 6526 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 6527 1.1 joerg /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and 6528 1.1 joerg * the most significant bit. Blecck. */ 6529 1.1 joerg /* parenthesized this expression since it appears to be 6530 1.1 joerg * causing OF to be misset */ 6531 1.1 joerg CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)), 6532 1.1 joerg F_OF); 6533 1.1 joerg 6534 1.1 joerg } 6535 1.1 joerg return (uint8_t) res; 6536 1.1 joerg } 6537 1.1 joerg /**************************************************************************** 6538 1.1 joerg REMARKS: 6539 1.1 joerg Implements the RCL instruction and side effects. 6540 1.1 joerg ****************************************************************************/ 6541 1.1 joerg static uint16_t 6542 1.1 joerg rcl_word(struct X86EMU *emu, uint16_t d, uint8_t s) 6543 1.1 joerg { 6544 1.1 joerg unsigned int res, cnt, mask, cf; 6545 1.1 joerg 6546 1.1 joerg res = d; 6547 1.1 joerg if ((cnt = s % 17) != 0) { 6548 1.1 joerg cf = (d >> (16 - cnt)) & 0x1; 6549 1.1 joerg res = (d << cnt) & 0xffff; 6550 1.1 joerg mask = (1 << (cnt - 1)) - 1; 6551 1.1 joerg res |= (d >> (17 - cnt)) & mask; 6552 1.1 joerg if (ACCESS_FLAG(F_CF)) { 6553 1.1 joerg res |= 1 << (cnt - 1); 6554 1.1 joerg } 6555 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 6556 1.1 joerg CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)), 6557 1.1 joerg F_OF); 6558 1.1 joerg } 6559 1.1 joerg return (uint16_t) res; 6560 1.1 joerg } 6561 1.1 joerg /**************************************************************************** 6562 1.1 joerg REMARKS: 6563 1.1 joerg Implements the RCL instruction and side effects. 6564 1.1 joerg ****************************************************************************/ 6565 1.1 joerg static uint32_t 6566 1.1 joerg rcl_long(struct X86EMU *emu, uint32_t d, uint8_t s) 6567 1.1 joerg { 6568 1.1 joerg uint32_t res, cnt, mask, cf; 6569 1.1 joerg 6570 1.1 joerg res = d; 6571 1.1 joerg if ((cnt = s % 33) != 0) { 6572 1.1 joerg cf = (d >> (32 - cnt)) & 0x1; 6573 1.1 joerg res = (d << cnt) & 0xffffffff; 6574 1.1 joerg mask = (1 << (cnt - 1)) - 1; 6575 1.1 joerg res |= (d >> (33 - cnt)) & mask; 6576 1.1 joerg if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6577 1.1 joerg res |= 1 << (cnt - 1); 6578 1.1 joerg } 6579 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 6580 1.1 joerg CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)), 6581 1.1 joerg F_OF); 6582 1.1 joerg } 6583 1.1 joerg return res; 6584 1.1 joerg } 6585 1.1 joerg /**************************************************************************** 6586 1.1 joerg REMARKS: 6587 1.1 joerg Implements the RCR instruction and side effects. 6588 1.1 joerg ****************************************************************************/ 6589 1.1 joerg static uint8_t 6590 1.1 joerg rcr_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6591 1.1 joerg { 6592 1.1 joerg uint32_t res, cnt; 6593 1.1 joerg uint32_t mask, cf, ocf = 0; 6594 1.1 joerg 6595 1.1 joerg /* rotate right through carry */ 6596 1.1 joerg /* s is the rotate distance. It varies from 0 - 8. d is the byte 6597 1.1 joerg * object rotated. 6598 1.1 joerg * 6599 1.1 joerg * have 6600 1.1 joerg * 6601 1.1 joerg * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 6602 1.1 joerg * 6603 1.1 joerg * The new rotate is done mod 9, and given this, for a rotation of n bits 6604 1.1 joerg * (mod 9) the new carry flag is then located n bits from the LSB. 6605 1.1 joerg * The low part is then shifted up cnt bits, and the high part is or'd 6606 1.1 joerg * in. Using CAPS for new values, and lowercase for the original 6607 1.1 joerg * values, this can be expressed as: 6608 1.1 joerg * 6609 1.1 joerg * IF n > 0 1) CF <- b_(n-1) 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 6610 1.1 joerg * 3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */ 6611 1.1 joerg res = d; 6612 1.1 joerg if ((cnt = s % 9) != 0) { 6613 1.1 joerg /* extract the new CARRY FLAG. */ 6614 1.1 joerg /* CF <- b_(n-1) */ 6615 1.1 joerg if (cnt == 1) { 6616 1.1 joerg cf = d & 0x1; 6617 1.1 joerg /* note hackery here. Access_flag(..) evaluates to 6618 1.1 joerg * either 0 if flag not set non-zero if flag is set. 6619 1.1 joerg * doing access_flag(..) != 0 casts that into either 6620 1.1 joerg * 0..1 in any representation of the flags register 6621 1.1 joerg * (i.e. packed bit array or unpacked.) */ 6622 1.1 joerg ocf = ACCESS_FLAG(F_CF) != 0; 6623 1.1 joerg } else 6624 1.1 joerg cf = (d >> (cnt - 1)) & 0x1; 6625 1.1 joerg 6626 1.1 joerg /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */ 6627 1.1 joerg /* note that the right hand side done by the mask This is 6628 1.1 joerg * effectively done by shifting the object to the right. The 6629 1.1 joerg * result must be masked, in case the object came in and was 6630 1.1 joerg * treated as a negative number. Needed??? */ 6631 1.1 joerg 6632 1.1 joerg mask = (1 << (8 - cnt)) - 1; 6633 1.1 joerg res = (d >> cnt) & mask; 6634 1.1 joerg 6635 1.1 joerg /* now the high stuff which rotated around into the positions 6636 1.1 joerg * B_cnt-2 .. B_0 */ 6637 1.1 joerg /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */ 6638 1.1 joerg /* shift it downward, 7-(n-2) = 9-n positions. and mask off 6639 1.1 joerg * the result before or'ing in. */ 6640 1.1 joerg res |= (d << (9 - cnt)); 6641 1.1 joerg 6642 1.1 joerg /* if the carry flag was set, or it in. */ 6643 1.1 joerg if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6644 1.1 joerg /* B_(8-n) <- cf */ 6645 1.1 joerg res |= 1 << (8 - cnt); 6646 1.1 joerg } 6647 1.1 joerg /* set the new carry flag, based on the variable "cf" */ 6648 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 6649 1.1 joerg /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and 6650 1.1 joerg * the most significant bit. Blecck. */ 6651 1.1 joerg /* parenthesized... */ 6652 1.1 joerg if (cnt == 1) { 6653 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)), 6654 1.1 joerg F_OF); 6655 1.1 joerg } 6656 1.1 joerg } 6657 1.1 joerg return (uint8_t) res; 6658 1.1 joerg } 6659 1.1 joerg /**************************************************************************** 6660 1.1 joerg REMARKS: 6661 1.1 joerg Implements the RCR instruction and side effects. 6662 1.1 joerg ****************************************************************************/ 6663 1.1 joerg static uint16_t 6664 1.1 joerg rcr_word(struct X86EMU *emu, uint16_t d, uint8_t s) 6665 1.1 joerg { 6666 1.1 joerg uint32_t res, cnt; 6667 1.1 joerg uint32_t mask, cf, ocf = 0; 6668 1.1 joerg 6669 1.1 joerg /* rotate right through carry */ 6670 1.1 joerg res = d; 6671 1.1 joerg if ((cnt = s % 17) != 0) { 6672 1.1 joerg if (cnt == 1) { 6673 1.1 joerg cf = d & 0x1; 6674 1.1 joerg ocf = ACCESS_FLAG(F_CF) != 0; 6675 1.1 joerg } else 6676 1.1 joerg cf = (d >> (cnt - 1)) & 0x1; 6677 1.1 joerg mask = (1 << (16 - cnt)) - 1; 6678 1.1 joerg res = (d >> cnt) & mask; 6679 1.1 joerg res |= (d << (17 - cnt)); 6680 1.1 joerg if (ACCESS_FLAG(F_CF)) { 6681 1.1 joerg res |= 1 << (16 - cnt); 6682 1.1 joerg } 6683 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 6684 1.1 joerg if (cnt == 1) { 6685 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)), 6686 1.1 joerg F_OF); 6687 1.1 joerg } 6688 1.1 joerg } 6689 1.1 joerg return (uint16_t) res; 6690 1.1 joerg } 6691 1.1 joerg /**************************************************************************** 6692 1.1 joerg REMARKS: 6693 1.1 joerg Implements the RCR instruction and side effects. 6694 1.1 joerg ****************************************************************************/ 6695 1.1 joerg static uint32_t 6696 1.1 joerg rcr_long(struct X86EMU *emu, uint32_t d, uint8_t s) 6697 1.1 joerg { 6698 1.1 joerg uint32_t res, cnt; 6699 1.1 joerg uint32_t mask, cf, ocf = 0; 6700 1.1 joerg 6701 1.1 joerg /* rotate right through carry */ 6702 1.1 joerg res = d; 6703 1.1 joerg if ((cnt = s % 33) != 0) { 6704 1.1 joerg if (cnt == 1) { 6705 1.1 joerg cf = d & 0x1; 6706 1.1 joerg ocf = ACCESS_FLAG(F_CF) != 0; 6707 1.1 joerg } else 6708 1.1 joerg cf = (d >> (cnt - 1)) & 0x1; 6709 1.1 joerg mask = (1 << (32 - cnt)) - 1; 6710 1.1 joerg res = (d >> cnt) & mask; 6711 1.1 joerg if (cnt != 1) 6712 1.1 joerg res |= (d << (33 - cnt)); 6713 1.1 joerg if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ 6714 1.1 joerg res |= 1 << (32 - cnt); 6715 1.1 joerg } 6716 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 6717 1.1 joerg if (cnt == 1) { 6718 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)), 6719 1.1 joerg F_OF); 6720 1.1 joerg } 6721 1.1 joerg } 6722 1.1 joerg return res; 6723 1.1 joerg } 6724 1.1 joerg /**************************************************************************** 6725 1.1 joerg REMARKS: 6726 1.1 joerg Implements the ROL instruction and side effects. 6727 1.1 joerg ****************************************************************************/ 6728 1.1 joerg static uint8_t 6729 1.1 joerg rol_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6730 1.1 joerg { 6731 1.1 joerg unsigned int res, cnt, mask; 6732 1.1 joerg 6733 1.1 joerg /* rotate left */ 6734 1.1 joerg /* s is the rotate distance. It varies from 0 - 8. d is the byte 6735 1.1 joerg * object rotated. 6736 1.1 joerg * 6737 1.1 joerg * have 6738 1.1 joerg * 6739 1.1 joerg * CF B_7 ... B_0 6740 1.1 joerg * 6741 1.1 joerg * The new rotate is done mod 8. Much simpler than the "rcl" or "rcr" 6742 1.1 joerg * operations. 6743 1.1 joerg * 6744 1.1 joerg * IF n > 0 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) 2) B_(n-1) .. 6745 1.1 joerg * B_(0) <- b_(7) .. b_(8-n) */ 6746 1.1 joerg res = d; 6747 1.1 joerg if ((cnt = s % 8) != 0) { 6748 1.1 joerg /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */ 6749 1.1 joerg res = (d << cnt); 6750 1.1 joerg 6751 1.1 joerg /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */ 6752 1.1 joerg mask = (1 << cnt) - 1; 6753 1.1 joerg res |= (d >> (8 - cnt)) & mask; 6754 1.1 joerg 6755 1.1 joerg /* set the new carry flag, Note that it is the low order bit 6756 1.1 joerg * of the result!!! */ 6757 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6758 1.1 joerg /* OVERFLOW is set *IFF* s==1, then it is the xor of CF and 6759 1.1 joerg * the most significant bit. Blecck. */ 6760 1.1 joerg CONDITIONAL_SET_FLAG(s == 1 && 6761 1.1 joerg XOR2((res & 0x1) + ((res >> 6) & 0x2)), 6762 1.1 joerg F_OF); 6763 1.1 joerg } if (s != 0) { 6764 1.1 joerg /* set the new carry flag, Note that it is the low order bit 6765 1.1 joerg * of the result!!! */ 6766 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6767 1.1 joerg } 6768 1.1 joerg return (uint8_t) res; 6769 1.1 joerg } 6770 1.1 joerg /**************************************************************************** 6771 1.1 joerg REMARKS: 6772 1.1 joerg Implements the ROL instruction and side effects. 6773 1.1 joerg ****************************************************************************/ 6774 1.1 joerg static uint16_t 6775 1.1 joerg rol_word(struct X86EMU *emu, uint16_t d, uint8_t s) 6776 1.1 joerg { 6777 1.1 joerg unsigned int res, cnt, mask; 6778 1.1 joerg 6779 1.1 joerg res = d; 6780 1.1 joerg if ((cnt = s % 16) != 0) { 6781 1.1 joerg res = (d << cnt); 6782 1.1 joerg mask = (1 << cnt) - 1; 6783 1.1 joerg res |= (d >> (16 - cnt)) & mask; 6784 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6785 1.1 joerg CONDITIONAL_SET_FLAG(s == 1 && 6786 1.1 joerg XOR2((res & 0x1) + ((res >> 14) & 0x2)), 6787 1.1 joerg F_OF); 6788 1.1 joerg } if (s != 0) { 6789 1.1 joerg /* set the new carry flag, Note that it is the low order bit 6790 1.1 joerg * of the result!!! */ 6791 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6792 1.1 joerg } 6793 1.1 joerg return (uint16_t) res; 6794 1.1 joerg } 6795 1.1 joerg /**************************************************************************** 6796 1.1 joerg REMARKS: 6797 1.1 joerg Implements the ROL instruction and side effects. 6798 1.1 joerg ****************************************************************************/ 6799 1.1 joerg static uint32_t 6800 1.1 joerg rol_long(struct X86EMU *emu, uint32_t d, uint8_t s) 6801 1.1 joerg { 6802 1.1 joerg uint32_t res, cnt, mask; 6803 1.1 joerg 6804 1.1 joerg res = d; 6805 1.1 joerg if ((cnt = s % 32) != 0) { 6806 1.1 joerg res = (d << cnt); 6807 1.1 joerg mask = (1 << cnt) - 1; 6808 1.1 joerg res |= (d >> (32 - cnt)) & mask; 6809 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6810 1.1 joerg CONDITIONAL_SET_FLAG(s == 1 && 6811 1.1 joerg XOR2((res & 0x1) + ((res >> 30) & 0x2)), 6812 1.1 joerg F_OF); 6813 1.1 joerg } if (s != 0) { 6814 1.1 joerg /* set the new carry flag, Note that it is the low order bit 6815 1.1 joerg * of the result!!! */ 6816 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x1, F_CF); 6817 1.1 joerg } 6818 1.1 joerg return res; 6819 1.1 joerg } 6820 1.1 joerg /**************************************************************************** 6821 1.1 joerg REMARKS: 6822 1.1 joerg Implements the ROR instruction and side effects. 6823 1.1 joerg ****************************************************************************/ 6824 1.1 joerg static uint8_t 6825 1.1 joerg ror_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6826 1.1 joerg { 6827 1.1 joerg unsigned int res, cnt, mask; 6828 1.1 joerg 6829 1.1 joerg /* rotate right */ 6830 1.1 joerg /* s is the rotate distance. It varies from 0 - 8. d is the byte 6831 1.1 joerg * object rotated. 6832 1.1 joerg * 6833 1.1 joerg * have 6834 1.1 joerg * 6835 1.1 joerg * B_7 ... B_0 6836 1.1 joerg * 6837 1.1 joerg * The rotate is done mod 8. 6838 1.1 joerg * 6839 1.1 joerg * IF n > 0 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 2) B_(7) .. 6840 1.1 joerg * B_(8-n) <- b_(n-1) .. b_(0) */ 6841 1.1 joerg res = d; 6842 1.1 joerg if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */ 6843 1.1 joerg /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */ 6844 1.1 joerg res = (d << (8 - cnt)); 6845 1.1 joerg 6846 1.1 joerg /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */ 6847 1.1 joerg mask = (1 << (8 - cnt)) - 1; 6848 1.1 joerg res |= (d >> (cnt)) & mask; 6849 1.1 joerg 6850 1.1 joerg /* set the new carry flag, Note that it is the low order bit 6851 1.1 joerg * of the result!!! */ 6852 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_CF); 6853 1.1 joerg /* OVERFLOW is set *IFF* s==1, then it is the xor of the two 6854 1.1 joerg * most significant bits. Blecck. */ 6855 1.1 joerg CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF); 6856 1.1 joerg } else if (s != 0) { 6857 1.1 joerg /* set the new carry flag, Note that it is the low order bit 6858 1.1 joerg * of the result!!! */ 6859 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_CF); 6860 1.1 joerg } 6861 1.1 joerg return (uint8_t) res; 6862 1.1 joerg } 6863 1.1 joerg /**************************************************************************** 6864 1.1 joerg REMARKS: 6865 1.1 joerg Implements the ROR instruction and side effects. 6866 1.1 joerg ****************************************************************************/ 6867 1.1 joerg static uint16_t 6868 1.1 joerg ror_word(struct X86EMU *emu, uint16_t d, uint8_t s) 6869 1.1 joerg { 6870 1.1 joerg unsigned int res, cnt, mask; 6871 1.1 joerg 6872 1.1 joerg res = d; 6873 1.1 joerg if ((cnt = s % 16) != 0) { 6874 1.1 joerg res = (d << (16 - cnt)); 6875 1.1 joerg mask = (1 << (16 - cnt)) - 1; 6876 1.1 joerg res |= (d >> (cnt)) & mask; 6877 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_CF); 6878 1.1 joerg CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF); 6879 1.1 joerg } else if (s != 0) { 6880 1.1 joerg /* set the new carry flag, Note that it is the low order bit 6881 1.1 joerg * of the result!!! */ 6882 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_CF); 6883 1.1 joerg } 6884 1.1 joerg return (uint16_t) res; 6885 1.1 joerg } 6886 1.1 joerg /**************************************************************************** 6887 1.1 joerg REMARKS: 6888 1.1 joerg Implements the ROR instruction and side effects. 6889 1.1 joerg ****************************************************************************/ 6890 1.1 joerg static uint32_t 6891 1.1 joerg ror_long(struct X86EMU *emu, uint32_t d, uint8_t s) 6892 1.1 joerg { 6893 1.1 joerg uint32_t res, cnt, mask; 6894 1.1 joerg 6895 1.1 joerg res = d; 6896 1.1 joerg if ((cnt = s % 32) != 0) { 6897 1.1 joerg res = (d << (32 - cnt)); 6898 1.1 joerg mask = (1 << (32 - cnt)) - 1; 6899 1.1 joerg res |= (d >> (cnt)) & mask; 6900 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF); 6901 1.1 joerg CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF); 6902 1.1 joerg } else if (s != 0) { 6903 1.1 joerg /* set the new carry flag, Note that it is the low order bit 6904 1.1 joerg * of the result!!! */ 6905 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF); 6906 1.1 joerg } 6907 1.1 joerg return res; 6908 1.1 joerg } 6909 1.1 joerg /**************************************************************************** 6910 1.1 joerg REMARKS: 6911 1.1 joerg Implements the SHL instruction and side effects. 6912 1.1 joerg ****************************************************************************/ 6913 1.1 joerg static uint8_t 6914 1.1 joerg shl_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 6915 1.1 joerg { 6916 1.1 joerg unsigned int cnt, res, cf; 6917 1.1 joerg 6918 1.1 joerg if (s < 8) { 6919 1.1 joerg cnt = s % 8; 6920 1.1 joerg 6921 1.1 joerg /* last bit shifted out goes into carry flag */ 6922 1.1 joerg if (cnt > 0) { 6923 1.1 joerg res = d << cnt; 6924 1.1 joerg cf = d & (1 << (8 - cnt)); 6925 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 6926 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 6927 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 6928 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6929 1.1 joerg } else { 6930 1.1 joerg res = (uint8_t) d; 6931 1.1 joerg } 6932 1.1 joerg 6933 1.1 joerg if (cnt == 1) { 6934 1.1 joerg /* Needs simplification. */ 6935 1.1 joerg CONDITIONAL_SET_FLAG( 6936 1.1 joerg (((res & 0x80) == 0x80) ^ 6937 1.1 joerg (ACCESS_FLAG(F_CF) != 0)), 6938 1.1 joerg /* was (emu->x86.R_FLG&F_CF)==F_CF)), */ 6939 1.1 joerg F_OF); 6940 1.1 joerg } else { 6941 1.1 joerg CLEAR_FLAG(F_OF); 6942 1.1 joerg } 6943 1.1 joerg } else { 6944 1.1 joerg res = 0; 6945 1.1 joerg CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF); 6946 1.1 joerg CLEAR_FLAG(F_OF); 6947 1.1 joerg CLEAR_FLAG(F_SF); 6948 1.1 joerg SET_FLAG(F_PF); 6949 1.1 joerg SET_FLAG(F_ZF); 6950 1.1 joerg } 6951 1.1 joerg return (uint8_t) res; 6952 1.1 joerg } 6953 1.1 joerg /**************************************************************************** 6954 1.1 joerg REMARKS: 6955 1.1 joerg Implements the SHL instruction and side effects. 6956 1.1 joerg ****************************************************************************/ 6957 1.1 joerg static uint16_t 6958 1.1 joerg shl_word(struct X86EMU *emu, uint16_t d, uint8_t s) 6959 1.1 joerg { 6960 1.1 joerg unsigned int cnt, res, cf; 6961 1.1 joerg 6962 1.1 joerg if (s < 16) { 6963 1.1 joerg cnt = s % 16; 6964 1.1 joerg if (cnt > 0) { 6965 1.1 joerg res = d << cnt; 6966 1.1 joerg cf = d & (1 << (16 - cnt)); 6967 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 6968 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 6969 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 6970 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 6971 1.1 joerg } else { 6972 1.1 joerg res = (uint16_t) d; 6973 1.1 joerg } 6974 1.1 joerg 6975 1.1 joerg if (cnt == 1) { 6976 1.1 joerg CONDITIONAL_SET_FLAG( 6977 1.1 joerg (((res & 0x8000) == 0x8000) ^ 6978 1.1 joerg (ACCESS_FLAG(F_CF) != 0)), 6979 1.1 joerg F_OF); 6980 1.1 joerg } else { 6981 1.1 joerg CLEAR_FLAG(F_OF); 6982 1.1 joerg } 6983 1.1 joerg } else { 6984 1.1 joerg res = 0; 6985 1.1 joerg CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF); 6986 1.1 joerg CLEAR_FLAG(F_OF); 6987 1.1 joerg CLEAR_FLAG(F_SF); 6988 1.1 joerg SET_FLAG(F_PF); 6989 1.1 joerg SET_FLAG(F_ZF); 6990 1.1 joerg } 6991 1.1 joerg return (uint16_t) res; 6992 1.1 joerg } 6993 1.1 joerg /**************************************************************************** 6994 1.1 joerg REMARKS: 6995 1.1 joerg Implements the SHL instruction and side effects. 6996 1.1 joerg ****************************************************************************/ 6997 1.1 joerg static uint32_t 6998 1.1 joerg shl_long(struct X86EMU *emu, uint32_t d, uint8_t s) 6999 1.1 joerg { 7000 1.1 joerg unsigned int cnt, res, cf; 7001 1.1 joerg 7002 1.1 joerg if (s < 32) { 7003 1.1 joerg cnt = s % 32; 7004 1.1 joerg if (cnt > 0) { 7005 1.1 joerg res = d << cnt; 7006 1.1 joerg cf = d & (1 << (32 - cnt)); 7007 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 7008 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7009 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7010 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7011 1.1 joerg } else { 7012 1.1 joerg res = d; 7013 1.1 joerg } 7014 1.1 joerg if (cnt == 1) { 7015 1.1 joerg CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^ 7016 1.1 joerg (ACCESS_FLAG(F_CF) != 0)), F_OF); 7017 1.1 joerg } else { 7018 1.1 joerg CLEAR_FLAG(F_OF); 7019 1.1 joerg } 7020 1.1 joerg } else { 7021 1.1 joerg res = 0; 7022 1.1 joerg CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF); 7023 1.1 joerg CLEAR_FLAG(F_OF); 7024 1.1 joerg CLEAR_FLAG(F_SF); 7025 1.1 joerg SET_FLAG(F_PF); 7026 1.1 joerg SET_FLAG(F_ZF); 7027 1.1 joerg } 7028 1.1 joerg return res; 7029 1.1 joerg } 7030 1.1 joerg /**************************************************************************** 7031 1.1 joerg REMARKS: 7032 1.1 joerg Implements the SHR instruction and side effects. 7033 1.1 joerg ****************************************************************************/ 7034 1.1 joerg static uint8_t 7035 1.1 joerg shr_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 7036 1.1 joerg { 7037 1.1 joerg unsigned int cnt, res, cf; 7038 1.1 joerg 7039 1.1 joerg if (s < 8) { 7040 1.1 joerg cnt = s % 8; 7041 1.1 joerg if (cnt > 0) { 7042 1.1 joerg cf = d & (1 << (cnt - 1)); 7043 1.1 joerg res = d >> cnt; 7044 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 7045 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7046 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7047 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7048 1.1 joerg } else { 7049 1.1 joerg res = (uint8_t) d; 7050 1.1 joerg } 7051 1.1 joerg 7052 1.1 joerg if (cnt == 1) { 7053 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF); 7054 1.1 joerg } else { 7055 1.1 joerg CLEAR_FLAG(F_OF); 7056 1.1 joerg } 7057 1.1 joerg } else { 7058 1.1 joerg res = 0; 7059 1.1 joerg CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF); 7060 1.1 joerg CLEAR_FLAG(F_OF); 7061 1.1 joerg CLEAR_FLAG(F_SF); 7062 1.1 joerg SET_FLAG(F_PF); 7063 1.1 joerg SET_FLAG(F_ZF); 7064 1.1 joerg } 7065 1.1 joerg return (uint8_t) res; 7066 1.1 joerg } 7067 1.1 joerg /**************************************************************************** 7068 1.1 joerg REMARKS: 7069 1.1 joerg Implements the SHR instruction and side effects. 7070 1.1 joerg ****************************************************************************/ 7071 1.1 joerg static uint16_t 7072 1.1 joerg shr_word(struct X86EMU *emu, uint16_t d, uint8_t s) 7073 1.1 joerg { 7074 1.1 joerg unsigned int cnt, res, cf; 7075 1.1 joerg 7076 1.1 joerg if (s < 16) { 7077 1.1 joerg cnt = s % 16; 7078 1.1 joerg if (cnt > 0) { 7079 1.1 joerg cf = d & (1 << (cnt - 1)); 7080 1.1 joerg res = d >> cnt; 7081 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 7082 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7083 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7084 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7085 1.1 joerg } else { 7086 1.1 joerg res = d; 7087 1.1 joerg } 7088 1.1 joerg 7089 1.1 joerg if (cnt == 1) { 7090 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF); 7091 1.1 joerg } else { 7092 1.1 joerg CLEAR_FLAG(F_OF); 7093 1.1 joerg } 7094 1.1 joerg } else { 7095 1.1 joerg res = 0; 7096 1.1 joerg CLEAR_FLAG(F_CF); 7097 1.1 joerg CLEAR_FLAG(F_OF); 7098 1.1 joerg SET_FLAG(F_ZF); 7099 1.1 joerg CLEAR_FLAG(F_SF); 7100 1.1 joerg CLEAR_FLAG(F_PF); 7101 1.1 joerg } 7102 1.1 joerg return (uint16_t) res; 7103 1.1 joerg } 7104 1.1 joerg /**************************************************************************** 7105 1.1 joerg REMARKS: 7106 1.1 joerg Implements the SHR instruction and side effects. 7107 1.1 joerg ****************************************************************************/ 7108 1.1 joerg static uint32_t 7109 1.1 joerg shr_long(struct X86EMU *emu, uint32_t d, uint8_t s) 7110 1.1 joerg { 7111 1.1 joerg unsigned int cnt, res, cf; 7112 1.1 joerg 7113 1.1 joerg if (s < 32) { 7114 1.1 joerg cnt = s % 32; 7115 1.1 joerg if (cnt > 0) { 7116 1.1 joerg cf = d & (1 << (cnt - 1)); 7117 1.1 joerg res = d >> cnt; 7118 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 7119 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7120 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7121 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7122 1.1 joerg } else { 7123 1.1 joerg res = d; 7124 1.1 joerg } 7125 1.1 joerg if (cnt == 1) { 7126 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF); 7127 1.1 joerg } else { 7128 1.1 joerg CLEAR_FLAG(F_OF); 7129 1.1 joerg } 7130 1.1 joerg } else { 7131 1.1 joerg res = 0; 7132 1.1 joerg CLEAR_FLAG(F_CF); 7133 1.1 joerg CLEAR_FLAG(F_OF); 7134 1.1 joerg SET_FLAG(F_ZF); 7135 1.1 joerg CLEAR_FLAG(F_SF); 7136 1.1 joerg CLEAR_FLAG(F_PF); 7137 1.1 joerg } 7138 1.1 joerg return res; 7139 1.1 joerg } 7140 1.1 joerg /**************************************************************************** 7141 1.1 joerg REMARKS: 7142 1.1 joerg Implements the SAR instruction and side effects. 7143 1.1 joerg ****************************************************************************/ 7144 1.1 joerg static uint8_t 7145 1.1 joerg sar_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 7146 1.1 joerg { 7147 1.1 joerg unsigned int cnt, res, cf, mask, sf; 7148 1.1 joerg 7149 1.1 joerg res = d; 7150 1.1 joerg sf = d & 0x80; 7151 1.1 joerg cnt = s % 8; 7152 1.1 joerg if (cnt > 0 && cnt < 8) { 7153 1.1 joerg mask = (1 << (8 - cnt)) - 1; 7154 1.1 joerg cf = d & (1 << (cnt - 1)); 7155 1.1 joerg res = (d >> cnt) & mask; 7156 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 7157 1.1 joerg if (sf) { 7158 1.1 joerg res |= ~mask; 7159 1.1 joerg } 7160 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7161 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7162 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7163 1.1 joerg } else if (cnt >= 8) { 7164 1.1 joerg if (sf) { 7165 1.1 joerg res = 0xff; 7166 1.1 joerg SET_FLAG(F_CF); 7167 1.1 joerg CLEAR_FLAG(F_ZF); 7168 1.1 joerg SET_FLAG(F_SF); 7169 1.1 joerg SET_FLAG(F_PF); 7170 1.1 joerg } else { 7171 1.1 joerg res = 0; 7172 1.1 joerg CLEAR_FLAG(F_CF); 7173 1.1 joerg SET_FLAG(F_ZF); 7174 1.1 joerg CLEAR_FLAG(F_SF); 7175 1.1 joerg CLEAR_FLAG(F_PF); 7176 1.1 joerg } 7177 1.1 joerg } 7178 1.1 joerg return (uint8_t) res; 7179 1.1 joerg } 7180 1.1 joerg /**************************************************************************** 7181 1.1 joerg REMARKS: 7182 1.1 joerg Implements the SAR instruction and side effects. 7183 1.1 joerg ****************************************************************************/ 7184 1.1 joerg static uint16_t 7185 1.1 joerg sar_word(struct X86EMU *emu, uint16_t d, uint8_t s) 7186 1.1 joerg { 7187 1.1 joerg unsigned int cnt, res, cf, mask, sf; 7188 1.1 joerg 7189 1.1 joerg sf = d & 0x8000; 7190 1.1 joerg cnt = s % 16; 7191 1.1 joerg res = d; 7192 1.1 joerg if (cnt > 0 && cnt < 16) { 7193 1.1 joerg mask = (1 << (16 - cnt)) - 1; 7194 1.1 joerg cf = d & (1 << (cnt - 1)); 7195 1.1 joerg res = (d >> cnt) & mask; 7196 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 7197 1.1 joerg if (sf) { 7198 1.1 joerg res |= ~mask; 7199 1.1 joerg } 7200 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7201 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7202 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7203 1.1 joerg } else if (cnt >= 16) { 7204 1.1 joerg if (sf) { 7205 1.1 joerg res = 0xffff; 7206 1.1 joerg SET_FLAG(F_CF); 7207 1.1 joerg CLEAR_FLAG(F_ZF); 7208 1.1 joerg SET_FLAG(F_SF); 7209 1.1 joerg SET_FLAG(F_PF); 7210 1.1 joerg } else { 7211 1.1 joerg res = 0; 7212 1.1 joerg CLEAR_FLAG(F_CF); 7213 1.1 joerg SET_FLAG(F_ZF); 7214 1.1 joerg CLEAR_FLAG(F_SF); 7215 1.1 joerg CLEAR_FLAG(F_PF); 7216 1.1 joerg } 7217 1.1 joerg } 7218 1.1 joerg return (uint16_t) res; 7219 1.1 joerg } 7220 1.1 joerg /**************************************************************************** 7221 1.1 joerg REMARKS: 7222 1.1 joerg Implements the SAR instruction and side effects. 7223 1.1 joerg ****************************************************************************/ 7224 1.1 joerg static uint32_t 7225 1.1 joerg sar_long(struct X86EMU *emu, uint32_t d, uint8_t s) 7226 1.1 joerg { 7227 1.1 joerg uint32_t cnt, res, cf, mask, sf; 7228 1.1 joerg 7229 1.1 joerg sf = d & 0x80000000; 7230 1.1 joerg cnt = s % 32; 7231 1.1 joerg res = d; 7232 1.1 joerg if (cnt > 0 && cnt < 32) { 7233 1.1 joerg mask = (1 << (32 - cnt)) - 1; 7234 1.1 joerg cf = d & (1 << (cnt - 1)); 7235 1.1 joerg res = (d >> cnt) & mask; 7236 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 7237 1.1 joerg if (sf) { 7238 1.1 joerg res |= ~mask; 7239 1.1 joerg } 7240 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7241 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7242 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7243 1.1 joerg } else if (cnt >= 32) { 7244 1.1 joerg if (sf) { 7245 1.1 joerg res = 0xffffffff; 7246 1.1 joerg SET_FLAG(F_CF); 7247 1.1 joerg CLEAR_FLAG(F_ZF); 7248 1.1 joerg SET_FLAG(F_SF); 7249 1.1 joerg SET_FLAG(F_PF); 7250 1.1 joerg } else { 7251 1.1 joerg res = 0; 7252 1.1 joerg CLEAR_FLAG(F_CF); 7253 1.1 joerg SET_FLAG(F_ZF); 7254 1.1 joerg CLEAR_FLAG(F_SF); 7255 1.1 joerg CLEAR_FLAG(F_PF); 7256 1.1 joerg } 7257 1.1 joerg } 7258 1.1 joerg return res; 7259 1.1 joerg } 7260 1.1 joerg /**************************************************************************** 7261 1.1 joerg REMARKS: 7262 1.1 joerg Implements the SHLD instruction and side effects. 7263 1.1 joerg ****************************************************************************/ 7264 1.1 joerg static uint16_t 7265 1.1 joerg shld_word(struct X86EMU *emu, uint16_t d, uint16_t fill, uint8_t s) 7266 1.1 joerg { 7267 1.1 joerg unsigned int cnt, res, cf; 7268 1.1 joerg 7269 1.1 joerg if (s < 16) { 7270 1.1 joerg cnt = s % 16; 7271 1.1 joerg if (cnt > 0) { 7272 1.1 joerg res = (d << cnt) | (fill >> (16 - cnt)); 7273 1.1 joerg cf = d & (1 << (16 - cnt)); 7274 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 7275 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7276 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7277 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7278 1.1 joerg } else { 7279 1.1 joerg res = d; 7280 1.1 joerg } 7281 1.1 joerg if (cnt == 1) { 7282 1.1 joerg CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^ 7283 1.1 joerg (ACCESS_FLAG(F_CF) != 0)), F_OF); 7284 1.1 joerg } else { 7285 1.1 joerg CLEAR_FLAG(F_OF); 7286 1.1 joerg } 7287 1.1 joerg } else { 7288 1.1 joerg res = 0; 7289 1.1 joerg CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF); 7290 1.1 joerg CLEAR_FLAG(F_OF); 7291 1.1 joerg CLEAR_FLAG(F_SF); 7292 1.1 joerg SET_FLAG(F_PF); 7293 1.1 joerg SET_FLAG(F_ZF); 7294 1.1 joerg } 7295 1.1 joerg return (uint16_t) res; 7296 1.1 joerg } 7297 1.1 joerg /**************************************************************************** 7298 1.1 joerg REMARKS: 7299 1.1 joerg Implements the SHLD instruction and side effects. 7300 1.1 joerg ****************************************************************************/ 7301 1.1 joerg static uint32_t 7302 1.1 joerg shld_long(struct X86EMU *emu, uint32_t d, uint32_t fill, uint8_t s) 7303 1.1 joerg { 7304 1.1 joerg unsigned int cnt, res, cf; 7305 1.1 joerg 7306 1.1 joerg if (s < 32) { 7307 1.1 joerg cnt = s % 32; 7308 1.1 joerg if (cnt > 0) { 7309 1.1 joerg res = (d << cnt) | (fill >> (32 - cnt)); 7310 1.1 joerg cf = d & (1 << (32 - cnt)); 7311 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 7312 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7313 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7314 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7315 1.1 joerg } else { 7316 1.1 joerg res = d; 7317 1.1 joerg } 7318 1.1 joerg if (cnt == 1) { 7319 1.1 joerg CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^ 7320 1.1 joerg (ACCESS_FLAG(F_CF) != 0)), F_OF); 7321 1.1 joerg } else { 7322 1.1 joerg CLEAR_FLAG(F_OF); 7323 1.1 joerg } 7324 1.1 joerg } else { 7325 1.1 joerg res = 0; 7326 1.1 joerg CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF); 7327 1.1 joerg CLEAR_FLAG(F_OF); 7328 1.1 joerg CLEAR_FLAG(F_SF); 7329 1.1 joerg SET_FLAG(F_PF); 7330 1.1 joerg SET_FLAG(F_ZF); 7331 1.1 joerg } 7332 1.1 joerg return res; 7333 1.1 joerg } 7334 1.1 joerg /**************************************************************************** 7335 1.1 joerg REMARKS: 7336 1.1 joerg Implements the SHRD instruction and side effects. 7337 1.1 joerg ****************************************************************************/ 7338 1.1 joerg static uint16_t 7339 1.1 joerg shrd_word(struct X86EMU *emu, uint16_t d, uint16_t fill, uint8_t s) 7340 1.1 joerg { 7341 1.1 joerg unsigned int cnt, res, cf; 7342 1.1 joerg 7343 1.1 joerg if (s < 16) { 7344 1.1 joerg cnt = s % 16; 7345 1.1 joerg if (cnt > 0) { 7346 1.1 joerg cf = d & (1 << (cnt - 1)); 7347 1.1 joerg res = (d >> cnt) | (fill << (16 - cnt)); 7348 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 7349 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7350 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7351 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7352 1.1 joerg } else { 7353 1.1 joerg res = d; 7354 1.1 joerg } 7355 1.1 joerg 7356 1.1 joerg if (cnt == 1) { 7357 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF); 7358 1.1 joerg } else { 7359 1.1 joerg CLEAR_FLAG(F_OF); 7360 1.1 joerg } 7361 1.1 joerg } else { 7362 1.1 joerg res = 0; 7363 1.1 joerg CLEAR_FLAG(F_CF); 7364 1.1 joerg CLEAR_FLAG(F_OF); 7365 1.1 joerg SET_FLAG(F_ZF); 7366 1.1 joerg CLEAR_FLAG(F_SF); 7367 1.1 joerg CLEAR_FLAG(F_PF); 7368 1.1 joerg } 7369 1.1 joerg return (uint16_t) res; 7370 1.1 joerg } 7371 1.1 joerg /**************************************************************************** 7372 1.1 joerg REMARKS: 7373 1.1 joerg Implements the SHRD instruction and side effects. 7374 1.1 joerg ****************************************************************************/ 7375 1.1 joerg static uint32_t 7376 1.1 joerg shrd_long(struct X86EMU *emu, uint32_t d, uint32_t fill, uint8_t s) 7377 1.1 joerg { 7378 1.1 joerg unsigned int cnt, res, cf; 7379 1.1 joerg 7380 1.1 joerg if (s < 32) { 7381 1.1 joerg cnt = s % 32; 7382 1.1 joerg if (cnt > 0) { 7383 1.1 joerg cf = d & (1 << (cnt - 1)); 7384 1.1 joerg res = (d >> cnt) | (fill << (32 - cnt)); 7385 1.1 joerg CONDITIONAL_SET_FLAG(cf, F_CF); 7386 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7387 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7388 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7389 1.1 joerg } else { 7390 1.1 joerg res = d; 7391 1.1 joerg } 7392 1.1 joerg if (cnt == 1) { 7393 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF); 7394 1.1 joerg } else { 7395 1.1 joerg CLEAR_FLAG(F_OF); 7396 1.1 joerg } 7397 1.1 joerg } else { 7398 1.1 joerg res = 0; 7399 1.1 joerg CLEAR_FLAG(F_CF); 7400 1.1 joerg CLEAR_FLAG(F_OF); 7401 1.1 joerg SET_FLAG(F_ZF); 7402 1.1 joerg CLEAR_FLAG(F_SF); 7403 1.1 joerg CLEAR_FLAG(F_PF); 7404 1.1 joerg } 7405 1.1 joerg return res; 7406 1.1 joerg } 7407 1.1 joerg /**************************************************************************** 7408 1.1 joerg REMARKS: 7409 1.1 joerg Implements the SBB instruction and side effects. 7410 1.1 joerg ****************************************************************************/ 7411 1.1 joerg static uint8_t 7412 1.1 joerg sbb_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 7413 1.1 joerg { 7414 1.1 joerg uint32_t res; /* all operands in native machine order */ 7415 1.1 joerg uint32_t bc; 7416 1.1 joerg 7417 1.1 joerg if (ACCESS_FLAG(F_CF)) 7418 1.1 joerg res = d - s - 1; 7419 1.1 joerg else 7420 1.1 joerg res = d - s; 7421 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7422 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7423 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7424 1.1 joerg 7425 1.1 joerg /* calculate the borrow chain. See note at top */ 7426 1.1 joerg bc = (res & (~d | s)) | (~d & s); 7427 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); 7428 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 7429 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7430 1.1 joerg return (uint8_t) res; 7431 1.1 joerg } 7432 1.1 joerg /**************************************************************************** 7433 1.1 joerg REMARKS: 7434 1.1 joerg Implements the SBB instruction and side effects. 7435 1.1 joerg ****************************************************************************/ 7436 1.1 joerg static uint16_t 7437 1.1 joerg sbb_word(struct X86EMU *emu, uint16_t d, uint16_t s) 7438 1.1 joerg { 7439 1.1 joerg uint32_t res; /* all operands in native machine order */ 7440 1.1 joerg uint32_t bc; 7441 1.1 joerg 7442 1.1 joerg if (ACCESS_FLAG(F_CF)) 7443 1.1 joerg res = d - s - 1; 7444 1.1 joerg else 7445 1.1 joerg res = d - s; 7446 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7447 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7448 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7449 1.1 joerg 7450 1.1 joerg /* calculate the borrow chain. See note at top */ 7451 1.1 joerg bc = (res & (~d | s)) | (~d & s); 7452 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 7453 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 7454 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7455 1.1 joerg return (uint16_t) res; 7456 1.1 joerg } 7457 1.1 joerg /**************************************************************************** 7458 1.1 joerg REMARKS: 7459 1.1 joerg Implements the SBB instruction and side effects. 7460 1.1 joerg ****************************************************************************/ 7461 1.1 joerg static uint32_t 7462 1.1 joerg sbb_long(struct X86EMU *emu, uint32_t d, uint32_t s) 7463 1.1 joerg { 7464 1.1 joerg uint32_t res; /* all operands in native machine order */ 7465 1.1 joerg uint32_t bc; 7466 1.1 joerg 7467 1.1 joerg if (ACCESS_FLAG(F_CF)) 7468 1.1 joerg res = d - s - 1; 7469 1.1 joerg else 7470 1.1 joerg res = d - s; 7471 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7472 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7473 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7474 1.1 joerg 7475 1.1 joerg /* calculate the borrow chain. See note at top */ 7476 1.1 joerg bc = (res & (~d | s)) | (~d & s); 7477 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 7478 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 7479 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7480 1.1 joerg return res; 7481 1.1 joerg } 7482 1.1 joerg /**************************************************************************** 7483 1.1 joerg REMARKS: 7484 1.1 joerg Implements the SUB instruction and side effects. 7485 1.1 joerg ****************************************************************************/ 7486 1.1 joerg static uint8_t 7487 1.1 joerg sub_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 7488 1.1 joerg { 7489 1.1 joerg uint32_t res; /* all operands in native machine order */ 7490 1.1 joerg uint32_t bc; 7491 1.1 joerg 7492 1.1 joerg res = d - s; 7493 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7494 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); 7495 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7496 1.1 joerg 7497 1.1 joerg /* calculate the borrow chain. See note at top */ 7498 1.1 joerg bc = (res & (~d | s)) | (~d & s); 7499 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); 7500 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); 7501 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7502 1.1 joerg return (uint8_t) res; 7503 1.1 joerg } 7504 1.1 joerg /**************************************************************************** 7505 1.1 joerg REMARKS: 7506 1.1 joerg Implements the SUB instruction and side effects. 7507 1.1 joerg ****************************************************************************/ 7508 1.1 joerg static uint16_t 7509 1.1 joerg sub_word(struct X86EMU *emu, uint16_t d, uint16_t s) 7510 1.1 joerg { 7511 1.1 joerg uint32_t res; /* all operands in native machine order */ 7512 1.1 joerg uint32_t bc; 7513 1.1 joerg 7514 1.1 joerg res = d - s; 7515 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7516 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); 7517 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7518 1.1 joerg 7519 1.1 joerg /* calculate the borrow chain. See note at top */ 7520 1.1 joerg bc = (res & (~d | s)) | (~d & s); 7521 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); 7522 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); 7523 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7524 1.1 joerg return (uint16_t) res; 7525 1.1 joerg } 7526 1.1 joerg /**************************************************************************** 7527 1.1 joerg REMARKS: 7528 1.1 joerg Implements the SUB instruction and side effects. 7529 1.1 joerg ****************************************************************************/ 7530 1.1 joerg static uint32_t 7531 1.1 joerg sub_long(struct X86EMU *emu, uint32_t d, uint32_t s) 7532 1.1 joerg { 7533 1.1 joerg uint32_t res; /* all operands in native machine order */ 7534 1.1 joerg uint32_t bc; 7535 1.1 joerg 7536 1.1 joerg res = d - s; 7537 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7538 1.1 joerg CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); 7539 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7540 1.1 joerg 7541 1.1 joerg /* calculate the borrow chain. See note at top */ 7542 1.1 joerg bc = (res & (~d | s)) | (~d & s); 7543 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); 7544 1.1 joerg CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); 7545 1.1 joerg CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); 7546 1.1 joerg return res; 7547 1.1 joerg } 7548 1.1 joerg /**************************************************************************** 7549 1.1 joerg REMARKS: 7550 1.1 joerg Implements the TEST instruction and side effects. 7551 1.1 joerg ****************************************************************************/ 7552 1.1 joerg static void 7553 1.1 joerg test_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 7554 1.1 joerg { 7555 1.1 joerg uint32_t res; /* all operands in native machine order */ 7556 1.1 joerg 7557 1.1 joerg res = d & s; 7558 1.1 joerg 7559 1.1 joerg CLEAR_FLAG(F_OF); 7560 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7561 1.1 joerg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7562 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7563 1.1 joerg /* AF == dont care */ 7564 1.1 joerg CLEAR_FLAG(F_CF); 7565 1.1 joerg } 7566 1.1 joerg /**************************************************************************** 7567 1.1 joerg REMARKS: 7568 1.1 joerg Implements the TEST instruction and side effects. 7569 1.1 joerg ****************************************************************************/ 7570 1.1 joerg static void 7571 1.1 joerg test_word(struct X86EMU *emu, uint16_t d, uint16_t s) 7572 1.1 joerg { 7573 1.1 joerg uint32_t res; /* all operands in native machine order */ 7574 1.1 joerg 7575 1.1 joerg res = d & s; 7576 1.1 joerg 7577 1.1 joerg CLEAR_FLAG(F_OF); 7578 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7579 1.1 joerg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7580 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7581 1.1 joerg /* AF == dont care */ 7582 1.1 joerg CLEAR_FLAG(F_CF); 7583 1.1 joerg } 7584 1.1 joerg /**************************************************************************** 7585 1.1 joerg REMARKS: 7586 1.1 joerg Implements the TEST instruction and side effects. 7587 1.1 joerg ****************************************************************************/ 7588 1.1 joerg static void 7589 1.1 joerg test_long(struct X86EMU *emu, uint32_t d, uint32_t s) 7590 1.1 joerg { 7591 1.1 joerg uint32_t res; /* all operands in native machine order */ 7592 1.1 joerg 7593 1.1 joerg res = d & s; 7594 1.1 joerg 7595 1.1 joerg CLEAR_FLAG(F_OF); 7596 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7597 1.1 joerg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7598 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7599 1.1 joerg /* AF == dont care */ 7600 1.1 joerg CLEAR_FLAG(F_CF); 7601 1.1 joerg } 7602 1.1 joerg /**************************************************************************** 7603 1.1 joerg REMARKS: 7604 1.1 joerg Implements the XOR instruction and side effects. 7605 1.1 joerg ****************************************************************************/ 7606 1.1 joerg static uint8_t 7607 1.1 joerg xor_byte(struct X86EMU *emu, uint8_t d, uint8_t s) 7608 1.1 joerg { 7609 1.1 joerg uint8_t res; /* all operands in native machine order */ 7610 1.1 joerg 7611 1.1 joerg res = d ^ s; 7612 1.1 joerg CLEAR_FLAG(F_OF); 7613 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80, F_SF); 7614 1.1 joerg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7615 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res), F_PF); 7616 1.1 joerg CLEAR_FLAG(F_CF); 7617 1.1 joerg CLEAR_FLAG(F_AF); 7618 1.1 joerg return res; 7619 1.1 joerg } 7620 1.1 joerg /**************************************************************************** 7621 1.1 joerg REMARKS: 7622 1.1 joerg Implements the XOR instruction and side effects. 7623 1.1 joerg ****************************************************************************/ 7624 1.1 joerg static uint16_t 7625 1.1 joerg xor_word(struct X86EMU *emu, uint16_t d, uint16_t s) 7626 1.1 joerg { 7627 1.1 joerg uint16_t res; /* all operands in native machine order */ 7628 1.1 joerg 7629 1.1 joerg res = d ^ s; 7630 1.1 joerg CLEAR_FLAG(F_OF); 7631 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); 7632 1.1 joerg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7633 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7634 1.1 joerg CLEAR_FLAG(F_CF); 7635 1.1 joerg CLEAR_FLAG(F_AF); 7636 1.1 joerg return res; 7637 1.1 joerg } 7638 1.1 joerg /**************************************************************************** 7639 1.1 joerg REMARKS: 7640 1.1 joerg Implements the XOR instruction and side effects. 7641 1.1 joerg ****************************************************************************/ 7642 1.1 joerg static uint32_t 7643 1.1 joerg xor_long(struct X86EMU *emu, uint32_t d, uint32_t s) 7644 1.1 joerg { 7645 1.1 joerg uint32_t res; /* all operands in native machine order */ 7646 1.1 joerg 7647 1.1 joerg res = d ^ s; 7648 1.1 joerg CLEAR_FLAG(F_OF); 7649 1.1 joerg CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); 7650 1.1 joerg CONDITIONAL_SET_FLAG(res == 0, F_ZF); 7651 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); 7652 1.1 joerg CLEAR_FLAG(F_CF); 7653 1.1 joerg CLEAR_FLAG(F_AF); 7654 1.1 joerg return res; 7655 1.1 joerg } 7656 1.1 joerg /**************************************************************************** 7657 1.1 joerg REMARKS: 7658 1.1 joerg Implements the IMUL instruction and side effects. 7659 1.1 joerg ****************************************************************************/ 7660 1.1 joerg static void 7661 1.1 joerg imul_byte(struct X86EMU *emu, uint8_t s) 7662 1.1 joerg { 7663 1.1 joerg int16_t res = (int16_t) ((int8_t) emu->x86.R_AL * (int8_t) s); 7664 1.1 joerg 7665 1.1 joerg emu->x86.R_AX = res; 7666 1.1 joerg if (((emu->x86.R_AL & 0x80) == 0 && emu->x86.R_AH == 0x00) || 7667 1.1 joerg ((emu->x86.R_AL & 0x80) != 0 && emu->x86.R_AH == 0xFF)) { 7668 1.1 joerg CLEAR_FLAG(F_CF); 7669 1.1 joerg CLEAR_FLAG(F_OF); 7670 1.1 joerg } else { 7671 1.1 joerg SET_FLAG(F_CF); 7672 1.1 joerg SET_FLAG(F_OF); 7673 1.1 joerg } 7674 1.1 joerg } 7675 1.1 joerg /**************************************************************************** 7676 1.1 joerg REMARKS: 7677 1.1 joerg Implements the IMUL instruction and side effects. 7678 1.1 joerg ****************************************************************************/ 7679 1.1 joerg static void 7680 1.1 joerg imul_word(struct X86EMU *emu, uint16_t s) 7681 1.1 joerg { 7682 1.1 joerg int32_t res = (int16_t) emu->x86.R_AX * (int16_t) s; 7683 1.1 joerg 7684 1.1 joerg emu->x86.R_AX = (uint16_t) res; 7685 1.1 joerg emu->x86.R_DX = (uint16_t) (res >> 16); 7686 1.1 joerg if (((emu->x86.R_AX & 0x8000) == 0 && emu->x86.R_DX == 0x00) || 7687 1.1 joerg ((emu->x86.R_AX & 0x8000) != 0 && emu->x86.R_DX == 0xFF)) { 7688 1.1 joerg CLEAR_FLAG(F_CF); 7689 1.1 joerg CLEAR_FLAG(F_OF); 7690 1.1 joerg } else { 7691 1.1 joerg SET_FLAG(F_CF); 7692 1.1 joerg SET_FLAG(F_OF); 7693 1.1 joerg } 7694 1.1 joerg } 7695 1.1 joerg /**************************************************************************** 7696 1.1 joerg REMARKS: 7697 1.1 joerg Implements the IMUL instruction and side effects. 7698 1.1 joerg ****************************************************************************/ 7699 1.1 joerg static void 7700 1.1 joerg imul_long(struct X86EMU *emu, uint32_t s) 7701 1.1 joerg { 7702 1.1 joerg int64_t res; 7703 1.1 joerg 7704 1.1 joerg res = (int64_t)(int32_t)emu->x86.R_EAX * (int32_t)s; 7705 1.1 joerg emu->x86.R_EAX = (uint32_t)res; 7706 1.1 joerg emu->x86.R_EDX = ((uint64_t)res) >> 32; 7707 1.1 joerg if (((emu->x86.R_EAX & 0x80000000) == 0 && emu->x86.R_EDX == 0x00) || 7708 1.1 joerg ((emu->x86.R_EAX & 0x80000000) != 0 && emu->x86.R_EDX == 0xFF)) { 7709 1.1 joerg CLEAR_FLAG(F_CF); 7710 1.1 joerg CLEAR_FLAG(F_OF); 7711 1.1 joerg } else { 7712 1.1 joerg SET_FLAG(F_CF); 7713 1.1 joerg SET_FLAG(F_OF); 7714 1.1 joerg } 7715 1.1 joerg } 7716 1.1 joerg /**************************************************************************** 7717 1.1 joerg REMARKS: 7718 1.1 joerg Implements the MUL instruction and side effects. 7719 1.1 joerg ****************************************************************************/ 7720 1.1 joerg static void 7721 1.1 joerg mul_byte(struct X86EMU *emu, uint8_t s) 7722 1.1 joerg { 7723 1.1 joerg uint16_t res = (uint16_t) (emu->x86.R_AL * s); 7724 1.1 joerg 7725 1.1 joerg emu->x86.R_AX = res; 7726 1.1 joerg if (emu->x86.R_AH == 0) { 7727 1.1 joerg CLEAR_FLAG(F_CF); 7728 1.1 joerg CLEAR_FLAG(F_OF); 7729 1.1 joerg } else { 7730 1.1 joerg SET_FLAG(F_CF); 7731 1.1 joerg SET_FLAG(F_OF); 7732 1.1 joerg } 7733 1.1 joerg } 7734 1.1 joerg /**************************************************************************** 7735 1.1 joerg REMARKS: 7736 1.1 joerg Implements the MUL instruction and side effects. 7737 1.1 joerg ****************************************************************************/ 7738 1.1 joerg static void 7739 1.1 joerg mul_word(struct X86EMU *emu, uint16_t s) 7740 1.1 joerg { 7741 1.1 joerg uint32_t res = emu->x86.R_AX * s; 7742 1.1 joerg 7743 1.1 joerg emu->x86.R_AX = (uint16_t) res; 7744 1.1 joerg emu->x86.R_DX = (uint16_t) (res >> 16); 7745 1.1 joerg if (emu->x86.R_DX == 0) { 7746 1.1 joerg CLEAR_FLAG(F_CF); 7747 1.1 joerg CLEAR_FLAG(F_OF); 7748 1.1 joerg } else { 7749 1.1 joerg SET_FLAG(F_CF); 7750 1.1 joerg SET_FLAG(F_OF); 7751 1.1 joerg } 7752 1.1 joerg } 7753 1.1 joerg /**************************************************************************** 7754 1.1 joerg REMARKS: 7755 1.1 joerg Implements the MUL instruction and side effects. 7756 1.1 joerg ****************************************************************************/ 7757 1.1 joerg static void 7758 1.1 joerg mul_long(struct X86EMU *emu, uint32_t s) 7759 1.1 joerg { 7760 1.1 joerg uint64_t res = (uint64_t) emu->x86.R_EAX * s; 7761 1.1 joerg 7762 1.1 joerg emu->x86.R_EAX = (uint32_t) res; 7763 1.1 joerg emu->x86.R_EDX = (uint32_t) (res >> 32); 7764 1.1 joerg 7765 1.1 joerg if (emu->x86.R_EDX == 0) { 7766 1.1 joerg CLEAR_FLAG(F_CF); 7767 1.1 joerg CLEAR_FLAG(F_OF); 7768 1.1 joerg } else { 7769 1.1 joerg SET_FLAG(F_CF); 7770 1.1 joerg SET_FLAG(F_OF); 7771 1.1 joerg } 7772 1.1 joerg } 7773 1.1 joerg /**************************************************************************** 7774 1.1 joerg REMARKS: 7775 1.1 joerg Implements the IDIV instruction and side effects. 7776 1.1 joerg ****************************************************************************/ 7777 1.1 joerg static void 7778 1.1 joerg idiv_byte(struct X86EMU *emu, uint8_t s) 7779 1.1 joerg { 7780 1.1 joerg int32_t dvd, div, mod; 7781 1.1 joerg 7782 1.1 joerg dvd = (int16_t) emu->x86.R_AX; 7783 1.1 joerg if (s == 0) { 7784 1.5 joerg x86emu_intr_raise(emu, 8); 7785 1.1 joerg return; 7786 1.1 joerg } 7787 1.1 joerg div = dvd / (int8_t) s; 7788 1.1 joerg mod = dvd % (int8_t) s; 7789 1.1 joerg if (div > 0x7f || div < -0x7f) { 7790 1.5 joerg x86emu_intr_raise(emu, 8); 7791 1.1 joerg return; 7792 1.1 joerg } 7793 1.1 joerg emu->x86.R_AL = (int8_t) div; 7794 1.1 joerg emu->x86.R_AH = (int8_t) mod; 7795 1.1 joerg } 7796 1.1 joerg /**************************************************************************** 7797 1.1 joerg REMARKS: 7798 1.1 joerg Implements the IDIV instruction and side effects. 7799 1.1 joerg ****************************************************************************/ 7800 1.1 joerg static void 7801 1.1 joerg idiv_word(struct X86EMU *emu, uint16_t s) 7802 1.1 joerg { 7803 1.1 joerg int32_t dvd, div, mod; 7804 1.1 joerg 7805 1.1 joerg dvd = (((int32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX; 7806 1.1 joerg if (s == 0) { 7807 1.5 joerg x86emu_intr_raise(emu, 8); 7808 1.1 joerg return; 7809 1.1 joerg } 7810 1.1 joerg div = dvd / (int16_t) s; 7811 1.1 joerg mod = dvd % (int16_t) s; 7812 1.1 joerg if (div > 0x7fff || div < -0x7fff) { 7813 1.5 joerg x86emu_intr_raise(emu, 8); 7814 1.1 joerg return; 7815 1.1 joerg } 7816 1.1 joerg CLEAR_FLAG(F_CF); 7817 1.1 joerg CLEAR_FLAG(F_SF); 7818 1.1 joerg CONDITIONAL_SET_FLAG(div == 0, F_ZF); 7819 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 7820 1.1 joerg 7821 1.1 joerg emu->x86.R_AX = (uint16_t) div; 7822 1.1 joerg emu->x86.R_DX = (uint16_t) mod; 7823 1.1 joerg } 7824 1.1 joerg /**************************************************************************** 7825 1.1 joerg REMARKS: 7826 1.1 joerg Implements the IDIV instruction and side effects. 7827 1.1 joerg ****************************************************************************/ 7828 1.1 joerg static void 7829 1.1 joerg idiv_long(struct X86EMU *emu, uint32_t s) 7830 1.1 joerg { 7831 1.1 joerg int64_t dvd, div, mod; 7832 1.1 joerg 7833 1.1 joerg dvd = (((int64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX; 7834 1.1 joerg if (s == 0) { 7835 1.5 joerg x86emu_intr_raise(emu, 8); 7836 1.1 joerg return; 7837 1.1 joerg } 7838 1.1 joerg div = dvd / (int32_t) s; 7839 1.1 joerg mod = dvd % (int32_t) s; 7840 1.1 joerg if (div > 0x7fffffff || div < -0x7fffffff) { 7841 1.5 joerg x86emu_intr_raise(emu, 8); 7842 1.1 joerg return; 7843 1.1 joerg } 7844 1.1 joerg CLEAR_FLAG(F_CF); 7845 1.1 joerg CLEAR_FLAG(F_AF); 7846 1.1 joerg CLEAR_FLAG(F_SF); 7847 1.1 joerg SET_FLAG(F_ZF); 7848 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 7849 1.1 joerg 7850 1.1 joerg emu->x86.R_EAX = (uint32_t) div; 7851 1.1 joerg emu->x86.R_EDX = (uint32_t) mod; 7852 1.1 joerg } 7853 1.1 joerg /**************************************************************************** 7854 1.1 joerg REMARKS: 7855 1.1 joerg Implements the DIV instruction and side effects. 7856 1.1 joerg ****************************************************************************/ 7857 1.1 joerg static void 7858 1.1 joerg div_byte(struct X86EMU *emu, uint8_t s) 7859 1.1 joerg { 7860 1.1 joerg uint32_t dvd, div, mod; 7861 1.1 joerg 7862 1.1 joerg dvd = emu->x86.R_AX; 7863 1.1 joerg if (s == 0) { 7864 1.5 joerg x86emu_intr_raise(emu, 8); 7865 1.1 joerg return; 7866 1.1 joerg } 7867 1.1 joerg div = dvd / (uint8_t) s; 7868 1.1 joerg mod = dvd % (uint8_t) s; 7869 1.1 joerg if (div > 0xff) { 7870 1.5 joerg x86emu_intr_raise(emu, 8); 7871 1.1 joerg return; 7872 1.1 joerg } 7873 1.1 joerg emu->x86.R_AL = (uint8_t) div; 7874 1.1 joerg emu->x86.R_AH = (uint8_t) mod; 7875 1.1 joerg } 7876 1.1 joerg /**************************************************************************** 7877 1.1 joerg REMARKS: 7878 1.1 joerg Implements the DIV instruction and side effects. 7879 1.1 joerg ****************************************************************************/ 7880 1.1 joerg static void 7881 1.1 joerg div_word(struct X86EMU *emu, uint16_t s) 7882 1.1 joerg { 7883 1.1 joerg uint32_t dvd, div, mod; 7884 1.1 joerg 7885 1.1 joerg dvd = (((uint32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX; 7886 1.1 joerg if (s == 0) { 7887 1.5 joerg x86emu_intr_raise(emu, 8); 7888 1.1 joerg return; 7889 1.1 joerg } 7890 1.1 joerg div = dvd / (uint16_t) s; 7891 1.1 joerg mod = dvd % (uint16_t) s; 7892 1.1 joerg if (div > 0xffff) { 7893 1.5 joerg x86emu_intr_raise(emu, 8); 7894 1.1 joerg return; 7895 1.1 joerg } 7896 1.1 joerg CLEAR_FLAG(F_CF); 7897 1.1 joerg CLEAR_FLAG(F_SF); 7898 1.1 joerg CONDITIONAL_SET_FLAG(div == 0, F_ZF); 7899 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 7900 1.1 joerg 7901 1.1 joerg emu->x86.R_AX = (uint16_t) div; 7902 1.1 joerg emu->x86.R_DX = (uint16_t) mod; 7903 1.1 joerg } 7904 1.1 joerg /**************************************************************************** 7905 1.1 joerg REMARKS: 7906 1.1 joerg Implements the DIV instruction and side effects. 7907 1.1 joerg ****************************************************************************/ 7908 1.1 joerg static void 7909 1.1 joerg div_long(struct X86EMU *emu, uint32_t s) 7910 1.1 joerg { 7911 1.1 joerg uint64_t dvd, div, mod; 7912 1.1 joerg 7913 1.1 joerg dvd = (((uint64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX; 7914 1.1 joerg if (s == 0) { 7915 1.5 joerg x86emu_intr_raise(emu, 8); 7916 1.1 joerg return; 7917 1.1 joerg } 7918 1.1 joerg div = dvd / (uint32_t) s; 7919 1.1 joerg mod = dvd % (uint32_t) s; 7920 1.1 joerg if (div > 0xffffffff) { 7921 1.5 joerg x86emu_intr_raise(emu, 8); 7922 1.1 joerg return; 7923 1.1 joerg } 7924 1.1 joerg CLEAR_FLAG(F_CF); 7925 1.1 joerg CLEAR_FLAG(F_AF); 7926 1.1 joerg CLEAR_FLAG(F_SF); 7927 1.1 joerg SET_FLAG(F_ZF); 7928 1.1 joerg CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); 7929 1.1 joerg 7930 1.1 joerg emu->x86.R_EAX = (uint32_t) div; 7931 1.1 joerg emu->x86.R_EDX = (uint32_t) mod; 7932 1.1 joerg } 7933 1.1 joerg /**************************************************************************** 7934 1.1 joerg REMARKS: 7935 1.1 joerg Implements the IN string instruction and side effects. 7936 1.1 joerg ****************************************************************************/ 7937 1.1 joerg static void 7938 1.1 joerg ins(struct X86EMU *emu, int size) 7939 1.1 joerg { 7940 1.1 joerg int inc = size; 7941 1.1 joerg 7942 1.1 joerg if (ACCESS_FLAG(F_DF)) { 7943 1.1 joerg inc = -size; 7944 1.1 joerg } 7945 1.1 joerg if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 7946 1.1 joerg /* dont care whether REPE or REPNE */ 7947 1.1 joerg /* in until CX is ZERO. */ 7948 1.1 joerg uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ? 7949 1.1 joerg emu->x86.R_ECX : emu->x86.R_CX); 7950 1.1 joerg switch (size) { 7951 1.1 joerg case 1: 7952 1.1 joerg while (count--) { 7953 1.1 joerg store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, 7954 1.1 joerg (*emu->emu_inb) (emu, emu->x86.R_DX)); 7955 1.1 joerg emu->x86.R_DI += inc; 7956 1.1 joerg } 7957 1.1 joerg break; 7958 1.1 joerg 7959 1.1 joerg case 2: 7960 1.1 joerg while (count--) { 7961 1.1 joerg store_word(emu, emu->x86.R_ES, emu->x86.R_DI, 7962 1.1 joerg (*emu->emu_inw) (emu, emu->x86.R_DX)); 7963 1.1 joerg emu->x86.R_DI += inc; 7964 1.1 joerg } 7965 1.1 joerg break; 7966 1.1 joerg case 4: 7967 1.1 joerg while (count--) { 7968 1.1 joerg store_long(emu, emu->x86.R_ES, emu->x86.R_DI, 7969 1.1 joerg (*emu->emu_inl) (emu, emu->x86.R_DX)); 7970 1.1 joerg emu->x86.R_DI += inc; 7971 1.1 joerg break; 7972 1.1 joerg } 7973 1.1 joerg } 7974 1.1 joerg emu->x86.R_CX = 0; 7975 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 7976 1.1 joerg emu->x86.R_ECX = 0; 7977 1.1 joerg } 7978 1.1 joerg emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 7979 1.1 joerg } else { 7980 1.1 joerg switch (size) { 7981 1.1 joerg case 1: 7982 1.1 joerg store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, 7983 1.1 joerg (*emu->emu_inb) (emu, emu->x86.R_DX)); 7984 1.1 joerg break; 7985 1.1 joerg case 2: 7986 1.1 joerg store_word(emu, emu->x86.R_ES, emu->x86.R_DI, 7987 1.1 joerg (*emu->emu_inw) (emu, emu->x86.R_DX)); 7988 1.1 joerg break; 7989 1.1 joerg case 4: 7990 1.1 joerg store_long(emu, emu->x86.R_ES, emu->x86.R_DI, 7991 1.1 joerg (*emu->emu_inl) (emu, emu->x86.R_DX)); 7992 1.1 joerg break; 7993 1.1 joerg } 7994 1.1 joerg emu->x86.R_DI += inc; 7995 1.1 joerg } 7996 1.1 joerg } 7997 1.1 joerg /**************************************************************************** 7998 1.1 joerg REMARKS: 7999 1.1 joerg Implements the OUT string instruction and side effects. 8000 1.1 joerg ****************************************************************************/ 8001 1.1 joerg static void 8002 1.1 joerg outs(struct X86EMU *emu, int size) 8003 1.1 joerg { 8004 1.1 joerg int inc = size; 8005 1.1 joerg 8006 1.1 joerg if (ACCESS_FLAG(F_DF)) { 8007 1.1 joerg inc = -size; 8008 1.1 joerg } 8009 1.1 joerg if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { 8010 1.1 joerg /* dont care whether REPE or REPNE */ 8011 1.1 joerg /* out until CX is ZERO. */ 8012 1.1 joerg uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ? 8013 1.1 joerg emu->x86.R_ECX : emu->x86.R_CX); 8014 1.1 joerg switch (size) { 8015 1.1 joerg case 1: 8016 1.1 joerg while (count--) { 8017 1.1 joerg (*emu->emu_outb) (emu, emu->x86.R_DX, 8018 1.1 joerg fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI)); 8019 1.1 joerg emu->x86.R_SI += inc; 8020 1.1 joerg } 8021 1.1 joerg break; 8022 1.1 joerg 8023 1.1 joerg case 2: 8024 1.1 joerg while (count--) { 8025 1.1 joerg (*emu->emu_outw) (emu, emu->x86.R_DX, 8026 1.1 joerg fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI)); 8027 1.1 joerg emu->x86.R_SI += inc; 8028 1.1 joerg } 8029 1.1 joerg break; 8030 1.1 joerg case 4: 8031 1.1 joerg while (count--) { 8032 1.1 joerg (*emu->emu_outl) (emu, emu->x86.R_DX, 8033 1.1 joerg fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI)); 8034 1.1 joerg emu->x86.R_SI += inc; 8035 1.1 joerg break; 8036 1.1 joerg } 8037 1.1 joerg } 8038 1.1 joerg emu->x86.R_CX = 0; 8039 1.1 joerg if (emu->x86.mode & SYSMODE_PREFIX_DATA) { 8040 1.1 joerg emu->x86.R_ECX = 0; 8041 1.1 joerg } 8042 1.1 joerg emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); 8043 1.1 joerg } else { 8044 1.1 joerg switch (size) { 8045 1.1 joerg case 1: 8046 1.1 joerg (*emu->emu_outb) (emu, emu->x86.R_DX, 8047 1.1 joerg fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI)); 8048 1.1 joerg break; 8049 1.1 joerg case 2: 8050 1.1 joerg (*emu->emu_outw) (emu, emu->x86.R_DX, 8051 1.1 joerg fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI)); 8052 1.1 joerg break; 8053 1.1 joerg case 4: 8054 1.1 joerg (*emu->emu_outl) (emu, emu->x86.R_DX, 8055 1.1 joerg fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI)); 8056 1.1 joerg break; 8057 1.1 joerg } 8058 1.1 joerg emu->x86.R_SI += inc; 8059 1.1 joerg } 8060 1.1 joerg } 8061 1.1 joerg /**************************************************************************** 8062 1.1 joerg REMARKS: 8063 1.1 joerg Pushes a word onto the stack. 8064 1.1 joerg 8065 1.1 joerg NOTE: Do not inline this, as (*emu->emu_wrX) is already inline! 8066 1.1 joerg ****************************************************************************/ 8067 1.1 joerg static void 8068 1.1 joerg push_word(struct X86EMU *emu, uint16_t w) 8069 1.1 joerg { 8070 1.1 joerg emu->x86.R_SP -= 2; 8071 1.1 joerg store_word(emu, emu->x86.R_SS, emu->x86.R_SP, w); 8072 1.1 joerg } 8073 1.1 joerg /**************************************************************************** 8074 1.1 joerg REMARKS: 8075 1.1 joerg Pushes a long onto the stack. 8076 1.1 joerg 8077 1.1 joerg NOTE: Do not inline this, as (*emu->emu_wrX) is already inline! 8078 1.1 joerg ****************************************************************************/ 8079 1.1 joerg static void 8080 1.1 joerg push_long(struct X86EMU *emu, uint32_t w) 8081 1.1 joerg { 8082 1.1 joerg emu->x86.R_SP -= 4; 8083 1.1 joerg store_long(emu, emu->x86.R_SS, emu->x86.R_SP, w); 8084 1.1 joerg } 8085 1.1 joerg /**************************************************************************** 8086 1.1 joerg REMARKS: 8087 1.1 joerg Pops a word from the stack. 8088 1.1 joerg 8089 1.1 joerg NOTE: Do not inline this, as (*emu->emu_rdX) is already inline! 8090 1.1 joerg ****************************************************************************/ 8091 1.1 joerg static uint16_t 8092 1.1 joerg pop_word(struct X86EMU *emu) 8093 1.1 joerg { 8094 1.1 joerg uint16_t res; 8095 1.1 joerg 8096 1.1 joerg res = fetch_word(emu, emu->x86.R_SS, emu->x86.R_SP); 8097 1.1 joerg emu->x86.R_SP += 2; 8098 1.1 joerg return res; 8099 1.1 joerg } 8100 1.1 joerg /**************************************************************************** 8101 1.1 joerg REMARKS: 8102 1.1 joerg Pops a long from the stack. 8103 1.1 joerg 8104 1.1 joerg NOTE: Do not inline this, as (*emu->emu_rdX) is already inline! 8105 1.1 joerg ****************************************************************************/ 8106 1.1 joerg static uint32_t 8107 1.1 joerg pop_long(struct X86EMU *emu) 8108 1.1 joerg { 8109 1.1 joerg uint32_t res; 8110 1.1 joerg 8111 1.1 joerg res = fetch_long(emu, emu->x86.R_SS, emu->x86.R_SP); 8112 1.1 joerg emu->x86.R_SP += 4; 8113 1.1 joerg return res; 8114 1.1 joerg } 8115