xref: /freebsd/sys/contrib/x86emu/x86emu.c (revision cc68614da8232d8baaca0ae0d0dd8f890f06623e)
1 /*	$OpenBSD: x86emu.c,v 1.9 2014/06/15 11:04:49 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 	uint32_t destoffset;
2155 
2156 	fetch_decode_modrm(emu);
2157 	if (emu->cur_mod == 3)
2158 		x86emu_halt_sys(emu);
2159 
2160 	destoffset = decode_rl_address(emu);
2161 	if (emu->x86.mode & SYSMODE_PREFIX_ADDR) {
2162 		uint32_t *srcreg;
2163 
2164 		srcreg = decode_rh_long_register(emu);
2165 		*srcreg = (uint32_t) destoffset;
2166 	} else {
2167 		uint16_t *srcreg;
2168 
2169 		srcreg = decode_rh_word_register(emu);
2170 		*srcreg = (uint16_t) destoffset;
2171 	}
2172 }
2173 
2174 /*
2175  * REMARKS:
2176  * Handles opcode 0x8e
2177  */
2178 static void
2179 x86emuOp_mov_word_SR_RM(struct x86emu *emu)
2180 {
2181 	uint16_t *destreg;
2182 
2183 	fetch_decode_modrm(emu);
2184 	destreg = decode_rh_seg_register(emu);
2185 	*destreg = decode_and_fetch_word(emu);
2186 	/*
2187          * Clean up, and reset all the R_xSP pointers to the correct
2188          * locations.  This is about 3x too much overhead (doing all the
2189          * segreg ptrs when only one is needed, but this instruction
2190          * *cannot* be that common, and this isn't too much work anyway.
2191          */
2192 }
2193 
2194 /*
2195  * REMARKS:
2196  * Handles opcode 0x8f
2197  */
2198 static void
2199 x86emuOp32_pop_RM(struct x86emu *emu)
2200 {
2201 	uint32_t destoffset;
2202 	uint32_t destval, *destreg;
2203 
2204 	fetch_decode_modrm(emu);
2205 	if (emu->cur_mod != 3) {
2206 		destoffset = decode_rl_address(emu);
2207 		destval = pop_long(emu);
2208 		store_data_long(emu, destoffset, destval);
2209 	} else {
2210 		destreg = decode_rl_long_register(emu);
2211 		*destreg = pop_long(emu);
2212 	}
2213 }
2214 
2215 static void
2216 x86emuOp16_pop_RM(struct x86emu *emu)
2217 {
2218 	uint32_t destoffset;
2219 	uint16_t destval, *destreg;
2220 
2221 	fetch_decode_modrm(emu);
2222 	if (emu->cur_mod != 3) {
2223 		destoffset = decode_rl_address(emu);
2224 		destval = pop_word(emu);
2225 		store_data_word(emu, destoffset, destval);
2226 	} else {
2227 		destreg = decode_rl_word_register(emu);
2228 		*destreg = pop_word(emu);
2229 	}
2230 }
2231 
2232 static void
2233 x86emuOp_pop_RM(struct x86emu *emu)
2234 {
2235 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2236 		x86emuOp32_pop_RM(emu);
2237 	else
2238 		x86emuOp16_pop_RM(emu);
2239 }
2240 
2241 /*
2242  * REMARKS:
2243  * Handles opcode 0x91
2244  */
2245 static void
2246 x86emuOp_xchg_word_AX_CX(struct x86emu *emu)
2247 {
2248 	uint32_t tmp;
2249 
2250 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2251 		tmp = emu->x86.R_EAX;
2252 		emu->x86.R_EAX = emu->x86.R_ECX;
2253 		emu->x86.R_ECX = tmp;
2254 	} else {
2255 		tmp = emu->x86.R_AX;
2256 		emu->x86.R_AX = emu->x86.R_CX;
2257 		emu->x86.R_CX = (uint16_t) tmp;
2258 	}
2259 }
2260 
2261 /*
2262  * REMARKS:
2263  * Handles opcode 0x92
2264  */
2265 static void
2266 x86emuOp_xchg_word_AX_DX(struct x86emu *emu)
2267 {
2268 	uint32_t tmp;
2269 
2270 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2271 		tmp = emu->x86.R_EAX;
2272 		emu->x86.R_EAX = emu->x86.R_EDX;
2273 		emu->x86.R_EDX = tmp;
2274 	} else {
2275 		tmp = emu->x86.R_AX;
2276 		emu->x86.R_AX = emu->x86.R_DX;
2277 		emu->x86.R_DX = (uint16_t) tmp;
2278 	}
2279 }
2280 
2281 /*
2282  * REMARKS:
2283  * Handles opcode 0x93
2284  */
2285 static void
2286 x86emuOp_xchg_word_AX_BX(struct x86emu *emu)
2287 {
2288 	uint32_t tmp;
2289 
2290 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2291 		tmp = emu->x86.R_EAX;
2292 		emu->x86.R_EAX = emu->x86.R_EBX;
2293 		emu->x86.R_EBX = tmp;
2294 	} else {
2295 		tmp = emu->x86.R_AX;
2296 		emu->x86.R_AX = emu->x86.R_BX;
2297 		emu->x86.R_BX = (uint16_t) tmp;
2298 	}
2299 }
2300 
2301 /*
2302  * REMARKS:
2303  * Handles opcode 0x94
2304  */
2305 static void
2306 x86emuOp_xchg_word_AX_SP(struct x86emu *emu)
2307 {
2308 	uint32_t tmp;
2309 
2310 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2311 		tmp = emu->x86.R_EAX;
2312 		emu->x86.R_EAX = emu->x86.R_ESP;
2313 		emu->x86.R_ESP = tmp;
2314 	} else {
2315 		tmp = emu->x86.R_AX;
2316 		emu->x86.R_AX = emu->x86.R_SP;
2317 		emu->x86.R_SP = (uint16_t) tmp;
2318 	}
2319 }
2320 
2321 /*
2322  * REMARKS:
2323  * Handles opcode 0x95
2324  */
2325 static void
2326 x86emuOp_xchg_word_AX_BP(struct x86emu *emu)
2327 {
2328 	uint32_t tmp;
2329 
2330 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2331 		tmp = emu->x86.R_EAX;
2332 		emu->x86.R_EAX = emu->x86.R_EBP;
2333 		emu->x86.R_EBP = tmp;
2334 	} else {
2335 		tmp = emu->x86.R_AX;
2336 		emu->x86.R_AX = emu->x86.R_BP;
2337 		emu->x86.R_BP = (uint16_t) tmp;
2338 	}
2339 }
2340 
2341 /*
2342  * REMARKS:
2343  * Handles opcode 0x96
2344  */
2345 static void
2346 x86emuOp_xchg_word_AX_SI(struct x86emu *emu)
2347 {
2348 	uint32_t tmp;
2349 
2350 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2351 		tmp = emu->x86.R_EAX;
2352 		emu->x86.R_EAX = emu->x86.R_ESI;
2353 		emu->x86.R_ESI = tmp;
2354 	} else {
2355 		tmp = emu->x86.R_AX;
2356 		emu->x86.R_AX = emu->x86.R_SI;
2357 		emu->x86.R_SI = (uint16_t) tmp;
2358 	}
2359 }
2360 
2361 /*
2362  * REMARKS:
2363  * Handles opcode 0x97
2364  */
2365 static void
2366 x86emuOp_xchg_word_AX_DI(struct x86emu *emu)
2367 {
2368 	uint32_t tmp;
2369 
2370 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2371 		tmp = emu->x86.R_EAX;
2372 		emu->x86.R_EAX = emu->x86.R_EDI;
2373 		emu->x86.R_EDI = tmp;
2374 	} else {
2375 		tmp = emu->x86.R_AX;
2376 		emu->x86.R_AX = emu->x86.R_DI;
2377 		emu->x86.R_DI = (uint16_t) tmp;
2378 	}
2379 }
2380 
2381 /*
2382  * REMARKS:
2383  * Handles opcode 0x98
2384  */
2385 static void
2386 x86emuOp_cbw(struct x86emu *emu)
2387 {
2388 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2389 		if (emu->x86.R_AX & 0x8000) {
2390 			emu->x86.R_EAX |= 0xffff0000;
2391 		} else {
2392 			emu->x86.R_EAX &= 0x0000ffff;
2393 		}
2394 	} else {
2395 		if (emu->x86.R_AL & 0x80) {
2396 			emu->x86.R_AH = 0xff;
2397 		} else {
2398 			emu->x86.R_AH = 0x0;
2399 		}
2400 	}
2401 }
2402 
2403 /*
2404  * REMARKS:
2405  * Handles opcode 0x99
2406  */
2407 static void
2408 x86emuOp_cwd(struct x86emu *emu)
2409 {
2410 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2411 		if (emu->x86.R_EAX & 0x80000000) {
2412 			emu->x86.R_EDX = 0xffffffff;
2413 		} else {
2414 			emu->x86.R_EDX = 0x0;
2415 		}
2416 	} else {
2417 		if (emu->x86.R_AX & 0x8000) {
2418 			emu->x86.R_DX = 0xffff;
2419 		} else {
2420 			emu->x86.R_DX = 0x0;
2421 		}
2422 	}
2423 }
2424 
2425 /*
2426  * REMARKS:
2427  * Handles opcode 0x9a
2428  */
2429 static void
2430 x86emuOp_call_far_IMM(struct x86emu *emu)
2431 {
2432 	uint16_t farseg, faroff;
2433 
2434 	faroff = fetch_word_imm(emu);
2435 	farseg = fetch_word_imm(emu);
2436 	/* XXX
2437 	 *
2438 	 * Hooked interrupt vectors calling into our "BIOS" will cause problems
2439 	 * unless all intersegment stuff is checked for BIOS access.  Check
2440 	 * needed here.  For moment, let it alone. */
2441 	push_word(emu, emu->x86.R_CS);
2442 	emu->x86.R_CS = farseg;
2443 	push_word(emu, emu->x86.R_IP);
2444 	emu->x86.R_IP = faroff;
2445 }
2446 
2447 /*
2448  * REMARKS:
2449  * Handles opcode 0x9c
2450  */
2451 static void
2452 x86emuOp_pushf_word(struct x86emu *emu)
2453 {
2454 	uint32_t flags;
2455 
2456 	/* clear out *all* bits not representing flags, and turn on real bits */
2457 	flags = (emu->x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2458 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2459 		push_long(emu, flags);
2460 	} else {
2461 		push_word(emu, (uint16_t) flags);
2462 	}
2463 }
2464 
2465 /*
2466  * REMARKS:
2467  * Handles opcode 0x9d
2468  */
2469 static void
2470 x86emuOp_popf_word(struct x86emu *emu)
2471 {
2472 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2473 		emu->x86.R_EFLG = pop_long(emu);
2474 	} else {
2475 		emu->x86.R_FLG = pop_word(emu);
2476 	}
2477 }
2478 
2479 /*
2480  * REMARKS:
2481  * Handles opcode 0x9e
2482  */
2483 static void
2484 x86emuOp_sahf(struct x86emu *emu)
2485 {
2486 	/* clear the lower bits of the flag register */
2487 	emu->x86.R_FLG &= 0xffffff00;
2488 	/* or in the AH register into the flags register */
2489 	emu->x86.R_FLG |= emu->x86.R_AH;
2490 }
2491 
2492 /*
2493  * REMARKS:
2494  * Handles opcode 0x9f
2495  */
2496 static void
2497 x86emuOp_lahf(struct x86emu *emu)
2498 {
2499 	emu->x86.R_AH = (uint8_t) (emu->x86.R_FLG & 0xff);
2500 	/* undocumented TC++ behavior??? Nope.  It's documented, but you have
2501 	 * too look real hard to notice it. */
2502 	emu->x86.R_AH |= 0x2;
2503 }
2504 
2505 /*
2506  * REMARKS:
2507  * Handles opcode 0xa0
2508  */
2509 static void
2510 x86emuOp_mov_AL_M_IMM(struct x86emu *emu)
2511 {
2512 	uint16_t offset;
2513 
2514 	offset = fetch_word_imm(emu);
2515 	emu->x86.R_AL = fetch_data_byte(emu, offset);
2516 }
2517 
2518 /*
2519  * REMARKS:
2520  * Handles opcode 0xa1
2521  */
2522 static void
2523 x86emuOp_mov_AX_M_IMM(struct x86emu *emu)
2524 {
2525 	uint16_t offset;
2526 
2527 	offset = fetch_word_imm(emu);
2528 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2529 		emu->x86.R_EAX = fetch_data_long(emu, offset);
2530 	} else {
2531 		emu->x86.R_AX = fetch_data_word(emu, offset);
2532 	}
2533 }
2534 
2535 /*
2536  * REMARKS:
2537  * Handles opcode 0xa2
2538  */
2539 static void
2540 x86emuOp_mov_M_AL_IMM(struct x86emu *emu)
2541 {
2542 	uint16_t offset;
2543 
2544 	offset = fetch_word_imm(emu);
2545 	store_data_byte(emu, offset, emu->x86.R_AL);
2546 }
2547 
2548 /*
2549  * REMARKS:
2550  * Handles opcode 0xa3
2551  */
2552 static void
2553 x86emuOp_mov_M_AX_IMM(struct x86emu *emu)
2554 {
2555 	uint16_t offset;
2556 
2557 	offset = fetch_word_imm(emu);
2558 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2559 		store_data_long(emu, offset, emu->x86.R_EAX);
2560 	} else {
2561 		store_data_word(emu, offset, emu->x86.R_AX);
2562 	}
2563 }
2564 
2565 /*
2566  * REMARKS:
2567  * Handles opcode 0xa4
2568  */
2569 static void
2570 x86emuOp_movs_byte(struct x86emu *emu)
2571 {
2572 	uint8_t val;
2573 	uint32_t count;
2574 	int inc;
2575 
2576 	if (ACCESS_FLAG(F_DF))	/* down */
2577 		inc = -1;
2578 	else
2579 		inc = 1;
2580 	count = 1;
2581 	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2582 		/* dont care whether REPE or REPNE */
2583 		/* move them until CX is ZERO. */
2584 		count = emu->x86.R_CX;
2585 		emu->x86.R_CX = 0;
2586 		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2587 	}
2588 	while (count--) {
2589 		val = fetch_data_byte(emu, emu->x86.R_SI);
2590 		store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2591 		emu->x86.R_SI += inc;
2592 		emu->x86.R_DI += inc;
2593 	}
2594 }
2595 
2596 /*
2597  * REMARKS:
2598  * Handles opcode 0xa5
2599  */
2600 static void
2601 x86emuOp_movs_word(struct x86emu *emu)
2602 {
2603 	uint32_t val;
2604 	int inc;
2605 	uint32_t count;
2606 
2607 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2608 		inc = 4;
2609 	else
2610 		inc = 2;
2611 
2612 	if (ACCESS_FLAG(F_DF))	/* down */
2613 		inc = -inc;
2614 
2615 	count = 1;
2616 	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2617 		/* dont care whether REPE or REPNE */
2618 		/* move them until CX is ZERO. */
2619 		count = emu->x86.R_CX;
2620 		emu->x86.R_CX = 0;
2621 		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2622 	}
2623 	while (count--) {
2624 		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2625 			val = fetch_data_long(emu, emu->x86.R_SI);
2626 			store_long(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2627 		} else {
2628 			val = fetch_data_word(emu, emu->x86.R_SI);
2629 			store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
2630 			    (uint16_t) val);
2631 		}
2632 		emu->x86.R_SI += inc;
2633 		emu->x86.R_DI += inc;
2634 	}
2635 }
2636 
2637 /*
2638  * REMARKS:
2639  * Handles opcode 0xa6
2640  */
2641 static void
2642 x86emuOp_cmps_byte(struct x86emu *emu)
2643 {
2644 	int8_t val1, val2;
2645 	int inc;
2646 
2647 	if (ACCESS_FLAG(F_DF))	/* down */
2648 		inc = -1;
2649 	else
2650 		inc = 1;
2651 
2652 	if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2653 		/* REPE  */
2654 		/* move them until CX is ZERO. */
2655 		while (emu->x86.R_CX != 0) {
2656 			val1 = fetch_data_byte(emu, emu->x86.R_SI);
2657 			val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2658 			cmp_byte(emu, val1, val2);
2659 			emu->x86.R_CX -= 1;
2660 			emu->x86.R_SI += inc;
2661 			emu->x86.R_DI += inc;
2662 			if (ACCESS_FLAG(F_ZF) == 0)
2663 				break;
2664 		}
2665 		emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2666 	} else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2667 		/* REPNE  */
2668 		/* move them until CX is ZERO. */
2669 		while (emu->x86.R_CX != 0) {
2670 			val1 = fetch_data_byte(emu, emu->x86.R_SI);
2671 			val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2672 			cmp_byte(emu, val1, val2);
2673 			emu->x86.R_CX -= 1;
2674 			emu->x86.R_SI += inc;
2675 			emu->x86.R_DI += inc;
2676 			if (ACCESS_FLAG(F_ZF))
2677 				break;	/* zero flag set means equal */
2678 		}
2679 		emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2680 	} else {
2681 		val1 = fetch_data_byte(emu, emu->x86.R_SI);
2682 		val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2683 		cmp_byte(emu, val1, val2);
2684 		emu->x86.R_SI += inc;
2685 		emu->x86.R_DI += inc;
2686 	}
2687 }
2688 
2689 /*
2690  * REMARKS:
2691  * Handles opcode 0xa7
2692  */
2693 static void
2694 x86emuOp_cmps_word(struct x86emu *emu)
2695 {
2696 	uint32_t val1, val2;
2697 	int inc;
2698 
2699 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2700 		if (ACCESS_FLAG(F_DF))	/* down */
2701 			inc = -4;
2702 		else
2703 			inc = 4;
2704 	} else {
2705 		if (ACCESS_FLAG(F_DF))	/* down */
2706 			inc = -2;
2707 		else
2708 			inc = 2;
2709 	}
2710 	if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2711 		/* REPE  */
2712 		/* move them until CX is ZERO. */
2713 		while (emu->x86.R_CX != 0) {
2714 			if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2715 				val1 = fetch_data_long(emu, emu->x86.R_SI);
2716 				val2 = fetch_long(emu, emu->x86.R_ES,
2717 				    emu->x86.R_DI);
2718 				cmp_long(emu, val1, val2);
2719 			} else {
2720 				val1 = fetch_data_word(emu, emu->x86.R_SI);
2721 				val2 = fetch_word(emu, emu->x86.R_ES,
2722 				    emu->x86.R_DI);
2723 				cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2724 			}
2725 			emu->x86.R_CX -= 1;
2726 			emu->x86.R_SI += inc;
2727 			emu->x86.R_DI += inc;
2728 			if (ACCESS_FLAG(F_ZF) == 0)
2729 				break;
2730 		}
2731 		emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2732 	} else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2733 		/* REPNE  */
2734 		/* move them until CX is ZERO. */
2735 		while (emu->x86.R_CX != 0) {
2736 			if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2737 				val1 = fetch_data_long(emu, emu->x86.R_SI);
2738 				val2 = fetch_long(emu, emu->x86.R_ES,
2739 				    emu->x86.R_DI);
2740 				cmp_long(emu, val1, val2);
2741 			} else {
2742 				val1 = fetch_data_word(emu, emu->x86.R_SI);
2743 				val2 = fetch_word(emu, emu->x86.R_ES,
2744 				    emu->x86.R_DI);
2745 				cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2746 			}
2747 			emu->x86.R_CX -= 1;
2748 			emu->x86.R_SI += inc;
2749 			emu->x86.R_DI += inc;
2750 			if (ACCESS_FLAG(F_ZF))
2751 				break;	/* zero flag set means equal */
2752 		}
2753 		emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2754 	} else {
2755 		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2756 			val1 = fetch_data_long(emu, emu->x86.R_SI);
2757 			val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2758 			cmp_long(emu, val1, val2);
2759 		} else {
2760 			val1 = fetch_data_word(emu, emu->x86.R_SI);
2761 			val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2762 			cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2763 		}
2764 		emu->x86.R_SI += inc;
2765 		emu->x86.R_DI += inc;
2766 	}
2767 }
2768 
2769 /*
2770  * REMARKS:
2771  * Handles opcode 0xa9
2772  */
2773 static void
2774 x86emuOp_test_AX_IMM(struct x86emu *emu)
2775 {
2776 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2777 		test_long(emu, emu->x86.R_EAX, fetch_long_imm(emu));
2778 	} else {
2779 		test_word(emu, emu->x86.R_AX, fetch_word_imm(emu));
2780 	}
2781 }
2782 
2783 /*
2784  * REMARKS:
2785  * Handles opcode 0xaa
2786  */
2787 static void
2788 x86emuOp_stos_byte(struct x86emu *emu)
2789 {
2790 	int inc;
2791 
2792 	if (ACCESS_FLAG(F_DF))	/* down */
2793 		inc = -1;
2794 	else
2795 		inc = 1;
2796 	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2797 		/* dont care whether REPE or REPNE */
2798 		/* move them until CX is ZERO. */
2799 		while (emu->x86.R_CX != 0) {
2800 			store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
2801 			    emu->x86.R_AL);
2802 			emu->x86.R_CX -= 1;
2803 			emu->x86.R_DI += inc;
2804 		}
2805 		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2806 	} else {
2807 		store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL);
2808 		emu->x86.R_DI += inc;
2809 	}
2810 }
2811 
2812 /*
2813  * REMARKS:
2814  * Handles opcode 0xab
2815  */
2816 static void
2817 x86emuOp_stos_word(struct x86emu *emu)
2818 {
2819 	int inc;
2820 	uint32_t count;
2821 
2822 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2823 		inc = 4;
2824 	else
2825 		inc = 2;
2826 
2827 	if (ACCESS_FLAG(F_DF))	/* down */
2828 		inc = -inc;
2829 
2830 	count = 1;
2831 	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2832 		/* dont care whether REPE or REPNE */
2833 		/* move them until CX is ZERO. */
2834 		count = emu->x86.R_CX;
2835 		emu->x86.R_CX = 0;
2836 		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2837 	}
2838 	while (count--) {
2839 		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2840 			store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
2841 			    emu->x86.R_EAX);
2842 		} else {
2843 			store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
2844 			    emu->x86.R_AX);
2845 		}
2846 		emu->x86.R_DI += inc;
2847 	}
2848 }
2849 
2850 /*
2851  * REMARKS:
2852  * Handles opcode 0xac
2853  */
2854 static void
2855 x86emuOp_lods_byte(struct x86emu *emu)
2856 {
2857 	int inc;
2858 
2859 	if (ACCESS_FLAG(F_DF))	/* down */
2860 		inc = -1;
2861 	else
2862 		inc = 1;
2863 	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2864 		/* dont care whether REPE or REPNE */
2865 		/* move them until CX is ZERO. */
2866 		while (emu->x86.R_CX != 0) {
2867 			emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2868 			emu->x86.R_CX -= 1;
2869 			emu->x86.R_SI += inc;
2870 		}
2871 		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2872 	} else {
2873 		emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2874 		emu->x86.R_SI += inc;
2875 	}
2876 }
2877 
2878 /*
2879  * REMARKS:
2880  * Handles opcode 0xad
2881  */
2882 static void
2883 x86emuOp_lods_word(struct x86emu *emu)
2884 {
2885 	int inc;
2886 	uint32_t count;
2887 
2888 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2889 		inc = 4;
2890 	else
2891 		inc = 2;
2892 
2893 	if (ACCESS_FLAG(F_DF))	/* down */
2894 		inc = -inc;
2895 
2896 	count = 1;
2897 	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2898 		/* dont care whether REPE or REPNE */
2899 		/* move them until CX is ZERO. */
2900 		count = emu->x86.R_CX;
2901 		emu->x86.R_CX = 0;
2902 		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2903 	}
2904 	while (count--) {
2905 		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2906 			emu->x86.R_EAX = fetch_data_long(emu, emu->x86.R_SI);
2907 		} else {
2908 			emu->x86.R_AX = fetch_data_word(emu, emu->x86.R_SI);
2909 		}
2910 		emu->x86.R_SI += inc;
2911 	}
2912 }
2913 
2914 /*
2915  * REMARKS:
2916  * Handles opcode 0xae
2917  */
2918 static void
2919 x86emuOp_scas_byte(struct x86emu *emu)
2920 {
2921 	int8_t val2;
2922 	int inc;
2923 
2924 	if (ACCESS_FLAG(F_DF))	/* down */
2925 		inc = -1;
2926 	else
2927 		inc = 1;
2928 	if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2929 		/* REPE  */
2930 		/* move them until CX is ZERO. */
2931 		while (emu->x86.R_CX != 0) {
2932 			val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2933 			cmp_byte(emu, emu->x86.R_AL, val2);
2934 			emu->x86.R_CX -= 1;
2935 			emu->x86.R_DI += inc;
2936 			if (ACCESS_FLAG(F_ZF) == 0)
2937 				break;
2938 		}
2939 		emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2940 	} else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2941 		/* REPNE  */
2942 		/* move them until CX is ZERO. */
2943 		while (emu->x86.R_CX != 0) {
2944 			val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2945 			cmp_byte(emu, emu->x86.R_AL, val2);
2946 			emu->x86.R_CX -= 1;
2947 			emu->x86.R_DI += inc;
2948 			if (ACCESS_FLAG(F_ZF))
2949 				break;	/* zero flag set means equal */
2950 		}
2951 		emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2952 	} else {
2953 		val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2954 		cmp_byte(emu, emu->x86.R_AL, val2);
2955 		emu->x86.R_DI += inc;
2956 	}
2957 }
2958 
2959 /*
2960  * REMARKS:
2961  * Handles opcode 0xaf
2962  */
2963 static void
2964 x86emuOp_scas_word(struct x86emu *emu)
2965 {
2966 	int inc;
2967 	uint32_t val;
2968 
2969 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2970 		inc = 4;
2971 	else
2972 		inc = 2;
2973 
2974 	if (ACCESS_FLAG(F_DF))	/* down */
2975 		inc = -inc;
2976 
2977 	if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2978 		/* REPE  */
2979 		/* move them until CX is ZERO. */
2980 		while (emu->x86.R_CX != 0) {
2981 			if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2982 				val = fetch_long(emu, emu->x86.R_ES,
2983 				    emu->x86.R_DI);
2984 				cmp_long(emu, emu->x86.R_EAX, val);
2985 			} else {
2986 				val = fetch_word(emu, emu->x86.R_ES,
2987 				    emu->x86.R_DI);
2988 				cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
2989 			}
2990 			emu->x86.R_CX -= 1;
2991 			emu->x86.R_DI += inc;
2992 			if (ACCESS_FLAG(F_ZF) == 0)
2993 				break;
2994 		}
2995 		emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2996 	} else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2997 		/* REPNE  */
2998 		/* move them until CX is ZERO. */
2999 		while (emu->x86.R_CX != 0) {
3000 			if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3001 				val = fetch_long(emu, emu->x86.R_ES,
3002 				    emu->x86.R_DI);
3003 				cmp_long(emu, emu->x86.R_EAX, val);
3004 			} else {
3005 				val = fetch_word(emu, emu->x86.R_ES,
3006 				    emu->x86.R_DI);
3007 				cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
3008 			}
3009 			emu->x86.R_CX -= 1;
3010 			emu->x86.R_DI += inc;
3011 			if (ACCESS_FLAG(F_ZF))
3012 				break;	/* zero flag set means equal */
3013 		}
3014 		emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
3015 	} else {
3016 		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3017 			val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
3018 			cmp_long(emu, emu->x86.R_EAX, val);
3019 		} else {
3020 			val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
3021 			cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
3022 		}
3023 		emu->x86.R_DI += inc;
3024 	}
3025 }
3026 
3027 /*
3028  * REMARKS:
3029  * Handles opcode 0xb8
3030  */
3031 static void
3032 x86emuOp_mov_word_AX_IMM(struct x86emu *emu)
3033 {
3034 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3035 		emu->x86.R_EAX = fetch_long_imm(emu);
3036 	else
3037 		emu->x86.R_AX = fetch_word_imm(emu);
3038 }
3039 
3040 /*
3041  * REMARKS:
3042  * Handles opcode 0xb9
3043  */
3044 static void
3045 x86emuOp_mov_word_CX_IMM(struct x86emu *emu)
3046 {
3047 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3048 		emu->x86.R_ECX = fetch_long_imm(emu);
3049 	else
3050 		emu->x86.R_CX = fetch_word_imm(emu);
3051 }
3052 
3053 /*
3054  * REMARKS:
3055  * Handles opcode 0xba
3056  */
3057 static void
3058 x86emuOp_mov_word_DX_IMM(struct x86emu *emu)
3059 {
3060 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3061 		emu->x86.R_EDX = fetch_long_imm(emu);
3062 	else
3063 		emu->x86.R_DX = fetch_word_imm(emu);
3064 }
3065 
3066 /*
3067  * REMARKS:
3068  * Handles opcode 0xbb
3069  */
3070 static void
3071 x86emuOp_mov_word_BX_IMM(struct x86emu *emu)
3072 {
3073 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3074 		emu->x86.R_EBX = fetch_long_imm(emu);
3075 	else
3076 		emu->x86.R_BX = fetch_word_imm(emu);
3077 }
3078 
3079 /*
3080  * REMARKS:
3081  * Handles opcode 0xbc
3082  */
3083 static void
3084 x86emuOp_mov_word_SP_IMM(struct x86emu *emu)
3085 {
3086 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3087 		emu->x86.R_ESP = fetch_long_imm(emu);
3088 	else
3089 		emu->x86.R_SP = fetch_word_imm(emu);
3090 }
3091 
3092 /*
3093  * REMARKS:
3094  * Handles opcode 0xbd
3095  */
3096 static void
3097 x86emuOp_mov_word_BP_IMM(struct x86emu *emu)
3098 {
3099 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3100 		emu->x86.R_EBP = fetch_long_imm(emu);
3101 	else
3102 		emu->x86.R_BP = fetch_word_imm(emu);
3103 }
3104 
3105 /*
3106  * REMARKS:
3107  * Handles opcode 0xbe
3108  */
3109 static void
3110 x86emuOp_mov_word_SI_IMM(struct x86emu *emu)
3111 {
3112 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3113 		emu->x86.R_ESI = fetch_long_imm(emu);
3114 	else
3115 		emu->x86.R_SI = fetch_word_imm(emu);
3116 }
3117 
3118 /*
3119  * REMARKS:
3120  * Handles opcode 0xbf
3121  */
3122 static void
3123 x86emuOp_mov_word_DI_IMM(struct x86emu *emu)
3124 {
3125 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3126 		emu->x86.R_EDI = fetch_long_imm(emu);
3127 	else
3128 		emu->x86.R_DI = fetch_word_imm(emu);
3129 }
3130 /* used by opcodes c0, d0, and d2. */
3131 static
3132 uint8_t(* const opcD0_byte_operation[])
3133     (struct x86emu *, uint8_t d, uint8_t s) =
3134 {
3135 	rol_byte,
3136 	ror_byte,
3137 	rcl_byte,
3138 	rcr_byte,
3139 	shl_byte,
3140 	shr_byte,
3141 	shl_byte,		/* sal_byte === shl_byte  by definition */
3142 	sar_byte,
3143 };
3144 
3145 /*
3146  * REMARKS:
3147  * Handles opcode 0xc0
3148  */
3149 static void
3150 x86emuOp_opcC0_byte_RM_MEM(struct x86emu *emu)
3151 {
3152 	uint8_t destval, amt;
3153 
3154 	/*
3155          * Yet another weirdo special case instruction format.  Part of
3156          * the opcode held below in "RH".  Doubly nested case would
3157          * result, except that the decoded instruction
3158          */
3159 	fetch_decode_modrm(emu);
3160 	/* know operation, decode the mod byte to find the addressing mode. */
3161 	destval = decode_and_fetch_byte_imm8(emu, &amt);
3162 	destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, amt);
3163 	write_back_byte(emu, destval);
3164 }
3165 /* used by opcodes c1, d1, and d3. */
3166 static
3167 uint16_t(* const opcD1_word_operation[])
3168     (struct x86emu *, uint16_t s, uint8_t d) =
3169 {
3170 	rol_word,
3171 	ror_word,
3172 	rcl_word,
3173 	rcr_word,
3174 	shl_word,
3175 	shr_word,
3176 	shl_word,		/* sal_byte === shl_byte  by definition */
3177 	sar_word,
3178 };
3179 /* used by opcodes c1, d1, and d3. */
3180 static
3181 uint32_t(* const opcD1_long_operation[])
3182     (struct x86emu *, uint32_t s, uint8_t d) =
3183 {
3184 	rol_long,
3185 	ror_long,
3186 	rcl_long,
3187 	rcr_long,
3188 	shl_long,
3189 	shr_long,
3190 	shl_long,		/* sal_byte === shl_byte  by definition */
3191 	sar_long,
3192 };
3193 
3194 /*
3195  * REMARKS:
3196  * Handles opcode 0xc1
3197  */
3198 static void
3199 x86emuOp_opcC1_word_RM_MEM(struct x86emu *emu)
3200 {
3201 	uint8_t amt;
3202 
3203 	/*
3204          * Yet another weirdo special case instruction format.  Part of
3205          * the opcode held below in "RH".  Doubly nested case would
3206          * result, except that the decoded instruction
3207          */
3208 	fetch_decode_modrm(emu);
3209 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3210 		uint32_t destval;
3211 
3212 		destval = decode_and_fetch_long_imm8(emu, &amt);
3213 		destval = (*opcD1_long_operation[emu->cur_rh])
3214 		    (emu, destval, amt);
3215 		write_back_long(emu, destval);
3216 	} else {
3217 		uint16_t destval;
3218 
3219 		destval = decode_and_fetch_word_imm8(emu, &amt);
3220 		destval = (*opcD1_word_operation[emu->cur_rh])
3221 		    (emu, destval, amt);
3222 		write_back_word(emu, destval);
3223 	}
3224 }
3225 
3226 /*
3227  * REMARKS:
3228  * Handles opcode 0xc2
3229  */
3230 static void
3231 x86emuOp_ret_near_IMM(struct x86emu *emu)
3232 {
3233 	uint16_t imm;
3234 
3235 	imm = fetch_word_imm(emu);
3236 	emu->x86.R_IP = pop_word(emu);
3237 	emu->x86.R_SP += imm;
3238 }
3239 
3240 /*
3241  * REMARKS:
3242  * Handles opcode 0xc6
3243  */
3244 static void
3245 x86emuOp_mov_byte_RM_IMM(struct x86emu *emu)
3246 {
3247 	uint8_t *destreg;
3248 	uint32_t destoffset;
3249 	uint8_t imm;
3250 
3251 	fetch_decode_modrm(emu);
3252 	if (emu->cur_rh != 0)
3253 		x86emu_halt_sys(emu);
3254 	if (emu->cur_mod != 3) {
3255 		destoffset = decode_rl_address(emu);
3256 		imm = fetch_byte_imm(emu);
3257 		store_data_byte(emu, destoffset, imm);
3258 	} else {
3259 		destreg = decode_rl_byte_register(emu);
3260 		imm = fetch_byte_imm(emu);
3261 		*destreg = imm;
3262 	}
3263 }
3264 
3265 /*
3266  * REMARKS:
3267  * Handles opcode 0xc7
3268  */
3269 static void
3270 x86emuOp32_mov_word_RM_IMM(struct x86emu *emu)
3271 {
3272 	uint32_t destoffset;
3273 	uint32_t imm, *destreg;
3274 
3275 	fetch_decode_modrm(emu);
3276 	if (emu->cur_rh != 0)
3277 		x86emu_halt_sys(emu);
3278 
3279 	if (emu->cur_mod != 3) {
3280 		destoffset = decode_rl_address(emu);
3281 		imm = fetch_long_imm(emu);
3282 		store_data_long(emu, destoffset, imm);
3283 	} else {
3284 		destreg = decode_rl_long_register(emu);
3285 		imm = fetch_long_imm(emu);
3286 		*destreg = imm;
3287 	}
3288 }
3289 
3290 static void
3291 x86emuOp16_mov_word_RM_IMM(struct x86emu *emu)
3292 {
3293 	uint32_t destoffset;
3294 	uint16_t imm, *destreg;
3295 
3296 	fetch_decode_modrm(emu);
3297 	if (emu->cur_rh != 0)
3298 		x86emu_halt_sys(emu);
3299 
3300 	if (emu->cur_mod != 3) {
3301 		destoffset = decode_rl_address(emu);
3302 		imm = fetch_word_imm(emu);
3303 		store_data_word(emu, destoffset, imm);
3304 	} else {
3305 		destreg = decode_rl_word_register(emu);
3306 		imm = fetch_word_imm(emu);
3307 		*destreg = imm;
3308 	}
3309 }
3310 
3311 static void
3312 x86emuOp_mov_word_RM_IMM(struct x86emu *emu)
3313 {
3314 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3315 		x86emuOp32_mov_word_RM_IMM(emu);
3316 	else
3317 		x86emuOp16_mov_word_RM_IMM(emu);
3318 }
3319 
3320 /*
3321  * REMARKS:
3322  * Handles opcode 0xc8
3323  */
3324 static void
3325 x86emuOp_enter(struct x86emu *emu)
3326 {
3327 	uint16_t local, frame_pointer;
3328 	uint8_t nesting;
3329 	int i;
3330 
3331 	local = fetch_word_imm(emu);
3332 	nesting = fetch_byte_imm(emu);
3333 	push_word(emu, emu->x86.R_BP);
3334 	frame_pointer = emu->x86.R_SP;
3335 	if (nesting > 0) {
3336 		for (i = 1; i < nesting; i++) {
3337 			emu->x86.R_BP -= 2;
3338 			push_word(emu, fetch_word(emu, emu->x86.R_SS,
3339 			    emu->x86.R_BP));
3340 		}
3341 		push_word(emu, frame_pointer);
3342 	}
3343 	emu->x86.R_BP = frame_pointer;
3344 	emu->x86.R_SP = (uint16_t) (emu->x86.R_SP - local);
3345 }
3346 
3347 /*
3348  * REMARKS:
3349  * Handles opcode 0xc9
3350  */
3351 static void
3352 x86emuOp_leave(struct x86emu *emu)
3353 {
3354 	emu->x86.R_SP = emu->x86.R_BP;
3355 	emu->x86.R_BP = pop_word(emu);
3356 }
3357 
3358 /*
3359  * REMARKS:
3360  * Handles opcode 0xca
3361  */
3362 static void
3363 x86emuOp_ret_far_IMM(struct x86emu *emu)
3364 {
3365 	uint16_t imm;
3366 
3367 	imm = fetch_word_imm(emu);
3368 	emu->x86.R_IP = pop_word(emu);
3369 	emu->x86.R_CS = pop_word(emu);
3370 	emu->x86.R_SP += imm;
3371 }
3372 
3373 /*
3374  * REMARKS:
3375  * Handles opcode 0xcb
3376  */
3377 static void
3378 x86emuOp_ret_far(struct x86emu *emu)
3379 {
3380 	emu->x86.R_IP = pop_word(emu);
3381 	emu->x86.R_CS = pop_word(emu);
3382 }
3383 
3384 /*
3385  * REMARKS:
3386  * Handles opcode 0xcc
3387  */
3388 static void
3389 x86emuOp_int3(struct x86emu *emu)
3390 {
3391 	x86emu_intr_dispatch(emu, 3);
3392 }
3393 
3394 /*
3395  * REMARKS:
3396  * Handles opcode 0xcd
3397  */
3398 static void
3399 x86emuOp_int_IMM(struct x86emu *emu)
3400 {
3401 	uint8_t intnum;
3402 
3403 	intnum = fetch_byte_imm(emu);
3404 	x86emu_intr_dispatch(emu, intnum);
3405 }
3406 
3407 /*
3408  * REMARKS:
3409  * Handles opcode 0xce
3410  */
3411 static void
3412 x86emuOp_into(struct x86emu *emu)
3413 {
3414 	if (ACCESS_FLAG(F_OF))
3415 		x86emu_intr_dispatch(emu, 4);
3416 }
3417 
3418 /*
3419  * REMARKS:
3420  * Handles opcode 0xcf
3421  */
3422 static void
3423 x86emuOp_iret(struct x86emu *emu)
3424 {
3425 	emu->x86.R_IP = pop_word(emu);
3426 	emu->x86.R_CS = pop_word(emu);
3427 	emu->x86.R_FLG = pop_word(emu);
3428 }
3429 
3430 /*
3431  * REMARKS:
3432  * Handles opcode 0xd0
3433  */
3434 static void
3435 x86emuOp_opcD0_byte_RM_1(struct x86emu *emu)
3436 {
3437 	uint8_t destval;
3438 
3439 	fetch_decode_modrm(emu);
3440 	destval = decode_and_fetch_byte(emu);
3441 	destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, 1);
3442 	write_back_byte(emu, destval);
3443 }
3444 
3445 /*
3446  * REMARKS:
3447  * Handles opcode 0xd1
3448  */
3449 static void
3450 x86emuOp_opcD1_word_RM_1(struct x86emu *emu)
3451 {
3452 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3453 		uint32_t destval;
3454 
3455 		fetch_decode_modrm(emu);
3456 		destval = decode_and_fetch_long(emu);
3457 		destval = (*opcD1_long_operation[emu->cur_rh])(emu, destval, 1);
3458 		write_back_long(emu, destval);
3459 	} else {
3460 		uint16_t destval;
3461 
3462 		fetch_decode_modrm(emu);
3463 		destval = decode_and_fetch_word(emu);
3464 		destval = (*opcD1_word_operation[emu->cur_rh])(emu, destval, 1);
3465 		write_back_word(emu, destval);
3466 	}
3467 }
3468 
3469 /*
3470  * REMARKS:
3471  * Handles opcode 0xd2
3472  */
3473 static void
3474 x86emuOp_opcD2_byte_RM_CL(struct x86emu *emu)
3475 {
3476 	uint8_t destval;
3477 
3478 	fetch_decode_modrm(emu);
3479 	destval = decode_and_fetch_byte(emu);
3480 	destval = (*opcD0_byte_operation[emu->cur_rh])
3481 	    (emu, destval, emu->x86.R_CL);
3482 	write_back_byte(emu, destval);
3483 }
3484 
3485 /*
3486  * REMARKS:
3487  * Handles opcode 0xd3
3488  */
3489 static void
3490 x86emuOp_opcD3_word_RM_CL(struct x86emu *emu)
3491 {
3492 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3493 		uint32_t destval;
3494 
3495 		fetch_decode_modrm(emu);
3496 		destval = decode_and_fetch_long(emu);
3497 		destval = (*opcD1_long_operation[emu->cur_rh])
3498 		    (emu, destval, emu->x86.R_CL);
3499 		write_back_long(emu, destval);
3500 	} else {
3501 		uint16_t destval;
3502 
3503 		fetch_decode_modrm(emu);
3504 		destval = decode_and_fetch_word(emu);
3505 		destval = (*opcD1_word_operation[emu->cur_rh])
3506 		    (emu, destval, emu->x86.R_CL);
3507 		write_back_word(emu, destval);
3508 	}
3509 }
3510 
3511 /*
3512  * REMARKS:
3513  * Handles opcode 0xd4
3514  */
3515 static void
3516 x86emuOp_aam(struct x86emu *emu)
3517 {
3518 	uint8_t a;
3519 
3520 	a = fetch_byte_imm(emu);	/* this is a stupid encoding. */
3521 	if (a != 10) {
3522 		/* fix: add base decoding aam_word(uint8_t val, int base a) */
3523 		x86emu_halt_sys(emu);
3524 	}
3525 	/* note the type change here --- returning AL and AH in AX. */
3526 	emu->x86.R_AX = aam_word(emu, emu->x86.R_AL);
3527 }
3528 
3529 /*
3530  * REMARKS:
3531  * Handles opcode 0xd5
3532  */
3533 static void
3534 x86emuOp_aad(struct x86emu *emu)
3535 {
3536 	uint8_t a;
3537 
3538 	a = fetch_byte_imm(emu);
3539 	if (a != 10) {
3540 		/* fix: add base decoding aad_word(uint16_t val, int base a) */
3541 		x86emu_halt_sys(emu);
3542 	}
3543 	emu->x86.R_AX = aad_word(emu, emu->x86.R_AX);
3544 }
3545 /* opcode 0xd6 ILLEGAL OPCODE */
3546 
3547 
3548 /*
3549  * REMARKS:
3550  * Handles opcode 0xd7
3551  */
3552 static void
3553 x86emuOp_xlat(struct x86emu *emu)
3554 {
3555 	uint16_t addr;
3556 
3557 	addr = (uint16_t) (emu->x86.R_BX + (uint8_t) emu->x86.R_AL);
3558 	emu->x86.R_AL = fetch_data_byte(emu, addr);
3559 }
3560 
3561 /* opcode=0xd8 */
3562 static void
3563 x86emuOp_esc_coprocess_d8(struct x86emu *emu)
3564 {
3565 }
3566 /* opcode=0xd9 */
3567 static void
3568 x86emuOp_esc_coprocess_d9(struct x86emu *emu)
3569 {
3570 	fetch_decode_modrm(emu);
3571 	if (emu->cur_mod != 3)
3572 		decode_rl_address(emu);
3573 }
3574 /* opcode=0xda */
3575 static void
3576 x86emuOp_esc_coprocess_da(struct x86emu *emu)
3577 {
3578 	fetch_decode_modrm(emu);
3579 	if (emu->cur_mod != 3)
3580 		decode_rl_address(emu);
3581 }
3582 /* opcode=0xdb */
3583 static void
3584 x86emuOp_esc_coprocess_db(struct x86emu *emu)
3585 {
3586 	fetch_decode_modrm(emu);
3587 	if (emu->cur_mod != 3)
3588 		decode_rl_address(emu);
3589 }
3590 /* opcode=0xdc */
3591 static void
3592 x86emuOp_esc_coprocess_dc(struct x86emu *emu)
3593 {
3594 	fetch_decode_modrm(emu);
3595 	if (emu->cur_mod != 3)
3596 		decode_rl_address(emu);
3597 }
3598 /* opcode=0xdd */
3599 static void
3600 x86emuOp_esc_coprocess_dd(struct x86emu *emu)
3601 {
3602 	fetch_decode_modrm(emu);
3603 	if (emu->cur_mod != 3)
3604 		decode_rl_address(emu);
3605 }
3606 /* opcode=0xde */
3607 static void
3608 x86emuOp_esc_coprocess_de(struct x86emu *emu)
3609 {
3610 	fetch_decode_modrm(emu);
3611 	if (emu->cur_mod != 3)
3612 		decode_rl_address(emu);
3613 }
3614 /* opcode=0xdf */
3615 static void
3616 x86emuOp_esc_coprocess_df(struct x86emu *emu)
3617 {
3618 	fetch_decode_modrm(emu);
3619 	if (emu->cur_mod != 3)
3620 		decode_rl_address(emu);
3621 }
3622 
3623 
3624 /*
3625  * REMARKS:
3626  * Handles opcode 0xe0
3627  */
3628 static void
3629 x86emuOp_loopne(struct x86emu *emu)
3630 {
3631 	int16_t ip;
3632 
3633 	ip = (int8_t) fetch_byte_imm(emu);
3634 	ip += (int16_t) emu->x86.R_IP;
3635 	emu->x86.R_CX -= 1;
3636 	if (emu->x86.R_CX != 0 && !ACCESS_FLAG(F_ZF))	/* CX != 0 and !ZF */
3637 		emu->x86.R_IP = ip;
3638 }
3639 
3640 /*
3641  * REMARKS:
3642  * Handles opcode 0xe1
3643  */
3644 static void
3645 x86emuOp_loope(struct x86emu *emu)
3646 {
3647 	int16_t ip;
3648 
3649 	ip = (int8_t) fetch_byte_imm(emu);
3650 	ip += (int16_t) emu->x86.R_IP;
3651 	emu->x86.R_CX -= 1;
3652 	if (emu->x86.R_CX != 0 && ACCESS_FLAG(F_ZF))	/* CX != 0 and ZF */
3653 		emu->x86.R_IP = ip;
3654 }
3655 
3656 /*
3657  * REMARKS:
3658  * Handles opcode 0xe2
3659  */
3660 static void
3661 x86emuOp_loop(struct x86emu *emu)
3662 {
3663 	int16_t ip;
3664 
3665 	ip = (int8_t) fetch_byte_imm(emu);
3666 	ip += (int16_t) emu->x86.R_IP;
3667 	emu->x86.R_CX -= 1;
3668 	if (emu->x86.R_CX != 0)
3669 		emu->x86.R_IP = ip;
3670 }
3671 
3672 /*
3673  * REMARKS:
3674  * Handles opcode 0xe3
3675  */
3676 static void
3677 x86emuOp_jcxz(struct x86emu *emu)
3678 {
3679 	uint16_t target;
3680 	int8_t offset;
3681 
3682 	/* jump to byte offset if overflow flag is set */
3683 	offset = (int8_t) fetch_byte_imm(emu);
3684 	target = (uint16_t) (emu->x86.R_IP + offset);
3685 	if (emu->x86.R_CX == 0)
3686 		emu->x86.R_IP = target;
3687 }
3688 
3689 /*
3690  * REMARKS:
3691  * Handles opcode 0xe4
3692  */
3693 static void
3694 x86emuOp_in_byte_AL_IMM(struct x86emu *emu)
3695 {
3696 	uint8_t port;
3697 
3698 	port = (uint8_t) fetch_byte_imm(emu);
3699 	emu->x86.R_AL = (*emu->emu_inb) (emu, port);
3700 }
3701 
3702 /*
3703  * REMARKS:
3704  * Handles opcode 0xe5
3705  */
3706 static void
3707 x86emuOp_in_word_AX_IMM(struct x86emu *emu)
3708 {
3709 	uint8_t port;
3710 
3711 	port = (uint8_t) fetch_byte_imm(emu);
3712 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3713 		emu->x86.R_EAX = (*emu->emu_inl) (emu, port);
3714 	} else {
3715 		emu->x86.R_AX = (*emu->emu_inw) (emu, port);
3716 	}
3717 }
3718 
3719 /*
3720  * REMARKS:
3721  * Handles opcode 0xe6
3722  */
3723 static void
3724 x86emuOp_out_byte_IMM_AL(struct x86emu *emu)
3725 {
3726 	uint8_t port;
3727 
3728 	port = (uint8_t) fetch_byte_imm(emu);
3729 	(*emu->emu_outb) (emu, port, emu->x86.R_AL);
3730 }
3731 
3732 /*
3733  * REMARKS:
3734  * Handles opcode 0xe7
3735  */
3736 static void
3737 x86emuOp_out_word_IMM_AX(struct x86emu *emu)
3738 {
3739 	uint8_t port;
3740 
3741 	port = (uint8_t) fetch_byte_imm(emu);
3742 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3743 		(*emu->emu_outl) (emu, port, emu->x86.R_EAX);
3744 	} else {
3745 		(*emu->emu_outw) (emu, port, emu->x86.R_AX);
3746 	}
3747 }
3748 
3749 /*
3750  * REMARKS:
3751  * Handles opcode 0xe8
3752  */
3753 static void
3754 x86emuOp_call_near_IMM(struct x86emu *emu)
3755 {
3756 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3757 		int32_t ip;
3758 		ip = (int32_t) fetch_long_imm(emu);
3759 		ip += (int32_t) emu->x86.R_EIP;
3760 		push_long(emu, emu->x86.R_EIP);
3761 		emu->x86.R_EIP = ip;
3762 	} else {
3763 		int16_t ip;
3764 		ip = (int16_t) fetch_word_imm(emu);
3765 		ip += (int16_t) emu->x86.R_IP;	/* CHECK SIGN */
3766 		push_word(emu, emu->x86.R_IP);
3767 		emu->x86.R_IP = ip;
3768 	}
3769 }
3770 
3771 /*
3772  * REMARKS:
3773  * Handles opcode 0xe9
3774  */
3775 static void
3776 x86emuOp_jump_near_IMM(struct x86emu *emu)
3777 {
3778 	int ip;
3779 
3780 	ip = (int16_t) fetch_word_imm(emu);
3781 	ip += (int16_t) emu->x86.R_IP;
3782 	emu->x86.R_IP = (uint16_t) ip;
3783 }
3784 
3785 /*
3786  * REMARKS:
3787  * Handles opcode 0xea
3788  */
3789 static void
3790 x86emuOp_jump_far_IMM(struct x86emu *emu)
3791 {
3792 	uint16_t cs, ip;
3793 
3794 	ip = fetch_word_imm(emu);
3795 	cs = fetch_word_imm(emu);
3796 	emu->x86.R_IP = ip;
3797 	emu->x86.R_CS = cs;
3798 }
3799 
3800 /*
3801  * REMARKS:
3802  * Handles opcode 0xeb
3803  */
3804 static void
3805 x86emuOp_jump_byte_IMM(struct x86emu *emu)
3806 {
3807 	uint16_t target;
3808 	int8_t offset;
3809 
3810 	offset = (int8_t) fetch_byte_imm(emu);
3811 	target = (uint16_t) (emu->x86.R_IP + offset);
3812 	emu->x86.R_IP = target;
3813 }
3814 
3815 /*
3816  * REMARKS:
3817  * Handles opcode 0xec
3818  */
3819 static void
3820 x86emuOp_in_byte_AL_DX(struct x86emu *emu)
3821 {
3822 	emu->x86.R_AL = (*emu->emu_inb) (emu, emu->x86.R_DX);
3823 }
3824 
3825 /*
3826  * REMARKS:
3827  * Handles opcode 0xed
3828  */
3829 static void
3830 x86emuOp_in_word_AX_DX(struct x86emu *emu)
3831 {
3832 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3833 		emu->x86.R_EAX = (*emu->emu_inl) (emu, emu->x86.R_DX);
3834 	} else {
3835 		emu->x86.R_AX = (*emu->emu_inw) (emu, emu->x86.R_DX);
3836 	}
3837 }
3838 
3839 /*
3840  * REMARKS:
3841  * Handles opcode 0xee
3842  */
3843 static void
3844 x86emuOp_out_byte_DX_AL(struct x86emu *emu)
3845 {
3846 	(*emu->emu_outb) (emu, emu->x86.R_DX, emu->x86.R_AL);
3847 }
3848 
3849 /*
3850  * REMARKS:
3851  * Handles opcode 0xef
3852  */
3853 static void
3854 x86emuOp_out_word_DX_AX(struct x86emu *emu)
3855 {
3856 	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3857 		(*emu->emu_outl) (emu, emu->x86.R_DX, emu->x86.R_EAX);
3858 	} else {
3859 		(*emu->emu_outw) (emu, emu->x86.R_DX, emu->x86.R_AX);
3860 	}
3861 }
3862 
3863 /*
3864  * REMARKS:
3865  * Handles opcode 0xf0
3866  */
3867 static void
3868 x86emuOp_lock(struct x86emu *emu)
3869 {
3870 }
3871 /*opcode 0xf1 ILLEGAL OPERATION */
3872 
3873 
3874 /*
3875  * REMARKS:
3876  * Handles opcode 0xf5
3877  */
3878 static void
3879 x86emuOp_cmc(struct x86emu *emu)
3880 {
3881 	if (ACCESS_FLAG(F_CF))
3882 		CLEAR_FLAG(F_CF);
3883 	else
3884 		SET_FLAG(F_CF);
3885 }
3886 
3887 /*
3888  * REMARKS:
3889  * Handles opcode 0xf6
3890  */
3891 static void
3892 x86emuOp_opcF6_byte_RM(struct x86emu *emu)
3893 {
3894 	uint8_t destval, srcval;
3895 
3896 	/* long, drawn out code follows.  Double switch for a total of 32
3897 	 * cases.  */
3898 	fetch_decode_modrm(emu);
3899 	if (emu->cur_rh == 1)
3900 		x86emu_halt_sys(emu);
3901 
3902 	if (emu->cur_rh == 0) {
3903 		destval = decode_and_fetch_byte_imm8(emu, &srcval);
3904 		test_byte(emu, destval, srcval);
3905 		return;
3906 	}
3907 	destval = decode_and_fetch_byte(emu);
3908 	switch (emu->cur_rh) {
3909 	case 2:
3910 		destval = ~destval;
3911 		write_back_byte(emu, destval);
3912 		break;
3913 	case 3:
3914 		destval = neg_byte(emu, destval);
3915 		write_back_byte(emu, destval);
3916 		break;
3917 	case 4:
3918 		mul_byte(emu, destval);
3919 		break;
3920 	case 5:
3921 		imul_byte(emu, destval);
3922 		break;
3923 	case 6:
3924 		div_byte(emu, destval);
3925 		break;
3926 	case 7:
3927 		idiv_byte(emu, destval);
3928 		break;
3929 	}
3930 }
3931 
3932 /*
3933  * REMARKS:
3934  * Handles opcode 0xf7
3935  */
3936 static void
3937 x86emuOp32_opcF7_word_RM(struct x86emu *emu)
3938 {
3939 	uint32_t destval, srcval;
3940 
3941 	/* long, drawn out code follows.  Double switch for a total of 32
3942 	 * cases.  */
3943 	fetch_decode_modrm(emu);
3944 	if (emu->cur_rh == 1)
3945 		x86emu_halt_sys(emu);
3946 
3947 	if (emu->cur_rh == 0) {
3948 		if (emu->cur_mod != 3) {
3949 			uint32_t destoffset;
3950 
3951 			destoffset = decode_rl_address(emu);
3952 			srcval = fetch_long_imm(emu);
3953 			destval = fetch_data_long(emu, destoffset);
3954 		} else {
3955 			srcval = fetch_long_imm(emu);
3956 			destval = *decode_rl_long_register(emu);
3957 		}
3958 		test_long(emu, destval, srcval);
3959 		return;
3960 	}
3961 	destval = decode_and_fetch_long(emu);
3962 	switch (emu->cur_rh) {
3963 	case 2:
3964 		destval = ~destval;
3965 		write_back_long(emu, destval);
3966 		break;
3967 	case 3:
3968 		destval = neg_long(emu, destval);
3969 		write_back_long(emu, destval);
3970 		break;
3971 	case 4:
3972 		mul_long(emu, destval);
3973 		break;
3974 	case 5:
3975 		imul_long(emu, destval);
3976 		break;
3977 	case 6:
3978 		div_long(emu, destval);
3979 		break;
3980 	case 7:
3981 		idiv_long(emu, destval);
3982 		break;
3983 	}
3984 }
3985 static void
3986 x86emuOp16_opcF7_word_RM(struct x86emu *emu)
3987 {
3988 	uint16_t destval, srcval;
3989 
3990 	/* long, drawn out code follows.  Double switch for a total of 32
3991 	 * cases.  */
3992 	fetch_decode_modrm(emu);
3993 	if (emu->cur_rh == 1)
3994 		x86emu_halt_sys(emu);
3995 
3996 	if (emu->cur_rh == 0) {
3997 		if (emu->cur_mod != 3) {
3998 			uint32_t destoffset;
3999 
4000 			destoffset = decode_rl_address(emu);
4001 			srcval = fetch_word_imm(emu);
4002 			destval = fetch_data_word(emu, destoffset);
4003 		} else {
4004 			srcval = fetch_word_imm(emu);
4005 			destval = *decode_rl_word_register(emu);
4006 		}
4007 		test_word(emu, destval, srcval);
4008 		return;
4009 	}
4010 	destval = decode_and_fetch_word(emu);
4011 	switch (emu->cur_rh) {
4012 	case 2:
4013 		destval = ~destval;
4014 		write_back_word(emu, destval);
4015 		break;
4016 	case 3:
4017 		destval = neg_word(emu, destval);
4018 		write_back_word(emu, destval);
4019 		break;
4020 	case 4:
4021 		mul_word(emu, destval);
4022 		break;
4023 	case 5:
4024 		imul_word(emu, destval);
4025 		break;
4026 	case 6:
4027 		div_word(emu, destval);
4028 		break;
4029 	case 7:
4030 		idiv_word(emu, destval);
4031 		break;
4032 	}
4033 }
4034 static void
4035 x86emuOp_opcF7_word_RM(struct x86emu *emu)
4036 {
4037 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4038 		x86emuOp32_opcF7_word_RM(emu);
4039 	else
4040 		x86emuOp16_opcF7_word_RM(emu);
4041 }
4042 
4043 /*
4044  * REMARKS:
4045  * Handles opcode 0xfe
4046  */
4047 static void
4048 x86emuOp_opcFE_byte_RM(struct x86emu *emu)
4049 {
4050 	uint8_t destval;
4051 	uint32_t destoffset;
4052 	uint8_t *destreg;
4053 
4054 	/* Yet another special case instruction. */
4055 	fetch_decode_modrm(emu);
4056 	if (emu->cur_mod != 3) {
4057 		destoffset = decode_rl_address(emu);
4058 		switch (emu->cur_rh) {
4059 		case 0:	/* inc word ptr ... */
4060 			destval = fetch_data_byte(emu, destoffset);
4061 			destval = inc_byte(emu, destval);
4062 			store_data_byte(emu, destoffset, destval);
4063 			break;
4064 		case 1:	/* dec word ptr ... */
4065 			destval = fetch_data_byte(emu, destoffset);
4066 			destval = dec_byte(emu, destval);
4067 			store_data_byte(emu, destoffset, destval);
4068 			break;
4069 		}
4070 	} else {
4071 		destreg = decode_rl_byte_register(emu);
4072 		switch (emu->cur_rh) {
4073 		case 0:
4074 			*destreg = inc_byte(emu, *destreg);
4075 			break;
4076 		case 1:
4077 			*destreg = dec_byte(emu, *destreg);
4078 			break;
4079 		}
4080 	}
4081 }
4082 
4083 /*
4084  * REMARKS:
4085  * Handles opcode 0xff
4086  */
4087 static void
4088 x86emuOp32_opcFF_word_RM(struct x86emu *emu)
4089 {
4090 	uint32_t destoffset = 0;
4091 	uint32_t destval, *destreg;
4092 
4093 	if (emu->cur_mod != 3) {
4094 		destoffset = decode_rl_address(emu);
4095 		destval = fetch_data_long(emu, destoffset);
4096 		switch (emu->cur_rh) {
4097 		case 0:	/* inc word ptr ... */
4098 			destval = inc_long(emu, destval);
4099 			store_data_long(emu, destoffset, destval);
4100 			break;
4101 		case 1:	/* dec word ptr ... */
4102 			destval = dec_long(emu, destval);
4103 			store_data_long(emu, destoffset, destval);
4104 			break;
4105 		case 6:	/* push word ptr ... */
4106 			push_long(emu, destval);
4107 			break;
4108 		}
4109 	} else {
4110 		destreg = decode_rl_long_register(emu);
4111 		switch (emu->cur_rh) {
4112 		case 0:
4113 			*destreg = inc_long(emu, *destreg);
4114 			break;
4115 		case 1:
4116 			*destreg = dec_long(emu, *destreg);
4117 			break;
4118 		case 6:
4119 			push_long(emu, *destreg);
4120 			break;
4121 		}
4122 	}
4123 }
4124 
4125 static void
4126 x86emuOp16_opcFF_word_RM(struct x86emu *emu)
4127 {
4128 	uint32_t destoffset = 0;
4129 	uint16_t *destreg;
4130 	uint16_t destval;
4131 
4132 	if (emu->cur_mod != 3) {
4133 		destoffset = decode_rl_address(emu);
4134 		destval = fetch_data_word(emu, destoffset);
4135 		switch (emu->cur_rh) {
4136 		case 0:
4137 			destval = inc_word(emu, destval);
4138 			store_data_word(emu, destoffset, destval);
4139 			break;
4140 		case 1:	/* dec word ptr ... */
4141 			destval = dec_word(emu, destval);
4142 			store_data_word(emu, destoffset, destval);
4143 			break;
4144 		case 6:	/* push word ptr ... */
4145 			push_word(emu, destval);
4146 			break;
4147 		}
4148 	} else {
4149 		destreg = decode_rl_word_register(emu);
4150 		switch (emu->cur_rh) {
4151 		case 0:
4152 			*destreg = inc_word(emu, *destreg);
4153 			break;
4154 		case 1:
4155 			*destreg = dec_word(emu, *destreg);
4156 			break;
4157 		case 6:
4158 			push_word(emu, *destreg);
4159 			break;
4160 		}
4161 	}
4162 }
4163 
4164 static void
4165 x86emuOp_opcFF_word_RM(struct x86emu *emu)
4166 {
4167 	uint32_t destoffset = 0;
4168 	uint16_t destval, destval2;
4169 
4170 	/* Yet another special case instruction. */
4171 	fetch_decode_modrm(emu);
4172 	if ((emu->cur_mod == 3 && (emu->cur_rh == 3 || emu->cur_rh == 5)) ||
4173 	    emu->cur_rh == 7)
4174 		x86emu_halt_sys(emu);
4175 	if (emu->cur_rh == 0 || emu->cur_rh == 1 || emu->cur_rh == 6) {
4176 		if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4177 			x86emuOp32_opcFF_word_RM(emu);
4178 		else
4179 			x86emuOp16_opcFF_word_RM(emu);
4180 		return;
4181 	}
4182 
4183 	if (emu->cur_mod != 3) {
4184 		destoffset = decode_rl_address(emu);
4185 		destval = fetch_data_word(emu, destoffset);
4186 		switch (emu->cur_rh) {
4187 		case 3:	/* call far ptr ... */
4188 			destval2 = fetch_data_word(emu, destoffset + 2);
4189 			push_word(emu, emu->x86.R_CS);
4190 			emu->x86.R_CS = destval2;
4191 			push_word(emu, emu->x86.R_IP);
4192 			emu->x86.R_IP = destval;
4193 			break;
4194 		case 5:	/* jmp far ptr ... */
4195 			destval2 = fetch_data_word(emu, destoffset + 2);
4196 			emu->x86.R_IP = destval;
4197 			emu->x86.R_CS = destval2;
4198 			break;
4199 		}
4200 	} else {
4201 		destval = *decode_rl_word_register(emu);
4202 	}
4203 
4204 	switch (emu->cur_rh) {
4205 	case 2: /* call word ptr */
4206 		push_word(emu, emu->x86.R_IP);
4207 		emu->x86.R_IP = destval;
4208 		break;
4209 	case 4: /* jmp */
4210 		emu->x86.R_IP = destval;
4211 		break;
4212 	}
4213 }
4214 
4215 /*
4216  *  * Single byte operation code table:
4217  */
4218 static void
4219 x86emu_exec_one_byte(struct x86emu * emu)
4220 {
4221 	uint8_t op1;
4222 
4223 	op1 = fetch_byte_imm(emu);
4224 
4225 	switch (op1) {
4226 	case 0x00:
4227 		common_binop_byte_rm_r(emu, add_byte);
4228 		break;
4229 	case 0x01:
4230 		common_binop_word_long_rm_r(emu, add_word, add_long);
4231 		break;
4232 	case 0x02:
4233 		common_binop_byte_r_rm(emu, add_byte);
4234 		break;
4235 	case 0x03:
4236 		common_binop_word_long_r_rm(emu, add_word, add_long);
4237 		break;
4238 	case 0x04:
4239 		common_binop_byte_imm(emu, add_byte);
4240 		break;
4241 	case 0x05:
4242 		common_binop_word_long_imm(emu, add_word, add_long);
4243 		break;
4244 	case 0x06:
4245 		push_word(emu, emu->x86.R_ES);
4246 		break;
4247 	case 0x07:
4248 		emu->x86.R_ES = pop_word(emu);
4249 		break;
4250 
4251 	case 0x08:
4252 		common_binop_byte_rm_r(emu, or_byte);
4253 		break;
4254 	case 0x09:
4255 		common_binop_word_long_rm_r(emu, or_word, or_long);
4256 		break;
4257 	case 0x0a:
4258 		common_binop_byte_r_rm(emu, or_byte);
4259 		break;
4260 	case 0x0b:
4261 		common_binop_word_long_r_rm(emu, or_word, or_long);
4262 		break;
4263 	case 0x0c:
4264 		common_binop_byte_imm(emu, or_byte);
4265 		break;
4266 	case 0x0d:
4267 		common_binop_word_long_imm(emu, or_word, or_long);
4268 		break;
4269 	case 0x0e:
4270 		push_word(emu, emu->x86.R_CS);
4271 		break;
4272 	case 0x0f:
4273 		x86emu_exec_two_byte(emu);
4274 		break;
4275 
4276 	case 0x10:
4277 		common_binop_byte_rm_r(emu, adc_byte);
4278 		break;
4279 	case 0x11:
4280 		common_binop_word_long_rm_r(emu, adc_word, adc_long);
4281 		break;
4282 	case 0x12:
4283 		common_binop_byte_r_rm(emu, adc_byte);
4284 		break;
4285 	case 0x13:
4286 		common_binop_word_long_r_rm(emu, adc_word, adc_long);
4287 		break;
4288 	case 0x14:
4289 		common_binop_byte_imm(emu, adc_byte);
4290 		break;
4291 	case 0x15:
4292 		common_binop_word_long_imm(emu, adc_word, adc_long);
4293 		break;
4294 	case 0x16:
4295 		push_word(emu, emu->x86.R_SS);
4296 		break;
4297 	case 0x17:
4298 		emu->x86.R_SS = pop_word(emu);
4299 		break;
4300 
4301 	case 0x18:
4302 		common_binop_byte_rm_r(emu, sbb_byte);
4303 		break;
4304 	case 0x19:
4305 		common_binop_word_long_rm_r(emu, sbb_word, sbb_long);
4306 		break;
4307 	case 0x1a:
4308 		common_binop_byte_r_rm(emu, sbb_byte);
4309 		break;
4310 	case 0x1b:
4311 		common_binop_word_long_r_rm(emu, sbb_word, sbb_long);
4312 		break;
4313 	case 0x1c:
4314 		common_binop_byte_imm(emu, sbb_byte);
4315 		break;
4316 	case 0x1d:
4317 		common_binop_word_long_imm(emu, sbb_word, sbb_long);
4318 		break;
4319 	case 0x1e:
4320 		push_word(emu, emu->x86.R_DS);
4321 		break;
4322 	case 0x1f:
4323 		emu->x86.R_DS = pop_word(emu);
4324 		break;
4325 
4326 	case 0x20:
4327 		common_binop_byte_rm_r(emu, and_byte);
4328 		break;
4329 	case 0x21:
4330 		common_binop_word_long_rm_r(emu, and_word, and_long);
4331 		break;
4332 	case 0x22:
4333 		common_binop_byte_r_rm(emu, and_byte);
4334 		break;
4335 	case 0x23:
4336 		common_binop_word_long_r_rm(emu, and_word, and_long);
4337 		break;
4338 	case 0x24:
4339 		common_binop_byte_imm(emu, and_byte);
4340 		break;
4341 	case 0x25:
4342 		common_binop_word_long_imm(emu, and_word, and_long);
4343 		break;
4344 	case 0x26:
4345 		emu->x86.mode |= SYSMODE_SEGOVR_ES;
4346 		break;
4347 	case 0x27:
4348 		emu->x86.R_AL = daa_byte(emu, emu->x86.R_AL);
4349 		break;
4350 
4351 	case 0x28:
4352 		common_binop_byte_rm_r(emu, sub_byte);
4353 		break;
4354 	case 0x29:
4355 		common_binop_word_long_rm_r(emu, sub_word, sub_long);
4356 		break;
4357 	case 0x2a:
4358 		common_binop_byte_r_rm(emu, sub_byte);
4359 		break;
4360 	case 0x2b:
4361 		common_binop_word_long_r_rm(emu, sub_word, sub_long);
4362 		break;
4363 	case 0x2c:
4364 		common_binop_byte_imm(emu, sub_byte);
4365 		break;
4366 	case 0x2d:
4367 		common_binop_word_long_imm(emu, sub_word, sub_long);
4368 		break;
4369 	case 0x2e:
4370 		emu->x86.mode |= SYSMODE_SEGOVR_CS;
4371 		break;
4372 	case 0x2f:
4373 		emu->x86.R_AL = das_byte(emu, emu->x86.R_AL);
4374 		break;
4375 
4376 	case 0x30:
4377 		common_binop_byte_rm_r(emu, xor_byte);
4378 		break;
4379 	case 0x31:
4380 		common_binop_word_long_rm_r(emu, xor_word, xor_long);
4381 		break;
4382 	case 0x32:
4383 		common_binop_byte_r_rm(emu, xor_byte);
4384 		break;
4385 	case 0x33:
4386 		common_binop_word_long_r_rm(emu, xor_word, xor_long);
4387 		break;
4388 	case 0x34:
4389 		common_binop_byte_imm(emu, xor_byte);
4390 		break;
4391 	case 0x35:
4392 		common_binop_word_long_imm(emu, xor_word, xor_long);
4393 		break;
4394 	case 0x36:
4395 		emu->x86.mode |= SYSMODE_SEGOVR_SS;
4396 		break;
4397 	case 0x37:
4398 		emu->x86.R_AX = aaa_word(emu, emu->x86.R_AX);
4399 		break;
4400 
4401 	case 0x38:
4402 		common_binop_ns_byte_rm_r(emu, cmp_byte_no_return);
4403 		break;
4404 	case 0x39:
4405 		common_binop_ns_word_long_rm_r(emu, cmp_word_no_return,
4406 		    cmp_long_no_return);
4407 		break;
4408 	case 0x3a:
4409 		x86emuOp_cmp_byte_R_RM(emu);
4410 		break;
4411 	case 0x3b:
4412 		x86emuOp_cmp_word_R_RM(emu);
4413 		break;
4414 	case 0x3c:
4415 		x86emuOp_cmp_byte_AL_IMM(emu);
4416 		break;
4417 	case 0x3d:
4418 		x86emuOp_cmp_word_AX_IMM(emu);
4419 		break;
4420 	case 0x3e:
4421 		emu->x86.mode |= SYSMODE_SEGOVR_DS;
4422 		break;
4423 	case 0x3f:
4424 		emu->x86.R_AX = aas_word(emu, emu->x86.R_AX);
4425 		break;
4426 
4427 	case 0x40:
4428 		common_inc_word_long(emu, &emu->x86.register_a);
4429 		break;
4430 	case 0x41:
4431 		common_inc_word_long(emu, &emu->x86.register_c);
4432 		break;
4433 	case 0x42:
4434 		common_inc_word_long(emu, &emu->x86.register_d);
4435 		break;
4436 	case 0x43:
4437 		common_inc_word_long(emu, &emu->x86.register_b);
4438 		break;
4439 	case 0x44:
4440 		common_inc_word_long(emu, &emu->x86.register_sp);
4441 		break;
4442 	case 0x45:
4443 		common_inc_word_long(emu, &emu->x86.register_bp);
4444 		break;
4445 	case 0x46:
4446 		common_inc_word_long(emu, &emu->x86.register_si);
4447 		break;
4448 	case 0x47:
4449 		common_inc_word_long(emu, &emu->x86.register_di);
4450 		break;
4451 
4452 	case 0x48:
4453 		common_dec_word_long(emu, &emu->x86.register_a);
4454 		break;
4455 	case 0x49:
4456 		common_dec_word_long(emu, &emu->x86.register_c);
4457 		break;
4458 	case 0x4a:
4459 		common_dec_word_long(emu, &emu->x86.register_d);
4460 		break;
4461 	case 0x4b:
4462 		common_dec_word_long(emu, &emu->x86.register_b);
4463 		break;
4464 	case 0x4c:
4465 		common_dec_word_long(emu, &emu->x86.register_sp);
4466 		break;
4467 	case 0x4d:
4468 		common_dec_word_long(emu, &emu->x86.register_bp);
4469 		break;
4470 	case 0x4e:
4471 		common_dec_word_long(emu, &emu->x86.register_si);
4472 		break;
4473 	case 0x4f:
4474 		common_dec_word_long(emu, &emu->x86.register_di);
4475 		break;
4476 
4477 	case 0x50:
4478 		common_push_word_long(emu, &emu->x86.register_a);
4479 		break;
4480 	case 0x51:
4481 		common_push_word_long(emu, &emu->x86.register_c);
4482 		break;
4483 	case 0x52:
4484 		common_push_word_long(emu, &emu->x86.register_d);
4485 		break;
4486 	case 0x53:
4487 		common_push_word_long(emu, &emu->x86.register_b);
4488 		break;
4489 	case 0x54:
4490 		common_push_word_long(emu, &emu->x86.register_sp);
4491 		break;
4492 	case 0x55:
4493 		common_push_word_long(emu, &emu->x86.register_bp);
4494 		break;
4495 	case 0x56:
4496 		common_push_word_long(emu, &emu->x86.register_si);
4497 		break;
4498 	case 0x57:
4499 		common_push_word_long(emu, &emu->x86.register_di);
4500 		break;
4501 
4502 	case 0x58:
4503 		common_pop_word_long(emu, &emu->x86.register_a);
4504 		break;
4505 	case 0x59:
4506 		common_pop_word_long(emu, &emu->x86.register_c);
4507 		break;
4508 	case 0x5a:
4509 		common_pop_word_long(emu, &emu->x86.register_d);
4510 		break;
4511 	case 0x5b:
4512 		common_pop_word_long(emu, &emu->x86.register_b);
4513 		break;
4514 	case 0x5c:
4515 		common_pop_word_long(emu, &emu->x86.register_sp);
4516 		break;
4517 	case 0x5d:
4518 		common_pop_word_long(emu, &emu->x86.register_bp);
4519 		break;
4520 	case 0x5e:
4521 		common_pop_word_long(emu, &emu->x86.register_si);
4522 		break;
4523 	case 0x5f:
4524 		common_pop_word_long(emu, &emu->x86.register_di);
4525 		break;
4526 
4527 	case 0x60:
4528 		x86emuOp_push_all(emu);
4529 		break;
4530 	case 0x61:
4531 		x86emuOp_pop_all(emu);
4532 		break;
4533 	/* 0x62 bound */
4534 	/* 0x63 arpl */
4535 	case 0x64:
4536 		emu->x86.mode |= SYSMODE_SEGOVR_FS;
4537 		break;
4538 	case 0x65:
4539 		emu->x86.mode |= SYSMODE_SEGOVR_GS;
4540 		break;
4541 	case 0x66:
4542 		emu->x86.mode |= SYSMODE_PREFIX_DATA;
4543 		break;
4544 	case 0x67:
4545 		emu->x86.mode |= SYSMODE_PREFIX_ADDR;
4546 		break;
4547 
4548 	case 0x68:
4549 		x86emuOp_push_word_IMM(emu);
4550 		break;
4551 	case 0x69:
4552 		common_imul_imm(emu, 0);
4553 		break;
4554 	case 0x6a:
4555 		x86emuOp_push_byte_IMM(emu);
4556 		break;
4557 	case 0x6b:
4558 		common_imul_imm(emu, 1);
4559 		break;
4560 	case 0x6c:
4561 		ins(emu, 1);
4562 		break;
4563 	case 0x6d:
4564 		x86emuOp_ins_word(emu);
4565 		break;
4566 	case 0x6e:
4567 		outs(emu, 1);
4568 		break;
4569 	case 0x6f:
4570 		x86emuOp_outs_word(emu);
4571 		break;
4572 
4573 	case 0x70:
4574 		common_jmp_near(emu, ACCESS_FLAG(F_OF));
4575 		break;
4576 	case 0x71:
4577 		common_jmp_near(emu, !ACCESS_FLAG(F_OF));
4578 		break;
4579 	case 0x72:
4580 		common_jmp_near(emu, ACCESS_FLAG(F_CF));
4581 		break;
4582 	case 0x73:
4583 		common_jmp_near(emu, !ACCESS_FLAG(F_CF));
4584 		break;
4585 	case 0x74:
4586 		common_jmp_near(emu, ACCESS_FLAG(F_ZF));
4587 		break;
4588 	case 0x75:
4589 		common_jmp_near(emu, !ACCESS_FLAG(F_ZF));
4590 		break;
4591 	case 0x76:
4592 		common_jmp_near(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
4593 		break;
4594 	case 0x77:
4595 		common_jmp_near(emu, !ACCESS_FLAG(F_CF) && !ACCESS_FLAG(F_ZF));
4596 		break;
4597 
4598 	case 0x78:
4599 		common_jmp_near(emu, ACCESS_FLAG(F_SF));
4600 		break;
4601 	case 0x79:
4602 		common_jmp_near(emu, !ACCESS_FLAG(F_SF));
4603 		break;
4604 	case 0x7a:
4605 		common_jmp_near(emu, ACCESS_FLAG(F_PF));
4606 		break;
4607 	case 0x7b:
4608 		common_jmp_near(emu, !ACCESS_FLAG(F_PF));
4609 		break;
4610 	case 0x7c:
4611 		x86emuOp_jump_near_L(emu);
4612 		break;
4613 	case 0x7d:
4614 		x86emuOp_jump_near_NL(emu);
4615 		break;
4616 	case 0x7e:
4617 		x86emuOp_jump_near_LE(emu);
4618 		break;
4619 	case 0x7f:
4620 		x86emuOp_jump_near_NLE(emu);
4621 		break;
4622 
4623 	case 0x80:
4624 		x86emuOp_opc80_byte_RM_IMM(emu);
4625 		break;
4626 	case 0x81:
4627 		x86emuOp_opc81_word_RM_IMM(emu);
4628 		break;
4629 	case 0x82:
4630 		x86emuOp_opc82_byte_RM_IMM(emu);
4631 		break;
4632 	case 0x83:
4633 		x86emuOp_opc83_word_RM_IMM(emu);
4634 		break;
4635 	case 0x84:
4636 		common_binop_ns_byte_rm_r(emu, test_byte);
4637 		break;
4638 	case 0x85:
4639 		common_binop_ns_word_long_rm_r(emu, test_word, test_long);
4640 		break;
4641 	case 0x86:
4642 		x86emuOp_xchg_byte_RM_R(emu);
4643 		break;
4644 	case 0x87:
4645 		x86emuOp_xchg_word_RM_R(emu);
4646 		break;
4647 
4648 	case 0x88:
4649 		x86emuOp_mov_byte_RM_R(emu);
4650 		break;
4651 	case 0x89:
4652 		x86emuOp_mov_word_RM_R(emu);
4653 		break;
4654 	case 0x8a:
4655 		x86emuOp_mov_byte_R_RM(emu);
4656 		break;
4657 	case 0x8b:
4658 		x86emuOp_mov_word_R_RM(emu);
4659 		break;
4660 	case 0x8c:
4661 		x86emuOp_mov_word_RM_SR(emu);
4662 		break;
4663 	case 0x8d:
4664 		x86emuOp_lea_word_R_M(emu);
4665 		break;
4666 	case 0x8e:
4667 		x86emuOp_mov_word_SR_RM(emu);
4668 		break;
4669 	case 0x8f:
4670 		x86emuOp_pop_RM(emu);
4671 		break;
4672 
4673 	case 0x90:
4674 		/* nop */
4675 		break;
4676 	case 0x91:
4677 		x86emuOp_xchg_word_AX_CX(emu);
4678 		break;
4679 	case 0x92:
4680 		x86emuOp_xchg_word_AX_DX(emu);
4681 		break;
4682 	case 0x93:
4683 		x86emuOp_xchg_word_AX_BX(emu);
4684 		break;
4685 	case 0x94:
4686 		x86emuOp_xchg_word_AX_SP(emu);
4687 		break;
4688 	case 0x95:
4689 		x86emuOp_xchg_word_AX_BP(emu);
4690 		break;
4691 	case 0x96:
4692 		x86emuOp_xchg_word_AX_SI(emu);
4693 		break;
4694 	case 0x97:
4695 		x86emuOp_xchg_word_AX_DI(emu);
4696 		break;
4697 
4698 	case 0x98:
4699 		x86emuOp_cbw(emu);
4700 		break;
4701 	case 0x99:
4702 		x86emuOp_cwd(emu);
4703 		break;
4704 	case 0x9a:
4705 		x86emuOp_call_far_IMM(emu);
4706 		break;
4707 	case 0x9b:
4708 		/* wait */
4709 		break;
4710 	case 0x9c:
4711 		x86emuOp_pushf_word(emu);
4712 		break;
4713 	case 0x9d:
4714 		x86emuOp_popf_word(emu);
4715 		break;
4716 	case 0x9e:
4717 		x86emuOp_sahf(emu);
4718 		break;
4719 	case 0x9f:
4720 		x86emuOp_lahf(emu);
4721 		break;
4722 
4723 	case 0xa0:
4724 		x86emuOp_mov_AL_M_IMM(emu);
4725 		break;
4726 	case 0xa1:
4727 		x86emuOp_mov_AX_M_IMM(emu);
4728 		break;
4729 	case 0xa2:
4730 		x86emuOp_mov_M_AL_IMM(emu);
4731 		break;
4732 	case 0xa3:
4733 		x86emuOp_mov_M_AX_IMM(emu);
4734 		break;
4735 	case 0xa4:
4736 		x86emuOp_movs_byte(emu);
4737 		break;
4738 	case 0xa5:
4739 		x86emuOp_movs_word(emu);
4740 		break;
4741 	case 0xa6:
4742 		x86emuOp_cmps_byte(emu);
4743 		break;
4744 	case 0xa7:
4745 		x86emuOp_cmps_word(emu);
4746 		break;
4747 
4748 	case 0xa8:
4749 		test_byte(emu, emu->x86.R_AL, fetch_byte_imm(emu));
4750 		break;
4751 	case 0xa9:
4752 		x86emuOp_test_AX_IMM(emu);
4753 		break;
4754 	case 0xaa:
4755 		x86emuOp_stos_byte(emu);
4756 		break;
4757 	case 0xab:
4758 		x86emuOp_stos_word(emu);
4759 		break;
4760 	case 0xac:
4761 		x86emuOp_lods_byte(emu);
4762 		break;
4763 	case 0xad:
4764 		x86emuOp_lods_word(emu);
4765 		break;
4766 	case 0xae:
4767 		x86emuOp_scas_byte(emu);
4768 		break;
4769 	case 0xaf:
4770 		x86emuOp_scas_word(emu);
4771 		break;
4772 
4773 	case 0xb0:
4774 		emu->x86.R_AL = fetch_byte_imm(emu);
4775 		break;
4776 	case 0xb1:
4777 		emu->x86.R_CL = fetch_byte_imm(emu);
4778 		break;
4779 	case 0xb2:
4780 		emu->x86.R_DL = fetch_byte_imm(emu);
4781 		break;
4782 	case 0xb3:
4783 		emu->x86.R_BL = fetch_byte_imm(emu);
4784 		break;
4785 	case 0xb4:
4786 		emu->x86.R_AH = fetch_byte_imm(emu);
4787 		break;
4788 	case 0xb5:
4789 		emu->x86.R_CH = fetch_byte_imm(emu);
4790 		break;
4791 	case 0xb6:
4792 		emu->x86.R_DH = fetch_byte_imm(emu);
4793 		break;
4794 	case 0xb7:
4795 		emu->x86.R_BH = fetch_byte_imm(emu);
4796 		break;
4797 
4798 	case 0xb8:
4799 		x86emuOp_mov_word_AX_IMM(emu);
4800 		break;
4801 	case 0xb9:
4802 		x86emuOp_mov_word_CX_IMM(emu);
4803 		break;
4804 	case 0xba:
4805 		x86emuOp_mov_word_DX_IMM(emu);
4806 		break;
4807 	case 0xbb:
4808 		x86emuOp_mov_word_BX_IMM(emu);
4809 		break;
4810 	case 0xbc:
4811 
4812 		x86emuOp_mov_word_SP_IMM(emu);
4813 		break;
4814 	case 0xbd:
4815 		x86emuOp_mov_word_BP_IMM(emu);
4816 		break;
4817 	case 0xbe:
4818 		x86emuOp_mov_word_SI_IMM(emu);
4819 		break;
4820 	case 0xbf:
4821 		x86emuOp_mov_word_DI_IMM(emu);
4822 		break;
4823 
4824 	case 0xc0:
4825 		x86emuOp_opcC0_byte_RM_MEM(emu);
4826 		break;
4827 	case 0xc1:
4828 		x86emuOp_opcC1_word_RM_MEM(emu);
4829 		break;
4830 	case 0xc2:
4831 		x86emuOp_ret_near_IMM(emu);
4832 		break;
4833 	case 0xc3:
4834 		emu->x86.R_IP = pop_word(emu);
4835 		break;
4836 	case 0xc4:
4837 		common_load_far_pointer(emu, &emu->x86.R_ES);
4838 		break;
4839 	case 0xc5:
4840 		common_load_far_pointer(emu, &emu->x86.R_DS);
4841 		break;
4842 	case 0xc6:
4843 		x86emuOp_mov_byte_RM_IMM(emu);
4844 		break;
4845 	case 0xc7:
4846 		x86emuOp_mov_word_RM_IMM(emu);
4847 		break;
4848 	case 0xc8:
4849 		x86emuOp_enter(emu);
4850 		break;
4851 	case 0xc9:
4852 		x86emuOp_leave(emu);
4853 		break;
4854 	case 0xca:
4855 		x86emuOp_ret_far_IMM(emu);
4856 		break;
4857 	case 0xcb:
4858 		x86emuOp_ret_far(emu);
4859 		break;
4860 	case 0xcc:
4861 		x86emuOp_int3(emu);
4862 		break;
4863 	case 0xcd:
4864 		x86emuOp_int_IMM(emu);
4865 		break;
4866 	case 0xce:
4867 		x86emuOp_into(emu);
4868 		break;
4869 	case 0xcf:
4870 		x86emuOp_iret(emu);
4871 		break;
4872 
4873 	case 0xd0:
4874 		x86emuOp_opcD0_byte_RM_1(emu);
4875 		break;
4876 	case 0xd1:
4877 		x86emuOp_opcD1_word_RM_1(emu);
4878 		break;
4879 	case 0xd2:
4880 		x86emuOp_opcD2_byte_RM_CL(emu);
4881 		break;
4882 	case 0xd3:
4883 		x86emuOp_opcD3_word_RM_CL(emu);
4884 		break;
4885 	case 0xd4:
4886 		x86emuOp_aam(emu);
4887 		break;
4888 	case 0xd5:
4889 		x86emuOp_aad(emu);
4890 		break;
4891 	/* 0xd6 Undocumented SETALC instruction */
4892 	case 0xd7:
4893 		x86emuOp_xlat(emu);
4894 		break;
4895 	case 0xd8:
4896 		x86emuOp_esc_coprocess_d8(emu);
4897 		break;
4898 	case 0xd9:
4899 		x86emuOp_esc_coprocess_d9(emu);
4900 		break;
4901 	case 0xda:
4902 		x86emuOp_esc_coprocess_da(emu);
4903 		break;
4904 	case 0xdb:
4905 		x86emuOp_esc_coprocess_db(emu);
4906 		break;
4907 	case 0xdc:
4908 		x86emuOp_esc_coprocess_dc(emu);
4909 		break;
4910 	case 0xdd:
4911 		x86emuOp_esc_coprocess_dd(emu);
4912 		break;
4913 	case 0xde:
4914 		x86emuOp_esc_coprocess_de(emu);
4915 		break;
4916 	case 0xdf:
4917 		x86emuOp_esc_coprocess_df(emu);
4918 		break;
4919 
4920 	case 0xe0:
4921 		x86emuOp_loopne(emu);
4922 		break;
4923 	case 0xe1:
4924 		x86emuOp_loope(emu);
4925 		break;
4926 	case 0xe2:
4927 		x86emuOp_loop(emu);
4928 		break;
4929 	case 0xe3:
4930 		x86emuOp_jcxz(emu);
4931 		break;
4932 	case 0xe4:
4933 		x86emuOp_in_byte_AL_IMM(emu);
4934 		break;
4935 	case 0xe5:
4936 		x86emuOp_in_word_AX_IMM(emu);
4937 		break;
4938 	case 0xe6:
4939 		x86emuOp_out_byte_IMM_AL(emu);
4940 		break;
4941 	case 0xe7:
4942 		x86emuOp_out_word_IMM_AX(emu);
4943 		break;
4944 
4945 	case 0xe8:
4946 		x86emuOp_call_near_IMM(emu);
4947 		break;
4948 	case 0xe9:
4949 		x86emuOp_jump_near_IMM(emu);
4950 		break;
4951 	case 0xea:
4952 		x86emuOp_jump_far_IMM(emu);
4953 		break;
4954 	case 0xeb:
4955 		x86emuOp_jump_byte_IMM(emu);
4956 		break;
4957 	case 0xec:
4958 		x86emuOp_in_byte_AL_DX(emu);
4959 		break;
4960 	case 0xed:
4961 		x86emuOp_in_word_AX_DX(emu);
4962 		break;
4963 	case 0xee:
4964 		x86emuOp_out_byte_DX_AL(emu);
4965 		break;
4966 	case 0xef:
4967 		x86emuOp_out_word_DX_AX(emu);
4968 		break;
4969 
4970 	case 0xf0:
4971 		x86emuOp_lock(emu);
4972 		break;
4973 	case 0xf2:
4974 		emu->x86.mode |= SYSMODE_PREFIX_REPNE;
4975 		break;
4976 	case 0xf3:
4977 		emu->x86.mode |= SYSMODE_PREFIX_REPE;
4978 		break;
4979 	case 0xf4:
4980 		x86emu_halt_sys(emu);
4981 		break;
4982 	case 0xf5:
4983 		x86emuOp_cmc(emu);
4984 		break;
4985 	case 0xf6:
4986 		x86emuOp_opcF6_byte_RM(emu);
4987 		break;
4988 	case 0xf7:
4989 		x86emuOp_opcF7_word_RM(emu);
4990 		break;
4991 
4992 	case 0xf8:
4993 		CLEAR_FLAG(F_CF);
4994 		break;
4995 	case 0xf9:
4996 		SET_FLAG(F_CF);
4997 		break;
4998 	case 0xfa:
4999 		CLEAR_FLAG(F_IF);
5000 		break;
5001 	case 0xfb:
5002 		SET_FLAG(F_IF);
5003 		break;
5004 	case 0xfc:
5005 		CLEAR_FLAG(F_DF);
5006 		break;
5007 	case 0xfd:
5008 		SET_FLAG(F_DF);
5009 		break;
5010 	case 0xfe:
5011 		x86emuOp_opcFE_byte_RM(emu);
5012 		break;
5013 	case 0xff:
5014 		x86emuOp_opcFF_word_RM(emu);
5015 		break;
5016 	default:
5017 		x86emu_halt_sys(emu);
5018 		break;
5019 	}
5020 	if (op1 != 0x26 && op1 != 0x2e && op1 != 0x36 && op1 != 0x3e &&
5021 	    (op1 | 3) != 0x67)
5022 		emu->x86.mode &= ~SYSMODE_CLRMASK;
5023 }
5024 
5025 static void
5026 common_jmp_long(struct x86emu *emu, int cond)
5027 {
5028 	int16_t target;
5029 
5030 	target = (int16_t) fetch_word_imm(emu);
5031 	target += (int16_t) emu->x86.R_IP;
5032 	if (cond)
5033 		emu->x86.R_IP = (uint16_t) target;
5034 }
5035 
5036 static void
5037 common_set_byte(struct x86emu *emu, int cond)
5038 {
5039 	uint32_t destoffset;
5040 	uint8_t *destreg, destval;
5041 
5042 	fetch_decode_modrm(emu);
5043 	destval = cond ? 0x01 : 0x00;
5044 	if (emu->cur_mod != 3) {
5045 		destoffset = decode_rl_address(emu);
5046 		store_data_byte(emu, destoffset, destval);
5047 	} else {
5048 		destreg = decode_rl_byte_register(emu);
5049 		*destreg = destval;
5050 	}
5051 }
5052 
5053 static void
5054 common_bitstring32(struct x86emu *emu, int op)
5055 {
5056 	int bit;
5057 	uint32_t srcval, *shiftreg, mask;
5058 
5059 	fetch_decode_modrm(emu);
5060 	shiftreg = decode_rh_long_register(emu);
5061 	srcval = decode_and_fetch_long_disp(emu, (int16_t) *shiftreg >> 5);
5062 	bit = *shiftreg & 0x1F;
5063 	mask =  0x1 << bit;
5064 	CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5065 
5066 	switch (op) {
5067 	case 0:
5068 		break;
5069 	case 1:
5070 		write_back_long(emu, srcval | mask);
5071 		break;
5072 	case 2:
5073 		write_back_long(emu, srcval & ~mask);
5074 		break;
5075 	case 3:
5076 		write_back_long(emu, srcval ^ mask);
5077 		break;
5078 	}
5079 }
5080 
5081 static void
5082 common_bitstring16(struct x86emu *emu, int op)
5083 {
5084 	int bit;
5085 	uint16_t srcval, *shiftreg, mask;
5086 
5087 	fetch_decode_modrm(emu);
5088 	shiftreg = decode_rh_word_register(emu);
5089 	srcval = decode_and_fetch_word_disp(emu, (int16_t) *shiftreg >> 4);
5090 	bit = *shiftreg & 0xF;
5091 	mask =  0x1 << bit;
5092 	CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5093 
5094 	switch (op) {
5095 	case 0:
5096 		break;
5097 	case 1:
5098 		write_back_word(emu, srcval | mask);
5099 		break;
5100 	case 2:
5101 		write_back_word(emu, srcval & ~mask);
5102 		break;
5103 	case 3:
5104 		write_back_word(emu, srcval ^ mask);
5105 		break;
5106 	}
5107 }
5108 
5109 static void
5110 common_bitstring(struct x86emu *emu, int op)
5111 {
5112 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5113 		common_bitstring32(emu, op);
5114 	else
5115 		common_bitstring16(emu, op);
5116 }
5117 
5118 static void
5119 common_bitsearch32(struct x86emu *emu, int diff)
5120 {
5121 	uint32_t srcval, *dstreg;
5122 
5123 	fetch_decode_modrm(emu);
5124 	dstreg = decode_rh_long_register(emu);
5125 	srcval = decode_and_fetch_long(emu);
5126 	CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
5127 	for (*dstreg = 0; *dstreg < 32; *dstreg += diff) {
5128 		if ((srcval >> *dstreg) & 1)
5129 			break;
5130 	}
5131 }
5132 
5133 static void
5134 common_bitsearch16(struct x86emu *emu, int diff)
5135 {
5136 	uint16_t srcval, *dstreg;
5137 
5138 	fetch_decode_modrm(emu);
5139 	dstreg = decode_rh_word_register(emu);
5140 	srcval = decode_and_fetch_word(emu);
5141 	CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
5142 	for (*dstreg = 0; *dstreg < 16; *dstreg += diff) {
5143 		if ((srcval >> *dstreg) & 1)
5144 			break;
5145 	}
5146 }
5147 
5148 static void
5149 common_bitsearch(struct x86emu *emu, int diff)
5150 {
5151 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5152 		common_bitsearch32(emu, diff);
5153 	else
5154 		common_bitsearch16(emu, diff);
5155 }
5156 
5157 static void
5158 common_shift32(struct x86emu *emu, int shift_left, int use_cl)
5159 {
5160 	uint8_t shift;
5161 	uint32_t destval, *shiftreg;
5162 
5163 	fetch_decode_modrm(emu);
5164 	shiftreg = decode_rh_long_register(emu);
5165 	if (use_cl) {
5166 		destval = decode_and_fetch_long(emu);
5167 		shift = emu->x86.R_CL;
5168 	} else {
5169 		destval = decode_and_fetch_long_imm8(emu, &shift);
5170 	}
5171 	if (shift_left)
5172 		destval = shld_long(emu, destval, *shiftreg, shift);
5173 	else
5174 		destval = shrd_long(emu, destval, *shiftreg, shift);
5175 	write_back_long(emu, destval);
5176 }
5177 
5178 static void
5179 common_shift16(struct x86emu *emu, int shift_left, int use_cl)
5180 {
5181 	uint8_t shift;
5182 	uint16_t destval, *shiftreg;
5183 
5184 	fetch_decode_modrm(emu);
5185 	shiftreg = decode_rh_word_register(emu);
5186 	if (use_cl) {
5187 		destval = decode_and_fetch_word(emu);
5188 		shift = emu->x86.R_CL;
5189 	} else {
5190 		destval = decode_and_fetch_word_imm8(emu, &shift);
5191 	}
5192 	if (shift_left)
5193 		destval = shld_word(emu, destval, *shiftreg, shift);
5194 	else
5195 		destval = shrd_word(emu, destval, *shiftreg, shift);
5196 	write_back_word(emu, destval);
5197 }
5198 
5199 static void
5200 common_shift(struct x86emu *emu, int shift_left, int use_cl)
5201 {
5202 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5203 		common_shift32(emu, shift_left, use_cl);
5204 	else
5205 		common_shift16(emu, shift_left, use_cl);
5206 }
5207 
5208 /*
5209  * Implementation
5210  */
5211 #define xorl(a,b)   ((a) && !(b)) || (!(a) && (b))
5212 
5213 
5214 /*
5215  * REMARKS:
5216  * Handles opcode 0x0f,0x31
5217  */
5218 static void
5219 x86emuOp2_rdtsc(struct x86emu *emu)
5220 {
5221 	emu->x86.R_EAX = emu->cur_cycles & 0xffffffff;
5222 	emu->x86.R_EDX = emu->cur_cycles >> 32;
5223 }
5224 
5225 /*
5226  * REMARKS:
5227  * Handles opcode 0x0f,0xa0
5228  */
5229 static void
5230 x86emuOp2_push_FS(struct x86emu *emu)
5231 {
5232 	push_word(emu, emu->x86.R_FS);
5233 }
5234 
5235 /*
5236  * REMARKS:
5237  * Handles opcode 0x0f,0xa1
5238  */
5239 static void
5240 x86emuOp2_pop_FS(struct x86emu *emu)
5241 {
5242 	emu->x86.R_FS = pop_word(emu);
5243 }
5244 
5245 /*
5246  * REMARKS:
5247  * Handles opcode 0x0f,0xa1
5248  */
5249 #if defined(__i386__) || defined(__amd64__)
5250 static void
5251 hw_cpuid(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
5252 {
5253 	__asm__ volatile("cpuid"
5254 			     : "=a" (*a), "=b" (*b),
5255 			       "=c" (*c), "=d" (*d)
5256 			     : "a" (*a), "c" (*c)
5257 			     : "cc");
5258 }
5259 #endif
5260 static void
5261 x86emuOp2_cpuid(struct x86emu *emu)
5262 {
5263 #if defined(__i386__) || defined(__amd64__)
5264 	hw_cpuid(&emu->x86.R_EAX, &emu->x86.R_EBX, &emu->x86.R_ECX,
5265 	    &emu->x86.R_EDX);
5266 #endif
5267 	switch (emu->x86.R_EAX) {
5268 	case 0:
5269 		emu->x86.R_EAX = 1;
5270 #if !defined(__i386__) && !defined(__amd64__)
5271 		/* "GenuineIntel" */
5272 		emu->x86.R_EBX = 0x756e6547;
5273 		emu->x86.R_EDX = 0x49656e69;
5274 		emu->x86.R_ECX = 0x6c65746e;
5275 #endif
5276 		break;
5277 	case 1:
5278 #if !defined(__i386__) && !defined(__amd64__)
5279 		emu->x86.R_EAX = 0x00000480;
5280 		emu->x86.R_EBX = emu->x86.R_ECX = 0;
5281 		emu->x86.R_EDX = 0x00000002;
5282 #else
5283 		emu->x86.R_EDX &= 0x00000012;
5284 #endif
5285 		break;
5286 	default:
5287 		emu->x86.R_EAX = emu->x86.R_EBX = emu->x86.R_ECX =
5288 		    emu->x86.R_EDX = 0;
5289 		break;
5290 	}
5291 }
5292 
5293 /*
5294  * REMARKS:
5295  * Handles opcode 0x0f,0xa3
5296  */
5297 static void
5298 x86emuOp2_bt_R(struct x86emu *emu)
5299 {
5300 	common_bitstring(emu, 0);
5301 }
5302 
5303 /*
5304  * REMARKS:
5305  * Handles opcode 0x0f,0xa4
5306  */
5307 static void
5308 x86emuOp2_shld_IMM(struct x86emu *emu)
5309 {
5310 	common_shift(emu, 1, 0);
5311 }
5312 
5313 /*
5314  * REMARKS:
5315  * Handles opcode 0x0f,0xa5
5316  */
5317 static void
5318 x86emuOp2_shld_CL(struct x86emu *emu)
5319 {
5320 	common_shift(emu, 1, 1);
5321 }
5322 
5323 /*
5324  * REMARKS:
5325  * Handles opcode 0x0f,0xa8
5326  */
5327 static void
5328 x86emuOp2_push_GS(struct x86emu *emu)
5329 {
5330 	push_word(emu, emu->x86.R_GS);
5331 }
5332 
5333 /*
5334  * REMARKS:
5335  * Handles opcode 0x0f,0xa9
5336  */
5337 static void
5338 x86emuOp2_pop_GS(struct x86emu *emu)
5339 {
5340 	emu->x86.R_GS = pop_word(emu);
5341 }
5342 
5343 /*
5344  * REMARKS:
5345  * Handles opcode 0x0f,0xab
5346  */
5347 static void
5348 x86emuOp2_bts_R(struct x86emu *emu)
5349 {
5350 	common_bitstring(emu, 1);
5351 }
5352 
5353 /*
5354  * REMARKS:
5355  * Handles opcode 0x0f,0xac
5356  */
5357 static void
5358 x86emuOp2_shrd_IMM(struct x86emu *emu)
5359 {
5360 	common_shift(emu, 0, 0);
5361 }
5362 
5363 /*
5364  * REMARKS:
5365  * Handles opcode 0x0f,0xad
5366  */
5367 static void
5368 x86emuOp2_shrd_CL(struct x86emu *emu)
5369 {
5370 	common_shift(emu, 0, 1);
5371 }
5372 
5373 /*
5374  * REMARKS:
5375  * Handles opcode 0x0f,0xaf
5376  */
5377 static void
5378 x86emuOp2_32_imul_R_RM(struct x86emu *emu)
5379 {
5380 	uint32_t *destreg, srcval;
5381 	uint64_t res;
5382 
5383 	fetch_decode_modrm(emu);
5384 	destreg = decode_rh_long_register(emu);
5385 	srcval = decode_and_fetch_long(emu);
5386 	res = (int32_t) *destreg * (int32_t)srcval;
5387 	if (res > 0xffffffff) {
5388 		SET_FLAG(F_CF);
5389 		SET_FLAG(F_OF);
5390 	} else {
5391 		CLEAR_FLAG(F_CF);
5392 		CLEAR_FLAG(F_OF);
5393 	}
5394 	*destreg = (uint32_t) res;
5395 }
5396 
5397 static void
5398 x86emuOp2_16_imul_R_RM(struct x86emu *emu)
5399 {
5400 	uint16_t *destreg, srcval;
5401 	uint32_t res;
5402 
5403 	fetch_decode_modrm(emu);
5404 	destreg = decode_rh_word_register(emu);
5405 	srcval = decode_and_fetch_word(emu);
5406 	res = (int16_t) * destreg * (int16_t)srcval;
5407 	if (res > 0xFFFF) {
5408 		SET_FLAG(F_CF);
5409 		SET_FLAG(F_OF);
5410 	} else {
5411 		CLEAR_FLAG(F_CF);
5412 		CLEAR_FLAG(F_OF);
5413 	}
5414 	*destreg = (uint16_t) res;
5415 }
5416 
5417 static void
5418 x86emuOp2_imul_R_RM(struct x86emu *emu)
5419 {
5420 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5421 		x86emuOp2_32_imul_R_RM(emu);
5422 	else
5423 		x86emuOp2_16_imul_R_RM(emu);
5424 }
5425 
5426 /*
5427  * REMARKS:
5428  * Handles opcode 0x0f,0xb2
5429  */
5430 static void
5431 x86emuOp2_lss_R_IMM(struct x86emu *emu)
5432 {
5433 	common_load_far_pointer(emu, &emu->x86.R_SS);
5434 }
5435 
5436 /*
5437  * REMARKS:
5438  * Handles opcode 0x0f,0xb3
5439  */
5440 static void
5441 x86emuOp2_btr_R(struct x86emu *emu)
5442 {
5443 	common_bitstring(emu, 2);
5444 }
5445 
5446 /*
5447  * REMARKS:
5448  * Handles opcode 0x0f,0xb4
5449  */
5450 static void
5451 x86emuOp2_lfs_R_IMM(struct x86emu *emu)
5452 {
5453 	common_load_far_pointer(emu, &emu->x86.R_FS);
5454 }
5455 
5456 /*
5457  * REMARKS:
5458  * Handles opcode 0x0f,0xb5
5459  */
5460 static void
5461 x86emuOp2_lgs_R_IMM(struct x86emu *emu)
5462 {
5463 	common_load_far_pointer(emu, &emu->x86.R_GS);
5464 }
5465 
5466 /*
5467  * REMARKS:
5468  * Handles opcode 0x0f,0xb6
5469  */
5470 static void
5471 x86emuOp2_32_movzx_byte_R_RM(struct x86emu *emu)
5472 {
5473 	uint32_t *destreg;
5474 
5475 	fetch_decode_modrm(emu);
5476 	destreg = decode_rh_long_register(emu);
5477 	*destreg = decode_and_fetch_byte(emu);
5478 }
5479 
5480 static void
5481 x86emuOp2_16_movzx_byte_R_RM(struct x86emu *emu)
5482 {
5483 	uint16_t *destreg;
5484 
5485 	fetch_decode_modrm(emu);
5486 	destreg = decode_rh_word_register(emu);
5487 	*destreg = decode_and_fetch_byte(emu);
5488 }
5489 
5490 static void
5491 x86emuOp2_movzx_byte_R_RM(struct x86emu *emu)
5492 {
5493 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5494 		x86emuOp2_32_movzx_byte_R_RM(emu);
5495 	else
5496 		x86emuOp2_16_movzx_byte_R_RM(emu);
5497 }
5498 
5499 /*
5500  * REMARKS:
5501  * Handles opcode 0x0f,0xb7
5502  */
5503 static void
5504 x86emuOp2_movzx_word_R_RM(struct x86emu *emu)
5505 {
5506 	uint32_t *destreg;
5507 
5508 	fetch_decode_modrm(emu);
5509 	destreg = decode_rh_long_register(emu);
5510 	*destreg = decode_and_fetch_word(emu);
5511 }
5512 
5513 /*
5514  * REMARKS:
5515  * Handles opcode 0x0f,0xba
5516  */
5517 static void
5518 x86emuOp2_32_btX_I(struct x86emu *emu)
5519 {
5520 	int bit;
5521 	uint32_t srcval, mask;
5522 	uint8_t shift;
5523 
5524 	fetch_decode_modrm(emu);
5525 	if (emu->cur_rh < 4)
5526 		x86emu_halt_sys(emu);
5527 
5528 	srcval = decode_and_fetch_long_imm8(emu, &shift);
5529 	bit = shift & 0x1F;
5530 	mask = (0x1 << bit);
5531 
5532 	switch (emu->cur_rh) {
5533 	case 5:
5534 		write_back_long(emu, srcval | mask);
5535 		break;
5536 	case 6:
5537 		write_back_long(emu, srcval & ~mask);
5538 		break;
5539 	case 7:
5540 		write_back_long(emu, srcval ^ mask);
5541 		break;
5542 	}
5543 	CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5544 }
5545 
5546 static void
5547 x86emuOp2_16_btX_I(struct x86emu *emu)
5548 {
5549 	int bit;
5550 
5551 	uint16_t srcval, mask;
5552 	uint8_t shift;
5553 
5554 	fetch_decode_modrm(emu);
5555 	if (emu->cur_rh < 4)
5556 		x86emu_halt_sys(emu);
5557 
5558 	srcval = decode_and_fetch_word_imm8(emu, &shift);
5559 	bit = shift & 0xF;
5560 	mask = (0x1 << bit);
5561 	switch (emu->cur_rh) {
5562 	case 5:
5563 		write_back_word(emu, srcval | mask);
5564 		break;
5565 	case 6:
5566 		write_back_word(emu, srcval & ~mask);
5567 		break;
5568 	case 7:
5569 		write_back_word(emu, srcval ^ mask);
5570 		break;
5571 	}
5572 	CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5573 }
5574 
5575 static void
5576 x86emuOp2_btX_I(struct x86emu *emu)
5577 {
5578 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5579 		x86emuOp2_32_btX_I(emu);
5580 	else
5581 		x86emuOp2_16_btX_I(emu);
5582 }
5583 
5584 /*
5585  * REMARKS:
5586  * Handles opcode 0x0f,0xbb
5587  */
5588 static void
5589 x86emuOp2_btc_R(struct x86emu *emu)
5590 {
5591 	common_bitstring(emu, 3);
5592 }
5593 
5594 /*
5595  * REMARKS:
5596  * Handles opcode 0x0f,0xbc
5597  */
5598 static void
5599 x86emuOp2_bsf(struct x86emu *emu)
5600 {
5601 	common_bitsearch(emu, +1);
5602 }
5603 
5604 /*
5605  * REMARKS:
5606  * Handles opcode 0x0f,0xbd
5607  */
5608 static void
5609 x86emuOp2_bsr(struct x86emu *emu)
5610 {
5611 	common_bitsearch(emu, -1);
5612 }
5613 
5614 /*
5615  * REMARKS:
5616  * Handles opcode 0x0f,0xbe
5617  */
5618 static void
5619 x86emuOp2_32_movsx_byte_R_RM(struct x86emu *emu)
5620 {
5621 	uint32_t *destreg;
5622 
5623 	fetch_decode_modrm(emu);
5624 	destreg = decode_rh_long_register(emu);
5625 	*destreg = (int32_t)(int8_t)decode_and_fetch_byte(emu);
5626 }
5627 
5628 static void
5629 x86emuOp2_16_movsx_byte_R_RM(struct x86emu *emu)
5630 {
5631 	uint16_t *destreg;
5632 
5633 	fetch_decode_modrm(emu);
5634 	destreg = decode_rh_word_register(emu);
5635 	*destreg = (int16_t)(int8_t)decode_and_fetch_byte(emu);
5636 }
5637 
5638 static void
5639 x86emuOp2_movsx_byte_R_RM(struct x86emu *emu)
5640 {
5641 	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5642 		x86emuOp2_32_movsx_byte_R_RM(emu);
5643 	else
5644 		x86emuOp2_16_movsx_byte_R_RM(emu);
5645 }
5646 
5647 /*
5648  * REMARKS:
5649  * Handles opcode 0x0f,0xbf
5650  */
5651 static void
5652 x86emuOp2_movsx_word_R_RM(struct x86emu *emu)
5653 {
5654 	uint32_t *destreg;
5655 
5656 	fetch_decode_modrm(emu);
5657 	destreg = decode_rh_long_register(emu);
5658 	*destreg = (int32_t)(int16_t)decode_and_fetch_word(emu);
5659 }
5660 
5661 static void
5662 x86emu_exec_two_byte(struct x86emu * emu)
5663 {
5664 	uint8_t op2;
5665 
5666 	op2 = fetch_byte_imm(emu);
5667 
5668 	switch (op2) {
5669 	/* 0x00 Group F (ring 0 PM)      */
5670 	/* 0x01 Group G (ring 0 PM)      */
5671 	/* 0x02 lar (ring 0 PM)          */
5672 	/* 0x03 lsl (ring 0 PM)          */
5673 	/* 0x05 loadall (undocumented)   */
5674 	/* 0x06 clts (ring 0 PM)         */
5675 	/* 0x07 loadall (undocumented)   */
5676 	/* 0x08 invd (ring 0 PM)         */
5677 	/* 0x09 wbinvd (ring 0 PM)       */
5678 
5679 	/* 0x20 mov reg32(op2); break;creg (ring 0 PM) */
5680 	/* 0x21 mov reg32(op2); break;dreg (ring 0 PM) */
5681 	/* 0x22 mov creg(op2); break;reg32 (ring 0 PM) */
5682 	/* 0x23 mov dreg(op2); break;reg32 (ring 0 PM) */
5683 	/* 0x24 mov reg32(op2); break;treg (ring 0 PM) */
5684 	/* 0x26 mov treg(op2); break;reg32 (ring 0 PM) */
5685 
5686 	case 0x31:
5687 		x86emuOp2_rdtsc(emu);
5688 		break;
5689 
5690 	case 0x80:
5691 		common_jmp_long(emu, ACCESS_FLAG(F_OF));
5692 		break;
5693 	case 0x81:
5694 		common_jmp_long(emu, !ACCESS_FLAG(F_OF));
5695 		break;
5696 	case 0x82:
5697 		common_jmp_long(emu, ACCESS_FLAG(F_CF));
5698 		break;
5699 	case 0x83:
5700 		common_jmp_long(emu, !ACCESS_FLAG(F_CF));
5701 		break;
5702 	case 0x84:
5703 		common_jmp_long(emu, ACCESS_FLAG(F_ZF));
5704 		break;
5705 	case 0x85:
5706 		common_jmp_long(emu, !ACCESS_FLAG(F_ZF));
5707 		break;
5708 	case 0x86:
5709 		common_jmp_long(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5710 		break;
5711 	case 0x87:
5712 		common_jmp_long(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5713 		break;
5714 	case 0x88:
5715 		common_jmp_long(emu, ACCESS_FLAG(F_SF));
5716 		break;
5717 	case 0x89:
5718 		common_jmp_long(emu, !ACCESS_FLAG(F_SF));
5719 		break;
5720 	case 0x8a:
5721 		common_jmp_long(emu, ACCESS_FLAG(F_PF));
5722 		break;
5723 	case 0x8b:
5724 		common_jmp_long(emu, !ACCESS_FLAG(F_PF));
5725 		break;
5726 	case 0x8c:
5727 		common_jmp_long(emu, xorl(ACCESS_FLAG(F_SF),
5728 		    ACCESS_FLAG(F_OF)));
5729 		break;
5730 	case 0x8d:
5731 		common_jmp_long(emu, !(xorl(ACCESS_FLAG(F_SF),
5732 		    ACCESS_FLAG(F_OF))));
5733 		break;
5734 	case 0x8e:
5735 		common_jmp_long(emu, (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))
5736 		    || ACCESS_FLAG(F_ZF)));
5737 		break;
5738 	case 0x8f:
5739 		common_jmp_long(emu,
5740 		    !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5741 		    ACCESS_FLAG(F_ZF)));
5742 		break;
5743 
5744 	case 0x90:
5745 		common_set_byte(emu, ACCESS_FLAG(F_OF));
5746 		break;
5747 	case 0x91:
5748 		common_set_byte(emu, !ACCESS_FLAG(F_OF));
5749 		break;
5750 	case 0x92:
5751 		common_set_byte(emu, ACCESS_FLAG(F_CF));
5752 		break;
5753 	case 0x93:
5754 		common_set_byte(emu, !ACCESS_FLAG(F_CF));
5755 		break;
5756 	case 0x94:
5757 		common_set_byte(emu, ACCESS_FLAG(F_ZF));
5758 		break;
5759 	case 0x95:
5760 		common_set_byte(emu, !ACCESS_FLAG(F_ZF));
5761 		break;
5762 	case 0x96:
5763 		common_set_byte(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5764 		break;
5765 	case 0x97:
5766 		common_set_byte(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5767 		break;
5768 	case 0x98:
5769 		common_set_byte(emu, ACCESS_FLAG(F_SF));
5770 		break;
5771 	case 0x99:
5772 		common_set_byte(emu, !ACCESS_FLAG(F_SF));
5773 		break;
5774 	case 0x9a:
5775 		common_set_byte(emu, ACCESS_FLAG(F_PF));
5776 		break;
5777 	case 0x9b:
5778 		common_set_byte(emu, !ACCESS_FLAG(F_PF));
5779 		break;
5780 	case 0x9c:
5781 		common_set_byte(emu, xorl(ACCESS_FLAG(F_SF),
5782 		    ACCESS_FLAG(F_OF)));
5783 		break;
5784 	case 0x9d:
5785 		common_set_byte(emu, xorl(ACCESS_FLAG(F_SF),
5786 		    ACCESS_FLAG(F_OF)));
5787 		break;
5788 	case 0x9e:
5789 		common_set_byte(emu,
5790 		    (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5791 		    ACCESS_FLAG(F_ZF)));
5792 		break;
5793 	case 0x9f:
5794 		common_set_byte(emu,
5795 		    !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5796 		    ACCESS_FLAG(F_ZF)));
5797 		break;
5798 
5799 	case 0xa0:
5800 		x86emuOp2_push_FS(emu);
5801 		break;
5802 	case 0xa1:
5803 		x86emuOp2_pop_FS(emu);
5804 		break;
5805 	case 0xa2:
5806 		x86emuOp2_cpuid(emu);
5807 		break;
5808 	case 0xa3:
5809 		x86emuOp2_bt_R(emu);
5810 		break;
5811 	case 0xa4:
5812 		x86emuOp2_shld_IMM(emu);
5813 		break;
5814 	case 0xa5:
5815 		x86emuOp2_shld_CL(emu);
5816 		break;
5817 	case 0xa8:
5818 		x86emuOp2_push_GS(emu);
5819 		break;
5820 	case 0xa9:
5821 		x86emuOp2_pop_GS(emu);
5822 		break;
5823 	case 0xab:
5824 		x86emuOp2_bts_R(emu);
5825 		break;
5826 	case 0xac:
5827 		x86emuOp2_shrd_IMM(emu);
5828 		break;
5829 	case 0xad:
5830 		x86emuOp2_shrd_CL(emu);
5831 		break;
5832 	case 0xaf:
5833 		x86emuOp2_imul_R_RM(emu);
5834 		break;
5835 
5836 	/* 0xb0 TODO: cmpxchg */
5837 	/* 0xb1 TODO: cmpxchg */
5838 	case 0xb2:
5839 		x86emuOp2_lss_R_IMM(emu);
5840 		break;
5841 	case 0xb3:
5842 		x86emuOp2_btr_R(emu);
5843 		break;
5844 	case 0xb4:
5845 		x86emuOp2_lfs_R_IMM(emu);
5846 		break;
5847 	case 0xb5:
5848 		x86emuOp2_lgs_R_IMM(emu);
5849 		break;
5850 	case 0xb6:
5851 		x86emuOp2_movzx_byte_R_RM(emu);
5852 		break;
5853 	case 0xb7:
5854 		x86emuOp2_movzx_word_R_RM(emu);
5855 		break;
5856 	case 0xba:
5857 		x86emuOp2_btX_I(emu);
5858 		break;
5859 	case 0xbb:
5860 		x86emuOp2_btc_R(emu);
5861 		break;
5862 	case 0xbc:
5863 		x86emuOp2_bsf(emu);
5864 		break;
5865 	case 0xbd:
5866 		x86emuOp2_bsr(emu);
5867 		break;
5868 	case 0xbe:
5869 		x86emuOp2_movsx_byte_R_RM(emu);
5870 		break;
5871 	case 0xbf:
5872 		x86emuOp2_movsx_word_R_RM(emu);
5873 		break;
5874 
5875 	/* 0xc0 TODO: xadd */
5876 	/* 0xc1 TODO: xadd */
5877 	/* 0xc8 TODO: bswap */
5878 	/* 0xc9 TODO: bswap */
5879 	/* 0xca TODO: bswap */
5880 	/* 0xcb TODO: bswap */
5881 	/* 0xcc TODO: bswap */
5882 	/* 0xcd TODO: bswap */
5883 	/* 0xce TODO: bswap */
5884 	/* 0xcf TODO: bswap */
5885 
5886 	default:
5887 		x86emu_halt_sys(emu);
5888 		break;
5889 	}
5890 }
5891 
5892 /*
5893  * Carry Chain Calculation
5894  *
5895  * This represents a somewhat expensive calculation which is
5896  * apparently required to emulate the setting of the OF and AF flag.
5897  * The latter is not so important, but the former is.  The overflow
5898  * flag is the XOR of the top two bits of the carry chain for an
5899  * addition (similar for subtraction).  Since we do not want to
5900  * simulate the addition in a bitwise manner, we try to calculate the
5901  * carry chain given the two operands and the result.
5902  *
5903  * So, given the following table, which represents the addition of two
5904  * bits, we can derive a formula for the carry chain.
5905  *
5906  * a   b   cin   r     cout
5907  * 0   0   0     0     0
5908  * 0   0   1     1     0
5909  * 0   1   0     1     0
5910  * 0   1   1     0     1
5911  * 1   0   0     1     0
5912  * 1   0   1     0     1
5913  * 1   1   0     0     1
5914  * 1   1   1     1     1
5915  *
5916  * Construction of table for cout:
5917  *
5918  * ab
5919  * r  \  00   01   11  10
5920  * |------------------
5921  * 0  |   0    1    1   1
5922  * 1  |   0    0    1   0
5923  *
5924  * By inspection, one gets:  cc = ab +  r'(a + b)
5925  *
5926  * That represents alot of operations, but NO CHOICE....
5927  *
5928  * Borrow Chain Calculation.
5929  *
5930  * The following table represents the subtraction of two bits, from
5931  * which we can derive a formula for the borrow chain.
5932  *
5933  * a   b   bin   r     bout
5934  * 0   0   0     0     0
5935  * 0   0   1     1     1
5936  * 0   1   0     1     1
5937  * 0   1   1     0     1
5938  * 1   0   0     1     0
5939  * 1   0   1     0     0
5940  * 1   1   0     0     0
5941  * 1   1   1     1     1
5942  *
5943  * Construction of table for cout:
5944  *
5945  * ab
5946  * r  \  00   01   11  10
5947  * |------------------
5948  * 0  |   0    1    0   0
5949  * 1  |   1    1    1   0
5950  *
5951  * By inspection, one gets:  bc = a'b +  r(a' + b)
5952  *
5953  */
5954 
5955 /*
5956  * Global Variables
5957  */
5958 
5959 static uint32_t x86emu_parity_tab[8] =
5960 {
5961 	0x96696996,
5962 	0x69969669,
5963 	0x69969669,
5964 	0x96696996,
5965 	0x69969669,
5966 	0x96696996,
5967 	0x96696996,
5968 	0x69969669,
5969 };
5970 #define PARITY(x)   (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
5971 #define XOR2(x) 	(((x) ^ ((x)>>1)) & 0x1)
5972 
5973 
5974 /*
5975  * REMARKS:
5976  * Implements the AAA instruction and side effects.
5977  */
5978 static uint16_t
5979 aaa_word(struct x86emu *emu, uint16_t d)
5980 {
5981 	uint16_t res;
5982 	if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
5983 		d += 0x6;
5984 		d += 0x100;
5985 		SET_FLAG(F_AF);
5986 		SET_FLAG(F_CF);
5987 	} else {
5988 		CLEAR_FLAG(F_CF);
5989 		CLEAR_FLAG(F_AF);
5990 	}
5991 	res = (uint16_t) (d & 0xFF0F);
5992 	CLEAR_FLAG(F_SF);
5993 	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
5994 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5995 	return res;
5996 }
5997 
5998 /*
5999  * REMARKS:
6000  * Implements the AAA instruction and side effects.
6001  */
6002 static uint16_t
6003 aas_word(struct x86emu *emu, uint16_t d)
6004 {
6005 	uint16_t res;
6006 	if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
6007 		d -= 0x6;
6008 		d -= 0x100;
6009 		SET_FLAG(F_AF);
6010 		SET_FLAG(F_CF);
6011 	} else {
6012 		CLEAR_FLAG(F_CF);
6013 		CLEAR_FLAG(F_AF);
6014 	}
6015 	res = (uint16_t) (d & 0xFF0F);
6016 	CLEAR_FLAG(F_SF);
6017 	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6018 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6019 	return res;
6020 }
6021 
6022 /*
6023  * REMARKS:
6024  * Implements the AAD instruction and side effects.
6025  */
6026 static uint16_t
6027 aad_word(struct x86emu *emu, uint16_t d)
6028 {
6029 	uint16_t l;
6030 	uint8_t hb, lb;
6031 
6032 	hb = (uint8_t) ((d >> 8) & 0xff);
6033 	lb = (uint8_t) ((d & 0xff));
6034 	l = (uint16_t) ((lb + 10 * hb) & 0xFF);
6035 
6036 	CLEAR_FLAG(F_CF);
6037 	CLEAR_FLAG(F_AF);
6038 	CLEAR_FLAG(F_OF);
6039 	CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
6040 	CONDITIONAL_SET_FLAG(l == 0, F_ZF);
6041 	CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
6042 	return l;
6043 }
6044 
6045 /*
6046  * REMARKS:
6047  * Implements the AAM instruction and side effects.
6048  */
6049 static uint16_t
6050 aam_word(struct x86emu *emu, uint8_t d)
6051 {
6052 	uint16_t h, l;
6053 
6054 	h = (uint16_t) (d / 10);
6055 	l = (uint16_t) (d % 10);
6056 	l |= (uint16_t) (h << 8);
6057 
6058 	CLEAR_FLAG(F_CF);
6059 	CLEAR_FLAG(F_AF);
6060 	CLEAR_FLAG(F_OF);
6061 	CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
6062 	CONDITIONAL_SET_FLAG(l == 0, F_ZF);
6063 	CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
6064 	return l;
6065 }
6066 
6067 /*
6068  * REMARKS:
6069  * Implements the ADC instruction and side effects.
6070  */
6071 static uint8_t
6072 adc_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6073 {
6074 	uint32_t res;	/* all operands in native machine order */
6075 	uint32_t cc;
6076 
6077 	if (ACCESS_FLAG(F_CF))
6078 		res = 1 + d + s;
6079 	else
6080 		res = d + s;
6081 
6082 	CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
6083 	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6084 	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6085 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6086 
6087 	/* calculate the carry chain  SEE NOTE AT TOP. */
6088 	cc = (s & d) | ((~res) & (s | d));
6089 	CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6090 	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6091 	return (uint8_t) res;
6092 }
6093 
6094 /*
6095  * REMARKS:
6096  * Implements the ADC instruction and side effects.
6097  */
6098 static uint16_t
6099 adc_word(struct x86emu *emu, uint16_t d, uint16_t s)
6100 {
6101 	uint32_t res;	/* all operands in native machine order */
6102 	uint32_t cc;
6103 
6104 	if (ACCESS_FLAG(F_CF))
6105 		res = 1 + d + s;
6106 	else
6107 		res = d + s;
6108 
6109 	CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
6110 	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6111 	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6112 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6113 
6114 	/* calculate the carry chain  SEE NOTE AT TOP. */
6115 	cc = (s & d) | ((~res) & (s | d));
6116 	CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6117 	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6118 	return (uint16_t) res;
6119 }
6120 
6121 /*
6122  * REMARKS:
6123  * Implements the ADC instruction and side effects.
6124  */
6125 static uint32_t
6126 adc_long(struct x86emu *emu, uint32_t d, uint32_t s)
6127 {
6128 	uint32_t lo;	/* all operands in native machine order */
6129 	uint32_t hi;
6130 	uint32_t res;
6131 	uint32_t cc;
6132 
6133 	if (ACCESS_FLAG(F_CF)) {
6134 		lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
6135 		res = 1 + d + s;
6136 	} else {
6137 		lo = (d & 0xFFFF) + (s & 0xFFFF);
6138 		res = d + s;
6139 	}
6140 	hi = (lo >> 16) + (d >> 16) + (s >> 16);
6141 
6142 	CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
6143 	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6144 	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6145 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6146 
6147 	/* calculate the carry chain  SEE NOTE AT TOP. */
6148 	cc = (s & d) | ((~res) & (s | d));
6149 	CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6150 	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6151 	return res;
6152 }
6153 
6154 /*
6155  * REMARKS:
6156  * Implements the ADD instruction and side effects.
6157  */
6158 static uint8_t
6159 add_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6160 {
6161 	uint32_t res;	/* all operands in native machine order */
6162 	uint32_t cc;
6163 
6164 	res = d + s;
6165 	CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
6166 	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6167 	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6168 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6169 
6170 	/* calculate the carry chain  SEE NOTE AT TOP. */
6171 	cc = (s & d) | ((~res) & (s | d));
6172 	CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6173 	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6174 	return (uint8_t) res;
6175 }
6176 
6177 /*
6178  * REMARKS:
6179  * Implements the ADD instruction and side effects.
6180  */
6181 static uint16_t
6182 add_word(struct x86emu *emu, uint16_t d, uint16_t s)
6183 {
6184 	uint32_t res;	/* all operands in native machine order */
6185 	uint32_t cc;
6186 
6187 	res = d + s;
6188 	CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
6189 	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6190 	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6191 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6192 
6193 	/* calculate the carry chain  SEE NOTE AT TOP. */
6194 	cc = (s & d) | ((~res) & (s | d));
6195 	CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6196 	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6197 	return (uint16_t) res;
6198 }
6199 
6200 /*
6201  * REMARKS:
6202  * Implements the ADD instruction and side effects.
6203  */
6204 static uint32_t
6205 add_long(struct x86emu *emu, uint32_t d, uint32_t s)
6206 {
6207 	uint32_t lo;	/* all operands in native machine order */
6208 	uint32_t hi;
6209 	uint32_t res;
6210 	uint32_t cc;
6211 
6212 	lo = (d & 0xFFFF) + (s & 0xFFFF);
6213 	res = d + s;
6214 	hi = (lo >> 16) + (d >> 16) + (s >> 16);
6215 
6216 	CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
6217 	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6218 	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6219 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6220 
6221 	/* calculate the carry chain  SEE NOTE AT TOP. */
6222 	cc = (s & d) | ((~res) & (s | d));
6223 	CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6224 	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6225 
6226 	return res;
6227 }
6228 
6229 /*
6230  * REMARKS:
6231  * Implements the AND instruction and side effects.
6232  */
6233 static uint8_t
6234 and_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6235 {
6236 	uint8_t res;	/* all operands in native machine order */
6237 
6238 	res = d & s;
6239 
6240 	/* set the flags  */
6241 	CLEAR_FLAG(F_OF);
6242 	CLEAR_FLAG(F_CF);
6243 	CLEAR_FLAG(F_AF);
6244 	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6245 	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6246 	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6247 	return res;
6248 }
6249 
6250 /*
6251  * REMARKS:
6252  * Implements the AND instruction and side effects.
6253  */
6254 static uint16_t
6255 and_word(struct x86emu *emu, uint16_t d, uint16_t s)
6256 {
6257 	uint16_t res;	/* all operands in native machine order */
6258 
6259 	res = d & s;
6260 
6261 	/* set the flags  */
6262 	CLEAR_FLAG(F_OF);
6263 	CLEAR_FLAG(F_CF);
6264 	CLEAR_FLAG(F_AF);
6265 	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6266 	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6267 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6268 	return res;
6269 }
6270 
6271 /*
6272  * REMARKS:
6273  * Implements the AND instruction and side effects.
6274  */
6275 static uint32_t
6276 and_long(struct x86emu *emu, uint32_t d, uint32_t s)
6277 {
6278 	uint32_t res;	/* all operands in native machine order */
6279 
6280 	res = d & s;
6281 
6282 	/* set the flags  */
6283 	CLEAR_FLAG(F_OF);
6284 	CLEAR_FLAG(F_CF);
6285 	CLEAR_FLAG(F_AF);
6286 	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6287 	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6288 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6289 	return res;
6290 }
6291 
6292 /*
6293  * REMARKS:
6294  * Implements the CMP instruction and side effects.
6295  */
6296 static uint8_t
6297 cmp_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6298 {
6299 	uint32_t res;	/* all operands in native machine order */
6300 	uint32_t bc;
6301 
6302 	res = d - s;
6303 	CLEAR_FLAG(F_CF);
6304 	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6305 	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6306 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6307 
6308 	/* calculate the borrow chain.  See note at top */
6309 	bc = (res & (~d | s)) | (~d & s);
6310 	CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
6311 	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6312 	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6313 	return d;
6314 }
6315 
6316 static void
6317 cmp_byte_no_return(struct x86emu *emu, uint8_t d, uint8_t s)
6318 {
6319 	cmp_byte(emu, d, s);
6320 }
6321 
6322 /*
6323  * REMARKS:
6324  * Implements the CMP instruction and side effects.
6325  */
6326 static uint16_t
6327 cmp_word(struct x86emu *emu, uint16_t d, uint16_t s)
6328 {
6329 	uint32_t res;	/* all operands in native machine order */
6330 	uint32_t bc;
6331 
6332 	res = d - s;
6333 	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6334 	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6335 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6336 
6337 	/* calculate the borrow chain.  See note at top */
6338 	bc = (res & (~d | s)) | (~d & s);
6339 	CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
6340 	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6341 	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6342 	return d;
6343 }
6344 
6345 static void
6346 cmp_word_no_return(struct x86emu *emu, uint16_t d, uint16_t s)
6347 {
6348 	cmp_word(emu, d, s);
6349 }
6350 
6351 /*
6352  * REMARKS:
6353  * Implements the CMP instruction and side effects.
6354  */
6355 static uint32_t
6356 cmp_long(struct x86emu *emu, uint32_t d, uint32_t s)
6357 {
6358 	uint32_t res;	/* all operands in native machine order */
6359 	uint32_t bc;
6360 
6361 	res = d - s;
6362 	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6363 	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6364 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6365 
6366 	/* calculate the borrow chain.  See note at top */
6367 	bc = (res & (~d | s)) | (~d & s);
6368 	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
6369 	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6370 	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6371 	return d;
6372 }
6373 
6374 static void
6375 cmp_long_no_return(struct x86emu *emu, uint32_t d, uint32_t s)
6376 {
6377 	cmp_long(emu, d, s);
6378 }
6379 
6380 /*
6381  * REMARKS:
6382  * Implements the DAA instruction and side effects.
6383  */
6384 static uint8_t
6385 daa_byte(struct x86emu *emu, uint8_t d)
6386 {
6387 	uint32_t res = d;
6388 	if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6389 		res += 6;
6390 		SET_FLAG(F_AF);
6391 	}
6392 	if (res > 0x9F || ACCESS_FLAG(F_CF)) {
6393 		res += 0x60;
6394 		SET_FLAG(F_CF);
6395 	}
6396 	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6397 	CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
6398 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6399 	return (uint8_t) res;
6400 }
6401 
6402 /*
6403  * REMARKS:
6404  * Implements the DAS instruction and side effects.
6405  */
6406 static uint8_t
6407 das_byte(struct x86emu *emu, uint8_t d)
6408 {
6409 	if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6410 		d -= 6;
6411 		SET_FLAG(F_AF);
6412 	}
6413 	if (d > 0x9F || ACCESS_FLAG(F_CF)) {
6414 		d -= 0x60;
6415 		SET_FLAG(F_CF);
6416 	}
6417 	CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
6418 	CONDITIONAL_SET_FLAG(d == 0, F_ZF);
6419 	CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
6420 	return d;
6421 }
6422 
6423 /*
6424  * REMARKS:
6425  * Implements the DEC instruction and side effects.
6426  */
6427 static uint8_t
6428 dec_byte(struct x86emu *emu, uint8_t d)
6429 {
6430 	uint32_t res;	/* all operands in native machine order */
6431 	uint32_t bc;
6432 
6433 	res = d - 1;
6434 	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6435 	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6436 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6437 
6438 	/* calculate the borrow chain.  See note at top */
6439 	/* based on sub_byte, uses s==1.  */
6440 	bc = (res & (~d | 1)) | (~d & 1);
6441 	/* carry flag unchanged */
6442 	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6443 	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6444 	return (uint8_t) res;
6445 }
6446 
6447 /*
6448  * REMARKS:
6449  * Implements the DEC instruction and side effects.
6450  */
6451 static uint16_t
6452 dec_word(struct x86emu *emu, uint16_t d)
6453 {
6454 	uint32_t res;	/* all operands in native machine order */
6455 	uint32_t bc;
6456 
6457 	res = d - 1;
6458 	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6459 	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6460 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6461 
6462 	/* calculate the borrow chain.  See note at top */
6463 	/* based on the sub_byte routine, with s==1 */
6464 	bc = (res & (~d | 1)) | (~d & 1);
6465 	/* carry flag unchanged */
6466 	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6467 	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6468 	return (uint16_t) res;
6469 }
6470 
6471 /*
6472  * REMARKS:
6473  * Implements the DEC instruction and side effects.
6474  */
6475 static uint32_t
6476 dec_long(struct x86emu *emu, uint32_t d)
6477 {
6478 	uint32_t res;	/* all operands in native machine order */
6479 	uint32_t bc;
6480 
6481 	res = d - 1;
6482 
6483 	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6484 	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6485 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6486 
6487 	/* calculate the borrow chain.  See note at top */
6488 	bc = (res & (~d | 1)) | (~d & 1);
6489 	/* carry flag unchanged */
6490 	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6491 	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6492 	return res;
6493 }
6494 
6495 /*
6496  * REMARKS:
6497  * Implements the INC instruction and side effects.
6498  */
6499 static uint8_t
6500 inc_byte(struct x86emu *emu, uint8_t d)
6501 {
6502 	uint32_t res;	/* all operands in native machine order */
6503 	uint32_t cc;
6504 
6505 	res = d + 1;
6506 	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6507 	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6508 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6509 
6510 	/* calculate the carry chain  SEE NOTE AT TOP. */
6511 	cc = ((1 & d) | (~res)) & (1 | d);
6512 	CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6513 	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6514 	return (uint8_t) res;
6515 }
6516 
6517 /*
6518  * REMARKS:
6519  * Implements the INC instruction and side effects.
6520  */
6521 static uint16_t
6522 inc_word(struct x86emu *emu, uint16_t d)
6523 {
6524 	uint32_t res;	/* all operands in native machine order */
6525 	uint32_t cc;
6526 
6527 	res = d + 1;
6528 	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6529 	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6530 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6531 
6532 	/* calculate the carry chain  SEE NOTE AT TOP. */
6533 	cc = (1 & d) | ((~res) & (1 | d));
6534 	CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6535 	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6536 	return (uint16_t) res;
6537 }
6538 
6539 /*
6540  * REMARKS:
6541  * Implements the INC instruction and side effects.
6542  */
6543 static uint32_t
6544 inc_long(struct x86emu *emu, uint32_t d)
6545 {
6546 	uint32_t res;	/* all operands in native machine order */
6547 	uint32_t cc;
6548 
6549 	res = d + 1;
6550 	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6551 	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6552 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6553 
6554 	/* calculate the carry chain  SEE NOTE AT TOP. */
6555 	cc = (1 & d) | ((~res) & (1 | d));
6556 	CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6557 	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6558 	return res;
6559 }
6560 
6561 /*
6562  * REMARKS:
6563  * Implements the OR instruction and side effects.
6564  */
6565 static uint8_t
6566 or_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6567 {
6568 	uint8_t res;	/* all operands in native machine order */
6569 
6570 	res = d | s;
6571 	CLEAR_FLAG(F_OF);
6572 	CLEAR_FLAG(F_CF);
6573 	CLEAR_FLAG(F_AF);
6574 	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6575 	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6576 	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6577 	return res;
6578 }
6579 
6580 /*
6581  * REMARKS:
6582  * Implements the OR instruction and side effects.
6583  */
6584 static uint16_t
6585 or_word(struct x86emu *emu, uint16_t d, uint16_t s)
6586 {
6587 	uint16_t res;	/* all operands in native machine order */
6588 
6589 	res = d | s;
6590 	/* set the carry flag to be bit 8 */
6591 	CLEAR_FLAG(F_OF);
6592 	CLEAR_FLAG(F_CF);
6593 	CLEAR_FLAG(F_AF);
6594 	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6595 	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6596 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6597 	return res;
6598 }
6599 
6600 /*
6601  * REMARKS:
6602  * Implements the OR instruction and side effects.
6603  */
6604 static uint32_t
6605 or_long(struct x86emu *emu, uint32_t d, uint32_t s)
6606 {
6607 	uint32_t res;	/* all operands in native machine order */
6608 
6609 	res = d | s;
6610 
6611 	/* set the carry flag to be bit 8 */
6612 	CLEAR_FLAG(F_OF);
6613 	CLEAR_FLAG(F_CF);
6614 	CLEAR_FLAG(F_AF);
6615 	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6616 	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6617 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6618 	return res;
6619 }
6620 
6621 /*
6622  * REMARKS:
6623  * Implements the OR instruction and side effects.
6624  */
6625 static uint8_t
6626 neg_byte(struct x86emu *emu, uint8_t s)
6627 {
6628 	uint8_t res;
6629 	uint8_t bc;
6630 
6631 	CONDITIONAL_SET_FLAG(s != 0, F_CF);
6632 	res = (uint8_t) - s;
6633 	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6634 	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6635 	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6636 	/* calculate the borrow chain --- modified such that d=0.
6637 	 * substitutiing d=0 into     bc= res&(~d|s)|(~d&s); (the one used for
6638 	 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6639 	 * res&0xfff... == res.  Similarly ~d&s == s.  So the simplified
6640 	 * result is: */
6641 	bc = res | s;
6642 	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6643 	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6644 	return res;
6645 }
6646 
6647 /*
6648  * REMARKS:
6649  * Implements the OR instruction and side effects.
6650  */
6651 static uint16_t
6652 neg_word(struct x86emu *emu, uint16_t s)
6653 {
6654 	uint16_t res;
6655 	uint16_t bc;
6656 
6657 	CONDITIONAL_SET_FLAG(s != 0, F_CF);
6658 	res = (uint16_t) - s;
6659 	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6660 	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6661 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6662 
6663 	/* calculate the borrow chain --- modified such that d=0.
6664 	 * substitutiing d=0 into     bc= res&(~d|s)|(~d&s); (the one used for
6665 	 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6666 	 * res&0xfff... == res.  Similarly ~d&s == s.  So the simplified
6667 	 * result is: */
6668 	bc = res | s;
6669 	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6670 	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6671 	return res;
6672 }
6673 
6674 /*
6675  * REMARKS:
6676  * Implements the OR instruction and side effects.
6677  */
6678 static uint32_t
6679 neg_long(struct x86emu *emu, uint32_t s)
6680 {
6681 	uint32_t res;
6682 	uint32_t bc;
6683 
6684 	CONDITIONAL_SET_FLAG(s != 0, F_CF);
6685 	res = (uint32_t) - s;
6686 	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6687 	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6688 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6689 
6690 	/* calculate the borrow chain --- modified such that d=0.
6691 	 * substitutiing d=0 into     bc= res&(~d|s)|(~d&s); (the one used for
6692 	 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6693 	 * res&0xfff... == res.  Similarly ~d&s == s.  So the simplified
6694 	 * result is: */
6695 	bc = res | s;
6696 	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6697 	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6698 	return res;
6699 }
6700 
6701 /*
6702  * REMARKS:
6703  * Implements the RCL instruction and side effects.
6704  */
6705 static uint8_t
6706 rcl_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6707 {
6708 	unsigned int res, cnt, mask, cf;
6709 
6710 	/* s is the rotate distance.  It varies from 0 - 8. */
6711 	/* have
6712 	 *
6713 	 * CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6714 	 *
6715 	 * want to rotate through the carry by "s" bits.  We could loop, but
6716 	 * that's inefficient.  So the width is 9, and we split into three
6717 	 * parts:
6718 	 *
6719 	 * The new carry flag   (was B_n) the stuff in B_n-1 .. B_0 the stuff
6720 	 * in B_7 .. B_n+1
6721 	 *
6722 	 * The new rotate is done mod 9, and given this, for a rotation of n
6723 	 * bits (mod 9) the new carry flag is then located n bits from the MSB.
6724 	 * The low part is then shifted up cnt bits, and the high part is or'd
6725 	 * in.  Using CAPS for new values, and lowercase for the original
6726 	 * values, this can be expressed as:
6727 	 *
6728 	 * IF n > 0 1) CF <-  b_(8-n) 2) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0
6729 	 * 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1))
6730 	 */
6731 	res = d;
6732 	if ((cnt = s % 9) != 0) {
6733 		/* extract the new CARRY FLAG. */
6734 		/* CF <-  b_(8-n)             */
6735 		cf = (d >> (8 - cnt)) & 0x1;
6736 
6737 		/*
6738 		 * Get the low stuff which rotated into the range B_7 .. B_cnt
6739 		 * B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0
6740 		 * note that the right hand side done by the mask.
6741 		 */
6742 		res = (d << cnt) & 0xff;
6743 
6744 		/*
6745 		 * now the high stuff which rotated around into the positions
6746 		 * B_cnt-2 .. B_0
6747 		 * B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1))
6748 		 * shift it downward, 7-(n-2) = 9-n positions. and mask off
6749 		 * the result before or'ing in.
6750 		 */
6751 		mask = (1 << (cnt - 1)) - 1;
6752 		res |= (d >> (9 - cnt)) & mask;
6753 
6754 		/* if the carry flag was set, or it in.  */
6755 		if (ACCESS_FLAG(F_CF)) {	/* carry flag is set */
6756 			/* B_(n-1) <- cf */
6757 			res |= 1 << (cnt - 1);
6758 		}
6759 		/* set the new carry flag, based on the variable "cf" */
6760 		CONDITIONAL_SET_FLAG(cf, F_CF);
6761 		/* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6762 		 * the most significant bit.  Blecck. */
6763 		/* parenthesized this expression since it appears to be
6764 		 * causing OF to be misset */
6765 		CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
6766 		    F_OF);
6767 
6768 	}
6769 	return (uint8_t) res;
6770 }
6771 
6772 /*
6773  * REMARKS:
6774  * Implements the RCL instruction and side effects.
6775  */
6776 static uint16_t
6777 rcl_word(struct x86emu *emu, uint16_t d, uint8_t s)
6778 {
6779 	unsigned int res, cnt, mask, cf;
6780 
6781 	res = d;
6782 	if ((cnt = s % 17) != 0) {
6783 		cf = (d >> (16 - cnt)) & 0x1;
6784 		res = (d << cnt) & 0xffff;
6785 		mask = (1 << (cnt - 1)) - 1;
6786 		res |= (d >> (17 - cnt)) & mask;
6787 		if (ACCESS_FLAG(F_CF)) {
6788 			res |= 1 << (cnt - 1);
6789 		}
6790 		CONDITIONAL_SET_FLAG(cf, F_CF);
6791 		CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
6792 		    F_OF);
6793 	}
6794 	return (uint16_t) res;
6795 }
6796 
6797 /*
6798  * REMARKS:
6799  * Implements the RCL instruction and side effects.
6800  */
6801 static uint32_t
6802 rcl_long(struct x86emu *emu, uint32_t d, uint8_t s)
6803 {
6804 	uint32_t res, cnt, mask, cf;
6805 
6806 	res = d;
6807 	if ((cnt = s % 33) != 0) {
6808 		cf = (d >> (32 - cnt)) & 0x1;
6809 		res = (d << cnt) & 0xffffffff;
6810 		mask = (1 << (cnt - 1)) - 1;
6811 		res |= (d >> (33 - cnt)) & mask;
6812 		if (ACCESS_FLAG(F_CF)) {	/* carry flag is set */
6813 			res |= 1 << (cnt - 1);
6814 		}
6815 		CONDITIONAL_SET_FLAG(cf, F_CF);
6816 		CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
6817 		    F_OF);
6818 	}
6819 	return res;
6820 }
6821 
6822 /*
6823  * REMARKS:
6824  * Implements the RCR instruction and side effects.
6825  */
6826 static uint8_t
6827 rcr_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6828 {
6829 	uint32_t res, cnt;
6830 	uint32_t mask, cf, ocf = 0;
6831 
6832 	/* rotate right through carry */
6833 	/* s is the rotate distance.  It varies from 0 - 8. d is the byte
6834 	 * object rotated.
6835 	 *
6836 	 * have
6837 	 *
6838 	 * CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6839 	 *
6840 	 * The new rotate is done mod 9, and given this, for a rotation of n
6841 	 * bits (mod 9) the new carry flag is then located n bits from the LSB.
6842 	 * The low part is then shifted up cnt bits, and the high part is or'd
6843 	 * in.  Using CAPS for new values, and lowercase for the original
6844 	 * values, this can be expressed as:
6845 	 *
6846 	 * IF n > 0
6847 	 *	1) CF <-  b_(n-1)
6848 	 *	2) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
6849 	 * 	3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0)
6850 	 */
6851 	res = d;
6852 	if ((cnt = s % 9) != 0) {
6853 		/* extract the new CARRY FLAG. */
6854 		/* CF <-  b_(n-1)              */
6855 		if (cnt == 1) {
6856 			cf = d & 0x1;
6857 			/* note hackery here.  Access_flag(..) evaluates to
6858 			 * either 0 if flag not set non-zero if flag is set.
6859 			 * doing access_flag(..) != 0 casts that into either
6860 			 * 0..1 in any representation of the flags register
6861 			 * (i.e. packed bit array or unpacked.) */
6862 			ocf = ACCESS_FLAG(F_CF) != 0;
6863 		} else
6864 			cf = (d >> (cnt - 1)) & 0x1;
6865 
6866 		/* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_n  */
6867 		/* note that the right hand side done by the mask This is
6868 		 * effectively done by shifting the object to the right.  The
6869 		 * result must be masked, in case the object came in and was
6870 		 * treated as a negative number.  Needed??? */
6871 
6872 		mask = (1 << (8 - cnt)) - 1;
6873 		res = (d >> cnt) & mask;
6874 
6875 		/* now the high stuff which rotated around into the positions
6876 		 * B_cnt-2 .. B_0 */
6877 		/* B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0) */
6878 		/* shift it downward, 7-(n-2) = 9-n positions. and mask off
6879 		 * the result before or'ing in. */
6880 		res |= (d << (9 - cnt));
6881 
6882 		/* if the carry flag was set, or it in.  */
6883 		if (ACCESS_FLAG(F_CF)) {	/* carry flag is set */
6884 			/* B_(8-n) <- cf */
6885 			res |= 1 << (8 - cnt);
6886 		}
6887 		/* set the new carry flag, based on the variable "cf" */
6888 		CONDITIONAL_SET_FLAG(cf, F_CF);
6889 		/* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6890 		 * the most significant bit.  Blecck. */
6891 		/* parenthesized... */
6892 		if (cnt == 1) {
6893 			CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
6894 			    F_OF);
6895 		}
6896 	}
6897 	return (uint8_t) res;
6898 }
6899 
6900 /*
6901  * REMARKS:
6902  * Implements the RCR instruction and side effects.
6903  */
6904 static uint16_t
6905 rcr_word(struct x86emu *emu, uint16_t d, uint8_t s)
6906 {
6907 	uint32_t res, cnt;
6908 	uint32_t mask, cf, ocf = 0;
6909 
6910 	/* rotate right through carry */
6911 	res = d;
6912 	if ((cnt = s % 17) != 0) {
6913 		if (cnt == 1) {
6914 			cf = d & 0x1;
6915 			ocf = ACCESS_FLAG(F_CF) != 0;
6916 		} else
6917 			cf = (d >> (cnt - 1)) & 0x1;
6918 		mask = (1 << (16 - cnt)) - 1;
6919 		res = (d >> cnt) & mask;
6920 		res |= (d << (17 - cnt));
6921 		if (ACCESS_FLAG(F_CF)) {
6922 			res |= 1 << (16 - cnt);
6923 		}
6924 		CONDITIONAL_SET_FLAG(cf, F_CF);
6925 		if (cnt == 1) {
6926 			CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
6927 			    F_OF);
6928 		}
6929 	}
6930 	return (uint16_t) res;
6931 }
6932 
6933 /*
6934  * REMARKS:
6935  * Implements the RCR instruction and side effects.
6936  */
6937 static uint32_t
6938 rcr_long(struct x86emu *emu, uint32_t d, uint8_t s)
6939 {
6940 	uint32_t res, cnt;
6941 	uint32_t mask, cf, ocf = 0;
6942 
6943 	/* rotate right through carry */
6944 	res = d;
6945 	if ((cnt = s % 33) != 0) {
6946 		if (cnt == 1) {
6947 			cf = d & 0x1;
6948 			ocf = ACCESS_FLAG(F_CF) != 0;
6949 		} else
6950 			cf = (d >> (cnt - 1)) & 0x1;
6951 		mask = (1 << (32 - cnt)) - 1;
6952 		res = (d >> cnt) & mask;
6953 		if (cnt != 1)
6954 			res |= (d << (33 - cnt));
6955 		if (ACCESS_FLAG(F_CF)) {	/* carry flag is set */
6956 			res |= 1 << (32 - cnt);
6957 		}
6958 		CONDITIONAL_SET_FLAG(cf, F_CF);
6959 		if (cnt == 1) {
6960 			CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
6961 			    F_OF);
6962 		}
6963 	}
6964 	return res;
6965 }
6966 
6967 /*
6968  * REMARKS:
6969  * Implements the ROL instruction and side effects.
6970  */
6971 static uint8_t
6972 rol_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6973 {
6974 	unsigned int res, cnt, mask;
6975 
6976 	/* rotate left */
6977 	/* s is the rotate distance.  It varies from 0 - 8. d is the byte
6978 	 * object rotated.
6979 	 *
6980 	 * have
6981 	 *
6982 	 * CF  B_7 ... B_0
6983 	 *
6984 	 * The new rotate is done mod 8. Much simpler than the "rcl" or "rcr"
6985 	 * operations.
6986 	 *
6987 	 * IF n > 0 1) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) 2) B_(n-1) ..
6988 	 * B_(0) <-  b_(7) .. b_(8-n) */
6989 	res = d;
6990 	if ((cnt = s % 8) != 0) {
6991 		/* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) */
6992 		res = (d << cnt);
6993 
6994 		/* B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n) */
6995 		mask = (1 << cnt) - 1;
6996 		res |= (d >> (8 - cnt)) & mask;
6997 
6998 		/* OVERFLOW is set *IFF* s==1, then it is the xor of CF and
6999 		 * the most significant bit.  Blecck. */
7000 		CONDITIONAL_SET_FLAG(s == 1 &&
7001 		    XOR2((res & 0x1) + ((res >> 6) & 0x2)),
7002 		    F_OF);
7003 	}
7004 	if (s != 0) {
7005 		/* set the new carry flag, Note that it is the low order bit
7006 		 * of the result!!!                               */
7007 		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7008 	}
7009 	return (uint8_t) res;
7010 }
7011 
7012 /*
7013  * REMARKS:
7014  * Implements the ROL instruction and side effects.
7015  */
7016 static uint16_t
7017 rol_word(struct x86emu *emu, uint16_t d, uint8_t s)
7018 {
7019 	unsigned int res, cnt, mask;
7020 
7021 	res = d;
7022 	if ((cnt = s % 16) != 0) {
7023 		res = (d << cnt);
7024 		mask = (1 << cnt) - 1;
7025 		res |= (d >> (16 - cnt)) & mask;
7026 		CONDITIONAL_SET_FLAG(s == 1 &&
7027 		    XOR2((res & 0x1) + ((res >> 14) & 0x2)),
7028 		    F_OF);
7029 	}
7030 	if (s != 0) {
7031 		/* set the new carry flag, Note that it is the low order bit
7032 		 * of the result!!!                               */
7033 		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7034 	}
7035 	return (uint16_t) res;
7036 }
7037 
7038 /*
7039  * REMARKS:
7040  * Implements the ROL instruction and side effects.
7041  */
7042 static uint32_t
7043 rol_long(struct x86emu *emu, uint32_t d, uint8_t s)
7044 {
7045 	uint32_t res, cnt, mask;
7046 
7047 	res = d;
7048 	if ((cnt = s % 32) != 0) {
7049 		res = (d << cnt);
7050 		mask = (1 << cnt) - 1;
7051 		res |= (d >> (32 - cnt)) & mask;
7052 		CONDITIONAL_SET_FLAG(s == 1 &&
7053 		    XOR2((res & 0x1) + ((res >> 30) & 0x2)),
7054 		    F_OF);
7055 	}
7056 	if (s != 0) {
7057 		/* set the new carry flag, Note that it is the low order bit
7058 		 * of the result!!!                               */
7059 		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7060 	}
7061 	return res;
7062 }
7063 
7064 /*
7065  * REMARKS:
7066  * Implements the ROR instruction and side effects.
7067  */
7068 static uint8_t
7069 ror_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7070 {
7071 	unsigned int res, cnt, mask;
7072 
7073 	/* rotate right */
7074 	/* s is the rotate distance.  It varies from 0 - 8. d is the byte
7075 	 * object rotated.
7076 	 *
7077 	 * have
7078 	 *
7079 	 * B_7 ... B_0
7080 	 *
7081 	 * The rotate is done mod 8.
7082 	 *
7083 	 * IF n > 0 1) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n) 2) B_(7) ..
7084 	 * B_(8-n) <-  b_(n-1) .. b_(0) */
7085 	res = d;
7086 	if ((cnt = s % 8) != 0) {	/* not a typo, do nada if cnt==0 */
7087 		/* B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0) */
7088 		res = (d << (8 - cnt));
7089 
7090 		/* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n) */
7091 		mask = (1 << (8 - cnt)) - 1;
7092 		res |= (d >> (cnt)) & mask;
7093 
7094 		/* OVERFLOW is set *IFF* s==1, then it is the xor of the two
7095 		 * most significant bits.  Blecck. */
7096 		CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
7097 	}
7098 	if (s != 0) {
7099 		/* set the new carry flag, Note that it is the high order bit
7100 		 * of the result!!!                               */
7101 		CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
7102 	}
7103 	return (uint8_t) res;
7104 }
7105 
7106 /*
7107  * REMARKS:
7108  * Implements the ROR instruction and side effects.
7109  */
7110 static uint16_t
7111 ror_word(struct x86emu *emu, uint16_t d, uint8_t s)
7112 {
7113 	unsigned int res, cnt, mask;
7114 
7115 	res = d;
7116 	if ((cnt = s % 16) != 0) {
7117 		res = (d << (16 - cnt));
7118 		mask = (1 << (16 - cnt)) - 1;
7119 		res |= (d >> (cnt)) & mask;
7120 		CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
7121 	}
7122 	if (s != 0) {
7123 		/* set the new carry flag, Note that it is the high order bit
7124 		 * of the result!!!                               */
7125 		CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
7126 	}
7127 	return (uint16_t) res;
7128 }
7129 
7130 /*
7131  * REMARKS:
7132  * Implements the ROR instruction and side effects.
7133  */
7134 static uint32_t
7135 ror_long(struct x86emu *emu, uint32_t d, uint8_t s)
7136 {
7137 	uint32_t res, cnt, mask;
7138 
7139 	res = d;
7140 	if ((cnt = s % 32) != 0) {
7141 		res = (d << (32 - cnt));
7142 		mask = (1 << (32 - cnt)) - 1;
7143 		res |= (d >> (cnt)) & mask;
7144 		CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
7145 	}
7146 	if (s != 0) {
7147 		/* set the new carry flag, Note that it is the high order bit
7148 		 * of the result!!!                               */
7149 		CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
7150 	}
7151 	return res;
7152 }
7153 
7154 /*
7155  * REMARKS:
7156  * Implements the SHL instruction and side effects.
7157  */
7158 static uint8_t
7159 shl_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7160 {
7161 	unsigned int cnt, res, cf;
7162 
7163 	if (s < 8) {
7164 		cnt = s % 8;
7165 
7166 		/* last bit shifted out goes into carry flag */
7167 		if (cnt > 0) {
7168 			res = d << cnt;
7169 			cf = d & (1 << (8 - cnt));
7170 			CONDITIONAL_SET_FLAG(cf, F_CF);
7171 			CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7172 			CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7173 			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7174 		} else {
7175 			res = (uint8_t) d;
7176 		}
7177 
7178 		if (cnt == 1) {
7179 			/* Needs simplification. */
7180 			CONDITIONAL_SET_FLAG(
7181 			    (((res & 0x80) == 0x80) ^
7182 				(ACCESS_FLAG(F_CF) != 0)),
7183 			/* was (emu->x86.R_FLG&F_CF)==F_CF)), */
7184 			    F_OF);
7185 		} else {
7186 			CLEAR_FLAG(F_OF);
7187 		}
7188 	} else {
7189 		res = 0;
7190 		CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF);
7191 		CLEAR_FLAG(F_OF);
7192 		CLEAR_FLAG(F_SF);
7193 		SET_FLAG(F_PF);
7194 		SET_FLAG(F_ZF);
7195 	}
7196 	return (uint8_t) res;
7197 }
7198 
7199 /*
7200  * REMARKS:
7201  * Implements the SHL instruction and side effects.
7202  */
7203 static uint16_t
7204 shl_word(struct x86emu *emu, uint16_t d, uint8_t s)
7205 {
7206 	unsigned int cnt, res, cf;
7207 
7208 	if (s < 16) {
7209 		cnt = s % 16;
7210 		if (cnt > 0) {
7211 			res = d << cnt;
7212 			cf = d & (1 << (16 - cnt));
7213 			CONDITIONAL_SET_FLAG(cf, F_CF);
7214 			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7215 			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7216 			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7217 		} else {
7218 			res = (uint16_t) d;
7219 		}
7220 
7221 		if (cnt == 1) {
7222 			CONDITIONAL_SET_FLAG(
7223 			    (((res & 0x8000) == 0x8000) ^
7224 				(ACCESS_FLAG(F_CF) != 0)),
7225 			    F_OF);
7226 		} else {
7227 			CLEAR_FLAG(F_OF);
7228 		}
7229 	} else {
7230 		res = 0;
7231 		CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
7232 		CLEAR_FLAG(F_OF);
7233 		CLEAR_FLAG(F_SF);
7234 		SET_FLAG(F_PF);
7235 		SET_FLAG(F_ZF);
7236 	}
7237 	return (uint16_t) res;
7238 }
7239 
7240 /*
7241  * REMARKS:
7242  * Implements the SHL instruction and side effects.
7243  */
7244 static uint32_t
7245 shl_long(struct x86emu *emu, uint32_t d, uint8_t s)
7246 {
7247 	unsigned int cnt, res, cf;
7248 
7249 	if (s < 32) {
7250 		cnt = s % 32;
7251 		if (cnt > 0) {
7252 			res = d << cnt;
7253 			cf = d & (1 << (32 - cnt));
7254 			CONDITIONAL_SET_FLAG(cf, F_CF);
7255 			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7256 			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7257 			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7258 		} else {
7259 			res = d;
7260 		}
7261 		if (cnt == 1) {
7262 			CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000)
7263 			    ^ (ACCESS_FLAG(F_CF) != 0)), F_OF);
7264 		} else {
7265 			CLEAR_FLAG(F_OF);
7266 		}
7267 	} else {
7268 		res = 0;
7269 		CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7270 		CLEAR_FLAG(F_OF);
7271 		CLEAR_FLAG(F_SF);
7272 		SET_FLAG(F_PF);
7273 		SET_FLAG(F_ZF);
7274 	}
7275 	return res;
7276 }
7277 
7278 /*
7279  * REMARKS:
7280  * Implements the SHR instruction and side effects.
7281  */
7282 static uint8_t
7283 shr_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7284 {
7285 	unsigned int cnt, res, cf;
7286 
7287 	if (s < 8) {
7288 		cnt = s % 8;
7289 		if (cnt > 0) {
7290 			cf = d & (1 << (cnt - 1));
7291 			res = d >> cnt;
7292 			CONDITIONAL_SET_FLAG(cf, F_CF);
7293 			CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7294 			CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7295 			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7296 		} else {
7297 			res = (uint8_t) d;
7298 		}
7299 
7300 		if (cnt == 1) {
7301 			CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
7302 		} else {
7303 			CLEAR_FLAG(F_OF);
7304 		}
7305 	} else {
7306 		res = 0;
7307 		CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF);
7308 		CLEAR_FLAG(F_OF);
7309 		CLEAR_FLAG(F_SF);
7310 		SET_FLAG(F_PF);
7311 		SET_FLAG(F_ZF);
7312 	}
7313 	return (uint8_t) res;
7314 }
7315 
7316 /*
7317  * REMARKS:
7318  * Implements the SHR instruction and side effects.
7319  */
7320 static uint16_t
7321 shr_word(struct x86emu *emu, uint16_t d, uint8_t s)
7322 {
7323 	unsigned int cnt, res, cf;
7324 
7325 	if (s < 16) {
7326 		cnt = s % 16;
7327 		if (cnt > 0) {
7328 			cf = d & (1 << (cnt - 1));
7329 			res = d >> cnt;
7330 			CONDITIONAL_SET_FLAG(cf, F_CF);
7331 			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7332 			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7333 			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7334 		} else {
7335 			res = d;
7336 		}
7337 
7338 		if (cnt == 1) {
7339 			CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7340 		} else {
7341 			CLEAR_FLAG(F_OF);
7342 		}
7343 	} else {
7344 		res = 0;
7345 		CLEAR_FLAG(F_CF);
7346 		CLEAR_FLAG(F_OF);
7347 		SET_FLAG(F_ZF);
7348 		CLEAR_FLAG(F_SF);
7349 		CLEAR_FLAG(F_PF);
7350 	}
7351 	return (uint16_t) res;
7352 }
7353 
7354 /*
7355  * REMARKS:
7356  * Implements the SHR instruction and side effects.
7357  */
7358 static uint32_t
7359 shr_long(struct x86emu *emu, uint32_t d, uint8_t s)
7360 {
7361 	unsigned int cnt, res, cf;
7362 
7363 	if (s < 32) {
7364 		cnt = s % 32;
7365 		if (cnt > 0) {
7366 			cf = d & (1 << (cnt - 1));
7367 			res = d >> cnt;
7368 			CONDITIONAL_SET_FLAG(cf, F_CF);
7369 			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7370 			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7371 			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7372 		} else {
7373 			res = d;
7374 		}
7375 		if (cnt == 1) {
7376 			CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7377 		} else {
7378 			CLEAR_FLAG(F_OF);
7379 		}
7380 	} else {
7381 		res = 0;
7382 		CLEAR_FLAG(F_CF);
7383 		CLEAR_FLAG(F_OF);
7384 		SET_FLAG(F_ZF);
7385 		CLEAR_FLAG(F_SF);
7386 		CLEAR_FLAG(F_PF);
7387 	}
7388 	return res;
7389 }
7390 
7391 /*
7392  * REMARKS:
7393  * Implements the SAR instruction and side effects.
7394  */
7395 static uint8_t
7396 sar_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7397 {
7398 	unsigned int cnt, res, cf, mask, sf;
7399 
7400 	res = d;
7401 	sf = d & 0x80;
7402 	cnt = s % 8;
7403 	if (cnt > 0 && cnt < 8) {
7404 		mask = (1 << (8 - cnt)) - 1;
7405 		cf = d & (1 << (cnt - 1));
7406 		res = (d >> cnt) & mask;
7407 		CONDITIONAL_SET_FLAG(cf, F_CF);
7408 		if (sf) {
7409 			res |= ~mask;
7410 		}
7411 		CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7412 		CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7413 		CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7414 	} else if (cnt >= 8) {
7415 		if (sf) {
7416 			res = 0xff;
7417 			SET_FLAG(F_CF);
7418 			CLEAR_FLAG(F_ZF);
7419 			SET_FLAG(F_SF);
7420 			SET_FLAG(F_PF);
7421 		} else {
7422 			res = 0;
7423 			CLEAR_FLAG(F_CF);
7424 			SET_FLAG(F_ZF);
7425 			CLEAR_FLAG(F_SF);
7426 			CLEAR_FLAG(F_PF);
7427 		}
7428 	}
7429 	return (uint8_t) res;
7430 }
7431 
7432 /*
7433  * REMARKS:
7434  * Implements the SAR instruction and side effects.
7435  */
7436 static uint16_t
7437 sar_word(struct x86emu *emu, uint16_t d, uint8_t s)
7438 {
7439 	unsigned int cnt, res, cf, mask, sf;
7440 
7441 	sf = d & 0x8000;
7442 	cnt = s % 16;
7443 	res = d;
7444 	if (cnt > 0 && cnt < 16) {
7445 		mask = (1 << (16 - cnt)) - 1;
7446 		cf = d & (1 << (cnt - 1));
7447 		res = (d >> cnt) & mask;
7448 		CONDITIONAL_SET_FLAG(cf, F_CF);
7449 		if (sf) {
7450 			res |= ~mask;
7451 		}
7452 		CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7453 		CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7454 		CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7455 	} else if (cnt >= 16) {
7456 		if (sf) {
7457 			res = 0xffff;
7458 			SET_FLAG(F_CF);
7459 			CLEAR_FLAG(F_ZF);
7460 			SET_FLAG(F_SF);
7461 			SET_FLAG(F_PF);
7462 		} else {
7463 			res = 0;
7464 			CLEAR_FLAG(F_CF);
7465 			SET_FLAG(F_ZF);
7466 			CLEAR_FLAG(F_SF);
7467 			CLEAR_FLAG(F_PF);
7468 		}
7469 	}
7470 	return (uint16_t) res;
7471 }
7472 
7473 /*
7474  * REMARKS:
7475  * Implements the SAR instruction and side effects.
7476  */
7477 static uint32_t
7478 sar_long(struct x86emu *emu, uint32_t d, uint8_t s)
7479 {
7480 	uint32_t cnt, res, cf, mask, sf;
7481 
7482 	sf = d & 0x80000000;
7483 	cnt = s % 32;
7484 	res = d;
7485 	if (cnt > 0 && cnt < 32) {
7486 		mask = (1 << (32 - cnt)) - 1;
7487 		cf = d & (1 << (cnt - 1));
7488 		res = (d >> cnt) & mask;
7489 		CONDITIONAL_SET_FLAG(cf, F_CF);
7490 		if (sf) {
7491 			res |= ~mask;
7492 		}
7493 		CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7494 		CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7495 		CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7496 	} else if (cnt >= 32) {
7497 		if (sf) {
7498 			res = 0xffffffff;
7499 			SET_FLAG(F_CF);
7500 			CLEAR_FLAG(F_ZF);
7501 			SET_FLAG(F_SF);
7502 			SET_FLAG(F_PF);
7503 		} else {
7504 			res = 0;
7505 			CLEAR_FLAG(F_CF);
7506 			SET_FLAG(F_ZF);
7507 			CLEAR_FLAG(F_SF);
7508 			CLEAR_FLAG(F_PF);
7509 		}
7510 	}
7511 	return res;
7512 }
7513 
7514 /*
7515  * REMARKS:
7516  * Implements the SHLD instruction and side effects.
7517  */
7518 static uint16_t
7519 shld_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s)
7520 {
7521 	unsigned int cnt, res, cf;
7522 
7523 	if (s < 16) {
7524 		cnt = s % 16;
7525 		if (cnt > 0) {
7526 			res = (d << cnt) | (fill >> (16 - cnt));
7527 			cf = d & (1 << (16 - cnt));
7528 			CONDITIONAL_SET_FLAG(cf, F_CF);
7529 			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7530 			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7531 			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7532 		} else {
7533 			res = d;
7534 		}
7535 		if (cnt == 1) {
7536 			CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
7537 				(ACCESS_FLAG(F_CF) != 0)), F_OF);
7538 		} else {
7539 			CLEAR_FLAG(F_OF);
7540 		}
7541 	} else {
7542 		res = 0;
7543 		CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
7544 		CLEAR_FLAG(F_OF);
7545 		CLEAR_FLAG(F_SF);
7546 		SET_FLAG(F_PF);
7547 		SET_FLAG(F_ZF);
7548 	}
7549 	return (uint16_t) res;
7550 }
7551 
7552 /*
7553  * REMARKS:
7554  * Implements the SHLD instruction and side effects.
7555  */
7556 static uint32_t
7557 shld_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s)
7558 {
7559 	unsigned int cnt, res, cf;
7560 
7561 	if (s < 32) {
7562 		cnt = s % 32;
7563 		if (cnt > 0) {
7564 			res = (d << cnt) | (fill >> (32 - cnt));
7565 			cf = d & (1 << (32 - cnt));
7566 			CONDITIONAL_SET_FLAG(cf, F_CF);
7567 			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7568 			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7569 			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7570 		} else {
7571 			res = d;
7572 		}
7573 		if (cnt == 1) {
7574 			CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000)
7575 			    ^ (ACCESS_FLAG(F_CF) != 0)), F_OF);
7576 		} else {
7577 			CLEAR_FLAG(F_OF);
7578 		}
7579 	} else {
7580 		res = 0;
7581 		CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7582 		CLEAR_FLAG(F_OF);
7583 		CLEAR_FLAG(F_SF);
7584 		SET_FLAG(F_PF);
7585 		SET_FLAG(F_ZF);
7586 	}
7587 	return res;
7588 }
7589 
7590 /*
7591  * REMARKS:
7592  * Implements the SHRD instruction and side effects.
7593  */
7594 static uint16_t
7595 shrd_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s)
7596 {
7597 	unsigned int cnt, res, cf;
7598 
7599 	if (s < 16) {
7600 		cnt = s % 16;
7601 		if (cnt > 0) {
7602 			cf = d & (1 << (cnt - 1));
7603 			res = (d >> cnt) | (fill << (16 - cnt));
7604 			CONDITIONAL_SET_FLAG(cf, F_CF);
7605 			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7606 			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7607 			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7608 		} else {
7609 			res = d;
7610 		}
7611 
7612 		if (cnt == 1) {
7613 			CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7614 		} else {
7615 			CLEAR_FLAG(F_OF);
7616 		}
7617 	} else {
7618 		res = 0;
7619 		CLEAR_FLAG(F_CF);
7620 		CLEAR_FLAG(F_OF);
7621 		SET_FLAG(F_ZF);
7622 		CLEAR_FLAG(F_SF);
7623 		CLEAR_FLAG(F_PF);
7624 	}
7625 	return (uint16_t) res;
7626 }
7627 
7628 /*
7629  * REMARKS:
7630  * Implements the SHRD instruction and side effects.
7631  */
7632 static uint32_t
7633 shrd_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s)
7634 {
7635 	unsigned int cnt, res, cf;
7636 
7637 	if (s < 32) {
7638 		cnt = s % 32;
7639 		if (cnt > 0) {
7640 			cf = d & (1 << (cnt - 1));
7641 			res = (d >> cnt) | (fill << (32 - cnt));
7642 			CONDITIONAL_SET_FLAG(cf, F_CF);
7643 			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7644 			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7645 			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7646 		} else {
7647 			res = d;
7648 		}
7649 		if (cnt == 1) {
7650 			CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7651 		} else {
7652 			CLEAR_FLAG(F_OF);
7653 		}
7654 	} else {
7655 		res = 0;
7656 		CLEAR_FLAG(F_CF);
7657 		CLEAR_FLAG(F_OF);
7658 		SET_FLAG(F_ZF);
7659 		CLEAR_FLAG(F_SF);
7660 		CLEAR_FLAG(F_PF);
7661 	}
7662 	return res;
7663 }
7664 
7665 /*
7666  * REMARKS:
7667  * Implements the SBB instruction and side effects.
7668  */
7669 static uint8_t
7670 sbb_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7671 {
7672 	uint32_t res;	/* all operands in native machine order */
7673 	uint32_t bc;
7674 
7675 	if (ACCESS_FLAG(F_CF))
7676 		res = d - s - 1;
7677 	else
7678 		res = d - s;
7679 	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7680 	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7681 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7682 
7683 	/* calculate the borrow chain.  See note at top */
7684 	bc = (res & (~d | s)) | (~d & s);
7685 	CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7686 	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7687 	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7688 	return (uint8_t) res;
7689 }
7690 
7691 /*
7692  * REMARKS:
7693  * Implements the SBB instruction and side effects.
7694  */
7695 static uint16_t
7696 sbb_word(struct x86emu *emu, uint16_t d, uint16_t s)
7697 {
7698 	uint32_t res;	/* all operands in native machine order */
7699 	uint32_t bc;
7700 
7701 	if (ACCESS_FLAG(F_CF))
7702 		res = d - s - 1;
7703 	else
7704 		res = d - s;
7705 	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7706 	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7707 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7708 
7709 	/* calculate the borrow chain.  See note at top */
7710 	bc = (res & (~d | s)) | (~d & s);
7711 	CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7712 	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7713 	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7714 	return (uint16_t) res;
7715 }
7716 
7717 /*
7718  * REMARKS:
7719  * Implements the SBB instruction and side effects.
7720  */
7721 static uint32_t
7722 sbb_long(struct x86emu *emu, uint32_t d, uint32_t s)
7723 {
7724 	uint32_t res;	/* all operands in native machine order */
7725 	uint32_t bc;
7726 
7727 	if (ACCESS_FLAG(F_CF))
7728 		res = d - s - 1;
7729 	else
7730 		res = d - s;
7731 	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7732 	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7733 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7734 
7735 	/* calculate the borrow chain.  See note at top */
7736 	bc = (res & (~d | s)) | (~d & s);
7737 	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7738 	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7739 	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7740 	return res;
7741 }
7742 
7743 /*
7744  * REMARKS:
7745  * Implements the SUB instruction and side effects.
7746  */
7747 static uint8_t
7748 sub_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7749 {
7750 	uint32_t res;	/* all operands in native machine order */
7751 	uint32_t bc;
7752 
7753 	res = d - s;
7754 	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7755 	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7756 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7757 
7758 	/* calculate the borrow chain.  See note at top */
7759 	bc = (res & (~d | s)) | (~d & s);
7760 	CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7761 	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7762 	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7763 	return (uint8_t) res;
7764 }
7765 
7766 /*
7767  * REMARKS:
7768  * Implements the SUB instruction and side effects.
7769  */
7770 static uint16_t
7771 sub_word(struct x86emu *emu, uint16_t d, uint16_t s)
7772 {
7773 	uint32_t res;	/* all operands in native machine order */
7774 	uint32_t bc;
7775 
7776 	res = d - s;
7777 	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7778 	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7779 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7780 
7781 	/* calculate the borrow chain.  See note at top */
7782 	bc = (res & (~d | s)) | (~d & s);
7783 	CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7784 	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7785 	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7786 	return (uint16_t) res;
7787 }
7788 
7789 /*
7790  * REMARKS:
7791  * Implements the SUB instruction and side effects.
7792  */
7793 static uint32_t
7794 sub_long(struct x86emu *emu, uint32_t d, uint32_t s)
7795 {
7796 	uint32_t res;	/* all operands in native machine order */
7797 	uint32_t bc;
7798 
7799 	res = d - s;
7800 	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7801 	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7802 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7803 
7804 	/* calculate the borrow chain.  See note at top */
7805 	bc = (res & (~d | s)) | (~d & s);
7806 	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7807 	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7808 	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7809 	return res;
7810 }
7811 
7812 /*
7813  * REMARKS:
7814  * Implements the TEST instruction and side effects.
7815  */
7816 static void
7817 test_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7818 {
7819 	uint32_t res;	/* all operands in native machine order */
7820 
7821 	res = d & s;
7822 
7823 	CLEAR_FLAG(F_OF);
7824 	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7825 	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7826 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7827 	/* AF == dont care */
7828 	CLEAR_FLAG(F_CF);
7829 }
7830 
7831 /*
7832  * REMARKS:
7833  * Implements the TEST instruction and side effects.
7834  */
7835 static void
7836 test_word(struct x86emu *emu, uint16_t d, uint16_t s)
7837 {
7838 	uint32_t res;	/* all operands in native machine order */
7839 
7840 	res = d & s;
7841 
7842 	CLEAR_FLAG(F_OF);
7843 	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7844 	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7845 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7846 	/* AF == dont care */
7847 	CLEAR_FLAG(F_CF);
7848 }
7849 
7850 /*
7851  * REMARKS:
7852  * Implements the TEST instruction and side effects.
7853  */
7854 static void
7855 test_long(struct x86emu *emu, uint32_t d, uint32_t s)
7856 {
7857 	uint32_t res;	/* all operands in native machine order */
7858 
7859 	res = d & s;
7860 
7861 	CLEAR_FLAG(F_OF);
7862 	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7863 	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7864 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7865 	/* AF == dont care */
7866 	CLEAR_FLAG(F_CF);
7867 }
7868 
7869 /*
7870  * REMARKS:
7871  * Implements the XOR instruction and side effects.
7872  */
7873 static uint8_t
7874 xor_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7875 {
7876 	uint8_t res;	/* all operands in native machine order */
7877 
7878 	res = d ^ s;
7879 	CLEAR_FLAG(F_OF);
7880 	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7881 	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7882 	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
7883 	CLEAR_FLAG(F_CF);
7884 	CLEAR_FLAG(F_AF);
7885 	return res;
7886 }
7887 
7888 /*
7889  * REMARKS:
7890  * Implements the XOR instruction and side effects.
7891  */
7892 static uint16_t
7893 xor_word(struct x86emu *emu, uint16_t d, uint16_t s)
7894 {
7895 	uint16_t res;	/* all operands in native machine order */
7896 
7897 	res = d ^ s;
7898 	CLEAR_FLAG(F_OF);
7899 	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7900 	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7901 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7902 	CLEAR_FLAG(F_CF);
7903 	CLEAR_FLAG(F_AF);
7904 	return res;
7905 }
7906 
7907 /*
7908  * REMARKS:
7909  * Implements the XOR instruction and side effects.
7910  */
7911 static uint32_t
7912 xor_long(struct x86emu *emu, uint32_t d, uint32_t s)
7913 {
7914 	uint32_t res;	/* all operands in native machine order */
7915 
7916 	res = d ^ s;
7917 	CLEAR_FLAG(F_OF);
7918 	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7919 	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7920 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7921 	CLEAR_FLAG(F_CF);
7922 	CLEAR_FLAG(F_AF);
7923 	return res;
7924 }
7925 
7926 /*
7927  * REMARKS:
7928  * Implements the IMUL instruction and side effects.
7929  */
7930 static void
7931 imul_byte(struct x86emu *emu, uint8_t s)
7932 {
7933 	int16_t res = (int16_t) ((int8_t) emu->x86.R_AL * (int8_t) s);
7934 
7935 	emu->x86.R_AX = res;
7936 	if (((emu->x86.R_AL & 0x80) == 0 && emu->x86.R_AH == 0x00) ||
7937 	    ((emu->x86.R_AL & 0x80) != 0 && emu->x86.R_AH == 0xFF)) {
7938 		CLEAR_FLAG(F_CF);
7939 		CLEAR_FLAG(F_OF);
7940 	} else {
7941 		SET_FLAG(F_CF);
7942 		SET_FLAG(F_OF);
7943 	}
7944 }
7945 
7946 /*
7947  * REMARKS:
7948  * Implements the IMUL instruction and side effects.
7949  */
7950 static void
7951 imul_word(struct x86emu *emu, uint16_t s)
7952 {
7953 	int32_t res = (int16_t) emu->x86.R_AX * (int16_t) s;
7954 
7955 	emu->x86.R_AX = (uint16_t) res;
7956 	emu->x86.R_DX = (uint16_t) (res >> 16);
7957 	if (((emu->x86.R_AX & 0x8000) == 0 && emu->x86.R_DX == 0x00) ||
7958 	    ((emu->x86.R_AX & 0x8000) != 0 && emu->x86.R_DX == 0xFF)) {
7959 		CLEAR_FLAG(F_CF);
7960 		CLEAR_FLAG(F_OF);
7961 	} else {
7962 		SET_FLAG(F_CF);
7963 		SET_FLAG(F_OF);
7964 	}
7965 }
7966 
7967 /*
7968  * REMARKS:
7969  * Implements the IMUL instruction and side effects.
7970  */
7971 static void
7972 imul_long(struct x86emu *emu, uint32_t s)
7973 {
7974 	int64_t res;
7975 
7976 	res = (int64_t)(int32_t)emu->x86.R_EAX * (int32_t)s;
7977 	emu->x86.R_EAX = (uint32_t)res;
7978 	emu->x86.R_EDX = ((uint64_t)res) >> 32;
7979 	if (((emu->x86.R_EAX & 0x80000000) == 0 && emu->x86.R_EDX == 0x00) ||
7980 	    ((emu->x86.R_EAX & 0x80000000) != 0 && emu->x86.R_EDX == 0xFF)) {
7981 		CLEAR_FLAG(F_CF);
7982 		CLEAR_FLAG(F_OF);
7983 	} else {
7984 		SET_FLAG(F_CF);
7985 		SET_FLAG(F_OF);
7986 	}
7987 }
7988 
7989 /*
7990  * REMARKS:
7991  * Implements the MUL instruction and side effects.
7992  */
7993 static void
7994 mul_byte(struct x86emu *emu, uint8_t s)
7995 {
7996 	uint16_t res = (uint16_t) (emu->x86.R_AL * s);
7997 
7998 	emu->x86.R_AX = res;
7999 	if (emu->x86.R_AH == 0) {
8000 		CLEAR_FLAG(F_CF);
8001 		CLEAR_FLAG(F_OF);
8002 	} else {
8003 		SET_FLAG(F_CF);
8004 		SET_FLAG(F_OF);
8005 	}
8006 }
8007 
8008 /*
8009  * REMARKS:
8010  * Implements the MUL instruction and side effects.
8011  */
8012 static void
8013 mul_word(struct x86emu *emu, uint16_t s)
8014 {
8015 	uint32_t res = emu->x86.R_AX * s;
8016 
8017 	emu->x86.R_AX = (uint16_t) res;
8018 	emu->x86.R_DX = (uint16_t) (res >> 16);
8019 	if (emu->x86.R_DX == 0) {
8020 		CLEAR_FLAG(F_CF);
8021 		CLEAR_FLAG(F_OF);
8022 	} else {
8023 		SET_FLAG(F_CF);
8024 		SET_FLAG(F_OF);
8025 	}
8026 }
8027 
8028 /*
8029  * REMARKS:
8030  * Implements the MUL instruction and side effects.
8031  */
8032 static void
8033 mul_long(struct x86emu *emu, uint32_t s)
8034 {
8035 	uint64_t res = (uint64_t) emu->x86.R_EAX * s;
8036 
8037 	emu->x86.R_EAX = (uint32_t) res;
8038 	emu->x86.R_EDX = (uint32_t) (res >> 32);
8039 
8040 	if (emu->x86.R_EDX == 0) {
8041 		CLEAR_FLAG(F_CF);
8042 		CLEAR_FLAG(F_OF);
8043 	} else {
8044 		SET_FLAG(F_CF);
8045 		SET_FLAG(F_OF);
8046 	}
8047 }
8048 
8049 /*
8050  * REMARKS:
8051  * Implements the IDIV instruction and side effects.
8052  */
8053 static void
8054 idiv_byte(struct x86emu *emu, uint8_t s)
8055 {
8056 	int32_t dvd, div, mod;
8057 
8058 	dvd = (int16_t) emu->x86.R_AX;
8059 	if (s == 0) {
8060 		x86emu_intr_raise(emu, 8);
8061 		return;
8062 	}
8063 	div = dvd / (int8_t) s;
8064 	mod = dvd % (int8_t) s;
8065 	if (div > 0x7f || div < -0x7f) {
8066 		x86emu_intr_raise(emu, 8);
8067 		return;
8068 	}
8069 	emu->x86.R_AL = (int8_t) div;
8070 	emu->x86.R_AH = (int8_t) mod;
8071 }
8072 
8073 /*
8074  * REMARKS:
8075  * Implements the IDIV instruction and side effects.
8076  */
8077 static void
8078 idiv_word(struct x86emu *emu, uint16_t s)
8079 {
8080 	int32_t dvd, div, mod;
8081 
8082 	dvd = (((int32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
8083 	if (s == 0) {
8084 		x86emu_intr_raise(emu, 8);
8085 		return;
8086 	}
8087 	div = dvd / (int16_t) s;
8088 	mod = dvd % (int16_t) s;
8089 	if (div > 0x7fff || div < -0x7fff) {
8090 		x86emu_intr_raise(emu, 8);
8091 		return;
8092 	}
8093 	CLEAR_FLAG(F_CF);
8094 	CLEAR_FLAG(F_SF);
8095 	CONDITIONAL_SET_FLAG(div == 0, F_ZF);
8096 	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8097 
8098 	emu->x86.R_AX = (uint16_t) div;
8099 	emu->x86.R_DX = (uint16_t) mod;
8100 }
8101 
8102 /*
8103  * REMARKS:
8104  * Implements the IDIV instruction and side effects.
8105  */
8106 static void
8107 idiv_long(struct x86emu *emu, uint32_t s)
8108 {
8109 	int64_t dvd, div, mod;
8110 
8111 	dvd = (((int64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
8112 	if (s == 0) {
8113 		x86emu_intr_raise(emu, 8);
8114 		return;
8115 	}
8116 	div = dvd / (int32_t) s;
8117 	mod = dvd % (int32_t) s;
8118 	if (div > 0x7fffffff || div < -0x7fffffff) {
8119 		x86emu_intr_raise(emu, 8);
8120 		return;
8121 	}
8122 	CLEAR_FLAG(F_CF);
8123 	CLEAR_FLAG(F_AF);
8124 	CLEAR_FLAG(F_SF);
8125 	SET_FLAG(F_ZF);
8126 	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8127 
8128 	emu->x86.R_EAX = (uint32_t) div;
8129 	emu->x86.R_EDX = (uint32_t) mod;
8130 }
8131 
8132 /*
8133  * REMARKS:
8134  * Implements the DIV instruction and side effects.
8135  */
8136 static void
8137 div_byte(struct x86emu *emu, uint8_t s)
8138 {
8139 	uint32_t dvd, div, mod;
8140 
8141 	dvd = emu->x86.R_AX;
8142 	if (s == 0) {
8143 		x86emu_intr_raise(emu, 8);
8144 		return;
8145 	}
8146 	div = dvd / (uint8_t) s;
8147 	mod = dvd % (uint8_t) s;
8148 	if (div > 0xff) {
8149 		x86emu_intr_raise(emu, 8);
8150 		return;
8151 	}
8152 	emu->x86.R_AL = (uint8_t) div;
8153 	emu->x86.R_AH = (uint8_t) mod;
8154 }
8155 
8156 /*
8157  * REMARKS:
8158  * Implements the DIV instruction and side effects.
8159  */
8160 static void
8161 div_word(struct x86emu *emu, uint16_t s)
8162 {
8163 	uint32_t dvd, div, mod;
8164 
8165 	dvd = (((uint32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
8166 	if (s == 0) {
8167 		x86emu_intr_raise(emu, 8);
8168 		return;
8169 	}
8170 	div = dvd / (uint16_t) s;
8171 	mod = dvd % (uint16_t) s;
8172 	if (div > 0xffff) {
8173 		x86emu_intr_raise(emu, 8);
8174 		return;
8175 	}
8176 	CLEAR_FLAG(F_CF);
8177 	CLEAR_FLAG(F_SF);
8178 	CONDITIONAL_SET_FLAG(div == 0, F_ZF);
8179 	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8180 
8181 	emu->x86.R_AX = (uint16_t) div;
8182 	emu->x86.R_DX = (uint16_t) mod;
8183 }
8184 
8185 /*
8186  * REMARKS:
8187  * Implements the DIV instruction and side effects.
8188  */
8189 static void
8190 div_long(struct x86emu *emu, uint32_t s)
8191 {
8192 	uint64_t dvd, div, mod;
8193 
8194 	dvd = (((uint64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
8195 	if (s == 0) {
8196 		x86emu_intr_raise(emu, 8);
8197 		return;
8198 	}
8199 	div = dvd / (uint32_t) s;
8200 	mod = dvd % (uint32_t) s;
8201 	if (div > 0xffffffff) {
8202 		x86emu_intr_raise(emu, 8);
8203 		return;
8204 	}
8205 	CLEAR_FLAG(F_CF);
8206 	CLEAR_FLAG(F_AF);
8207 	CLEAR_FLAG(F_SF);
8208 	SET_FLAG(F_ZF);
8209 	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8210 
8211 	emu->x86.R_EAX = (uint32_t) div;
8212 	emu->x86.R_EDX = (uint32_t) mod;
8213 }
8214 
8215 /*
8216  * REMARKS:
8217  * Implements the IN string instruction and side effects.
8218  */
8219 static void
8220 ins(struct x86emu *emu, int size)
8221 {
8222 	int inc = size;
8223 
8224 	if (ACCESS_FLAG(F_DF)) {
8225 		inc = -size;
8226 	}
8227 	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
8228 		/* dont care whether REPE or REPNE */
8229 		/* in until CX is ZERO. */
8230 		uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
8231 		    emu->x86.R_ECX : emu->x86.R_CX);
8232 		switch (size) {
8233 		case 1:
8234 			while (count--) {
8235 				store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
8236 				    (*emu->emu_inb) (emu, emu->x86.R_DX));
8237 				emu->x86.R_DI += inc;
8238 			}
8239 			break;
8240 
8241 		case 2:
8242 			while (count--) {
8243 				store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
8244 				    (*emu->emu_inw) (emu, emu->x86.R_DX));
8245 				emu->x86.R_DI += inc;
8246 			}
8247 			break;
8248 		case 4:
8249 			while (count--) {
8250 				store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
8251 				    (*emu->emu_inl) (emu, emu->x86.R_DX));
8252 				emu->x86.R_DI += inc;
8253 				break;
8254 			}
8255 		}
8256 		emu->x86.R_CX = 0;
8257 		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
8258 			emu->x86.R_ECX = 0;
8259 		}
8260 		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
8261 	} else {
8262 		switch (size) {
8263 		case 1:
8264 			store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
8265 			    (*emu->emu_inb) (emu, emu->x86.R_DX));
8266 			break;
8267 		case 2:
8268 			store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
8269 			    (*emu->emu_inw) (emu, emu->x86.R_DX));
8270 			break;
8271 		case 4:
8272 			store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
8273 			    (*emu->emu_inl) (emu, emu->x86.R_DX));
8274 			break;
8275 		}
8276 		emu->x86.R_DI += inc;
8277 	}
8278 }
8279 
8280 /*
8281  * REMARKS:
8282  * Implements the OUT string instruction and side effects.
8283  */
8284 static void
8285 outs(struct x86emu *emu, int size)
8286 {
8287 	int inc = size;
8288 
8289 	if (ACCESS_FLAG(F_DF)) {
8290 		inc = -size;
8291 	}
8292 	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
8293 		/* dont care whether REPE or REPNE */
8294 		/* out until CX is ZERO. */
8295 		uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
8296 		    emu->x86.R_ECX : emu->x86.R_CX);
8297 		switch (size) {
8298 		case 1:
8299 			while (count--) {
8300 				(*emu->emu_outb) (emu, emu->x86.R_DX,
8301 				    fetch_byte(emu, emu->x86.R_ES,
8302 				    emu->x86.R_SI));
8303 				emu->x86.R_SI += inc;
8304 			}
8305 			break;
8306 
8307 		case 2:
8308 			while (count--) {
8309 				(*emu->emu_outw) (emu, emu->x86.R_DX,
8310 				    fetch_word(emu, emu->x86.R_ES,
8311 				    emu->x86.R_SI));
8312 				emu->x86.R_SI += inc;
8313 			}
8314 			break;
8315 		case 4:
8316 			while (count--) {
8317 				(*emu->emu_outl) (emu, emu->x86.R_DX,
8318 				    fetch_long(emu, emu->x86.R_ES,
8319 				    emu->x86.R_SI));
8320 				emu->x86.R_SI += inc;
8321 				break;
8322 			}
8323 		}
8324 		emu->x86.R_CX = 0;
8325 		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
8326 			emu->x86.R_ECX = 0;
8327 		}
8328 		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
8329 	} else {
8330 		switch (size) {
8331 		case 1:
8332 			(*emu->emu_outb) (emu, emu->x86.R_DX,
8333 			    fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI));
8334 			break;
8335 		case 2:
8336 			(*emu->emu_outw) (emu, emu->x86.R_DX,
8337 			    fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI));
8338 			break;
8339 		case 4:
8340 			(*emu->emu_outl) (emu, emu->x86.R_DX,
8341 			    fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI));
8342 			break;
8343 		}
8344 		emu->x86.R_SI += inc;
8345 	}
8346 }
8347 
8348 /*
8349  * REMARKS:
8350  * Pushes a word onto the stack.
8351  *
8352  * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8353  */
8354 static void
8355 push_word(struct x86emu *emu, uint16_t w)
8356 {
8357 	emu->x86.R_SP -= 2;
8358 	store_word(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8359 }
8360 
8361 /*
8362  * REMARKS:
8363  * Pushes a long onto the stack.
8364  *
8365  * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8366  */
8367 static void
8368 push_long(struct x86emu *emu, uint32_t w)
8369 {
8370 	emu->x86.R_SP -= 4;
8371 	store_long(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8372 }
8373 
8374 /*
8375  * REMARKS:
8376  * Pops a word from the stack.
8377  *
8378  * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8379  */
8380 static uint16_t
8381 pop_word(struct x86emu *emu)
8382 {
8383 	uint16_t res;
8384 
8385 	res = fetch_word(emu, emu->x86.R_SS, emu->x86.R_SP);
8386 	emu->x86.R_SP += 2;
8387 	return res;
8388 }
8389 
8390 /*
8391  * REMARKS:
8392  * Pops a long from the stack.
8393  *
8394  * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8395  */
8396 static uint32_t
8397 pop_long(struct x86emu *emu)
8398 {
8399 	uint32_t res;
8400 
8401 	res = fetch_long(emu, emu->x86.R_SS, emu->x86.R_SP);
8402 	emu->x86.R_SP += 4;
8403 	return res;
8404 }
8405