1281502Sdelphij/*	$OpenBSD: x86emu.c,v 1.9 2014/06/15 11:04:49 pirofti Exp $	*/
2197007Sdelphij/*	$NetBSD: x86emu.c,v 1.7 2009/02/03 19:26:29 joerg Exp $	*/
3197007Sdelphij
4197007Sdelphij/*
5197007Sdelphij *
6197007Sdelphij *  Realmode X86 Emulator Library
7197007Sdelphij *
8197007Sdelphij *  Copyright (C) 1996-1999 SciTech Software, Inc.
9197007Sdelphij *  Copyright (C) David Mosberger-Tang
10197007Sdelphij *  Copyright (C) 1999 Egbert Eich
11197007Sdelphij *  Copyright (C) 2007 Joerg Sonnenberger
12197007Sdelphij *
13197007Sdelphij *  ========================================================================
14197007Sdelphij *
15197007Sdelphij *  Permission to use, copy, modify, distribute, and sell this software and
16197007Sdelphij *  its documentation for any purpose is hereby granted without fee,
17197007Sdelphij *  provided that the above copyright notice appear in all copies and that
18197007Sdelphij *  both that copyright notice and this permission notice appear in
19197007Sdelphij *  supporting documentation, and that the name of the authors not be used
20197007Sdelphij *  in advertising or publicity pertaining to distribution of the software
21197007Sdelphij *  without specific, written prior permission.  The authors makes no
22197007Sdelphij *  representations about the suitability of this software for any purpose.
23197007Sdelphij *  It is provided "as is" without express or implied warranty.
24197007Sdelphij *
25197007Sdelphij *  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
26197007Sdelphij *  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
27197007Sdelphij *  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
28197007Sdelphij *  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
29197007Sdelphij *  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
30197007Sdelphij *  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
31197007Sdelphij *  PERFORMANCE OF THIS SOFTWARE.
32197007Sdelphij *
33197007Sdelphij */
34197007Sdelphij
35197386Sdelphij#include <sys/cdefs.h>
36197386Sdelphij__FBSDID("$FreeBSD$");
37197386Sdelphij
38197019Sdelphij#include <contrib/x86emu/x86emu.h>
39197019Sdelphij#include <contrib/x86emu/x86emu_regs.h>
40197019Sdelphij
41197007Sdelphijstatic void 	x86emu_intr_raise (struct x86emu *, uint8_t type);
42197007Sdelphij
43197007Sdelphijstatic void	x86emu_exec_one_byte(struct x86emu *);
44197007Sdelphijstatic void	x86emu_exec_two_byte(struct x86emu *);
45197007Sdelphij
46197007Sdelphijstatic void	fetch_decode_modrm (struct x86emu *);
47197007Sdelphijstatic uint8_t	fetch_byte_imm (struct x86emu *);
48197007Sdelphijstatic uint16_t	fetch_word_imm (struct x86emu *);
49197007Sdelphijstatic uint32_t	fetch_long_imm (struct x86emu *);
50197007Sdelphijstatic uint8_t	fetch_data_byte (struct x86emu *, uint32_t offset);
51197019Sdelphijstatic uint8_t	fetch_byte (struct x86emu *, u_int segment, uint32_t offset);
52197007Sdelphijstatic uint16_t	fetch_data_word (struct x86emu *, uint32_t offset);
53197007Sdelphijstatic uint16_t	fetch_word (struct x86emu *, uint32_t segment, uint32_t offset);
54197007Sdelphijstatic uint32_t	fetch_data_long (struct x86emu *, uint32_t offset);
55197007Sdelphijstatic uint32_t	fetch_long (struct x86emu *, uint32_t segment, uint32_t offset);
56197007Sdelphijstatic void	store_data_byte (struct x86emu *, uint32_t offset, uint8_t val);
57197007Sdelphijstatic void	store_byte (struct x86emu *, uint32_t segment, uint32_t offset, uint8_t val);
58197007Sdelphijstatic void	store_data_word (struct x86emu *, uint32_t offset, uint16_t val);
59197007Sdelphijstatic void	store_word (struct x86emu *, uint32_t segment, uint32_t offset, uint16_t val);
60197007Sdelphijstatic void	store_data_long (struct x86emu *, uint32_t offset, uint32_t val);
61197007Sdelphijstatic void	store_long (struct x86emu *, uint32_t segment, uint32_t offset, uint32_t val);
62197007Sdelphijstatic uint8_t*	decode_rl_byte_register(struct x86emu *);
63197007Sdelphijstatic uint16_t*	decode_rl_word_register(struct x86emu *);
64197007Sdelphijstatic uint32_t* 	decode_rl_long_register(struct x86emu *);
65197007Sdelphijstatic uint8_t* 	decode_rh_byte_register(struct x86emu *);
66197007Sdelphijstatic uint16_t* 	decode_rh_word_register(struct x86emu *);
67197007Sdelphijstatic uint32_t* 	decode_rh_long_register(struct x86emu *);
68197007Sdelphijstatic uint16_t* 	decode_rh_seg_register(struct x86emu *);
69197007Sdelphijstatic uint32_t	decode_rl_address(struct x86emu *);
70197007Sdelphij
71197007Sdelphijstatic uint8_t 	decode_and_fetch_byte(struct x86emu *);
72197007Sdelphijstatic uint16_t 	decode_and_fetch_word(struct x86emu *);
73197007Sdelphijstatic uint32_t 	decode_and_fetch_long(struct x86emu *);
74197007Sdelphij
75197007Sdelphijstatic uint8_t 	decode_and_fetch_byte_imm8(struct x86emu *, uint8_t *);
76197007Sdelphijstatic uint16_t 	decode_and_fetch_word_imm8(struct x86emu *, uint8_t *);
77197007Sdelphijstatic uint32_t 	decode_and_fetch_long_imm8(struct x86emu *, uint8_t *);
78197007Sdelphij
79197007Sdelphijstatic uint16_t 	decode_and_fetch_word_disp(struct x86emu *, int16_t);
80197007Sdelphijstatic uint32_t 	decode_and_fetch_long_disp(struct x86emu *, int16_t);
81197007Sdelphij
82197007Sdelphijstatic void	write_back_byte(struct x86emu *, uint8_t);
83197007Sdelphijstatic void	write_back_word(struct x86emu *, uint16_t);
84197007Sdelphijstatic void	write_back_long(struct x86emu *, uint32_t);
85197007Sdelphij
86197007Sdelphijstatic uint16_t	aaa_word (struct x86emu *, uint16_t d);
87197007Sdelphijstatic uint16_t	aas_word (struct x86emu *, uint16_t d);
88197007Sdelphijstatic uint16_t	aad_word (struct x86emu *, uint16_t d);
89197007Sdelphijstatic uint16_t	aam_word (struct x86emu *, uint8_t d);
90197007Sdelphijstatic uint8_t	adc_byte (struct x86emu *, uint8_t d, uint8_t s);
91197007Sdelphijstatic uint16_t	adc_word (struct x86emu *, uint16_t d, uint16_t s);
92197007Sdelphijstatic uint32_t	adc_long (struct x86emu *, uint32_t d, uint32_t s);
93197007Sdelphijstatic uint8_t	add_byte (struct x86emu *, uint8_t d, uint8_t s);
94197007Sdelphijstatic uint16_t	add_word (struct x86emu *, uint16_t d, uint16_t s);
95197007Sdelphijstatic uint32_t	add_long (struct x86emu *, uint32_t d, uint32_t s);
96197007Sdelphijstatic uint8_t	and_byte (struct x86emu *, uint8_t d, uint8_t s);
97197007Sdelphijstatic uint16_t	and_word (struct x86emu *, uint16_t d, uint16_t s);
98197007Sdelphijstatic uint32_t	and_long (struct x86emu *, uint32_t d, uint32_t s);
99197007Sdelphijstatic uint8_t	cmp_byte (struct x86emu *, uint8_t d, uint8_t s);
100197007Sdelphijstatic uint16_t	cmp_word (struct x86emu *, uint16_t d, uint16_t s);
101197007Sdelphijstatic uint32_t	cmp_long (struct x86emu *, uint32_t d, uint32_t s);
102197007Sdelphijstatic void	cmp_byte_no_return (struct x86emu *, uint8_t d, uint8_t s);
103197007Sdelphijstatic void	cmp_word_no_return (struct x86emu *, uint16_t d, uint16_t s);
104197007Sdelphijstatic void	cmp_long_no_return (struct x86emu *, uint32_t d, uint32_t s);
105197007Sdelphijstatic uint8_t	daa_byte (struct x86emu *, uint8_t d);
106197007Sdelphijstatic uint8_t	das_byte (struct x86emu *, uint8_t d);
107197007Sdelphijstatic uint8_t	dec_byte (struct x86emu *, uint8_t d);
108197007Sdelphijstatic uint16_t	dec_word (struct x86emu *, uint16_t d);
109197007Sdelphijstatic uint32_t	dec_long (struct x86emu *, uint32_t d);
110197007Sdelphijstatic uint8_t	inc_byte (struct x86emu *, uint8_t d);
111197007Sdelphijstatic uint16_t	inc_word (struct x86emu *, uint16_t d);
112197007Sdelphijstatic uint32_t	inc_long (struct x86emu *, uint32_t d);
113197007Sdelphijstatic uint8_t	or_byte (struct x86emu *, uint8_t d, uint8_t s);
114197007Sdelphijstatic uint16_t	or_word (struct x86emu *, uint16_t d, uint16_t s);
115197007Sdelphijstatic uint32_t	or_long (struct x86emu *, uint32_t d, uint32_t s);
116197007Sdelphijstatic uint8_t	neg_byte (struct x86emu *, uint8_t s);
117197007Sdelphijstatic uint16_t	neg_word (struct x86emu *, uint16_t s);
118197007Sdelphijstatic uint32_t	neg_long (struct x86emu *, uint32_t s);
119197007Sdelphijstatic uint8_t	rcl_byte (struct x86emu *, uint8_t d, uint8_t s);
120197007Sdelphijstatic uint16_t	rcl_word (struct x86emu *, uint16_t d, uint8_t s);
121197007Sdelphijstatic uint32_t	rcl_long (struct x86emu *, uint32_t d, uint8_t s);
122197007Sdelphijstatic uint8_t	rcr_byte (struct x86emu *, uint8_t d, uint8_t s);
123197007Sdelphijstatic uint16_t	rcr_word (struct x86emu *, uint16_t d, uint8_t s);
124197007Sdelphijstatic uint32_t	rcr_long (struct x86emu *, uint32_t d, uint8_t s);
125197007Sdelphijstatic uint8_t	rol_byte (struct x86emu *, uint8_t d, uint8_t s);
126197007Sdelphijstatic uint16_t	rol_word (struct x86emu *, uint16_t d, uint8_t s);
127197007Sdelphijstatic uint32_t	rol_long (struct x86emu *, uint32_t d, uint8_t s);
128197007Sdelphijstatic uint8_t	ror_byte (struct x86emu *, uint8_t d, uint8_t s);
129197007Sdelphijstatic uint16_t	ror_word (struct x86emu *, uint16_t d, uint8_t s);
130197007Sdelphijstatic uint32_t	ror_long (struct x86emu *, uint32_t d, uint8_t s);
131197007Sdelphijstatic uint8_t	shl_byte (struct x86emu *, uint8_t d, uint8_t s);
132197007Sdelphijstatic uint16_t	shl_word (struct x86emu *, uint16_t d, uint8_t s);
133197007Sdelphijstatic uint32_t	shl_long (struct x86emu *, uint32_t d, uint8_t s);
134197007Sdelphijstatic uint8_t	shr_byte (struct x86emu *, uint8_t d, uint8_t s);
135197007Sdelphijstatic uint16_t	shr_word (struct x86emu *, uint16_t d, uint8_t s);
136197007Sdelphijstatic uint32_t	shr_long (struct x86emu *, uint32_t d, uint8_t s);
137197007Sdelphijstatic uint8_t	sar_byte (struct x86emu *, uint8_t d, uint8_t s);
138197007Sdelphijstatic uint16_t	sar_word (struct x86emu *, uint16_t d, uint8_t s);
139197007Sdelphijstatic uint32_t	sar_long (struct x86emu *, uint32_t d, uint8_t s);
140197007Sdelphijstatic uint16_t	shld_word (struct x86emu *, uint16_t d, uint16_t fill, uint8_t s);
141197007Sdelphijstatic uint32_t	shld_long (struct x86emu *, uint32_t d, uint32_t fill, uint8_t s);
142197007Sdelphijstatic uint16_t	shrd_word (struct x86emu *, uint16_t d, uint16_t fill, uint8_t s);
143197007Sdelphijstatic uint32_t	shrd_long (struct x86emu *, uint32_t d, uint32_t fill, uint8_t s);
144197007Sdelphijstatic uint8_t	sbb_byte (struct x86emu *, uint8_t d, uint8_t s);
145197007Sdelphijstatic uint16_t	sbb_word (struct x86emu *, uint16_t d, uint16_t s);
146197007Sdelphijstatic uint32_t	sbb_long (struct x86emu *, uint32_t d, uint32_t s);
147197007Sdelphijstatic uint8_t	sub_byte (struct x86emu *, uint8_t d, uint8_t s);
148197007Sdelphijstatic uint16_t	sub_word (struct x86emu *, uint16_t d, uint16_t s);
149197007Sdelphijstatic uint32_t	sub_long (struct x86emu *, uint32_t d, uint32_t s);
150197007Sdelphijstatic void	test_byte (struct x86emu *, uint8_t d, uint8_t s);
151197007Sdelphijstatic void	test_word (struct x86emu *, uint16_t d, uint16_t s);
152197007Sdelphijstatic void	test_long (struct x86emu *, uint32_t d, uint32_t s);
153197007Sdelphijstatic uint8_t	xor_byte (struct x86emu *, uint8_t d, uint8_t s);
154197007Sdelphijstatic uint16_t	xor_word (struct x86emu *, uint16_t d, uint16_t s);
155197007Sdelphijstatic uint32_t	xor_long (struct x86emu *, uint32_t d, uint32_t s);
156197007Sdelphijstatic void	imul_byte (struct x86emu *, uint8_t s);
157197007Sdelphijstatic void	imul_word (struct x86emu *, uint16_t s);
158197007Sdelphijstatic void	imul_long (struct x86emu *, uint32_t s);
159197007Sdelphijstatic void	mul_byte (struct x86emu *, uint8_t s);
160197007Sdelphijstatic void	mul_word (struct x86emu *, uint16_t s);
161197007Sdelphijstatic void	mul_long (struct x86emu *, uint32_t s);
162197007Sdelphijstatic void	idiv_byte (struct x86emu *, uint8_t s);
163197007Sdelphijstatic void	idiv_word (struct x86emu *, uint16_t s);
164197007Sdelphijstatic void	idiv_long (struct x86emu *, uint32_t s);
165197007Sdelphijstatic void	div_byte (struct x86emu *, uint8_t s);
166197007Sdelphijstatic void	div_word (struct x86emu *, uint16_t s);
167197007Sdelphijstatic void	div_long (struct x86emu *, uint32_t s);
168197007Sdelphijstatic void	ins (struct x86emu *, int size);
169197007Sdelphijstatic void	outs (struct x86emu *, int size);
170197007Sdelphijstatic void	push_word (struct x86emu *, uint16_t w);
171197007Sdelphijstatic void	push_long (struct x86emu *, uint32_t w);
172197007Sdelphijstatic uint16_t	pop_word (struct x86emu *);
173197007Sdelphijstatic uint32_t	pop_long (struct x86emu *);
174197007Sdelphij
175197007Sdelphij/*
176197007Sdelphij * REMARKS:
177197007Sdelphij * Handles any pending asychronous interrupts.
178197007Sdelphij */
179197007Sdelphijstatic void
180197007Sdelphijx86emu_intr_dispatch(struct x86emu *emu, uint8_t intno)
181197007Sdelphij{
182197007Sdelphij	if (emu->_x86emu_intrTab[intno]) {
183197007Sdelphij		(*emu->_x86emu_intrTab[intno]) (emu, intno);
184197007Sdelphij	} else {
185197007Sdelphij		push_word(emu, (uint16_t) emu->x86.R_FLG);
186197007Sdelphij		CLEAR_FLAG(F_IF);
187197007Sdelphij		CLEAR_FLAG(F_TF);
188197007Sdelphij		push_word(emu, emu->x86.R_CS);
189197007Sdelphij		emu->x86.R_CS = fetch_word(emu, 0, intno * 4 + 2);
190197007Sdelphij		push_word(emu, emu->x86.R_IP);
191197007Sdelphij		emu->x86.R_IP = fetch_word(emu, 0, intno * 4);
192197007Sdelphij	}
193197007Sdelphij}
194197007Sdelphij
195197007Sdelphijstatic void
196197007Sdelphijx86emu_intr_handle(struct x86emu *emu)
197197007Sdelphij{
198197007Sdelphij	uint8_t intno;
199197007Sdelphij
200197007Sdelphij	if (emu->x86.intr & INTR_SYNCH) {
201197007Sdelphij		intno = emu->x86.intno;
202197007Sdelphij		emu->x86.intr = 0;
203197007Sdelphij		x86emu_intr_dispatch(emu, intno);
204197007Sdelphij	}
205197007Sdelphij}
206197007Sdelphij
207197007Sdelphij/*
208197007Sdelphij * PARAMETERS:
209197007Sdelphij * intrnum - Interrupt number to raise
210197007Sdelphij *
211197007Sdelphij * REMARKS:
212197007Sdelphij * Raise the specified interrupt to be handled before the execution of the
213197007Sdelphij * next instruction.
214197007Sdelphij */
215197007Sdelphijvoid
216197007Sdelphijx86emu_intr_raise(struct x86emu *emu, uint8_t intrnum)
217197007Sdelphij{
218197007Sdelphij	emu->x86.intno = intrnum;
219197007Sdelphij	emu->x86.intr |= INTR_SYNCH;
220197007Sdelphij}
221197007Sdelphij
222197007Sdelphij/*
223197007Sdelphij * REMARKS:
224197007Sdelphij * Main execution loop for the emulator. We return from here when the system
225197007Sdelphij * halts, which is normally caused by a stack fault when we return from the
226197007Sdelphij * original real mode call.
227197007Sdelphij */
228197007Sdelphijvoid
229197007Sdelphijx86emu_exec(struct x86emu *emu)
230197007Sdelphij{
231197007Sdelphij	emu->x86.intr = 0;
232197007Sdelphij
233197007Sdelphij	if (setjmp(emu->exec_state))
234197007Sdelphij		return;
235197007Sdelphij
236197007Sdelphij	for (;;) {
237197007Sdelphij		if (emu->x86.intr) {
238204934Sdelphij			if (((emu->x86.intr & INTR_SYNCH) &&
239204934Sdelphij			    (emu->x86.intno == 0 || emu->x86.intno == 2)) ||
240197007Sdelphij			    !ACCESS_FLAG(F_IF)) {
241197007Sdelphij				x86emu_intr_handle(emu);
242197007Sdelphij			}
243197007Sdelphij		}
244197007Sdelphij		if (emu->x86.R_CS == 0 && emu->x86.R_IP == 0)
245197007Sdelphij			return;
246197007Sdelphij		x86emu_exec_one_byte(emu);
247197007Sdelphij		++emu->cur_cycles;
248197007Sdelphij	}
249197007Sdelphij}
250197007Sdelphij
251197007Sdelphijvoid
252197007Sdelphijx86emu_exec_call(struct x86emu *emu, uint16_t seg, uint16_t off)
253197007Sdelphij{
254197007Sdelphij	push_word(emu, 0);
255197007Sdelphij	push_word(emu, 0);
256197007Sdelphij	emu->x86.R_CS = seg;
257197007Sdelphij	emu->x86.R_IP = off;
258197007Sdelphij
259197007Sdelphij	x86emu_exec(emu);
260197007Sdelphij}
261197007Sdelphij
262197007Sdelphijvoid
263197007Sdelphijx86emu_exec_intr(struct x86emu *emu, uint8_t intr)
264197007Sdelphij{
265197007Sdelphij	push_word(emu, emu->x86.R_FLG);
266197007Sdelphij	CLEAR_FLAG(F_IF);
267197007Sdelphij	CLEAR_FLAG(F_TF);
268197007Sdelphij	push_word(emu, 0);
269197007Sdelphij	push_word(emu, 0);
270197007Sdelphij	emu->x86.R_CS = (*emu->emu_rdw)(emu, intr * 4 + 2);
271197007Sdelphij	emu->x86.R_IP = (*emu->emu_rdw)(emu, intr * 4);
272197007Sdelphij	emu->x86.intr = 0;
273197007Sdelphij
274197007Sdelphij	x86emu_exec(emu);
275197007Sdelphij}
276197007Sdelphij
277197007Sdelphij/*
278197007Sdelphij * REMARKS:
279197007Sdelphij * Halts the system by setting the halted system flag.
280197007Sdelphij */
281197007Sdelphijvoid
282197007Sdelphijx86emu_halt_sys(struct x86emu *emu)
283197007Sdelphij{
284197007Sdelphij	longjmp(emu->exec_state, 1);
285197007Sdelphij}
286197007Sdelphij
287197007Sdelphij/*
288197007Sdelphij * PARAMETERS:
289197007Sdelphij * mod		- Mod value from decoded byte
290197007Sdelphij * regh	- Reg h value from decoded byte
291197007Sdelphij * regl	- Reg l value from decoded byte
292197007Sdelphij *
293197007Sdelphij * REMARKS:
294197007Sdelphij * Raise the specified interrupt to be handled before the execution of the
295197007Sdelphij * next instruction.
296197007Sdelphij *
297197007Sdelphij * NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
298197007Sdelphij */
299197007Sdelphijstatic void
300197007Sdelphijfetch_decode_modrm(struct x86emu *emu)
301197007Sdelphij{
302197007Sdelphij	int fetched;
303197007Sdelphij
304197007Sdelphij	fetched = fetch_byte_imm(emu);
305197007Sdelphij	emu->cur_mod = (fetched >> 6) & 0x03;
306197007Sdelphij	emu->cur_rh = (fetched >> 3) & 0x07;
307197007Sdelphij	emu->cur_rl = (fetched >> 0) & 0x07;
308197007Sdelphij}
309197007Sdelphij
310197007Sdelphij/*
311197007Sdelphij * RETURNS:
312197007Sdelphij * Immediate byte value read from instruction queue
313197007Sdelphij *
314197007Sdelphij * REMARKS:
315197007Sdelphij * This function returns the immediate byte from the instruction queue, and
316197007Sdelphij * moves the instruction pointer to the next value.
317197007Sdelphij *
318197007Sdelphij * NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
319197007Sdelphij */
320197007Sdelphijstatic uint8_t
321197007Sdelphijfetch_byte_imm(struct x86emu *emu)
322197007Sdelphij{
323197007Sdelphij	uint8_t fetched;
324197007Sdelphij
325197007Sdelphij	fetched = fetch_byte(emu, emu->x86.R_CS, emu->x86.R_IP);
326197007Sdelphij	emu->x86.R_IP++;
327197007Sdelphij	return fetched;
328197007Sdelphij}
329197007Sdelphij
330197007Sdelphij/*
331197007Sdelphij * RETURNS:
332197007Sdelphij * Immediate word value read from instruction queue
333197007Sdelphij *
334197007Sdelphij * REMARKS:
335197007Sdelphij * This function returns the immediate byte from the instruction queue, and
336197007Sdelphij * moves the instruction pointer to the next value.
337197007Sdelphij *
338197007Sdelphij * NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
339197007Sdelphij */
340197007Sdelphijstatic uint16_t
341197007Sdelphijfetch_word_imm(struct x86emu *emu)
342197007Sdelphij{
343197007Sdelphij	uint16_t fetched;
344197007Sdelphij
345197007Sdelphij	fetched = fetch_word(emu, emu->x86.R_CS, emu->x86.R_IP);
346197007Sdelphij	emu->x86.R_IP += 2;
347197007Sdelphij	return fetched;
348197007Sdelphij}
349197007Sdelphij
350197007Sdelphij/*
351197007Sdelphij * RETURNS:
352197007Sdelphij * Immediate lone value read from instruction queue
353197007Sdelphij *
354197007Sdelphij * REMARKS:
355197007Sdelphij * This function returns the immediate byte from the instruction queue, and
356197007Sdelphij * moves the instruction pointer to the next value.
357197007Sdelphij *
358197007Sdelphij * NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
359197007Sdelphij */
360197007Sdelphijstatic uint32_t
361197007Sdelphijfetch_long_imm(struct x86emu *emu)
362197007Sdelphij{
363197007Sdelphij	uint32_t fetched;
364197007Sdelphij
365197007Sdelphij	fetched = fetch_long(emu, emu->x86.R_CS, emu->x86.R_IP);
366197007Sdelphij	emu->x86.R_IP += 4;
367197007Sdelphij	return fetched;
368197007Sdelphij}
369197007Sdelphij
370197007Sdelphij/*
371197007Sdelphij * RETURNS:
372197007Sdelphij * Value of the default data segment
373197007Sdelphij *
374197007Sdelphij * REMARKS:
375197007Sdelphij * Inline function that returns the default data segment for the current
376197007Sdelphij * instruction.
377197007Sdelphij *
378197007Sdelphij * On the x86 processor, the default segment is not always DS if there is
379197007Sdelphij * no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
380197007Sdelphij * addresses relative to SS (ie: on the stack). So, at the minimum, all
381197007Sdelphij * decodings of addressing modes would have to set/clear a bit describing
382197007Sdelphij * whether the access is relative to DS or SS.  That is the function of the
383197007Sdelphij * cpu-state-varible emu->x86.mode. There are several potential states:
384197007Sdelphij *
385197007Sdelphij * 	repe prefix seen  (handled elsewhere)
386197007Sdelphij * 	repne prefix seen  (ditto)
387197007Sdelphij *
388197007Sdelphij * 	cs segment override
389197007Sdelphij * 	ds segment override
390197007Sdelphij * 	es segment override
391197007Sdelphij * 	fs segment override
392197007Sdelphij * 	gs segment override
393197007Sdelphij * 	ss segment override
394197007Sdelphij *
395197007Sdelphij * 	ds/ss select (in absense of override)
396197007Sdelphij *
397197007Sdelphij * Each of the above 7 items are handled with a bit in the mode field.
398197007Sdelphij */
399197007Sdelphijstatic uint32_t
400197007Sdelphijget_data_segment(struct x86emu *emu)
401197007Sdelphij{
402197007Sdelphij	switch (emu->x86.mode & SYSMODE_SEGMASK) {
403197007Sdelphij	case 0:		/* default case: use ds register */
404197007Sdelphij	case SYSMODE_SEGOVR_DS:
405197007Sdelphij	case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
406197007Sdelphij		return emu->x86.R_DS;
407197007Sdelphij	case SYSMODE_SEG_DS_SS:/* non-overridden, use ss register */
408197007Sdelphij		return emu->x86.R_SS;
409197007Sdelphij	case SYSMODE_SEGOVR_CS:
410197007Sdelphij	case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
411197007Sdelphij		return emu->x86.R_CS;
412197007Sdelphij	case SYSMODE_SEGOVR_ES:
413197007Sdelphij	case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
414197007Sdelphij		return emu->x86.R_ES;
415197007Sdelphij	case SYSMODE_SEGOVR_FS:
416197007Sdelphij	case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
417197007Sdelphij		return emu->x86.R_FS;
418197007Sdelphij	case SYSMODE_SEGOVR_GS:
419197007Sdelphij	case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
420197007Sdelphij		return emu->x86.R_GS;
421197007Sdelphij	case SYSMODE_SEGOVR_SS:
422197007Sdelphij	case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
423197007Sdelphij		return emu->x86.R_SS;
424197007Sdelphij	}
425197007Sdelphij	x86emu_halt_sys(emu);
426197007Sdelphij}
427197007Sdelphij
428197007Sdelphij/*
429197007Sdelphij * PARAMETERS:
430197007Sdelphij * offset	- Offset to load data from
431197007Sdelphij *
432197007Sdelphij * RETURNS:
433197007Sdelphij * Byte value read from the absolute memory location.
434197007Sdelphij *
435197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
436197007Sdelphij */
437197007Sdelphijstatic uint8_t
438197007Sdelphijfetch_data_byte(struct x86emu *emu, uint32_t offset)
439197007Sdelphij{
440197007Sdelphij	return fetch_byte(emu, get_data_segment(emu), offset);
441197007Sdelphij}
442197007Sdelphij
443197007Sdelphij/*
444197007Sdelphij * PARAMETERS:
445197007Sdelphij * offset	- Offset to load data from
446197007Sdelphij *
447197007Sdelphij * RETURNS:
448197007Sdelphij * Word value read from the absolute memory location.
449197007Sdelphij *
450197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
451197007Sdelphij */
452197007Sdelphijstatic uint16_t
453197007Sdelphijfetch_data_word(struct x86emu *emu, uint32_t offset)
454197007Sdelphij{
455197007Sdelphij	return fetch_word(emu, get_data_segment(emu), offset);
456197007Sdelphij}
457197007Sdelphij
458197007Sdelphij/*
459197007Sdelphij * PARAMETERS:
460197007Sdelphij * offset	- Offset to load data from
461197007Sdelphij *
462197007Sdelphij * RETURNS:
463197007Sdelphij * Long value read from the absolute memory location.
464197007Sdelphij *
465197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
466197007Sdelphij */
467197007Sdelphijstatic uint32_t
468197007Sdelphijfetch_data_long(struct x86emu *emu, uint32_t offset)
469197007Sdelphij{
470197007Sdelphij	return fetch_long(emu, get_data_segment(emu), offset);
471197007Sdelphij}
472197007Sdelphij
473197007Sdelphij/*
474197007Sdelphij * PARAMETERS:
475197007Sdelphij * segment	- Segment to load data from
476197007Sdelphij * offset	- Offset to load data from
477197007Sdelphij *
478197007Sdelphij * RETURNS:
479197007Sdelphij * Byte value read from the absolute memory location.
480197007Sdelphij *
481197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
482197007Sdelphij */
483197007Sdelphijstatic uint8_t
484197007Sdelphijfetch_byte(struct x86emu *emu, uint32_t segment, uint32_t offset)
485197007Sdelphij{
486197007Sdelphij	return (*emu->emu_rdb) (emu, ((uint32_t) segment << 4) + offset);
487197007Sdelphij}
488197007Sdelphij
489197007Sdelphij/*
490197007Sdelphij * PARAMETERS:
491197007Sdelphij * segment	- Segment to load data from
492197007Sdelphij * offset	- Offset to load data from
493197007Sdelphij *
494197007Sdelphij * RETURNS:
495197007Sdelphij * Word value read from the absolute memory location.
496197007Sdelphij *
497197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
498197007Sdelphij */
499197007Sdelphijstatic uint16_t
500197007Sdelphijfetch_word(struct x86emu *emu, uint32_t segment, uint32_t offset)
501197007Sdelphij{
502197007Sdelphij	return (*emu->emu_rdw) (emu, ((uint32_t) segment << 4) + offset);
503197007Sdelphij}
504197007Sdelphij
505197007Sdelphij/*
506197007Sdelphij * PARAMETERS:
507197007Sdelphij * segment	- Segment to load data from
508197007Sdelphij * offset	- Offset to load data from
509197007Sdelphij *
510197007Sdelphij * RETURNS:
511197007Sdelphij * Long value read from the absolute memory location.
512197007Sdelphij *
513197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
514197007Sdelphij */
515197007Sdelphijstatic uint32_t
516197007Sdelphijfetch_long(struct x86emu *emu, uint32_t segment, uint32_t offset)
517197007Sdelphij{
518197007Sdelphij	return (*emu->emu_rdl) (emu, ((uint32_t) segment << 4) + offset);
519197007Sdelphij}
520197007Sdelphij
521197007Sdelphij/*
522197007Sdelphij * PARAMETERS:
523197007Sdelphij * offset	- Offset to store data at
524197007Sdelphij * val		- Value to store
525197007Sdelphij *
526197007Sdelphij * REMARKS:
527197007Sdelphij * Writes a word value to an segmented memory location. The segment used is
528197007Sdelphij * the current 'default' segment, which may have been overridden.
529197007Sdelphij *
530197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
531197007Sdelphij */
532197007Sdelphijstatic void
533197007Sdelphijstore_data_byte(struct x86emu *emu, uint32_t offset, uint8_t val)
534197007Sdelphij{
535197007Sdelphij	store_byte(emu, get_data_segment(emu), offset, val);
536197007Sdelphij}
537197007Sdelphij
538197007Sdelphij/*
539197007Sdelphij * PARAMETERS:
540197007Sdelphij * offset	- Offset to store data at
541197007Sdelphij * val		- Value to store
542197007Sdelphij *
543197007Sdelphij * REMARKS:
544197007Sdelphij * Writes a word value to an segmented memory location. The segment used is
545197007Sdelphij * the current 'default' segment, which may have been overridden.
546197007Sdelphij *
547197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
548197007Sdelphij */
549197007Sdelphijstatic void
550197007Sdelphijstore_data_word(struct x86emu *emu, uint32_t offset, uint16_t val)
551197007Sdelphij{
552197007Sdelphij	store_word(emu, get_data_segment(emu), offset, val);
553197007Sdelphij}
554197007Sdelphij
555197007Sdelphij/*
556197007Sdelphij * PARAMETERS:
557197007Sdelphij * offset	- Offset to store data at
558197007Sdelphij * val		- Value to store
559197007Sdelphij *
560197007Sdelphij * REMARKS:
561197007Sdelphij * Writes a long value to an segmented memory location. The segment used is
562197007Sdelphij * the current 'default' segment, which may have been overridden.
563197007Sdelphij *
564197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
565197007Sdelphij */
566197007Sdelphijstatic void
567197007Sdelphijstore_data_long(struct x86emu *emu, uint32_t offset, uint32_t val)
568197007Sdelphij{
569197007Sdelphij	store_long(emu, get_data_segment(emu), offset, val);
570197007Sdelphij}
571197007Sdelphij
572197007Sdelphij/*
573197007Sdelphij * PARAMETERS:
574197007Sdelphij * segment	- Segment to store data at
575197007Sdelphij * offset	- Offset to store data at
576197007Sdelphij * val		- Value to store
577197007Sdelphij *
578197007Sdelphij * REMARKS:
579197007Sdelphij * Writes a byte value to an absolute memory location.
580197007Sdelphij *
581197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
582197007Sdelphij */
583197007Sdelphijstatic void
584197007Sdelphijstore_byte(struct x86emu *emu, uint32_t segment, uint32_t offset, uint8_t val)
585197007Sdelphij{
586197007Sdelphij	(*emu->emu_wrb) (emu, ((uint32_t) segment << 4) + offset, val);
587197007Sdelphij}
588197007Sdelphij
589197007Sdelphij/*
590197007Sdelphij * PARAMETERS:
591197007Sdelphij * segment	- Segment to store data at
592197007Sdelphij * offset	- Offset to store data at
593197007Sdelphij * val		- Value to store
594197007Sdelphij *
595197007Sdelphij * REMARKS:
596197007Sdelphij * Writes a word value to an absolute memory location.
597197007Sdelphij *
598197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
599197007Sdelphij */
600197007Sdelphijstatic void
601197007Sdelphijstore_word(struct x86emu *emu, uint32_t segment, uint32_t offset, uint16_t val)
602197007Sdelphij{
603197007Sdelphij	(*emu->emu_wrw) (emu, ((uint32_t) segment << 4) + offset, val);
604197007Sdelphij}
605197007Sdelphij
606197007Sdelphij/*
607197007Sdelphij * PARAMETERS:
608197007Sdelphij * segment	- Segment to store data at
609197007Sdelphij * offset	- Offset to store data at
610197007Sdelphij * val		- Value to store
611197007Sdelphij *
612197007Sdelphij * REMARKS:
613197007Sdelphij * Writes a long value to an absolute memory location.
614197007Sdelphij *
615197007Sdelphij * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
616197007Sdelphij */
617197007Sdelphijstatic void
618197007Sdelphijstore_long(struct x86emu *emu, uint32_t segment, uint32_t offset, uint32_t val)
619197007Sdelphij{
620197007Sdelphij	(*emu->emu_wrl) (emu, ((uint32_t) segment << 4) + offset, val);
621197007Sdelphij}
622197007Sdelphij
623197007Sdelphij/*
624197007Sdelphij * PARAMETERS:
625197007Sdelphij * reg	- Register to decode
626197007Sdelphij *
627197007Sdelphij * RETURNS:
628197007Sdelphij * Pointer to the appropriate register
629197007Sdelphij *
630197007Sdelphij * REMARKS:
631197007Sdelphij * Return a pointer to the register given by the R/RM field of the
632197007Sdelphij * modrm byte, for byte operands. Also enables the decoding of instructions.
633197007Sdelphij */
634197007Sdelphijstatic uint8_t *
635197007Sdelphijdecode_rm_byte_register(struct x86emu *emu, int reg)
636197007Sdelphij{
637197007Sdelphij	switch (reg) {
638197007Sdelphij	case 0:
639197007Sdelphij		return &emu->x86.R_AL;
640197007Sdelphij	case 1:
641197007Sdelphij		return &emu->x86.R_CL;
642197007Sdelphij	case 2:
643197007Sdelphij		return &emu->x86.R_DL;
644197007Sdelphij	case 3:
645197007Sdelphij		return &emu->x86.R_BL;
646197007Sdelphij	case 4:
647197007Sdelphij		return &emu->x86.R_AH;
648197007Sdelphij	case 5:
649197007Sdelphij		return &emu->x86.R_CH;
650197007Sdelphij	case 6:
651197007Sdelphij		return &emu->x86.R_DH;
652197007Sdelphij	case 7:
653197007Sdelphij		return &emu->x86.R_BH;
654197007Sdelphij	default:
655197007Sdelphij		x86emu_halt_sys(emu);
656197007Sdelphij	}
657197007Sdelphij}
658197007Sdelphij
659197007Sdelphijstatic uint8_t *
660197007Sdelphijdecode_rl_byte_register(struct x86emu *emu)
661197007Sdelphij{
662197007Sdelphij	return decode_rm_byte_register(emu, emu->cur_rl);
663197007Sdelphij}
664197007Sdelphij
665197007Sdelphijstatic uint8_t *
666197007Sdelphijdecode_rh_byte_register(struct x86emu *emu)
667197007Sdelphij{
668197007Sdelphij	return decode_rm_byte_register(emu, emu->cur_rh);
669197007Sdelphij}
670197007Sdelphij
671197007Sdelphij/*
672197007Sdelphij * PARAMETERS:
673197007Sdelphij * reg	- Register to decode
674197007Sdelphij *
675197007Sdelphij * RETURNS:
676197007Sdelphij * Pointer to the appropriate register
677197007Sdelphij *
678197007Sdelphij * REMARKS:
679197007Sdelphij * Return a pointer to the register given by the R/RM field of the
680197007Sdelphij * modrm byte, for word operands.  Also enables the decoding of instructions.
681197007Sdelphij */
682197007Sdelphijstatic uint16_t *
683197007Sdelphijdecode_rm_word_register(struct x86emu *emu, int reg)
684197007Sdelphij{
685197007Sdelphij	switch (reg) {
686197007Sdelphij	case 0:
687197007Sdelphij		return &emu->x86.R_AX;
688197007Sdelphij	case 1:
689197007Sdelphij		return &emu->x86.R_CX;
690197007Sdelphij	case 2:
691197007Sdelphij		return &emu->x86.R_DX;
692197007Sdelphij	case 3:
693197007Sdelphij		return &emu->x86.R_BX;
694197007Sdelphij	case 4:
695197007Sdelphij		return &emu->x86.R_SP;
696197007Sdelphij	case 5:
697197007Sdelphij		return &emu->x86.R_BP;
698197007Sdelphij	case 6:
699197007Sdelphij		return &emu->x86.R_SI;
700197007Sdelphij	case 7:
701197007Sdelphij		return &emu->x86.R_DI;
702197007Sdelphij	default:
703197007Sdelphij		x86emu_halt_sys(emu);
704197007Sdelphij	}
705197007Sdelphij}
706197007Sdelphij
707197007Sdelphijstatic uint16_t *
708197007Sdelphijdecode_rl_word_register(struct x86emu *emu)
709197007Sdelphij{
710197007Sdelphij	return decode_rm_word_register(emu, emu->cur_rl);
711197007Sdelphij}
712197007Sdelphij
713197007Sdelphijstatic uint16_t *
714197007Sdelphijdecode_rh_word_register(struct x86emu *emu)
715197007Sdelphij{
716197007Sdelphij	return decode_rm_word_register(emu, emu->cur_rh);
717197007Sdelphij}
718197007Sdelphij
719197007Sdelphij/*
720197007Sdelphij * PARAMETERS:
721197007Sdelphij * reg	- Register to decode
722197007Sdelphij *
723197007Sdelphij * RETURNS:
724197007Sdelphij * Pointer to the appropriate register
725197007Sdelphij *
726197007Sdelphij * REMARKS:
727197007Sdelphij * Return a pointer to the register given by the R/RM field of the
728197007Sdelphij * modrm byte, for dword operands.  Also enables the decoding of instructions.
729197007Sdelphij */
730197007Sdelphijstatic uint32_t *
731197007Sdelphijdecode_rm_long_register(struct x86emu *emu, int reg)
732197007Sdelphij{
733197007Sdelphij	switch (reg) {
734197007Sdelphij	case 0:
735197007Sdelphij		return &emu->x86.R_EAX;
736197007Sdelphij	case 1:
737197007Sdelphij		return &emu->x86.R_ECX;
738197007Sdelphij	case 2:
739197007Sdelphij		return &emu->x86.R_EDX;
740197007Sdelphij	case 3:
741197007Sdelphij		return &emu->x86.R_EBX;
742197007Sdelphij	case 4:
743197007Sdelphij		return &emu->x86.R_ESP;
744197007Sdelphij	case 5:
745197007Sdelphij		return &emu->x86.R_EBP;
746197007Sdelphij	case 6:
747197007Sdelphij		return &emu->x86.R_ESI;
748197007Sdelphij	case 7:
749197007Sdelphij		return &emu->x86.R_EDI;
750197007Sdelphij	default:
751197007Sdelphij		x86emu_halt_sys(emu);
752197007Sdelphij	}
753197007Sdelphij}
754197007Sdelphij
755197007Sdelphijstatic uint32_t *
756197007Sdelphijdecode_rl_long_register(struct x86emu *emu)
757197007Sdelphij{
758197007Sdelphij	return decode_rm_long_register(emu, emu->cur_rl);
759197007Sdelphij}
760197007Sdelphij
761197007Sdelphijstatic uint32_t *
762197007Sdelphijdecode_rh_long_register(struct x86emu *emu)
763197007Sdelphij{
764197007Sdelphij	return decode_rm_long_register(emu, emu->cur_rh);
765197007Sdelphij}
766197007Sdelphij
767197007Sdelphij
768197007Sdelphij/*
769197007Sdelphij * PARAMETERS:
770197007Sdelphij * reg	- Register to decode
771197007Sdelphij *
772197007Sdelphij * RETURNS:
773197007Sdelphij * Pointer to the appropriate register
774197007Sdelphij *
775197007Sdelphij * REMARKS:
776197007Sdelphij * Return a pointer to the register given by the R/RM field of the
777197007Sdelphij * modrm byte, for word operands, modified from above for the weirdo
778197007Sdelphij * special case of segreg operands.  Also enables the decoding of instructions.
779197007Sdelphij */
780197007Sdelphijstatic uint16_t *
781197007Sdelphijdecode_rh_seg_register(struct x86emu *emu)
782197007Sdelphij{
783197007Sdelphij	switch (emu->cur_rh) {
784197007Sdelphij	case 0:
785197007Sdelphij		return &emu->x86.R_ES;
786197007Sdelphij	case 1:
787197007Sdelphij		return &emu->x86.R_CS;
788197007Sdelphij	case 2:
789197007Sdelphij		return &emu->x86.R_SS;
790197007Sdelphij	case 3:
791197007Sdelphij		return &emu->x86.R_DS;
792197007Sdelphij	case 4:
793197007Sdelphij		return &emu->x86.R_FS;
794197007Sdelphij	case 5:
795197007Sdelphij		return &emu->x86.R_GS;
796197007Sdelphij	default:
797197007Sdelphij		x86emu_halt_sys(emu);
798197007Sdelphij	}
799197007Sdelphij}
800204934Sdelphij
801197007Sdelphij/*
802204934Sdelphij * Return offset from the SIB Byte.
803197007Sdelphij */
804197007Sdelphijstatic uint32_t
805197007Sdelphijdecode_sib_address(struct x86emu *emu, int sib, int mod)
806197007Sdelphij{
807197007Sdelphij	uint32_t base = 0, i = 0, scale = 1;
808197007Sdelphij
809197007Sdelphij	switch (sib & 0x07) {
810197007Sdelphij	case 0:
811197007Sdelphij		base = emu->x86.R_EAX;
812197007Sdelphij		break;
813197007Sdelphij	case 1:
814197007Sdelphij		base = emu->x86.R_ECX;
815197007Sdelphij
816197007Sdelphij		break;
817197007Sdelphij	case 2:
818197007Sdelphij		base = emu->x86.R_EDX;
819197007Sdelphij		break;
820197007Sdelphij	case 3:
821197007Sdelphij		base = emu->x86.R_EBX;
822197007Sdelphij		break;
823197007Sdelphij	case 4:
824197007Sdelphij		base = emu->x86.R_ESP;
825197007Sdelphij		emu->x86.mode |= SYSMODE_SEG_DS_SS;
826197007Sdelphij		break;
827197007Sdelphij	case 5:
828197007Sdelphij		if (mod == 0) {
829197007Sdelphij			base = fetch_long_imm(emu);
830197007Sdelphij		} else {
831197007Sdelphij			base = emu->x86.R_EBP;
832197007Sdelphij			emu->x86.mode |= SYSMODE_SEG_DS_SS;
833197007Sdelphij		}
834197007Sdelphij		break;
835197007Sdelphij	case 6:
836197007Sdelphij		base = emu->x86.R_ESI;
837197007Sdelphij		break;
838197007Sdelphij	case 7:
839197007Sdelphij		base = emu->x86.R_EDI;
840197007Sdelphij		break;
841197007Sdelphij	}
842197007Sdelphij	switch ((sib >> 3) & 0x07) {
843197007Sdelphij	case 0:
844197007Sdelphij		i = emu->x86.R_EAX;
845197007Sdelphij		break;
846197007Sdelphij	case 1:
847197007Sdelphij		i = emu->x86.R_ECX;
848197007Sdelphij		break;
849197007Sdelphij	case 2:
850197007Sdelphij		i = emu->x86.R_EDX;
851197007Sdelphij		break;
852197007Sdelphij	case 3:
853197007Sdelphij		i = emu->x86.R_EBX;
854197007Sdelphij		break;
855197007Sdelphij	case 4:
856197007Sdelphij		i = 0;
857197007Sdelphij		break;
858197007Sdelphij	case 5:
859197007Sdelphij		i = emu->x86.R_EBP;
860197007Sdelphij		break;
861197007Sdelphij	case 6:
862197007Sdelphij		i = emu->x86.R_ESI;
863197007Sdelphij		break;
864197007Sdelphij	case 7:
865197007Sdelphij		i = emu->x86.R_EDI;
866197007Sdelphij		break;
867197007Sdelphij	}
868197007Sdelphij	scale = 1 << ((sib >> 6) & 0x03);
869197007Sdelphij	return base + (i * scale);
870197007Sdelphij}
871197007Sdelphij
872197007Sdelphij/*
873197007Sdelphij * PARAMETERS:
874197007Sdelphij * rm	- RM value to decode
875197007Sdelphij *
876197007Sdelphij * RETURNS:
877197007Sdelphij * Offset in memory for the address decoding
878197007Sdelphij *
879197007Sdelphij * REMARKS:
880197007Sdelphij * Return the offset given by mod=00, mod=01 or mod=10 addressing.
881197007Sdelphij * Also enables the decoding of instructions.
882197007Sdelphij */
883197007Sdelphijstatic uint32_t
884197007Sdelphijdecode_rl_address(struct x86emu *emu)
885197007Sdelphij{
886197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_ADDR) {
887197007Sdelphij		uint32_t offset, sib;
888197007Sdelphij		/* 32-bit addressing */
889197007Sdelphij		switch (emu->cur_rl) {
890197007Sdelphij		case 0:
891197007Sdelphij			offset = emu->x86.R_EAX;
892197007Sdelphij			break;
893197007Sdelphij		case 1:
894197007Sdelphij			offset = emu->x86.R_ECX;
895197007Sdelphij			break;
896197007Sdelphij		case 2:
897197007Sdelphij			offset = emu->x86.R_EDX;
898197007Sdelphij			break;
899197007Sdelphij		case 3:
900197007Sdelphij			offset = emu->x86.R_EBX;
901197007Sdelphij			break;
902197007Sdelphij		case 4:
903197007Sdelphij			sib = fetch_byte_imm(emu);
904197007Sdelphij			offset = decode_sib_address(emu, sib, 0);
905197007Sdelphij			break;
906197007Sdelphij		case 5:
907197007Sdelphij			if (emu->cur_mod == 0) {
908197007Sdelphij				offset = fetch_long_imm(emu);
909197007Sdelphij			} else {
910197007Sdelphij				emu->x86.mode |= SYSMODE_SEG_DS_SS;
911197007Sdelphij				offset = emu->x86.R_EBP;
912197007Sdelphij			}
913197007Sdelphij			break;
914197007Sdelphij		case 6:
915197007Sdelphij			offset = emu->x86.R_ESI;
916197007Sdelphij			break;
917197007Sdelphij		case 7:
918197007Sdelphij			offset = emu->x86.R_EDI;
919197007Sdelphij			break;
920197007Sdelphij		default:
921197007Sdelphij			x86emu_halt_sys(emu);
922197007Sdelphij		}
923197007Sdelphij		if (emu->cur_mod == 1)
924197007Sdelphij			offset += (int8_t)fetch_byte_imm(emu);
925197007Sdelphij		else if (emu->cur_mod == 2)
926197007Sdelphij			offset += fetch_long_imm(emu);
927197007Sdelphij		return offset;
928197007Sdelphij	} else {
929197007Sdelphij		uint16_t offset;
930197007Sdelphij
931197007Sdelphij		/* 16-bit addressing */
932197007Sdelphij		switch (emu->cur_rl) {
933197007Sdelphij		case 0:
934197007Sdelphij			offset = emu->x86.R_BX + emu->x86.R_SI;
935197007Sdelphij			break;
936197007Sdelphij		case 1:
937197007Sdelphij			offset = emu->x86.R_BX + emu->x86.R_DI;
938197007Sdelphij			break;
939197007Sdelphij		case 2:
940197007Sdelphij			emu->x86.mode |= SYSMODE_SEG_DS_SS;
941197007Sdelphij			offset = emu->x86.R_BP + emu->x86.R_SI;
942197007Sdelphij			break;
943197007Sdelphij		case 3:
944197007Sdelphij			emu->x86.mode |= SYSMODE_SEG_DS_SS;
945197007Sdelphij			offset = emu->x86.R_BP + emu->x86.R_DI;
946197007Sdelphij			break;
947197007Sdelphij		case 4:
948197007Sdelphij			offset = emu->x86.R_SI;
949197007Sdelphij			break;
950197007Sdelphij		case 5:
951197007Sdelphij			offset = emu->x86.R_DI;
952197007Sdelphij			break;
953197007Sdelphij		case 6:
954197007Sdelphij			if (emu->cur_mod == 0) {
955197007Sdelphij				offset = fetch_word_imm(emu);
956197007Sdelphij			} else {
957197007Sdelphij				emu->x86.mode |= SYSMODE_SEG_DS_SS;
958197007Sdelphij				offset = emu->x86.R_BP;
959197007Sdelphij			}
960197007Sdelphij			break;
961197007Sdelphij		case 7:
962197007Sdelphij			offset = emu->x86.R_BX;
963197007Sdelphij			break;
964197007Sdelphij		default:
965197007Sdelphij			x86emu_halt_sys(emu);
966197007Sdelphij		}
967197007Sdelphij		if (emu->cur_mod == 1)
968197007Sdelphij			offset += (int8_t)fetch_byte_imm(emu);
969197007Sdelphij		else if (emu->cur_mod == 2)
970197007Sdelphij			offset += fetch_word_imm(emu);
971197007Sdelphij		return offset;
972197007Sdelphij	}
973197007Sdelphij}
974197007Sdelphij
975197007Sdelphijstatic uint8_t
976197007Sdelphijdecode_and_fetch_byte(struct x86emu *emu)
977197007Sdelphij{
978197007Sdelphij	if (emu->cur_mod != 3) {
979197007Sdelphij		emu->cur_offset = decode_rl_address(emu);
980197007Sdelphij		return fetch_data_byte(emu, emu->cur_offset);
981197007Sdelphij	} else {
982197007Sdelphij		return *decode_rl_byte_register(emu);
983197007Sdelphij	}
984197007Sdelphij}
985197007Sdelphij
986197007Sdelphijstatic uint16_t
987197007Sdelphijdecode_and_fetch_word_disp(struct x86emu *emu, int16_t disp)
988197007Sdelphij{
989197007Sdelphij	if (emu->cur_mod != 3) {
990197007Sdelphij		/* TODO: A20 gate emulation */
991197007Sdelphij		emu->cur_offset = decode_rl_address(emu) + disp;
992197007Sdelphij		if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0)
993197007Sdelphij			emu->cur_offset &= 0xffff;
994197007Sdelphij		return fetch_data_word(emu, emu->cur_offset);
995197007Sdelphij	} else {
996197007Sdelphij		return *decode_rl_word_register(emu);
997197007Sdelphij	}
998197007Sdelphij}
999197007Sdelphij
1000197007Sdelphijstatic uint32_t
1001197007Sdelphijdecode_and_fetch_long_disp(struct x86emu *emu, int16_t disp)
1002197007Sdelphij{
1003197007Sdelphij	if (emu->cur_mod != 3) {
1004197007Sdelphij		/* TODO: A20 gate emulation */
1005197007Sdelphij		emu->cur_offset = decode_rl_address(emu) + disp;
1006197007Sdelphij		if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0)
1007197007Sdelphij			emu->cur_offset &= 0xffff;
1008197007Sdelphij		return fetch_data_long(emu, emu->cur_offset);
1009197007Sdelphij	} else {
1010197007Sdelphij		return *decode_rl_long_register(emu);
1011197007Sdelphij	}
1012197007Sdelphij}
1013197007Sdelphij
1014197007Sdelphijuint16_t
1015197007Sdelphijdecode_and_fetch_word(struct x86emu *emu)
1016197007Sdelphij{
1017197007Sdelphij	return decode_and_fetch_word_disp(emu, 0);
1018197007Sdelphij}
1019197007Sdelphij
1020197007Sdelphijuint32_t
1021197007Sdelphijdecode_and_fetch_long(struct x86emu *emu)
1022197007Sdelphij{
1023197007Sdelphij	return decode_and_fetch_long_disp(emu, 0);
1024197007Sdelphij}
1025197007Sdelphij
1026197007Sdelphijuint8_t
1027197007Sdelphijdecode_and_fetch_byte_imm8(struct x86emu *emu, uint8_t *imm)
1028197007Sdelphij{
1029197007Sdelphij	if (emu->cur_mod != 3) {
1030197007Sdelphij		emu->cur_offset = decode_rl_address(emu);
1031197007Sdelphij		*imm = fetch_byte_imm(emu);
1032197007Sdelphij		return fetch_data_byte(emu, emu->cur_offset);
1033197007Sdelphij	} else {
1034197007Sdelphij		*imm = fetch_byte_imm(emu);
1035197007Sdelphij		return *decode_rl_byte_register(emu);
1036197007Sdelphij	}
1037197007Sdelphij}
1038197007Sdelphij
1039197007Sdelphijstatic uint16_t
1040197007Sdelphijdecode_and_fetch_word_imm8(struct x86emu *emu, uint8_t *imm)
1041197007Sdelphij{
1042197007Sdelphij	if (emu->cur_mod != 3) {
1043197007Sdelphij		emu->cur_offset = decode_rl_address(emu);
1044197007Sdelphij		*imm = fetch_byte_imm(emu);
1045197007Sdelphij		return fetch_data_word(emu, emu->cur_offset);
1046197007Sdelphij	} else {
1047197007Sdelphij		*imm = fetch_byte_imm(emu);
1048197007Sdelphij		return *decode_rl_word_register(emu);
1049197007Sdelphij	}
1050197007Sdelphij}
1051197007Sdelphij
1052197007Sdelphijstatic uint32_t
1053197007Sdelphijdecode_and_fetch_long_imm8(struct x86emu *emu, uint8_t *imm)
1054197007Sdelphij{
1055197007Sdelphij	if (emu->cur_mod != 3) {
1056197007Sdelphij		emu->cur_offset = decode_rl_address(emu);
1057197007Sdelphij		*imm = fetch_byte_imm(emu);
1058197007Sdelphij		return fetch_data_long(emu, emu->cur_offset);
1059197007Sdelphij	} else {
1060197007Sdelphij		*imm = fetch_byte_imm(emu);
1061197007Sdelphij		return *decode_rl_long_register(emu);
1062197007Sdelphij	}
1063197007Sdelphij}
1064197007Sdelphij
1065197007Sdelphijstatic void
1066197007Sdelphijwrite_back_byte(struct x86emu *emu, uint8_t val)
1067197007Sdelphij{
1068197007Sdelphij	if (emu->cur_mod != 3)
1069197007Sdelphij		store_data_byte(emu, emu->cur_offset, val);
1070197007Sdelphij	else
1071197007Sdelphij		*decode_rl_byte_register(emu) = val;
1072197007Sdelphij}
1073197007Sdelphij
1074197007Sdelphijstatic void
1075197007Sdelphijwrite_back_word(struct x86emu *emu, uint16_t val)
1076197007Sdelphij{
1077197007Sdelphij	if (emu->cur_mod != 3)
1078197007Sdelphij		store_data_word(emu, emu->cur_offset, val);
1079197007Sdelphij	else
1080197007Sdelphij		*decode_rl_word_register(emu) = val;
1081197007Sdelphij}
1082197007Sdelphij
1083197007Sdelphijstatic void
1084197007Sdelphijwrite_back_long(struct x86emu *emu, uint32_t val)
1085197007Sdelphij{
1086197007Sdelphij	if (emu->cur_mod != 3)
1087197007Sdelphij		store_data_long(emu, emu->cur_offset, val);
1088197007Sdelphij	else
1089197007Sdelphij		*decode_rl_long_register(emu) = val;
1090197007Sdelphij}
1091197007Sdelphij
1092197007Sdelphijstatic void
1093197007Sdelphijcommon_inc_word_long(struct x86emu *emu, union x86emu_register *reg)
1094197007Sdelphij{
1095197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1096197007Sdelphij		reg->I32_reg.e_reg = inc_long(emu, reg->I32_reg.e_reg);
1097197007Sdelphij	else
1098197007Sdelphij		reg->I16_reg.x_reg = inc_word(emu, reg->I16_reg.x_reg);
1099197007Sdelphij}
1100197007Sdelphij
1101197007Sdelphijstatic void
1102197007Sdelphijcommon_dec_word_long(struct x86emu *emu, union x86emu_register *reg)
1103197007Sdelphij{
1104197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1105197007Sdelphij		reg->I32_reg.e_reg = dec_long(emu, reg->I32_reg.e_reg);
1106197007Sdelphij	else
1107197007Sdelphij		reg->I16_reg.x_reg = dec_word(emu, reg->I16_reg.x_reg);
1108197007Sdelphij}
1109197007Sdelphij
1110197007Sdelphijstatic void
1111204934Sdelphijcommon_binop_byte_rm_r(struct x86emu *emu,
1112204934Sdelphij    uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t))
1113197007Sdelphij{
1114197007Sdelphij	uint32_t destoffset;
1115197007Sdelphij	uint8_t *destreg, srcval;
1116197007Sdelphij	uint8_t destval;
1117197007Sdelphij
1118197007Sdelphij	fetch_decode_modrm(emu);
1119197007Sdelphij	srcval = *decode_rh_byte_register(emu);
1120197007Sdelphij	if (emu->cur_mod != 3) {
1121197007Sdelphij		destoffset = decode_rl_address(emu);
1122197007Sdelphij		destval = fetch_data_byte(emu, destoffset);
1123197007Sdelphij		destval = (*binop)(emu, destval, srcval);
1124197007Sdelphij		store_data_byte(emu, destoffset, destval);
1125197007Sdelphij	} else {
1126197007Sdelphij		destreg = decode_rl_byte_register(emu);
1127197007Sdelphij		*destreg = (*binop)(emu, *destreg, srcval);
1128197007Sdelphij	}
1129197007Sdelphij}
1130197007Sdelphij
1131197007Sdelphijstatic void
1132204934Sdelphijcommon_binop_ns_byte_rm_r(struct x86emu *emu,
1133204934Sdelphij    void (*binop)(struct x86emu *, uint8_t, uint8_t))
1134197007Sdelphij{
1135197007Sdelphij	uint32_t destoffset;
1136197007Sdelphij	uint8_t destval, srcval;
1137197007Sdelphij
1138197007Sdelphij	fetch_decode_modrm(emu);
1139197007Sdelphij	srcval = *decode_rh_byte_register(emu);
1140197007Sdelphij	if (emu->cur_mod != 3) {
1141197007Sdelphij		destoffset = decode_rl_address(emu);
1142197007Sdelphij		destval = fetch_data_byte(emu, destoffset);
1143197007Sdelphij	} else {
1144197007Sdelphij		destval = *decode_rl_byte_register(emu);
1145197007Sdelphij	}
1146197007Sdelphij	(*binop)(emu, destval, srcval);
1147197007Sdelphij}
1148197007Sdelphij
1149197007Sdelphijstatic void
1150204934Sdelphijcommon_binop_word_rm_r(struct x86emu *emu,
1151204934Sdelphij    uint16_t (*binop)(struct x86emu *, uint16_t, uint16_t))
1152197007Sdelphij{
1153197007Sdelphij	uint32_t destoffset;
1154197007Sdelphij	uint16_t destval, *destreg, srcval;
1155197007Sdelphij
1156197007Sdelphij	fetch_decode_modrm(emu);
1157197007Sdelphij	srcval = *decode_rh_word_register(emu);
1158197007Sdelphij	if (emu->cur_mod != 3) {
1159197007Sdelphij		destoffset = decode_rl_address(emu);
1160197007Sdelphij		destval = fetch_data_word(emu, destoffset);
1161197007Sdelphij		destval = (*binop)(emu, destval, srcval);
1162197007Sdelphij		store_data_word(emu, destoffset, destval);
1163197007Sdelphij	} else {
1164197007Sdelphij		destreg = decode_rl_word_register(emu);
1165197007Sdelphij		*destreg = (*binop)(emu, *destreg, srcval);
1166197007Sdelphij	}
1167197007Sdelphij}
1168197007Sdelphij
1169197007Sdelphijstatic void
1170204934Sdelphijcommon_binop_byte_r_rm(struct x86emu *emu,
1171204934Sdelphij    uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t))
1172197007Sdelphij{
1173197007Sdelphij	uint8_t *destreg, srcval;
1174197007Sdelphij	uint32_t srcoffset;
1175197007Sdelphij
1176197007Sdelphij	fetch_decode_modrm(emu);
1177197007Sdelphij	destreg = decode_rh_byte_register(emu);
1178197007Sdelphij	if (emu->cur_mod != 3) {
1179197007Sdelphij		srcoffset = decode_rl_address(emu);
1180197007Sdelphij		srcval = fetch_data_byte(emu, srcoffset);
1181197007Sdelphij	} else {
1182197007Sdelphij		srcval = *decode_rl_byte_register(emu);
1183197007Sdelphij	}
1184197007Sdelphij	*destreg = (*binop)(emu, *destreg, srcval);
1185197007Sdelphij}
1186197007Sdelphij
1187197007Sdelphijstatic void
1188204934Sdelphijcommon_binop_long_rm_r(struct x86emu *emu,
1189204934Sdelphij    uint32_t (*binop)(struct x86emu *, uint32_t, uint32_t))
1190197007Sdelphij{
1191197007Sdelphij	uint32_t destoffset;
1192197007Sdelphij	uint32_t destval, *destreg, srcval;
1193197007Sdelphij
1194197007Sdelphij	fetch_decode_modrm(emu);
1195197007Sdelphij	srcval = *decode_rh_long_register(emu);
1196197007Sdelphij	if (emu->cur_mod != 3) {
1197197007Sdelphij		destoffset = decode_rl_address(emu);
1198197007Sdelphij		destval = fetch_data_long(emu, destoffset);
1199197007Sdelphij		destval = (*binop)(emu, destval, srcval);
1200197007Sdelphij		store_data_long(emu, destoffset, destval);
1201197007Sdelphij	} else {
1202197007Sdelphij		destreg = decode_rl_long_register(emu);
1203197007Sdelphij		*destreg = (*binop)(emu, *destreg, srcval);
1204197007Sdelphij	}
1205197007Sdelphij}
1206197007Sdelphij
1207197007Sdelphijstatic void
1208197007Sdelphijcommon_binop_word_long_rm_r(struct x86emu *emu,
1209204934Sdelphij    uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t),
1210204934Sdelphij    uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t))
1211197007Sdelphij{
1212197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1213197007Sdelphij		common_binop_long_rm_r(emu, binop32);
1214197007Sdelphij	else
1215197007Sdelphij		common_binop_word_rm_r(emu, binop16);
1216197007Sdelphij}
1217197007Sdelphij
1218197007Sdelphijstatic void
1219204934Sdelphijcommon_binop_ns_word_rm_r(struct x86emu *emu,
1220204934Sdelphij    void (*binop)(struct x86emu *, uint16_t, uint16_t))
1221197007Sdelphij{
1222197007Sdelphij	uint32_t destoffset;
1223197007Sdelphij	uint16_t destval, srcval;
1224197007Sdelphij
1225197007Sdelphij	fetch_decode_modrm(emu);
1226197007Sdelphij	srcval = *decode_rh_word_register(emu);
1227197007Sdelphij	if (emu->cur_mod != 3) {
1228197007Sdelphij		destoffset = decode_rl_address(emu);
1229197007Sdelphij		destval = fetch_data_word(emu, destoffset);
1230197007Sdelphij	} else {
1231197007Sdelphij		destval = *decode_rl_word_register(emu);
1232197007Sdelphij	}
1233197007Sdelphij	(*binop)(emu, destval, srcval);
1234197007Sdelphij}
1235197007Sdelphij
1236197007Sdelphij
1237197007Sdelphijstatic void
1238204934Sdelphijcommon_binop_ns_long_rm_r(struct x86emu *emu,
1239204934Sdelphij    void (*binop)(struct x86emu *, uint32_t, uint32_t))
1240197007Sdelphij{
1241197007Sdelphij	uint32_t destoffset;
1242197007Sdelphij	uint32_t destval, srcval;
1243197007Sdelphij
1244197007Sdelphij	fetch_decode_modrm(emu);
1245197007Sdelphij	srcval = *decode_rh_long_register(emu);
1246197007Sdelphij	if (emu->cur_mod != 3) {
1247197007Sdelphij		destoffset = decode_rl_address(emu);
1248197007Sdelphij		destval = fetch_data_long(emu, destoffset);
1249197007Sdelphij	} else {
1250197007Sdelphij		destval = *decode_rl_long_register(emu);
1251197007Sdelphij	}
1252197007Sdelphij	(*binop)(emu, destval, srcval);
1253197007Sdelphij}
1254197007Sdelphij
1255197007Sdelphijstatic void
1256197007Sdelphijcommon_binop_ns_word_long_rm_r(struct x86emu *emu,
1257204934Sdelphij    void (*binop16)(struct x86emu *, uint16_t, uint16_t),
1258204934Sdelphij    void (*binop32)(struct x86emu *, uint32_t, uint32_t))
1259197007Sdelphij{
1260197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1261197007Sdelphij		common_binop_ns_long_rm_r(emu, binop32);
1262197007Sdelphij	else
1263197007Sdelphij		common_binop_ns_word_rm_r(emu, binop16);
1264197007Sdelphij}
1265197007Sdelphij
1266197007Sdelphijstatic void
1267204934Sdelphijcommon_binop_long_r_rm(struct x86emu *emu,
1268204934Sdelphij    uint32_t (*binop)(struct x86emu *, uint32_t, uint32_t))
1269197007Sdelphij{
1270197007Sdelphij	uint32_t srcoffset;
1271197007Sdelphij	uint32_t *destreg, srcval;
1272197007Sdelphij
1273197007Sdelphij	fetch_decode_modrm(emu);
1274197007Sdelphij	destreg = decode_rh_long_register(emu);
1275197007Sdelphij	if (emu->cur_mod != 3) {
1276197007Sdelphij		srcoffset = decode_rl_address(emu);
1277197007Sdelphij		srcval = fetch_data_long(emu, srcoffset);
1278197007Sdelphij	} else {
1279197007Sdelphij		srcval = *decode_rl_long_register(emu);
1280197007Sdelphij	}
1281197007Sdelphij	*destreg = (*binop)(emu, *destreg, srcval);
1282197007Sdelphij}
1283197007Sdelphij
1284197007Sdelphijstatic void
1285204934Sdelphijcommon_binop_word_r_rm(struct x86emu *emu,
1286204934Sdelphij    uint16_t (*binop)(struct x86emu *, uint16_t, uint16_t))
1287197007Sdelphij{
1288197007Sdelphij	uint32_t srcoffset;
1289197007Sdelphij	uint16_t *destreg, srcval;
1290197007Sdelphij
1291197007Sdelphij	fetch_decode_modrm(emu);
1292197007Sdelphij	destreg = decode_rh_word_register(emu);
1293197007Sdelphij	if (emu->cur_mod != 3) {
1294197007Sdelphij		srcoffset = decode_rl_address(emu);
1295197007Sdelphij		srcval = fetch_data_word(emu, srcoffset);
1296197007Sdelphij	} else {
1297197007Sdelphij		srcval = *decode_rl_word_register(emu);
1298197007Sdelphij	}
1299197007Sdelphij	*destreg = (*binop)(emu, *destreg, srcval);
1300197007Sdelphij}
1301197007Sdelphij
1302197007Sdelphijstatic void
1303197007Sdelphijcommon_binop_word_long_r_rm(struct x86emu *emu,
1304204934Sdelphij    uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t),
1305204934Sdelphij    uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t))
1306197007Sdelphij{
1307197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1308197007Sdelphij		common_binop_long_r_rm(emu, binop32);
1309197007Sdelphij	else
1310197007Sdelphij		common_binop_word_r_rm(emu, binop16);
1311197007Sdelphij}
1312197007Sdelphij
1313197007Sdelphijstatic void
1314204934Sdelphijcommon_binop_byte_imm(struct x86emu *emu,
1315204934Sdelphij    uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t))
1316197007Sdelphij{
1317197007Sdelphij	uint8_t srcval;
1318197007Sdelphij
1319197007Sdelphij	srcval = fetch_byte_imm(emu);
1320197007Sdelphij	emu->x86.R_AL = (*binop)(emu, emu->x86.R_AL, srcval);
1321197007Sdelphij}
1322197007Sdelphij
1323197007Sdelphijstatic void
1324197007Sdelphijcommon_binop_word_long_imm(struct x86emu *emu,
1325204934Sdelphij    uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t),
1326204934Sdelphij    uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t))
1327197007Sdelphij{
1328197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1329197007Sdelphij		uint32_t srcval;
1330197007Sdelphij
1331197007Sdelphij		srcval = fetch_long_imm(emu);
1332197007Sdelphij		emu->x86.R_EAX = (*binop32)(emu, emu->x86.R_EAX, srcval);
1333197007Sdelphij	} else {
1334197007Sdelphij		uint16_t srcval;
1335197007Sdelphij
1336197007Sdelphij		srcval = fetch_word_imm(emu);
1337197007Sdelphij		emu->x86.R_AX = (*binop16)(emu, emu->x86.R_AX, srcval);
1338197007Sdelphij	}
1339197007Sdelphij}
1340197007Sdelphij
1341197007Sdelphijstatic void
1342197007Sdelphijcommon_push_word_long(struct x86emu *emu, union x86emu_register *reg)
1343197007Sdelphij{
1344197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1345197007Sdelphij		push_long(emu, reg->I32_reg.e_reg);
1346197007Sdelphij	else
1347197007Sdelphij		push_word(emu, reg->I16_reg.x_reg);
1348197007Sdelphij}
1349197007Sdelphij
1350197007Sdelphijstatic void
1351197007Sdelphijcommon_pop_word_long(struct x86emu *emu, union x86emu_register *reg)
1352197007Sdelphij{
1353197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1354197007Sdelphij		reg->I32_reg.e_reg = pop_long(emu);
1355197007Sdelphij	else
1356197007Sdelphij		reg->I16_reg.x_reg = pop_word(emu);
1357197007Sdelphij}
1358197007Sdelphij
1359197007Sdelphijstatic void
1360197007Sdelphijcommon_imul_long_IMM(struct x86emu *emu, int byte_imm)
1361197007Sdelphij{
1362197007Sdelphij	uint32_t srcoffset;
1363197007Sdelphij	uint32_t *destreg, srcval;
1364197007Sdelphij	int32_t imm;
1365197007Sdelphij	uint64_t res;
1366197007Sdelphij
1367197007Sdelphij	fetch_decode_modrm(emu);
1368197007Sdelphij	destreg = decode_rh_long_register(emu);
1369197007Sdelphij	if (emu->cur_mod != 3) {
1370197007Sdelphij		srcoffset = decode_rl_address(emu);
1371197007Sdelphij		srcval = fetch_data_long(emu, srcoffset);
1372197007Sdelphij	} else {
1373197007Sdelphij		srcval = *decode_rl_long_register(emu);
1374197007Sdelphij	}
1375197007Sdelphij
1376197007Sdelphij	if (byte_imm)
1377197007Sdelphij		imm = (int8_t)fetch_byte_imm(emu);
1378197007Sdelphij	else
1379197007Sdelphij		imm = fetch_long_imm(emu);
1380197007Sdelphij	res = (int32_t)srcval * imm;
1381197007Sdelphij
1382197007Sdelphij	if (res > 0xffffffff) {
1383197007Sdelphij		SET_FLAG(F_CF);
1384197007Sdelphij		SET_FLAG(F_OF);
1385197007Sdelphij	} else {
1386197007Sdelphij		CLEAR_FLAG(F_CF);
1387197007Sdelphij		CLEAR_FLAG(F_OF);
1388197007Sdelphij	}
1389197007Sdelphij	*destreg = (uint32_t)res;
1390197007Sdelphij}
1391197007Sdelphij
1392197007Sdelphijstatic void
1393197007Sdelphijcommon_imul_word_IMM(struct x86emu *emu, int byte_imm)
1394197007Sdelphij{
1395197007Sdelphij	uint32_t srcoffset;
1396197007Sdelphij	uint16_t *destreg, srcval;
1397197007Sdelphij	int16_t imm;
1398197007Sdelphij	uint32_t res;
1399197007Sdelphij
1400197007Sdelphij	fetch_decode_modrm(emu);
1401197007Sdelphij	destreg = decode_rh_word_register(emu);
1402197007Sdelphij	if (emu->cur_mod != 3) {
1403197007Sdelphij		srcoffset = decode_rl_address(emu);
1404197007Sdelphij		srcval = fetch_data_word(emu, srcoffset);
1405197007Sdelphij	} else {
1406197007Sdelphij		srcval = *decode_rl_word_register(emu);
1407197007Sdelphij	}
1408197007Sdelphij
1409197007Sdelphij	if (byte_imm)
1410197007Sdelphij		imm = (int8_t)fetch_byte_imm(emu);
1411197007Sdelphij	else
1412197007Sdelphij		imm = fetch_word_imm(emu);
1413197007Sdelphij	res = (int16_t)srcval * imm;
1414197007Sdelphij
1415197007Sdelphij	if (res > 0xffff) {
1416197007Sdelphij		SET_FLAG(F_CF);
1417197007Sdelphij		SET_FLAG(F_OF);
1418197007Sdelphij	} else {
1419197007Sdelphij		CLEAR_FLAG(F_CF);
1420197007Sdelphij		CLEAR_FLAG(F_OF);
1421197007Sdelphij	}
1422197007Sdelphij	*destreg = (uint16_t) res;
1423197007Sdelphij}
1424197007Sdelphij
1425197007Sdelphijstatic void
1426197007Sdelphijcommon_imul_imm(struct x86emu *emu, int byte_imm)
1427197007Sdelphij{
1428197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1429197007Sdelphij		common_imul_long_IMM(emu, byte_imm);
1430197007Sdelphij	else
1431197007Sdelphij		common_imul_word_IMM(emu, byte_imm);
1432197007Sdelphij}
1433197007Sdelphij
1434197007Sdelphijstatic void
1435197007Sdelphijcommon_jmp_near(struct x86emu *emu, int cond)
1436197007Sdelphij{
1437197007Sdelphij	int8_t offset;
1438197007Sdelphij	uint16_t target;
1439197007Sdelphij
1440197007Sdelphij	offset = (int8_t) fetch_byte_imm(emu);
1441197007Sdelphij	target = (uint16_t) (emu->x86.R_IP + (int16_t) offset);
1442197007Sdelphij	if (cond)
1443197007Sdelphij		emu->x86.R_IP = target;
1444197007Sdelphij}
1445197007Sdelphij
1446197007Sdelphijstatic void
1447197007Sdelphijcommon_load_far_pointer(struct x86emu *emu, uint16_t *seg)
1448197007Sdelphij{
1449197007Sdelphij	uint16_t *dstreg;
1450197007Sdelphij	uint32_t srcoffset;
1451197007Sdelphij
1452197007Sdelphij	fetch_decode_modrm(emu);
1453197007Sdelphij	if (emu->cur_mod == 3)
1454197007Sdelphij		x86emu_halt_sys(emu);
1455197007Sdelphij
1456197007Sdelphij	dstreg = decode_rh_word_register(emu);
1457197007Sdelphij	srcoffset = decode_rl_address(emu);
1458197007Sdelphij	*dstreg = fetch_data_word(emu, srcoffset);
1459197007Sdelphij	*seg = fetch_data_word(emu, srcoffset + 2);
1460197007Sdelphij}
1461197007Sdelphij
1462197007Sdelphij/* Implementation */
1463197007Sdelphij
1464197007Sdelphij/*
1465197007Sdelphij * REMARKS:
1466197007Sdelphij * Handles opcode 0x3a
1467197007Sdelphij */
1468197007Sdelphijstatic void
1469197007Sdelphijx86emuOp_cmp_byte_R_RM(struct x86emu *emu)
1470197007Sdelphij{
1471197007Sdelphij	uint8_t *destreg, srcval;
1472197007Sdelphij
1473197007Sdelphij	fetch_decode_modrm(emu);
1474197007Sdelphij	destreg = decode_rh_byte_register(emu);
1475197007Sdelphij	srcval = decode_and_fetch_byte(emu);
1476197007Sdelphij	cmp_byte(emu, *destreg, srcval);
1477197007Sdelphij}
1478197007Sdelphij
1479197007Sdelphij/*
1480197007Sdelphij * REMARKS:
1481197007Sdelphij *
1482197007Sdelphij * Handles opcode 0x3b
1483197007Sdelphij */
1484197007Sdelphijstatic void
1485197007Sdelphijx86emuOp32_cmp_word_R_RM(struct x86emu *emu)
1486197007Sdelphij{
1487197007Sdelphij	uint32_t srcval, *destreg;
1488197007Sdelphij
1489197007Sdelphij	fetch_decode_modrm(emu);
1490197007Sdelphij	destreg = decode_rh_long_register(emu);
1491197007Sdelphij	srcval = decode_and_fetch_long(emu);
1492197007Sdelphij	cmp_long(emu, *destreg, srcval);
1493197007Sdelphij}
1494197007Sdelphij
1495197007Sdelphijstatic void
1496197007Sdelphijx86emuOp16_cmp_word_R_RM(struct x86emu *emu)
1497197007Sdelphij{
1498197007Sdelphij	uint16_t srcval, *destreg;
1499197007Sdelphij
1500197007Sdelphij	fetch_decode_modrm(emu);
1501197007Sdelphij	destreg = decode_rh_word_register(emu);
1502197007Sdelphij	srcval = decode_and_fetch_word(emu);
1503197007Sdelphij	cmp_word(emu, *destreg, srcval);
1504197007Sdelphij}
1505197007Sdelphij
1506197007Sdelphijstatic void
1507197007Sdelphijx86emuOp_cmp_word_R_RM(struct x86emu *emu)
1508197007Sdelphij{
1509197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1510197007Sdelphij		x86emuOp32_cmp_word_R_RM(emu);
1511197007Sdelphij	else
1512197007Sdelphij		x86emuOp16_cmp_word_R_RM(emu);
1513197007Sdelphij}
1514197007Sdelphij
1515197007Sdelphij/*
1516197007Sdelphij * REMARKS:
1517197007Sdelphij * Handles opcode 0x3c
1518197007Sdelphij */
1519197007Sdelphijstatic void
1520197007Sdelphijx86emuOp_cmp_byte_AL_IMM(struct x86emu *emu)
1521197007Sdelphij{
1522197007Sdelphij	uint8_t srcval;
1523197007Sdelphij
1524197007Sdelphij	srcval = fetch_byte_imm(emu);
1525197007Sdelphij	cmp_byte(emu, emu->x86.R_AL, srcval);
1526197007Sdelphij}
1527197007Sdelphij
1528197007Sdelphij/*
1529197007Sdelphij * REMARKS:
1530197007Sdelphij * Handles opcode 0x3d
1531197007Sdelphij */
1532197007Sdelphijstatic void
1533197007Sdelphijx86emuOp32_cmp_word_AX_IMM(struct x86emu *emu)
1534197007Sdelphij{
1535197007Sdelphij	uint32_t srcval;
1536197007Sdelphij
1537197007Sdelphij	srcval = fetch_long_imm(emu);
1538197007Sdelphij	cmp_long(emu, emu->x86.R_EAX, srcval);
1539197007Sdelphij}
1540197007Sdelphij
1541197007Sdelphijstatic void
1542197007Sdelphijx86emuOp16_cmp_word_AX_IMM(struct x86emu *emu)
1543197007Sdelphij{
1544197007Sdelphij	uint16_t srcval;
1545197007Sdelphij
1546197007Sdelphij	srcval = fetch_word_imm(emu);
1547197007Sdelphij	cmp_word(emu, emu->x86.R_AX, srcval);
1548197007Sdelphij}
1549197007Sdelphij
1550197007Sdelphijstatic void
1551197007Sdelphijx86emuOp_cmp_word_AX_IMM(struct x86emu *emu)
1552197007Sdelphij{
1553197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1554197007Sdelphij		x86emuOp32_cmp_word_AX_IMM(emu);
1555197007Sdelphij	else
1556197007Sdelphij		x86emuOp16_cmp_word_AX_IMM(emu);
1557197007Sdelphij}
1558197007Sdelphij
1559197007Sdelphij/*
1560197007Sdelphij * REMARKS:
1561197007Sdelphij * Handles opcode 0x60
1562197007Sdelphij */
1563197007Sdelphijstatic void
1564197007Sdelphijx86emuOp_push_all(struct x86emu *emu)
1565197007Sdelphij{
1566197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1567197007Sdelphij		uint32_t old_sp = emu->x86.R_ESP;
1568197007Sdelphij
1569197007Sdelphij		push_long(emu, emu->x86.R_EAX);
1570197007Sdelphij		push_long(emu, emu->x86.R_ECX);
1571197007Sdelphij		push_long(emu, emu->x86.R_EDX);
1572197007Sdelphij		push_long(emu, emu->x86.R_EBX);
1573197007Sdelphij		push_long(emu, old_sp);
1574197007Sdelphij		push_long(emu, emu->x86.R_EBP);
1575197007Sdelphij		push_long(emu, emu->x86.R_ESI);
1576197007Sdelphij		push_long(emu, emu->x86.R_EDI);
1577197007Sdelphij	} else {
1578197007Sdelphij		uint16_t old_sp = emu->x86.R_SP;
1579197007Sdelphij
1580197007Sdelphij		push_word(emu, emu->x86.R_AX);
1581197007Sdelphij		push_word(emu, emu->x86.R_CX);
1582197007Sdelphij		push_word(emu, emu->x86.R_DX);
1583197007Sdelphij		push_word(emu, emu->x86.R_BX);
1584197007Sdelphij		push_word(emu, old_sp);
1585197007Sdelphij		push_word(emu, emu->x86.R_BP);
1586197007Sdelphij		push_word(emu, emu->x86.R_SI);
1587197007Sdelphij		push_word(emu, emu->x86.R_DI);
1588197007Sdelphij	}
1589197007Sdelphij}
1590197007Sdelphij
1591197007Sdelphij/*
1592197007Sdelphij * REMARKS:
1593197007Sdelphij * Handles opcode 0x61
1594197007Sdelphij */
1595197007Sdelphijstatic void
1596197007Sdelphijx86emuOp_pop_all(struct x86emu *emu)
1597197007Sdelphij{
1598197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1599197007Sdelphij		emu->x86.R_EDI = pop_long(emu);
1600197007Sdelphij		emu->x86.R_ESI = pop_long(emu);
1601197007Sdelphij		emu->x86.R_EBP = pop_long(emu);
1602197007Sdelphij		emu->x86.R_ESP += 4;	/* skip ESP */
1603197007Sdelphij		emu->x86.R_EBX = pop_long(emu);
1604197007Sdelphij		emu->x86.R_EDX = pop_long(emu);
1605197007Sdelphij		emu->x86.R_ECX = pop_long(emu);
1606197007Sdelphij		emu->x86.R_EAX = pop_long(emu);
1607197007Sdelphij	} else {
1608197007Sdelphij		emu->x86.R_DI = pop_word(emu);
1609197007Sdelphij		emu->x86.R_SI = pop_word(emu);
1610197007Sdelphij		emu->x86.R_BP = pop_word(emu);
1611197007Sdelphij		emu->x86.R_SP += 2;/* skip SP */
1612197007Sdelphij		emu->x86.R_BX = pop_word(emu);
1613197007Sdelphij		emu->x86.R_DX = pop_word(emu);
1614197007Sdelphij		emu->x86.R_CX = pop_word(emu);
1615197007Sdelphij		emu->x86.R_AX = pop_word(emu);
1616197007Sdelphij	}
1617197007Sdelphij}
1618197007Sdelphij/*opcode 0x62   ILLEGAL OP, calls x86emuOp_illegal_op() */
1619197007Sdelphij/*opcode 0x63   ILLEGAL OP, calls x86emuOp_illegal_op() */
1620197007Sdelphij
1621197007Sdelphij
1622197007Sdelphij/*
1623197007Sdelphij * REMARKS:
1624197007Sdelphij * Handles opcode 0x68
1625197007Sdelphij */
1626197007Sdelphijstatic void
1627197007Sdelphijx86emuOp_push_word_IMM(struct x86emu *emu)
1628197007Sdelphij{
1629197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1630197007Sdelphij		uint32_t imm;
1631197007Sdelphij
1632197007Sdelphij		imm = fetch_long_imm(emu);
1633197007Sdelphij		push_long(emu, imm);
1634197007Sdelphij	} else {
1635197007Sdelphij		uint16_t imm;
1636197007Sdelphij
1637197007Sdelphij		imm = fetch_word_imm(emu);
1638197007Sdelphij		push_word(emu, imm);
1639197007Sdelphij	}
1640197007Sdelphij}
1641197007Sdelphij
1642197007Sdelphij/*
1643197007Sdelphij * REMARKS:
1644197007Sdelphij * Handles opcode 0x6a
1645197007Sdelphij */
1646197007Sdelphijstatic void
1647197007Sdelphijx86emuOp_push_byte_IMM(struct x86emu *emu)
1648197007Sdelphij{
1649197007Sdelphij	int16_t imm;
1650197007Sdelphij
1651197007Sdelphij	imm = (int8_t) fetch_byte_imm(emu);
1652197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1653197007Sdelphij		push_long(emu, (int32_t) imm);
1654197007Sdelphij	} else {
1655197007Sdelphij		push_word(emu, imm);
1656197007Sdelphij	}
1657197007Sdelphij}
1658197007Sdelphij
1659197007Sdelphij/*
1660197007Sdelphij * REMARKS:
1661197007Sdelphij * Handles opcode 0x6c and 0x6d
1662197007Sdelphij */
1663197007Sdelphijstatic void
1664197007Sdelphijx86emuOp_ins_word(struct x86emu *emu)
1665197007Sdelphij{
1666197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1667197007Sdelphij		ins(emu, 4);
1668197007Sdelphij	} else {
1669197007Sdelphij		ins(emu, 2);
1670197007Sdelphij	}
1671197007Sdelphij}
1672197007Sdelphij
1673197007Sdelphij/*
1674197007Sdelphij * REMARKS:
1675197007Sdelphij * Handles opcode 0x6f
1676197007Sdelphij */
1677197007Sdelphijstatic void
1678197007Sdelphijx86emuOp_outs_word(struct x86emu *emu)
1679197007Sdelphij{
1680197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1681197007Sdelphij		outs(emu, 4);
1682197007Sdelphij	} else {
1683197007Sdelphij		outs(emu, 2);
1684197007Sdelphij	}
1685197007Sdelphij}
1686197007Sdelphij
1687197007Sdelphij/*
1688197007Sdelphij * REMARKS:
1689197007Sdelphij * Handles opcode 0x7c
1690197007Sdelphij */
1691197007Sdelphijstatic void
1692197007Sdelphijx86emuOp_jump_near_L(struct x86emu *emu)
1693197007Sdelphij{
1694197007Sdelphij	int sf, of;
1695197007Sdelphij
1696197007Sdelphij	sf = ACCESS_FLAG(F_SF) != 0;
1697197007Sdelphij	of = ACCESS_FLAG(F_OF) != 0;
1698197007Sdelphij
1699197007Sdelphij	common_jmp_near(emu, sf != of);
1700197007Sdelphij}
1701197007Sdelphij
1702197007Sdelphij/*
1703197007Sdelphij * REMARKS:
1704197007Sdelphij * Handles opcode 0x7d
1705197007Sdelphij */
1706197007Sdelphijstatic void
1707197007Sdelphijx86emuOp_jump_near_NL(struct x86emu *emu)
1708197007Sdelphij{
1709197007Sdelphij	int sf, of;
1710197007Sdelphij
1711197007Sdelphij	sf = ACCESS_FLAG(F_SF) != 0;
1712197007Sdelphij	of = ACCESS_FLAG(F_OF) != 0;
1713197007Sdelphij
1714197007Sdelphij	common_jmp_near(emu, sf == of);
1715197007Sdelphij}
1716197007Sdelphij
1717197007Sdelphij/*
1718197007Sdelphij * REMARKS:
1719197007Sdelphij * Handles opcode 0x7e
1720197007Sdelphij */
1721197007Sdelphijstatic void
1722197007Sdelphijx86emuOp_jump_near_LE(struct x86emu *emu)
1723197007Sdelphij{
1724197007Sdelphij	int sf, of;
1725197007Sdelphij
1726197007Sdelphij	sf = ACCESS_FLAG(F_SF) != 0;
1727197007Sdelphij	of = ACCESS_FLAG(F_OF) != 0;
1728197007Sdelphij
1729197007Sdelphij	common_jmp_near(emu, sf != of || ACCESS_FLAG(F_ZF));
1730197007Sdelphij}
1731197007Sdelphij
1732197007Sdelphij/*
1733197007Sdelphij * REMARKS:
1734197007Sdelphij * Handles opcode 0x7f
1735197007Sdelphij */
1736197007Sdelphijstatic void
1737197007Sdelphijx86emuOp_jump_near_NLE(struct x86emu *emu)
1738197007Sdelphij{
1739197007Sdelphij	int sf, of;
1740197007Sdelphij
1741197007Sdelphij	sf = ACCESS_FLAG(F_SF) != 0;
1742197007Sdelphij	of = ACCESS_FLAG(F_OF) != 0;
1743197007Sdelphij
1744197007Sdelphij	common_jmp_near(emu, sf == of && !ACCESS_FLAG(F_ZF));
1745197007Sdelphij}
1746197007Sdelphij
1747197007Sdelphijstatic
1748197007Sdelphijuint8_t(*const opc80_byte_operation[]) (struct x86emu *, uint8_t d, uint8_t s) =
1749197007Sdelphij{
1750197007Sdelphij	add_byte,		/* 00 */
1751197007Sdelphij	or_byte,		/* 01 */
1752197007Sdelphij	adc_byte,		/* 02 */
1753197007Sdelphij	sbb_byte,		/* 03 */
1754197007Sdelphij	and_byte,		/* 04 */
1755197007Sdelphij	sub_byte,		/* 05 */
1756197007Sdelphij	xor_byte,		/* 06 */
1757197007Sdelphij	cmp_byte,		/* 07 */
1758197007Sdelphij};
1759197007Sdelphij
1760197007Sdelphij/*
1761197007Sdelphij * REMARKS:
1762197007Sdelphij * Handles opcode 0x80
1763197007Sdelphij */
1764197007Sdelphijstatic void
1765197007Sdelphijx86emuOp_opc80_byte_RM_IMM(struct x86emu *emu)
1766197007Sdelphij{
1767197007Sdelphij	uint8_t imm, destval;
1768197007Sdelphij
1769197007Sdelphij	/*
1770197007Sdelphij         * Weirdo special case instruction format.  Part of the opcode
1771197007Sdelphij         * held below in "RH".  Doubly nested case would result, except
1772197007Sdelphij         * that the decoded instruction
1773197007Sdelphij         */
1774197007Sdelphij	fetch_decode_modrm(emu);
1775197007Sdelphij	destval = decode_and_fetch_byte(emu);
1776197007Sdelphij	imm = fetch_byte_imm(emu);
1777197007Sdelphij	destval = (*opc80_byte_operation[emu->cur_rh]) (emu, destval, imm);
1778197007Sdelphij	if (emu->cur_rh != 7)
1779197007Sdelphij		write_back_byte(emu, destval);
1780197007Sdelphij}
1781197007Sdelphij
1782197007Sdelphijstatic
1783204934Sdelphijuint16_t(* const opc81_word_operation[])
1784204934Sdelphij    (struct x86emu *, uint16_t d, uint16_t s) =
1785197007Sdelphij{
1786197007Sdelphij	add_word,		/* 00 */
1787197007Sdelphij	or_word,		/* 01 */
1788197007Sdelphij	adc_word,		/* 02 */
1789197007Sdelphij	sbb_word,		/* 03 */
1790197007Sdelphij	and_word,		/* 04 */
1791197007Sdelphij	sub_word,		/* 05 */
1792197007Sdelphij	xor_word,		/* 06 */
1793197007Sdelphij	cmp_word,		/* 07 */
1794197007Sdelphij};
1795197007Sdelphij
1796197007Sdelphijstatic
1797204934Sdelphijuint32_t(* const opc81_long_operation[])
1798204934Sdelphij    (struct x86emu *, uint32_t d, uint32_t s) =
1799197007Sdelphij{
1800197007Sdelphij	add_long,		/* 00 */
1801197007Sdelphij	or_long,		/* 01 */
1802197007Sdelphij	adc_long,		/* 02 */
1803197007Sdelphij	sbb_long,		/* 03 */
1804197007Sdelphij	and_long,		/* 04 */
1805197007Sdelphij	sub_long,		/* 05 */
1806197007Sdelphij	xor_long,		/* 06 */
1807197007Sdelphij	cmp_long,		/* 07 */
1808197007Sdelphij};
1809197007Sdelphij
1810197007Sdelphij/*
1811197007Sdelphij * REMARKS:
1812197007Sdelphij * Handles opcode 0x81
1813197007Sdelphij */
1814197007Sdelphijstatic void
1815197007Sdelphijx86emuOp32_opc81_word_RM_IMM(struct x86emu *emu)
1816197007Sdelphij{
1817197007Sdelphij	uint32_t destval, imm;
1818197007Sdelphij
1819197007Sdelphij	/*
1820197007Sdelphij         * Weirdo special case instruction format.  Part of the opcode
1821197007Sdelphij         * held below in "RH".  Doubly nested case would result, except
1822197007Sdelphij         * that the decoded instruction
1823197007Sdelphij         */
1824197007Sdelphij	fetch_decode_modrm(emu);
1825197007Sdelphij	destval = decode_and_fetch_long(emu);
1826197007Sdelphij	imm = fetch_long_imm(emu);
1827197007Sdelphij	destval = (*opc81_long_operation[emu->cur_rh]) (emu, destval, imm);
1828197007Sdelphij	if (emu->cur_rh != 7)
1829197007Sdelphij		write_back_long(emu, destval);
1830197007Sdelphij}
1831197007Sdelphij
1832197007Sdelphijstatic void
1833197007Sdelphijx86emuOp16_opc81_word_RM_IMM(struct x86emu *emu)
1834197007Sdelphij{
1835197007Sdelphij	uint16_t destval, imm;
1836197007Sdelphij
1837197007Sdelphij	/*
1838197007Sdelphij         * Weirdo special case instruction format.  Part of the opcode
1839197007Sdelphij         * held below in "RH".  Doubly nested case would result, except
1840197007Sdelphij         * that the decoded instruction
1841197007Sdelphij         */
1842197007Sdelphij	fetch_decode_modrm(emu);
1843197007Sdelphij	destval = decode_and_fetch_word(emu);
1844197007Sdelphij	imm = fetch_word_imm(emu);
1845197007Sdelphij	destval = (*opc81_word_operation[emu->cur_rh]) (emu, destval, imm);
1846197007Sdelphij	if (emu->cur_rh != 7)
1847197007Sdelphij		write_back_word(emu, destval);
1848197007Sdelphij}
1849197007Sdelphij
1850197007Sdelphijstatic void
1851197007Sdelphijx86emuOp_opc81_word_RM_IMM(struct x86emu *emu)
1852197007Sdelphij{
1853197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1854197007Sdelphij		x86emuOp32_opc81_word_RM_IMM(emu);
1855197007Sdelphij	else
1856197007Sdelphij		x86emuOp16_opc81_word_RM_IMM(emu);
1857197007Sdelphij}
1858197007Sdelphij
1859197007Sdelphijstatic
1860204934Sdelphijuint8_t(* const opc82_byte_operation[])
1861204934Sdelphij    (struct x86emu *, uint8_t s, uint8_t d) =
1862197007Sdelphij{
1863197007Sdelphij	add_byte,		/* 00 */
1864197007Sdelphij	or_byte,		/* 01 *//* YYY UNUSED ???? */
1865197007Sdelphij	adc_byte,		/* 02 */
1866197007Sdelphij	sbb_byte,		/* 03 */
1867197007Sdelphij	and_byte,		/* 04 *//* YYY UNUSED ???? */
1868197007Sdelphij	sub_byte,		/* 05 */
1869197007Sdelphij	xor_byte,		/* 06 *//* YYY UNUSED ???? */
1870197007Sdelphij	cmp_byte,		/* 07 */
1871197007Sdelphij};
1872197007Sdelphij
1873197007Sdelphij/*
1874197007Sdelphij * REMARKS:
1875197007Sdelphij * Handles opcode 0x82
1876197007Sdelphij */
1877197007Sdelphijstatic void
1878197007Sdelphijx86emuOp_opc82_byte_RM_IMM(struct x86emu *emu)
1879197007Sdelphij{
1880197007Sdelphij	uint8_t imm, destval;
1881197007Sdelphij
1882197007Sdelphij	/*
1883197007Sdelphij         * Weirdo special case instruction format.  Part of the opcode
1884197007Sdelphij         * held below in "RH".  Doubly nested case would result, except
1885197007Sdelphij         * that the decoded instruction Similar to opcode 81, except that
1886197007Sdelphij         * the immediate byte is sign extended to a word length.
1887197007Sdelphij         */
1888197007Sdelphij	fetch_decode_modrm(emu);
1889197007Sdelphij	destval = decode_and_fetch_byte(emu);
1890197007Sdelphij	imm = fetch_byte_imm(emu);
1891197007Sdelphij	destval = (*opc82_byte_operation[emu->cur_rh]) (emu, destval, imm);
1892197007Sdelphij	if (emu->cur_rh != 7)
1893197007Sdelphij		write_back_byte(emu, destval);
1894197007Sdelphij}
1895197007Sdelphij
1896197007Sdelphijstatic
1897204934Sdelphijuint16_t(* const opc83_word_operation[])
1898204934Sdelphij    (struct x86emu *, uint16_t s, uint16_t d) =
1899197007Sdelphij{
1900197007Sdelphij	add_word,		/* 00 */
1901197007Sdelphij	or_word,		/* 01 *//* YYY UNUSED ???? */
1902197007Sdelphij	adc_word,		/* 02 */
1903197007Sdelphij	sbb_word,		/* 03 */
1904197007Sdelphij	and_word,		/* 04 *//* YYY UNUSED ???? */
1905197007Sdelphij	sub_word,		/* 05 */
1906197007Sdelphij	xor_word,		/* 06 *//* YYY UNUSED ???? */
1907197007Sdelphij	cmp_word,		/* 07 */
1908197007Sdelphij};
1909197007Sdelphij
1910197007Sdelphijstatic
1911204934Sdelphijuint32_t(* const opc83_long_operation[])
1912204934Sdelphij    (struct x86emu *, uint32_t s, uint32_t d) =
1913197007Sdelphij{
1914197007Sdelphij	add_long,		/* 00 */
1915197007Sdelphij	or_long,		/* 01 *//* YYY UNUSED ???? */
1916197007Sdelphij	adc_long,		/* 02 */
1917197007Sdelphij	sbb_long,		/* 03 */
1918197007Sdelphij	and_long,		/* 04 *//* YYY UNUSED ???? */
1919197007Sdelphij	sub_long,		/* 05 */
1920197007Sdelphij	xor_long,		/* 06 *//* YYY UNUSED ???? */
1921197007Sdelphij	cmp_long,		/* 07 */
1922197007Sdelphij};
1923197007Sdelphij
1924197007Sdelphij/*
1925197007Sdelphij * REMARKS:
1926197007Sdelphij * Handles opcode 0x83
1927197007Sdelphij */
1928197007Sdelphijstatic void
1929197007Sdelphijx86emuOp32_opc83_word_RM_IMM(struct x86emu *emu)
1930197007Sdelphij{
1931197007Sdelphij	uint32_t destval, imm;
1932197007Sdelphij
1933197007Sdelphij	fetch_decode_modrm(emu);
1934197007Sdelphij	destval = decode_and_fetch_long(emu);
1935197007Sdelphij	imm = (int8_t) fetch_byte_imm(emu);
1936197007Sdelphij	destval = (*opc83_long_operation[emu->cur_rh]) (emu, destval, imm);
1937197007Sdelphij	if (emu->cur_rh != 7)
1938197007Sdelphij		write_back_long(emu, destval);
1939197007Sdelphij}
1940197007Sdelphij
1941197007Sdelphijstatic void
1942197007Sdelphijx86emuOp16_opc83_word_RM_IMM(struct x86emu *emu)
1943197007Sdelphij{
1944197007Sdelphij	uint16_t destval, imm;
1945197007Sdelphij
1946197007Sdelphij	fetch_decode_modrm(emu);
1947197007Sdelphij	destval = decode_and_fetch_word(emu);
1948197007Sdelphij	imm = (int8_t) fetch_byte_imm(emu);
1949197007Sdelphij	destval = (*opc83_word_operation[emu->cur_rh]) (emu, destval, imm);
1950197007Sdelphij	if (emu->cur_rh != 7)
1951197007Sdelphij		write_back_word(emu, destval);
1952197007Sdelphij}
1953197007Sdelphij
1954197007Sdelphijstatic void
1955197007Sdelphijx86emuOp_opc83_word_RM_IMM(struct x86emu *emu)
1956197007Sdelphij{
1957197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1958197007Sdelphij		x86emuOp32_opc83_word_RM_IMM(emu);
1959197007Sdelphij	else
1960197007Sdelphij		x86emuOp16_opc83_word_RM_IMM(emu);
1961197007Sdelphij}
1962197007Sdelphij
1963197007Sdelphij/*
1964197007Sdelphij * REMARKS:
1965197007Sdelphij * Handles opcode 0x86
1966197007Sdelphij */
1967197007Sdelphijstatic void
1968197007Sdelphijx86emuOp_xchg_byte_RM_R(struct x86emu *emu)
1969197007Sdelphij{
1970197007Sdelphij	uint8_t *srcreg, destval, tmp;
1971197007Sdelphij
1972197007Sdelphij	fetch_decode_modrm(emu);
1973197007Sdelphij	destval = decode_and_fetch_byte(emu);
1974197007Sdelphij	srcreg = decode_rh_byte_register(emu);
1975197007Sdelphij	tmp = destval;
1976197007Sdelphij	destval = *srcreg;
1977197007Sdelphij	*srcreg = tmp;
1978197007Sdelphij	write_back_byte(emu, destval);
1979197007Sdelphij}
1980197007Sdelphij
1981197007Sdelphij/*
1982197007Sdelphij * REMARKS:
1983197007Sdelphij * Handles opcode 0x87
1984197007Sdelphij */
1985197007Sdelphijstatic void
1986197007Sdelphijx86emuOp32_xchg_word_RM_R(struct x86emu *emu)
1987197007Sdelphij{
1988197007Sdelphij	uint32_t *srcreg, destval, tmp;
1989197007Sdelphij
1990197007Sdelphij	fetch_decode_modrm(emu);
1991197007Sdelphij	destval = decode_and_fetch_long(emu);
1992197007Sdelphij	srcreg = decode_rh_long_register(emu);
1993197007Sdelphij	tmp = destval;
1994197007Sdelphij	destval = *srcreg;
1995197007Sdelphij	*srcreg = tmp;
1996197007Sdelphij	write_back_long(emu, destval);
1997197007Sdelphij}
1998197007Sdelphij
1999197007Sdelphijstatic void
2000197007Sdelphijx86emuOp16_xchg_word_RM_R(struct x86emu *emu)
2001197007Sdelphij{
2002197007Sdelphij	uint16_t *srcreg, destval, tmp;
2003197007Sdelphij
2004197007Sdelphij	fetch_decode_modrm(emu);
2005197007Sdelphij	destval = decode_and_fetch_word(emu);
2006197007Sdelphij	srcreg = decode_rh_word_register(emu);
2007197007Sdelphij	tmp = destval;
2008197007Sdelphij	destval = *srcreg;
2009197007Sdelphij	*srcreg = tmp;
2010197007Sdelphij	write_back_word(emu, destval);
2011197007Sdelphij}
2012197007Sdelphij
2013197007Sdelphijstatic void
2014197007Sdelphijx86emuOp_xchg_word_RM_R(struct x86emu *emu)
2015197007Sdelphij{
2016197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2017197007Sdelphij		x86emuOp32_xchg_word_RM_R(emu);
2018197007Sdelphij	else
2019197007Sdelphij		x86emuOp16_xchg_word_RM_R(emu);
2020197007Sdelphij}
2021197007Sdelphij
2022197007Sdelphij/*
2023197007Sdelphij * REMARKS:
2024197007Sdelphij * Handles opcode 0x88
2025197007Sdelphij */
2026197007Sdelphijstatic void
2027197007Sdelphijx86emuOp_mov_byte_RM_R(struct x86emu *emu)
2028197007Sdelphij{
2029197007Sdelphij	uint8_t *destreg, *srcreg;
2030197007Sdelphij	uint32_t destoffset;
2031197007Sdelphij
2032197007Sdelphij	fetch_decode_modrm(emu);
2033197007Sdelphij	srcreg = decode_rh_byte_register(emu);
2034197007Sdelphij	if (emu->cur_mod != 3) {
2035197007Sdelphij		destoffset = decode_rl_address(emu);
2036197007Sdelphij		store_data_byte(emu, destoffset, *srcreg);
2037197007Sdelphij	} else {
2038197007Sdelphij		destreg = decode_rl_byte_register(emu);
2039197007Sdelphij		*destreg = *srcreg;
2040197007Sdelphij	}
2041197007Sdelphij}
2042197007Sdelphij
2043197007Sdelphij/*
2044197007Sdelphij * REMARKS:
2045197007Sdelphij * Handles opcode 0x89
2046197007Sdelphij */
2047197007Sdelphijstatic void
2048197007Sdelphijx86emuOp32_mov_word_RM_R(struct x86emu *emu)
2049197007Sdelphij{
2050197007Sdelphij	uint32_t destoffset;
2051197007Sdelphij	uint32_t *destreg, srcval;
2052197007Sdelphij
2053197007Sdelphij	fetch_decode_modrm(emu);
2054197007Sdelphij	srcval = *decode_rh_long_register(emu);
2055197007Sdelphij	if (emu->cur_mod != 3) {
2056197007Sdelphij		destoffset = decode_rl_address(emu);
2057197007Sdelphij		store_data_long(emu, destoffset, srcval);
2058197007Sdelphij	} else {
2059197007Sdelphij		destreg = decode_rl_long_register(emu);
2060197007Sdelphij		*destreg = srcval;
2061197007Sdelphij	}
2062197007Sdelphij}
2063197007Sdelphij
2064197007Sdelphijstatic void
2065197007Sdelphijx86emuOp16_mov_word_RM_R(struct x86emu *emu)
2066197007Sdelphij{
2067197007Sdelphij	uint32_t destoffset;
2068197007Sdelphij	uint16_t *destreg, srcval;
2069197007Sdelphij
2070197007Sdelphij	fetch_decode_modrm(emu);
2071197007Sdelphij	srcval = *decode_rh_word_register(emu);
2072197007Sdelphij	if (emu->cur_mod != 3) {
2073197007Sdelphij		destoffset = decode_rl_address(emu);
2074197007Sdelphij		store_data_word(emu, destoffset, srcval);
2075197007Sdelphij	} else {
2076197007Sdelphij		destreg = decode_rl_word_register(emu);
2077197007Sdelphij		*destreg = srcval;
2078197007Sdelphij	}
2079197007Sdelphij}
2080197007Sdelphij
2081197007Sdelphijstatic void
2082197007Sdelphijx86emuOp_mov_word_RM_R(struct x86emu *emu)
2083197007Sdelphij{
2084197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2085197007Sdelphij		x86emuOp32_mov_word_RM_R(emu);
2086197007Sdelphij	else
2087197007Sdelphij		x86emuOp16_mov_word_RM_R(emu);
2088197007Sdelphij}
2089197007Sdelphij
2090197007Sdelphij/*
2091197007Sdelphij * REMARKS:
2092197007Sdelphij * Handles opcode 0x8a
2093197007Sdelphij */
2094197007Sdelphijstatic void
2095197007Sdelphijx86emuOp_mov_byte_R_RM(struct x86emu *emu)
2096197007Sdelphij{
2097197007Sdelphij	uint8_t *destreg;
2098197007Sdelphij
2099197007Sdelphij	fetch_decode_modrm(emu);
2100197007Sdelphij	destreg = decode_rh_byte_register(emu);
2101197007Sdelphij	*destreg = decode_and_fetch_byte(emu);
2102197007Sdelphij}
2103197007Sdelphij
2104197007Sdelphij/*
2105197007Sdelphij * REMARKS:
2106197007Sdelphij * Handles opcode 0x8b
2107197007Sdelphij */
2108197007Sdelphijstatic void
2109197007Sdelphijx86emuOp_mov_word_R_RM(struct x86emu *emu)
2110197007Sdelphij{
2111197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2112197007Sdelphij		uint32_t *destreg;
2113197007Sdelphij
2114197007Sdelphij		fetch_decode_modrm(emu);
2115197007Sdelphij		destreg = decode_rh_long_register(emu);
2116197007Sdelphij		*destreg = decode_and_fetch_long(emu);
2117197007Sdelphij	} else {
2118197007Sdelphij		uint16_t *destreg;
2119197007Sdelphij
2120197007Sdelphij		fetch_decode_modrm(emu);
2121197007Sdelphij		destreg = decode_rh_word_register(emu);
2122197007Sdelphij		*destreg = decode_and_fetch_word(emu);
2123197007Sdelphij	}
2124197007Sdelphij}
2125197007Sdelphij
2126197007Sdelphij/*
2127197007Sdelphij * REMARKS:
2128197007Sdelphij * Handles opcode 0x8c
2129197007Sdelphij */
2130197007Sdelphijstatic void
2131197007Sdelphijx86emuOp_mov_word_RM_SR(struct x86emu *emu)
2132197007Sdelphij{
2133197007Sdelphij	uint16_t *destreg, srcval;
2134197007Sdelphij	uint32_t destoffset;
2135197007Sdelphij
2136197007Sdelphij	fetch_decode_modrm(emu);
2137197007Sdelphij	srcval = *decode_rh_seg_register(emu);
2138197007Sdelphij	if (emu->cur_mod != 3) {
2139197007Sdelphij		destoffset = decode_rl_address(emu);
2140197007Sdelphij		store_data_word(emu, destoffset, srcval);
2141197007Sdelphij	} else {
2142197007Sdelphij		destreg = decode_rl_word_register(emu);
2143197007Sdelphij		*destreg = srcval;
2144197007Sdelphij	}
2145197007Sdelphij}
2146197007Sdelphij
2147197007Sdelphij/*
2148197007Sdelphij * REMARKS:
2149197007Sdelphij * Handles opcode 0x8d
2150197007Sdelphij */
2151197007Sdelphijstatic void
2152197007Sdelphijx86emuOp_lea_word_R_M(struct x86emu *emu)
2153197007Sdelphij{
2154197007Sdelphij	uint32_t destoffset;
2155197007Sdelphij
2156197007Sdelphij	fetch_decode_modrm(emu);
2157197007Sdelphij	if (emu->cur_mod == 3)
2158197007Sdelphij		x86emu_halt_sys(emu);
2159197007Sdelphij
2160197007Sdelphij	destoffset = decode_rl_address(emu);
2161267373Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_ADDR) {
2162267373Sdelphij		uint32_t *srcreg;
2163267373Sdelphij
2164267373Sdelphij		srcreg = decode_rh_long_register(emu);
2165267373Sdelphij		*srcreg = (uint32_t) destoffset;
2166267373Sdelphij	} else {
2167267373Sdelphij		uint16_t *srcreg;
2168267373Sdelphij
2169267373Sdelphij		srcreg = decode_rh_word_register(emu);
2170267373Sdelphij		*srcreg = (uint16_t) destoffset;
2171267373Sdelphij	}
2172197007Sdelphij}
2173197007Sdelphij
2174197007Sdelphij/*
2175197007Sdelphij * REMARKS:
2176197007Sdelphij * Handles opcode 0x8e
2177197007Sdelphij */
2178197007Sdelphijstatic void
2179197007Sdelphijx86emuOp_mov_word_SR_RM(struct x86emu *emu)
2180197007Sdelphij{
2181197007Sdelphij	uint16_t *destreg;
2182197007Sdelphij
2183197007Sdelphij	fetch_decode_modrm(emu);
2184197007Sdelphij	destreg = decode_rh_seg_register(emu);
2185197007Sdelphij	*destreg = decode_and_fetch_word(emu);
2186197007Sdelphij	/*
2187197007Sdelphij         * Clean up, and reset all the R_xSP pointers to the correct
2188197007Sdelphij         * locations.  This is about 3x too much overhead (doing all the
2189197007Sdelphij         * segreg ptrs when only one is needed, but this instruction
2190197007Sdelphij         * *cannot* be that common, and this isn't too much work anyway.
2191197007Sdelphij         */
2192197007Sdelphij}
2193197007Sdelphij
2194197007Sdelphij/*
2195197007Sdelphij * REMARKS:
2196197007Sdelphij * Handles opcode 0x8f
2197197007Sdelphij */
2198197007Sdelphijstatic void
2199197007Sdelphijx86emuOp32_pop_RM(struct x86emu *emu)
2200197007Sdelphij{
2201197007Sdelphij	uint32_t destoffset;
2202197007Sdelphij	uint32_t destval, *destreg;
2203197007Sdelphij
2204197007Sdelphij	fetch_decode_modrm(emu);
2205197007Sdelphij	if (emu->cur_mod != 3) {
2206197007Sdelphij		destoffset = decode_rl_address(emu);
2207197007Sdelphij		destval = pop_long(emu);
2208197007Sdelphij		store_data_long(emu, destoffset, destval);
2209197007Sdelphij	} else {
2210197007Sdelphij		destreg = decode_rl_long_register(emu);
2211197007Sdelphij		*destreg = pop_long(emu);
2212197007Sdelphij	}
2213197007Sdelphij}
2214197007Sdelphij
2215197007Sdelphijstatic void
2216197007Sdelphijx86emuOp16_pop_RM(struct x86emu *emu)
2217197007Sdelphij{
2218197007Sdelphij	uint32_t destoffset;
2219197007Sdelphij	uint16_t destval, *destreg;
2220197007Sdelphij
2221197007Sdelphij	fetch_decode_modrm(emu);
2222197007Sdelphij	if (emu->cur_mod != 3) {
2223197007Sdelphij		destoffset = decode_rl_address(emu);
2224197007Sdelphij		destval = pop_word(emu);
2225197007Sdelphij		store_data_word(emu, destoffset, destval);
2226197007Sdelphij	} else {
2227197007Sdelphij		destreg = decode_rl_word_register(emu);
2228197007Sdelphij		*destreg = pop_word(emu);
2229197007Sdelphij	}
2230197007Sdelphij}
2231197007Sdelphij
2232197007Sdelphijstatic void
2233197007Sdelphijx86emuOp_pop_RM(struct x86emu *emu)
2234197007Sdelphij{
2235197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2236197007Sdelphij		x86emuOp32_pop_RM(emu);
2237197007Sdelphij	else
2238197007Sdelphij		x86emuOp16_pop_RM(emu);
2239197007Sdelphij}
2240197007Sdelphij
2241197007Sdelphij/*
2242197007Sdelphij * REMARKS:
2243197007Sdelphij * Handles opcode 0x91
2244197007Sdelphij */
2245197007Sdelphijstatic void
2246197007Sdelphijx86emuOp_xchg_word_AX_CX(struct x86emu *emu)
2247197007Sdelphij{
2248197007Sdelphij	uint32_t tmp;
2249197007Sdelphij
2250197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2251197007Sdelphij		tmp = emu->x86.R_EAX;
2252197007Sdelphij		emu->x86.R_EAX = emu->x86.R_ECX;
2253197007Sdelphij		emu->x86.R_ECX = tmp;
2254197007Sdelphij	} else {
2255197007Sdelphij		tmp = emu->x86.R_AX;
2256197007Sdelphij		emu->x86.R_AX = emu->x86.R_CX;
2257197007Sdelphij		emu->x86.R_CX = (uint16_t) tmp;
2258197007Sdelphij	}
2259197007Sdelphij}
2260197007Sdelphij
2261197007Sdelphij/*
2262197007Sdelphij * REMARKS:
2263197007Sdelphij * Handles opcode 0x92
2264197007Sdelphij */
2265197007Sdelphijstatic void
2266197007Sdelphijx86emuOp_xchg_word_AX_DX(struct x86emu *emu)
2267197007Sdelphij{
2268197007Sdelphij	uint32_t tmp;
2269197007Sdelphij
2270197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2271197007Sdelphij		tmp = emu->x86.R_EAX;
2272197007Sdelphij		emu->x86.R_EAX = emu->x86.R_EDX;
2273197007Sdelphij		emu->x86.R_EDX = tmp;
2274197007Sdelphij	} else {
2275197007Sdelphij		tmp = emu->x86.R_AX;
2276197007Sdelphij		emu->x86.R_AX = emu->x86.R_DX;
2277197007Sdelphij		emu->x86.R_DX = (uint16_t) tmp;
2278197007Sdelphij	}
2279197007Sdelphij}
2280197007Sdelphij
2281197007Sdelphij/*
2282197007Sdelphij * REMARKS:
2283197007Sdelphij * Handles opcode 0x93
2284197007Sdelphij */
2285197007Sdelphijstatic void
2286197007Sdelphijx86emuOp_xchg_word_AX_BX(struct x86emu *emu)
2287197007Sdelphij{
2288197007Sdelphij	uint32_t tmp;
2289197007Sdelphij
2290197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2291197007Sdelphij		tmp = emu->x86.R_EAX;
2292197007Sdelphij		emu->x86.R_EAX = emu->x86.R_EBX;
2293197007Sdelphij		emu->x86.R_EBX = tmp;
2294197007Sdelphij	} else {
2295197007Sdelphij		tmp = emu->x86.R_AX;
2296197007Sdelphij		emu->x86.R_AX = emu->x86.R_BX;
2297197007Sdelphij		emu->x86.R_BX = (uint16_t) tmp;
2298197007Sdelphij	}
2299197007Sdelphij}
2300197007Sdelphij
2301197007Sdelphij/*
2302197007Sdelphij * REMARKS:
2303197007Sdelphij * Handles opcode 0x94
2304197007Sdelphij */
2305197007Sdelphijstatic void
2306197007Sdelphijx86emuOp_xchg_word_AX_SP(struct x86emu *emu)
2307197007Sdelphij{
2308197007Sdelphij	uint32_t tmp;
2309197007Sdelphij
2310197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2311197007Sdelphij		tmp = emu->x86.R_EAX;
2312197007Sdelphij		emu->x86.R_EAX = emu->x86.R_ESP;
2313197007Sdelphij		emu->x86.R_ESP = tmp;
2314197007Sdelphij	} else {
2315197007Sdelphij		tmp = emu->x86.R_AX;
2316197007Sdelphij		emu->x86.R_AX = emu->x86.R_SP;
2317197007Sdelphij		emu->x86.R_SP = (uint16_t) tmp;
2318197007Sdelphij	}
2319197007Sdelphij}
2320197007Sdelphij
2321197007Sdelphij/*
2322197007Sdelphij * REMARKS:
2323197007Sdelphij * Handles opcode 0x95
2324197007Sdelphij */
2325197007Sdelphijstatic void
2326197007Sdelphijx86emuOp_xchg_word_AX_BP(struct x86emu *emu)
2327197007Sdelphij{
2328197007Sdelphij	uint32_t tmp;
2329197007Sdelphij
2330197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2331197007Sdelphij		tmp = emu->x86.R_EAX;
2332197007Sdelphij		emu->x86.R_EAX = emu->x86.R_EBP;
2333197007Sdelphij		emu->x86.R_EBP = tmp;
2334197007Sdelphij	} else {
2335197007Sdelphij		tmp = emu->x86.R_AX;
2336197007Sdelphij		emu->x86.R_AX = emu->x86.R_BP;
2337197007Sdelphij		emu->x86.R_BP = (uint16_t) tmp;
2338197007Sdelphij	}
2339197007Sdelphij}
2340197007Sdelphij
2341197007Sdelphij/*
2342197007Sdelphij * REMARKS:
2343197007Sdelphij * Handles opcode 0x96
2344197007Sdelphij */
2345197007Sdelphijstatic void
2346197007Sdelphijx86emuOp_xchg_word_AX_SI(struct x86emu *emu)
2347197007Sdelphij{
2348197007Sdelphij	uint32_t tmp;
2349197007Sdelphij
2350197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2351197007Sdelphij		tmp = emu->x86.R_EAX;
2352197007Sdelphij		emu->x86.R_EAX = emu->x86.R_ESI;
2353197007Sdelphij		emu->x86.R_ESI = tmp;
2354197007Sdelphij	} else {
2355197007Sdelphij		tmp = emu->x86.R_AX;
2356197007Sdelphij		emu->x86.R_AX = emu->x86.R_SI;
2357197007Sdelphij		emu->x86.R_SI = (uint16_t) tmp;
2358197007Sdelphij	}
2359197007Sdelphij}
2360197007Sdelphij
2361197007Sdelphij/*
2362197007Sdelphij * REMARKS:
2363197007Sdelphij * Handles opcode 0x97
2364197007Sdelphij */
2365197007Sdelphijstatic void
2366197007Sdelphijx86emuOp_xchg_word_AX_DI(struct x86emu *emu)
2367197007Sdelphij{
2368197007Sdelphij	uint32_t tmp;
2369197007Sdelphij
2370197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2371197007Sdelphij		tmp = emu->x86.R_EAX;
2372197007Sdelphij		emu->x86.R_EAX = emu->x86.R_EDI;
2373197007Sdelphij		emu->x86.R_EDI = tmp;
2374197007Sdelphij	} else {
2375197007Sdelphij		tmp = emu->x86.R_AX;
2376197007Sdelphij		emu->x86.R_AX = emu->x86.R_DI;
2377197007Sdelphij		emu->x86.R_DI = (uint16_t) tmp;
2378197007Sdelphij	}
2379197007Sdelphij}
2380197007Sdelphij
2381197007Sdelphij/*
2382197007Sdelphij * REMARKS:
2383197007Sdelphij * Handles opcode 0x98
2384197007Sdelphij */
2385197007Sdelphijstatic void
2386197007Sdelphijx86emuOp_cbw(struct x86emu *emu)
2387197007Sdelphij{
2388197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2389197007Sdelphij		if (emu->x86.R_AX & 0x8000) {
2390197007Sdelphij			emu->x86.R_EAX |= 0xffff0000;
2391197007Sdelphij		} else {
2392197007Sdelphij			emu->x86.R_EAX &= 0x0000ffff;
2393197007Sdelphij		}
2394197007Sdelphij	} else {
2395197007Sdelphij		if (emu->x86.R_AL & 0x80) {
2396197007Sdelphij			emu->x86.R_AH = 0xff;
2397197007Sdelphij		} else {
2398197007Sdelphij			emu->x86.R_AH = 0x0;
2399197007Sdelphij		}
2400197007Sdelphij	}
2401197007Sdelphij}
2402197007Sdelphij
2403197007Sdelphij/*
2404197007Sdelphij * REMARKS:
2405197007Sdelphij * Handles opcode 0x99
2406197007Sdelphij */
2407197007Sdelphijstatic void
2408197007Sdelphijx86emuOp_cwd(struct x86emu *emu)
2409197007Sdelphij{
2410197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2411197007Sdelphij		if (emu->x86.R_EAX & 0x80000000) {
2412197007Sdelphij			emu->x86.R_EDX = 0xffffffff;
2413197007Sdelphij		} else {
2414197007Sdelphij			emu->x86.R_EDX = 0x0;
2415197007Sdelphij		}
2416197007Sdelphij	} else {
2417197007Sdelphij		if (emu->x86.R_AX & 0x8000) {
2418197007Sdelphij			emu->x86.R_DX = 0xffff;
2419197007Sdelphij		} else {
2420197007Sdelphij			emu->x86.R_DX = 0x0;
2421197007Sdelphij		}
2422197007Sdelphij	}
2423197007Sdelphij}
2424197007Sdelphij
2425197007Sdelphij/*
2426197007Sdelphij * REMARKS:
2427197007Sdelphij * Handles opcode 0x9a
2428197007Sdelphij */
2429197007Sdelphijstatic void
2430197007Sdelphijx86emuOp_call_far_IMM(struct x86emu *emu)
2431197007Sdelphij{
2432197007Sdelphij	uint16_t farseg, faroff;
2433197007Sdelphij
2434197007Sdelphij	faroff = fetch_word_imm(emu);
2435197007Sdelphij	farseg = fetch_word_imm(emu);
2436197007Sdelphij	/* XXX
2437197007Sdelphij	 *
2438197007Sdelphij	 * Hooked interrupt vectors calling into our "BIOS" will cause problems
2439197007Sdelphij	 * unless all intersegment stuff is checked for BIOS access.  Check
2440197007Sdelphij	 * needed here.  For moment, let it alone. */
2441197007Sdelphij	push_word(emu, emu->x86.R_CS);
2442197007Sdelphij	emu->x86.R_CS = farseg;
2443197007Sdelphij	push_word(emu, emu->x86.R_IP);
2444197007Sdelphij	emu->x86.R_IP = faroff;
2445197007Sdelphij}
2446197007Sdelphij
2447197007Sdelphij/*
2448197007Sdelphij * REMARKS:
2449197007Sdelphij * Handles opcode 0x9c
2450197007Sdelphij */
2451197007Sdelphijstatic void
2452197007Sdelphijx86emuOp_pushf_word(struct x86emu *emu)
2453197007Sdelphij{
2454197007Sdelphij	uint32_t flags;
2455197007Sdelphij
2456197007Sdelphij	/* clear out *all* bits not representing flags, and turn on real bits */
2457197007Sdelphij	flags = (emu->x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2458197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2459197007Sdelphij		push_long(emu, flags);
2460197007Sdelphij	} else {
2461197007Sdelphij		push_word(emu, (uint16_t) flags);
2462197007Sdelphij	}
2463197007Sdelphij}
2464197007Sdelphij
2465197007Sdelphij/*
2466197007Sdelphij * REMARKS:
2467197007Sdelphij * Handles opcode 0x9d
2468197007Sdelphij */
2469197007Sdelphijstatic void
2470197007Sdelphijx86emuOp_popf_word(struct x86emu *emu)
2471197007Sdelphij{
2472197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2473197007Sdelphij		emu->x86.R_EFLG = pop_long(emu);
2474197007Sdelphij	} else {
2475197007Sdelphij		emu->x86.R_FLG = pop_word(emu);
2476197007Sdelphij	}
2477197007Sdelphij}
2478197007Sdelphij
2479197007Sdelphij/*
2480197007Sdelphij * REMARKS:
2481197007Sdelphij * Handles opcode 0x9e
2482197007Sdelphij */
2483197007Sdelphijstatic void
2484197007Sdelphijx86emuOp_sahf(struct x86emu *emu)
2485197007Sdelphij{
2486197007Sdelphij	/* clear the lower bits of the flag register */
2487197007Sdelphij	emu->x86.R_FLG &= 0xffffff00;
2488197007Sdelphij	/* or in the AH register into the flags register */
2489197007Sdelphij	emu->x86.R_FLG |= emu->x86.R_AH;
2490197007Sdelphij}
2491197007Sdelphij
2492197007Sdelphij/*
2493197007Sdelphij * REMARKS:
2494197007Sdelphij * Handles opcode 0x9f
2495197007Sdelphij */
2496197007Sdelphijstatic void
2497197007Sdelphijx86emuOp_lahf(struct x86emu *emu)
2498197007Sdelphij{
2499197007Sdelphij	emu->x86.R_AH = (uint8_t) (emu->x86.R_FLG & 0xff);
2500197007Sdelphij	/* undocumented TC++ behavior??? Nope.  It's documented, but you have
2501197007Sdelphij	 * too look real hard to notice it. */
2502197007Sdelphij	emu->x86.R_AH |= 0x2;
2503197007Sdelphij}
2504197007Sdelphij
2505197007Sdelphij/*
2506197007Sdelphij * REMARKS:
2507197007Sdelphij * Handles opcode 0xa0
2508197007Sdelphij */
2509197007Sdelphijstatic void
2510197007Sdelphijx86emuOp_mov_AL_M_IMM(struct x86emu *emu)
2511197007Sdelphij{
2512197007Sdelphij	uint16_t offset;
2513197007Sdelphij
2514197007Sdelphij	offset = fetch_word_imm(emu);
2515197007Sdelphij	emu->x86.R_AL = fetch_data_byte(emu, offset);
2516197007Sdelphij}
2517197007Sdelphij
2518197007Sdelphij/*
2519197007Sdelphij * REMARKS:
2520197007Sdelphij * Handles opcode 0xa1
2521197007Sdelphij */
2522197007Sdelphijstatic void
2523197007Sdelphijx86emuOp_mov_AX_M_IMM(struct x86emu *emu)
2524197007Sdelphij{
2525197007Sdelphij	uint16_t offset;
2526197007Sdelphij
2527197007Sdelphij	offset = fetch_word_imm(emu);
2528197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2529197007Sdelphij		emu->x86.R_EAX = fetch_data_long(emu, offset);
2530197007Sdelphij	} else {
2531197007Sdelphij		emu->x86.R_AX = fetch_data_word(emu, offset);
2532197007Sdelphij	}
2533197007Sdelphij}
2534197007Sdelphij
2535197007Sdelphij/*
2536197007Sdelphij * REMARKS:
2537197007Sdelphij * Handles opcode 0xa2
2538197007Sdelphij */
2539197007Sdelphijstatic void
2540197007Sdelphijx86emuOp_mov_M_AL_IMM(struct x86emu *emu)
2541197007Sdelphij{
2542197007Sdelphij	uint16_t offset;
2543197007Sdelphij
2544197007Sdelphij	offset = fetch_word_imm(emu);
2545197007Sdelphij	store_data_byte(emu, offset, emu->x86.R_AL);
2546197007Sdelphij}
2547197007Sdelphij
2548197007Sdelphij/*
2549197007Sdelphij * REMARKS:
2550197007Sdelphij * Handles opcode 0xa3
2551197007Sdelphij */
2552197007Sdelphijstatic void
2553197007Sdelphijx86emuOp_mov_M_AX_IMM(struct x86emu *emu)
2554197007Sdelphij{
2555197007Sdelphij	uint16_t offset;
2556197007Sdelphij
2557197007Sdelphij	offset = fetch_word_imm(emu);
2558197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2559197007Sdelphij		store_data_long(emu, offset, emu->x86.R_EAX);
2560197007Sdelphij	} else {
2561197007Sdelphij		store_data_word(emu, offset, emu->x86.R_AX);
2562197007Sdelphij	}
2563197007Sdelphij}
2564197007Sdelphij
2565197007Sdelphij/*
2566197007Sdelphij * REMARKS:
2567197007Sdelphij * Handles opcode 0xa4
2568197007Sdelphij */
2569197007Sdelphijstatic void
2570197007Sdelphijx86emuOp_movs_byte(struct x86emu *emu)
2571197007Sdelphij{
2572197007Sdelphij	uint8_t val;
2573197007Sdelphij	uint32_t count;
2574197007Sdelphij	int inc;
2575197007Sdelphij
2576197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2577197007Sdelphij		inc = -1;
2578197007Sdelphij	else
2579197007Sdelphij		inc = 1;
2580197007Sdelphij	count = 1;
2581197007Sdelphij	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2582197007Sdelphij		/* dont care whether REPE or REPNE */
2583197007Sdelphij		/* move them until CX is ZERO. */
2584197007Sdelphij		count = emu->x86.R_CX;
2585197007Sdelphij		emu->x86.R_CX = 0;
2586197007Sdelphij		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2587197007Sdelphij	}
2588197007Sdelphij	while (count--) {
2589197007Sdelphij		val = fetch_data_byte(emu, emu->x86.R_SI);
2590197007Sdelphij		store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2591197007Sdelphij		emu->x86.R_SI += inc;
2592197007Sdelphij		emu->x86.R_DI += inc;
2593197007Sdelphij	}
2594197007Sdelphij}
2595197007Sdelphij
2596197007Sdelphij/*
2597197007Sdelphij * REMARKS:
2598197007Sdelphij * Handles opcode 0xa5
2599197007Sdelphij */
2600197007Sdelphijstatic void
2601197007Sdelphijx86emuOp_movs_word(struct x86emu *emu)
2602197007Sdelphij{
2603197007Sdelphij	uint32_t val;
2604197007Sdelphij	int inc;
2605197007Sdelphij	uint32_t count;
2606197007Sdelphij
2607197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2608197007Sdelphij		inc = 4;
2609197007Sdelphij	else
2610197007Sdelphij		inc = 2;
2611197007Sdelphij
2612197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2613197007Sdelphij		inc = -inc;
2614197007Sdelphij
2615197007Sdelphij	count = 1;
2616197007Sdelphij	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2617197007Sdelphij		/* dont care whether REPE or REPNE */
2618197007Sdelphij		/* move them until CX is ZERO. */
2619197007Sdelphij		count = emu->x86.R_CX;
2620197007Sdelphij		emu->x86.R_CX = 0;
2621197007Sdelphij		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2622197007Sdelphij	}
2623197007Sdelphij	while (count--) {
2624197007Sdelphij		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2625197007Sdelphij			val = fetch_data_long(emu, emu->x86.R_SI);
2626197007Sdelphij			store_long(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2627197007Sdelphij		} else {
2628197007Sdelphij			val = fetch_data_word(emu, emu->x86.R_SI);
2629204934Sdelphij			store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
2630204934Sdelphij			    (uint16_t) val);
2631197007Sdelphij		}
2632197007Sdelphij		emu->x86.R_SI += inc;
2633197007Sdelphij		emu->x86.R_DI += inc;
2634197007Sdelphij	}
2635197007Sdelphij}
2636197007Sdelphij
2637197007Sdelphij/*
2638197007Sdelphij * REMARKS:
2639197007Sdelphij * Handles opcode 0xa6
2640197007Sdelphij */
2641197007Sdelphijstatic void
2642197007Sdelphijx86emuOp_cmps_byte(struct x86emu *emu)
2643197007Sdelphij{
2644197007Sdelphij	int8_t val1, val2;
2645197007Sdelphij	int inc;
2646197007Sdelphij
2647197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2648197007Sdelphij		inc = -1;
2649197007Sdelphij	else
2650197007Sdelphij		inc = 1;
2651197007Sdelphij
2652197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2653197007Sdelphij		/* REPE  */
2654197007Sdelphij		/* move them until CX is ZERO. */
2655197007Sdelphij		while (emu->x86.R_CX != 0) {
2656197007Sdelphij			val1 = fetch_data_byte(emu, emu->x86.R_SI);
2657197007Sdelphij			val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2658197007Sdelphij			cmp_byte(emu, val1, val2);
2659197007Sdelphij			emu->x86.R_CX -= 1;
2660197007Sdelphij			emu->x86.R_SI += inc;
2661197007Sdelphij			emu->x86.R_DI += inc;
2662197007Sdelphij			if (ACCESS_FLAG(F_ZF) == 0)
2663197007Sdelphij				break;
2664197007Sdelphij		}
2665197007Sdelphij		emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2666197007Sdelphij	} else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2667197007Sdelphij		/* REPNE  */
2668197007Sdelphij		/* move them until CX is ZERO. */
2669197007Sdelphij		while (emu->x86.R_CX != 0) {
2670197007Sdelphij			val1 = fetch_data_byte(emu, emu->x86.R_SI);
2671197007Sdelphij			val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2672197007Sdelphij			cmp_byte(emu, val1, val2);
2673197007Sdelphij			emu->x86.R_CX -= 1;
2674197007Sdelphij			emu->x86.R_SI += inc;
2675197007Sdelphij			emu->x86.R_DI += inc;
2676197007Sdelphij			if (ACCESS_FLAG(F_ZF))
2677197007Sdelphij				break;	/* zero flag set means equal */
2678197007Sdelphij		}
2679197007Sdelphij		emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2680197007Sdelphij	} else {
2681197007Sdelphij		val1 = fetch_data_byte(emu, emu->x86.R_SI);
2682197007Sdelphij		val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2683197007Sdelphij		cmp_byte(emu, val1, val2);
2684197007Sdelphij		emu->x86.R_SI += inc;
2685197007Sdelphij		emu->x86.R_DI += inc;
2686197007Sdelphij	}
2687197007Sdelphij}
2688197007Sdelphij
2689197007Sdelphij/*
2690197007Sdelphij * REMARKS:
2691197007Sdelphij * Handles opcode 0xa7
2692197007Sdelphij */
2693197007Sdelphijstatic void
2694197007Sdelphijx86emuOp_cmps_word(struct x86emu *emu)
2695197007Sdelphij{
2696197007Sdelphij	uint32_t val1, val2;
2697197007Sdelphij	int inc;
2698197007Sdelphij
2699197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2700197007Sdelphij		if (ACCESS_FLAG(F_DF))	/* down */
2701197007Sdelphij			inc = -4;
2702197007Sdelphij		else
2703197007Sdelphij			inc = 4;
2704197007Sdelphij	} else {
2705197007Sdelphij		if (ACCESS_FLAG(F_DF))	/* down */
2706197007Sdelphij			inc = -2;
2707197007Sdelphij		else
2708197007Sdelphij			inc = 2;
2709197007Sdelphij	}
2710197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2711197007Sdelphij		/* REPE  */
2712197007Sdelphij		/* move them until CX is ZERO. */
2713197007Sdelphij		while (emu->x86.R_CX != 0) {
2714197007Sdelphij			if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2715197007Sdelphij				val1 = fetch_data_long(emu, emu->x86.R_SI);
2716204934Sdelphij				val2 = fetch_long(emu, emu->x86.R_ES,
2717204934Sdelphij				    emu->x86.R_DI);
2718197007Sdelphij				cmp_long(emu, val1, val2);
2719197007Sdelphij			} else {
2720197007Sdelphij				val1 = fetch_data_word(emu, emu->x86.R_SI);
2721204934Sdelphij				val2 = fetch_word(emu, emu->x86.R_ES,
2722204934Sdelphij				    emu->x86.R_DI);
2723197007Sdelphij				cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2724197007Sdelphij			}
2725197007Sdelphij			emu->x86.R_CX -= 1;
2726197007Sdelphij			emu->x86.R_SI += inc;
2727197007Sdelphij			emu->x86.R_DI += inc;
2728197007Sdelphij			if (ACCESS_FLAG(F_ZF) == 0)
2729197007Sdelphij				break;
2730197007Sdelphij		}
2731197007Sdelphij		emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2732197007Sdelphij	} else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2733197007Sdelphij		/* REPNE  */
2734197007Sdelphij		/* move them until CX is ZERO. */
2735197007Sdelphij		while (emu->x86.R_CX != 0) {
2736197007Sdelphij			if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2737197007Sdelphij				val1 = fetch_data_long(emu, emu->x86.R_SI);
2738204934Sdelphij				val2 = fetch_long(emu, emu->x86.R_ES,
2739204934Sdelphij				    emu->x86.R_DI);
2740197007Sdelphij				cmp_long(emu, val1, val2);
2741197007Sdelphij			} else {
2742197007Sdelphij				val1 = fetch_data_word(emu, emu->x86.R_SI);
2743204934Sdelphij				val2 = fetch_word(emu, emu->x86.R_ES,
2744204934Sdelphij				    emu->x86.R_DI);
2745197007Sdelphij				cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2746197007Sdelphij			}
2747197007Sdelphij			emu->x86.R_CX -= 1;
2748197007Sdelphij			emu->x86.R_SI += inc;
2749197007Sdelphij			emu->x86.R_DI += inc;
2750197007Sdelphij			if (ACCESS_FLAG(F_ZF))
2751197007Sdelphij				break;	/* zero flag set means equal */
2752197007Sdelphij		}
2753197007Sdelphij		emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2754197007Sdelphij	} else {
2755197007Sdelphij		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2756197007Sdelphij			val1 = fetch_data_long(emu, emu->x86.R_SI);
2757197007Sdelphij			val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2758197007Sdelphij			cmp_long(emu, val1, val2);
2759197007Sdelphij		} else {
2760197007Sdelphij			val1 = fetch_data_word(emu, emu->x86.R_SI);
2761197007Sdelphij			val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2762197007Sdelphij			cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2763197007Sdelphij		}
2764197007Sdelphij		emu->x86.R_SI += inc;
2765197007Sdelphij		emu->x86.R_DI += inc;
2766197007Sdelphij	}
2767197007Sdelphij}
2768197007Sdelphij
2769197007Sdelphij/*
2770197007Sdelphij * REMARKS:
2771197007Sdelphij * Handles opcode 0xa9
2772197007Sdelphij */
2773197007Sdelphijstatic void
2774197007Sdelphijx86emuOp_test_AX_IMM(struct x86emu *emu)
2775197007Sdelphij{
2776197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2777197007Sdelphij		test_long(emu, emu->x86.R_EAX, fetch_long_imm(emu));
2778197007Sdelphij	} else {
2779197007Sdelphij		test_word(emu, emu->x86.R_AX, fetch_word_imm(emu));
2780197007Sdelphij	}
2781197007Sdelphij}
2782197007Sdelphij
2783197007Sdelphij/*
2784197007Sdelphij * REMARKS:
2785197007Sdelphij * Handles opcode 0xaa
2786197007Sdelphij */
2787197007Sdelphijstatic void
2788197007Sdelphijx86emuOp_stos_byte(struct x86emu *emu)
2789197007Sdelphij{
2790197007Sdelphij	int inc;
2791197007Sdelphij
2792197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2793197007Sdelphij		inc = -1;
2794197007Sdelphij	else
2795197007Sdelphij		inc = 1;
2796197007Sdelphij	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2797197007Sdelphij		/* dont care whether REPE or REPNE */
2798197007Sdelphij		/* move them until CX is ZERO. */
2799197007Sdelphij		while (emu->x86.R_CX != 0) {
2800204934Sdelphij			store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
2801204934Sdelphij			    emu->x86.R_AL);
2802197007Sdelphij			emu->x86.R_CX -= 1;
2803197007Sdelphij			emu->x86.R_DI += inc;
2804197007Sdelphij		}
2805197007Sdelphij		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2806197007Sdelphij	} else {
2807197007Sdelphij		store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL);
2808197007Sdelphij		emu->x86.R_DI += inc;
2809197007Sdelphij	}
2810197007Sdelphij}
2811197007Sdelphij
2812197007Sdelphij/*
2813197007Sdelphij * REMARKS:
2814197007Sdelphij * Handles opcode 0xab
2815197007Sdelphij */
2816197007Sdelphijstatic void
2817197007Sdelphijx86emuOp_stos_word(struct x86emu *emu)
2818197007Sdelphij{
2819197007Sdelphij	int inc;
2820197007Sdelphij	uint32_t count;
2821197007Sdelphij
2822197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2823197007Sdelphij		inc = 4;
2824197007Sdelphij	else
2825197007Sdelphij		inc = 2;
2826197007Sdelphij
2827197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2828197007Sdelphij		inc = -inc;
2829197007Sdelphij
2830197007Sdelphij	count = 1;
2831197007Sdelphij	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2832197007Sdelphij		/* dont care whether REPE or REPNE */
2833197007Sdelphij		/* move them until CX is ZERO. */
2834197007Sdelphij		count = emu->x86.R_CX;
2835197007Sdelphij		emu->x86.R_CX = 0;
2836197007Sdelphij		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2837197007Sdelphij	}
2838197007Sdelphij	while (count--) {
2839197007Sdelphij		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2840204934Sdelphij			store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
2841204934Sdelphij			    emu->x86.R_EAX);
2842197007Sdelphij		} else {
2843204934Sdelphij			store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
2844204934Sdelphij			    emu->x86.R_AX);
2845197007Sdelphij		}
2846197007Sdelphij		emu->x86.R_DI += inc;
2847197007Sdelphij	}
2848197007Sdelphij}
2849197007Sdelphij
2850197007Sdelphij/*
2851197007Sdelphij * REMARKS:
2852197007Sdelphij * Handles opcode 0xac
2853197007Sdelphij */
2854197007Sdelphijstatic void
2855197007Sdelphijx86emuOp_lods_byte(struct x86emu *emu)
2856197007Sdelphij{
2857197007Sdelphij	int inc;
2858197007Sdelphij
2859197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2860197007Sdelphij		inc = -1;
2861197007Sdelphij	else
2862197007Sdelphij		inc = 1;
2863197007Sdelphij	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2864197007Sdelphij		/* dont care whether REPE or REPNE */
2865197007Sdelphij		/* move them until CX is ZERO. */
2866197007Sdelphij		while (emu->x86.R_CX != 0) {
2867197007Sdelphij			emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2868197007Sdelphij			emu->x86.R_CX -= 1;
2869197007Sdelphij			emu->x86.R_SI += inc;
2870197007Sdelphij		}
2871197007Sdelphij		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2872197007Sdelphij	} else {
2873197007Sdelphij		emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2874197007Sdelphij		emu->x86.R_SI += inc;
2875197007Sdelphij	}
2876197007Sdelphij}
2877197007Sdelphij
2878197007Sdelphij/*
2879197007Sdelphij * REMARKS:
2880197007Sdelphij * Handles opcode 0xad
2881197007Sdelphij */
2882197007Sdelphijstatic void
2883197007Sdelphijx86emuOp_lods_word(struct x86emu *emu)
2884197007Sdelphij{
2885197007Sdelphij	int inc;
2886197007Sdelphij	uint32_t count;
2887197007Sdelphij
2888197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2889197007Sdelphij		inc = 4;
2890197007Sdelphij	else
2891197007Sdelphij		inc = 2;
2892197007Sdelphij
2893197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2894197007Sdelphij		inc = -inc;
2895197007Sdelphij
2896197007Sdelphij	count = 1;
2897197007Sdelphij	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2898197007Sdelphij		/* dont care whether REPE or REPNE */
2899197007Sdelphij		/* move them until CX is ZERO. */
2900197007Sdelphij		count = emu->x86.R_CX;
2901197007Sdelphij		emu->x86.R_CX = 0;
2902197007Sdelphij		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2903197007Sdelphij	}
2904197007Sdelphij	while (count--) {
2905197007Sdelphij		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2906197007Sdelphij			emu->x86.R_EAX = fetch_data_long(emu, emu->x86.R_SI);
2907197007Sdelphij		} else {
2908197007Sdelphij			emu->x86.R_AX = fetch_data_word(emu, emu->x86.R_SI);
2909197007Sdelphij		}
2910197007Sdelphij		emu->x86.R_SI += inc;
2911197007Sdelphij	}
2912197007Sdelphij}
2913197007Sdelphij
2914197007Sdelphij/*
2915197007Sdelphij * REMARKS:
2916197007Sdelphij * Handles opcode 0xae
2917197007Sdelphij */
2918197007Sdelphijstatic void
2919197007Sdelphijx86emuOp_scas_byte(struct x86emu *emu)
2920197007Sdelphij{
2921197007Sdelphij	int8_t val2;
2922197007Sdelphij	int inc;
2923197007Sdelphij
2924197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2925197007Sdelphij		inc = -1;
2926197007Sdelphij	else
2927197007Sdelphij		inc = 1;
2928197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2929197007Sdelphij		/* REPE  */
2930197007Sdelphij		/* move them until CX is ZERO. */
2931197007Sdelphij		while (emu->x86.R_CX != 0) {
2932197007Sdelphij			val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2933197007Sdelphij			cmp_byte(emu, emu->x86.R_AL, val2);
2934197007Sdelphij			emu->x86.R_CX -= 1;
2935197007Sdelphij			emu->x86.R_DI += inc;
2936197007Sdelphij			if (ACCESS_FLAG(F_ZF) == 0)
2937197007Sdelphij				break;
2938197007Sdelphij		}
2939197007Sdelphij		emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2940197007Sdelphij	} else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2941197007Sdelphij		/* REPNE  */
2942197007Sdelphij		/* move them until CX is ZERO. */
2943197007Sdelphij		while (emu->x86.R_CX != 0) {
2944197007Sdelphij			val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2945197007Sdelphij			cmp_byte(emu, emu->x86.R_AL, val2);
2946197007Sdelphij			emu->x86.R_CX -= 1;
2947197007Sdelphij			emu->x86.R_DI += inc;
2948197007Sdelphij			if (ACCESS_FLAG(F_ZF))
2949197007Sdelphij				break;	/* zero flag set means equal */
2950197007Sdelphij		}
2951197007Sdelphij		emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2952197007Sdelphij	} else {
2953197007Sdelphij		val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2954197007Sdelphij		cmp_byte(emu, emu->x86.R_AL, val2);
2955197007Sdelphij		emu->x86.R_DI += inc;
2956197007Sdelphij	}
2957197007Sdelphij}
2958197007Sdelphij
2959197007Sdelphij/*
2960197007Sdelphij * REMARKS:
2961197007Sdelphij * Handles opcode 0xaf
2962197007Sdelphij */
2963197007Sdelphijstatic void
2964197007Sdelphijx86emuOp_scas_word(struct x86emu *emu)
2965197007Sdelphij{
2966197007Sdelphij	int inc;
2967197007Sdelphij	uint32_t val;
2968197007Sdelphij
2969197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2970197007Sdelphij		inc = 4;
2971197007Sdelphij	else
2972197007Sdelphij		inc = 2;
2973197007Sdelphij
2974197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2975197007Sdelphij		inc = -inc;
2976197007Sdelphij
2977197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2978197007Sdelphij		/* REPE  */
2979197007Sdelphij		/* move them until CX is ZERO. */
2980197007Sdelphij		while (emu->x86.R_CX != 0) {
2981197007Sdelphij			if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2982204934Sdelphij				val = fetch_long(emu, emu->x86.R_ES,
2983204934Sdelphij				    emu->x86.R_DI);
2984197007Sdelphij				cmp_long(emu, emu->x86.R_EAX, val);
2985197007Sdelphij			} else {
2986204934Sdelphij				val = fetch_word(emu, emu->x86.R_ES,
2987204934Sdelphij				    emu->x86.R_DI);
2988197007Sdelphij				cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
2989197007Sdelphij			}
2990197007Sdelphij			emu->x86.R_CX -= 1;
2991197007Sdelphij			emu->x86.R_DI += inc;
2992197007Sdelphij			if (ACCESS_FLAG(F_ZF) == 0)
2993197007Sdelphij				break;
2994197007Sdelphij		}
2995197007Sdelphij		emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2996197007Sdelphij	} else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2997197007Sdelphij		/* REPNE  */
2998197007Sdelphij		/* move them until CX is ZERO. */
2999197007Sdelphij		while (emu->x86.R_CX != 0) {
3000197007Sdelphij			if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3001204934Sdelphij				val = fetch_long(emu, emu->x86.R_ES,
3002204934Sdelphij				    emu->x86.R_DI);
3003197007Sdelphij				cmp_long(emu, emu->x86.R_EAX, val);
3004197007Sdelphij			} else {
3005204934Sdelphij				val = fetch_word(emu, emu->x86.R_ES,
3006204934Sdelphij				    emu->x86.R_DI);
3007197007Sdelphij				cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
3008197007Sdelphij			}
3009197007Sdelphij			emu->x86.R_CX -= 1;
3010197007Sdelphij			emu->x86.R_DI += inc;
3011197007Sdelphij			if (ACCESS_FLAG(F_ZF))
3012197007Sdelphij				break;	/* zero flag set means equal */
3013197007Sdelphij		}
3014197007Sdelphij		emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
3015197007Sdelphij	} else {
3016197007Sdelphij		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3017197007Sdelphij			val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
3018197007Sdelphij			cmp_long(emu, emu->x86.R_EAX, val);
3019197007Sdelphij		} else {
3020197007Sdelphij			val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
3021197007Sdelphij			cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
3022197007Sdelphij		}
3023197007Sdelphij		emu->x86.R_DI += inc;
3024197007Sdelphij	}
3025197007Sdelphij}
3026197007Sdelphij
3027197007Sdelphij/*
3028197007Sdelphij * REMARKS:
3029197007Sdelphij * Handles opcode 0xb8
3030197007Sdelphij */
3031197007Sdelphijstatic void
3032197007Sdelphijx86emuOp_mov_word_AX_IMM(struct x86emu *emu)
3033197007Sdelphij{
3034197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3035197007Sdelphij		emu->x86.R_EAX = fetch_long_imm(emu);
3036197007Sdelphij	else
3037197007Sdelphij		emu->x86.R_AX = fetch_word_imm(emu);
3038197007Sdelphij}
3039197007Sdelphij
3040197007Sdelphij/*
3041197007Sdelphij * REMARKS:
3042197007Sdelphij * Handles opcode 0xb9
3043197007Sdelphij */
3044197007Sdelphijstatic void
3045197007Sdelphijx86emuOp_mov_word_CX_IMM(struct x86emu *emu)
3046197007Sdelphij{
3047197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3048197007Sdelphij		emu->x86.R_ECX = fetch_long_imm(emu);
3049197007Sdelphij	else
3050197007Sdelphij		emu->x86.R_CX = fetch_word_imm(emu);
3051197007Sdelphij}
3052197007Sdelphij
3053197007Sdelphij/*
3054197007Sdelphij * REMARKS:
3055197007Sdelphij * Handles opcode 0xba
3056197007Sdelphij */
3057197007Sdelphijstatic void
3058197007Sdelphijx86emuOp_mov_word_DX_IMM(struct x86emu *emu)
3059197007Sdelphij{
3060197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3061197007Sdelphij		emu->x86.R_EDX = fetch_long_imm(emu);
3062197007Sdelphij	else
3063197007Sdelphij		emu->x86.R_DX = fetch_word_imm(emu);
3064197007Sdelphij}
3065197007Sdelphij
3066197007Sdelphij/*
3067197007Sdelphij * REMARKS:
3068197007Sdelphij * Handles opcode 0xbb
3069197007Sdelphij */
3070197007Sdelphijstatic void
3071197007Sdelphijx86emuOp_mov_word_BX_IMM(struct x86emu *emu)
3072197007Sdelphij{
3073197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3074197007Sdelphij		emu->x86.R_EBX = fetch_long_imm(emu);
3075197007Sdelphij	else
3076197007Sdelphij		emu->x86.R_BX = fetch_word_imm(emu);
3077197007Sdelphij}
3078197007Sdelphij
3079197007Sdelphij/*
3080197007Sdelphij * REMARKS:
3081197007Sdelphij * Handles opcode 0xbc
3082197007Sdelphij */
3083197007Sdelphijstatic void
3084197007Sdelphijx86emuOp_mov_word_SP_IMM(struct x86emu *emu)
3085197007Sdelphij{
3086197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3087197007Sdelphij		emu->x86.R_ESP = fetch_long_imm(emu);
3088197007Sdelphij	else
3089197007Sdelphij		emu->x86.R_SP = fetch_word_imm(emu);
3090197007Sdelphij}
3091197007Sdelphij
3092197007Sdelphij/*
3093197007Sdelphij * REMARKS:
3094197007Sdelphij * Handles opcode 0xbd
3095197007Sdelphij */
3096197007Sdelphijstatic void
3097197007Sdelphijx86emuOp_mov_word_BP_IMM(struct x86emu *emu)
3098197007Sdelphij{
3099197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3100197007Sdelphij		emu->x86.R_EBP = fetch_long_imm(emu);
3101197007Sdelphij	else
3102197007Sdelphij		emu->x86.R_BP = fetch_word_imm(emu);
3103197007Sdelphij}
3104197007Sdelphij
3105197007Sdelphij/*
3106197007Sdelphij * REMARKS:
3107197007Sdelphij * Handles opcode 0xbe
3108197007Sdelphij */
3109197007Sdelphijstatic void
3110197007Sdelphijx86emuOp_mov_word_SI_IMM(struct x86emu *emu)
3111197007Sdelphij{
3112197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3113197007Sdelphij		emu->x86.R_ESI = fetch_long_imm(emu);
3114197007Sdelphij	else
3115197007Sdelphij		emu->x86.R_SI = fetch_word_imm(emu);
3116197007Sdelphij}
3117197007Sdelphij
3118197007Sdelphij/*
3119197007Sdelphij * REMARKS:
3120197007Sdelphij * Handles opcode 0xbf
3121197007Sdelphij */
3122197007Sdelphijstatic void
3123197007Sdelphijx86emuOp_mov_word_DI_IMM(struct x86emu *emu)
3124197007Sdelphij{
3125197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3126197007Sdelphij		emu->x86.R_EDI = fetch_long_imm(emu);
3127197007Sdelphij	else
3128197007Sdelphij		emu->x86.R_DI = fetch_word_imm(emu);
3129197007Sdelphij}
3130197007Sdelphij/* used by opcodes c0, d0, and d2. */
3131197007Sdelphijstatic
3132204934Sdelphijuint8_t(* const opcD0_byte_operation[])
3133204934Sdelphij    (struct x86emu *, uint8_t d, uint8_t s) =
3134197007Sdelphij{
3135197007Sdelphij	rol_byte,
3136197007Sdelphij	ror_byte,
3137197007Sdelphij	rcl_byte,
3138197007Sdelphij	rcr_byte,
3139197007Sdelphij	shl_byte,
3140197007Sdelphij	shr_byte,
3141197007Sdelphij	shl_byte,		/* sal_byte === shl_byte  by definition */
3142197007Sdelphij	sar_byte,
3143197007Sdelphij};
3144197007Sdelphij
3145197007Sdelphij/*
3146197007Sdelphij * REMARKS:
3147197007Sdelphij * Handles opcode 0xc0
3148197007Sdelphij */
3149197007Sdelphijstatic void
3150197007Sdelphijx86emuOp_opcC0_byte_RM_MEM(struct x86emu *emu)
3151197007Sdelphij{
3152197007Sdelphij	uint8_t destval, amt;
3153197007Sdelphij
3154197007Sdelphij	/*
3155197007Sdelphij         * Yet another weirdo special case instruction format.  Part of
3156197007Sdelphij         * the opcode held below in "RH".  Doubly nested case would
3157197007Sdelphij         * result, except that the decoded instruction
3158197007Sdelphij         */
3159197007Sdelphij	fetch_decode_modrm(emu);
3160197007Sdelphij	/* know operation, decode the mod byte to find the addressing mode. */
3161197007Sdelphij	destval = decode_and_fetch_byte_imm8(emu, &amt);
3162197007Sdelphij	destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, amt);
3163197007Sdelphij	write_back_byte(emu, destval);
3164197007Sdelphij}
3165197007Sdelphij/* used by opcodes c1, d1, and d3. */
3166197007Sdelphijstatic
3167204934Sdelphijuint16_t(* const opcD1_word_operation[])
3168204934Sdelphij    (struct x86emu *, uint16_t s, uint8_t d) =
3169197007Sdelphij{
3170197007Sdelphij	rol_word,
3171197007Sdelphij	ror_word,
3172197007Sdelphij	rcl_word,
3173197007Sdelphij	rcr_word,
3174197007Sdelphij	shl_word,
3175197007Sdelphij	shr_word,
3176197007Sdelphij	shl_word,		/* sal_byte === shl_byte  by definition */
3177197007Sdelphij	sar_word,
3178197007Sdelphij};
3179197007Sdelphij/* used by opcodes c1, d1, and d3. */
3180197007Sdelphijstatic
3181204934Sdelphijuint32_t(* const opcD1_long_operation[])
3182204934Sdelphij    (struct x86emu *, uint32_t s, uint8_t d) =
3183197007Sdelphij{
3184197007Sdelphij	rol_long,
3185197007Sdelphij	ror_long,
3186197007Sdelphij	rcl_long,
3187197007Sdelphij	rcr_long,
3188197007Sdelphij	shl_long,
3189197007Sdelphij	shr_long,
3190197007Sdelphij	shl_long,		/* sal_byte === shl_byte  by definition */
3191197007Sdelphij	sar_long,
3192197007Sdelphij};
3193197007Sdelphij
3194197007Sdelphij/*
3195197007Sdelphij * REMARKS:
3196197007Sdelphij * Handles opcode 0xc1
3197197007Sdelphij */
3198197007Sdelphijstatic void
3199197007Sdelphijx86emuOp_opcC1_word_RM_MEM(struct x86emu *emu)
3200197007Sdelphij{
3201197007Sdelphij	uint8_t amt;
3202197007Sdelphij
3203197007Sdelphij	/*
3204197007Sdelphij         * Yet another weirdo special case instruction format.  Part of
3205197007Sdelphij         * the opcode held below in "RH".  Doubly nested case would
3206197007Sdelphij         * result, except that the decoded instruction
3207197007Sdelphij         */
3208197007Sdelphij	fetch_decode_modrm(emu);
3209197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3210197007Sdelphij		uint32_t destval;
3211197007Sdelphij
3212197007Sdelphij		destval = decode_and_fetch_long_imm8(emu, &amt);
3213204934Sdelphij		destval = (*opcD1_long_operation[emu->cur_rh])
3214204934Sdelphij		    (emu, destval, amt);
3215197007Sdelphij		write_back_long(emu, destval);
3216197007Sdelphij	} else {
3217197007Sdelphij		uint16_t destval;
3218197007Sdelphij
3219197007Sdelphij		destval = decode_and_fetch_word_imm8(emu, &amt);
3220204934Sdelphij		destval = (*opcD1_word_operation[emu->cur_rh])
3221204934Sdelphij		    (emu, destval, amt);
3222197007Sdelphij		write_back_word(emu, destval);
3223197007Sdelphij	}
3224197007Sdelphij}
3225197007Sdelphij
3226197007Sdelphij/*
3227197007Sdelphij * REMARKS:
3228197007Sdelphij * Handles opcode 0xc2
3229197007Sdelphij */
3230197007Sdelphijstatic void
3231197007Sdelphijx86emuOp_ret_near_IMM(struct x86emu *emu)
3232197007Sdelphij{
3233197007Sdelphij	uint16_t imm;
3234197007Sdelphij
3235197007Sdelphij	imm = fetch_word_imm(emu);
3236197007Sdelphij	emu->x86.R_IP = pop_word(emu);
3237197007Sdelphij	emu->x86.R_SP += imm;
3238197007Sdelphij}
3239197007Sdelphij
3240197007Sdelphij/*
3241197007Sdelphij * REMARKS:
3242197007Sdelphij * Handles opcode 0xc6
3243197007Sdelphij */
3244197007Sdelphijstatic void
3245197007Sdelphijx86emuOp_mov_byte_RM_IMM(struct x86emu *emu)
3246197007Sdelphij{
3247197007Sdelphij	uint8_t *destreg;
3248197007Sdelphij	uint32_t destoffset;
3249197007Sdelphij	uint8_t imm;
3250197007Sdelphij
3251197007Sdelphij	fetch_decode_modrm(emu);
3252197007Sdelphij	if (emu->cur_rh != 0)
3253197007Sdelphij		x86emu_halt_sys(emu);
3254197007Sdelphij	if (emu->cur_mod != 3) {
3255197007Sdelphij		destoffset = decode_rl_address(emu);
3256197007Sdelphij		imm = fetch_byte_imm(emu);
3257197007Sdelphij		store_data_byte(emu, destoffset, imm);
3258197007Sdelphij	} else {
3259197007Sdelphij		destreg = decode_rl_byte_register(emu);
3260197007Sdelphij		imm = fetch_byte_imm(emu);
3261197007Sdelphij		*destreg = imm;
3262197007Sdelphij	}
3263197007Sdelphij}
3264197007Sdelphij
3265197007Sdelphij/*
3266197007Sdelphij * REMARKS:
3267197007Sdelphij * Handles opcode 0xc7
3268197007Sdelphij */
3269197007Sdelphijstatic void
3270197007Sdelphijx86emuOp32_mov_word_RM_IMM(struct x86emu *emu)
3271197007Sdelphij{
3272197007Sdelphij	uint32_t destoffset;
3273197007Sdelphij	uint32_t imm, *destreg;
3274197007Sdelphij
3275197007Sdelphij	fetch_decode_modrm(emu);
3276197007Sdelphij	if (emu->cur_rh != 0)
3277197007Sdelphij		x86emu_halt_sys(emu);
3278197007Sdelphij
3279197007Sdelphij	if (emu->cur_mod != 3) {
3280197007Sdelphij		destoffset = decode_rl_address(emu);
3281197007Sdelphij		imm = fetch_long_imm(emu);
3282197007Sdelphij		store_data_long(emu, destoffset, imm);
3283197007Sdelphij	} else {
3284197007Sdelphij		destreg = decode_rl_long_register(emu);
3285197007Sdelphij		imm = fetch_long_imm(emu);
3286197007Sdelphij		*destreg = imm;
3287197007Sdelphij	}
3288197007Sdelphij}
3289197007Sdelphij
3290197007Sdelphijstatic void
3291197007Sdelphijx86emuOp16_mov_word_RM_IMM(struct x86emu *emu)
3292197007Sdelphij{
3293197007Sdelphij	uint32_t destoffset;
3294197007Sdelphij	uint16_t imm, *destreg;
3295197007Sdelphij
3296197007Sdelphij	fetch_decode_modrm(emu);
3297197007Sdelphij	if (emu->cur_rh != 0)
3298197007Sdelphij		x86emu_halt_sys(emu);
3299197007Sdelphij
3300197007Sdelphij	if (emu->cur_mod != 3) {
3301197007Sdelphij		destoffset = decode_rl_address(emu);
3302197007Sdelphij		imm = fetch_word_imm(emu);
3303197007Sdelphij		store_data_word(emu, destoffset, imm);
3304197007Sdelphij	} else {
3305197007Sdelphij		destreg = decode_rl_word_register(emu);
3306197007Sdelphij		imm = fetch_word_imm(emu);
3307197007Sdelphij		*destreg = imm;
3308197007Sdelphij	}
3309197007Sdelphij}
3310197007Sdelphij
3311197007Sdelphijstatic void
3312197007Sdelphijx86emuOp_mov_word_RM_IMM(struct x86emu *emu)
3313197007Sdelphij{
3314197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3315197007Sdelphij		x86emuOp32_mov_word_RM_IMM(emu);
3316197007Sdelphij	else
3317197007Sdelphij		x86emuOp16_mov_word_RM_IMM(emu);
3318197007Sdelphij}
3319197007Sdelphij
3320197007Sdelphij/*
3321197007Sdelphij * REMARKS:
3322197007Sdelphij * Handles opcode 0xc8
3323197007Sdelphij */
3324197007Sdelphijstatic void
3325197007Sdelphijx86emuOp_enter(struct x86emu *emu)
3326197007Sdelphij{
3327197007Sdelphij	uint16_t local, frame_pointer;
3328197007Sdelphij	uint8_t nesting;
3329197007Sdelphij	int i;
3330197007Sdelphij
3331197007Sdelphij	local = fetch_word_imm(emu);
3332197007Sdelphij	nesting = fetch_byte_imm(emu);
3333197007Sdelphij	push_word(emu, emu->x86.R_BP);
3334197007Sdelphij	frame_pointer = emu->x86.R_SP;
3335197007Sdelphij	if (nesting > 0) {
3336197007Sdelphij		for (i = 1; i < nesting; i++) {
3337197007Sdelphij			emu->x86.R_BP -= 2;
3338204934Sdelphij			push_word(emu, fetch_word(emu, emu->x86.R_SS,
3339204934Sdelphij			    emu->x86.R_BP));
3340197007Sdelphij		}
3341197007Sdelphij		push_word(emu, frame_pointer);
3342197007Sdelphij	}
3343197007Sdelphij	emu->x86.R_BP = frame_pointer;
3344197007Sdelphij	emu->x86.R_SP = (uint16_t) (emu->x86.R_SP - local);
3345197007Sdelphij}
3346197007Sdelphij
3347197007Sdelphij/*
3348197007Sdelphij * REMARKS:
3349197007Sdelphij * Handles opcode 0xc9
3350197007Sdelphij */
3351197007Sdelphijstatic void
3352197007Sdelphijx86emuOp_leave(struct x86emu *emu)
3353197007Sdelphij{
3354197007Sdelphij	emu->x86.R_SP = emu->x86.R_BP;
3355197007Sdelphij	emu->x86.R_BP = pop_word(emu);
3356197007Sdelphij}
3357197007Sdelphij
3358197007Sdelphij/*
3359197007Sdelphij * REMARKS:
3360197007Sdelphij * Handles opcode 0xca
3361197007Sdelphij */
3362197007Sdelphijstatic void
3363197007Sdelphijx86emuOp_ret_far_IMM(struct x86emu *emu)
3364197007Sdelphij{
3365197007Sdelphij	uint16_t imm;
3366197007Sdelphij
3367197007Sdelphij	imm = fetch_word_imm(emu);
3368197007Sdelphij	emu->x86.R_IP = pop_word(emu);
3369197007Sdelphij	emu->x86.R_CS = pop_word(emu);
3370197007Sdelphij	emu->x86.R_SP += imm;
3371197007Sdelphij}
3372197007Sdelphij
3373197007Sdelphij/*
3374197007Sdelphij * REMARKS:
3375197007Sdelphij * Handles opcode 0xcb
3376197007Sdelphij */
3377197007Sdelphijstatic void
3378197007Sdelphijx86emuOp_ret_far(struct x86emu *emu)
3379197007Sdelphij{
3380197007Sdelphij	emu->x86.R_IP = pop_word(emu);
3381197007Sdelphij	emu->x86.R_CS = pop_word(emu);
3382197007Sdelphij}
3383197007Sdelphij
3384197007Sdelphij/*
3385197007Sdelphij * REMARKS:
3386197007Sdelphij * Handles opcode 0xcc
3387197007Sdelphij */
3388197007Sdelphijstatic void
3389197007Sdelphijx86emuOp_int3(struct x86emu *emu)
3390197007Sdelphij{
3391197007Sdelphij	x86emu_intr_dispatch(emu, 3);
3392197007Sdelphij}
3393197007Sdelphij
3394197007Sdelphij/*
3395197007Sdelphij * REMARKS:
3396197007Sdelphij * Handles opcode 0xcd
3397197007Sdelphij */
3398197007Sdelphijstatic void
3399197007Sdelphijx86emuOp_int_IMM(struct x86emu *emu)
3400197007Sdelphij{
3401197007Sdelphij	uint8_t intnum;
3402197007Sdelphij
3403197007Sdelphij	intnum = fetch_byte_imm(emu);
3404197007Sdelphij	x86emu_intr_dispatch(emu, intnum);
3405197007Sdelphij}
3406197007Sdelphij
3407197007Sdelphij/*
3408197007Sdelphij * REMARKS:
3409197007Sdelphij * Handles opcode 0xce
3410197007Sdelphij */
3411197007Sdelphijstatic void
3412197007Sdelphijx86emuOp_into(struct x86emu *emu)
3413197007Sdelphij{
3414197007Sdelphij	if (ACCESS_FLAG(F_OF))
3415197007Sdelphij		x86emu_intr_dispatch(emu, 4);
3416197007Sdelphij}
3417197007Sdelphij
3418197007Sdelphij/*
3419197007Sdelphij * REMARKS:
3420197007Sdelphij * Handles opcode 0xcf
3421197007Sdelphij */
3422197007Sdelphijstatic void
3423197007Sdelphijx86emuOp_iret(struct x86emu *emu)
3424197007Sdelphij{
3425197007Sdelphij	emu->x86.R_IP = pop_word(emu);
3426197007Sdelphij	emu->x86.R_CS = pop_word(emu);
3427197007Sdelphij	emu->x86.R_FLG = pop_word(emu);
3428197007Sdelphij}
3429197007Sdelphij
3430197007Sdelphij/*
3431197007Sdelphij * REMARKS:
3432197007Sdelphij * Handles opcode 0xd0
3433197007Sdelphij */
3434197007Sdelphijstatic void
3435197007Sdelphijx86emuOp_opcD0_byte_RM_1(struct x86emu *emu)
3436197007Sdelphij{
3437197007Sdelphij	uint8_t destval;
3438197007Sdelphij
3439197007Sdelphij	fetch_decode_modrm(emu);
3440197007Sdelphij	destval = decode_and_fetch_byte(emu);
3441197007Sdelphij	destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, 1);
3442197007Sdelphij	write_back_byte(emu, destval);
3443197007Sdelphij}
3444197007Sdelphij
3445197007Sdelphij/*
3446197007Sdelphij * REMARKS:
3447197007Sdelphij * Handles opcode 0xd1
3448197007Sdelphij */
3449197007Sdelphijstatic void
3450197007Sdelphijx86emuOp_opcD1_word_RM_1(struct x86emu *emu)
3451197007Sdelphij{
3452197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3453197007Sdelphij		uint32_t destval;
3454197007Sdelphij
3455197007Sdelphij		fetch_decode_modrm(emu);
3456197007Sdelphij		destval = decode_and_fetch_long(emu);
3457204934Sdelphij		destval = (*opcD1_long_operation[emu->cur_rh])(emu, destval, 1);
3458197007Sdelphij		write_back_long(emu, destval);
3459197007Sdelphij	} else {
3460197007Sdelphij		uint16_t destval;
3461197007Sdelphij
3462197007Sdelphij		fetch_decode_modrm(emu);
3463197007Sdelphij		destval = decode_and_fetch_word(emu);
3464204934Sdelphij		destval = (*opcD1_word_operation[emu->cur_rh])(emu, destval, 1);
3465197007Sdelphij		write_back_word(emu, destval);
3466197007Sdelphij	}
3467197007Sdelphij}
3468197007Sdelphij
3469197007Sdelphij/*
3470197007Sdelphij * REMARKS:
3471197007Sdelphij * Handles opcode 0xd2
3472197007Sdelphij */
3473197007Sdelphijstatic void
3474197007Sdelphijx86emuOp_opcD2_byte_RM_CL(struct x86emu *emu)
3475197007Sdelphij{
3476197007Sdelphij	uint8_t destval;
3477197007Sdelphij
3478197007Sdelphij	fetch_decode_modrm(emu);
3479197007Sdelphij	destval = decode_and_fetch_byte(emu);
3480204934Sdelphij	destval = (*opcD0_byte_operation[emu->cur_rh])
3481204934Sdelphij	    (emu, destval, emu->x86.R_CL);
3482197007Sdelphij	write_back_byte(emu, destval);
3483197007Sdelphij}
3484197007Sdelphij
3485197007Sdelphij/*
3486197007Sdelphij * REMARKS:
3487197007Sdelphij * Handles opcode 0xd3
3488197007Sdelphij */
3489197007Sdelphijstatic void
3490197007Sdelphijx86emuOp_opcD3_word_RM_CL(struct x86emu *emu)
3491197007Sdelphij{
3492197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3493197007Sdelphij		uint32_t destval;
3494197007Sdelphij
3495197007Sdelphij		fetch_decode_modrm(emu);
3496197007Sdelphij		destval = decode_and_fetch_long(emu);
3497204934Sdelphij		destval = (*opcD1_long_operation[emu->cur_rh])
3498204934Sdelphij		    (emu, destval, emu->x86.R_CL);
3499197007Sdelphij		write_back_long(emu, destval);
3500197007Sdelphij	} else {
3501197007Sdelphij		uint16_t destval;
3502197007Sdelphij
3503197007Sdelphij		fetch_decode_modrm(emu);
3504197007Sdelphij		destval = decode_and_fetch_word(emu);
3505204934Sdelphij		destval = (*opcD1_word_operation[emu->cur_rh])
3506204934Sdelphij		    (emu, destval, emu->x86.R_CL);
3507197007Sdelphij		write_back_word(emu, destval);
3508197007Sdelphij	}
3509197007Sdelphij}
3510197007Sdelphij
3511197007Sdelphij/*
3512197007Sdelphij * REMARKS:
3513197007Sdelphij * Handles opcode 0xd4
3514197007Sdelphij */
3515197007Sdelphijstatic void
3516197007Sdelphijx86emuOp_aam(struct x86emu *emu)
3517197007Sdelphij{
3518197007Sdelphij	uint8_t a;
3519197007Sdelphij
3520197007Sdelphij	a = fetch_byte_imm(emu);	/* this is a stupid encoding. */
3521197007Sdelphij	if (a != 10) {
3522197007Sdelphij		/* fix: add base decoding aam_word(uint8_t val, int base a) */
3523197007Sdelphij		x86emu_halt_sys(emu);
3524197007Sdelphij	}
3525197007Sdelphij	/* note the type change here --- returning AL and AH in AX. */
3526197007Sdelphij	emu->x86.R_AX = aam_word(emu, emu->x86.R_AL);
3527197007Sdelphij}
3528197007Sdelphij
3529197007Sdelphij/*
3530197007Sdelphij * REMARKS:
3531197007Sdelphij * Handles opcode 0xd5
3532197007Sdelphij */
3533197007Sdelphijstatic void
3534197007Sdelphijx86emuOp_aad(struct x86emu *emu)
3535197007Sdelphij{
3536197007Sdelphij	uint8_t a;
3537197007Sdelphij
3538197007Sdelphij	a = fetch_byte_imm(emu);
3539197007Sdelphij	if (a != 10) {
3540197007Sdelphij		/* fix: add base decoding aad_word(uint16_t val, int base a) */
3541197007Sdelphij		x86emu_halt_sys(emu);
3542197007Sdelphij	}
3543197007Sdelphij	emu->x86.R_AX = aad_word(emu, emu->x86.R_AX);
3544197007Sdelphij}
3545197007Sdelphij/* opcode 0xd6 ILLEGAL OPCODE */
3546197007Sdelphij
3547197007Sdelphij
3548197007Sdelphij/*
3549197007Sdelphij * REMARKS:
3550197007Sdelphij * Handles opcode 0xd7
3551197007Sdelphij */
3552197007Sdelphijstatic void
3553197007Sdelphijx86emuOp_xlat(struct x86emu *emu)
3554197007Sdelphij{
3555197007Sdelphij	uint16_t addr;
3556197007Sdelphij
3557197007Sdelphij	addr = (uint16_t) (emu->x86.R_BX + (uint8_t) emu->x86.R_AL);
3558197007Sdelphij	emu->x86.R_AL = fetch_data_byte(emu, addr);
3559197007Sdelphij}
3560197007Sdelphij
3561197007Sdelphij/* opcode=0xd8 */
3562197007Sdelphijstatic void
3563197007Sdelphijx86emuOp_esc_coprocess_d8(struct x86emu *emu)
3564197007Sdelphij{
3565197007Sdelphij}
3566197007Sdelphij/* opcode=0xd9 */
3567197007Sdelphijstatic void
3568197007Sdelphijx86emuOp_esc_coprocess_d9(struct x86emu *emu)
3569197007Sdelphij{
3570197007Sdelphij	fetch_decode_modrm(emu);
3571197007Sdelphij	if (emu->cur_mod != 3)
3572197007Sdelphij		decode_rl_address(emu);
3573197007Sdelphij}
3574197007Sdelphij/* opcode=0xda */
3575197007Sdelphijstatic void
3576197007Sdelphijx86emuOp_esc_coprocess_da(struct x86emu *emu)
3577197007Sdelphij{
3578197007Sdelphij	fetch_decode_modrm(emu);
3579197007Sdelphij	if (emu->cur_mod != 3)
3580197007Sdelphij		decode_rl_address(emu);
3581197007Sdelphij}
3582197007Sdelphij/* opcode=0xdb */
3583197007Sdelphijstatic void
3584197007Sdelphijx86emuOp_esc_coprocess_db(struct x86emu *emu)
3585197007Sdelphij{
3586197007Sdelphij	fetch_decode_modrm(emu);
3587197007Sdelphij	if (emu->cur_mod != 3)
3588197007Sdelphij		decode_rl_address(emu);
3589197007Sdelphij}
3590197007Sdelphij/* opcode=0xdc */
3591197007Sdelphijstatic void
3592197007Sdelphijx86emuOp_esc_coprocess_dc(struct x86emu *emu)
3593197007Sdelphij{
3594197007Sdelphij	fetch_decode_modrm(emu);
3595197007Sdelphij	if (emu->cur_mod != 3)
3596197007Sdelphij		decode_rl_address(emu);
3597197007Sdelphij}
3598197007Sdelphij/* opcode=0xdd */
3599197007Sdelphijstatic void
3600197007Sdelphijx86emuOp_esc_coprocess_dd(struct x86emu *emu)
3601197007Sdelphij{
3602197007Sdelphij	fetch_decode_modrm(emu);
3603197007Sdelphij	if (emu->cur_mod != 3)
3604197007Sdelphij		decode_rl_address(emu);
3605197007Sdelphij}
3606197007Sdelphij/* opcode=0xde */
3607197007Sdelphijstatic void
3608197007Sdelphijx86emuOp_esc_coprocess_de(struct x86emu *emu)
3609197007Sdelphij{
3610197007Sdelphij	fetch_decode_modrm(emu);
3611197007Sdelphij	if (emu->cur_mod != 3)
3612197007Sdelphij		decode_rl_address(emu);
3613197007Sdelphij}
3614197007Sdelphij/* opcode=0xdf */
3615197007Sdelphijstatic void
3616197007Sdelphijx86emuOp_esc_coprocess_df(struct x86emu *emu)
3617197007Sdelphij{
3618197007Sdelphij	fetch_decode_modrm(emu);
3619197007Sdelphij	if (emu->cur_mod != 3)
3620197007Sdelphij		decode_rl_address(emu);
3621197007Sdelphij}
3622197007Sdelphij
3623197007Sdelphij
3624197007Sdelphij/*
3625197007Sdelphij * REMARKS:
3626197007Sdelphij * Handles opcode 0xe0
3627197007Sdelphij */
3628197007Sdelphijstatic void
3629197007Sdelphijx86emuOp_loopne(struct x86emu *emu)
3630197007Sdelphij{
3631197007Sdelphij	int16_t ip;
3632197007Sdelphij
3633197007Sdelphij	ip = (int8_t) fetch_byte_imm(emu);
3634197007Sdelphij	ip += (int16_t) emu->x86.R_IP;
3635197007Sdelphij	emu->x86.R_CX -= 1;
3636197007Sdelphij	if (emu->x86.R_CX != 0 && !ACCESS_FLAG(F_ZF))	/* CX != 0 and !ZF */
3637197007Sdelphij		emu->x86.R_IP = ip;
3638197007Sdelphij}
3639197007Sdelphij
3640197007Sdelphij/*
3641197007Sdelphij * REMARKS:
3642197007Sdelphij * Handles opcode 0xe1
3643197007Sdelphij */
3644197007Sdelphijstatic void
3645197007Sdelphijx86emuOp_loope(struct x86emu *emu)
3646197007Sdelphij{
3647197007Sdelphij	int16_t ip;
3648197007Sdelphij
3649197007Sdelphij	ip = (int8_t) fetch_byte_imm(emu);
3650197007Sdelphij	ip += (int16_t) emu->x86.R_IP;
3651197007Sdelphij	emu->x86.R_CX -= 1;
3652197007Sdelphij	if (emu->x86.R_CX != 0 && ACCESS_FLAG(F_ZF))	/* CX != 0 and ZF */
3653197007Sdelphij		emu->x86.R_IP = ip;
3654197007Sdelphij}
3655197007Sdelphij
3656197007Sdelphij/*
3657197007Sdelphij * REMARKS:
3658197007Sdelphij * Handles opcode 0xe2
3659197007Sdelphij */
3660197007Sdelphijstatic void
3661197007Sdelphijx86emuOp_loop(struct x86emu *emu)
3662197007Sdelphij{
3663197007Sdelphij	int16_t ip;
3664197007Sdelphij
3665197007Sdelphij	ip = (int8_t) fetch_byte_imm(emu);
3666197007Sdelphij	ip += (int16_t) emu->x86.R_IP;
3667197007Sdelphij	emu->x86.R_CX -= 1;
3668197007Sdelphij	if (emu->x86.R_CX != 0)
3669197007Sdelphij		emu->x86.R_IP = ip;
3670197007Sdelphij}
3671197007Sdelphij
3672197007Sdelphij/*
3673197007Sdelphij * REMARKS:
3674197007Sdelphij * Handles opcode 0xe3
3675197007Sdelphij */
3676197007Sdelphijstatic void
3677197007Sdelphijx86emuOp_jcxz(struct x86emu *emu)
3678197007Sdelphij{
3679197007Sdelphij	uint16_t target;
3680197007Sdelphij	int8_t offset;
3681197007Sdelphij
3682197007Sdelphij	/* jump to byte offset if overflow flag is set */
3683197007Sdelphij	offset = (int8_t) fetch_byte_imm(emu);
3684197007Sdelphij	target = (uint16_t) (emu->x86.R_IP + offset);
3685197007Sdelphij	if (emu->x86.R_CX == 0)
3686197007Sdelphij		emu->x86.R_IP = target;
3687197007Sdelphij}
3688197007Sdelphij
3689197007Sdelphij/*
3690197007Sdelphij * REMARKS:
3691197007Sdelphij * Handles opcode 0xe4
3692197007Sdelphij */
3693197007Sdelphijstatic void
3694197007Sdelphijx86emuOp_in_byte_AL_IMM(struct x86emu *emu)
3695197007Sdelphij{
3696197007Sdelphij	uint8_t port;
3697197007Sdelphij
3698197007Sdelphij	port = (uint8_t) fetch_byte_imm(emu);
3699197007Sdelphij	emu->x86.R_AL = (*emu->emu_inb) (emu, port);
3700197007Sdelphij}
3701197007Sdelphij
3702197007Sdelphij/*
3703197007Sdelphij * REMARKS:
3704197007Sdelphij * Handles opcode 0xe5
3705197007Sdelphij */
3706197007Sdelphijstatic void
3707197007Sdelphijx86emuOp_in_word_AX_IMM(struct x86emu *emu)
3708197007Sdelphij{
3709197007Sdelphij	uint8_t port;
3710197007Sdelphij
3711197007Sdelphij	port = (uint8_t) fetch_byte_imm(emu);
3712197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3713197007Sdelphij		emu->x86.R_EAX = (*emu->emu_inl) (emu, port);
3714197007Sdelphij	} else {
3715197007Sdelphij		emu->x86.R_AX = (*emu->emu_inw) (emu, port);
3716197007Sdelphij	}
3717197007Sdelphij}
3718197007Sdelphij
3719197007Sdelphij/*
3720197007Sdelphij * REMARKS:
3721197007Sdelphij * Handles opcode 0xe6
3722197007Sdelphij */
3723197007Sdelphijstatic void
3724197007Sdelphijx86emuOp_out_byte_IMM_AL(struct x86emu *emu)
3725197007Sdelphij{
3726197007Sdelphij	uint8_t port;
3727197007Sdelphij
3728197007Sdelphij	port = (uint8_t) fetch_byte_imm(emu);
3729197007Sdelphij	(*emu->emu_outb) (emu, port, emu->x86.R_AL);
3730197007Sdelphij}
3731197007Sdelphij
3732197007Sdelphij/*
3733197007Sdelphij * REMARKS:
3734197007Sdelphij * Handles opcode 0xe7
3735197007Sdelphij */
3736197007Sdelphijstatic void
3737197007Sdelphijx86emuOp_out_word_IMM_AX(struct x86emu *emu)
3738197007Sdelphij{
3739197007Sdelphij	uint8_t port;
3740197007Sdelphij
3741197007Sdelphij	port = (uint8_t) fetch_byte_imm(emu);
3742197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3743197007Sdelphij		(*emu->emu_outl) (emu, port, emu->x86.R_EAX);
3744197007Sdelphij	} else {
3745197007Sdelphij		(*emu->emu_outw) (emu, port, emu->x86.R_AX);
3746197007Sdelphij	}
3747197007Sdelphij}
3748197007Sdelphij
3749197007Sdelphij/*
3750197007Sdelphij * REMARKS:
3751197007Sdelphij * Handles opcode 0xe8
3752197007Sdelphij */
3753197007Sdelphijstatic void
3754197007Sdelphijx86emuOp_call_near_IMM(struct x86emu *emu)
3755197007Sdelphij{
3756267374Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3757267374Sdelphij		int32_t ip;
3758267374Sdelphij		ip = (int32_t) fetch_long_imm(emu);
3759267374Sdelphij		ip += (int32_t) emu->x86.R_EIP;
3760267374Sdelphij		push_long(emu, emu->x86.R_EIP);
3761267374Sdelphij		emu->x86.R_EIP = ip;
3762267374Sdelphij	} else {
3763267374Sdelphij		int16_t ip;
3764267374Sdelphij		ip = (int16_t) fetch_word_imm(emu);
3765267374Sdelphij		ip += (int16_t) emu->x86.R_IP;	/* CHECK SIGN */
3766267374Sdelphij		push_word(emu, emu->x86.R_IP);
3767267374Sdelphij		emu->x86.R_IP = ip;
3768267374Sdelphij	}
3769197007Sdelphij}
3770197007Sdelphij
3771197007Sdelphij/*
3772197007Sdelphij * REMARKS:
3773197007Sdelphij * Handles opcode 0xe9
3774197007Sdelphij */
3775197007Sdelphijstatic void
3776197007Sdelphijx86emuOp_jump_near_IMM(struct x86emu *emu)
3777197007Sdelphij{
3778197007Sdelphij	int ip;
3779197007Sdelphij
3780197007Sdelphij	ip = (int16_t) fetch_word_imm(emu);
3781197007Sdelphij	ip += (int16_t) emu->x86.R_IP;
3782197007Sdelphij	emu->x86.R_IP = (uint16_t) ip;
3783197007Sdelphij}
3784197007Sdelphij
3785197007Sdelphij/*
3786197007Sdelphij * REMARKS:
3787197007Sdelphij * Handles opcode 0xea
3788197007Sdelphij */
3789197007Sdelphijstatic void
3790197007Sdelphijx86emuOp_jump_far_IMM(struct x86emu *emu)
3791197007Sdelphij{
3792197007Sdelphij	uint16_t cs, ip;
3793197007Sdelphij
3794197007Sdelphij	ip = fetch_word_imm(emu);
3795197007Sdelphij	cs = fetch_word_imm(emu);
3796197007Sdelphij	emu->x86.R_IP = ip;
3797197007Sdelphij	emu->x86.R_CS = cs;
3798197007Sdelphij}
3799197007Sdelphij
3800197007Sdelphij/*
3801197007Sdelphij * REMARKS:
3802197007Sdelphij * Handles opcode 0xeb
3803197007Sdelphij */
3804197007Sdelphijstatic void
3805197007Sdelphijx86emuOp_jump_byte_IMM(struct x86emu *emu)
3806197007Sdelphij{
3807197007Sdelphij	uint16_t target;
3808197007Sdelphij	int8_t offset;
3809197007Sdelphij
3810197007Sdelphij	offset = (int8_t) fetch_byte_imm(emu);
3811197007Sdelphij	target = (uint16_t) (emu->x86.R_IP + offset);
3812197007Sdelphij	emu->x86.R_IP = target;
3813197007Sdelphij}
3814197007Sdelphij
3815197007Sdelphij/*
3816197007Sdelphij * REMARKS:
3817197007Sdelphij * Handles opcode 0xec
3818197007Sdelphij */
3819197007Sdelphijstatic void
3820197007Sdelphijx86emuOp_in_byte_AL_DX(struct x86emu *emu)
3821197007Sdelphij{
3822197007Sdelphij	emu->x86.R_AL = (*emu->emu_inb) (emu, emu->x86.R_DX);
3823197007Sdelphij}
3824197007Sdelphij
3825197007Sdelphij/*
3826197007Sdelphij * REMARKS:
3827197007Sdelphij * Handles opcode 0xed
3828197007Sdelphij */
3829197007Sdelphijstatic void
3830197007Sdelphijx86emuOp_in_word_AX_DX(struct x86emu *emu)
3831197007Sdelphij{
3832197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3833197007Sdelphij		emu->x86.R_EAX = (*emu->emu_inl) (emu, emu->x86.R_DX);
3834197007Sdelphij	} else {
3835197007Sdelphij		emu->x86.R_AX = (*emu->emu_inw) (emu, emu->x86.R_DX);
3836197007Sdelphij	}
3837197007Sdelphij}
3838197007Sdelphij
3839197007Sdelphij/*
3840197007Sdelphij * REMARKS:
3841197007Sdelphij * Handles opcode 0xee
3842197007Sdelphij */
3843197007Sdelphijstatic void
3844197007Sdelphijx86emuOp_out_byte_DX_AL(struct x86emu *emu)
3845197007Sdelphij{
3846197007Sdelphij	(*emu->emu_outb) (emu, emu->x86.R_DX, emu->x86.R_AL);
3847197007Sdelphij}
3848197007Sdelphij
3849197007Sdelphij/*
3850197007Sdelphij * REMARKS:
3851197007Sdelphij * Handles opcode 0xef
3852197007Sdelphij */
3853197007Sdelphijstatic void
3854197007Sdelphijx86emuOp_out_word_DX_AX(struct x86emu *emu)
3855197007Sdelphij{
3856197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3857197007Sdelphij		(*emu->emu_outl) (emu, emu->x86.R_DX, emu->x86.R_EAX);
3858197007Sdelphij	} else {
3859197007Sdelphij		(*emu->emu_outw) (emu, emu->x86.R_DX, emu->x86.R_AX);
3860197007Sdelphij	}
3861197007Sdelphij}
3862197007Sdelphij
3863197007Sdelphij/*
3864197007Sdelphij * REMARKS:
3865197007Sdelphij * Handles opcode 0xf0
3866197007Sdelphij */
3867197007Sdelphijstatic void
3868197007Sdelphijx86emuOp_lock(struct x86emu *emu)
3869197007Sdelphij{
3870197007Sdelphij}
3871197007Sdelphij/*opcode 0xf1 ILLEGAL OPERATION */
3872197007Sdelphij
3873197007Sdelphij
3874197007Sdelphij/*
3875197007Sdelphij * REMARKS:
3876197007Sdelphij * Handles opcode 0xf5
3877197007Sdelphij */
3878197007Sdelphijstatic void
3879197007Sdelphijx86emuOp_cmc(struct x86emu *emu)
3880197007Sdelphij{
3881197007Sdelphij	if (ACCESS_FLAG(F_CF))
3882197007Sdelphij		CLEAR_FLAG(F_CF);
3883197007Sdelphij	else
3884197007Sdelphij		SET_FLAG(F_CF);
3885197007Sdelphij}
3886197007Sdelphij
3887197007Sdelphij/*
3888197007Sdelphij * REMARKS:
3889197007Sdelphij * Handles opcode 0xf6
3890197007Sdelphij */
3891197007Sdelphijstatic void
3892197007Sdelphijx86emuOp_opcF6_byte_RM(struct x86emu *emu)
3893197007Sdelphij{
3894197007Sdelphij	uint8_t destval, srcval;
3895197007Sdelphij
3896197007Sdelphij	/* long, drawn out code follows.  Double switch for a total of 32
3897197007Sdelphij	 * cases.  */
3898197007Sdelphij	fetch_decode_modrm(emu);
3899197007Sdelphij	if (emu->cur_rh == 1)
3900197007Sdelphij		x86emu_halt_sys(emu);
3901197007Sdelphij
3902197007Sdelphij	if (emu->cur_rh == 0) {
3903197007Sdelphij		destval = decode_and_fetch_byte_imm8(emu, &srcval);
3904197007Sdelphij		test_byte(emu, destval, srcval);
3905197007Sdelphij		return;
3906197007Sdelphij	}
3907197007Sdelphij	destval = decode_and_fetch_byte(emu);
3908197007Sdelphij	switch (emu->cur_rh) {
3909197007Sdelphij	case 2:
3910197007Sdelphij		destval = ~destval;
3911197007Sdelphij		write_back_byte(emu, destval);
3912197007Sdelphij		break;
3913197007Sdelphij	case 3:
3914197007Sdelphij		destval = neg_byte(emu, destval);
3915197007Sdelphij		write_back_byte(emu, destval);
3916197007Sdelphij		break;
3917197007Sdelphij	case 4:
3918197007Sdelphij		mul_byte(emu, destval);
3919197007Sdelphij		break;
3920197007Sdelphij	case 5:
3921197007Sdelphij		imul_byte(emu, destval);
3922197007Sdelphij		break;
3923197007Sdelphij	case 6:
3924197007Sdelphij		div_byte(emu, destval);
3925197007Sdelphij		break;
3926197007Sdelphij	case 7:
3927197007Sdelphij		idiv_byte(emu, destval);
3928197007Sdelphij		break;
3929197007Sdelphij	}
3930197007Sdelphij}
3931197007Sdelphij
3932197007Sdelphij/*
3933197007Sdelphij * REMARKS:
3934197007Sdelphij * Handles opcode 0xf7
3935197007Sdelphij */
3936197007Sdelphijstatic void
3937197007Sdelphijx86emuOp32_opcF7_word_RM(struct x86emu *emu)
3938197007Sdelphij{
3939197007Sdelphij	uint32_t destval, srcval;
3940197007Sdelphij
3941197007Sdelphij	/* long, drawn out code follows.  Double switch for a total of 32
3942197007Sdelphij	 * cases.  */
3943197007Sdelphij	fetch_decode_modrm(emu);
3944197007Sdelphij	if (emu->cur_rh == 1)
3945197007Sdelphij		x86emu_halt_sys(emu);
3946197007Sdelphij
3947197007Sdelphij	if (emu->cur_rh == 0) {
3948197007Sdelphij		if (emu->cur_mod != 3) {
3949197007Sdelphij			uint32_t destoffset;
3950197007Sdelphij
3951197007Sdelphij			destoffset = decode_rl_address(emu);
3952197007Sdelphij			srcval = fetch_long_imm(emu);
3953197007Sdelphij			destval = fetch_data_long(emu, destoffset);
3954197007Sdelphij		} else {
3955197007Sdelphij			srcval = fetch_long_imm(emu);
3956197007Sdelphij			destval = *decode_rl_long_register(emu);
3957197007Sdelphij		}
3958197007Sdelphij		test_long(emu, destval, srcval);
3959197007Sdelphij		return;
3960197007Sdelphij	}
3961197007Sdelphij	destval = decode_and_fetch_long(emu);
3962197007Sdelphij	switch (emu->cur_rh) {
3963197007Sdelphij	case 2:
3964197007Sdelphij		destval = ~destval;
3965197007Sdelphij		write_back_long(emu, destval);
3966197007Sdelphij		break;
3967197007Sdelphij	case 3:
3968197007Sdelphij		destval = neg_long(emu, destval);
3969197007Sdelphij		write_back_long(emu, destval);
3970197007Sdelphij		break;
3971197007Sdelphij	case 4:
3972197007Sdelphij		mul_long(emu, destval);
3973197007Sdelphij		break;
3974197007Sdelphij	case 5:
3975197007Sdelphij		imul_long(emu, destval);
3976197007Sdelphij		break;
3977197007Sdelphij	case 6:
3978197007Sdelphij		div_long(emu, destval);
3979197007Sdelphij		break;
3980197007Sdelphij	case 7:
3981197007Sdelphij		idiv_long(emu, destval);
3982197007Sdelphij		break;
3983197007Sdelphij	}
3984197007Sdelphij}
3985197007Sdelphijstatic void
3986197007Sdelphijx86emuOp16_opcF7_word_RM(struct x86emu *emu)
3987197007Sdelphij{
3988197007Sdelphij	uint16_t destval, srcval;
3989197007Sdelphij
3990197007Sdelphij	/* long, drawn out code follows.  Double switch for a total of 32
3991197007Sdelphij	 * cases.  */
3992197007Sdelphij	fetch_decode_modrm(emu);
3993197007Sdelphij	if (emu->cur_rh == 1)
3994197007Sdelphij		x86emu_halt_sys(emu);
3995197007Sdelphij
3996197007Sdelphij	if (emu->cur_rh == 0) {
3997197007Sdelphij		if (emu->cur_mod != 3) {
3998197007Sdelphij			uint32_t destoffset;
3999197007Sdelphij
4000197007Sdelphij			destoffset = decode_rl_address(emu);
4001197007Sdelphij			srcval = fetch_word_imm(emu);
4002197007Sdelphij			destval = fetch_data_word(emu, destoffset);
4003197007Sdelphij		} else {
4004197007Sdelphij			srcval = fetch_word_imm(emu);
4005197007Sdelphij			destval = *decode_rl_word_register(emu);
4006197007Sdelphij		}
4007197007Sdelphij		test_word(emu, destval, srcval);
4008197007Sdelphij		return;
4009197007Sdelphij	}
4010197007Sdelphij	destval = decode_and_fetch_word(emu);
4011197007Sdelphij	switch (emu->cur_rh) {
4012197007Sdelphij	case 2:
4013197007Sdelphij		destval = ~destval;
4014197007Sdelphij		write_back_word(emu, destval);
4015197007Sdelphij		break;
4016197007Sdelphij	case 3:
4017197007Sdelphij		destval = neg_word(emu, destval);
4018197007Sdelphij		write_back_word(emu, destval);
4019197007Sdelphij		break;
4020197007Sdelphij	case 4:
4021197007Sdelphij		mul_word(emu, destval);
4022197007Sdelphij		break;
4023197007Sdelphij	case 5:
4024197007Sdelphij		imul_word(emu, destval);
4025197007Sdelphij		break;
4026197007Sdelphij	case 6:
4027197007Sdelphij		div_word(emu, destval);
4028197007Sdelphij		break;
4029197007Sdelphij	case 7:
4030197007Sdelphij		idiv_word(emu, destval);
4031197007Sdelphij		break;
4032197007Sdelphij	}
4033197007Sdelphij}
4034197007Sdelphijstatic void
4035197007Sdelphijx86emuOp_opcF7_word_RM(struct x86emu *emu)
4036197007Sdelphij{
4037197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4038197007Sdelphij		x86emuOp32_opcF7_word_RM(emu);
4039197007Sdelphij	else
4040197007Sdelphij		x86emuOp16_opcF7_word_RM(emu);
4041197007Sdelphij}
4042197007Sdelphij
4043197007Sdelphij/*
4044197007Sdelphij * REMARKS:
4045197007Sdelphij * Handles opcode 0xfe
4046197007Sdelphij */
4047197007Sdelphijstatic void
4048197007Sdelphijx86emuOp_opcFE_byte_RM(struct x86emu *emu)
4049197007Sdelphij{
4050197007Sdelphij	uint8_t destval;
4051197007Sdelphij	uint32_t destoffset;
4052197007Sdelphij	uint8_t *destreg;
4053197007Sdelphij
4054197007Sdelphij	/* Yet another special case instruction. */
4055197007Sdelphij	fetch_decode_modrm(emu);
4056197007Sdelphij	if (emu->cur_mod != 3) {
4057197007Sdelphij		destoffset = decode_rl_address(emu);
4058197007Sdelphij		switch (emu->cur_rh) {
4059197007Sdelphij		case 0:	/* inc word ptr ... */
4060197007Sdelphij			destval = fetch_data_byte(emu, destoffset);
4061197007Sdelphij			destval = inc_byte(emu, destval);
4062197007Sdelphij			store_data_byte(emu, destoffset, destval);
4063197007Sdelphij			break;
4064197007Sdelphij		case 1:	/* dec word ptr ... */
4065197007Sdelphij			destval = fetch_data_byte(emu, destoffset);
4066197007Sdelphij			destval = dec_byte(emu, destval);
4067197007Sdelphij			store_data_byte(emu, destoffset, destval);
4068197007Sdelphij			break;
4069197007Sdelphij		}
4070197007Sdelphij	} else {
4071197007Sdelphij		destreg = decode_rl_byte_register(emu);
4072197007Sdelphij		switch (emu->cur_rh) {
4073197007Sdelphij		case 0:
4074197007Sdelphij			*destreg = inc_byte(emu, *destreg);
4075197007Sdelphij			break;
4076197007Sdelphij		case 1:
4077197007Sdelphij			*destreg = dec_byte(emu, *destreg);
4078197007Sdelphij			break;
4079197007Sdelphij		}
4080197007Sdelphij	}
4081197007Sdelphij}
4082197007Sdelphij
4083197007Sdelphij/*
4084197007Sdelphij * REMARKS:
4085197007Sdelphij * Handles opcode 0xff
4086197007Sdelphij */
4087197007Sdelphijstatic void
4088197007Sdelphijx86emuOp32_opcFF_word_RM(struct x86emu *emu)
4089197007Sdelphij{
4090197007Sdelphij	uint32_t destoffset = 0;
4091197007Sdelphij	uint32_t destval, *destreg;
4092197007Sdelphij
4093197007Sdelphij	if (emu->cur_mod != 3) {
4094197007Sdelphij		destoffset = decode_rl_address(emu);
4095197007Sdelphij		destval = fetch_data_long(emu, destoffset);
4096197007Sdelphij		switch (emu->cur_rh) {
4097197007Sdelphij		case 0:	/* inc word ptr ... */
4098197007Sdelphij			destval = inc_long(emu, destval);
4099197007Sdelphij			store_data_long(emu, destoffset, destval);
4100197007Sdelphij			break;
4101197007Sdelphij		case 1:	/* dec word ptr ... */
4102197007Sdelphij			destval = dec_long(emu, destval);
4103197007Sdelphij			store_data_long(emu, destoffset, destval);
4104197007Sdelphij			break;
4105197007Sdelphij		case 6:	/* push word ptr ... */
4106197007Sdelphij			push_long(emu, destval);
4107197007Sdelphij			break;
4108197007Sdelphij		}
4109197007Sdelphij	} else {
4110197007Sdelphij		destreg = decode_rl_long_register(emu);
4111197007Sdelphij		switch (emu->cur_rh) {
4112197007Sdelphij		case 0:
4113197007Sdelphij			*destreg = inc_long(emu, *destreg);
4114197007Sdelphij			break;
4115197007Sdelphij		case 1:
4116197007Sdelphij			*destreg = dec_long(emu, *destreg);
4117197007Sdelphij			break;
4118197007Sdelphij		case 6:
4119197007Sdelphij			push_long(emu, *destreg);
4120197007Sdelphij			break;
4121197007Sdelphij		}
4122197007Sdelphij	}
4123197007Sdelphij}
4124197007Sdelphij
4125197007Sdelphijstatic void
4126197007Sdelphijx86emuOp16_opcFF_word_RM(struct x86emu *emu)
4127197007Sdelphij{
4128197007Sdelphij	uint32_t destoffset = 0;
4129197007Sdelphij	uint16_t *destreg;
4130197007Sdelphij	uint16_t destval;
4131197007Sdelphij
4132197007Sdelphij	if (emu->cur_mod != 3) {
4133197007Sdelphij		destoffset = decode_rl_address(emu);
4134197007Sdelphij		destval = fetch_data_word(emu, destoffset);
4135197007Sdelphij		switch (emu->cur_rh) {
4136197007Sdelphij		case 0:
4137197007Sdelphij			destval = inc_word(emu, destval);
4138197007Sdelphij			store_data_word(emu, destoffset, destval);
4139197007Sdelphij			break;
4140197007Sdelphij		case 1:	/* dec word ptr ... */
4141197007Sdelphij			destval = dec_word(emu, destval);
4142197007Sdelphij			store_data_word(emu, destoffset, destval);
4143197007Sdelphij			break;
4144197007Sdelphij		case 6:	/* push word ptr ... */
4145197007Sdelphij			push_word(emu, destval);
4146197007Sdelphij			break;
4147197007Sdelphij		}
4148197007Sdelphij	} else {
4149197007Sdelphij		destreg = decode_rl_word_register(emu);
4150197007Sdelphij		switch (emu->cur_rh) {
4151197007Sdelphij		case 0:
4152197007Sdelphij			*destreg = inc_word(emu, *destreg);
4153197007Sdelphij			break;
4154197007Sdelphij		case 1:
4155197007Sdelphij			*destreg = dec_word(emu, *destreg);
4156197007Sdelphij			break;
4157197007Sdelphij		case 6:
4158197007Sdelphij			push_word(emu, *destreg);
4159197007Sdelphij			break;
4160197007Sdelphij		}
4161197007Sdelphij	}
4162197007Sdelphij}
4163197007Sdelphij
4164197007Sdelphijstatic void
4165197007Sdelphijx86emuOp_opcFF_word_RM(struct x86emu *emu)
4166197007Sdelphij{
4167197007Sdelphij	uint32_t destoffset = 0;
4168197007Sdelphij	uint16_t destval, destval2;
4169197007Sdelphij
4170197007Sdelphij	/* Yet another special case instruction. */
4171197007Sdelphij	fetch_decode_modrm(emu);
4172204934Sdelphij	if ((emu->cur_mod == 3 && (emu->cur_rh == 3 || emu->cur_rh == 5)) ||
4173204934Sdelphij	    emu->cur_rh == 7)
4174197007Sdelphij		x86emu_halt_sys(emu);
4175197007Sdelphij	if (emu->cur_rh == 0 || emu->cur_rh == 1 || emu->cur_rh == 6) {
4176197007Sdelphij		if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4177197007Sdelphij			x86emuOp32_opcFF_word_RM(emu);
4178197007Sdelphij		else
4179197007Sdelphij			x86emuOp16_opcFF_word_RM(emu);
4180197007Sdelphij		return;
4181197007Sdelphij	}
4182197007Sdelphij
4183197007Sdelphij	if (emu->cur_mod != 3) {
4184197007Sdelphij		destoffset = decode_rl_address(emu);
4185197007Sdelphij		destval = fetch_data_word(emu, destoffset);
4186197007Sdelphij		switch (emu->cur_rh) {
4187197007Sdelphij		case 3:	/* call far ptr ... */
4188197007Sdelphij			destval2 = fetch_data_word(emu, destoffset + 2);
4189197007Sdelphij			push_word(emu, emu->x86.R_CS);
4190197007Sdelphij			emu->x86.R_CS = destval2;
4191197007Sdelphij			push_word(emu, emu->x86.R_IP);
4192197007Sdelphij			emu->x86.R_IP = destval;
4193197007Sdelphij			break;
4194197007Sdelphij		case 5:	/* jmp far ptr ... */
4195197007Sdelphij			destval2 = fetch_data_word(emu, destoffset + 2);
4196197007Sdelphij			emu->x86.R_IP = destval;
4197197007Sdelphij			emu->x86.R_CS = destval2;
4198197007Sdelphij			break;
4199197007Sdelphij		}
4200197007Sdelphij	} else {
4201197007Sdelphij		destval = *decode_rl_word_register(emu);
4202197007Sdelphij	}
4203197007Sdelphij
4204197007Sdelphij	switch (emu->cur_rh) {
4205197007Sdelphij	case 2: /* call word ptr */
4206197007Sdelphij		push_word(emu, emu->x86.R_IP);
4207197007Sdelphij		emu->x86.R_IP = destval;
4208197007Sdelphij		break;
4209197007Sdelphij	case 4: /* jmp */
4210197007Sdelphij		emu->x86.R_IP = destval;
4211197007Sdelphij		break;
4212197007Sdelphij	}
4213197007Sdelphij}
4214197007Sdelphij
4215197007Sdelphij/*
4216197007Sdelphij *  * Single byte operation code table:
4217197007Sdelphij */
4218197007Sdelphijstatic void
4219197007Sdelphijx86emu_exec_one_byte(struct x86emu * emu)
4220197007Sdelphij{
4221197007Sdelphij	uint8_t op1;
4222197007Sdelphij
4223197007Sdelphij	op1 = fetch_byte_imm(emu);
4224197007Sdelphij
4225197007Sdelphij	switch (op1) {
4226197007Sdelphij	case 0x00:
4227197007Sdelphij		common_binop_byte_rm_r(emu, add_byte);
4228197007Sdelphij		break;
4229197007Sdelphij	case 0x01:
4230197007Sdelphij		common_binop_word_long_rm_r(emu, add_word, add_long);
4231197007Sdelphij		break;
4232197007Sdelphij	case 0x02:
4233197007Sdelphij		common_binop_byte_r_rm(emu, add_byte);
4234197007Sdelphij		break;
4235197007Sdelphij	case 0x03:
4236197007Sdelphij		common_binop_word_long_r_rm(emu, add_word, add_long);
4237197007Sdelphij		break;
4238197007Sdelphij	case 0x04:
4239197007Sdelphij		common_binop_byte_imm(emu, add_byte);
4240197007Sdelphij		break;
4241197007Sdelphij	case 0x05:
4242197007Sdelphij		common_binop_word_long_imm(emu, add_word, add_long);
4243197007Sdelphij		break;
4244197007Sdelphij	case 0x06:
4245197007Sdelphij		push_word(emu, emu->x86.R_ES);
4246197007Sdelphij		break;
4247197007Sdelphij	case 0x07:
4248197007Sdelphij		emu->x86.R_ES = pop_word(emu);
4249197007Sdelphij		break;
4250197007Sdelphij
4251197007Sdelphij	case 0x08:
4252197007Sdelphij		common_binop_byte_rm_r(emu, or_byte);
4253197007Sdelphij		break;
4254197007Sdelphij	case 0x09:
4255197007Sdelphij		common_binop_word_long_rm_r(emu, or_word, or_long);
4256197007Sdelphij		break;
4257197007Sdelphij	case 0x0a:
4258197007Sdelphij		common_binop_byte_r_rm(emu, or_byte);
4259197007Sdelphij		break;
4260197007Sdelphij	case 0x0b:
4261197007Sdelphij		common_binop_word_long_r_rm(emu, or_word, or_long);
4262197007Sdelphij		break;
4263197007Sdelphij	case 0x0c:
4264197007Sdelphij		common_binop_byte_imm(emu, or_byte);
4265197007Sdelphij		break;
4266197007Sdelphij	case 0x0d:
4267197007Sdelphij		common_binop_word_long_imm(emu, or_word, or_long);
4268197007Sdelphij		break;
4269197007Sdelphij	case 0x0e:
4270197007Sdelphij		push_word(emu, emu->x86.R_CS);
4271197007Sdelphij		break;
4272197007Sdelphij	case 0x0f:
4273197007Sdelphij		x86emu_exec_two_byte(emu);
4274197007Sdelphij		break;
4275197007Sdelphij
4276197007Sdelphij	case 0x10:
4277197007Sdelphij		common_binop_byte_rm_r(emu, adc_byte);
4278197007Sdelphij		break;
4279197007Sdelphij	case 0x11:
4280197007Sdelphij		common_binop_word_long_rm_r(emu, adc_word, adc_long);
4281197007Sdelphij		break;
4282197007Sdelphij	case 0x12:
4283197007Sdelphij		common_binop_byte_r_rm(emu, adc_byte);
4284197007Sdelphij		break;
4285197007Sdelphij	case 0x13:
4286197007Sdelphij		common_binop_word_long_r_rm(emu, adc_word, adc_long);
4287197007Sdelphij		break;
4288197007Sdelphij	case 0x14:
4289197007Sdelphij		common_binop_byte_imm(emu, adc_byte);
4290197007Sdelphij		break;
4291197007Sdelphij	case 0x15:
4292197007Sdelphij		common_binop_word_long_imm(emu, adc_word, adc_long);
4293197007Sdelphij		break;
4294197007Sdelphij	case 0x16:
4295197007Sdelphij		push_word(emu, emu->x86.R_SS);
4296197007Sdelphij		break;
4297197007Sdelphij	case 0x17:
4298197007Sdelphij		emu->x86.R_SS = pop_word(emu);
4299197007Sdelphij		break;
4300197007Sdelphij
4301197007Sdelphij	case 0x18:
4302197007Sdelphij		common_binop_byte_rm_r(emu, sbb_byte);
4303197007Sdelphij		break;
4304197007Sdelphij	case 0x19:
4305197007Sdelphij		common_binop_word_long_rm_r(emu, sbb_word, sbb_long);
4306197007Sdelphij		break;
4307197007Sdelphij	case 0x1a:
4308197007Sdelphij		common_binop_byte_r_rm(emu, sbb_byte);
4309197007Sdelphij		break;
4310197007Sdelphij	case 0x1b:
4311197007Sdelphij		common_binop_word_long_r_rm(emu, sbb_word, sbb_long);
4312197007Sdelphij		break;
4313197007Sdelphij	case 0x1c:
4314197007Sdelphij		common_binop_byte_imm(emu, sbb_byte);
4315197007Sdelphij		break;
4316197007Sdelphij	case 0x1d:
4317197007Sdelphij		common_binop_word_long_imm(emu, sbb_word, sbb_long);
4318197007Sdelphij		break;
4319197007Sdelphij	case 0x1e:
4320197007Sdelphij		push_word(emu, emu->x86.R_DS);
4321197007Sdelphij		break;
4322197007Sdelphij	case 0x1f:
4323197007Sdelphij		emu->x86.R_DS = pop_word(emu);
4324197007Sdelphij		break;
4325197007Sdelphij
4326197007Sdelphij	case 0x20:
4327197007Sdelphij		common_binop_byte_rm_r(emu, and_byte);
4328197007Sdelphij		break;
4329197007Sdelphij	case 0x21:
4330197007Sdelphij		common_binop_word_long_rm_r(emu, and_word, and_long);
4331197007Sdelphij		break;
4332197007Sdelphij	case 0x22:
4333197007Sdelphij		common_binop_byte_r_rm(emu, and_byte);
4334197007Sdelphij		break;
4335197007Sdelphij	case 0x23:
4336197007Sdelphij		common_binop_word_long_r_rm(emu, and_word, and_long);
4337197007Sdelphij		break;
4338197007Sdelphij	case 0x24:
4339197007Sdelphij		common_binop_byte_imm(emu, and_byte);
4340197007Sdelphij		break;
4341197007Sdelphij	case 0x25:
4342197007Sdelphij		common_binop_word_long_imm(emu, and_word, and_long);
4343197007Sdelphij		break;
4344197007Sdelphij	case 0x26:
4345197007Sdelphij		emu->x86.mode |= SYSMODE_SEGOVR_ES;
4346197007Sdelphij		break;
4347197007Sdelphij	case 0x27:
4348197007Sdelphij		emu->x86.R_AL = daa_byte(emu, emu->x86.R_AL);
4349197007Sdelphij		break;
4350197007Sdelphij
4351197007Sdelphij	case 0x28:
4352197007Sdelphij		common_binop_byte_rm_r(emu, sub_byte);
4353197007Sdelphij		break;
4354197007Sdelphij	case 0x29:
4355197007Sdelphij		common_binop_word_long_rm_r(emu, sub_word, sub_long);
4356197007Sdelphij		break;
4357197007Sdelphij	case 0x2a:
4358197007Sdelphij		common_binop_byte_r_rm(emu, sub_byte);
4359197007Sdelphij		break;
4360197007Sdelphij	case 0x2b:
4361197007Sdelphij		common_binop_word_long_r_rm(emu, sub_word, sub_long);
4362197007Sdelphij		break;
4363197007Sdelphij	case 0x2c:
4364197007Sdelphij		common_binop_byte_imm(emu, sub_byte);
4365197007Sdelphij		break;
4366197007Sdelphij	case 0x2d:
4367197007Sdelphij		common_binop_word_long_imm(emu, sub_word, sub_long);
4368197007Sdelphij		break;
4369197007Sdelphij	case 0x2e:
4370197007Sdelphij		emu->x86.mode |= SYSMODE_SEGOVR_CS;
4371197007Sdelphij		break;
4372197007Sdelphij	case 0x2f:
4373197007Sdelphij		emu->x86.R_AL = das_byte(emu, emu->x86.R_AL);
4374197007Sdelphij		break;
4375197007Sdelphij
4376197007Sdelphij	case 0x30:
4377197007Sdelphij		common_binop_byte_rm_r(emu, xor_byte);
4378197007Sdelphij		break;
4379197007Sdelphij	case 0x31:
4380197007Sdelphij		common_binop_word_long_rm_r(emu, xor_word, xor_long);
4381197007Sdelphij		break;
4382197007Sdelphij	case 0x32:
4383197007Sdelphij		common_binop_byte_r_rm(emu, xor_byte);
4384197007Sdelphij		break;
4385197007Sdelphij	case 0x33:
4386197007Sdelphij		common_binop_word_long_r_rm(emu, xor_word, xor_long);
4387197007Sdelphij		break;
4388197007Sdelphij	case 0x34:
4389197007Sdelphij		common_binop_byte_imm(emu, xor_byte);
4390197007Sdelphij		break;
4391197007Sdelphij	case 0x35:
4392197007Sdelphij		common_binop_word_long_imm(emu, xor_word, xor_long);
4393197007Sdelphij		break;
4394197007Sdelphij	case 0x36:
4395197007Sdelphij		emu->x86.mode |= SYSMODE_SEGOVR_SS;
4396197007Sdelphij		break;
4397197007Sdelphij	case 0x37:
4398197007Sdelphij		emu->x86.R_AX = aaa_word(emu, emu->x86.R_AX);
4399197007Sdelphij		break;
4400197007Sdelphij
4401197007Sdelphij	case 0x38:
4402197007Sdelphij		common_binop_ns_byte_rm_r(emu, cmp_byte_no_return);
4403197007Sdelphij		break;
4404197007Sdelphij	case 0x39:
4405197007Sdelphij		common_binop_ns_word_long_rm_r(emu, cmp_word_no_return,
4406197007Sdelphij		    cmp_long_no_return);
4407197007Sdelphij		break;
4408197007Sdelphij	case 0x3a:
4409197007Sdelphij		x86emuOp_cmp_byte_R_RM(emu);
4410197007Sdelphij		break;
4411197007Sdelphij	case 0x3b:
4412197007Sdelphij		x86emuOp_cmp_word_R_RM(emu);
4413197007Sdelphij		break;
4414197007Sdelphij	case 0x3c:
4415197007Sdelphij		x86emuOp_cmp_byte_AL_IMM(emu);
4416197007Sdelphij		break;
4417197007Sdelphij	case 0x3d:
4418197007Sdelphij		x86emuOp_cmp_word_AX_IMM(emu);
4419197007Sdelphij		break;
4420197007Sdelphij	case 0x3e:
4421197007Sdelphij		emu->x86.mode |= SYSMODE_SEGOVR_DS;
4422197007Sdelphij		break;
4423197007Sdelphij	case 0x3f:
4424197007Sdelphij		emu->x86.R_AX = aas_word(emu, emu->x86.R_AX);
4425197007Sdelphij		break;
4426197007Sdelphij
4427197007Sdelphij	case 0x40:
4428197007Sdelphij		common_inc_word_long(emu, &emu->x86.register_a);
4429197007Sdelphij		break;
4430197007Sdelphij	case 0x41:
4431197007Sdelphij		common_inc_word_long(emu, &emu->x86.register_c);
4432197007Sdelphij		break;
4433197007Sdelphij	case 0x42:
4434197007Sdelphij		common_inc_word_long(emu, &emu->x86.register_d);
4435197007Sdelphij		break;
4436197007Sdelphij	case 0x43:
4437197007Sdelphij		common_inc_word_long(emu, &emu->x86.register_b);
4438197007Sdelphij		break;
4439197007Sdelphij	case 0x44:
4440197007Sdelphij		common_inc_word_long(emu, &emu->x86.register_sp);
4441197007Sdelphij		break;
4442197007Sdelphij	case 0x45:
4443197007Sdelphij		common_inc_word_long(emu, &emu->x86.register_bp);
4444197007Sdelphij		break;
4445197007Sdelphij	case 0x46:
4446197007Sdelphij		common_inc_word_long(emu, &emu->x86.register_si);
4447197007Sdelphij		break;
4448197007Sdelphij	case 0x47:
4449197007Sdelphij		common_inc_word_long(emu, &emu->x86.register_di);
4450197007Sdelphij		break;
4451197007Sdelphij
4452197007Sdelphij	case 0x48:
4453197007Sdelphij		common_dec_word_long(emu, &emu->x86.register_a);
4454197007Sdelphij		break;
4455197007Sdelphij	case 0x49:
4456197007Sdelphij		common_dec_word_long(emu, &emu->x86.register_c);
4457197007Sdelphij		break;
4458197007Sdelphij	case 0x4a:
4459197007Sdelphij		common_dec_word_long(emu, &emu->x86.register_d);
4460197007Sdelphij		break;
4461197007Sdelphij	case 0x4b:
4462197007Sdelphij		common_dec_word_long(emu, &emu->x86.register_b);
4463197007Sdelphij		break;
4464197007Sdelphij	case 0x4c:
4465197007Sdelphij		common_dec_word_long(emu, &emu->x86.register_sp);
4466197007Sdelphij		break;
4467197007Sdelphij	case 0x4d:
4468197007Sdelphij		common_dec_word_long(emu, &emu->x86.register_bp);
4469197007Sdelphij		break;
4470197007Sdelphij	case 0x4e:
4471197007Sdelphij		common_dec_word_long(emu, &emu->x86.register_si);
4472197007Sdelphij		break;
4473197007Sdelphij	case 0x4f:
4474197007Sdelphij		common_dec_word_long(emu, &emu->x86.register_di);
4475197007Sdelphij		break;
4476197007Sdelphij
4477197007Sdelphij	case 0x50:
4478197007Sdelphij		common_push_word_long(emu, &emu->x86.register_a);
4479197007Sdelphij		break;
4480197007Sdelphij	case 0x51:
4481197007Sdelphij		common_push_word_long(emu, &emu->x86.register_c);
4482197007Sdelphij		break;
4483197007Sdelphij	case 0x52:
4484197007Sdelphij		common_push_word_long(emu, &emu->x86.register_d);
4485197007Sdelphij		break;
4486197007Sdelphij	case 0x53:
4487197007Sdelphij		common_push_word_long(emu, &emu->x86.register_b);
4488197007Sdelphij		break;
4489197007Sdelphij	case 0x54:
4490197007Sdelphij		common_push_word_long(emu, &emu->x86.register_sp);
4491197007Sdelphij		break;
4492197007Sdelphij	case 0x55:
4493197007Sdelphij		common_push_word_long(emu, &emu->x86.register_bp);
4494197007Sdelphij		break;
4495197007Sdelphij	case 0x56:
4496197007Sdelphij		common_push_word_long(emu, &emu->x86.register_si);
4497197007Sdelphij		break;
4498197007Sdelphij	case 0x57:
4499197007Sdelphij		common_push_word_long(emu, &emu->x86.register_di);
4500197007Sdelphij		break;
4501197007Sdelphij
4502197007Sdelphij	case 0x58:
4503197007Sdelphij		common_pop_word_long(emu, &emu->x86.register_a);
4504197007Sdelphij		break;
4505197007Sdelphij	case 0x59:
4506197007Sdelphij		common_pop_word_long(emu, &emu->x86.register_c);
4507197007Sdelphij		break;
4508197007Sdelphij	case 0x5a:
4509197007Sdelphij		common_pop_word_long(emu, &emu->x86.register_d);
4510197007Sdelphij		break;
4511197007Sdelphij	case 0x5b:
4512197007Sdelphij		common_pop_word_long(emu, &emu->x86.register_b);
4513197007Sdelphij		break;
4514197007Sdelphij	case 0x5c:
4515197007Sdelphij		common_pop_word_long(emu, &emu->x86.register_sp);
4516197007Sdelphij		break;
4517197007Sdelphij	case 0x5d:
4518197007Sdelphij		common_pop_word_long(emu, &emu->x86.register_bp);
4519197007Sdelphij		break;
4520197007Sdelphij	case 0x5e:
4521197007Sdelphij		common_pop_word_long(emu, &emu->x86.register_si);
4522197007Sdelphij		break;
4523197007Sdelphij	case 0x5f:
4524197007Sdelphij		common_pop_word_long(emu, &emu->x86.register_di);
4525197007Sdelphij		break;
4526197007Sdelphij
4527197007Sdelphij	case 0x60:
4528197007Sdelphij		x86emuOp_push_all(emu);
4529197007Sdelphij		break;
4530197007Sdelphij	case 0x61:
4531197007Sdelphij		x86emuOp_pop_all(emu);
4532197007Sdelphij		break;
4533197007Sdelphij	/* 0x62 bound */
4534197007Sdelphij	/* 0x63 arpl */
4535197007Sdelphij	case 0x64:
4536197007Sdelphij		emu->x86.mode |= SYSMODE_SEGOVR_FS;
4537197007Sdelphij		break;
4538197007Sdelphij	case 0x65:
4539197007Sdelphij		emu->x86.mode |= SYSMODE_SEGOVR_GS;
4540197007Sdelphij		break;
4541197007Sdelphij	case 0x66:
4542197007Sdelphij		emu->x86.mode |= SYSMODE_PREFIX_DATA;
4543197007Sdelphij		break;
4544197007Sdelphij	case 0x67:
4545197007Sdelphij		emu->x86.mode |= SYSMODE_PREFIX_ADDR;
4546197007Sdelphij		break;
4547197007Sdelphij
4548197007Sdelphij	case 0x68:
4549197007Sdelphij		x86emuOp_push_word_IMM(emu);
4550197007Sdelphij		break;
4551197007Sdelphij	case 0x69:
4552197007Sdelphij		common_imul_imm(emu, 0);
4553197007Sdelphij		break;
4554197007Sdelphij	case 0x6a:
4555197007Sdelphij		x86emuOp_push_byte_IMM(emu);
4556197007Sdelphij		break;
4557197007Sdelphij	case 0x6b:
4558197007Sdelphij		common_imul_imm(emu, 1);
4559197007Sdelphij		break;
4560197007Sdelphij	case 0x6c:
4561197007Sdelphij		ins(emu, 1);
4562197007Sdelphij		break;
4563197007Sdelphij	case 0x6d:
4564197007Sdelphij		x86emuOp_ins_word(emu);
4565197007Sdelphij		break;
4566197007Sdelphij	case 0x6e:
4567197007Sdelphij		outs(emu, 1);
4568197007Sdelphij		break;
4569197007Sdelphij	case 0x6f:
4570197007Sdelphij		x86emuOp_outs_word(emu);
4571197007Sdelphij		break;
4572197007Sdelphij
4573197007Sdelphij	case 0x70:
4574197007Sdelphij		common_jmp_near(emu, ACCESS_FLAG(F_OF));
4575197007Sdelphij		break;
4576197007Sdelphij	case 0x71:
4577197007Sdelphij		common_jmp_near(emu, !ACCESS_FLAG(F_OF));
4578197007Sdelphij		break;
4579197007Sdelphij	case 0x72:
4580197007Sdelphij		common_jmp_near(emu, ACCESS_FLAG(F_CF));
4581197007Sdelphij		break;
4582197007Sdelphij	case 0x73:
4583197007Sdelphij		common_jmp_near(emu, !ACCESS_FLAG(F_CF));
4584197007Sdelphij		break;
4585197007Sdelphij	case 0x74:
4586197007Sdelphij		common_jmp_near(emu, ACCESS_FLAG(F_ZF));
4587197007Sdelphij		break;
4588197007Sdelphij	case 0x75:
4589197007Sdelphij		common_jmp_near(emu, !ACCESS_FLAG(F_ZF));
4590197007Sdelphij		break;
4591197007Sdelphij	case 0x76:
4592197007Sdelphij		common_jmp_near(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
4593197007Sdelphij		break;
4594197007Sdelphij	case 0x77:
4595197007Sdelphij		common_jmp_near(emu, !ACCESS_FLAG(F_CF) && !ACCESS_FLAG(F_ZF));
4596197007Sdelphij		break;
4597197007Sdelphij
4598197007Sdelphij	case 0x78:
4599197007Sdelphij		common_jmp_near(emu, ACCESS_FLAG(F_SF));
4600197007Sdelphij		break;
4601197007Sdelphij	case 0x79:
4602197007Sdelphij		common_jmp_near(emu, !ACCESS_FLAG(F_SF));
4603197007Sdelphij		break;
4604197007Sdelphij	case 0x7a:
4605197007Sdelphij		common_jmp_near(emu, ACCESS_FLAG(F_PF));
4606197007Sdelphij		break;
4607197007Sdelphij	case 0x7b:
4608197007Sdelphij		common_jmp_near(emu, !ACCESS_FLAG(F_PF));
4609197007Sdelphij		break;
4610197007Sdelphij	case 0x7c:
4611197007Sdelphij		x86emuOp_jump_near_L(emu);
4612197007Sdelphij		break;
4613197007Sdelphij	case 0x7d:
4614197007Sdelphij		x86emuOp_jump_near_NL(emu);
4615197007Sdelphij		break;
4616197007Sdelphij	case 0x7e:
4617197007Sdelphij		x86emuOp_jump_near_LE(emu);
4618197007Sdelphij		break;
4619197007Sdelphij	case 0x7f:
4620197007Sdelphij		x86emuOp_jump_near_NLE(emu);
4621197007Sdelphij		break;
4622197007Sdelphij
4623197007Sdelphij	case 0x80:
4624197007Sdelphij		x86emuOp_opc80_byte_RM_IMM(emu);
4625197007Sdelphij		break;
4626197007Sdelphij	case 0x81:
4627197007Sdelphij		x86emuOp_opc81_word_RM_IMM(emu);
4628197007Sdelphij		break;
4629197007Sdelphij	case 0x82:
4630197007Sdelphij		x86emuOp_opc82_byte_RM_IMM(emu);
4631197007Sdelphij		break;
4632197007Sdelphij	case 0x83:
4633197007Sdelphij		x86emuOp_opc83_word_RM_IMM(emu);
4634197007Sdelphij		break;
4635197007Sdelphij	case 0x84:
4636197007Sdelphij		common_binop_ns_byte_rm_r(emu, test_byte);
4637197007Sdelphij		break;
4638197007Sdelphij	case 0x85:
4639197007Sdelphij		common_binop_ns_word_long_rm_r(emu, test_word, test_long);
4640197007Sdelphij		break;
4641197007Sdelphij	case 0x86:
4642197007Sdelphij		x86emuOp_xchg_byte_RM_R(emu);
4643197007Sdelphij		break;
4644197007Sdelphij	case 0x87:
4645197007Sdelphij		x86emuOp_xchg_word_RM_R(emu);
4646197007Sdelphij		break;
4647197007Sdelphij
4648197007Sdelphij	case 0x88:
4649197007Sdelphij		x86emuOp_mov_byte_RM_R(emu);
4650197007Sdelphij		break;
4651197007Sdelphij	case 0x89:
4652197007Sdelphij		x86emuOp_mov_word_RM_R(emu);
4653197007Sdelphij		break;
4654197007Sdelphij	case 0x8a:
4655197007Sdelphij		x86emuOp_mov_byte_R_RM(emu);
4656197007Sdelphij		break;
4657197007Sdelphij	case 0x8b:
4658197007Sdelphij		x86emuOp_mov_word_R_RM(emu);
4659197007Sdelphij		break;
4660197007Sdelphij	case 0x8c:
4661197007Sdelphij		x86emuOp_mov_word_RM_SR(emu);
4662197007Sdelphij		break;
4663197007Sdelphij	case 0x8d:
4664197007Sdelphij		x86emuOp_lea_word_R_M(emu);
4665197007Sdelphij		break;
4666197007Sdelphij	case 0x8e:
4667197007Sdelphij		x86emuOp_mov_word_SR_RM(emu);
4668197007Sdelphij		break;
4669197007Sdelphij	case 0x8f:
4670197007Sdelphij		x86emuOp_pop_RM(emu);
4671197007Sdelphij		break;
4672197007Sdelphij
4673197007Sdelphij	case 0x90:
4674197007Sdelphij		/* nop */
4675197007Sdelphij		break;
4676197007Sdelphij	case 0x91:
4677197007Sdelphij		x86emuOp_xchg_word_AX_CX(emu);
4678197007Sdelphij		break;
4679197007Sdelphij	case 0x92:
4680197007Sdelphij		x86emuOp_xchg_word_AX_DX(emu);
4681197007Sdelphij		break;
4682197007Sdelphij	case 0x93:
4683197007Sdelphij		x86emuOp_xchg_word_AX_BX(emu);
4684197007Sdelphij		break;
4685197007Sdelphij	case 0x94:
4686197007Sdelphij		x86emuOp_xchg_word_AX_SP(emu);
4687197007Sdelphij		break;
4688197007Sdelphij	case 0x95:
4689197007Sdelphij		x86emuOp_xchg_word_AX_BP(emu);
4690197007Sdelphij		break;
4691197007Sdelphij	case 0x96:
4692197007Sdelphij		x86emuOp_xchg_word_AX_SI(emu);
4693197007Sdelphij		break;
4694197007Sdelphij	case 0x97:
4695197007Sdelphij		x86emuOp_xchg_word_AX_DI(emu);
4696197007Sdelphij		break;
4697197007Sdelphij
4698197007Sdelphij	case 0x98:
4699197007Sdelphij		x86emuOp_cbw(emu);
4700197007Sdelphij		break;
4701197007Sdelphij	case 0x99:
4702197007Sdelphij		x86emuOp_cwd(emu);
4703197007Sdelphij		break;
4704197007Sdelphij	case 0x9a:
4705197007Sdelphij		x86emuOp_call_far_IMM(emu);
4706197007Sdelphij		break;
4707197007Sdelphij	case 0x9b:
4708197007Sdelphij		/* wait */
4709197007Sdelphij		break;
4710197007Sdelphij	case 0x9c:
4711197007Sdelphij		x86emuOp_pushf_word(emu);
4712197007Sdelphij		break;
4713197007Sdelphij	case 0x9d:
4714197007Sdelphij		x86emuOp_popf_word(emu);
4715197007Sdelphij		break;
4716197007Sdelphij	case 0x9e:
4717197007Sdelphij		x86emuOp_sahf(emu);
4718197007Sdelphij		break;
4719197007Sdelphij	case 0x9f:
4720197007Sdelphij		x86emuOp_lahf(emu);
4721197007Sdelphij		break;
4722197007Sdelphij
4723197007Sdelphij	case 0xa0:
4724197007Sdelphij		x86emuOp_mov_AL_M_IMM(emu);
4725197007Sdelphij		break;
4726197007Sdelphij	case 0xa1:
4727197007Sdelphij		x86emuOp_mov_AX_M_IMM(emu);
4728197007Sdelphij		break;
4729197007Sdelphij	case 0xa2:
4730197007Sdelphij		x86emuOp_mov_M_AL_IMM(emu);
4731197007Sdelphij		break;
4732197007Sdelphij	case 0xa3:
4733197007Sdelphij		x86emuOp_mov_M_AX_IMM(emu);
4734197007Sdelphij		break;
4735197007Sdelphij	case 0xa4:
4736197007Sdelphij		x86emuOp_movs_byte(emu);
4737197007Sdelphij		break;
4738197007Sdelphij	case 0xa5:
4739197007Sdelphij		x86emuOp_movs_word(emu);
4740197007Sdelphij		break;
4741197007Sdelphij	case 0xa6:
4742197007Sdelphij		x86emuOp_cmps_byte(emu);
4743197007Sdelphij		break;
4744197007Sdelphij	case 0xa7:
4745197007Sdelphij		x86emuOp_cmps_word(emu);
4746197007Sdelphij		break;
4747197007Sdelphij
4748197007Sdelphij	case 0xa8:
4749197007Sdelphij		test_byte(emu, emu->x86.R_AL, fetch_byte_imm(emu));
4750197007Sdelphij		break;
4751197007Sdelphij	case 0xa9:
4752197007Sdelphij		x86emuOp_test_AX_IMM(emu);
4753197007Sdelphij		break;
4754197007Sdelphij	case 0xaa:
4755197007Sdelphij		x86emuOp_stos_byte(emu);
4756197007Sdelphij		break;
4757197007Sdelphij	case 0xab:
4758197007Sdelphij		x86emuOp_stos_word(emu);
4759197007Sdelphij		break;
4760197007Sdelphij	case 0xac:
4761197007Sdelphij		x86emuOp_lods_byte(emu);
4762197007Sdelphij		break;
4763197007Sdelphij	case 0xad:
4764197007Sdelphij		x86emuOp_lods_word(emu);
4765197007Sdelphij		break;
4766197007Sdelphij	case 0xae:
4767197007Sdelphij		x86emuOp_scas_byte(emu);
4768197007Sdelphij		break;
4769197007Sdelphij	case 0xaf:
4770197007Sdelphij		x86emuOp_scas_word(emu);
4771197007Sdelphij		break;
4772197007Sdelphij
4773197007Sdelphij	case 0xb0:
4774197007Sdelphij		emu->x86.R_AL = fetch_byte_imm(emu);
4775197007Sdelphij		break;
4776197007Sdelphij	case 0xb1:
4777197007Sdelphij		emu->x86.R_CL = fetch_byte_imm(emu);
4778197007Sdelphij		break;
4779197007Sdelphij	case 0xb2:
4780197007Sdelphij		emu->x86.R_DL = fetch_byte_imm(emu);
4781197007Sdelphij		break;
4782197007Sdelphij	case 0xb3:
4783197007Sdelphij		emu->x86.R_BL = fetch_byte_imm(emu);
4784197007Sdelphij		break;
4785197007Sdelphij	case 0xb4:
4786197007Sdelphij		emu->x86.R_AH = fetch_byte_imm(emu);
4787197007Sdelphij		break;
4788197007Sdelphij	case 0xb5:
4789197007Sdelphij		emu->x86.R_CH = fetch_byte_imm(emu);
4790197007Sdelphij		break;
4791197007Sdelphij	case 0xb6:
4792197007Sdelphij		emu->x86.R_DH = fetch_byte_imm(emu);
4793197007Sdelphij		break;
4794197007Sdelphij	case 0xb7:
4795197007Sdelphij		emu->x86.R_BH = fetch_byte_imm(emu);
4796197007Sdelphij		break;
4797197007Sdelphij
4798197007Sdelphij	case 0xb8:
4799197007Sdelphij		x86emuOp_mov_word_AX_IMM(emu);
4800197007Sdelphij		break;
4801197007Sdelphij	case 0xb9:
4802197007Sdelphij		x86emuOp_mov_word_CX_IMM(emu);
4803197007Sdelphij		break;
4804197007Sdelphij	case 0xba:
4805197007Sdelphij		x86emuOp_mov_word_DX_IMM(emu);
4806197007Sdelphij		break;
4807197007Sdelphij	case 0xbb:
4808197007Sdelphij		x86emuOp_mov_word_BX_IMM(emu);
4809197007Sdelphij		break;
4810197007Sdelphij	case 0xbc:
4811197007Sdelphij
4812197007Sdelphij		x86emuOp_mov_word_SP_IMM(emu);
4813197007Sdelphij		break;
4814197007Sdelphij	case 0xbd:
4815197007Sdelphij		x86emuOp_mov_word_BP_IMM(emu);
4816197007Sdelphij		break;
4817197007Sdelphij	case 0xbe:
4818197007Sdelphij		x86emuOp_mov_word_SI_IMM(emu);
4819197007Sdelphij		break;
4820197007Sdelphij	case 0xbf:
4821197007Sdelphij		x86emuOp_mov_word_DI_IMM(emu);
4822197007Sdelphij		break;
4823197007Sdelphij
4824197007Sdelphij	case 0xc0:
4825197007Sdelphij		x86emuOp_opcC0_byte_RM_MEM(emu);
4826197007Sdelphij		break;
4827197007Sdelphij	case 0xc1:
4828197007Sdelphij		x86emuOp_opcC1_word_RM_MEM(emu);
4829197007Sdelphij		break;
4830197007Sdelphij	case 0xc2:
4831197007Sdelphij		x86emuOp_ret_near_IMM(emu);
4832197007Sdelphij		break;
4833197007Sdelphij	case 0xc3:
4834197007Sdelphij		emu->x86.R_IP = pop_word(emu);
4835197007Sdelphij		break;
4836197007Sdelphij	case 0xc4:
4837197007Sdelphij		common_load_far_pointer(emu, &emu->x86.R_ES);
4838197007Sdelphij		break;
4839197007Sdelphij	case 0xc5:
4840197007Sdelphij		common_load_far_pointer(emu, &emu->x86.R_DS);
4841197007Sdelphij		break;
4842197007Sdelphij	case 0xc6:
4843197007Sdelphij		x86emuOp_mov_byte_RM_IMM(emu);
4844197007Sdelphij		break;
4845197007Sdelphij	case 0xc7:
4846197007Sdelphij		x86emuOp_mov_word_RM_IMM(emu);
4847197007Sdelphij		break;
4848197007Sdelphij	case 0xc8:
4849197007Sdelphij		x86emuOp_enter(emu);
4850197007Sdelphij		break;
4851197007Sdelphij	case 0xc9:
4852197007Sdelphij		x86emuOp_leave(emu);
4853197007Sdelphij		break;
4854197007Sdelphij	case 0xca:
4855197007Sdelphij		x86emuOp_ret_far_IMM(emu);
4856197007Sdelphij		break;
4857197007Sdelphij	case 0xcb:
4858197007Sdelphij		x86emuOp_ret_far(emu);
4859197007Sdelphij		break;
4860197007Sdelphij	case 0xcc:
4861197007Sdelphij		x86emuOp_int3(emu);
4862197007Sdelphij		break;
4863197007Sdelphij	case 0xcd:
4864197007Sdelphij		x86emuOp_int_IMM(emu);
4865197007Sdelphij		break;
4866197007Sdelphij	case 0xce:
4867197007Sdelphij		x86emuOp_into(emu);
4868197007Sdelphij		break;
4869197007Sdelphij	case 0xcf:
4870197007Sdelphij		x86emuOp_iret(emu);
4871197007Sdelphij		break;
4872197007Sdelphij
4873197007Sdelphij	case 0xd0:
4874197007Sdelphij		x86emuOp_opcD0_byte_RM_1(emu);
4875197007Sdelphij		break;
4876197007Sdelphij	case 0xd1:
4877197007Sdelphij		x86emuOp_opcD1_word_RM_1(emu);
4878197007Sdelphij		break;
4879197007Sdelphij	case 0xd2:
4880197007Sdelphij		x86emuOp_opcD2_byte_RM_CL(emu);
4881197007Sdelphij		break;
4882197007Sdelphij	case 0xd3:
4883197007Sdelphij		x86emuOp_opcD3_word_RM_CL(emu);
4884197007Sdelphij		break;
4885197007Sdelphij	case 0xd4:
4886197007Sdelphij		x86emuOp_aam(emu);
4887197007Sdelphij		break;
4888197007Sdelphij	case 0xd5:
4889197007Sdelphij		x86emuOp_aad(emu);
4890197007Sdelphij		break;
4891197007Sdelphij	/* 0xd6 Undocumented SETALC instruction */
4892197007Sdelphij	case 0xd7:
4893197007Sdelphij		x86emuOp_xlat(emu);
4894197007Sdelphij		break;
4895197007Sdelphij	case 0xd8:
4896197007Sdelphij		x86emuOp_esc_coprocess_d8(emu);
4897197007Sdelphij		break;
4898197007Sdelphij	case 0xd9:
4899197007Sdelphij		x86emuOp_esc_coprocess_d9(emu);
4900197007Sdelphij		break;
4901197007Sdelphij	case 0xda:
4902197007Sdelphij		x86emuOp_esc_coprocess_da(emu);
4903197007Sdelphij		break;
4904197007Sdelphij	case 0xdb:
4905197007Sdelphij		x86emuOp_esc_coprocess_db(emu);
4906197007Sdelphij		break;
4907197007Sdelphij	case 0xdc:
4908197007Sdelphij		x86emuOp_esc_coprocess_dc(emu);
4909197007Sdelphij		break;
4910197007Sdelphij	case 0xdd:
4911197007Sdelphij		x86emuOp_esc_coprocess_dd(emu);
4912197007Sdelphij		break;
4913197007Sdelphij	case 0xde:
4914197007Sdelphij		x86emuOp_esc_coprocess_de(emu);
4915197007Sdelphij		break;
4916197007Sdelphij	case 0xdf:
4917197007Sdelphij		x86emuOp_esc_coprocess_df(emu);
4918197007Sdelphij		break;
4919197007Sdelphij
4920197007Sdelphij	case 0xe0:
4921197007Sdelphij		x86emuOp_loopne(emu);
4922197007Sdelphij		break;
4923197007Sdelphij	case 0xe1:
4924197007Sdelphij		x86emuOp_loope(emu);
4925197007Sdelphij		break;
4926197007Sdelphij	case 0xe2:
4927197007Sdelphij		x86emuOp_loop(emu);
4928197007Sdelphij		break;
4929197007Sdelphij	case 0xe3:
4930197007Sdelphij		x86emuOp_jcxz(emu);
4931197007Sdelphij		break;
4932197007Sdelphij	case 0xe4:
4933197007Sdelphij		x86emuOp_in_byte_AL_IMM(emu);
4934197007Sdelphij		break;
4935197007Sdelphij	case 0xe5:
4936197007Sdelphij		x86emuOp_in_word_AX_IMM(emu);
4937197007Sdelphij		break;
4938197007Sdelphij	case 0xe6:
4939197007Sdelphij		x86emuOp_out_byte_IMM_AL(emu);
4940197007Sdelphij		break;
4941197007Sdelphij	case 0xe7:
4942197007Sdelphij		x86emuOp_out_word_IMM_AX(emu);
4943197007Sdelphij		break;
4944197007Sdelphij
4945197007Sdelphij	case 0xe8:
4946197007Sdelphij		x86emuOp_call_near_IMM(emu);
4947197007Sdelphij		break;
4948197007Sdelphij	case 0xe9:
4949197007Sdelphij		x86emuOp_jump_near_IMM(emu);
4950197007Sdelphij		break;
4951197007Sdelphij	case 0xea:
4952197007Sdelphij		x86emuOp_jump_far_IMM(emu);
4953197007Sdelphij		break;
4954197007Sdelphij	case 0xeb:
4955197007Sdelphij		x86emuOp_jump_byte_IMM(emu);
4956197007Sdelphij		break;
4957197007Sdelphij	case 0xec:
4958197007Sdelphij		x86emuOp_in_byte_AL_DX(emu);
4959197007Sdelphij		break;
4960197007Sdelphij	case 0xed:
4961197007Sdelphij		x86emuOp_in_word_AX_DX(emu);
4962197007Sdelphij		break;
4963197007Sdelphij	case 0xee:
4964197007Sdelphij		x86emuOp_out_byte_DX_AL(emu);
4965197007Sdelphij		break;
4966197007Sdelphij	case 0xef:
4967197007Sdelphij		x86emuOp_out_word_DX_AX(emu);
4968197007Sdelphij		break;
4969197007Sdelphij
4970197007Sdelphij	case 0xf0:
4971197007Sdelphij		x86emuOp_lock(emu);
4972197007Sdelphij		break;
4973197007Sdelphij	case 0xf2:
4974197007Sdelphij		emu->x86.mode |= SYSMODE_PREFIX_REPNE;
4975197007Sdelphij		break;
4976197007Sdelphij	case 0xf3:
4977197007Sdelphij		emu->x86.mode |= SYSMODE_PREFIX_REPE;
4978197007Sdelphij		break;
4979197007Sdelphij	case 0xf4:
4980197007Sdelphij		x86emu_halt_sys(emu);
4981197007Sdelphij		break;
4982197007Sdelphij	case 0xf5:
4983197007Sdelphij		x86emuOp_cmc(emu);
4984197007Sdelphij		break;
4985197007Sdelphij	case 0xf6:
4986197007Sdelphij		x86emuOp_opcF6_byte_RM(emu);
4987197007Sdelphij		break;
4988197007Sdelphij	case 0xf7:
4989197007Sdelphij		x86emuOp_opcF7_word_RM(emu);
4990197007Sdelphij		break;
4991197007Sdelphij
4992197007Sdelphij	case 0xf8:
4993197007Sdelphij		CLEAR_FLAG(F_CF);
4994197007Sdelphij		break;
4995197007Sdelphij	case 0xf9:
4996197007Sdelphij		SET_FLAG(F_CF);
4997197007Sdelphij		break;
4998197007Sdelphij	case 0xfa:
4999197007Sdelphij		CLEAR_FLAG(F_IF);
5000197007Sdelphij		break;
5001197007Sdelphij	case 0xfb:
5002197007Sdelphij		SET_FLAG(F_IF);
5003197007Sdelphij		break;
5004197007Sdelphij	case 0xfc:
5005197007Sdelphij		CLEAR_FLAG(F_DF);
5006197007Sdelphij		break;
5007197007Sdelphij	case 0xfd:
5008197007Sdelphij		SET_FLAG(F_DF);
5009197007Sdelphij		break;
5010197007Sdelphij	case 0xfe:
5011197007Sdelphij		x86emuOp_opcFE_byte_RM(emu);
5012197007Sdelphij		break;
5013197007Sdelphij	case 0xff:
5014197007Sdelphij		x86emuOp_opcFF_word_RM(emu);
5015197007Sdelphij		break;
5016197007Sdelphij	default:
5017197007Sdelphij		x86emu_halt_sys(emu);
5018197007Sdelphij		break;
5019197007Sdelphij	}
5020197007Sdelphij	if (op1 != 0x26 && op1 != 0x2e && op1 != 0x36 && op1 != 0x3e &&
5021197007Sdelphij	    (op1 | 3) != 0x67)
5022197007Sdelphij		emu->x86.mode &= ~SYSMODE_CLRMASK;
5023197007Sdelphij}
5024197007Sdelphij
5025197007Sdelphijstatic void
5026197007Sdelphijcommon_jmp_long(struct x86emu *emu, int cond)
5027197007Sdelphij{
5028197007Sdelphij	int16_t target;
5029197007Sdelphij
5030197007Sdelphij	target = (int16_t) fetch_word_imm(emu);
5031197007Sdelphij	target += (int16_t) emu->x86.R_IP;
5032197007Sdelphij	if (cond)
5033197007Sdelphij		emu->x86.R_IP = (uint16_t) target;
5034197007Sdelphij}
5035197007Sdelphij
5036197007Sdelphijstatic void
5037197007Sdelphijcommon_set_byte(struct x86emu *emu, int cond)
5038197007Sdelphij{
5039197007Sdelphij	uint32_t destoffset;
5040197007Sdelphij	uint8_t *destreg, destval;
5041197007Sdelphij
5042197007Sdelphij	fetch_decode_modrm(emu);
5043197007Sdelphij	destval = cond ? 0x01 : 0x00;
5044197007Sdelphij	if (emu->cur_mod != 3) {
5045197007Sdelphij		destoffset = decode_rl_address(emu);
5046197007Sdelphij		store_data_byte(emu, destoffset, destval);
5047197007Sdelphij	} else {
5048197007Sdelphij		destreg = decode_rl_byte_register(emu);
5049197007Sdelphij		*destreg = destval;
5050197007Sdelphij	}
5051197007Sdelphij}
5052197007Sdelphij
5053197007Sdelphijstatic void
5054197007Sdelphijcommon_bitstring32(struct x86emu *emu, int op)
5055197007Sdelphij{
5056197007Sdelphij	int bit;
5057197007Sdelphij	uint32_t srcval, *shiftreg, mask;
5058197007Sdelphij
5059197007Sdelphij	fetch_decode_modrm(emu);
5060197007Sdelphij	shiftreg = decode_rh_long_register(emu);
5061197007Sdelphij	srcval = decode_and_fetch_long_disp(emu, (int16_t) *shiftreg >> 5);
5062197007Sdelphij	bit = *shiftreg & 0x1F;
5063197007Sdelphij	mask =  0x1 << bit;
5064197007Sdelphij	CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5065197007Sdelphij
5066197007Sdelphij	switch (op) {
5067197007Sdelphij	case 0:
5068197007Sdelphij		break;
5069197007Sdelphij	case 1:
5070197007Sdelphij		write_back_long(emu, srcval | mask);
5071197007Sdelphij		break;
5072197007Sdelphij	case 2:
5073197007Sdelphij		write_back_long(emu, srcval & ~mask);
5074197007Sdelphij		break;
5075197007Sdelphij	case 3:
5076197007Sdelphij		write_back_long(emu, srcval ^ mask);
5077197007Sdelphij		break;
5078197007Sdelphij	}
5079197007Sdelphij}
5080197007Sdelphij
5081197007Sdelphijstatic void
5082197007Sdelphijcommon_bitstring16(struct x86emu *emu, int op)
5083197007Sdelphij{
5084197007Sdelphij	int bit;
5085197007Sdelphij	uint16_t srcval, *shiftreg, mask;
5086197007Sdelphij
5087197007Sdelphij	fetch_decode_modrm(emu);
5088197007Sdelphij	shiftreg = decode_rh_word_register(emu);
5089197007Sdelphij	srcval = decode_and_fetch_word_disp(emu, (int16_t) *shiftreg >> 4);
5090197007Sdelphij	bit = *shiftreg & 0xF;
5091197007Sdelphij	mask =  0x1 << bit;
5092197007Sdelphij	CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5093197007Sdelphij
5094197007Sdelphij	switch (op) {
5095197007Sdelphij	case 0:
5096197007Sdelphij		break;
5097197007Sdelphij	case 1:
5098197007Sdelphij		write_back_word(emu, srcval | mask);
5099197007Sdelphij		break;
5100197007Sdelphij	case 2:
5101197007Sdelphij		write_back_word(emu, srcval & ~mask);
5102197007Sdelphij		break;
5103197007Sdelphij	case 3:
5104197007Sdelphij		write_back_word(emu, srcval ^ mask);
5105197007Sdelphij		break;
5106197007Sdelphij	}
5107197007Sdelphij}
5108197007Sdelphij
5109197007Sdelphijstatic void
5110197007Sdelphijcommon_bitstring(struct x86emu *emu, int op)
5111197007Sdelphij{
5112197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5113197007Sdelphij		common_bitstring32(emu, op);
5114197007Sdelphij	else
5115197007Sdelphij		common_bitstring16(emu, op);
5116197007Sdelphij}
5117197007Sdelphij
5118197007Sdelphijstatic void
5119197007Sdelphijcommon_bitsearch32(struct x86emu *emu, int diff)
5120197007Sdelphij{
5121197007Sdelphij	uint32_t srcval, *dstreg;
5122197007Sdelphij
5123197007Sdelphij	fetch_decode_modrm(emu);
5124197007Sdelphij	dstreg = decode_rh_long_register(emu);
5125197007Sdelphij	srcval = decode_and_fetch_long(emu);
5126197007Sdelphij	CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
5127197007Sdelphij	for (*dstreg = 0; *dstreg < 32; *dstreg += diff) {
5128197007Sdelphij		if ((srcval >> *dstreg) & 1)
5129197007Sdelphij			break;
5130197007Sdelphij	}
5131197007Sdelphij}
5132197007Sdelphij
5133197007Sdelphijstatic void
5134197007Sdelphijcommon_bitsearch16(struct x86emu *emu, int diff)
5135197007Sdelphij{
5136197007Sdelphij	uint16_t srcval, *dstreg;
5137197007Sdelphij
5138197007Sdelphij	fetch_decode_modrm(emu);
5139197007Sdelphij	dstreg = decode_rh_word_register(emu);
5140197007Sdelphij	srcval = decode_and_fetch_word(emu);
5141197007Sdelphij	CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
5142197007Sdelphij	for (*dstreg = 0; *dstreg < 16; *dstreg += diff) {
5143197007Sdelphij		if ((srcval >> *dstreg) & 1)
5144197007Sdelphij			break;
5145197007Sdelphij	}
5146197007Sdelphij}
5147197007Sdelphij
5148197007Sdelphijstatic void
5149197007Sdelphijcommon_bitsearch(struct x86emu *emu, int diff)
5150197007Sdelphij{
5151197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5152197007Sdelphij		common_bitsearch32(emu, diff);
5153197007Sdelphij	else
5154197007Sdelphij		common_bitsearch16(emu, diff);
5155197007Sdelphij}
5156197007Sdelphij
5157197007Sdelphijstatic void
5158197007Sdelphijcommon_shift32(struct x86emu *emu, int shift_left, int use_cl)
5159197007Sdelphij{
5160197007Sdelphij	uint8_t shift;
5161197007Sdelphij	uint32_t destval, *shiftreg;
5162197007Sdelphij
5163197007Sdelphij	fetch_decode_modrm(emu);
5164197007Sdelphij	shiftreg = decode_rh_long_register(emu);
5165197007Sdelphij	if (use_cl) {
5166197007Sdelphij		destval = decode_and_fetch_long(emu);
5167197007Sdelphij		shift = emu->x86.R_CL;
5168197007Sdelphij	} else {
5169197007Sdelphij		destval = decode_and_fetch_long_imm8(emu, &shift);
5170197007Sdelphij	}
5171197007Sdelphij	if (shift_left)
5172197007Sdelphij		destval = shld_long(emu, destval, *shiftreg, shift);
5173197007Sdelphij	else
5174197007Sdelphij		destval = shrd_long(emu, destval, *shiftreg, shift);
5175197007Sdelphij	write_back_long(emu, destval);
5176197007Sdelphij}
5177197007Sdelphij
5178197007Sdelphijstatic void
5179197007Sdelphijcommon_shift16(struct x86emu *emu, int shift_left, int use_cl)
5180197007Sdelphij{
5181197007Sdelphij	uint8_t shift;
5182197007Sdelphij	uint16_t destval, *shiftreg;
5183197007Sdelphij
5184197007Sdelphij	fetch_decode_modrm(emu);
5185197007Sdelphij	shiftreg = decode_rh_word_register(emu);
5186197007Sdelphij	if (use_cl) {
5187197007Sdelphij		destval = decode_and_fetch_word(emu);
5188197007Sdelphij		shift = emu->x86.R_CL;
5189197007Sdelphij	} else {
5190197007Sdelphij		destval = decode_and_fetch_word_imm8(emu, &shift);
5191197007Sdelphij	}
5192197007Sdelphij	if (shift_left)
5193197007Sdelphij		destval = shld_word(emu, destval, *shiftreg, shift);
5194197007Sdelphij	else
5195197007Sdelphij		destval = shrd_word(emu, destval, *shiftreg, shift);
5196197007Sdelphij	write_back_word(emu, destval);
5197197007Sdelphij}
5198197007Sdelphij
5199197007Sdelphijstatic void
5200197007Sdelphijcommon_shift(struct x86emu *emu, int shift_left, int use_cl)
5201197007Sdelphij{
5202197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5203197007Sdelphij		common_shift32(emu, shift_left, use_cl);
5204197007Sdelphij	else
5205197007Sdelphij		common_shift16(emu, shift_left, use_cl);
5206197007Sdelphij}
5207197007Sdelphij
5208204934Sdelphij/*
5209204934Sdelphij * Implementation
5210204934Sdelphij */
5211197007Sdelphij#define xorl(a,b)   ((a) && !(b)) || (!(a) && (b))
5212197007Sdelphij
5213197007Sdelphij
5214197007Sdelphij/*
5215197007Sdelphij * REMARKS:
5216197007Sdelphij * Handles opcode 0x0f,0x31
5217197007Sdelphij */
5218197007Sdelphijstatic void
5219197007Sdelphijx86emuOp2_rdtsc(struct x86emu *emu)
5220197007Sdelphij{
5221197007Sdelphij	emu->x86.R_EAX = emu->cur_cycles & 0xffffffff;
5222197007Sdelphij	emu->x86.R_EDX = emu->cur_cycles >> 32;
5223197007Sdelphij}
5224197007Sdelphij
5225197007Sdelphij/*
5226197007Sdelphij * REMARKS:
5227197007Sdelphij * Handles opcode 0x0f,0xa0
5228197007Sdelphij */
5229197007Sdelphijstatic void
5230197007Sdelphijx86emuOp2_push_FS(struct x86emu *emu)
5231197007Sdelphij{
5232197007Sdelphij	push_word(emu, emu->x86.R_FS);
5233197007Sdelphij}
5234197007Sdelphij
5235197007Sdelphij/*
5236197007Sdelphij * REMARKS:
5237197007Sdelphij * Handles opcode 0x0f,0xa1
5238197007Sdelphij */
5239197007Sdelphijstatic void
5240197007Sdelphijx86emuOp2_pop_FS(struct x86emu *emu)
5241197007Sdelphij{
5242197007Sdelphij	emu->x86.R_FS = pop_word(emu);
5243197007Sdelphij}
5244197007Sdelphij
5245197007Sdelphij/*
5246197007Sdelphij * REMARKS:
5247197007Sdelphij * Handles opcode 0x0f,0xa1
5248197007Sdelphij */
5249197007Sdelphij#if defined(__i386__) || defined(__amd64__)
5250197007Sdelphijstatic void
5251197007Sdelphijhw_cpuid(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
5252197007Sdelphij{
5253281502Sdelphij	__asm__ volatile("cpuid"
5254197007Sdelphij			     : "=a" (*a), "=b" (*b),
5255197007Sdelphij			       "=c" (*c), "=d" (*d)
5256197007Sdelphij			     : "a" (*a), "c" (*c)
5257197007Sdelphij			     : "cc");
5258197007Sdelphij}
5259197007Sdelphij#endif
5260197007Sdelphijstatic void
5261197007Sdelphijx86emuOp2_cpuid(struct x86emu *emu)
5262197007Sdelphij{
5263197007Sdelphij#if defined(__i386__) || defined(__amd64__)
5264197007Sdelphij	hw_cpuid(&emu->x86.R_EAX, &emu->x86.R_EBX, &emu->x86.R_ECX,
5265197007Sdelphij	    &emu->x86.R_EDX);
5266197007Sdelphij#endif
5267197007Sdelphij	switch (emu->x86.R_EAX) {
5268197007Sdelphij	case 0:
5269197007Sdelphij		emu->x86.R_EAX = 1;
5270197007Sdelphij#if !defined(__i386__) && !defined(__amd64__)
5271197007Sdelphij		/* "GenuineIntel" */
5272197007Sdelphij		emu->x86.R_EBX = 0x756e6547;
5273197007Sdelphij		emu->x86.R_EDX = 0x49656e69;
5274197007Sdelphij		emu->x86.R_ECX = 0x6c65746e;
5275197007Sdelphij#endif
5276197007Sdelphij		break;
5277197007Sdelphij	case 1:
5278197007Sdelphij#if !defined(__i386__) && !defined(__amd64__)
5279197007Sdelphij		emu->x86.R_EAX = 0x00000480;
5280197007Sdelphij		emu->x86.R_EBX = emu->x86.R_ECX = 0;
5281197007Sdelphij		emu->x86.R_EDX = 0x00000002;
5282197007Sdelphij#else
5283197007Sdelphij		emu->x86.R_EDX &= 0x00000012;
5284197007Sdelphij#endif
5285197007Sdelphij		break;
5286197007Sdelphij	default:
5287197007Sdelphij		emu->x86.R_EAX = emu->x86.R_EBX = emu->x86.R_ECX =
5288197007Sdelphij		    emu->x86.R_EDX = 0;
5289197007Sdelphij		break;
5290197007Sdelphij	}
5291197007Sdelphij}
5292197007Sdelphij
5293197007Sdelphij/*
5294197007Sdelphij * REMARKS:
5295197007Sdelphij * Handles opcode 0x0f,0xa3
5296197007Sdelphij */
5297197007Sdelphijstatic void
5298197007Sdelphijx86emuOp2_bt_R(struct x86emu *emu)
5299197007Sdelphij{
5300197007Sdelphij	common_bitstring(emu, 0);
5301197007Sdelphij}
5302197007Sdelphij
5303197007Sdelphij/*
5304197007Sdelphij * REMARKS:
5305197007Sdelphij * Handles opcode 0x0f,0xa4
5306197007Sdelphij */
5307197007Sdelphijstatic void
5308197007Sdelphijx86emuOp2_shld_IMM(struct x86emu *emu)
5309197007Sdelphij{
5310197007Sdelphij	common_shift(emu, 1, 0);
5311197007Sdelphij}
5312197007Sdelphij
5313197007Sdelphij/*
5314197007Sdelphij * REMARKS:
5315197007Sdelphij * Handles opcode 0x0f,0xa5
5316197007Sdelphij */
5317197007Sdelphijstatic void
5318197007Sdelphijx86emuOp2_shld_CL(struct x86emu *emu)
5319197007Sdelphij{
5320197007Sdelphij	common_shift(emu, 1, 1);
5321197007Sdelphij}
5322197007Sdelphij
5323197007Sdelphij/*
5324197007Sdelphij * REMARKS:
5325197007Sdelphij * Handles opcode 0x0f,0xa8
5326197007Sdelphij */
5327197007Sdelphijstatic void
5328197007Sdelphijx86emuOp2_push_GS(struct x86emu *emu)
5329197007Sdelphij{
5330197007Sdelphij	push_word(emu, emu->x86.R_GS);
5331197007Sdelphij}
5332197007Sdelphij
5333197007Sdelphij/*
5334197007Sdelphij * REMARKS:
5335197007Sdelphij * Handles opcode 0x0f,0xa9
5336197007Sdelphij */
5337197007Sdelphijstatic void
5338197007Sdelphijx86emuOp2_pop_GS(struct x86emu *emu)
5339197007Sdelphij{
5340197007Sdelphij	emu->x86.R_GS = pop_word(emu);
5341197007Sdelphij}
5342197007Sdelphij
5343197007Sdelphij/*
5344197007Sdelphij * REMARKS:
5345197007Sdelphij * Handles opcode 0x0f,0xab
5346197007Sdelphij */
5347197007Sdelphijstatic void
5348197007Sdelphijx86emuOp2_bts_R(struct x86emu *emu)
5349197007Sdelphij{
5350197007Sdelphij	common_bitstring(emu, 1);
5351197007Sdelphij}
5352197007Sdelphij
5353197007Sdelphij/*
5354197007Sdelphij * REMARKS:
5355197007Sdelphij * Handles opcode 0x0f,0xac
5356197007Sdelphij */
5357197007Sdelphijstatic void
5358197007Sdelphijx86emuOp2_shrd_IMM(struct x86emu *emu)
5359197007Sdelphij{
5360197007Sdelphij	common_shift(emu, 0, 0);
5361197007Sdelphij}
5362197007Sdelphij
5363197007Sdelphij/*
5364197007Sdelphij * REMARKS:
5365197007Sdelphij * Handles opcode 0x0f,0xad
5366197007Sdelphij */
5367197007Sdelphijstatic void
5368197007Sdelphijx86emuOp2_shrd_CL(struct x86emu *emu)
5369197007Sdelphij{
5370197007Sdelphij	common_shift(emu, 0, 1);
5371197007Sdelphij}
5372197007Sdelphij
5373197007Sdelphij/*
5374197007Sdelphij * REMARKS:
5375197007Sdelphij * Handles opcode 0x0f,0xaf
5376197007Sdelphij */
5377197007Sdelphijstatic void
5378197007Sdelphijx86emuOp2_32_imul_R_RM(struct x86emu *emu)
5379197007Sdelphij{
5380197007Sdelphij	uint32_t *destreg, srcval;
5381197007Sdelphij	uint64_t res;
5382197007Sdelphij
5383197007Sdelphij	fetch_decode_modrm(emu);
5384197007Sdelphij	destreg = decode_rh_long_register(emu);
5385197007Sdelphij	srcval = decode_and_fetch_long(emu);
5386197007Sdelphij	res = (int32_t) *destreg * (int32_t)srcval;
5387197007Sdelphij	if (res > 0xffffffff) {
5388197007Sdelphij		SET_FLAG(F_CF);
5389197007Sdelphij		SET_FLAG(F_OF);
5390197007Sdelphij	} else {
5391197007Sdelphij		CLEAR_FLAG(F_CF);
5392197007Sdelphij		CLEAR_FLAG(F_OF);
5393197007Sdelphij	}
5394197007Sdelphij	*destreg = (uint32_t) res;
5395197007Sdelphij}
5396197007Sdelphij
5397197007Sdelphijstatic void
5398197007Sdelphijx86emuOp2_16_imul_R_RM(struct x86emu *emu)
5399197007Sdelphij{
5400197007Sdelphij	uint16_t *destreg, srcval;
5401197007Sdelphij	uint32_t res;
5402197007Sdelphij
5403197007Sdelphij	fetch_decode_modrm(emu);
5404197007Sdelphij	destreg = decode_rh_word_register(emu);
5405197007Sdelphij	srcval = decode_and_fetch_word(emu);
5406197007Sdelphij	res = (int16_t) * destreg * (int16_t)srcval;
5407197007Sdelphij	if (res > 0xFFFF) {
5408197007Sdelphij		SET_FLAG(F_CF);
5409197007Sdelphij		SET_FLAG(F_OF);
5410197007Sdelphij	} else {
5411197007Sdelphij		CLEAR_FLAG(F_CF);
5412197007Sdelphij		CLEAR_FLAG(F_OF);
5413197007Sdelphij	}
5414197007Sdelphij	*destreg = (uint16_t) res;
5415197007Sdelphij}
5416197007Sdelphij
5417197007Sdelphijstatic void
5418197007Sdelphijx86emuOp2_imul_R_RM(struct x86emu *emu)
5419197007Sdelphij{
5420197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5421197007Sdelphij		x86emuOp2_32_imul_R_RM(emu);
5422197007Sdelphij	else
5423197007Sdelphij		x86emuOp2_16_imul_R_RM(emu);
5424197007Sdelphij}
5425197007Sdelphij
5426197007Sdelphij/*
5427197007Sdelphij * REMARKS:
5428197007Sdelphij * Handles opcode 0x0f,0xb2
5429197007Sdelphij */
5430197007Sdelphijstatic void
5431197007Sdelphijx86emuOp2_lss_R_IMM(struct x86emu *emu)
5432197007Sdelphij{
5433197007Sdelphij	common_load_far_pointer(emu, &emu->x86.R_SS);
5434197007Sdelphij}
5435197007Sdelphij
5436197007Sdelphij/*
5437197007Sdelphij * REMARKS:
5438197007Sdelphij * Handles opcode 0x0f,0xb3
5439197007Sdelphij */
5440197007Sdelphijstatic void
5441197007Sdelphijx86emuOp2_btr_R(struct x86emu *emu)
5442197007Sdelphij{
5443197007Sdelphij	common_bitstring(emu, 2);
5444197007Sdelphij}
5445197007Sdelphij
5446197007Sdelphij/*
5447197007Sdelphij * REMARKS:
5448197007Sdelphij * Handles opcode 0x0f,0xb4
5449197007Sdelphij */
5450197007Sdelphijstatic void
5451197007Sdelphijx86emuOp2_lfs_R_IMM(struct x86emu *emu)
5452197007Sdelphij{
5453197007Sdelphij	common_load_far_pointer(emu, &emu->x86.R_FS);
5454197007Sdelphij}
5455197007Sdelphij
5456197007Sdelphij/*
5457197007Sdelphij * REMARKS:
5458197007Sdelphij * Handles opcode 0x0f,0xb5
5459197007Sdelphij */
5460197007Sdelphijstatic void
5461197007Sdelphijx86emuOp2_lgs_R_IMM(struct x86emu *emu)
5462197007Sdelphij{
5463197007Sdelphij	common_load_far_pointer(emu, &emu->x86.R_GS);
5464197007Sdelphij}
5465197007Sdelphij
5466197007Sdelphij/*
5467197007Sdelphij * REMARKS:
5468197007Sdelphij * Handles opcode 0x0f,0xb6
5469197007Sdelphij */
5470197007Sdelphijstatic void
5471197007Sdelphijx86emuOp2_32_movzx_byte_R_RM(struct x86emu *emu)
5472197007Sdelphij{
5473197007Sdelphij	uint32_t *destreg;
5474197007Sdelphij
5475197007Sdelphij	fetch_decode_modrm(emu);
5476197007Sdelphij	destreg = decode_rh_long_register(emu);
5477197007Sdelphij	*destreg = decode_and_fetch_byte(emu);
5478197007Sdelphij}
5479197007Sdelphij
5480197007Sdelphijstatic void
5481197007Sdelphijx86emuOp2_16_movzx_byte_R_RM(struct x86emu *emu)
5482197007Sdelphij{
5483197007Sdelphij	uint16_t *destreg;
5484197007Sdelphij
5485197007Sdelphij	fetch_decode_modrm(emu);
5486197007Sdelphij	destreg = decode_rh_word_register(emu);
5487197007Sdelphij	*destreg = decode_and_fetch_byte(emu);
5488197007Sdelphij}
5489197007Sdelphij
5490197007Sdelphijstatic void
5491197007Sdelphijx86emuOp2_movzx_byte_R_RM(struct x86emu *emu)
5492197007Sdelphij{
5493197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5494197007Sdelphij		x86emuOp2_32_movzx_byte_R_RM(emu);
5495197007Sdelphij	else
5496197007Sdelphij		x86emuOp2_16_movzx_byte_R_RM(emu);
5497197007Sdelphij}
5498197007Sdelphij
5499197007Sdelphij/*
5500197007Sdelphij * REMARKS:
5501197007Sdelphij * Handles opcode 0x0f,0xb7
5502197007Sdelphij */
5503197007Sdelphijstatic void
5504197007Sdelphijx86emuOp2_movzx_word_R_RM(struct x86emu *emu)
5505197007Sdelphij{
5506197007Sdelphij	uint32_t *destreg;
5507197007Sdelphij
5508197007Sdelphij	fetch_decode_modrm(emu);
5509197007Sdelphij	destreg = decode_rh_long_register(emu);
5510197007Sdelphij	*destreg = decode_and_fetch_word(emu);
5511197007Sdelphij}
5512197007Sdelphij
5513197007Sdelphij/*
5514197007Sdelphij * REMARKS:
5515197007Sdelphij * Handles opcode 0x0f,0xba
5516197007Sdelphij */
5517197007Sdelphijstatic void
5518197007Sdelphijx86emuOp2_32_btX_I(struct x86emu *emu)
5519197007Sdelphij{
5520197007Sdelphij	int bit;
5521197007Sdelphij	uint32_t srcval, mask;
5522197007Sdelphij	uint8_t shift;
5523197007Sdelphij
5524197007Sdelphij	fetch_decode_modrm(emu);
5525197007Sdelphij	if (emu->cur_rh < 4)
5526197007Sdelphij		x86emu_halt_sys(emu);
5527197007Sdelphij
5528197007Sdelphij	srcval = decode_and_fetch_long_imm8(emu, &shift);
5529197007Sdelphij	bit = shift & 0x1F;
5530197007Sdelphij	mask = (0x1 << bit);
5531197007Sdelphij
5532197007Sdelphij	switch (emu->cur_rh) {
5533197007Sdelphij	case 5:
5534197007Sdelphij		write_back_long(emu, srcval | mask);
5535197007Sdelphij		break;
5536197007Sdelphij	case 6:
5537197007Sdelphij		write_back_long(emu, srcval & ~mask);
5538197007Sdelphij		break;
5539197007Sdelphij	case 7:
5540197007Sdelphij		write_back_long(emu, srcval ^ mask);
5541197007Sdelphij		break;
5542197007Sdelphij	}
5543197007Sdelphij	CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5544197007Sdelphij}
5545197007Sdelphij
5546197007Sdelphijstatic void
5547197007Sdelphijx86emuOp2_16_btX_I(struct x86emu *emu)
5548197007Sdelphij{
5549197007Sdelphij	int bit;
5550197007Sdelphij
5551197007Sdelphij	uint16_t srcval, mask;
5552197007Sdelphij	uint8_t shift;
5553197007Sdelphij
5554197007Sdelphij	fetch_decode_modrm(emu);
5555197007Sdelphij	if (emu->cur_rh < 4)
5556197007Sdelphij		x86emu_halt_sys(emu);
5557197007Sdelphij
5558197007Sdelphij	srcval = decode_and_fetch_word_imm8(emu, &shift);
5559197007Sdelphij	bit = shift & 0xF;
5560197007Sdelphij	mask = (0x1 << bit);
5561197007Sdelphij	switch (emu->cur_rh) {
5562197007Sdelphij	case 5:
5563197007Sdelphij		write_back_word(emu, srcval | mask);
5564197007Sdelphij		break;
5565197007Sdelphij	case 6:
5566197007Sdelphij		write_back_word(emu, srcval & ~mask);
5567197007Sdelphij		break;
5568197007Sdelphij	case 7:
5569197007Sdelphij		write_back_word(emu, srcval ^ mask);
5570197007Sdelphij		break;
5571197007Sdelphij	}
5572197007Sdelphij	CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5573197007Sdelphij}
5574197007Sdelphij
5575197007Sdelphijstatic void
5576197007Sdelphijx86emuOp2_btX_I(struct x86emu *emu)
5577197007Sdelphij{
5578197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5579197007Sdelphij		x86emuOp2_32_btX_I(emu);
5580197007Sdelphij	else
5581197007Sdelphij		x86emuOp2_16_btX_I(emu);
5582197007Sdelphij}
5583197007Sdelphij
5584197007Sdelphij/*
5585197007Sdelphij * REMARKS:
5586197007Sdelphij * Handles opcode 0x0f,0xbb
5587197007Sdelphij */
5588197007Sdelphijstatic void
5589197007Sdelphijx86emuOp2_btc_R(struct x86emu *emu)
5590197007Sdelphij{
5591197007Sdelphij	common_bitstring(emu, 3);
5592197007Sdelphij}
5593197007Sdelphij
5594197007Sdelphij/*
5595197007Sdelphij * REMARKS:
5596197007Sdelphij * Handles opcode 0x0f,0xbc
5597197007Sdelphij */
5598197007Sdelphijstatic void
5599197007Sdelphijx86emuOp2_bsf(struct x86emu *emu)
5600197007Sdelphij{
5601197007Sdelphij	common_bitsearch(emu, +1);
5602197007Sdelphij}
5603197007Sdelphij
5604197007Sdelphij/*
5605197007Sdelphij * REMARKS:
5606197007Sdelphij * Handles opcode 0x0f,0xbd
5607197007Sdelphij */
5608197007Sdelphijstatic void
5609197007Sdelphijx86emuOp2_bsr(struct x86emu *emu)
5610197007Sdelphij{
5611197007Sdelphij	common_bitsearch(emu, -1);
5612197007Sdelphij}
5613197007Sdelphij
5614197007Sdelphij/*
5615197007Sdelphij * REMARKS:
5616197007Sdelphij * Handles opcode 0x0f,0xbe
5617197007Sdelphij */
5618197007Sdelphijstatic void
5619197007Sdelphijx86emuOp2_32_movsx_byte_R_RM(struct x86emu *emu)
5620197007Sdelphij{
5621197007Sdelphij	uint32_t *destreg;
5622197007Sdelphij
5623267372Sdelphij	fetch_decode_modrm(emu);
5624197007Sdelphij	destreg = decode_rh_long_register(emu);
5625197007Sdelphij	*destreg = (int32_t)(int8_t)decode_and_fetch_byte(emu);
5626197007Sdelphij}
5627197007Sdelphij
5628197007Sdelphijstatic void
5629197007Sdelphijx86emuOp2_16_movsx_byte_R_RM(struct x86emu *emu)
5630197007Sdelphij{
5631197007Sdelphij	uint16_t *destreg;
5632197007Sdelphij
5633197007Sdelphij	fetch_decode_modrm(emu);
5634197007Sdelphij	destreg = decode_rh_word_register(emu);
5635197007Sdelphij	*destreg = (int16_t)(int8_t)decode_and_fetch_byte(emu);
5636197007Sdelphij}
5637197007Sdelphij
5638197007Sdelphijstatic void
5639197007Sdelphijx86emuOp2_movsx_byte_R_RM(struct x86emu *emu)
5640197007Sdelphij{
5641197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5642197007Sdelphij		x86emuOp2_32_movsx_byte_R_RM(emu);
5643197007Sdelphij	else
5644197007Sdelphij		x86emuOp2_16_movsx_byte_R_RM(emu);
5645197007Sdelphij}
5646197007Sdelphij
5647197007Sdelphij/*
5648197007Sdelphij * REMARKS:
5649197007Sdelphij * Handles opcode 0x0f,0xbf
5650197007Sdelphij */
5651197007Sdelphijstatic void
5652197007Sdelphijx86emuOp2_movsx_word_R_RM(struct x86emu *emu)
5653197007Sdelphij{
5654197007Sdelphij	uint32_t *destreg;
5655197007Sdelphij
5656197007Sdelphij	fetch_decode_modrm(emu);
5657197007Sdelphij	destreg = decode_rh_long_register(emu);
5658197007Sdelphij	*destreg = (int32_t)(int16_t)decode_and_fetch_word(emu);
5659197007Sdelphij}
5660197007Sdelphij
5661197007Sdelphijstatic void
5662197007Sdelphijx86emu_exec_two_byte(struct x86emu * emu)
5663197007Sdelphij{
5664197007Sdelphij	uint8_t op2;
5665197007Sdelphij
5666197007Sdelphij	op2 = fetch_byte_imm(emu);
5667197007Sdelphij
5668197007Sdelphij	switch (op2) {
5669197007Sdelphij	/* 0x00 Group F (ring 0 PM)      */
5670197007Sdelphij	/* 0x01 Group G (ring 0 PM)      */
5671197007Sdelphij	/* 0x02 lar (ring 0 PM)          */
5672197007Sdelphij	/* 0x03 lsl (ring 0 PM)          */
5673197007Sdelphij	/* 0x05 loadall (undocumented)   */
5674197007Sdelphij	/* 0x06 clts (ring 0 PM)         */
5675197007Sdelphij	/* 0x07 loadall (undocumented)   */
5676197007Sdelphij	/* 0x08 invd (ring 0 PM)         */
5677197007Sdelphij	/* 0x09 wbinvd (ring 0 PM)       */
5678197007Sdelphij
5679197007Sdelphij	/* 0x20 mov reg32(op2); break;creg (ring 0 PM) */
5680197007Sdelphij	/* 0x21 mov reg32(op2); break;dreg (ring 0 PM) */
5681197007Sdelphij	/* 0x22 mov creg(op2); break;reg32 (ring 0 PM) */
5682197007Sdelphij	/* 0x23 mov dreg(op2); break;reg32 (ring 0 PM) */
5683197007Sdelphij	/* 0x24 mov reg32(op2); break;treg (ring 0 PM) */
5684197007Sdelphij	/* 0x26 mov treg(op2); break;reg32 (ring 0 PM) */
5685197007Sdelphij
5686197007Sdelphij	case 0x31:
5687197007Sdelphij		x86emuOp2_rdtsc(emu);
5688197007Sdelphij		break;
5689197007Sdelphij
5690197007Sdelphij	case 0x80:
5691197007Sdelphij		common_jmp_long(emu, ACCESS_FLAG(F_OF));
5692197007Sdelphij		break;
5693197007Sdelphij	case 0x81:
5694197007Sdelphij		common_jmp_long(emu, !ACCESS_FLAG(F_OF));
5695197007Sdelphij		break;
5696197007Sdelphij	case 0x82:
5697197007Sdelphij		common_jmp_long(emu, ACCESS_FLAG(F_CF));
5698197007Sdelphij		break;
5699197007Sdelphij	case 0x83:
5700197007Sdelphij		common_jmp_long(emu, !ACCESS_FLAG(F_CF));
5701197007Sdelphij		break;
5702197007Sdelphij	case 0x84:
5703197007Sdelphij		common_jmp_long(emu, ACCESS_FLAG(F_ZF));
5704197007Sdelphij		break;
5705197007Sdelphij	case 0x85:
5706197007Sdelphij		common_jmp_long(emu, !ACCESS_FLAG(F_ZF));
5707197007Sdelphij		break;
5708197007Sdelphij	case 0x86:
5709197007Sdelphij		common_jmp_long(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5710197007Sdelphij		break;
5711197007Sdelphij	case 0x87:
5712197007Sdelphij		common_jmp_long(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5713197007Sdelphij		break;
5714197007Sdelphij	case 0x88:
5715197007Sdelphij		common_jmp_long(emu, ACCESS_FLAG(F_SF));
5716197007Sdelphij		break;
5717197007Sdelphij	case 0x89:
5718197007Sdelphij		common_jmp_long(emu, !ACCESS_FLAG(F_SF));
5719197007Sdelphij		break;
5720197007Sdelphij	case 0x8a:
5721197007Sdelphij		common_jmp_long(emu, ACCESS_FLAG(F_PF));
5722197007Sdelphij		break;
5723197007Sdelphij	case 0x8b:
5724197007Sdelphij		common_jmp_long(emu, !ACCESS_FLAG(F_PF));
5725197007Sdelphij		break;
5726197007Sdelphij	case 0x8c:
5727204934Sdelphij		common_jmp_long(emu, xorl(ACCESS_FLAG(F_SF),
5728204934Sdelphij		    ACCESS_FLAG(F_OF)));
5729197007Sdelphij		break;
5730197007Sdelphij	case 0x8d:
5731204934Sdelphij		common_jmp_long(emu, !(xorl(ACCESS_FLAG(F_SF),
5732204934Sdelphij		    ACCESS_FLAG(F_OF))));
5733197007Sdelphij		break;
5734197007Sdelphij	case 0x8e:
5735204934Sdelphij		common_jmp_long(emu, (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))
5736204934Sdelphij		    || ACCESS_FLAG(F_ZF)));
5737197007Sdelphij		break;
5738197007Sdelphij	case 0x8f:
5739204934Sdelphij		common_jmp_long(emu,
5740204934Sdelphij		    !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5741204934Sdelphij		    ACCESS_FLAG(F_ZF)));
5742197007Sdelphij		break;
5743197007Sdelphij
5744197007Sdelphij	case 0x90:
5745197007Sdelphij		common_set_byte(emu, ACCESS_FLAG(F_OF));
5746197007Sdelphij		break;
5747197007Sdelphij	case 0x91:
5748197007Sdelphij		common_set_byte(emu, !ACCESS_FLAG(F_OF));
5749197007Sdelphij		break;
5750197007Sdelphij	case 0x92:
5751197007Sdelphij		common_set_byte(emu, ACCESS_FLAG(F_CF));
5752197007Sdelphij		break;
5753197007Sdelphij	case 0x93:
5754197007Sdelphij		common_set_byte(emu, !ACCESS_FLAG(F_CF));
5755197007Sdelphij		break;
5756197007Sdelphij	case 0x94:
5757197007Sdelphij		common_set_byte(emu, ACCESS_FLAG(F_ZF));
5758197007Sdelphij		break;
5759197007Sdelphij	case 0x95:
5760197007Sdelphij		common_set_byte(emu, !ACCESS_FLAG(F_ZF));
5761197007Sdelphij		break;
5762197007Sdelphij	case 0x96:
5763197007Sdelphij		common_set_byte(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5764197007Sdelphij		break;
5765197007Sdelphij	case 0x97:
5766197007Sdelphij		common_set_byte(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5767197007Sdelphij		break;
5768197007Sdelphij	case 0x98:
5769197007Sdelphij		common_set_byte(emu, ACCESS_FLAG(F_SF));
5770197007Sdelphij		break;
5771197007Sdelphij	case 0x99:
5772197007Sdelphij		common_set_byte(emu, !ACCESS_FLAG(F_SF));
5773197007Sdelphij		break;
5774197007Sdelphij	case 0x9a:
5775197007Sdelphij		common_set_byte(emu, ACCESS_FLAG(F_PF));
5776197007Sdelphij		break;
5777197007Sdelphij	case 0x9b:
5778197007Sdelphij		common_set_byte(emu, !ACCESS_FLAG(F_PF));
5779197007Sdelphij		break;
5780197007Sdelphij	case 0x9c:
5781204934Sdelphij		common_set_byte(emu, xorl(ACCESS_FLAG(F_SF),
5782204934Sdelphij		    ACCESS_FLAG(F_OF)));
5783197007Sdelphij		break;
5784197007Sdelphij	case 0x9d:
5785204934Sdelphij		common_set_byte(emu, xorl(ACCESS_FLAG(F_SF),
5786204934Sdelphij		    ACCESS_FLAG(F_OF)));
5787197007Sdelphij		break;
5788197007Sdelphij	case 0x9e:
5789197007Sdelphij		common_set_byte(emu,
5790197007Sdelphij		    (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5791197007Sdelphij		    ACCESS_FLAG(F_ZF)));
5792197007Sdelphij		break;
5793197007Sdelphij	case 0x9f:
5794197007Sdelphij		common_set_byte(emu,
5795197007Sdelphij		    !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5796197007Sdelphij		    ACCESS_FLAG(F_ZF)));
5797197007Sdelphij		break;
5798197007Sdelphij
5799197007Sdelphij	case 0xa0:
5800197007Sdelphij		x86emuOp2_push_FS(emu);
5801197007Sdelphij		break;
5802197007Sdelphij	case 0xa1:
5803197007Sdelphij		x86emuOp2_pop_FS(emu);
5804197007Sdelphij		break;
5805197007Sdelphij	case 0xa2:
5806197007Sdelphij		x86emuOp2_cpuid(emu);
5807197007Sdelphij		break;
5808197007Sdelphij	case 0xa3:
5809197007Sdelphij		x86emuOp2_bt_R(emu);
5810197007Sdelphij		break;
5811197007Sdelphij	case 0xa4:
5812197007Sdelphij		x86emuOp2_shld_IMM(emu);
5813197007Sdelphij		break;
5814197007Sdelphij	case 0xa5:
5815197007Sdelphij		x86emuOp2_shld_CL(emu);
5816197007Sdelphij		break;
5817197007Sdelphij	case 0xa8:
5818197007Sdelphij		x86emuOp2_push_GS(emu);
5819197007Sdelphij		break;
5820197007Sdelphij	case 0xa9:
5821197007Sdelphij		x86emuOp2_pop_GS(emu);
5822197007Sdelphij		break;
5823197007Sdelphij	case 0xab:
5824197007Sdelphij		x86emuOp2_bts_R(emu);
5825197007Sdelphij		break;
5826197007Sdelphij	case 0xac:
5827197007Sdelphij		x86emuOp2_shrd_IMM(emu);
5828197007Sdelphij		break;
5829197007Sdelphij	case 0xad:
5830197007Sdelphij		x86emuOp2_shrd_CL(emu);
5831197007Sdelphij		break;
5832197007Sdelphij	case 0xaf:
5833197007Sdelphij		x86emuOp2_imul_R_RM(emu);
5834197007Sdelphij		break;
5835197007Sdelphij
5836197007Sdelphij	/* 0xb0 TODO: cmpxchg */
5837197007Sdelphij	/* 0xb1 TODO: cmpxchg */
5838197007Sdelphij	case 0xb2:
5839197007Sdelphij		x86emuOp2_lss_R_IMM(emu);
5840197007Sdelphij		break;
5841197007Sdelphij	case 0xb3:
5842197007Sdelphij		x86emuOp2_btr_R(emu);
5843197007Sdelphij		break;
5844197007Sdelphij	case 0xb4:
5845197007Sdelphij		x86emuOp2_lfs_R_IMM(emu);
5846197007Sdelphij		break;
5847197007Sdelphij	case 0xb5:
5848197007Sdelphij		x86emuOp2_lgs_R_IMM(emu);
5849197007Sdelphij		break;
5850197007Sdelphij	case 0xb6:
5851197007Sdelphij		x86emuOp2_movzx_byte_R_RM(emu);
5852197007Sdelphij		break;
5853197007Sdelphij	case 0xb7:
5854197007Sdelphij		x86emuOp2_movzx_word_R_RM(emu);
5855197007Sdelphij		break;
5856197007Sdelphij	case 0xba:
5857197007Sdelphij		x86emuOp2_btX_I(emu);
5858197007Sdelphij		break;
5859197007Sdelphij	case 0xbb:
5860197007Sdelphij		x86emuOp2_btc_R(emu);
5861197007Sdelphij		break;
5862197007Sdelphij	case 0xbc:
5863197007Sdelphij		x86emuOp2_bsf(emu);
5864197007Sdelphij		break;
5865197007Sdelphij	case 0xbd:
5866197007Sdelphij		x86emuOp2_bsr(emu);
5867197007Sdelphij		break;
5868197007Sdelphij	case 0xbe:
5869197007Sdelphij		x86emuOp2_movsx_byte_R_RM(emu);
5870197007Sdelphij		break;
5871197007Sdelphij	case 0xbf:
5872197007Sdelphij		x86emuOp2_movsx_word_R_RM(emu);
5873197007Sdelphij		break;
5874197007Sdelphij
5875197007Sdelphij	/* 0xc0 TODO: xadd */
5876197007Sdelphij	/* 0xc1 TODO: xadd */
5877197007Sdelphij	/* 0xc8 TODO: bswap */
5878197007Sdelphij	/* 0xc9 TODO: bswap */
5879197007Sdelphij	/* 0xca TODO: bswap */
5880197007Sdelphij	/* 0xcb TODO: bswap */
5881197007Sdelphij	/* 0xcc TODO: bswap */
5882197007Sdelphij	/* 0xcd TODO: bswap */
5883197007Sdelphij	/* 0xce TODO: bswap */
5884197007Sdelphij	/* 0xcf TODO: bswap */
5885197007Sdelphij
5886197007Sdelphij	default:
5887197007Sdelphij		x86emu_halt_sys(emu);
5888197007Sdelphij		break;
5889197007Sdelphij	}
5890197007Sdelphij}
5891197007Sdelphij
5892197007Sdelphij/*
5893204934Sdelphij * Carry Chain Calculation
5894204934Sdelphij *
5895204934Sdelphij * This represents a somewhat expensive calculation which is
5896204934Sdelphij * apparently required to emulate the setting of the OF and AF flag.
5897204934Sdelphij * The latter is not so important, but the former is.  The overflow
5898204934Sdelphij * flag is the XOR of the top two bits of the carry chain for an
5899204934Sdelphij * addition (similar for subtraction).  Since we do not want to
5900204934Sdelphij * simulate the addition in a bitwise manner, we try to calculate the
5901204934Sdelphij * carry chain given the two operands and the result.
5902204934Sdelphij *
5903204934Sdelphij * So, given the following table, which represents the addition of two
5904204934Sdelphij * bits, we can derive a formula for the carry chain.
5905204934Sdelphij *
5906204934Sdelphij * a   b   cin   r     cout
5907204934Sdelphij * 0   0   0     0     0
5908204934Sdelphij * 0   0   1     1     0
5909204934Sdelphij * 0   1   0     1     0
5910204934Sdelphij * 0   1   1     0     1
5911204934Sdelphij * 1   0   0     1     0
5912204934Sdelphij * 1   0   1     0     1
5913204934Sdelphij * 1   1   0     0     1
5914204934Sdelphij * 1   1   1     1     1
5915204934Sdelphij *
5916204934Sdelphij * Construction of table for cout:
5917204934Sdelphij *
5918204934Sdelphij * ab
5919204934Sdelphij * r  \  00   01   11  10
5920204934Sdelphij * |------------------
5921204934Sdelphij * 0  |   0    1    1   1
5922204934Sdelphij * 1  |   0    0    1   0
5923204934Sdelphij *
5924204934Sdelphij * By inspection, one gets:  cc = ab +  r'(a + b)
5925204934Sdelphij *
5926204934Sdelphij * That represents alot of operations, but NO CHOICE....
5927204934Sdelphij *
5928204934Sdelphij * Borrow Chain Calculation.
5929204934Sdelphij *
5930204934Sdelphij * The following table represents the subtraction of two bits, from
5931204934Sdelphij * which we can derive a formula for the borrow chain.
5932204934Sdelphij *
5933204934Sdelphij * a   b   bin   r     bout
5934204934Sdelphij * 0   0   0     0     0
5935204934Sdelphij * 0   0   1     1     1
5936204934Sdelphij * 0   1   0     1     1
5937204934Sdelphij * 0   1   1     0     1
5938204934Sdelphij * 1   0   0     1     0
5939204934Sdelphij * 1   0   1     0     0
5940204934Sdelphij * 1   1   0     0     0
5941204934Sdelphij * 1   1   1     1     1
5942204934Sdelphij *
5943204934Sdelphij * Construction of table for cout:
5944204934Sdelphij *
5945204934Sdelphij * ab
5946204934Sdelphij * r  \  00   01   11  10
5947204934Sdelphij * |------------------
5948204934Sdelphij * 0  |   0    1    0   0
5949204934Sdelphij * 1  |   1    1    1   0
5950204934Sdelphij *
5951204934Sdelphij * By inspection, one gets:  bc = a'b +  r(a' + b)
5952204934Sdelphij *
5953197007Sdelphij */
5954197007Sdelphij
5955204934Sdelphij/*
5956204934Sdelphij * Global Variables
5957204934Sdelphij */
5958197007Sdelphij
5959197007Sdelphijstatic uint32_t x86emu_parity_tab[8] =
5960197007Sdelphij{
5961197007Sdelphij	0x96696996,
5962197007Sdelphij	0x69969669,
5963197007Sdelphij	0x69969669,
5964197007Sdelphij	0x96696996,
5965197007Sdelphij	0x69969669,
5966197007Sdelphij	0x96696996,
5967197007Sdelphij	0x96696996,
5968197007Sdelphij	0x69969669,
5969197007Sdelphij};
5970197007Sdelphij#define PARITY(x)   (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
5971197007Sdelphij#define XOR2(x) 	(((x) ^ ((x)>>1)) & 0x1)
5972197007Sdelphij
5973197007Sdelphij
5974197007Sdelphij/*
5975197007Sdelphij * REMARKS:
5976197007Sdelphij * Implements the AAA instruction and side effects.
5977197007Sdelphij */
5978197007Sdelphijstatic uint16_t
5979197007Sdelphijaaa_word(struct x86emu *emu, uint16_t d)
5980197007Sdelphij{
5981197007Sdelphij	uint16_t res;
5982197007Sdelphij	if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
5983197007Sdelphij		d += 0x6;
5984197007Sdelphij		d += 0x100;
5985197007Sdelphij		SET_FLAG(F_AF);
5986197007Sdelphij		SET_FLAG(F_CF);
5987197007Sdelphij	} else {
5988197007Sdelphij		CLEAR_FLAG(F_CF);
5989197007Sdelphij		CLEAR_FLAG(F_AF);
5990197007Sdelphij	}
5991197007Sdelphij	res = (uint16_t) (d & 0xFF0F);
5992197007Sdelphij	CLEAR_FLAG(F_SF);
5993197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
5994197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5995197007Sdelphij	return res;
5996197007Sdelphij}
5997197007Sdelphij
5998197007Sdelphij/*
5999197007Sdelphij * REMARKS:
6000197007Sdelphij * Implements the AAA instruction and side effects.
6001197007Sdelphij */
6002197007Sdelphijstatic uint16_t
6003197007Sdelphijaas_word(struct x86emu *emu, uint16_t d)
6004197007Sdelphij{
6005197007Sdelphij	uint16_t res;
6006197007Sdelphij	if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
6007197007Sdelphij		d -= 0x6;
6008197007Sdelphij		d -= 0x100;
6009197007Sdelphij		SET_FLAG(F_AF);
6010197007Sdelphij		SET_FLAG(F_CF);
6011197007Sdelphij	} else {
6012197007Sdelphij		CLEAR_FLAG(F_CF);
6013197007Sdelphij		CLEAR_FLAG(F_AF);
6014197007Sdelphij	}
6015197007Sdelphij	res = (uint16_t) (d & 0xFF0F);
6016197007Sdelphij	CLEAR_FLAG(F_SF);
6017197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6018197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6019197007Sdelphij	return res;
6020197007Sdelphij}
6021197007Sdelphij
6022197007Sdelphij/*
6023197007Sdelphij * REMARKS:
6024197007Sdelphij * Implements the AAD instruction and side effects.
6025197007Sdelphij */
6026197007Sdelphijstatic uint16_t
6027197007Sdelphijaad_word(struct x86emu *emu, uint16_t d)
6028197007Sdelphij{
6029197007Sdelphij	uint16_t l;
6030197007Sdelphij	uint8_t hb, lb;
6031197007Sdelphij
6032197007Sdelphij	hb = (uint8_t) ((d >> 8) & 0xff);
6033197007Sdelphij	lb = (uint8_t) ((d & 0xff));
6034197007Sdelphij	l = (uint16_t) ((lb + 10 * hb) & 0xFF);
6035197007Sdelphij
6036197007Sdelphij	CLEAR_FLAG(F_CF);
6037197007Sdelphij	CLEAR_FLAG(F_AF);
6038197007Sdelphij	CLEAR_FLAG(F_OF);
6039197007Sdelphij	CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
6040197007Sdelphij	CONDITIONAL_SET_FLAG(l == 0, F_ZF);
6041197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
6042197007Sdelphij	return l;
6043197007Sdelphij}
6044197007Sdelphij
6045197007Sdelphij/*
6046197007Sdelphij * REMARKS:
6047197007Sdelphij * Implements the AAM instruction and side effects.
6048197007Sdelphij */
6049197007Sdelphijstatic uint16_t
6050197007Sdelphijaam_word(struct x86emu *emu, uint8_t d)
6051197007Sdelphij{
6052197007Sdelphij	uint16_t h, l;
6053197007Sdelphij
6054197007Sdelphij	h = (uint16_t) (d / 10);
6055197007Sdelphij	l = (uint16_t) (d % 10);
6056197007Sdelphij	l |= (uint16_t) (h << 8);
6057197007Sdelphij
6058197007Sdelphij	CLEAR_FLAG(F_CF);
6059197007Sdelphij	CLEAR_FLAG(F_AF);
6060197007Sdelphij	CLEAR_FLAG(F_OF);
6061197007Sdelphij	CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
6062197007Sdelphij	CONDITIONAL_SET_FLAG(l == 0, F_ZF);
6063197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
6064197007Sdelphij	return l;
6065197007Sdelphij}
6066197007Sdelphij
6067197007Sdelphij/*
6068197007Sdelphij * REMARKS:
6069197007Sdelphij * Implements the ADC instruction and side effects.
6070197007Sdelphij */
6071197007Sdelphijstatic uint8_t
6072197007Sdelphijadc_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6073197007Sdelphij{
6074197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6075197007Sdelphij	uint32_t cc;
6076197007Sdelphij
6077197007Sdelphij	if (ACCESS_FLAG(F_CF))
6078197007Sdelphij		res = 1 + d + s;
6079197007Sdelphij	else
6080197007Sdelphij		res = d + s;
6081197007Sdelphij
6082197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
6083197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6084197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6085197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6086197007Sdelphij
6087197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6088197007Sdelphij	cc = (s & d) | ((~res) & (s | d));
6089197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6090197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6091197007Sdelphij	return (uint8_t) res;
6092197007Sdelphij}
6093197007Sdelphij
6094197007Sdelphij/*
6095197007Sdelphij * REMARKS:
6096197007Sdelphij * Implements the ADC instruction and side effects.
6097197007Sdelphij */
6098197007Sdelphijstatic uint16_t
6099197007Sdelphijadc_word(struct x86emu *emu, uint16_t d, uint16_t s)
6100197007Sdelphij{
6101197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6102197007Sdelphij	uint32_t cc;
6103197007Sdelphij
6104197007Sdelphij	if (ACCESS_FLAG(F_CF))
6105197007Sdelphij		res = 1 + d + s;
6106197007Sdelphij	else
6107197007Sdelphij		res = d + s;
6108197007Sdelphij
6109197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
6110197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6111197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6112197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6113197007Sdelphij
6114197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6115197007Sdelphij	cc = (s & d) | ((~res) & (s | d));
6116197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6117197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6118197007Sdelphij	return (uint16_t) res;
6119197007Sdelphij}
6120197007Sdelphij
6121197007Sdelphij/*
6122197007Sdelphij * REMARKS:
6123197007Sdelphij * Implements the ADC instruction and side effects.
6124197007Sdelphij */
6125197007Sdelphijstatic uint32_t
6126197007Sdelphijadc_long(struct x86emu *emu, uint32_t d, uint32_t s)
6127197007Sdelphij{
6128197007Sdelphij	uint32_t lo;	/* all operands in native machine order */
6129197007Sdelphij	uint32_t hi;
6130197007Sdelphij	uint32_t res;
6131197007Sdelphij	uint32_t cc;
6132197007Sdelphij
6133197007Sdelphij	if (ACCESS_FLAG(F_CF)) {
6134197007Sdelphij		lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
6135197007Sdelphij		res = 1 + d + s;
6136197007Sdelphij	} else {
6137197007Sdelphij		lo = (d & 0xFFFF) + (s & 0xFFFF);
6138197007Sdelphij		res = d + s;
6139197007Sdelphij	}
6140197007Sdelphij	hi = (lo >> 16) + (d >> 16) + (s >> 16);
6141197007Sdelphij
6142197007Sdelphij	CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
6143197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6144197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6145197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6146197007Sdelphij
6147197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6148197007Sdelphij	cc = (s & d) | ((~res) & (s | d));
6149197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6150197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6151197007Sdelphij	return res;
6152197007Sdelphij}
6153197007Sdelphij
6154197007Sdelphij/*
6155197007Sdelphij * REMARKS:
6156197007Sdelphij * Implements the ADD instruction and side effects.
6157197007Sdelphij */
6158197007Sdelphijstatic uint8_t
6159197007Sdelphijadd_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6160197007Sdelphij{
6161197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6162197007Sdelphij	uint32_t cc;
6163197007Sdelphij
6164197007Sdelphij	res = d + s;
6165197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
6166197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6167197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6168197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6169197007Sdelphij
6170197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6171197007Sdelphij	cc = (s & d) | ((~res) & (s | d));
6172197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6173197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6174197007Sdelphij	return (uint8_t) res;
6175197007Sdelphij}
6176197007Sdelphij
6177197007Sdelphij/*
6178197007Sdelphij * REMARKS:
6179197007Sdelphij * Implements the ADD instruction and side effects.
6180197007Sdelphij */
6181197007Sdelphijstatic uint16_t
6182197007Sdelphijadd_word(struct x86emu *emu, uint16_t d, uint16_t s)
6183197007Sdelphij{
6184197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6185197007Sdelphij	uint32_t cc;
6186197007Sdelphij
6187197007Sdelphij	res = d + s;
6188197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
6189197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6190197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6191197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6192197007Sdelphij
6193197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6194197007Sdelphij	cc = (s & d) | ((~res) & (s | d));
6195197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6196197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6197197007Sdelphij	return (uint16_t) res;
6198197007Sdelphij}
6199197007Sdelphij
6200197007Sdelphij/*
6201197007Sdelphij * REMARKS:
6202197007Sdelphij * Implements the ADD instruction and side effects.
6203197007Sdelphij */
6204197007Sdelphijstatic uint32_t
6205197007Sdelphijadd_long(struct x86emu *emu, uint32_t d, uint32_t s)
6206197007Sdelphij{
6207197007Sdelphij	uint32_t lo;	/* all operands in native machine order */
6208197007Sdelphij	uint32_t hi;
6209197007Sdelphij	uint32_t res;
6210197007Sdelphij	uint32_t cc;
6211197007Sdelphij
6212197007Sdelphij	lo = (d & 0xFFFF) + (s & 0xFFFF);
6213197007Sdelphij	res = d + s;
6214197007Sdelphij	hi = (lo >> 16) + (d >> 16) + (s >> 16);
6215197007Sdelphij
6216197007Sdelphij	CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
6217197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6218197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6219197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6220197007Sdelphij
6221197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6222197007Sdelphij	cc = (s & d) | ((~res) & (s | d));
6223197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6224197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6225197007Sdelphij
6226197007Sdelphij	return res;
6227197007Sdelphij}
6228197007Sdelphij
6229197007Sdelphij/*
6230197007Sdelphij * REMARKS:
6231197007Sdelphij * Implements the AND instruction and side effects.
6232197007Sdelphij */
6233197007Sdelphijstatic uint8_t
6234197007Sdelphijand_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6235197007Sdelphij{
6236197007Sdelphij	uint8_t res;	/* all operands in native machine order */
6237197007Sdelphij
6238197007Sdelphij	res = d & s;
6239197007Sdelphij
6240197007Sdelphij	/* set the flags  */
6241197007Sdelphij	CLEAR_FLAG(F_OF);
6242197007Sdelphij	CLEAR_FLAG(F_CF);
6243197007Sdelphij	CLEAR_FLAG(F_AF);
6244197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6245197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6246197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6247197007Sdelphij	return res;
6248197007Sdelphij}
6249197007Sdelphij
6250197007Sdelphij/*
6251197007Sdelphij * REMARKS:
6252197007Sdelphij * Implements the AND instruction and side effects.
6253197007Sdelphij */
6254197007Sdelphijstatic uint16_t
6255197007Sdelphijand_word(struct x86emu *emu, uint16_t d, uint16_t s)
6256197007Sdelphij{
6257197007Sdelphij	uint16_t res;	/* all operands in native machine order */
6258197007Sdelphij
6259197007Sdelphij	res = d & s;
6260197007Sdelphij
6261197007Sdelphij	/* set the flags  */
6262197007Sdelphij	CLEAR_FLAG(F_OF);
6263197007Sdelphij	CLEAR_FLAG(F_CF);
6264197007Sdelphij	CLEAR_FLAG(F_AF);
6265197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6266197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6267197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6268197007Sdelphij	return res;
6269197007Sdelphij}
6270197007Sdelphij
6271197007Sdelphij/*
6272197007Sdelphij * REMARKS:
6273197007Sdelphij * Implements the AND instruction and side effects.
6274197007Sdelphij */
6275197007Sdelphijstatic uint32_t
6276197007Sdelphijand_long(struct x86emu *emu, uint32_t d, uint32_t s)
6277197007Sdelphij{
6278197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6279197007Sdelphij
6280197007Sdelphij	res = d & s;
6281197007Sdelphij
6282197007Sdelphij	/* set the flags  */
6283197007Sdelphij	CLEAR_FLAG(F_OF);
6284197007Sdelphij	CLEAR_FLAG(F_CF);
6285197007Sdelphij	CLEAR_FLAG(F_AF);
6286197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6287197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6288197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6289197007Sdelphij	return res;
6290197007Sdelphij}
6291197007Sdelphij
6292197007Sdelphij/*
6293197007Sdelphij * REMARKS:
6294197007Sdelphij * Implements the CMP instruction and side effects.
6295197007Sdelphij */
6296197007Sdelphijstatic uint8_t
6297197007Sdelphijcmp_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6298197007Sdelphij{
6299197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6300197007Sdelphij	uint32_t bc;
6301197007Sdelphij
6302197007Sdelphij	res = d - s;
6303197007Sdelphij	CLEAR_FLAG(F_CF);
6304197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6305197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6306197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6307197007Sdelphij
6308197007Sdelphij	/* calculate the borrow chain.  See note at top */
6309197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
6310197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
6311197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6312197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6313197007Sdelphij	return d;
6314197007Sdelphij}
6315197007Sdelphij
6316197007Sdelphijstatic void
6317197007Sdelphijcmp_byte_no_return(struct x86emu *emu, uint8_t d, uint8_t s)
6318197007Sdelphij{
6319197007Sdelphij	cmp_byte(emu, d, s);
6320197007Sdelphij}
6321197007Sdelphij
6322197007Sdelphij/*
6323197007Sdelphij * REMARKS:
6324197007Sdelphij * Implements the CMP instruction and side effects.
6325197007Sdelphij */
6326197007Sdelphijstatic uint16_t
6327197007Sdelphijcmp_word(struct x86emu *emu, uint16_t d, uint16_t s)
6328197007Sdelphij{
6329197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6330197007Sdelphij	uint32_t bc;
6331197007Sdelphij
6332197007Sdelphij	res = d - s;
6333197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6334197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6335197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6336197007Sdelphij
6337197007Sdelphij	/* calculate the borrow chain.  See note at top */
6338197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
6339197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
6340197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6341197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6342197007Sdelphij	return d;
6343197007Sdelphij}
6344197007Sdelphij
6345197007Sdelphijstatic void
6346197007Sdelphijcmp_word_no_return(struct x86emu *emu, uint16_t d, uint16_t s)
6347197007Sdelphij{
6348197007Sdelphij	cmp_word(emu, d, s);
6349197007Sdelphij}
6350197007Sdelphij
6351197007Sdelphij/*
6352197007Sdelphij * REMARKS:
6353197007Sdelphij * Implements the CMP instruction and side effects.
6354197007Sdelphij */
6355197007Sdelphijstatic uint32_t
6356197007Sdelphijcmp_long(struct x86emu *emu, uint32_t d, uint32_t s)
6357197007Sdelphij{
6358197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6359197007Sdelphij	uint32_t bc;
6360197007Sdelphij
6361197007Sdelphij	res = d - s;
6362197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6363197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6364197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6365197007Sdelphij
6366197007Sdelphij	/* calculate the borrow chain.  See note at top */
6367197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
6368197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
6369197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6370197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6371197007Sdelphij	return d;
6372197007Sdelphij}
6373197007Sdelphij
6374197007Sdelphijstatic void
6375197007Sdelphijcmp_long_no_return(struct x86emu *emu, uint32_t d, uint32_t s)
6376197007Sdelphij{
6377197007Sdelphij	cmp_long(emu, d, s);
6378197007Sdelphij}
6379197007Sdelphij
6380197007Sdelphij/*
6381197007Sdelphij * REMARKS:
6382197007Sdelphij * Implements the DAA instruction and side effects.
6383197007Sdelphij */
6384197007Sdelphijstatic uint8_t
6385197007Sdelphijdaa_byte(struct x86emu *emu, uint8_t d)
6386197007Sdelphij{
6387197007Sdelphij	uint32_t res = d;
6388197007Sdelphij	if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6389197007Sdelphij		res += 6;
6390197007Sdelphij		SET_FLAG(F_AF);
6391197007Sdelphij	}
6392197007Sdelphij	if (res > 0x9F || ACCESS_FLAG(F_CF)) {
6393197007Sdelphij		res += 0x60;
6394197007Sdelphij		SET_FLAG(F_CF);
6395197007Sdelphij	}
6396197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6397197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
6398197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6399197007Sdelphij	return (uint8_t) res;
6400197007Sdelphij}
6401197007Sdelphij
6402197007Sdelphij/*
6403197007Sdelphij * REMARKS:
6404197007Sdelphij * Implements the DAS instruction and side effects.
6405197007Sdelphij */
6406197007Sdelphijstatic uint8_t
6407197007Sdelphijdas_byte(struct x86emu *emu, uint8_t d)
6408197007Sdelphij{
6409197007Sdelphij	if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6410197007Sdelphij		d -= 6;
6411197007Sdelphij		SET_FLAG(F_AF);
6412197007Sdelphij	}
6413197007Sdelphij	if (d > 0x9F || ACCESS_FLAG(F_CF)) {
6414197007Sdelphij		d -= 0x60;
6415197007Sdelphij		SET_FLAG(F_CF);
6416197007Sdelphij	}
6417197007Sdelphij	CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
6418197007Sdelphij	CONDITIONAL_SET_FLAG(d == 0, F_ZF);
6419197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
6420197007Sdelphij	return d;
6421197007Sdelphij}
6422197007Sdelphij
6423197007Sdelphij/*
6424197007Sdelphij * REMARKS:
6425197007Sdelphij * Implements the DEC instruction and side effects.
6426197007Sdelphij */
6427197007Sdelphijstatic uint8_t
6428197007Sdelphijdec_byte(struct x86emu *emu, uint8_t d)
6429197007Sdelphij{
6430197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6431197007Sdelphij	uint32_t bc;
6432197007Sdelphij
6433197007Sdelphij	res = d - 1;
6434197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6435197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6436197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6437197007Sdelphij
6438197007Sdelphij	/* calculate the borrow chain.  See note at top */
6439197007Sdelphij	/* based on sub_byte, uses s==1.  */
6440197007Sdelphij	bc = (res & (~d | 1)) | (~d & 1);
6441197007Sdelphij	/* carry flag unchanged */
6442197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6443197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6444197007Sdelphij	return (uint8_t) res;
6445197007Sdelphij}
6446197007Sdelphij
6447197007Sdelphij/*
6448197007Sdelphij * REMARKS:
6449197007Sdelphij * Implements the DEC instruction and side effects.
6450197007Sdelphij */
6451197007Sdelphijstatic uint16_t
6452197007Sdelphijdec_word(struct x86emu *emu, uint16_t d)
6453197007Sdelphij{
6454197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6455197007Sdelphij	uint32_t bc;
6456197007Sdelphij
6457197007Sdelphij	res = d - 1;
6458197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6459197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6460197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6461197007Sdelphij
6462197007Sdelphij	/* calculate the borrow chain.  See note at top */
6463197007Sdelphij	/* based on the sub_byte routine, with s==1 */
6464197007Sdelphij	bc = (res & (~d | 1)) | (~d & 1);
6465197007Sdelphij	/* carry flag unchanged */
6466197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6467197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6468197007Sdelphij	return (uint16_t) res;
6469197007Sdelphij}
6470197007Sdelphij
6471197007Sdelphij/*
6472197007Sdelphij * REMARKS:
6473197007Sdelphij * Implements the DEC instruction and side effects.
6474197007Sdelphij */
6475197007Sdelphijstatic uint32_t
6476197007Sdelphijdec_long(struct x86emu *emu, uint32_t d)
6477197007Sdelphij{
6478197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6479197007Sdelphij	uint32_t bc;
6480197007Sdelphij
6481197007Sdelphij	res = d - 1;
6482197007Sdelphij
6483197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6484197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6485197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6486197007Sdelphij
6487197007Sdelphij	/* calculate the borrow chain.  See note at top */
6488197007Sdelphij	bc = (res & (~d | 1)) | (~d & 1);
6489197007Sdelphij	/* carry flag unchanged */
6490197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6491197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6492197007Sdelphij	return res;
6493197007Sdelphij}
6494197007Sdelphij
6495197007Sdelphij/*
6496197007Sdelphij * REMARKS:
6497197007Sdelphij * Implements the INC instruction and side effects.
6498197007Sdelphij */
6499197007Sdelphijstatic uint8_t
6500197007Sdelphijinc_byte(struct x86emu *emu, uint8_t d)
6501197007Sdelphij{
6502197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6503197007Sdelphij	uint32_t cc;
6504197007Sdelphij
6505197007Sdelphij	res = d + 1;
6506197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6507197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6508197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6509197007Sdelphij
6510197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6511197007Sdelphij	cc = ((1 & d) | (~res)) & (1 | d);
6512197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6513197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6514197007Sdelphij	return (uint8_t) res;
6515197007Sdelphij}
6516197007Sdelphij
6517197007Sdelphij/*
6518197007Sdelphij * REMARKS:
6519197007Sdelphij * Implements the INC instruction and side effects.
6520197007Sdelphij */
6521197007Sdelphijstatic uint16_t
6522197007Sdelphijinc_word(struct x86emu *emu, uint16_t d)
6523197007Sdelphij{
6524197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6525197007Sdelphij	uint32_t cc;
6526197007Sdelphij
6527197007Sdelphij	res = d + 1;
6528197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6529197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6530197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6531197007Sdelphij
6532197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6533197007Sdelphij	cc = (1 & d) | ((~res) & (1 | d));
6534197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6535197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6536197007Sdelphij	return (uint16_t) res;
6537197007Sdelphij}
6538197007Sdelphij
6539197007Sdelphij/*
6540197007Sdelphij * REMARKS:
6541197007Sdelphij * Implements the INC instruction and side effects.
6542197007Sdelphij */
6543197007Sdelphijstatic uint32_t
6544197007Sdelphijinc_long(struct x86emu *emu, uint32_t d)
6545197007Sdelphij{
6546197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6547197007Sdelphij	uint32_t cc;
6548197007Sdelphij
6549197007Sdelphij	res = d + 1;
6550197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6551197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6552197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6553197007Sdelphij
6554197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6555197007Sdelphij	cc = (1 & d) | ((~res) & (1 | d));
6556197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6557197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6558197007Sdelphij	return res;
6559197007Sdelphij}
6560197007Sdelphij
6561197007Sdelphij/*
6562197007Sdelphij * REMARKS:
6563197007Sdelphij * Implements the OR instruction and side effects.
6564197007Sdelphij */
6565197007Sdelphijstatic uint8_t
6566197007Sdelphijor_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6567197007Sdelphij{
6568197007Sdelphij	uint8_t res;	/* all operands in native machine order */
6569197007Sdelphij
6570197007Sdelphij	res = d | s;
6571197007Sdelphij	CLEAR_FLAG(F_OF);
6572197007Sdelphij	CLEAR_FLAG(F_CF);
6573197007Sdelphij	CLEAR_FLAG(F_AF);
6574197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6575197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6576197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6577197007Sdelphij	return res;
6578197007Sdelphij}
6579197007Sdelphij
6580197007Sdelphij/*
6581197007Sdelphij * REMARKS:
6582197007Sdelphij * Implements the OR instruction and side effects.
6583197007Sdelphij */
6584197007Sdelphijstatic uint16_t
6585197007Sdelphijor_word(struct x86emu *emu, uint16_t d, uint16_t s)
6586197007Sdelphij{
6587197007Sdelphij	uint16_t res;	/* all operands in native machine order */
6588197007Sdelphij
6589197007Sdelphij	res = d | s;
6590197007Sdelphij	/* set the carry flag to be bit 8 */
6591197007Sdelphij	CLEAR_FLAG(F_OF);
6592197007Sdelphij	CLEAR_FLAG(F_CF);
6593197007Sdelphij	CLEAR_FLAG(F_AF);
6594197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6595197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6596197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6597197007Sdelphij	return res;
6598197007Sdelphij}
6599197007Sdelphij
6600197007Sdelphij/*
6601197007Sdelphij * REMARKS:
6602197007Sdelphij * Implements the OR instruction and side effects.
6603197007Sdelphij */
6604197007Sdelphijstatic uint32_t
6605197007Sdelphijor_long(struct x86emu *emu, uint32_t d, uint32_t s)
6606197007Sdelphij{
6607197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6608197007Sdelphij
6609197007Sdelphij	res = d | s;
6610197007Sdelphij
6611197007Sdelphij	/* set the carry flag to be bit 8 */
6612197007Sdelphij	CLEAR_FLAG(F_OF);
6613197007Sdelphij	CLEAR_FLAG(F_CF);
6614197007Sdelphij	CLEAR_FLAG(F_AF);
6615197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6616197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6617197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6618197007Sdelphij	return res;
6619197007Sdelphij}
6620197007Sdelphij
6621197007Sdelphij/*
6622197007Sdelphij * REMARKS:
6623197007Sdelphij * Implements the OR instruction and side effects.
6624197007Sdelphij */
6625197007Sdelphijstatic uint8_t
6626197007Sdelphijneg_byte(struct x86emu *emu, uint8_t s)
6627197007Sdelphij{
6628197007Sdelphij	uint8_t res;
6629197007Sdelphij	uint8_t bc;
6630197007Sdelphij
6631197007Sdelphij	CONDITIONAL_SET_FLAG(s != 0, F_CF);
6632197007Sdelphij	res = (uint8_t) - s;
6633197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6634197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6635197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6636197007Sdelphij	/* calculate the borrow chain --- modified such that d=0.
6637197007Sdelphij	 * substitutiing d=0 into     bc= res&(~d|s)|(~d&s); (the one used for
6638197007Sdelphij	 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6639197007Sdelphij	 * res&0xfff... == res.  Similarly ~d&s == s.  So the simplified
6640197007Sdelphij	 * result is: */
6641197007Sdelphij	bc = res | s;
6642197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6643197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6644197007Sdelphij	return res;
6645197007Sdelphij}
6646197007Sdelphij
6647197007Sdelphij/*
6648197007Sdelphij * REMARKS:
6649197007Sdelphij * Implements the OR instruction and side effects.
6650197007Sdelphij */
6651197007Sdelphijstatic uint16_t
6652197007Sdelphijneg_word(struct x86emu *emu, uint16_t s)
6653197007Sdelphij{
6654197007Sdelphij	uint16_t res;
6655197007Sdelphij	uint16_t bc;
6656197007Sdelphij
6657197007Sdelphij	CONDITIONAL_SET_FLAG(s != 0, F_CF);
6658197007Sdelphij	res = (uint16_t) - s;
6659197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6660197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6661197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6662197007Sdelphij
6663197007Sdelphij	/* calculate the borrow chain --- modified such that d=0.
6664197007Sdelphij	 * substitutiing d=0 into     bc= res&(~d|s)|(~d&s); (the one used for
6665197007Sdelphij	 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6666197007Sdelphij	 * res&0xfff... == res.  Similarly ~d&s == s.  So the simplified
6667197007Sdelphij	 * result is: */
6668197007Sdelphij	bc = res | s;
6669197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6670197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6671197007Sdelphij	return res;
6672197007Sdelphij}
6673197007Sdelphij
6674197007Sdelphij/*
6675197007Sdelphij * REMARKS:
6676197007Sdelphij * Implements the OR instruction and side effects.
6677197007Sdelphij */
6678197007Sdelphijstatic uint32_t
6679197007Sdelphijneg_long(struct x86emu *emu, uint32_t s)
6680197007Sdelphij{
6681197007Sdelphij	uint32_t res;
6682197007Sdelphij	uint32_t bc;
6683197007Sdelphij
6684197007Sdelphij	CONDITIONAL_SET_FLAG(s != 0, F_CF);
6685197007Sdelphij	res = (uint32_t) - s;
6686197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6687197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6688197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6689197007Sdelphij
6690197007Sdelphij	/* calculate the borrow chain --- modified such that d=0.
6691197007Sdelphij	 * substitutiing d=0 into     bc= res&(~d|s)|(~d&s); (the one used for
6692197007Sdelphij	 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6693197007Sdelphij	 * res&0xfff... == res.  Similarly ~d&s == s.  So the simplified
6694197007Sdelphij	 * result is: */
6695197007Sdelphij	bc = res | s;
6696197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6697197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6698197007Sdelphij	return res;
6699197007Sdelphij}
6700197007Sdelphij
6701197007Sdelphij/*
6702197007Sdelphij * REMARKS:
6703197007Sdelphij * Implements the RCL instruction and side effects.
6704197007Sdelphij */
6705197007Sdelphijstatic uint8_t
6706197007Sdelphijrcl_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6707197007Sdelphij{
6708197007Sdelphij	unsigned int res, cnt, mask, cf;
6709197007Sdelphij
6710197007Sdelphij	/* s is the rotate distance.  It varies from 0 - 8. */
6711197007Sdelphij	/* have
6712197007Sdelphij	 *
6713197007Sdelphij	 * CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6714197007Sdelphij	 *
6715197007Sdelphij	 * want to rotate through the carry by "s" bits.  We could loop, but
6716197007Sdelphij	 * that's inefficient.  So the width is 9, and we split into three
6717197007Sdelphij	 * parts:
6718197007Sdelphij	 *
6719204934Sdelphij	 * The new carry flag   (was B_n) the stuff in B_n-1 .. B_0 the stuff
6720204934Sdelphij	 * in B_7 .. B_n+1
6721197007Sdelphij	 *
6722204934Sdelphij	 * The new rotate is done mod 9, and given this, for a rotation of n
6723204934Sdelphij	 * bits (mod 9) the new carry flag is then located n bits from the MSB.
6724197007Sdelphij	 * The low part is then shifted up cnt bits, and the high part is or'd
6725197007Sdelphij	 * in.  Using CAPS for new values, and lowercase for the original
6726197007Sdelphij	 * values, this can be expressed as:
6727197007Sdelphij	 *
6728197007Sdelphij	 * IF n > 0 1) CF <-  b_(8-n) 2) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0
6729204934Sdelphij	 * 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1))
6730204934Sdelphij	 */
6731197007Sdelphij	res = d;
6732197007Sdelphij	if ((cnt = s % 9) != 0) {
6733197007Sdelphij		/* extract the new CARRY FLAG. */
6734197007Sdelphij		/* CF <-  b_(8-n)             */
6735197007Sdelphij		cf = (d >> (8 - cnt)) & 0x1;
6736197007Sdelphij
6737204934Sdelphij		/*
6738204934Sdelphij		 * Get the low stuff which rotated into the range B_7 .. B_cnt
6739204934Sdelphij		 * B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0
6740204934Sdelphij		 * note that the right hand side done by the mask.
6741204934Sdelphij		 */
6742197007Sdelphij		res = (d << cnt) & 0xff;
6743197007Sdelphij
6744204934Sdelphij		/*
6745204934Sdelphij		 * now the high stuff which rotated around into the positions
6746204934Sdelphij		 * B_cnt-2 .. B_0
6747204934Sdelphij		 * B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1))
6748204934Sdelphij		 * shift it downward, 7-(n-2) = 9-n positions. and mask off
6749204934Sdelphij		 * the result before or'ing in.
6750204934Sdelphij		 */
6751197007Sdelphij		mask = (1 << (cnt - 1)) - 1;
6752197007Sdelphij		res |= (d >> (9 - cnt)) & mask;
6753197007Sdelphij
6754197007Sdelphij		/* if the carry flag was set, or it in.  */
6755197007Sdelphij		if (ACCESS_FLAG(F_CF)) {	/* carry flag is set */
6756197007Sdelphij			/* B_(n-1) <- cf */
6757197007Sdelphij			res |= 1 << (cnt - 1);
6758197007Sdelphij		}
6759197007Sdelphij		/* set the new carry flag, based on the variable "cf" */
6760197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
6761197007Sdelphij		/* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6762197007Sdelphij		 * the most significant bit.  Blecck. */
6763197007Sdelphij		/* parenthesized this expression since it appears to be
6764197007Sdelphij		 * causing OF to be misset */
6765197007Sdelphij		CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
6766197007Sdelphij		    F_OF);
6767197007Sdelphij
6768197007Sdelphij	}
6769197007Sdelphij	return (uint8_t) res;
6770197007Sdelphij}
6771197007Sdelphij
6772197007Sdelphij/*
6773197007Sdelphij * REMARKS:
6774197007Sdelphij * Implements the RCL instruction and side effects.
6775197007Sdelphij */
6776197007Sdelphijstatic uint16_t
6777197007Sdelphijrcl_word(struct x86emu *emu, uint16_t d, uint8_t s)
6778197007Sdelphij{
6779197007Sdelphij	unsigned int res, cnt, mask, cf;
6780197007Sdelphij
6781197007Sdelphij	res = d;
6782197007Sdelphij	if ((cnt = s % 17) != 0) {
6783197007Sdelphij		cf = (d >> (16 - cnt)) & 0x1;
6784197007Sdelphij		res = (d << cnt) & 0xffff;
6785197007Sdelphij		mask = (1 << (cnt - 1)) - 1;
6786197007Sdelphij		res |= (d >> (17 - cnt)) & mask;
6787197007Sdelphij		if (ACCESS_FLAG(F_CF)) {
6788197007Sdelphij			res |= 1 << (cnt - 1);
6789197007Sdelphij		}
6790197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
6791197007Sdelphij		CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
6792197007Sdelphij		    F_OF);
6793197007Sdelphij	}
6794197007Sdelphij	return (uint16_t) res;
6795197007Sdelphij}
6796197007Sdelphij
6797197007Sdelphij/*
6798197007Sdelphij * REMARKS:
6799197007Sdelphij * Implements the RCL instruction and side effects.
6800197007Sdelphij */
6801197007Sdelphijstatic uint32_t
6802197007Sdelphijrcl_long(struct x86emu *emu, uint32_t d, uint8_t s)
6803197007Sdelphij{
6804197007Sdelphij	uint32_t res, cnt, mask, cf;
6805197007Sdelphij
6806197007Sdelphij	res = d;
6807197007Sdelphij	if ((cnt = s % 33) != 0) {
6808197007Sdelphij		cf = (d >> (32 - cnt)) & 0x1;
6809197007Sdelphij		res = (d << cnt) & 0xffffffff;
6810197007Sdelphij		mask = (1 << (cnt - 1)) - 1;
6811197007Sdelphij		res |= (d >> (33 - cnt)) & mask;
6812197007Sdelphij		if (ACCESS_FLAG(F_CF)) {	/* carry flag is set */
6813197007Sdelphij			res |= 1 << (cnt - 1);
6814197007Sdelphij		}
6815197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
6816197007Sdelphij		CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
6817197007Sdelphij		    F_OF);
6818197007Sdelphij	}
6819197007Sdelphij	return res;
6820197007Sdelphij}
6821197007Sdelphij
6822197007Sdelphij/*
6823197007Sdelphij * REMARKS:
6824197007Sdelphij * Implements the RCR instruction and side effects.
6825197007Sdelphij */
6826197007Sdelphijstatic uint8_t
6827197007Sdelphijrcr_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6828197007Sdelphij{
6829197007Sdelphij	uint32_t res, cnt;
6830197007Sdelphij	uint32_t mask, cf, ocf = 0;
6831197007Sdelphij
6832197007Sdelphij	/* rotate right through carry */
6833197007Sdelphij	/* s is the rotate distance.  It varies from 0 - 8. d is the byte
6834197007Sdelphij	 * object rotated.
6835197007Sdelphij	 *
6836197007Sdelphij	 * have
6837197007Sdelphij	 *
6838197007Sdelphij	 * CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6839197007Sdelphij	 *
6840204934Sdelphij	 * The new rotate is done mod 9, and given this, for a rotation of n
6841204934Sdelphij	 * bits (mod 9) the new carry flag is then located n bits from the LSB.
6842197007Sdelphij	 * The low part is then shifted up cnt bits, and the high part is or'd
6843197007Sdelphij	 * in.  Using CAPS for new values, and lowercase for the original
6844197007Sdelphij	 * values, this can be expressed as:
6845197007Sdelphij	 *
6846204934Sdelphij	 * IF n > 0
6847204934Sdelphij	 *	1) CF <-  b_(n-1)
6848204934Sdelphij	 *	2) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
6849204934Sdelphij	 * 	3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0)
6850204934Sdelphij	 */
6851197007Sdelphij	res = d;
6852197007Sdelphij	if ((cnt = s % 9) != 0) {
6853197007Sdelphij		/* extract the new CARRY FLAG. */
6854197007Sdelphij		/* CF <-  b_(n-1)              */
6855197007Sdelphij		if (cnt == 1) {
6856197007Sdelphij			cf = d & 0x1;
6857197007Sdelphij			/* note hackery here.  Access_flag(..) evaluates to
6858197007Sdelphij			 * either 0 if flag not set non-zero if flag is set.
6859197007Sdelphij			 * doing access_flag(..) != 0 casts that into either
6860197007Sdelphij			 * 0..1 in any representation of the flags register
6861197007Sdelphij			 * (i.e. packed bit array or unpacked.) */
6862197007Sdelphij			ocf = ACCESS_FLAG(F_CF) != 0;
6863197007Sdelphij		} else
6864197007Sdelphij			cf = (d >> (cnt - 1)) & 0x1;
6865197007Sdelphij
6866197007Sdelphij		/* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_n  */
6867197007Sdelphij		/* note that the right hand side done by the mask This is
6868197007Sdelphij		 * effectively done by shifting the object to the right.  The
6869197007Sdelphij		 * result must be masked, in case the object came in and was
6870197007Sdelphij		 * treated as a negative number.  Needed??? */
6871197007Sdelphij
6872197007Sdelphij		mask = (1 << (8 - cnt)) - 1;
6873197007Sdelphij		res = (d >> cnt) & mask;
6874197007Sdelphij
6875197007Sdelphij		/* now the high stuff which rotated around into the positions
6876197007Sdelphij		 * B_cnt-2 .. B_0 */
6877197007Sdelphij		/* B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0) */
6878197007Sdelphij		/* shift it downward, 7-(n-2) = 9-n positions. and mask off
6879197007Sdelphij		 * the result before or'ing in. */
6880197007Sdelphij		res |= (d << (9 - cnt));
6881197007Sdelphij
6882197007Sdelphij		/* if the carry flag was set, or it in.  */
6883197007Sdelphij		if (ACCESS_FLAG(F_CF)) {	/* carry flag is set */
6884197007Sdelphij			/* B_(8-n) <- cf */
6885197007Sdelphij			res |= 1 << (8 - cnt);
6886197007Sdelphij		}
6887197007Sdelphij		/* set the new carry flag, based on the variable "cf" */
6888197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
6889197007Sdelphij		/* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6890197007Sdelphij		 * the most significant bit.  Blecck. */
6891197007Sdelphij		/* parenthesized... */
6892197007Sdelphij		if (cnt == 1) {
6893197007Sdelphij			CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
6894197007Sdelphij			    F_OF);
6895197007Sdelphij		}
6896197007Sdelphij	}
6897197007Sdelphij	return (uint8_t) res;
6898197007Sdelphij}
6899197007Sdelphij
6900197007Sdelphij/*
6901197007Sdelphij * REMARKS:
6902197007Sdelphij * Implements the RCR instruction and side effects.
6903197007Sdelphij */
6904197007Sdelphijstatic uint16_t
6905197007Sdelphijrcr_word(struct x86emu *emu, uint16_t d, uint8_t s)
6906197007Sdelphij{
6907197007Sdelphij	uint32_t res, cnt;
6908197007Sdelphij	uint32_t mask, cf, ocf = 0;
6909197007Sdelphij
6910197007Sdelphij	/* rotate right through carry */
6911197007Sdelphij	res = d;
6912197007Sdelphij	if ((cnt = s % 17) != 0) {
6913197007Sdelphij		if (cnt == 1) {
6914197007Sdelphij			cf = d & 0x1;
6915197007Sdelphij			ocf = ACCESS_FLAG(F_CF) != 0;
6916197007Sdelphij		} else
6917197007Sdelphij			cf = (d >> (cnt - 1)) & 0x1;
6918197007Sdelphij		mask = (1 << (16 - cnt)) - 1;
6919197007Sdelphij		res = (d >> cnt) & mask;
6920197007Sdelphij		res |= (d << (17 - cnt));
6921197007Sdelphij		if (ACCESS_FLAG(F_CF)) {
6922197007Sdelphij			res |= 1 << (16 - cnt);
6923197007Sdelphij		}
6924197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
6925197007Sdelphij		if (cnt == 1) {
6926197007Sdelphij			CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
6927197007Sdelphij			    F_OF);
6928197007Sdelphij		}
6929197007Sdelphij	}
6930197007Sdelphij	return (uint16_t) res;
6931197007Sdelphij}
6932197007Sdelphij
6933197007Sdelphij/*
6934197007Sdelphij * REMARKS:
6935197007Sdelphij * Implements the RCR instruction and side effects.
6936197007Sdelphij */
6937197007Sdelphijstatic uint32_t
6938197007Sdelphijrcr_long(struct x86emu *emu, uint32_t d, uint8_t s)
6939197007Sdelphij{
6940197007Sdelphij	uint32_t res, cnt;
6941197007Sdelphij	uint32_t mask, cf, ocf = 0;
6942197007Sdelphij
6943197007Sdelphij	/* rotate right through carry */
6944197007Sdelphij	res = d;
6945197007Sdelphij	if ((cnt = s % 33) != 0) {
6946197007Sdelphij		if (cnt == 1) {
6947197007Sdelphij			cf = d & 0x1;
6948197007Sdelphij			ocf = ACCESS_FLAG(F_CF) != 0;
6949197007Sdelphij		} else
6950197007Sdelphij			cf = (d >> (cnt - 1)) & 0x1;
6951197007Sdelphij		mask = (1 << (32 - cnt)) - 1;
6952197007Sdelphij		res = (d >> cnt) & mask;
6953197007Sdelphij		if (cnt != 1)
6954197007Sdelphij			res |= (d << (33 - cnt));
6955197007Sdelphij		if (ACCESS_FLAG(F_CF)) {	/* carry flag is set */
6956197007Sdelphij			res |= 1 << (32 - cnt);
6957197007Sdelphij		}
6958197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
6959197007Sdelphij		if (cnt == 1) {
6960197007Sdelphij			CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
6961197007Sdelphij			    F_OF);
6962197007Sdelphij		}
6963197007Sdelphij	}
6964197007Sdelphij	return res;
6965197007Sdelphij}
6966197007Sdelphij
6967197007Sdelphij/*
6968197007Sdelphij * REMARKS:
6969197007Sdelphij * Implements the ROL instruction and side effects.
6970197007Sdelphij */
6971197007Sdelphijstatic uint8_t
6972197007Sdelphijrol_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6973197007Sdelphij{
6974197007Sdelphij	unsigned int res, cnt, mask;
6975197007Sdelphij
6976197007Sdelphij	/* rotate left */
6977197007Sdelphij	/* s is the rotate distance.  It varies from 0 - 8. d is the byte
6978197007Sdelphij	 * object rotated.
6979197007Sdelphij	 *
6980197007Sdelphij	 * have
6981197007Sdelphij	 *
6982197007Sdelphij	 * CF  B_7 ... B_0
6983197007Sdelphij	 *
6984197007Sdelphij	 * The new rotate is done mod 8. Much simpler than the "rcl" or "rcr"
6985197007Sdelphij	 * operations.
6986197007Sdelphij	 *
6987197007Sdelphij	 * IF n > 0 1) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) 2) B_(n-1) ..
6988197007Sdelphij	 * B_(0) <-  b_(7) .. b_(8-n) */
6989197007Sdelphij	res = d;
6990197007Sdelphij	if ((cnt = s % 8) != 0) {
6991197007Sdelphij		/* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) */
6992197007Sdelphij		res = (d << cnt);
6993197007Sdelphij
6994197007Sdelphij		/* B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n) */
6995197007Sdelphij		mask = (1 << cnt) - 1;
6996197007Sdelphij		res |= (d >> (8 - cnt)) & mask;
6997197007Sdelphij
6998197007Sdelphij		/* OVERFLOW is set *IFF* s==1, then it is the xor of CF and
6999197007Sdelphij		 * the most significant bit.  Blecck. */
7000197007Sdelphij		CONDITIONAL_SET_FLAG(s == 1 &&
7001197007Sdelphij		    XOR2((res & 0x1) + ((res >> 6) & 0x2)),
7002197007Sdelphij		    F_OF);
7003295776Sjkim	}
7004295776Sjkim	if (s != 0) {
7005197007Sdelphij		/* set the new carry flag, Note that it is the low order bit
7006197007Sdelphij		 * of the result!!!                               */
7007197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7008197007Sdelphij	}
7009197007Sdelphij	return (uint8_t) res;
7010197007Sdelphij}
7011197007Sdelphij
7012197007Sdelphij/*
7013197007Sdelphij * REMARKS:
7014197007Sdelphij * Implements the ROL instruction and side effects.
7015197007Sdelphij */
7016197007Sdelphijstatic uint16_t
7017197007Sdelphijrol_word(struct x86emu *emu, uint16_t d, uint8_t s)
7018197007Sdelphij{
7019197007Sdelphij	unsigned int res, cnt, mask;
7020197007Sdelphij
7021197007Sdelphij	res = d;
7022197007Sdelphij	if ((cnt = s % 16) != 0) {
7023197007Sdelphij		res = (d << cnt);
7024197007Sdelphij		mask = (1 << cnt) - 1;
7025197007Sdelphij		res |= (d >> (16 - cnt)) & mask;
7026197007Sdelphij		CONDITIONAL_SET_FLAG(s == 1 &&
7027197007Sdelphij		    XOR2((res & 0x1) + ((res >> 14) & 0x2)),
7028197007Sdelphij		    F_OF);
7029295776Sjkim	}
7030295776Sjkim	if (s != 0) {
7031197007Sdelphij		/* set the new carry flag, Note that it is the low order bit
7032197007Sdelphij		 * of the result!!!                               */
7033197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7034197007Sdelphij	}
7035197007Sdelphij	return (uint16_t) res;
7036197007Sdelphij}
7037197007Sdelphij
7038197007Sdelphij/*
7039197007Sdelphij * REMARKS:
7040197007Sdelphij * Implements the ROL instruction and side effects.
7041197007Sdelphij */
7042197007Sdelphijstatic uint32_t
7043197007Sdelphijrol_long(struct x86emu *emu, uint32_t d, uint8_t s)
7044197007Sdelphij{
7045197007Sdelphij	uint32_t res, cnt, mask;
7046197007Sdelphij
7047197007Sdelphij	res = d;
7048197007Sdelphij	if ((cnt = s % 32) != 0) {
7049197007Sdelphij		res = (d << cnt);
7050197007Sdelphij		mask = (1 << cnt) - 1;
7051197007Sdelphij		res |= (d >> (32 - cnt)) & mask;
7052197007Sdelphij		CONDITIONAL_SET_FLAG(s == 1 &&
7053197007Sdelphij		    XOR2((res & 0x1) + ((res >> 30) & 0x2)),
7054197007Sdelphij		    F_OF);
7055295776Sjkim	}
7056295776Sjkim	if (s != 0) {
7057197007Sdelphij		/* set the new carry flag, Note that it is the low order bit
7058197007Sdelphij		 * of the result!!!                               */
7059197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7060197007Sdelphij	}
7061197007Sdelphij	return res;
7062197007Sdelphij}
7063197007Sdelphij
7064197007Sdelphij/*
7065197007Sdelphij * REMARKS:
7066197007Sdelphij * Implements the ROR instruction and side effects.
7067197007Sdelphij */
7068197007Sdelphijstatic uint8_t
7069197007Sdelphijror_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7070197007Sdelphij{
7071197007Sdelphij	unsigned int res, cnt, mask;
7072197007Sdelphij
7073197007Sdelphij	/* rotate right */
7074197007Sdelphij	/* s is the rotate distance.  It varies from 0 - 8. d is the byte
7075197007Sdelphij	 * object rotated.
7076197007Sdelphij	 *
7077197007Sdelphij	 * have
7078197007Sdelphij	 *
7079197007Sdelphij	 * B_7 ... B_0
7080197007Sdelphij	 *
7081197007Sdelphij	 * The rotate is done mod 8.
7082197007Sdelphij	 *
7083197007Sdelphij	 * IF n > 0 1) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n) 2) B_(7) ..
7084197007Sdelphij	 * B_(8-n) <-  b_(n-1) .. b_(0) */
7085197007Sdelphij	res = d;
7086197007Sdelphij	if ((cnt = s % 8) != 0) {	/* not a typo, do nada if cnt==0 */
7087197007Sdelphij		/* B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0) */
7088197007Sdelphij		res = (d << (8 - cnt));
7089197007Sdelphij
7090197007Sdelphij		/* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n) */
7091197007Sdelphij		mask = (1 << (8 - cnt)) - 1;
7092197007Sdelphij		res |= (d >> (cnt)) & mask;
7093197007Sdelphij
7094197007Sdelphij		/* OVERFLOW is set *IFF* s==1, then it is the xor of the two
7095197007Sdelphij		 * most significant bits.  Blecck. */
7096197007Sdelphij		CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
7097295776Sjkim	}
7098295776Sjkim	if (s != 0) {
7099295776Sjkim		/* set the new carry flag, Note that it is the high order bit
7100197007Sdelphij		 * of the result!!!                               */
7101197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
7102197007Sdelphij	}
7103197007Sdelphij	return (uint8_t) res;
7104197007Sdelphij}
7105197007Sdelphij
7106197007Sdelphij/*
7107197007Sdelphij * REMARKS:
7108197007Sdelphij * Implements the ROR instruction and side effects.
7109197007Sdelphij */
7110197007Sdelphijstatic uint16_t
7111197007Sdelphijror_word(struct x86emu *emu, uint16_t d, uint8_t s)
7112197007Sdelphij{
7113197007Sdelphij	unsigned int res, cnt, mask;
7114197007Sdelphij
7115197007Sdelphij	res = d;
7116197007Sdelphij	if ((cnt = s % 16) != 0) {
7117197007Sdelphij		res = (d << (16 - cnt));
7118197007Sdelphij		mask = (1 << (16 - cnt)) - 1;
7119197007Sdelphij		res |= (d >> (cnt)) & mask;
7120197007Sdelphij		CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
7121295776Sjkim	}
7122295776Sjkim	if (s != 0) {
7123295776Sjkim		/* set the new carry flag, Note that it is the high order bit
7124197007Sdelphij		 * of the result!!!                               */
7125197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
7126197007Sdelphij	}
7127197007Sdelphij	return (uint16_t) res;
7128197007Sdelphij}
7129197007Sdelphij
7130197007Sdelphij/*
7131197007Sdelphij * REMARKS:
7132197007Sdelphij * Implements the ROR instruction and side effects.
7133197007Sdelphij */
7134197007Sdelphijstatic uint32_t
7135197007Sdelphijror_long(struct x86emu *emu, uint32_t d, uint8_t s)
7136197007Sdelphij{
7137197007Sdelphij	uint32_t res, cnt, mask;
7138197007Sdelphij
7139197007Sdelphij	res = d;
7140197007Sdelphij	if ((cnt = s % 32) != 0) {
7141197007Sdelphij		res = (d << (32 - cnt));
7142197007Sdelphij		mask = (1 << (32 - cnt)) - 1;
7143197007Sdelphij		res |= (d >> (cnt)) & mask;
7144197007Sdelphij		CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
7145295776Sjkim	}
7146295776Sjkim	if (s != 0) {
7147295776Sjkim		/* set the new carry flag, Note that it is the high order bit
7148197007Sdelphij		 * of the result!!!                               */
7149197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
7150197007Sdelphij	}
7151197007Sdelphij	return res;
7152197007Sdelphij}
7153197007Sdelphij
7154197007Sdelphij/*
7155197007Sdelphij * REMARKS:
7156197007Sdelphij * Implements the SHL instruction and side effects.
7157197007Sdelphij */
7158197007Sdelphijstatic uint8_t
7159197007Sdelphijshl_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7160197007Sdelphij{
7161197007Sdelphij	unsigned int cnt, res, cf;
7162197007Sdelphij
7163197007Sdelphij	if (s < 8) {
7164197007Sdelphij		cnt = s % 8;
7165197007Sdelphij
7166197007Sdelphij		/* last bit shifted out goes into carry flag */
7167197007Sdelphij		if (cnt > 0) {
7168197007Sdelphij			res = d << cnt;
7169197007Sdelphij			cf = d & (1 << (8 - cnt));
7170197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7171197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7172197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7173197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7174197007Sdelphij		} else {
7175197007Sdelphij			res = (uint8_t) d;
7176197007Sdelphij		}
7177197007Sdelphij
7178197007Sdelphij		if (cnt == 1) {
7179197007Sdelphij			/* Needs simplification. */
7180197007Sdelphij			CONDITIONAL_SET_FLAG(
7181197007Sdelphij			    (((res & 0x80) == 0x80) ^
7182197007Sdelphij				(ACCESS_FLAG(F_CF) != 0)),
7183197007Sdelphij			/* was (emu->x86.R_FLG&F_CF)==F_CF)), */
7184197007Sdelphij			    F_OF);
7185197007Sdelphij		} else {
7186197007Sdelphij			CLEAR_FLAG(F_OF);
7187197007Sdelphij		}
7188197007Sdelphij	} else {
7189197007Sdelphij		res = 0;
7190197007Sdelphij		CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF);
7191197007Sdelphij		CLEAR_FLAG(F_OF);
7192197007Sdelphij		CLEAR_FLAG(F_SF);
7193197007Sdelphij		SET_FLAG(F_PF);
7194197007Sdelphij		SET_FLAG(F_ZF);
7195197007Sdelphij	}
7196197007Sdelphij	return (uint8_t) res;
7197197007Sdelphij}
7198197007Sdelphij
7199197007Sdelphij/*
7200197007Sdelphij * REMARKS:
7201197007Sdelphij * Implements the SHL instruction and side effects.
7202197007Sdelphij */
7203197007Sdelphijstatic uint16_t
7204197007Sdelphijshl_word(struct x86emu *emu, uint16_t d, uint8_t s)
7205197007Sdelphij{
7206197007Sdelphij	unsigned int cnt, res, cf;
7207197007Sdelphij
7208197007Sdelphij	if (s < 16) {
7209197007Sdelphij		cnt = s % 16;
7210197007Sdelphij		if (cnt > 0) {
7211197007Sdelphij			res = d << cnt;
7212197007Sdelphij			cf = d & (1 << (16 - cnt));
7213197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7214197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7215197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7216197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7217197007Sdelphij		} else {
7218197007Sdelphij			res = (uint16_t) d;
7219197007Sdelphij		}
7220197007Sdelphij
7221197007Sdelphij		if (cnt == 1) {
7222197007Sdelphij			CONDITIONAL_SET_FLAG(
7223197007Sdelphij			    (((res & 0x8000) == 0x8000) ^
7224197007Sdelphij				(ACCESS_FLAG(F_CF) != 0)),
7225197007Sdelphij			    F_OF);
7226197007Sdelphij		} else {
7227197007Sdelphij			CLEAR_FLAG(F_OF);
7228197007Sdelphij		}
7229197007Sdelphij	} else {
7230197007Sdelphij		res = 0;
7231197007Sdelphij		CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
7232197007Sdelphij		CLEAR_FLAG(F_OF);
7233197007Sdelphij		CLEAR_FLAG(F_SF);
7234197007Sdelphij		SET_FLAG(F_PF);
7235197007Sdelphij		SET_FLAG(F_ZF);
7236197007Sdelphij	}
7237197007Sdelphij	return (uint16_t) res;
7238197007Sdelphij}
7239197007Sdelphij
7240197007Sdelphij/*
7241197007Sdelphij * REMARKS:
7242197007Sdelphij * Implements the SHL instruction and side effects.
7243197007Sdelphij */
7244197007Sdelphijstatic uint32_t
7245197007Sdelphijshl_long(struct x86emu *emu, uint32_t d, uint8_t s)
7246197007Sdelphij{
7247197007Sdelphij	unsigned int cnt, res, cf;
7248197007Sdelphij
7249197007Sdelphij	if (s < 32) {
7250197007Sdelphij		cnt = s % 32;
7251197007Sdelphij		if (cnt > 0) {
7252197007Sdelphij			res = d << cnt;
7253197007Sdelphij			cf = d & (1 << (32 - cnt));
7254197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7255197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7256197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7257197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7258197007Sdelphij		} else {
7259197007Sdelphij			res = d;
7260197007Sdelphij		}
7261197007Sdelphij		if (cnt == 1) {
7262204934Sdelphij			CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000)
7263204934Sdelphij			    ^ (ACCESS_FLAG(F_CF) != 0)), F_OF);
7264197007Sdelphij		} else {
7265197007Sdelphij			CLEAR_FLAG(F_OF);
7266197007Sdelphij		}
7267197007Sdelphij	} else {
7268197007Sdelphij		res = 0;
7269197007Sdelphij		CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7270197007Sdelphij		CLEAR_FLAG(F_OF);
7271197007Sdelphij		CLEAR_FLAG(F_SF);
7272197007Sdelphij		SET_FLAG(F_PF);
7273197007Sdelphij		SET_FLAG(F_ZF);
7274197007Sdelphij	}
7275197007Sdelphij	return res;
7276197007Sdelphij}
7277197007Sdelphij
7278197007Sdelphij/*
7279197007Sdelphij * REMARKS:
7280197007Sdelphij * Implements the SHR instruction and side effects.
7281197007Sdelphij */
7282197007Sdelphijstatic uint8_t
7283197007Sdelphijshr_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7284197007Sdelphij{
7285197007Sdelphij	unsigned int cnt, res, cf;
7286197007Sdelphij
7287197007Sdelphij	if (s < 8) {
7288197007Sdelphij		cnt = s % 8;
7289197007Sdelphij		if (cnt > 0) {
7290197007Sdelphij			cf = d & (1 << (cnt - 1));
7291197007Sdelphij			res = d >> cnt;
7292197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7293197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7294197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7295197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7296197007Sdelphij		} else {
7297197007Sdelphij			res = (uint8_t) d;
7298197007Sdelphij		}
7299197007Sdelphij
7300197007Sdelphij		if (cnt == 1) {
7301197007Sdelphij			CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
7302197007Sdelphij		} else {
7303197007Sdelphij			CLEAR_FLAG(F_OF);
7304197007Sdelphij		}
7305197007Sdelphij	} else {
7306197007Sdelphij		res = 0;
7307197007Sdelphij		CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF);
7308197007Sdelphij		CLEAR_FLAG(F_OF);
7309197007Sdelphij		CLEAR_FLAG(F_SF);
7310197007Sdelphij		SET_FLAG(F_PF);
7311197007Sdelphij		SET_FLAG(F_ZF);
7312197007Sdelphij	}
7313197007Sdelphij	return (uint8_t) res;
7314197007Sdelphij}
7315197007Sdelphij
7316197007Sdelphij/*
7317197007Sdelphij * REMARKS:
7318197007Sdelphij * Implements the SHR instruction and side effects.
7319197007Sdelphij */
7320197007Sdelphijstatic uint16_t
7321197007Sdelphijshr_word(struct x86emu *emu, uint16_t d, uint8_t s)
7322197007Sdelphij{
7323197007Sdelphij	unsigned int cnt, res, cf;
7324197007Sdelphij
7325197007Sdelphij	if (s < 16) {
7326197007Sdelphij		cnt = s % 16;
7327197007Sdelphij		if (cnt > 0) {
7328197007Sdelphij			cf = d & (1 << (cnt - 1));
7329197007Sdelphij			res = d >> cnt;
7330197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7331197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7332197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7333197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7334197007Sdelphij		} else {
7335197007Sdelphij			res = d;
7336197007Sdelphij		}
7337197007Sdelphij
7338197007Sdelphij		if (cnt == 1) {
7339197007Sdelphij			CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7340197007Sdelphij		} else {
7341197007Sdelphij			CLEAR_FLAG(F_OF);
7342197007Sdelphij		}
7343197007Sdelphij	} else {
7344197007Sdelphij		res = 0;
7345197007Sdelphij		CLEAR_FLAG(F_CF);
7346197007Sdelphij		CLEAR_FLAG(F_OF);
7347197007Sdelphij		SET_FLAG(F_ZF);
7348197007Sdelphij		CLEAR_FLAG(F_SF);
7349197007Sdelphij		CLEAR_FLAG(F_PF);
7350197007Sdelphij	}
7351197007Sdelphij	return (uint16_t) res;
7352197007Sdelphij}
7353197007Sdelphij
7354197007Sdelphij/*
7355197007Sdelphij * REMARKS:
7356197007Sdelphij * Implements the SHR instruction and side effects.
7357197007Sdelphij */
7358197007Sdelphijstatic uint32_t
7359197007Sdelphijshr_long(struct x86emu *emu, uint32_t d, uint8_t s)
7360197007Sdelphij{
7361197007Sdelphij	unsigned int cnt, res, cf;
7362197007Sdelphij
7363197007Sdelphij	if (s < 32) {
7364197007Sdelphij		cnt = s % 32;
7365197007Sdelphij		if (cnt > 0) {
7366197007Sdelphij			cf = d & (1 << (cnt - 1));
7367197007Sdelphij			res = d >> cnt;
7368197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7369197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7370197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7371197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7372197007Sdelphij		} else {
7373197007Sdelphij			res = d;
7374197007Sdelphij		}
7375197007Sdelphij		if (cnt == 1) {
7376197007Sdelphij			CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7377197007Sdelphij		} else {
7378197007Sdelphij			CLEAR_FLAG(F_OF);
7379197007Sdelphij		}
7380197007Sdelphij	} else {
7381197007Sdelphij		res = 0;
7382197007Sdelphij		CLEAR_FLAG(F_CF);
7383197007Sdelphij		CLEAR_FLAG(F_OF);
7384197007Sdelphij		SET_FLAG(F_ZF);
7385197007Sdelphij		CLEAR_FLAG(F_SF);
7386197007Sdelphij		CLEAR_FLAG(F_PF);
7387197007Sdelphij	}
7388197007Sdelphij	return res;
7389197007Sdelphij}
7390197007Sdelphij
7391197007Sdelphij/*
7392197007Sdelphij * REMARKS:
7393197007Sdelphij * Implements the SAR instruction and side effects.
7394197007Sdelphij */
7395197007Sdelphijstatic uint8_t
7396197007Sdelphijsar_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7397197007Sdelphij{
7398197007Sdelphij	unsigned int cnt, res, cf, mask, sf;
7399197007Sdelphij
7400197007Sdelphij	res = d;
7401197007Sdelphij	sf = d & 0x80;
7402197007Sdelphij	cnt = s % 8;
7403197007Sdelphij	if (cnt > 0 && cnt < 8) {
7404197007Sdelphij		mask = (1 << (8 - cnt)) - 1;
7405197007Sdelphij		cf = d & (1 << (cnt - 1));
7406197007Sdelphij		res = (d >> cnt) & mask;
7407197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
7408197007Sdelphij		if (sf) {
7409197007Sdelphij			res |= ~mask;
7410197007Sdelphij		}
7411197007Sdelphij		CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7412197007Sdelphij		CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7413197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7414197007Sdelphij	} else if (cnt >= 8) {
7415197007Sdelphij		if (sf) {
7416197007Sdelphij			res = 0xff;
7417197007Sdelphij			SET_FLAG(F_CF);
7418197007Sdelphij			CLEAR_FLAG(F_ZF);
7419197007Sdelphij			SET_FLAG(F_SF);
7420197007Sdelphij			SET_FLAG(F_PF);
7421197007Sdelphij		} else {
7422197007Sdelphij			res = 0;
7423197007Sdelphij			CLEAR_FLAG(F_CF);
7424197007Sdelphij			SET_FLAG(F_ZF);
7425197007Sdelphij			CLEAR_FLAG(F_SF);
7426197007Sdelphij			CLEAR_FLAG(F_PF);
7427197007Sdelphij		}
7428197007Sdelphij	}
7429197007Sdelphij	return (uint8_t) res;
7430197007Sdelphij}
7431197007Sdelphij
7432197007Sdelphij/*
7433197007Sdelphij * REMARKS:
7434197007Sdelphij * Implements the SAR instruction and side effects.
7435197007Sdelphij */
7436197007Sdelphijstatic uint16_t
7437197007Sdelphijsar_word(struct x86emu *emu, uint16_t d, uint8_t s)
7438197007Sdelphij{
7439197007Sdelphij	unsigned int cnt, res, cf, mask, sf;
7440197007Sdelphij
7441197007Sdelphij	sf = d & 0x8000;
7442197007Sdelphij	cnt = s % 16;
7443197007Sdelphij	res = d;
7444197007Sdelphij	if (cnt > 0 && cnt < 16) {
7445197007Sdelphij		mask = (1 << (16 - cnt)) - 1;
7446197007Sdelphij		cf = d & (1 << (cnt - 1));
7447197007Sdelphij		res = (d >> cnt) & mask;
7448197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
7449197007Sdelphij		if (sf) {
7450197007Sdelphij			res |= ~mask;
7451197007Sdelphij		}
7452197007Sdelphij		CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7453197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7454197007Sdelphij		CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7455197007Sdelphij	} else if (cnt >= 16) {
7456197007Sdelphij		if (sf) {
7457197007Sdelphij			res = 0xffff;
7458197007Sdelphij			SET_FLAG(F_CF);
7459197007Sdelphij			CLEAR_FLAG(F_ZF);
7460197007Sdelphij			SET_FLAG(F_SF);
7461197007Sdelphij			SET_FLAG(F_PF);
7462197007Sdelphij		} else {
7463197007Sdelphij			res = 0;
7464197007Sdelphij			CLEAR_FLAG(F_CF);
7465197007Sdelphij			SET_FLAG(F_ZF);
7466197007Sdelphij			CLEAR_FLAG(F_SF);
7467197007Sdelphij			CLEAR_FLAG(F_PF);
7468197007Sdelphij		}
7469197007Sdelphij	}
7470197007Sdelphij	return (uint16_t) res;
7471197007Sdelphij}
7472197007Sdelphij
7473197007Sdelphij/*
7474197007Sdelphij * REMARKS:
7475197007Sdelphij * Implements the SAR instruction and side effects.
7476197007Sdelphij */
7477197007Sdelphijstatic uint32_t
7478197007Sdelphijsar_long(struct x86emu *emu, uint32_t d, uint8_t s)
7479197007Sdelphij{
7480197007Sdelphij	uint32_t cnt, res, cf, mask, sf;
7481197007Sdelphij
7482197007Sdelphij	sf = d & 0x80000000;
7483197007Sdelphij	cnt = s % 32;
7484197007Sdelphij	res = d;
7485197007Sdelphij	if (cnt > 0 && cnt < 32) {
7486197007Sdelphij		mask = (1 << (32 - cnt)) - 1;
7487197007Sdelphij		cf = d & (1 << (cnt - 1));
7488197007Sdelphij		res = (d >> cnt) & mask;
7489197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
7490197007Sdelphij		if (sf) {
7491197007Sdelphij			res |= ~mask;
7492197007Sdelphij		}
7493197007Sdelphij		CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7494197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7495197007Sdelphij		CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7496197007Sdelphij	} else if (cnt >= 32) {
7497197007Sdelphij		if (sf) {
7498197007Sdelphij			res = 0xffffffff;
7499197007Sdelphij			SET_FLAG(F_CF);
7500197007Sdelphij			CLEAR_FLAG(F_ZF);
7501197007Sdelphij			SET_FLAG(F_SF);
7502197007Sdelphij			SET_FLAG(F_PF);
7503197007Sdelphij		} else {
7504197007Sdelphij			res = 0;
7505197007Sdelphij			CLEAR_FLAG(F_CF);
7506197007Sdelphij			SET_FLAG(F_ZF);
7507197007Sdelphij			CLEAR_FLAG(F_SF);
7508197007Sdelphij			CLEAR_FLAG(F_PF);
7509197007Sdelphij		}
7510197007Sdelphij	}
7511197007Sdelphij	return res;
7512197007Sdelphij}
7513197007Sdelphij
7514197007Sdelphij/*
7515197007Sdelphij * REMARKS:
7516197007Sdelphij * Implements the SHLD instruction and side effects.
7517197007Sdelphij */
7518197007Sdelphijstatic uint16_t
7519197007Sdelphijshld_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s)
7520197007Sdelphij{
7521197007Sdelphij	unsigned int cnt, res, cf;
7522197007Sdelphij
7523197007Sdelphij	if (s < 16) {
7524197007Sdelphij		cnt = s % 16;
7525197007Sdelphij		if (cnt > 0) {
7526197007Sdelphij			res = (d << cnt) | (fill >> (16 - cnt));
7527197007Sdelphij			cf = d & (1 << (16 - cnt));
7528197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7529197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7530197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7531197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7532197007Sdelphij		} else {
7533197007Sdelphij			res = d;
7534197007Sdelphij		}
7535197007Sdelphij		if (cnt == 1) {
7536197007Sdelphij			CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
7537197007Sdelphij				(ACCESS_FLAG(F_CF) != 0)), F_OF);
7538197007Sdelphij		} else {
7539197007Sdelphij			CLEAR_FLAG(F_OF);
7540197007Sdelphij		}
7541197007Sdelphij	} else {
7542197007Sdelphij		res = 0;
7543197007Sdelphij		CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
7544197007Sdelphij		CLEAR_FLAG(F_OF);
7545197007Sdelphij		CLEAR_FLAG(F_SF);
7546197007Sdelphij		SET_FLAG(F_PF);
7547197007Sdelphij		SET_FLAG(F_ZF);
7548197007Sdelphij	}
7549197007Sdelphij	return (uint16_t) res;
7550197007Sdelphij}
7551197007Sdelphij
7552197007Sdelphij/*
7553197007Sdelphij * REMARKS:
7554197007Sdelphij * Implements the SHLD instruction and side effects.
7555197007Sdelphij */
7556197007Sdelphijstatic uint32_t
7557197007Sdelphijshld_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s)
7558197007Sdelphij{
7559197007Sdelphij	unsigned int cnt, res, cf;
7560197007Sdelphij
7561197007Sdelphij	if (s < 32) {
7562197007Sdelphij		cnt = s % 32;
7563197007Sdelphij		if (cnt > 0) {
7564197007Sdelphij			res = (d << cnt) | (fill >> (32 - cnt));
7565197007Sdelphij			cf = d & (1 << (32 - cnt));
7566197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7567197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7568197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7569197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7570197007Sdelphij		} else {
7571197007Sdelphij			res = d;
7572197007Sdelphij		}
7573197007Sdelphij		if (cnt == 1) {
7574204934Sdelphij			CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000)
7575204934Sdelphij			    ^ (ACCESS_FLAG(F_CF) != 0)), F_OF);
7576197007Sdelphij		} else {
7577197007Sdelphij			CLEAR_FLAG(F_OF);
7578197007Sdelphij		}
7579197007Sdelphij	} else {
7580197007Sdelphij		res = 0;
7581197007Sdelphij		CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7582197007Sdelphij		CLEAR_FLAG(F_OF);
7583197007Sdelphij		CLEAR_FLAG(F_SF);
7584197007Sdelphij		SET_FLAG(F_PF);
7585197007Sdelphij		SET_FLAG(F_ZF);
7586197007Sdelphij	}
7587197007Sdelphij	return res;
7588197007Sdelphij}
7589197007Sdelphij
7590197007Sdelphij/*
7591197007Sdelphij * REMARKS:
7592197007Sdelphij * Implements the SHRD instruction and side effects.
7593197007Sdelphij */
7594197007Sdelphijstatic uint16_t
7595197007Sdelphijshrd_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s)
7596197007Sdelphij{
7597197007Sdelphij	unsigned int cnt, res, cf;
7598197007Sdelphij
7599197007Sdelphij	if (s < 16) {
7600197007Sdelphij		cnt = s % 16;
7601197007Sdelphij		if (cnt > 0) {
7602197007Sdelphij			cf = d & (1 << (cnt - 1));
7603197007Sdelphij			res = (d >> cnt) | (fill << (16 - cnt));
7604197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7605197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7606197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7607197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7608197007Sdelphij		} else {
7609197007Sdelphij			res = d;
7610197007Sdelphij		}
7611197007Sdelphij
7612197007Sdelphij		if (cnt == 1) {
7613197007Sdelphij			CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7614197007Sdelphij		} else {
7615197007Sdelphij			CLEAR_FLAG(F_OF);
7616197007Sdelphij		}
7617197007Sdelphij	} else {
7618197007Sdelphij		res = 0;
7619197007Sdelphij		CLEAR_FLAG(F_CF);
7620197007Sdelphij		CLEAR_FLAG(F_OF);
7621197007Sdelphij		SET_FLAG(F_ZF);
7622197007Sdelphij		CLEAR_FLAG(F_SF);
7623197007Sdelphij		CLEAR_FLAG(F_PF);
7624197007Sdelphij	}
7625197007Sdelphij	return (uint16_t) res;
7626197007Sdelphij}
7627197007Sdelphij
7628197007Sdelphij/*
7629197007Sdelphij * REMARKS:
7630197007Sdelphij * Implements the SHRD instruction and side effects.
7631197007Sdelphij */
7632197007Sdelphijstatic uint32_t
7633197007Sdelphijshrd_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s)
7634197007Sdelphij{
7635197007Sdelphij	unsigned int cnt, res, cf;
7636197007Sdelphij
7637197007Sdelphij	if (s < 32) {
7638197007Sdelphij		cnt = s % 32;
7639197007Sdelphij		if (cnt > 0) {
7640197007Sdelphij			cf = d & (1 << (cnt - 1));
7641197007Sdelphij			res = (d >> cnt) | (fill << (32 - cnt));
7642197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7643197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7644197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7645197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7646197007Sdelphij		} else {
7647197007Sdelphij			res = d;
7648197007Sdelphij		}
7649197007Sdelphij		if (cnt == 1) {
7650197007Sdelphij			CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7651197007Sdelphij		} else {
7652197007Sdelphij			CLEAR_FLAG(F_OF);
7653197007Sdelphij		}
7654197007Sdelphij	} else {
7655197007Sdelphij		res = 0;
7656197007Sdelphij		CLEAR_FLAG(F_CF);
7657197007Sdelphij		CLEAR_FLAG(F_OF);
7658197007Sdelphij		SET_FLAG(F_ZF);
7659197007Sdelphij		CLEAR_FLAG(F_SF);
7660197007Sdelphij		CLEAR_FLAG(F_PF);
7661197007Sdelphij	}
7662197007Sdelphij	return res;
7663197007Sdelphij}
7664197007Sdelphij
7665197007Sdelphij/*
7666197007Sdelphij * REMARKS:
7667197007Sdelphij * Implements the SBB instruction and side effects.
7668197007Sdelphij */
7669197007Sdelphijstatic uint8_t
7670197007Sdelphijsbb_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7671197007Sdelphij{
7672197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7673197007Sdelphij	uint32_t bc;
7674197007Sdelphij
7675197007Sdelphij	if (ACCESS_FLAG(F_CF))
7676197007Sdelphij		res = d - s - 1;
7677197007Sdelphij	else
7678197007Sdelphij		res = d - s;
7679197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7680197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7681197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7682197007Sdelphij
7683197007Sdelphij	/* calculate the borrow chain.  See note at top */
7684197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
7685197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7686197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7687197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7688197007Sdelphij	return (uint8_t) res;
7689197007Sdelphij}
7690197007Sdelphij
7691197007Sdelphij/*
7692197007Sdelphij * REMARKS:
7693197007Sdelphij * Implements the SBB instruction and side effects.
7694197007Sdelphij */
7695197007Sdelphijstatic uint16_t
7696197007Sdelphijsbb_word(struct x86emu *emu, uint16_t d, uint16_t s)
7697197007Sdelphij{
7698197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7699197007Sdelphij	uint32_t bc;
7700197007Sdelphij
7701197007Sdelphij	if (ACCESS_FLAG(F_CF))
7702197007Sdelphij		res = d - s - 1;
7703197007Sdelphij	else
7704197007Sdelphij		res = d - s;
7705197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7706197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7707197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7708197007Sdelphij
7709197007Sdelphij	/* calculate the borrow chain.  See note at top */
7710197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
7711197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7712197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7713197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7714197007Sdelphij	return (uint16_t) res;
7715197007Sdelphij}
7716197007Sdelphij
7717197007Sdelphij/*
7718197007Sdelphij * REMARKS:
7719197007Sdelphij * Implements the SBB instruction and side effects.
7720197007Sdelphij */
7721197007Sdelphijstatic uint32_t
7722197007Sdelphijsbb_long(struct x86emu *emu, uint32_t d, uint32_t s)
7723197007Sdelphij{
7724197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7725197007Sdelphij	uint32_t bc;
7726197007Sdelphij
7727197007Sdelphij	if (ACCESS_FLAG(F_CF))
7728197007Sdelphij		res = d - s - 1;
7729197007Sdelphij	else
7730197007Sdelphij		res = d - s;
7731197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7732197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7733197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7734197007Sdelphij
7735197007Sdelphij	/* calculate the borrow chain.  See note at top */
7736197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
7737197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7738197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7739197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7740197007Sdelphij	return res;
7741197007Sdelphij}
7742197007Sdelphij
7743197007Sdelphij/*
7744197007Sdelphij * REMARKS:
7745197007Sdelphij * Implements the SUB instruction and side effects.
7746197007Sdelphij */
7747197007Sdelphijstatic uint8_t
7748197007Sdelphijsub_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7749197007Sdelphij{
7750197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7751197007Sdelphij	uint32_t bc;
7752197007Sdelphij
7753197007Sdelphij	res = d - s;
7754197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7755197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7756197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7757197007Sdelphij
7758197007Sdelphij	/* calculate the borrow chain.  See note at top */
7759197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
7760197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7761197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7762197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7763197007Sdelphij	return (uint8_t) res;
7764197007Sdelphij}
7765197007Sdelphij
7766197007Sdelphij/*
7767197007Sdelphij * REMARKS:
7768197007Sdelphij * Implements the SUB instruction and side effects.
7769197007Sdelphij */
7770197007Sdelphijstatic uint16_t
7771197007Sdelphijsub_word(struct x86emu *emu, uint16_t d, uint16_t s)
7772197007Sdelphij{
7773197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7774197007Sdelphij	uint32_t bc;
7775197007Sdelphij
7776197007Sdelphij	res = d - s;
7777197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7778197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7779197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7780197007Sdelphij
7781197007Sdelphij	/* calculate the borrow chain.  See note at top */
7782197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
7783197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7784197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7785197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7786197007Sdelphij	return (uint16_t) res;
7787197007Sdelphij}
7788197007Sdelphij
7789197007Sdelphij/*
7790197007Sdelphij * REMARKS:
7791197007Sdelphij * Implements the SUB instruction and side effects.
7792197007Sdelphij */
7793197007Sdelphijstatic uint32_t
7794197007Sdelphijsub_long(struct x86emu *emu, uint32_t d, uint32_t s)
7795197007Sdelphij{
7796197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7797197007Sdelphij	uint32_t bc;
7798197007Sdelphij
7799197007Sdelphij	res = d - s;
7800197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7801197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7802197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7803197007Sdelphij
7804197007Sdelphij	/* calculate the borrow chain.  See note at top */
7805197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
7806197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7807197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7808197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7809197007Sdelphij	return res;
7810197007Sdelphij}
7811197007Sdelphij
7812197007Sdelphij/*
7813197007Sdelphij * REMARKS:
7814197007Sdelphij * Implements the TEST instruction and side effects.
7815197007Sdelphij */
7816197007Sdelphijstatic void
7817197007Sdelphijtest_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7818197007Sdelphij{
7819197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7820197007Sdelphij
7821197007Sdelphij	res = d & s;
7822197007Sdelphij
7823197007Sdelphij	CLEAR_FLAG(F_OF);
7824197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7825197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7826197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7827197007Sdelphij	/* AF == dont care */
7828197007Sdelphij	CLEAR_FLAG(F_CF);
7829197007Sdelphij}
7830197007Sdelphij
7831197007Sdelphij/*
7832197007Sdelphij * REMARKS:
7833197007Sdelphij * Implements the TEST instruction and side effects.
7834197007Sdelphij */
7835197007Sdelphijstatic void
7836197007Sdelphijtest_word(struct x86emu *emu, uint16_t d, uint16_t s)
7837197007Sdelphij{
7838197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7839197007Sdelphij
7840197007Sdelphij	res = d & s;
7841197007Sdelphij
7842197007Sdelphij	CLEAR_FLAG(F_OF);
7843197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7844197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7845197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7846197007Sdelphij	/* AF == dont care */
7847197007Sdelphij	CLEAR_FLAG(F_CF);
7848197007Sdelphij}
7849197007Sdelphij
7850197007Sdelphij/*
7851197007Sdelphij * REMARKS:
7852197007Sdelphij * Implements the TEST instruction and side effects.
7853197007Sdelphij */
7854197007Sdelphijstatic void
7855197007Sdelphijtest_long(struct x86emu *emu, uint32_t d, uint32_t s)
7856197007Sdelphij{
7857197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7858197007Sdelphij
7859197007Sdelphij	res = d & s;
7860197007Sdelphij
7861197007Sdelphij	CLEAR_FLAG(F_OF);
7862197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7863197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7864197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7865197007Sdelphij	/* AF == dont care */
7866197007Sdelphij	CLEAR_FLAG(F_CF);
7867197007Sdelphij}
7868197007Sdelphij
7869197007Sdelphij/*
7870197007Sdelphij * REMARKS:
7871197007Sdelphij * Implements the XOR instruction and side effects.
7872197007Sdelphij */
7873197007Sdelphijstatic uint8_t
7874197007Sdelphijxor_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7875197007Sdelphij{
7876197007Sdelphij	uint8_t res;	/* all operands in native machine order */
7877197007Sdelphij
7878197007Sdelphij	res = d ^ s;
7879197007Sdelphij	CLEAR_FLAG(F_OF);
7880197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7881197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7882197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
7883197007Sdelphij	CLEAR_FLAG(F_CF);
7884197007Sdelphij	CLEAR_FLAG(F_AF);
7885197007Sdelphij	return res;
7886197007Sdelphij}
7887197007Sdelphij
7888197007Sdelphij/*
7889197007Sdelphij * REMARKS:
7890197007Sdelphij * Implements the XOR instruction and side effects.
7891197007Sdelphij */
7892197007Sdelphijstatic uint16_t
7893197007Sdelphijxor_word(struct x86emu *emu, uint16_t d, uint16_t s)
7894197007Sdelphij{
7895197007Sdelphij	uint16_t res;	/* all operands in native machine order */
7896197007Sdelphij
7897197007Sdelphij	res = d ^ s;
7898197007Sdelphij	CLEAR_FLAG(F_OF);
7899197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7900197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7901197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7902197007Sdelphij	CLEAR_FLAG(F_CF);
7903197007Sdelphij	CLEAR_FLAG(F_AF);
7904197007Sdelphij	return res;
7905197007Sdelphij}
7906197007Sdelphij
7907197007Sdelphij/*
7908197007Sdelphij * REMARKS:
7909197007Sdelphij * Implements the XOR instruction and side effects.
7910197007Sdelphij */
7911197007Sdelphijstatic uint32_t
7912197007Sdelphijxor_long(struct x86emu *emu, uint32_t d, uint32_t s)
7913197007Sdelphij{
7914197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7915197007Sdelphij
7916197007Sdelphij	res = d ^ s;
7917197007Sdelphij	CLEAR_FLAG(F_OF);
7918197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7919197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7920197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7921197007Sdelphij	CLEAR_FLAG(F_CF);
7922197007Sdelphij	CLEAR_FLAG(F_AF);
7923197007Sdelphij	return res;
7924197007Sdelphij}
7925197007Sdelphij
7926197007Sdelphij/*
7927197007Sdelphij * REMARKS:
7928197007Sdelphij * Implements the IMUL instruction and side effects.
7929197007Sdelphij */
7930197007Sdelphijstatic void
7931197007Sdelphijimul_byte(struct x86emu *emu, uint8_t s)
7932197007Sdelphij{
7933197007Sdelphij	int16_t res = (int16_t) ((int8_t) emu->x86.R_AL * (int8_t) s);
7934197007Sdelphij
7935197007Sdelphij	emu->x86.R_AX = res;
7936197007Sdelphij	if (((emu->x86.R_AL & 0x80) == 0 && emu->x86.R_AH == 0x00) ||
7937197007Sdelphij	    ((emu->x86.R_AL & 0x80) != 0 && emu->x86.R_AH == 0xFF)) {
7938197007Sdelphij		CLEAR_FLAG(F_CF);
7939197007Sdelphij		CLEAR_FLAG(F_OF);
7940197007Sdelphij	} else {
7941197007Sdelphij		SET_FLAG(F_CF);
7942197007Sdelphij		SET_FLAG(F_OF);
7943197007Sdelphij	}
7944197007Sdelphij}
7945197007Sdelphij
7946197007Sdelphij/*
7947197007Sdelphij * REMARKS:
7948197007Sdelphij * Implements the IMUL instruction and side effects.
7949197007Sdelphij */
7950197007Sdelphijstatic void
7951197007Sdelphijimul_word(struct x86emu *emu, uint16_t s)
7952197007Sdelphij{
7953197007Sdelphij	int32_t res = (int16_t) emu->x86.R_AX * (int16_t) s;
7954197007Sdelphij
7955197007Sdelphij	emu->x86.R_AX = (uint16_t) res;
7956197007Sdelphij	emu->x86.R_DX = (uint16_t) (res >> 16);
7957197007Sdelphij	if (((emu->x86.R_AX & 0x8000) == 0 && emu->x86.R_DX == 0x00) ||
7958197007Sdelphij	    ((emu->x86.R_AX & 0x8000) != 0 && emu->x86.R_DX == 0xFF)) {
7959197007Sdelphij		CLEAR_FLAG(F_CF);
7960197007Sdelphij		CLEAR_FLAG(F_OF);
7961197007Sdelphij	} else {
7962197007Sdelphij		SET_FLAG(F_CF);
7963197007Sdelphij		SET_FLAG(F_OF);
7964197007Sdelphij	}
7965197007Sdelphij}
7966197007Sdelphij
7967197007Sdelphij/*
7968197007Sdelphij * REMARKS:
7969197007Sdelphij * Implements the IMUL instruction and side effects.
7970197007Sdelphij */
7971197007Sdelphijstatic void
7972197007Sdelphijimul_long(struct x86emu *emu, uint32_t s)
7973197007Sdelphij{
7974197007Sdelphij	int64_t res;
7975197007Sdelphij
7976197007Sdelphij	res = (int64_t)(int32_t)emu->x86.R_EAX * (int32_t)s;
7977197007Sdelphij	emu->x86.R_EAX = (uint32_t)res;
7978197007Sdelphij	emu->x86.R_EDX = ((uint64_t)res) >> 32;
7979197007Sdelphij	if (((emu->x86.R_EAX & 0x80000000) == 0 && emu->x86.R_EDX == 0x00) ||
7980197007Sdelphij	    ((emu->x86.R_EAX & 0x80000000) != 0 && emu->x86.R_EDX == 0xFF)) {
7981197007Sdelphij		CLEAR_FLAG(F_CF);
7982197007Sdelphij		CLEAR_FLAG(F_OF);
7983197007Sdelphij	} else {
7984197007Sdelphij		SET_FLAG(F_CF);
7985197007Sdelphij		SET_FLAG(F_OF);
7986197007Sdelphij	}
7987197007Sdelphij}
7988197007Sdelphij
7989197007Sdelphij/*
7990197007Sdelphij * REMARKS:
7991197007Sdelphij * Implements the MUL instruction and side effects.
7992197007Sdelphij */
7993197007Sdelphijstatic void
7994197007Sdelphijmul_byte(struct x86emu *emu, uint8_t s)
7995197007Sdelphij{
7996197007Sdelphij	uint16_t res = (uint16_t) (emu->x86.R_AL * s);
7997197007Sdelphij
7998197007Sdelphij	emu->x86.R_AX = res;
7999197007Sdelphij	if (emu->x86.R_AH == 0) {
8000197007Sdelphij		CLEAR_FLAG(F_CF);
8001197007Sdelphij		CLEAR_FLAG(F_OF);
8002197007Sdelphij	} else {
8003197007Sdelphij		SET_FLAG(F_CF);
8004197007Sdelphij		SET_FLAG(F_OF);
8005197007Sdelphij	}
8006197007Sdelphij}
8007197007Sdelphij
8008197007Sdelphij/*
8009197007Sdelphij * REMARKS:
8010197007Sdelphij * Implements the MUL instruction and side effects.
8011197007Sdelphij */
8012197007Sdelphijstatic void
8013197007Sdelphijmul_word(struct x86emu *emu, uint16_t s)
8014197007Sdelphij{
8015197007Sdelphij	uint32_t res = emu->x86.R_AX * s;
8016197007Sdelphij
8017197007Sdelphij	emu->x86.R_AX = (uint16_t) res;
8018197007Sdelphij	emu->x86.R_DX = (uint16_t) (res >> 16);
8019197007Sdelphij	if (emu->x86.R_DX == 0) {
8020197007Sdelphij		CLEAR_FLAG(F_CF);
8021197007Sdelphij		CLEAR_FLAG(F_OF);
8022197007Sdelphij	} else {
8023197007Sdelphij		SET_FLAG(F_CF);
8024197007Sdelphij		SET_FLAG(F_OF);
8025197007Sdelphij	}
8026197007Sdelphij}
8027197007Sdelphij
8028197007Sdelphij/*
8029197007Sdelphij * REMARKS:
8030197007Sdelphij * Implements the MUL instruction and side effects.
8031197007Sdelphij */
8032197007Sdelphijstatic void
8033197007Sdelphijmul_long(struct x86emu *emu, uint32_t s)
8034197007Sdelphij{
8035197007Sdelphij	uint64_t res = (uint64_t) emu->x86.R_EAX * s;
8036197007Sdelphij
8037197007Sdelphij	emu->x86.R_EAX = (uint32_t) res;
8038197007Sdelphij	emu->x86.R_EDX = (uint32_t) (res >> 32);
8039197007Sdelphij
8040197007Sdelphij	if (emu->x86.R_EDX == 0) {
8041197007Sdelphij		CLEAR_FLAG(F_CF);
8042197007Sdelphij		CLEAR_FLAG(F_OF);
8043197007Sdelphij	} else {
8044197007Sdelphij		SET_FLAG(F_CF);
8045197007Sdelphij		SET_FLAG(F_OF);
8046197007Sdelphij	}
8047197007Sdelphij}
8048197007Sdelphij
8049197007Sdelphij/*
8050197007Sdelphij * REMARKS:
8051197007Sdelphij * Implements the IDIV instruction and side effects.
8052197007Sdelphij */
8053197007Sdelphijstatic void
8054197007Sdelphijidiv_byte(struct x86emu *emu, uint8_t s)
8055197007Sdelphij{
8056197007Sdelphij	int32_t dvd, div, mod;
8057197007Sdelphij
8058197007Sdelphij	dvd = (int16_t) emu->x86.R_AX;
8059197007Sdelphij	if (s == 0) {
8060197007Sdelphij		x86emu_intr_raise(emu, 8);
8061197007Sdelphij		return;
8062197007Sdelphij	}
8063197007Sdelphij	div = dvd / (int8_t) s;
8064197007Sdelphij	mod = dvd % (int8_t) s;
8065197007Sdelphij	if (div > 0x7f || div < -0x7f) {
8066197007Sdelphij		x86emu_intr_raise(emu, 8);
8067197007Sdelphij		return;
8068197007Sdelphij	}
8069197007Sdelphij	emu->x86.R_AL = (int8_t) div;
8070197007Sdelphij	emu->x86.R_AH = (int8_t) mod;
8071197007Sdelphij}
8072197007Sdelphij
8073197007Sdelphij/*
8074197007Sdelphij * REMARKS:
8075197007Sdelphij * Implements the IDIV instruction and side effects.
8076197007Sdelphij */
8077197007Sdelphijstatic void
8078197007Sdelphijidiv_word(struct x86emu *emu, uint16_t s)
8079197007Sdelphij{
8080197007Sdelphij	int32_t dvd, div, mod;
8081197007Sdelphij
8082197007Sdelphij	dvd = (((int32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
8083197007Sdelphij	if (s == 0) {
8084197007Sdelphij		x86emu_intr_raise(emu, 8);
8085197007Sdelphij		return;
8086197007Sdelphij	}
8087197007Sdelphij	div = dvd / (int16_t) s;
8088197007Sdelphij	mod = dvd % (int16_t) s;
8089197007Sdelphij	if (div > 0x7fff || div < -0x7fff) {
8090197007Sdelphij		x86emu_intr_raise(emu, 8);
8091197007Sdelphij		return;
8092197007Sdelphij	}
8093197007Sdelphij	CLEAR_FLAG(F_CF);
8094197007Sdelphij	CLEAR_FLAG(F_SF);
8095197007Sdelphij	CONDITIONAL_SET_FLAG(div == 0, F_ZF);
8096197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8097197007Sdelphij
8098197007Sdelphij	emu->x86.R_AX = (uint16_t) div;
8099197007Sdelphij	emu->x86.R_DX = (uint16_t) mod;
8100197007Sdelphij}
8101197007Sdelphij
8102197007Sdelphij/*
8103197007Sdelphij * REMARKS:
8104197007Sdelphij * Implements the IDIV instruction and side effects.
8105197007Sdelphij */
8106197007Sdelphijstatic void
8107197007Sdelphijidiv_long(struct x86emu *emu, uint32_t s)
8108197007Sdelphij{
8109197007Sdelphij	int64_t dvd, div, mod;
8110197007Sdelphij
8111197007Sdelphij	dvd = (((int64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
8112197007Sdelphij	if (s == 0) {
8113197007Sdelphij		x86emu_intr_raise(emu, 8);
8114197007Sdelphij		return;
8115197007Sdelphij	}
8116197007Sdelphij	div = dvd / (int32_t) s;
8117197007Sdelphij	mod = dvd % (int32_t) s;
8118197007Sdelphij	if (div > 0x7fffffff || div < -0x7fffffff) {
8119197007Sdelphij		x86emu_intr_raise(emu, 8);
8120197007Sdelphij		return;
8121197007Sdelphij	}
8122197007Sdelphij	CLEAR_FLAG(F_CF);
8123197007Sdelphij	CLEAR_FLAG(F_AF);
8124197007Sdelphij	CLEAR_FLAG(F_SF);
8125197007Sdelphij	SET_FLAG(F_ZF);
8126197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8127197007Sdelphij
8128197007Sdelphij	emu->x86.R_EAX = (uint32_t) div;
8129197007Sdelphij	emu->x86.R_EDX = (uint32_t) mod;
8130197007Sdelphij}
8131197007Sdelphij
8132197007Sdelphij/*
8133197007Sdelphij * REMARKS:
8134197007Sdelphij * Implements the DIV instruction and side effects.
8135197007Sdelphij */
8136197007Sdelphijstatic void
8137197007Sdelphijdiv_byte(struct x86emu *emu, uint8_t s)
8138197007Sdelphij{
8139197007Sdelphij	uint32_t dvd, div, mod;
8140197007Sdelphij
8141197007Sdelphij	dvd = emu->x86.R_AX;
8142197007Sdelphij	if (s == 0) {
8143197007Sdelphij		x86emu_intr_raise(emu, 8);
8144197007Sdelphij		return;
8145197007Sdelphij	}
8146197007Sdelphij	div = dvd / (uint8_t) s;
8147197007Sdelphij	mod = dvd % (uint8_t) s;
8148197007Sdelphij	if (div > 0xff) {
8149197007Sdelphij		x86emu_intr_raise(emu, 8);
8150197007Sdelphij		return;
8151197007Sdelphij	}
8152197007Sdelphij	emu->x86.R_AL = (uint8_t) div;
8153197007Sdelphij	emu->x86.R_AH = (uint8_t) mod;
8154197007Sdelphij}
8155197007Sdelphij
8156197007Sdelphij/*
8157197007Sdelphij * REMARKS:
8158197007Sdelphij * Implements the DIV instruction and side effects.
8159197007Sdelphij */
8160197007Sdelphijstatic void
8161197007Sdelphijdiv_word(struct x86emu *emu, uint16_t s)
8162197007Sdelphij{
8163197007Sdelphij	uint32_t dvd, div, mod;
8164197007Sdelphij
8165197007Sdelphij	dvd = (((uint32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
8166197007Sdelphij	if (s == 0) {
8167197007Sdelphij		x86emu_intr_raise(emu, 8);
8168197007Sdelphij		return;
8169197007Sdelphij	}
8170197007Sdelphij	div = dvd / (uint16_t) s;
8171197007Sdelphij	mod = dvd % (uint16_t) s;
8172197007Sdelphij	if (div > 0xffff) {
8173197007Sdelphij		x86emu_intr_raise(emu, 8);
8174197007Sdelphij		return;
8175197007Sdelphij	}
8176197007Sdelphij	CLEAR_FLAG(F_CF);
8177197007Sdelphij	CLEAR_FLAG(F_SF);
8178197007Sdelphij	CONDITIONAL_SET_FLAG(div == 0, F_ZF);
8179197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8180197007Sdelphij
8181197007Sdelphij	emu->x86.R_AX = (uint16_t) div;
8182197007Sdelphij	emu->x86.R_DX = (uint16_t) mod;
8183197007Sdelphij}
8184197007Sdelphij
8185197007Sdelphij/*
8186197007Sdelphij * REMARKS:
8187197007Sdelphij * Implements the DIV instruction and side effects.
8188197007Sdelphij */
8189197007Sdelphijstatic void
8190197007Sdelphijdiv_long(struct x86emu *emu, uint32_t s)
8191197007Sdelphij{
8192197007Sdelphij	uint64_t dvd, div, mod;
8193197007Sdelphij
8194197007Sdelphij	dvd = (((uint64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
8195197007Sdelphij	if (s == 0) {
8196197007Sdelphij		x86emu_intr_raise(emu, 8);
8197197007Sdelphij		return;
8198197007Sdelphij	}
8199197007Sdelphij	div = dvd / (uint32_t) s;
8200197007Sdelphij	mod = dvd % (uint32_t) s;
8201197007Sdelphij	if (div > 0xffffffff) {
8202197007Sdelphij		x86emu_intr_raise(emu, 8);
8203197007Sdelphij		return;
8204197007Sdelphij	}
8205197007Sdelphij	CLEAR_FLAG(F_CF);
8206197007Sdelphij	CLEAR_FLAG(F_AF);
8207197007Sdelphij	CLEAR_FLAG(F_SF);
8208197007Sdelphij	SET_FLAG(F_ZF);
8209197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8210197007Sdelphij
8211197007Sdelphij	emu->x86.R_EAX = (uint32_t) div;
8212197007Sdelphij	emu->x86.R_EDX = (uint32_t) mod;
8213197007Sdelphij}
8214197007Sdelphij
8215197007Sdelphij/*
8216197007Sdelphij * REMARKS:
8217197007Sdelphij * Implements the IN string instruction and side effects.
8218197007Sdelphij */
8219197007Sdelphijstatic void
8220197007Sdelphijins(struct x86emu *emu, int size)
8221197007Sdelphij{
8222197007Sdelphij	int inc = size;
8223197007Sdelphij
8224197007Sdelphij	if (ACCESS_FLAG(F_DF)) {
8225197007Sdelphij		inc = -size;
8226197007Sdelphij	}
8227197007Sdelphij	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
8228197007Sdelphij		/* dont care whether REPE or REPNE */
8229197007Sdelphij		/* in until CX is ZERO. */
8230197007Sdelphij		uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
8231197007Sdelphij		    emu->x86.R_ECX : emu->x86.R_CX);
8232197007Sdelphij		switch (size) {
8233197007Sdelphij		case 1:
8234197007Sdelphij			while (count--) {
8235197007Sdelphij				store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
8236197007Sdelphij				    (*emu->emu_inb) (emu, emu->x86.R_DX));
8237197007Sdelphij				emu->x86.R_DI += inc;
8238197007Sdelphij			}
8239197007Sdelphij			break;
8240197007Sdelphij
8241197007Sdelphij		case 2:
8242197007Sdelphij			while (count--) {
8243197007Sdelphij				store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
8244197007Sdelphij				    (*emu->emu_inw) (emu, emu->x86.R_DX));
8245197007Sdelphij				emu->x86.R_DI += inc;
8246197007Sdelphij			}
8247197007Sdelphij			break;
8248197007Sdelphij		case 4:
8249197007Sdelphij			while (count--) {
8250197007Sdelphij				store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
8251197007Sdelphij				    (*emu->emu_inl) (emu, emu->x86.R_DX));
8252197007Sdelphij				emu->x86.R_DI += inc;
8253197007Sdelphij				break;
8254197007Sdelphij			}
8255197007Sdelphij		}
8256197007Sdelphij		emu->x86.R_CX = 0;
8257197007Sdelphij		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
8258197007Sdelphij			emu->x86.R_ECX = 0;
8259197007Sdelphij		}
8260197007Sdelphij		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
8261197007Sdelphij	} else {
8262197007Sdelphij		switch (size) {
8263197007Sdelphij		case 1:
8264197007Sdelphij			store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
8265197007Sdelphij			    (*emu->emu_inb) (emu, emu->x86.R_DX));
8266197007Sdelphij			break;
8267197007Sdelphij		case 2:
8268197007Sdelphij			store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
8269197007Sdelphij			    (*emu->emu_inw) (emu, emu->x86.R_DX));
8270197007Sdelphij			break;
8271197007Sdelphij		case 4:
8272197007Sdelphij			store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
8273197007Sdelphij			    (*emu->emu_inl) (emu, emu->x86.R_DX));
8274197007Sdelphij			break;
8275197007Sdelphij		}
8276197007Sdelphij		emu->x86.R_DI += inc;
8277197007Sdelphij	}
8278197007Sdelphij}
8279197007Sdelphij
8280197007Sdelphij/*
8281197007Sdelphij * REMARKS:
8282197007Sdelphij * Implements the OUT string instruction and side effects.
8283197007Sdelphij */
8284197007Sdelphijstatic void
8285197007Sdelphijouts(struct x86emu *emu, int size)
8286197007Sdelphij{
8287197007Sdelphij	int inc = size;
8288197007Sdelphij
8289197007Sdelphij	if (ACCESS_FLAG(F_DF)) {
8290197007Sdelphij		inc = -size;
8291197007Sdelphij	}
8292197007Sdelphij	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
8293197007Sdelphij		/* dont care whether REPE or REPNE */
8294197007Sdelphij		/* out until CX is ZERO. */
8295197007Sdelphij		uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
8296197007Sdelphij		    emu->x86.R_ECX : emu->x86.R_CX);
8297197007Sdelphij		switch (size) {
8298197007Sdelphij		case 1:
8299197007Sdelphij			while (count--) {
8300197007Sdelphij				(*emu->emu_outb) (emu, emu->x86.R_DX,
8301204934Sdelphij				    fetch_byte(emu, emu->x86.R_ES,
8302204934Sdelphij				    emu->x86.R_SI));
8303197007Sdelphij				emu->x86.R_SI += inc;
8304197007Sdelphij			}
8305197007Sdelphij			break;
8306197007Sdelphij
8307197007Sdelphij		case 2:
8308197007Sdelphij			while (count--) {
8309197007Sdelphij				(*emu->emu_outw) (emu, emu->x86.R_DX,
8310204934Sdelphij				    fetch_word(emu, emu->x86.R_ES,
8311204934Sdelphij				    emu->x86.R_SI));
8312197007Sdelphij				emu->x86.R_SI += inc;
8313197007Sdelphij			}
8314197007Sdelphij			break;
8315197007Sdelphij		case 4:
8316197007Sdelphij			while (count--) {
8317197007Sdelphij				(*emu->emu_outl) (emu, emu->x86.R_DX,
8318204934Sdelphij				    fetch_long(emu, emu->x86.R_ES,
8319204934Sdelphij				    emu->x86.R_SI));
8320197007Sdelphij				emu->x86.R_SI += inc;
8321197007Sdelphij				break;
8322197007Sdelphij			}
8323197007Sdelphij		}
8324197007Sdelphij		emu->x86.R_CX = 0;
8325197007Sdelphij		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
8326197007Sdelphij			emu->x86.R_ECX = 0;
8327197007Sdelphij		}
8328197007Sdelphij		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
8329197007Sdelphij	} else {
8330197007Sdelphij		switch (size) {
8331197007Sdelphij		case 1:
8332197007Sdelphij			(*emu->emu_outb) (emu, emu->x86.R_DX,
8333197007Sdelphij			    fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI));
8334197007Sdelphij			break;
8335197007Sdelphij		case 2:
8336197007Sdelphij			(*emu->emu_outw) (emu, emu->x86.R_DX,
8337197007Sdelphij			    fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI));
8338197007Sdelphij			break;
8339197007Sdelphij		case 4:
8340197007Sdelphij			(*emu->emu_outl) (emu, emu->x86.R_DX,
8341197007Sdelphij			    fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI));
8342197007Sdelphij			break;
8343197007Sdelphij		}
8344197007Sdelphij		emu->x86.R_SI += inc;
8345197007Sdelphij	}
8346197007Sdelphij}
8347197007Sdelphij
8348197007Sdelphij/*
8349197007Sdelphij * REMARKS:
8350197007Sdelphij * Pushes a word onto the stack.
8351197007Sdelphij *
8352197007Sdelphij * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8353197007Sdelphij */
8354197007Sdelphijstatic void
8355197007Sdelphijpush_word(struct x86emu *emu, uint16_t w)
8356197007Sdelphij{
8357197007Sdelphij	emu->x86.R_SP -= 2;
8358197007Sdelphij	store_word(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8359197007Sdelphij}
8360197007Sdelphij
8361197007Sdelphij/*
8362197007Sdelphij * REMARKS:
8363197007Sdelphij * Pushes a long onto the stack.
8364197007Sdelphij *
8365197007Sdelphij * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8366197007Sdelphij */
8367197007Sdelphijstatic void
8368197007Sdelphijpush_long(struct x86emu *emu, uint32_t w)
8369197007Sdelphij{
8370197007Sdelphij	emu->x86.R_SP -= 4;
8371197007Sdelphij	store_long(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8372197007Sdelphij}
8373197007Sdelphij
8374197007Sdelphij/*
8375197007Sdelphij * REMARKS:
8376197007Sdelphij * Pops a word from the stack.
8377197007Sdelphij *
8378197007Sdelphij * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8379197007Sdelphij */
8380197007Sdelphijstatic uint16_t
8381197007Sdelphijpop_word(struct x86emu *emu)
8382197007Sdelphij{
8383197007Sdelphij	uint16_t res;
8384197007Sdelphij
8385197007Sdelphij	res = fetch_word(emu, emu->x86.R_SS, emu->x86.R_SP);
8386197007Sdelphij	emu->x86.R_SP += 2;
8387197007Sdelphij	return res;
8388197007Sdelphij}
8389197007Sdelphij
8390197007Sdelphij/*
8391197007Sdelphij * REMARKS:
8392197007Sdelphij * Pops a long from the stack.
8393197007Sdelphij *
8394197007Sdelphij * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8395197007Sdelphij */
8396197007Sdelphijstatic uint32_t
8397197007Sdelphijpop_long(struct x86emu *emu)
8398197007Sdelphij{
8399197007Sdelphij	uint32_t res;
8400197007Sdelphij
8401197007Sdelphij	res = fetch_long(emu, emu->x86.R_SS, emu->x86.R_SP);
8402197007Sdelphij	emu->x86.R_SP += 4;
8403197007Sdelphij	return res;
8404197007Sdelphij}
8405