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