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