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