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