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