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