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