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