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