1/* $NetBSD: x86emu.c,v 1.10 2014/08/04 21:41:44 joerg Exp $ */
2
3/****************************************************************************
4*
5* Realmode X86 Emulator Library
6*
7* Copyright (C) 1996-1999 SciTech Software, Inc.
8* Copyright (C) David Mosberger-Tang
9* Copyright (C) 1999 Egbert Eich
10* Copyright (C) 2007 Joerg Sonnenberger
11*
12* ========================================================================
13*
14* Permission to use, copy, modify, distribute, and sell this software and
15* its documentation for any purpose is hereby granted without fee,
16* provided that the above copyright notice appear in all copies and that
17* both that copyright notice and this permission notice appear in
18* supporting documentation, and that the name of the authors not be used
19* in advertising or publicity pertaining to distribution of the software
20* without specific, written prior permission. The authors makes no
21* representations about the suitability of this software for any purpose.
22* It is provided "as is" without express or implied warranty.
23*
24* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
25* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
26* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
27* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
28* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
29* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
30* PERFORMANCE OF THIS SOFTWARE.
31*
32****************************************************************************/
33
34#ifndef _KERNEL
35#include <stdbool.h>
36#endif
37
38#include <x86emu/x86emu.h>
39#include <x86emu/x86emu_regs.h>
40
41static void x86emu_intr_raise (struct X86EMU *, uint8_t type);
42
43static void X86EMU_exec_one_byte(struct X86EMU *);
44static void X86EMU_exec_two_byte(struct X86EMU *);
45
46static void fetch_decode_modrm (struct X86EMU *);
47static uint8_t fetch_byte_imm (struct X86EMU *);
48static uint16_t fetch_word_imm (struct X86EMU *);
49static uint32_t fetch_long_imm (struct X86EMU *);
50static uint8_t fetch_data_byte (struct X86EMU *, uint32_t offset);
51static uint8_t fetch_byte (struct X86EMU *, uint segment, uint32_t offset);
52static uint16_t fetch_data_word (struct X86EMU *, uint32_t offset);
53static uint16_t fetch_word (struct X86EMU *, uint32_t segment, uint32_t offset);
54static uint32_t fetch_data_long (struct X86EMU *, uint32_t offset);
55static uint32_t fetch_long (struct X86EMU *, uint32_t segment, uint32_t offset);
56static void store_data_byte (struct X86EMU *, uint32_t offset, uint8_t val);
57static void store_byte (struct X86EMU *, uint32_t segment, uint32_t offset, uint8_t val);
58static void store_data_word (struct X86EMU *, uint32_t offset, uint16_t val);
59static void store_word (struct X86EMU *, uint32_t segment, uint32_t offset, uint16_t val);
60static void store_data_long (struct X86EMU *, uint32_t offset, uint32_t val);
61static void store_long (struct X86EMU *, uint32_t segment, uint32_t offset, uint32_t val);
62static uint8_t* decode_rl_byte_register(struct X86EMU *);
63static uint16_t* decode_rl_word_register(struct X86EMU *);
64static uint32_t* decode_rl_long_register(struct X86EMU *);
65static uint8_t* decode_rh_byte_register(struct X86EMU *);
66static uint16_t* decode_rh_word_register(struct X86EMU *);
67static uint32_t* decode_rh_long_register(struct X86EMU *);
68static uint16_t* decode_rh_seg_register(struct X86EMU *);
69static uint32_t decode_rl_address(struct X86EMU *);
70
71static uint8_t decode_and_fetch_byte(struct X86EMU *);
72static uint16_t decode_and_fetch_word(struct X86EMU *);
73static uint32_t decode_and_fetch_long(struct X86EMU *);
74
75static uint8_t decode_and_fetch_byte_imm8(struct X86EMU *, uint8_t *);
76static uint16_t decode_and_fetch_word_imm8(struct X86EMU *, uint8_t *);
77static uint32_t decode_and_fetch_long_imm8(struct X86EMU *, uint8_t *);
78
79static uint16_t decode_and_fetch_word_disp(struct X86EMU *, int16_t);
80static uint32_t decode_and_fetch_long_disp(struct X86EMU *, int16_t);
81
82static void write_back_byte(struct X86EMU *, uint8_t);
83static void write_back_word(struct X86EMU *, uint16_t);
84static void write_back_long(struct X86EMU *, uint32_t);
85
86static uint16_t aaa_word (struct X86EMU *, uint16_t d);
87static uint16_t aas_word (struct X86EMU *, uint16_t d);
88static uint16_t aad_word (struct X86EMU *, uint16_t d);
89static uint16_t aam_word (struct X86EMU *, uint8_t d);
90static uint8_t adc_byte (struct X86EMU *, uint8_t d, uint8_t s);
91static uint16_t adc_word (struct X86EMU *, uint16_t d, uint16_t s);
92static uint32_t adc_long (struct X86EMU *, uint32_t d, uint32_t s);
93static uint8_t add_byte (struct X86EMU *, uint8_t d, uint8_t s);
94static uint16_t add_word (struct X86EMU *, uint16_t d, uint16_t s);
95static uint32_t add_long (struct X86EMU *, uint32_t d, uint32_t s);
96static uint8_t and_byte (struct X86EMU *, uint8_t d, uint8_t s);
97static uint16_t and_word (struct X86EMU *, uint16_t d, uint16_t s);
98static uint32_t and_long (struct X86EMU *, uint32_t d, uint32_t s);
99static uint8_t cmp_byte (struct X86EMU *, uint8_t d, uint8_t s);
100static uint16_t cmp_word (struct X86EMU *, uint16_t d, uint16_t s);
101static uint32_t cmp_long (struct X86EMU *, uint32_t d, uint32_t s);
102static void cmp_byte_no_return (struct X86EMU *, uint8_t d, uint8_t s);
103static void cmp_word_no_return (struct X86EMU *, uint16_t d, uint16_t s);
104static void cmp_long_no_return (struct X86EMU *, uint32_t d, uint32_t s);
105static uint8_t daa_byte (struct X86EMU *, uint8_t d);
106static uint8_t das_byte (struct X86EMU *, uint8_t d);
107static uint8_t dec_byte (struct X86EMU *, uint8_t d);
108static uint16_t dec_word (struct X86EMU *, uint16_t d);
109static uint32_t dec_long (struct X86EMU *, uint32_t d);
110static uint8_t inc_byte (struct X86EMU *, uint8_t d);
111static uint16_t inc_word (struct X86EMU *, uint16_t d);
112static uint32_t inc_long (struct X86EMU *, uint32_t d);
113static uint8_t or_byte (struct X86EMU *, uint8_t d, uint8_t s);
114static uint16_t or_word (struct X86EMU *, uint16_t d, uint16_t s);
115static uint32_t or_long (struct X86EMU *, uint32_t d, uint32_t s);
116static uint8_t neg_byte (struct X86EMU *, uint8_t s);
117static uint16_t neg_word (struct X86EMU *, uint16_t s);
118static uint32_t neg_long (struct X86EMU *, uint32_t s);
119static uint8_t rcl_byte (struct X86EMU *, uint8_t d, uint8_t s);
120static uint16_t rcl_word (struct X86EMU *, uint16_t d, uint8_t s);
121static uint32_t rcl_long (struct X86EMU *, uint32_t d, uint8_t s);
122static uint8_t rcr_byte (struct X86EMU *, uint8_t d, uint8_t s);
123static uint16_t rcr_word (struct X86EMU *, uint16_t d, uint8_t s);
124static uint32_t rcr_long (struct X86EMU *, uint32_t d, uint8_t s);
125static uint8_t rol_byte (struct X86EMU *, uint8_t d, uint8_t s);
126static uint16_t rol_word (struct X86EMU *, uint16_t d, uint8_t s);
127static uint32_t rol_long (struct X86EMU *, uint32_t d, uint8_t s);
128static uint8_t ror_byte (struct X86EMU *, uint8_t d, uint8_t s);
129static uint16_t ror_word (struct X86EMU *, uint16_t d, uint8_t s);
130static uint32_t ror_long (struct X86EMU *, uint32_t d, uint8_t s);
131static uint8_t shl_byte (struct X86EMU *, uint8_t d, uint8_t s);
132static uint16_t shl_word (struct X86EMU *, uint16_t d, uint8_t s);
133static uint32_t shl_long (struct X86EMU *, uint32_t d, uint8_t s);
134static uint8_t shr_byte (struct X86EMU *, uint8_t d, uint8_t s);
135static uint16_t shr_word (struct X86EMU *, uint16_t d, uint8_t s);
136static uint32_t shr_long (struct X86EMU *, uint32_t d, uint8_t s);
137static uint8_t sar_byte (struct X86EMU *, uint8_t d, uint8_t s);
138static uint16_t sar_word (struct X86EMU *, uint16_t d, uint8_t s);
139static uint32_t sar_long (struct X86EMU *, uint32_t d, uint8_t s);
140static uint16_t shld_word (struct X86EMU *, uint16_t d, uint16_t fill, uint8_t s);
141static uint32_t shld_long (struct X86EMU *, uint32_t d, uint32_t fill, uint8_t s);
142static uint16_t shrd_word (struct X86EMU *, uint16_t d, uint16_t fill, uint8_t s);
143static uint32_t shrd_long (struct X86EMU *, uint32_t d, uint32_t fill, uint8_t s);
144static uint8_t sbb_byte (struct X86EMU *, uint8_t d, uint8_t s);
145static uint16_t sbb_word (struct X86EMU *, uint16_t d, uint16_t s);
146static uint32_t sbb_long (struct X86EMU *, uint32_t d, uint32_t s);
147static uint8_t sub_byte (struct X86EMU *, uint8_t d, uint8_t s);
148static uint16_t sub_word (struct X86EMU *, uint16_t d, uint16_t s);
149static uint32_t sub_long (struct X86EMU *, uint32_t d, uint32_t s);
150static void test_byte (struct X86EMU *, uint8_t d, uint8_t s);
151static void test_word (struct X86EMU *, uint16_t d, uint16_t s);
152static void test_long (struct X86EMU *, uint32_t d, uint32_t s);
153static uint8_t xor_byte (struct X86EMU *, uint8_t d, uint8_t s);
154static uint16_t xor_word (struct X86EMU *, uint16_t d, uint16_t s);
155static uint32_t xor_long (struct X86EMU *, uint32_t d, uint32_t s);
156static void imul_byte (struct X86EMU *, uint8_t s);
157static void imul_word (struct X86EMU *, uint16_t s);
158static void imul_long (struct X86EMU *, uint32_t s);
159static void mul_byte (struct X86EMU *, uint8_t s);
160static void mul_word (struct X86EMU *, uint16_t s);
161static void mul_long (struct X86EMU *, uint32_t s);
162static void idiv_byte (struct X86EMU *, uint8_t s);
163static void idiv_word (struct X86EMU *, uint16_t s);
164static void idiv_long (struct X86EMU *, uint32_t s);
165static void div_byte (struct X86EMU *, uint8_t s);
166static void div_word (struct X86EMU *, uint16_t s);
167static void div_long (struct X86EMU *, uint32_t s);
168static void ins (struct X86EMU *, int size);
169static void outs (struct X86EMU *, int size);
170static void push_word (struct X86EMU *, uint16_t w);
171static void push_long (struct X86EMU *, uint32_t w);
172static uint16_t pop_word (struct X86EMU *);
173static uint32_t pop_long (struct X86EMU *);
174
175/****************************************************************************
176REMARKS:
177Handles any pending asychronous interrupts.
178****************************************************************************/
179static void
180x86emu_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
195static void
196x86emu_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/****************************************************************************
207PARAMETERS:
208intrnum - Interrupt number to raise
209
210REMARKS:
211Raise the specified interrupt to be handled before the execution of the
212next instruction.
213****************************************************************************/
214void
215x86emu_intr_raise(struct X86EMU *emu, uint8_t intrnum)
216{
217 emu->x86.intno = intrnum;
218 emu->x86.intr |= INTR_SYNCH;
219}
220/****************************************************************************
221REMARKS:
222Main execution loop for the emulator. We return from here when the system
223halts, which is normally caused by a stack fault when we return from the
224original real mode call.
225****************************************************************************/
226void
227X86EMU_exec(struct X86EMU *emu)
228{
229 emu->x86.intr = 0;
230
231#ifdef _KERNEL
232 if (setjmp(&emu->exec_state))
233 return;
234#else
235 if (setjmp(emu->exec_state))
236 return;
237#endif
238
239 for (;;) {
240 if (emu->x86.intr) {
241 if (((emu->x86.intr & INTR_SYNCH) && (emu->x86.intno == 0 || emu->x86.intno == 2)) ||
242 !ACCESS_FLAG(F_IF)) {
243 x86emu_intr_handle(emu);
244 }
245 }
246 if (emu->x86.R_CS == 0 && emu->x86.R_IP == 0)
247 return;
248 X86EMU_exec_one_byte(emu);
249 ++emu->cur_cycles;
250 }
251}
252
253void
254X86EMU_exec_call(struct X86EMU *emu, uint16_t seg, uint16_t off)
255{
256 push_word(emu, 0);
257 push_word(emu, 0);
258 emu->x86.R_CS = seg;
259 emu->x86.R_IP = off;
260
261 X86EMU_exec(emu);
262}
263
264void
265X86EMU_exec_intr(struct X86EMU *emu, uint8_t intr)
266{
267 push_word(emu, emu->x86.R_FLG);
268 CLEAR_FLAG(F_IF);
269 CLEAR_FLAG(F_TF);
270 push_word(emu, 0);
271 push_word(emu, 0);
272 emu->x86.R_CS = (*emu->emu_rdw)(emu, intr * 4 + 2);
273 emu->x86.R_IP = (*emu->emu_rdw)(emu, intr * 4);
274 emu->x86.intr = 0;
275
276 X86EMU_exec(emu);
277}
278/****************************************************************************
279REMARKS:
280Halts the system by setting the halted system flag.
281****************************************************************************/
282void
283X86EMU_halt_sys(struct X86EMU *emu)
284{
285#ifdef _KERNEL
286 longjmp(&emu->exec_state);
287#else
288 longjmp(emu->exec_state, 1);
289#endif
290}
291/****************************************************************************
292PARAMETERS:
293mod - Mod value from decoded byte
294regh - Reg h value from decoded byte
295regl - Reg l value from decoded byte
296
297REMARKS:
298Raise the specified interrupt to be handled before the execution of the
299next instruction.
300
301NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
302****************************************************************************/
303static void
304fetch_decode_modrm(struct X86EMU *emu)
305{
306 int fetched;
307
308 fetched = fetch_byte_imm(emu);
309 emu->cur_mod = (fetched >> 6) & 0x03;
310 emu->cur_rh = (fetched >> 3) & 0x07;
311 emu->cur_rl = (fetched >> 0) & 0x07;
312}
313/****************************************************************************
314RETURNS:
315Immediate byte value read from instruction queue
316
317REMARKS:
318This function returns the immediate byte from the instruction queue, and
319moves the instruction pointer to the next value.
320
321NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
322****************************************************************************/
323static uint8_t
324fetch_byte_imm(struct X86EMU *emu)
325{
326 uint8_t fetched;
327
328 fetched = fetch_byte(emu, emu->x86.R_CS, emu->x86.R_IP);
329 emu->x86.R_IP++;
330 return fetched;
331}
332/****************************************************************************
333RETURNS:
334Immediate word value read from instruction queue
335
336REMARKS:
337This function returns the immediate byte from the instruction queue, and
338moves the instruction pointer to the next value.
339
340NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
341****************************************************************************/
342static uint16_t
343fetch_word_imm(struct X86EMU *emu)
344{
345 uint16_t fetched;
346
347 fetched = fetch_word(emu, emu->x86.R_CS, emu->x86.R_IP);
348 emu->x86.R_IP += 2;
349 return fetched;
350}
351/****************************************************************************
352RETURNS:
353Immediate lone value read from instruction queue
354
355REMARKS:
356This function returns the immediate byte from the instruction queue, and
357moves the instruction pointer to the next value.
358
359NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
360****************************************************************************/
361static uint32_t
362fetch_long_imm(struct X86EMU *emu)
363{
364 uint32_t fetched;
365
366 fetched = fetch_long(emu, emu->x86.R_CS, emu->x86.R_IP);
367 emu->x86.R_IP += 4;
368 return fetched;
369}
370/****************************************************************************
371RETURNS:
372Value of the default data segment
373
374REMARKS:
375Inline function that returns the default data segment for the current
376instruction.
377
378On the x86 processor, the default segment is not always DS if there is
379no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
380addresses relative to SS (ie: on the stack). So, at the minimum, all
381decodings of addressing modes would have to set/clear a bit describing
382whether the access is relative to DS or SS. That is the function of the
383cpu-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
397Each of the above 7 items are handled with a bit in the mode field.
398****************************************************************************/
399static uint32_t
400get_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/****************************************************************************
428PARAMETERS:
429offset - Offset to load data from
430
431RETURNS:
432Byte value read from the absolute memory location.
433
434NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
435****************************************************************************/
436static uint8_t
437fetch_data_byte(struct X86EMU *emu, uint32_t offset)
438{
439 return fetch_byte(emu, get_data_segment(emu), offset);
440}
441/****************************************************************************
442PARAMETERS:
443offset - Offset to load data from
444
445RETURNS:
446Word value read from the absolute memory location.
447
448NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
449****************************************************************************/
450static uint16_t
451fetch_data_word(struct X86EMU *emu, uint32_t offset)
452{
453 return fetch_word(emu, get_data_segment(emu), offset);
454}
455/****************************************************************************
456PARAMETERS:
457offset - Offset to load data from
458
459RETURNS:
460Long value read from the absolute memory location.
461
462NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
463****************************************************************************/
464static uint32_t
465fetch_data_long(struct X86EMU *emu, uint32_t offset)
466{
467 return fetch_long(emu, get_data_segment(emu), offset);
468}
469/****************************************************************************
470PARAMETERS:
471segment - Segment to load data from
472offset - Offset to load data from
473
474RETURNS:
475Byte value read from the absolute memory location.
476
477NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
478****************************************************************************/
479static uint8_t
480fetch_byte(struct X86EMU *emu, uint32_t segment, uint32_t offset)
481{
482 return (*emu->emu_rdb) (emu, ((uint32_t) segment << 4) + offset);
483}
484/****************************************************************************
485PARAMETERS:
486segment - Segment to load data from
487offset - Offset to load data from
488
489RETURNS:
490Word value read from the absolute memory location.
491
492NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
493****************************************************************************/
494static uint16_t
495fetch_word(struct X86EMU *emu, uint32_t segment, uint32_t offset)
496{
497 return (*emu->emu_rdw) (emu, ((uint32_t) segment << 4) + offset);
498}
499/****************************************************************************
500PARAMETERS:
501segment - Segment to load data from
502offset - Offset to load data from
503
504RETURNS:
505Long value read from the absolute memory location.
506
507NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
508****************************************************************************/
509static uint32_t
510fetch_long(struct X86EMU *emu, uint32_t segment, uint32_t offset)
511{
512 return (*emu->emu_rdl) (emu, ((uint32_t) segment << 4) + offset);
513}
514/****************************************************************************
515PARAMETERS:
516offset - Offset to store data at
517val - Value to store
518
519REMARKS:
520Writes a word value to an segmented memory location. The segment used is
521the current 'default' segment, which may have been overridden.
522
523NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
524****************************************************************************/
525static void
526store_data_byte(struct X86EMU *emu, uint32_t offset, uint8_t val)
527{
528 store_byte(emu, get_data_segment(emu), offset, val);
529}
530/****************************************************************************
531PARAMETERS:
532offset - Offset to store data at
533val - Value to store
534
535REMARKS:
536Writes a word value to an segmented memory location. The segment used is
537the current 'default' segment, which may have been overridden.
538
539NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
540****************************************************************************/
541static void
542store_data_word(struct X86EMU *emu, uint32_t offset, uint16_t val)
543{
544 store_word(emu, get_data_segment(emu), offset, val);
545}
546/****************************************************************************
547PARAMETERS:
548offset - Offset to store data at
549val - Value to store
550
551REMARKS:
552Writes a long value to an segmented memory location. The segment used is
553the current 'default' segment, which may have been overridden.
554
555NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
556****************************************************************************/
557static void
558store_data_long(struct X86EMU *emu, uint32_t offset, uint32_t val)
559{
560 store_long(emu, get_data_segment(emu), offset, val);
561}
562/****************************************************************************
563PARAMETERS:
564segment - Segment to store data at
565offset - Offset to store data at
566val - Value to store
567
568REMARKS:
569Writes a byte value to an absolute memory location.
570
571NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
572****************************************************************************/
573static void
574store_byte(struct X86EMU *emu, uint32_t segment, uint32_t offset, uint8_t val)
575{
576 (*emu->emu_wrb) (emu, ((uint32_t) segment << 4) + offset, val);
577}
578/****************************************************************************
579PARAMETERS:
580segment - Segment to store data at
581offset - Offset to store data at
582val - Value to store
583
584REMARKS:
585Writes a word value to an absolute memory location.
586
587NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
588****************************************************************************/
589static void
590store_word(struct X86EMU *emu, uint32_t segment, uint32_t offset, uint16_t val)
591{
592 (*emu->emu_wrw) (emu, ((uint32_t) segment << 4) + offset, val);
593}
594/****************************************************************************
595PARAMETERS:
596segment - Segment to store data at
597offset - Offset to store data at
598val - Value to store
599
600REMARKS:
601Writes a long value to an absolute memory location.
602
603NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
604****************************************************************************/
605static void
606store_long(struct X86EMU *emu, uint32_t segment, uint32_t offset, uint32_t val)
607{
608 (*emu->emu_wrl) (emu, ((uint32_t) segment << 4) + offset, val);
609}
610/****************************************************************************
611PARAMETERS:
612reg - Register to decode
613
614RETURNS:
615Pointer to the appropriate register
616
617REMARKS:
618Return a pointer to the register given by the R/RM field of the
619modrm byte, for byte operands. Also enables the decoding of instructions.
620****************************************************************************/
621static uint8_t *
622decode_rm_byte_register(struct X86EMU *emu, int reg)
623{
624 switch (reg) {
625 case 0:
626 return &emu->x86.R_AL;
627 case 1:
628 return &emu->x86.R_CL;
629 case 2:
630 return &emu->x86.R_DL;
631 case 3:
632 return &emu->x86.R_BL;
633 case 4:
634 return &emu->x86.R_AH;
635 case 5:
636 return &emu->x86.R_CH;
637 case 6:
638 return &emu->x86.R_DH;
639 case 7:
640 return &emu->x86.R_BH;
641 default:
642 X86EMU_halt_sys(emu);
643 }
644}
645
646static uint8_t *
647decode_rl_byte_register(struct X86EMU *emu)
648{
649 return decode_rm_byte_register(emu, emu->cur_rl);
650}
651
652static uint8_t *
653decode_rh_byte_register(struct X86EMU *emu)
654{
655 return decode_rm_byte_register(emu, emu->cur_rh);
656}
657/****************************************************************************
658PARAMETERS:
659reg - Register to decode
660
661RETURNS:
662Pointer to the appropriate register
663
664REMARKS:
665Return a pointer to the register given by the R/RM field of the
666modrm byte, for word operands. Also enables the decoding of instructions.
667****************************************************************************/
668static uint16_t *
669decode_rm_word_register(struct X86EMU *emu, int reg)
670{
671 switch (reg) {
672 case 0:
673 return &emu->x86.R_AX;
674 case 1:
675 return &emu->x86.R_CX;
676 case 2:
677 return &emu->x86.R_DX;
678 case 3:
679 return &emu->x86.R_BX;
680 case 4:
681 return &emu->x86.R_SP;
682 case 5:
683 return &emu->x86.R_BP;
684 case 6:
685 return &emu->x86.R_SI;
686 case 7:
687 return &emu->x86.R_DI;
688 default:
689 X86EMU_halt_sys(emu);
690 }
691}
692
693static uint16_t *
694decode_rl_word_register(struct X86EMU *emu)
695{
696 return decode_rm_word_register(emu, emu->cur_rl);
697}
698
699static uint16_t *
700decode_rh_word_register(struct X86EMU *emu)
701{
702 return decode_rm_word_register(emu, emu->cur_rh);
703}
704/****************************************************************************
705PARAMETERS:
706reg - Register to decode
707
708RETURNS:
709Pointer to the appropriate register
710
711REMARKS:
712Return a pointer to the register given by the R/RM field of the
713modrm byte, for dword operands. Also enables the decoding of instructions.
714****************************************************************************/
715static uint32_t *
716decode_rm_long_register(struct X86EMU *emu, int reg)
717{
718 switch (reg) {
719 case 0:
720 return &emu->x86.R_EAX;
721 case 1:
722 return &emu->x86.R_ECX;
723 case 2:
724 return &emu->x86.R_EDX;
725 case 3:
726 return &emu->x86.R_EBX;
727 case 4:
728 return &emu->x86.R_ESP;
729 case 5:
730 return &emu->x86.R_EBP;
731 case 6:
732 return &emu->x86.R_ESI;
733 case 7:
734 return &emu->x86.R_EDI;
735 default:
736 X86EMU_halt_sys(emu);
737 }
738}
739
740static uint32_t *
741decode_rl_long_register(struct X86EMU *emu)
742{
743 return decode_rm_long_register(emu, emu->cur_rl);
744}
745
746static uint32_t *
747decode_rh_long_register(struct X86EMU *emu)
748{
749 return decode_rm_long_register(emu, emu->cur_rh);
750}
751
752/****************************************************************************
753PARAMETERS:
754reg - Register to decode
755
756RETURNS:
757Pointer to the appropriate register
758
759REMARKS:
760Return a pointer to the register given by the R/RM field of the
761modrm byte, for word operands, modified from above for the weirdo
762special case of segreg operands. Also enables the decoding of instructions.
763****************************************************************************/
764static uint16_t *
765decode_rh_seg_register(struct X86EMU *emu)
766{
767 switch (emu->cur_rh) {
768 case 0:
769 return &emu->x86.R_ES;
770 case 1:
771 return &emu->x86.R_CS;
772 case 2:
773 return &emu->x86.R_SS;
774 case 3:
775 return &emu->x86.R_DS;
776 case 4:
777 return &emu->x86.R_FS;
778 case 5:
779 return &emu->x86.R_GS;
780 default:
781 X86EMU_halt_sys(emu);
782 }
783}
784/*
785 *
786 * return offset from the SIB Byte
787 */
788static uint32_t
789decode_sib_address(struct X86EMU *emu, int sib, int mod)
790{
791 uint32_t base = 0, i = 0, scale = 1;
792
793 switch (sib & 0x07) {
794 case 0:
795 base = emu->x86.R_EAX;
796 break;
797 case 1:
798 base = emu->x86.R_ECX;
799 break;
800 case 2:
801 base = emu->x86.R_EDX;
802 break;
803 case 3:
804 base = emu->x86.R_EBX;
805 break;
806 case 4:
807 base = emu->x86.R_ESP;
808 emu->x86.mode |= SYSMODE_SEG_DS_SS;
809 break;
810 case 5:
811 if (mod == 0) {
812 base = fetch_long_imm(emu);
813 } else {
814 base = emu->x86.R_EBP;
815 emu->x86.mode |= SYSMODE_SEG_DS_SS;
816 }
817 break;
818 case 6:
819 base = emu->x86.R_ESI;
820 break;
821 case 7:
822 base = emu->x86.R_EDI;
823 break;
824 }
825 switch ((sib >> 3) & 0x07) {
826 case 0:
827 i = emu->x86.R_EAX;
828 break;
829 case 1:
830 i = emu->x86.R_ECX;
831 break;
832 case 2:
833 i = emu->x86.R_EDX;
834 break;
835 case 3:
836 i = emu->x86.R_EBX;
837 break;
838 case 4:
839 i = 0;
840 break;
841 case 5:
842 i = emu->x86.R_EBP;
843 break;
844 case 6:
845 i = emu->x86.R_ESI;
846 break;
847 case 7:
848 i = emu->x86.R_EDI;
849 break;
850 }
851 scale = 1 << ((sib >> 6) & 0x03);
852 return base + (i * scale);
853}
854/****************************************************************************
855PARAMETERS:
856rm - RM value to decode
857
858RETURNS:
859Offset in memory for the address decoding
860
861REMARKS:
862Return the offset given by mod=00, mod=01 or mod=10 addressing.
863Also enables the decoding of instructions.
864****************************************************************************/
865static uint32_t
866decode_rl_address(struct X86EMU *emu)
867{
868 if (emu->x86.mode & SYSMODE_PREFIX_ADDR) {
869 uint32_t offset, sib;
870 /* 32-bit addressing */
871 switch (emu->cur_rl) {
872 case 0:
873 offset = emu->x86.R_EAX;
874 break;
875 case 1:
876 offset = emu->x86.R_ECX;
877 break;
878 case 2:
879 offset = emu->x86.R_EDX;
880 break;
881 case 3:
882 offset = emu->x86.R_EBX;
883 break;
884 case 4:
885 sib = fetch_byte_imm(emu);
886 offset = decode_sib_address(emu, sib, 0);
887 break;
888 case 5:
889 if (emu->cur_mod == 0) {
890 offset = fetch_long_imm(emu);
891 } else {
892 emu->x86.mode |= SYSMODE_SEG_DS_SS;
893 offset = emu->x86.R_EBP;
894 }
895 break;
896 case 6:
897 offset = emu->x86.R_ESI;
898 break;
899 case 7:
900 offset = emu->x86.R_EDI;
901 break;
902 default:
903 X86EMU_halt_sys(emu);
904 }
905 if (emu->cur_mod == 1)
906 offset += (int8_t)fetch_byte_imm(emu);
907 else if (emu->cur_mod == 2)
908 offset += fetch_long_imm(emu);
909 return offset;
910 } else {
911 uint16_t offset;
912
913 /* 16-bit addressing */
914 switch (emu->cur_rl) {
915 case 0:
916 offset = emu->x86.R_BX + emu->x86.R_SI;
917 break;
918 case 1:
919 offset = emu->x86.R_BX + emu->x86.R_DI;
920 break;
921 case 2:
922 emu->x86.mode |= SYSMODE_SEG_DS_SS;
923 offset = emu->x86.R_BP + emu->x86.R_SI;
924 break;
925 case 3:
926 emu->x86.mode |= SYSMODE_SEG_DS_SS;
927 offset = emu->x86.R_BP + emu->x86.R_DI;
928 break;
929 case 4:
930 offset = emu->x86.R_SI;
931 break;
932 case 5:
933 offset = emu->x86.R_DI;
934 break;
935 case 6:
936 if (emu->cur_mod == 0) {
937 offset = fetch_word_imm(emu);
938 } else {
939 emu->x86.mode |= SYSMODE_SEG_DS_SS;
940 offset = emu->x86.R_BP;
941 }
942 break;
943 case 7:
944 offset = emu->x86.R_BX;
945 break;
946 default:
947 X86EMU_halt_sys(emu);
948 }
949 if (emu->cur_mod == 1)
950 offset += (int8_t)fetch_byte_imm(emu);
951 else if (emu->cur_mod == 2)
952 offset += fetch_word_imm(emu);
953 return offset;
954 }
955}
956
957static uint8_t
958decode_and_fetch_byte(struct X86EMU *emu)
959{
960 if (emu->cur_mod != 3) {
961 emu->cur_offset = decode_rl_address(emu);
962 return fetch_data_byte(emu, emu->cur_offset);
963 } else {
964 return *decode_rl_byte_register(emu);
965 }
966}
967
968static uint16_t
969decode_and_fetch_word_disp(struct X86EMU *emu, int16_t disp)
970{
971 if (emu->cur_mod != 3) {
972 /* TODO: A20 gate emulation */
973 emu->cur_offset = decode_rl_address(emu) + disp;
974 if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0)
975 emu->cur_offset &= 0xffff;
976 return fetch_data_word(emu, emu->cur_offset);
977 } else {
978 return *decode_rl_word_register(emu);
979 }
980}
981
982static uint32_t
983decode_and_fetch_long_disp(struct X86EMU *emu, int16_t disp)
984{
985 if (emu->cur_mod != 3) {
986 /* TODO: A20 gate emulation */
987 emu->cur_offset = decode_rl_address(emu) + disp;
988 if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0)
989 emu->cur_offset &= 0xffff;
990 return fetch_data_long(emu, emu->cur_offset);
991 } else {
992 return *decode_rl_long_register(emu);
993 }
994}
995
996uint16_t
997decode_and_fetch_word(struct X86EMU *emu)
998{
999 return decode_and_fetch_word_disp(emu, 0);
1000}
1001
1002uint32_t
1003decode_and_fetch_long(struct X86EMU *emu)
1004{
1005 return decode_and_fetch_long_disp(emu, 0);
1006}
1007
1008uint8_t
1009decode_and_fetch_byte_imm8(struct X86EMU *emu, uint8_t *imm)
1010{
1011 if (emu->cur_mod != 3) {
1012 emu->cur_offset = decode_rl_address(emu);
1013 *imm = fetch_byte_imm(emu);
1014 return fetch_data_byte(emu, emu->cur_offset);
1015 } else {
1016 *imm = fetch_byte_imm(emu);
1017 return *decode_rl_byte_register(emu);
1018 }
1019}
1020
1021static uint16_t
1022decode_and_fetch_word_imm8(struct X86EMU *emu, uint8_t *imm)
1023{
1024 if (emu->cur_mod != 3) {
1025 emu->cur_offset = decode_rl_address(emu);
1026 *imm = fetch_byte_imm(emu);
1027 return fetch_data_word(emu, emu->cur_offset);
1028 } else {
1029 *imm = fetch_byte_imm(emu);
1030 return *decode_rl_word_register(emu);
1031 }
1032}
1033
1034static uint32_t
1035decode_and_fetch_long_imm8(struct X86EMU *emu, uint8_t *imm)
1036{
1037 if (emu->cur_mod != 3) {
1038 emu->cur_offset = decode_rl_address(emu);
1039 *imm = fetch_byte_imm(emu);
1040 return fetch_data_long(emu, emu->cur_offset);
1041 } else {
1042 *imm = fetch_byte_imm(emu);
1043 return *decode_rl_long_register(emu);
1044 }
1045}
1046
1047static void
1048write_back_byte(struct X86EMU *emu, uint8_t val)
1049{
1050 if (emu->cur_mod != 3)
1051 store_data_byte(emu, emu->cur_offset, val);
1052 else
1053 *decode_rl_byte_register(emu) = val;
1054}
1055
1056static void
1057write_back_word(struct X86EMU *emu, uint16_t val)
1058{
1059 if (emu->cur_mod != 3)
1060 store_data_word(emu, emu->cur_offset, val);
1061 else
1062 *decode_rl_word_register(emu) = val;
1063}
1064
1065static void
1066write_back_long(struct X86EMU *emu, uint32_t val)
1067{
1068 if (emu->cur_mod != 3)
1069 store_data_long(emu, emu->cur_offset, val);
1070 else
1071 *decode_rl_long_register(emu) = val;
1072}
1073
1074static void
1075common_inc_word_long(struct X86EMU *emu, union X86EMU_register *reg)
1076{
1077 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1078 reg->I32_reg.e_reg = inc_long(emu, reg->I32_reg.e_reg);
1079 else
1080 reg->I16_reg.x_reg = inc_word(emu, reg->I16_reg.x_reg);
1081}
1082
1083static void
1084common_dec_word_long(struct X86EMU *emu, union X86EMU_register *reg)
1085{
1086 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1087 reg->I32_reg.e_reg = dec_long(emu, reg->I32_reg.e_reg);
1088 else
1089 reg->I16_reg.x_reg = dec_word(emu, reg->I16_reg.x_reg);
1090}
1091
1092static void
1093common_binop_byte_rm_r(struct X86EMU *emu, uint8_t (*binop)(struct X86EMU *, uint8_t, uint8_t))
1094{
1095 uint32_t destoffset;
1096 uint8_t *destreg, srcval;
1097 uint8_t destval;
1098
1099 fetch_decode_modrm(emu);
1100 srcval = *decode_rh_byte_register(emu);
1101 if (emu->cur_mod != 3) {
1102 destoffset = decode_rl_address(emu);
1103 destval = fetch_data_byte(emu, destoffset);
1104 destval = (*binop)(emu, destval, srcval);
1105 store_data_byte(emu, destoffset, destval);
1106 } else {
1107 destreg = decode_rl_byte_register(emu);
1108 *destreg = (*binop)(emu, *destreg, srcval);
1109 }
1110}
1111
1112static void
1113common_binop_ns_byte_rm_r(struct X86EMU *emu, void (*binop)(struct X86EMU *, uint8_t, uint8_t))
1114{
1115 uint32_t destoffset;
1116 uint8_t destval, srcval;
1117
1118 fetch_decode_modrm(emu);
1119 srcval = *decode_rh_byte_register(emu);
1120 if (emu->cur_mod != 3) {
1121 destoffset = decode_rl_address(emu);
1122 destval = fetch_data_byte(emu, destoffset);
1123 } else {
1124 destval = *decode_rl_byte_register(emu);
1125 }
1126 (*binop)(emu, destval, srcval);
1127}
1128
1129static void
1130common_binop_word_rm_r(struct X86EMU *emu, uint16_t (*binop)(struct X86EMU *, uint16_t, uint16_t))
1131{
1132 uint32_t destoffset;
1133 uint16_t destval, *destreg, srcval;
1134
1135 fetch_decode_modrm(emu);
1136 srcval = *decode_rh_word_register(emu);
1137 if (emu->cur_mod != 3) {
1138 destoffset = decode_rl_address(emu);
1139 destval = fetch_data_word(emu, destoffset);
1140 destval = (*binop)(emu, destval, srcval);
1141 store_data_word(emu, destoffset, destval);
1142 } else {
1143 destreg = decode_rl_word_register(emu);
1144 *destreg = (*binop)(emu, *destreg, srcval);
1145 }
1146}
1147
1148static void
1149common_binop_byte_r_rm(struct X86EMU *emu, uint8_t (*binop)(struct X86EMU *, uint8_t, uint8_t))
1150{
1151 uint8_t *destreg, srcval;
1152 uint32_t srcoffset;
1153
1154 fetch_decode_modrm(emu);
1155 destreg = decode_rh_byte_register(emu);
1156 if (emu->cur_mod != 3) {
1157 srcoffset = decode_rl_address(emu);
1158 srcval = fetch_data_byte(emu, srcoffset);
1159 } else {
1160 srcval = *decode_rl_byte_register(emu);
1161 }
1162 *destreg = (*binop)(emu, *destreg, srcval);
1163}
1164
1165static void
1166common_binop_long_rm_r(struct X86EMU *emu, uint32_t (*binop)(struct X86EMU *, uint32_t, uint32_t))
1167{
1168 uint32_t destoffset;
1169 uint32_t destval, *destreg, srcval;
1170
1171 fetch_decode_modrm(emu);
1172 srcval = *decode_rh_long_register(emu);
1173 if (emu->cur_mod != 3) {
1174 destoffset = decode_rl_address(emu);
1175 destval = fetch_data_long(emu, destoffset);
1176 destval = (*binop)(emu, destval, srcval);
1177 store_data_long(emu, destoffset, destval);
1178 } else {
1179 destreg = decode_rl_long_register(emu);
1180 *destreg = (*binop)(emu, *destreg, srcval);
1181 }
1182}
1183
1184static void
1185common_binop_word_long_rm_r(struct X86EMU *emu,
1186 uint16_t (*binop16)(struct X86EMU *, uint16_t, uint16_t), uint32_t (*binop32)(struct X86EMU *, uint32_t, uint32_t))
1187{
1188 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1189 common_binop_long_rm_r(emu, binop32);
1190 else
1191 common_binop_word_rm_r(emu, binop16);
1192}
1193
1194static void
1195common_binop_ns_word_rm_r(struct X86EMU *emu, void (*binop)(struct X86EMU *, uint16_t, uint16_t))
1196{
1197 uint32_t destoffset;
1198 uint16_t destval, srcval;
1199
1200 fetch_decode_modrm(emu);
1201 srcval = *decode_rh_word_register(emu);
1202 if (emu->cur_mod != 3) {
1203 destoffset = decode_rl_address(emu);
1204 destval = fetch_data_word(emu, destoffset);
1205 } else {
1206 destval = *decode_rl_word_register(emu);
1207 }
1208 (*binop)(emu, destval, srcval);
1209}
1210
1211
1212static void
1213common_binop_ns_long_rm_r(struct X86EMU *emu, void (*binop)(struct X86EMU *, uint32_t, uint32_t))
1214{
1215 uint32_t destoffset;
1216 uint32_t destval, srcval;
1217
1218 fetch_decode_modrm(emu);
1219 srcval = *decode_rh_long_register(emu);
1220 if (emu->cur_mod != 3) {
1221 destoffset = decode_rl_address(emu);
1222 destval = fetch_data_long(emu, destoffset);
1223 } else {
1224 destval = *decode_rl_long_register(emu);
1225 }
1226 (*binop)(emu, destval, srcval);
1227}
1228
1229static void
1230common_binop_ns_word_long_rm_r(struct X86EMU *emu,
1231 void (*binop16)(struct X86EMU *, uint16_t, uint16_t), void (*binop32)(struct X86EMU *, uint32_t, uint32_t))
1232{
1233 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1234 common_binop_ns_long_rm_r(emu, binop32);
1235 else
1236 common_binop_ns_word_rm_r(emu, binop16);
1237}
1238
1239static void
1240common_binop_long_r_rm(struct X86EMU *emu, uint32_t (*binop)(struct X86EMU *, uint32_t, uint32_t))
1241{
1242 uint32_t srcoffset;
1243 uint32_t *destreg, srcval;
1244
1245 fetch_decode_modrm(emu);
1246 destreg = decode_rh_long_register(emu);
1247 if (emu->cur_mod != 3) {
1248 srcoffset = decode_rl_address(emu);
1249 srcval = fetch_data_long(emu, srcoffset);
1250 } else {
1251 srcval = *decode_rl_long_register(emu);
1252 }
1253 *destreg = (*binop)(emu, *destreg, srcval);
1254}
1255
1256static void
1257common_binop_word_r_rm(struct X86EMU *emu, uint16_t (*binop)(struct X86EMU *, uint16_t, uint16_t))
1258{
1259 uint32_t srcoffset;
1260 uint16_t *destreg, srcval;
1261
1262 fetch_decode_modrm(emu);
1263 destreg = decode_rh_word_register(emu);
1264 if (emu->cur_mod != 3) {
1265 srcoffset = decode_rl_address(emu);
1266 srcval = fetch_data_word(emu, srcoffset);
1267 } else {
1268 srcval = *decode_rl_word_register(emu);
1269 }
1270 *destreg = (*binop)(emu, *destreg, srcval);
1271}
1272
1273static void
1274common_binop_word_long_r_rm(struct X86EMU *emu,
1275 uint16_t (*binop16)(struct X86EMU *, uint16_t, uint16_t), uint32_t (*binop32)(struct X86EMU *, uint32_t, uint32_t))
1276{
1277 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1278 common_binop_long_r_rm(emu, binop32);
1279 else
1280 common_binop_word_r_rm(emu, binop16);
1281}
1282
1283static void
1284common_binop_byte_imm(struct X86EMU *emu, uint8_t (*binop)(struct X86EMU *, uint8_t, uint8_t))
1285{
1286 uint8_t srcval;
1287
1288 srcval = fetch_byte_imm(emu);
1289 emu->x86.R_AL = (*binop)(emu, emu->x86.R_AL, srcval);
1290}
1291
1292static void
1293common_binop_word_long_imm(struct X86EMU *emu,
1294 uint16_t (*binop16)(struct X86EMU *, uint16_t, uint16_t), uint32_t (*binop32)(struct X86EMU *, uint32_t, uint32_t))
1295{
1296 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1297 uint32_t srcval;
1298
1299 srcval = fetch_long_imm(emu);
1300 emu->x86.R_EAX = (*binop32)(emu, emu->x86.R_EAX, srcval);
1301 } else {
1302 uint16_t srcval;
1303
1304 srcval = fetch_word_imm(emu);
1305 emu->x86.R_AX = (*binop16)(emu, emu->x86.R_AX, srcval);
1306 }
1307}
1308
1309static void
1310common_push_word_long(struct X86EMU *emu, union X86EMU_register *reg)
1311{
1312 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1313 push_long(emu, reg->I32_reg.e_reg);
1314 else
1315 push_word(emu, reg->I16_reg.x_reg);
1316}
1317
1318static void
1319common_pop_word_long(struct X86EMU *emu, union X86EMU_register *reg)
1320{
1321 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1322 reg->I32_reg.e_reg = pop_long(emu);
1323 else
1324 reg->I16_reg.x_reg = pop_word(emu);
1325}
1326
1327static void
1328common_imul_long_IMM(struct X86EMU *emu, bool byte_imm)
1329{
1330 uint32_t srcoffset;
1331 uint32_t *destreg, srcval;
1332 int32_t imm;
1333 uint64_t res;
1334
1335 fetch_decode_modrm(emu);
1336 destreg = decode_rh_long_register(emu);
1337 if (emu->cur_mod != 3) {
1338 srcoffset = decode_rl_address(emu);
1339 srcval = fetch_data_long(emu, srcoffset);
1340 } else {
1341 srcval = *decode_rl_long_register(emu);
1342 }
1343
1344 if (byte_imm)
1345 imm = (int8_t)fetch_byte_imm(emu);
1346 else
1347 imm = fetch_long_imm(emu);
1348 res = (int32_t)srcval * imm;
1349
1350 if (res > 0xffffffff) {
1351 SET_FLAG(F_CF);
1352 SET_FLAG(F_OF);
1353 } else {
1354 CLEAR_FLAG(F_CF);
1355 CLEAR_FLAG(F_OF);
1356 }
1357 *destreg = (uint32_t)res;
1358}
1359
1360static void
1361common_imul_word_IMM(struct X86EMU *emu, bool byte_imm)
1362{
1363 uint32_t srcoffset;
1364 uint16_t *destreg, srcval;
1365 int16_t imm;
1366 uint32_t res;
1367
1368 fetch_decode_modrm(emu);
1369 destreg = decode_rh_word_register(emu);
1370 if (emu->cur_mod != 3) {
1371 srcoffset = decode_rl_address(emu);
1372 srcval = fetch_data_word(emu, srcoffset);
1373 } else {
1374 srcval = *decode_rl_word_register(emu);
1375 }
1376
1377 if (byte_imm)
1378 imm = (int8_t)fetch_byte_imm(emu);
1379 else
1380 imm = fetch_word_imm(emu);
1381 res = (int16_t)srcval * imm;
1382
1383 if (res > 0xffff) {
1384 SET_FLAG(F_CF);
1385 SET_FLAG(F_OF);
1386 } else {
1387 CLEAR_FLAG(F_CF);
1388 CLEAR_FLAG(F_OF);
1389 }
1390 *destreg = (uint16_t) res;
1391}
1392
1393static void
1394common_imul_imm(struct X86EMU *emu, bool byte_imm)
1395{
1396 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1397 common_imul_long_IMM(emu, byte_imm);
1398 else
1399 common_imul_word_IMM(emu, byte_imm);
1400}
1401
1402static void
1403common_jmp_near(struct X86EMU *emu, bool cond)
1404{
1405 int8_t offset;
1406 uint16_t target;
1407
1408 offset = (int8_t) fetch_byte_imm(emu);
1409 target = (uint16_t) (emu->x86.R_IP + (int16_t) offset);
1410 if (cond)
1411 emu->x86.R_IP = target;
1412}
1413
1414static void
1415common_load_far_pointer(struct X86EMU *emu, uint16_t *seg)
1416{
1417 uint16_t *dstreg;
1418 uint32_t srcoffset;
1419
1420 fetch_decode_modrm(emu);
1421 if (emu->cur_mod == 3)
1422 X86EMU_halt_sys(emu);
1423
1424 dstreg = decode_rh_word_register(emu);
1425 srcoffset = decode_rl_address(emu);
1426 *dstreg = fetch_data_word(emu, srcoffset);
1427 *seg = fetch_data_word(emu, srcoffset + 2);
1428}
1429
1430/*----------------------------- Implementation ----------------------------*/
1431/****************************************************************************
1432REMARKS:
1433Handles opcode 0x3a
1434****************************************************************************/
1435static void
1436x86emuOp_cmp_byte_R_RM(struct X86EMU *emu)
1437{
1438 uint8_t *destreg, srcval;
1439
1440 fetch_decode_modrm(emu);
1441 destreg = decode_rh_byte_register(emu);
1442 srcval = decode_and_fetch_byte(emu);
1443 cmp_byte(emu, *destreg, srcval);
1444}
1445/****************************************************************************
1446REMARKS:
1447Handles opcode 0x3b
1448****************************************************************************/
1449static void
1450x86emuOp32_cmp_word_R_RM(struct X86EMU *emu)
1451{
1452 uint32_t srcval, *destreg;
1453
1454 fetch_decode_modrm(emu);
1455 destreg = decode_rh_long_register(emu);
1456 srcval = decode_and_fetch_long(emu);
1457 cmp_long(emu, *destreg, srcval);
1458}
1459
1460static void
1461x86emuOp16_cmp_word_R_RM(struct X86EMU *emu)
1462{
1463 uint16_t srcval, *destreg;
1464
1465 fetch_decode_modrm(emu);
1466 destreg = decode_rh_word_register(emu);
1467 srcval = decode_and_fetch_word(emu);
1468 cmp_word(emu, *destreg, srcval);
1469}
1470
1471static void
1472x86emuOp_cmp_word_R_RM(struct X86EMU *emu)
1473{
1474 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1475 x86emuOp32_cmp_word_R_RM(emu);
1476 else
1477 x86emuOp16_cmp_word_R_RM(emu);
1478}
1479/****************************************************************************
1480REMARKS:
1481Handles opcode 0x3c
1482****************************************************************************/
1483static void
1484x86emuOp_cmp_byte_AL_IMM(struct X86EMU *emu)
1485{
1486 uint8_t srcval;
1487
1488 srcval = fetch_byte_imm(emu);
1489 cmp_byte(emu, emu->x86.R_AL, srcval);
1490}
1491/****************************************************************************
1492REMARKS:
1493Handles opcode 0x3d
1494****************************************************************************/
1495static void
1496x86emuOp32_cmp_word_AX_IMM(struct X86EMU *emu)
1497{
1498 uint32_t srcval;
1499
1500 srcval = fetch_long_imm(emu);
1501 cmp_long(emu, emu->x86.R_EAX, srcval);
1502}
1503
1504static void
1505x86emuOp16_cmp_word_AX_IMM(struct X86EMU *emu)
1506{
1507 uint16_t srcval;
1508
1509 srcval = fetch_word_imm(emu);
1510 cmp_word(emu, emu->x86.R_AX, srcval);
1511}
1512
1513static void
1514x86emuOp_cmp_word_AX_IMM(struct X86EMU *emu)
1515{
1516 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1517 x86emuOp32_cmp_word_AX_IMM(emu);
1518 else
1519 x86emuOp16_cmp_word_AX_IMM(emu);
1520}
1521/****************************************************************************
1522REMARKS:
1523Handles opcode 0x60
1524****************************************************************************/
1525static void
1526x86emuOp_push_all(struct X86EMU *emu)
1527{
1528 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1529 uint32_t old_sp = emu->x86.R_ESP;
1530
1531 push_long(emu, emu->x86.R_EAX);
1532 push_long(emu, emu->x86.R_ECX);
1533 push_long(emu, emu->x86.R_EDX);
1534 push_long(emu, emu->x86.R_EBX);
1535 push_long(emu, old_sp);
1536 push_long(emu, emu->x86.R_EBP);
1537 push_long(emu, emu->x86.R_ESI);
1538 push_long(emu, emu->x86.R_EDI);
1539 } else {
1540 uint16_t old_sp = emu->x86.R_SP;
1541
1542 push_word(emu, emu->x86.R_AX);
1543 push_word(emu, emu->x86.R_CX);
1544 push_word(emu, emu->x86.R_DX);
1545 push_word(emu, emu->x86.R_BX);
1546 push_word(emu, old_sp);
1547 push_word(emu, emu->x86.R_BP);
1548 push_word(emu, emu->x86.R_SI);
1549 push_word(emu, emu->x86.R_DI);
1550 }
1551}
1552/****************************************************************************
1553REMARKS:
1554Handles opcode 0x61
1555****************************************************************************/
1556static void
1557x86emuOp_pop_all(struct X86EMU *emu)
1558{
1559 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1560 emu->x86.R_EDI = pop_long(emu);
1561 emu->x86.R_ESI = pop_long(emu);
1562 emu->x86.R_EBP = pop_long(emu);
1563 emu->x86.R_ESP += 4; /* skip ESP */
1564 emu->x86.R_EBX = pop_long(emu);
1565 emu->x86.R_EDX = pop_long(emu);
1566 emu->x86.R_ECX = pop_long(emu);
1567 emu->x86.R_EAX = pop_long(emu);
1568 } else {
1569 emu->x86.R_DI = pop_word(emu);
1570 emu->x86.R_SI = pop_word(emu);
1571 emu->x86.R_BP = pop_word(emu);
1572 emu->x86.R_SP += 2;/* skip SP */
1573 emu->x86.R_BX = pop_word(emu);
1574 emu->x86.R_DX = pop_word(emu);
1575 emu->x86.R_CX = pop_word(emu);
1576 emu->x86.R_AX = pop_word(emu);
1577 }
1578}
1579/*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
1580/*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
1581
1582/****************************************************************************
1583REMARKS:
1584Handles opcode 0x68
1585****************************************************************************/
1586static void
1587x86emuOp_push_word_IMM(struct X86EMU *emu)
1588{
1589 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1590 uint32_t imm;
1591
1592 imm = fetch_long_imm(emu);
1593 push_long(emu, imm);
1594 } else {
1595 uint16_t imm;
1596
1597 imm = fetch_word_imm(emu);
1598 push_word(emu, imm);
1599 }
1600}
1601/****************************************************************************
1602REMARKS:
1603Handles opcode 0x6a
1604****************************************************************************/
1605static void
1606x86emuOp_push_byte_IMM(struct X86EMU *emu)
1607{
1608 int16_t imm;
1609
1610 imm = (int8_t) fetch_byte_imm(emu);
1611 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1612 push_long(emu, (int32_t) imm);
1613 } else {
1614 push_word(emu, imm);
1615 }
1616}
1617/****************************************************************************
1618REMARKS:
1619Handles opcode 0x6c
1620****************************************************************************/
1621/****************************************************************************
1622REMARKS:
1623Handles opcode 0x6d
1624****************************************************************************/
1625static void
1626x86emuOp_ins_word(struct X86EMU *emu)
1627{
1628 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1629 ins(emu, 4);
1630 } else {
1631 ins(emu, 2);
1632 }
1633}
1634/****************************************************************************
1635REMARKS:
1636Handles opcode 0x6f
1637****************************************************************************/
1638static void
1639x86emuOp_outs_word(struct X86EMU *emu)
1640{
1641 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1642 outs(emu, 4);
1643 } else {
1644 outs(emu, 2);
1645 }
1646}
1647/****************************************************************************
1648REMARKS:
1649Handles opcode 0x7c
1650****************************************************************************/
1651static void
1652x86emuOp_jump_near_L(struct X86EMU *emu)
1653{
1654 bool sf, of;
1655
1656 sf = ACCESS_FLAG(F_SF) != 0;
1657 of = ACCESS_FLAG(F_OF) != 0;
1658
1659 common_jmp_near(emu, sf != of);
1660}
1661/****************************************************************************
1662REMARKS:
1663Handles opcode 0x7d
1664****************************************************************************/
1665static void
1666x86emuOp_jump_near_NL(struct X86EMU *emu)
1667{
1668 bool sf, of;
1669
1670 sf = ACCESS_FLAG(F_SF) != 0;
1671 of = ACCESS_FLAG(F_OF) != 0;
1672
1673 common_jmp_near(emu, sf == of);
1674}
1675/****************************************************************************
1676REMARKS:
1677Handles opcode 0x7e
1678****************************************************************************/
1679static void
1680x86emuOp_jump_near_LE(struct X86EMU *emu)
1681{
1682 bool sf, of;
1683
1684 sf = ACCESS_FLAG(F_SF) != 0;
1685 of = ACCESS_FLAG(F_OF) != 0;
1686
1687 common_jmp_near(emu, sf != of || ACCESS_FLAG(F_ZF));
1688}
1689/****************************************************************************
1690REMARKS:
1691Handles opcode 0x7f
1692****************************************************************************/
1693static void
1694x86emuOp_jump_near_NLE(struct X86EMU *emu)
1695{
1696 bool sf, of;
1697
1698 sf = ACCESS_FLAG(F_SF) != 0;
1699 of = ACCESS_FLAG(F_OF) != 0;
1700
1701 common_jmp_near(emu, sf == of && !ACCESS_FLAG(F_ZF));
1702}
1703
1704static
1705uint8_t(*const opc80_byte_operation[]) (struct X86EMU *, uint8_t d, uint8_t s) =
1706{
1707 add_byte, /* 00 */
1708 or_byte, /* 01 */
1709 adc_byte, /* 02 */
1710 sbb_byte, /* 03 */
1711 and_byte, /* 04 */
1712 sub_byte, /* 05 */
1713 xor_byte, /* 06 */
1714 cmp_byte, /* 07 */
1715};
1716/****************************************************************************
1717REMARKS:
1718Handles opcode 0x80
1719****************************************************************************/
1720static void
1721x86emuOp_opc80_byte_RM_IMM(struct X86EMU *emu)
1722{
1723 uint8_t imm, destval;
1724
1725 /*
1726 * Weirdo special case instruction format. Part of the opcode
1727 * held below in "RH". Doubly nested case would result, except
1728 * that the decoded instruction
1729 */
1730 fetch_decode_modrm(emu);
1731 destval = decode_and_fetch_byte(emu);
1732 imm = fetch_byte_imm(emu);
1733 destval = (*opc80_byte_operation[emu->cur_rh]) (emu, destval, imm);
1734 if (emu->cur_rh != 7)
1735 write_back_byte(emu, destval);
1736}
1737
1738static
1739uint16_t(* const opc81_word_operation[]) (struct X86EMU *, uint16_t d, uint16_t s) =
1740{
1741 add_word, /* 00 */
1742 or_word, /* 01 */
1743 adc_word, /* 02 */
1744 sbb_word, /* 03 */
1745 and_word, /* 04 */
1746 sub_word, /* 05 */
1747 xor_word, /* 06 */
1748 cmp_word, /* 07 */
1749};
1750
1751static
1752uint32_t(* const opc81_long_operation[]) (struct X86EMU *, uint32_t d, uint32_t s) =
1753{
1754 add_long, /* 00 */
1755 or_long, /* 01 */
1756 adc_long, /* 02 */
1757 sbb_long, /* 03 */
1758 and_long, /* 04 */
1759 sub_long, /* 05 */
1760 xor_long, /* 06 */
1761 cmp_long, /* 07 */
1762};
1763/****************************************************************************
1764REMARKS:
1765Handles opcode 0x81
1766****************************************************************************/
1767static void
1768x86emuOp32_opc81_word_RM_IMM(struct X86EMU *emu)
1769{
1770 uint32_t destval, imm;
1771
1772 /*
1773 * Weirdo special case instruction format. Part of the opcode
1774 * held below in "RH". Doubly nested case would result, except
1775 * that the decoded instruction
1776 */
1777 fetch_decode_modrm(emu);
1778 destval = decode_and_fetch_long(emu);
1779 imm = fetch_long_imm(emu);
1780 destval = (*opc81_long_operation[emu->cur_rh]) (emu, destval, imm);
1781 if (emu->cur_rh != 7)
1782 write_back_long(emu, destval);
1783}
1784
1785static void
1786x86emuOp16_opc81_word_RM_IMM(struct X86EMU *emu)
1787{
1788 uint16_t destval, imm;
1789
1790 /*
1791 * Weirdo special case instruction format. Part of the opcode
1792 * held below in "RH". Doubly nested case would result, except
1793 * that the decoded instruction
1794 */
1795 fetch_decode_modrm(emu);
1796 destval = decode_and_fetch_word(emu);
1797 imm = fetch_word_imm(emu);
1798 destval = (*opc81_word_operation[emu->cur_rh]) (emu, destval, imm);
1799 if (emu->cur_rh != 7)
1800 write_back_word(emu, destval);
1801}
1802
1803static void
1804x86emuOp_opc81_word_RM_IMM(struct X86EMU *emu)
1805{
1806 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1807 x86emuOp32_opc81_word_RM_IMM(emu);
1808 else
1809 x86emuOp16_opc81_word_RM_IMM(emu);
1810}
1811
1812static
1813uint8_t(* const opc82_byte_operation[]) (struct X86EMU *, uint8_t s, uint8_t d) =
1814{
1815 add_byte, /* 00 */
1816 or_byte, /* 01 *//* YYY UNUSED ???? */
1817 adc_byte, /* 02 */
1818 sbb_byte, /* 03 */
1819 and_byte, /* 04 *//* YYY UNUSED ???? */
1820 sub_byte, /* 05 */
1821 xor_byte, /* 06 *//* YYY UNUSED ???? */
1822 cmp_byte, /* 07 */
1823};
1824/****************************************************************************
1825REMARKS:
1826Handles opcode 0x82
1827****************************************************************************/
1828static void
1829x86emuOp_opc82_byte_RM_IMM(struct X86EMU *emu)
1830{
1831 uint8_t imm, destval;
1832
1833 /*
1834 * Weirdo special case instruction format. Part of the opcode
1835 * held below in "RH". Doubly nested case would result, except
1836 * that the decoded instruction Similar to opcode 81, except that
1837 * the immediate byte is sign extended to a word length.
1838 */
1839 fetch_decode_modrm(emu);
1840 destval = decode_and_fetch_byte(emu);
1841 imm = fetch_byte_imm(emu);
1842 destval = (*opc82_byte_operation[emu->cur_rh]) (emu, destval, imm);
1843 if (emu->cur_rh != 7)
1844 write_back_byte(emu, destval);
1845}
1846
1847static
1848uint16_t(* const opc83_word_operation[]) (struct X86EMU *, uint16_t s, uint16_t d) =
1849{
1850 add_word, /* 00 */
1851 or_word, /* 01 *//* YYY UNUSED ???? */
1852 adc_word, /* 02 */
1853 sbb_word, /* 03 */
1854 and_word, /* 04 *//* YYY UNUSED ???? */
1855 sub_word, /* 05 */
1856 xor_word, /* 06 *//* YYY UNUSED ???? */
1857 cmp_word, /* 07 */
1858};
1859
1860static
1861uint32_t(* const opc83_long_operation[]) (struct X86EMU *, uint32_t s, uint32_t d) =
1862{
1863 add_long, /* 00 */
1864 or_long, /* 01 *//* YYY UNUSED ???? */
1865 adc_long, /* 02 */
1866 sbb_long, /* 03 */
1867 and_long, /* 04 *//* YYY UNUSED ???? */
1868 sub_long, /* 05 */
1869 xor_long, /* 06 *//* YYY UNUSED ???? */
1870 cmp_long, /* 07 */
1871};
1872/****************************************************************************
1873REMARKS:
1874Handles opcode 0x83
1875****************************************************************************/
1876static void
1877x86emuOp32_opc83_word_RM_IMM(struct X86EMU *emu)
1878{
1879 uint32_t destval, imm;
1880
1881 fetch_decode_modrm(emu);
1882 destval = decode_and_fetch_long(emu);
1883 imm = (int8_t) fetch_byte_imm(emu);
1884 destval = (*opc83_long_operation[emu->cur_rh]) (emu, destval, imm);
1885 if (emu->cur_rh != 7)
1886 write_back_long(emu, destval);
1887}
1888
1889static void
1890x86emuOp16_opc83_word_RM_IMM(struct X86EMU *emu)
1891{
1892 uint16_t destval, imm;
1893
1894 fetch_decode_modrm(emu);
1895 destval = decode_and_fetch_word(emu);
1896 imm = (int8_t) fetch_byte_imm(emu);
1897 destval = (*opc83_word_operation[emu->cur_rh]) (emu, destval, imm);
1898 if (emu->cur_rh != 7)
1899 write_back_word(emu, destval);
1900}
1901
1902static void
1903x86emuOp_opc83_word_RM_IMM(struct X86EMU *emu)
1904{
1905 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1906 x86emuOp32_opc83_word_RM_IMM(emu);
1907 else
1908 x86emuOp16_opc83_word_RM_IMM(emu);
1909}
1910/****************************************************************************
1911REMARKS:
1912Handles opcode 0x86
1913****************************************************************************/
1914static void
1915x86emuOp_xchg_byte_RM_R(struct X86EMU *emu)
1916{
1917 uint8_t *srcreg, destval, tmp;
1918
1919 fetch_decode_modrm(emu);
1920 destval = decode_and_fetch_byte(emu);
1921 srcreg = decode_rh_byte_register(emu);
1922 tmp = destval;
1923 destval = *srcreg;
1924 *srcreg = tmp;
1925 write_back_byte(emu, destval);
1926}
1927/****************************************************************************
1928REMARKS:
1929Handles opcode 0x87
1930****************************************************************************/
1931static void
1932x86emuOp32_xchg_word_RM_R(struct X86EMU *emu)
1933{
1934 uint32_t *srcreg, destval, tmp;
1935
1936 fetch_decode_modrm(emu);
1937 destval = decode_and_fetch_long(emu);
1938 srcreg = decode_rh_long_register(emu);
1939 tmp = destval;
1940 destval = *srcreg;
1941 *srcreg = tmp;
1942 write_back_long(emu, destval);
1943}
1944
1945static void
1946x86emuOp16_xchg_word_RM_R(struct X86EMU *emu)
1947{
1948 uint16_t *srcreg, destval, tmp;
1949
1950 fetch_decode_modrm(emu);
1951 destval = decode_and_fetch_word(emu);
1952 srcreg = decode_rh_word_register(emu);
1953 tmp = destval;
1954 destval = *srcreg;
1955 *srcreg = tmp;
1956 write_back_word(emu, destval);
1957}
1958
1959static void
1960x86emuOp_xchg_word_RM_R(struct X86EMU *emu)
1961{
1962 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1963 x86emuOp32_xchg_word_RM_R(emu);
1964 else
1965 x86emuOp16_xchg_word_RM_R(emu);
1966}
1967/****************************************************************************
1968REMARKS:
1969Handles opcode 0x88
1970****************************************************************************/
1971static void
1972x86emuOp_mov_byte_RM_R(struct X86EMU *emu)
1973{
1974 uint8_t *destreg, *srcreg;
1975 uint32_t destoffset;
1976
1977 fetch_decode_modrm(emu);
1978 srcreg = decode_rh_byte_register(emu);
1979 if (emu->cur_mod != 3) {
1980 destoffset = decode_rl_address(emu);
1981 store_data_byte(emu, destoffset, *srcreg);
1982 } else {
1983 destreg = decode_rl_byte_register(emu);
1984 *destreg = *srcreg;
1985 }
1986}
1987/****************************************************************************
1988REMARKS:
1989Handles opcode 0x89
1990****************************************************************************/
1991static void
1992x86emuOp32_mov_word_RM_R(struct X86EMU *emu)
1993{
1994 uint32_t destoffset;
1995 uint32_t *destreg, srcval;
1996
1997 fetch_decode_modrm(emu);
1998 srcval = *decode_rh_long_register(emu);
1999 if (emu->cur_mod != 3) {
2000 destoffset = decode_rl_address(emu);
2001 store_data_long(emu, destoffset, srcval);
2002 } else {
2003 destreg = decode_rl_long_register(emu);
2004 *destreg = srcval;
2005 }
2006}
2007
2008static void
2009x86emuOp16_mov_word_RM_R(struct X86EMU *emu)
2010{
2011 uint32_t destoffset;
2012 uint16_t *destreg, srcval;
2013
2014 fetch_decode_modrm(emu);
2015 srcval = *decode_rh_word_register(emu);
2016 if (emu->cur_mod != 3) {
2017 destoffset = decode_rl_address(emu);
2018 store_data_word(emu, destoffset, srcval);
2019 } else {
2020 destreg = decode_rl_word_register(emu);
2021 *destreg = srcval;
2022 }
2023}
2024
2025static void
2026x86emuOp_mov_word_RM_R(struct X86EMU *emu)
2027{
2028 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2029 x86emuOp32_mov_word_RM_R(emu);
2030 else
2031 x86emuOp16_mov_word_RM_R(emu);
2032}
2033/****************************************************************************
2034REMARKS:
2035Handles opcode 0x8a
2036****************************************************************************/
2037static void
2038x86emuOp_mov_byte_R_RM(struct X86EMU *emu)
2039{
2040 uint8_t *destreg;
2041
2042 fetch_decode_modrm(emu);
2043 destreg = decode_rh_byte_register(emu);
2044 *destreg = decode_and_fetch_byte(emu);
2045}
2046/****************************************************************************
2047REMARKS:
2048Handles opcode 0x8b
2049****************************************************************************/
2050static void
2051x86emuOp_mov_word_R_RM(struct X86EMU *emu)
2052{
2053 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2054 uint32_t *destreg;
2055
2056 fetch_decode_modrm(emu);
2057 destreg = decode_rh_long_register(emu);
2058 *destreg = decode_and_fetch_long(emu);
2059 } else {
2060 uint16_t *destreg;
2061
2062 fetch_decode_modrm(emu);
2063 destreg = decode_rh_word_register(emu);
2064 *destreg = decode_and_fetch_word(emu);
2065 }
2066}
2067/****************************************************************************
2068REMARKS:
2069Handles opcode 0x8c
2070****************************************************************************/
2071static void
2072x86emuOp_mov_word_RM_SR(struct X86EMU *emu)
2073{
2074 uint16_t *destreg, srcval;
2075 uint32_t destoffset;
2076
2077 fetch_decode_modrm(emu);
2078 srcval = *decode_rh_seg_register(emu);
2079 if (emu->cur_mod != 3) {
2080 destoffset = decode_rl_address(emu);
2081 store_data_word(emu, destoffset, srcval);
2082 } else {
2083 destreg = decode_rl_word_register(emu);
2084 *destreg = srcval;
2085 }
2086}
2087/****************************************************************************
2088REMARKS:
2089Handles opcode 0x8d
2090****************************************************************************/
2091static void
2092x86emuOp_lea_word_R_M(struct X86EMU *emu)
2093{
2094 uint32_t destoffset;
2095
2096 fetch_decode_modrm(emu);
2097 if (emu->cur_mod == 3)
2098 X86EMU_halt_sys(emu);
2099
2100 destoffset = decode_rl_address(emu);
2101 if (emu->x86.mode & SYSMODE_PREFIX_ADDR) {
2102 uint32_t *srcreg;
2103
2104 srcreg = decode_rh_long_register(emu);
2105 *srcreg = (uint32_t) destoffset;
2106 } else {
2107 uint16_t *srcreg;
2108
2109 srcreg = decode_rh_word_register(emu);
2110 *srcreg = (uint16_t) destoffset;
2111 }
2112}
2113/****************************************************************************
2114REMARKS:
2115Handles opcode 0x8e
2116****************************************************************************/
2117static void
2118x86emuOp_mov_word_SR_RM(struct X86EMU *emu)
2119{
2120 uint16_t *destreg;
2121
2122 fetch_decode_modrm(emu);
2123 destreg = decode_rh_seg_register(emu);
2124 *destreg = decode_and_fetch_word(emu);
2125 /*
2126 * Clean up, and reset all the R_xSP pointers to the correct
2127 * locations. This is about 3x too much overhead (doing all the
2128 * segreg ptrs when only one is needed, but this instruction
2129 * *cannot* be that common, and this isn't too much work anyway.
2130 */
2131}
2132/****************************************************************************
2133REMARKS:
2134Handles opcode 0x8f
2135****************************************************************************/
2136static void
2137x86emuOp32_pop_RM(struct X86EMU *emu)
2138{
2139 uint32_t destoffset;
2140 uint32_t destval, *destreg;
2141
2142 fetch_decode_modrm(emu);
2143 if (emu->cur_mod != 3) {
2144 destoffset = decode_rl_address(emu);
2145 destval = pop_long(emu);
2146 store_data_long(emu, destoffset, destval);
2147 } else {
2148 destreg = decode_rl_long_register(emu);
2149 *destreg = pop_long(emu);
2150 }
2151}
2152
2153static void
2154x86emuOp16_pop_RM(struct X86EMU *emu)
2155{
2156 uint32_t destoffset;
2157 uint16_t destval, *destreg;
2158
2159 fetch_decode_modrm(emu);
2160 if (emu->cur_mod != 3) {
2161 destoffset = decode_rl_address(emu);
2162 destval = pop_word(emu);
2163 store_data_word(emu, destoffset, destval);
2164 } else {
2165 destreg = decode_rl_word_register(emu);
2166 *destreg = pop_word(emu);
2167 }
2168}
2169
2170static void
2171x86emuOp_pop_RM(struct X86EMU *emu)
2172{
2173 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2174 x86emuOp32_pop_RM(emu);
2175 else
2176 x86emuOp16_pop_RM(emu);
2177}
2178/****************************************************************************
2179REMARKS:
2180Handles opcode 0x91
2181****************************************************************************/
2182static void
2183x86emuOp_xchg_word_AX_CX(struct X86EMU *emu)
2184{
2185 uint32_t tmp;
2186
2187 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2188 tmp = emu->x86.R_EAX;
2189 emu->x86.R_EAX = emu->x86.R_ECX;
2190 emu->x86.R_ECX = tmp;
2191 } else {
2192 tmp = emu->x86.R_AX;
2193 emu->x86.R_AX = emu->x86.R_CX;
2194 emu->x86.R_CX = (uint16_t) tmp;
2195 }
2196}
2197/****************************************************************************
2198REMARKS:
2199Handles opcode 0x92
2200****************************************************************************/
2201static void
2202x86emuOp_xchg_word_AX_DX(struct X86EMU *emu)
2203{
2204 uint32_t tmp;
2205
2206 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2207 tmp = emu->x86.R_EAX;
2208 emu->x86.R_EAX = emu->x86.R_EDX;
2209 emu->x86.R_EDX = tmp;
2210 } else {
2211 tmp = emu->x86.R_AX;
2212 emu->x86.R_AX = emu->x86.R_DX;
2213 emu->x86.R_DX = (uint16_t) tmp;
2214 }
2215}
2216/****************************************************************************
2217REMARKS:
2218Handles opcode 0x93
2219****************************************************************************/
2220static void
2221x86emuOp_xchg_word_AX_BX(struct X86EMU *emu)
2222{
2223 uint32_t tmp;
2224
2225 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2226 tmp = emu->x86.R_EAX;
2227 emu->x86.R_EAX = emu->x86.R_EBX;
2228 emu->x86.R_EBX = tmp;
2229 } else {
2230 tmp = emu->x86.R_AX;
2231 emu->x86.R_AX = emu->x86.R_BX;
2232 emu->x86.R_BX = (uint16_t) tmp;
2233 }
2234}
2235/****************************************************************************
2236REMARKS:
2237Handles opcode 0x94
2238****************************************************************************/
2239static void
2240x86emuOp_xchg_word_AX_SP(struct X86EMU *emu)
2241{
2242 uint32_t tmp;
2243
2244 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2245 tmp = emu->x86.R_EAX;
2246 emu->x86.R_EAX = emu->x86.R_ESP;
2247 emu->x86.R_ESP = tmp;
2248 } else {
2249 tmp = emu->x86.R_AX;
2250 emu->x86.R_AX = emu->x86.R_SP;
2251 emu->x86.R_SP = (uint16_t) tmp;
2252 }
2253}
2254/****************************************************************************
2255REMARKS:
2256Handles opcode 0x95
2257****************************************************************************/
2258static void
2259x86emuOp_xchg_word_AX_BP(struct X86EMU *emu)
2260{
2261 uint32_t tmp;
2262
2263 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2264 tmp = emu->x86.R_EAX;
2265 emu->x86.R_EAX = emu->x86.R_EBP;
2266 emu->x86.R_EBP = tmp;
2267 } else {
2268 tmp = emu->x86.R_AX;
2269 emu->x86.R_AX = emu->x86.R_BP;
2270 emu->x86.R_BP = (uint16_t) tmp;
2271 }
2272}
2273/****************************************************************************
2274REMARKS:
2275Handles opcode 0x96
2276****************************************************************************/
2277static void
2278x86emuOp_xchg_word_AX_SI(struct X86EMU *emu)
2279{
2280 uint32_t tmp;
2281
2282 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2283 tmp = emu->x86.R_EAX;
2284 emu->x86.R_EAX = emu->x86.R_ESI;
2285 emu->x86.R_ESI = tmp;
2286 } else {
2287 tmp = emu->x86.R_AX;
2288 emu->x86.R_AX = emu->x86.R_SI;
2289 emu->x86.R_SI = (uint16_t) tmp;
2290 }
2291}
2292/****************************************************************************
2293REMARKS:
2294Handles opcode 0x97
2295****************************************************************************/
2296static void
2297x86emuOp_xchg_word_AX_DI(struct X86EMU *emu)
2298{
2299 uint32_t tmp;
2300
2301 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2302 tmp = emu->x86.R_EAX;
2303 emu->x86.R_EAX = emu->x86.R_EDI;
2304 emu->x86.R_EDI = tmp;
2305 } else {
2306 tmp = emu->x86.R_AX;
2307 emu->x86.R_AX = emu->x86.R_DI;
2308 emu->x86.R_DI = (uint16_t) tmp;
2309 }
2310}
2311/****************************************************************************
2312REMARKS:
2313Handles opcode 0x98
2314****************************************************************************/
2315static void
2316x86emuOp_cbw(struct X86EMU *emu)
2317{
2318 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2319 if (emu->x86.R_AX & 0x8000) {
2320 emu->x86.R_EAX |= 0xffff0000;
2321 } else {
2322 emu->x86.R_EAX &= 0x0000ffff;
2323 }
2324 } else {
2325 if (emu->x86.R_AL & 0x80) {
2326 emu->x86.R_AH = 0xff;
2327 } else {
2328 emu->x86.R_AH = 0x0;
2329 }
2330 }
2331}
2332/****************************************************************************
2333REMARKS:
2334Handles opcode 0x99
2335****************************************************************************/
2336static void
2337x86emuOp_cwd(struct X86EMU *emu)
2338{
2339 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2340 if (emu->x86.R_EAX & 0x80000000) {
2341 emu->x86.R_EDX = 0xffffffff;
2342 } else {
2343 emu->x86.R_EDX = 0x0;
2344 }
2345 } else {
2346 if (emu->x86.R_AX & 0x8000) {
2347 emu->x86.R_DX = 0xffff;
2348 } else {
2349 emu->x86.R_DX = 0x0;
2350 }
2351 }
2352}
2353/****************************************************************************
2354REMARKS:
2355Handles opcode 0x9a
2356****************************************************************************/
2357static void
2358x86emuOp_call_far_IMM(struct X86EMU *emu)
2359{
2360 uint16_t farseg, faroff;
2361
2362 faroff = fetch_word_imm(emu);
2363 farseg = fetch_word_imm(emu);
2364 /* XXX
2365 *
2366 * Hooked interrupt vectors calling into our "BIOS" will cause problems
2367 * unless all intersegment stuff is checked for BIOS access. Check
2368 * needed here. For moment, let it alone. */
2369 push_word(emu, emu->x86.R_CS);
2370 emu->x86.R_CS = farseg;
2371 push_word(emu, emu->x86.R_IP);
2372 emu->x86.R_IP = faroff;
2373}
2374/****************************************************************************
2375REMARKS:
2376Handles opcode 0x9c
2377****************************************************************************/
2378static void
2379x86emuOp_pushf_word(struct X86EMU *emu)
2380{
2381 uint32_t flags;
2382
2383 /* clear out *all* bits not representing flags, and turn on real bits */
2384 flags = (emu->x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2385 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2386 push_long(emu, flags);
2387 } else {
2388 push_word(emu, (uint16_t) flags);
2389 }
2390}
2391/****************************************************************************
2392REMARKS:
2393Handles opcode 0x9d
2394****************************************************************************/
2395static void
2396x86emuOp_popf_word(struct X86EMU *emu)
2397{
2398 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2399 emu->x86.R_EFLG = pop_long(emu);
2400 } else {
2401 emu->x86.R_FLG = pop_word(emu);
2402 }
2403}
2404/****************************************************************************
2405REMARKS:
2406Handles opcode 0x9e
2407****************************************************************************/
2408static void
2409x86emuOp_sahf(struct X86EMU *emu)
2410{
2411 /* clear the lower bits of the flag register */
2412 emu->x86.R_FLG &= 0xffffff00;
2413 /* or in the AH register into the flags register */
2414 emu->x86.R_FLG |= emu->x86.R_AH;
2415}
2416/****************************************************************************
2417REMARKS:
2418Handles opcode 0x9f
2419****************************************************************************/
2420static void
2421x86emuOp_lahf(struct X86EMU *emu)
2422{
2423 emu->x86.R_AH = (uint8_t) (emu->x86.R_FLG & 0xff);
2424 /* undocumented TC++ behavior??? Nope. It's documented, but you have
2425 * too look real hard to notice it. */
2426 emu->x86.R_AH |= 0x2;
2427}
2428/****************************************************************************
2429REMARKS:
2430Handles opcode 0xa0
2431****************************************************************************/
2432static void
2433x86emuOp_mov_AL_M_IMM(struct X86EMU *emu)
2434{
2435 uint16_t offset;
2436
2437 offset = fetch_word_imm(emu);
2438 emu->x86.R_AL = fetch_data_byte(emu, offset);
2439}
2440/****************************************************************************
2441REMARKS:
2442Handles opcode 0xa1
2443****************************************************************************/
2444static void
2445x86emuOp_mov_AX_M_IMM(struct X86EMU *emu)
2446{
2447 uint16_t offset;
2448
2449 offset = fetch_word_imm(emu);
2450 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2451 emu->x86.R_EAX = fetch_data_long(emu, offset);
2452 } else {
2453 emu->x86.R_AX = fetch_data_word(emu, offset);
2454 }
2455}
2456/****************************************************************************
2457REMARKS:
2458Handles opcode 0xa2
2459****************************************************************************/
2460static void
2461x86emuOp_mov_M_AL_IMM(struct X86EMU *emu)
2462{
2463 uint16_t offset;
2464
2465 offset = fetch_word_imm(emu);
2466 store_data_byte(emu, offset, emu->x86.R_AL);
2467}
2468/****************************************************************************
2469REMARKS:
2470Handles opcode 0xa3
2471****************************************************************************/
2472static void
2473x86emuOp_mov_M_AX_IMM(struct X86EMU *emu)
2474{
2475 uint16_t offset;
2476
2477 offset = fetch_word_imm(emu);
2478 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2479 store_data_long(emu, offset, emu->x86.R_EAX);
2480 } else {
2481 store_data_word(emu, offset, emu->x86.R_AX);
2482 }
2483}
2484/****************************************************************************
2485REMARKS:
2486Handles opcode 0xa4
2487****************************************************************************/
2488static void
2489x86emuOp_movs_byte(struct X86EMU *emu)
2490{
2491 uint8_t val;
2492 uint32_t count;
2493 int inc;
2494
2495 if (ACCESS_FLAG(F_DF)) /* down */
2496 inc = -1;
2497 else
2498 inc = 1;
2499 count = 1;
2500 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2501 /* dont care whether REPE or REPNE */
2502 /* move them until CX is ZERO. */
2503 count = emu->x86.R_CX;
2504 emu->x86.R_CX = 0;
2505 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2506 }
2507 while (count--) {
2508 val = fetch_data_byte(emu, emu->x86.R_SI);
2509 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2510 emu->x86.R_SI += inc;
2511 emu->x86.R_DI += inc;
2512 }
2513}
2514/****************************************************************************
2515REMARKS:
2516Handles opcode 0xa5
2517****************************************************************************/
2518static void
2519x86emuOp_movs_word(struct X86EMU *emu)
2520{
2521 uint32_t val;
2522 int inc;
2523 uint32_t count;
2524
2525 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2526 inc = 4;
2527 else
2528 inc = 2;
2529
2530 if (ACCESS_FLAG(F_DF)) /* down */
2531 inc = -inc;
2532
2533 count = 1;
2534 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2535 /* dont care whether REPE or REPNE */
2536 /* move them until CX is ZERO. */
2537 count = emu->x86.R_CX;
2538 emu->x86.R_CX = 0;
2539 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2540 }
2541 while (count--) {
2542 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2543 val = fetch_data_long(emu, emu->x86.R_SI);
2544 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2545 } else {
2546 val = fetch_data_word(emu, emu->x86.R_SI);
2547 store_word(emu, emu->x86.R_ES, emu->x86.R_DI, (uint16_t) val);
2548 }
2549 emu->x86.R_SI += inc;
2550 emu->x86.R_DI += inc;
2551 }
2552}
2553/****************************************************************************
2554REMARKS:
2555Handles opcode 0xa6
2556****************************************************************************/
2557static void
2558x86emuOp_cmps_byte(struct X86EMU *emu)
2559{
2560 int8_t val1, val2;
2561 int inc;
2562
2563 if (ACCESS_FLAG(F_DF)) /* down */
2564 inc = -1;
2565 else
2566 inc = 1;
2567
2568 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2569 /* REPE */
2570 /* move them until CX is ZERO. */
2571 while (emu->x86.R_CX != 0) {
2572 val1 = fetch_data_byte(emu, emu->x86.R_SI);
2573 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2574 cmp_byte(emu, val1, val2);
2575 emu->x86.R_CX -= 1;
2576 emu->x86.R_SI += inc;
2577 emu->x86.R_DI += inc;
2578 if (ACCESS_FLAG(F_ZF) == 0)
2579 break;
2580 }
2581 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2582 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2583 /* REPNE */
2584 /* move them until CX is ZERO. */
2585 while (emu->x86.R_CX != 0) {
2586 val1 = fetch_data_byte(emu, emu->x86.R_SI);
2587 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2588 cmp_byte(emu, val1, val2);
2589 emu->x86.R_CX -= 1;
2590 emu->x86.R_SI += inc;
2591 emu->x86.R_DI += inc;
2592 if (ACCESS_FLAG(F_ZF))
2593 break; /* zero flag set means equal */
2594 }
2595 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2596 } else {
2597 val1 = fetch_data_byte(emu, emu->x86.R_SI);
2598 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2599 cmp_byte(emu, val1, val2);
2600 emu->x86.R_SI += inc;
2601 emu->x86.R_DI += inc;
2602 }
2603}
2604/****************************************************************************
2605REMARKS:
2606Handles opcode 0xa7
2607****************************************************************************/
2608static void
2609x86emuOp_cmps_word(struct X86EMU *emu)
2610{
2611 uint32_t val1, val2;
2612 int inc;
2613
2614 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2615 if (ACCESS_FLAG(F_DF)) /* down */
2616 inc = -4;
2617 else
2618 inc = 4;
2619 } else {
2620 if (ACCESS_FLAG(F_DF)) /* down */
2621 inc = -2;
2622 else
2623 inc = 2;
2624 }
2625 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2626 /* REPE */
2627 /* move them until CX is ZERO. */
2628 while (emu->x86.R_CX != 0) {
2629 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2630 val1 = fetch_data_long(emu, emu->x86.R_SI);
2631 val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2632 cmp_long(emu, val1, val2);
2633 } else {
2634 val1 = fetch_data_word(emu, emu->x86.R_SI);
2635 val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2636 cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2637 }
2638 emu->x86.R_CX -= 1;
2639 emu->x86.R_SI += inc;
2640 emu->x86.R_DI += inc;
2641 if (ACCESS_FLAG(F_ZF) == 0)
2642 break;
2643 }
2644 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2645 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2646 /* REPNE */
2647 /* move them until CX is ZERO. */
2648 while (emu->x86.R_CX != 0) {
2649 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2650 val1 = fetch_data_long(emu, emu->x86.R_SI);
2651 val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2652 cmp_long(emu, val1, val2);
2653 } else {
2654 val1 = fetch_data_word(emu, emu->x86.R_SI);
2655 val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2656 cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2657 }
2658 emu->x86.R_CX -= 1;
2659 emu->x86.R_SI += inc;
2660 emu->x86.R_DI += inc;
2661 if (ACCESS_FLAG(F_ZF))
2662 break; /* zero flag set means equal */
2663 }
2664 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2665 } else {
2666 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2667 val1 = fetch_data_long(emu, emu->x86.R_SI);
2668 val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2669 cmp_long(emu, val1, val2);
2670 } else {
2671 val1 = fetch_data_word(emu, emu->x86.R_SI);
2672 val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2673 cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2674 }
2675 emu->x86.R_SI += inc;
2676 emu->x86.R_DI += inc;
2677 }
2678}
2679/****************************************************************************
2680REMARKS:
2681Handles opcode 0xa9
2682****************************************************************************/
2683static void
2684x86emuOp_test_AX_IMM(struct X86EMU *emu)
2685{
2686 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2687 test_long(emu, emu->x86.R_EAX, fetch_long_imm(emu));
2688 } else {
2689 test_word(emu, emu->x86.R_AX, fetch_word_imm(emu));
2690 }
2691}
2692/****************************************************************************
2693REMARKS:
2694Handles opcode 0xaa
2695****************************************************************************/
2696static void
2697x86emuOp_stos_byte(struct X86EMU *emu)
2698{
2699 int inc;
2700
2701 if (ACCESS_FLAG(F_DF)) /* down */
2702 inc = -1;
2703 else
2704 inc = 1;
2705 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2706 /* dont care whether REPE or REPNE */
2707 /* move them until CX is ZERO. */
2708 while (emu->x86.R_CX != 0) {
2709 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL);
2710 emu->x86.R_CX -= 1;
2711 emu->x86.R_DI += inc;
2712 }
2713 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2714 } else {
2715 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL);
2716 emu->x86.R_DI += inc;
2717 }
2718}
2719/****************************************************************************
2720REMARKS:
2721Handles opcode 0xab
2722****************************************************************************/
2723static void
2724x86emuOp_stos_word(struct X86EMU *emu)
2725{
2726 int inc;
2727 uint32_t count;
2728
2729 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2730 inc = 4;
2731 else
2732 inc = 2;
2733
2734 if (ACCESS_FLAG(F_DF)) /* down */
2735 inc = -inc;
2736
2737 count = 1;
2738 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2739 /* dont care whether REPE or REPNE */
2740 /* move them until CX is ZERO. */
2741 count = emu->x86.R_CX;
2742 emu->x86.R_CX = 0;
2743 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2744 }
2745 while (count--) {
2746 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2747 store_long(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_EAX);
2748 } else {
2749 store_word(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AX);
2750 }
2751 emu->x86.R_DI += inc;
2752 }
2753}
2754/****************************************************************************
2755REMARKS:
2756Handles opcode 0xac
2757****************************************************************************/
2758static void
2759x86emuOp_lods_byte(struct X86EMU *emu)
2760{
2761 int inc;
2762
2763 if (ACCESS_FLAG(F_DF)) /* down */
2764 inc = -1;
2765 else
2766 inc = 1;
2767 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2768 /* dont care whether REPE or REPNE */
2769 /* move them until CX is ZERO. */
2770 while (emu->x86.R_CX != 0) {
2771 emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2772 emu->x86.R_CX -= 1;
2773 emu->x86.R_SI += inc;
2774 }
2775 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2776 } else {
2777 emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2778 emu->x86.R_SI += inc;
2779 }
2780}
2781/****************************************************************************
2782REMARKS:
2783Handles opcode 0xad
2784****************************************************************************/
2785static void
2786x86emuOp_lods_word(struct X86EMU *emu)
2787{
2788 int inc;
2789 uint32_t count;
2790
2791 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2792 inc = 4;
2793 else
2794 inc = 2;
2795
2796 if (ACCESS_FLAG(F_DF)) /* down */
2797 inc = -inc;
2798
2799 count = 1;
2800 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2801 /* dont care whether REPE or REPNE */
2802 /* move them until CX is ZERO. */
2803 count = emu->x86.R_CX;
2804 emu->x86.R_CX = 0;
2805 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2806 }
2807 while (count--) {
2808 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2809 emu->x86.R_EAX = fetch_data_long(emu, emu->x86.R_SI);
2810 } else {
2811 emu->x86.R_AX = fetch_data_word(emu, emu->x86.R_SI);
2812 }
2813 emu->x86.R_SI += inc;
2814 }
2815}
2816/****************************************************************************
2817REMARKS:
2818Handles opcode 0xae
2819****************************************************************************/
2820static void
2821x86emuOp_scas_byte(struct X86EMU *emu)
2822{
2823 int8_t val2;
2824 int inc;
2825
2826 if (ACCESS_FLAG(F_DF)) /* down */
2827 inc = -1;
2828 else
2829 inc = 1;
2830 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2831 /* REPE */
2832 /* move them until CX is ZERO. */
2833 while (emu->x86.R_CX != 0) {
2834 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2835 cmp_byte(emu, emu->x86.R_AL, val2);
2836 emu->x86.R_CX -= 1;
2837 emu->x86.R_DI += inc;
2838 if (ACCESS_FLAG(F_ZF) == 0)
2839 break;
2840 }
2841 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2842 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2843 /* REPNE */
2844 /* move them until CX is ZERO. */
2845 while (emu->x86.R_CX != 0) {
2846 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2847 cmp_byte(emu, emu->x86.R_AL, val2);
2848 emu->x86.R_CX -= 1;
2849 emu->x86.R_DI += inc;
2850 if (ACCESS_FLAG(F_ZF))
2851 break; /* zero flag set means equal */
2852 }
2853 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2854 } else {
2855 val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2856 cmp_byte(emu, emu->x86.R_AL, val2);
2857 emu->x86.R_DI += inc;
2858 }
2859}
2860/****************************************************************************
2861REMARKS:
2862Handles opcode 0xaf
2863****************************************************************************/
2864static void
2865x86emuOp_scas_word(struct X86EMU *emu)
2866{
2867 int inc;
2868 uint32_t val;
2869
2870 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2871 inc = 4;
2872 else
2873 inc = 2;
2874
2875 if (ACCESS_FLAG(F_DF)) /* down */
2876 inc = -inc;
2877
2878 if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2879 /* REPE */
2880 /* move them until CX is ZERO. */
2881 while (emu->x86.R_CX != 0) {
2882 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2883 val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2884 cmp_long(emu, emu->x86.R_EAX, val);
2885 } else {
2886 val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2887 cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
2888 }
2889 emu->x86.R_CX -= 1;
2890 emu->x86.R_DI += inc;
2891 if (ACCESS_FLAG(F_ZF) == 0)
2892 break;
2893 }
2894 emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2895 } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2896 /* REPNE */
2897 /* move them until CX is ZERO. */
2898 while (emu->x86.R_CX != 0) {
2899 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2900 val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2901 cmp_long(emu, emu->x86.R_EAX, val);
2902 } else {
2903 val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2904 cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
2905 }
2906 emu->x86.R_CX -= 1;
2907 emu->x86.R_DI += inc;
2908 if (ACCESS_FLAG(F_ZF))
2909 break; /* zero flag set means equal */
2910 }
2911 emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2912 } else {
2913 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2914 val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2915 cmp_long(emu, emu->x86.R_EAX, val);
2916 } else {
2917 val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2918 cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
2919 }
2920 emu->x86.R_DI += inc;
2921 }
2922}
2923/****************************************************************************
2924REMARKS:
2925Handles opcode 0xb8
2926****************************************************************************/
2927static void
2928x86emuOp_mov_word_AX_IMM(struct X86EMU *emu)
2929{
2930 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2931 emu->x86.R_EAX = fetch_long_imm(emu);
2932 else
2933 emu->x86.R_AX = fetch_word_imm(emu);
2934}
2935/****************************************************************************
2936REMARKS:
2937Handles opcode 0xb9
2938****************************************************************************/
2939static void
2940x86emuOp_mov_word_CX_IMM(struct X86EMU *emu)
2941{
2942 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2943 emu->x86.R_ECX = fetch_long_imm(emu);
2944 else
2945 emu->x86.R_CX = fetch_word_imm(emu);
2946}
2947/****************************************************************************
2948REMARKS:
2949Handles opcode 0xba
2950****************************************************************************/
2951static void
2952x86emuOp_mov_word_DX_IMM(struct X86EMU *emu)
2953{
2954 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2955 emu->x86.R_EDX = fetch_long_imm(emu);
2956 else
2957 emu->x86.R_DX = fetch_word_imm(emu);
2958}
2959/****************************************************************************
2960REMARKS:
2961Handles opcode 0xbb
2962****************************************************************************/
2963static void
2964x86emuOp_mov_word_BX_IMM(struct X86EMU *emu)
2965{
2966 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2967 emu->x86.R_EBX = fetch_long_imm(emu);
2968 else
2969 emu->x86.R_BX = fetch_word_imm(emu);
2970}
2971/****************************************************************************
2972REMARKS:
2973Handles opcode 0xbc
2974****************************************************************************/
2975static void
2976x86emuOp_mov_word_SP_IMM(struct X86EMU *emu)
2977{
2978 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2979 emu->x86.R_ESP = fetch_long_imm(emu);
2980 else
2981 emu->x86.R_SP = fetch_word_imm(emu);
2982}
2983/****************************************************************************
2984REMARKS:
2985Handles opcode 0xbd
2986****************************************************************************/
2987static void
2988x86emuOp_mov_word_BP_IMM(struct X86EMU *emu)
2989{
2990 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2991 emu->x86.R_EBP = fetch_long_imm(emu);
2992 else
2993 emu->x86.R_BP = fetch_word_imm(emu);
2994}
2995/****************************************************************************
2996REMARKS:
2997Handles opcode 0xbe
2998****************************************************************************/
2999static void
3000x86emuOp_mov_word_SI_IMM(struct X86EMU *emu)
3001{
3002 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3003 emu->x86.R_ESI = fetch_long_imm(emu);
3004 else
3005 emu->x86.R_SI = fetch_word_imm(emu);
3006}
3007/****************************************************************************
3008REMARKS:
3009Handles opcode 0xbf
3010****************************************************************************/
3011static void
3012x86emuOp_mov_word_DI_IMM(struct X86EMU *emu)
3013{
3014 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3015 emu->x86.R_EDI = fetch_long_imm(emu);
3016 else
3017 emu->x86.R_DI = fetch_word_imm(emu);
3018}
3019/* used by opcodes c0, d0, and d2. */
3020static
3021uint8_t(* const opcD0_byte_operation[]) (struct X86EMU *, uint8_t d, uint8_t s) =
3022{
3023 rol_byte,
3024 ror_byte,
3025 rcl_byte,
3026 rcr_byte,
3027 shl_byte,
3028 shr_byte,
3029 shl_byte, /* sal_byte === shl_byte by definition */
3030 sar_byte,
3031};
3032/****************************************************************************
3033REMARKS:
3034Handles opcode 0xc0
3035****************************************************************************/
3036static void
3037x86emuOp_opcC0_byte_RM_MEM(struct X86EMU *emu)
3038{
3039 uint8_t destval, amt;
3040
3041 /*
3042 * Yet another weirdo special case instruction format. Part of
3043 * the opcode held below in "RH". Doubly nested case would
3044 * result, except that the decoded instruction
3045 */
3046 fetch_decode_modrm(emu);
3047 /* know operation, decode the mod byte to find the addressing mode. */
3048 destval = decode_and_fetch_byte_imm8(emu, &amt);
3049 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, amt);
3050 write_back_byte(emu, destval);
3051}
3052/* used by opcodes c1, d1, and d3. */
3053static
3054uint16_t(* const opcD1_word_operation[]) (struct X86EMU *, uint16_t s, uint8_t d) =
3055{
3056 rol_word,
3057 ror_word,
3058 rcl_word,
3059 rcr_word,
3060 shl_word,
3061 shr_word,
3062 shl_word, /* sal_byte === shl_byte by definition */
3063 sar_word,
3064};
3065/* used by opcodes c1, d1, and d3. */
3066static
3067uint32_t(* const opcD1_long_operation[]) (struct X86EMU *, uint32_t s, uint8_t d) =
3068{
3069 rol_long,
3070 ror_long,
3071 rcl_long,
3072 rcr_long,
3073 shl_long,
3074 shr_long,
3075 shl_long, /* sal_byte === shl_byte by definition */
3076 sar_long,
3077};
3078/****************************************************************************
3079REMARKS:
3080Handles opcode 0xc1
3081****************************************************************************/
3082static void
3083x86emuOp_opcC1_word_RM_MEM(struct X86EMU *emu)
3084{
3085 uint8_t amt;
3086
3087 /*
3088 * Yet another weirdo special case instruction format. Part of
3089 * the opcode held below in "RH". Doubly nested case would
3090 * result, except that the decoded instruction
3091 */
3092 fetch_decode_modrm(emu);
3093 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3094 uint32_t destval;
3095
3096 destval = decode_and_fetch_long_imm8(emu, &amt);
3097 destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, amt);
3098 write_back_long(emu, destval);
3099 } else {
3100 uint16_t destval;
3101
3102 destval = decode_and_fetch_word_imm8(emu, &amt);
3103 destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, amt);
3104 write_back_word(emu, destval);
3105 }
3106}
3107/****************************************************************************
3108REMARKS:
3109Handles opcode 0xc2
3110****************************************************************************/
3111static void
3112x86emuOp_ret_near_IMM(struct X86EMU *emu)
3113{
3114 uint16_t imm;
3115
3116 imm = fetch_word_imm(emu);
3117 emu->x86.R_IP = pop_word(emu);
3118 emu->x86.R_SP += imm;
3119}
3120/****************************************************************************
3121REMARKS:
3122Handles opcode 0xc6
3123****************************************************************************/
3124static void
3125x86emuOp_mov_byte_RM_IMM(struct X86EMU *emu)
3126{
3127 uint8_t *destreg;
3128 uint32_t destoffset;
3129 uint8_t imm;
3130
3131 fetch_decode_modrm(emu);
3132 if (emu->cur_rh != 0)
3133 X86EMU_halt_sys(emu);
3134 if (emu->cur_mod != 3) {
3135 destoffset = decode_rl_address(emu);
3136 imm = fetch_byte_imm(emu);
3137 store_data_byte(emu, destoffset, imm);
3138 } else {
3139 destreg = decode_rl_byte_register(emu);
3140 imm = fetch_byte_imm(emu);
3141 *destreg = imm;
3142 }
3143}
3144/****************************************************************************
3145REMARKS:
3146Handles opcode 0xc7
3147****************************************************************************/
3148static void
3149x86emuOp32_mov_word_RM_IMM(struct X86EMU *emu)
3150{
3151 uint32_t destoffset;
3152 uint32_t imm, *destreg;
3153
3154 fetch_decode_modrm(emu);
3155 if (emu->cur_rh != 0)
3156 X86EMU_halt_sys(emu);
3157
3158 if (emu->cur_mod != 3) {
3159 destoffset = decode_rl_address(emu);
3160 imm = fetch_long_imm(emu);
3161 store_data_long(emu, destoffset, imm);
3162 } else {
3163 destreg = decode_rl_long_register(emu);
3164 imm = fetch_long_imm(emu);
3165 *destreg = imm;
3166 }
3167}
3168
3169static void
3170x86emuOp16_mov_word_RM_IMM(struct X86EMU *emu)
3171{
3172 uint32_t destoffset;
3173 uint16_t imm, *destreg;
3174
3175 fetch_decode_modrm(emu);
3176 if (emu->cur_rh != 0)
3177 X86EMU_halt_sys(emu);
3178
3179 if (emu->cur_mod != 3) {
3180 destoffset = decode_rl_address(emu);
3181 imm = fetch_word_imm(emu);
3182 store_data_word(emu, destoffset, imm);
3183 } else {
3184 destreg = decode_rl_word_register(emu);
3185 imm = fetch_word_imm(emu);
3186 *destreg = imm;
3187 }
3188}
3189
3190static void
3191x86emuOp_mov_word_RM_IMM(struct X86EMU *emu)
3192{
3193 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3194 x86emuOp32_mov_word_RM_IMM(emu);
3195 else
3196 x86emuOp16_mov_word_RM_IMM(emu);
3197}
3198/****************************************************************************
3199REMARKS:
3200Handles opcode 0xc8
3201****************************************************************************/
3202static void
3203x86emuOp_enter(struct X86EMU *emu)
3204{
3205 uint16_t local, frame_pointer;
3206 uint8_t nesting;
3207 int i;
3208
3209 local = fetch_word_imm(emu);
3210 nesting = fetch_byte_imm(emu);
3211 push_word(emu, emu->x86.R_BP);
3212 frame_pointer = emu->x86.R_SP;
3213 if (nesting > 0) {
3214 for (i = 1; i < nesting; i++) {
3215 emu->x86.R_BP -= 2;
3216 push_word(emu, fetch_word(emu, emu->x86.R_SS, emu->x86.R_BP));
3217 }
3218 push_word(emu, frame_pointer);
3219 }
3220 emu->x86.R_BP = frame_pointer;
3221 emu->x86.R_SP = (uint16_t) (emu->x86.R_SP - local);
3222}
3223/****************************************************************************
3224REMARKS:
3225Handles opcode 0xc9
3226****************************************************************************/
3227static void
3228x86emuOp_leave(struct X86EMU *emu)
3229{
3230 emu->x86.R_SP = emu->x86.R_BP;
3231 emu->x86.R_BP = pop_word(emu);
3232}
3233/****************************************************************************
3234REMARKS:
3235Handles opcode 0xca
3236****************************************************************************/
3237static void
3238x86emuOp_ret_far_IMM(struct X86EMU *emu)
3239{
3240 uint16_t imm;
3241
3242 imm = fetch_word_imm(emu);
3243 emu->x86.R_IP = pop_word(emu);
3244 emu->x86.R_CS = pop_word(emu);
3245 emu->x86.R_SP += imm;
3246}
3247/****************************************************************************
3248REMARKS:
3249Handles opcode 0xcb
3250****************************************************************************/
3251static void
3252x86emuOp_ret_far(struct X86EMU *emu)
3253{
3254 emu->x86.R_IP = pop_word(emu);
3255 emu->x86.R_CS = pop_word(emu);
3256}
3257/****************************************************************************
3258REMARKS:
3259Handles opcode 0xcc
3260****************************************************************************/
3261static void
3262x86emuOp_int3(struct X86EMU *emu)
3263{
3264 x86emu_intr_dispatch(emu, 3);
3265}
3266/****************************************************************************
3267REMARKS:
3268Handles opcode 0xcd
3269****************************************************************************/
3270static void
3271x86emuOp_int_IMM(struct X86EMU *emu)
3272{
3273 uint8_t intnum;
3274
3275 intnum = fetch_byte_imm(emu);
3276 x86emu_intr_dispatch(emu, intnum);
3277}
3278/****************************************************************************
3279REMARKS:
3280Handles opcode 0xce
3281****************************************************************************/
3282static void
3283x86emuOp_into(struct X86EMU *emu)
3284{
3285 if (ACCESS_FLAG(F_OF))
3286 x86emu_intr_dispatch(emu, 4);
3287}
3288/****************************************************************************
3289REMARKS:
3290Handles opcode 0xcf
3291****************************************************************************/
3292static void
3293x86emuOp_iret(struct X86EMU *emu)
3294{
3295 emu->x86.R_IP = pop_word(emu);
3296 emu->x86.R_CS = pop_word(emu);
3297 emu->x86.R_FLG = pop_word(emu);
3298}
3299/****************************************************************************
3300REMARKS:
3301Handles opcode 0xd0
3302****************************************************************************/
3303static void
3304x86emuOp_opcD0_byte_RM_1(struct X86EMU *emu)
3305{
3306 uint8_t destval;
3307
3308 fetch_decode_modrm(emu);
3309 destval = decode_and_fetch_byte(emu);
3310 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, 1);
3311 write_back_byte(emu, destval);
3312}
3313/****************************************************************************
3314REMARKS:
3315Handles opcode 0xd1
3316****************************************************************************/
3317static void
3318x86emuOp_opcD1_word_RM_1(struct X86EMU *emu)
3319{
3320 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3321 uint32_t destval;
3322
3323 fetch_decode_modrm(emu);
3324 destval = decode_and_fetch_long(emu);
3325 destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, 1);
3326 write_back_long(emu, destval);
3327 } else {
3328 uint16_t destval;
3329
3330 fetch_decode_modrm(emu);
3331 destval = decode_and_fetch_word(emu);
3332 destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, 1);
3333 write_back_word(emu, destval);
3334 }
3335}
3336/****************************************************************************
3337REMARKS:
3338Handles opcode 0xd2
3339****************************************************************************/
3340static void
3341x86emuOp_opcD2_byte_RM_CL(struct X86EMU *emu)
3342{
3343 uint8_t destval;
3344
3345 fetch_decode_modrm(emu);
3346 destval = decode_and_fetch_byte(emu);
3347 destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL);
3348 write_back_byte(emu, destval);
3349}
3350/****************************************************************************
3351REMARKS:
3352Handles opcode 0xd3
3353****************************************************************************/
3354static void
3355x86emuOp_opcD3_word_RM_CL(struct X86EMU *emu)
3356{
3357 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3358 uint32_t destval;
3359
3360 fetch_decode_modrm(emu);
3361 destval = decode_and_fetch_long(emu);
3362 destval = (*opcD1_long_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL);
3363 write_back_long(emu, destval);
3364 } else {
3365 uint16_t destval;
3366
3367 fetch_decode_modrm(emu);
3368 destval = decode_and_fetch_word(emu);
3369 destval = (*opcD1_word_operation[emu->cur_rh]) (emu, destval, emu->x86.R_CL);
3370 write_back_word(emu, destval);
3371 }
3372}
3373/****************************************************************************
3374REMARKS:
3375Handles opcode 0xd4
3376****************************************************************************/
3377static void
3378x86emuOp_aam(struct X86EMU *emu)
3379{
3380 uint8_t a;
3381
3382 a = fetch_byte_imm(emu); /* this is a stupid encoding. */
3383 if (a != 10) {
3384 /* fix: add base decoding aam_word(uint8_t val, int base a) */
3385 X86EMU_halt_sys(emu);
3386 }
3387 /* note the type change here --- returning AL and AH in AX. */
3388 emu->x86.R_AX = aam_word(emu, emu->x86.R_AL);
3389}
3390/****************************************************************************
3391REMARKS:
3392Handles opcode 0xd5
3393****************************************************************************/
3394static void
3395x86emuOp_aad(struct X86EMU *emu)
3396{
3397 uint8_t a;
3398
3399 a = fetch_byte_imm(emu);
3400 if (a != 10) {
3401 /* fix: add base decoding aad_word(uint16_t val, int base a) */
3402 X86EMU_halt_sys(emu);
3403 }
3404 emu->x86.R_AX = aad_word(emu, emu->x86.R_AX);
3405}
3406/* opcode 0xd6 ILLEGAL OPCODE */
3407
3408/****************************************************************************
3409REMARKS:
3410Handles opcode 0xd7
3411****************************************************************************/
3412static void
3413x86emuOp_xlat(struct X86EMU *emu)
3414{
3415 uint16_t addr;
3416
3417 addr = (uint16_t) (emu->x86.R_BX + (uint8_t) emu->x86.R_AL);
3418 emu->x86.R_AL = fetch_data_byte(emu, addr);
3419}
3420
3421/* opcode=0xd8 */
3422static void
3423x86emuOp_esc_coprocess_d8(struct X86EMU *emu)
3424{
3425}
3426/* opcode=0xd9 */
3427static void
3428x86emuOp_esc_coprocess_d9(struct X86EMU *emu)
3429{
3430 fetch_decode_modrm(emu);
3431 if (emu->cur_mod != 3)
3432 decode_rl_address(emu);
3433}
3434/* opcode=0xda */
3435static void
3436x86emuOp_esc_coprocess_da(struct X86EMU *emu)
3437{
3438 fetch_decode_modrm(emu);
3439 if (emu->cur_mod != 3)
3440 decode_rl_address(emu);
3441}
3442/* opcode=0xdb */
3443static void
3444x86emuOp_esc_coprocess_db(struct X86EMU *emu)
3445{
3446 fetch_decode_modrm(emu);
3447 if (emu->cur_mod != 3)
3448 decode_rl_address(emu);
3449}
3450/* opcode=0xdc */
3451static void
3452x86emuOp_esc_coprocess_dc(struct X86EMU *emu)
3453{
3454 fetch_decode_modrm(emu);
3455 if (emu->cur_mod != 3)
3456 decode_rl_address(emu);
3457}
3458/* opcode=0xdd */
3459static void
3460x86emuOp_esc_coprocess_dd(struct X86EMU *emu)
3461{
3462 fetch_decode_modrm(emu);
3463 if (emu->cur_mod != 3)
3464 decode_rl_address(emu);
3465}
3466/* opcode=0xde */
3467static void
3468x86emuOp_esc_coprocess_de(struct X86EMU *emu)
3469{
3470 fetch_decode_modrm(emu);
3471 if (emu->cur_mod != 3)
3472 decode_rl_address(emu);
3473}
3474/* opcode=0xdf */
3475static void
3476x86emuOp_esc_coprocess_df(struct X86EMU *emu)
3477{
3478 fetch_decode_modrm(emu);
3479 if (emu->cur_mod != 3)
3480 decode_rl_address(emu);
3481}
3482
3483/****************************************************************************
3484REMARKS:
3485Handles opcode 0xe0
3486****************************************************************************/
3487static void
3488x86emuOp_loopne(struct X86EMU *emu)
3489{
3490 int16_t ip;
3491
3492 ip = (int8_t) fetch_byte_imm(emu);
3493 ip += (int16_t) emu->x86.R_IP;
3494 emu->x86.R_CX -= 1;
3495 if (emu->x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
3496 emu->x86.R_IP = ip;
3497}
3498/****************************************************************************
3499REMARKS:
3500Handles opcode 0xe1
3501****************************************************************************/
3502static void
3503x86emuOp_loope(struct X86EMU *emu)
3504{
3505 int16_t ip;
3506
3507 ip = (int8_t) fetch_byte_imm(emu);
3508 ip += (int16_t) emu->x86.R_IP;
3509 emu->x86.R_CX -= 1;
3510 if (emu->x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
3511 emu->x86.R_IP = ip;
3512}
3513/****************************************************************************
3514REMARKS:
3515Handles opcode 0xe2
3516****************************************************************************/
3517static void
3518x86emuOp_loop(struct X86EMU *emu)
3519{
3520 int16_t ip;
3521
3522 ip = (int8_t) fetch_byte_imm(emu);
3523 ip += (int16_t) emu->x86.R_IP;
3524 emu->x86.R_CX -= 1;
3525 if (emu->x86.R_CX != 0)
3526 emu->x86.R_IP = ip;
3527}
3528/****************************************************************************
3529REMARKS:
3530Handles opcode 0xe3
3531****************************************************************************/
3532static void
3533x86emuOp_jcxz(struct X86EMU *emu)
3534{
3535 uint16_t target;
3536 int8_t offset;
3537
3538 /* jump to byte offset if overflow flag is set */
3539 offset = (int8_t) fetch_byte_imm(emu);
3540 target = (uint16_t) (emu->x86.R_IP + offset);
3541 if (emu->x86.R_CX == 0)
3542 emu->x86.R_IP = target;
3543}
3544/****************************************************************************
3545REMARKS:
3546Handles opcode 0xe4
3547****************************************************************************/
3548static void
3549x86emuOp_in_byte_AL_IMM(struct X86EMU *emu)
3550{
3551 uint8_t port;
3552
3553 port = (uint8_t) fetch_byte_imm(emu);
3554 emu->x86.R_AL = (*emu->emu_inb) (emu, port);
3555}
3556/****************************************************************************
3557REMARKS:
3558Handles opcode 0xe5
3559****************************************************************************/
3560static void
3561x86emuOp_in_word_AX_IMM(struct X86EMU *emu)
3562{
3563 uint8_t port;
3564
3565 port = (uint8_t) fetch_byte_imm(emu);
3566 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3567 emu->x86.R_EAX = (*emu->emu_inl) (emu, port);
3568 } else {
3569 emu->x86.R_AX = (*emu->emu_inw) (emu, port);
3570 }
3571}
3572/****************************************************************************
3573REMARKS:
3574Handles opcode 0xe6
3575****************************************************************************/
3576static void
3577x86emuOp_out_byte_IMM_AL(struct X86EMU *emu)
3578{
3579 uint8_t port;
3580
3581 port = (uint8_t) fetch_byte_imm(emu);
3582 (*emu->emu_outb) (emu, port, emu->x86.R_AL);
3583}
3584/****************************************************************************
3585REMARKS:
3586Handles opcode 0xe7
3587****************************************************************************/
3588static void
3589x86emuOp_out_word_IMM_AX(struct X86EMU *emu)
3590{
3591 uint8_t port;
3592
3593 port = (uint8_t) fetch_byte_imm(emu);
3594 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3595 (*emu->emu_outl) (emu, port, emu->x86.R_EAX);
3596 } else {
3597 (*emu->emu_outw) (emu, port, emu->x86.R_AX);
3598 }
3599}
3600/****************************************************************************
3601REMARKS:
3602Handles opcode 0xe8
3603****************************************************************************/
3604static void
3605x86emuOp_call_near_IMM(struct X86EMU *emu)
3606{
3607 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3608 int32_t ip;
3609 ip = (int32_t) fetch_long_imm(emu);
3610 ip += (int32_t) emu->x86.R_EIP;
3611 push_long(emu, emu->x86.R_EIP);
3612 emu->x86.R_EIP = ip;
3613 } else {
3614 int16_t ip;
3615 ip = (int16_t) fetch_word_imm(emu);
3616 ip += (int16_t) emu->x86.R_IP; /* CHECK SIGN */
3617 push_word(emu, emu->x86.R_IP);
3618 emu->x86.R_IP = ip;
3619 }
3620}
3621/****************************************************************************
3622REMARKS:
3623Handles opcode 0xe9
3624****************************************************************************/
3625static void
3626x86emuOp_jump_near_IMM(struct X86EMU *emu)
3627{
3628 int ip;
3629
3630 ip = (int16_t) fetch_word_imm(emu);
3631 ip += (int16_t) emu->x86.R_IP;
3632 emu->x86.R_IP = (uint16_t) ip;
3633}
3634/****************************************************************************
3635REMARKS:
3636Handles opcode 0xea
3637****************************************************************************/
3638static void
3639x86emuOp_jump_far_IMM(struct X86EMU *emu)
3640{
3641 uint16_t cs, ip;
3642
3643 ip = fetch_word_imm(emu);
3644 cs = fetch_word_imm(emu);
3645 emu->x86.R_IP = ip;
3646 emu->x86.R_CS = cs;
3647}
3648/****************************************************************************
3649REMARKS:
3650Handles opcode 0xeb
3651****************************************************************************/
3652static void
3653x86emuOp_jump_byte_IMM(struct X86EMU *emu)
3654{
3655 uint16_t target;
3656 int8_t offset;
3657
3658 offset = (int8_t) fetch_byte_imm(emu);
3659 target = (uint16_t) (emu->x86.R_IP + offset);
3660 emu->x86.R_IP = target;
3661}
3662/****************************************************************************
3663REMARKS:
3664Handles opcode 0xec
3665****************************************************************************/
3666static void
3667x86emuOp_in_byte_AL_DX(struct X86EMU *emu)
3668{
3669 emu->x86.R_AL = (*emu->emu_inb) (emu, emu->x86.R_DX);
3670}
3671/****************************************************************************
3672REMARKS:
3673Handles opcode 0xed
3674****************************************************************************/
3675static void
3676x86emuOp_in_word_AX_DX(struct X86EMU *emu)
3677{
3678 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3679 emu->x86.R_EAX = (*emu->emu_inl) (emu, emu->x86.R_DX);
3680 } else {
3681 emu->x86.R_AX = (*emu->emu_inw) (emu, emu->x86.R_DX);
3682 }
3683}
3684/****************************************************************************
3685REMARKS:
3686Handles opcode 0xee
3687****************************************************************************/
3688static void
3689x86emuOp_out_byte_DX_AL(struct X86EMU *emu)
3690{
3691 (*emu->emu_outb) (emu, emu->x86.R_DX, emu->x86.R_AL);
3692}
3693/****************************************************************************
3694REMARKS:
3695Handles opcode 0xef
3696****************************************************************************/
3697static void
3698x86emuOp_out_word_DX_AX(struct X86EMU *emu)
3699{
3700 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3701 (*emu->emu_outl) (emu, emu->x86.R_DX, emu->x86.R_EAX);
3702 } else {
3703 (*emu->emu_outw) (emu, emu->x86.R_DX, emu->x86.R_AX);
3704 }
3705}
3706/****************************************************************************
3707REMARKS:
3708Handles opcode 0xf0
3709****************************************************************************/
3710static void
3711x86emuOp_lock(struct X86EMU *emu)
3712{
3713}
3714/*opcode 0xf1 ILLEGAL OPERATION */
3715
3716/****************************************************************************
3717REMARKS:
3718Handles opcode 0xf5
3719****************************************************************************/
3720static void
3721x86emuOp_cmc(struct X86EMU *emu)
3722{
3723 if (ACCESS_FLAG(F_CF))
3724 CLEAR_FLAG(F_CF);
3725 else
3726 SET_FLAG(F_CF);
3727}
3728/****************************************************************************
3729REMARKS:
3730Handles opcode 0xf6
3731****************************************************************************/
3732static void
3733x86emuOp_opcF6_byte_RM(struct X86EMU *emu)
3734{
3735 uint8_t destval, srcval;
3736
3737 /* long, drawn out code follows. Double switch for a total of 32
3738 * cases. */
3739 fetch_decode_modrm(emu);
3740 if (emu->cur_rh == 1)
3741 X86EMU_halt_sys(emu);
3742
3743 if (emu->cur_rh == 0) {
3744 destval = decode_and_fetch_byte_imm8(emu, &srcval);
3745 test_byte(emu, destval, srcval);
3746 return;
3747 }
3748 destval = decode_and_fetch_byte(emu);
3749 switch (emu->cur_rh) {
3750 case 2:
3751 destval = ~destval;
3752 write_back_byte(emu, destval);
3753 break;
3754 case 3:
3755 destval = neg_byte(emu, destval);
3756 write_back_byte(emu, destval);
3757 break;
3758 case 4:
3759 mul_byte(emu, destval);
3760 break;
3761 case 5:
3762 imul_byte(emu, destval);
3763 break;
3764 case 6:
3765 div_byte(emu, destval);
3766 break;
3767 case 7:
3768 idiv_byte(emu, destval);
3769 break;
3770 }
3771}
3772/****************************************************************************
3773REMARKS:
3774Handles opcode 0xf7
3775****************************************************************************/
3776static void
3777x86emuOp32_opcF7_word_RM(struct X86EMU *emu)
3778{
3779 uint32_t destval, srcval;
3780
3781 /* long, drawn out code follows. Double switch for a total of 32
3782 * cases. */
3783 fetch_decode_modrm(emu);
3784 if (emu->cur_rh == 1)
3785 X86EMU_halt_sys(emu);
3786
3787 if (emu->cur_rh == 0) {
3788 if (emu->cur_mod != 3) {
3789 uint32_t destoffset;
3790
3791 destoffset = decode_rl_address(emu);
3792 srcval = fetch_long_imm(emu);
3793 destval = fetch_data_long(emu, destoffset);
3794 } else {
3795 srcval = fetch_long_imm(emu);
3796 destval = *decode_rl_long_register(emu);
3797 }
3798 test_long(emu, destval, srcval);
3799 return;
3800 }
3801 destval = decode_and_fetch_long(emu);
3802 switch (emu->cur_rh) {
3803 case 2:
3804 destval = ~destval;
3805 write_back_long(emu, destval);
3806 break;
3807 case 3:
3808 destval = neg_long(emu, destval);
3809 write_back_long(emu, destval);
3810 break;
3811 case 4:
3812 mul_long(emu, destval);
3813 break;
3814 case 5:
3815 imul_long(emu, destval);
3816 break;
3817 case 6:
3818 div_long(emu, destval);
3819 break;
3820 case 7:
3821 idiv_long(emu, destval);
3822 break;
3823 }
3824}
3825static void
3826x86emuOp16_opcF7_word_RM(struct X86EMU *emu)
3827{
3828 uint16_t destval, srcval;
3829
3830 /* long, drawn out code follows. Double switch for a total of 32
3831 * cases. */
3832 fetch_decode_modrm(emu);
3833 if (emu->cur_rh == 1)
3834 X86EMU_halt_sys(emu);
3835
3836 if (emu->cur_rh == 0) {
3837 if (emu->cur_mod != 3) {
3838 uint32_t destoffset;
3839
3840 destoffset = decode_rl_address(emu);
3841 srcval = fetch_word_imm(emu);
3842 destval = fetch_data_word(emu, destoffset);
3843 } else {
3844 srcval = fetch_word_imm(emu);
3845 destval = *decode_rl_word_register(emu);
3846 }
3847 test_word(emu, destval, srcval);
3848 return;
3849 }
3850 destval = decode_and_fetch_word(emu);
3851 switch (emu->cur_rh) {
3852 case 2:
3853 destval = ~destval;
3854 write_back_word(emu, destval);
3855 break;
3856 case 3:
3857 destval = neg_word(emu, destval);
3858 write_back_word(emu, destval);
3859 break;
3860 case 4:
3861 mul_word(emu, destval);
3862 break;
3863 case 5:
3864 imul_word(emu, destval);
3865 break;
3866 case 6:
3867 div_word(emu, destval);
3868 break;
3869 case 7:
3870 idiv_word(emu, destval);
3871 break;
3872 }
3873}
3874static void
3875x86emuOp_opcF7_word_RM(struct X86EMU *emu)
3876{
3877 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3878 x86emuOp32_opcF7_word_RM(emu);
3879 else
3880 x86emuOp16_opcF7_word_RM(emu);
3881}
3882/****************************************************************************
3883REMARKS:
3884Handles opcode 0xfe
3885****************************************************************************/
3886static void
3887x86emuOp_opcFE_byte_RM(struct X86EMU *emu)
3888{
3889 uint8_t destval;
3890 uint32_t destoffset;
3891 uint8_t *destreg;
3892
3893 /* Yet another special case instruction. */
3894 fetch_decode_modrm(emu);
3895 if (emu->cur_mod != 3) {
3896 destoffset = decode_rl_address(emu);
3897 switch (emu->cur_rh) {
3898 case 0: /* inc word ptr ... */
3899 destval = fetch_data_byte(emu, destoffset);
3900 destval = inc_byte(emu, destval);
3901 store_data_byte(emu, destoffset, destval);
3902 break;
3903 case 1: /* dec word ptr ... */
3904 destval = fetch_data_byte(emu, destoffset);
3905 destval = dec_byte(emu, destval);
3906 store_data_byte(emu, destoffset, destval);
3907 break;
3908 }
3909 } else {
3910 destreg = decode_rl_byte_register(emu);
3911 switch (emu->cur_rh) {
3912 case 0:
3913 *destreg = inc_byte(emu, *destreg);
3914 break;
3915 case 1:
3916 *destreg = dec_byte(emu, *destreg);
3917 break;
3918 }
3919 }
3920}
3921/****************************************************************************
3922REMARKS:
3923Handles opcode 0xff
3924****************************************************************************/
3925static void
3926x86emuOp32_opcFF_word_RM(struct X86EMU *emu)
3927{
3928 uint32_t destoffset = 0;
3929 uint32_t destval, *destreg;
3930
3931 if (emu->cur_mod != 3) {
3932 destoffset = decode_rl_address(emu);
3933 destval = fetch_data_long(emu, destoffset);
3934 switch (emu->cur_rh) {
3935 case 0: /* inc word ptr ... */
3936 destval = inc_long(emu, destval);
3937 store_data_long(emu, destoffset, destval);
3938 break;
3939 case 1: /* dec word ptr ... */
3940 destval = dec_long(emu, destval);
3941 store_data_long(emu, destoffset, destval);
3942 break;
3943 case 6: /* push word ptr ... */
3944 push_long(emu, destval);
3945 break;
3946 }
3947 } else {
3948 destreg = decode_rl_long_register(emu);
3949 switch (emu->cur_rh) {
3950 case 0:
3951 *destreg = inc_long(emu, *destreg);
3952 break;
3953 case 1:
3954 *destreg = dec_long(emu, *destreg);
3955 break;
3956 case 6:
3957 push_long(emu, *destreg);
3958 break;
3959 }
3960 }
3961}
3962
3963static void
3964x86emuOp16_opcFF_word_RM(struct X86EMU *emu)
3965{
3966 uint32_t destoffset = 0;
3967 uint16_t *destreg;
3968 uint16_t destval;
3969
3970 if (emu->cur_mod != 3) {
3971 destoffset = decode_rl_address(emu);
3972 destval = fetch_data_word(emu, destoffset);
3973 switch (emu->cur_rh) {
3974 case 0:
3975 destval = inc_word(emu, destval);
3976 store_data_word(emu, destoffset, destval);
3977 break;
3978 case 1: /* dec word ptr ... */
3979 destval = dec_word(emu, destval);
3980 store_data_word(emu, destoffset, destval);
3981 break;
3982 case 6: /* push word ptr ... */
3983 push_word(emu, destval);
3984 break;
3985 }
3986 } else {
3987 destreg = decode_rl_word_register(emu);
3988 switch (emu->cur_rh) {
3989 case 0:
3990 *destreg = inc_word(emu, *destreg);
3991 break;
3992 case 1:
3993 *destreg = dec_word(emu, *destreg);
3994 break;
3995 case 6:
3996 push_word(emu, *destreg);
3997 break;
3998 }
3999 }
4000}
4001
4002static void
4003x86emuOp_opcFF_word_RM(struct X86EMU *emu)
4004{
4005 uint32_t destoffset = 0;
4006 uint16_t destval, destval2;
4007
4008 /* Yet another special case instruction. */
4009 fetch_decode_modrm(emu);
4010 if ((emu->cur_mod == 3 && (emu->cur_rh == 3 || emu->cur_rh == 5)) || emu->cur_rh == 7)
4011 X86EMU_halt_sys(emu);
4012 if (emu->cur_rh == 0 || emu->cur_rh == 1 || emu->cur_rh == 6) {
4013 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4014 x86emuOp32_opcFF_word_RM(emu);
4015 else
4016 x86emuOp16_opcFF_word_RM(emu);
4017 return;
4018 }
4019
4020 if (emu->cur_mod != 3) {
4021 destoffset = decode_rl_address(emu);
4022 destval = fetch_data_word(emu, destoffset);
4023 switch (emu->cur_rh) {
4024 case 3: /* call far ptr ... */
4025 destval2 = fetch_data_word(emu, destoffset + 2);
4026 push_word(emu, emu->x86.R_CS);
4027 emu->x86.R_CS = destval2;
4028 push_word(emu, emu->x86.R_IP);
4029 emu->x86.R_IP = destval;
4030 break;
4031 case 5: /* jmp far ptr ... */
4032 destval2 = fetch_data_word(emu, destoffset + 2);
4033 emu->x86.R_IP = destval;
4034 emu->x86.R_CS = destval2;
4035 break;
4036 }
4037 } else {
4038 destval = *decode_rl_word_register(emu);
4039 }
4040
4041 switch (emu->cur_rh) {
4042 case 2: /* call word ptr */
4043 push_word(emu, emu->x86.R_IP);
4044 emu->x86.R_IP = destval;
4045 break;
4046 case 4: /* jmp */
4047 emu->x86.R_IP = destval;
4048 break;
4049 }
4050}
4051/***************************************************************************
4052 * Single byte operation code table:
4053 **************************************************************************/
4054static void
4055X86EMU_exec_one_byte(struct X86EMU * emu)
4056{
4057 uint8_t op1;
4058
4059 op1 = fetch_byte_imm(emu);
4060
4061 switch (op1) {
4062 case 0x00:
4063 common_binop_byte_rm_r(emu, add_byte);
4064 break;
4065 case 0x01:
4066 common_binop_word_long_rm_r(emu, add_word, add_long);
4067 break;
4068 case 0x02:
4069 common_binop_byte_r_rm(emu, add_byte);
4070 break;
4071 case 0x03:
4072 common_binop_word_long_r_rm(emu, add_word, add_long);
4073 break;
4074 case 0x04:
4075 common_binop_byte_imm(emu, add_byte);
4076 break;
4077 case 0x05:
4078 common_binop_word_long_imm(emu, add_word, add_long);
4079 break;
4080 case 0x06:
4081 push_word(emu, emu->x86.R_ES);
4082 break;
4083 case 0x07:
4084 emu->x86.R_ES = pop_word(emu);
4085 break;
4086
4087 case 0x08:
4088 common_binop_byte_rm_r(emu, or_byte);
4089 break;
4090 case 0x09:
4091 common_binop_word_long_rm_r(emu, or_word, or_long);
4092 break;
4093 case 0x0a:
4094 common_binop_byte_r_rm(emu, or_byte);
4095 break;
4096 case 0x0b:
4097 common_binop_word_long_r_rm(emu, or_word, or_long);
4098 break;
4099 case 0x0c:
4100 common_binop_byte_imm(emu, or_byte);
4101 break;
4102 case 0x0d:
4103 common_binop_word_long_imm(emu, or_word, or_long);
4104 break;
4105 case 0x0e:
4106 push_word(emu, emu->x86.R_CS);
4107 break;
4108 case 0x0f:
4109 X86EMU_exec_two_byte(emu);
4110 break;
4111
4112 case 0x10:
4113 common_binop_byte_rm_r(emu, adc_byte);
4114 break;
4115 case 0x11:
4116 common_binop_word_long_rm_r(emu, adc_word, adc_long);
4117 break;
4118 case 0x12:
4119 common_binop_byte_r_rm(emu, adc_byte);
4120 break;
4121 case 0x13:
4122 common_binop_word_long_r_rm(emu, adc_word, adc_long);
4123 break;
4124 case 0x14:
4125 common_binop_byte_imm(emu, adc_byte);
4126 break;
4127 case 0x15:
4128 common_binop_word_long_imm(emu, adc_word, adc_long);
4129 break;
4130 case 0x16:
4131 push_word(emu, emu->x86.R_SS);
4132 break;
4133 case 0x17:
4134 emu->x86.R_SS = pop_word(emu);
4135 break;
4136
4137 case 0x18:
4138 common_binop_byte_rm_r(emu, sbb_byte);
4139 break;
4140 case 0x19:
4141 common_binop_word_long_rm_r(emu, sbb_word, sbb_long);
4142 break;
4143 case 0x1a:
4144 common_binop_byte_r_rm(emu, sbb_byte);
4145 break;
4146 case 0x1b:
4147 common_binop_word_long_r_rm(emu, sbb_word, sbb_long);
4148 break;
4149 case 0x1c:
4150 common_binop_byte_imm(emu, sbb_byte);
4151 break;
4152 case 0x1d:
4153 common_binop_word_long_imm(emu, sbb_word, sbb_long);
4154 break;
4155 case 0x1e:
4156 push_word(emu, emu->x86.R_DS);
4157 break;
4158 case 0x1f:
4159 emu->x86.R_DS = pop_word(emu);
4160 break;
4161
4162 case 0x20:
4163 common_binop_byte_rm_r(emu, and_byte);
4164 break;
4165 case 0x21:
4166 common_binop_word_long_rm_r(emu, and_word, and_long);
4167 break;
4168 case 0x22:
4169 common_binop_byte_r_rm(emu, and_byte);
4170 break;
4171 case 0x23:
4172 common_binop_word_long_r_rm(emu, and_word, and_long);
4173 break;
4174 case 0x24:
4175 common_binop_byte_imm(emu, and_byte);
4176 break;
4177 case 0x25:
4178 common_binop_word_long_imm(emu, and_word, and_long);
4179 break;
4180 case 0x26:
4181 emu->x86.mode |= SYSMODE_SEGOVR_ES;
4182 break;
4183 case 0x27:
4184 emu->x86.R_AL = daa_byte(emu, emu->x86.R_AL);
4185 break;
4186
4187 case 0x28:
4188 common_binop_byte_rm_r(emu, sub_byte);
4189 break;
4190 case 0x29:
4191 common_binop_word_long_rm_r(emu, sub_word, sub_long);
4192 break;
4193 case 0x2a:
4194 common_binop_byte_r_rm(emu, sub_byte);
4195 break;
4196 case 0x2b:
4197 common_binop_word_long_r_rm(emu, sub_word, sub_long);
4198 break;
4199 case 0x2c:
4200 common_binop_byte_imm(emu, sub_byte);
4201 break;
4202 case 0x2d:
4203 common_binop_word_long_imm(emu, sub_word, sub_long);
4204 break;
4205 case 0x2e:
4206 emu->x86.mode |= SYSMODE_SEGOVR_CS;
4207 break;
4208 case 0x2f:
4209 emu->x86.R_AL = das_byte(emu, emu->x86.R_AL);
4210 break;
4211
4212 case 0x30:
4213 common_binop_byte_rm_r(emu, xor_byte);
4214 break;
4215 case 0x31:
4216 common_binop_word_long_rm_r(emu, xor_word, xor_long);
4217 break;
4218 case 0x32:
4219 common_binop_byte_r_rm(emu, xor_byte);
4220 break;
4221 case 0x33:
4222 common_binop_word_long_r_rm(emu, xor_word, xor_long);
4223 break;
4224 case 0x34:
4225 common_binop_byte_imm(emu, xor_byte);
4226 break;
4227 case 0x35:
4228 common_binop_word_long_imm(emu, xor_word, xor_long);
4229 break;
4230 case 0x36:
4231 emu->x86.mode |= SYSMODE_SEGOVR_SS;
4232 break;
4233 case 0x37:
4234 emu->x86.R_AX = aaa_word(emu, emu->x86.R_AX);
4235 break;
4236
4237 case 0x38:
4238 common_binop_ns_byte_rm_r(emu, cmp_byte_no_return);
4239 break;
4240 case 0x39:
4241 common_binop_ns_word_long_rm_r(emu, cmp_word_no_return,
4242 cmp_long_no_return);
4243 break;
4244 case 0x3a:
4245 x86emuOp_cmp_byte_R_RM(emu);
4246 break;
4247 case 0x3b:
4248 x86emuOp_cmp_word_R_RM(emu);
4249 break;
4250 case 0x3c:
4251 x86emuOp_cmp_byte_AL_IMM(emu);
4252 break;
4253 case 0x3d:
4254 x86emuOp_cmp_word_AX_IMM(emu);
4255 break;
4256 case 0x3e:
4257 emu->x86.mode |= SYSMODE_SEGOVR_DS;
4258 break;
4259 case 0x3f:
4260 emu->x86.R_AX = aas_word(emu, emu->x86.R_AX);
4261 break;
4262