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