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