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