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