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