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