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