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