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