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