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