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
4263 case 0x40:
4264 common_inc_word_long(emu, &emu->x86.register_a);
4265 break;
4266 case 0x41:
4267 common_inc_word_long(emu, &emu->x86.register_c);
4268 break;
4269 case 0x42:
4270 common_inc_word_long(emu, &emu->x86.register_d);
4271 break;
4272 case 0x43:
4273 common_inc_word_long(emu, &emu->x86.register_b);
4274 break;
4275 case 0x44:
4276 common_inc_word_long(emu, &emu->x86.register_sp);
4277 break;
4278 case 0x45:
4279 common_inc_word_long(emu, &emu->x86.register_bp);
4280 break;
4281 case 0x46:
4282 common_inc_word_long(emu, &emu->x86.register_si);
4283 break;
4284 case 0x47:
4285 common_inc_word_long(emu, &emu->x86.register_di);
4286 break;
4287
4288 case 0x48:
4289 common_dec_word_long(emu, &emu->x86.register_a);
4290 break;
4291 case 0x49:
4292 common_dec_word_long(emu, &emu->x86.register_c);
4293 break;
4294 case 0x4a:
4295 common_dec_word_long(emu, &emu->x86.register_d);
4296 break;
4297 case 0x4b:
4298 common_dec_word_long(emu, &emu->x86.register_b);
4299 break;
4300 case 0x4c:
4301 common_dec_word_long(emu, &emu->x86.register_sp);
4302 break;
4303 case 0x4d:
4304 common_dec_word_long(emu, &emu->x86.register_bp);
4305 break;
4306 case 0x4e:
4307 common_dec_word_long(emu, &emu->x86.register_si);
4308 break;
4309 case 0x4f:
4310 common_dec_word_long(emu, &emu->x86.register_di);
4311 break;
4312
4313 case 0x50:
4314 common_push_word_long(emu, &emu->x86.register_a);
4315 break;
4316 case 0x51:
4317 common_push_word_long(emu, &emu->x86.register_c);
4318 break;
4319 case 0x52:
4320 common_push_word_long(emu, &emu->x86.register_d);
4321 break;
4322 case 0x53:
4323 common_push_word_long(emu, &emu->x86.register_b);
4324 break;
4325 case 0x54:
4326 common_push_word_long(emu, &emu->x86.register_sp);
4327 break;
4328 case 0x55:
4329 common_push_word_long(emu, &emu->x86.register_bp);
4330 break;
4331 case 0x56:
4332 common_push_word_long(emu, &emu->x86.register_si);
4333 break;
4334 case 0x57:
4335 common_push_word_long(emu, &emu->x86.register_di);
4336 break;
4337
4338 case 0x58:
4339 common_pop_word_long(emu, &emu->x86.register_a);
4340 break;
4341 case 0x59:
4342 common_pop_word_long(emu, &emu->x86.register_c);
4343 break;
4344 case 0x5a:
4345 common_pop_word_long(emu, &emu->x86.register_d);
4346 break;
4347 case 0x5b:
4348 common_pop_word_long(emu, &emu->x86.register_b);
4349 break;
4350 case 0x5c:
4351 common_pop_word_long(emu, &emu->x86.register_sp);
4352 break;
4353 case 0x5d:
4354 common_pop_word_long(emu, &emu->x86.register_bp);
4355 break;
4356 case 0x5e:
4357 common_pop_word_long(emu, &emu->x86.register_si);
4358 break;
4359 case 0x5f:
4360 common_pop_word_long(emu, &emu->x86.register_di);
4361 break;
4362
4363 case 0x60:
4364 x86emuOp_push_all(emu);
4365 break;
4366 case 0x61:
4367 x86emuOp_pop_all(emu);
4368 break;
4369 /* 0x62 bound */
4370 /* 0x63 arpl */
4371 case 0x64:
4372 emu->x86.mode |= SYSMODE_SEGOVR_FS;
4373 break;
4374 case 0x65:
4375 emu->x86.mode |= SYSMODE_SEGOVR_GS;
4376 break;
4377 case 0x66:
4378 emu->x86.mode |= SYSMODE_PREFIX_DATA;
4379 break;
4380 case 0x67:
4381 emu->x86.mode |= SYSMODE_PREFIX_ADDR;
4382 break;
4383
4384 case 0x68:
4385 x86emuOp_push_word_IMM(emu);
4386 break;
4387 case 0x69:
4388 common_imul_imm(emu, false);
4389 break;
4390 case 0x6a:
4391 x86emuOp_push_byte_IMM(emu);
4392 break;
4393 case 0x6b:
4394 common_imul_imm(emu, true);
4395 break;
4396 case 0x6c:
4397 ins(emu, 1);
4398 break;
4399 case 0x6d:
4400 x86emuOp_ins_word(emu);
4401 break;
4402 case 0x6e:
4403 outs(emu, 1);
4404 break;
4405 case 0x6f:
4406 x86emuOp_outs_word(emu);
4407 break;
4408
4409 case 0x70:
4410 common_jmp_near(emu, ACCESS_FLAG(F_OF));
4411 break;
4412 case 0x71:
4413 common_jmp_near(emu, !ACCESS_FLAG(F_OF));
4414 break;
4415 case 0x72:
4416 common_jmp_near(emu, ACCESS_FLAG(F_CF));
4417 break;
4418 case 0x73:
4419 common_jmp_near(emu, !ACCESS_FLAG(F_CF));
4420 break;
4421 case 0x74:
4422 common_jmp_near(emu, ACCESS_FLAG(F_ZF));
4423 break;
4424 case 0x75:
4425 common_jmp_near(emu, !ACCESS_FLAG(F_ZF));
4426 break;
4427 case 0x76:
4428 common_jmp_near(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
4429 break;
4430 case 0x77:
4431 common_jmp_near(emu, !ACCESS_FLAG(F_CF) && !ACCESS_FLAG(F_ZF));
4432 break;
4433
4434 case 0x78:
4435 common_jmp_near(emu, ACCESS_FLAG(F_SF));
4436 break;
4437 case 0x79:
4438 common_jmp_near(emu, !ACCESS_FLAG(F_SF));
4439 break;
4440 case 0x7a:
4441 common_jmp_near(emu, ACCESS_FLAG(F_PF));
4442 break;
4443 case 0x7b:
4444 common_jmp_near(emu, !ACCESS_FLAG(F_PF));
4445 break;
4446 case 0x7c:
4447 x86emuOp_jump_near_L(emu);
4448 break;
4449 case 0x7d:
4450 x86emuOp_jump_near_NL(emu);
4451 break;
4452 case 0x7e:
4453 x86emuOp_jump_near_LE(emu);
4454 break;
4455 case 0x7f:
4456 x86emuOp_jump_near_NLE(emu);
4457 break;
4458
4459 case 0x80:
4460 x86emuOp_opc80_byte_RM_IMM(emu);
4461 break;
4462 case 0x81:
4463 x86emuOp_opc81_word_RM_IMM(emu);
4464 break;
4465 case 0x82:
4466 x86emuOp_opc82_byte_RM_IMM(emu);
4467 break;
4468 case 0x83:
4469 x86emuOp_opc83_word_RM_IMM(emu);
4470 break;
4471 case 0x84:
4472 common_binop_ns_byte_rm_r(emu, test_byte);
4473 break;
4474 case 0x85:
4475 common_binop_ns_word_long_rm_r(emu, test_word, test_long);
4476 break;
4477 case 0x86:
4478 x86emuOp_xchg_byte_RM_R(emu);
4479 break;
4480 case 0x87:
4481 x86emuOp_xchg_word_RM_R(emu);
4482 break;
4483
4484 case 0x88:
4485 x86emuOp_mov_byte_RM_R(emu);
4486 break;
4487 case 0x89:
4488 x86emuOp_mov_word_RM_R(emu);
4489 break;
4490 case 0x8a:
4491 x86emuOp_mov_byte_R_RM(emu);
4492 break;
4493 case 0x8b:
4494 x86emuOp_mov_word_R_RM(emu);
4495 break;
4496 case 0x8c:
4497 x86emuOp_mov_word_RM_SR(emu);
4498 break;
4499 case 0x8d:
4500 x86emuOp_lea_word_R_M(emu);
4501 break;
4502 case 0x8e:
4503 x86emuOp_mov_word_SR_RM(emu);
4504 break;
4505 case 0x8f:
4506 x86emuOp_pop_RM(emu);
4507 break;
4508
4509 case 0x90:
4510 /* nop */
4511 break;
4512 case 0x91:
4513 x86emuOp_xchg_word_AX_CX(emu);
4514 break;
4515 case 0x92:
4516 x86emuOp_xchg_word_AX_DX(emu);
4517 break;
4518 case 0x93:
4519 x86emuOp_xchg_word_AX_BX(emu);
4520 break;
4521 case 0x94:
4522 x86emuOp_xchg_word_AX_SP(emu);
4523 break;
4524 case 0x95:
4525 x86emuOp_xchg_word_AX_BP(emu);
4526 break;
4527 case 0x96:
4528 x86emuOp_xchg_word_AX_SI(emu);
4529 break;
4530 case 0x97:
4531 x86emuOp_xchg_word_AX_DI(emu);
4532 break;
4533
4534 case 0x98:
4535 x86emuOp_cbw(emu);
4536 break;
4537 case 0x99:
4538 x86emuOp_cwd(emu);
4539 break;
4540 case 0x9a:
4541 x86emuOp_call_far_IMM(emu);
4542 break;
4543 case 0x9b:
4544 /* wait */
4545 break;
4546 case 0x9c:
4547 x86emuOp_pushf_word(emu);
4548 break;
4549 case 0x9d:
4550 x86emuOp_popf_word(emu);
4551 break;
4552 case 0x9e:
4553 x86emuOp_sahf(emu);
4554 break;
4555 case 0x9f:
4556 x86emuOp_lahf(emu);
4557 break;
4558
4559 case 0xa0:
4560 x86emuOp_mov_AL_M_IMM(emu);
4561 break;
4562 case 0xa1:
4563 x86emuOp_mov_AX_M_IMM(emu);
4564 break;
4565 case 0xa2:
4566 x86emuOp_mov_M_AL_IMM(emu);
4567 break;
4568 case 0xa3:
4569 x86emuOp_mov_M_AX_IMM(emu);
4570 break;
4571 case 0xa4:
4572 x86emuOp_movs_byte(emu);
4573 break;
4574 case 0xa5:
4575 x86emuOp_movs_word(emu);
4576 break;
4577 case 0xa6:
4578 x86emuOp_cmps_byte(emu);
4579 break;
4580 case 0xa7:
4581 x86emuOp_cmps_word(emu);
4582 break;
4583
4584 case 0xa8:
4585 test_byte(emu, emu->x86.R_AL, fetch_byte_imm(emu));
4586 break;
4587 case 0xa9:
4588 x86emuOp_test_AX_IMM(emu);
4589 break;
4590 case 0xaa:
4591 x86emuOp_stos_byte(emu);
4592 break;
4593 case 0xab:
4594 x86emuOp_stos_word(emu);
4595 break;
4596 case 0xac:
4597 x86emuOp_lods_byte(emu);
4598 break;
4599 case 0xad:
4600 x86emuOp_lods_word(emu);
4601 break;
4602 case 0xae:
4603 x86emuOp_scas_byte(emu);
4604 break;
4605 case 0xaf:
4606 x86emuOp_scas_word(emu);
4607 break;
4608
4609 case 0xb0:
4610 emu->x86.R_AL = fetch_byte_imm(emu);
4611 break;
4612 case 0xb1:
4613 emu->x86.R_CL = fetch_byte_imm(emu);
4614 break;
4615 case 0xb2:
4616 emu->x86.R_DL = fetch_byte_imm(emu);
4617 break;
4618 case 0xb3:
4619 emu->x86.R_BL = fetch_byte_imm(emu);
4620 break;
4621 case 0xb4:
4622 emu->x86.R_AH = fetch_byte_imm(emu);
4623 break;
4624 case 0xb5:
4625 emu->x86.R_CH = fetch_byte_imm(emu);
4626 break;
4627 case 0xb6:
4628 emu->x86.R_DH = fetch_byte_imm(emu);
4629 break;
4630 case 0xb7:
4631 emu->x86.R_BH = fetch_byte_imm(emu);
4632 break;
4633
4634 case 0xb8:
4635 x86emuOp_mov_word_AX_IMM(emu);
4636 break;
4637 case 0xb9:
4638 x86emuOp_mov_word_CX_IMM(emu);
4639 break;
4640 case 0xba:
4641 x86emuOp_mov_word_DX_IMM(emu);
4642 break;
4643 case 0xbb:
4644 x86emuOp_mov_word_BX_IMM(emu);
4645 break;
4646 case 0xbc:
4647 x86emuOp_mov_word_SP_IMM(emu);
4648 break;
4649 case 0xbd:
4650 x86emuOp_mov_word_BP_IMM(emu);
4651 break;
4652 case 0xbe:
4653 x86emuOp_mov_word_SI_IMM(emu);
4654 break;
4655 case 0xbf:
4656 x86emuOp_mov_word_DI_IMM(emu);
4657 break;
4658
4659 case 0xc0:
4660 x86emuOp_opcC0_byte_RM_MEM(emu);
4661 break;
4662 case 0xc1:
4663 x86emuOp_opcC1_word_RM_MEM(emu);
4664 break;
4665 case 0xc2:
4666 x86emuOp_ret_near_IMM(emu);
4667 break;
4668 case 0xc3:
4669 emu->x86.R_IP = pop_word(emu);
4670 break;
4671 case 0xc4:
4672 common_load_far_pointer(emu, &emu->x86.R_ES);
4673 break;
4674 case 0xc5:
4675 common_load_far_pointer(emu, &emu->x86.R_DS);
4676 break;
4677 case 0xc6:
4678 x86emuOp_mov_byte_RM_IMM(emu);
4679 break;
4680 case 0xc7:
4681 x86emuOp_mov_word_RM_IMM(emu);
4682 break;
4683 case 0xc8:
4684 x86emuOp_enter(emu);
4685 break;
4686 case 0xc9:
4687 x86emuOp_leave(emu);
4688 break;
4689 case 0xca:
4690 x86emuOp_ret_far_IMM(emu);
4691 break;
4692 case 0xcb:
4693 x86emuOp_ret_far(emu);
4694 break;
4695 case 0xcc:
4696 x86emuOp_int3(emu);
4697 break;
4698 case 0xcd:
4699 x86emuOp_int_IMM(emu);
4700 break;
4701 case 0xce:
4702 x86emuOp_into(emu);
4703 break;
4704 case 0xcf:
4705 x86emuOp_iret(emu);
4706 break;
4707
4708 case 0xd0:
4709 x86emuOp_opcD0_byte_RM_1(emu);
4710 break;
4711 case 0xd1:
4712 x86emuOp_opcD1_word_RM_1(emu);
4713 break;
4714 case 0xd2:
4715 x86emuOp_opcD2_byte_RM_CL(emu);
4716 break;
4717 case 0xd3:
4718 x86emuOp_opcD3_word_RM_CL(emu);
4719 break;
4720 case 0xd4:
4721 x86emuOp_aam(emu);
4722 break;
4723 case 0xd5:
4724 x86emuOp_aad(emu);
4725 break;
4726 /* 0xd6 Undocumented SETALC instruction */
4727 case 0xd7:
4728 x86emuOp_xlat(emu);
4729 break;
4730 case 0xd8:
4731 x86emuOp_esc_coprocess_d8(emu);
4732 break;
4733 case 0xd9:
4734 x86emuOp_esc_coprocess_d9(emu);
4735 break;
4736 case 0xda:
4737 x86emuOp_esc_coprocess_da(emu);
4738 break;
4739 case 0xdb:
4740 x86emuOp_esc_coprocess_db(emu);
4741 break;
4742 case 0xdc:
4743 x86emuOp_esc_coprocess_dc(emu);
4744 break;
4745 case 0xdd:
4746 x86emuOp_esc_coprocess_dd(emu);
4747 break;
4748 case 0xde:
4749 x86emuOp_esc_coprocess_de(emu);
4750 break;
4751 case 0xdf:
4752 x86emuOp_esc_coprocess_df(emu);
4753 break;
4754
4755 case 0xe0:
4756 x86emuOp_loopne(emu);
4757 break;
4758 case 0xe1:
4759 x86emuOp_loope(emu);
4760 break;
4761 case 0xe2:
4762 x86emuOp_loop(emu);
4763 break;
4764 case 0xe3:
4765 x86emuOp_jcxz(emu);
4766 break;
4767 case 0xe4:
4768 x86emuOp_in_byte_AL_IMM(emu);
4769 break;
4770 case 0xe5:
4771 x86emuOp_in_word_AX_IMM(emu);
4772 break;
4773 case 0xe6:
4774 x86emuOp_out_byte_IMM_AL(emu);
4775 break;
4776 case 0xe7:
4777 x86emuOp_out_word_IMM_AX(emu);
4778 break;
4779
4780 case 0xe8:
4781 x86emuOp_call_near_IMM(emu);
4782 break;
4783 case 0xe9:
4784 x86emuOp_jump_near_IMM(emu);
4785 break;
4786 case 0xea:
4787 x86emuOp_jump_far_IMM(emu);
4788 break;
4789 case 0xeb:
4790 x86emuOp_jump_byte_IMM(emu);
4791 break;
4792 case 0xec:
4793 x86emuOp_in_byte_AL_DX(emu);
4794 break;
4795 case 0xed:
4796 x86emuOp_in_word_AX_DX(emu);
4797 break;
4798 case 0xee:
4799 x86emuOp_out_byte_DX_AL(emu);
4800 break;
4801 case 0xef:
4802 x86emuOp_out_word_DX_AX(emu);
4803 break;
4804
4805 case 0xf0:
4806 x86emuOp_lock(emu);
4807 break;
4808 case 0xf2:
4809 emu->x86.mode |= SYSMODE_PREFIX_REPNE;
4810 break;
4811 case 0xf3:
4812 emu->x86.mode |= SYSMODE_PREFIX_REPE;
4813 break;
4814 case 0xf4:
4815 X86EMU_halt_sys(emu);
4816 break;
4817 case 0xf5:
4818 x86emuOp_cmc(emu);
4819 break;
4820 case 0xf6:
4821 x86emuOp_opcF6_byte_RM(emu);
4822 break;
4823 case 0xf7:
4824 x86emuOp_opcF7_word_RM(emu);
4825 break;
4826
4827 case 0xf8:
4828 CLEAR_FLAG(F_CF);
4829 break;
4830 case 0xf9:
4831 SET_FLAG(F_CF);
4832 break;
4833 case 0xfa:
4834 CLEAR_FLAG(F_IF);
4835 break;
4836 case 0xfb:
4837 SET_FLAG(F_IF);
4838 break;
4839 case 0xfc:
4840 CLEAR_FLAG(F_DF);
4841 break;
4842 case 0xfd:
4843 SET_FLAG(F_DF);
4844 break;
4845 case 0xfe:
4846 x86emuOp_opcFE_byte_RM(emu);
4847 break;
4848 case 0xff:
4849 x86emuOp_opcFF_word_RM(emu);
4850 break;
4851 default:
4852 X86EMU_halt_sys(emu);
4853 break;
4854 }
4855 if (op1 != 0x26 && op1 != 0x2e && op1 != 0x36 && op1 != 0x3e &&
4856 (op1 | 3) != 0x67)
4857 emu->x86.mode &= ~SYSMODE_CLRMASK;
4858}
4859
4860static void
4861common_jmp_long(struct X86EMU *emu, bool cond)
4862{
4863 int16_t target;
4864
4865 target = (int16_t) fetch_word_imm(emu);
4866 target += (int16_t) emu->x86.R_IP;
4867 if (cond)
4868 emu->x86.R_IP = (uint16_t) target;
4869}
4870
4871static void
4872common_set_byte(struct X86EMU *emu, bool cond)
4873{
4874 uint32_t destoffset;
4875 uint8_t *destreg, destval;
4876
4877 fetch_decode_modrm(emu);
4878 destval = cond ? 0x01 : 0x00;
4879 if (emu->cur_mod != 3) {
4880 destoffset = decode_rl_address(emu);
4881 store_data_byte(emu, destoffset, destval);
4882 } else {
4883 destreg = decode_rl_byte_register(emu);
4884 *destreg = destval;
4885 }
4886}
4887
4888static void
4889common_bitstring32(struct X86EMU *emu, int op)
4890{
4891 int bit;
4892 uint32_t srcval, *shiftreg, mask;
4893
4894 fetch_decode_modrm(emu);
4895 shiftreg = decode_rh_long_register(emu);
4896 srcval = decode_and_fetch_long_disp(emu, (int16_t) *shiftreg >> 5);
4897 bit = *shiftreg & 0x1F;
4898 mask = 0x1 << bit;
4899 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
4900
4901 switch (op) {
4902 case 0:
4903 break;
4904 case 1:
4905 write_back_long(emu, srcval | mask);
4906 break;
4907 case 2:
4908 write_back_long(emu, srcval & ~mask);
4909 break;
4910 case 3:
4911 write_back_long(emu, srcval ^ mask);
4912 break;
4913 }
4914}
4915
4916static void
4917common_bitstring16(struct X86EMU *emu, int op)
4918{
4919 int bit;
4920 uint16_t srcval, *shiftreg, mask;
4921
4922 fetch_decode_modrm(emu);
4923 shiftreg = decode_rh_word_register(emu);
4924 srcval = decode_and_fetch_word_disp(emu, (int16_t) *shiftreg >> 4);
4925 bit = *shiftreg & 0xF;
4926 mask = 0x1 << bit;
4927 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
4928
4929 switch (op) {
4930 case 0:
4931 break;
4932 case 1:
4933 write_back_word(emu, srcval | mask);
4934 break;
4935 case 2:
4936 write_back_word(emu, srcval & ~mask);
4937 break;
4938 case 3:
4939 write_back_word(emu, srcval ^ mask);
4940 break;
4941 }
4942}
4943
4944static void
4945common_bitstring(struct X86EMU *emu, int op)
4946{
4947 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4948 common_bitstring32(emu, op);
4949 else
4950 common_bitstring16(emu, op);
4951}
4952
4953static void
4954common_bitsearch32(struct X86EMU *emu, int diff)
4955{
4956 uint32_t srcval, *dstreg;
4957
4958 fetch_decode_modrm(emu);
4959 dstreg = decode_rh_long_register(emu);
4960 srcval = decode_and_fetch_long(emu);
4961 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
4962 for (*dstreg = 0; *dstreg < 32; *dstreg += diff) {
4963 if ((srcval >> *dstreg) & 1)
4964 break;
4965 }
4966}
4967
4968static void
4969common_bitsearch16(struct X86EMU *emu, int diff)
4970{
4971 uint16_t srcval, *dstreg;
4972
4973 fetch_decode_modrm(emu);
4974 dstreg = decode_rh_word_register(emu);
4975 srcval = decode_and_fetch_word(emu);
4976 CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
4977 for (*dstreg = 0; *dstreg < 16; *dstreg += diff) {
4978 if ((srcval >> *dstreg) & 1)
4979 break;
4980 }
4981}
4982
4983static void
4984common_bitsearch(struct X86EMU *emu, int diff)
4985{
4986 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4987 common_bitsearch32(emu, diff);
4988 else
4989 common_bitsearch16(emu, diff);
4990}
4991
4992static void
4993common_shift32(struct X86EMU *emu, bool shift_left, bool use_cl)
4994{
4995 uint8_t shift;
4996 uint32_t destval, *shiftreg;
4997
4998 fetch_decode_modrm(emu);
4999 shiftreg = decode_rh_long_register(emu);
5000 if (use_cl) {
5001 destval = decode_and_fetch_long(emu);
5002 shift = emu->x86.R_CL;
5003 } else {
5004 destval = decode_and_fetch_long_imm8(emu, &shift);
5005 }
5006 if (shift_left)
5007 destval = shld_long(emu, destval, *shiftreg, shift);
5008 else
5009 destval = shrd_long(emu, destval, *shiftreg, shift);
5010 write_back_long(emu, destval);
5011}
5012
5013static void
5014common_shift16(struct X86EMU *emu, bool shift_left, bool use_cl)
5015{
5016 uint8_t shift;
5017 uint16_t destval, *shiftreg;
5018
5019 fetch_decode_modrm(emu);
5020 shiftreg = decode_rh_word_register(emu);
5021 if (use_cl) {
5022 destval = decode_and_fetch_word(emu);
5023 shift = emu->x86.R_CL;
5024 } else {
5025 destval = decode_and_fetch_word_imm8(emu, &shift);
5026 }
5027 if (shift_left)
5028 destval = shld_word(emu, destval, *shiftreg, shift);
5029 else
5030 destval = shrd_word(emu, destval, *shiftreg, shift);
5031 write_back_word(emu, destval);
5032}
5033
5034static void
5035common_shift(struct X86EMU *emu, bool shift_left, bool use_cl)
5036{
5037 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5038 common_shift32(emu, shift_left, use_cl);
5039 else
5040 common_shift16(emu, shift_left, use_cl);
5041}
5042
5043/*----------------------------- Implementation ----------------------------*/
5044#define xorl(a,b) ((a) && !(b)) || (!(a) && (b))
5045
5046/****************************************************************************
5047REMARKS:
5048Handles opcode 0x0f,0x31
5049****************************************************************************/
5050static void
5051x86emuOp2_rdtsc(struct X86EMU *emu)
5052{
5053 emu->x86.R_EAX = emu->cur_cycles & 0xffffffff;
5054 emu->x86.R_EDX = emu->cur_cycles >> 32;
5055}
5056/****************************************************************************
5057REMARKS:
5058Handles opcode 0x0f,0xa0
5059****************************************************************************/
5060static void
5061x86emuOp2_push_FS(struct X86EMU *emu)
5062{
5063 push_word(emu, emu->x86.R_FS);
5064}
5065/****************************************************************************
5066REMARKS:
5067Handles opcode 0x0f,0xa1
5068****************************************************************************/
5069static void
5070x86emuOp2_pop_FS(struct X86EMU *emu)
5071{
5072 emu->x86.R_FS = pop_word(emu);
5073}
5074/****************************************************************************
5075REMARKS:
5076Handles opcode 0x0f,0xa1
5077****************************************************************************/
5078#if defined(__i386__) || defined(__amd64__)
5079static void
5080hw_cpuid(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
5081{
5082 __asm__ __volatile__("cpuid"
5083 : "=a" (*a), "=b" (*b),
5084 "=c" (*c), "=d" (*d)
5085 : "a" (*a), "c" (*c)
5086 : "cc");
5087}
5088#endif
5089static void
5090x86emuOp2_cpuid(struct X86EMU *emu)
5091{
5092#if defined(__i386__) || defined(__amd64__)
5093 hw_cpuid(&emu->x86.R_EAX, &emu->x86.R_EBX, &emu->x86.R_ECX,
5094 &emu->x86.R_EDX);
5095#endif
5096 switch (emu->x86.R_EAX) {
5097 case 0:
5098 emu->x86.R_EAX = 1;
5099#if !defined(__i386__) && !defined(__amd64__)
5100 /* "GenuineIntel" */
5101 emu->x86.R_EBX = 0x756e6547;
5102 emu->x86.R_EDX = 0x49656e69;
5103 emu->x86.R_ECX = 0x6c65746e;
5104#endif
5105 break;
5106 case 1:
5107#if !defined(__i386__) && !defined(__amd64__)
5108 emu->x86.R_EAX = 0x00000480;
5109 emu->x86.R_EBX = emu->x86.R_ECX = 0;
5110 emu->x86.R_EDX = 0x00000002;
5111#else
5112 emu->x86.R_EDX &= 0x00000012;
5113#endif
5114 break;
5115 default:
5116 emu->x86.R_EAX = emu->x86.R_EBX = emu->x86.R_ECX =
5117 emu->x86.R_EDX = 0;
5118 break;
5119 }
5120}
5121/****************************************************************************
5122REMARKS:
5123Handles opcode 0x0f,0xa3
5124****************************************************************************/
5125static void
5126x86emuOp2_bt_R(struct X86EMU *emu)
5127{
5128 common_bitstring(emu, 0);
5129}
5130/****************************************************************************
5131REMARKS:
5132Handles opcode 0x0f,0xa4
5133****************************************************************************/
5134static void
5135x86emuOp2_shld_IMM(struct X86EMU *emu)
5136{
5137 common_shift(emu, true, false);
5138}
5139/****************************************************************************
5140REMARKS:
5141Handles opcode 0x0f,0xa5
5142****************************************************************************/
5143static void
5144x86emuOp2_shld_CL(struct X86EMU *emu)
5145{
5146 common_shift(emu, true, true);
5147}
5148/****************************************************************************
5149REMARKS:
5150Handles opcode 0x0f,0xa8
5151****************************************************************************/
5152static void
5153x86emuOp2_push_GS(struct X86EMU *emu)
5154{
5155 push_word(emu, emu->x86.R_GS);
5156}
5157/****************************************************************************
5158REMARKS:
5159Handles opcode 0x0f,0xa9
5160****************************************************************************/
5161static void
5162x86emuOp2_pop_GS(struct X86EMU *emu)
5163{
5164 emu->x86.R_GS = pop_word(emu);
5165}
5166/****************************************************************************
5167REMARKS:
5168Handles opcode 0x0f,0xab
5169****************************************************************************/
5170static void
5171x86emuOp2_bts_R(struct X86EMU *emu)
5172{
5173 common_bitstring(emu, 1);
5174}
5175/****************************************************************************
5176REMARKS:
5177Handles opcode 0x0f,0xac
5178****************************************************************************/
5179static void
5180x86emuOp2_shrd_IMM(struct X86EMU *emu)
5181{
5182 common_shift(emu, false, false);
5183}
5184/****************************************************************************
5185REMARKS:
5186Handles opcode 0x0f,0xad
5187****************************************************************************/
5188static void
5189x86emuOp2_shrd_CL(struct X86EMU *emu)
5190{
5191 common_shift(emu, false, true);
5192}
5193/****************************************************************************
5194REMARKS:
5195Handles opcode 0x0f,0xaf
5196****************************************************************************/
5197static void
5198x86emuOp2_32_imul_R_RM(struct X86EMU *emu)
5199{
5200 uint32_t *destreg, srcval;
5201 uint64_t res;
5202
5203 fetch_decode_modrm(emu);
5204 destreg = decode_rh_long_register(emu);
5205 srcval = decode_and_fetch_long(emu);
5206 res = (int32_t) *destreg * (int32_t)srcval;
5207 if (res > 0xffffffff) {
5208 SET_FLAG(F_CF);
5209 SET_FLAG(F_OF);
5210 } else {
5211 CLEAR_FLAG(F_CF);
5212 CLEAR_FLAG(F_OF);
5213 }
5214 *destreg = (uint32_t) res;
5215}
5216
5217static void
5218x86emuOp2_16_imul_R_RM(struct X86EMU *emu)
5219{
5220 uint16_t *destreg, srcval;
5221 uint32_t res;
5222
5223 fetch_decode_modrm(emu);
5224 destreg = decode_rh_word_register(emu);
5225 srcval = decode_and_fetch_word(emu);
5226 res = (int16_t) * destreg * (int16_t)srcval;
5227 if (res > 0xFFFF) {
5228 SET_FLAG(F_CF);
5229 SET_FLAG(F_OF);
5230 } else {
5231 CLEAR_FLAG(F_CF);
5232 CLEAR_FLAG(F_OF);
5233 }
5234 *destreg = (uint16_t) res;
5235}
5236
5237static void
5238x86emuOp2_imul_R_RM(struct X86EMU *emu)
5239{
5240 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5241 x86emuOp2_32_imul_R_RM(emu);
5242 else
5243 x86emuOp2_16_imul_R_RM(emu);
5244}
5245/****************************************************************************
5246REMARKS:
5247Handles opcode 0x0f,0xb2
5248****************************************************************************/
5249static void
5250x86emuOp2_lss_R_IMM(struct X86EMU *emu)
5251{
5252 common_load_far_pointer(emu, &emu->x86.R_SS);
5253}
5254/****************************************************************************
5255REMARKS:
5256Handles opcode 0x0f,0xb3
5257****************************************************************************/
5258static void
5259x86emuOp2_btr_R(struct X86EMU *emu)
5260{
5261 common_bitstring(emu, 2);
5262}
5263/****************************************************************************
5264REMARKS:
5265Handles opcode 0x0f,0xb4
5266****************************************************************************/
5267static void
5268x86emuOp2_lfs_R_IMM(struct X86EMU *emu)
5269{
5270 common_load_far_pointer(emu, &emu->x86.R_FS);
5271}
5272/****************************************************************************
5273REMARKS:
5274Handles opcode 0x0f,0xb5
5275****************************************************************************/
5276static void
5277x86emuOp2_lgs_R_IMM(struct X86EMU *emu)
5278{
5279 common_load_far_pointer(emu, &emu->x86.R_GS);
5280}
5281/****************************************************************************
5282REMARKS:
5283Handles opcode 0x0f,0xb6
5284****************************************************************************/
5285static void
5286x86emuOp2_32_movzx_byte_R_RM(struct X86EMU *emu)
5287{
5288 uint32_t *destreg;
5289
5290 fetch_decode_modrm(emu);
5291 destreg = decode_rh_long_register(emu);
5292 *destreg = decode_and_fetch_byte(emu);
5293}
5294
5295static void
5296x86emuOp2_16_movzx_byte_R_RM(struct X86EMU *emu)
5297{
5298 uint16_t *destreg;
5299
5300 fetch_decode_modrm(emu);
5301 destreg = decode_rh_word_register(emu);
5302 *destreg = decode_and_fetch_byte(emu);
5303}
5304
5305static void
5306x86emuOp2_movzx_byte_R_RM(struct X86EMU *emu)
5307{
5308 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5309 x86emuOp2_32_movzx_byte_R_RM(emu);
5310 else
5311 x86emuOp2_16_movzx_byte_R_RM(emu);
5312}
5313/****************************************************************************
5314REMARKS:
5315Handles opcode 0x0f,0xb7
5316****************************************************************************/
5317static void
5318x86emuOp2_movzx_word_R_RM(struct X86EMU *emu)
5319{
5320 uint32_t *destreg;
5321
5322 fetch_decode_modrm(emu);
5323 destreg = decode_rh_long_register(emu);
5324 *destreg = decode_and_fetch_word(emu);
5325}
5326/****************************************************************************
5327REMARKS:
5328Handles opcode 0x0f,0xba
5329****************************************************************************/
5330static void
5331x86emuOp2_32_btX_I(struct X86EMU *emu)
5332{
5333 int bit;
5334 uint32_t srcval, mask;
5335 uint8_t shift;
5336
5337 fetch_decode_modrm(emu);
5338 if (emu->cur_rh < 4)
5339 X86EMU_halt_sys(emu);
5340
5341 srcval = decode_and_fetch_long_imm8(emu, &shift);
5342 bit = shift & 0x1F;
5343 mask = (0x1 << bit);
5344
5345 switch (emu->cur_rh) {
5346 case 5:
5347 write_back_long(emu, srcval | mask);
5348 break;
5349 case 6:
5350 write_back_long(emu, srcval & ~mask);
5351 break;
5352 case 7:
5353 write_back_long(emu, srcval ^ mask);
5354 break;
5355 }
5356 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5357}
5358
5359static void
5360x86emuOp2_16_btX_I(struct X86EMU *emu)
5361{
5362 int bit;
5363
5364 uint16_t srcval, mask;
5365 uint8_t shift;
5366
5367 fetch_decode_modrm(emu);
5368 if (emu->cur_rh < 4)
5369 X86EMU_halt_sys(emu);
5370
5371 srcval = decode_and_fetch_word_imm8(emu, &shift);
5372 bit = shift & 0xF;
5373 mask = (0x1 << bit);
5374 switch (emu->cur_rh) {
5375 case 5:
5376 write_back_word(emu, srcval | mask);
5377 break;
5378 case 6:
5379 write_back_word(emu, srcval & ~mask);
5380 break;
5381 case 7:
5382 write_back_word(emu, srcval ^ mask);
5383 break;
5384 }
5385 CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5386}
5387
5388static void
5389x86emuOp2_btX_I(struct X86EMU *emu)
5390{
5391 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5392 x86emuOp2_32_btX_I(emu);
5393 else
5394 x86emuOp2_16_btX_I(emu);
5395}
5396/****************************************************************************
5397REMARKS:
5398Handles opcode 0x0f,0xbb
5399****************************************************************************/
5400static void
5401x86emuOp2_btc_R(struct X86EMU *emu)
5402{
5403 common_bitstring(emu, 3);
5404}
5405/****************************************************************************
5406REMARKS:
5407Handles opcode 0x0f,0xbc
5408****************************************************************************/
5409static void
5410x86emuOp2_bsf(struct X86EMU *emu)
5411{
5412 common_bitsearch(emu, +1);
5413}
5414/****************************************************************************
5415REMARKS:
5416Handles opcode 0x0f,0xbd
5417****************************************************************************/
5418static void
5419x86emuOp2_bsr(struct X86EMU *emu)
5420{
5421 common_bitsearch(emu, -1);
5422}
5423/****************************************************************************
5424REMARKS:
5425Handles opcode 0x0f,0xbe
5426****************************************************************************/
5427static void
5428x86emuOp2_32_movsx_byte_R_RM(struct X86EMU *emu)
5429{
5430 uint32_t *destreg;
5431
5432 fetch_decode_modrm(emu);
5433 destreg = decode_rh_long_register(emu);
5434 *destreg = (int32_t)(int8_t)decode_and_fetch_byte(emu);
5435}
5436
5437static void
5438x86emuOp2_16_movsx_byte_R_RM(struct X86EMU *emu)
5439{
5440 uint16_t *destreg;
5441
5442 fetch_decode_modrm(emu);
5443 destreg = decode_rh_word_register(emu);
5444 *destreg = (int16_t)(int8_t)decode_and_fetch_byte(emu);
5445}
5446
5447static void
5448x86emuOp2_movsx_byte_R_RM(struct X86EMU *emu)
5449{
5450 if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5451 x86emuOp2_32_movsx_byte_R_RM(emu);
5452 else
5453 x86emuOp2_16_movsx_byte_R_RM(emu);
5454}
5455/****************************************************************************
5456REMARKS:
5457Handles opcode 0x0f,0xbf
5458****************************************************************************/
5459static void
5460x86emuOp2_movsx_word_R_RM(struct X86EMU *emu)
5461{
5462 uint32_t *destreg;
5463
5464 fetch_decode_modrm(emu);
5465 destreg = decode_rh_long_register(emu);
5466 *destreg = (int32_t)(int16_t)decode_and_fetch_word(emu);
5467}
5468
5469static void
5470X86EMU_exec_two_byte(struct X86EMU * emu)
5471{
5472 uint8_t op2;
5473
5474 op2 = fetch_byte_imm(emu);
5475
5476 switch (op2) {
5477 /* 0x00 Group F (ring 0 PM) */
5478 /* 0x01 Group G (ring 0 PM) */
5479 /* 0x02 lar (ring 0 PM) */
5480 /* 0x03 lsl (ring 0 PM) */
5481 /* 0x05 loadall (undocumented) */
5482 /* 0x06 clts (ring 0 PM) */
5483 /* 0x07 loadall (undocumented) */
5484 /* 0x08 invd (ring 0 PM) */
5485 /* 0x09 wbinvd (ring 0 PM) */
5486
5487 /* 0x20 mov reg32(op2); break;creg (ring 0 PM) */
5488 /* 0x21 mov reg32(op2); break;dreg (ring 0 PM) */
5489 /* 0x22 mov creg(op2); break;reg32 (ring 0 PM) */
5490 /* 0x23 mov dreg(op2); break;reg32 (ring 0 PM) */
5491 /* 0x24 mov reg32(op2); break;treg (ring 0 PM) */
5492 /* 0x26 mov treg(op2); break;reg32 (ring 0 PM) */
5493
5494 case 0x31:
5495 x86emuOp2_rdtsc(emu);
5496 break;
5497
5498 case 0x80:
5499 common_jmp_long(emu, ACCESS_FLAG(F_OF));
5500 break;
5501 case 0x81:
5502 common_jmp_long(emu, !ACCESS_FLAG(F_OF));
5503 break;
5504 case 0x82:
5505 common_jmp_long(emu, ACCESS_FLAG(F_CF));
5506 break;
5507 case 0x83:
5508 common_jmp_long(emu, !ACCESS_FLAG(F_CF));
5509 break;
5510 case 0x84:
5511 common_jmp_long(emu, ACCESS_FLAG(F_ZF));
5512 break;
5513 case 0x85:
5514 common_jmp_long(emu, !ACCESS_FLAG(F_ZF));
5515 break;
5516 case 0x86:
5517 common_jmp_long(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5518 break;
5519 case 0x87:
5520 common_jmp_long(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5521 break;
5522 case 0x88:
5523 common_jmp_long(emu, ACCESS_FLAG(F_SF));
5524 break;
5525 case 0x89:
5526 common_jmp_long(emu, !ACCESS_FLAG(F_SF));
5527 break;
5528 case 0x8a:
5529 common_jmp_long(emu, ACCESS_FLAG(F_PF));
5530 break;
5531 case 0x8b:
5532 common_jmp_long(emu, !ACCESS_FLAG(F_PF));
5533 break;
5534 case 0x8c:
5535 common_jmp_long(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)));
5536 break;
5537 case 0x8d:
5538 common_jmp_long(emu, !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))));
5539 break;
5540 case 0x8e:
5541 common_jmp_long(emu,
5542 (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF)));
5543 break;
5544 case 0x8f:
5545 common_jmp_long(emu,
5546 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF)));
5547 break;
5548
5549 case 0x90:
5550 common_set_byte(emu, ACCESS_FLAG(F_OF));
5551 break;
5552 case 0x91:
5553 common_set_byte(emu, !ACCESS_FLAG(F_OF));
5554 break;
5555 case 0x92:
5556 common_set_byte(emu, ACCESS_FLAG(F_CF));
5557 break;
5558 case 0x93:
5559 common_set_byte(emu, !ACCESS_FLAG(F_CF));
5560 break;
5561 case 0x94:
5562 common_set_byte(emu, ACCESS_FLAG(F_ZF));
5563 break;
5564 case 0x95:
5565 common_set_byte(emu, !ACCESS_FLAG(F_ZF));
5566 break;
5567 case 0x96:
5568 common_set_byte(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5569 break;
5570 case 0x97:
5571 common_set_byte(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5572 break;
5573 case 0x98:
5574 common_set_byte(emu, ACCESS_FLAG(F_SF));
5575 break;
5576 case 0x99:
5577 common_set_byte(emu, !ACCESS_FLAG(F_SF));
5578 break;
5579 case 0x9a:
5580 common_set_byte(emu, ACCESS_FLAG(F_PF));
5581 break;
5582 case 0x9b:
5583 common_set_byte(emu, !ACCESS_FLAG(F_PF));
5584 break;
5585 case 0x9c:
5586 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)));
5587 break;
5588 case 0x9d:
5589 common_set_byte(emu, xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)));
5590 break;
5591 case 0x9e:
5592 common_set_byte(emu,
5593 (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5594 ACCESS_FLAG(F_ZF)));
5595 break;
5596 case 0x9f:
5597 common_set_byte(emu,
5598 !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5599 ACCESS_FLAG(F_ZF)));
5600 break;
5601
5602 case 0xa0:
5603 x86emuOp2_push_FS(emu);
5604 break;
5605 case 0xa1:
5606 x86emuOp2_pop_FS(emu);
5607 break;
5608 case 0xa2:
5609 x86emuOp2_cpuid(emu);
5610 break;
5611 case 0xa3:
5612 x86emuOp2_bt_R(emu);
5613 break;
5614 case 0xa4:
5615 x86emuOp2_shld_IMM(emu);
5616 break;
5617 case 0xa5:
5618 x86emuOp2_shld_CL(emu);
5619 break;
5620 case 0xa8:
5621 x86emuOp2_push_GS(emu);
5622 break;
5623 case 0xa9:
5624 x86emuOp2_pop_GS(emu);
5625 break;
5626 case 0xab:
5627 x86emuOp2_bts_R(emu);
5628 break;
5629 case 0xac:
5630 x86emuOp2_shrd_IMM(emu);
5631 break;
5632 case 0xad:
5633 x86emuOp2_shrd_CL(emu);
5634 break;
5635 case 0xaf:
5636 x86emuOp2_imul_R_RM(emu);
5637 break;
5638
5639 /* 0xb0 TODO: cmpxchg */
5640 /* 0xb1 TODO: cmpxchg */
5641 case 0xb2:
5642 x86emuOp2_lss_R_IMM(emu);
5643 break;
5644 case 0xb3:
5645 x86emuOp2_btr_R(emu);
5646 break;
5647 case 0xb4:
5648 x86emuOp2_lfs_R_IMM(emu);
5649 break;
5650 case 0xb5:
5651 x86emuOp2_lgs_R_IMM(emu);
5652 break;
5653 case 0xb6:
5654 x86emuOp2_movzx_byte_R_RM(emu);
5655 break;
5656 case 0xb7:
5657 x86emuOp2_movzx_word_R_RM(emu);
5658 break;
5659 case 0xba:
5660 x86emuOp2_btX_I(emu);
5661 break;
5662 case 0xbb:
5663 x86emuOp2_btc_R(emu);
5664 break;
5665 case 0xbc:
5666 x86emuOp2_bsf(emu);
5667 break;
5668 case 0xbd:
5669 x86emuOp2_bsr(emu);
5670 break;
5671 case 0xbe:
5672 x86emuOp2_movsx_byte_R_RM(emu);
5673 break;
5674 case 0xbf:
5675 x86emuOp2_movsx_word_R_RM(emu);
5676 break;
5677
5678 /* 0xc0 TODO: xadd */
5679 /* 0xc1 TODO: xadd */
5680 /* 0xc8 TODO: bswap */
5681 /* 0xc9 TODO: bswap */
5682 /* 0xca TODO: bswap */
5683 /* 0xcb TODO: bswap */
5684 /* 0xcc TODO: bswap */
5685 /* 0xcd TODO: bswap */
5686 /* 0xce TODO: bswap */
5687 /* 0xcf TODO: bswap */
5688
5689 default:
5690 X86EMU_halt_sys(emu);
5691 break;
5692 }
5693}
5694
5695/*
5696* Carry Chain Calculation
5697*
5698* This represents a somewhat expensive calculation which is
5699* apparently required to emulate the setting of the OF and AF flag.
5700* The latter is not so important, but the former is. The overflow
5701* flag is the XOR of the top two bits of the carry chain for an
5702* addition (similar for subtraction). Since we do not want to
5703* simulate the addition in a bitwise manner, we try to calculate the
5704* carry chain given the two operands and the result.
5705*
5706* So, given the following table, which represents the addition of two
5707* bits, we can derive a formula for the carry chain.
5708*
5709* a b cin r cout
5710* 0 0 0 0 0
5711* 0 0 1 1 0
5712* 0 1 0 1 0
5713* 0 1 1 0 1
5714* 1 0 0 1 0
5715* 1 0 1 0 1
5716* 1 1 0 0 1
5717* 1 1 1 1 1
5718*
5719* Construction of table for cout:
5720*
5721* ab
5722* r \ 00 01 11 10
5723* |------------------
5724* 0 | 0 1 1 1
5725* 1 | 0 0 1 0
5726*
5727* By inspection, one gets: cc = ab + r'(a + b)
5728*
5729* That represents alot of operations, but NO CHOICE....
5730*
5731* Borrow Chain Calculation.
5732*
5733* The following table represents the subtraction of two bits, from
5734* which we can derive a formula for the borrow chain.
5735*
5736* a b bin r bout
5737* 0 0 0 0 0
5738* 0 0 1 1 1
5739* 0 1 0 1 1
5740* 0 1 1 0 1
5741* 1 0 0 1 0
5742* 1 0 1 0 0
5743* 1 1 0 0 0
5744* 1 1 1 1 1
5745*
5746* Construction of table for cout:
5747*
5748* ab
5749* r \ 00 01 11 10
5750* |------------------
5751* 0 | 0 1 0 0
5752* 1 | 1 1 1 0
5753*
5754* By inspection, one gets: bc = a'b + r(a' + b)
5755*
5756****************************************************************************/
5757
5758/*------------------------- Global Variables ------------------------------*/
5759
5760static uint32_t x86emu_parity_tab[8] =
5761{
5762 0x96696996,
5763 0x69969669,
5764 0x69969669,
5765 0x96696996,
5766 0x69969669,
5767 0x96696996,
5768 0x96696996,
5769 0x69969669,
5770};
5771#define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
5772#define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
5773
5774/****************************************************************************
5775REMARKS:
5776Implements the AAA instruction and side effects.
5777****************************************************************************/
5778static uint16_t
5779aaa_word(struct X86EMU *emu, uint16_t d)
5780{
5781 uint16_t res;
5782 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
5783 d += 0x6;
5784 d += 0x100;
5785 SET_FLAG(F_AF);
5786 SET_FLAG(F_CF);
5787 } else {
5788 CLEAR_FLAG(F_CF);
5789 CLEAR_FLAG(F_AF);
5790 }
5791 res = (uint16_t) (d & 0xFF0F);
5792 CLEAR_FLAG(F_SF);
5793 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
5794 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5795 return res;
5796}
5797/****************************************************************************
5798REMARKS:
5799Implements the AAA instruction and side effects.
5800****************************************************************************/
5801static uint16_t
5802aas_word(struct X86EMU *emu, uint16_t d)
5803{
5804 uint16_t res;
5805 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
5806 d -= 0x6;
5807 d -= 0x100;
5808 SET_FLAG(F_AF);
5809 SET_FLAG(F_CF);
5810 } else {
5811 CLEAR_FLAG(F_CF);
5812 CLEAR_FLAG(F_AF);
5813 }
5814 res = (uint16_t) (d & 0xFF0F);
5815 CLEAR_FLAG(F_SF);
5816 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
5817 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5818 return res;
5819}
5820/****************************************************************************
5821REMARKS:
5822Implements the AAD instruction and side effects.
5823****************************************************************************/
5824static uint16_t
5825aad_word(struct X86EMU *emu, uint16_t d)
5826{
5827 uint16_t l;
5828 uint8_t hb, lb;
5829
5830 hb = (uint8_t) ((d >> 8) & 0xff);
5831 lb = (uint8_t) ((d & 0xff));
5832 l = (uint16_t) ((lb + 10 * hb) & 0xFF);
5833
5834 CLEAR_FLAG(F_CF);
5835 CLEAR_FLAG(F_AF);
5836 CLEAR_FLAG(F_OF);
5837 CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
5838 CONDITIONAL_SET_FLAG(l == 0, F_ZF);
5839 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
5840 return l;
5841}
5842/****************************************************************************
5843REMARKS:
5844Implements the AAM instruction and side effects.
5845****************************************************************************/
5846static uint16_t
5847aam_word(struct X86EMU *emu, uint8_t d)
5848{
5849 uint16_t h, l;
5850
5851 h = (uint16_t) (d / 10);
5852 l = (uint16_t) (d % 10);
5853 l |= (uint16_t) (h << 8);
5854
5855 CLEAR_FLAG(F_CF);
5856 CLEAR_FLAG(F_AF);
5857 CLEAR_FLAG(F_OF);
5858 CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
5859 CONDITIONAL_SET_FLAG(l == 0, F_ZF);
5860 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
5861 return l;
5862}
5863/****************************************************************************
5864REMARKS:
5865Implements the ADC instruction and side effects.
5866****************************************************************************/
5867static uint8_t
5868adc_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
5869{
5870 uint32_t res; /* all operands in native machine order */
5871 uint32_t cc;
5872
5873 if (ACCESS_FLAG(F_CF))
5874 res = 1 + d + s;
5875 else
5876 res = d + s;
5877
5878 CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
5879 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
5880 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
5881 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5882
5883 /* calculate the carry chain SEE NOTE AT TOP. */
5884 cc = (s & d) | ((~res) & (s | d));
5885 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
5886 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
5887 return (uint8_t) res;
5888}
5889/****************************************************************************
5890REMARKS:
5891Implements the ADC instruction and side effects.
5892****************************************************************************/
5893static uint16_t
5894adc_word(struct X86EMU *emu, uint16_t d, uint16_t s)
5895{
5896 uint32_t res; /* all operands in native machine order */
5897 uint32_t cc;
5898
5899 if (ACCESS_FLAG(F_CF))
5900 res = 1 + d + s;
5901 else
5902 res = d + s;
5903
5904 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
5905 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
5906 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
5907 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5908
5909 /* calculate the carry chain SEE NOTE AT TOP. */
5910 cc = (s & d) | ((~res) & (s | d));
5911 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
5912 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
5913 return (uint16_t) res;
5914}
5915/****************************************************************************
5916REMARKS:
5917Implements the ADC instruction and side effects.
5918****************************************************************************/
5919static uint32_t
5920adc_long(struct X86EMU *emu, uint32_t d, uint32_t s)
5921{
5922 uint32_t lo; /* all operands in native machine order */
5923 uint32_t hi;
5924 uint32_t res;
5925 uint32_t cc;
5926
5927 if (ACCESS_FLAG(F_CF)) {
5928 lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
5929 res = 1 + d + s;
5930 } else {
5931 lo = (d & 0xFFFF) + (s & 0xFFFF);
5932 res = d + s;
5933 }
5934 hi = (lo >> 16) + (d >> 16) + (s >> 16);
5935
5936 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
5937 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
5938 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
5939 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5940
5941 /* calculate the carry chain SEE NOTE AT TOP. */
5942 cc = (s & d) | ((~res) & (s | d));
5943 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
5944 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
5945 return res;
5946}
5947/****************************************************************************
5948REMARKS:
5949Implements the ADD instruction and side effects.
5950****************************************************************************/
5951static uint8_t
5952add_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
5953{
5954 uint32_t res; /* all operands in native machine order */
5955 uint32_t cc;
5956
5957 res = d + s;
5958 CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
5959 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
5960 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
5961 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5962
5963 /* calculate the carry chain SEE NOTE AT TOP. */
5964 cc = (s & d) | ((~res) & (s | d));
5965 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
5966 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
5967 return (uint8_t) res;
5968}
5969/****************************************************************************
5970REMARKS:
5971Implements the ADD instruction and side effects.
5972****************************************************************************/
5973static uint16_t
5974add_word(struct X86EMU *emu, uint16_t d, uint16_t s)
5975{
5976 uint32_t res; /* all operands in native machine order */
5977 uint32_t cc;
5978
5979 res = d + s;
5980 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
5981 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
5982 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
5983 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
5984
5985 /* calculate the carry chain SEE NOTE AT TOP. */
5986 cc = (s & d) | ((~res) & (s | d));
5987 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
5988 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
5989 return (uint16_t) res;
5990}
5991/****************************************************************************
5992REMARKS:
5993Implements the ADD instruction and side effects.
5994****************************************************************************/
5995static uint32_t
5996add_long(struct X86EMU *emu, uint32_t d, uint32_t s)
5997{
5998 uint32_t lo; /* all operands in native machine order */
5999 uint32_t hi;
6000 uint32_t res;
6001 uint32_t cc;
6002
6003 lo = (d & 0xFFFF) + (s & 0xFFFF);
6004 res = d + s;
6005 hi = (lo >> 16) + (d >> 16) + (s >> 16);
6006
6007 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
6008 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6009 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6010 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6011
6012 /* calculate the carry chain SEE NOTE AT TOP. */
6013 cc = (s & d) | ((~res) & (s | d));
6014 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6015 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6016
6017 return res;
6018}
6019/****************************************************************************
6020REMARKS:
6021Implements the AND instruction and side effects.
6022****************************************************************************/
6023static uint8_t
6024and_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6025{
6026 uint8_t res; /* all operands in native machine order */
6027
6028 res = d & s;
6029
6030 /* set the flags */
6031 CLEAR_FLAG(F_OF);
6032 CLEAR_FLAG(F_CF);
6033 CLEAR_FLAG(F_AF);
6034 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6035 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6036 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6037 return res;
6038}
6039/****************************************************************************
6040REMARKS:
6041Implements the AND instruction and side effects.
6042****************************************************************************/
6043static uint16_t
6044and_word(struct X86EMU *emu, uint16_t d, uint16_t s)
6045{
6046 uint16_t res; /* all operands in native machine order */
6047
6048 res = d & s;
6049
6050 /* set the flags */
6051 CLEAR_FLAG(F_OF);
6052 CLEAR_FLAG(F_CF);
6053 CLEAR_FLAG(F_AF);
6054 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6055 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6056 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6057 return res;
6058}
6059/****************************************************************************
6060REMARKS:
6061Implements the AND instruction and side effects.
6062****************************************************************************/
6063static uint32_t
6064and_long(struct X86EMU *emu, uint32_t d, uint32_t s)
6065{
6066 uint32_t res; /* all operands in native machine order */
6067
6068 res = d & s;
6069
6070 /* set the flags */
6071 CLEAR_FLAG(F_OF);
6072 CLEAR_FLAG(F_CF);
6073 CLEAR_FLAG(F_AF);
6074 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6075 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6076 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6077 return res;
6078}
6079/****************************************************************************
6080REMARKS:
6081Implements the CMP instruction and side effects.
6082****************************************************************************/
6083static uint8_t
6084cmp_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6085{
6086 uint32_t res; /* all operands in native machine order */
6087 uint32_t bc;
6088
6089 res = d - s;
6090 CLEAR_FLAG(F_CF);
6091 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6092 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6093 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6094
6095 /* calculate the borrow chain. See note at top */
6096 bc = (res & (~d | s)) | (~d & s);
6097 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
6098 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6099 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6100 return d;
6101}
6102
6103static void
6104cmp_byte_no_return(struct X86EMU *emu, uint8_t d, uint8_t s)
6105{
6106 cmp_byte(emu, d, s);
6107}
6108/****************************************************************************
6109REMARKS:
6110Implements the CMP instruction and side effects.
6111****************************************************************************/
6112static uint16_t
6113cmp_word(struct X86EMU *emu, uint16_t d, uint16_t s)
6114{
6115 uint32_t res; /* all operands in native machine order */
6116 uint32_t bc;
6117
6118 res = d - s;
6119 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6120 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6121 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6122
6123 /* calculate the borrow chain. See note at top */
6124 bc = (res & (~d | s)) | (~d & s);
6125 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
6126 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6127 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6128 return d;
6129}
6130
6131static void
6132cmp_word_no_return(struct X86EMU *emu, uint16_t d, uint16_t s)
6133{
6134 cmp_word(emu, d, s);
6135}
6136/****************************************************************************
6137REMARKS:
6138Implements the CMP instruction and side effects.
6139****************************************************************************/
6140static uint32_t
6141cmp_long(struct X86EMU *emu, uint32_t d, uint32_t s)
6142{
6143 uint32_t res; /* all operands in native machine order */
6144 uint32_t bc;
6145
6146 res = d - s;
6147 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6148 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6149 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6150
6151 /* calculate the borrow chain. See note at top */
6152 bc = (res & (~d | s)) | (~d & s);
6153 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
6154 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6155 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6156 return d;
6157}
6158
6159static void
6160cmp_long_no_return(struct X86EMU *emu, uint32_t d, uint32_t s)
6161{
6162 cmp_long(emu, d, s);
6163}
6164/****************************************************************************
6165REMARKS:
6166Implements the DAA instruction and side effects.
6167****************************************************************************/
6168static uint8_t
6169daa_byte(struct X86EMU *emu, uint8_t d)
6170{
6171 uint32_t res = d;
6172 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6173 res += 6;
6174 SET_FLAG(F_AF);
6175 }
6176 if (res > 0x9F || ACCESS_FLAG(F_CF)) {
6177 res += 0x60;
6178 SET_FLAG(F_CF);
6179 }
6180 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6181 CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
6182 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6183 return (uint8_t) res;
6184}
6185/****************************************************************************
6186REMARKS:
6187Implements the DAS instruction and side effects.
6188****************************************************************************/
6189static uint8_t
6190das_byte(struct X86EMU *emu, uint8_t d)
6191{
6192 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6193 d -= 6;
6194 SET_FLAG(F_AF);
6195 }
6196 if (d > 0x9F || ACCESS_FLAG(F_CF)) {
6197 d -= 0x60;
6198 SET_FLAG(F_CF);
6199 }
6200 CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
6201 CONDITIONAL_SET_FLAG(d == 0, F_ZF);
6202 CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
6203 return d;
6204}
6205/****************************************************************************
6206REMARKS:
6207Implements the DEC instruction and side effects.
6208****************************************************************************/
6209static uint8_t
6210dec_byte(struct X86EMU *emu, uint8_t d)
6211{
6212 uint32_t res; /* all operands in native machine order */
6213 uint32_t bc;
6214
6215 res = d - 1;
6216 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6217 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6218 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6219
6220 /* calculate the borrow chain. See note at top */
6221 /* based on sub_byte, uses s==1. */
6222 bc = (res & (~d | 1)) | (~d & 1);
6223 /* carry flag unchanged */
6224 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6225 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6226 return (uint8_t) res;
6227}
6228/****************************************************************************
6229REMARKS:
6230Implements the DEC instruction and side effects.
6231****************************************************************************/
6232static uint16_t
6233dec_word(struct X86EMU *emu, uint16_t d)
6234{
6235 uint32_t res; /* all operands in native machine order */
6236 uint32_t bc;
6237
6238 res = d - 1;
6239 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6240 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6241 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6242
6243 /* calculate the borrow chain. See note at top */
6244 /* based on the sub_byte routine, with s==1 */
6245 bc = (res & (~d | 1)) | (~d & 1);
6246 /* carry flag unchanged */
6247 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6248 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6249 return (uint16_t) res;
6250}
6251/****************************************************************************
6252REMARKS:
6253Implements the DEC instruction and side effects.
6254****************************************************************************/
6255static uint32_t
6256dec_long(struct X86EMU *emu, uint32_t d)
6257{
6258 uint32_t res; /* all operands in native machine order */
6259 uint32_t bc;
6260
6261 res = d - 1;
6262
6263 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6264 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6265 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6266
6267 /* calculate the borrow chain. See note at top */
6268 bc = (res & (~d | 1)) | (~d & 1);
6269 /* carry flag unchanged */
6270 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6271 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6272 return res;
6273}
6274/****************************************************************************
6275REMARKS:
6276Implements the INC instruction and side effects.
6277****************************************************************************/
6278static uint8_t
6279inc_byte(struct X86EMU *emu, uint8_t d)
6280{
6281 uint32_t res; /* all operands in native machine order */
6282 uint32_t cc;
6283
6284 res = d + 1;
6285 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6286 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6287 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6288
6289 /* calculate the carry chain SEE NOTE AT TOP. */
6290 cc = ((1 & d) | (~res)) & (1 | d);
6291 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6292 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6293 return (uint8_t) res;
6294}
6295/****************************************************************************
6296REMARKS:
6297Implements the INC instruction and side effects.
6298****************************************************************************/
6299static uint16_t
6300inc_word(struct X86EMU *emu, uint16_t d)
6301{
6302 uint32_t res; /* all operands in native machine order */
6303 uint32_t cc;
6304
6305 res = d + 1;
6306 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6307 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6308 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6309
6310 /* calculate the carry chain SEE NOTE AT TOP. */
6311 cc = (1 & d) | ((~res) & (1 | d));
6312 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6313 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6314 return (uint16_t) res;
6315}
6316/****************************************************************************
6317REMARKS:
6318Implements the INC instruction and side effects.
6319****************************************************************************/
6320static uint32_t
6321inc_long(struct X86EMU *emu, uint32_t d)
6322{
6323 uint32_t res; /* all operands in native machine order */
6324 uint32_t cc;
6325
6326 res = d + 1;
6327 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6328 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6329 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6330
6331 /* calculate the carry chain SEE NOTE AT TOP. */
6332 cc = (1 & d) | ((~res) & (1 | d));
6333 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6334 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6335 return res;
6336}
6337/****************************************************************************
6338REMARKS:
6339Implements the OR instruction and side effects.
6340****************************************************************************/
6341static uint8_t
6342or_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6343{
6344 uint8_t res; /* all operands in native machine order */
6345
6346 res = d | s;
6347 CLEAR_FLAG(F_OF);
6348 CLEAR_FLAG(F_CF);
6349 CLEAR_FLAG(F_AF);
6350 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6351 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6352 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6353 return res;
6354}
6355/****************************************************************************
6356REMARKS:
6357Implements the OR instruction and side effects.
6358****************************************************************************/
6359static uint16_t
6360or_word(struct X86EMU *emu, uint16_t d, uint16_t s)
6361{
6362 uint16_t res; /* all operands in native machine order */
6363
6364 res = d | s;
6365 /* set the carry flag to be bit 8 */
6366 CLEAR_FLAG(F_OF);
6367 CLEAR_FLAG(F_CF);
6368 CLEAR_FLAG(F_AF);
6369 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6370 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6371 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6372 return res;
6373}
6374/****************************************************************************
6375REMARKS:
6376Implements the OR instruction and side effects.
6377****************************************************************************/
6378static uint32_t
6379or_long(struct X86EMU *emu, uint32_t d, uint32_t s)
6380{
6381 uint32_t res; /* all operands in native machine order */
6382
6383 res = d | s;
6384
6385 /* set the carry flag to be bit 8 */
6386 CLEAR_FLAG(F_OF);
6387 CLEAR_FLAG(F_CF);
6388 CLEAR_FLAG(F_AF);
6389 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6390 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6391 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6392 return res;
6393}
6394/****************************************************************************
6395REMARKS:
6396Implements the OR instruction and side effects.
6397****************************************************************************/
6398static uint8_t
6399neg_byte(struct X86EMU *emu, uint8_t s)
6400{
6401 uint8_t res;
6402 uint8_t bc;
6403
6404 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6405 res = (uint8_t) - s;
6406 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6407 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6408 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6409 /* calculate the borrow chain --- modified such that d=0.
6410 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6411 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6412 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6413 * result is: */
6414 bc = res | s;
6415 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6416 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6417 return res;
6418}
6419/****************************************************************************
6420REMARKS:
6421Implements the OR instruction and side effects.
6422****************************************************************************/
6423static uint16_t
6424neg_word(struct X86EMU *emu, uint16_t s)
6425{
6426 uint16_t res;
6427 uint16_t bc;
6428
6429 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6430 res = (uint16_t) - s;
6431 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6432 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6433 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6434
6435 /* calculate the borrow chain --- modified such that d=0.
6436 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6437 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6438 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6439 * result is: */
6440 bc = res | s;
6441 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6442 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6443 return res;
6444}
6445/****************************************************************************
6446REMARKS:
6447Implements the OR instruction and side effects.
6448****************************************************************************/
6449static uint32_t
6450neg_long(struct X86EMU *emu, uint32_t s)
6451{
6452 uint32_t res;
6453 uint32_t bc;
6454
6455 CONDITIONAL_SET_FLAG(s != 0, F_CF);
6456 res = (uint32_t) - s;
6457 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6458 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6459 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6460
6461 /* calculate the borrow chain --- modified such that d=0.
6462 * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6463 * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6464 * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6465 * result is: */
6466 bc = res | s;
6467 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6468 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6469 return res;
6470}
6471/****************************************************************************
6472REMARKS:
6473Implements the RCL instruction and side effects.
6474****************************************************************************/
6475static uint8_t
6476rcl_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6477{
6478 unsigned int res, cnt, mask, cf;
6479
6480 /* s is the rotate distance. It varies from 0 - 8. */
6481 /* have
6482 *
6483 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6484 *
6485 * want to rotate through the carry by "s" bits. We could loop, but
6486 * that's inefficient. So the width is 9, and we split into three
6487 * parts:
6488 *
6489 * The new carry flag (was B_n) the stuff in B_n-1 .. B_0 the stuff in
6490 * B_7 .. B_n+1
6491 *
6492 * The new rotate is done mod 9, and given this, for a rotation of n bits
6493 * (mod 9) the new carry flag is then located n bits from the MSB.
6494 * The low part is then shifted up cnt bits, and the high part is or'd
6495 * in. Using CAPS for new values, and lowercase for the original
6496 * values, this can be expressed as:
6497 *
6498 * IF n > 0 1) CF <- b_(8-n) 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
6499 * 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
6500 res = d;
6501 if ((cnt = s % 9) != 0) {
6502 /* extract the new CARRY FLAG. */
6503 /* CF <- b_(8-n) */
6504 cf = (d >> (8 - cnt)) & 0x1;
6505
6506 /* get the low stuff which rotated into the range B_7 .. B_cnt */
6507 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
6508 /* note that the right hand side done by the mask */
6509 res = (d << cnt) & 0xff;
6510
6511 /* now the high stuff which rotated around into the positions
6512 * B_cnt-2 .. B_0 */
6513 /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
6514 /* shift it downward, 7-(n-2) = 9-n positions. and mask off
6515 * the result before or'ing in. */
6516 mask = (1 << (cnt - 1)) - 1;
6517 res |= (d >> (9 - cnt)) & mask;
6518
6519 /* if the carry flag was set, or it in. */
6520 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6521 /* B_(n-1) <- cf */
6522 res |= 1 << (cnt - 1);
6523 }
6524 /* set the new carry flag, based on the variable "cf" */
6525 CONDITIONAL_SET_FLAG(cf, F_CF);
6526 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6527 * the most significant bit. Blecck. */
6528 /* parenthesized this expression since it appears to be
6529 * causing OF to be misset */
6530 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
6531 F_OF);
6532
6533 }
6534 return (uint8_t) res;
6535}
6536/****************************************************************************
6537REMARKS:
6538Implements the RCL instruction and side effects.
6539****************************************************************************/
6540static uint16_t
6541rcl_word(struct X86EMU *emu, uint16_t d, uint8_t s)
6542{
6543 unsigned int res, cnt, mask, cf;
6544
6545 res = d;
6546 if ((cnt = s % 17) != 0) {
6547 cf = (d >> (16 - cnt)) & 0x1;
6548 res = (d << cnt) & 0xffff;
6549 mask = (1 << (cnt - 1)) - 1;
6550 res |= (d >> (17 - cnt)) & mask;
6551 if (ACCESS_FLAG(F_CF)) {
6552 res |= 1 << (cnt - 1);
6553 }
6554 CONDITIONAL_SET_FLAG(cf, F_CF);
6555 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
6556 F_OF);
6557 }
6558 return (uint16_t) res;
6559}
6560/****************************************************************************
6561REMARKS:
6562Implements the RCL instruction and side effects.
6563****************************************************************************/
6564static uint32_t
6565rcl_long(struct X86EMU *emu, uint32_t d, uint8_t s)
6566{
6567 uint32_t res, cnt, mask, cf;
6568
6569 res = d;
6570 if ((cnt = s % 33) != 0) {
6571 cf = (d >> (32 - cnt)) & 0x1;
6572 res = (d << cnt) & 0xffffffff;
6573 mask = (1 << (cnt - 1)) - 1;
6574 res |= (d >> (33 - cnt)) & mask;
6575 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6576 res |= 1 << (cnt - 1);
6577 }
6578 CONDITIONAL_SET_FLAG(cf, F_CF);
6579 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
6580 F_OF);
6581 }
6582 return res;
6583}
6584/****************************************************************************
6585REMARKS:
6586Implements the RCR instruction and side effects.
6587****************************************************************************/
6588static uint8_t
6589rcr_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6590{
6591 uint32_t res, cnt;
6592 uint32_t mask, cf, ocf = 0;
6593
6594 /* rotate right through carry */
6595 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6596 * object rotated.
6597 *
6598 * have
6599 *
6600 * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6601 *
6602 * The new rotate is done mod 9, and given this, for a rotation of n bits
6603 * (mod 9) the new carry flag is then located n bits from the LSB.
6604 * The low part is then shifted up cnt bits, and the high part is or'd
6605 * in. Using CAPS for new values, and lowercase for the original
6606 * values, this can be expressed as:
6607 *
6608 * IF n > 0 1) CF <- b_(n-1) 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
6609 * 3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
6610 res = d;
6611 if ((cnt = s % 9) != 0) {
6612 /* extract the new CARRY FLAG. */
6613 /* CF <- b_(n-1) */
6614 if (cnt == 1) {
6615 cf = d & 0x1;
6616 /* note hackery here. Access_flag(..) evaluates to
6617 * either 0 if flag not set non-zero if flag is set.
6618 * doing access_flag(..) != 0 casts that into either
6619 * 0..1 in any representation of the flags register
6620 * (i.e. packed bit array or unpacked.) */
6621 ocf = ACCESS_FLAG(F_CF) != 0;
6622 } else
6623 cf = (d >> (cnt - 1)) & 0x1;
6624
6625 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
6626 /* note that the right hand side done by the mask This is
6627 * effectively done by shifting the object to the right. The
6628 * result must be masked, in case the object came in and was
6629 * treated as a negative number. Needed??? */
6630
6631 mask = (1 << (8 - cnt)) - 1;
6632 res = (d >> cnt) & mask;
6633
6634 /* now the high stuff which rotated around into the positions
6635 * B_cnt-2 .. B_0 */
6636 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
6637 /* shift it downward, 7-(n-2) = 9-n positions. and mask off
6638 * the result before or'ing in. */
6639 res |= (d << (9 - cnt));
6640
6641 /* if the carry flag was set, or it in. */
6642 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6643 /* B_(8-n) <- cf */
6644 res |= 1 << (8 - cnt);
6645 }
6646 /* set the new carry flag, based on the variable "cf" */
6647 CONDITIONAL_SET_FLAG(cf, F_CF);
6648 /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6649 * the most significant bit. Blecck. */
6650 /* parenthesized... */
6651 if (cnt == 1) {
6652 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
6653 F_OF);
6654 }
6655 }
6656 return (uint8_t) res;
6657}
6658/****************************************************************************
6659REMARKS:
6660Implements the RCR instruction and side effects.
6661****************************************************************************/
6662static uint16_t
6663rcr_word(struct X86EMU *emu, uint16_t d, uint8_t s)
6664{
6665 uint32_t res, cnt;
6666 uint32_t mask, cf, ocf = 0;
6667
6668 /* rotate right through carry */
6669 res = d;
6670 if ((cnt = s % 17) != 0) {
6671 if (cnt == 1) {
6672 cf = d & 0x1;
6673 ocf = ACCESS_FLAG(F_CF) != 0;
6674 } else
6675 cf = (d >> (cnt - 1)) & 0x1;
6676 mask = (1 << (16 - cnt)) - 1;
6677 res = (d >> cnt) & mask;
6678 res |= (d << (17 - cnt));
6679 if (ACCESS_FLAG(F_CF)) {
6680 res |= 1 << (16 - cnt);
6681 }
6682 CONDITIONAL_SET_FLAG(cf, F_CF);
6683 if (cnt == 1) {
6684 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
6685 F_OF);
6686 }
6687 }
6688 return (uint16_t) res;
6689}
6690/****************************************************************************
6691REMARKS:
6692Implements the RCR instruction and side effects.
6693****************************************************************************/
6694static uint32_t
6695rcr_long(struct X86EMU *emu, uint32_t d, uint8_t s)
6696{
6697 uint32_t res, cnt;
6698 uint32_t mask, cf, ocf = 0;
6699
6700 /* rotate right through carry */
6701 res = d;
6702 if ((cnt = s % 33) != 0) {
6703 if (cnt == 1) {
6704 cf = d & 0x1;
6705 ocf = ACCESS_FLAG(F_CF) != 0;
6706 } else
6707 cf = (d >> (cnt - 1)) & 0x1;
6708 mask = (1 << (32 - cnt)) - 1;
6709 res = (d >> cnt) & mask;
6710 if (cnt != 1)
6711 res |= (d << (33 - cnt));
6712 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6713 res |= 1 << (32 - cnt);
6714 }
6715 CONDITIONAL_SET_FLAG(cf, F_CF);
6716 if (cnt == 1) {
6717 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
6718 F_OF);
6719 }
6720 }
6721 return res;
6722}
6723/****************************************************************************
6724REMARKS:
6725Implements the ROL instruction and side effects.
6726****************************************************************************/
6727static uint8_t
6728rol_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6729{
6730 unsigned int res, cnt, mask;
6731
6732 /* rotate left */
6733 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6734 * object rotated.
6735 *
6736 * have
6737 *
6738 * CF B_7 ... B_0
6739 *
6740 * The new rotate is done mod 8. Much simpler than the "rcl" or "rcr"
6741 * operations.
6742 *
6743 * IF n > 0 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) 2) B_(n-1) ..
6744 * B_(0) <- b_(7) .. b_(8-n) */
6745 res = d;
6746 if ((cnt = s % 8) != 0) {
6747 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
6748 res = (d << cnt);
6749
6750 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
6751 mask = (1 << cnt) - 1;
6752 res |= (d >> (8 - cnt)) & mask;
6753
6754 /* set the new carry flag, Note that it is the low order bit
6755 * of the result!!! */
6756 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6757 /* OVERFLOW is set *IFF* s==1, then it is the xor of CF and
6758 * the most significant bit. Blecck. */
6759 CONDITIONAL_SET_FLAG(s == 1 &&
6760 XOR2((res & 0x1) + ((res >> 6) & 0x2)),
6761 F_OF);
6762 } if (s != 0) {
6763 /* set the new carry flag, Note that it is the low order bit
6764 * of the result!!! */
6765 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6766 }
6767 return (uint8_t) res;
6768}
6769/****************************************************************************
6770REMARKS:
6771Implements the ROL instruction and side effects.
6772****************************************************************************/
6773static uint16_t
6774rol_word(struct X86EMU *emu, uint16_t d, uint8_t s)
6775{
6776 unsigned int res, cnt, mask;
6777
6778 res = d;
6779 if ((cnt = s % 16) != 0) {
6780 res = (d << cnt);
6781 mask = (1 << cnt) - 1;
6782 res |= (d >> (16 - cnt)) & mask;
6783 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6784 CONDITIONAL_SET_FLAG(s == 1 &&
6785 XOR2((res & 0x1) + ((res >> 14) & 0x2)),
6786 F_OF);
6787 } if (s != 0) {
6788 /* set the new carry flag, Note that it is the low order bit
6789 * of the result!!! */
6790 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6791 }
6792 return (uint16_t) res;
6793}
6794/****************************************************************************
6795REMARKS:
6796Implements the ROL instruction and side effects.
6797****************************************************************************/
6798static uint32_t
6799rol_long(struct X86EMU *emu, uint32_t d, uint8_t s)
6800{
6801 uint32_t res, cnt, mask;
6802
6803 res = d;
6804 if ((cnt = s % 32) != 0) {
6805 res = (d << cnt);
6806 mask = (1 << cnt) - 1;
6807 res |= (d >> (32 - cnt)) & mask;
6808 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6809 CONDITIONAL_SET_FLAG(s == 1 &&
6810 XOR2((res & 0x1) + ((res >> 30) & 0x2)),
6811 F_OF);
6812 } if (s != 0) {
6813 /* set the new carry flag, Note that it is the low order bit
6814 * of the result!!! */
6815 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
6816 }
6817 return res;
6818}
6819/****************************************************************************
6820REMARKS:
6821Implements the ROR instruction and side effects.
6822****************************************************************************/
6823static uint8_t
6824ror_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6825{
6826 unsigned int res, cnt, mask;
6827
6828 /* rotate right */
6829 /* s is the rotate distance. It varies from 0 - 8. d is the byte
6830 * object rotated.
6831 *
6832 * have
6833 *
6834 * B_7 ... B_0
6835 *
6836 * The rotate is done mod 8.
6837 *
6838 * IF n > 0 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 2) B_(7) ..
6839 * B_(8-n) <- b_(n-1) .. b_(0) */
6840 res = d;
6841 if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */
6842 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
6843 res = (d << (8 - cnt));
6844
6845 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
6846 mask = (1 << (8 - cnt)) - 1;
6847 res |= (d >> (cnt)) & mask;
6848
6849 /* set the new carry flag, Note that it is the low order bit
6850 * of the result!!! */
6851 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
6852 /* OVERFLOW is set *IFF* s==1, then it is the xor of the two
6853 * most significant bits. Blecck. */
6854 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
6855 } else if (s != 0) {
6856 /* set the new carry flag, Note that it is the low order bit
6857 * of the result!!! */
6858 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
6859 }
6860 return (uint8_t) res;
6861}
6862/****************************************************************************
6863REMARKS:
6864Implements the ROR instruction and side effects.
6865****************************************************************************/
6866static uint16_t
6867ror_word(struct X86EMU *emu, uint16_t d, uint8_t s)
6868{
6869 unsigned int res, cnt, mask;
6870
6871 res = d;
6872 if ((cnt = s % 16) != 0) {
6873 res = (d << (16 - cnt));
6874 mask = (1 << (16 - cnt)) - 1;
6875 res |= (d >> (cnt)) & mask;
6876 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
6877 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
6878 } else if (s != 0) {
6879 /* set the new carry flag, Note that it is the low order bit
6880 * of the result!!! */
6881 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
6882 }
6883 return (uint16_t) res;
6884}
6885/****************************************************************************
6886REMARKS:
6887Implements the ROR instruction and side effects.
6888****************************************************************************/
6889static uint32_t
6890ror_long(struct X86EMU *emu, uint32_t d, uint8_t s)
6891{
6892 uint32_t res, cnt, mask;
6893
6894 res = d;
6895 if ((cnt = s % 32) != 0) {
6896 res = (d << (32 - cnt));
6897 mask = (1 << (32 - cnt)) - 1;
6898 res |= (d >> (cnt)) & mask;
6899 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
6900 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
6901 } else if (s != 0) {
6902 /* set the new carry flag, Note that it is the low order bit
6903 * of the result!!! */
6904 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
6905 }
6906 return res;
6907}
6908/****************************************************************************
6909REMARKS:
6910Implements the SHL instruction and side effects.
6911****************************************************************************/
6912static uint8_t
6913shl_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
6914{
6915 unsigned int cnt, res, cf;
6916
6917 if (s < 8) {
6918 cnt = s % 8;
6919
6920 /* last bit shifted out goes into carry flag */
6921 if (cnt > 0) {
6922 res = d << cnt;
6923 cf = d & (1 << (8 - cnt));
6924 CONDITIONAL_SET_FLAG(cf, F_CF);
6925 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6926 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6927 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6928 } else {
6929 res = (uint8_t) d;
6930 }
6931
6932 if (cnt == 1) {
6933 /* Needs simplification. */
6934 CONDITIONAL_SET_FLAG(
6935 (((res & 0x80) == 0x80) ^
6936 (ACCESS_FLAG(F_CF) != 0)),
6937 /* was (emu->x86.R_FLG&F_CF)==F_CF)), */
6938 F_OF);
6939 } else {
6940 CLEAR_FLAG(F_OF);
6941 }
6942 } else {
6943 res = 0;
6944 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF);
6945 CLEAR_FLAG(F_OF);
6946 CLEAR_FLAG(F_SF);
6947 SET_FLAG(F_PF);
6948 SET_FLAG(F_ZF);
6949 }
6950 return (uint8_t) res;
6951}
6952/****************************************************************************
6953REMARKS:
6954Implements the SHL instruction and side effects.
6955****************************************************************************/
6956static uint16_t
6957shl_word(struct X86EMU *emu, uint16_t d, uint8_t s)
6958{
6959 unsigned int cnt, res, cf;
6960
6961 if (s < 16) {
6962 cnt = s % 16;
6963 if (cnt > 0) {
6964 res = d << cnt;
6965 cf = d & (1 << (16 - cnt));
6966 CONDITIONAL_SET_FLAG(cf, F_CF);
6967 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6968 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6969 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6970 } else {
6971 res = (uint16_t) d;
6972 }
6973
6974 if (cnt == 1) {
6975 CONDITIONAL_SET_FLAG(
6976 (((res & 0x8000) == 0x8000) ^
6977 (ACCESS_FLAG(F_CF) != 0)),
6978 F_OF);
6979 } else {
6980 CLEAR_FLAG(F_OF);
6981 }
6982 } else {
6983 res = 0;
6984 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
6985 CLEAR_FLAG(F_OF);
6986 CLEAR_FLAG(F_SF);
6987 SET_FLAG(F_PF);
6988 SET_FLAG(F_ZF);
6989 }
6990 return (uint16_t) res;
6991}
6992/****************************************************************************
6993REMARKS:
6994Implements the SHL instruction and side effects.
6995****************************************************************************/
6996static uint32_t
6997shl_long(struct X86EMU *emu, uint32_t d, uint8_t s)
6998{
6999 unsigned int cnt, res, cf;
7000
7001 if (s < 32) {
7002 cnt = s % 32;
7003 if (cnt > 0) {
7004 res = d << cnt;
7005 cf = d & (1 << (32 - cnt));
7006 CONDITIONAL_SET_FLAG(cf, F_CF);
7007 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7008 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7009 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7010 } else {
7011 res = d;
7012 }
7013 if (cnt == 1) {
7014 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
7015 (ACCESS_FLAG(F_CF) != 0)), F_OF);
7016 } else {
7017 CLEAR_FLAG(F_OF);
7018 }
7019 } else {
7020 res = 0;
7021 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7022 CLEAR_FLAG(F_OF);
7023 CLEAR_FLAG(F_SF);
7024 SET_FLAG(F_PF);
7025 SET_FLAG(F_ZF);
7026 }
7027 return res;
7028}
7029/****************************************************************************
7030REMARKS:
7031Implements the SHR instruction and side effects.
7032****************************************************************************/
7033static uint8_t
7034shr_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7035{
7036 unsigned int cnt, res, cf;
7037
7038 if (s < 8) {
7039 cnt = s % 8;
7040 if (cnt > 0) {
7041 cf = d & (1 << (cnt - 1));
7042 res = d >> cnt;
7043 CONDITIONAL_SET_FLAG(cf, F_CF);
7044 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7045 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7046 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7047 } else {
7048 res = (uint8_t) d;
7049 }
7050
7051 if (cnt == 1) {
7052 CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
7053 } else {
7054 CLEAR_FLAG(F_OF);
7055 }
7056 } else {
7057 res = 0;
7058 CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF);
7059 CLEAR_FLAG(F_OF);
7060 CLEAR_FLAG(F_SF);
7061 SET_FLAG(F_PF);
7062 SET_FLAG(F_ZF);
7063 }
7064 return (uint8_t) res;
7065}
7066/****************************************************************************
7067REMARKS:
7068Implements the SHR instruction and side effects.
7069****************************************************************************/
7070static uint16_t
7071shr_word(struct X86EMU *emu, uint16_t d, uint8_t s)
7072{
7073 unsigned int cnt, res, cf;
7074
7075 if (s < 16) {
7076 cnt = s % 16;
7077 if (cnt > 0) {
7078 cf = d & (1 << (cnt - 1));
7079 res = d >> cnt;
7080 CONDITIONAL_SET_FLAG(cf, F_CF);
7081 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7082 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7083 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7084 } else {
7085 res = d;
7086 }
7087
7088 if (cnt == 1) {
7089 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7090 } else {
7091 CLEAR_FLAG(F_OF);
7092 }
7093 } else {
7094 res = 0;
7095 CLEAR_FLAG(F_CF);
7096 CLEAR_FLAG(F_OF);
7097 SET_FLAG(F_ZF);
7098 CLEAR_FLAG(F_SF);
7099 CLEAR_FLAG(F_PF);
7100 }
7101 return (uint16_t) res;
7102}
7103/****************************************************************************
7104REMARKS:
7105Implements the SHR instruction and side effects.
7106****************************************************************************/
7107static uint32_t
7108shr_long(struct X86EMU *emu, uint32_t d, uint8_t s)
7109{
7110 unsigned int cnt, res, cf;
7111
7112 if (s < 32) {
7113 cnt = s % 32;
7114 if (cnt > 0) {
7115 cf = d & (1 << (cnt - 1));
7116 res = d >> cnt;
7117 CONDITIONAL_SET_FLAG(cf, F_CF);
7118 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7119 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7120 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7121 } else {
7122 res = d;
7123 }
7124 if (cnt == 1) {
7125 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7126 } else {
7127 CLEAR_FLAG(F_OF);
7128 }
7129 } else {
7130 res = 0;
7131 CLEAR_FLAG(F_CF);
7132 CLEAR_FLAG(F_OF);
7133 SET_FLAG(F_ZF);
7134 CLEAR_FLAG(F_SF);
7135 CLEAR_FLAG(F_PF);
7136 }
7137 return res;
7138}
7139/****************************************************************************
7140REMARKS:
7141Implements the SAR instruction and side effects.
7142****************************************************************************/
7143static uint8_t
7144sar_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7145{
7146 unsigned int cnt, res, cf, mask, sf;
7147
7148 res = d;
7149 sf = d & 0x80;
7150 cnt = s % 8;
7151 if (cnt > 0 && cnt < 8) {
7152 mask = (1 << (8 - cnt)) - 1;
7153 cf = d & (1 << (cnt - 1));
7154 res = (d >> cnt) & mask;
7155 CONDITIONAL_SET_FLAG(cf, F_CF);
7156 if (sf) {
7157 res |= ~mask;
7158 }
7159 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7160 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7161 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7162 } else if (cnt >= 8) {
7163 if (sf) {
7164 res = 0xff;
7165 SET_FLAG(F_CF);
7166 CLEAR_FLAG(F_ZF);
7167 SET_FLAG(F_SF);
7168 SET_FLAG(F_PF);
7169 } else {
7170 res = 0;
7171 CLEAR_FLAG(F_CF);
7172 SET_FLAG(F_ZF);
7173 CLEAR_FLAG(F_SF);
7174 CLEAR_FLAG(F_PF);
7175 }
7176 }
7177 return (uint8_t) res;
7178}
7179/****************************************************************************
7180REMARKS:
7181Implements the SAR instruction and side effects.
7182****************************************************************************/
7183static uint16_t
7184sar_word(struct X86EMU *emu, uint16_t d, uint8_t s)
7185{
7186 unsigned int cnt, res, cf, mask, sf;
7187
7188 sf = d & 0x8000;
7189 cnt = s % 16;
7190 res = d;
7191 if (cnt > 0 && cnt < 16) {
7192 mask = (1 << (16 - cnt)) - 1;
7193 cf = d & (1 << (cnt - 1));
7194 res = (d >> cnt) & mask;
7195 CONDITIONAL_SET_FLAG(cf, F_CF);
7196 if (sf) {
7197 res |= ~mask;
7198 }
7199 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7200 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7201 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7202 } else if (cnt >= 16) {
7203 if (sf) {
7204 res = 0xffff;
7205 SET_FLAG(F_CF);
7206 CLEAR_FLAG(F_ZF);
7207 SET_FLAG(F_SF);
7208 SET_FLAG(F_PF);
7209 } else {
7210 res = 0;
7211 CLEAR_FLAG(F_CF);
7212 SET_FLAG(F_ZF);
7213 CLEAR_FLAG(F_SF);
7214 CLEAR_FLAG(F_PF);
7215 }
7216 }
7217 return (uint16_t) res;
7218}
7219/****************************************************************************
7220REMARKS:
7221Implements the SAR instruction and side effects.
7222****************************************************************************/
7223static uint32_t
7224sar_long(struct X86EMU *emu, uint32_t d, uint8_t s)
7225{
7226 uint32_t cnt, res, cf, mask, sf;
7227
7228 sf = d & 0x80000000;
7229 cnt = s % 32;
7230 res = d;
7231 if (cnt > 0 && cnt < 32) {
7232 mask = (1 << (32 - cnt)) - 1;
7233 cf = d & (1 << (cnt - 1));
7234 res = (d >> cnt) & mask;
7235 CONDITIONAL_SET_FLAG(cf, F_CF);
7236 if (sf) {
7237 res |= ~mask;
7238 }
7239 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7240 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7241 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7242 } else if (cnt >= 32) {
7243 if (sf) {
7244 res = 0xffffffff;
7245 SET_FLAG(F_CF);
7246 CLEAR_FLAG(F_ZF);
7247 SET_FLAG(F_SF);
7248 SET_FLAG(F_PF);
7249 } else {
7250 res = 0;
7251 CLEAR_FLAG(F_CF);
7252 SET_FLAG(F_ZF);
7253 CLEAR_FLAG(F_SF);
7254 CLEAR_FLAG(F_PF);
7255 }
7256 }
7257 return res;
7258}
7259/****************************************************************************
7260REMARKS:
7261Implements the SHLD instruction and side effects.
7262****************************************************************************/
7263static uint16_t
7264shld_word(struct X86EMU *emu, uint16_t d, uint16_t fill, uint8_t s)
7265{
7266 unsigned int cnt, res, cf;
7267
7268 if (s < 16) {
7269 cnt = s % 16;
7270 if (cnt > 0) {
7271 res = (d << cnt) | (fill >> (16 - cnt));
7272 cf = d & (1 << (16 - cnt));
7273 CONDITIONAL_SET_FLAG(cf, F_CF);
7274 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7275 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7276 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7277 } else {
7278 res = d;
7279 }
7280 if (cnt == 1) {
7281 CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
7282 (ACCESS_FLAG(F_CF) != 0)), F_OF);
7283 } else {
7284 CLEAR_FLAG(F_OF);
7285 }
7286 } else {
7287 res = 0;
7288 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
7289 CLEAR_FLAG(F_OF);
7290 CLEAR_FLAG(F_SF);
7291 SET_FLAG(F_PF);
7292 SET_FLAG(F_ZF);
7293 }
7294 return (uint16_t) res;
7295}
7296/****************************************************************************
7297REMARKS:
7298Implements the SHLD instruction and side effects.
7299****************************************************************************/
7300static uint32_t
7301shld_long(struct X86EMU *emu, uint32_t d, uint32_t fill, uint8_t s)
7302{
7303 unsigned int cnt, res, cf;
7304
7305 if (s < 32) {
7306 cnt = s % 32;
7307 if (cnt > 0) {
7308 res = (d << cnt) | (fill >> (32 - cnt));
7309 cf = d & (1 << (32 - cnt));
7310 CONDITIONAL_SET_FLAG(cf, F_CF);
7311 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7312 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7313 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7314 } else {
7315 res = d;
7316 }
7317 if (cnt == 1) {
7318 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
7319 (ACCESS_FLAG(F_CF) != 0)), F_OF);
7320 } else {
7321 CLEAR_FLAG(F_OF);
7322 }
7323 } else {
7324 res = 0;
7325 CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7326 CLEAR_FLAG(F_OF);
7327 CLEAR_FLAG(F_SF);
7328 SET_FLAG(F_PF);
7329 SET_FLAG(F_ZF);
7330 }
7331 return res;
7332}
7333/****************************************************************************
7334REMARKS:
7335Implements the SHRD instruction and side effects.
7336****************************************************************************/
7337static uint16_t
7338shrd_word(struct X86EMU *emu, uint16_t d, uint16_t fill, uint8_t s)
7339{
7340 unsigned int cnt, res, cf;
7341
7342 if (s < 16) {
7343 cnt = s % 16;
7344 if (cnt > 0) {
7345 cf = d & (1 << (cnt - 1));
7346 res = (d >> cnt) | (fill << (16 - cnt));
7347 CONDITIONAL_SET_FLAG(cf, F_CF);
7348 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7349 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7350 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7351 } else {
7352 res = d;
7353 }
7354
7355 if (cnt == 1) {
7356 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7357 } else {
7358 CLEAR_FLAG(F_OF);
7359 }
7360 } else {
7361 res = 0;
7362 CLEAR_FLAG(F_CF);
7363 CLEAR_FLAG(F_OF);
7364 SET_FLAG(F_ZF);
7365 CLEAR_FLAG(F_SF);
7366 CLEAR_FLAG(F_PF);
7367 }
7368 return (uint16_t) res;
7369}
7370/****************************************************************************
7371REMARKS:
7372Implements the SHRD instruction and side effects.
7373****************************************************************************/
7374static uint32_t
7375shrd_long(struct X86EMU *emu, uint32_t d, uint32_t fill, uint8_t s)
7376{
7377 unsigned int cnt, res, cf;
7378
7379 if (s < 32) {
7380 cnt = s % 32;
7381 if (cnt > 0) {
7382 cf = d & (1 << (cnt - 1));
7383 res = (d >> cnt) | (fill << (32 - cnt));
7384 CONDITIONAL_SET_FLAG(cf, F_CF);
7385 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7386 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7387 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7388 } else {
7389 res = d;
7390 }
7391 if (cnt == 1) {
7392 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7393 } else {
7394 CLEAR_FLAG(F_OF);
7395 }
7396 } else {
7397 res = 0;
7398 CLEAR_FLAG(F_CF);
7399 CLEAR_FLAG(F_OF);
7400 SET_FLAG(F_ZF);
7401 CLEAR_FLAG(F_SF);
7402 CLEAR_FLAG(F_PF);
7403 }
7404 return res;
7405}
7406/****************************************************************************
7407REMARKS:
7408Implements the SBB instruction and side effects.
7409****************************************************************************/
7410static uint8_t
7411sbb_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7412{
7413 uint32_t res; /* all operands in native machine order */
7414 uint32_t bc;
7415
7416 if (ACCESS_FLAG(F_CF))
7417 res = d - s - 1;
7418 else
7419 res = d - s;
7420 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7421 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7422 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7423
7424 /* calculate the borrow chain. See note at top */
7425 bc = (res & (~d | s)) | (~d & s);
7426 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7427 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7428 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7429 return (uint8_t) res;
7430}
7431/****************************************************************************
7432REMARKS:
7433Implements the SBB instruction and side effects.
7434****************************************************************************/
7435static uint16_t
7436sbb_word(struct X86EMU *emu, uint16_t d, uint16_t s)
7437{
7438 uint32_t res; /* all operands in native machine order */
7439 uint32_t bc;
7440
7441 if (ACCESS_FLAG(F_CF))
7442 res = d - s - 1;
7443 else
7444 res = d - s;
7445 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7446 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7447 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7448
7449 /* calculate the borrow chain. See note at top */
7450 bc = (res & (~d | s)) | (~d & s);
7451 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7452 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7453 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7454 return (uint16_t) res;
7455}
7456/****************************************************************************
7457REMARKS:
7458Implements the SBB instruction and side effects.
7459****************************************************************************/
7460static uint32_t
7461sbb_long(struct X86EMU *emu, uint32_t d, uint32_t s)
7462{
7463 uint32_t res; /* all operands in native machine order */
7464 uint32_t bc;
7465
7466 if (ACCESS_FLAG(F_CF))
7467 res = d - s - 1;
7468 else
7469 res = d - s;
7470 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7471 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7472 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7473
7474 /* calculate the borrow chain. See note at top */
7475 bc = (res & (~d | s)) | (~d & s);
7476 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7477 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7478 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7479 return res;
7480}
7481/****************************************************************************
7482REMARKS:
7483Implements the SUB instruction and side effects.
7484****************************************************************************/
7485static uint8_t
7486sub_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7487{
7488 uint32_t res; /* all operands in native machine order */
7489 uint32_t bc;
7490
7491 res = d - s;
7492 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7493 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7494 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7495
7496 /* calculate the borrow chain. See note at top */
7497 bc = (res & (~d | s)) | (~d & s);
7498 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7499 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7500 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7501 return (uint8_t) res;
7502}
7503/****************************************************************************
7504REMARKS:
7505Implements the SUB instruction and side effects.
7506****************************************************************************/
7507static uint16_t
7508sub_word(struct X86EMU *emu, uint16_t d, uint16_t s)
7509{
7510 uint32_t res; /* all operands in native machine order */
7511 uint32_t bc;
7512
7513 res = d - s;
7514 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7515 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7516 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7517
7518 /* calculate the borrow chain. See note at top */
7519 bc = (res & (~d | s)) | (~d & s);
7520 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7521 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7522 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7523 return (uint16_t) res;
7524}
7525/****************************************************************************
7526REMARKS:
7527Implements the SUB instruction and side effects.
7528****************************************************************************/
7529static uint32_t
7530sub_long(struct X86EMU *emu, uint32_t d, uint32_t s)
7531{
7532 uint32_t res; /* all operands in native machine order */
7533 uint32_t bc;
7534
7535 res = d - s;
7536 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7537 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7538 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7539
7540 /* calculate the borrow chain. See note at top */
7541 bc = (res & (~d | s)) | (~d & s);
7542 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7543 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7544 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7545 return res;
7546}
7547/****************************************************************************
7548REMARKS:
7549Implements the TEST instruction and side effects.
7550****************************************************************************/
7551static void
7552test_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7553{
7554 uint32_t res; /* all operands in native machine order */
7555
7556 res = d & s;
7557
7558 CLEAR_FLAG(F_OF);
7559 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7560 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7561 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7562 /* AF == dont care */
7563 CLEAR_FLAG(F_CF);
7564}
7565/****************************************************************************
7566REMARKS:
7567Implements the TEST instruction and side effects.
7568****************************************************************************/
7569static void
7570test_word(struct X86EMU *emu, uint16_t d, uint16_t s)
7571{
7572 uint32_t res; /* all operands in native machine order */
7573
7574 res = d & s;
7575
7576 CLEAR_FLAG(F_OF);
7577 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7578 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7579 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7580 /* AF == dont care */
7581 CLEAR_FLAG(F_CF);
7582}
7583/****************************************************************************
7584REMARKS:
7585Implements the TEST instruction and side effects.
7586****************************************************************************/
7587static void
7588test_long(struct X86EMU *emu, uint32_t d, uint32_t s)
7589{
7590 uint32_t res; /* all operands in native machine order */
7591
7592 res = d & s;
7593
7594 CLEAR_FLAG(F_OF);
7595 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7596 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7597 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7598 /* AF == dont care */
7599 CLEAR_FLAG(F_CF);
7600}
7601/****************************************************************************
7602REMARKS:
7603Implements the XOR instruction and side effects.
7604****************************************************************************/
7605static uint8_t
7606xor_byte(struct X86EMU *emu, uint8_t d, uint8_t s)
7607{
7608 uint8_t res; /* all operands in native machine order */
7609
7610 res = d ^ s;
7611 CLEAR_FLAG(F_OF);
7612 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7613 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7614 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
7615 CLEAR_FLAG(F_CF);
7616 CLEAR_FLAG(F_AF);
7617 return res;
7618}
7619/****************************************************************************
7620REMARKS:
7621Implements the XOR instruction and side effects.
7622****************************************************************************/
7623static uint16_t
7624xor_word(struct X86EMU *emu, uint16_t d, uint16_t s)
7625{
7626 uint16_t res; /* all operands in native machine order */
7627
7628 res = d ^ s;
7629 CLEAR_FLAG(F_OF);
7630 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7631 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7632 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7633 CLEAR_FLAG(F_CF);
7634 CLEAR_FLAG(F_AF);
7635 return res;
7636}
7637/****************************************************************************
7638REMARKS:
7639Implements the XOR instruction and side effects.
7640****************************************************************************/
7641static uint32_t
7642xor_long(struct X86EMU *emu, uint32_t d, uint32_t s)
7643{
7644 uint32_t res; /* all operands in native machine order */
7645
7646 res = d ^ s;
7647 CLEAR_FLAG(F_OF);
7648 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7649 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7650 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7651 CLEAR_FLAG(F_CF);
7652 CLEAR_FLAG(F_AF);
7653 return res;
7654}
7655/****************************************************************************
7656REMARKS:
7657Implements the IMUL instruction and side effects.
7658****************************************************************************/
7659static void
7660imul_byte(struct X86EMU *emu, uint8_t s)
7661{
7662 int16_t res = (int16_t) ((int8_t) emu->x86.R_AL * (int8_t) s);
7663
7664 emu->x86.R_AX = res;
7665 if (((emu->x86.R_AL & 0x80) == 0 && emu->x86.R_AH == 0x00) ||
7666 ((emu->x86.R_AL & 0x80) != 0 && emu->x86.R_AH == 0xFF)) {
7667 CLEAR_FLAG(F_CF);
7668 CLEAR_FLAG(F_OF);
7669 } else {
7670 SET_FLAG(F_CF);
7671 SET_FLAG(F_OF);
7672 }
7673}
7674/****************************************************************************
7675REMARKS:
7676Implements the IMUL instruction and side effects.
7677****************************************************************************/
7678static void
7679imul_word(struct X86EMU *emu, uint16_t s)
7680{
7681 int32_t res = (int16_t) emu->x86.R_AX * (int16_t) s;
7682
7683 emu->x86.R_AX = (uint16_t) res;
7684 emu->x86.R_DX = (uint16_t) (res >> 16);
7685 if (((emu->x86.R_AX & 0x8000) == 0 && emu->x86.R_DX == 0x00) ||
7686 ((emu->x86.R_AX & 0x8000) != 0 && emu->x86.R_DX == 0xFF)) {
7687 CLEAR_FLAG(F_CF);
7688 CLEAR_FLAG(F_OF);
7689 } else {
7690 SET_FLAG(F_CF);
7691 SET_FLAG(F_OF);
7692 }
7693}
7694/****************************************************************************
7695REMARKS:
7696Implements the IMUL instruction and side effects.
7697****************************************************************************/
7698static void
7699imul_long(struct X86EMU *emu, uint32_t s)
7700{
7701 int64_t res;
7702
7703 res = (int64_t)(int32_t)emu->x86.R_EAX * (int32_t)s;
7704 emu->x86.R_EAX = (uint32_t)res;
7705 emu->x86.R_EDX = ((uint64_t)res) >> 32;
7706 if (((emu->x86.R_EAX & 0x80000000) == 0 && emu->x86.R_EDX == 0x00) ||
7707 ((emu->x86.R_EAX & 0x80000000) != 0 && emu->x86.R_EDX == 0xFF)) {
7708 CLEAR_FLAG(F_CF);
7709 CLEAR_FLAG(F_OF);
7710 } else {
7711 SET_FLAG(F_CF);
7712 SET_FLAG(F_OF);
7713 }
7714}
7715/****************************************************************************
7716REMARKS:
7717Implements the MUL instruction and side effects.
7718****************************************************************************/
7719static void
7720mul_byte(struct X86EMU *emu, uint8_t s)
7721{
7722 uint16_t res = (uint16_t) (emu->x86.R_AL * s);
7723
7724 emu->x86.R_AX = res;
7725 if (emu->x86.R_AH == 0) {
7726 CLEAR_FLAG(F_CF);
7727 CLEAR_FLAG(F_OF);
7728 } else {
7729 SET_FLAG(F_CF);
7730 SET_FLAG(F_OF);
7731 }
7732}
7733/****************************************************************************
7734REMARKS:
7735Implements the MUL instruction and side effects.
7736****************************************************************************/
7737static void
7738mul_word(struct X86EMU *emu, uint16_t s)
7739{
7740 uint32_t res = emu->x86.R_AX * s;
7741
7742 emu->x86.R_AX = (uint16_t) res;
7743 emu->x86.R_DX = (uint16_t) (res >> 16);
7744 if (emu->x86.R_DX == 0) {
7745 CLEAR_FLAG(F_CF);
7746 CLEAR_FLAG(F_OF);
7747 } else {
7748 SET_FLAG(F_CF);
7749 SET_FLAG(F_OF);
7750 }
7751}
7752/****************************************************************************
7753REMARKS:
7754Implements the MUL instruction and side effects.
7755****************************************************************************/
7756static void
7757mul_long(struct X86EMU *emu, uint32_t s)
7758{
7759 uint64_t res = (uint64_t) emu->x86.R_EAX * s;
7760
7761 emu->x86.R_EAX = (uint32_t) res;
7762 emu->x86.R_EDX = (uint32_t) (res >> 32);
7763
7764 if (emu->x86.R_EDX == 0) {
7765 CLEAR_FLAG(F_CF);
7766 CLEAR_FLAG(F_OF);
7767 } else {
7768 SET_FLAG(F_CF);
7769 SET_FLAG(F_OF);
7770 }
7771}
7772/****************************************************************************
7773REMARKS:
7774Implements the IDIV instruction and side effects.
7775****************************************************************************/
7776static void
7777idiv_byte(struct X86EMU *emu, uint8_t s)
7778{
7779 int32_t dvd, div, mod;
7780
7781 dvd = (int16_t) emu->x86.R_AX;
7782 if (s == 0) {
7783 x86emu_intr_raise(emu, 8);
7784 return;
7785 }
7786 div = dvd / (int8_t) s;
7787 mod = dvd % (int8_t) s;
7788 if (div > 0x7f || div < -0x7f) {
7789 x86emu_intr_raise(emu, 8);
7790 return;
7791 }
7792 emu->x86.R_AL = (int8_t) div;
7793 emu->x86.R_AH = (int8_t) mod;
7794}
7795/****************************************************************************
7796REMARKS:
7797Implements the IDIV instruction and side effects.
7798****************************************************************************/
7799static void
7800idiv_word(struct X86EMU *emu, uint16_t s)
7801{
7802 int32_t dvd, div, mod;
7803
7804 dvd = (((int32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
7805 if (s == 0) {
7806 x86emu_intr_raise(emu, 8);
7807 return;
7808 }
7809 div = dvd / (int16_t) s;
7810 mod = dvd % (int16_t) s;
7811 if (div > 0x7fff || div < -0x7fff) {
7812 x86emu_intr_raise(emu, 8);
7813 return;
7814 }
7815 CLEAR_FLAG(F_CF);
7816 CLEAR_FLAG(F_SF);
7817 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
7818 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
7819
7820 emu->x86.R_AX = (uint16_t) div;
7821 emu->x86.R_DX = (uint16_t) mod;
7822}
7823/****************************************************************************
7824REMARKS:
7825Implements the IDIV instruction and side effects.
7826****************************************************************************/
7827static void
7828idiv_long(struct X86EMU *emu, uint32_t s)
7829{
7830 int64_t dvd, div, mod;
7831
7832 dvd = (((int64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
7833 if (s == 0) {
7834 x86emu_intr_raise(emu, 8);
7835 return;
7836 }
7837 div = dvd / (int32_t) s;
7838 mod = dvd % (int32_t) s;
7839 if (div > 0x7fffffff || div < -0x7fffffff) {
7840 x86emu_intr_raise(emu, 8);
7841 return;
7842 }
7843 CLEAR_FLAG(F_CF);
7844 CLEAR_FLAG(F_AF);
7845 CLEAR_FLAG(F_SF);
7846 SET_FLAG(F_ZF);
7847 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
7848
7849 emu->x86.R_EAX = (uint32_t) div;
7850 emu->x86.R_EDX = (uint32_t) mod;
7851}
7852/****************************************************************************
7853REMARKS:
7854Implements the DIV instruction and side effects.
7855****************************************************************************/
7856static void
7857div_byte(struct X86EMU *emu, uint8_t s)
7858{
7859 uint32_t dvd, div, mod;
7860
7861 dvd = emu->x86.R_AX;
7862 if (s == 0) {
7863 x86emu_intr_raise(emu, 8);
7864 return;
7865 }
7866 div = dvd / (uint8_t) s;
7867 mod = dvd % (uint8_t) s;
7868 if (div > 0xff) {
7869 x86emu_intr_raise(emu, 8);
7870 return;
7871 }
7872 emu->x86.R_AL = (uint8_t) div;
7873 emu->x86.R_AH = (uint8_t) mod;
7874}
7875/****************************************************************************
7876REMARKS:
7877Implements the DIV instruction and side effects.
7878****************************************************************************/
7879static void
7880div_word(struct X86EMU *emu, uint16_t s)
7881{
7882 uint32_t dvd, div, mod;
7883
7884 dvd = (((uint32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
7885 if (s == 0) {
7886 x86emu_intr_raise(emu, 8);
7887 return;
7888 }
7889 div = dvd / (uint16_t) s;
7890 mod = dvd % (uint16_t) s;
7891 if (div > 0xffff) {
7892 x86emu_intr_raise(emu, 8);
7893 return;
7894 }
7895 CLEAR_FLAG(F_CF);
7896 CLEAR_FLAG(F_SF);
7897 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
7898 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
7899
7900 emu->x86.R_AX = (uint16_t) div;
7901 emu->x86.R_DX = (uint16_t) mod;
7902}
7903/****************************************************************************
7904REMARKS:
7905Implements the DIV instruction and side effects.
7906****************************************************************************/
7907static void
7908div_long(struct X86EMU *emu, uint32_t s)
7909{
7910 uint64_t dvd, div, mod;
7911
7912 dvd = (((uint64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
7913 if (s == 0) {
7914 x86emu_intr_raise(emu, 8);
7915 return;
7916 }
7917 div = dvd / (uint32_t) s;
7918 mod = dvd % (uint32_t) s;
7919 if (div > 0xffffffff) {
7920 x86emu_intr_raise(emu, 8);
7921 return;
7922 }
7923 CLEAR_FLAG(F_CF);
7924 CLEAR_FLAG(F_AF);
7925 CLEAR_FLAG(F_SF);
7926 SET_FLAG(F_ZF);
7927 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
7928
7929 emu->x86.R_EAX = (uint32_t) div;
7930 emu->x86.R_EDX = (uint32_t) mod;
7931}
7932/****************************************************************************
7933REMARKS:
7934Implements the IN string instruction and side effects.
7935****************************************************************************/
7936static void
7937ins(struct X86EMU *emu, int size)
7938{
7939 int inc = size;
7940
7941 if (ACCESS_FLAG(F_DF)) {
7942 inc = -size;
7943 }
7944 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
7945 /* dont care whether REPE or REPNE */
7946 /* in until CX is ZERO. */
7947 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
7948 emu->x86.R_ECX : emu->x86.R_CX);
7949 switch (size) {
7950 case 1:
7951 while (count--) {
7952 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
7953 (*emu->emu_inb) (emu, emu->x86.R_DX));
7954 emu->x86.R_DI += inc;
7955 }
7956 break;
7957
7958 case 2:
7959 while (count--) {
7960 store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
7961 (*emu->emu_inw) (emu, emu->x86.R_DX));
7962 emu->x86.R_DI += inc;
7963 }
7964 break;
7965 case 4:
7966 while (count--) {
7967 store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
7968 (*emu->emu_inl) (emu, emu->x86.R_DX));
7969 emu->x86.R_DI += inc;
7970 break;
7971 }
7972 }
7973 emu->x86.R_CX = 0;
7974 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
7975 emu->x86.R_ECX = 0;
7976 }
7977 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
7978 } else {
7979 switch (size) {
7980 case 1:
7981 store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
7982 (*emu->emu_inb) (emu, emu->x86.R_DX));
7983 break;
7984 case 2:
7985 store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
7986 (*emu->emu_inw) (emu, emu->x86.R_DX));
7987 break;
7988 case 4:
7989 store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
7990 (*emu->emu_inl) (emu, emu->x86.R_DX));
7991 break;
7992 }
7993 emu->x86.R_DI += inc;
7994 }
7995}
7996/****************************************************************************
7997REMARKS:
7998Implements the OUT string instruction and side effects.
7999****************************************************************************/
8000static void
8001outs(struct X86EMU *emu, int size)
8002{
8003 int inc = size;
8004
8005 if (ACCESS_FLAG(F_DF)) {
8006 inc = -size;
8007 }
8008 if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
8009 /* dont care whether REPE or REPNE */
8010 /* out until CX is ZERO. */
8011 uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
8012 emu->x86.R_ECX : emu->x86.R_CX);
8013 switch (size) {
8014 case 1:
8015 while (count--) {
8016 (*emu->emu_outb) (emu, emu->x86.R_DX,
8017 fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI));
8018 emu->x86.R_SI += inc;
8019 }
8020 break;
8021
8022 case 2:
8023 while (count--) {
8024 (*emu->emu_outw) (emu, emu->x86.R_DX,
8025 fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI));
8026 emu->x86.R_SI += inc;
8027 }
8028 break;
8029 case 4:
8030 while (count--) {
8031 (*emu->emu_outl) (emu, emu->x86.R_DX,
8032 fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI));
8033 emu->x86.R_SI += inc;
8034 break;
8035 }
8036 }
8037 emu->x86.R_CX = 0;
8038 if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
8039 emu->x86.R_ECX = 0;
8040 }
8041 emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
8042 } else {
8043 switch (size) {
8044 case 1:
8045 (*emu->emu_outb) (emu, emu->x86.R_DX,
8046 fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI));
8047 break;
8048 case 2:
8049 (*emu->emu_outw) (emu, emu->x86.R_DX,
8050 fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI));
8051 break;
8052 case 4:
8053 (*emu->emu_outl) (emu, emu->x86.R_DX,
8054 fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI));
8055 break;
8056 }
8057 emu->x86.R_SI += inc;
8058 }
8059}
8060/****************************************************************************
8061REMARKS:
8062Pushes a word onto the stack.
8063
8064NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8065****************************************************************************/
8066static void
8067push_word(struct X86EMU *emu, uint16_t w)
8068{
8069 emu->x86.R_SP -= 2;
8070 store_word(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8071}
8072/****************************************************************************
8073REMARKS:
8074Pushes a long onto the stack.
8075
8076NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8077****************************************************************************/
8078static void
8079push_long(struct X86EMU *emu, uint32_t w)
8080{
8081 emu->x86.R_SP -= 4;
8082 store_long(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8083}
8084/****************************************************************************
8085REMARKS:
8086Pops a word from the stack.
8087
8088NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8089****************************************************************************/
8090static uint16_t
8091pop_word(struct X86EMU *emu)
8092{
8093 uint16_t res;
8094
8095 res = fetch_word(emu, emu->x86.R_SS, emu->x86.R_SP);
8096 emu->x86.R_SP += 2;
8097 return res;
8098}
8099/****************************************************************************
8100REMARKS:
8101Pops a long from the stack.
8102
8103NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8104****************************************************************************/
8105static uint32_t
8106pop_long(struct X86EMU *emu)
8107{
8108 uint32_t res;
8109
8110 res = fetch_long(emu, emu->x86.R_SS, emu->x86.R_SP);
8111 emu->x86.R_SP += 4;
8112 return res;
8113}
8114