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