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