x86emu.c revision 267372
1204934Sdelphij/*	$OpenBSD: x86emu.c,v 1.5 2010/02/17 15:09:47 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: head/sys/contrib/x86emu/x86emu.c 267372 2014-06-11 20:22:14Z delphij $");
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	uint16_t *srcreg;
2155197007Sdelphij	uint32_t destoffset;
2156197007Sdelphij
2157197007Sdelphij/*
2158197007Sdelphij * TODO: Need to handle address size prefix!
2159197007Sdelphij *
2160197007Sdelphij * lea  eax,[eax+ebx*2] ??
2161197007Sdelphij */
2162197007Sdelphij	fetch_decode_modrm(emu);
2163197007Sdelphij	if (emu->cur_mod == 3)
2164197007Sdelphij		x86emu_halt_sys(emu);
2165197007Sdelphij
2166197007Sdelphij	srcreg = decode_rh_word_register(emu);
2167197007Sdelphij	destoffset = decode_rl_address(emu);
2168197007Sdelphij	*srcreg = (uint16_t) destoffset;
2169197007Sdelphij}
2170197007Sdelphij
2171197007Sdelphij/*
2172197007Sdelphij * REMARKS:
2173197007Sdelphij * Handles opcode 0x8e
2174197007Sdelphij */
2175197007Sdelphijstatic void
2176197007Sdelphijx86emuOp_mov_word_SR_RM(struct x86emu *emu)
2177197007Sdelphij{
2178197007Sdelphij	uint16_t *destreg;
2179197007Sdelphij
2180197007Sdelphij	fetch_decode_modrm(emu);
2181197007Sdelphij	destreg = decode_rh_seg_register(emu);
2182197007Sdelphij	*destreg = decode_and_fetch_word(emu);
2183197007Sdelphij	/*
2184197007Sdelphij         * Clean up, and reset all the R_xSP pointers to the correct
2185197007Sdelphij         * locations.  This is about 3x too much overhead (doing all the
2186197007Sdelphij         * segreg ptrs when only one is needed, but this instruction
2187197007Sdelphij         * *cannot* be that common, and this isn't too much work anyway.
2188197007Sdelphij         */
2189197007Sdelphij}
2190197007Sdelphij
2191197007Sdelphij/*
2192197007Sdelphij * REMARKS:
2193197007Sdelphij * Handles opcode 0x8f
2194197007Sdelphij */
2195197007Sdelphijstatic void
2196197007Sdelphijx86emuOp32_pop_RM(struct x86emu *emu)
2197197007Sdelphij{
2198197007Sdelphij	uint32_t destoffset;
2199197007Sdelphij	uint32_t destval, *destreg;
2200197007Sdelphij
2201197007Sdelphij	fetch_decode_modrm(emu);
2202197007Sdelphij	if (emu->cur_mod != 3) {
2203197007Sdelphij		destoffset = decode_rl_address(emu);
2204197007Sdelphij		destval = pop_long(emu);
2205197007Sdelphij		store_data_long(emu, destoffset, destval);
2206197007Sdelphij	} else {
2207197007Sdelphij		destreg = decode_rl_long_register(emu);
2208197007Sdelphij		*destreg = pop_long(emu);
2209197007Sdelphij	}
2210197007Sdelphij}
2211197007Sdelphij
2212197007Sdelphijstatic void
2213197007Sdelphijx86emuOp16_pop_RM(struct x86emu *emu)
2214197007Sdelphij{
2215197007Sdelphij	uint32_t destoffset;
2216197007Sdelphij	uint16_t destval, *destreg;
2217197007Sdelphij
2218197007Sdelphij	fetch_decode_modrm(emu);
2219197007Sdelphij	if (emu->cur_mod != 3) {
2220197007Sdelphij		destoffset = decode_rl_address(emu);
2221197007Sdelphij		destval = pop_word(emu);
2222197007Sdelphij		store_data_word(emu, destoffset, destval);
2223197007Sdelphij	} else {
2224197007Sdelphij		destreg = decode_rl_word_register(emu);
2225197007Sdelphij		*destreg = pop_word(emu);
2226197007Sdelphij	}
2227197007Sdelphij}
2228197007Sdelphij
2229197007Sdelphijstatic void
2230197007Sdelphijx86emuOp_pop_RM(struct x86emu *emu)
2231197007Sdelphij{
2232197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2233197007Sdelphij		x86emuOp32_pop_RM(emu);
2234197007Sdelphij	else
2235197007Sdelphij		x86emuOp16_pop_RM(emu);
2236197007Sdelphij}
2237197007Sdelphij
2238197007Sdelphij/*
2239197007Sdelphij * REMARKS:
2240197007Sdelphij * Handles opcode 0x91
2241197007Sdelphij */
2242197007Sdelphijstatic void
2243197007Sdelphijx86emuOp_xchg_word_AX_CX(struct x86emu *emu)
2244197007Sdelphij{
2245197007Sdelphij	uint32_t tmp;
2246197007Sdelphij
2247197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2248197007Sdelphij		tmp = emu->x86.R_EAX;
2249197007Sdelphij		emu->x86.R_EAX = emu->x86.R_ECX;
2250197007Sdelphij		emu->x86.R_ECX = tmp;
2251197007Sdelphij	} else {
2252197007Sdelphij		tmp = emu->x86.R_AX;
2253197007Sdelphij		emu->x86.R_AX = emu->x86.R_CX;
2254197007Sdelphij		emu->x86.R_CX = (uint16_t) tmp;
2255197007Sdelphij	}
2256197007Sdelphij}
2257197007Sdelphij
2258197007Sdelphij/*
2259197007Sdelphij * REMARKS:
2260197007Sdelphij * Handles opcode 0x92
2261197007Sdelphij */
2262197007Sdelphijstatic void
2263197007Sdelphijx86emuOp_xchg_word_AX_DX(struct x86emu *emu)
2264197007Sdelphij{
2265197007Sdelphij	uint32_t tmp;
2266197007Sdelphij
2267197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2268197007Sdelphij		tmp = emu->x86.R_EAX;
2269197007Sdelphij		emu->x86.R_EAX = emu->x86.R_EDX;
2270197007Sdelphij		emu->x86.R_EDX = tmp;
2271197007Sdelphij	} else {
2272197007Sdelphij		tmp = emu->x86.R_AX;
2273197007Sdelphij		emu->x86.R_AX = emu->x86.R_DX;
2274197007Sdelphij		emu->x86.R_DX = (uint16_t) tmp;
2275197007Sdelphij	}
2276197007Sdelphij}
2277197007Sdelphij
2278197007Sdelphij/*
2279197007Sdelphij * REMARKS:
2280197007Sdelphij * Handles opcode 0x93
2281197007Sdelphij */
2282197007Sdelphijstatic void
2283197007Sdelphijx86emuOp_xchg_word_AX_BX(struct x86emu *emu)
2284197007Sdelphij{
2285197007Sdelphij	uint32_t tmp;
2286197007Sdelphij
2287197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2288197007Sdelphij		tmp = emu->x86.R_EAX;
2289197007Sdelphij		emu->x86.R_EAX = emu->x86.R_EBX;
2290197007Sdelphij		emu->x86.R_EBX = tmp;
2291197007Sdelphij	} else {
2292197007Sdelphij		tmp = emu->x86.R_AX;
2293197007Sdelphij		emu->x86.R_AX = emu->x86.R_BX;
2294197007Sdelphij		emu->x86.R_BX = (uint16_t) tmp;
2295197007Sdelphij	}
2296197007Sdelphij}
2297197007Sdelphij
2298197007Sdelphij/*
2299197007Sdelphij * REMARKS:
2300197007Sdelphij * Handles opcode 0x94
2301197007Sdelphij */
2302197007Sdelphijstatic void
2303197007Sdelphijx86emuOp_xchg_word_AX_SP(struct x86emu *emu)
2304197007Sdelphij{
2305197007Sdelphij	uint32_t tmp;
2306197007Sdelphij
2307197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2308197007Sdelphij		tmp = emu->x86.R_EAX;
2309197007Sdelphij		emu->x86.R_EAX = emu->x86.R_ESP;
2310197007Sdelphij		emu->x86.R_ESP = tmp;
2311197007Sdelphij	} else {
2312197007Sdelphij		tmp = emu->x86.R_AX;
2313197007Sdelphij		emu->x86.R_AX = emu->x86.R_SP;
2314197007Sdelphij		emu->x86.R_SP = (uint16_t) tmp;
2315197007Sdelphij	}
2316197007Sdelphij}
2317197007Sdelphij
2318197007Sdelphij/*
2319197007Sdelphij * REMARKS:
2320197007Sdelphij * Handles opcode 0x95
2321197007Sdelphij */
2322197007Sdelphijstatic void
2323197007Sdelphijx86emuOp_xchg_word_AX_BP(struct x86emu *emu)
2324197007Sdelphij{
2325197007Sdelphij	uint32_t tmp;
2326197007Sdelphij
2327197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2328197007Sdelphij		tmp = emu->x86.R_EAX;
2329197007Sdelphij		emu->x86.R_EAX = emu->x86.R_EBP;
2330197007Sdelphij		emu->x86.R_EBP = tmp;
2331197007Sdelphij	} else {
2332197007Sdelphij		tmp = emu->x86.R_AX;
2333197007Sdelphij		emu->x86.R_AX = emu->x86.R_BP;
2334197007Sdelphij		emu->x86.R_BP = (uint16_t) tmp;
2335197007Sdelphij	}
2336197007Sdelphij}
2337197007Sdelphij
2338197007Sdelphij/*
2339197007Sdelphij * REMARKS:
2340197007Sdelphij * Handles opcode 0x96
2341197007Sdelphij */
2342197007Sdelphijstatic void
2343197007Sdelphijx86emuOp_xchg_word_AX_SI(struct x86emu *emu)
2344197007Sdelphij{
2345197007Sdelphij	uint32_t tmp;
2346197007Sdelphij
2347197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2348197007Sdelphij		tmp = emu->x86.R_EAX;
2349197007Sdelphij		emu->x86.R_EAX = emu->x86.R_ESI;
2350197007Sdelphij		emu->x86.R_ESI = tmp;
2351197007Sdelphij	} else {
2352197007Sdelphij		tmp = emu->x86.R_AX;
2353197007Sdelphij		emu->x86.R_AX = emu->x86.R_SI;
2354197007Sdelphij		emu->x86.R_SI = (uint16_t) tmp;
2355197007Sdelphij	}
2356197007Sdelphij}
2357197007Sdelphij
2358197007Sdelphij/*
2359197007Sdelphij * REMARKS:
2360197007Sdelphij * Handles opcode 0x97
2361197007Sdelphij */
2362197007Sdelphijstatic void
2363197007Sdelphijx86emuOp_xchg_word_AX_DI(struct x86emu *emu)
2364197007Sdelphij{
2365197007Sdelphij	uint32_t tmp;
2366197007Sdelphij
2367197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2368197007Sdelphij		tmp = emu->x86.R_EAX;
2369197007Sdelphij		emu->x86.R_EAX = emu->x86.R_EDI;
2370197007Sdelphij		emu->x86.R_EDI = tmp;
2371197007Sdelphij	} else {
2372197007Sdelphij		tmp = emu->x86.R_AX;
2373197007Sdelphij		emu->x86.R_AX = emu->x86.R_DI;
2374197007Sdelphij		emu->x86.R_DI = (uint16_t) tmp;
2375197007Sdelphij	}
2376197007Sdelphij}
2377197007Sdelphij
2378197007Sdelphij/*
2379197007Sdelphij * REMARKS:
2380197007Sdelphij * Handles opcode 0x98
2381197007Sdelphij */
2382197007Sdelphijstatic void
2383197007Sdelphijx86emuOp_cbw(struct x86emu *emu)
2384197007Sdelphij{
2385197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2386197007Sdelphij		if (emu->x86.R_AX & 0x8000) {
2387197007Sdelphij			emu->x86.R_EAX |= 0xffff0000;
2388197007Sdelphij		} else {
2389197007Sdelphij			emu->x86.R_EAX &= 0x0000ffff;
2390197007Sdelphij		}
2391197007Sdelphij	} else {
2392197007Sdelphij		if (emu->x86.R_AL & 0x80) {
2393197007Sdelphij			emu->x86.R_AH = 0xff;
2394197007Sdelphij		} else {
2395197007Sdelphij			emu->x86.R_AH = 0x0;
2396197007Sdelphij		}
2397197007Sdelphij	}
2398197007Sdelphij}
2399197007Sdelphij
2400197007Sdelphij/*
2401197007Sdelphij * REMARKS:
2402197007Sdelphij * Handles opcode 0x99
2403197007Sdelphij */
2404197007Sdelphijstatic void
2405197007Sdelphijx86emuOp_cwd(struct x86emu *emu)
2406197007Sdelphij{
2407197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2408197007Sdelphij		if (emu->x86.R_EAX & 0x80000000) {
2409197007Sdelphij			emu->x86.R_EDX = 0xffffffff;
2410197007Sdelphij		} else {
2411197007Sdelphij			emu->x86.R_EDX = 0x0;
2412197007Sdelphij		}
2413197007Sdelphij	} else {
2414197007Sdelphij		if (emu->x86.R_AX & 0x8000) {
2415197007Sdelphij			emu->x86.R_DX = 0xffff;
2416197007Sdelphij		} else {
2417197007Sdelphij			emu->x86.R_DX = 0x0;
2418197007Sdelphij		}
2419197007Sdelphij	}
2420197007Sdelphij}
2421197007Sdelphij
2422197007Sdelphij/*
2423197007Sdelphij * REMARKS:
2424197007Sdelphij * Handles opcode 0x9a
2425197007Sdelphij */
2426197007Sdelphijstatic void
2427197007Sdelphijx86emuOp_call_far_IMM(struct x86emu *emu)
2428197007Sdelphij{
2429197007Sdelphij	uint16_t farseg, faroff;
2430197007Sdelphij
2431197007Sdelphij	faroff = fetch_word_imm(emu);
2432197007Sdelphij	farseg = fetch_word_imm(emu);
2433197007Sdelphij	/* XXX
2434197007Sdelphij	 *
2435197007Sdelphij	 * Hooked interrupt vectors calling into our "BIOS" will cause problems
2436197007Sdelphij	 * unless all intersegment stuff is checked for BIOS access.  Check
2437197007Sdelphij	 * needed here.  For moment, let it alone. */
2438197007Sdelphij	push_word(emu, emu->x86.R_CS);
2439197007Sdelphij	emu->x86.R_CS = farseg;
2440197007Sdelphij	push_word(emu, emu->x86.R_IP);
2441197007Sdelphij	emu->x86.R_IP = faroff;
2442197007Sdelphij}
2443197007Sdelphij
2444197007Sdelphij/*
2445197007Sdelphij * REMARKS:
2446197007Sdelphij * Handles opcode 0x9c
2447197007Sdelphij */
2448197007Sdelphijstatic void
2449197007Sdelphijx86emuOp_pushf_word(struct x86emu *emu)
2450197007Sdelphij{
2451197007Sdelphij	uint32_t flags;
2452197007Sdelphij
2453197007Sdelphij	/* clear out *all* bits not representing flags, and turn on real bits */
2454197007Sdelphij	flags = (emu->x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2455197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2456197007Sdelphij		push_long(emu, flags);
2457197007Sdelphij	} else {
2458197007Sdelphij		push_word(emu, (uint16_t) flags);
2459197007Sdelphij	}
2460197007Sdelphij}
2461197007Sdelphij
2462197007Sdelphij/*
2463197007Sdelphij * REMARKS:
2464197007Sdelphij * Handles opcode 0x9d
2465197007Sdelphij */
2466197007Sdelphijstatic void
2467197007Sdelphijx86emuOp_popf_word(struct x86emu *emu)
2468197007Sdelphij{
2469197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2470197007Sdelphij		emu->x86.R_EFLG = pop_long(emu);
2471197007Sdelphij	} else {
2472197007Sdelphij		emu->x86.R_FLG = pop_word(emu);
2473197007Sdelphij	}
2474197007Sdelphij}
2475197007Sdelphij
2476197007Sdelphij/*
2477197007Sdelphij * REMARKS:
2478197007Sdelphij * Handles opcode 0x9e
2479197007Sdelphij */
2480197007Sdelphijstatic void
2481197007Sdelphijx86emuOp_sahf(struct x86emu *emu)
2482197007Sdelphij{
2483197007Sdelphij	/* clear the lower bits of the flag register */
2484197007Sdelphij	emu->x86.R_FLG &= 0xffffff00;
2485197007Sdelphij	/* or in the AH register into the flags register */
2486197007Sdelphij	emu->x86.R_FLG |= emu->x86.R_AH;
2487197007Sdelphij}
2488197007Sdelphij
2489197007Sdelphij/*
2490197007Sdelphij * REMARKS:
2491197007Sdelphij * Handles opcode 0x9f
2492197007Sdelphij */
2493197007Sdelphijstatic void
2494197007Sdelphijx86emuOp_lahf(struct x86emu *emu)
2495197007Sdelphij{
2496197007Sdelphij	emu->x86.R_AH = (uint8_t) (emu->x86.R_FLG & 0xff);
2497197007Sdelphij	/* undocumented TC++ behavior??? Nope.  It's documented, but you have
2498197007Sdelphij	 * too look real hard to notice it. */
2499197007Sdelphij	emu->x86.R_AH |= 0x2;
2500197007Sdelphij}
2501197007Sdelphij
2502197007Sdelphij/*
2503197007Sdelphij * REMARKS:
2504197007Sdelphij * Handles opcode 0xa0
2505197007Sdelphij */
2506197007Sdelphijstatic void
2507197007Sdelphijx86emuOp_mov_AL_M_IMM(struct x86emu *emu)
2508197007Sdelphij{
2509197007Sdelphij	uint16_t offset;
2510197007Sdelphij
2511197007Sdelphij	offset = fetch_word_imm(emu);
2512197007Sdelphij	emu->x86.R_AL = fetch_data_byte(emu, offset);
2513197007Sdelphij}
2514197007Sdelphij
2515197007Sdelphij/*
2516197007Sdelphij * REMARKS:
2517197007Sdelphij * Handles opcode 0xa1
2518197007Sdelphij */
2519197007Sdelphijstatic void
2520197007Sdelphijx86emuOp_mov_AX_M_IMM(struct x86emu *emu)
2521197007Sdelphij{
2522197007Sdelphij	uint16_t offset;
2523197007Sdelphij
2524197007Sdelphij	offset = fetch_word_imm(emu);
2525197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2526197007Sdelphij		emu->x86.R_EAX = fetch_data_long(emu, offset);
2527197007Sdelphij	} else {
2528197007Sdelphij		emu->x86.R_AX = fetch_data_word(emu, offset);
2529197007Sdelphij	}
2530197007Sdelphij}
2531197007Sdelphij
2532197007Sdelphij/*
2533197007Sdelphij * REMARKS:
2534197007Sdelphij * Handles opcode 0xa2
2535197007Sdelphij */
2536197007Sdelphijstatic void
2537197007Sdelphijx86emuOp_mov_M_AL_IMM(struct x86emu *emu)
2538197007Sdelphij{
2539197007Sdelphij	uint16_t offset;
2540197007Sdelphij
2541197007Sdelphij	offset = fetch_word_imm(emu);
2542197007Sdelphij	store_data_byte(emu, offset, emu->x86.R_AL);
2543197007Sdelphij}
2544197007Sdelphij
2545197007Sdelphij/*
2546197007Sdelphij * REMARKS:
2547197007Sdelphij * Handles opcode 0xa3
2548197007Sdelphij */
2549197007Sdelphijstatic void
2550197007Sdelphijx86emuOp_mov_M_AX_IMM(struct x86emu *emu)
2551197007Sdelphij{
2552197007Sdelphij	uint16_t offset;
2553197007Sdelphij
2554197007Sdelphij	offset = fetch_word_imm(emu);
2555197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2556197007Sdelphij		store_data_long(emu, offset, emu->x86.R_EAX);
2557197007Sdelphij	} else {
2558197007Sdelphij		store_data_word(emu, offset, emu->x86.R_AX);
2559197007Sdelphij	}
2560197007Sdelphij}
2561197007Sdelphij
2562197007Sdelphij/*
2563197007Sdelphij * REMARKS:
2564197007Sdelphij * Handles opcode 0xa4
2565197007Sdelphij */
2566197007Sdelphijstatic void
2567197007Sdelphijx86emuOp_movs_byte(struct x86emu *emu)
2568197007Sdelphij{
2569197007Sdelphij	uint8_t val;
2570197007Sdelphij	uint32_t count;
2571197007Sdelphij	int inc;
2572197007Sdelphij
2573197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2574197007Sdelphij		inc = -1;
2575197007Sdelphij	else
2576197007Sdelphij		inc = 1;
2577197007Sdelphij	count = 1;
2578197007Sdelphij	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2579197007Sdelphij		/* dont care whether REPE or REPNE */
2580197007Sdelphij		/* move them until CX is ZERO. */
2581197007Sdelphij		count = emu->x86.R_CX;
2582197007Sdelphij		emu->x86.R_CX = 0;
2583197007Sdelphij		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2584197007Sdelphij	}
2585197007Sdelphij	while (count--) {
2586197007Sdelphij		val = fetch_data_byte(emu, emu->x86.R_SI);
2587197007Sdelphij		store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2588197007Sdelphij		emu->x86.R_SI += inc;
2589197007Sdelphij		emu->x86.R_DI += inc;
2590197007Sdelphij	}
2591197007Sdelphij}
2592197007Sdelphij
2593197007Sdelphij/*
2594197007Sdelphij * REMARKS:
2595197007Sdelphij * Handles opcode 0xa5
2596197007Sdelphij */
2597197007Sdelphijstatic void
2598197007Sdelphijx86emuOp_movs_word(struct x86emu *emu)
2599197007Sdelphij{
2600197007Sdelphij	uint32_t val;
2601197007Sdelphij	int inc;
2602197007Sdelphij	uint32_t count;
2603197007Sdelphij
2604197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2605197007Sdelphij		inc = 4;
2606197007Sdelphij	else
2607197007Sdelphij		inc = 2;
2608197007Sdelphij
2609197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2610197007Sdelphij		inc = -inc;
2611197007Sdelphij
2612197007Sdelphij	count = 1;
2613197007Sdelphij	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2614197007Sdelphij		/* dont care whether REPE or REPNE */
2615197007Sdelphij		/* move them until CX is ZERO. */
2616197007Sdelphij		count = emu->x86.R_CX;
2617197007Sdelphij		emu->x86.R_CX = 0;
2618197007Sdelphij		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2619197007Sdelphij	}
2620197007Sdelphij	while (count--) {
2621197007Sdelphij		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2622197007Sdelphij			val = fetch_data_long(emu, emu->x86.R_SI);
2623197007Sdelphij			store_long(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2624197007Sdelphij		} else {
2625197007Sdelphij			val = fetch_data_word(emu, emu->x86.R_SI);
2626204934Sdelphij			store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
2627204934Sdelphij			    (uint16_t) val);
2628197007Sdelphij		}
2629197007Sdelphij		emu->x86.R_SI += inc;
2630197007Sdelphij		emu->x86.R_DI += inc;
2631197007Sdelphij	}
2632197007Sdelphij}
2633197007Sdelphij
2634197007Sdelphij/*
2635197007Sdelphij * REMARKS:
2636197007Sdelphij * Handles opcode 0xa6
2637197007Sdelphij */
2638197007Sdelphijstatic void
2639197007Sdelphijx86emuOp_cmps_byte(struct x86emu *emu)
2640197007Sdelphij{
2641197007Sdelphij	int8_t val1, val2;
2642197007Sdelphij	int inc;
2643197007Sdelphij
2644197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2645197007Sdelphij		inc = -1;
2646197007Sdelphij	else
2647197007Sdelphij		inc = 1;
2648197007Sdelphij
2649197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2650197007Sdelphij		/* REPE  */
2651197007Sdelphij		/* move them until CX is ZERO. */
2652197007Sdelphij		while (emu->x86.R_CX != 0) {
2653197007Sdelphij			val1 = fetch_data_byte(emu, emu->x86.R_SI);
2654197007Sdelphij			val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2655197007Sdelphij			cmp_byte(emu, val1, val2);
2656197007Sdelphij			emu->x86.R_CX -= 1;
2657197007Sdelphij			emu->x86.R_SI += inc;
2658197007Sdelphij			emu->x86.R_DI += inc;
2659197007Sdelphij			if (ACCESS_FLAG(F_ZF) == 0)
2660197007Sdelphij				break;
2661197007Sdelphij		}
2662197007Sdelphij		emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2663197007Sdelphij	} else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2664197007Sdelphij		/* REPNE  */
2665197007Sdelphij		/* move them until CX is ZERO. */
2666197007Sdelphij		while (emu->x86.R_CX != 0) {
2667197007Sdelphij			val1 = fetch_data_byte(emu, emu->x86.R_SI);
2668197007Sdelphij			val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2669197007Sdelphij			cmp_byte(emu, val1, val2);
2670197007Sdelphij			emu->x86.R_CX -= 1;
2671197007Sdelphij			emu->x86.R_SI += inc;
2672197007Sdelphij			emu->x86.R_DI += inc;
2673197007Sdelphij			if (ACCESS_FLAG(F_ZF))
2674197007Sdelphij				break;	/* zero flag set means equal */
2675197007Sdelphij		}
2676197007Sdelphij		emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2677197007Sdelphij	} else {
2678197007Sdelphij		val1 = fetch_data_byte(emu, emu->x86.R_SI);
2679197007Sdelphij		val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2680197007Sdelphij		cmp_byte(emu, val1, val2);
2681197007Sdelphij		emu->x86.R_SI += inc;
2682197007Sdelphij		emu->x86.R_DI += inc;
2683197007Sdelphij	}
2684197007Sdelphij}
2685197007Sdelphij
2686197007Sdelphij/*
2687197007Sdelphij * REMARKS:
2688197007Sdelphij * Handles opcode 0xa7
2689197007Sdelphij */
2690197007Sdelphijstatic void
2691197007Sdelphijx86emuOp_cmps_word(struct x86emu *emu)
2692197007Sdelphij{
2693197007Sdelphij	uint32_t val1, val2;
2694197007Sdelphij	int inc;
2695197007Sdelphij
2696197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2697197007Sdelphij		if (ACCESS_FLAG(F_DF))	/* down */
2698197007Sdelphij			inc = -4;
2699197007Sdelphij		else
2700197007Sdelphij			inc = 4;
2701197007Sdelphij	} else {
2702197007Sdelphij		if (ACCESS_FLAG(F_DF))	/* down */
2703197007Sdelphij			inc = -2;
2704197007Sdelphij		else
2705197007Sdelphij			inc = 2;
2706197007Sdelphij	}
2707197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2708197007Sdelphij		/* REPE  */
2709197007Sdelphij		/* move them until CX is ZERO. */
2710197007Sdelphij		while (emu->x86.R_CX != 0) {
2711197007Sdelphij			if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2712197007Sdelphij				val1 = fetch_data_long(emu, emu->x86.R_SI);
2713204934Sdelphij				val2 = fetch_long(emu, emu->x86.R_ES,
2714204934Sdelphij				    emu->x86.R_DI);
2715197007Sdelphij				cmp_long(emu, val1, val2);
2716197007Sdelphij			} else {
2717197007Sdelphij				val1 = fetch_data_word(emu, emu->x86.R_SI);
2718204934Sdelphij				val2 = fetch_word(emu, emu->x86.R_ES,
2719204934Sdelphij				    emu->x86.R_DI);
2720197007Sdelphij				cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2721197007Sdelphij			}
2722197007Sdelphij			emu->x86.R_CX -= 1;
2723197007Sdelphij			emu->x86.R_SI += inc;
2724197007Sdelphij			emu->x86.R_DI += inc;
2725197007Sdelphij			if (ACCESS_FLAG(F_ZF) == 0)
2726197007Sdelphij				break;
2727197007Sdelphij		}
2728197007Sdelphij		emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2729197007Sdelphij	} else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2730197007Sdelphij		/* REPNE  */
2731197007Sdelphij		/* move them until CX is ZERO. */
2732197007Sdelphij		while (emu->x86.R_CX != 0) {
2733197007Sdelphij			if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2734197007Sdelphij				val1 = fetch_data_long(emu, emu->x86.R_SI);
2735204934Sdelphij				val2 = fetch_long(emu, emu->x86.R_ES,
2736204934Sdelphij				    emu->x86.R_DI);
2737197007Sdelphij				cmp_long(emu, val1, val2);
2738197007Sdelphij			} else {
2739197007Sdelphij				val1 = fetch_data_word(emu, emu->x86.R_SI);
2740204934Sdelphij				val2 = fetch_word(emu, emu->x86.R_ES,
2741204934Sdelphij				    emu->x86.R_DI);
2742197007Sdelphij				cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2743197007Sdelphij			}
2744197007Sdelphij			emu->x86.R_CX -= 1;
2745197007Sdelphij			emu->x86.R_SI += inc;
2746197007Sdelphij			emu->x86.R_DI += inc;
2747197007Sdelphij			if (ACCESS_FLAG(F_ZF))
2748197007Sdelphij				break;	/* zero flag set means equal */
2749197007Sdelphij		}
2750197007Sdelphij		emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2751197007Sdelphij	} else {
2752197007Sdelphij		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2753197007Sdelphij			val1 = fetch_data_long(emu, emu->x86.R_SI);
2754197007Sdelphij			val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2755197007Sdelphij			cmp_long(emu, val1, val2);
2756197007Sdelphij		} else {
2757197007Sdelphij			val1 = fetch_data_word(emu, emu->x86.R_SI);
2758197007Sdelphij			val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2759197007Sdelphij			cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2760197007Sdelphij		}
2761197007Sdelphij		emu->x86.R_SI += inc;
2762197007Sdelphij		emu->x86.R_DI += inc;
2763197007Sdelphij	}
2764197007Sdelphij}
2765197007Sdelphij
2766197007Sdelphij/*
2767197007Sdelphij * REMARKS:
2768197007Sdelphij * Handles opcode 0xa9
2769197007Sdelphij */
2770197007Sdelphijstatic void
2771197007Sdelphijx86emuOp_test_AX_IMM(struct x86emu *emu)
2772197007Sdelphij{
2773197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2774197007Sdelphij		test_long(emu, emu->x86.R_EAX, fetch_long_imm(emu));
2775197007Sdelphij	} else {
2776197007Sdelphij		test_word(emu, emu->x86.R_AX, fetch_word_imm(emu));
2777197007Sdelphij	}
2778197007Sdelphij}
2779197007Sdelphij
2780197007Sdelphij/*
2781197007Sdelphij * REMARKS:
2782197007Sdelphij * Handles opcode 0xaa
2783197007Sdelphij */
2784197007Sdelphijstatic void
2785197007Sdelphijx86emuOp_stos_byte(struct x86emu *emu)
2786197007Sdelphij{
2787197007Sdelphij	int inc;
2788197007Sdelphij
2789197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2790197007Sdelphij		inc = -1;
2791197007Sdelphij	else
2792197007Sdelphij		inc = 1;
2793197007Sdelphij	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2794197007Sdelphij		/* dont care whether REPE or REPNE */
2795197007Sdelphij		/* move them until CX is ZERO. */
2796197007Sdelphij		while (emu->x86.R_CX != 0) {
2797204934Sdelphij			store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
2798204934Sdelphij			    emu->x86.R_AL);
2799197007Sdelphij			emu->x86.R_CX -= 1;
2800197007Sdelphij			emu->x86.R_DI += inc;
2801197007Sdelphij		}
2802197007Sdelphij		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2803197007Sdelphij	} else {
2804197007Sdelphij		store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL);
2805197007Sdelphij		emu->x86.R_DI += inc;
2806197007Sdelphij	}
2807197007Sdelphij}
2808197007Sdelphij
2809197007Sdelphij/*
2810197007Sdelphij * REMARKS:
2811197007Sdelphij * Handles opcode 0xab
2812197007Sdelphij */
2813197007Sdelphijstatic void
2814197007Sdelphijx86emuOp_stos_word(struct x86emu *emu)
2815197007Sdelphij{
2816197007Sdelphij	int inc;
2817197007Sdelphij	uint32_t count;
2818197007Sdelphij
2819197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2820197007Sdelphij		inc = 4;
2821197007Sdelphij	else
2822197007Sdelphij		inc = 2;
2823197007Sdelphij
2824197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2825197007Sdelphij		inc = -inc;
2826197007Sdelphij
2827197007Sdelphij	count = 1;
2828197007Sdelphij	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2829197007Sdelphij		/* dont care whether REPE or REPNE */
2830197007Sdelphij		/* move them until CX is ZERO. */
2831197007Sdelphij		count = emu->x86.R_CX;
2832197007Sdelphij		emu->x86.R_CX = 0;
2833197007Sdelphij		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2834197007Sdelphij	}
2835197007Sdelphij	while (count--) {
2836197007Sdelphij		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2837204934Sdelphij			store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
2838204934Sdelphij			    emu->x86.R_EAX);
2839197007Sdelphij		} else {
2840204934Sdelphij			store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
2841204934Sdelphij			    emu->x86.R_AX);
2842197007Sdelphij		}
2843197007Sdelphij		emu->x86.R_DI += inc;
2844197007Sdelphij	}
2845197007Sdelphij}
2846197007Sdelphij
2847197007Sdelphij/*
2848197007Sdelphij * REMARKS:
2849197007Sdelphij * Handles opcode 0xac
2850197007Sdelphij */
2851197007Sdelphijstatic void
2852197007Sdelphijx86emuOp_lods_byte(struct x86emu *emu)
2853197007Sdelphij{
2854197007Sdelphij	int inc;
2855197007Sdelphij
2856197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2857197007Sdelphij		inc = -1;
2858197007Sdelphij	else
2859197007Sdelphij		inc = 1;
2860197007Sdelphij	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2861197007Sdelphij		/* dont care whether REPE or REPNE */
2862197007Sdelphij		/* move them until CX is ZERO. */
2863197007Sdelphij		while (emu->x86.R_CX != 0) {
2864197007Sdelphij			emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2865197007Sdelphij			emu->x86.R_CX -= 1;
2866197007Sdelphij			emu->x86.R_SI += inc;
2867197007Sdelphij		}
2868197007Sdelphij		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2869197007Sdelphij	} else {
2870197007Sdelphij		emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2871197007Sdelphij		emu->x86.R_SI += inc;
2872197007Sdelphij	}
2873197007Sdelphij}
2874197007Sdelphij
2875197007Sdelphij/*
2876197007Sdelphij * REMARKS:
2877197007Sdelphij * Handles opcode 0xad
2878197007Sdelphij */
2879197007Sdelphijstatic void
2880197007Sdelphijx86emuOp_lods_word(struct x86emu *emu)
2881197007Sdelphij{
2882197007Sdelphij	int inc;
2883197007Sdelphij	uint32_t count;
2884197007Sdelphij
2885197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2886197007Sdelphij		inc = 4;
2887197007Sdelphij	else
2888197007Sdelphij		inc = 2;
2889197007Sdelphij
2890197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2891197007Sdelphij		inc = -inc;
2892197007Sdelphij
2893197007Sdelphij	count = 1;
2894197007Sdelphij	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2895197007Sdelphij		/* dont care whether REPE or REPNE */
2896197007Sdelphij		/* move them until CX is ZERO. */
2897197007Sdelphij		count = emu->x86.R_CX;
2898197007Sdelphij		emu->x86.R_CX = 0;
2899197007Sdelphij		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2900197007Sdelphij	}
2901197007Sdelphij	while (count--) {
2902197007Sdelphij		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2903197007Sdelphij			emu->x86.R_EAX = fetch_data_long(emu, emu->x86.R_SI);
2904197007Sdelphij		} else {
2905197007Sdelphij			emu->x86.R_AX = fetch_data_word(emu, emu->x86.R_SI);
2906197007Sdelphij		}
2907197007Sdelphij		emu->x86.R_SI += inc;
2908197007Sdelphij	}
2909197007Sdelphij}
2910197007Sdelphij
2911197007Sdelphij/*
2912197007Sdelphij * REMARKS:
2913197007Sdelphij * Handles opcode 0xae
2914197007Sdelphij */
2915197007Sdelphijstatic void
2916197007Sdelphijx86emuOp_scas_byte(struct x86emu *emu)
2917197007Sdelphij{
2918197007Sdelphij	int8_t val2;
2919197007Sdelphij	int inc;
2920197007Sdelphij
2921197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2922197007Sdelphij		inc = -1;
2923197007Sdelphij	else
2924197007Sdelphij		inc = 1;
2925197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2926197007Sdelphij		/* REPE  */
2927197007Sdelphij		/* move them until CX is ZERO. */
2928197007Sdelphij		while (emu->x86.R_CX != 0) {
2929197007Sdelphij			val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2930197007Sdelphij			cmp_byte(emu, emu->x86.R_AL, val2);
2931197007Sdelphij			emu->x86.R_CX -= 1;
2932197007Sdelphij			emu->x86.R_DI += inc;
2933197007Sdelphij			if (ACCESS_FLAG(F_ZF) == 0)
2934197007Sdelphij				break;
2935197007Sdelphij		}
2936197007Sdelphij		emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2937197007Sdelphij	} else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2938197007Sdelphij		/* REPNE  */
2939197007Sdelphij		/* move them until CX is ZERO. */
2940197007Sdelphij		while (emu->x86.R_CX != 0) {
2941197007Sdelphij			val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2942197007Sdelphij			cmp_byte(emu, emu->x86.R_AL, val2);
2943197007Sdelphij			emu->x86.R_CX -= 1;
2944197007Sdelphij			emu->x86.R_DI += inc;
2945197007Sdelphij			if (ACCESS_FLAG(F_ZF))
2946197007Sdelphij				break;	/* zero flag set means equal */
2947197007Sdelphij		}
2948197007Sdelphij		emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2949197007Sdelphij	} else {
2950197007Sdelphij		val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2951197007Sdelphij		cmp_byte(emu, emu->x86.R_AL, val2);
2952197007Sdelphij		emu->x86.R_DI += inc;
2953197007Sdelphij	}
2954197007Sdelphij}
2955197007Sdelphij
2956197007Sdelphij/*
2957197007Sdelphij * REMARKS:
2958197007Sdelphij * Handles opcode 0xaf
2959197007Sdelphij */
2960197007Sdelphijstatic void
2961197007Sdelphijx86emuOp_scas_word(struct x86emu *emu)
2962197007Sdelphij{
2963197007Sdelphij	int inc;
2964197007Sdelphij	uint32_t val;
2965197007Sdelphij
2966197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2967197007Sdelphij		inc = 4;
2968197007Sdelphij	else
2969197007Sdelphij		inc = 2;
2970197007Sdelphij
2971197007Sdelphij	if (ACCESS_FLAG(F_DF))	/* down */
2972197007Sdelphij		inc = -inc;
2973197007Sdelphij
2974197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2975197007Sdelphij		/* REPE  */
2976197007Sdelphij		/* move them until CX is ZERO. */
2977197007Sdelphij		while (emu->x86.R_CX != 0) {
2978197007Sdelphij			if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2979204934Sdelphij				val = fetch_long(emu, emu->x86.R_ES,
2980204934Sdelphij				    emu->x86.R_DI);
2981197007Sdelphij				cmp_long(emu, emu->x86.R_EAX, val);
2982197007Sdelphij			} else {
2983204934Sdelphij				val = fetch_word(emu, emu->x86.R_ES,
2984204934Sdelphij				    emu->x86.R_DI);
2985197007Sdelphij				cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
2986197007Sdelphij			}
2987197007Sdelphij			emu->x86.R_CX -= 1;
2988197007Sdelphij			emu->x86.R_DI += inc;
2989197007Sdelphij			if (ACCESS_FLAG(F_ZF) == 0)
2990197007Sdelphij				break;
2991197007Sdelphij		}
2992197007Sdelphij		emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2993197007Sdelphij	} else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2994197007Sdelphij		/* REPNE  */
2995197007Sdelphij		/* move them until CX is ZERO. */
2996197007Sdelphij		while (emu->x86.R_CX != 0) {
2997197007Sdelphij			if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2998204934Sdelphij				val = fetch_long(emu, emu->x86.R_ES,
2999204934Sdelphij				    emu->x86.R_DI);
3000197007Sdelphij				cmp_long(emu, emu->x86.R_EAX, val);
3001197007Sdelphij			} else {
3002204934Sdelphij				val = fetch_word(emu, emu->x86.R_ES,
3003204934Sdelphij				    emu->x86.R_DI);
3004197007Sdelphij				cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
3005197007Sdelphij			}
3006197007Sdelphij			emu->x86.R_CX -= 1;
3007197007Sdelphij			emu->x86.R_DI += inc;
3008197007Sdelphij			if (ACCESS_FLAG(F_ZF))
3009197007Sdelphij				break;	/* zero flag set means equal */
3010197007Sdelphij		}
3011197007Sdelphij		emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
3012197007Sdelphij	} else {
3013197007Sdelphij		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3014197007Sdelphij			val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
3015197007Sdelphij			cmp_long(emu, emu->x86.R_EAX, val);
3016197007Sdelphij		} else {
3017197007Sdelphij			val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
3018197007Sdelphij			cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
3019197007Sdelphij		}
3020197007Sdelphij		emu->x86.R_DI += inc;
3021197007Sdelphij	}
3022197007Sdelphij}
3023197007Sdelphij
3024197007Sdelphij/*
3025197007Sdelphij * REMARKS:
3026197007Sdelphij * Handles opcode 0xb8
3027197007Sdelphij */
3028197007Sdelphijstatic void
3029197007Sdelphijx86emuOp_mov_word_AX_IMM(struct x86emu *emu)
3030197007Sdelphij{
3031197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3032197007Sdelphij		emu->x86.R_EAX = fetch_long_imm(emu);
3033197007Sdelphij	else
3034197007Sdelphij		emu->x86.R_AX = fetch_word_imm(emu);
3035197007Sdelphij}
3036197007Sdelphij
3037197007Sdelphij/*
3038197007Sdelphij * REMARKS:
3039197007Sdelphij * Handles opcode 0xb9
3040197007Sdelphij */
3041197007Sdelphijstatic void
3042197007Sdelphijx86emuOp_mov_word_CX_IMM(struct x86emu *emu)
3043197007Sdelphij{
3044197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3045197007Sdelphij		emu->x86.R_ECX = fetch_long_imm(emu);
3046197007Sdelphij	else
3047197007Sdelphij		emu->x86.R_CX = fetch_word_imm(emu);
3048197007Sdelphij}
3049197007Sdelphij
3050197007Sdelphij/*
3051197007Sdelphij * REMARKS:
3052197007Sdelphij * Handles opcode 0xba
3053197007Sdelphij */
3054197007Sdelphijstatic void
3055197007Sdelphijx86emuOp_mov_word_DX_IMM(struct x86emu *emu)
3056197007Sdelphij{
3057197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3058197007Sdelphij		emu->x86.R_EDX = fetch_long_imm(emu);
3059197007Sdelphij	else
3060197007Sdelphij		emu->x86.R_DX = fetch_word_imm(emu);
3061197007Sdelphij}
3062197007Sdelphij
3063197007Sdelphij/*
3064197007Sdelphij * REMARKS:
3065197007Sdelphij * Handles opcode 0xbb
3066197007Sdelphij */
3067197007Sdelphijstatic void
3068197007Sdelphijx86emuOp_mov_word_BX_IMM(struct x86emu *emu)
3069197007Sdelphij{
3070197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3071197007Sdelphij		emu->x86.R_EBX = fetch_long_imm(emu);
3072197007Sdelphij	else
3073197007Sdelphij		emu->x86.R_BX = fetch_word_imm(emu);
3074197007Sdelphij}
3075197007Sdelphij
3076197007Sdelphij/*
3077197007Sdelphij * REMARKS:
3078197007Sdelphij * Handles opcode 0xbc
3079197007Sdelphij */
3080197007Sdelphijstatic void
3081197007Sdelphijx86emuOp_mov_word_SP_IMM(struct x86emu *emu)
3082197007Sdelphij{
3083197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3084197007Sdelphij		emu->x86.R_ESP = fetch_long_imm(emu);
3085197007Sdelphij	else
3086197007Sdelphij		emu->x86.R_SP = fetch_word_imm(emu);
3087197007Sdelphij}
3088197007Sdelphij
3089197007Sdelphij/*
3090197007Sdelphij * REMARKS:
3091197007Sdelphij * Handles opcode 0xbd
3092197007Sdelphij */
3093197007Sdelphijstatic void
3094197007Sdelphijx86emuOp_mov_word_BP_IMM(struct x86emu *emu)
3095197007Sdelphij{
3096197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3097197007Sdelphij		emu->x86.R_EBP = fetch_long_imm(emu);
3098197007Sdelphij	else
3099197007Sdelphij		emu->x86.R_BP = fetch_word_imm(emu);
3100197007Sdelphij}
3101197007Sdelphij
3102197007Sdelphij/*
3103197007Sdelphij * REMARKS:
3104197007Sdelphij * Handles opcode 0xbe
3105197007Sdelphij */
3106197007Sdelphijstatic void
3107197007Sdelphijx86emuOp_mov_word_SI_IMM(struct x86emu *emu)
3108197007Sdelphij{
3109197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3110197007Sdelphij		emu->x86.R_ESI = fetch_long_imm(emu);
3111197007Sdelphij	else
3112197007Sdelphij		emu->x86.R_SI = fetch_word_imm(emu);
3113197007Sdelphij}
3114197007Sdelphij
3115197007Sdelphij/*
3116197007Sdelphij * REMARKS:
3117197007Sdelphij * Handles opcode 0xbf
3118197007Sdelphij */
3119197007Sdelphijstatic void
3120197007Sdelphijx86emuOp_mov_word_DI_IMM(struct x86emu *emu)
3121197007Sdelphij{
3122197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3123197007Sdelphij		emu->x86.R_EDI = fetch_long_imm(emu);
3124197007Sdelphij	else
3125197007Sdelphij		emu->x86.R_DI = fetch_word_imm(emu);
3126197007Sdelphij}
3127197007Sdelphij/* used by opcodes c0, d0, and d2. */
3128197007Sdelphijstatic
3129204934Sdelphijuint8_t(* const opcD0_byte_operation[])
3130204934Sdelphij    (struct x86emu *, uint8_t d, uint8_t s) =
3131197007Sdelphij{
3132197007Sdelphij	rol_byte,
3133197007Sdelphij	ror_byte,
3134197007Sdelphij	rcl_byte,
3135197007Sdelphij	rcr_byte,
3136197007Sdelphij	shl_byte,
3137197007Sdelphij	shr_byte,
3138197007Sdelphij	shl_byte,		/* sal_byte === shl_byte  by definition */
3139197007Sdelphij	sar_byte,
3140197007Sdelphij};
3141197007Sdelphij
3142197007Sdelphij/*
3143197007Sdelphij * REMARKS:
3144197007Sdelphij * Handles opcode 0xc0
3145197007Sdelphij */
3146197007Sdelphijstatic void
3147197007Sdelphijx86emuOp_opcC0_byte_RM_MEM(struct x86emu *emu)
3148197007Sdelphij{
3149197007Sdelphij	uint8_t destval, amt;
3150197007Sdelphij
3151197007Sdelphij	/*
3152197007Sdelphij         * Yet another weirdo special case instruction format.  Part of
3153197007Sdelphij         * the opcode held below in "RH".  Doubly nested case would
3154197007Sdelphij         * result, except that the decoded instruction
3155197007Sdelphij         */
3156197007Sdelphij	fetch_decode_modrm(emu);
3157197007Sdelphij	/* know operation, decode the mod byte to find the addressing mode. */
3158197007Sdelphij	destval = decode_and_fetch_byte_imm8(emu, &amt);
3159197007Sdelphij	destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, amt);
3160197007Sdelphij	write_back_byte(emu, destval);
3161197007Sdelphij}
3162197007Sdelphij/* used by opcodes c1, d1, and d3. */
3163197007Sdelphijstatic
3164204934Sdelphijuint16_t(* const opcD1_word_operation[])
3165204934Sdelphij    (struct x86emu *, uint16_t s, uint8_t d) =
3166197007Sdelphij{
3167197007Sdelphij	rol_word,
3168197007Sdelphij	ror_word,
3169197007Sdelphij	rcl_word,
3170197007Sdelphij	rcr_word,
3171197007Sdelphij	shl_word,
3172197007Sdelphij	shr_word,
3173197007Sdelphij	shl_word,		/* sal_byte === shl_byte  by definition */
3174197007Sdelphij	sar_word,
3175197007Sdelphij};
3176197007Sdelphij/* used by opcodes c1, d1, and d3. */
3177197007Sdelphijstatic
3178204934Sdelphijuint32_t(* const opcD1_long_operation[])
3179204934Sdelphij    (struct x86emu *, uint32_t s, uint8_t d) =
3180197007Sdelphij{
3181197007Sdelphij	rol_long,
3182197007Sdelphij	ror_long,
3183197007Sdelphij	rcl_long,
3184197007Sdelphij	rcr_long,
3185197007Sdelphij	shl_long,
3186197007Sdelphij	shr_long,
3187197007Sdelphij	shl_long,		/* sal_byte === shl_byte  by definition */
3188197007Sdelphij	sar_long,
3189197007Sdelphij};
3190197007Sdelphij
3191197007Sdelphij/*
3192197007Sdelphij * REMARKS:
3193197007Sdelphij * Handles opcode 0xc1
3194197007Sdelphij */
3195197007Sdelphijstatic void
3196197007Sdelphijx86emuOp_opcC1_word_RM_MEM(struct x86emu *emu)
3197197007Sdelphij{
3198197007Sdelphij	uint8_t amt;
3199197007Sdelphij
3200197007Sdelphij	/*
3201197007Sdelphij         * Yet another weirdo special case instruction format.  Part of
3202197007Sdelphij         * the opcode held below in "RH".  Doubly nested case would
3203197007Sdelphij         * result, except that the decoded instruction
3204197007Sdelphij         */
3205197007Sdelphij	fetch_decode_modrm(emu);
3206197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3207197007Sdelphij		uint32_t destval;
3208197007Sdelphij
3209197007Sdelphij		destval = decode_and_fetch_long_imm8(emu, &amt);
3210204934Sdelphij		destval = (*opcD1_long_operation[emu->cur_rh])
3211204934Sdelphij		    (emu, destval, amt);
3212197007Sdelphij		write_back_long(emu, destval);
3213197007Sdelphij	} else {
3214197007Sdelphij		uint16_t destval;
3215197007Sdelphij
3216197007Sdelphij		destval = decode_and_fetch_word_imm8(emu, &amt);
3217204934Sdelphij		destval = (*opcD1_word_operation[emu->cur_rh])
3218204934Sdelphij		    (emu, destval, amt);
3219197007Sdelphij		write_back_word(emu, destval);
3220197007Sdelphij	}
3221197007Sdelphij}
3222197007Sdelphij
3223197007Sdelphij/*
3224197007Sdelphij * REMARKS:
3225197007Sdelphij * Handles opcode 0xc2
3226197007Sdelphij */
3227197007Sdelphijstatic void
3228197007Sdelphijx86emuOp_ret_near_IMM(struct x86emu *emu)
3229197007Sdelphij{
3230197007Sdelphij	uint16_t imm;
3231197007Sdelphij
3232197007Sdelphij	imm = fetch_word_imm(emu);
3233197007Sdelphij	emu->x86.R_IP = pop_word(emu);
3234197007Sdelphij	emu->x86.R_SP += imm;
3235197007Sdelphij}
3236197007Sdelphij
3237197007Sdelphij/*
3238197007Sdelphij * REMARKS:
3239197007Sdelphij * Handles opcode 0xc6
3240197007Sdelphij */
3241197007Sdelphijstatic void
3242197007Sdelphijx86emuOp_mov_byte_RM_IMM(struct x86emu *emu)
3243197007Sdelphij{
3244197007Sdelphij	uint8_t *destreg;
3245197007Sdelphij	uint32_t destoffset;
3246197007Sdelphij	uint8_t imm;
3247197007Sdelphij
3248197007Sdelphij	fetch_decode_modrm(emu);
3249197007Sdelphij	if (emu->cur_rh != 0)
3250197007Sdelphij		x86emu_halt_sys(emu);
3251197007Sdelphij	if (emu->cur_mod != 3) {
3252197007Sdelphij		destoffset = decode_rl_address(emu);
3253197007Sdelphij		imm = fetch_byte_imm(emu);
3254197007Sdelphij		store_data_byte(emu, destoffset, imm);
3255197007Sdelphij	} else {
3256197007Sdelphij		destreg = decode_rl_byte_register(emu);
3257197007Sdelphij		imm = fetch_byte_imm(emu);
3258197007Sdelphij		*destreg = imm;
3259197007Sdelphij	}
3260197007Sdelphij}
3261197007Sdelphij
3262197007Sdelphij/*
3263197007Sdelphij * REMARKS:
3264197007Sdelphij * Handles opcode 0xc7
3265197007Sdelphij */
3266197007Sdelphijstatic void
3267197007Sdelphijx86emuOp32_mov_word_RM_IMM(struct x86emu *emu)
3268197007Sdelphij{
3269197007Sdelphij	uint32_t destoffset;
3270197007Sdelphij	uint32_t imm, *destreg;
3271197007Sdelphij
3272197007Sdelphij	fetch_decode_modrm(emu);
3273197007Sdelphij	if (emu->cur_rh != 0)
3274197007Sdelphij		x86emu_halt_sys(emu);
3275197007Sdelphij
3276197007Sdelphij	if (emu->cur_mod != 3) {
3277197007Sdelphij		destoffset = decode_rl_address(emu);
3278197007Sdelphij		imm = fetch_long_imm(emu);
3279197007Sdelphij		store_data_long(emu, destoffset, imm);
3280197007Sdelphij	} else {
3281197007Sdelphij		destreg = decode_rl_long_register(emu);
3282197007Sdelphij		imm = fetch_long_imm(emu);
3283197007Sdelphij		*destreg = imm;
3284197007Sdelphij	}
3285197007Sdelphij}
3286197007Sdelphij
3287197007Sdelphijstatic void
3288197007Sdelphijx86emuOp16_mov_word_RM_IMM(struct x86emu *emu)
3289197007Sdelphij{
3290197007Sdelphij	uint32_t destoffset;
3291197007Sdelphij	uint16_t imm, *destreg;
3292197007Sdelphij
3293197007Sdelphij	fetch_decode_modrm(emu);
3294197007Sdelphij	if (emu->cur_rh != 0)
3295197007Sdelphij		x86emu_halt_sys(emu);
3296197007Sdelphij
3297197007Sdelphij	if (emu->cur_mod != 3) {
3298197007Sdelphij		destoffset = decode_rl_address(emu);
3299197007Sdelphij		imm = fetch_word_imm(emu);
3300197007Sdelphij		store_data_word(emu, destoffset, imm);
3301197007Sdelphij	} else {
3302197007Sdelphij		destreg = decode_rl_word_register(emu);
3303197007Sdelphij		imm = fetch_word_imm(emu);
3304197007Sdelphij		*destreg = imm;
3305197007Sdelphij	}
3306197007Sdelphij}
3307197007Sdelphij
3308197007Sdelphijstatic void
3309197007Sdelphijx86emuOp_mov_word_RM_IMM(struct x86emu *emu)
3310197007Sdelphij{
3311197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3312197007Sdelphij		x86emuOp32_mov_word_RM_IMM(emu);
3313197007Sdelphij	else
3314197007Sdelphij		x86emuOp16_mov_word_RM_IMM(emu);
3315197007Sdelphij}
3316197007Sdelphij
3317197007Sdelphij/*
3318197007Sdelphij * REMARKS:
3319197007Sdelphij * Handles opcode 0xc8
3320197007Sdelphij */
3321197007Sdelphijstatic void
3322197007Sdelphijx86emuOp_enter(struct x86emu *emu)
3323197007Sdelphij{
3324197007Sdelphij	uint16_t local, frame_pointer;
3325197007Sdelphij	uint8_t nesting;
3326197007Sdelphij	int i;
3327197007Sdelphij
3328197007Sdelphij	local = fetch_word_imm(emu);
3329197007Sdelphij	nesting = fetch_byte_imm(emu);
3330197007Sdelphij	push_word(emu, emu->x86.R_BP);
3331197007Sdelphij	frame_pointer = emu->x86.R_SP;
3332197007Sdelphij	if (nesting > 0) {
3333197007Sdelphij		for (i = 1; i < nesting; i++) {
3334197007Sdelphij			emu->x86.R_BP -= 2;
3335204934Sdelphij			push_word(emu, fetch_word(emu, emu->x86.R_SS,
3336204934Sdelphij			    emu->x86.R_BP));
3337197007Sdelphij		}
3338197007Sdelphij		push_word(emu, frame_pointer);
3339197007Sdelphij	}
3340197007Sdelphij	emu->x86.R_BP = frame_pointer;
3341197007Sdelphij	emu->x86.R_SP = (uint16_t) (emu->x86.R_SP - local);
3342197007Sdelphij}
3343197007Sdelphij
3344197007Sdelphij/*
3345197007Sdelphij * REMARKS:
3346197007Sdelphij * Handles opcode 0xc9
3347197007Sdelphij */
3348197007Sdelphijstatic void
3349197007Sdelphijx86emuOp_leave(struct x86emu *emu)
3350197007Sdelphij{
3351197007Sdelphij	emu->x86.R_SP = emu->x86.R_BP;
3352197007Sdelphij	emu->x86.R_BP = pop_word(emu);
3353197007Sdelphij}
3354197007Sdelphij
3355197007Sdelphij/*
3356197007Sdelphij * REMARKS:
3357197007Sdelphij * Handles opcode 0xca
3358197007Sdelphij */
3359197007Sdelphijstatic void
3360197007Sdelphijx86emuOp_ret_far_IMM(struct x86emu *emu)
3361197007Sdelphij{
3362197007Sdelphij	uint16_t imm;
3363197007Sdelphij
3364197007Sdelphij	imm = fetch_word_imm(emu);
3365197007Sdelphij	emu->x86.R_IP = pop_word(emu);
3366197007Sdelphij	emu->x86.R_CS = pop_word(emu);
3367197007Sdelphij	emu->x86.R_SP += imm;
3368197007Sdelphij}
3369197007Sdelphij
3370197007Sdelphij/*
3371197007Sdelphij * REMARKS:
3372197007Sdelphij * Handles opcode 0xcb
3373197007Sdelphij */
3374197007Sdelphijstatic void
3375197007Sdelphijx86emuOp_ret_far(struct x86emu *emu)
3376197007Sdelphij{
3377197007Sdelphij	emu->x86.R_IP = pop_word(emu);
3378197007Sdelphij	emu->x86.R_CS = pop_word(emu);
3379197007Sdelphij}
3380197007Sdelphij
3381197007Sdelphij/*
3382197007Sdelphij * REMARKS:
3383197007Sdelphij * Handles opcode 0xcc
3384197007Sdelphij */
3385197007Sdelphijstatic void
3386197007Sdelphijx86emuOp_int3(struct x86emu *emu)
3387197007Sdelphij{
3388197007Sdelphij	x86emu_intr_dispatch(emu, 3);
3389197007Sdelphij}
3390197007Sdelphij
3391197007Sdelphij/*
3392197007Sdelphij * REMARKS:
3393197007Sdelphij * Handles opcode 0xcd
3394197007Sdelphij */
3395197007Sdelphijstatic void
3396197007Sdelphijx86emuOp_int_IMM(struct x86emu *emu)
3397197007Sdelphij{
3398197007Sdelphij	uint8_t intnum;
3399197007Sdelphij
3400197007Sdelphij	intnum = fetch_byte_imm(emu);
3401197007Sdelphij	x86emu_intr_dispatch(emu, intnum);
3402197007Sdelphij}
3403197007Sdelphij
3404197007Sdelphij/*
3405197007Sdelphij * REMARKS:
3406197007Sdelphij * Handles opcode 0xce
3407197007Sdelphij */
3408197007Sdelphijstatic void
3409197007Sdelphijx86emuOp_into(struct x86emu *emu)
3410197007Sdelphij{
3411197007Sdelphij	if (ACCESS_FLAG(F_OF))
3412197007Sdelphij		x86emu_intr_dispatch(emu, 4);
3413197007Sdelphij}
3414197007Sdelphij
3415197007Sdelphij/*
3416197007Sdelphij * REMARKS:
3417197007Sdelphij * Handles opcode 0xcf
3418197007Sdelphij */
3419197007Sdelphijstatic void
3420197007Sdelphijx86emuOp_iret(struct x86emu *emu)
3421197007Sdelphij{
3422197007Sdelphij	emu->x86.R_IP = pop_word(emu);
3423197007Sdelphij	emu->x86.R_CS = pop_word(emu);
3424197007Sdelphij	emu->x86.R_FLG = pop_word(emu);
3425197007Sdelphij}
3426197007Sdelphij
3427197007Sdelphij/*
3428197007Sdelphij * REMARKS:
3429197007Sdelphij * Handles opcode 0xd0
3430197007Sdelphij */
3431197007Sdelphijstatic void
3432197007Sdelphijx86emuOp_opcD0_byte_RM_1(struct x86emu *emu)
3433197007Sdelphij{
3434197007Sdelphij	uint8_t destval;
3435197007Sdelphij
3436197007Sdelphij	fetch_decode_modrm(emu);
3437197007Sdelphij	destval = decode_and_fetch_byte(emu);
3438197007Sdelphij	destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, 1);
3439197007Sdelphij	write_back_byte(emu, destval);
3440197007Sdelphij}
3441197007Sdelphij
3442197007Sdelphij/*
3443197007Sdelphij * REMARKS:
3444197007Sdelphij * Handles opcode 0xd1
3445197007Sdelphij */
3446197007Sdelphijstatic void
3447197007Sdelphijx86emuOp_opcD1_word_RM_1(struct x86emu *emu)
3448197007Sdelphij{
3449197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3450197007Sdelphij		uint32_t destval;
3451197007Sdelphij
3452197007Sdelphij		fetch_decode_modrm(emu);
3453197007Sdelphij		destval = decode_and_fetch_long(emu);
3454204934Sdelphij		destval = (*opcD1_long_operation[emu->cur_rh])(emu, destval, 1);
3455197007Sdelphij		write_back_long(emu, destval);
3456197007Sdelphij	} else {
3457197007Sdelphij		uint16_t destval;
3458197007Sdelphij
3459197007Sdelphij		fetch_decode_modrm(emu);
3460197007Sdelphij		destval = decode_and_fetch_word(emu);
3461204934Sdelphij		destval = (*opcD1_word_operation[emu->cur_rh])(emu, destval, 1);
3462197007Sdelphij		write_back_word(emu, destval);
3463197007Sdelphij	}
3464197007Sdelphij}
3465197007Sdelphij
3466197007Sdelphij/*
3467197007Sdelphij * REMARKS:
3468197007Sdelphij * Handles opcode 0xd2
3469197007Sdelphij */
3470197007Sdelphijstatic void
3471197007Sdelphijx86emuOp_opcD2_byte_RM_CL(struct x86emu *emu)
3472197007Sdelphij{
3473197007Sdelphij	uint8_t destval;
3474197007Sdelphij
3475197007Sdelphij	fetch_decode_modrm(emu);
3476197007Sdelphij	destval = decode_and_fetch_byte(emu);
3477204934Sdelphij	destval = (*opcD0_byte_operation[emu->cur_rh])
3478204934Sdelphij	    (emu, destval, emu->x86.R_CL);
3479197007Sdelphij	write_back_byte(emu, destval);
3480197007Sdelphij}
3481197007Sdelphij
3482197007Sdelphij/*
3483197007Sdelphij * REMARKS:
3484197007Sdelphij * Handles opcode 0xd3
3485197007Sdelphij */
3486197007Sdelphijstatic void
3487197007Sdelphijx86emuOp_opcD3_word_RM_CL(struct x86emu *emu)
3488197007Sdelphij{
3489197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3490197007Sdelphij		uint32_t destval;
3491197007Sdelphij
3492197007Sdelphij		fetch_decode_modrm(emu);
3493197007Sdelphij		destval = decode_and_fetch_long(emu);
3494204934Sdelphij		destval = (*opcD1_long_operation[emu->cur_rh])
3495204934Sdelphij		    (emu, destval, emu->x86.R_CL);
3496197007Sdelphij		write_back_long(emu, destval);
3497197007Sdelphij	} else {
3498197007Sdelphij		uint16_t destval;
3499197007Sdelphij
3500197007Sdelphij		fetch_decode_modrm(emu);
3501197007Sdelphij		destval = decode_and_fetch_word(emu);
3502204934Sdelphij		destval = (*opcD1_word_operation[emu->cur_rh])
3503204934Sdelphij		    (emu, destval, emu->x86.R_CL);
3504197007Sdelphij		write_back_word(emu, destval);
3505197007Sdelphij	}
3506197007Sdelphij}
3507197007Sdelphij
3508197007Sdelphij/*
3509197007Sdelphij * REMARKS:
3510197007Sdelphij * Handles opcode 0xd4
3511197007Sdelphij */
3512197007Sdelphijstatic void
3513197007Sdelphijx86emuOp_aam(struct x86emu *emu)
3514197007Sdelphij{
3515197007Sdelphij	uint8_t a;
3516197007Sdelphij
3517197007Sdelphij	a = fetch_byte_imm(emu);	/* this is a stupid encoding. */
3518197007Sdelphij	if (a != 10) {
3519197007Sdelphij		/* fix: add base decoding aam_word(uint8_t val, int base a) */
3520197007Sdelphij		x86emu_halt_sys(emu);
3521197007Sdelphij	}
3522197007Sdelphij	/* note the type change here --- returning AL and AH in AX. */
3523197007Sdelphij	emu->x86.R_AX = aam_word(emu, emu->x86.R_AL);
3524197007Sdelphij}
3525197007Sdelphij
3526197007Sdelphij/*
3527197007Sdelphij * REMARKS:
3528197007Sdelphij * Handles opcode 0xd5
3529197007Sdelphij */
3530197007Sdelphijstatic void
3531197007Sdelphijx86emuOp_aad(struct x86emu *emu)
3532197007Sdelphij{
3533197007Sdelphij	uint8_t a;
3534197007Sdelphij
3535197007Sdelphij	a = fetch_byte_imm(emu);
3536197007Sdelphij	if (a != 10) {
3537197007Sdelphij		/* fix: add base decoding aad_word(uint16_t val, int base a) */
3538197007Sdelphij		x86emu_halt_sys(emu);
3539197007Sdelphij	}
3540197007Sdelphij	emu->x86.R_AX = aad_word(emu, emu->x86.R_AX);
3541197007Sdelphij}
3542197007Sdelphij/* opcode 0xd6 ILLEGAL OPCODE */
3543197007Sdelphij
3544197007Sdelphij
3545197007Sdelphij/*
3546197007Sdelphij * REMARKS:
3547197007Sdelphij * Handles opcode 0xd7
3548197007Sdelphij */
3549197007Sdelphijstatic void
3550197007Sdelphijx86emuOp_xlat(struct x86emu *emu)
3551197007Sdelphij{
3552197007Sdelphij	uint16_t addr;
3553197007Sdelphij
3554197007Sdelphij	addr = (uint16_t) (emu->x86.R_BX + (uint8_t) emu->x86.R_AL);
3555197007Sdelphij	emu->x86.R_AL = fetch_data_byte(emu, addr);
3556197007Sdelphij}
3557197007Sdelphij
3558197007Sdelphij/* opcode=0xd8 */
3559197007Sdelphijstatic void
3560197007Sdelphijx86emuOp_esc_coprocess_d8(struct x86emu *emu)
3561197007Sdelphij{
3562197007Sdelphij}
3563197007Sdelphij/* opcode=0xd9 */
3564197007Sdelphijstatic void
3565197007Sdelphijx86emuOp_esc_coprocess_d9(struct x86emu *emu)
3566197007Sdelphij{
3567197007Sdelphij	fetch_decode_modrm(emu);
3568197007Sdelphij	if (emu->cur_mod != 3)
3569197007Sdelphij		decode_rl_address(emu);
3570197007Sdelphij}
3571197007Sdelphij/* opcode=0xda */
3572197007Sdelphijstatic void
3573197007Sdelphijx86emuOp_esc_coprocess_da(struct x86emu *emu)
3574197007Sdelphij{
3575197007Sdelphij	fetch_decode_modrm(emu);
3576197007Sdelphij	if (emu->cur_mod != 3)
3577197007Sdelphij		decode_rl_address(emu);
3578197007Sdelphij}
3579197007Sdelphij/* opcode=0xdb */
3580197007Sdelphijstatic void
3581197007Sdelphijx86emuOp_esc_coprocess_db(struct x86emu *emu)
3582197007Sdelphij{
3583197007Sdelphij	fetch_decode_modrm(emu);
3584197007Sdelphij	if (emu->cur_mod != 3)
3585197007Sdelphij		decode_rl_address(emu);
3586197007Sdelphij}
3587197007Sdelphij/* opcode=0xdc */
3588197007Sdelphijstatic void
3589197007Sdelphijx86emuOp_esc_coprocess_dc(struct x86emu *emu)
3590197007Sdelphij{
3591197007Sdelphij	fetch_decode_modrm(emu);
3592197007Sdelphij	if (emu->cur_mod != 3)
3593197007Sdelphij		decode_rl_address(emu);
3594197007Sdelphij}
3595197007Sdelphij/* opcode=0xdd */
3596197007Sdelphijstatic void
3597197007Sdelphijx86emuOp_esc_coprocess_dd(struct x86emu *emu)
3598197007Sdelphij{
3599197007Sdelphij	fetch_decode_modrm(emu);
3600197007Sdelphij	if (emu->cur_mod != 3)
3601197007Sdelphij		decode_rl_address(emu);
3602197007Sdelphij}
3603197007Sdelphij/* opcode=0xde */
3604197007Sdelphijstatic void
3605197007Sdelphijx86emuOp_esc_coprocess_de(struct x86emu *emu)
3606197007Sdelphij{
3607197007Sdelphij	fetch_decode_modrm(emu);
3608197007Sdelphij	if (emu->cur_mod != 3)
3609197007Sdelphij		decode_rl_address(emu);
3610197007Sdelphij}
3611197007Sdelphij/* opcode=0xdf */
3612197007Sdelphijstatic void
3613197007Sdelphijx86emuOp_esc_coprocess_df(struct x86emu *emu)
3614197007Sdelphij{
3615197007Sdelphij	fetch_decode_modrm(emu);
3616197007Sdelphij	if (emu->cur_mod != 3)
3617197007Sdelphij		decode_rl_address(emu);
3618197007Sdelphij}
3619197007Sdelphij
3620197007Sdelphij
3621197007Sdelphij/*
3622197007Sdelphij * REMARKS:
3623197007Sdelphij * Handles opcode 0xe0
3624197007Sdelphij */
3625197007Sdelphijstatic void
3626197007Sdelphijx86emuOp_loopne(struct x86emu *emu)
3627197007Sdelphij{
3628197007Sdelphij	int16_t ip;
3629197007Sdelphij
3630197007Sdelphij	ip = (int8_t) fetch_byte_imm(emu);
3631197007Sdelphij	ip += (int16_t) emu->x86.R_IP;
3632197007Sdelphij	emu->x86.R_CX -= 1;
3633197007Sdelphij	if (emu->x86.R_CX != 0 && !ACCESS_FLAG(F_ZF))	/* CX != 0 and !ZF */
3634197007Sdelphij		emu->x86.R_IP = ip;
3635197007Sdelphij}
3636197007Sdelphij
3637197007Sdelphij/*
3638197007Sdelphij * REMARKS:
3639197007Sdelphij * Handles opcode 0xe1
3640197007Sdelphij */
3641197007Sdelphijstatic void
3642197007Sdelphijx86emuOp_loope(struct x86emu *emu)
3643197007Sdelphij{
3644197007Sdelphij	int16_t ip;
3645197007Sdelphij
3646197007Sdelphij	ip = (int8_t) fetch_byte_imm(emu);
3647197007Sdelphij	ip += (int16_t) emu->x86.R_IP;
3648197007Sdelphij	emu->x86.R_CX -= 1;
3649197007Sdelphij	if (emu->x86.R_CX != 0 && ACCESS_FLAG(F_ZF))	/* CX != 0 and ZF */
3650197007Sdelphij		emu->x86.R_IP = ip;
3651197007Sdelphij}
3652197007Sdelphij
3653197007Sdelphij/*
3654197007Sdelphij * REMARKS:
3655197007Sdelphij * Handles opcode 0xe2
3656197007Sdelphij */
3657197007Sdelphijstatic void
3658197007Sdelphijx86emuOp_loop(struct x86emu *emu)
3659197007Sdelphij{
3660197007Sdelphij	int16_t ip;
3661197007Sdelphij
3662197007Sdelphij	ip = (int8_t) fetch_byte_imm(emu);
3663197007Sdelphij	ip += (int16_t) emu->x86.R_IP;
3664197007Sdelphij	emu->x86.R_CX -= 1;
3665197007Sdelphij	if (emu->x86.R_CX != 0)
3666197007Sdelphij		emu->x86.R_IP = ip;
3667197007Sdelphij}
3668197007Sdelphij
3669197007Sdelphij/*
3670197007Sdelphij * REMARKS:
3671197007Sdelphij * Handles opcode 0xe3
3672197007Sdelphij */
3673197007Sdelphijstatic void
3674197007Sdelphijx86emuOp_jcxz(struct x86emu *emu)
3675197007Sdelphij{
3676197007Sdelphij	uint16_t target;
3677197007Sdelphij	int8_t offset;
3678197007Sdelphij
3679197007Sdelphij	/* jump to byte offset if overflow flag is set */
3680197007Sdelphij	offset = (int8_t) fetch_byte_imm(emu);
3681197007Sdelphij	target = (uint16_t) (emu->x86.R_IP + offset);
3682197007Sdelphij	if (emu->x86.R_CX == 0)
3683197007Sdelphij		emu->x86.R_IP = target;
3684197007Sdelphij}
3685197007Sdelphij
3686197007Sdelphij/*
3687197007Sdelphij * REMARKS:
3688197007Sdelphij * Handles opcode 0xe4
3689197007Sdelphij */
3690197007Sdelphijstatic void
3691197007Sdelphijx86emuOp_in_byte_AL_IMM(struct x86emu *emu)
3692197007Sdelphij{
3693197007Sdelphij	uint8_t port;
3694197007Sdelphij
3695197007Sdelphij	port = (uint8_t) fetch_byte_imm(emu);
3696197007Sdelphij	emu->x86.R_AL = (*emu->emu_inb) (emu, port);
3697197007Sdelphij}
3698197007Sdelphij
3699197007Sdelphij/*
3700197007Sdelphij * REMARKS:
3701197007Sdelphij * Handles opcode 0xe5
3702197007Sdelphij */
3703197007Sdelphijstatic void
3704197007Sdelphijx86emuOp_in_word_AX_IMM(struct x86emu *emu)
3705197007Sdelphij{
3706197007Sdelphij	uint8_t port;
3707197007Sdelphij
3708197007Sdelphij	port = (uint8_t) fetch_byte_imm(emu);
3709197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3710197007Sdelphij		emu->x86.R_EAX = (*emu->emu_inl) (emu, port);
3711197007Sdelphij	} else {
3712197007Sdelphij		emu->x86.R_AX = (*emu->emu_inw) (emu, port);
3713197007Sdelphij	}
3714197007Sdelphij}
3715197007Sdelphij
3716197007Sdelphij/*
3717197007Sdelphij * REMARKS:
3718197007Sdelphij * Handles opcode 0xe6
3719197007Sdelphij */
3720197007Sdelphijstatic void
3721197007Sdelphijx86emuOp_out_byte_IMM_AL(struct x86emu *emu)
3722197007Sdelphij{
3723197007Sdelphij	uint8_t port;
3724197007Sdelphij
3725197007Sdelphij	port = (uint8_t) fetch_byte_imm(emu);
3726197007Sdelphij	(*emu->emu_outb) (emu, port, emu->x86.R_AL);
3727197007Sdelphij}
3728197007Sdelphij
3729197007Sdelphij/*
3730197007Sdelphij * REMARKS:
3731197007Sdelphij * Handles opcode 0xe7
3732197007Sdelphij */
3733197007Sdelphijstatic void
3734197007Sdelphijx86emuOp_out_word_IMM_AX(struct x86emu *emu)
3735197007Sdelphij{
3736197007Sdelphij	uint8_t port;
3737197007Sdelphij
3738197007Sdelphij	port = (uint8_t) fetch_byte_imm(emu);
3739197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3740197007Sdelphij		(*emu->emu_outl) (emu, port, emu->x86.R_EAX);
3741197007Sdelphij	} else {
3742197007Sdelphij		(*emu->emu_outw) (emu, port, emu->x86.R_AX);
3743197007Sdelphij	}
3744197007Sdelphij}
3745197007Sdelphij
3746197007Sdelphij/*
3747197007Sdelphij * REMARKS:
3748197007Sdelphij * Handles opcode 0xe8
3749197007Sdelphij */
3750197007Sdelphijstatic void
3751197007Sdelphijx86emuOp_call_near_IMM(struct x86emu *emu)
3752197007Sdelphij{
3753197007Sdelphij	int16_t ip;
3754197007Sdelphij
3755197007Sdelphij	ip = (int16_t) fetch_word_imm(emu);
3756197007Sdelphij	ip += (int16_t) emu->x86.R_IP;	/* CHECK SIGN */
3757197007Sdelphij	push_word(emu, emu->x86.R_IP);
3758197007Sdelphij	emu->x86.R_IP = ip;
3759197007Sdelphij}
3760197007Sdelphij
3761197007Sdelphij/*
3762197007Sdelphij * REMARKS:
3763197007Sdelphij * Handles opcode 0xe9
3764197007Sdelphij */
3765197007Sdelphijstatic void
3766197007Sdelphijx86emuOp_jump_near_IMM(struct x86emu *emu)
3767197007Sdelphij{
3768197007Sdelphij	int ip;
3769197007Sdelphij
3770197007Sdelphij	ip = (int16_t) fetch_word_imm(emu);
3771197007Sdelphij	ip += (int16_t) emu->x86.R_IP;
3772197007Sdelphij	emu->x86.R_IP = (uint16_t) ip;
3773197007Sdelphij}
3774197007Sdelphij
3775197007Sdelphij/*
3776197007Sdelphij * REMARKS:
3777197007Sdelphij * Handles opcode 0xea
3778197007Sdelphij */
3779197007Sdelphijstatic void
3780197007Sdelphijx86emuOp_jump_far_IMM(struct x86emu *emu)
3781197007Sdelphij{
3782197007Sdelphij	uint16_t cs, ip;
3783197007Sdelphij
3784197007Sdelphij	ip = fetch_word_imm(emu);
3785197007Sdelphij	cs = fetch_word_imm(emu);
3786197007Sdelphij	emu->x86.R_IP = ip;
3787197007Sdelphij	emu->x86.R_CS = cs;
3788197007Sdelphij}
3789197007Sdelphij
3790197007Sdelphij/*
3791197007Sdelphij * REMARKS:
3792197007Sdelphij * Handles opcode 0xeb
3793197007Sdelphij */
3794197007Sdelphijstatic void
3795197007Sdelphijx86emuOp_jump_byte_IMM(struct x86emu *emu)
3796197007Sdelphij{
3797197007Sdelphij	uint16_t target;
3798197007Sdelphij	int8_t offset;
3799197007Sdelphij
3800197007Sdelphij	offset = (int8_t) fetch_byte_imm(emu);
3801197007Sdelphij	target = (uint16_t) (emu->x86.R_IP + offset);
3802197007Sdelphij	emu->x86.R_IP = target;
3803197007Sdelphij}
3804197007Sdelphij
3805197007Sdelphij/*
3806197007Sdelphij * REMARKS:
3807197007Sdelphij * Handles opcode 0xec
3808197007Sdelphij */
3809197007Sdelphijstatic void
3810197007Sdelphijx86emuOp_in_byte_AL_DX(struct x86emu *emu)
3811197007Sdelphij{
3812197007Sdelphij	emu->x86.R_AL = (*emu->emu_inb) (emu, emu->x86.R_DX);
3813197007Sdelphij}
3814197007Sdelphij
3815197007Sdelphij/*
3816197007Sdelphij * REMARKS:
3817197007Sdelphij * Handles opcode 0xed
3818197007Sdelphij */
3819197007Sdelphijstatic void
3820197007Sdelphijx86emuOp_in_word_AX_DX(struct x86emu *emu)
3821197007Sdelphij{
3822197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3823197007Sdelphij		emu->x86.R_EAX = (*emu->emu_inl) (emu, emu->x86.R_DX);
3824197007Sdelphij	} else {
3825197007Sdelphij		emu->x86.R_AX = (*emu->emu_inw) (emu, emu->x86.R_DX);
3826197007Sdelphij	}
3827197007Sdelphij}
3828197007Sdelphij
3829197007Sdelphij/*
3830197007Sdelphij * REMARKS:
3831197007Sdelphij * Handles opcode 0xee
3832197007Sdelphij */
3833197007Sdelphijstatic void
3834197007Sdelphijx86emuOp_out_byte_DX_AL(struct x86emu *emu)
3835197007Sdelphij{
3836197007Sdelphij	(*emu->emu_outb) (emu, emu->x86.R_DX, emu->x86.R_AL);
3837197007Sdelphij}
3838197007Sdelphij
3839197007Sdelphij/*
3840197007Sdelphij * REMARKS:
3841197007Sdelphij * Handles opcode 0xef
3842197007Sdelphij */
3843197007Sdelphijstatic void
3844197007Sdelphijx86emuOp_out_word_DX_AX(struct x86emu *emu)
3845197007Sdelphij{
3846197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3847197007Sdelphij		(*emu->emu_outl) (emu, emu->x86.R_DX, emu->x86.R_EAX);
3848197007Sdelphij	} else {
3849197007Sdelphij		(*emu->emu_outw) (emu, emu->x86.R_DX, emu->x86.R_AX);
3850197007Sdelphij	}
3851197007Sdelphij}
3852197007Sdelphij
3853197007Sdelphij/*
3854197007Sdelphij * REMARKS:
3855197007Sdelphij * Handles opcode 0xf0
3856197007Sdelphij */
3857197007Sdelphijstatic void
3858197007Sdelphijx86emuOp_lock(struct x86emu *emu)
3859197007Sdelphij{
3860197007Sdelphij}
3861197007Sdelphij/*opcode 0xf1 ILLEGAL OPERATION */
3862197007Sdelphij
3863197007Sdelphij
3864197007Sdelphij/*
3865197007Sdelphij * REMARKS:
3866197007Sdelphij * Handles opcode 0xf5
3867197007Sdelphij */
3868197007Sdelphijstatic void
3869197007Sdelphijx86emuOp_cmc(struct x86emu *emu)
3870197007Sdelphij{
3871197007Sdelphij	if (ACCESS_FLAG(F_CF))
3872197007Sdelphij		CLEAR_FLAG(F_CF);
3873197007Sdelphij	else
3874197007Sdelphij		SET_FLAG(F_CF);
3875197007Sdelphij}
3876197007Sdelphij
3877197007Sdelphij/*
3878197007Sdelphij * REMARKS:
3879197007Sdelphij * Handles opcode 0xf6
3880197007Sdelphij */
3881197007Sdelphijstatic void
3882197007Sdelphijx86emuOp_opcF6_byte_RM(struct x86emu *emu)
3883197007Sdelphij{
3884197007Sdelphij	uint8_t destval, srcval;
3885197007Sdelphij
3886197007Sdelphij	/* long, drawn out code follows.  Double switch for a total of 32
3887197007Sdelphij	 * cases.  */
3888197007Sdelphij	fetch_decode_modrm(emu);
3889197007Sdelphij	if (emu->cur_rh == 1)
3890197007Sdelphij		x86emu_halt_sys(emu);
3891197007Sdelphij
3892197007Sdelphij	if (emu->cur_rh == 0) {
3893197007Sdelphij		destval = decode_and_fetch_byte_imm8(emu, &srcval);
3894197007Sdelphij		test_byte(emu, destval, srcval);
3895197007Sdelphij		return;
3896197007Sdelphij	}
3897197007Sdelphij	destval = decode_and_fetch_byte(emu);
3898197007Sdelphij	switch (emu->cur_rh) {
3899197007Sdelphij	case 2:
3900197007Sdelphij		destval = ~destval;
3901197007Sdelphij		write_back_byte(emu, destval);
3902197007Sdelphij		break;
3903197007Sdelphij	case 3:
3904197007Sdelphij		destval = neg_byte(emu, destval);
3905197007Sdelphij		write_back_byte(emu, destval);
3906197007Sdelphij		break;
3907197007Sdelphij	case 4:
3908197007Sdelphij		mul_byte(emu, destval);
3909197007Sdelphij		break;
3910197007Sdelphij	case 5:
3911197007Sdelphij		imul_byte(emu, destval);
3912197007Sdelphij		break;
3913197007Sdelphij	case 6:
3914197007Sdelphij		div_byte(emu, destval);
3915197007Sdelphij		break;
3916197007Sdelphij	case 7:
3917197007Sdelphij		idiv_byte(emu, destval);
3918197007Sdelphij		break;
3919197007Sdelphij	}
3920197007Sdelphij}
3921197007Sdelphij
3922197007Sdelphij/*
3923197007Sdelphij * REMARKS:
3924197007Sdelphij * Handles opcode 0xf7
3925197007Sdelphij */
3926197007Sdelphijstatic void
3927197007Sdelphijx86emuOp32_opcF7_word_RM(struct x86emu *emu)
3928197007Sdelphij{
3929197007Sdelphij	uint32_t destval, srcval;
3930197007Sdelphij
3931197007Sdelphij	/* long, drawn out code follows.  Double switch for a total of 32
3932197007Sdelphij	 * cases.  */
3933197007Sdelphij	fetch_decode_modrm(emu);
3934197007Sdelphij	if (emu->cur_rh == 1)
3935197007Sdelphij		x86emu_halt_sys(emu);
3936197007Sdelphij
3937197007Sdelphij	if (emu->cur_rh == 0) {
3938197007Sdelphij		if (emu->cur_mod != 3) {
3939197007Sdelphij			uint32_t destoffset;
3940197007Sdelphij
3941197007Sdelphij			destoffset = decode_rl_address(emu);
3942197007Sdelphij			srcval = fetch_long_imm(emu);
3943197007Sdelphij			destval = fetch_data_long(emu, destoffset);
3944197007Sdelphij		} else {
3945197007Sdelphij			srcval = fetch_long_imm(emu);
3946197007Sdelphij			destval = *decode_rl_long_register(emu);
3947197007Sdelphij		}
3948197007Sdelphij		test_long(emu, destval, srcval);
3949197007Sdelphij		return;
3950197007Sdelphij	}
3951197007Sdelphij	destval = decode_and_fetch_long(emu);
3952197007Sdelphij	switch (emu->cur_rh) {
3953197007Sdelphij	case 2:
3954197007Sdelphij		destval = ~destval;
3955197007Sdelphij		write_back_long(emu, destval);
3956197007Sdelphij		break;
3957197007Sdelphij	case 3:
3958197007Sdelphij		destval = neg_long(emu, destval);
3959197007Sdelphij		write_back_long(emu, destval);
3960197007Sdelphij		break;
3961197007Sdelphij	case 4:
3962197007Sdelphij		mul_long(emu, destval);
3963197007Sdelphij		break;
3964197007Sdelphij	case 5:
3965197007Sdelphij		imul_long(emu, destval);
3966197007Sdelphij		break;
3967197007Sdelphij	case 6:
3968197007Sdelphij		div_long(emu, destval);
3969197007Sdelphij		break;
3970197007Sdelphij	case 7:
3971197007Sdelphij		idiv_long(emu, destval);
3972197007Sdelphij		break;
3973197007Sdelphij	}
3974197007Sdelphij}
3975197007Sdelphijstatic void
3976197007Sdelphijx86emuOp16_opcF7_word_RM(struct x86emu *emu)
3977197007Sdelphij{
3978197007Sdelphij	uint16_t destval, srcval;
3979197007Sdelphij
3980197007Sdelphij	/* long, drawn out code follows.  Double switch for a total of 32
3981197007Sdelphij	 * cases.  */
3982197007Sdelphij	fetch_decode_modrm(emu);
3983197007Sdelphij	if (emu->cur_rh == 1)
3984197007Sdelphij		x86emu_halt_sys(emu);
3985197007Sdelphij
3986197007Sdelphij	if (emu->cur_rh == 0) {
3987197007Sdelphij		if (emu->cur_mod != 3) {
3988197007Sdelphij			uint32_t destoffset;
3989197007Sdelphij
3990197007Sdelphij			destoffset = decode_rl_address(emu);
3991197007Sdelphij			srcval = fetch_word_imm(emu);
3992197007Sdelphij			destval = fetch_data_word(emu, destoffset);
3993197007Sdelphij		} else {
3994197007Sdelphij			srcval = fetch_word_imm(emu);
3995197007Sdelphij			destval = *decode_rl_word_register(emu);
3996197007Sdelphij		}
3997197007Sdelphij		test_word(emu, destval, srcval);
3998197007Sdelphij		return;
3999197007Sdelphij	}
4000197007Sdelphij	destval = decode_and_fetch_word(emu);
4001197007Sdelphij	switch (emu->cur_rh) {
4002197007Sdelphij	case 2:
4003197007Sdelphij		destval = ~destval;
4004197007Sdelphij		write_back_word(emu, destval);
4005197007Sdelphij		break;
4006197007Sdelphij	case 3:
4007197007Sdelphij		destval = neg_word(emu, destval);
4008197007Sdelphij		write_back_word(emu, destval);
4009197007Sdelphij		break;
4010197007Sdelphij	case 4:
4011197007Sdelphij		mul_word(emu, destval);
4012197007Sdelphij		break;
4013197007Sdelphij	case 5:
4014197007Sdelphij		imul_word(emu, destval);
4015197007Sdelphij		break;
4016197007Sdelphij	case 6:
4017197007Sdelphij		div_word(emu, destval);
4018197007Sdelphij		break;
4019197007Sdelphij	case 7:
4020197007Sdelphij		idiv_word(emu, destval);
4021197007Sdelphij		break;
4022197007Sdelphij	}
4023197007Sdelphij}
4024197007Sdelphijstatic void
4025197007Sdelphijx86emuOp_opcF7_word_RM(struct x86emu *emu)
4026197007Sdelphij{
4027197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4028197007Sdelphij		x86emuOp32_opcF7_word_RM(emu);
4029197007Sdelphij	else
4030197007Sdelphij		x86emuOp16_opcF7_word_RM(emu);
4031197007Sdelphij}
4032197007Sdelphij
4033197007Sdelphij/*
4034197007Sdelphij * REMARKS:
4035197007Sdelphij * Handles opcode 0xfe
4036197007Sdelphij */
4037197007Sdelphijstatic void
4038197007Sdelphijx86emuOp_opcFE_byte_RM(struct x86emu *emu)
4039197007Sdelphij{
4040197007Sdelphij	uint8_t destval;
4041197007Sdelphij	uint32_t destoffset;
4042197007Sdelphij	uint8_t *destreg;
4043197007Sdelphij
4044197007Sdelphij	/* Yet another special case instruction. */
4045197007Sdelphij	fetch_decode_modrm(emu);
4046197007Sdelphij	if (emu->cur_mod != 3) {
4047197007Sdelphij		destoffset = decode_rl_address(emu);
4048197007Sdelphij		switch (emu->cur_rh) {
4049197007Sdelphij		case 0:	/* inc word ptr ... */
4050197007Sdelphij			destval = fetch_data_byte(emu, destoffset);
4051197007Sdelphij			destval = inc_byte(emu, destval);
4052197007Sdelphij			store_data_byte(emu, destoffset, destval);
4053197007Sdelphij			break;
4054197007Sdelphij		case 1:	/* dec word ptr ... */
4055197007Sdelphij			destval = fetch_data_byte(emu, destoffset);
4056197007Sdelphij			destval = dec_byte(emu, destval);
4057197007Sdelphij			store_data_byte(emu, destoffset, destval);
4058197007Sdelphij			break;
4059197007Sdelphij		}
4060197007Sdelphij	} else {
4061197007Sdelphij		destreg = decode_rl_byte_register(emu);
4062197007Sdelphij		switch (emu->cur_rh) {
4063197007Sdelphij		case 0:
4064197007Sdelphij			*destreg = inc_byte(emu, *destreg);
4065197007Sdelphij			break;
4066197007Sdelphij		case 1:
4067197007Sdelphij			*destreg = dec_byte(emu, *destreg);
4068197007Sdelphij			break;
4069197007Sdelphij		}
4070197007Sdelphij	}
4071197007Sdelphij}
4072197007Sdelphij
4073197007Sdelphij/*
4074197007Sdelphij * REMARKS:
4075197007Sdelphij * Handles opcode 0xff
4076197007Sdelphij */
4077197007Sdelphijstatic void
4078197007Sdelphijx86emuOp32_opcFF_word_RM(struct x86emu *emu)
4079197007Sdelphij{
4080197007Sdelphij	uint32_t destoffset = 0;
4081197007Sdelphij	uint32_t destval, *destreg;
4082197007Sdelphij
4083197007Sdelphij	if (emu->cur_mod != 3) {
4084197007Sdelphij		destoffset = decode_rl_address(emu);
4085197007Sdelphij		destval = fetch_data_long(emu, destoffset);
4086197007Sdelphij		switch (emu->cur_rh) {
4087197007Sdelphij		case 0:	/* inc word ptr ... */
4088197007Sdelphij			destval = inc_long(emu, destval);
4089197007Sdelphij			store_data_long(emu, destoffset, destval);
4090197007Sdelphij			break;
4091197007Sdelphij		case 1:	/* dec word ptr ... */
4092197007Sdelphij			destval = dec_long(emu, destval);
4093197007Sdelphij			store_data_long(emu, destoffset, destval);
4094197007Sdelphij			break;
4095197007Sdelphij		case 6:	/* push word ptr ... */
4096197007Sdelphij			push_long(emu, destval);
4097197007Sdelphij			break;
4098197007Sdelphij		}
4099197007Sdelphij	} else {
4100197007Sdelphij		destreg = decode_rl_long_register(emu);
4101197007Sdelphij		switch (emu->cur_rh) {
4102197007Sdelphij		case 0:
4103197007Sdelphij			*destreg = inc_long(emu, *destreg);
4104197007Sdelphij			break;
4105197007Sdelphij		case 1:
4106197007Sdelphij			*destreg = dec_long(emu, *destreg);
4107197007Sdelphij			break;
4108197007Sdelphij		case 6:
4109197007Sdelphij			push_long(emu, *destreg);
4110197007Sdelphij			break;
4111197007Sdelphij		}
4112197007Sdelphij	}
4113197007Sdelphij}
4114197007Sdelphij
4115197007Sdelphijstatic void
4116197007Sdelphijx86emuOp16_opcFF_word_RM(struct x86emu *emu)
4117197007Sdelphij{
4118197007Sdelphij	uint32_t destoffset = 0;
4119197007Sdelphij	uint16_t *destreg;
4120197007Sdelphij	uint16_t destval;
4121197007Sdelphij
4122197007Sdelphij	if (emu->cur_mod != 3) {
4123197007Sdelphij		destoffset = decode_rl_address(emu);
4124197007Sdelphij		destval = fetch_data_word(emu, destoffset);
4125197007Sdelphij		switch (emu->cur_rh) {
4126197007Sdelphij		case 0:
4127197007Sdelphij			destval = inc_word(emu, destval);
4128197007Sdelphij			store_data_word(emu, destoffset, destval);
4129197007Sdelphij			break;
4130197007Sdelphij		case 1:	/* dec word ptr ... */
4131197007Sdelphij			destval = dec_word(emu, destval);
4132197007Sdelphij			store_data_word(emu, destoffset, destval);
4133197007Sdelphij			break;
4134197007Sdelphij		case 6:	/* push word ptr ... */
4135197007Sdelphij			push_word(emu, destval);
4136197007Sdelphij			break;
4137197007Sdelphij		}
4138197007Sdelphij	} else {
4139197007Sdelphij		destreg = decode_rl_word_register(emu);
4140197007Sdelphij		switch (emu->cur_rh) {
4141197007Sdelphij		case 0:
4142197007Sdelphij			*destreg = inc_word(emu, *destreg);
4143197007Sdelphij			break;
4144197007Sdelphij		case 1:
4145197007Sdelphij			*destreg = dec_word(emu, *destreg);
4146197007Sdelphij			break;
4147197007Sdelphij		case 6:
4148197007Sdelphij			push_word(emu, *destreg);
4149197007Sdelphij			break;
4150197007Sdelphij		}
4151197007Sdelphij	}
4152197007Sdelphij}
4153197007Sdelphij
4154197007Sdelphijstatic void
4155197007Sdelphijx86emuOp_opcFF_word_RM(struct x86emu *emu)
4156197007Sdelphij{
4157197007Sdelphij	uint32_t destoffset = 0;
4158197007Sdelphij	uint16_t destval, destval2;
4159197007Sdelphij
4160197007Sdelphij	/* Yet another special case instruction. */
4161197007Sdelphij	fetch_decode_modrm(emu);
4162204934Sdelphij	if ((emu->cur_mod == 3 && (emu->cur_rh == 3 || emu->cur_rh == 5)) ||
4163204934Sdelphij	    emu->cur_rh == 7)
4164197007Sdelphij		x86emu_halt_sys(emu);
4165197007Sdelphij	if (emu->cur_rh == 0 || emu->cur_rh == 1 || emu->cur_rh == 6) {
4166197007Sdelphij		if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4167197007Sdelphij			x86emuOp32_opcFF_word_RM(emu);
4168197007Sdelphij		else
4169197007Sdelphij			x86emuOp16_opcFF_word_RM(emu);
4170197007Sdelphij		return;
4171197007Sdelphij	}
4172197007Sdelphij
4173197007Sdelphij	if (emu->cur_mod != 3) {
4174197007Sdelphij		destoffset = decode_rl_address(emu);
4175197007Sdelphij		destval = fetch_data_word(emu, destoffset);
4176197007Sdelphij		switch (emu->cur_rh) {
4177197007Sdelphij		case 3:	/* call far ptr ... */
4178197007Sdelphij			destval2 = fetch_data_word(emu, destoffset + 2);
4179197007Sdelphij			push_word(emu, emu->x86.R_CS);
4180197007Sdelphij			emu->x86.R_CS = destval2;
4181197007Sdelphij			push_word(emu, emu->x86.R_IP);
4182197007Sdelphij			emu->x86.R_IP = destval;
4183197007Sdelphij			break;
4184197007Sdelphij		case 5:	/* jmp far ptr ... */
4185197007Sdelphij			destval2 = fetch_data_word(emu, destoffset + 2);
4186197007Sdelphij			emu->x86.R_IP = destval;
4187197007Sdelphij			emu->x86.R_CS = destval2;
4188197007Sdelphij			break;
4189197007Sdelphij		}
4190197007Sdelphij	} else {
4191197007Sdelphij		destval = *decode_rl_word_register(emu);
4192197007Sdelphij	}
4193197007Sdelphij
4194197007Sdelphij	switch (emu->cur_rh) {
4195197007Sdelphij	case 2: /* call word ptr */
4196197007Sdelphij		push_word(emu, emu->x86.R_IP);
4197197007Sdelphij		emu->x86.R_IP = destval;
4198197007Sdelphij		break;
4199197007Sdelphij	case 4: /* jmp */
4200197007Sdelphij		emu->x86.R_IP = destval;
4201197007Sdelphij		break;
4202197007Sdelphij	}
4203197007Sdelphij}
4204197007Sdelphij
4205197007Sdelphij/*
4206197007Sdelphij *  * Single byte operation code table:
4207197007Sdelphij */
4208197007Sdelphijstatic void
4209197007Sdelphijx86emu_exec_one_byte(struct x86emu * emu)
4210197007Sdelphij{
4211197007Sdelphij	uint8_t op1;
4212197007Sdelphij
4213197007Sdelphij	op1 = fetch_byte_imm(emu);
4214197007Sdelphij
4215197007Sdelphij	switch (op1) {
4216197007Sdelphij	case 0x00:
4217197007Sdelphij		common_binop_byte_rm_r(emu, add_byte);
4218197007Sdelphij		break;
4219197007Sdelphij	case 0x01:
4220197007Sdelphij		common_binop_word_long_rm_r(emu, add_word, add_long);
4221197007Sdelphij		break;
4222197007Sdelphij	case 0x02:
4223197007Sdelphij		common_binop_byte_r_rm(emu, add_byte);
4224197007Sdelphij		break;
4225197007Sdelphij	case 0x03:
4226197007Sdelphij		common_binop_word_long_r_rm(emu, add_word, add_long);
4227197007Sdelphij		break;
4228197007Sdelphij	case 0x04:
4229197007Sdelphij		common_binop_byte_imm(emu, add_byte);
4230197007Sdelphij		break;
4231197007Sdelphij	case 0x05:
4232197007Sdelphij		common_binop_word_long_imm(emu, add_word, add_long);
4233197007Sdelphij		break;
4234197007Sdelphij	case 0x06:
4235197007Sdelphij		push_word(emu, emu->x86.R_ES);
4236197007Sdelphij		break;
4237197007Sdelphij	case 0x07:
4238197007Sdelphij		emu->x86.R_ES = pop_word(emu);
4239197007Sdelphij		break;
4240197007Sdelphij
4241197007Sdelphij	case 0x08:
4242197007Sdelphij		common_binop_byte_rm_r(emu, or_byte);
4243197007Sdelphij		break;
4244197007Sdelphij	case 0x09:
4245197007Sdelphij		common_binop_word_long_rm_r(emu, or_word, or_long);
4246197007Sdelphij		break;
4247197007Sdelphij	case 0x0a:
4248197007Sdelphij		common_binop_byte_r_rm(emu, or_byte);
4249197007Sdelphij		break;
4250197007Sdelphij	case 0x0b:
4251197007Sdelphij		common_binop_word_long_r_rm(emu, or_word, or_long);
4252197007Sdelphij		break;
4253197007Sdelphij	case 0x0c:
4254197007Sdelphij		common_binop_byte_imm(emu, or_byte);
4255197007Sdelphij		break;
4256197007Sdelphij	case 0x0d:
4257197007Sdelphij		common_binop_word_long_imm(emu, or_word, or_long);
4258197007Sdelphij		break;
4259197007Sdelphij	case 0x0e:
4260197007Sdelphij		push_word(emu, emu->x86.R_CS);
4261197007Sdelphij		break;
4262197007Sdelphij	case 0x0f:
4263197007Sdelphij		x86emu_exec_two_byte(emu);
4264197007Sdelphij		break;
4265197007Sdelphij
4266197007Sdelphij	case 0x10:
4267197007Sdelphij		common_binop_byte_rm_r(emu, adc_byte);
4268197007Sdelphij		break;
4269197007Sdelphij	case 0x11:
4270197007Sdelphij		common_binop_word_long_rm_r(emu, adc_word, adc_long);
4271197007Sdelphij		break;
4272197007Sdelphij	case 0x12:
4273197007Sdelphij		common_binop_byte_r_rm(emu, adc_byte);
4274197007Sdelphij		break;
4275197007Sdelphij	case 0x13:
4276197007Sdelphij		common_binop_word_long_r_rm(emu, adc_word, adc_long);
4277197007Sdelphij		break;
4278197007Sdelphij	case 0x14:
4279197007Sdelphij		common_binop_byte_imm(emu, adc_byte);
4280197007Sdelphij		break;
4281197007Sdelphij	case 0x15:
4282197007Sdelphij		common_binop_word_long_imm(emu, adc_word, adc_long);
4283197007Sdelphij		break;
4284197007Sdelphij	case 0x16:
4285197007Sdelphij		push_word(emu, emu->x86.R_SS);
4286197007Sdelphij		break;
4287197007Sdelphij	case 0x17:
4288197007Sdelphij		emu->x86.R_SS = pop_word(emu);
4289197007Sdelphij		break;
4290197007Sdelphij
4291197007Sdelphij	case 0x18:
4292197007Sdelphij		common_binop_byte_rm_r(emu, sbb_byte);
4293197007Sdelphij		break;
4294197007Sdelphij	case 0x19:
4295197007Sdelphij		common_binop_word_long_rm_r(emu, sbb_word, sbb_long);
4296197007Sdelphij		break;
4297197007Sdelphij	case 0x1a:
4298197007Sdelphij		common_binop_byte_r_rm(emu, sbb_byte);
4299197007Sdelphij		break;
4300197007Sdelphij	case 0x1b:
4301197007Sdelphij		common_binop_word_long_r_rm(emu, sbb_word, sbb_long);
4302197007Sdelphij		break;
4303197007Sdelphij	case 0x1c:
4304197007Sdelphij		common_binop_byte_imm(emu, sbb_byte);
4305197007Sdelphij		break;
4306197007Sdelphij	case 0x1d:
4307197007Sdelphij		common_binop_word_long_imm(emu, sbb_word, sbb_long);
4308197007Sdelphij		break;
4309197007Sdelphij	case 0x1e:
4310197007Sdelphij		push_word(emu, emu->x86.R_DS);
4311197007Sdelphij		break;
4312197007Sdelphij	case 0x1f:
4313197007Sdelphij		emu->x86.R_DS = pop_word(emu);
4314197007Sdelphij		break;
4315197007Sdelphij
4316197007Sdelphij	case 0x20:
4317197007Sdelphij		common_binop_byte_rm_r(emu, and_byte);
4318197007Sdelphij		break;
4319197007Sdelphij	case 0x21:
4320197007Sdelphij		common_binop_word_long_rm_r(emu, and_word, and_long);
4321197007Sdelphij		break;
4322197007Sdelphij	case 0x22:
4323197007Sdelphij		common_binop_byte_r_rm(emu, and_byte);
4324197007Sdelphij		break;
4325197007Sdelphij	case 0x23:
4326197007Sdelphij		common_binop_word_long_r_rm(emu, and_word, and_long);
4327197007Sdelphij		break;
4328197007Sdelphij	case 0x24:
4329197007Sdelphij		common_binop_byte_imm(emu, and_byte);
4330197007Sdelphij		break;
4331197007Sdelphij	case 0x25:
4332197007Sdelphij		common_binop_word_long_imm(emu, and_word, and_long);
4333197007Sdelphij		break;
4334197007Sdelphij	case 0x26:
4335197007Sdelphij		emu->x86.mode |= SYSMODE_SEGOVR_ES;
4336197007Sdelphij		break;
4337197007Sdelphij	case 0x27:
4338197007Sdelphij		emu->x86.R_AL = daa_byte(emu, emu->x86.R_AL);
4339197007Sdelphij		break;
4340197007Sdelphij
4341197007Sdelphij	case 0x28:
4342197007Sdelphij		common_binop_byte_rm_r(emu, sub_byte);
4343197007Sdelphij		break;
4344197007Sdelphij	case 0x29:
4345197007Sdelphij		common_binop_word_long_rm_r(emu, sub_word, sub_long);
4346197007Sdelphij		break;
4347197007Sdelphij	case 0x2a:
4348197007Sdelphij		common_binop_byte_r_rm(emu, sub_byte);
4349197007Sdelphij		break;
4350197007Sdelphij	case 0x2b:
4351197007Sdelphij		common_binop_word_long_r_rm(emu, sub_word, sub_long);
4352197007Sdelphij		break;
4353197007Sdelphij	case 0x2c:
4354197007Sdelphij		common_binop_byte_imm(emu, sub_byte);
4355197007Sdelphij		break;
4356197007Sdelphij	case 0x2d:
4357197007Sdelphij		common_binop_word_long_imm(emu, sub_word, sub_long);
4358197007Sdelphij		break;
4359197007Sdelphij	case 0x2e:
4360197007Sdelphij		emu->x86.mode |= SYSMODE_SEGOVR_CS;
4361197007Sdelphij		break;
4362197007Sdelphij	case 0x2f:
4363197007Sdelphij		emu->x86.R_AL = das_byte(emu, emu->x86.R_AL);
4364197007Sdelphij		break;
4365197007Sdelphij
4366197007Sdelphij	case 0x30:
4367197007Sdelphij		common_binop_byte_rm_r(emu, xor_byte);
4368197007Sdelphij		break;
4369197007Sdelphij	case 0x31:
4370197007Sdelphij		common_binop_word_long_rm_r(emu, xor_word, xor_long);
4371197007Sdelphij		break;
4372197007Sdelphij	case 0x32:
4373197007Sdelphij		common_binop_byte_r_rm(emu, xor_byte);
4374197007Sdelphij		break;
4375197007Sdelphij	case 0x33:
4376197007Sdelphij		common_binop_word_long_r_rm(emu, xor_word, xor_long);
4377197007Sdelphij		break;
4378197007Sdelphij	case 0x34:
4379197007Sdelphij		common_binop_byte_imm(emu, xor_byte);
4380197007Sdelphij		break;
4381197007Sdelphij	case 0x35:
4382197007Sdelphij		common_binop_word_long_imm(emu, xor_word, xor_long);
4383197007Sdelphij		break;
4384197007Sdelphij	case 0x36:
4385197007Sdelphij		emu->x86.mode |= SYSMODE_SEGOVR_SS;
4386197007Sdelphij		break;
4387197007Sdelphij	case 0x37:
4388197007Sdelphij		emu->x86.R_AX = aaa_word(emu, emu->x86.R_AX);
4389197007Sdelphij		break;
4390197007Sdelphij
4391197007Sdelphij	case 0x38:
4392197007Sdelphij		common_binop_ns_byte_rm_r(emu, cmp_byte_no_return);
4393197007Sdelphij		break;
4394197007Sdelphij	case 0x39:
4395197007Sdelphij		common_binop_ns_word_long_rm_r(emu, cmp_word_no_return,
4396197007Sdelphij		    cmp_long_no_return);
4397197007Sdelphij		break;
4398197007Sdelphij	case 0x3a:
4399197007Sdelphij		x86emuOp_cmp_byte_R_RM(emu);
4400197007Sdelphij		break;
4401197007Sdelphij	case 0x3b:
4402197007Sdelphij		x86emuOp_cmp_word_R_RM(emu);
4403197007Sdelphij		break;
4404197007Sdelphij	case 0x3c:
4405197007Sdelphij		x86emuOp_cmp_byte_AL_IMM(emu);
4406197007Sdelphij		break;
4407197007Sdelphij	case 0x3d:
4408197007Sdelphij		x86emuOp_cmp_word_AX_IMM(emu);
4409197007Sdelphij		break;
4410197007Sdelphij	case 0x3e:
4411197007Sdelphij		emu->x86.mode |= SYSMODE_SEGOVR_DS;
4412197007Sdelphij		break;
4413197007Sdelphij	case 0x3f:
4414197007Sdelphij		emu->x86.R_AX = aas_word(emu, emu->x86.R_AX);
4415197007Sdelphij		break;
4416197007Sdelphij
4417197007Sdelphij	case 0x40:
4418197007Sdelphij		common_inc_word_long(emu, &emu->x86.register_a);
4419197007Sdelphij		break;
4420197007Sdelphij	case 0x41:
4421197007Sdelphij		common_inc_word_long(emu, &emu->x86.register_c);
4422197007Sdelphij		break;
4423197007Sdelphij	case 0x42:
4424197007Sdelphij		common_inc_word_long(emu, &emu->x86.register_d);
4425197007Sdelphij		break;
4426197007Sdelphij	case 0x43:
4427197007Sdelphij		common_inc_word_long(emu, &emu->x86.register_b);
4428197007Sdelphij		break;
4429197007Sdelphij	case 0x44:
4430197007Sdelphij		common_inc_word_long(emu, &emu->x86.register_sp);
4431197007Sdelphij		break;
4432197007Sdelphij	case 0x45:
4433197007Sdelphij		common_inc_word_long(emu, &emu->x86.register_bp);
4434197007Sdelphij		break;
4435197007Sdelphij	case 0x46:
4436197007Sdelphij		common_inc_word_long(emu, &emu->x86.register_si);
4437197007Sdelphij		break;
4438197007Sdelphij	case 0x47:
4439197007Sdelphij		common_inc_word_long(emu, &emu->x86.register_di);
4440197007Sdelphij		break;
4441197007Sdelphij
4442197007Sdelphij	case 0x48:
4443197007Sdelphij		common_dec_word_long(emu, &emu->x86.register_a);
4444197007Sdelphij		break;
4445197007Sdelphij	case 0x49:
4446197007Sdelphij		common_dec_word_long(emu, &emu->x86.register_c);
4447197007Sdelphij		break;
4448197007Sdelphij	case 0x4a:
4449197007Sdelphij		common_dec_word_long(emu, &emu->x86.register_d);
4450197007Sdelphij		break;
4451197007Sdelphij	case 0x4b:
4452197007Sdelphij		common_dec_word_long(emu, &emu->x86.register_b);
4453197007Sdelphij		break;
4454197007Sdelphij	case 0x4c:
4455197007Sdelphij		common_dec_word_long(emu, &emu->x86.register_sp);
4456197007Sdelphij		break;
4457197007Sdelphij	case 0x4d:
4458197007Sdelphij		common_dec_word_long(emu, &emu->x86.register_bp);
4459197007Sdelphij		break;
4460197007Sdelphij	case 0x4e:
4461197007Sdelphij		common_dec_word_long(emu, &emu->x86.register_si);
4462197007Sdelphij		break;
4463197007Sdelphij	case 0x4f:
4464197007Sdelphij		common_dec_word_long(emu, &emu->x86.register_di);
4465197007Sdelphij		break;
4466197007Sdelphij
4467197007Sdelphij	case 0x50:
4468197007Sdelphij		common_push_word_long(emu, &emu->x86.register_a);
4469197007Sdelphij		break;
4470197007Sdelphij	case 0x51:
4471197007Sdelphij		common_push_word_long(emu, &emu->x86.register_c);
4472197007Sdelphij		break;
4473197007Sdelphij	case 0x52:
4474197007Sdelphij		common_push_word_long(emu, &emu->x86.register_d);
4475197007Sdelphij		break;
4476197007Sdelphij	case 0x53:
4477197007Sdelphij		common_push_word_long(emu, &emu->x86.register_b);
4478197007Sdelphij		break;
4479197007Sdelphij	case 0x54:
4480197007Sdelphij		common_push_word_long(emu, &emu->x86.register_sp);
4481197007Sdelphij		break;
4482197007Sdelphij	case 0x55:
4483197007Sdelphij		common_push_word_long(emu, &emu->x86.register_bp);
4484197007Sdelphij		break;
4485197007Sdelphij	case 0x56:
4486197007Sdelphij		common_push_word_long(emu, &emu->x86.register_si);
4487197007Sdelphij		break;
4488197007Sdelphij	case 0x57:
4489197007Sdelphij		common_push_word_long(emu, &emu->x86.register_di);
4490197007Sdelphij		break;
4491197007Sdelphij
4492197007Sdelphij	case 0x58:
4493197007Sdelphij		common_pop_word_long(emu, &emu->x86.register_a);
4494197007Sdelphij		break;
4495197007Sdelphij	case 0x59:
4496197007Sdelphij		common_pop_word_long(emu, &emu->x86.register_c);
4497197007Sdelphij		break;
4498197007Sdelphij	case 0x5a:
4499197007Sdelphij		common_pop_word_long(emu, &emu->x86.register_d);
4500197007Sdelphij		break;
4501197007Sdelphij	case 0x5b:
4502197007Sdelphij		common_pop_word_long(emu, &emu->x86.register_b);
4503197007Sdelphij		break;
4504197007Sdelphij	case 0x5c:
4505197007Sdelphij		common_pop_word_long(emu, &emu->x86.register_sp);
4506197007Sdelphij		break;
4507197007Sdelphij	case 0x5d:
4508197007Sdelphij		common_pop_word_long(emu, &emu->x86.register_bp);
4509197007Sdelphij		break;
4510197007Sdelphij	case 0x5e:
4511197007Sdelphij		common_pop_word_long(emu, &emu->x86.register_si);
4512197007Sdelphij		break;
4513197007Sdelphij	case 0x5f:
4514197007Sdelphij		common_pop_word_long(emu, &emu->x86.register_di);
4515197007Sdelphij		break;
4516197007Sdelphij
4517197007Sdelphij	case 0x60:
4518197007Sdelphij		x86emuOp_push_all(emu);
4519197007Sdelphij		break;
4520197007Sdelphij	case 0x61:
4521197007Sdelphij		x86emuOp_pop_all(emu);
4522197007Sdelphij		break;
4523197007Sdelphij	/* 0x62 bound */
4524197007Sdelphij	/* 0x63 arpl */
4525197007Sdelphij	case 0x64:
4526197007Sdelphij		emu->x86.mode |= SYSMODE_SEGOVR_FS;
4527197007Sdelphij		break;
4528197007Sdelphij	case 0x65:
4529197007Sdelphij		emu->x86.mode |= SYSMODE_SEGOVR_GS;
4530197007Sdelphij		break;
4531197007Sdelphij	case 0x66:
4532197007Sdelphij		emu->x86.mode |= SYSMODE_PREFIX_DATA;
4533197007Sdelphij		break;
4534197007Sdelphij	case 0x67:
4535197007Sdelphij		emu->x86.mode |= SYSMODE_PREFIX_ADDR;
4536197007Sdelphij		break;
4537197007Sdelphij
4538197007Sdelphij	case 0x68:
4539197007Sdelphij		x86emuOp_push_word_IMM(emu);
4540197007Sdelphij		break;
4541197007Sdelphij	case 0x69:
4542197007Sdelphij		common_imul_imm(emu, 0);
4543197007Sdelphij		break;
4544197007Sdelphij	case 0x6a:
4545197007Sdelphij		x86emuOp_push_byte_IMM(emu);
4546197007Sdelphij		break;
4547197007Sdelphij	case 0x6b:
4548197007Sdelphij		common_imul_imm(emu, 1);
4549197007Sdelphij		break;
4550197007Sdelphij	case 0x6c:
4551197007Sdelphij		ins(emu, 1);
4552197007Sdelphij		break;
4553197007Sdelphij	case 0x6d:
4554197007Sdelphij		x86emuOp_ins_word(emu);
4555197007Sdelphij		break;
4556197007Sdelphij	case 0x6e:
4557197007Sdelphij		outs(emu, 1);
4558197007Sdelphij		break;
4559197007Sdelphij	case 0x6f:
4560197007Sdelphij		x86emuOp_outs_word(emu);
4561197007Sdelphij		break;
4562197007Sdelphij
4563197007Sdelphij	case 0x70:
4564197007Sdelphij		common_jmp_near(emu, ACCESS_FLAG(F_OF));
4565197007Sdelphij		break;
4566197007Sdelphij	case 0x71:
4567197007Sdelphij		common_jmp_near(emu, !ACCESS_FLAG(F_OF));
4568197007Sdelphij		break;
4569197007Sdelphij	case 0x72:
4570197007Sdelphij		common_jmp_near(emu, ACCESS_FLAG(F_CF));
4571197007Sdelphij		break;
4572197007Sdelphij	case 0x73:
4573197007Sdelphij		common_jmp_near(emu, !ACCESS_FLAG(F_CF));
4574197007Sdelphij		break;
4575197007Sdelphij	case 0x74:
4576197007Sdelphij		common_jmp_near(emu, ACCESS_FLAG(F_ZF));
4577197007Sdelphij		break;
4578197007Sdelphij	case 0x75:
4579197007Sdelphij		common_jmp_near(emu, !ACCESS_FLAG(F_ZF));
4580197007Sdelphij		break;
4581197007Sdelphij	case 0x76:
4582197007Sdelphij		common_jmp_near(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
4583197007Sdelphij		break;
4584197007Sdelphij	case 0x77:
4585197007Sdelphij		common_jmp_near(emu, !ACCESS_FLAG(F_CF) && !ACCESS_FLAG(F_ZF));
4586197007Sdelphij		break;
4587197007Sdelphij
4588197007Sdelphij	case 0x78:
4589197007Sdelphij		common_jmp_near(emu, ACCESS_FLAG(F_SF));
4590197007Sdelphij		break;
4591197007Sdelphij	case 0x79:
4592197007Sdelphij		common_jmp_near(emu, !ACCESS_FLAG(F_SF));
4593197007Sdelphij		break;
4594197007Sdelphij	case 0x7a:
4595197007Sdelphij		common_jmp_near(emu, ACCESS_FLAG(F_PF));
4596197007Sdelphij		break;
4597197007Sdelphij	case 0x7b:
4598197007Sdelphij		common_jmp_near(emu, !ACCESS_FLAG(F_PF));
4599197007Sdelphij		break;
4600197007Sdelphij	case 0x7c:
4601197007Sdelphij		x86emuOp_jump_near_L(emu);
4602197007Sdelphij		break;
4603197007Sdelphij	case 0x7d:
4604197007Sdelphij		x86emuOp_jump_near_NL(emu);
4605197007Sdelphij		break;
4606197007Sdelphij	case 0x7e:
4607197007Sdelphij		x86emuOp_jump_near_LE(emu);
4608197007Sdelphij		break;
4609197007Sdelphij	case 0x7f:
4610197007Sdelphij		x86emuOp_jump_near_NLE(emu);
4611197007Sdelphij		break;
4612197007Sdelphij
4613197007Sdelphij	case 0x80:
4614197007Sdelphij		x86emuOp_opc80_byte_RM_IMM(emu);
4615197007Sdelphij		break;
4616197007Sdelphij	case 0x81:
4617197007Sdelphij		x86emuOp_opc81_word_RM_IMM(emu);
4618197007Sdelphij		break;
4619197007Sdelphij	case 0x82:
4620197007Sdelphij		x86emuOp_opc82_byte_RM_IMM(emu);
4621197007Sdelphij		break;
4622197007Sdelphij	case 0x83:
4623197007Sdelphij		x86emuOp_opc83_word_RM_IMM(emu);
4624197007Sdelphij		break;
4625197007Sdelphij	case 0x84:
4626197007Sdelphij		common_binop_ns_byte_rm_r(emu, test_byte);
4627197007Sdelphij		break;
4628197007Sdelphij	case 0x85:
4629197007Sdelphij		common_binop_ns_word_long_rm_r(emu, test_word, test_long);
4630197007Sdelphij		break;
4631197007Sdelphij	case 0x86:
4632197007Sdelphij		x86emuOp_xchg_byte_RM_R(emu);
4633197007Sdelphij		break;
4634197007Sdelphij	case 0x87:
4635197007Sdelphij		x86emuOp_xchg_word_RM_R(emu);
4636197007Sdelphij		break;
4637197007Sdelphij
4638197007Sdelphij	case 0x88:
4639197007Sdelphij		x86emuOp_mov_byte_RM_R(emu);
4640197007Sdelphij		break;
4641197007Sdelphij	case 0x89:
4642197007Sdelphij		x86emuOp_mov_word_RM_R(emu);
4643197007Sdelphij		break;
4644197007Sdelphij	case 0x8a:
4645197007Sdelphij		x86emuOp_mov_byte_R_RM(emu);
4646197007Sdelphij		break;
4647197007Sdelphij	case 0x8b:
4648197007Sdelphij		x86emuOp_mov_word_R_RM(emu);
4649197007Sdelphij		break;
4650197007Sdelphij	case 0x8c:
4651197007Sdelphij		x86emuOp_mov_word_RM_SR(emu);
4652197007Sdelphij		break;
4653197007Sdelphij	case 0x8d:
4654197007Sdelphij		x86emuOp_lea_word_R_M(emu);
4655197007Sdelphij		break;
4656197007Sdelphij	case 0x8e:
4657197007Sdelphij		x86emuOp_mov_word_SR_RM(emu);
4658197007Sdelphij		break;
4659197007Sdelphij	case 0x8f:
4660197007Sdelphij		x86emuOp_pop_RM(emu);
4661197007Sdelphij		break;
4662197007Sdelphij
4663197007Sdelphij	case 0x90:
4664197007Sdelphij		/* nop */
4665197007Sdelphij		break;
4666197007Sdelphij	case 0x91:
4667197007Sdelphij		x86emuOp_xchg_word_AX_CX(emu);
4668197007Sdelphij		break;
4669197007Sdelphij	case 0x92:
4670197007Sdelphij		x86emuOp_xchg_word_AX_DX(emu);
4671197007Sdelphij		break;
4672197007Sdelphij	case 0x93:
4673197007Sdelphij		x86emuOp_xchg_word_AX_BX(emu);
4674197007Sdelphij		break;
4675197007Sdelphij	case 0x94:
4676197007Sdelphij		x86emuOp_xchg_word_AX_SP(emu);
4677197007Sdelphij		break;
4678197007Sdelphij	case 0x95:
4679197007Sdelphij		x86emuOp_xchg_word_AX_BP(emu);
4680197007Sdelphij		break;
4681197007Sdelphij	case 0x96:
4682197007Sdelphij		x86emuOp_xchg_word_AX_SI(emu);
4683197007Sdelphij		break;
4684197007Sdelphij	case 0x97:
4685197007Sdelphij		x86emuOp_xchg_word_AX_DI(emu);
4686197007Sdelphij		break;
4687197007Sdelphij
4688197007Sdelphij	case 0x98:
4689197007Sdelphij		x86emuOp_cbw(emu);
4690197007Sdelphij		break;
4691197007Sdelphij	case 0x99:
4692197007Sdelphij		x86emuOp_cwd(emu);
4693197007Sdelphij		break;
4694197007Sdelphij	case 0x9a:
4695197007Sdelphij		x86emuOp_call_far_IMM(emu);
4696197007Sdelphij		break;
4697197007Sdelphij	case 0x9b:
4698197007Sdelphij		/* wait */
4699197007Sdelphij		break;
4700197007Sdelphij	case 0x9c:
4701197007Sdelphij		x86emuOp_pushf_word(emu);
4702197007Sdelphij		break;
4703197007Sdelphij	case 0x9d:
4704197007Sdelphij		x86emuOp_popf_word(emu);
4705197007Sdelphij		break;
4706197007Sdelphij	case 0x9e:
4707197007Sdelphij		x86emuOp_sahf(emu);
4708197007Sdelphij		break;
4709197007Sdelphij	case 0x9f:
4710197007Sdelphij		x86emuOp_lahf(emu);
4711197007Sdelphij		break;
4712197007Sdelphij
4713197007Sdelphij	case 0xa0:
4714197007Sdelphij		x86emuOp_mov_AL_M_IMM(emu);
4715197007Sdelphij		break;
4716197007Sdelphij	case 0xa1:
4717197007Sdelphij		x86emuOp_mov_AX_M_IMM(emu);
4718197007Sdelphij		break;
4719197007Sdelphij	case 0xa2:
4720197007Sdelphij		x86emuOp_mov_M_AL_IMM(emu);
4721197007Sdelphij		break;
4722197007Sdelphij	case 0xa3:
4723197007Sdelphij		x86emuOp_mov_M_AX_IMM(emu);
4724197007Sdelphij		break;
4725197007Sdelphij	case 0xa4:
4726197007Sdelphij		x86emuOp_movs_byte(emu);
4727197007Sdelphij		break;
4728197007Sdelphij	case 0xa5:
4729197007Sdelphij		x86emuOp_movs_word(emu);
4730197007Sdelphij		break;
4731197007Sdelphij	case 0xa6:
4732197007Sdelphij		x86emuOp_cmps_byte(emu);
4733197007Sdelphij		break;
4734197007Sdelphij	case 0xa7:
4735197007Sdelphij		x86emuOp_cmps_word(emu);
4736197007Sdelphij		break;
4737197007Sdelphij
4738197007Sdelphij	case 0xa8:
4739197007Sdelphij		test_byte(emu, emu->x86.R_AL, fetch_byte_imm(emu));
4740197007Sdelphij		break;
4741197007Sdelphij	case 0xa9:
4742197007Sdelphij		x86emuOp_test_AX_IMM(emu);
4743197007Sdelphij		break;
4744197007Sdelphij	case 0xaa:
4745197007Sdelphij		x86emuOp_stos_byte(emu);
4746197007Sdelphij		break;
4747197007Sdelphij	case 0xab:
4748197007Sdelphij		x86emuOp_stos_word(emu);
4749197007Sdelphij		break;
4750197007Sdelphij	case 0xac:
4751197007Sdelphij		x86emuOp_lods_byte(emu);
4752197007Sdelphij		break;
4753197007Sdelphij	case 0xad:
4754197007Sdelphij		x86emuOp_lods_word(emu);
4755197007Sdelphij		break;
4756197007Sdelphij	case 0xae:
4757197007Sdelphij		x86emuOp_scas_byte(emu);
4758197007Sdelphij		break;
4759197007Sdelphij	case 0xaf:
4760197007Sdelphij		x86emuOp_scas_word(emu);
4761197007Sdelphij		break;
4762197007Sdelphij
4763197007Sdelphij	case 0xb0:
4764197007Sdelphij		emu->x86.R_AL = fetch_byte_imm(emu);
4765197007Sdelphij		break;
4766197007Sdelphij	case 0xb1:
4767197007Sdelphij		emu->x86.R_CL = fetch_byte_imm(emu);
4768197007Sdelphij		break;
4769197007Sdelphij	case 0xb2:
4770197007Sdelphij		emu->x86.R_DL = fetch_byte_imm(emu);
4771197007Sdelphij		break;
4772197007Sdelphij	case 0xb3:
4773197007Sdelphij		emu->x86.R_BL = fetch_byte_imm(emu);
4774197007Sdelphij		break;
4775197007Sdelphij	case 0xb4:
4776197007Sdelphij		emu->x86.R_AH = fetch_byte_imm(emu);
4777197007Sdelphij		break;
4778197007Sdelphij	case 0xb5:
4779197007Sdelphij		emu->x86.R_CH = fetch_byte_imm(emu);
4780197007Sdelphij		break;
4781197007Sdelphij	case 0xb6:
4782197007Sdelphij		emu->x86.R_DH = fetch_byte_imm(emu);
4783197007Sdelphij		break;
4784197007Sdelphij	case 0xb7:
4785197007Sdelphij		emu->x86.R_BH = fetch_byte_imm(emu);
4786197007Sdelphij		break;
4787197007Sdelphij
4788197007Sdelphij	case 0xb8:
4789197007Sdelphij		x86emuOp_mov_word_AX_IMM(emu);
4790197007Sdelphij		break;
4791197007Sdelphij	case 0xb9:
4792197007Sdelphij		x86emuOp_mov_word_CX_IMM(emu);
4793197007Sdelphij		break;
4794197007Sdelphij	case 0xba:
4795197007Sdelphij		x86emuOp_mov_word_DX_IMM(emu);
4796197007Sdelphij		break;
4797197007Sdelphij	case 0xbb:
4798197007Sdelphij		x86emuOp_mov_word_BX_IMM(emu);
4799197007Sdelphij		break;
4800197007Sdelphij	case 0xbc:
4801197007Sdelphij
4802197007Sdelphij		x86emuOp_mov_word_SP_IMM(emu);
4803197007Sdelphij		break;
4804197007Sdelphij	case 0xbd:
4805197007Sdelphij		x86emuOp_mov_word_BP_IMM(emu);
4806197007Sdelphij		break;
4807197007Sdelphij	case 0xbe:
4808197007Sdelphij		x86emuOp_mov_word_SI_IMM(emu);
4809197007Sdelphij		break;
4810197007Sdelphij	case 0xbf:
4811197007Sdelphij		x86emuOp_mov_word_DI_IMM(emu);
4812197007Sdelphij		break;
4813197007Sdelphij
4814197007Sdelphij	case 0xc0:
4815197007Sdelphij		x86emuOp_opcC0_byte_RM_MEM(emu);
4816197007Sdelphij		break;
4817197007Sdelphij	case 0xc1:
4818197007Sdelphij		x86emuOp_opcC1_word_RM_MEM(emu);
4819197007Sdelphij		break;
4820197007Sdelphij	case 0xc2:
4821197007Sdelphij		x86emuOp_ret_near_IMM(emu);
4822197007Sdelphij		break;
4823197007Sdelphij	case 0xc3:
4824197007Sdelphij		emu->x86.R_IP = pop_word(emu);
4825197007Sdelphij		break;
4826197007Sdelphij	case 0xc4:
4827197007Sdelphij		common_load_far_pointer(emu, &emu->x86.R_ES);
4828197007Sdelphij		break;
4829197007Sdelphij	case 0xc5:
4830197007Sdelphij		common_load_far_pointer(emu, &emu->x86.R_DS);
4831197007Sdelphij		break;
4832197007Sdelphij	case 0xc6:
4833197007Sdelphij		x86emuOp_mov_byte_RM_IMM(emu);
4834197007Sdelphij		break;
4835197007Sdelphij	case 0xc7:
4836197007Sdelphij		x86emuOp_mov_word_RM_IMM(emu);
4837197007Sdelphij		break;
4838197007Sdelphij	case 0xc8:
4839197007Sdelphij		x86emuOp_enter(emu);
4840197007Sdelphij		break;
4841197007Sdelphij	case 0xc9:
4842197007Sdelphij		x86emuOp_leave(emu);
4843197007Sdelphij		break;
4844197007Sdelphij	case 0xca:
4845197007Sdelphij		x86emuOp_ret_far_IMM(emu);
4846197007Sdelphij		break;
4847197007Sdelphij	case 0xcb:
4848197007Sdelphij		x86emuOp_ret_far(emu);
4849197007Sdelphij		break;
4850197007Sdelphij	case 0xcc:
4851197007Sdelphij		x86emuOp_int3(emu);
4852197007Sdelphij		break;
4853197007Sdelphij	case 0xcd:
4854197007Sdelphij		x86emuOp_int_IMM(emu);
4855197007Sdelphij		break;
4856197007Sdelphij	case 0xce:
4857197007Sdelphij		x86emuOp_into(emu);
4858197007Sdelphij		break;
4859197007Sdelphij	case 0xcf:
4860197007Sdelphij		x86emuOp_iret(emu);
4861197007Sdelphij		break;
4862197007Sdelphij
4863197007Sdelphij	case 0xd0:
4864197007Sdelphij		x86emuOp_opcD0_byte_RM_1(emu);
4865197007Sdelphij		break;
4866197007Sdelphij	case 0xd1:
4867197007Sdelphij		x86emuOp_opcD1_word_RM_1(emu);
4868197007Sdelphij		break;
4869197007Sdelphij	case 0xd2:
4870197007Sdelphij		x86emuOp_opcD2_byte_RM_CL(emu);
4871197007Sdelphij		break;
4872197007Sdelphij	case 0xd3:
4873197007Sdelphij		x86emuOp_opcD3_word_RM_CL(emu);
4874197007Sdelphij		break;
4875197007Sdelphij	case 0xd4:
4876197007Sdelphij		x86emuOp_aam(emu);
4877197007Sdelphij		break;
4878197007Sdelphij	case 0xd5:
4879197007Sdelphij		x86emuOp_aad(emu);
4880197007Sdelphij		break;
4881197007Sdelphij	/* 0xd6 Undocumented SETALC instruction */
4882197007Sdelphij	case 0xd7:
4883197007Sdelphij		x86emuOp_xlat(emu);
4884197007Sdelphij		break;
4885197007Sdelphij	case 0xd8:
4886197007Sdelphij		x86emuOp_esc_coprocess_d8(emu);
4887197007Sdelphij		break;
4888197007Sdelphij	case 0xd9:
4889197007Sdelphij		x86emuOp_esc_coprocess_d9(emu);
4890197007Sdelphij		break;
4891197007Sdelphij	case 0xda:
4892197007Sdelphij		x86emuOp_esc_coprocess_da(emu);
4893197007Sdelphij		break;
4894197007Sdelphij	case 0xdb:
4895197007Sdelphij		x86emuOp_esc_coprocess_db(emu);
4896197007Sdelphij		break;
4897197007Sdelphij	case 0xdc:
4898197007Sdelphij		x86emuOp_esc_coprocess_dc(emu);
4899197007Sdelphij		break;
4900197007Sdelphij	case 0xdd:
4901197007Sdelphij		x86emuOp_esc_coprocess_dd(emu);
4902197007Sdelphij		break;
4903197007Sdelphij	case 0xde:
4904197007Sdelphij		x86emuOp_esc_coprocess_de(emu);
4905197007Sdelphij		break;
4906197007Sdelphij	case 0xdf:
4907197007Sdelphij		x86emuOp_esc_coprocess_df(emu);
4908197007Sdelphij		break;
4909197007Sdelphij
4910197007Sdelphij	case 0xe0:
4911197007Sdelphij		x86emuOp_loopne(emu);
4912197007Sdelphij		break;
4913197007Sdelphij	case 0xe1:
4914197007Sdelphij		x86emuOp_loope(emu);
4915197007Sdelphij		break;
4916197007Sdelphij	case 0xe2:
4917197007Sdelphij		x86emuOp_loop(emu);
4918197007Sdelphij		break;
4919197007Sdelphij	case 0xe3:
4920197007Sdelphij		x86emuOp_jcxz(emu);
4921197007Sdelphij		break;
4922197007Sdelphij	case 0xe4:
4923197007Sdelphij		x86emuOp_in_byte_AL_IMM(emu);
4924197007Sdelphij		break;
4925197007Sdelphij	case 0xe5:
4926197007Sdelphij		x86emuOp_in_word_AX_IMM(emu);
4927197007Sdelphij		break;
4928197007Sdelphij	case 0xe6:
4929197007Sdelphij		x86emuOp_out_byte_IMM_AL(emu);
4930197007Sdelphij		break;
4931197007Sdelphij	case 0xe7:
4932197007Sdelphij		x86emuOp_out_word_IMM_AX(emu);
4933197007Sdelphij		break;
4934197007Sdelphij
4935197007Sdelphij	case 0xe8:
4936197007Sdelphij		x86emuOp_call_near_IMM(emu);
4937197007Sdelphij		break;
4938197007Sdelphij	case 0xe9:
4939197007Sdelphij		x86emuOp_jump_near_IMM(emu);
4940197007Sdelphij		break;
4941197007Sdelphij	case 0xea:
4942197007Sdelphij		x86emuOp_jump_far_IMM(emu);
4943197007Sdelphij		break;
4944197007Sdelphij	case 0xeb:
4945197007Sdelphij		x86emuOp_jump_byte_IMM(emu);
4946197007Sdelphij		break;
4947197007Sdelphij	case 0xec:
4948197007Sdelphij		x86emuOp_in_byte_AL_DX(emu);
4949197007Sdelphij		break;
4950197007Sdelphij	case 0xed:
4951197007Sdelphij		x86emuOp_in_word_AX_DX(emu);
4952197007Sdelphij		break;
4953197007Sdelphij	case 0xee:
4954197007Sdelphij		x86emuOp_out_byte_DX_AL(emu);
4955197007Sdelphij		break;
4956197007Sdelphij	case 0xef:
4957197007Sdelphij		x86emuOp_out_word_DX_AX(emu);
4958197007Sdelphij		break;
4959197007Sdelphij
4960197007Sdelphij	case 0xf0:
4961197007Sdelphij		x86emuOp_lock(emu);
4962197007Sdelphij		break;
4963197007Sdelphij	case 0xf2:
4964197007Sdelphij		emu->x86.mode |= SYSMODE_PREFIX_REPNE;
4965197007Sdelphij		break;
4966197007Sdelphij	case 0xf3:
4967197007Sdelphij		emu->x86.mode |= SYSMODE_PREFIX_REPE;
4968197007Sdelphij		break;
4969197007Sdelphij	case 0xf4:
4970197007Sdelphij		x86emu_halt_sys(emu);
4971197007Sdelphij		break;
4972197007Sdelphij	case 0xf5:
4973197007Sdelphij		x86emuOp_cmc(emu);
4974197007Sdelphij		break;
4975197007Sdelphij	case 0xf6:
4976197007Sdelphij		x86emuOp_opcF6_byte_RM(emu);
4977197007Sdelphij		break;
4978197007Sdelphij	case 0xf7:
4979197007Sdelphij		x86emuOp_opcF7_word_RM(emu);
4980197007Sdelphij		break;
4981197007Sdelphij
4982197007Sdelphij	case 0xf8:
4983197007Sdelphij		CLEAR_FLAG(F_CF);
4984197007Sdelphij		break;
4985197007Sdelphij	case 0xf9:
4986197007Sdelphij		SET_FLAG(F_CF);
4987197007Sdelphij		break;
4988197007Sdelphij	case 0xfa:
4989197007Sdelphij		CLEAR_FLAG(F_IF);
4990197007Sdelphij		break;
4991197007Sdelphij	case 0xfb:
4992197007Sdelphij		SET_FLAG(F_IF);
4993197007Sdelphij		break;
4994197007Sdelphij	case 0xfc:
4995197007Sdelphij		CLEAR_FLAG(F_DF);
4996197007Sdelphij		break;
4997197007Sdelphij	case 0xfd:
4998197007Sdelphij		SET_FLAG(F_DF);
4999197007Sdelphij		break;
5000197007Sdelphij	case 0xfe:
5001197007Sdelphij		x86emuOp_opcFE_byte_RM(emu);
5002197007Sdelphij		break;
5003197007Sdelphij	case 0xff:
5004197007Sdelphij		x86emuOp_opcFF_word_RM(emu);
5005197007Sdelphij		break;
5006197007Sdelphij	default:
5007197007Sdelphij		x86emu_halt_sys(emu);
5008197007Sdelphij		break;
5009197007Sdelphij	}
5010197007Sdelphij	if (op1 != 0x26 && op1 != 0x2e && op1 != 0x36 && op1 != 0x3e &&
5011197007Sdelphij	    (op1 | 3) != 0x67)
5012197007Sdelphij		emu->x86.mode &= ~SYSMODE_CLRMASK;
5013197007Sdelphij}
5014197007Sdelphij
5015197007Sdelphijstatic void
5016197007Sdelphijcommon_jmp_long(struct x86emu *emu, int cond)
5017197007Sdelphij{
5018197007Sdelphij	int16_t target;
5019197007Sdelphij
5020197007Sdelphij	target = (int16_t) fetch_word_imm(emu);
5021197007Sdelphij	target += (int16_t) emu->x86.R_IP;
5022197007Sdelphij	if (cond)
5023197007Sdelphij		emu->x86.R_IP = (uint16_t) target;
5024197007Sdelphij}
5025197007Sdelphij
5026197007Sdelphijstatic void
5027197007Sdelphijcommon_set_byte(struct x86emu *emu, int cond)
5028197007Sdelphij{
5029197007Sdelphij	uint32_t destoffset;
5030197007Sdelphij	uint8_t *destreg, destval;
5031197007Sdelphij
5032197007Sdelphij	fetch_decode_modrm(emu);
5033197007Sdelphij	destval = cond ? 0x01 : 0x00;
5034197007Sdelphij	if (emu->cur_mod != 3) {
5035197007Sdelphij		destoffset = decode_rl_address(emu);
5036197007Sdelphij		store_data_byte(emu, destoffset, destval);
5037197007Sdelphij	} else {
5038197007Sdelphij		destreg = decode_rl_byte_register(emu);
5039197007Sdelphij		*destreg = destval;
5040197007Sdelphij	}
5041197007Sdelphij}
5042197007Sdelphij
5043197007Sdelphijstatic void
5044197007Sdelphijcommon_bitstring32(struct x86emu *emu, int op)
5045197007Sdelphij{
5046197007Sdelphij	int bit;
5047197007Sdelphij	uint32_t srcval, *shiftreg, mask;
5048197007Sdelphij
5049197007Sdelphij	fetch_decode_modrm(emu);
5050197007Sdelphij	shiftreg = decode_rh_long_register(emu);
5051197007Sdelphij	srcval = decode_and_fetch_long_disp(emu, (int16_t) *shiftreg >> 5);
5052197007Sdelphij	bit = *shiftreg & 0x1F;
5053197007Sdelphij	mask =  0x1 << bit;
5054197007Sdelphij	CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5055197007Sdelphij
5056197007Sdelphij	switch (op) {
5057197007Sdelphij	case 0:
5058197007Sdelphij		break;
5059197007Sdelphij	case 1:
5060197007Sdelphij		write_back_long(emu, srcval | mask);
5061197007Sdelphij		break;
5062197007Sdelphij	case 2:
5063197007Sdelphij		write_back_long(emu, srcval & ~mask);
5064197007Sdelphij		break;
5065197007Sdelphij	case 3:
5066197007Sdelphij		write_back_long(emu, srcval ^ mask);
5067197007Sdelphij		break;
5068197007Sdelphij	}
5069197007Sdelphij}
5070197007Sdelphij
5071197007Sdelphijstatic void
5072197007Sdelphijcommon_bitstring16(struct x86emu *emu, int op)
5073197007Sdelphij{
5074197007Sdelphij	int bit;
5075197007Sdelphij	uint16_t srcval, *shiftreg, mask;
5076197007Sdelphij
5077197007Sdelphij	fetch_decode_modrm(emu);
5078197007Sdelphij	shiftreg = decode_rh_word_register(emu);
5079197007Sdelphij	srcval = decode_and_fetch_word_disp(emu, (int16_t) *shiftreg >> 4);
5080197007Sdelphij	bit = *shiftreg & 0xF;
5081197007Sdelphij	mask =  0x1 << bit;
5082197007Sdelphij	CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5083197007Sdelphij
5084197007Sdelphij	switch (op) {
5085197007Sdelphij	case 0:
5086197007Sdelphij		break;
5087197007Sdelphij	case 1:
5088197007Sdelphij		write_back_word(emu, srcval | mask);
5089197007Sdelphij		break;
5090197007Sdelphij	case 2:
5091197007Sdelphij		write_back_word(emu, srcval & ~mask);
5092197007Sdelphij		break;
5093197007Sdelphij	case 3:
5094197007Sdelphij		write_back_word(emu, srcval ^ mask);
5095197007Sdelphij		break;
5096197007Sdelphij	}
5097197007Sdelphij}
5098197007Sdelphij
5099197007Sdelphijstatic void
5100197007Sdelphijcommon_bitstring(struct x86emu *emu, int op)
5101197007Sdelphij{
5102197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5103197007Sdelphij		common_bitstring32(emu, op);
5104197007Sdelphij	else
5105197007Sdelphij		common_bitstring16(emu, op);
5106197007Sdelphij}
5107197007Sdelphij
5108197007Sdelphijstatic void
5109197007Sdelphijcommon_bitsearch32(struct x86emu *emu, int diff)
5110197007Sdelphij{
5111197007Sdelphij	uint32_t srcval, *dstreg;
5112197007Sdelphij
5113197007Sdelphij	fetch_decode_modrm(emu);
5114197007Sdelphij	dstreg = decode_rh_long_register(emu);
5115197007Sdelphij	srcval = decode_and_fetch_long(emu);
5116197007Sdelphij	CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
5117197007Sdelphij	for (*dstreg = 0; *dstreg < 32; *dstreg += diff) {
5118197007Sdelphij		if ((srcval >> *dstreg) & 1)
5119197007Sdelphij			break;
5120197007Sdelphij	}
5121197007Sdelphij}
5122197007Sdelphij
5123197007Sdelphijstatic void
5124197007Sdelphijcommon_bitsearch16(struct x86emu *emu, int diff)
5125197007Sdelphij{
5126197007Sdelphij	uint16_t srcval, *dstreg;
5127197007Sdelphij
5128197007Sdelphij	fetch_decode_modrm(emu);
5129197007Sdelphij	dstreg = decode_rh_word_register(emu);
5130197007Sdelphij	srcval = decode_and_fetch_word(emu);
5131197007Sdelphij	CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
5132197007Sdelphij	for (*dstreg = 0; *dstreg < 16; *dstreg += diff) {
5133197007Sdelphij		if ((srcval >> *dstreg) & 1)
5134197007Sdelphij			break;
5135197007Sdelphij	}
5136197007Sdelphij}
5137197007Sdelphij
5138197007Sdelphijstatic void
5139197007Sdelphijcommon_bitsearch(struct x86emu *emu, int diff)
5140197007Sdelphij{
5141197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5142197007Sdelphij		common_bitsearch32(emu, diff);
5143197007Sdelphij	else
5144197007Sdelphij		common_bitsearch16(emu, diff);
5145197007Sdelphij}
5146197007Sdelphij
5147197007Sdelphijstatic void
5148197007Sdelphijcommon_shift32(struct x86emu *emu, int shift_left, int use_cl)
5149197007Sdelphij{
5150197007Sdelphij	uint8_t shift;
5151197007Sdelphij	uint32_t destval, *shiftreg;
5152197007Sdelphij
5153197007Sdelphij	fetch_decode_modrm(emu);
5154197007Sdelphij	shiftreg = decode_rh_long_register(emu);
5155197007Sdelphij	if (use_cl) {
5156197007Sdelphij		destval = decode_and_fetch_long(emu);
5157197007Sdelphij		shift = emu->x86.R_CL;
5158197007Sdelphij	} else {
5159197007Sdelphij		destval = decode_and_fetch_long_imm8(emu, &shift);
5160197007Sdelphij	}
5161197007Sdelphij	if (shift_left)
5162197007Sdelphij		destval = shld_long(emu, destval, *shiftreg, shift);
5163197007Sdelphij	else
5164197007Sdelphij		destval = shrd_long(emu, destval, *shiftreg, shift);
5165197007Sdelphij	write_back_long(emu, destval);
5166197007Sdelphij}
5167197007Sdelphij
5168197007Sdelphijstatic void
5169197007Sdelphijcommon_shift16(struct x86emu *emu, int shift_left, int use_cl)
5170197007Sdelphij{
5171197007Sdelphij	uint8_t shift;
5172197007Sdelphij	uint16_t destval, *shiftreg;
5173197007Sdelphij
5174197007Sdelphij	fetch_decode_modrm(emu);
5175197007Sdelphij	shiftreg = decode_rh_word_register(emu);
5176197007Sdelphij	if (use_cl) {
5177197007Sdelphij		destval = decode_and_fetch_word(emu);
5178197007Sdelphij		shift = emu->x86.R_CL;
5179197007Sdelphij	} else {
5180197007Sdelphij		destval = decode_and_fetch_word_imm8(emu, &shift);
5181197007Sdelphij	}
5182197007Sdelphij	if (shift_left)
5183197007Sdelphij		destval = shld_word(emu, destval, *shiftreg, shift);
5184197007Sdelphij	else
5185197007Sdelphij		destval = shrd_word(emu, destval, *shiftreg, shift);
5186197007Sdelphij	write_back_word(emu, destval);
5187197007Sdelphij}
5188197007Sdelphij
5189197007Sdelphijstatic void
5190197007Sdelphijcommon_shift(struct x86emu *emu, int shift_left, int use_cl)
5191197007Sdelphij{
5192197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5193197007Sdelphij		common_shift32(emu, shift_left, use_cl);
5194197007Sdelphij	else
5195197007Sdelphij		common_shift16(emu, shift_left, use_cl);
5196197007Sdelphij}
5197197007Sdelphij
5198204934Sdelphij/*
5199204934Sdelphij * Implementation
5200204934Sdelphij */
5201197007Sdelphij#define xorl(a,b)   ((a) && !(b)) || (!(a) && (b))
5202197007Sdelphij
5203197007Sdelphij
5204197007Sdelphij/*
5205197007Sdelphij * REMARKS:
5206197007Sdelphij * Handles opcode 0x0f,0x31
5207197007Sdelphij */
5208197007Sdelphijstatic void
5209197007Sdelphijx86emuOp2_rdtsc(struct x86emu *emu)
5210197007Sdelphij{
5211197007Sdelphij	emu->x86.R_EAX = emu->cur_cycles & 0xffffffff;
5212197007Sdelphij	emu->x86.R_EDX = emu->cur_cycles >> 32;
5213197007Sdelphij}
5214197007Sdelphij
5215197007Sdelphij/*
5216197007Sdelphij * REMARKS:
5217197007Sdelphij * Handles opcode 0x0f,0xa0
5218197007Sdelphij */
5219197007Sdelphijstatic void
5220197007Sdelphijx86emuOp2_push_FS(struct x86emu *emu)
5221197007Sdelphij{
5222197007Sdelphij	push_word(emu, emu->x86.R_FS);
5223197007Sdelphij}
5224197007Sdelphij
5225197007Sdelphij/*
5226197007Sdelphij * REMARKS:
5227197007Sdelphij * Handles opcode 0x0f,0xa1
5228197007Sdelphij */
5229197007Sdelphijstatic void
5230197007Sdelphijx86emuOp2_pop_FS(struct x86emu *emu)
5231197007Sdelphij{
5232197007Sdelphij	emu->x86.R_FS = pop_word(emu);
5233197007Sdelphij}
5234197007Sdelphij
5235197007Sdelphij/*
5236197007Sdelphij * REMARKS:
5237197007Sdelphij * Handles opcode 0x0f,0xa1
5238197007Sdelphij */
5239197007Sdelphij#if defined(__i386__) || defined(__amd64__)
5240197007Sdelphijstatic void
5241197007Sdelphijhw_cpuid(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
5242197007Sdelphij{
5243197007Sdelphij	__asm__ __volatile__("cpuid"
5244197007Sdelphij			     : "=a" (*a), "=b" (*b),
5245197007Sdelphij			       "=c" (*c), "=d" (*d)
5246197007Sdelphij			     : "a" (*a), "c" (*c)
5247197007Sdelphij			     : "cc");
5248197007Sdelphij}
5249197007Sdelphij#endif
5250197007Sdelphijstatic void
5251197007Sdelphijx86emuOp2_cpuid(struct x86emu *emu)
5252197007Sdelphij{
5253197007Sdelphij#if defined(__i386__) || defined(__amd64__)
5254197007Sdelphij	hw_cpuid(&emu->x86.R_EAX, &emu->x86.R_EBX, &emu->x86.R_ECX,
5255197007Sdelphij	    &emu->x86.R_EDX);
5256197007Sdelphij#endif
5257197007Sdelphij	switch (emu->x86.R_EAX) {
5258197007Sdelphij	case 0:
5259197007Sdelphij		emu->x86.R_EAX = 1;
5260197007Sdelphij#if !defined(__i386__) && !defined(__amd64__)
5261197007Sdelphij		/* "GenuineIntel" */
5262197007Sdelphij		emu->x86.R_EBX = 0x756e6547;
5263197007Sdelphij		emu->x86.R_EDX = 0x49656e69;
5264197007Sdelphij		emu->x86.R_ECX = 0x6c65746e;
5265197007Sdelphij#endif
5266197007Sdelphij		break;
5267197007Sdelphij	case 1:
5268197007Sdelphij#if !defined(__i386__) && !defined(__amd64__)
5269197007Sdelphij		emu->x86.R_EAX = 0x00000480;
5270197007Sdelphij		emu->x86.R_EBX = emu->x86.R_ECX = 0;
5271197007Sdelphij		emu->x86.R_EDX = 0x00000002;
5272197007Sdelphij#else
5273197007Sdelphij		emu->x86.R_EDX &= 0x00000012;
5274197007Sdelphij#endif
5275197007Sdelphij		break;
5276197007Sdelphij	default:
5277197007Sdelphij		emu->x86.R_EAX = emu->x86.R_EBX = emu->x86.R_ECX =
5278197007Sdelphij		    emu->x86.R_EDX = 0;
5279197007Sdelphij		break;
5280197007Sdelphij	}
5281197007Sdelphij}
5282197007Sdelphij
5283197007Sdelphij/*
5284197007Sdelphij * REMARKS:
5285197007Sdelphij * Handles opcode 0x0f,0xa3
5286197007Sdelphij */
5287197007Sdelphijstatic void
5288197007Sdelphijx86emuOp2_bt_R(struct x86emu *emu)
5289197007Sdelphij{
5290197007Sdelphij	common_bitstring(emu, 0);
5291197007Sdelphij}
5292197007Sdelphij
5293197007Sdelphij/*
5294197007Sdelphij * REMARKS:
5295197007Sdelphij * Handles opcode 0x0f,0xa4
5296197007Sdelphij */
5297197007Sdelphijstatic void
5298197007Sdelphijx86emuOp2_shld_IMM(struct x86emu *emu)
5299197007Sdelphij{
5300197007Sdelphij	common_shift(emu, 1, 0);
5301197007Sdelphij}
5302197007Sdelphij
5303197007Sdelphij/*
5304197007Sdelphij * REMARKS:
5305197007Sdelphij * Handles opcode 0x0f,0xa5
5306197007Sdelphij */
5307197007Sdelphijstatic void
5308197007Sdelphijx86emuOp2_shld_CL(struct x86emu *emu)
5309197007Sdelphij{
5310197007Sdelphij	common_shift(emu, 1, 1);
5311197007Sdelphij}
5312197007Sdelphij
5313197007Sdelphij/*
5314197007Sdelphij * REMARKS:
5315197007Sdelphij * Handles opcode 0x0f,0xa8
5316197007Sdelphij */
5317197007Sdelphijstatic void
5318197007Sdelphijx86emuOp2_push_GS(struct x86emu *emu)
5319197007Sdelphij{
5320197007Sdelphij	push_word(emu, emu->x86.R_GS);
5321197007Sdelphij}
5322197007Sdelphij
5323197007Sdelphij/*
5324197007Sdelphij * REMARKS:
5325197007Sdelphij * Handles opcode 0x0f,0xa9
5326197007Sdelphij */
5327197007Sdelphijstatic void
5328197007Sdelphijx86emuOp2_pop_GS(struct x86emu *emu)
5329197007Sdelphij{
5330197007Sdelphij	emu->x86.R_GS = pop_word(emu);
5331197007Sdelphij}
5332197007Sdelphij
5333197007Sdelphij/*
5334197007Sdelphij * REMARKS:
5335197007Sdelphij * Handles opcode 0x0f,0xab
5336197007Sdelphij */
5337197007Sdelphijstatic void
5338197007Sdelphijx86emuOp2_bts_R(struct x86emu *emu)
5339197007Sdelphij{
5340197007Sdelphij	common_bitstring(emu, 1);
5341197007Sdelphij}
5342197007Sdelphij
5343197007Sdelphij/*
5344197007Sdelphij * REMARKS:
5345197007Sdelphij * Handles opcode 0x0f,0xac
5346197007Sdelphij */
5347197007Sdelphijstatic void
5348197007Sdelphijx86emuOp2_shrd_IMM(struct x86emu *emu)
5349197007Sdelphij{
5350197007Sdelphij	common_shift(emu, 0, 0);
5351197007Sdelphij}
5352197007Sdelphij
5353197007Sdelphij/*
5354197007Sdelphij * REMARKS:
5355197007Sdelphij * Handles opcode 0x0f,0xad
5356197007Sdelphij */
5357197007Sdelphijstatic void
5358197007Sdelphijx86emuOp2_shrd_CL(struct x86emu *emu)
5359197007Sdelphij{
5360197007Sdelphij	common_shift(emu, 0, 1);
5361197007Sdelphij}
5362197007Sdelphij
5363197007Sdelphij/*
5364197007Sdelphij * REMARKS:
5365197007Sdelphij * Handles opcode 0x0f,0xaf
5366197007Sdelphij */
5367197007Sdelphijstatic void
5368197007Sdelphijx86emuOp2_32_imul_R_RM(struct x86emu *emu)
5369197007Sdelphij{
5370197007Sdelphij	uint32_t *destreg, srcval;
5371197007Sdelphij	uint64_t res;
5372197007Sdelphij
5373197007Sdelphij	fetch_decode_modrm(emu);
5374197007Sdelphij	destreg = decode_rh_long_register(emu);
5375197007Sdelphij	srcval = decode_and_fetch_long(emu);
5376197007Sdelphij	res = (int32_t) *destreg * (int32_t)srcval;
5377197007Sdelphij	if (res > 0xffffffff) {
5378197007Sdelphij		SET_FLAG(F_CF);
5379197007Sdelphij		SET_FLAG(F_OF);
5380197007Sdelphij	} else {
5381197007Sdelphij		CLEAR_FLAG(F_CF);
5382197007Sdelphij		CLEAR_FLAG(F_OF);
5383197007Sdelphij	}
5384197007Sdelphij	*destreg = (uint32_t) res;
5385197007Sdelphij}
5386197007Sdelphij
5387197007Sdelphijstatic void
5388197007Sdelphijx86emuOp2_16_imul_R_RM(struct x86emu *emu)
5389197007Sdelphij{
5390197007Sdelphij	uint16_t *destreg, srcval;
5391197007Sdelphij	uint32_t res;
5392197007Sdelphij
5393197007Sdelphij	fetch_decode_modrm(emu);
5394197007Sdelphij	destreg = decode_rh_word_register(emu);
5395197007Sdelphij	srcval = decode_and_fetch_word(emu);
5396197007Sdelphij	res = (int16_t) * destreg * (int16_t)srcval;
5397197007Sdelphij	if (res > 0xFFFF) {
5398197007Sdelphij		SET_FLAG(F_CF);
5399197007Sdelphij		SET_FLAG(F_OF);
5400197007Sdelphij	} else {
5401197007Sdelphij		CLEAR_FLAG(F_CF);
5402197007Sdelphij		CLEAR_FLAG(F_OF);
5403197007Sdelphij	}
5404197007Sdelphij	*destreg = (uint16_t) res;
5405197007Sdelphij}
5406197007Sdelphij
5407197007Sdelphijstatic void
5408197007Sdelphijx86emuOp2_imul_R_RM(struct x86emu *emu)
5409197007Sdelphij{
5410197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5411197007Sdelphij		x86emuOp2_32_imul_R_RM(emu);
5412197007Sdelphij	else
5413197007Sdelphij		x86emuOp2_16_imul_R_RM(emu);
5414197007Sdelphij}
5415197007Sdelphij
5416197007Sdelphij/*
5417197007Sdelphij * REMARKS:
5418197007Sdelphij * Handles opcode 0x0f,0xb2
5419197007Sdelphij */
5420197007Sdelphijstatic void
5421197007Sdelphijx86emuOp2_lss_R_IMM(struct x86emu *emu)
5422197007Sdelphij{
5423197007Sdelphij	common_load_far_pointer(emu, &emu->x86.R_SS);
5424197007Sdelphij}
5425197007Sdelphij
5426197007Sdelphij/*
5427197007Sdelphij * REMARKS:
5428197007Sdelphij * Handles opcode 0x0f,0xb3
5429197007Sdelphij */
5430197007Sdelphijstatic void
5431197007Sdelphijx86emuOp2_btr_R(struct x86emu *emu)
5432197007Sdelphij{
5433197007Sdelphij	common_bitstring(emu, 2);
5434197007Sdelphij}
5435197007Sdelphij
5436197007Sdelphij/*
5437197007Sdelphij * REMARKS:
5438197007Sdelphij * Handles opcode 0x0f,0xb4
5439197007Sdelphij */
5440197007Sdelphijstatic void
5441197007Sdelphijx86emuOp2_lfs_R_IMM(struct x86emu *emu)
5442197007Sdelphij{
5443197007Sdelphij	common_load_far_pointer(emu, &emu->x86.R_FS);
5444197007Sdelphij}
5445197007Sdelphij
5446197007Sdelphij/*
5447197007Sdelphij * REMARKS:
5448197007Sdelphij * Handles opcode 0x0f,0xb5
5449197007Sdelphij */
5450197007Sdelphijstatic void
5451197007Sdelphijx86emuOp2_lgs_R_IMM(struct x86emu *emu)
5452197007Sdelphij{
5453197007Sdelphij	common_load_far_pointer(emu, &emu->x86.R_GS);
5454197007Sdelphij}
5455197007Sdelphij
5456197007Sdelphij/*
5457197007Sdelphij * REMARKS:
5458197007Sdelphij * Handles opcode 0x0f,0xb6
5459197007Sdelphij */
5460197007Sdelphijstatic void
5461197007Sdelphijx86emuOp2_32_movzx_byte_R_RM(struct x86emu *emu)
5462197007Sdelphij{
5463197007Sdelphij	uint32_t *destreg;
5464197007Sdelphij
5465197007Sdelphij	fetch_decode_modrm(emu);
5466197007Sdelphij	destreg = decode_rh_long_register(emu);
5467197007Sdelphij	*destreg = decode_and_fetch_byte(emu);
5468197007Sdelphij}
5469197007Sdelphij
5470197007Sdelphijstatic void
5471197007Sdelphijx86emuOp2_16_movzx_byte_R_RM(struct x86emu *emu)
5472197007Sdelphij{
5473197007Sdelphij	uint16_t *destreg;
5474197007Sdelphij
5475197007Sdelphij	fetch_decode_modrm(emu);
5476197007Sdelphij	destreg = decode_rh_word_register(emu);
5477197007Sdelphij	*destreg = decode_and_fetch_byte(emu);
5478197007Sdelphij}
5479197007Sdelphij
5480197007Sdelphijstatic void
5481197007Sdelphijx86emuOp2_movzx_byte_R_RM(struct x86emu *emu)
5482197007Sdelphij{
5483197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5484197007Sdelphij		x86emuOp2_32_movzx_byte_R_RM(emu);
5485197007Sdelphij	else
5486197007Sdelphij		x86emuOp2_16_movzx_byte_R_RM(emu);
5487197007Sdelphij}
5488197007Sdelphij
5489197007Sdelphij/*
5490197007Sdelphij * REMARKS:
5491197007Sdelphij * Handles opcode 0x0f,0xb7
5492197007Sdelphij */
5493197007Sdelphijstatic void
5494197007Sdelphijx86emuOp2_movzx_word_R_RM(struct x86emu *emu)
5495197007Sdelphij{
5496197007Sdelphij	uint32_t *destreg;
5497197007Sdelphij
5498197007Sdelphij	fetch_decode_modrm(emu);
5499197007Sdelphij	destreg = decode_rh_long_register(emu);
5500197007Sdelphij	*destreg = decode_and_fetch_word(emu);
5501197007Sdelphij}
5502197007Sdelphij
5503197007Sdelphij/*
5504197007Sdelphij * REMARKS:
5505197007Sdelphij * Handles opcode 0x0f,0xba
5506197007Sdelphij */
5507197007Sdelphijstatic void
5508197007Sdelphijx86emuOp2_32_btX_I(struct x86emu *emu)
5509197007Sdelphij{
5510197007Sdelphij	int bit;
5511197007Sdelphij	uint32_t srcval, mask;
5512197007Sdelphij	uint8_t shift;
5513197007Sdelphij
5514197007Sdelphij	fetch_decode_modrm(emu);
5515197007Sdelphij	if (emu->cur_rh < 4)
5516197007Sdelphij		x86emu_halt_sys(emu);
5517197007Sdelphij
5518197007Sdelphij	srcval = decode_and_fetch_long_imm8(emu, &shift);
5519197007Sdelphij	bit = shift & 0x1F;
5520197007Sdelphij	mask = (0x1 << bit);
5521197007Sdelphij
5522197007Sdelphij	switch (emu->cur_rh) {
5523197007Sdelphij	case 5:
5524197007Sdelphij		write_back_long(emu, srcval | mask);
5525197007Sdelphij		break;
5526197007Sdelphij	case 6:
5527197007Sdelphij		write_back_long(emu, srcval & ~mask);
5528197007Sdelphij		break;
5529197007Sdelphij	case 7:
5530197007Sdelphij		write_back_long(emu, srcval ^ mask);
5531197007Sdelphij		break;
5532197007Sdelphij	}
5533197007Sdelphij	CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5534197007Sdelphij}
5535197007Sdelphij
5536197007Sdelphijstatic void
5537197007Sdelphijx86emuOp2_16_btX_I(struct x86emu *emu)
5538197007Sdelphij{
5539197007Sdelphij	int bit;
5540197007Sdelphij
5541197007Sdelphij	uint16_t srcval, mask;
5542197007Sdelphij	uint8_t shift;
5543197007Sdelphij
5544197007Sdelphij	fetch_decode_modrm(emu);
5545197007Sdelphij	if (emu->cur_rh < 4)
5546197007Sdelphij		x86emu_halt_sys(emu);
5547197007Sdelphij
5548197007Sdelphij	srcval = decode_and_fetch_word_imm8(emu, &shift);
5549197007Sdelphij	bit = shift & 0xF;
5550197007Sdelphij	mask = (0x1 << bit);
5551197007Sdelphij	switch (emu->cur_rh) {
5552197007Sdelphij	case 5:
5553197007Sdelphij		write_back_word(emu, srcval | mask);
5554197007Sdelphij		break;
5555197007Sdelphij	case 6:
5556197007Sdelphij		write_back_word(emu, srcval & ~mask);
5557197007Sdelphij		break;
5558197007Sdelphij	case 7:
5559197007Sdelphij		write_back_word(emu, srcval ^ mask);
5560197007Sdelphij		break;
5561197007Sdelphij	}
5562197007Sdelphij	CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5563197007Sdelphij}
5564197007Sdelphij
5565197007Sdelphijstatic void
5566197007Sdelphijx86emuOp2_btX_I(struct x86emu *emu)
5567197007Sdelphij{
5568197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5569197007Sdelphij		x86emuOp2_32_btX_I(emu);
5570197007Sdelphij	else
5571197007Sdelphij		x86emuOp2_16_btX_I(emu);
5572197007Sdelphij}
5573197007Sdelphij
5574197007Sdelphij/*
5575197007Sdelphij * REMARKS:
5576197007Sdelphij * Handles opcode 0x0f,0xbb
5577197007Sdelphij */
5578197007Sdelphijstatic void
5579197007Sdelphijx86emuOp2_btc_R(struct x86emu *emu)
5580197007Sdelphij{
5581197007Sdelphij	common_bitstring(emu, 3);
5582197007Sdelphij}
5583197007Sdelphij
5584197007Sdelphij/*
5585197007Sdelphij * REMARKS:
5586197007Sdelphij * Handles opcode 0x0f,0xbc
5587197007Sdelphij */
5588197007Sdelphijstatic void
5589197007Sdelphijx86emuOp2_bsf(struct x86emu *emu)
5590197007Sdelphij{
5591197007Sdelphij	common_bitsearch(emu, +1);
5592197007Sdelphij}
5593197007Sdelphij
5594197007Sdelphij/*
5595197007Sdelphij * REMARKS:
5596197007Sdelphij * Handles opcode 0x0f,0xbd
5597197007Sdelphij */
5598197007Sdelphijstatic void
5599197007Sdelphijx86emuOp2_bsr(struct x86emu *emu)
5600197007Sdelphij{
5601197007Sdelphij	common_bitsearch(emu, -1);
5602197007Sdelphij}
5603197007Sdelphij
5604197007Sdelphij/*
5605197007Sdelphij * REMARKS:
5606197007Sdelphij * Handles opcode 0x0f,0xbe
5607197007Sdelphij */
5608197007Sdelphijstatic void
5609197007Sdelphijx86emuOp2_32_movsx_byte_R_RM(struct x86emu *emu)
5610197007Sdelphij{
5611197007Sdelphij	uint32_t *destreg;
5612197007Sdelphij
5613267372Sdelphij	fetch_decode_modrm(emu);
5614197007Sdelphij	destreg = decode_rh_long_register(emu);
5615197007Sdelphij	*destreg = (int32_t)(int8_t)decode_and_fetch_byte(emu);
5616197007Sdelphij}
5617197007Sdelphij
5618197007Sdelphijstatic void
5619197007Sdelphijx86emuOp2_16_movsx_byte_R_RM(struct x86emu *emu)
5620197007Sdelphij{
5621197007Sdelphij	uint16_t *destreg;
5622197007Sdelphij
5623197007Sdelphij	fetch_decode_modrm(emu);
5624197007Sdelphij	destreg = decode_rh_word_register(emu);
5625197007Sdelphij	*destreg = (int16_t)(int8_t)decode_and_fetch_byte(emu);
5626197007Sdelphij}
5627197007Sdelphij
5628197007Sdelphijstatic void
5629197007Sdelphijx86emuOp2_movsx_byte_R_RM(struct x86emu *emu)
5630197007Sdelphij{
5631197007Sdelphij	if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5632197007Sdelphij		x86emuOp2_32_movsx_byte_R_RM(emu);
5633197007Sdelphij	else
5634197007Sdelphij		x86emuOp2_16_movsx_byte_R_RM(emu);
5635197007Sdelphij}
5636197007Sdelphij
5637197007Sdelphij/*
5638197007Sdelphij * REMARKS:
5639197007Sdelphij * Handles opcode 0x0f,0xbf
5640197007Sdelphij */
5641197007Sdelphijstatic void
5642197007Sdelphijx86emuOp2_movsx_word_R_RM(struct x86emu *emu)
5643197007Sdelphij{
5644197007Sdelphij	uint32_t *destreg;
5645197007Sdelphij
5646197007Sdelphij	fetch_decode_modrm(emu);
5647197007Sdelphij	destreg = decode_rh_long_register(emu);
5648197007Sdelphij	*destreg = (int32_t)(int16_t)decode_and_fetch_word(emu);
5649197007Sdelphij}
5650197007Sdelphij
5651197007Sdelphijstatic void
5652197007Sdelphijx86emu_exec_two_byte(struct x86emu * emu)
5653197007Sdelphij{
5654197007Sdelphij	uint8_t op2;
5655197007Sdelphij
5656197007Sdelphij	op2 = fetch_byte_imm(emu);
5657197007Sdelphij
5658197007Sdelphij	switch (op2) {
5659197007Sdelphij	/* 0x00 Group F (ring 0 PM)      */
5660197007Sdelphij	/* 0x01 Group G (ring 0 PM)      */
5661197007Sdelphij	/* 0x02 lar (ring 0 PM)          */
5662197007Sdelphij	/* 0x03 lsl (ring 0 PM)          */
5663197007Sdelphij	/* 0x05 loadall (undocumented)   */
5664197007Sdelphij	/* 0x06 clts (ring 0 PM)         */
5665197007Sdelphij	/* 0x07 loadall (undocumented)   */
5666197007Sdelphij	/* 0x08 invd (ring 0 PM)         */
5667197007Sdelphij	/* 0x09 wbinvd (ring 0 PM)       */
5668197007Sdelphij
5669197007Sdelphij	/* 0x20 mov reg32(op2); break;creg (ring 0 PM) */
5670197007Sdelphij	/* 0x21 mov reg32(op2); break;dreg (ring 0 PM) */
5671197007Sdelphij	/* 0x22 mov creg(op2); break;reg32 (ring 0 PM) */
5672197007Sdelphij	/* 0x23 mov dreg(op2); break;reg32 (ring 0 PM) */
5673197007Sdelphij	/* 0x24 mov reg32(op2); break;treg (ring 0 PM) */
5674197007Sdelphij	/* 0x26 mov treg(op2); break;reg32 (ring 0 PM) */
5675197007Sdelphij
5676197007Sdelphij	case 0x31:
5677197007Sdelphij		x86emuOp2_rdtsc(emu);
5678197007Sdelphij		break;
5679197007Sdelphij
5680197007Sdelphij	case 0x80:
5681197007Sdelphij		common_jmp_long(emu, ACCESS_FLAG(F_OF));
5682197007Sdelphij		break;
5683197007Sdelphij	case 0x81:
5684197007Sdelphij		common_jmp_long(emu, !ACCESS_FLAG(F_OF));
5685197007Sdelphij		break;
5686197007Sdelphij	case 0x82:
5687197007Sdelphij		common_jmp_long(emu, ACCESS_FLAG(F_CF));
5688197007Sdelphij		break;
5689197007Sdelphij	case 0x83:
5690197007Sdelphij		common_jmp_long(emu, !ACCESS_FLAG(F_CF));
5691197007Sdelphij		break;
5692197007Sdelphij	case 0x84:
5693197007Sdelphij		common_jmp_long(emu, ACCESS_FLAG(F_ZF));
5694197007Sdelphij		break;
5695197007Sdelphij	case 0x85:
5696197007Sdelphij		common_jmp_long(emu, !ACCESS_FLAG(F_ZF));
5697197007Sdelphij		break;
5698197007Sdelphij	case 0x86:
5699197007Sdelphij		common_jmp_long(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5700197007Sdelphij		break;
5701197007Sdelphij	case 0x87:
5702197007Sdelphij		common_jmp_long(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5703197007Sdelphij		break;
5704197007Sdelphij	case 0x88:
5705197007Sdelphij		common_jmp_long(emu, ACCESS_FLAG(F_SF));
5706197007Sdelphij		break;
5707197007Sdelphij	case 0x89:
5708197007Sdelphij		common_jmp_long(emu, !ACCESS_FLAG(F_SF));
5709197007Sdelphij		break;
5710197007Sdelphij	case 0x8a:
5711197007Sdelphij		common_jmp_long(emu, ACCESS_FLAG(F_PF));
5712197007Sdelphij		break;
5713197007Sdelphij	case 0x8b:
5714197007Sdelphij		common_jmp_long(emu, !ACCESS_FLAG(F_PF));
5715197007Sdelphij		break;
5716197007Sdelphij	case 0x8c:
5717204934Sdelphij		common_jmp_long(emu, xorl(ACCESS_FLAG(F_SF),
5718204934Sdelphij		    ACCESS_FLAG(F_OF)));
5719197007Sdelphij		break;
5720197007Sdelphij	case 0x8d:
5721204934Sdelphij		common_jmp_long(emu, !(xorl(ACCESS_FLAG(F_SF),
5722204934Sdelphij		    ACCESS_FLAG(F_OF))));
5723197007Sdelphij		break;
5724197007Sdelphij	case 0x8e:
5725204934Sdelphij		common_jmp_long(emu, (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))
5726204934Sdelphij		    || ACCESS_FLAG(F_ZF)));
5727197007Sdelphij		break;
5728197007Sdelphij	case 0x8f:
5729204934Sdelphij		common_jmp_long(emu,
5730204934Sdelphij		    !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5731204934Sdelphij		    ACCESS_FLAG(F_ZF)));
5732197007Sdelphij		break;
5733197007Sdelphij
5734197007Sdelphij	case 0x90:
5735197007Sdelphij		common_set_byte(emu, ACCESS_FLAG(F_OF));
5736197007Sdelphij		break;
5737197007Sdelphij	case 0x91:
5738197007Sdelphij		common_set_byte(emu, !ACCESS_FLAG(F_OF));
5739197007Sdelphij		break;
5740197007Sdelphij	case 0x92:
5741197007Sdelphij		common_set_byte(emu, ACCESS_FLAG(F_CF));
5742197007Sdelphij		break;
5743197007Sdelphij	case 0x93:
5744197007Sdelphij		common_set_byte(emu, !ACCESS_FLAG(F_CF));
5745197007Sdelphij		break;
5746197007Sdelphij	case 0x94:
5747197007Sdelphij		common_set_byte(emu, ACCESS_FLAG(F_ZF));
5748197007Sdelphij		break;
5749197007Sdelphij	case 0x95:
5750197007Sdelphij		common_set_byte(emu, !ACCESS_FLAG(F_ZF));
5751197007Sdelphij		break;
5752197007Sdelphij	case 0x96:
5753197007Sdelphij		common_set_byte(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5754197007Sdelphij		break;
5755197007Sdelphij	case 0x97:
5756197007Sdelphij		common_set_byte(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5757197007Sdelphij		break;
5758197007Sdelphij	case 0x98:
5759197007Sdelphij		common_set_byte(emu, ACCESS_FLAG(F_SF));
5760197007Sdelphij		break;
5761197007Sdelphij	case 0x99:
5762197007Sdelphij		common_set_byte(emu, !ACCESS_FLAG(F_SF));
5763197007Sdelphij		break;
5764197007Sdelphij	case 0x9a:
5765197007Sdelphij		common_set_byte(emu, ACCESS_FLAG(F_PF));
5766197007Sdelphij		break;
5767197007Sdelphij	case 0x9b:
5768197007Sdelphij		common_set_byte(emu, !ACCESS_FLAG(F_PF));
5769197007Sdelphij		break;
5770197007Sdelphij	case 0x9c:
5771204934Sdelphij		common_set_byte(emu, xorl(ACCESS_FLAG(F_SF),
5772204934Sdelphij		    ACCESS_FLAG(F_OF)));
5773197007Sdelphij		break;
5774197007Sdelphij	case 0x9d:
5775204934Sdelphij		common_set_byte(emu, xorl(ACCESS_FLAG(F_SF),
5776204934Sdelphij		    ACCESS_FLAG(F_OF)));
5777197007Sdelphij		break;
5778197007Sdelphij	case 0x9e:
5779197007Sdelphij		common_set_byte(emu,
5780197007Sdelphij		    (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5781197007Sdelphij		    ACCESS_FLAG(F_ZF)));
5782197007Sdelphij		break;
5783197007Sdelphij	case 0x9f:
5784197007Sdelphij		common_set_byte(emu,
5785197007Sdelphij		    !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5786197007Sdelphij		    ACCESS_FLAG(F_ZF)));
5787197007Sdelphij		break;
5788197007Sdelphij
5789197007Sdelphij	case 0xa0:
5790197007Sdelphij		x86emuOp2_push_FS(emu);
5791197007Sdelphij		break;
5792197007Sdelphij	case 0xa1:
5793197007Sdelphij		x86emuOp2_pop_FS(emu);
5794197007Sdelphij		break;
5795197007Sdelphij	case 0xa2:
5796197007Sdelphij		x86emuOp2_cpuid(emu);
5797197007Sdelphij		break;
5798197007Sdelphij	case 0xa3:
5799197007Sdelphij		x86emuOp2_bt_R(emu);
5800197007Sdelphij		break;
5801197007Sdelphij	case 0xa4:
5802197007Sdelphij		x86emuOp2_shld_IMM(emu);
5803197007Sdelphij		break;
5804197007Sdelphij	case 0xa5:
5805197007Sdelphij		x86emuOp2_shld_CL(emu);
5806197007Sdelphij		break;
5807197007Sdelphij	case 0xa8:
5808197007Sdelphij		x86emuOp2_push_GS(emu);
5809197007Sdelphij		break;
5810197007Sdelphij	case 0xa9:
5811197007Sdelphij		x86emuOp2_pop_GS(emu);
5812197007Sdelphij		break;
5813197007Sdelphij	case 0xab:
5814197007Sdelphij		x86emuOp2_bts_R(emu);
5815197007Sdelphij		break;
5816197007Sdelphij	case 0xac:
5817197007Sdelphij		x86emuOp2_shrd_IMM(emu);
5818197007Sdelphij		break;
5819197007Sdelphij	case 0xad:
5820197007Sdelphij		x86emuOp2_shrd_CL(emu);
5821197007Sdelphij		break;
5822197007Sdelphij	case 0xaf:
5823197007Sdelphij		x86emuOp2_imul_R_RM(emu);
5824197007Sdelphij		break;
5825197007Sdelphij
5826197007Sdelphij	/* 0xb0 TODO: cmpxchg */
5827197007Sdelphij	/* 0xb1 TODO: cmpxchg */
5828197007Sdelphij	case 0xb2:
5829197007Sdelphij		x86emuOp2_lss_R_IMM(emu);
5830197007Sdelphij		break;
5831197007Sdelphij	case 0xb3:
5832197007Sdelphij		x86emuOp2_btr_R(emu);
5833197007Sdelphij		break;
5834197007Sdelphij	case 0xb4:
5835197007Sdelphij		x86emuOp2_lfs_R_IMM(emu);
5836197007Sdelphij		break;
5837197007Sdelphij	case 0xb5:
5838197007Sdelphij		x86emuOp2_lgs_R_IMM(emu);
5839197007Sdelphij		break;
5840197007Sdelphij	case 0xb6:
5841197007Sdelphij		x86emuOp2_movzx_byte_R_RM(emu);
5842197007Sdelphij		break;
5843197007Sdelphij	case 0xb7:
5844197007Sdelphij		x86emuOp2_movzx_word_R_RM(emu);
5845197007Sdelphij		break;
5846197007Sdelphij	case 0xba:
5847197007Sdelphij		x86emuOp2_btX_I(emu);
5848197007Sdelphij		break;
5849197007Sdelphij	case 0xbb:
5850197007Sdelphij		x86emuOp2_btc_R(emu);
5851197007Sdelphij		break;
5852197007Sdelphij	case 0xbc:
5853197007Sdelphij		x86emuOp2_bsf(emu);
5854197007Sdelphij		break;
5855197007Sdelphij	case 0xbd:
5856197007Sdelphij		x86emuOp2_bsr(emu);
5857197007Sdelphij		break;
5858197007Sdelphij	case 0xbe:
5859197007Sdelphij		x86emuOp2_movsx_byte_R_RM(emu);
5860197007Sdelphij		break;
5861197007Sdelphij	case 0xbf:
5862197007Sdelphij		x86emuOp2_movsx_word_R_RM(emu);
5863197007Sdelphij		break;
5864197007Sdelphij
5865197007Sdelphij	/* 0xc0 TODO: xadd */
5866197007Sdelphij	/* 0xc1 TODO: xadd */
5867197007Sdelphij	/* 0xc8 TODO: bswap */
5868197007Sdelphij	/* 0xc9 TODO: bswap */
5869197007Sdelphij	/* 0xca TODO: bswap */
5870197007Sdelphij	/* 0xcb TODO: bswap */
5871197007Sdelphij	/* 0xcc TODO: bswap */
5872197007Sdelphij	/* 0xcd TODO: bswap */
5873197007Sdelphij	/* 0xce TODO: bswap */
5874197007Sdelphij	/* 0xcf TODO: bswap */
5875197007Sdelphij
5876197007Sdelphij	default:
5877197007Sdelphij		x86emu_halt_sys(emu);
5878197007Sdelphij		break;
5879197007Sdelphij	}
5880197007Sdelphij}
5881197007Sdelphij
5882197007Sdelphij/*
5883204934Sdelphij * Carry Chain Calculation
5884204934Sdelphij *
5885204934Sdelphij * This represents a somewhat expensive calculation which is
5886204934Sdelphij * apparently required to emulate the setting of the OF and AF flag.
5887204934Sdelphij * The latter is not so important, but the former is.  The overflow
5888204934Sdelphij * flag is the XOR of the top two bits of the carry chain for an
5889204934Sdelphij * addition (similar for subtraction).  Since we do not want to
5890204934Sdelphij * simulate the addition in a bitwise manner, we try to calculate the
5891204934Sdelphij * carry chain given the two operands and the result.
5892204934Sdelphij *
5893204934Sdelphij * So, given the following table, which represents the addition of two
5894204934Sdelphij * bits, we can derive a formula for the carry chain.
5895204934Sdelphij *
5896204934Sdelphij * a   b   cin   r     cout
5897204934Sdelphij * 0   0   0     0     0
5898204934Sdelphij * 0   0   1     1     0
5899204934Sdelphij * 0   1   0     1     0
5900204934Sdelphij * 0   1   1     0     1
5901204934Sdelphij * 1   0   0     1     0
5902204934Sdelphij * 1   0   1     0     1
5903204934Sdelphij * 1   1   0     0     1
5904204934Sdelphij * 1   1   1     1     1
5905204934Sdelphij *
5906204934Sdelphij * Construction of table for cout:
5907204934Sdelphij *
5908204934Sdelphij * ab
5909204934Sdelphij * r  \  00   01   11  10
5910204934Sdelphij * |------------------
5911204934Sdelphij * 0  |   0    1    1   1
5912204934Sdelphij * 1  |   0    0    1   0
5913204934Sdelphij *
5914204934Sdelphij * By inspection, one gets:  cc = ab +  r'(a + b)
5915204934Sdelphij *
5916204934Sdelphij * That represents alot of operations, but NO CHOICE....
5917204934Sdelphij *
5918204934Sdelphij * Borrow Chain Calculation.
5919204934Sdelphij *
5920204934Sdelphij * The following table represents the subtraction of two bits, from
5921204934Sdelphij * which we can derive a formula for the borrow chain.
5922204934Sdelphij *
5923204934Sdelphij * a   b   bin   r     bout
5924204934Sdelphij * 0   0   0     0     0
5925204934Sdelphij * 0   0   1     1     1
5926204934Sdelphij * 0   1   0     1     1
5927204934Sdelphij * 0   1   1     0     1
5928204934Sdelphij * 1   0   0     1     0
5929204934Sdelphij * 1   0   1     0     0
5930204934Sdelphij * 1   1   0     0     0
5931204934Sdelphij * 1   1   1     1     1
5932204934Sdelphij *
5933204934Sdelphij * Construction of table for cout:
5934204934Sdelphij *
5935204934Sdelphij * ab
5936204934Sdelphij * r  \  00   01   11  10
5937204934Sdelphij * |------------------
5938204934Sdelphij * 0  |   0    1    0   0
5939204934Sdelphij * 1  |   1    1    1   0
5940204934Sdelphij *
5941204934Sdelphij * By inspection, one gets:  bc = a'b +  r(a' + b)
5942204934Sdelphij *
5943197007Sdelphij */
5944197007Sdelphij
5945204934Sdelphij/*
5946204934Sdelphij * Global Variables
5947204934Sdelphij */
5948197007Sdelphij
5949197007Sdelphijstatic uint32_t x86emu_parity_tab[8] =
5950197007Sdelphij{
5951197007Sdelphij	0x96696996,
5952197007Sdelphij	0x69969669,
5953197007Sdelphij	0x69969669,
5954197007Sdelphij	0x96696996,
5955197007Sdelphij	0x69969669,
5956197007Sdelphij	0x96696996,
5957197007Sdelphij	0x96696996,
5958197007Sdelphij	0x69969669,
5959197007Sdelphij};
5960197007Sdelphij#define PARITY(x)   (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
5961197007Sdelphij#define XOR2(x) 	(((x) ^ ((x)>>1)) & 0x1)
5962197007Sdelphij
5963197007Sdelphij
5964197007Sdelphij/*
5965197007Sdelphij * REMARKS:
5966197007Sdelphij * Implements the AAA instruction and side effects.
5967197007Sdelphij */
5968197007Sdelphijstatic uint16_t
5969197007Sdelphijaaa_word(struct x86emu *emu, uint16_t d)
5970197007Sdelphij{
5971197007Sdelphij	uint16_t res;
5972197007Sdelphij	if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
5973197007Sdelphij		d += 0x6;
5974197007Sdelphij		d += 0x100;
5975197007Sdelphij		SET_FLAG(F_AF);
5976197007Sdelphij		SET_FLAG(F_CF);
5977197007Sdelphij	} else {
5978197007Sdelphij		CLEAR_FLAG(F_CF);
5979197007Sdelphij		CLEAR_FLAG(F_AF);
5980197007Sdelphij	}
5981197007Sdelphij	res = (uint16_t) (d & 0xFF0F);
5982197007Sdelphij	CLEAR_FLAG(F_SF);
5983197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
5984197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5985197007Sdelphij	return res;
5986197007Sdelphij}
5987197007Sdelphij
5988197007Sdelphij/*
5989197007Sdelphij * REMARKS:
5990197007Sdelphij * Implements the AAA instruction and side effects.
5991197007Sdelphij */
5992197007Sdelphijstatic uint16_t
5993197007Sdelphijaas_word(struct x86emu *emu, uint16_t d)
5994197007Sdelphij{
5995197007Sdelphij	uint16_t res;
5996197007Sdelphij	if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
5997197007Sdelphij		d -= 0x6;
5998197007Sdelphij		d -= 0x100;
5999197007Sdelphij		SET_FLAG(F_AF);
6000197007Sdelphij		SET_FLAG(F_CF);
6001197007Sdelphij	} else {
6002197007Sdelphij		CLEAR_FLAG(F_CF);
6003197007Sdelphij		CLEAR_FLAG(F_AF);
6004197007Sdelphij	}
6005197007Sdelphij	res = (uint16_t) (d & 0xFF0F);
6006197007Sdelphij	CLEAR_FLAG(F_SF);
6007197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6008197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6009197007Sdelphij	return res;
6010197007Sdelphij}
6011197007Sdelphij
6012197007Sdelphij/*
6013197007Sdelphij * REMARKS:
6014197007Sdelphij * Implements the AAD instruction and side effects.
6015197007Sdelphij */
6016197007Sdelphijstatic uint16_t
6017197007Sdelphijaad_word(struct x86emu *emu, uint16_t d)
6018197007Sdelphij{
6019197007Sdelphij	uint16_t l;
6020197007Sdelphij	uint8_t hb, lb;
6021197007Sdelphij
6022197007Sdelphij	hb = (uint8_t) ((d >> 8) & 0xff);
6023197007Sdelphij	lb = (uint8_t) ((d & 0xff));
6024197007Sdelphij	l = (uint16_t) ((lb + 10 * hb) & 0xFF);
6025197007Sdelphij
6026197007Sdelphij	CLEAR_FLAG(F_CF);
6027197007Sdelphij	CLEAR_FLAG(F_AF);
6028197007Sdelphij	CLEAR_FLAG(F_OF);
6029197007Sdelphij	CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
6030197007Sdelphij	CONDITIONAL_SET_FLAG(l == 0, F_ZF);
6031197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
6032197007Sdelphij	return l;
6033197007Sdelphij}
6034197007Sdelphij
6035197007Sdelphij/*
6036197007Sdelphij * REMARKS:
6037197007Sdelphij * Implements the AAM instruction and side effects.
6038197007Sdelphij */
6039197007Sdelphijstatic uint16_t
6040197007Sdelphijaam_word(struct x86emu *emu, uint8_t d)
6041197007Sdelphij{
6042197007Sdelphij	uint16_t h, l;
6043197007Sdelphij
6044197007Sdelphij	h = (uint16_t) (d / 10);
6045197007Sdelphij	l = (uint16_t) (d % 10);
6046197007Sdelphij	l |= (uint16_t) (h << 8);
6047197007Sdelphij
6048197007Sdelphij	CLEAR_FLAG(F_CF);
6049197007Sdelphij	CLEAR_FLAG(F_AF);
6050197007Sdelphij	CLEAR_FLAG(F_OF);
6051197007Sdelphij	CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
6052197007Sdelphij	CONDITIONAL_SET_FLAG(l == 0, F_ZF);
6053197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
6054197007Sdelphij	return l;
6055197007Sdelphij}
6056197007Sdelphij
6057197007Sdelphij/*
6058197007Sdelphij * REMARKS:
6059197007Sdelphij * Implements the ADC instruction and side effects.
6060197007Sdelphij */
6061197007Sdelphijstatic uint8_t
6062197007Sdelphijadc_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6063197007Sdelphij{
6064197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6065197007Sdelphij	uint32_t cc;
6066197007Sdelphij
6067197007Sdelphij	if (ACCESS_FLAG(F_CF))
6068197007Sdelphij		res = 1 + d + s;
6069197007Sdelphij	else
6070197007Sdelphij		res = d + s;
6071197007Sdelphij
6072197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
6073197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6074197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6075197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6076197007Sdelphij
6077197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6078197007Sdelphij	cc = (s & d) | ((~res) & (s | d));
6079197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6080197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6081197007Sdelphij	return (uint8_t) res;
6082197007Sdelphij}
6083197007Sdelphij
6084197007Sdelphij/*
6085197007Sdelphij * REMARKS:
6086197007Sdelphij * Implements the ADC instruction and side effects.
6087197007Sdelphij */
6088197007Sdelphijstatic uint16_t
6089197007Sdelphijadc_word(struct x86emu *emu, uint16_t d, uint16_t s)
6090197007Sdelphij{
6091197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6092197007Sdelphij	uint32_t cc;
6093197007Sdelphij
6094197007Sdelphij	if (ACCESS_FLAG(F_CF))
6095197007Sdelphij		res = 1 + d + s;
6096197007Sdelphij	else
6097197007Sdelphij		res = d + s;
6098197007Sdelphij
6099197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
6100197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6101197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6102197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6103197007Sdelphij
6104197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6105197007Sdelphij	cc = (s & d) | ((~res) & (s | d));
6106197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6107197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6108197007Sdelphij	return (uint16_t) res;
6109197007Sdelphij}
6110197007Sdelphij
6111197007Sdelphij/*
6112197007Sdelphij * REMARKS:
6113197007Sdelphij * Implements the ADC instruction and side effects.
6114197007Sdelphij */
6115197007Sdelphijstatic uint32_t
6116197007Sdelphijadc_long(struct x86emu *emu, uint32_t d, uint32_t s)
6117197007Sdelphij{
6118197007Sdelphij	uint32_t lo;	/* all operands in native machine order */
6119197007Sdelphij	uint32_t hi;
6120197007Sdelphij	uint32_t res;
6121197007Sdelphij	uint32_t cc;
6122197007Sdelphij
6123197007Sdelphij	if (ACCESS_FLAG(F_CF)) {
6124197007Sdelphij		lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
6125197007Sdelphij		res = 1 + d + s;
6126197007Sdelphij	} else {
6127197007Sdelphij		lo = (d & 0xFFFF) + (s & 0xFFFF);
6128197007Sdelphij		res = d + s;
6129197007Sdelphij	}
6130197007Sdelphij	hi = (lo >> 16) + (d >> 16) + (s >> 16);
6131197007Sdelphij
6132197007Sdelphij	CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
6133197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6134197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6135197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6136197007Sdelphij
6137197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6138197007Sdelphij	cc = (s & d) | ((~res) & (s | d));
6139197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6140197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6141197007Sdelphij	return res;
6142197007Sdelphij}
6143197007Sdelphij
6144197007Sdelphij/*
6145197007Sdelphij * REMARKS:
6146197007Sdelphij * Implements the ADD instruction and side effects.
6147197007Sdelphij */
6148197007Sdelphijstatic uint8_t
6149197007Sdelphijadd_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6150197007Sdelphij{
6151197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6152197007Sdelphij	uint32_t cc;
6153197007Sdelphij
6154197007Sdelphij	res = d + s;
6155197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
6156197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6157197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6158197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6159197007Sdelphij
6160197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6161197007Sdelphij	cc = (s & d) | ((~res) & (s | d));
6162197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6163197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6164197007Sdelphij	return (uint8_t) res;
6165197007Sdelphij}
6166197007Sdelphij
6167197007Sdelphij/*
6168197007Sdelphij * REMARKS:
6169197007Sdelphij * Implements the ADD instruction and side effects.
6170197007Sdelphij */
6171197007Sdelphijstatic uint16_t
6172197007Sdelphijadd_word(struct x86emu *emu, uint16_t d, uint16_t s)
6173197007Sdelphij{
6174197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6175197007Sdelphij	uint32_t cc;
6176197007Sdelphij
6177197007Sdelphij	res = d + s;
6178197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
6179197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6180197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6181197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6182197007Sdelphij
6183197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6184197007Sdelphij	cc = (s & d) | ((~res) & (s | d));
6185197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6186197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6187197007Sdelphij	return (uint16_t) res;
6188197007Sdelphij}
6189197007Sdelphij
6190197007Sdelphij/*
6191197007Sdelphij * REMARKS:
6192197007Sdelphij * Implements the ADD instruction and side effects.
6193197007Sdelphij */
6194197007Sdelphijstatic uint32_t
6195197007Sdelphijadd_long(struct x86emu *emu, uint32_t d, uint32_t s)
6196197007Sdelphij{
6197197007Sdelphij	uint32_t lo;	/* all operands in native machine order */
6198197007Sdelphij	uint32_t hi;
6199197007Sdelphij	uint32_t res;
6200197007Sdelphij	uint32_t cc;
6201197007Sdelphij
6202197007Sdelphij	lo = (d & 0xFFFF) + (s & 0xFFFF);
6203197007Sdelphij	res = d + s;
6204197007Sdelphij	hi = (lo >> 16) + (d >> 16) + (s >> 16);
6205197007Sdelphij
6206197007Sdelphij	CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
6207197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6208197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6209197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6210197007Sdelphij
6211197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6212197007Sdelphij	cc = (s & d) | ((~res) & (s | d));
6213197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6214197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6215197007Sdelphij
6216197007Sdelphij	return res;
6217197007Sdelphij}
6218197007Sdelphij
6219197007Sdelphij/*
6220197007Sdelphij * REMARKS:
6221197007Sdelphij * Implements the AND instruction and side effects.
6222197007Sdelphij */
6223197007Sdelphijstatic uint8_t
6224197007Sdelphijand_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6225197007Sdelphij{
6226197007Sdelphij	uint8_t res;	/* all operands in native machine order */
6227197007Sdelphij
6228197007Sdelphij	res = d & s;
6229197007Sdelphij
6230197007Sdelphij	/* set the flags  */
6231197007Sdelphij	CLEAR_FLAG(F_OF);
6232197007Sdelphij	CLEAR_FLAG(F_CF);
6233197007Sdelphij	CLEAR_FLAG(F_AF);
6234197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6235197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6236197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6237197007Sdelphij	return res;
6238197007Sdelphij}
6239197007Sdelphij
6240197007Sdelphij/*
6241197007Sdelphij * REMARKS:
6242197007Sdelphij * Implements the AND instruction and side effects.
6243197007Sdelphij */
6244197007Sdelphijstatic uint16_t
6245197007Sdelphijand_word(struct x86emu *emu, uint16_t d, uint16_t s)
6246197007Sdelphij{
6247197007Sdelphij	uint16_t res;	/* all operands in native machine order */
6248197007Sdelphij
6249197007Sdelphij	res = d & s;
6250197007Sdelphij
6251197007Sdelphij	/* set the flags  */
6252197007Sdelphij	CLEAR_FLAG(F_OF);
6253197007Sdelphij	CLEAR_FLAG(F_CF);
6254197007Sdelphij	CLEAR_FLAG(F_AF);
6255197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6256197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6257197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6258197007Sdelphij	return res;
6259197007Sdelphij}
6260197007Sdelphij
6261197007Sdelphij/*
6262197007Sdelphij * REMARKS:
6263197007Sdelphij * Implements the AND instruction and side effects.
6264197007Sdelphij */
6265197007Sdelphijstatic uint32_t
6266197007Sdelphijand_long(struct x86emu *emu, uint32_t d, uint32_t s)
6267197007Sdelphij{
6268197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6269197007Sdelphij
6270197007Sdelphij	res = d & s;
6271197007Sdelphij
6272197007Sdelphij	/* set the flags  */
6273197007Sdelphij	CLEAR_FLAG(F_OF);
6274197007Sdelphij	CLEAR_FLAG(F_CF);
6275197007Sdelphij	CLEAR_FLAG(F_AF);
6276197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6277197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6278197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6279197007Sdelphij	return res;
6280197007Sdelphij}
6281197007Sdelphij
6282197007Sdelphij/*
6283197007Sdelphij * REMARKS:
6284197007Sdelphij * Implements the CMP instruction and side effects.
6285197007Sdelphij */
6286197007Sdelphijstatic uint8_t
6287197007Sdelphijcmp_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6288197007Sdelphij{
6289197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6290197007Sdelphij	uint32_t bc;
6291197007Sdelphij
6292197007Sdelphij	res = d - s;
6293197007Sdelphij	CLEAR_FLAG(F_CF);
6294197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6295197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6296197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6297197007Sdelphij
6298197007Sdelphij	/* calculate the borrow chain.  See note at top */
6299197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
6300197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
6301197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6302197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6303197007Sdelphij	return d;
6304197007Sdelphij}
6305197007Sdelphij
6306197007Sdelphijstatic void
6307197007Sdelphijcmp_byte_no_return(struct x86emu *emu, uint8_t d, uint8_t s)
6308197007Sdelphij{
6309197007Sdelphij	cmp_byte(emu, d, s);
6310197007Sdelphij}
6311197007Sdelphij
6312197007Sdelphij/*
6313197007Sdelphij * REMARKS:
6314197007Sdelphij * Implements the CMP instruction and side effects.
6315197007Sdelphij */
6316197007Sdelphijstatic uint16_t
6317197007Sdelphijcmp_word(struct x86emu *emu, uint16_t d, uint16_t s)
6318197007Sdelphij{
6319197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6320197007Sdelphij	uint32_t bc;
6321197007Sdelphij
6322197007Sdelphij	res = d - s;
6323197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6324197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6325197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6326197007Sdelphij
6327197007Sdelphij	/* calculate the borrow chain.  See note at top */
6328197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
6329197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
6330197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6331197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6332197007Sdelphij	return d;
6333197007Sdelphij}
6334197007Sdelphij
6335197007Sdelphijstatic void
6336197007Sdelphijcmp_word_no_return(struct x86emu *emu, uint16_t d, uint16_t s)
6337197007Sdelphij{
6338197007Sdelphij	cmp_word(emu, d, s);
6339197007Sdelphij}
6340197007Sdelphij
6341197007Sdelphij/*
6342197007Sdelphij * REMARKS:
6343197007Sdelphij * Implements the CMP instruction and side effects.
6344197007Sdelphij */
6345197007Sdelphijstatic uint32_t
6346197007Sdelphijcmp_long(struct x86emu *emu, uint32_t d, uint32_t s)
6347197007Sdelphij{
6348197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6349197007Sdelphij	uint32_t bc;
6350197007Sdelphij
6351197007Sdelphij	res = d - s;
6352197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6353197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6354197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6355197007Sdelphij
6356197007Sdelphij	/* calculate the borrow chain.  See note at top */
6357197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
6358197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
6359197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6360197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6361197007Sdelphij	return d;
6362197007Sdelphij}
6363197007Sdelphij
6364197007Sdelphijstatic void
6365197007Sdelphijcmp_long_no_return(struct x86emu *emu, uint32_t d, uint32_t s)
6366197007Sdelphij{
6367197007Sdelphij	cmp_long(emu, d, s);
6368197007Sdelphij}
6369197007Sdelphij
6370197007Sdelphij/*
6371197007Sdelphij * REMARKS:
6372197007Sdelphij * Implements the DAA instruction and side effects.
6373197007Sdelphij */
6374197007Sdelphijstatic uint8_t
6375197007Sdelphijdaa_byte(struct x86emu *emu, uint8_t d)
6376197007Sdelphij{
6377197007Sdelphij	uint32_t res = d;
6378197007Sdelphij	if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6379197007Sdelphij		res += 6;
6380197007Sdelphij		SET_FLAG(F_AF);
6381197007Sdelphij	}
6382197007Sdelphij	if (res > 0x9F || ACCESS_FLAG(F_CF)) {
6383197007Sdelphij		res += 0x60;
6384197007Sdelphij		SET_FLAG(F_CF);
6385197007Sdelphij	}
6386197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6387197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
6388197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6389197007Sdelphij	return (uint8_t) res;
6390197007Sdelphij}
6391197007Sdelphij
6392197007Sdelphij/*
6393197007Sdelphij * REMARKS:
6394197007Sdelphij * Implements the DAS instruction and side effects.
6395197007Sdelphij */
6396197007Sdelphijstatic uint8_t
6397197007Sdelphijdas_byte(struct x86emu *emu, uint8_t d)
6398197007Sdelphij{
6399197007Sdelphij	if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6400197007Sdelphij		d -= 6;
6401197007Sdelphij		SET_FLAG(F_AF);
6402197007Sdelphij	}
6403197007Sdelphij	if (d > 0x9F || ACCESS_FLAG(F_CF)) {
6404197007Sdelphij		d -= 0x60;
6405197007Sdelphij		SET_FLAG(F_CF);
6406197007Sdelphij	}
6407197007Sdelphij	CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
6408197007Sdelphij	CONDITIONAL_SET_FLAG(d == 0, F_ZF);
6409197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
6410197007Sdelphij	return d;
6411197007Sdelphij}
6412197007Sdelphij
6413197007Sdelphij/*
6414197007Sdelphij * REMARKS:
6415197007Sdelphij * Implements the DEC instruction and side effects.
6416197007Sdelphij */
6417197007Sdelphijstatic uint8_t
6418197007Sdelphijdec_byte(struct x86emu *emu, uint8_t d)
6419197007Sdelphij{
6420197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6421197007Sdelphij	uint32_t bc;
6422197007Sdelphij
6423197007Sdelphij	res = d - 1;
6424197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6425197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6426197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6427197007Sdelphij
6428197007Sdelphij	/* calculate the borrow chain.  See note at top */
6429197007Sdelphij	/* based on sub_byte, uses s==1.  */
6430197007Sdelphij	bc = (res & (~d | 1)) | (~d & 1);
6431197007Sdelphij	/* carry flag unchanged */
6432197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6433197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6434197007Sdelphij	return (uint8_t) res;
6435197007Sdelphij}
6436197007Sdelphij
6437197007Sdelphij/*
6438197007Sdelphij * REMARKS:
6439197007Sdelphij * Implements the DEC instruction and side effects.
6440197007Sdelphij */
6441197007Sdelphijstatic uint16_t
6442197007Sdelphijdec_word(struct x86emu *emu, uint16_t d)
6443197007Sdelphij{
6444197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6445197007Sdelphij	uint32_t bc;
6446197007Sdelphij
6447197007Sdelphij	res = d - 1;
6448197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6449197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6450197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6451197007Sdelphij
6452197007Sdelphij	/* calculate the borrow chain.  See note at top */
6453197007Sdelphij	/* based on the sub_byte routine, with s==1 */
6454197007Sdelphij	bc = (res & (~d | 1)) | (~d & 1);
6455197007Sdelphij	/* carry flag unchanged */
6456197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6457197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6458197007Sdelphij	return (uint16_t) res;
6459197007Sdelphij}
6460197007Sdelphij
6461197007Sdelphij/*
6462197007Sdelphij * REMARKS:
6463197007Sdelphij * Implements the DEC instruction and side effects.
6464197007Sdelphij */
6465197007Sdelphijstatic uint32_t
6466197007Sdelphijdec_long(struct x86emu *emu, uint32_t d)
6467197007Sdelphij{
6468197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6469197007Sdelphij	uint32_t bc;
6470197007Sdelphij
6471197007Sdelphij	res = d - 1;
6472197007Sdelphij
6473197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6474197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6475197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6476197007Sdelphij
6477197007Sdelphij	/* calculate the borrow chain.  See note at top */
6478197007Sdelphij	bc = (res & (~d | 1)) | (~d & 1);
6479197007Sdelphij	/* carry flag unchanged */
6480197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6481197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6482197007Sdelphij	return res;
6483197007Sdelphij}
6484197007Sdelphij
6485197007Sdelphij/*
6486197007Sdelphij * REMARKS:
6487197007Sdelphij * Implements the INC instruction and side effects.
6488197007Sdelphij */
6489197007Sdelphijstatic uint8_t
6490197007Sdelphijinc_byte(struct x86emu *emu, uint8_t d)
6491197007Sdelphij{
6492197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6493197007Sdelphij	uint32_t cc;
6494197007Sdelphij
6495197007Sdelphij	res = d + 1;
6496197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6497197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6498197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6499197007Sdelphij
6500197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6501197007Sdelphij	cc = ((1 & d) | (~res)) & (1 | d);
6502197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6503197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6504197007Sdelphij	return (uint8_t) res;
6505197007Sdelphij}
6506197007Sdelphij
6507197007Sdelphij/*
6508197007Sdelphij * REMARKS:
6509197007Sdelphij * Implements the INC instruction and side effects.
6510197007Sdelphij */
6511197007Sdelphijstatic uint16_t
6512197007Sdelphijinc_word(struct x86emu *emu, uint16_t d)
6513197007Sdelphij{
6514197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6515197007Sdelphij	uint32_t cc;
6516197007Sdelphij
6517197007Sdelphij	res = d + 1;
6518197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6519197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6520197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6521197007Sdelphij
6522197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6523197007Sdelphij	cc = (1 & d) | ((~res) & (1 | d));
6524197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6525197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6526197007Sdelphij	return (uint16_t) res;
6527197007Sdelphij}
6528197007Sdelphij
6529197007Sdelphij/*
6530197007Sdelphij * REMARKS:
6531197007Sdelphij * Implements the INC instruction and side effects.
6532197007Sdelphij */
6533197007Sdelphijstatic uint32_t
6534197007Sdelphijinc_long(struct x86emu *emu, uint32_t d)
6535197007Sdelphij{
6536197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6537197007Sdelphij	uint32_t cc;
6538197007Sdelphij
6539197007Sdelphij	res = d + 1;
6540197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6541197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6542197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6543197007Sdelphij
6544197007Sdelphij	/* calculate the carry chain  SEE NOTE AT TOP. */
6545197007Sdelphij	cc = (1 & d) | ((~res) & (1 | d));
6546197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6547197007Sdelphij	CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6548197007Sdelphij	return res;
6549197007Sdelphij}
6550197007Sdelphij
6551197007Sdelphij/*
6552197007Sdelphij * REMARKS:
6553197007Sdelphij * Implements the OR instruction and side effects.
6554197007Sdelphij */
6555197007Sdelphijstatic uint8_t
6556197007Sdelphijor_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6557197007Sdelphij{
6558197007Sdelphij	uint8_t res;	/* all operands in native machine order */
6559197007Sdelphij
6560197007Sdelphij	res = d | s;
6561197007Sdelphij	CLEAR_FLAG(F_OF);
6562197007Sdelphij	CLEAR_FLAG(F_CF);
6563197007Sdelphij	CLEAR_FLAG(F_AF);
6564197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6565197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6566197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6567197007Sdelphij	return res;
6568197007Sdelphij}
6569197007Sdelphij
6570197007Sdelphij/*
6571197007Sdelphij * REMARKS:
6572197007Sdelphij * Implements the OR instruction and side effects.
6573197007Sdelphij */
6574197007Sdelphijstatic uint16_t
6575197007Sdelphijor_word(struct x86emu *emu, uint16_t d, uint16_t s)
6576197007Sdelphij{
6577197007Sdelphij	uint16_t res;	/* all operands in native machine order */
6578197007Sdelphij
6579197007Sdelphij	res = d | s;
6580197007Sdelphij	/* set the carry flag to be bit 8 */
6581197007Sdelphij	CLEAR_FLAG(F_OF);
6582197007Sdelphij	CLEAR_FLAG(F_CF);
6583197007Sdelphij	CLEAR_FLAG(F_AF);
6584197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6585197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6586197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6587197007Sdelphij	return res;
6588197007Sdelphij}
6589197007Sdelphij
6590197007Sdelphij/*
6591197007Sdelphij * REMARKS:
6592197007Sdelphij * Implements the OR instruction and side effects.
6593197007Sdelphij */
6594197007Sdelphijstatic uint32_t
6595197007Sdelphijor_long(struct x86emu *emu, uint32_t d, uint32_t s)
6596197007Sdelphij{
6597197007Sdelphij	uint32_t res;	/* all operands in native machine order */
6598197007Sdelphij
6599197007Sdelphij	res = d | s;
6600197007Sdelphij
6601197007Sdelphij	/* set the carry flag to be bit 8 */
6602197007Sdelphij	CLEAR_FLAG(F_OF);
6603197007Sdelphij	CLEAR_FLAG(F_CF);
6604197007Sdelphij	CLEAR_FLAG(F_AF);
6605197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6606197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6607197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6608197007Sdelphij	return res;
6609197007Sdelphij}
6610197007Sdelphij
6611197007Sdelphij/*
6612197007Sdelphij * REMARKS:
6613197007Sdelphij * Implements the OR instruction and side effects.
6614197007Sdelphij */
6615197007Sdelphijstatic uint8_t
6616197007Sdelphijneg_byte(struct x86emu *emu, uint8_t s)
6617197007Sdelphij{
6618197007Sdelphij	uint8_t res;
6619197007Sdelphij	uint8_t bc;
6620197007Sdelphij
6621197007Sdelphij	CONDITIONAL_SET_FLAG(s != 0, F_CF);
6622197007Sdelphij	res = (uint8_t) - s;
6623197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6624197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6625197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6626197007Sdelphij	/* calculate the borrow chain --- modified such that d=0.
6627197007Sdelphij	 * substitutiing d=0 into     bc= res&(~d|s)|(~d&s); (the one used for
6628197007Sdelphij	 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6629197007Sdelphij	 * res&0xfff... == res.  Similarly ~d&s == s.  So the simplified
6630197007Sdelphij	 * result is: */
6631197007Sdelphij	bc = res | s;
6632197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6633197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6634197007Sdelphij	return res;
6635197007Sdelphij}
6636197007Sdelphij
6637197007Sdelphij/*
6638197007Sdelphij * REMARKS:
6639197007Sdelphij * Implements the OR instruction and side effects.
6640197007Sdelphij */
6641197007Sdelphijstatic uint16_t
6642197007Sdelphijneg_word(struct x86emu *emu, uint16_t s)
6643197007Sdelphij{
6644197007Sdelphij	uint16_t res;
6645197007Sdelphij	uint16_t bc;
6646197007Sdelphij
6647197007Sdelphij	CONDITIONAL_SET_FLAG(s != 0, F_CF);
6648197007Sdelphij	res = (uint16_t) - s;
6649197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6650197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6651197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6652197007Sdelphij
6653197007Sdelphij	/* calculate the borrow chain --- modified such that d=0.
6654197007Sdelphij	 * substitutiing d=0 into     bc= res&(~d|s)|(~d&s); (the one used for
6655197007Sdelphij	 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6656197007Sdelphij	 * res&0xfff... == res.  Similarly ~d&s == s.  So the simplified
6657197007Sdelphij	 * result is: */
6658197007Sdelphij	bc = res | s;
6659197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6660197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6661197007Sdelphij	return res;
6662197007Sdelphij}
6663197007Sdelphij
6664197007Sdelphij/*
6665197007Sdelphij * REMARKS:
6666197007Sdelphij * Implements the OR instruction and side effects.
6667197007Sdelphij */
6668197007Sdelphijstatic uint32_t
6669197007Sdelphijneg_long(struct x86emu *emu, uint32_t s)
6670197007Sdelphij{
6671197007Sdelphij	uint32_t res;
6672197007Sdelphij	uint32_t bc;
6673197007Sdelphij
6674197007Sdelphij	CONDITIONAL_SET_FLAG(s != 0, F_CF);
6675197007Sdelphij	res = (uint32_t) - s;
6676197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6677197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6678197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6679197007Sdelphij
6680197007Sdelphij	/* calculate the borrow chain --- modified such that d=0.
6681197007Sdelphij	 * substitutiing d=0 into     bc= res&(~d|s)|(~d&s); (the one used for
6682197007Sdelphij	 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6683197007Sdelphij	 * res&0xfff... == res.  Similarly ~d&s == s.  So the simplified
6684197007Sdelphij	 * result is: */
6685197007Sdelphij	bc = res | s;
6686197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6687197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6688197007Sdelphij	return res;
6689197007Sdelphij}
6690197007Sdelphij
6691197007Sdelphij/*
6692197007Sdelphij * REMARKS:
6693197007Sdelphij * Implements the RCL instruction and side effects.
6694197007Sdelphij */
6695197007Sdelphijstatic uint8_t
6696197007Sdelphijrcl_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6697197007Sdelphij{
6698197007Sdelphij	unsigned int res, cnt, mask, cf;
6699197007Sdelphij
6700197007Sdelphij	/* s is the rotate distance.  It varies from 0 - 8. */
6701197007Sdelphij	/* have
6702197007Sdelphij	 *
6703197007Sdelphij	 * CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6704197007Sdelphij	 *
6705197007Sdelphij	 * want to rotate through the carry by "s" bits.  We could loop, but
6706197007Sdelphij	 * that's inefficient.  So the width is 9, and we split into three
6707197007Sdelphij	 * parts:
6708197007Sdelphij	 *
6709204934Sdelphij	 * The new carry flag   (was B_n) the stuff in B_n-1 .. B_0 the stuff
6710204934Sdelphij	 * in B_7 .. B_n+1
6711197007Sdelphij	 *
6712204934Sdelphij	 * The new rotate is done mod 9, and given this, for a rotation of n
6713204934Sdelphij	 * bits (mod 9) the new carry flag is then located n bits from the MSB.
6714197007Sdelphij	 * The low part is then shifted up cnt bits, and the high part is or'd
6715197007Sdelphij	 * in.  Using CAPS for new values, and lowercase for the original
6716197007Sdelphij	 * values, this can be expressed as:
6717197007Sdelphij	 *
6718197007Sdelphij	 * IF n > 0 1) CF <-  b_(8-n) 2) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0
6719204934Sdelphij	 * 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1))
6720204934Sdelphij	 */
6721197007Sdelphij	res = d;
6722197007Sdelphij	if ((cnt = s % 9) != 0) {
6723197007Sdelphij		/* extract the new CARRY FLAG. */
6724197007Sdelphij		/* CF <-  b_(8-n)             */
6725197007Sdelphij		cf = (d >> (8 - cnt)) & 0x1;
6726197007Sdelphij
6727204934Sdelphij		/*
6728204934Sdelphij		 * Get the low stuff which rotated into the range B_7 .. B_cnt
6729204934Sdelphij		 * B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0
6730204934Sdelphij		 * note that the right hand side done by the mask.
6731204934Sdelphij		 */
6732197007Sdelphij		res = (d << cnt) & 0xff;
6733197007Sdelphij
6734204934Sdelphij		/*
6735204934Sdelphij		 * now the high stuff which rotated around into the positions
6736204934Sdelphij		 * B_cnt-2 .. B_0
6737204934Sdelphij		 * B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1))
6738204934Sdelphij		 * shift it downward, 7-(n-2) = 9-n positions. and mask off
6739204934Sdelphij		 * the result before or'ing in.
6740204934Sdelphij		 */
6741197007Sdelphij		mask = (1 << (cnt - 1)) - 1;
6742197007Sdelphij		res |= (d >> (9 - cnt)) & mask;
6743197007Sdelphij
6744197007Sdelphij		/* if the carry flag was set, or it in.  */
6745197007Sdelphij		if (ACCESS_FLAG(F_CF)) {	/* carry flag is set */
6746197007Sdelphij			/* B_(n-1) <- cf */
6747197007Sdelphij			res |= 1 << (cnt - 1);
6748197007Sdelphij		}
6749197007Sdelphij		/* set the new carry flag, based on the variable "cf" */
6750197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
6751197007Sdelphij		/* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6752197007Sdelphij		 * the most significant bit.  Blecck. */
6753197007Sdelphij		/* parenthesized this expression since it appears to be
6754197007Sdelphij		 * causing OF to be misset */
6755197007Sdelphij		CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
6756197007Sdelphij		    F_OF);
6757197007Sdelphij
6758197007Sdelphij	}
6759197007Sdelphij	return (uint8_t) res;
6760197007Sdelphij}
6761197007Sdelphij
6762197007Sdelphij/*
6763197007Sdelphij * REMARKS:
6764197007Sdelphij * Implements the RCL instruction and side effects.
6765197007Sdelphij */
6766197007Sdelphijstatic uint16_t
6767197007Sdelphijrcl_word(struct x86emu *emu, uint16_t d, uint8_t s)
6768197007Sdelphij{
6769197007Sdelphij	unsigned int res, cnt, mask, cf;
6770197007Sdelphij
6771197007Sdelphij	res = d;
6772197007Sdelphij	if ((cnt = s % 17) != 0) {
6773197007Sdelphij		cf = (d >> (16 - cnt)) & 0x1;
6774197007Sdelphij		res = (d << cnt) & 0xffff;
6775197007Sdelphij		mask = (1 << (cnt - 1)) - 1;
6776197007Sdelphij		res |= (d >> (17 - cnt)) & mask;
6777197007Sdelphij		if (ACCESS_FLAG(F_CF)) {
6778197007Sdelphij			res |= 1 << (cnt - 1);
6779197007Sdelphij		}
6780197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
6781197007Sdelphij		CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
6782197007Sdelphij		    F_OF);
6783197007Sdelphij	}
6784197007Sdelphij	return (uint16_t) res;
6785197007Sdelphij}
6786197007Sdelphij
6787197007Sdelphij/*
6788197007Sdelphij * REMARKS:
6789197007Sdelphij * Implements the RCL instruction and side effects.
6790197007Sdelphij */
6791197007Sdelphijstatic uint32_t
6792197007Sdelphijrcl_long(struct x86emu *emu, uint32_t d, uint8_t s)
6793197007Sdelphij{
6794197007Sdelphij	uint32_t res, cnt, mask, cf;
6795197007Sdelphij
6796197007Sdelphij	res = d;
6797197007Sdelphij	if ((cnt = s % 33) != 0) {
6798197007Sdelphij		cf = (d >> (32 - cnt)) & 0x1;
6799197007Sdelphij		res = (d << cnt) & 0xffffffff;
6800197007Sdelphij		mask = (1 << (cnt - 1)) - 1;
6801197007Sdelphij		res |= (d >> (33 - cnt)) & mask;
6802197007Sdelphij		if (ACCESS_FLAG(F_CF)) {	/* carry flag is set */
6803197007Sdelphij			res |= 1 << (cnt - 1);
6804197007Sdelphij		}
6805197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
6806197007Sdelphij		CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
6807197007Sdelphij		    F_OF);
6808197007Sdelphij	}
6809197007Sdelphij	return res;
6810197007Sdelphij}
6811197007Sdelphij
6812197007Sdelphij/*
6813197007Sdelphij * REMARKS:
6814197007Sdelphij * Implements the RCR instruction and side effects.
6815197007Sdelphij */
6816197007Sdelphijstatic uint8_t
6817197007Sdelphijrcr_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6818197007Sdelphij{
6819197007Sdelphij	uint32_t res, cnt;
6820197007Sdelphij	uint32_t mask, cf, ocf = 0;
6821197007Sdelphij
6822197007Sdelphij	/* rotate right through carry */
6823197007Sdelphij	/* s is the rotate distance.  It varies from 0 - 8. d is the byte
6824197007Sdelphij	 * object rotated.
6825197007Sdelphij	 *
6826197007Sdelphij	 * have
6827197007Sdelphij	 *
6828197007Sdelphij	 * CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6829197007Sdelphij	 *
6830204934Sdelphij	 * The new rotate is done mod 9, and given this, for a rotation of n
6831204934Sdelphij	 * bits (mod 9) the new carry flag is then located n bits from the LSB.
6832197007Sdelphij	 * The low part is then shifted up cnt bits, and the high part is or'd
6833197007Sdelphij	 * in.  Using CAPS for new values, and lowercase for the original
6834197007Sdelphij	 * values, this can be expressed as:
6835197007Sdelphij	 *
6836204934Sdelphij	 * IF n > 0
6837204934Sdelphij	 *	1) CF <-  b_(n-1)
6838204934Sdelphij	 *	2) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
6839204934Sdelphij	 * 	3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0)
6840204934Sdelphij	 */
6841197007Sdelphij	res = d;
6842197007Sdelphij	if ((cnt = s % 9) != 0) {
6843197007Sdelphij		/* extract the new CARRY FLAG. */
6844197007Sdelphij		/* CF <-  b_(n-1)              */
6845197007Sdelphij		if (cnt == 1) {
6846197007Sdelphij			cf = d & 0x1;
6847197007Sdelphij			/* note hackery here.  Access_flag(..) evaluates to
6848197007Sdelphij			 * either 0 if flag not set non-zero if flag is set.
6849197007Sdelphij			 * doing access_flag(..) != 0 casts that into either
6850197007Sdelphij			 * 0..1 in any representation of the flags register
6851197007Sdelphij			 * (i.e. packed bit array or unpacked.) */
6852197007Sdelphij			ocf = ACCESS_FLAG(F_CF) != 0;
6853197007Sdelphij		} else
6854197007Sdelphij			cf = (d >> (cnt - 1)) & 0x1;
6855197007Sdelphij
6856197007Sdelphij		/* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_n  */
6857197007Sdelphij		/* note that the right hand side done by the mask This is
6858197007Sdelphij		 * effectively done by shifting the object to the right.  The
6859197007Sdelphij		 * result must be masked, in case the object came in and was
6860197007Sdelphij		 * treated as a negative number.  Needed??? */
6861197007Sdelphij
6862197007Sdelphij		mask = (1 << (8 - cnt)) - 1;
6863197007Sdelphij		res = (d >> cnt) & mask;
6864197007Sdelphij
6865197007Sdelphij		/* now the high stuff which rotated around into the positions
6866197007Sdelphij		 * B_cnt-2 .. B_0 */
6867197007Sdelphij		/* B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0) */
6868197007Sdelphij		/* shift it downward, 7-(n-2) = 9-n positions. and mask off
6869197007Sdelphij		 * the result before or'ing in. */
6870197007Sdelphij		res |= (d << (9 - cnt));
6871197007Sdelphij
6872197007Sdelphij		/* if the carry flag was set, or it in.  */
6873197007Sdelphij		if (ACCESS_FLAG(F_CF)) {	/* carry flag is set */
6874197007Sdelphij			/* B_(8-n) <- cf */
6875197007Sdelphij			res |= 1 << (8 - cnt);
6876197007Sdelphij		}
6877197007Sdelphij		/* set the new carry flag, based on the variable "cf" */
6878197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
6879197007Sdelphij		/* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6880197007Sdelphij		 * the most significant bit.  Blecck. */
6881197007Sdelphij		/* parenthesized... */
6882197007Sdelphij		if (cnt == 1) {
6883197007Sdelphij			CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
6884197007Sdelphij			    F_OF);
6885197007Sdelphij		}
6886197007Sdelphij	}
6887197007Sdelphij	return (uint8_t) res;
6888197007Sdelphij}
6889197007Sdelphij
6890197007Sdelphij/*
6891197007Sdelphij * REMARKS:
6892197007Sdelphij * Implements the RCR instruction and side effects.
6893197007Sdelphij */
6894197007Sdelphijstatic uint16_t
6895197007Sdelphijrcr_word(struct x86emu *emu, uint16_t d, uint8_t s)
6896197007Sdelphij{
6897197007Sdelphij	uint32_t res, cnt;
6898197007Sdelphij	uint32_t mask, cf, ocf = 0;
6899197007Sdelphij
6900197007Sdelphij	/* rotate right through carry */
6901197007Sdelphij	res = d;
6902197007Sdelphij	if ((cnt = s % 17) != 0) {
6903197007Sdelphij		if (cnt == 1) {
6904197007Sdelphij			cf = d & 0x1;
6905197007Sdelphij			ocf = ACCESS_FLAG(F_CF) != 0;
6906197007Sdelphij		} else
6907197007Sdelphij			cf = (d >> (cnt - 1)) & 0x1;
6908197007Sdelphij		mask = (1 << (16 - cnt)) - 1;
6909197007Sdelphij		res = (d >> cnt) & mask;
6910197007Sdelphij		res |= (d << (17 - cnt));
6911197007Sdelphij		if (ACCESS_FLAG(F_CF)) {
6912197007Sdelphij			res |= 1 << (16 - cnt);
6913197007Sdelphij		}
6914197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
6915197007Sdelphij		if (cnt == 1) {
6916197007Sdelphij			CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
6917197007Sdelphij			    F_OF);
6918197007Sdelphij		}
6919197007Sdelphij	}
6920197007Sdelphij	return (uint16_t) res;
6921197007Sdelphij}
6922197007Sdelphij
6923197007Sdelphij/*
6924197007Sdelphij * REMARKS:
6925197007Sdelphij * Implements the RCR instruction and side effects.
6926197007Sdelphij */
6927197007Sdelphijstatic uint32_t
6928197007Sdelphijrcr_long(struct x86emu *emu, uint32_t d, uint8_t s)
6929197007Sdelphij{
6930197007Sdelphij	uint32_t res, cnt;
6931197007Sdelphij	uint32_t mask, cf, ocf = 0;
6932197007Sdelphij
6933197007Sdelphij	/* rotate right through carry */
6934197007Sdelphij	res = d;
6935197007Sdelphij	if ((cnt = s % 33) != 0) {
6936197007Sdelphij		if (cnt == 1) {
6937197007Sdelphij			cf = d & 0x1;
6938197007Sdelphij			ocf = ACCESS_FLAG(F_CF) != 0;
6939197007Sdelphij		} else
6940197007Sdelphij			cf = (d >> (cnt - 1)) & 0x1;
6941197007Sdelphij		mask = (1 << (32 - cnt)) - 1;
6942197007Sdelphij		res = (d >> cnt) & mask;
6943197007Sdelphij		if (cnt != 1)
6944197007Sdelphij			res |= (d << (33 - cnt));
6945197007Sdelphij		if (ACCESS_FLAG(F_CF)) {	/* carry flag is set */
6946197007Sdelphij			res |= 1 << (32 - cnt);
6947197007Sdelphij		}
6948197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
6949197007Sdelphij		if (cnt == 1) {
6950197007Sdelphij			CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
6951197007Sdelphij			    F_OF);
6952197007Sdelphij		}
6953197007Sdelphij	}
6954197007Sdelphij	return res;
6955197007Sdelphij}
6956197007Sdelphij
6957197007Sdelphij/*
6958197007Sdelphij * REMARKS:
6959197007Sdelphij * Implements the ROL instruction and side effects.
6960197007Sdelphij */
6961197007Sdelphijstatic uint8_t
6962197007Sdelphijrol_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6963197007Sdelphij{
6964197007Sdelphij	unsigned int res, cnt, mask;
6965197007Sdelphij
6966197007Sdelphij	/* rotate left */
6967197007Sdelphij	/* s is the rotate distance.  It varies from 0 - 8. d is the byte
6968197007Sdelphij	 * object rotated.
6969197007Sdelphij	 *
6970197007Sdelphij	 * have
6971197007Sdelphij	 *
6972197007Sdelphij	 * CF  B_7 ... B_0
6973197007Sdelphij	 *
6974197007Sdelphij	 * The new rotate is done mod 8. Much simpler than the "rcl" or "rcr"
6975197007Sdelphij	 * operations.
6976197007Sdelphij	 *
6977197007Sdelphij	 * IF n > 0 1) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) 2) B_(n-1) ..
6978197007Sdelphij	 * B_(0) <-  b_(7) .. b_(8-n) */
6979197007Sdelphij	res = d;
6980197007Sdelphij	if ((cnt = s % 8) != 0) {
6981197007Sdelphij		/* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) */
6982197007Sdelphij		res = (d << cnt);
6983197007Sdelphij
6984197007Sdelphij		/* B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n) */
6985197007Sdelphij		mask = (1 << cnt) - 1;
6986197007Sdelphij		res |= (d >> (8 - cnt)) & mask;
6987197007Sdelphij
6988197007Sdelphij		/* set the new carry flag, Note that it is the low order bit
6989197007Sdelphij		 * of the result!!!                               */
6990197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6991197007Sdelphij		/* OVERFLOW is set *IFF* s==1, then it is the xor of CF and
6992197007Sdelphij		 * the most significant bit.  Blecck. */
6993197007Sdelphij		CONDITIONAL_SET_FLAG(s == 1 &&
6994197007Sdelphij		    XOR2((res & 0x1) + ((res >> 6) & 0x2)),
6995197007Sdelphij		    F_OF);
6996197007Sdelphij	} if (s != 0) {
6997197007Sdelphij		/* set the new carry flag, Note that it is the low order bit
6998197007Sdelphij		 * of the result!!!                               */
6999197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7000197007Sdelphij	}
7001197007Sdelphij	return (uint8_t) res;
7002197007Sdelphij}
7003197007Sdelphij
7004197007Sdelphij/*
7005197007Sdelphij * REMARKS:
7006197007Sdelphij * Implements the ROL instruction and side effects.
7007197007Sdelphij */
7008197007Sdelphijstatic uint16_t
7009197007Sdelphijrol_word(struct x86emu *emu, uint16_t d, uint8_t s)
7010197007Sdelphij{
7011197007Sdelphij	unsigned int res, cnt, mask;
7012197007Sdelphij
7013197007Sdelphij	res = d;
7014197007Sdelphij	if ((cnt = s % 16) != 0) {
7015197007Sdelphij		res = (d << cnt);
7016197007Sdelphij		mask = (1 << cnt) - 1;
7017197007Sdelphij		res |= (d >> (16 - cnt)) & mask;
7018197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7019197007Sdelphij		CONDITIONAL_SET_FLAG(s == 1 &&
7020197007Sdelphij		    XOR2((res & 0x1) + ((res >> 14) & 0x2)),
7021197007Sdelphij		    F_OF);
7022197007Sdelphij	} if (s != 0) {
7023197007Sdelphij		/* set the new carry flag, Note that it is the low order bit
7024197007Sdelphij		 * of the result!!!                               */
7025197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7026197007Sdelphij	}
7027197007Sdelphij	return (uint16_t) res;
7028197007Sdelphij}
7029197007Sdelphij
7030197007Sdelphij/*
7031197007Sdelphij * REMARKS:
7032197007Sdelphij * Implements the ROL instruction and side effects.
7033197007Sdelphij */
7034197007Sdelphijstatic uint32_t
7035197007Sdelphijrol_long(struct x86emu *emu, uint32_t d, uint8_t s)
7036197007Sdelphij{
7037197007Sdelphij	uint32_t res, cnt, mask;
7038197007Sdelphij
7039197007Sdelphij	res = d;
7040197007Sdelphij	if ((cnt = s % 32) != 0) {
7041197007Sdelphij		res = (d << cnt);
7042197007Sdelphij		mask = (1 << cnt) - 1;
7043197007Sdelphij		res |= (d >> (32 - cnt)) & mask;
7044197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7045197007Sdelphij		CONDITIONAL_SET_FLAG(s == 1 &&
7046197007Sdelphij		    XOR2((res & 0x1) + ((res >> 30) & 0x2)),
7047197007Sdelphij		    F_OF);
7048197007Sdelphij	} if (s != 0) {
7049197007Sdelphij		/* set the new carry flag, Note that it is the low order bit
7050197007Sdelphij		 * of the result!!!                               */
7051197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7052197007Sdelphij	}
7053197007Sdelphij	return res;
7054197007Sdelphij}
7055197007Sdelphij
7056197007Sdelphij/*
7057197007Sdelphij * REMARKS:
7058197007Sdelphij * Implements the ROR instruction and side effects.
7059197007Sdelphij */
7060197007Sdelphijstatic uint8_t
7061197007Sdelphijror_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7062197007Sdelphij{
7063197007Sdelphij	unsigned int res, cnt, mask;
7064197007Sdelphij
7065197007Sdelphij	/* rotate right */
7066197007Sdelphij	/* s is the rotate distance.  It varies from 0 - 8. d is the byte
7067197007Sdelphij	 * object rotated.
7068197007Sdelphij	 *
7069197007Sdelphij	 * have
7070197007Sdelphij	 *
7071197007Sdelphij	 * B_7 ... B_0
7072197007Sdelphij	 *
7073197007Sdelphij	 * The rotate is done mod 8.
7074197007Sdelphij	 *
7075197007Sdelphij	 * IF n > 0 1) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n) 2) B_(7) ..
7076197007Sdelphij	 * B_(8-n) <-  b_(n-1) .. b_(0) */
7077197007Sdelphij	res = d;
7078197007Sdelphij	if ((cnt = s % 8) != 0) {	/* not a typo, do nada if cnt==0 */
7079197007Sdelphij		/* B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0) */
7080197007Sdelphij		res = (d << (8 - cnt));
7081197007Sdelphij
7082197007Sdelphij		/* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n) */
7083197007Sdelphij		mask = (1 << (8 - cnt)) - 1;
7084197007Sdelphij		res |= (d >> (cnt)) & mask;
7085197007Sdelphij
7086197007Sdelphij		/* set the new carry flag, Note that it is the low order bit
7087197007Sdelphij		 * of the result!!!                               */
7088197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
7089197007Sdelphij		/* OVERFLOW is set *IFF* s==1, then it is the xor of the two
7090197007Sdelphij		 * most significant bits.  Blecck. */
7091197007Sdelphij		CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
7092197007Sdelphij	} else if (s != 0) {
7093197007Sdelphij		/* set the new carry flag, Note that it is the low order bit
7094197007Sdelphij		 * of the result!!!                               */
7095197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
7096197007Sdelphij	}
7097197007Sdelphij	return (uint8_t) res;
7098197007Sdelphij}
7099197007Sdelphij
7100197007Sdelphij/*
7101197007Sdelphij * REMARKS:
7102197007Sdelphij * Implements the ROR instruction and side effects.
7103197007Sdelphij */
7104197007Sdelphijstatic uint16_t
7105197007Sdelphijror_word(struct x86emu *emu, uint16_t d, uint8_t s)
7106197007Sdelphij{
7107197007Sdelphij	unsigned int res, cnt, mask;
7108197007Sdelphij
7109197007Sdelphij	res = d;
7110197007Sdelphij	if ((cnt = s % 16) != 0) {
7111197007Sdelphij		res = (d << (16 - cnt));
7112197007Sdelphij		mask = (1 << (16 - cnt)) - 1;
7113197007Sdelphij		res |= (d >> (cnt)) & mask;
7114197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
7115197007Sdelphij		CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
7116197007Sdelphij	} else if (s != 0) {
7117197007Sdelphij		/* set the new carry flag, Note that it is the low order bit
7118197007Sdelphij		 * of the result!!!                               */
7119197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
7120197007Sdelphij	}
7121197007Sdelphij	return (uint16_t) res;
7122197007Sdelphij}
7123197007Sdelphij
7124197007Sdelphij/*
7125197007Sdelphij * REMARKS:
7126197007Sdelphij * Implements the ROR instruction and side effects.
7127197007Sdelphij */
7128197007Sdelphijstatic uint32_t
7129197007Sdelphijror_long(struct x86emu *emu, uint32_t d, uint8_t s)
7130197007Sdelphij{
7131197007Sdelphij	uint32_t res, cnt, mask;
7132197007Sdelphij
7133197007Sdelphij	res = d;
7134197007Sdelphij	if ((cnt = s % 32) != 0) {
7135197007Sdelphij		res = (d << (32 - cnt));
7136197007Sdelphij		mask = (1 << (32 - cnt)) - 1;
7137197007Sdelphij		res |= (d >> (cnt)) & mask;
7138197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
7139197007Sdelphij		CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
7140197007Sdelphij	} else if (s != 0) {
7141197007Sdelphij		/* set the new carry flag, Note that it is the low order bit
7142197007Sdelphij		 * of the result!!!                               */
7143197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
7144197007Sdelphij	}
7145197007Sdelphij	return res;
7146197007Sdelphij}
7147197007Sdelphij
7148197007Sdelphij/*
7149197007Sdelphij * REMARKS:
7150197007Sdelphij * Implements the SHL instruction and side effects.
7151197007Sdelphij */
7152197007Sdelphijstatic uint8_t
7153197007Sdelphijshl_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7154197007Sdelphij{
7155197007Sdelphij	unsigned int cnt, res, cf;
7156197007Sdelphij
7157197007Sdelphij	if (s < 8) {
7158197007Sdelphij		cnt = s % 8;
7159197007Sdelphij
7160197007Sdelphij		/* last bit shifted out goes into carry flag */
7161197007Sdelphij		if (cnt > 0) {
7162197007Sdelphij			res = d << cnt;
7163197007Sdelphij			cf = d & (1 << (8 - cnt));
7164197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7165197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7166197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7167197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7168197007Sdelphij		} else {
7169197007Sdelphij			res = (uint8_t) d;
7170197007Sdelphij		}
7171197007Sdelphij
7172197007Sdelphij		if (cnt == 1) {
7173197007Sdelphij			/* Needs simplification. */
7174197007Sdelphij			CONDITIONAL_SET_FLAG(
7175197007Sdelphij			    (((res & 0x80) == 0x80) ^
7176197007Sdelphij				(ACCESS_FLAG(F_CF) != 0)),
7177197007Sdelphij			/* was (emu->x86.R_FLG&F_CF)==F_CF)), */
7178197007Sdelphij			    F_OF);
7179197007Sdelphij		} else {
7180197007Sdelphij			CLEAR_FLAG(F_OF);
7181197007Sdelphij		}
7182197007Sdelphij	} else {
7183197007Sdelphij		res = 0;
7184197007Sdelphij		CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF);
7185197007Sdelphij		CLEAR_FLAG(F_OF);
7186197007Sdelphij		CLEAR_FLAG(F_SF);
7187197007Sdelphij		SET_FLAG(F_PF);
7188197007Sdelphij		SET_FLAG(F_ZF);
7189197007Sdelphij	}
7190197007Sdelphij	return (uint8_t) res;
7191197007Sdelphij}
7192197007Sdelphij
7193197007Sdelphij/*
7194197007Sdelphij * REMARKS:
7195197007Sdelphij * Implements the SHL instruction and side effects.
7196197007Sdelphij */
7197197007Sdelphijstatic uint16_t
7198197007Sdelphijshl_word(struct x86emu *emu, uint16_t d, uint8_t s)
7199197007Sdelphij{
7200197007Sdelphij	unsigned int cnt, res, cf;
7201197007Sdelphij
7202197007Sdelphij	if (s < 16) {
7203197007Sdelphij		cnt = s % 16;
7204197007Sdelphij		if (cnt > 0) {
7205197007Sdelphij			res = d << cnt;
7206197007Sdelphij			cf = d & (1 << (16 - cnt));
7207197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7208197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7209197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7210197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7211197007Sdelphij		} else {
7212197007Sdelphij			res = (uint16_t) d;
7213197007Sdelphij		}
7214197007Sdelphij
7215197007Sdelphij		if (cnt == 1) {
7216197007Sdelphij			CONDITIONAL_SET_FLAG(
7217197007Sdelphij			    (((res & 0x8000) == 0x8000) ^
7218197007Sdelphij				(ACCESS_FLAG(F_CF) != 0)),
7219197007Sdelphij			    F_OF);
7220197007Sdelphij		} else {
7221197007Sdelphij			CLEAR_FLAG(F_OF);
7222197007Sdelphij		}
7223197007Sdelphij	} else {
7224197007Sdelphij		res = 0;
7225197007Sdelphij		CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
7226197007Sdelphij		CLEAR_FLAG(F_OF);
7227197007Sdelphij		CLEAR_FLAG(F_SF);
7228197007Sdelphij		SET_FLAG(F_PF);
7229197007Sdelphij		SET_FLAG(F_ZF);
7230197007Sdelphij	}
7231197007Sdelphij	return (uint16_t) res;
7232197007Sdelphij}
7233197007Sdelphij
7234197007Sdelphij/*
7235197007Sdelphij * REMARKS:
7236197007Sdelphij * Implements the SHL instruction and side effects.
7237197007Sdelphij */
7238197007Sdelphijstatic uint32_t
7239197007Sdelphijshl_long(struct x86emu *emu, uint32_t d, uint8_t s)
7240197007Sdelphij{
7241197007Sdelphij	unsigned int cnt, res, cf;
7242197007Sdelphij
7243197007Sdelphij	if (s < 32) {
7244197007Sdelphij		cnt = s % 32;
7245197007Sdelphij		if (cnt > 0) {
7246197007Sdelphij			res = d << cnt;
7247197007Sdelphij			cf = d & (1 << (32 - cnt));
7248197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7249197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7250197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7251197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7252197007Sdelphij		} else {
7253197007Sdelphij			res = d;
7254197007Sdelphij		}
7255197007Sdelphij		if (cnt == 1) {
7256204934Sdelphij			CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000)
7257204934Sdelphij			    ^ (ACCESS_FLAG(F_CF) != 0)), F_OF);
7258197007Sdelphij		} else {
7259197007Sdelphij			CLEAR_FLAG(F_OF);
7260197007Sdelphij		}
7261197007Sdelphij	} else {
7262197007Sdelphij		res = 0;
7263197007Sdelphij		CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7264197007Sdelphij		CLEAR_FLAG(F_OF);
7265197007Sdelphij		CLEAR_FLAG(F_SF);
7266197007Sdelphij		SET_FLAG(F_PF);
7267197007Sdelphij		SET_FLAG(F_ZF);
7268197007Sdelphij	}
7269197007Sdelphij	return res;
7270197007Sdelphij}
7271197007Sdelphij
7272197007Sdelphij/*
7273197007Sdelphij * REMARKS:
7274197007Sdelphij * Implements the SHR instruction and side effects.
7275197007Sdelphij */
7276197007Sdelphijstatic uint8_t
7277197007Sdelphijshr_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7278197007Sdelphij{
7279197007Sdelphij	unsigned int cnt, res, cf;
7280197007Sdelphij
7281197007Sdelphij	if (s < 8) {
7282197007Sdelphij		cnt = s % 8;
7283197007Sdelphij		if (cnt > 0) {
7284197007Sdelphij			cf = d & (1 << (cnt - 1));
7285197007Sdelphij			res = d >> cnt;
7286197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7287197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7288197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7289197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7290197007Sdelphij		} else {
7291197007Sdelphij			res = (uint8_t) d;
7292197007Sdelphij		}
7293197007Sdelphij
7294197007Sdelphij		if (cnt == 1) {
7295197007Sdelphij			CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
7296197007Sdelphij		} else {
7297197007Sdelphij			CLEAR_FLAG(F_OF);
7298197007Sdelphij		}
7299197007Sdelphij	} else {
7300197007Sdelphij		res = 0;
7301197007Sdelphij		CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF);
7302197007Sdelphij		CLEAR_FLAG(F_OF);
7303197007Sdelphij		CLEAR_FLAG(F_SF);
7304197007Sdelphij		SET_FLAG(F_PF);
7305197007Sdelphij		SET_FLAG(F_ZF);
7306197007Sdelphij	}
7307197007Sdelphij	return (uint8_t) res;
7308197007Sdelphij}
7309197007Sdelphij
7310197007Sdelphij/*
7311197007Sdelphij * REMARKS:
7312197007Sdelphij * Implements the SHR instruction and side effects.
7313197007Sdelphij */
7314197007Sdelphijstatic uint16_t
7315197007Sdelphijshr_word(struct x86emu *emu, uint16_t d, uint8_t s)
7316197007Sdelphij{
7317197007Sdelphij	unsigned int cnt, res, cf;
7318197007Sdelphij
7319197007Sdelphij	if (s < 16) {
7320197007Sdelphij		cnt = s % 16;
7321197007Sdelphij		if (cnt > 0) {
7322197007Sdelphij			cf = d & (1 << (cnt - 1));
7323197007Sdelphij			res = d >> cnt;
7324197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7325197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7326197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7327197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7328197007Sdelphij		} else {
7329197007Sdelphij			res = d;
7330197007Sdelphij		}
7331197007Sdelphij
7332197007Sdelphij		if (cnt == 1) {
7333197007Sdelphij			CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7334197007Sdelphij		} else {
7335197007Sdelphij			CLEAR_FLAG(F_OF);
7336197007Sdelphij		}
7337197007Sdelphij	} else {
7338197007Sdelphij		res = 0;
7339197007Sdelphij		CLEAR_FLAG(F_CF);
7340197007Sdelphij		CLEAR_FLAG(F_OF);
7341197007Sdelphij		SET_FLAG(F_ZF);
7342197007Sdelphij		CLEAR_FLAG(F_SF);
7343197007Sdelphij		CLEAR_FLAG(F_PF);
7344197007Sdelphij	}
7345197007Sdelphij	return (uint16_t) res;
7346197007Sdelphij}
7347197007Sdelphij
7348197007Sdelphij/*
7349197007Sdelphij * REMARKS:
7350197007Sdelphij * Implements the SHR instruction and side effects.
7351197007Sdelphij */
7352197007Sdelphijstatic uint32_t
7353197007Sdelphijshr_long(struct x86emu *emu, uint32_t d, uint8_t s)
7354197007Sdelphij{
7355197007Sdelphij	unsigned int cnt, res, cf;
7356197007Sdelphij
7357197007Sdelphij	if (s < 32) {
7358197007Sdelphij		cnt = s % 32;
7359197007Sdelphij		if (cnt > 0) {
7360197007Sdelphij			cf = d & (1 << (cnt - 1));
7361197007Sdelphij			res = d >> cnt;
7362197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7363197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7364197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7365197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7366197007Sdelphij		} else {
7367197007Sdelphij			res = d;
7368197007Sdelphij		}
7369197007Sdelphij		if (cnt == 1) {
7370197007Sdelphij			CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7371197007Sdelphij		} else {
7372197007Sdelphij			CLEAR_FLAG(F_OF);
7373197007Sdelphij		}
7374197007Sdelphij	} else {
7375197007Sdelphij		res = 0;
7376197007Sdelphij		CLEAR_FLAG(F_CF);
7377197007Sdelphij		CLEAR_FLAG(F_OF);
7378197007Sdelphij		SET_FLAG(F_ZF);
7379197007Sdelphij		CLEAR_FLAG(F_SF);
7380197007Sdelphij		CLEAR_FLAG(F_PF);
7381197007Sdelphij	}
7382197007Sdelphij	return res;
7383197007Sdelphij}
7384197007Sdelphij
7385197007Sdelphij/*
7386197007Sdelphij * REMARKS:
7387197007Sdelphij * Implements the SAR instruction and side effects.
7388197007Sdelphij */
7389197007Sdelphijstatic uint8_t
7390197007Sdelphijsar_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7391197007Sdelphij{
7392197007Sdelphij	unsigned int cnt, res, cf, mask, sf;
7393197007Sdelphij
7394197007Sdelphij	res = d;
7395197007Sdelphij	sf = d & 0x80;
7396197007Sdelphij	cnt = s % 8;
7397197007Sdelphij	if (cnt > 0 && cnt < 8) {
7398197007Sdelphij		mask = (1 << (8 - cnt)) - 1;
7399197007Sdelphij		cf = d & (1 << (cnt - 1));
7400197007Sdelphij		res = (d >> cnt) & mask;
7401197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
7402197007Sdelphij		if (sf) {
7403197007Sdelphij			res |= ~mask;
7404197007Sdelphij		}
7405197007Sdelphij		CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7406197007Sdelphij		CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7407197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7408197007Sdelphij	} else if (cnt >= 8) {
7409197007Sdelphij		if (sf) {
7410197007Sdelphij			res = 0xff;
7411197007Sdelphij			SET_FLAG(F_CF);
7412197007Sdelphij			CLEAR_FLAG(F_ZF);
7413197007Sdelphij			SET_FLAG(F_SF);
7414197007Sdelphij			SET_FLAG(F_PF);
7415197007Sdelphij		} else {
7416197007Sdelphij			res = 0;
7417197007Sdelphij			CLEAR_FLAG(F_CF);
7418197007Sdelphij			SET_FLAG(F_ZF);
7419197007Sdelphij			CLEAR_FLAG(F_SF);
7420197007Sdelphij			CLEAR_FLAG(F_PF);
7421197007Sdelphij		}
7422197007Sdelphij	}
7423197007Sdelphij	return (uint8_t) res;
7424197007Sdelphij}
7425197007Sdelphij
7426197007Sdelphij/*
7427197007Sdelphij * REMARKS:
7428197007Sdelphij * Implements the SAR instruction and side effects.
7429197007Sdelphij */
7430197007Sdelphijstatic uint16_t
7431197007Sdelphijsar_word(struct x86emu *emu, uint16_t d, uint8_t s)
7432197007Sdelphij{
7433197007Sdelphij	unsigned int cnt, res, cf, mask, sf;
7434197007Sdelphij
7435197007Sdelphij	sf = d & 0x8000;
7436197007Sdelphij	cnt = s % 16;
7437197007Sdelphij	res = d;
7438197007Sdelphij	if (cnt > 0 && cnt < 16) {
7439197007Sdelphij		mask = (1 << (16 - cnt)) - 1;
7440197007Sdelphij		cf = d & (1 << (cnt - 1));
7441197007Sdelphij		res = (d >> cnt) & mask;
7442197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
7443197007Sdelphij		if (sf) {
7444197007Sdelphij			res |= ~mask;
7445197007Sdelphij		}
7446197007Sdelphij		CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7447197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7448197007Sdelphij		CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7449197007Sdelphij	} else if (cnt >= 16) {
7450197007Sdelphij		if (sf) {
7451197007Sdelphij			res = 0xffff;
7452197007Sdelphij			SET_FLAG(F_CF);
7453197007Sdelphij			CLEAR_FLAG(F_ZF);
7454197007Sdelphij			SET_FLAG(F_SF);
7455197007Sdelphij			SET_FLAG(F_PF);
7456197007Sdelphij		} else {
7457197007Sdelphij			res = 0;
7458197007Sdelphij			CLEAR_FLAG(F_CF);
7459197007Sdelphij			SET_FLAG(F_ZF);
7460197007Sdelphij			CLEAR_FLAG(F_SF);
7461197007Sdelphij			CLEAR_FLAG(F_PF);
7462197007Sdelphij		}
7463197007Sdelphij	}
7464197007Sdelphij	return (uint16_t) res;
7465197007Sdelphij}
7466197007Sdelphij
7467197007Sdelphij/*
7468197007Sdelphij * REMARKS:
7469197007Sdelphij * Implements the SAR instruction and side effects.
7470197007Sdelphij */
7471197007Sdelphijstatic uint32_t
7472197007Sdelphijsar_long(struct x86emu *emu, uint32_t d, uint8_t s)
7473197007Sdelphij{
7474197007Sdelphij	uint32_t cnt, res, cf, mask, sf;
7475197007Sdelphij
7476197007Sdelphij	sf = d & 0x80000000;
7477197007Sdelphij	cnt = s % 32;
7478197007Sdelphij	res = d;
7479197007Sdelphij	if (cnt > 0 && cnt < 32) {
7480197007Sdelphij		mask = (1 << (32 - cnt)) - 1;
7481197007Sdelphij		cf = d & (1 << (cnt - 1));
7482197007Sdelphij		res = (d >> cnt) & mask;
7483197007Sdelphij		CONDITIONAL_SET_FLAG(cf, F_CF);
7484197007Sdelphij		if (sf) {
7485197007Sdelphij			res |= ~mask;
7486197007Sdelphij		}
7487197007Sdelphij		CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7488197007Sdelphij		CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7489197007Sdelphij		CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7490197007Sdelphij	} else if (cnt >= 32) {
7491197007Sdelphij		if (sf) {
7492197007Sdelphij			res = 0xffffffff;
7493197007Sdelphij			SET_FLAG(F_CF);
7494197007Sdelphij			CLEAR_FLAG(F_ZF);
7495197007Sdelphij			SET_FLAG(F_SF);
7496197007Sdelphij			SET_FLAG(F_PF);
7497197007Sdelphij		} else {
7498197007Sdelphij			res = 0;
7499197007Sdelphij			CLEAR_FLAG(F_CF);
7500197007Sdelphij			SET_FLAG(F_ZF);
7501197007Sdelphij			CLEAR_FLAG(F_SF);
7502197007Sdelphij			CLEAR_FLAG(F_PF);
7503197007Sdelphij		}
7504197007Sdelphij	}
7505197007Sdelphij	return res;
7506197007Sdelphij}
7507197007Sdelphij
7508197007Sdelphij/*
7509197007Sdelphij * REMARKS:
7510197007Sdelphij * Implements the SHLD instruction and side effects.
7511197007Sdelphij */
7512197007Sdelphijstatic uint16_t
7513197007Sdelphijshld_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s)
7514197007Sdelphij{
7515197007Sdelphij	unsigned int cnt, res, cf;
7516197007Sdelphij
7517197007Sdelphij	if (s < 16) {
7518197007Sdelphij		cnt = s % 16;
7519197007Sdelphij		if (cnt > 0) {
7520197007Sdelphij			res = (d << cnt) | (fill >> (16 - cnt));
7521197007Sdelphij			cf = d & (1 << (16 - cnt));
7522197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7523197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7524197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7525197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7526197007Sdelphij		} else {
7527197007Sdelphij			res = d;
7528197007Sdelphij		}
7529197007Sdelphij		if (cnt == 1) {
7530197007Sdelphij			CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
7531197007Sdelphij				(ACCESS_FLAG(F_CF) != 0)), F_OF);
7532197007Sdelphij		} else {
7533197007Sdelphij			CLEAR_FLAG(F_OF);
7534197007Sdelphij		}
7535197007Sdelphij	} else {
7536197007Sdelphij		res = 0;
7537197007Sdelphij		CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
7538197007Sdelphij		CLEAR_FLAG(F_OF);
7539197007Sdelphij		CLEAR_FLAG(F_SF);
7540197007Sdelphij		SET_FLAG(F_PF);
7541197007Sdelphij		SET_FLAG(F_ZF);
7542197007Sdelphij	}
7543197007Sdelphij	return (uint16_t) res;
7544197007Sdelphij}
7545197007Sdelphij
7546197007Sdelphij/*
7547197007Sdelphij * REMARKS:
7548197007Sdelphij * Implements the SHLD instruction and side effects.
7549197007Sdelphij */
7550197007Sdelphijstatic uint32_t
7551197007Sdelphijshld_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s)
7552197007Sdelphij{
7553197007Sdelphij	unsigned int cnt, res, cf;
7554197007Sdelphij
7555197007Sdelphij	if (s < 32) {
7556197007Sdelphij		cnt = s % 32;
7557197007Sdelphij		if (cnt > 0) {
7558197007Sdelphij			res = (d << cnt) | (fill >> (32 - cnt));
7559197007Sdelphij			cf = d & (1 << (32 - cnt));
7560197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7561197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7562197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7563197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7564197007Sdelphij		} else {
7565197007Sdelphij			res = d;
7566197007Sdelphij		}
7567197007Sdelphij		if (cnt == 1) {
7568204934Sdelphij			CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000)
7569204934Sdelphij			    ^ (ACCESS_FLAG(F_CF) != 0)), F_OF);
7570197007Sdelphij		} else {
7571197007Sdelphij			CLEAR_FLAG(F_OF);
7572197007Sdelphij		}
7573197007Sdelphij	} else {
7574197007Sdelphij		res = 0;
7575197007Sdelphij		CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7576197007Sdelphij		CLEAR_FLAG(F_OF);
7577197007Sdelphij		CLEAR_FLAG(F_SF);
7578197007Sdelphij		SET_FLAG(F_PF);
7579197007Sdelphij		SET_FLAG(F_ZF);
7580197007Sdelphij	}
7581197007Sdelphij	return res;
7582197007Sdelphij}
7583197007Sdelphij
7584197007Sdelphij/*
7585197007Sdelphij * REMARKS:
7586197007Sdelphij * Implements the SHRD instruction and side effects.
7587197007Sdelphij */
7588197007Sdelphijstatic uint16_t
7589197007Sdelphijshrd_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s)
7590197007Sdelphij{
7591197007Sdelphij	unsigned int cnt, res, cf;
7592197007Sdelphij
7593197007Sdelphij	if (s < 16) {
7594197007Sdelphij		cnt = s % 16;
7595197007Sdelphij		if (cnt > 0) {
7596197007Sdelphij			cf = d & (1 << (cnt - 1));
7597197007Sdelphij			res = (d >> cnt) | (fill << (16 - cnt));
7598197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7599197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7600197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7601197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7602197007Sdelphij		} else {
7603197007Sdelphij			res = d;
7604197007Sdelphij		}
7605197007Sdelphij
7606197007Sdelphij		if (cnt == 1) {
7607197007Sdelphij			CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7608197007Sdelphij		} else {
7609197007Sdelphij			CLEAR_FLAG(F_OF);
7610197007Sdelphij		}
7611197007Sdelphij	} else {
7612197007Sdelphij		res = 0;
7613197007Sdelphij		CLEAR_FLAG(F_CF);
7614197007Sdelphij		CLEAR_FLAG(F_OF);
7615197007Sdelphij		SET_FLAG(F_ZF);
7616197007Sdelphij		CLEAR_FLAG(F_SF);
7617197007Sdelphij		CLEAR_FLAG(F_PF);
7618197007Sdelphij	}
7619197007Sdelphij	return (uint16_t) res;
7620197007Sdelphij}
7621197007Sdelphij
7622197007Sdelphij/*
7623197007Sdelphij * REMARKS:
7624197007Sdelphij * Implements the SHRD instruction and side effects.
7625197007Sdelphij */
7626197007Sdelphijstatic uint32_t
7627197007Sdelphijshrd_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s)
7628197007Sdelphij{
7629197007Sdelphij	unsigned int cnt, res, cf;
7630197007Sdelphij
7631197007Sdelphij	if (s < 32) {
7632197007Sdelphij		cnt = s % 32;
7633197007Sdelphij		if (cnt > 0) {
7634197007Sdelphij			cf = d & (1 << (cnt - 1));
7635197007Sdelphij			res = (d >> cnt) | (fill << (32 - cnt));
7636197007Sdelphij			CONDITIONAL_SET_FLAG(cf, F_CF);
7637197007Sdelphij			CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7638197007Sdelphij			CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7639197007Sdelphij			CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7640197007Sdelphij		} else {
7641197007Sdelphij			res = d;
7642197007Sdelphij		}
7643197007Sdelphij		if (cnt == 1) {
7644197007Sdelphij			CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7645197007Sdelphij		} else {
7646197007Sdelphij			CLEAR_FLAG(F_OF);
7647197007Sdelphij		}
7648197007Sdelphij	} else {
7649197007Sdelphij		res = 0;
7650197007Sdelphij		CLEAR_FLAG(F_CF);
7651197007Sdelphij		CLEAR_FLAG(F_OF);
7652197007Sdelphij		SET_FLAG(F_ZF);
7653197007Sdelphij		CLEAR_FLAG(F_SF);
7654197007Sdelphij		CLEAR_FLAG(F_PF);
7655197007Sdelphij	}
7656197007Sdelphij	return res;
7657197007Sdelphij}
7658197007Sdelphij
7659197007Sdelphij/*
7660197007Sdelphij * REMARKS:
7661197007Sdelphij * Implements the SBB instruction and side effects.
7662197007Sdelphij */
7663197007Sdelphijstatic uint8_t
7664197007Sdelphijsbb_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7665197007Sdelphij{
7666197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7667197007Sdelphij	uint32_t bc;
7668197007Sdelphij
7669197007Sdelphij	if (ACCESS_FLAG(F_CF))
7670197007Sdelphij		res = d - s - 1;
7671197007Sdelphij	else
7672197007Sdelphij		res = d - s;
7673197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7674197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7675197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7676197007Sdelphij
7677197007Sdelphij	/* calculate the borrow chain.  See note at top */
7678197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
7679197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7680197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7681197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7682197007Sdelphij	return (uint8_t) res;
7683197007Sdelphij}
7684197007Sdelphij
7685197007Sdelphij/*
7686197007Sdelphij * REMARKS:
7687197007Sdelphij * Implements the SBB instruction and side effects.
7688197007Sdelphij */
7689197007Sdelphijstatic uint16_t
7690197007Sdelphijsbb_word(struct x86emu *emu, uint16_t d, uint16_t s)
7691197007Sdelphij{
7692197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7693197007Sdelphij	uint32_t bc;
7694197007Sdelphij
7695197007Sdelphij	if (ACCESS_FLAG(F_CF))
7696197007Sdelphij		res = d - s - 1;
7697197007Sdelphij	else
7698197007Sdelphij		res = d - s;
7699197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7700197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7701197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7702197007Sdelphij
7703197007Sdelphij	/* calculate the borrow chain.  See note at top */
7704197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
7705197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7706197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7707197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7708197007Sdelphij	return (uint16_t) res;
7709197007Sdelphij}
7710197007Sdelphij
7711197007Sdelphij/*
7712197007Sdelphij * REMARKS:
7713197007Sdelphij * Implements the SBB instruction and side effects.
7714197007Sdelphij */
7715197007Sdelphijstatic uint32_t
7716197007Sdelphijsbb_long(struct x86emu *emu, uint32_t d, uint32_t s)
7717197007Sdelphij{
7718197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7719197007Sdelphij	uint32_t bc;
7720197007Sdelphij
7721197007Sdelphij	if (ACCESS_FLAG(F_CF))
7722197007Sdelphij		res = d - s - 1;
7723197007Sdelphij	else
7724197007Sdelphij		res = d - s;
7725197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7726197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7727197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7728197007Sdelphij
7729197007Sdelphij	/* calculate the borrow chain.  See note at top */
7730197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
7731197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7732197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7733197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7734197007Sdelphij	return res;
7735197007Sdelphij}
7736197007Sdelphij
7737197007Sdelphij/*
7738197007Sdelphij * REMARKS:
7739197007Sdelphij * Implements the SUB instruction and side effects.
7740197007Sdelphij */
7741197007Sdelphijstatic uint8_t
7742197007Sdelphijsub_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7743197007Sdelphij{
7744197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7745197007Sdelphij	uint32_t bc;
7746197007Sdelphij
7747197007Sdelphij	res = d - s;
7748197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7749197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7750197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7751197007Sdelphij
7752197007Sdelphij	/* calculate the borrow chain.  See note at top */
7753197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
7754197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7755197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7756197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7757197007Sdelphij	return (uint8_t) res;
7758197007Sdelphij}
7759197007Sdelphij
7760197007Sdelphij/*
7761197007Sdelphij * REMARKS:
7762197007Sdelphij * Implements the SUB instruction and side effects.
7763197007Sdelphij */
7764197007Sdelphijstatic uint16_t
7765197007Sdelphijsub_word(struct x86emu *emu, uint16_t d, uint16_t s)
7766197007Sdelphij{
7767197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7768197007Sdelphij	uint32_t bc;
7769197007Sdelphij
7770197007Sdelphij	res = d - s;
7771197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7772197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7773197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7774197007Sdelphij
7775197007Sdelphij	/* calculate the borrow chain.  See note at top */
7776197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
7777197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7778197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7779197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7780197007Sdelphij	return (uint16_t) res;
7781197007Sdelphij}
7782197007Sdelphij
7783197007Sdelphij/*
7784197007Sdelphij * REMARKS:
7785197007Sdelphij * Implements the SUB instruction and side effects.
7786197007Sdelphij */
7787197007Sdelphijstatic uint32_t
7788197007Sdelphijsub_long(struct x86emu *emu, uint32_t d, uint32_t s)
7789197007Sdelphij{
7790197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7791197007Sdelphij	uint32_t bc;
7792197007Sdelphij
7793197007Sdelphij	res = d - s;
7794197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7795197007Sdelphij	CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7796197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7797197007Sdelphij
7798197007Sdelphij	/* calculate the borrow chain.  See note at top */
7799197007Sdelphij	bc = (res & (~d | s)) | (~d & s);
7800197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7801197007Sdelphij	CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7802197007Sdelphij	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7803197007Sdelphij	return res;
7804197007Sdelphij}
7805197007Sdelphij
7806197007Sdelphij/*
7807197007Sdelphij * REMARKS:
7808197007Sdelphij * Implements the TEST instruction and side effects.
7809197007Sdelphij */
7810197007Sdelphijstatic void
7811197007Sdelphijtest_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7812197007Sdelphij{
7813197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7814197007Sdelphij
7815197007Sdelphij	res = d & s;
7816197007Sdelphij
7817197007Sdelphij	CLEAR_FLAG(F_OF);
7818197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7819197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7820197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7821197007Sdelphij	/* AF == dont care */
7822197007Sdelphij	CLEAR_FLAG(F_CF);
7823197007Sdelphij}
7824197007Sdelphij
7825197007Sdelphij/*
7826197007Sdelphij * REMARKS:
7827197007Sdelphij * Implements the TEST instruction and side effects.
7828197007Sdelphij */
7829197007Sdelphijstatic void
7830197007Sdelphijtest_word(struct x86emu *emu, uint16_t d, uint16_t s)
7831197007Sdelphij{
7832197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7833197007Sdelphij
7834197007Sdelphij	res = d & s;
7835197007Sdelphij
7836197007Sdelphij	CLEAR_FLAG(F_OF);
7837197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7838197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7839197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7840197007Sdelphij	/* AF == dont care */
7841197007Sdelphij	CLEAR_FLAG(F_CF);
7842197007Sdelphij}
7843197007Sdelphij
7844197007Sdelphij/*
7845197007Sdelphij * REMARKS:
7846197007Sdelphij * Implements the TEST instruction and side effects.
7847197007Sdelphij */
7848197007Sdelphijstatic void
7849197007Sdelphijtest_long(struct x86emu *emu, uint32_t d, uint32_t s)
7850197007Sdelphij{
7851197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7852197007Sdelphij
7853197007Sdelphij	res = d & s;
7854197007Sdelphij
7855197007Sdelphij	CLEAR_FLAG(F_OF);
7856197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7857197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7858197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7859197007Sdelphij	/* AF == dont care */
7860197007Sdelphij	CLEAR_FLAG(F_CF);
7861197007Sdelphij}
7862197007Sdelphij
7863197007Sdelphij/*
7864197007Sdelphij * REMARKS:
7865197007Sdelphij * Implements the XOR instruction and side effects.
7866197007Sdelphij */
7867197007Sdelphijstatic uint8_t
7868197007Sdelphijxor_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7869197007Sdelphij{
7870197007Sdelphij	uint8_t res;	/* all operands in native machine order */
7871197007Sdelphij
7872197007Sdelphij	res = d ^ s;
7873197007Sdelphij	CLEAR_FLAG(F_OF);
7874197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7875197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7876197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
7877197007Sdelphij	CLEAR_FLAG(F_CF);
7878197007Sdelphij	CLEAR_FLAG(F_AF);
7879197007Sdelphij	return res;
7880197007Sdelphij}
7881197007Sdelphij
7882197007Sdelphij/*
7883197007Sdelphij * REMARKS:
7884197007Sdelphij * Implements the XOR instruction and side effects.
7885197007Sdelphij */
7886197007Sdelphijstatic uint16_t
7887197007Sdelphijxor_word(struct x86emu *emu, uint16_t d, uint16_t s)
7888197007Sdelphij{
7889197007Sdelphij	uint16_t res;	/* all operands in native machine order */
7890197007Sdelphij
7891197007Sdelphij	res = d ^ s;
7892197007Sdelphij	CLEAR_FLAG(F_OF);
7893197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7894197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7895197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7896197007Sdelphij	CLEAR_FLAG(F_CF);
7897197007Sdelphij	CLEAR_FLAG(F_AF);
7898197007Sdelphij	return res;
7899197007Sdelphij}
7900197007Sdelphij
7901197007Sdelphij/*
7902197007Sdelphij * REMARKS:
7903197007Sdelphij * Implements the XOR instruction and side effects.
7904197007Sdelphij */
7905197007Sdelphijstatic uint32_t
7906197007Sdelphijxor_long(struct x86emu *emu, uint32_t d, uint32_t s)
7907197007Sdelphij{
7908197007Sdelphij	uint32_t res;	/* all operands in native machine order */
7909197007Sdelphij
7910197007Sdelphij	res = d ^ s;
7911197007Sdelphij	CLEAR_FLAG(F_OF);
7912197007Sdelphij	CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7913197007Sdelphij	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7914197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7915197007Sdelphij	CLEAR_FLAG(F_CF);
7916197007Sdelphij	CLEAR_FLAG(F_AF);
7917197007Sdelphij	return res;
7918197007Sdelphij}
7919197007Sdelphij
7920197007Sdelphij/*
7921197007Sdelphij * REMARKS:
7922197007Sdelphij * Implements the IMUL instruction and side effects.
7923197007Sdelphij */
7924197007Sdelphijstatic void
7925197007Sdelphijimul_byte(struct x86emu *emu, uint8_t s)
7926197007Sdelphij{
7927197007Sdelphij	int16_t res = (int16_t) ((int8_t) emu->x86.R_AL * (int8_t) s);
7928197007Sdelphij
7929197007Sdelphij	emu->x86.R_AX = res;
7930197007Sdelphij	if (((emu->x86.R_AL & 0x80) == 0 && emu->x86.R_AH == 0x00) ||
7931197007Sdelphij	    ((emu->x86.R_AL & 0x80) != 0 && emu->x86.R_AH == 0xFF)) {
7932197007Sdelphij		CLEAR_FLAG(F_CF);
7933197007Sdelphij		CLEAR_FLAG(F_OF);
7934197007Sdelphij	} else {
7935197007Sdelphij		SET_FLAG(F_CF);
7936197007Sdelphij		SET_FLAG(F_OF);
7937197007Sdelphij	}
7938197007Sdelphij}
7939197007Sdelphij
7940197007Sdelphij/*
7941197007Sdelphij * REMARKS:
7942197007Sdelphij * Implements the IMUL instruction and side effects.
7943197007Sdelphij */
7944197007Sdelphijstatic void
7945197007Sdelphijimul_word(struct x86emu *emu, uint16_t s)
7946197007Sdelphij{
7947197007Sdelphij	int32_t res = (int16_t) emu->x86.R_AX * (int16_t) s;
7948197007Sdelphij
7949197007Sdelphij	emu->x86.R_AX = (uint16_t) res;
7950197007Sdelphij	emu->x86.R_DX = (uint16_t) (res >> 16);
7951197007Sdelphij	if (((emu->x86.R_AX & 0x8000) == 0 && emu->x86.R_DX == 0x00) ||
7952197007Sdelphij	    ((emu->x86.R_AX & 0x8000) != 0 && emu->x86.R_DX == 0xFF)) {
7953197007Sdelphij		CLEAR_FLAG(F_CF);
7954197007Sdelphij		CLEAR_FLAG(F_OF);
7955197007Sdelphij	} else {
7956197007Sdelphij		SET_FLAG(F_CF);
7957197007Sdelphij		SET_FLAG(F_OF);
7958197007Sdelphij	}
7959197007Sdelphij}
7960197007Sdelphij
7961197007Sdelphij/*
7962197007Sdelphij * REMARKS:
7963197007Sdelphij * Implements the IMUL instruction and side effects.
7964197007Sdelphij */
7965197007Sdelphijstatic void
7966197007Sdelphijimul_long(struct x86emu *emu, uint32_t s)
7967197007Sdelphij{
7968197007Sdelphij	int64_t res;
7969197007Sdelphij
7970197007Sdelphij	res = (int64_t)(int32_t)emu->x86.R_EAX * (int32_t)s;
7971197007Sdelphij	emu->x86.R_EAX = (uint32_t)res;
7972197007Sdelphij	emu->x86.R_EDX = ((uint64_t)res) >> 32;
7973197007Sdelphij	if (((emu->x86.R_EAX & 0x80000000) == 0 && emu->x86.R_EDX == 0x00) ||
7974197007Sdelphij	    ((emu->x86.R_EAX & 0x80000000) != 0 && emu->x86.R_EDX == 0xFF)) {
7975197007Sdelphij		CLEAR_FLAG(F_CF);
7976197007Sdelphij		CLEAR_FLAG(F_OF);
7977197007Sdelphij	} else {
7978197007Sdelphij		SET_FLAG(F_CF);
7979197007Sdelphij		SET_FLAG(F_OF);
7980197007Sdelphij	}
7981197007Sdelphij}
7982197007Sdelphij
7983197007Sdelphij/*
7984197007Sdelphij * REMARKS:
7985197007Sdelphij * Implements the MUL instruction and side effects.
7986197007Sdelphij */
7987197007Sdelphijstatic void
7988197007Sdelphijmul_byte(struct x86emu *emu, uint8_t s)
7989197007Sdelphij{
7990197007Sdelphij	uint16_t res = (uint16_t) (emu->x86.R_AL * s);
7991197007Sdelphij
7992197007Sdelphij	emu->x86.R_AX = res;
7993197007Sdelphij	if (emu->x86.R_AH == 0) {
7994197007Sdelphij		CLEAR_FLAG(F_CF);
7995197007Sdelphij		CLEAR_FLAG(F_OF);
7996197007Sdelphij	} else {
7997197007Sdelphij		SET_FLAG(F_CF);
7998197007Sdelphij		SET_FLAG(F_OF);
7999197007Sdelphij	}
8000197007Sdelphij}
8001197007Sdelphij
8002197007Sdelphij/*
8003197007Sdelphij * REMARKS:
8004197007Sdelphij * Implements the MUL instruction and side effects.
8005197007Sdelphij */
8006197007Sdelphijstatic void
8007197007Sdelphijmul_word(struct x86emu *emu, uint16_t s)
8008197007Sdelphij{
8009197007Sdelphij	uint32_t res = emu->x86.R_AX * s;
8010197007Sdelphij
8011197007Sdelphij	emu->x86.R_AX = (uint16_t) res;
8012197007Sdelphij	emu->x86.R_DX = (uint16_t) (res >> 16);
8013197007Sdelphij	if (emu->x86.R_DX == 0) {
8014197007Sdelphij		CLEAR_FLAG(F_CF);
8015197007Sdelphij		CLEAR_FLAG(F_OF);
8016197007Sdelphij	} else {
8017197007Sdelphij		SET_FLAG(F_CF);
8018197007Sdelphij		SET_FLAG(F_OF);
8019197007Sdelphij	}
8020197007Sdelphij}
8021197007Sdelphij
8022197007Sdelphij/*
8023197007Sdelphij * REMARKS:
8024197007Sdelphij * Implements the MUL instruction and side effects.
8025197007Sdelphij */
8026197007Sdelphijstatic void
8027197007Sdelphijmul_long(struct x86emu *emu, uint32_t s)
8028197007Sdelphij{
8029197007Sdelphij	uint64_t res = (uint64_t) emu->x86.R_EAX * s;
8030197007Sdelphij
8031197007Sdelphij	emu->x86.R_EAX = (uint32_t) res;
8032197007Sdelphij	emu->x86.R_EDX = (uint32_t) (res >> 32);
8033197007Sdelphij
8034197007Sdelphij	if (emu->x86.R_EDX == 0) {
8035197007Sdelphij		CLEAR_FLAG(F_CF);
8036197007Sdelphij		CLEAR_FLAG(F_OF);
8037197007Sdelphij	} else {
8038197007Sdelphij		SET_FLAG(F_CF);
8039197007Sdelphij		SET_FLAG(F_OF);
8040197007Sdelphij	}
8041197007Sdelphij}
8042197007Sdelphij
8043197007Sdelphij/*
8044197007Sdelphij * REMARKS:
8045197007Sdelphij * Implements the IDIV instruction and side effects.
8046197007Sdelphij */
8047197007Sdelphijstatic void
8048197007Sdelphijidiv_byte(struct x86emu *emu, uint8_t s)
8049197007Sdelphij{
8050197007Sdelphij	int32_t dvd, div, mod;
8051197007Sdelphij
8052197007Sdelphij	dvd = (int16_t) emu->x86.R_AX;
8053197007Sdelphij	if (s == 0) {
8054197007Sdelphij		x86emu_intr_raise(emu, 8);
8055197007Sdelphij		return;
8056197007Sdelphij	}
8057197007Sdelphij	div = dvd / (int8_t) s;
8058197007Sdelphij	mod = dvd % (int8_t) s;
8059197007Sdelphij	if (div > 0x7f || div < -0x7f) {
8060197007Sdelphij		x86emu_intr_raise(emu, 8);
8061197007Sdelphij		return;
8062197007Sdelphij	}
8063197007Sdelphij	emu->x86.R_AL = (int8_t) div;
8064197007Sdelphij	emu->x86.R_AH = (int8_t) mod;
8065197007Sdelphij}
8066197007Sdelphij
8067197007Sdelphij/*
8068197007Sdelphij * REMARKS:
8069197007Sdelphij * Implements the IDIV instruction and side effects.
8070197007Sdelphij */
8071197007Sdelphijstatic void
8072197007Sdelphijidiv_word(struct x86emu *emu, uint16_t s)
8073197007Sdelphij{
8074197007Sdelphij	int32_t dvd, div, mod;
8075197007Sdelphij
8076197007Sdelphij	dvd = (((int32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
8077197007Sdelphij	if (s == 0) {
8078197007Sdelphij		x86emu_intr_raise(emu, 8);
8079197007Sdelphij		return;
8080197007Sdelphij	}
8081197007Sdelphij	div = dvd / (int16_t) s;
8082197007Sdelphij	mod = dvd % (int16_t) s;
8083197007Sdelphij	if (div > 0x7fff || div < -0x7fff) {
8084197007Sdelphij		x86emu_intr_raise(emu, 8);
8085197007Sdelphij		return;
8086197007Sdelphij	}
8087197007Sdelphij	CLEAR_FLAG(F_CF);
8088197007Sdelphij	CLEAR_FLAG(F_SF);
8089197007Sdelphij	CONDITIONAL_SET_FLAG(div == 0, F_ZF);
8090197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8091197007Sdelphij
8092197007Sdelphij	emu->x86.R_AX = (uint16_t) div;
8093197007Sdelphij	emu->x86.R_DX = (uint16_t) mod;
8094197007Sdelphij}
8095197007Sdelphij
8096197007Sdelphij/*
8097197007Sdelphij * REMARKS:
8098197007Sdelphij * Implements the IDIV instruction and side effects.
8099197007Sdelphij */
8100197007Sdelphijstatic void
8101197007Sdelphijidiv_long(struct x86emu *emu, uint32_t s)
8102197007Sdelphij{
8103197007Sdelphij	int64_t dvd, div, mod;
8104197007Sdelphij
8105197007Sdelphij	dvd = (((int64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
8106197007Sdelphij	if (s == 0) {
8107197007Sdelphij		x86emu_intr_raise(emu, 8);
8108197007Sdelphij		return;
8109197007Sdelphij	}
8110197007Sdelphij	div = dvd / (int32_t) s;
8111197007Sdelphij	mod = dvd % (int32_t) s;
8112197007Sdelphij	if (div > 0x7fffffff || div < -0x7fffffff) {
8113197007Sdelphij		x86emu_intr_raise(emu, 8);
8114197007Sdelphij		return;
8115197007Sdelphij	}
8116197007Sdelphij	CLEAR_FLAG(F_CF);
8117197007Sdelphij	CLEAR_FLAG(F_AF);
8118197007Sdelphij	CLEAR_FLAG(F_SF);
8119197007Sdelphij	SET_FLAG(F_ZF);
8120197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8121197007Sdelphij
8122197007Sdelphij	emu->x86.R_EAX = (uint32_t) div;
8123197007Sdelphij	emu->x86.R_EDX = (uint32_t) mod;
8124197007Sdelphij}
8125197007Sdelphij
8126197007Sdelphij/*
8127197007Sdelphij * REMARKS:
8128197007Sdelphij * Implements the DIV instruction and side effects.
8129197007Sdelphij */
8130197007Sdelphijstatic void
8131197007Sdelphijdiv_byte(struct x86emu *emu, uint8_t s)
8132197007Sdelphij{
8133197007Sdelphij	uint32_t dvd, div, mod;
8134197007Sdelphij
8135197007Sdelphij	dvd = emu->x86.R_AX;
8136197007Sdelphij	if (s == 0) {
8137197007Sdelphij		x86emu_intr_raise(emu, 8);
8138197007Sdelphij		return;
8139197007Sdelphij	}
8140197007Sdelphij	div = dvd / (uint8_t) s;
8141197007Sdelphij	mod = dvd % (uint8_t) s;
8142197007Sdelphij	if (div > 0xff) {
8143197007Sdelphij		x86emu_intr_raise(emu, 8);
8144197007Sdelphij		return;
8145197007Sdelphij	}
8146197007Sdelphij	emu->x86.R_AL = (uint8_t) div;
8147197007Sdelphij	emu->x86.R_AH = (uint8_t) mod;
8148197007Sdelphij}
8149197007Sdelphij
8150197007Sdelphij/*
8151197007Sdelphij * REMARKS:
8152197007Sdelphij * Implements the DIV instruction and side effects.
8153197007Sdelphij */
8154197007Sdelphijstatic void
8155197007Sdelphijdiv_word(struct x86emu *emu, uint16_t s)
8156197007Sdelphij{
8157197007Sdelphij	uint32_t dvd, div, mod;
8158197007Sdelphij
8159197007Sdelphij	dvd = (((uint32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
8160197007Sdelphij	if (s == 0) {
8161197007Sdelphij		x86emu_intr_raise(emu, 8);
8162197007Sdelphij		return;
8163197007Sdelphij	}
8164197007Sdelphij	div = dvd / (uint16_t) s;
8165197007Sdelphij	mod = dvd % (uint16_t) s;
8166197007Sdelphij	if (div > 0xffff) {
8167197007Sdelphij		x86emu_intr_raise(emu, 8);
8168197007Sdelphij		return;
8169197007Sdelphij	}
8170197007Sdelphij	CLEAR_FLAG(F_CF);
8171197007Sdelphij	CLEAR_FLAG(F_SF);
8172197007Sdelphij	CONDITIONAL_SET_FLAG(div == 0, F_ZF);
8173197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8174197007Sdelphij
8175197007Sdelphij	emu->x86.R_AX = (uint16_t) div;
8176197007Sdelphij	emu->x86.R_DX = (uint16_t) mod;
8177197007Sdelphij}
8178197007Sdelphij
8179197007Sdelphij/*
8180197007Sdelphij * REMARKS:
8181197007Sdelphij * Implements the DIV instruction and side effects.
8182197007Sdelphij */
8183197007Sdelphijstatic void
8184197007Sdelphijdiv_long(struct x86emu *emu, uint32_t s)
8185197007Sdelphij{
8186197007Sdelphij	uint64_t dvd, div, mod;
8187197007Sdelphij
8188197007Sdelphij	dvd = (((uint64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
8189197007Sdelphij	if (s == 0) {
8190197007Sdelphij		x86emu_intr_raise(emu, 8);
8191197007Sdelphij		return;
8192197007Sdelphij	}
8193197007Sdelphij	div = dvd / (uint32_t) s;
8194197007Sdelphij	mod = dvd % (uint32_t) s;
8195197007Sdelphij	if (div > 0xffffffff) {
8196197007Sdelphij		x86emu_intr_raise(emu, 8);
8197197007Sdelphij		return;
8198197007Sdelphij	}
8199197007Sdelphij	CLEAR_FLAG(F_CF);
8200197007Sdelphij	CLEAR_FLAG(F_AF);
8201197007Sdelphij	CLEAR_FLAG(F_SF);
8202197007Sdelphij	SET_FLAG(F_ZF);
8203197007Sdelphij	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8204197007Sdelphij
8205197007Sdelphij	emu->x86.R_EAX = (uint32_t) div;
8206197007Sdelphij	emu->x86.R_EDX = (uint32_t) mod;
8207197007Sdelphij}
8208197007Sdelphij
8209197007Sdelphij/*
8210197007Sdelphij * REMARKS:
8211197007Sdelphij * Implements the IN string instruction and side effects.
8212197007Sdelphij */
8213197007Sdelphijstatic void
8214197007Sdelphijins(struct x86emu *emu, int size)
8215197007Sdelphij{
8216197007Sdelphij	int inc = size;
8217197007Sdelphij
8218197007Sdelphij	if (ACCESS_FLAG(F_DF)) {
8219197007Sdelphij		inc = -size;
8220197007Sdelphij	}
8221197007Sdelphij	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
8222197007Sdelphij		/* dont care whether REPE or REPNE */
8223197007Sdelphij		/* in until CX is ZERO. */
8224197007Sdelphij		uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
8225197007Sdelphij		    emu->x86.R_ECX : emu->x86.R_CX);
8226197007Sdelphij		switch (size) {
8227197007Sdelphij		case 1:
8228197007Sdelphij			while (count--) {
8229197007Sdelphij				store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
8230197007Sdelphij				    (*emu->emu_inb) (emu, emu->x86.R_DX));
8231197007Sdelphij				emu->x86.R_DI += inc;
8232197007Sdelphij			}
8233197007Sdelphij			break;
8234197007Sdelphij
8235197007Sdelphij		case 2:
8236197007Sdelphij			while (count--) {
8237197007Sdelphij				store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
8238197007Sdelphij				    (*emu->emu_inw) (emu, emu->x86.R_DX));
8239197007Sdelphij				emu->x86.R_DI += inc;
8240197007Sdelphij			}
8241197007Sdelphij			break;
8242197007Sdelphij		case 4:
8243197007Sdelphij			while (count--) {
8244197007Sdelphij				store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
8245197007Sdelphij				    (*emu->emu_inl) (emu, emu->x86.R_DX));
8246197007Sdelphij				emu->x86.R_DI += inc;
8247197007Sdelphij				break;
8248197007Sdelphij			}
8249197007Sdelphij		}
8250197007Sdelphij		emu->x86.R_CX = 0;
8251197007Sdelphij		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
8252197007Sdelphij			emu->x86.R_ECX = 0;
8253197007Sdelphij		}
8254197007Sdelphij		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
8255197007Sdelphij	} else {
8256197007Sdelphij		switch (size) {
8257197007Sdelphij		case 1:
8258197007Sdelphij			store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
8259197007Sdelphij			    (*emu->emu_inb) (emu, emu->x86.R_DX));
8260197007Sdelphij			break;
8261197007Sdelphij		case 2:
8262197007Sdelphij			store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
8263197007Sdelphij			    (*emu->emu_inw) (emu, emu->x86.R_DX));
8264197007Sdelphij			break;
8265197007Sdelphij		case 4:
8266197007Sdelphij			store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
8267197007Sdelphij			    (*emu->emu_inl) (emu, emu->x86.R_DX));
8268197007Sdelphij			break;
8269197007Sdelphij		}
8270197007Sdelphij		emu->x86.R_DI += inc;
8271197007Sdelphij	}
8272197007Sdelphij}
8273197007Sdelphij
8274197007Sdelphij/*
8275197007Sdelphij * REMARKS:
8276197007Sdelphij * Implements the OUT string instruction and side effects.
8277197007Sdelphij */
8278197007Sdelphijstatic void
8279197007Sdelphijouts(struct x86emu *emu, int size)
8280197007Sdelphij{
8281197007Sdelphij	int inc = size;
8282197007Sdelphij
8283197007Sdelphij	if (ACCESS_FLAG(F_DF)) {
8284197007Sdelphij		inc = -size;
8285197007Sdelphij	}
8286197007Sdelphij	if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
8287197007Sdelphij		/* dont care whether REPE or REPNE */
8288197007Sdelphij		/* out until CX is ZERO. */
8289197007Sdelphij		uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
8290197007Sdelphij		    emu->x86.R_ECX : emu->x86.R_CX);
8291197007Sdelphij		switch (size) {
8292197007Sdelphij		case 1:
8293197007Sdelphij			while (count--) {
8294197007Sdelphij				(*emu->emu_outb) (emu, emu->x86.R_DX,
8295204934Sdelphij				    fetch_byte(emu, emu->x86.R_ES,
8296204934Sdelphij				    emu->x86.R_SI));
8297197007Sdelphij				emu->x86.R_SI += inc;
8298197007Sdelphij			}
8299197007Sdelphij			break;
8300197007Sdelphij
8301197007Sdelphij		case 2:
8302197007Sdelphij			while (count--) {
8303197007Sdelphij				(*emu->emu_outw) (emu, emu->x86.R_DX,
8304204934Sdelphij				    fetch_word(emu, emu->x86.R_ES,
8305204934Sdelphij				    emu->x86.R_SI));
8306197007Sdelphij				emu->x86.R_SI += inc;
8307197007Sdelphij			}
8308197007Sdelphij			break;
8309197007Sdelphij		case 4:
8310197007Sdelphij			while (count--) {
8311197007Sdelphij				(*emu->emu_outl) (emu, emu->x86.R_DX,
8312204934Sdelphij				    fetch_long(emu, emu->x86.R_ES,
8313204934Sdelphij				    emu->x86.R_SI));
8314197007Sdelphij				emu->x86.R_SI += inc;
8315197007Sdelphij				break;
8316197007Sdelphij			}
8317197007Sdelphij		}
8318197007Sdelphij		emu->x86.R_CX = 0;
8319197007Sdelphij		if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
8320197007Sdelphij			emu->x86.R_ECX = 0;
8321197007Sdelphij		}
8322197007Sdelphij		emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
8323197007Sdelphij	} else {
8324197007Sdelphij		switch (size) {
8325197007Sdelphij		case 1:
8326197007Sdelphij			(*emu->emu_outb) (emu, emu->x86.R_DX,
8327197007Sdelphij			    fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI));
8328197007Sdelphij			break;
8329197007Sdelphij		case 2:
8330197007Sdelphij			(*emu->emu_outw) (emu, emu->x86.R_DX,
8331197007Sdelphij			    fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI));
8332197007Sdelphij			break;
8333197007Sdelphij		case 4:
8334197007Sdelphij			(*emu->emu_outl) (emu, emu->x86.R_DX,
8335197007Sdelphij			    fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI));
8336197007Sdelphij			break;
8337197007Sdelphij		}
8338197007Sdelphij		emu->x86.R_SI += inc;
8339197007Sdelphij	}
8340197007Sdelphij}
8341197007Sdelphij
8342197007Sdelphij/*
8343197007Sdelphij * REMARKS:
8344197007Sdelphij * Pushes a word onto the stack.
8345197007Sdelphij *
8346197007Sdelphij * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8347197007Sdelphij */
8348197007Sdelphijstatic void
8349197007Sdelphijpush_word(struct x86emu *emu, uint16_t w)
8350197007Sdelphij{
8351197007Sdelphij	emu->x86.R_SP -= 2;
8352197007Sdelphij	store_word(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8353197007Sdelphij}
8354197007Sdelphij
8355197007Sdelphij/*
8356197007Sdelphij * REMARKS:
8357197007Sdelphij * Pushes a long onto the stack.
8358197007Sdelphij *
8359197007Sdelphij * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8360197007Sdelphij */
8361197007Sdelphijstatic void
8362197007Sdelphijpush_long(struct x86emu *emu, uint32_t w)
8363197007Sdelphij{
8364197007Sdelphij	emu->x86.R_SP -= 4;
8365197007Sdelphij	store_long(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8366197007Sdelphij}
8367197007Sdelphij
8368197007Sdelphij/*
8369197007Sdelphij * REMARKS:
8370197007Sdelphij * Pops a word from the stack.
8371197007Sdelphij *
8372197007Sdelphij * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8373197007Sdelphij */
8374197007Sdelphijstatic uint16_t
8375197007Sdelphijpop_word(struct x86emu *emu)
8376197007Sdelphij{
8377197007Sdelphij	uint16_t res;
8378197007Sdelphij
8379197007Sdelphij	res = fetch_word(emu, emu->x86.R_SS, emu->x86.R_SP);
8380197007Sdelphij	emu->x86.R_SP += 2;
8381197007Sdelphij	return res;
8382197007Sdelphij}
8383197007Sdelphij
8384197007Sdelphij/*
8385197007Sdelphij * REMARKS:
8386197007Sdelphij * Pops a long from the stack.
8387197007Sdelphij *
8388197007Sdelphij * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8389197007Sdelphij */
8390197007Sdelphijstatic uint32_t
8391197007Sdelphijpop_long(struct x86emu *emu)
8392197007Sdelphij{
8393197007Sdelphij	uint32_t res;
8394197007Sdelphij
8395197007Sdelphij	res = fetch_long(emu, emu->x86.R_SS, emu->x86.R_SP);
8396197007Sdelphij	emu->x86.R_SP += 4;
8397197007Sdelphij	return res;
8398197007Sdelphij}
8399