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