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