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