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