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