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