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