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