]> git.sur5r.net Git - u-boot/blob - board/MAI/bios_emulator/scitech/src/x86emu/prim_ops.c
* Code cleanup:
[u-boot] / board / MAI / bios_emulator / scitech / src / x86emu / prim_ops.c
1 /****************************************************************************
2 *
3 *                                               Realmode X86 Emulator Library
4 *
5 *               Copyright (C) 1996-1999 SciTech Software, Inc.
6 *                                    Copyright (C) David Mosberger-Tang
7 *                                          Copyright (C) 1999 Egbert Eich
8 *
9 *  ========================================================================
10 *
11 *  Permission to use, copy, modify, distribute, and sell this software and
12 *  its documentation for any purpose is hereby granted without fee,
13 *  provided that the above copyright notice appear in all copies and that
14 *  both that copyright notice and this permission notice appear in
15 *  supporting documentation, and that the name of the authors not be used
16 *  in advertising or publicity pertaining to distribution of the software
17 *  without specific, written prior permission.  The authors makes no
18 *  representations about the suitability of this software for any purpose.
19 *  It is provided "as is" without express or implied warranty.
20 *
21 *  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22 *  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23 *  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24 *  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
25 *  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26 *  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27 *  PERFORMANCE OF THIS SOFTWARE.
28 *
29 *  ========================================================================
30 *
31 * Language:             ANSI C
32 * Environment:  Any
33 * Developer:    Kendall Bennett
34 *
35 * Description:  This file contains the code to implement the primitive
36 *                               machine operations used by the emulation code in ops.c
37 *
38 * Carry Chain Calculation
39 *
40 * This represents a somewhat expensive calculation which is
41 * apparently required to emulate the setting of the OF and AF flag.
42 * The latter is not so important, but the former is.  The overflow
43 * flag is the XOR of the top two bits of the carry chain for an
44 * addition (similar for subtraction).  Since we do not want to
45 * simulate the addition in a bitwise manner, we try to calculate the
46 * carry chain given the two operands and the result.
47 *
48 * So, given the following table, which represents the addition of two
49 * bits, we can derive a formula for the carry chain.
50 *
51 * a   b   cin   r     cout
52 * 0   0   0     0     0
53 * 0   0   1     1     0
54 * 0   1   0     1     0
55 * 0   1   1     0     1
56 * 1   0   0     1     0
57 * 1   0   1     0     1
58 * 1   1   0     0     1
59 * 1   1   1     1     1
60 *
61 * Construction of table for cout:
62 *
63 * ab
64 * r  \  00   01   11  10
65 * |------------------
66 * 0  |   0    1    1   1
67 * 1  |   0    0    1   0
68 *
69 * By inspection, one gets:  cc = ab +  r'(a + b)
70 *
71 * That represents alot of operations, but NO CHOICE....
72 *
73 * Borrow Chain Calculation.
74 *
75 * The following table represents the subtraction of two bits, from
76 * which we can derive a formula for the borrow chain.
77 *
78 * a   b   bin   r     bout
79 * 0   0   0     0     0
80 * 0   0   1     1     1
81 * 0   1   0     1     1
82 * 0   1   1     0     1
83 * 1   0   0     1     0
84 * 1   0   1     0     0
85 * 1   1   0     0     0
86 * 1   1   1     1     1
87 *
88 * Construction of table for cout:
89 *
90 * ab
91 * r  \  00   01   11  10
92 * |------------------
93 * 0  |   0    1    0   0
94 * 1  |   1    1    1   0
95 *
96 * By inspection, one gets:  bc = a'b +  r(a' + b)
97 *
98 ****************************************************************************/
99
100 #define PRIM_OPS_NO_REDEFINE_ASM
101 #include "x86emu/x86emui.h"
102
103 /*------------------------- Global Variables ------------------------------*/
104
105 #ifndef __HAVE_INLINE_ASSEMBLER__
106
107 static u32 x86emu_parity_tab[8] =
108 {
109         0x96696996,
110         0x69969669,
111         0x69969669,
112         0x96696996,
113         0x69969669,
114         0x96696996,
115         0x96696996,
116         0x69969669,
117 };
118
119 #endif
120
121 #define PARITY(x)   (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
122 #define XOR2(x)         (((x) ^ ((x)>>1)) & 0x1)
123
124 /*----------------------------- Implementation ----------------------------*/
125
126 #ifndef __HAVE_INLINE_ASSEMBLER__
127
128 /****************************************************************************
129 REMARKS:
130 Implements the AAA instruction and side effects.
131 ****************************************************************************/
132 u16 aaa_word(u16 d)
133 {
134         u16     res;
135         if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
136                 d += 0x6;
137                 d += 0x100;
138                 SET_FLAG(F_AF);
139                 SET_FLAG(F_CF);
140         } else {
141                 CLEAR_FLAG(F_CF);
142                 CLEAR_FLAG(F_AF);
143         }
144         res = (u16)(d & 0xFF0F);
145         CLEAR_FLAG(F_SF);
146         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
147         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
148         return res;
149 }
150
151 /****************************************************************************
152 REMARKS:
153 Implements the AAA instruction and side effects.
154 ****************************************************************************/
155 u16 aas_word(u16 d)
156 {
157         u16     res;
158         if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
159                 d -= 0x6;
160                 d -= 0x100;
161                 SET_FLAG(F_AF);
162                 SET_FLAG(F_CF);
163         } else {
164                 CLEAR_FLAG(F_CF);
165                 CLEAR_FLAG(F_AF);
166         }
167         res = (u16)(d & 0xFF0F);
168         CLEAR_FLAG(F_SF);
169         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
170         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
171         return res;
172 }
173
174 /****************************************************************************
175 REMARKS:
176 Implements the AAD instruction and side effects.
177 ****************************************************************************/
178 u16 aad_word(u16 d)
179 {
180         u16 l;
181         u8 hb, lb;
182
183         hb = (u8)((d >> 8) & 0xff);
184         lb = (u8)((d & 0xff));
185         l = (u16)((lb + 10 * hb) & 0xFF);
186
187         CLEAR_FLAG(F_CF);
188         CLEAR_FLAG(F_AF);
189         CLEAR_FLAG(F_OF);
190         CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
191         CONDITIONAL_SET_FLAG(l == 0, F_ZF);
192         CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
193         return l;
194 }
195
196 /****************************************************************************
197 REMARKS:
198 Implements the AAM instruction and side effects.
199 ****************************************************************************/
200 u16 aam_word(u8 d)
201 {
202     u16 h, l;
203
204         h = (u16)(d / 10);
205         l = (u16)(d % 10);
206         l |= (u16)(h << 8);
207
208         CLEAR_FLAG(F_CF);
209         CLEAR_FLAG(F_AF);
210         CLEAR_FLAG(F_OF);
211         CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
212         CONDITIONAL_SET_FLAG(l == 0, F_ZF);
213         CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
214     return l;
215 }
216
217 /****************************************************************************
218 REMARKS:
219 Implements the ADC instruction and side effects.
220 ****************************************************************************/
221 u8 adc_byte(u8 d, u8 s)
222 {
223         register u32 res;   /* all operands in native machine order */
224         register u32 cc;
225
226         if (ACCESS_FLAG(F_CF))
227                 res = 1 + d + s;
228         else
229                 res = d + s;
230
231         CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
232         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
233         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
234         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
235
236         /* calculate the carry chain  SEE NOTE AT TOP. */
237         cc = (s & d) | ((~res) & (s | d));
238         CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
239         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
240         return (u8)res;
241 }
242
243 /****************************************************************************
244 REMARKS:
245 Implements the ADC instruction and side effects.
246 ****************************************************************************/
247 u16 adc_word(u16 d, u16 s)
248 {
249         register u32 res;   /* all operands in native machine order */
250         register u32 cc;
251
252         if (ACCESS_FLAG(F_CF))
253                 res = 1 + d + s;
254         else
255                 res = d + s;
256
257         CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
258         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
259         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
260         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
261
262         /* calculate the carry chain  SEE NOTE AT TOP. */
263         cc = (s & d) | ((~res) & (s | d));
264         CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
265         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
266         return (u16)res;
267 }
268
269 /****************************************************************************
270 REMARKS:
271 Implements the ADC instruction and side effects.
272 ****************************************************************************/
273 u32 adc_long(u32 d, u32 s)
274 {
275         register u32 lo;        /* all operands in native machine order */
276         register u32 hi;
277         register u32 res;
278         register u32 cc;
279
280         if (ACCESS_FLAG(F_CF)) {
281                 lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
282                 res = 1 + d + s;
283                 }
284         else {
285                 lo = (d & 0xFFFF) + (s & 0xFFFF);
286                 res = d + s;
287                 }
288         hi = (lo >> 16) + (d >> 16) + (s >> 16);
289
290         CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
291         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
292         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
293         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
294
295         /* calculate the carry chain  SEE NOTE AT TOP. */
296         cc = (s & d) | ((~res) & (s | d));
297         CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
298         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
299         return res;
300 }
301
302 /****************************************************************************
303 REMARKS:
304 Implements the ADD instruction and side effects.
305 ****************************************************************************/
306 u8 add_byte(u8 d, u8 s)
307 {
308         register u32 res;   /* all operands in native machine order */
309         register u32 cc;
310
311         res = d + s;
312         CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
313         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
314         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
315         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
316
317         /* calculate the carry chain  SEE NOTE AT TOP. */
318         cc = (s & d) | ((~res) & (s | d));
319         CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
320         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
321         return (u8)res;
322 }
323
324 /****************************************************************************
325 REMARKS:
326 Implements the ADD instruction and side effects.
327 ****************************************************************************/
328 u16 add_word(u16 d, u16 s)
329 {
330         register u32 res;   /* all operands in native machine order */
331         register u32 cc;
332
333         res = d + s;
334         CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
335         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
336         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
337         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
338
339         /* calculate the carry chain  SEE NOTE AT TOP. */
340         cc = (s & d) | ((~res) & (s | d));
341         CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
342         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
343         return (u16)res;
344 }
345
346 /****************************************************************************
347 REMARKS:
348 Implements the ADD instruction and side effects.
349 ****************************************************************************/
350 u32 add_long(u32 d, u32 s)
351 {
352         register u32 lo;        /* all operands in native machine order */
353         register u32 hi;
354         register u32 res;
355         register u32 cc;
356
357         lo = (d & 0xFFFF) + (s & 0xFFFF);
358         res = d + s;
359         hi = (lo >> 16) + (d >> 16) + (s >> 16);
360
361         CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
362         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
363         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
364         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
365
366     /* calculate the carry chain  SEE NOTE AT TOP. */
367     cc = (s & d) | ((~res) & (s | d));
368         CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
369         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
370
371     return res;
372 }
373
374 /****************************************************************************
375 REMARKS:
376 Implements the AND instruction and side effects.
377 ****************************************************************************/
378 u8 and_byte(u8 d, u8 s)
379 {
380         register u8 res;    /* all operands in native machine order */
381
382         res = d & s;
383
384         /* set the flags  */
385         CLEAR_FLAG(F_OF);
386         CLEAR_FLAG(F_CF);
387         CLEAR_FLAG(F_AF);
388         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
389         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
390         CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
391         return res;
392 }
393
394 /****************************************************************************
395 REMARKS:
396 Implements the AND instruction and side effects.
397 ****************************************************************************/
398 u16 and_word(u16 d, u16 s)
399 {
400     register u16 res;   /* all operands in native machine order */
401
402     res = d & s;
403
404     /* set the flags  */
405         CLEAR_FLAG(F_OF);
406         CLEAR_FLAG(F_CF);
407         CLEAR_FLAG(F_AF);
408         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
409         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
410         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
411     return res;
412 }
413
414 /****************************************************************************
415 REMARKS:
416 Implements the AND instruction and side effects.
417 ****************************************************************************/
418 u32 and_long(u32 d, u32 s)
419 {
420         register u32 res;   /* all operands in native machine order */
421
422         res = d & s;
423
424         /* set the flags  */
425         CLEAR_FLAG(F_OF);
426         CLEAR_FLAG(F_CF);
427         CLEAR_FLAG(F_AF);
428         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
429         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
430         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
431         return res;
432 }
433
434 /****************************************************************************
435 REMARKS:
436 Implements the CMP instruction and side effects.
437 ****************************************************************************/
438 u8 cmp_byte(u8 d, u8 s)
439 {
440         register u32 res;   /* all operands in native machine order */
441         register u32 bc;
442
443         res = d - s;
444         CLEAR_FLAG(F_CF);
445         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
446         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
447         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
448
449         /* calculate the borrow chain.  See note at top */
450         bc = (res & (~d | s)) | (~d & s);
451         CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
452         CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
453         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
454         return d;
455 }
456
457 /****************************************************************************
458 REMARKS:
459 Implements the CMP instruction and side effects.
460 ****************************************************************************/
461 u16 cmp_word(u16 d, u16 s)
462 {
463         register u32 res;   /* all operands in native machine order */
464         register u32 bc;
465
466         res = d - s;
467         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
468         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
469         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
470
471         /* calculate the borrow chain.  See note at top */
472     bc = (res & (~d | s)) | (~d & s);
473         CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
474         CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
475         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
476         return d;
477 }
478
479 /****************************************************************************
480 REMARKS:
481 Implements the CMP instruction and side effects.
482 ****************************************************************************/
483 u32 cmp_long(u32 d, u32 s)
484 {
485         register u32 res;   /* all operands in native machine order */
486         register u32 bc;
487
488         res = d - s;
489         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
490         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
491         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
492
493         /* calculate the borrow chain.  See note at top */
494         bc = (res & (~d | s)) | (~d & s);
495         CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
496         CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
497         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
498         return d;
499 }
500
501 /****************************************************************************
502 REMARKS:
503 Implements the DAA instruction and side effects.
504 ****************************************************************************/
505 u8 daa_byte(u8 d)
506 {
507         u32 res = d;
508         if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
509                 res += 6;
510                 SET_FLAG(F_AF);
511         }
512         if (res > 0x9F || ACCESS_FLAG(F_CF)) {
513                 res += 0x60;
514                 SET_FLAG(F_CF);
515         }
516         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
517         CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
518         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
519         return (u8)res;
520 }
521
522 /****************************************************************************
523 REMARKS:
524 Implements the DAS instruction and side effects.
525 ****************************************************************************/
526 u8 das_byte(u8 d)
527 {
528         if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
529                 d -= 6;
530                 SET_FLAG(F_AF);
531         }
532         if (d > 0x9F || ACCESS_FLAG(F_CF)) {
533                 d -= 0x60;
534                 SET_FLAG(F_CF);
535         }
536         CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
537         CONDITIONAL_SET_FLAG(d == 0, F_ZF);
538         CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
539         return d;
540 }
541
542 /****************************************************************************
543 REMARKS:
544 Implements the DEC instruction and side effects.
545 ****************************************************************************/
546 u8 dec_byte(u8 d)
547 {
548     register u32 res;   /* all operands in native machine order */
549     register u32 bc;
550
551     res = d - 1;
552         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
553         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
554         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
555
556         /* calculate the borrow chain.  See note at top */
557         /* based on sub_byte, uses s==1.  */
558         bc = (res & (~d | 1)) | (~d & 1);
559         /* carry flag unchanged */
560         CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
561         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
562         return (u8)res;
563 }
564
565 /****************************************************************************
566 REMARKS:
567 Implements the DEC instruction and side effects.
568 ****************************************************************************/
569 u16 dec_word(u16 d)
570 {
571     register u32 res;   /* all operands in native machine order */
572     register u32 bc;
573
574     res = d - 1;
575         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
576         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
577         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
578
579     /* calculate the borrow chain.  See note at top */
580     /* based on the sub_byte routine, with s==1 */
581     bc = (res & (~d | 1)) | (~d & 1);
582     /* carry flag unchanged */
583         CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
584         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
585         return (u16)res;
586 }
587
588 /****************************************************************************
589 REMARKS:
590 Implements the DEC instruction and side effects.
591 ****************************************************************************/
592 u32 dec_long(u32 d)
593 {
594     register u32 res;   /* all operands in native machine order */
595     register u32 bc;
596
597     res = d - 1;
598
599         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
600         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
601         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
602
603     /* calculate the borrow chain.  See note at top */
604         bc = (res & (~d | 1)) | (~d & 1);
605         /* carry flag unchanged */
606         CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
607         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
608         return res;
609 }
610
611 /****************************************************************************
612 REMARKS:
613 Implements the INC instruction and side effects.
614 ****************************************************************************/
615 u8 inc_byte(u8 d)
616 {
617         register u32 res;   /* all operands in native machine order */
618         register u32 cc;
619
620         res = d + 1;
621         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
622         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
623         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
624
625         /* calculate the carry chain  SEE NOTE AT TOP. */
626         cc = ((1 & d) | (~res)) & (1 | d);
627         CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
628         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
629         return (u8)res;
630 }
631
632 /****************************************************************************
633 REMARKS:
634 Implements the INC instruction and side effects.
635 ****************************************************************************/
636 u16 inc_word(u16 d)
637 {
638         register u32 res;   /* all operands in native machine order */
639         register u32 cc;
640
641         res = d + 1;
642         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
643         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
644         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
645
646         /* calculate the carry chain  SEE NOTE AT TOP. */
647         cc = (1 & d) | ((~res) & (1 | d));
648         CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
649         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
650         return (u16)res;
651 }
652
653 /****************************************************************************
654 REMARKS:
655 Implements the INC instruction and side effects.
656 ****************************************************************************/
657 u32 inc_long(u32 d)
658 {
659         register u32 res;   /* all operands in native machine order */
660         register u32 cc;
661
662         res = d + 1;
663         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
664         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
665         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
666
667         /* calculate the carry chain  SEE NOTE AT TOP. */
668         cc = (1 & d) | ((~res) & (1 | d));
669         CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
670         CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
671         return res;
672 }
673
674 /****************************************************************************
675 REMARKS:
676 Implements the OR instruction and side effects.
677 ****************************************************************************/
678 u8 or_byte(u8 d, u8 s)
679 {
680         register u8 res;    /* all operands in native machine order */
681
682         res = d | s;
683         CLEAR_FLAG(F_OF);
684         CLEAR_FLAG(F_CF);
685         CLEAR_FLAG(F_AF);
686         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
687         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
688         CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
689         return res;
690 }
691
692 /****************************************************************************
693 REMARKS:
694 Implements the OR instruction and side effects.
695 ****************************************************************************/
696 u16 or_word(u16 d, u16 s)
697 {
698         register u16 res;   /* all operands in native machine order */
699
700         res = d | s;
701         /* set the carry flag to be bit 8 */
702         CLEAR_FLAG(F_OF);
703         CLEAR_FLAG(F_CF);
704         CLEAR_FLAG(F_AF);
705         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
706         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
707         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
708         return res;
709 }
710
711 /****************************************************************************
712 REMARKS:
713 Implements the OR instruction and side effects.
714 ****************************************************************************/
715 u32 or_long(u32 d, u32 s)
716 {
717         register u32 res;   /* all operands in native machine order */
718
719         res = d | s;
720
721         /* set the carry flag to be bit 8 */
722         CLEAR_FLAG(F_OF);
723         CLEAR_FLAG(F_CF);
724         CLEAR_FLAG(F_AF);
725         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
726         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
727         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
728         return res;
729 }
730
731 /****************************************************************************
732 REMARKS:
733 Implements the OR instruction and side effects.
734 ****************************************************************************/
735 u8 neg_byte(u8 s)
736 {
737     register u8 res;
738     register u8 bc;
739
740         CONDITIONAL_SET_FLAG(s != 0, F_CF);
741         res = (u8)-s;
742         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
743         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
744         CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
745         /* calculate the borrow chain --- modified such that d=0.
746            substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
747            (the one used for sub) and simplifying, since ~d=0xff...,
748            ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
749            ~d&s == s.  So the simplified result is: */
750         bc = res | s;
751         CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
752         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
753         return res;
754 }
755
756 /****************************************************************************
757 REMARKS:
758 Implements the OR instruction and side effects.
759 ****************************************************************************/
760 u16 neg_word(u16 s)
761 {
762         register u16 res;
763         register u16 bc;
764
765         CONDITIONAL_SET_FLAG(s != 0, F_CF);
766         res = (u16)-s;
767         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
768         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
769         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
770
771         /* calculate the borrow chain --- modified such that d=0.
772            substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
773            (the one used for sub) and simplifying, since ~d=0xff...,
774            ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
775            ~d&s == s.  So the simplified result is: */
776         bc = res | s;
777         CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
778         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
779         return res;
780 }
781
782 /****************************************************************************
783 REMARKS:
784 Implements the OR instruction and side effects.
785 ****************************************************************************/
786 u32 neg_long(u32 s)
787 {
788         register u32 res;
789         register u32 bc;
790
791         CONDITIONAL_SET_FLAG(s != 0, F_CF);
792         res = (u32)-s;
793         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
794         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
795         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
796
797         /* calculate the borrow chain --- modified such that d=0.
798            substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
799            (the one used for sub) and simplifying, since ~d=0xff...,
800            ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
801            ~d&s == s.  So the simplified result is: */
802         bc = res | s;
803         CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
804         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
805         return res;
806 }
807
808 /****************************************************************************
809 REMARKS:
810 Implements the NOT instruction and side effects.
811 ****************************************************************************/
812 u8 not_byte(u8 s)
813 {
814         return ~s;
815 }
816
817 /****************************************************************************
818 REMARKS:
819 Implements the NOT instruction and side effects.
820 ****************************************************************************/
821 u16 not_word(u16 s)
822 {
823         return ~s;
824 }
825
826 /****************************************************************************
827 REMARKS:
828 Implements the NOT instruction and side effects.
829 ****************************************************************************/
830 u32 not_long(u32 s)
831 {
832         return ~s;
833 }
834
835 /****************************************************************************
836 REMARKS:
837 Implements the RCL instruction and side effects.
838 ****************************************************************************/
839 u8 rcl_byte(u8 d, u8 s)
840 {
841     register unsigned int res, cnt, mask, cf;
842
843     /* s is the rotate distance.  It varies from 0 - 8. */
844         /* have
845
846        CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
847
848        want to rotate through the carry by "s" bits.  We could
849        loop, but that's inefficient.  So the width is 9,
850        and we split into three parts:
851
852        The new carry flag   (was B_n)
853        the stuff in B_n-1 .. B_0
854        the stuff in B_7 .. B_n+1
855
856        The new rotate is done mod 9, and given this,
857        for a rotation of n bits (mod 9) the new carry flag is
858        then located n bits from the MSB.  The low part is
859        then shifted up cnt bits, and the high part is or'd
860        in.  Using CAPS for new values, and lowercase for the
861        original values, this can be expressed as:
862
863        IF n > 0
864        1) CF <-  b_(8-n)
865        2) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0
866        3) B_(n-1) <- cf
867        4) B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1))
868          */
869         res = d;
870         if ((cnt = s % 9) != 0) {
871         /* extract the new CARRY FLAG. */
872         /* CF <-  b_(8-n)             */
873         cf = (d >> (8 - cnt)) & 0x1;
874
875         /* get the low stuff which rotated
876            into the range B_7 .. B_cnt */
877         /* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0  */
878         /* note that the right hand side done by the mask */
879                 res = (d << cnt) & 0xff;
880
881         /* now the high stuff which rotated around
882            into the positions B_cnt-2 .. B_0 */
883         /* B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1)) */
884         /* shift it downward, 7-(n-2) = 9-n positions.
885            and mask off the result before or'ing in.
886          */
887         mask = (1 << (cnt - 1)) - 1;
888         res |= (d >> (9 - cnt)) & mask;
889
890         /* if the carry flag was set, or it in.  */
891                 if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
892             /*  B_(n-1) <- cf */
893             res |= 1 << (cnt - 1);
894         }
895         /* set the new carry flag, based on the variable "cf" */
896                 CONDITIONAL_SET_FLAG(cf, F_CF);
897         /* OVERFLOW is set *IFF* cnt==1, then it is the
898            xor of CF and the most significant bit.  Blecck. */
899         /* parenthesized this expression since it appears to
900            be causing OF to be misset */
901         CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
902                                                          F_OF);
903
904     }
905         return (u8)res;
906 }
907
908 /****************************************************************************
909 REMARKS:
910 Implements the RCL instruction and side effects.
911 ****************************************************************************/
912 u16 rcl_word(u16 d, u8 s)
913 {
914         register unsigned int res, cnt, mask, cf;
915
916         res = d;
917         if ((cnt = s % 17) != 0) {
918                 cf = (d >> (16 - cnt)) & 0x1;
919                 res = (d << cnt) & 0xffff;
920                 mask = (1 << (cnt - 1)) - 1;
921                 res |= (d >> (17 - cnt)) & mask;
922                 if (ACCESS_FLAG(F_CF)) {
923                         res |= 1 << (cnt - 1);
924                 }
925                 CONDITIONAL_SET_FLAG(cf, F_CF);
926                 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
927                                                          F_OF);
928         }
929         return (u16)res;
930 }
931
932 /****************************************************************************
933 REMARKS:
934 Implements the RCL instruction and side effects.
935 ****************************************************************************/
936 u32 rcl_long(u32 d, u8 s)
937 {
938         register u32 res, cnt, mask, cf;
939
940         res = d;
941         if ((cnt = s % 33) != 0) {
942                 cf = (d >> (32 - cnt)) & 0x1;
943                 res = (d << cnt) & 0xffffffff;
944                 mask = (1 << (cnt - 1)) - 1;
945                 res |= (d >> (33 - cnt)) & mask;
946                 if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
947                         res |= 1 << (cnt - 1);
948                 }
949                 CONDITIONAL_SET_FLAG(cf, F_CF);
950                 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
951                                                          F_OF);
952         }
953         return res;
954 }
955
956 /****************************************************************************
957 REMARKS:
958 Implements the RCR instruction and side effects.
959 ****************************************************************************/
960 u8 rcr_byte(u8 d, u8 s)
961 {
962         u32     res, cnt;
963         u32     mask, cf, ocf = 0;
964
965         /* rotate right through carry */
966     /*
967        s is the rotate distance.  It varies from 0 - 8.
968        d is the byte object rotated.
969
970        have
971
972        CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
973
974        The new rotate is done mod 9, and given this,
975        for a rotation of n bits (mod 9) the new carry flag is
976        then located n bits from the LSB.  The low part is
977        then shifted up cnt bits, and the high part is or'd
978        in.  Using CAPS for new values, and lowercase for the
979        original values, this can be expressed as:
980
981        IF n > 0
982        1) CF <-  b_(n-1)
983        2) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
984        3) B_(8-n) <- cf
985        4) B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0)
986          */
987         res = d;
988         if ((cnt = s % 9) != 0) {
989         /* extract the new CARRY FLAG. */
990         /* CF <-  b_(n-1)              */
991         if (cnt == 1) {
992             cf = d & 0x1;
993             /* note hackery here.  Access_flag(..) evaluates to either
994                0 if flag not set
995                non-zero if flag is set.
996                doing access_flag(..) != 0 casts that into either
997                            0..1 in any representation of the flags register
998                (i.e. packed bit array or unpacked.)
999              */
1000                         ocf = ACCESS_FLAG(F_CF) != 0;
1001         } else
1002             cf = (d >> (cnt - 1)) & 0x1;
1003
1004         /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_n  */
1005         /* note that the right hand side done by the mask
1006            This is effectively done by shifting the
1007            object to the right.  The result must be masked,
1008            in case the object came in and was treated
1009            as a negative number.  Needed??? */
1010
1011         mask = (1 << (8 - cnt)) - 1;
1012         res = (d >> cnt) & mask;
1013
1014         /* now the high stuff which rotated around
1015            into the positions B_cnt-2 .. B_0 */
1016         /* B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0) */
1017         /* shift it downward, 7-(n-2) = 9-n positions.
1018            and mask off the result before or'ing in.
1019          */
1020         res |= (d << (9 - cnt));
1021
1022         /* if the carry flag was set, or it in.  */
1023                 if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
1024             /*  B_(8-n) <- cf */
1025             res |= 1 << (8 - cnt);
1026         }
1027         /* set the new carry flag, based on the variable "cf" */
1028                 CONDITIONAL_SET_FLAG(cf, F_CF);
1029         /* OVERFLOW is set *IFF* cnt==1, then it is the
1030            xor of CF and the most significant bit.  Blecck. */
1031         /* parenthesized... */
1032                 if (cnt == 1) {
1033                         CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
1034                                                                  F_OF);
1035                 }
1036         }
1037         return (u8)res;
1038 }
1039
1040 /****************************************************************************
1041 REMARKS:
1042 Implements the RCR instruction and side effects.
1043 ****************************************************************************/
1044 u16 rcr_word(u16 d, u8 s)
1045 {
1046         u32 res, cnt;
1047         u32     mask, cf, ocf = 0;
1048
1049         /* rotate right through carry */
1050         res = d;
1051         if ((cnt = s % 17) != 0) {
1052                 if (cnt == 1) {
1053                         cf = d & 0x1;
1054                         ocf = ACCESS_FLAG(F_CF) != 0;
1055                 } else
1056                         cf = (d >> (cnt - 1)) & 0x1;
1057                 mask = (1 << (16 - cnt)) - 1;
1058                 res = (d >> cnt) & mask;
1059                 res |= (d << (17 - cnt));
1060                 if (ACCESS_FLAG(F_CF)) {
1061                         res |= 1 << (16 - cnt);
1062                 }
1063                 CONDITIONAL_SET_FLAG(cf, F_CF);
1064                 if (cnt == 1) {
1065                         CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
1066                                                                  F_OF);
1067                 }
1068         }
1069         return (u16)res;
1070 }
1071
1072 /****************************************************************************
1073 REMARKS:
1074 Implements the RCR instruction and side effects.
1075 ****************************************************************************/
1076 u32 rcr_long(u32 d, u8 s)
1077 {
1078         u32 res, cnt;
1079         u32 mask, cf, ocf = 0;
1080
1081         /* rotate right through carry */
1082         res = d;
1083         if ((cnt = s % 33) != 0) {
1084                 if (cnt == 1) {
1085                         cf = d & 0x1;
1086                         ocf = ACCESS_FLAG(F_CF) != 0;
1087                 } else
1088                         cf = (d >> (cnt - 1)) & 0x1;
1089                 mask = (1 << (32 - cnt)) - 1;
1090                 res = (d >> cnt) & mask;
1091                 if (cnt != 1)
1092                         res |= (d << (33 - cnt));
1093                 if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
1094                         res |= 1 << (32 - cnt);
1095                 }
1096                 CONDITIONAL_SET_FLAG(cf, F_CF);
1097                 if (cnt == 1) {
1098                         CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
1099                                                                  F_OF);
1100                 }
1101         }
1102         return res;
1103 }
1104
1105 /****************************************************************************
1106 REMARKS:
1107 Implements the ROL instruction and side effects.
1108 ****************************************************************************/
1109 u8 rol_byte(u8 d, u8 s)
1110 {
1111     register unsigned int res, cnt, mask;
1112
1113     /* rotate left */
1114     /*
1115        s is the rotate distance.  It varies from 0 - 8.
1116        d is the byte object rotated.
1117
1118        have
1119
1120        CF  B_7 ... B_0
1121
1122        The new rotate is done mod 8.
1123        Much simpler than the "rcl" or "rcr" operations.
1124
1125        IF n > 0
1126        1) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0)
1127        2) B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n)
1128          */
1129     res = d;
1130         if ((cnt = s % 8) != 0) {
1131                 /* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) */
1132                 res = (d << cnt);
1133
1134                 /* B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n) */
1135                 mask = (1 << cnt) - 1;
1136                 res |= (d >> (8 - cnt)) & mask;
1137
1138                 /* set the new carry flag, Note that it is the low order
1139                    bit of the result!!!                               */
1140                 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1141                 /* OVERFLOW is set *IFF* s==1, then it is the
1142                    xor of CF and the most significant bit.  Blecck. */
1143                 CONDITIONAL_SET_FLAG(s == 1 &&
1144                                                          XOR2((res & 0x1) + ((res >> 6) & 0x2)),
1145                                                          F_OF);
1146         } if (s != 0) {
1147                 /* set the new carry flag, Note that it is the low order
1148                    bit of the result!!!                               */
1149                 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1150         }
1151         return (u8)res;
1152 }
1153
1154 /****************************************************************************
1155 REMARKS:
1156 Implements the ROL instruction and side effects.
1157 ****************************************************************************/
1158 u16 rol_word(u16 d, u8 s)
1159 {
1160     register unsigned int res, cnt, mask;
1161
1162         res = d;
1163         if ((cnt = s % 16) != 0) {
1164                 res = (d << cnt);
1165                 mask = (1 << cnt) - 1;
1166                 res |= (d >> (16 - cnt)) & mask;
1167                 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1168                 CONDITIONAL_SET_FLAG(s == 1 &&
1169                                                          XOR2((res & 0x1) + ((res >> 14) & 0x2)),
1170                                                          F_OF);
1171         } if (s != 0) {
1172                 /* set the new carry flag, Note that it is the low order
1173                    bit of the result!!!                               */
1174                 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1175         }
1176         return (u16)res;
1177 }
1178
1179 /****************************************************************************
1180 REMARKS:
1181 Implements the ROL instruction and side effects.
1182 ****************************************************************************/
1183 u32 rol_long(u32 d, u8 s)
1184 {
1185     register u32 res, cnt, mask;
1186
1187         res = d;
1188         if ((cnt = s % 32) != 0) {
1189                 res = (d << cnt);
1190                 mask = (1 << cnt) - 1;
1191                 res |= (d >> (32 - cnt)) & mask;
1192                 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1193                 CONDITIONAL_SET_FLAG(s == 1 &&
1194                                                          XOR2((res & 0x1) + ((res >> 30) & 0x2)),
1195                                                          F_OF);
1196         } if (s != 0) {
1197                 /* set the new carry flag, Note that it is the low order
1198                    bit of the result!!!                               */
1199                 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1200         }
1201         return res;
1202 }
1203
1204 /****************************************************************************
1205 REMARKS:
1206 Implements the ROR instruction and side effects.
1207 ****************************************************************************/
1208 u8 ror_byte(u8 d, u8 s)
1209 {
1210     register unsigned int res, cnt, mask;
1211
1212     /* rotate right */
1213     /*
1214        s is the rotate distance.  It varies from 0 - 8.
1215        d is the byte object rotated.
1216
1217        have
1218
1219        B_7 ... B_0
1220
1221        The rotate is done mod 8.
1222
1223        IF n > 0
1224        1) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
1225        2) B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0)
1226          */
1227         res = d;
1228         if ((cnt = s % 8) != 0) {           /* not a typo, do nada if cnt==0 */
1229         /* B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0) */
1230         res = (d << (8 - cnt));
1231
1232         /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n) */
1233         mask = (1 << (8 - cnt)) - 1;
1234         res |= (d >> (cnt)) & mask;
1235
1236         /* set the new carry flag, Note that it is the low order
1237            bit of the result!!!                               */
1238                 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1239                 /* OVERFLOW is set *IFF* s==1, then it is the
1240            xor of the two most significant bits.  Blecck. */
1241                 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
1242         } else if (s != 0) {
1243                 /* set the new carry flag, Note that it is the low order
1244                    bit of the result!!!                               */
1245                 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1246         }
1247         return (u8)res;
1248 }
1249
1250 /****************************************************************************
1251 REMARKS:
1252 Implements the ROR instruction and side effects.
1253 ****************************************************************************/
1254 u16 ror_word(u16 d, u8 s)
1255 {
1256     register unsigned int res, cnt, mask;
1257
1258         res = d;
1259         if ((cnt = s % 16) != 0) {
1260                 res = (d << (16 - cnt));
1261                 mask = (1 << (16 - cnt)) - 1;
1262                 res |= (d >> (cnt)) & mask;
1263                 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1264                 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
1265         } else if (s != 0) {
1266                 /* set the new carry flag, Note that it is the low order
1267                    bit of the result!!!                               */
1268                 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1269         }
1270         return (u16)res;
1271 }
1272
1273 /****************************************************************************
1274 REMARKS:
1275 Implements the ROR instruction and side effects.
1276 ****************************************************************************/
1277 u32 ror_long(u32 d, u8 s)
1278 {
1279         register u32 res, cnt, mask;
1280
1281         res = d;
1282         if ((cnt = s % 32) != 0) {
1283                 res = (d << (32 - cnt));
1284                 mask = (1 << (32 - cnt)) - 1;
1285                 res |= (d >> (cnt)) & mask;
1286                 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1287                 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
1288         } else if (s != 0) {
1289                 /* set the new carry flag, Note that it is the low order
1290                    bit of the result!!!                               */
1291                 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1292         }
1293         return res;
1294 }
1295
1296 /****************************************************************************
1297 REMARKS:
1298 Implements the SHL instruction and side effects.
1299 ****************************************************************************/
1300 u8 shl_byte(u8 d, u8 s)
1301 {
1302         unsigned int cnt, res, cf;
1303
1304         if (s < 8) {
1305                 cnt = s % 8;
1306
1307                 /* last bit shifted out goes into carry flag */
1308                 if (cnt > 0) {
1309                         res = d << cnt;
1310                         cf = d & (1 << (8 - cnt));
1311                         CONDITIONAL_SET_FLAG(cf, F_CF);
1312                         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1313                         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1314                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1315                 } else {
1316                         res = (u8) d;
1317                 }
1318
1319                 if (cnt == 1) {
1320                         /* Needs simplification. */
1321                         CONDITIONAL_SET_FLAG(
1322                                                                         (((res & 0x80) == 0x80) ^
1323                                                                          (ACCESS_FLAG(F_CF) != 0)),
1324                         /* was (M.x86.R_FLG&F_CF)==F_CF)), */
1325                                                                         F_OF);
1326                 } else {
1327                         CLEAR_FLAG(F_OF);
1328                 }
1329         } else {
1330                 res = 0;
1331                 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
1332                 CLEAR_FLAG(F_OF);
1333                 CLEAR_FLAG(F_SF);
1334                 SET_FLAG(F_PF);
1335                 SET_FLAG(F_ZF);
1336     }
1337         return (u8)res;
1338 }
1339
1340 /****************************************************************************
1341 REMARKS:
1342 Implements the SHL instruction and side effects.
1343 ****************************************************************************/
1344 u16 shl_word(u16 d, u8 s)
1345 {
1346     unsigned int cnt, res, cf;
1347
1348         if (s < 16) {
1349                 cnt = s % 16;
1350                 if (cnt > 0) {
1351                         res = d << cnt;
1352                         cf = d & (1 << (16 - cnt));
1353                         CONDITIONAL_SET_FLAG(cf, F_CF);
1354                         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1355                         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1356                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1357                 } else {
1358                         res = (u16) d;
1359                 }
1360
1361                 if (cnt == 1) {
1362                         CONDITIONAL_SET_FLAG(
1363                                                                         (((res & 0x8000) == 0x8000) ^
1364                                                                          (ACCESS_FLAG(F_CF) != 0)),
1365                                                                         F_OF);
1366         } else {
1367                         CLEAR_FLAG(F_OF);
1368         }
1369     } else {
1370                 res = 0;
1371                 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1372                 CLEAR_FLAG(F_OF);
1373                 CLEAR_FLAG(F_SF);
1374                 SET_FLAG(F_PF);
1375                 SET_FLAG(F_ZF);
1376         }
1377         return (u16)res;
1378 }
1379
1380 /****************************************************************************
1381 REMARKS:
1382 Implements the SHL instruction and side effects.
1383 ****************************************************************************/
1384 u32 shl_long(u32 d, u8 s)
1385 {
1386         unsigned int cnt, res, cf;
1387
1388         if (s < 32) {
1389                 cnt = s % 32;
1390                 if (cnt > 0) {
1391                         res = d << cnt;
1392                         cf = d & (1 << (32 - cnt));
1393                         CONDITIONAL_SET_FLAG(cf, F_CF);
1394                         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1395                         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1396                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1397                 } else {
1398                         res = d;
1399                 }
1400                 if (cnt == 1) {
1401                         CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1402                                                                   (ACCESS_FLAG(F_CF) != 0)), F_OF);
1403                 } else {
1404                         CLEAR_FLAG(F_OF);
1405                 }
1406         } else {
1407                 res = 0;
1408                 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1409                 CLEAR_FLAG(F_OF);
1410                 CLEAR_FLAG(F_SF);
1411                 SET_FLAG(F_PF);
1412                 SET_FLAG(F_ZF);
1413         }
1414         return res;
1415 }
1416
1417 /****************************************************************************
1418 REMARKS:
1419 Implements the SHR instruction and side effects.
1420 ****************************************************************************/
1421 u8 shr_byte(u8 d, u8 s)
1422 {
1423         unsigned int cnt, res, cf;
1424
1425         if (s < 8) {
1426                 cnt = s % 8;
1427                 if (cnt > 0) {
1428                         cf = d & (1 << (cnt - 1));
1429                         res = d >> cnt;
1430                         CONDITIONAL_SET_FLAG(cf, F_CF);
1431                         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1432                         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1433                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1434                 } else {
1435                         res = (u8) d;
1436                 }
1437
1438                 if (cnt == 1) {
1439                         CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
1440                 } else {
1441                         CLEAR_FLAG(F_OF);
1442                 }
1443         } else {
1444                 res = 0;
1445                 CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
1446                 CLEAR_FLAG(F_OF);
1447                 CLEAR_FLAG(F_SF);
1448                 SET_FLAG(F_PF);
1449                 SET_FLAG(F_ZF);
1450         }
1451         return (u8)res;
1452 }
1453
1454 /****************************************************************************
1455 REMARKS:
1456 Implements the SHR instruction and side effects.
1457 ****************************************************************************/
1458 u16 shr_word(u16 d, u8 s)
1459 {
1460         unsigned int cnt, res, cf;
1461
1462         if (s < 16) {
1463                 cnt = s % 16;
1464                 if (cnt > 0) {
1465                         cf = d & (1 << (cnt - 1));
1466                         res = d >> cnt;
1467                         CONDITIONAL_SET_FLAG(cf, F_CF);
1468                         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1469                         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1470                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1471                 } else {
1472                         res = d;
1473                 }
1474
1475                 if (cnt == 1) {
1476                         CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1477         } else {
1478                         CLEAR_FLAG(F_OF);
1479         }
1480         } else {
1481                 res = 0;
1482                 CLEAR_FLAG(F_CF);
1483                 CLEAR_FLAG(F_OF);
1484                 SET_FLAG(F_ZF);
1485                 CLEAR_FLAG(F_SF);
1486                 CLEAR_FLAG(F_PF);
1487     }
1488         return (u16)res;
1489 }
1490
1491 /****************************************************************************
1492 REMARKS:
1493 Implements the SHR instruction and side effects.
1494 ****************************************************************************/
1495 u32 shr_long(u32 d, u8 s)
1496 {
1497         unsigned int cnt, res, cf;
1498
1499         if (s < 32) {
1500                 cnt = s % 32;
1501                 if (cnt > 0) {
1502                         cf = d & (1 << (cnt - 1));
1503                         res = d >> cnt;
1504                         CONDITIONAL_SET_FLAG(cf, F_CF);
1505                         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1506                         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1507                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1508         } else {
1509             res = d;
1510         }
1511         if (cnt == 1) {
1512                         CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1513         } else {
1514                         CLEAR_FLAG(F_OF);
1515         }
1516     } else {
1517         res = 0;
1518                 CLEAR_FLAG(F_CF);
1519                 CLEAR_FLAG(F_OF);
1520                 SET_FLAG(F_ZF);
1521                 CLEAR_FLAG(F_SF);
1522                 CLEAR_FLAG(F_PF);
1523     }
1524     return res;
1525 }
1526
1527 /****************************************************************************
1528 REMARKS:
1529 Implements the SAR instruction and side effects.
1530 ****************************************************************************/
1531 u8 sar_byte(u8 d, u8 s)
1532 {
1533         unsigned int cnt, res, cf, mask, sf;
1534
1535         res = d;
1536         sf = d & 0x80;
1537     cnt = s % 8;
1538         if (cnt > 0 && cnt < 8) {
1539                 mask = (1 << (8 - cnt)) - 1;
1540                 cf = d & (1 << (cnt - 1));
1541                 res = (d >> cnt) & mask;
1542                 CONDITIONAL_SET_FLAG(cf, F_CF);
1543                 if (sf) {
1544                         res |= ~mask;
1545                 }
1546                 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1547                 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1548                 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1549     } else if (cnt >= 8) {
1550         if (sf) {
1551             res = 0xff;
1552                         SET_FLAG(F_CF);
1553                         CLEAR_FLAG(F_ZF);
1554                         SET_FLAG(F_SF);
1555                         SET_FLAG(F_PF);
1556                 } else {
1557                         res = 0;
1558                         CLEAR_FLAG(F_CF);
1559                         SET_FLAG(F_ZF);
1560                         CLEAR_FLAG(F_SF);
1561                         CLEAR_FLAG(F_PF);
1562                 }
1563         }
1564         return (u8)res;
1565 }
1566
1567 /****************************************************************************
1568 REMARKS:
1569 Implements the SAR instruction and side effects.
1570 ****************************************************************************/
1571 u16 sar_word(u16 d, u8 s)
1572 {
1573     unsigned int cnt, res, cf, mask, sf;
1574
1575     sf = d & 0x8000;
1576     cnt = s % 16;
1577         res = d;
1578         if (cnt > 0 && cnt < 16) {
1579         mask = (1 << (16 - cnt)) - 1;
1580         cf = d & (1 << (cnt - 1));
1581         res = (d >> cnt) & mask;
1582                 CONDITIONAL_SET_FLAG(cf, F_CF);
1583         if (sf) {
1584             res |= ~mask;
1585         }
1586                 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1587                 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1588                 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1589     } else if (cnt >= 16) {
1590         if (sf) {
1591             res = 0xffff;
1592                         SET_FLAG(F_CF);
1593                         CLEAR_FLAG(F_ZF);
1594                         SET_FLAG(F_SF);
1595                         SET_FLAG(F_PF);
1596         } else {
1597             res = 0;
1598                         CLEAR_FLAG(F_CF);
1599                         SET_FLAG(F_ZF);
1600                         CLEAR_FLAG(F_SF);
1601                         CLEAR_FLAG(F_PF);
1602         }
1603     }
1604         return (u16)res;
1605 }
1606
1607 /****************************************************************************
1608 REMARKS:
1609 Implements the SAR instruction and side effects.
1610 ****************************************************************************/
1611 u32 sar_long(u32 d, u8 s)
1612 {
1613     u32 cnt, res, cf, mask, sf;
1614
1615     sf = d & 0x80000000;
1616     cnt = s % 32;
1617         res = d;
1618         if (cnt > 0 && cnt < 32) {
1619         mask = (1 << (32 - cnt)) - 1;
1620                 cf = d & (1 << (cnt - 1));
1621         res = (d >> cnt) & mask;
1622                 CONDITIONAL_SET_FLAG(cf, F_CF);
1623         if (sf) {
1624             res |= ~mask;
1625         }
1626                 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1627                 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1628                 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1629     } else if (cnt >= 32) {
1630         if (sf) {
1631             res = 0xffffffff;
1632                         SET_FLAG(F_CF);
1633                         CLEAR_FLAG(F_ZF);
1634                         SET_FLAG(F_SF);
1635                         SET_FLAG(F_PF);
1636                 } else {
1637                         res = 0;
1638                         CLEAR_FLAG(F_CF);
1639                         SET_FLAG(F_ZF);
1640                         CLEAR_FLAG(F_SF);
1641                         CLEAR_FLAG(F_PF);
1642                 }
1643         }
1644         return res;
1645 }
1646
1647 /****************************************************************************
1648 REMARKS:
1649 Implements the SHLD instruction and side effects.
1650 ****************************************************************************/
1651 u16 shld_word (u16 d, u16 fill, u8 s)
1652 {
1653         unsigned int cnt, res, cf;
1654
1655         if (s < 16) {
1656                 cnt = s % 16;
1657                 if (cnt > 0) {
1658                         res = (d << cnt) | (fill >> (16-cnt));
1659                         cf = d & (1 << (16 - cnt));
1660                         CONDITIONAL_SET_FLAG(cf, F_CF);
1661                         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1662                         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1663                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1664                 } else {
1665                         res = d;
1666                 }
1667                 if (cnt == 1) {
1668                         CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
1669                                                                   (ACCESS_FLAG(F_CF) != 0)), F_OF);
1670                 } else {
1671                         CLEAR_FLAG(F_OF);
1672                 }
1673         } else {
1674                 res = 0;
1675                 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1676                 CLEAR_FLAG(F_OF);
1677                 CLEAR_FLAG(F_SF);
1678                 SET_FLAG(F_PF);
1679                 SET_FLAG(F_ZF);
1680         }
1681         return (u16)res;
1682 }
1683
1684 /****************************************************************************
1685 REMARKS:
1686 Implements the SHLD instruction and side effects.
1687 ****************************************************************************/
1688 u32 shld_long (u32 d, u32 fill, u8 s)
1689 {
1690         unsigned int cnt, res, cf;
1691
1692         if (s < 32) {
1693                 cnt = s % 32;
1694                 if (cnt > 0) {
1695                         res = (d << cnt) | (fill >> (32-cnt));
1696                         cf = d & (1 << (32 - cnt));
1697                         CONDITIONAL_SET_FLAG(cf, F_CF);
1698                         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1699                         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1700                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1701                 } else {
1702                         res = d;
1703                 }
1704                 if (cnt == 1) {
1705                         CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1706                                                                   (ACCESS_FLAG(F_CF) != 0)), F_OF);
1707                 } else {
1708                         CLEAR_FLAG(F_OF);
1709                 }
1710         } else {
1711                 res = 0;
1712                 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1713                 CLEAR_FLAG(F_OF);
1714                 CLEAR_FLAG(F_SF);
1715                 SET_FLAG(F_PF);
1716                 SET_FLAG(F_ZF);
1717         }
1718         return res;
1719 }
1720
1721 /****************************************************************************
1722 REMARKS:
1723 Implements the SHRD instruction and side effects.
1724 ****************************************************************************/
1725 u16 shrd_word (u16 d, u16 fill, u8 s)
1726 {
1727         unsigned int cnt, res, cf;
1728
1729         if (s < 16) {
1730                 cnt = s % 16;
1731                 if (cnt > 0) {
1732                         cf = d & (1 << (cnt - 1));
1733                         res = (d >> cnt) | (fill << (16 - cnt));
1734                         CONDITIONAL_SET_FLAG(cf, F_CF);
1735                         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1736                         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1737                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1738                 } else {
1739                         res = d;
1740                 }
1741
1742                 if (cnt == 1) {
1743                         CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1744         } else {
1745                         CLEAR_FLAG(F_OF);
1746         }
1747         } else {
1748                 res = 0;
1749                 CLEAR_FLAG(F_CF);
1750                 CLEAR_FLAG(F_OF);
1751                 SET_FLAG(F_ZF);
1752                 CLEAR_FLAG(F_SF);
1753                 CLEAR_FLAG(F_PF);
1754     }
1755         return (u16)res;
1756 }
1757
1758 /****************************************************************************
1759 REMARKS:
1760 Implements the SHRD instruction and side effects.
1761 ****************************************************************************/
1762 u32 shrd_long (u32 d, u32 fill, u8 s)
1763 {
1764         unsigned int cnt, res, cf;
1765
1766         if (s < 32) {
1767                 cnt = s % 32;
1768                 if (cnt > 0) {
1769                         cf = d & (1 << (cnt - 1));
1770                         res = (d >> cnt) | (fill << (32 - cnt));
1771                         CONDITIONAL_SET_FLAG(cf, F_CF);
1772                         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1773                         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1774                         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1775                 } else {
1776                         res = d;
1777                 }
1778                 if (cnt == 1) {
1779                         CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1780         } else {
1781                         CLEAR_FLAG(F_OF);
1782         }
1783         } else {
1784                 res = 0;
1785                 CLEAR_FLAG(F_CF);
1786                 CLEAR_FLAG(F_OF);
1787                 SET_FLAG(F_ZF);
1788                 CLEAR_FLAG(F_SF);
1789                 CLEAR_FLAG(F_PF);
1790     }
1791         return res;
1792 }
1793
1794 /****************************************************************************
1795 REMARKS:
1796 Implements the SBB instruction and side effects.
1797 ****************************************************************************/
1798 u8 sbb_byte(u8 d, u8 s)
1799 {
1800     register u32 res;   /* all operands in native machine order */
1801     register u32 bc;
1802
1803         if (ACCESS_FLAG(F_CF))
1804                 res = d - s - 1;
1805         else
1806                 res = d - s;
1807         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1808         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1809         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1810
1811         /* calculate the borrow chain.  See note at top */
1812         bc = (res & (~d | s)) | (~d & s);
1813         CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1814         CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1815         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1816         return (u8)res;
1817 }
1818
1819 /****************************************************************************
1820 REMARKS:
1821 Implements the SBB instruction and side effects.
1822 ****************************************************************************/
1823 u16 sbb_word(u16 d, u16 s)
1824 {
1825     register u32 res;   /* all operands in native machine order */
1826     register u32 bc;
1827
1828         if (ACCESS_FLAG(F_CF))
1829         res = d - s - 1;
1830     else
1831         res = d - s;
1832         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1833         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1834         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1835
1836         /* calculate the borrow chain.  See note at top */
1837         bc = (res & (~d | s)) | (~d & s);
1838         CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1839         CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1840         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1841         return (u16)res;
1842 }
1843
1844 /****************************************************************************
1845 REMARKS:
1846 Implements the SBB instruction and side effects.
1847 ****************************************************************************/
1848 u32 sbb_long(u32 d, u32 s)
1849 {
1850         register u32 res;   /* all operands in native machine order */
1851         register u32 bc;
1852
1853         if (ACCESS_FLAG(F_CF))
1854         res = d - s - 1;
1855     else
1856         res = d - s;
1857         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1858         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1859         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1860
1861         /* calculate the borrow chain.  See note at top */
1862         bc = (res & (~d | s)) | (~d & s);
1863         CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1864         CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1865         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1866         return res;
1867 }
1868
1869 /****************************************************************************
1870 REMARKS:
1871 Implements the SUB instruction and side effects.
1872 ****************************************************************************/
1873 u8 sub_byte(u8 d, u8 s)
1874 {
1875         register u32 res;   /* all operands in native machine order */
1876         register u32 bc;
1877
1878         res = d - s;
1879         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1880         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1881         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1882
1883         /* calculate the borrow chain.  See note at top */
1884         bc = (res & (~d | s)) | (~d & s);
1885         CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1886         CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1887         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1888         return (u8)res;
1889 }
1890
1891 /****************************************************************************
1892 REMARKS:
1893 Implements the SUB instruction and side effects.
1894 ****************************************************************************/
1895 u16 sub_word(u16 d, u16 s)
1896 {
1897     register u32 res;   /* all operands in native machine order */
1898     register u32 bc;
1899
1900     res = d - s;
1901         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1902         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1903         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1904
1905         /* calculate the borrow chain.  See note at top */
1906         bc = (res & (~d | s)) | (~d & s);
1907         CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1908         CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1909         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1910         return (u16)res;
1911 }
1912
1913 /****************************************************************************
1914 REMARKS:
1915 Implements the SUB instruction and side effects.
1916 ****************************************************************************/
1917 u32 sub_long(u32 d, u32 s)
1918 {
1919         register u32 res;   /* all operands in native machine order */
1920         register u32 bc;
1921
1922         res = d - s;
1923         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1924         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1925         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1926
1927         /* calculate the borrow chain.  See note at top */
1928         bc = (res & (~d | s)) | (~d & s);
1929         CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1930         CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1931         CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1932         return res;
1933 }
1934
1935 /****************************************************************************
1936 REMARKS:
1937 Implements the TEST instruction and side effects.
1938 ****************************************************************************/
1939 void test_byte(u8 d, u8 s)
1940 {
1941     register u32 res;   /* all operands in native machine order */
1942
1943     res = d & s;
1944
1945         CLEAR_FLAG(F_OF);
1946         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1947         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1948         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1949     /* AF == dont care */
1950         CLEAR_FLAG(F_CF);
1951 }
1952
1953 /****************************************************************************
1954 REMARKS:
1955 Implements the TEST instruction and side effects.
1956 ****************************************************************************/
1957 void test_word(u16 d, u16 s)
1958 {
1959         register u32 res;   /* all operands in native machine order */
1960
1961         res = d & s;
1962
1963         CLEAR_FLAG(F_OF);
1964         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1965         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1966         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1967         /* AF == dont care */
1968         CLEAR_FLAG(F_CF);
1969 }
1970
1971 /****************************************************************************
1972 REMARKS:
1973 Implements the TEST instruction and side effects.
1974 ****************************************************************************/
1975 void test_long(u32 d, u32 s)
1976 {
1977         register u32 res;   /* all operands in native machine order */
1978
1979         res = d & s;
1980
1981         CLEAR_FLAG(F_OF);
1982         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1983         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1984         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1985         /* AF == dont care */
1986         CLEAR_FLAG(F_CF);
1987 }
1988
1989 /****************************************************************************
1990 REMARKS:
1991 Implements the XOR instruction and side effects.
1992 ****************************************************************************/
1993 u8 xor_byte(u8 d, u8 s)
1994 {
1995         register u8 res;    /* all operands in native machine order */
1996
1997         res = d ^ s;
1998         CLEAR_FLAG(F_OF);
1999         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
2000         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2001         CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
2002         CLEAR_FLAG(F_CF);
2003         CLEAR_FLAG(F_AF);
2004         return res;
2005 }
2006
2007 /****************************************************************************
2008 REMARKS:
2009 Implements the XOR instruction and side effects.
2010 ****************************************************************************/
2011 u16 xor_word(u16 d, u16 s)
2012 {
2013         register u16 res;   /* all operands in native machine order */
2014
2015         res = d ^ s;
2016         CLEAR_FLAG(F_OF);
2017         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
2018         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2019         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2020         CLEAR_FLAG(F_CF);
2021         CLEAR_FLAG(F_AF);
2022         return res;
2023 }
2024
2025 /****************************************************************************
2026 REMARKS:
2027 Implements the XOR instruction and side effects.
2028 ****************************************************************************/
2029 u32 xor_long(u32 d, u32 s)
2030 {
2031         register u32 res;   /* all operands in native machine order */
2032
2033         res = d ^ s;
2034         CLEAR_FLAG(F_OF);
2035         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
2036         CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2037         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2038         CLEAR_FLAG(F_CF);
2039         CLEAR_FLAG(F_AF);
2040         return res;
2041 }
2042
2043 /****************************************************************************
2044 REMARKS:
2045 Implements the IMUL instruction and side effects.
2046 ****************************************************************************/
2047 void imul_byte(u8 s)
2048 {
2049         s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
2050
2051         M.x86.R_AX = res;
2052         if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
2053                 ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
2054                 CLEAR_FLAG(F_CF);
2055                 CLEAR_FLAG(F_OF);
2056         } else {
2057                 SET_FLAG(F_CF);
2058                 SET_FLAG(F_OF);
2059         }
2060 }
2061
2062 /****************************************************************************
2063 REMARKS:
2064 Implements the IMUL instruction and side effects.
2065 ****************************************************************************/
2066 void imul_word(u16 s)
2067 {
2068         s32 res = (s16)M.x86.R_AX * (s16)s;
2069
2070         M.x86.R_AX = (u16)res;
2071         M.x86.R_DX = (u16)(res >> 16);
2072         if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x00) ||
2073                 ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFF)) {
2074                 CLEAR_FLAG(F_CF);
2075                 CLEAR_FLAG(F_OF);
2076         } else {
2077                 SET_FLAG(F_CF);
2078                 SET_FLAG(F_OF);
2079         }
2080 }
2081
2082 /****************************************************************************
2083 REMARKS:
2084 Implements the IMUL instruction and side effects.
2085 ****************************************************************************/
2086 void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
2087 {
2088 #ifdef  __HAS_LONG_LONG__
2089         s64 res = (s32)d * (s32)s;
2090
2091         *res_lo = (u32)res;
2092         *res_hi = (u32)(res >> 32);
2093 #else
2094         u32     d_lo,d_hi,d_sign;
2095         u32     s_lo,s_hi,s_sign;
2096         u32     rlo_lo,rlo_hi,rhi_lo;
2097
2098         if ((d_sign = d & 0x80000000) != 0)
2099                 d = -d;
2100         d_lo = d & 0xFFFF;
2101         d_hi = d >> 16;
2102         if ((s_sign = s & 0x80000000) != 0)
2103                 s = -s;
2104         s_lo = s & 0xFFFF;
2105         s_hi = s >> 16;
2106         rlo_lo = d_lo * s_lo;
2107         rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
2108         rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
2109         *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2110         *res_hi = rhi_lo;
2111         if (d_sign != s_sign) {
2112                 d = ~*res_lo;
2113                 s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
2114                 *res_lo = ~*res_lo+1;
2115                 *res_hi = ~*res_hi+(s >> 16);
2116                 }
2117 #endif
2118 }
2119
2120 /****************************************************************************
2121 REMARKS:
2122 Implements the IMUL instruction and side effects.
2123 ****************************************************************************/
2124 void imul_long(u32 s)
2125 {
2126         imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
2127         if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00) ||
2128                 ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFF)) {
2129                 CLEAR_FLAG(F_CF);
2130                 CLEAR_FLAG(F_OF);
2131         } else {
2132                 SET_FLAG(F_CF);
2133                 SET_FLAG(F_OF);
2134         }
2135 }
2136
2137 /****************************************************************************
2138 REMARKS:
2139 Implements the MUL instruction and side effects.
2140 ****************************************************************************/
2141 void mul_byte(u8 s)
2142 {
2143         u16 res = (u16)(M.x86.R_AL * s);
2144
2145         M.x86.R_AX = res;
2146         if (M.x86.R_AH == 0) {
2147                 CLEAR_FLAG(F_CF);
2148                 CLEAR_FLAG(F_OF);
2149         } else {
2150                 SET_FLAG(F_CF);
2151                 SET_FLAG(F_OF);
2152         }
2153 }
2154
2155 /****************************************************************************
2156 REMARKS:
2157 Implements the MUL instruction and side effects.
2158 ****************************************************************************/
2159 void mul_word(u16 s)
2160 {
2161         u32 res = M.x86.R_AX * s;
2162
2163         M.x86.R_AX = (u16)res;
2164         M.x86.R_DX = (u16)(res >> 16);
2165         if (M.x86.R_DX == 0) {
2166                 CLEAR_FLAG(F_CF);
2167                 CLEAR_FLAG(F_OF);
2168     } else {
2169                 SET_FLAG(F_CF);
2170                 SET_FLAG(F_OF);
2171     }
2172 }
2173
2174 /****************************************************************************
2175 REMARKS:
2176 Implements the MUL instruction and side effects.
2177 ****************************************************************************/
2178 void mul_long(u32 s)
2179 {
2180 #ifdef  __HAS_LONG_LONG__
2181         u64 res = (u32)M.x86.R_EAX * (u32)s;
2182
2183         M.x86.R_EAX = (u32)res;
2184         M.x86.R_EDX = (u32)(res >> 32);
2185 #else
2186         u32     a,a_lo,a_hi;
2187         u32     s_lo,s_hi;
2188         u32     rlo_lo,rlo_hi,rhi_lo;
2189
2190         a = M.x86.R_EAX;
2191         a_lo = a & 0xFFFF;
2192         a_hi = a >> 16;
2193         s_lo = s & 0xFFFF;
2194         s_hi = s >> 16;
2195         rlo_lo = a_lo * s_lo;
2196         rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
2197         rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
2198         M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2199         M.x86.R_EDX = rhi_lo;
2200 #endif
2201
2202         if (M.x86.R_EDX == 0) {
2203                 CLEAR_FLAG(F_CF);
2204                 CLEAR_FLAG(F_OF);
2205         } else {
2206                 SET_FLAG(F_CF);
2207                 SET_FLAG(F_OF);
2208     }
2209 }
2210
2211 /****************************************************************************
2212 REMARKS:
2213 Implements the IDIV instruction and side effects.
2214 ****************************************************************************/
2215 void idiv_byte(u8 s)
2216 {
2217     s32 dvd, div, mod;
2218
2219         dvd = (s16)M.x86.R_AX;
2220         if (s == 0) {
2221                 x86emu_intr_raise(0);
2222         return;
2223         }
2224         div = dvd / (s8)s;
2225         mod = dvd % (s8)s;
2226         if (abs(div) > 0x7f) {
2227                 x86emu_intr_raise(0);
2228                 return;
2229         }
2230         M.x86.R_AL = (s8) div;
2231         M.x86.R_AH = (s8) mod;
2232 }
2233
2234 /****************************************************************************
2235 REMARKS:
2236 Implements the IDIV instruction and side effects.
2237 ****************************************************************************/
2238 void idiv_word(u16 s)
2239 {
2240         s32 dvd, div, mod;
2241
2242         dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
2243         if (s == 0) {
2244                 x86emu_intr_raise(0);
2245                 return;
2246         }
2247         div = dvd / (s16)s;
2248         mod = dvd % (s16)s;
2249         if (abs(div) > 0x7fff) {
2250                 x86emu_intr_raise(0);
2251                 return;
2252         }
2253         CLEAR_FLAG(F_CF);
2254         CLEAR_FLAG(F_SF);
2255         CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2256         CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2257
2258         M.x86.R_AX = (u16)div;
2259         M.x86.R_DX = (u16)mod;
2260 }
2261
2262 /****************************************************************************
2263 REMARKS:
2264 Implements the IDIV instruction and side effects.
2265 ****************************************************************************/
2266 void idiv_long(u32 s)
2267 {
2268 #ifdef  __HAS_LONG_LONG__
2269         s64 dvd, div, mod;
2270
2271         dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2272         if (s == 0) {
2273                 x86emu_intr_raise(0);
2274                 return;
2275         }
2276         div = dvd / (s32)s;
2277         mod = dvd % (s32)s;
2278         if (abs(div) > 0x7fffffff) {
2279                 x86emu_intr_raise(0);
2280                 return;
2281         }
2282 #else
2283         s32 div = 0, mod;
2284         s32 h_dvd = M.x86.R_EDX;
2285         u32 l_dvd = M.x86.R_EAX;
2286         u32 abs_s = s & 0x7FFFFFFF;
2287         u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
2288         u32 h_s = abs_s >> 1;
2289         u32 l_s = abs_s << 31;
2290         int counter = 31;
2291         int carry;
2292
2293         if (s == 0) {
2294                 x86emu_intr_raise(0);
2295                 return;
2296         }
2297         do {
2298                 div <<= 1;
2299                 carry = (l_dvd >= l_s) ? 0 : 1;
2300
2301                 if (abs_h_dvd < (h_s + carry)) {
2302                         h_s >>= 1;
2303                         l_s = abs_s << (--counter);
2304                         continue;
2305                 } else {
2306                         abs_h_dvd -= (h_s + carry);
2307                         l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2308                                 : (l_dvd - l_s);
2309                         h_s >>= 1;
2310                         l_s = abs_s << (--counter);
2311                         div |= 1;
2312                         continue;
2313                 }
2314
2315         } while (counter > -1);
2316         /* overflow */
2317         if (abs_h_dvd || (l_dvd > abs_s)) {
2318                 x86emu_intr_raise(0);
2319                 return;
2320         }
2321         /* sign */
2322         div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
2323         mod = l_dvd;
2324
2325 #endif
2326         CLEAR_FLAG(F_CF);
2327         CLEAR_FLAG(F_AF);
2328         CLEAR_FLAG(F_SF);
2329         SET_FLAG(F_ZF);
2330         CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2331
2332         M.x86.R_EAX = (u32)div;
2333         M.x86.R_EDX = (u32)mod;
2334 }
2335
2336 /****************************************************************************
2337 REMARKS:
2338 Implements the DIV instruction and side effects.
2339 ****************************************************************************/
2340 void div_byte(u8 s)
2341 {
2342         u32 dvd, div, mod;
2343
2344         dvd = M.x86.R_AX;
2345     if (s == 0) {
2346                 x86emu_intr_raise(0);
2347         return;
2348     }
2349         div = dvd / (u8)s;
2350         mod = dvd % (u8)s;
2351         if (abs(div) > 0xff) {
2352                 x86emu_intr_raise(0);
2353         return;
2354         }
2355         M.x86.R_AL = (u8)div;
2356         M.x86.R_AH = (u8)mod;
2357 }
2358
2359 /****************************************************************************
2360 REMARKS:
2361 Implements the DIV instruction and side effects.
2362 ****************************************************************************/
2363 void div_word(u16 s)
2364 {
2365         u32 dvd, div, mod;
2366
2367         dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
2368         if (s == 0) {
2369                 x86emu_intr_raise(0);
2370         return;
2371     }
2372         div = dvd / (u16)s;
2373         mod = dvd % (u16)s;
2374         if (abs(div) > 0xffff) {
2375                 x86emu_intr_raise(0);
2376                 return;
2377         }
2378         CLEAR_FLAG(F_CF);
2379         CLEAR_FLAG(F_SF);
2380         CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2381         CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2382
2383         M.x86.R_AX = (u16)div;
2384         M.x86.R_DX = (u16)mod;
2385 }
2386
2387 /****************************************************************************
2388 REMARKS:
2389 Implements the DIV instruction and side effects.
2390 ****************************************************************************/
2391 void div_long(u32 s)
2392 {
2393 #ifdef  __HAS_LONG_LONG__
2394         u64 dvd, div, mod;
2395
2396         dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2397         if (s == 0) {
2398                 x86emu_intr_raise(0);
2399                 return;
2400         }
2401         div = dvd / (u32)s;
2402         mod = dvd % (u32)s;
2403         if (abs(div) > 0xffffffff) {
2404                 x86emu_intr_raise(0);
2405                 return;
2406         }
2407 #else
2408         s32 div = 0, mod;
2409         s32 h_dvd = M.x86.R_EDX;
2410         u32 l_dvd = M.x86.R_EAX;
2411
2412         u32 h_s = s;
2413         u32 l_s = 0;
2414         int counter = 32;
2415         int carry;
2416
2417         if (s == 0) {
2418                 x86emu_intr_raise(0);
2419                 return;
2420         }
2421         do {
2422                 div <<= 1;
2423                 carry = (l_dvd >= l_s) ? 0 : 1;
2424
2425                 if (h_dvd < (h_s + carry)) {
2426                         h_s >>= 1;
2427                         l_s = s << (--counter);
2428                         continue;
2429                 } else {
2430                         h_dvd -= (h_s + carry);
2431                         l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2432                                 : (l_dvd - l_s);
2433                         h_s >>= 1;
2434                         l_s = s << (--counter);
2435                         div |= 1;
2436                         continue;
2437                 }
2438
2439         } while (counter > -1);
2440         /* overflow */
2441         if (h_dvd || (l_dvd > s)) {
2442                 x86emu_intr_raise(0);
2443                 return;
2444         }
2445         mod = l_dvd;
2446 #endif
2447         CLEAR_FLAG(F_CF);
2448         CLEAR_FLAG(F_AF);
2449         CLEAR_FLAG(F_SF);
2450         SET_FLAG(F_ZF);
2451         CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2452
2453         M.x86.R_EAX = (u32)div;
2454         M.x86.R_EDX = (u32)mod;
2455 }
2456
2457 #endif  /* __HAVE_INLINE_ASSEMBLER__ */
2458
2459 /****************************************************************************
2460 REMARKS:
2461 Implements the IN string instruction and side effects.
2462 ****************************************************************************/
2463 void ins(int size)
2464 {
2465         int inc = size;
2466
2467         if (ACCESS_FLAG(F_DF)) {
2468                 inc = -size;
2469         }
2470         if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2471         /* dont care whether REPE or REPNE */
2472         /* in until CX is ZERO. */
2473                 u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2474                                          M.x86.R_ECX : M.x86.R_CX);
2475         switch (size) {
2476           case 1:
2477             while (count--) {
2478                                 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
2479                                                                         (*sys_inb)(M.x86.R_DX));
2480                                 M.x86.R_DI += inc;
2481             }
2482             break;
2483
2484           case 2:
2485             while (count--) {
2486                                 store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
2487                                                                         (*sys_inw)(M.x86.R_DX));
2488                                 M.x86.R_DI += inc;
2489             }
2490             break;
2491           case 4:
2492             while (count--) {
2493                                 store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
2494                                                                         (*sys_inl)(M.x86.R_DX));
2495                                 M.x86.R_DI += inc;
2496                 break;
2497             }
2498         }
2499                 M.x86.R_CX = 0;
2500                 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2501                         M.x86.R_ECX = 0;
2502         }
2503                 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2504     } else {
2505         switch (size) {
2506           case 1:
2507                         store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
2508                                                                 (*sys_inb)(M.x86.R_DX));
2509             break;
2510           case 2:
2511                         store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
2512                                                                 (*sys_inw)(M.x86.R_DX));
2513             break;
2514           case 4:
2515                         store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
2516                                                                 (*sys_inl)(M.x86.R_DX));
2517             break;
2518         }
2519                 M.x86.R_DI += inc;
2520     }
2521 }
2522
2523 /****************************************************************************
2524 REMARKS:
2525 Implements the OUT string instruction and side effects.
2526 ****************************************************************************/
2527 void outs(int size)
2528 {
2529     int inc = size;
2530
2531         if (ACCESS_FLAG(F_DF)) {
2532         inc = -size;
2533     }
2534         if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2535         /* dont care whether REPE or REPNE */
2536         /* out until CX is ZERO. */
2537                 u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2538                                          M.x86.R_ECX : M.x86.R_CX);
2539         switch (size) {
2540           case 1:
2541             while (count--) {
2542                                 (*sys_outb)(M.x86.R_DX,
2543                                                  fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2544                                 M.x86.R_SI += inc;
2545             }
2546             break;
2547
2548           case 2:
2549             while (count--) {
2550                                 (*sys_outw)(M.x86.R_DX,
2551                                                  fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2552                                 M.x86.R_SI += inc;
2553             }
2554             break;
2555           case 4:
2556             while (count--) {
2557                                 (*sys_outl)(M.x86.R_DX,
2558                                                  fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2559                                 M.x86.R_SI += inc;
2560                 break;
2561             }
2562         }
2563                 M.x86.R_CX = 0;
2564                 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2565                         M.x86.R_ECX = 0;
2566         }
2567                 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2568     } else {
2569         switch (size) {
2570           case 1:
2571                         (*sys_outb)(M.x86.R_DX,
2572                                          fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2573             break;
2574           case 2:
2575                         (*sys_outw)(M.x86.R_DX,
2576                                          fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2577             break;
2578           case 4:
2579                         (*sys_outl)(M.x86.R_DX,
2580                                          fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2581             break;
2582         }
2583                 M.x86.R_SI += inc;
2584     }
2585 }
2586
2587 /****************************************************************************
2588 PARAMETERS:
2589 addr    - Address to fetch word from
2590
2591 REMARKS:
2592 Fetches a word from emulator memory using an absolute address.
2593 ****************************************************************************/
2594 u16 mem_access_word(int addr)
2595 {
2596 DB(     if (CHECK_MEM_ACCESS())
2597           x86emu_check_mem_access(addr);)
2598         return (*sys_rdw)(addr);
2599 }
2600
2601 /****************************************************************************
2602 REMARKS:
2603 Pushes a word onto the stack.
2604
2605 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2606 ****************************************************************************/
2607 void push_word(u16 w)
2608 {
2609 DB(     if (CHECK_SP_ACCESS())
2610           x86emu_check_sp_access();)
2611         M.x86.R_SP -= 2;
2612         (*sys_wrw)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP, w);
2613 }
2614
2615 /****************************************************************************
2616 REMARKS:
2617 Pushes a long onto the stack.
2618
2619 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2620 ****************************************************************************/
2621 void push_long(u32 w)
2622 {
2623 DB(     if (CHECK_SP_ACCESS())
2624           x86emu_check_sp_access();)
2625         M.x86.R_SP -= 4;
2626         (*sys_wrl)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP, w);
2627 }
2628
2629 /****************************************************************************
2630 REMARKS:
2631 Pops a word from the stack.
2632
2633 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2634 ****************************************************************************/
2635 u16 pop_word(void)
2636 {
2637         register u16 res;
2638
2639 DB(     if (CHECK_SP_ACCESS())
2640           x86emu_check_sp_access();)
2641         res = (*sys_rdw)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP);
2642         M.x86.R_SP += 2;
2643         return res;
2644 }
2645
2646 /****************************************************************************
2647 REMARKS:
2648 Pops a long from the stack.
2649
2650 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2651 ****************************************************************************/
2652 u32 pop_long(void)
2653 {
2654     register u32 res;
2655
2656 DB(     if (CHECK_SP_ACCESS())
2657           x86emu_check_sp_access();)
2658         res = (*sys_rdl)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP);
2659         M.x86.R_SP += 4;
2660     return res;
2661 }
2662
2663 #ifdef  __HAVE_INLINE_ASSEMBLER__
2664
2665 u16 aaa_word (u16 d)
2666 { return aaa_word_asm(&M.x86.R_EFLG,d); }
2667
2668 u16 aas_word (u16 d)
2669 { return aas_word_asm(&M.x86.R_EFLG,d); }
2670
2671 u16 aad_word (u16 d)
2672 { return aad_word_asm(&M.x86.R_EFLG,d); }
2673
2674 u16 aam_word (u8 d)
2675 { return aam_word_asm(&M.x86.R_EFLG,d); }
2676
2677 u8 adc_byte (u8 d, u8 s)
2678 { return adc_byte_asm(&M.x86.R_EFLG,d,s); }
2679
2680 u16 adc_word (u16 d, u16 s)
2681 { return adc_word_asm(&M.x86.R_EFLG,d,s); }
2682
2683 u32 adc_long (u32 d, u32 s)
2684 { return adc_long_asm(&M.x86.R_EFLG,d,s); }
2685
2686 u8 add_byte (u8 d, u8 s)
2687 { return add_byte_asm(&M.x86.R_EFLG,d,s); }
2688
2689 u16 add_word (u16 d, u16 s)
2690 { return add_word_asm(&M.x86.R_EFLG,d,s); }
2691
2692 u32 add_long (u32 d, u32 s)
2693 { return add_long_asm(&M.x86.R_EFLG,d,s); }
2694
2695 u8 and_byte (u8 d, u8 s)
2696 { return and_byte_asm(&M.x86.R_EFLG,d,s); }
2697
2698 u16 and_word (u16 d, u16 s)
2699 { return and_word_asm(&M.x86.R_EFLG,d,s); }
2700
2701 u32 and_long (u32 d, u32 s)
2702 { return and_long_asm(&M.x86.R_EFLG,d,s); }
2703
2704 u8 cmp_byte (u8 d, u8 s)
2705 { return cmp_byte_asm(&M.x86.R_EFLG,d,s); }
2706
2707 u16 cmp_word (u16 d, u16 s)
2708 { return cmp_word_asm(&M.x86.R_EFLG,d,s); }
2709
2710 u32 cmp_long (u32 d, u32 s)
2711 { return cmp_long_asm(&M.x86.R_EFLG,d,s); }
2712
2713 u8 daa_byte (u8 d)
2714 { return daa_byte_asm(&M.x86.R_EFLG,d); }
2715
2716 u8 das_byte (u8 d)
2717 { return das_byte_asm(&M.x86.R_EFLG,d); }
2718
2719 u8 dec_byte (u8 d)
2720 { return dec_byte_asm(&M.x86.R_EFLG,d); }
2721
2722 u16 dec_word (u16 d)
2723 { return dec_word_asm(&M.x86.R_EFLG,d); }
2724
2725 u32 dec_long (u32 d)
2726 { return dec_long_asm(&M.x86.R_EFLG,d); }
2727
2728 u8 inc_byte (u8 d)
2729 { return inc_byte_asm(&M.x86.R_EFLG,d); }
2730
2731 u16 inc_word (u16 d)
2732 { return inc_word_asm(&M.x86.R_EFLG,d); }
2733
2734 u32 inc_long (u32 d)
2735 { return inc_long_asm(&M.x86.R_EFLG,d); }
2736
2737 u8 or_byte (u8 d, u8 s)
2738 { return or_byte_asm(&M.x86.R_EFLG,d,s); }
2739
2740 u16 or_word (u16 d, u16 s)
2741 { return or_word_asm(&M.x86.R_EFLG,d,s); }
2742
2743 u32 or_long (u32 d, u32 s)
2744 { return or_long_asm(&M.x86.R_EFLG,d,s); }
2745
2746 u8 neg_byte (u8 s)
2747 { return neg_byte_asm(&M.x86.R_EFLG,s); }
2748
2749 u16 neg_word (u16 s)
2750 { return neg_word_asm(&M.x86.R_EFLG,s); }
2751
2752 u32 neg_long (u32 s)
2753 { return neg_long_asm(&M.x86.R_EFLG,s); }
2754
2755 u8 not_byte (u8 s)
2756 { return not_byte_asm(&M.x86.R_EFLG,s); }
2757
2758 u16 not_word (u16 s)
2759 { return not_word_asm(&M.x86.R_EFLG,s); }
2760
2761 u32 not_long (u32 s)
2762 { return not_long_asm(&M.x86.R_EFLG,s); }
2763
2764 u8 rcl_byte (u8 d, u8 s)
2765 { return rcl_byte_asm(&M.x86.R_EFLG,d,s); }
2766
2767 u16 rcl_word (u16 d, u8 s)
2768 { return rcl_word_asm(&M.x86.R_EFLG,d,s); }
2769
2770 u32 rcl_long (u32 d, u8 s)
2771 { return rcl_long_asm(&M.x86.R_EFLG,d,s); }
2772
2773 u8 rcr_byte (u8 d, u8 s)
2774 { return rcr_byte_asm(&M.x86.R_EFLG,d,s); }
2775
2776 u16 rcr_word (u16 d, u8 s)
2777 { return rcr_word_asm(&M.x86.R_EFLG,d,s); }
2778
2779 u32 rcr_long (u32 d, u8 s)
2780 { return rcr_long_asm(&M.x86.R_EFLG,d,s); }
2781
2782 u8 rol_byte (u8 d, u8 s)
2783 { return rol_byte_asm(&M.x86.R_EFLG,d,s); }
2784
2785 u16 rol_word (u16 d, u8 s)
2786 { return rol_word_asm(&M.x86.R_EFLG,d,s); }
2787
2788 u32 rol_long (u32 d, u8 s)
2789 { return rol_long_asm(&M.x86.R_EFLG,d,s); }
2790
2791 u8 ror_byte (u8 d, u8 s)
2792 { return ror_byte_asm(&M.x86.R_EFLG,d,s); }
2793
2794 u16 ror_word (u16 d, u8 s)
2795 { return ror_word_asm(&M.x86.R_EFLG,d,s); }
2796
2797 u32 ror_long (u32 d, u8 s)
2798 { return ror_long_asm(&M.x86.R_EFLG,d,s); }
2799
2800 u8 shl_byte (u8 d, u8 s)
2801 { return shl_byte_asm(&M.x86.R_EFLG,d,s); }
2802
2803 u16 shl_word (u16 d, u8 s)
2804 { return shl_word_asm(&M.x86.R_EFLG,d,s); }
2805
2806 u32 shl_long (u32 d, u8 s)
2807 { return shl_long_asm(&M.x86.R_EFLG,d,s); }
2808
2809 u8 shr_byte (u8 d, u8 s)
2810 { return shr_byte_asm(&M.x86.R_EFLG,d,s); }
2811
2812 u16 shr_word (u16 d, u8 s)
2813 { return shr_word_asm(&M.x86.R_EFLG,d,s); }
2814
2815 u32 shr_long (u32 d, u8 s)
2816 { return shr_long_asm(&M.x86.R_EFLG,d,s); }
2817
2818 u8 sar_byte (u8 d, u8 s)
2819 { return sar_byte_asm(&M.x86.R_EFLG,d,s); }
2820
2821 u16 sar_word (u16 d, u8 s)
2822 { return sar_word_asm(&M.x86.R_EFLG,d,s); }
2823
2824 u32 sar_long (u32 d, u8 s)
2825 { return sar_long_asm(&M.x86.R_EFLG,d,s); }
2826
2827 u16 shld_word (u16 d, u16 fill, u8 s)
2828 { return shld_word_asm(&M.x86.R_EFLG,d,fill,s); }
2829
2830 u32 shld_long (u32 d, u32 fill, u8 s)
2831 { return shld_long_asm(&M.x86.R_EFLG,d,fill,s); }
2832
2833 u16 shrd_word (u16 d, u16 fill, u8 s)
2834 { return shrd_word_asm(&M.x86.R_EFLG,d,fill,s); }
2835
2836 u32 shrd_long (u32 d, u32 fill, u8 s)
2837 { return shrd_long_asm(&M.x86.R_EFLG,d,fill,s); }
2838
2839 u8 sbb_byte (u8 d, u8 s)
2840 { return sbb_byte_asm(&M.x86.R_EFLG,d,s); }
2841
2842 u16 sbb_word (u16 d, u16 s)
2843 { return sbb_word_asm(&M.x86.R_EFLG,d,s); }
2844
2845 u32 sbb_long (u32 d, u32 s)
2846 { return sbb_long_asm(&M.x86.R_EFLG,d,s); }
2847
2848 u8 sub_byte (u8 d, u8 s)
2849 { return sub_byte_asm(&M.x86.R_EFLG,d,s); }
2850
2851 u16 sub_word (u16 d, u16 s)
2852 { return sub_word_asm(&M.x86.R_EFLG,d,s); }
2853
2854 u32 sub_long (u32 d, u32 s)
2855 { return sub_long_asm(&M.x86.R_EFLG,d,s); }
2856
2857 void test_byte (u8 d, u8 s)
2858 { test_byte_asm(&M.x86.R_EFLG,d,s); }
2859
2860 void test_word (u16 d, u16 s)
2861 { test_word_asm(&M.x86.R_EFLG,d,s); }
2862
2863 void test_long (u32 d, u32 s)
2864 { test_long_asm(&M.x86.R_EFLG,d,s); }
2865
2866 u8 xor_byte (u8 d, u8 s)
2867 { return xor_byte_asm(&M.x86.R_EFLG,d,s); }
2868
2869 u16 xor_word (u16 d, u16 s)
2870 { return xor_word_asm(&M.x86.R_EFLG,d,s); }
2871
2872 u32 xor_long (u32 d, u32 s)
2873 { return xor_long_asm(&M.x86.R_EFLG,d,s); }
2874
2875 void imul_byte (u8 s)
2876 { imul_byte_asm(&M.x86.R_EFLG,&M.x86.R_AX,M.x86.R_AL,s); }
2877
2878 void imul_word (u16 s)
2879 { imul_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,s); }
2880
2881 void imul_long (u32 s)
2882 { imul_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s); }
2883
2884 void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
2885 { imul_long_asm(&M.x86.R_EFLG,res_lo,res_hi,d,s); }
2886
2887 void mul_byte (u8 s)
2888 { mul_byte_asm(&M.x86.R_EFLG,&M.x86.R_AX,M.x86.R_AL,s); }
2889
2890 void mul_word (u16 s)
2891 { mul_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,s); }
2892
2893 void mul_long (u32 s)
2894 { mul_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s); }
2895
2896 void idiv_byte (u8 s)
2897 { idiv_byte_asm(&M.x86.R_EFLG,&M.x86.R_AL,&M.x86.R_AH,M.x86.R_AX,s); }
2898
2899 void idiv_word (u16 s)
2900 { idiv_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,M.x86.R_DX,s); }
2901
2902 void idiv_long (u32 s)
2903 { idiv_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,M.x86.R_EDX,s); }
2904
2905 void div_byte (u8 s)
2906 { div_byte_asm(&M.x86.R_EFLG,&M.x86.R_AL,&M.x86.R_AH,M.x86.R_AX,s); }
2907
2908 void div_word (u16 s)
2909 { div_word_asm(&M.x86.R_EFLG,&M.x86.R_AX,&M.x86.R_DX,M.x86.R_AX,M.x86.R_DX,s); }
2910
2911 void div_long (u32 s)
2912 { div_long_asm(&M.x86.R_EFLG,&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,M.x86.R_EDX,s); }
2913
2914 #endif