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