105b261ecSmrg/****************************************************************************
205b261ecSmrg*
305b261ecSmrg*						Realmode X86 Emulator Library
405b261ecSmrg*
505b261ecSmrg*            	Copyright (C) 1996-1999 SciTech Software, Inc.
605b261ecSmrg* 				     Copyright (C) David Mosberger-Tang
705b261ecSmrg* 					   Copyright (C) 1999 Egbert Eich
805b261ecSmrg*
905b261ecSmrg*  ========================================================================
1005b261ecSmrg*
1105b261ecSmrg*  Permission to use, copy, modify, distribute, and sell this software and
1205b261ecSmrg*  its documentation for any purpose is hereby granted without fee,
1305b261ecSmrg*  provided that the above copyright notice appear in all copies and that
1405b261ecSmrg*  both that copyright notice and this permission notice appear in
1505b261ecSmrg*  supporting documentation, and that the name of the authors not be used
1605b261ecSmrg*  in advertising or publicity pertaining to distribution of the software
1705b261ecSmrg*  without specific, written prior permission.  The authors makes no
1805b261ecSmrg*  representations about the suitability of this software for any purpose.
1905b261ecSmrg*  It is provided "as is" without express or implied warranty.
2005b261ecSmrg*
2105b261ecSmrg*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
2205b261ecSmrg*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
2305b261ecSmrg*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
2405b261ecSmrg*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
2505b261ecSmrg*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
2605b261ecSmrg*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2705b261ecSmrg*  PERFORMANCE OF THIS SOFTWARE.
2805b261ecSmrg*
2905b261ecSmrg*  ========================================================================
3005b261ecSmrg*
3105b261ecSmrg* Language:		ANSI C
3205b261ecSmrg* Environment:	Any
3305b261ecSmrg* Developer:    Kendall Bennett
3405b261ecSmrg*
3505b261ecSmrg* Description:  This file contains the code to implement the primitive
3605b261ecSmrg*				machine operations used by the emulation code in ops.c
3705b261ecSmrg*
3805b261ecSmrg* Carry Chain Calculation
3905b261ecSmrg*
4005b261ecSmrg* This represents a somewhat expensive calculation which is
4105b261ecSmrg* apparently required to emulate the setting of the OF and AF flag.
4205b261ecSmrg* The latter is not so important, but the former is.  The overflow
4305b261ecSmrg* flag is the XOR of the top two bits of the carry chain for an
4405b261ecSmrg* addition (similar for subtraction).  Since we do not want to
4505b261ecSmrg* simulate the addition in a bitwise manner, we try to calculate the
4605b261ecSmrg* carry chain given the two operands and the result.
4705b261ecSmrg*
4805b261ecSmrg* So, given the following table, which represents the addition of two
4905b261ecSmrg* bits, we can derive a formula for the carry chain.
5005b261ecSmrg*
5105b261ecSmrg* a   b   cin   r     cout
5205b261ecSmrg* 0   0   0     0     0
5305b261ecSmrg* 0   0   1     1     0
5405b261ecSmrg* 0   1   0     1     0
5505b261ecSmrg* 0   1   1     0     1
5605b261ecSmrg* 1   0   0     1     0
5705b261ecSmrg* 1   0   1     0     1
5805b261ecSmrg* 1   1   0     0     1
5905b261ecSmrg* 1   1   1     1     1
6005b261ecSmrg*
6105b261ecSmrg* Construction of table for cout:
6205b261ecSmrg*
6305b261ecSmrg* ab
6405b261ecSmrg* r  \  00   01   11  10
6505b261ecSmrg* |------------------
6605b261ecSmrg* 0  |   0    1    1   1
6705b261ecSmrg* 1  |   0    0    1   0
6805b261ecSmrg*
6905b261ecSmrg* By inspection, one gets:  cc = ab +  r'(a + b)
7005b261ecSmrg*
715a112b11Smrg* That represents a lot of operations, but NO CHOICE....
7205b261ecSmrg*
7305b261ecSmrg* Borrow Chain Calculation.
7405b261ecSmrg*
7505b261ecSmrg* The following table represents the subtraction of two bits, from
7605b261ecSmrg* which we can derive a formula for the borrow chain.
7705b261ecSmrg*
7805b261ecSmrg* a   b   bin   r     bout
7905b261ecSmrg* 0   0   0     0     0
8005b261ecSmrg* 0   0   1     1     1
8105b261ecSmrg* 0   1   0     1     1
8205b261ecSmrg* 0   1   1     0     1
8305b261ecSmrg* 1   0   0     1     0
8405b261ecSmrg* 1   0   1     0     0
8505b261ecSmrg* 1   1   0     0     0
8605b261ecSmrg* 1   1   1     1     1
8705b261ecSmrg*
8805b261ecSmrg* Construction of table for cout:
8905b261ecSmrg*
9005b261ecSmrg* ab
9105b261ecSmrg* r  \  00   01   11  10
9205b261ecSmrg* |------------------
9305b261ecSmrg* 0  |   0    1    0   0
9405b261ecSmrg* 1  |   1    1    1   0
9505b261ecSmrg*
9605b261ecSmrg* By inspection, one gets:  bc = a'b +  r(a' + b)
9705b261ecSmrg*
9805b261ecSmrg****************************************************************************/
9905b261ecSmrg
10005b261ecSmrg#include <stdlib.h>
10105b261ecSmrg
10205b261ecSmrg#define	PRIM_OPS_NO_REDEFINE_ASM
10305b261ecSmrg#include "x86emu/x86emui.h"
10405b261ecSmrg
1054642e01fSmrg#if defined(__GNUC__)
106f7df2e56Smrg#if defined (__i386__) || defined(__i386) || defined(__AMD64__) || defined(__amd64__)
107f7df2e56Smrg#include "x86emu/prim_x86_gcc.h"
108f7df2e56Smrg#endif
1094642e01fSmrg#endif
1104642e01fSmrg
11105b261ecSmrg/*------------------------- Global Variables ------------------------------*/
11205b261ecSmrg
113f7df2e56Smrgstatic u32 x86emu_parity_tab[8] = {
114f7df2e56Smrg    0x96696996,
115f7df2e56Smrg    0x69969669,
116f7df2e56Smrg    0x69969669,
117f7df2e56Smrg    0x96696996,
118f7df2e56Smrg    0x69969669,
119f7df2e56Smrg    0x96696996,
120f7df2e56Smrg    0x96696996,
121f7df2e56Smrg    0x69969669,
12205b261ecSmrg};
12305b261ecSmrg
12405b261ecSmrg#define PARITY(x)   (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
12505b261ecSmrg#define XOR2(x) 	(((x) ^ ((x)>>1)) & 0x1)
12605b261ecSmrg
12705b261ecSmrg/*----------------------------- Implementation ----------------------------*/
12805b261ecSmrg
12905b261ecSmrg/****************************************************************************
13005b261ecSmrgREMARKS:
13105b261ecSmrgImplements the AAA instruction and side effects.
13205b261ecSmrg****************************************************************************/
133f7df2e56Smrgu16
134f7df2e56Smrgaaa_word(u16 d)
13505b261ecSmrg{
136f7df2e56Smrg    u16 res;
137f7df2e56Smrg
138f7df2e56Smrg    if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
139f7df2e56Smrg        d += 0x6;
140f7df2e56Smrg        d += 0x100;
141f7df2e56Smrg        SET_FLAG(F_AF);
142f7df2e56Smrg        SET_FLAG(F_CF);
143f7df2e56Smrg    }
144f7df2e56Smrg    else {
145f7df2e56Smrg        CLEAR_FLAG(F_CF);
146f7df2e56Smrg        CLEAR_FLAG(F_AF);
147f7df2e56Smrg    }
148f7df2e56Smrg    res = (u16) (d & 0xFF0F);
149f7df2e56Smrg    CLEAR_FLAG(F_SF);
150f7df2e56Smrg    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
151f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
152f7df2e56Smrg    return res;
15305b261ecSmrg}
15405b261ecSmrg
15505b261ecSmrg/****************************************************************************
15605b261ecSmrgREMARKS:
15705b261ecSmrgImplements the AAA instruction and side effects.
15805b261ecSmrg****************************************************************************/
159f7df2e56Smrgu16
160f7df2e56Smrgaas_word(u16 d)
16105b261ecSmrg{
162f7df2e56Smrg    u16 res;
163f7df2e56Smrg
164f7df2e56Smrg    if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
165f7df2e56Smrg        d -= 0x6;
166f7df2e56Smrg        d -= 0x100;
167f7df2e56Smrg        SET_FLAG(F_AF);
168f7df2e56Smrg        SET_FLAG(F_CF);
169f7df2e56Smrg    }
170f7df2e56Smrg    else {
171f7df2e56Smrg        CLEAR_FLAG(F_CF);
172f7df2e56Smrg        CLEAR_FLAG(F_AF);
173f7df2e56Smrg    }
174f7df2e56Smrg    res = (u16) (d & 0xFF0F);
175f7df2e56Smrg    CLEAR_FLAG(F_SF);
176f7df2e56Smrg    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
177f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
178f7df2e56Smrg    return res;
17905b261ecSmrg}
18005b261ecSmrg
18105b261ecSmrg/****************************************************************************
18205b261ecSmrgREMARKS:
18305b261ecSmrgImplements the AAD instruction and side effects.
18405b261ecSmrg****************************************************************************/
185f7df2e56Smrgu16
186f7df2e56Smrgaad_word(u16 d)
18705b261ecSmrg{
188f7df2e56Smrg    u16 l;
189f7df2e56Smrg    u8 hb, lb;
19005b261ecSmrg
191f7df2e56Smrg    hb = (u8) ((d >> 8) & 0xff);
192f7df2e56Smrg    lb = (u8) ((d & 0xff));
193f7df2e56Smrg    l = (u16) ((lb + 10 * hb) & 0xFF);
19405b261ecSmrg
195f7df2e56Smrg    CLEAR_FLAG(F_CF);
196f7df2e56Smrg    CLEAR_FLAG(F_AF);
197f7df2e56Smrg    CLEAR_FLAG(F_OF);
198f7df2e56Smrg    CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
199f7df2e56Smrg    CONDITIONAL_SET_FLAG(l == 0, F_ZF);
200f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
201f7df2e56Smrg    return l;
20205b261ecSmrg}
20305b261ecSmrg
20405b261ecSmrg/****************************************************************************
20505b261ecSmrgREMARKS:
20605b261ecSmrgImplements the AAM instruction and side effects.
20705b261ecSmrg****************************************************************************/
208f7df2e56Smrgu16
209f7df2e56Smrgaam_word(u8 d)
21005b261ecSmrg{
21105b261ecSmrg    u16 h, l;
21205b261ecSmrg
213f7df2e56Smrg    h = (u16) (d / 10);
214f7df2e56Smrg    l = (u16) (d % 10);
215f7df2e56Smrg    l |= (u16) (h << 8);
21605b261ecSmrg
217f7df2e56Smrg    CLEAR_FLAG(F_CF);
218f7df2e56Smrg    CLEAR_FLAG(F_AF);
219f7df2e56Smrg    CLEAR_FLAG(F_OF);
220f7df2e56Smrg    CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
221f7df2e56Smrg    CONDITIONAL_SET_FLAG(l == 0, F_ZF);
222f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
22305b261ecSmrg    return l;
22405b261ecSmrg}
22505b261ecSmrg
22605b261ecSmrg/****************************************************************************
22705b261ecSmrgREMARKS:
22805b261ecSmrgImplements the ADC instruction and side effects.
22905b261ecSmrg****************************************************************************/
230f7df2e56Smrgu8
231f7df2e56Smrgadc_byte(u8 d, u8 s)
23205b261ecSmrg{
233f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
234f7df2e56Smrg    register u32 cc;
23505b261ecSmrg
236f7df2e56Smrg    if (ACCESS_FLAG(F_CF))
237f7df2e56Smrg        res = 1 + d + s;
238f7df2e56Smrg    else
239f7df2e56Smrg        res = d + s;
24005b261ecSmrg
241f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
242f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
243f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
244f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
24505b261ecSmrg
246f7df2e56Smrg    /* calculate the carry chain  SEE NOTE AT TOP. */
247f7df2e56Smrg    cc = (s & d) | ((~res) & (s | d));
248f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
249f7df2e56Smrg    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
250f7df2e56Smrg    return (u8) res;
25105b261ecSmrg}
25205b261ecSmrg
25305b261ecSmrg/****************************************************************************
25405b261ecSmrgREMARKS:
25505b261ecSmrgImplements the ADC instruction and side effects.
25605b261ecSmrg****************************************************************************/
257f7df2e56Smrgu16
258f7df2e56Smrgadc_word(u16 d, u16 s)
25905b261ecSmrg{
260f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
261f7df2e56Smrg    register u32 cc;
26205b261ecSmrg
263f7df2e56Smrg    if (ACCESS_FLAG(F_CF))
264f7df2e56Smrg        res = 1 + d + s;
265f7df2e56Smrg    else
266f7df2e56Smrg        res = d + s;
26705b261ecSmrg
268f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
269f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
270f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
271f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
27205b261ecSmrg
273f7df2e56Smrg    /* calculate the carry chain  SEE NOTE AT TOP. */
274f7df2e56Smrg    cc = (s & d) | ((~res) & (s | d));
275f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
276f7df2e56Smrg    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
277f7df2e56Smrg    return (u16) res;
27805b261ecSmrg}
27905b261ecSmrg
28005b261ecSmrg/****************************************************************************
28105b261ecSmrgREMARKS:
28205b261ecSmrgImplements the ADC instruction and side effects.
28305b261ecSmrg****************************************************************************/
284f7df2e56Smrgu32
285f7df2e56Smrgadc_long(u32 d, u32 s)
28605b261ecSmrg{
287f7df2e56Smrg    register u32 lo;            /* all operands in native machine order */
288f7df2e56Smrg    register u32 hi;
289f7df2e56Smrg    register u32 res;
290f7df2e56Smrg    register u32 cc;
29105b261ecSmrg
292f7df2e56Smrg    if (ACCESS_FLAG(F_CF)) {
293f7df2e56Smrg        lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
294f7df2e56Smrg        res = 1 + d + s;
295f7df2e56Smrg    }
296f7df2e56Smrg    else {
297f7df2e56Smrg        lo = (d & 0xFFFF) + (s & 0xFFFF);
298f7df2e56Smrg        res = d + s;
299f7df2e56Smrg    }
300f7df2e56Smrg    hi = (lo >> 16) + (d >> 16) + (s >> 16);
30105b261ecSmrg
302f7df2e56Smrg    CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
303f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
304f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
305f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
30605b261ecSmrg
307f7df2e56Smrg    /* calculate the carry chain  SEE NOTE AT TOP. */
308f7df2e56Smrg    cc = (s & d) | ((~res) & (s | d));
309f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
310f7df2e56Smrg    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
311f7df2e56Smrg    return res;
31205b261ecSmrg}
31305b261ecSmrg
31405b261ecSmrg/****************************************************************************
31505b261ecSmrgREMARKS:
31605b261ecSmrgImplements the ADD instruction and side effects.
31705b261ecSmrg****************************************************************************/
318f7df2e56Smrgu8
319f7df2e56Smrgadd_byte(u8 d, u8 s)
32005b261ecSmrg{
321f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
322f7df2e56Smrg    register u32 cc;
32305b261ecSmrg
324f7df2e56Smrg    res = d + s;
325f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
326f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
327f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
328f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
32905b261ecSmrg
330f7df2e56Smrg    /* calculate the carry chain  SEE NOTE AT TOP. */
331f7df2e56Smrg    cc = (s & d) | ((~res) & (s | d));
332f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
333f7df2e56Smrg    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
334f7df2e56Smrg    return (u8) res;
33505b261ecSmrg}
33605b261ecSmrg
33705b261ecSmrg/****************************************************************************
33805b261ecSmrgREMARKS:
33905b261ecSmrgImplements the ADD instruction and side effects.
34005b261ecSmrg****************************************************************************/
341f7df2e56Smrgu16
342f7df2e56Smrgadd_word(u16 d, u16 s)
34305b261ecSmrg{
344f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
345f7df2e56Smrg    register u32 cc;
34605b261ecSmrg
347f7df2e56Smrg    res = d + s;
348f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
349f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
350f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
351f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
35205b261ecSmrg
353f7df2e56Smrg    /* calculate the carry chain  SEE NOTE AT TOP. */
354f7df2e56Smrg    cc = (s & d) | ((~res) & (s | d));
355f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
356f7df2e56Smrg    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
357f7df2e56Smrg    return (u16) res;
35805b261ecSmrg}
35905b261ecSmrg
36005b261ecSmrg/****************************************************************************
36105b261ecSmrgREMARKS:
36205b261ecSmrgImplements the ADD instruction and side effects.
36305b261ecSmrg****************************************************************************/
364f7df2e56Smrgu32
365f7df2e56Smrgadd_long(u32 d, u32 s)
36605b261ecSmrg{
367f7df2e56Smrg    register u32 lo;            /* all operands in native machine order */
368f7df2e56Smrg    register u32 hi;
369f7df2e56Smrg    register u32 res;
370f7df2e56Smrg    register u32 cc;
37105b261ecSmrg
372f7df2e56Smrg    lo = (d & 0xFFFF) + (s & 0xFFFF);
373f7df2e56Smrg    res = d + s;
374f7df2e56Smrg    hi = (lo >> 16) + (d >> 16) + (s >> 16);
37505b261ecSmrg
376f7df2e56Smrg    CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
377f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
378f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
379f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
38005b261ecSmrg
38105b261ecSmrg    /* calculate the carry chain  SEE NOTE AT TOP. */
38205b261ecSmrg    cc = (s & d) | ((~res) & (s | d));
383f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
384f7df2e56Smrg    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
38505b261ecSmrg
38605b261ecSmrg    return res;
38705b261ecSmrg}
38805b261ecSmrg
38905b261ecSmrg/****************************************************************************
39005b261ecSmrgREMARKS:
39105b261ecSmrgImplements the AND instruction and side effects.
39205b261ecSmrg****************************************************************************/
393f7df2e56Smrgu8
394f7df2e56Smrgand_byte(u8 d, u8 s)
39505b261ecSmrg{
396f7df2e56Smrg    register u8 res;            /* all operands in native machine order */
39705b261ecSmrg
398f7df2e56Smrg    res = d & s;
39905b261ecSmrg
400f7df2e56Smrg    /* set the flags  */
401f7df2e56Smrg    CLEAR_FLAG(F_OF);
402f7df2e56Smrg    CLEAR_FLAG(F_CF);
403f7df2e56Smrg    CLEAR_FLAG(F_AF);
404f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
405f7df2e56Smrg    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
406f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
407f7df2e56Smrg    return res;
40805b261ecSmrg}
40905b261ecSmrg
41005b261ecSmrg/****************************************************************************
41105b261ecSmrgREMARKS:
41205b261ecSmrgImplements the AND instruction and side effects.
41305b261ecSmrg****************************************************************************/
414f7df2e56Smrgu16
415f7df2e56Smrgand_word(u16 d, u16 s)
41605b261ecSmrg{
417f7df2e56Smrg    register u16 res;           /* all operands in native machine order */
41805b261ecSmrg
41905b261ecSmrg    res = d & s;
42005b261ecSmrg
42105b261ecSmrg    /* set the flags  */
422f7df2e56Smrg    CLEAR_FLAG(F_OF);
423f7df2e56Smrg    CLEAR_FLAG(F_CF);
424f7df2e56Smrg    CLEAR_FLAG(F_AF);
425f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
426f7df2e56Smrg    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
427f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
42805b261ecSmrg    return res;
42905b261ecSmrg}
43005b261ecSmrg
43105b261ecSmrg/****************************************************************************
43205b261ecSmrgREMARKS:
43305b261ecSmrgImplements the AND instruction and side effects.
43405b261ecSmrg****************************************************************************/
435f7df2e56Smrgu32
436f7df2e56Smrgand_long(u32 d, u32 s)
43705b261ecSmrg{
438f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
43905b261ecSmrg
440f7df2e56Smrg    res = d & s;
44105b261ecSmrg
442f7df2e56Smrg    /* set the flags  */
443f7df2e56Smrg    CLEAR_FLAG(F_OF);
444f7df2e56Smrg    CLEAR_FLAG(F_CF);
445f7df2e56Smrg    CLEAR_FLAG(F_AF);
446f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
447f7df2e56Smrg    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
448f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
449f7df2e56Smrg    return res;
45005b261ecSmrg}
45105b261ecSmrg
45205b261ecSmrg/****************************************************************************
45305b261ecSmrgREMARKS:
45405b261ecSmrgImplements the CMP instruction and side effects.
45505b261ecSmrg****************************************************************************/
456f7df2e56Smrgu8
457f7df2e56Smrgcmp_byte(u8 d, u8 s)
45805b261ecSmrg{
459f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
460f7df2e56Smrg    register u32 bc;
46105b261ecSmrg
462f7df2e56Smrg    res = d - s;
463f7df2e56Smrg    CLEAR_FLAG(F_CF);
464f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
465f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
466f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
46705b261ecSmrg
468f7df2e56Smrg    /* calculate the borrow chain.  See note at top */
469f7df2e56Smrg    bc = (res & (~d | s)) | (~d & s);
470f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
471f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
472f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
473f7df2e56Smrg    return d;
47405b261ecSmrg}
47505b261ecSmrg
47605b261ecSmrg/****************************************************************************
47705b261ecSmrgREMARKS:
47805b261ecSmrgImplements the CMP instruction and side effects.
47905b261ecSmrg****************************************************************************/
480f7df2e56Smrgu16
481f7df2e56Smrgcmp_word(u16 d, u16 s)
48205b261ecSmrg{
483f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
484f7df2e56Smrg    register u32 bc;
48505b261ecSmrg
486f7df2e56Smrg    res = d - s;
487f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
488f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
489f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
49005b261ecSmrg
491f7df2e56Smrg    /* calculate the borrow chain.  See note at top */
49205b261ecSmrg    bc = (res & (~d | s)) | (~d & s);
493f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
494f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
495f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
496f7df2e56Smrg    return d;
49705b261ecSmrg}
49805b261ecSmrg
49905b261ecSmrg/****************************************************************************
50005b261ecSmrgREMARKS:
50105b261ecSmrgImplements the CMP instruction and side effects.
50205b261ecSmrg****************************************************************************/
503f7df2e56Smrgu32
504f7df2e56Smrgcmp_long(u32 d, u32 s)
50505b261ecSmrg{
506f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
507f7df2e56Smrg    register u32 bc;
50805b261ecSmrg
509f7df2e56Smrg    res = d - s;
510f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
511f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
512f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
51305b261ecSmrg
514f7df2e56Smrg    /* calculate the borrow chain.  See note at top */
515f7df2e56Smrg    bc = (res & (~d | s)) | (~d & s);
516f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
517f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
518f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
519f7df2e56Smrg    return d;
52005b261ecSmrg}
52105b261ecSmrg
52205b261ecSmrg/****************************************************************************
52305b261ecSmrgREMARKS:
52405b261ecSmrgImplements the DAA instruction and side effects.
52505b261ecSmrg****************************************************************************/
526f7df2e56Smrgu8
527f7df2e56Smrgdaa_byte(u8 d)
52805b261ecSmrg{
529f7df2e56Smrg    u32 res = d;
530f7df2e56Smrg
531f7df2e56Smrg    if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
532f7df2e56Smrg        res += 6;
533f7df2e56Smrg        SET_FLAG(F_AF);
534f7df2e56Smrg    }
535f7df2e56Smrg    if (res > 0x9F || ACCESS_FLAG(F_CF)) {
536f7df2e56Smrg        res += 0x60;
537f7df2e56Smrg        SET_FLAG(F_CF);
538f7df2e56Smrg    }
539f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
540f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
541f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
542f7df2e56Smrg    return (u8) res;
54305b261ecSmrg}
54405b261ecSmrg
54505b261ecSmrg/****************************************************************************
54605b261ecSmrgREMARKS:
54705b261ecSmrgImplements the DAS instruction and side effects.
54805b261ecSmrg****************************************************************************/
549f7df2e56Smrgu8
550f7df2e56Smrgdas_byte(u8 d)
55105b261ecSmrg{
552f7df2e56Smrg    if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
553f7df2e56Smrg        d -= 6;
554f7df2e56Smrg        SET_FLAG(F_AF);
555f7df2e56Smrg    }
556f7df2e56Smrg    if (d > 0x9F || ACCESS_FLAG(F_CF)) {
557f7df2e56Smrg        d -= 0x60;
558f7df2e56Smrg        SET_FLAG(F_CF);
559f7df2e56Smrg    }
560f7df2e56Smrg    CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
561f7df2e56Smrg    CONDITIONAL_SET_FLAG(d == 0, F_ZF);
562f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
563f7df2e56Smrg    return d;
56405b261ecSmrg}
56505b261ecSmrg
56605b261ecSmrg/****************************************************************************
56705b261ecSmrgREMARKS:
56805b261ecSmrgImplements the DEC instruction and side effects.
56905b261ecSmrg****************************************************************************/
570f7df2e56Smrgu8
571f7df2e56Smrgdec_byte(u8 d)
57205b261ecSmrg{
573f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
57405b261ecSmrg    register u32 bc;
57505b261ecSmrg
57605b261ecSmrg    res = d - 1;
577f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
578f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
579f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
58005b261ecSmrg
581f7df2e56Smrg    /* calculate the borrow chain.  See note at top */
582f7df2e56Smrg    /* based on sub_byte, uses s==1.  */
583f7df2e56Smrg    bc = (res & (~d | 1)) | (~d & 1);
584f7df2e56Smrg    /* carry flag unchanged */
585f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
586f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
587f7df2e56Smrg    return (u8) res;
58805b261ecSmrg}
58905b261ecSmrg
59005b261ecSmrg/****************************************************************************
59105b261ecSmrgREMARKS:
59205b261ecSmrgImplements the DEC instruction and side effects.
59305b261ecSmrg****************************************************************************/
594f7df2e56Smrgu16
595f7df2e56Smrgdec_word(u16 d)
59605b261ecSmrg{
597f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
59805b261ecSmrg    register u32 bc;
59905b261ecSmrg
60005b261ecSmrg    res = d - 1;
601f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
602f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
603f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
60405b261ecSmrg
60505b261ecSmrg    /* calculate the borrow chain.  See note at top */
60605b261ecSmrg    /* based on the sub_byte routine, with s==1 */
60705b261ecSmrg    bc = (res & (~d | 1)) | (~d & 1);
60805b261ecSmrg    /* carry flag unchanged */
609f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
610f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
611f7df2e56Smrg    return (u16) res;
61205b261ecSmrg}
61305b261ecSmrg
61405b261ecSmrg/****************************************************************************
61505b261ecSmrgREMARKS:
61605b261ecSmrgImplements the DEC instruction and side effects.
61705b261ecSmrg****************************************************************************/
618f7df2e56Smrgu32
619f7df2e56Smrgdec_long(u32 d)
62005b261ecSmrg{
621f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
62205b261ecSmrg    register u32 bc;
62305b261ecSmrg
62405b261ecSmrg    res = d - 1;
62505b261ecSmrg
626f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
627f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
628f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
62905b261ecSmrg
63005b261ecSmrg    /* calculate the borrow chain.  See note at top */
631f7df2e56Smrg    bc = (res & (~d | 1)) | (~d & 1);
632f7df2e56Smrg    /* carry flag unchanged */
633f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
634f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
635f7df2e56Smrg    return res;
63605b261ecSmrg}
63705b261ecSmrg
63805b261ecSmrg/****************************************************************************
63905b261ecSmrgREMARKS:
64005b261ecSmrgImplements the INC instruction and side effects.
64105b261ecSmrg****************************************************************************/
642f7df2e56Smrgu8
643f7df2e56Smrginc_byte(u8 d)
64405b261ecSmrg{
645f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
646f7df2e56Smrg    register u32 cc;
64705b261ecSmrg
648f7df2e56Smrg    res = d + 1;
649f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
650f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
651f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
65205b261ecSmrg
653f7df2e56Smrg    /* calculate the carry chain  SEE NOTE AT TOP. */
654f7df2e56Smrg    cc = ((1 & d) | (~res)) & (1 | d);
655f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
656f7df2e56Smrg    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
657f7df2e56Smrg    return (u8) res;
65805b261ecSmrg}
65905b261ecSmrg
66005b261ecSmrg/****************************************************************************
66105b261ecSmrgREMARKS:
66205b261ecSmrgImplements the INC instruction and side effects.
66305b261ecSmrg****************************************************************************/
664f7df2e56Smrgu16
665f7df2e56Smrginc_word(u16 d)
66605b261ecSmrg{
667f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
668f7df2e56Smrg    register u32 cc;
66905b261ecSmrg
670f7df2e56Smrg    res = d + 1;
671f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
672f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
673f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
67405b261ecSmrg
675f7df2e56Smrg    /* calculate the carry chain  SEE NOTE AT TOP. */
676f7df2e56Smrg    cc = (1 & d) | ((~res) & (1 | d));
677f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
678f7df2e56Smrg    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
679f7df2e56Smrg    return (u16) res;
68005b261ecSmrg}
68105b261ecSmrg
68205b261ecSmrg/****************************************************************************
68305b261ecSmrgREMARKS:
68405b261ecSmrgImplements the INC instruction and side effects.
68505b261ecSmrg****************************************************************************/
686f7df2e56Smrgu32
687f7df2e56Smrginc_long(u32 d)
68805b261ecSmrg{
689f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
690f7df2e56Smrg    register u32 cc;
69105b261ecSmrg
692f7df2e56Smrg    res = d + 1;
693f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
694f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
695f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
69605b261ecSmrg
697f7df2e56Smrg    /* calculate the carry chain  SEE NOTE AT TOP. */
698f7df2e56Smrg    cc = (1 & d) | ((~res) & (1 | d));
699f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
700f7df2e56Smrg    CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
701f7df2e56Smrg    return res;
70205b261ecSmrg}
70305b261ecSmrg
70405b261ecSmrg/****************************************************************************
70505b261ecSmrgREMARKS:
70605b261ecSmrgImplements the OR instruction and side effects.
70705b261ecSmrg****************************************************************************/
708f7df2e56Smrgu8
709f7df2e56Smrgor_byte(u8 d, u8 s)
71005b261ecSmrg{
711f7df2e56Smrg    register u8 res;            /* all operands in native machine order */
71205b261ecSmrg
713f7df2e56Smrg    res = d | s;
714f7df2e56Smrg    CLEAR_FLAG(F_OF);
715f7df2e56Smrg    CLEAR_FLAG(F_CF);
716f7df2e56Smrg    CLEAR_FLAG(F_AF);
717f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
718f7df2e56Smrg    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
719f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
720f7df2e56Smrg    return res;
72105b261ecSmrg}
72205b261ecSmrg
72305b261ecSmrg/****************************************************************************
72405b261ecSmrgREMARKS:
72505b261ecSmrgImplements the OR instruction and side effects.
72605b261ecSmrg****************************************************************************/
727f7df2e56Smrgu16
728f7df2e56Smrgor_word(u16 d, u16 s)
72905b261ecSmrg{
730f7df2e56Smrg    register u16 res;           /* all operands in native machine order */
73105b261ecSmrg
732f7df2e56Smrg    res = d | s;
733f7df2e56Smrg    /* set the carry flag to be bit 8 */
734f7df2e56Smrg    CLEAR_FLAG(F_OF);
735f7df2e56Smrg    CLEAR_FLAG(F_CF);
736f7df2e56Smrg    CLEAR_FLAG(F_AF);
737f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
738f7df2e56Smrg    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
739f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
740f7df2e56Smrg    return res;
74105b261ecSmrg}
74205b261ecSmrg
74305b261ecSmrg/****************************************************************************
74405b261ecSmrgREMARKS:
74505b261ecSmrgImplements the OR instruction and side effects.
74605b261ecSmrg****************************************************************************/
747f7df2e56Smrgu32
748f7df2e56Smrgor_long(u32 d, u32 s)
74905b261ecSmrg{
750f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
75105b261ecSmrg
752f7df2e56Smrg    res = d | s;
75305b261ecSmrg
754f7df2e56Smrg    /* set the carry flag to be bit 8 */
755f7df2e56Smrg    CLEAR_FLAG(F_OF);
756f7df2e56Smrg    CLEAR_FLAG(F_CF);
757f7df2e56Smrg    CLEAR_FLAG(F_AF);
758f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
759f7df2e56Smrg    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
760f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
761f7df2e56Smrg    return res;
76205b261ecSmrg}
76305b261ecSmrg
76405b261ecSmrg/****************************************************************************
76505b261ecSmrgREMARKS:
76605b261ecSmrgImplements the OR instruction and side effects.
76705b261ecSmrg****************************************************************************/
768f7df2e56Smrgu8
769f7df2e56Smrgneg_byte(u8 s)
77005b261ecSmrg{
77105b261ecSmrg    register u8 res;
77205b261ecSmrg    register u8 bc;
77305b261ecSmrg
774f7df2e56Smrg    CONDITIONAL_SET_FLAG(s != 0, F_CF);
775f7df2e56Smrg    res = (u8) - s;
776f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
777f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
778f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
779f7df2e56Smrg    /* calculate the borrow chain --- modified such that d=0.
780f7df2e56Smrg       substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
781f7df2e56Smrg       (the one used for sub) and simplifying, since ~d=0xff...,
782f7df2e56Smrg       ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
783f7df2e56Smrg       ~d&s == s.  So the simplified result is: */
784f7df2e56Smrg    bc = res | s;
785f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
786f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
787f7df2e56Smrg    return res;
78805b261ecSmrg}
78905b261ecSmrg
79005b261ecSmrg/****************************************************************************
79105b261ecSmrgREMARKS:
79205b261ecSmrgImplements the OR instruction and side effects.
79305b261ecSmrg****************************************************************************/
794f7df2e56Smrgu16
795f7df2e56Smrgneg_word(u16 s)
796f7df2e56Smrg{
797f7df2e56Smrg    register u16 res;
798f7df2e56Smrg    register u16 bc;
799f7df2e56Smrg
800f7df2e56Smrg    CONDITIONAL_SET_FLAG(s != 0, F_CF);
801f7df2e56Smrg    res = (u16) - s;
802f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
803f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
804f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
805f7df2e56Smrg
806f7df2e56Smrg    /* calculate the borrow chain --- modified such that d=0.
807f7df2e56Smrg       substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
808f7df2e56Smrg       (the one used for sub) and simplifying, since ~d=0xff...,
809f7df2e56Smrg       ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
810f7df2e56Smrg       ~d&s == s.  So the simplified result is: */
811f7df2e56Smrg    bc = res | s;
812f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
813f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
814f7df2e56Smrg    return res;
81505b261ecSmrg}
81605b261ecSmrg
81705b261ecSmrg/****************************************************************************
81805b261ecSmrgREMARKS:
81905b261ecSmrgImplements the OR instruction and side effects.
82005b261ecSmrg****************************************************************************/
821f7df2e56Smrgu32
822f7df2e56Smrgneg_long(u32 s)
82305b261ecSmrg{
824f7df2e56Smrg    register u32 res;
825f7df2e56Smrg    register u32 bc;
82605b261ecSmrg
827f7df2e56Smrg    CONDITIONAL_SET_FLAG(s != 0, F_CF);
828f7df2e56Smrg    res = (u32) - s;
829f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
830f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
831f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
832f7df2e56Smrg
833f7df2e56Smrg    /* calculate the borrow chain --- modified such that d=0.
834f7df2e56Smrg       substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
835f7df2e56Smrg       (the one used for sub) and simplifying, since ~d=0xff...,
836f7df2e56Smrg       ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
837f7df2e56Smrg       ~d&s == s.  So the simplified result is: */
838f7df2e56Smrg    bc = res | s;
839f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
840f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
841f7df2e56Smrg    return res;
84205b261ecSmrg}
84305b261ecSmrg
84405b261ecSmrg/****************************************************************************
84505b261ecSmrgREMARKS:
84605b261ecSmrgImplements the NOT instruction and side effects.
84705b261ecSmrg****************************************************************************/
848f7df2e56Smrgu8
849f7df2e56Smrgnot_byte(u8 s)
85005b261ecSmrg{
851f7df2e56Smrg    return ~s;
85205b261ecSmrg}
85305b261ecSmrg
85405b261ecSmrg/****************************************************************************
85505b261ecSmrgREMARKS:
85605b261ecSmrgImplements the NOT instruction and side effects.
85705b261ecSmrg****************************************************************************/
858f7df2e56Smrgu16
859f7df2e56Smrgnot_word(u16 s)
86005b261ecSmrg{
861f7df2e56Smrg    return ~s;
86205b261ecSmrg}
86305b261ecSmrg
86405b261ecSmrg/****************************************************************************
86505b261ecSmrgREMARKS:
86605b261ecSmrgImplements the NOT instruction and side effects.
86705b261ecSmrg****************************************************************************/
868f7df2e56Smrgu32
869f7df2e56Smrgnot_long(u32 s)
87005b261ecSmrg{
871f7df2e56Smrg    return ~s;
87205b261ecSmrg}
87305b261ecSmrg
87405b261ecSmrg/****************************************************************************
87505b261ecSmrgREMARKS:
87605b261ecSmrgImplements the RCL instruction and side effects.
87705b261ecSmrg****************************************************************************/
878f7df2e56Smrgu8
879f7df2e56Smrgrcl_byte(u8 d, u8 s)
88005b261ecSmrg{
88105b261ecSmrg    register unsigned int res, cnt, mask, cf;
88205b261ecSmrg
88305b261ecSmrg    /* s is the rotate distance.  It varies from 0 - 8. */
884f7df2e56Smrg    /* have
88505b261ecSmrg
886f7df2e56Smrg       CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
88705b261ecSmrg
888f7df2e56Smrg       want to rotate through the carry by "s" bits.  We could
88905b261ecSmrg       loop, but that's inefficient.  So the width is 9,
89005b261ecSmrg       and we split into three parts:
89105b261ecSmrg
89205b261ecSmrg       The new carry flag   (was B_n)
89305b261ecSmrg       the stuff in B_n-1 .. B_0
89405b261ecSmrg       the stuff in B_7 .. B_n+1
89505b261ecSmrg
89605b261ecSmrg       The new rotate is done mod 9, and given this,
89705b261ecSmrg       for a rotation of n bits (mod 9) the new carry flag is
898f7df2e56Smrg       then located n bits from the MSB.  The low part is
89905b261ecSmrg       then shifted up cnt bits, and the high part is or'd
900f7df2e56Smrg       in.  Using CAPS for new values, and lowercase for the
90105b261ecSmrg       original values, this can be expressed as:
90205b261ecSmrg
903f7df2e56Smrg       IF n > 0
90405b261ecSmrg       1) CF <-  b_(8-n)
90505b261ecSmrg       2) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0
90605b261ecSmrg       3) B_(n-1) <- cf
90705b261ecSmrg       4) B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1))
908f7df2e56Smrg     */
909f7df2e56Smrg    res = d;
910f7df2e56Smrg    if ((cnt = s % 9) != 0) {
91105b261ecSmrg        /* extract the new CARRY FLAG. */
91205b261ecSmrg        /* CF <-  b_(8-n)             */
91305b261ecSmrg        cf = (d >> (8 - cnt)) & 0x1;
91405b261ecSmrg
915f7df2e56Smrg        /* get the low stuff which rotated
91605b261ecSmrg           into the range B_7 .. B_cnt */
91705b261ecSmrg        /* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0  */
91805b261ecSmrg        /* note that the right hand side done by the mask */
919f7df2e56Smrg        res = (d << cnt) & 0xff;
92005b261ecSmrg
921f7df2e56Smrg        /* now the high stuff which rotated around
92205b261ecSmrg           into the positions B_cnt-2 .. B_0 */
92305b261ecSmrg        /* B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1)) */
924f7df2e56Smrg        /* shift it downward, 7-(n-2) = 9-n positions.
925f7df2e56Smrg           and mask off the result before or'ing in.
92605b261ecSmrg         */
92705b261ecSmrg        mask = (1 << (cnt - 1)) - 1;
92805b261ecSmrg        res |= (d >> (9 - cnt)) & mask;
92905b261ecSmrg
93005b261ecSmrg        /* if the carry flag was set, or it in.  */
931f7df2e56Smrg        if (ACCESS_FLAG(F_CF)) {        /* carry flag is set */
93205b261ecSmrg            /*  B_(n-1) <- cf */
93305b261ecSmrg            res |= 1 << (cnt - 1);
93405b261ecSmrg        }
93505b261ecSmrg        /* set the new carry flag, based on the variable "cf" */
936f7df2e56Smrg        CONDITIONAL_SET_FLAG(cf, F_CF);
937f7df2e56Smrg        /* OVERFLOW is set *IFF* cnt==1, then it is the
93805b261ecSmrg           xor of CF and the most significant bit.  Blecck. */
93905b261ecSmrg        /* parenthesized this expression since it appears to
94005b261ecSmrg           be causing OF to be misset */
941f7df2e56Smrg        CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)), F_OF);
94205b261ecSmrg
94305b261ecSmrg    }
944f7df2e56Smrg    return (u8) res;
94505b261ecSmrg}
94605b261ecSmrg
94705b261ecSmrg/****************************************************************************
94805b261ecSmrgREMARKS:
94905b261ecSmrgImplements the RCL instruction and side effects.
95005b261ecSmrg****************************************************************************/
951f7df2e56Smrgu16
952f7df2e56Smrgrcl_word(u16 d, u8 s)
95305b261ecSmrg{
954f7df2e56Smrg    register unsigned int res, cnt, mask, cf;
95505b261ecSmrg
956f7df2e56Smrg    res = d;
957f7df2e56Smrg    if ((cnt = s % 17) != 0) {
958f7df2e56Smrg        cf = (d >> (16 - cnt)) & 0x1;
959f7df2e56Smrg        res = (d << cnt) & 0xffff;
960f7df2e56Smrg        mask = (1 << (cnt - 1)) - 1;
961f7df2e56Smrg        res |= (d >> (17 - cnt)) & mask;
962f7df2e56Smrg        if (ACCESS_FLAG(F_CF)) {
963f7df2e56Smrg            res |= 1 << (cnt - 1);
964f7df2e56Smrg        }
965f7df2e56Smrg        CONDITIONAL_SET_FLAG(cf, F_CF);
966f7df2e56Smrg        CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)), F_OF);
967f7df2e56Smrg    }
968f7df2e56Smrg    return (u16) res;
96905b261ecSmrg}
97005b261ecSmrg
97105b261ecSmrg/****************************************************************************
97205b261ecSmrgREMARKS:
97305b261ecSmrgImplements the RCL instruction and side effects.
97405b261ecSmrg****************************************************************************/
975f7df2e56Smrgu32
976f7df2e56Smrgrcl_long(u32 d, u8 s)
97705b261ecSmrg{
978f7df2e56Smrg    register u32 res, cnt, mask, cf;
97905b261ecSmrg
980f7df2e56Smrg    res = d;
981f7df2e56Smrg    if ((cnt = s % 33) != 0) {
982f7df2e56Smrg        cf = (d >> (32 - cnt)) & 0x1;
983f7df2e56Smrg        res = (d << cnt) & 0xffffffff;
984f7df2e56Smrg        mask = (1 << (cnt - 1)) - 1;
985f7df2e56Smrg        res |= (d >> (33 - cnt)) & mask;
986f7df2e56Smrg        if (ACCESS_FLAG(F_CF)) {        /* carry flag is set */
987f7df2e56Smrg            res |= 1 << (cnt - 1);
988f7df2e56Smrg        }
989f7df2e56Smrg        CONDITIONAL_SET_FLAG(cf, F_CF);
990f7df2e56Smrg        CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)), F_OF);
991f7df2e56Smrg    }
992f7df2e56Smrg    return res;
99305b261ecSmrg}
99405b261ecSmrg
99505b261ecSmrg/****************************************************************************
99605b261ecSmrgREMARKS:
99705b261ecSmrgImplements the RCR instruction and side effects.
99805b261ecSmrg****************************************************************************/
999f7df2e56Smrgu8
1000f7df2e56Smrgrcr_byte(u8 d, u8 s)
100105b261ecSmrg{
1002f7df2e56Smrg    u32 res, cnt;
1003f7df2e56Smrg    u32 mask, cf, ocf = 0;
100405b261ecSmrg
1005f7df2e56Smrg    /* rotate right through carry */
1006f7df2e56Smrg    /*
100705b261ecSmrg       s is the rotate distance.  It varies from 0 - 8.
1008f7df2e56Smrg       d is the byte object rotated.
100905b261ecSmrg
1010f7df2e56Smrg       have
101105b261ecSmrg
1012f7df2e56Smrg       CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
101305b261ecSmrg
101405b261ecSmrg       The new rotate is done mod 9, and given this,
101505b261ecSmrg       for a rotation of n bits (mod 9) the new carry flag is
1016f7df2e56Smrg       then located n bits from the LSB.  The low part is
101705b261ecSmrg       then shifted up cnt bits, and the high part is or'd
1018f7df2e56Smrg       in.  Using CAPS for new values, and lowercase for the
101905b261ecSmrg       original values, this can be expressed as:
102005b261ecSmrg
1021f7df2e56Smrg       IF n > 0
102205b261ecSmrg       1) CF <-  b_(n-1)
102305b261ecSmrg       2) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
102405b261ecSmrg       3) B_(8-n) <- cf
102505b261ecSmrg       4) B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0)
1026f7df2e56Smrg     */
1027f7df2e56Smrg    res = d;
1028f7df2e56Smrg    if ((cnt = s % 9) != 0) {
102905b261ecSmrg        /* extract the new CARRY FLAG. */
103005b261ecSmrg        /* CF <-  b_(n-1)              */
103105b261ecSmrg        if (cnt == 1) {
103205b261ecSmrg            cf = d & 0x1;
103305b261ecSmrg            /* note hackery here.  Access_flag(..) evaluates to either
103405b261ecSmrg               0 if flag not set
103505b261ecSmrg               non-zero if flag is set.
1036f7df2e56Smrg               doing access_flag(..) != 0 casts that into either
1037f7df2e56Smrg               0..1 in any representation of the flags register
103805b261ecSmrg               (i.e. packed bit array or unpacked.)
103905b261ecSmrg             */
1040f7df2e56Smrg            ocf = ACCESS_FLAG(F_CF) != 0;
1041f7df2e56Smrg        }
1042f7df2e56Smrg        else
104305b261ecSmrg            cf = (d >> (cnt - 1)) & 0x1;
104405b261ecSmrg
104505b261ecSmrg        /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_n  */
104605b261ecSmrg        /* note that the right hand side done by the mask
1047f7df2e56Smrg           This is effectively done by shifting the
104805b261ecSmrg           object to the right.  The result must be masked,
1049f7df2e56Smrg           in case the object came in and was treated
105005b261ecSmrg           as a negative number.  Needed??? */
105105b261ecSmrg
105205b261ecSmrg        mask = (1 << (8 - cnt)) - 1;
105305b261ecSmrg        res = (d >> cnt) & mask;
105405b261ecSmrg
1055f7df2e56Smrg        /* now the high stuff which rotated around
105605b261ecSmrg           into the positions B_cnt-2 .. B_0 */
105705b261ecSmrg        /* B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0) */
1058f7df2e56Smrg        /* shift it downward, 7-(n-2) = 9-n positions.
1059f7df2e56Smrg           and mask off the result before or'ing in.
106005b261ecSmrg         */
106105b261ecSmrg        res |= (d << (9 - cnt));
106205b261ecSmrg
106305b261ecSmrg        /* if the carry flag was set, or it in.  */
1064f7df2e56Smrg        if (ACCESS_FLAG(F_CF)) {        /* carry flag is set */
106505b261ecSmrg            /*  B_(8-n) <- cf */
106605b261ecSmrg            res |= 1 << (8 - cnt);
106705b261ecSmrg        }
106805b261ecSmrg        /* set the new carry flag, based on the variable "cf" */
1069f7df2e56Smrg        CONDITIONAL_SET_FLAG(cf, F_CF);
1070f7df2e56Smrg        /* OVERFLOW is set *IFF* cnt==1, then it is the
107105b261ecSmrg           xor of CF and the most significant bit.  Blecck. */
107205b261ecSmrg        /* parenthesized... */
1073f7df2e56Smrg        if (cnt == 1) {
1074f7df2e56Smrg            CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)), F_OF);
1075f7df2e56Smrg        }
1076f7df2e56Smrg    }
1077f7df2e56Smrg    return (u8) res;
107805b261ecSmrg}
107905b261ecSmrg
108005b261ecSmrg/****************************************************************************
108105b261ecSmrgREMARKS:
108205b261ecSmrgImplements the RCR instruction and side effects.
108305b261ecSmrg****************************************************************************/
1084f7df2e56Smrgu16
1085f7df2e56Smrgrcr_word(u16 d, u8 s)
108605b261ecSmrg{
1087f7df2e56Smrg    u32 res, cnt;
1088f7df2e56Smrg    u32 mask, cf, ocf = 0;
108905b261ecSmrg
1090f7df2e56Smrg    /* rotate right through carry */
1091f7df2e56Smrg    res = d;
1092f7df2e56Smrg    if ((cnt = s % 17) != 0) {
1093f7df2e56Smrg        if (cnt == 1) {
1094f7df2e56Smrg            cf = d & 0x1;
1095f7df2e56Smrg            ocf = ACCESS_FLAG(F_CF) != 0;
1096f7df2e56Smrg        }
1097f7df2e56Smrg        else
1098f7df2e56Smrg            cf = (d >> (cnt - 1)) & 0x1;
1099f7df2e56Smrg        mask = (1 << (16 - cnt)) - 1;
1100f7df2e56Smrg        res = (d >> cnt) & mask;
1101f7df2e56Smrg        res |= (d << (17 - cnt));
1102f7df2e56Smrg        if (ACCESS_FLAG(F_CF)) {
1103f7df2e56Smrg            res |= 1 << (16 - cnt);
1104f7df2e56Smrg        }
1105f7df2e56Smrg        CONDITIONAL_SET_FLAG(cf, F_CF);
1106f7df2e56Smrg        if (cnt == 1) {
1107f7df2e56Smrg            CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)), F_OF);
1108f7df2e56Smrg        }
1109f7df2e56Smrg    }
1110f7df2e56Smrg    return (u16) res;
111105b261ecSmrg}
111205b261ecSmrg
111305b261ecSmrg/****************************************************************************
111405b261ecSmrgREMARKS:
111505b261ecSmrgImplements the RCR instruction and side effects.
111605b261ecSmrg****************************************************************************/
1117f7df2e56Smrgu32
1118f7df2e56Smrgrcr_long(u32 d, u8 s)
1119f7df2e56Smrg{
1120f7df2e56Smrg    u32 res, cnt;
1121f7df2e56Smrg    u32 mask, cf, ocf = 0;
1122f7df2e56Smrg
1123f7df2e56Smrg    /* rotate right through carry */
1124f7df2e56Smrg    res = d;
1125f7df2e56Smrg    if ((cnt = s % 33) != 0) {
1126f7df2e56Smrg        if (cnt == 1) {
1127f7df2e56Smrg            cf = d & 0x1;
1128f7df2e56Smrg            ocf = ACCESS_FLAG(F_CF) != 0;
1129f7df2e56Smrg        }
1130f7df2e56Smrg        else
1131f7df2e56Smrg            cf = (d >> (cnt - 1)) & 0x1;
1132f7df2e56Smrg        mask = (1 << (32 - cnt)) - 1;
1133f7df2e56Smrg        res = (d >> cnt) & mask;
1134f7df2e56Smrg        if (cnt != 1)
1135f7df2e56Smrg            res |= (d << (33 - cnt));
1136f7df2e56Smrg        if (ACCESS_FLAG(F_CF)) {        /* carry flag is set */
1137f7df2e56Smrg            res |= 1 << (32 - cnt);
1138f7df2e56Smrg        }
1139f7df2e56Smrg        CONDITIONAL_SET_FLAG(cf, F_CF);
1140f7df2e56Smrg        if (cnt == 1) {
1141f7df2e56Smrg            CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)), F_OF);
1142f7df2e56Smrg        }
1143f7df2e56Smrg    }
1144f7df2e56Smrg    return res;
114505b261ecSmrg}
114605b261ecSmrg
114705b261ecSmrg/****************************************************************************
114805b261ecSmrgREMARKS:
114905b261ecSmrgImplements the ROL instruction and side effects.
115005b261ecSmrg****************************************************************************/
1151f7df2e56Smrgu8
1152f7df2e56Smrgrol_byte(u8 d, u8 s)
115305b261ecSmrg{
115405b261ecSmrg    register unsigned int res, cnt, mask;
115505b261ecSmrg
115605b261ecSmrg    /* rotate left */
1157f7df2e56Smrg    /*
115805b261ecSmrg       s is the rotate distance.  It varies from 0 - 8.
1159f7df2e56Smrg       d is the byte object rotated.
116005b261ecSmrg
1161f7df2e56Smrg       have
116205b261ecSmrg
1163f7df2e56Smrg       CF  B_7 ... B_0
116405b261ecSmrg
116505b261ecSmrg       The new rotate is done mod 8.
116605b261ecSmrg       Much simpler than the "rcl" or "rcr" operations.
116705b261ecSmrg
1168f7df2e56Smrg       IF n > 0
116905b261ecSmrg       1) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0)
117005b261ecSmrg       2) B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n)
1171f7df2e56Smrg     */
117205b261ecSmrg    res = d;
1173f7df2e56Smrg    if ((cnt = s % 8) != 0) {
1174f7df2e56Smrg        /* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) */
1175f7df2e56Smrg        res = (d << cnt);
117605b261ecSmrg
1177f7df2e56Smrg        /* B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n) */
1178f7df2e56Smrg        mask = (1 << cnt) - 1;
1179f7df2e56Smrg        res |= (d >> (8 - cnt)) & mask;
118005b261ecSmrg
1181f7df2e56Smrg        /* set the new carry flag, Note that it is the low order
1182f7df2e56Smrg           bit of the result!!!                               */
1183f7df2e56Smrg        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1184f7df2e56Smrg        /* OVERFLOW is set *IFF* s==1, then it is the
1185f7df2e56Smrg           xor of CF and the most significant bit.  Blecck. */
1186f7df2e56Smrg        CONDITIONAL_SET_FLAG(s == 1 &&
1187f7df2e56Smrg                             XOR2((res & 0x1) + ((res >> 6) & 0x2)), F_OF);
1188f7df2e56Smrg    }
1189f7df2e56Smrg    if (s != 0) {
1190f7df2e56Smrg        /* set the new carry flag, Note that it is the low order
1191f7df2e56Smrg           bit of the result!!!                               */
1192f7df2e56Smrg        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1193f7df2e56Smrg    }
1194f7df2e56Smrg    return (u8) res;
119505b261ecSmrg}
119605b261ecSmrg
119705b261ecSmrg/****************************************************************************
119805b261ecSmrgREMARKS:
119905b261ecSmrgImplements the ROL instruction and side effects.
120005b261ecSmrg****************************************************************************/
1201f7df2e56Smrgu16
1202f7df2e56Smrgrol_word(u16 d, u8 s)
120305b261ecSmrg{
120405b261ecSmrg    register unsigned int res, cnt, mask;
120505b261ecSmrg
1206f7df2e56Smrg    res = d;
1207f7df2e56Smrg    if ((cnt = s % 16) != 0) {
1208f7df2e56Smrg        res = (d << cnt);
1209f7df2e56Smrg        mask = (1 << cnt) - 1;
1210f7df2e56Smrg        res |= (d >> (16 - cnt)) & mask;
1211f7df2e56Smrg        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1212f7df2e56Smrg        CONDITIONAL_SET_FLAG(s == 1 &&
1213f7df2e56Smrg                             XOR2((res & 0x1) + ((res >> 14) & 0x2)), F_OF);
1214f7df2e56Smrg    }
1215f7df2e56Smrg    if (s != 0) {
1216f7df2e56Smrg        /* set the new carry flag, Note that it is the low order
1217f7df2e56Smrg           bit of the result!!!                               */
1218f7df2e56Smrg        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1219f7df2e56Smrg    }
1220f7df2e56Smrg    return (u16) res;
122105b261ecSmrg}
122205b261ecSmrg
122305b261ecSmrg/****************************************************************************
122405b261ecSmrgREMARKS:
122505b261ecSmrgImplements the ROL instruction and side effects.
122605b261ecSmrg****************************************************************************/
1227f7df2e56Smrgu32
1228f7df2e56Smrgrol_long(u32 d, u8 s)
122905b261ecSmrg{
123005b261ecSmrg    register u32 res, cnt, mask;
123105b261ecSmrg
1232f7df2e56Smrg    res = d;
1233f7df2e56Smrg    if ((cnt = s % 32) != 0) {
1234f7df2e56Smrg        res = (d << cnt);
1235f7df2e56Smrg        mask = (1 << cnt) - 1;
1236f7df2e56Smrg        res |= (d >> (32 - cnt)) & mask;
1237f7df2e56Smrg        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1238f7df2e56Smrg        CONDITIONAL_SET_FLAG(s == 1 &&
1239f7df2e56Smrg                             XOR2((res & 0x1) + ((res >> 30) & 0x2)), F_OF);
1240f7df2e56Smrg    }
1241f7df2e56Smrg    if (s != 0) {
1242f7df2e56Smrg        /* set the new carry flag, Note that it is the low order
1243f7df2e56Smrg           bit of the result!!!                               */
1244f7df2e56Smrg        CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1245f7df2e56Smrg    }
1246f7df2e56Smrg    return res;
124705b261ecSmrg}
124805b261ecSmrg
124905b261ecSmrg/****************************************************************************
125005b261ecSmrgREMARKS:
125105b261ecSmrgImplements the ROR instruction and side effects.
125205b261ecSmrg****************************************************************************/
1253f7df2e56Smrgu8
1254f7df2e56Smrgror_byte(u8 d, u8 s)
125505b261ecSmrg{
125605b261ecSmrg    register unsigned int res, cnt, mask;
125705b261ecSmrg
125805b261ecSmrg    /* rotate right */
1259f7df2e56Smrg    /*
126005b261ecSmrg       s is the rotate distance.  It varies from 0 - 8.
1261f7df2e56Smrg       d is the byte object rotated.
126205b261ecSmrg
1263f7df2e56Smrg       have
126405b261ecSmrg
1265f7df2e56Smrg       B_7 ... B_0
126605b261ecSmrg
126705b261ecSmrg       The rotate is done mod 8.
126805b261ecSmrg
1269f7df2e56Smrg       IF n > 0
127005b261ecSmrg       1) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
127105b261ecSmrg       2) B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0)
1272f7df2e56Smrg     */
1273f7df2e56Smrg    res = d;
1274f7df2e56Smrg    if ((cnt = s % 8) != 0) {   /* not a typo, do nada if cnt==0 */
127505b261ecSmrg        /* B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0) */
127605b261ecSmrg        res = (d << (8 - cnt));
127705b261ecSmrg
127805b261ecSmrg        /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n) */
127905b261ecSmrg        mask = (1 << (8 - cnt)) - 1;
128005b261ecSmrg        res |= (d >> (cnt)) & mask;
128105b261ecSmrg
1282f7df2e56Smrg        /* set the new carry flag, Note that it is the low order
128305b261ecSmrg           bit of the result!!!                               */
1284f7df2e56Smrg        CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1285f7df2e56Smrg        /* OVERFLOW is set *IFF* s==1, then it is the
128605b261ecSmrg           xor of the two most significant bits.  Blecck. */
1287f7df2e56Smrg        CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
1288f7df2e56Smrg    }
1289f7df2e56Smrg    else if (s != 0) {
1290f7df2e56Smrg        /* set the new carry flag, Note that it is the low order
1291f7df2e56Smrg           bit of the result!!!                               */
1292f7df2e56Smrg        CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1293f7df2e56Smrg    }
1294f7df2e56Smrg    return (u8) res;
129505b261ecSmrg}
129605b261ecSmrg
129705b261ecSmrg/****************************************************************************
129805b261ecSmrgREMARKS:
129905b261ecSmrgImplements the ROR instruction and side effects.
130005b261ecSmrg****************************************************************************/
1301f7df2e56Smrgu16
1302f7df2e56Smrgror_word(u16 d, u8 s)
130305b261ecSmrg{
130405b261ecSmrg    register unsigned int res, cnt, mask;
130505b261ecSmrg
1306f7df2e56Smrg    res = d;
1307f7df2e56Smrg    if ((cnt = s % 16) != 0) {
1308f7df2e56Smrg        res = (d << (16 - cnt));
1309f7df2e56Smrg        mask = (1 << (16 - cnt)) - 1;
1310f7df2e56Smrg        res |= (d >> (cnt)) & mask;
1311f7df2e56Smrg        CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1312f7df2e56Smrg        CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
1313f7df2e56Smrg    }
1314f7df2e56Smrg    else if (s != 0) {
1315f7df2e56Smrg        /* set the new carry flag, Note that it is the low order
1316f7df2e56Smrg           bit of the result!!!                               */
1317f7df2e56Smrg        CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1318f7df2e56Smrg    }
1319f7df2e56Smrg    return (u16) res;
132005b261ecSmrg}
132105b261ecSmrg
132205b261ecSmrg/****************************************************************************
132305b261ecSmrgREMARKS:
132405b261ecSmrgImplements the ROR instruction and side effects.
132505b261ecSmrg****************************************************************************/
1326f7df2e56Smrgu32
1327f7df2e56Smrgror_long(u32 d, u8 s)
132805b261ecSmrg{
1329f7df2e56Smrg    register u32 res, cnt, mask;
133005b261ecSmrg
1331f7df2e56Smrg    res = d;
1332f7df2e56Smrg    if ((cnt = s % 32) != 0) {
1333f7df2e56Smrg        res = (d << (32 - cnt));
1334f7df2e56Smrg        mask = (1 << (32 - cnt)) - 1;
1335f7df2e56Smrg        res |= (d >> (cnt)) & mask;
1336f7df2e56Smrg        CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1337f7df2e56Smrg        CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
1338f7df2e56Smrg    }
1339f7df2e56Smrg    else if (s != 0) {
1340f7df2e56Smrg        /* set the new carry flag, Note that it is the low order
1341f7df2e56Smrg           bit of the result!!!                               */
1342f7df2e56Smrg        CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1343f7df2e56Smrg    }
1344f7df2e56Smrg    return res;
134505b261ecSmrg}
134605b261ecSmrg
134705b261ecSmrg/****************************************************************************
134805b261ecSmrgREMARKS:
134905b261ecSmrgImplements the SHL instruction and side effects.
135005b261ecSmrg****************************************************************************/
1351f7df2e56Smrgu8
1352f7df2e56Smrgshl_byte(u8 d, u8 s)
135305b261ecSmrg{
1354f7df2e56Smrg    unsigned int cnt, res, cf;
135505b261ecSmrg
1356f7df2e56Smrg    if (s < 8) {
1357f7df2e56Smrg        cnt = s % 8;
1358f7df2e56Smrg
1359f7df2e56Smrg        /* last bit shifted out goes into carry flag */
1360f7df2e56Smrg        if (cnt > 0) {
1361f7df2e56Smrg            res = d << cnt;
1362f7df2e56Smrg            cf = d & (1 << (8 - cnt));
1363f7df2e56Smrg            CONDITIONAL_SET_FLAG(cf, F_CF);
1364f7df2e56Smrg            CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1365f7df2e56Smrg            CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1366f7df2e56Smrg            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1367f7df2e56Smrg        }
1368f7df2e56Smrg        else {
1369f7df2e56Smrg            res = (u8) d;
1370f7df2e56Smrg        }
137105b261ecSmrg
1372f7df2e56Smrg        if (cnt == 1) {
1373f7df2e56Smrg            /* Needs simplification. */
1374f7df2e56Smrg            CONDITIONAL_SET_FLAG((((res & 0x80) == 0x80) ^
1375f7df2e56Smrg                                  (ACCESS_FLAG(F_CF) != 0)),
1376f7df2e56Smrg                                 /* was (M.x86.R_FLG&F_CF)==F_CF)), */
1377f7df2e56Smrg                                 F_OF);
1378f7df2e56Smrg        }
1379f7df2e56Smrg        else {
1380f7df2e56Smrg            CLEAR_FLAG(F_OF);
1381f7df2e56Smrg        }
138205b261ecSmrg    }
1383f7df2e56Smrg    else {
1384f7df2e56Smrg        res = 0;
1385f7df2e56Smrg        CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF);
1386f7df2e56Smrg        CLEAR_FLAG(F_OF);
1387f7df2e56Smrg        CLEAR_FLAG(F_SF);
1388f7df2e56Smrg        SET_FLAG(F_PF);
1389f7df2e56Smrg        SET_FLAG(F_ZF);
1390f7df2e56Smrg    }
1391f7df2e56Smrg    return (u8) res;
139205b261ecSmrg}
139305b261ecSmrg
139405b261ecSmrg/****************************************************************************
139505b261ecSmrgREMARKS:
139605b261ecSmrgImplements the SHL instruction and side effects.
139705b261ecSmrg****************************************************************************/
1398f7df2e56Smrgu16
1399f7df2e56Smrgshl_word(u16 d, u8 s)
140005b261ecSmrg{
140105b261ecSmrg    unsigned int cnt, res, cf;
140205b261ecSmrg
1403f7df2e56Smrg    if (s < 16) {
1404f7df2e56Smrg        cnt = s % 16;
1405f7df2e56Smrg        if (cnt > 0) {
1406f7df2e56Smrg            res = d << cnt;
1407f7df2e56Smrg            cf = d & (1 << (16 - cnt));
1408f7df2e56Smrg            CONDITIONAL_SET_FLAG(cf, F_CF);
1409f7df2e56Smrg            CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1410f7df2e56Smrg            CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1411f7df2e56Smrg            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1412f7df2e56Smrg        }
1413f7df2e56Smrg        else {
1414f7df2e56Smrg            res = (u16) d;
1415f7df2e56Smrg        }
1416f7df2e56Smrg
1417f7df2e56Smrg        if (cnt == 1) {
1418f7df2e56Smrg            CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
1419f7df2e56Smrg                                  (ACCESS_FLAG(F_CF) != 0)), F_OF);
1420f7df2e56Smrg        }
1421f7df2e56Smrg        else {
1422f7df2e56Smrg            CLEAR_FLAG(F_OF);
1423f7df2e56Smrg        }
1424f7df2e56Smrg    }
1425f7df2e56Smrg    else {
1426f7df2e56Smrg        res = 0;
1427f7df2e56Smrg        CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
1428f7df2e56Smrg        CLEAR_FLAG(F_OF);
1429f7df2e56Smrg        CLEAR_FLAG(F_SF);
1430f7df2e56Smrg        SET_FLAG(F_PF);
1431f7df2e56Smrg        SET_FLAG(F_ZF);
1432f7df2e56Smrg    }
1433f7df2e56Smrg    return (u16) res;
143405b261ecSmrg}
143505b261ecSmrg
143605b261ecSmrg/****************************************************************************
143705b261ecSmrgREMARKS:
143805b261ecSmrgImplements the SHL instruction and side effects.
143905b261ecSmrg****************************************************************************/
1440f7df2e56Smrgu32
1441f7df2e56Smrgshl_long(u32 d, u8 s)
1442f7df2e56Smrg{
1443f7df2e56Smrg    unsigned int cnt, res, cf;
1444f7df2e56Smrg
1445f7df2e56Smrg    if (s < 32) {
1446f7df2e56Smrg        cnt = s % 32;
1447f7df2e56Smrg        if (cnt > 0) {
1448f7df2e56Smrg            res = d << cnt;
1449f7df2e56Smrg            cf = d & (1 << (32 - cnt));
1450f7df2e56Smrg            CONDITIONAL_SET_FLAG(cf, F_CF);
1451f7df2e56Smrg            CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1452f7df2e56Smrg            CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1453f7df2e56Smrg            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1454f7df2e56Smrg        }
1455f7df2e56Smrg        else {
1456f7df2e56Smrg            res = d;
1457f7df2e56Smrg        }
1458f7df2e56Smrg        if (cnt == 1) {
1459f7df2e56Smrg            CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1460f7df2e56Smrg                                  (ACCESS_FLAG(F_CF) != 0)), F_OF);
1461f7df2e56Smrg        }
1462f7df2e56Smrg        else {
1463f7df2e56Smrg            CLEAR_FLAG(F_OF);
1464f7df2e56Smrg        }
1465f7df2e56Smrg    }
1466f7df2e56Smrg    else {
1467f7df2e56Smrg        res = 0;
1468f7df2e56Smrg        CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
1469f7df2e56Smrg        CLEAR_FLAG(F_OF);
1470f7df2e56Smrg        CLEAR_FLAG(F_SF);
1471f7df2e56Smrg        SET_FLAG(F_PF);
1472f7df2e56Smrg        SET_FLAG(F_ZF);
1473f7df2e56Smrg    }
1474f7df2e56Smrg    return res;
147505b261ecSmrg}
147605b261ecSmrg
147705b261ecSmrg/****************************************************************************
147805b261ecSmrgREMARKS:
147905b261ecSmrgImplements the SHR instruction and side effects.
148005b261ecSmrg****************************************************************************/
1481f7df2e56Smrgu8
1482f7df2e56Smrgshr_byte(u8 d, u8 s)
1483f7df2e56Smrg{
1484f7df2e56Smrg    unsigned int cnt, res, cf;
1485f7df2e56Smrg
1486f7df2e56Smrg    if (s < 8) {
1487f7df2e56Smrg        cnt = s % 8;
1488f7df2e56Smrg        if (cnt > 0) {
1489f7df2e56Smrg            cf = d & (1 << (cnt - 1));
1490f7df2e56Smrg            res = d >> cnt;
1491f7df2e56Smrg            CONDITIONAL_SET_FLAG(cf, F_CF);
1492f7df2e56Smrg            CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1493f7df2e56Smrg            CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1494f7df2e56Smrg            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1495f7df2e56Smrg        }
1496f7df2e56Smrg        else {
1497f7df2e56Smrg            res = (u8) d;
1498f7df2e56Smrg        }
1499f7df2e56Smrg
1500f7df2e56Smrg        if (cnt == 1) {
1501f7df2e56Smrg            CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
1502f7df2e56Smrg        }
1503f7df2e56Smrg        else {
1504f7df2e56Smrg            CLEAR_FLAG(F_OF);
1505f7df2e56Smrg        }
1506f7df2e56Smrg    }
1507f7df2e56Smrg    else {
1508f7df2e56Smrg        res = 0;
1509f7df2e56Smrg        CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF);
1510f7df2e56Smrg        CLEAR_FLAG(F_OF);
1511f7df2e56Smrg        CLEAR_FLAG(F_SF);
1512f7df2e56Smrg        SET_FLAG(F_PF);
1513f7df2e56Smrg        SET_FLAG(F_ZF);
1514f7df2e56Smrg    }
1515f7df2e56Smrg    return (u8) res;
151605b261ecSmrg}
151705b261ecSmrg
151805b261ecSmrg/****************************************************************************
151905b261ecSmrgREMARKS:
152005b261ecSmrgImplements the SHR instruction and side effects.
152105b261ecSmrg****************************************************************************/
1522f7df2e56Smrgu16
1523f7df2e56Smrgshr_word(u16 d, u8 s)
152405b261ecSmrg{
1525f7df2e56Smrg    unsigned int cnt, res, cf;
152605b261ecSmrg
1527f7df2e56Smrg    if (s < 16) {
1528f7df2e56Smrg        cnt = s % 16;
1529f7df2e56Smrg        if (cnt > 0) {
1530f7df2e56Smrg            cf = d & (1 << (cnt - 1));
1531f7df2e56Smrg            res = d >> cnt;
1532f7df2e56Smrg            CONDITIONAL_SET_FLAG(cf, F_CF);
1533f7df2e56Smrg            CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1534f7df2e56Smrg            CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1535f7df2e56Smrg            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1536f7df2e56Smrg        }
1537f7df2e56Smrg        else {
1538f7df2e56Smrg            res = d;
1539f7df2e56Smrg        }
154005b261ecSmrg
1541f7df2e56Smrg        if (cnt == 1) {
1542f7df2e56Smrg            CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
154305b261ecSmrg        }
1544f7df2e56Smrg        else {
1545f7df2e56Smrg            CLEAR_FLAG(F_OF);
1546f7df2e56Smrg        }
1547f7df2e56Smrg    }
1548f7df2e56Smrg    else {
1549f7df2e56Smrg        res = 0;
1550f7df2e56Smrg        CLEAR_FLAG(F_CF);
1551f7df2e56Smrg        CLEAR_FLAG(F_OF);
1552f7df2e56Smrg        SET_FLAG(F_ZF);
1553f7df2e56Smrg        CLEAR_FLAG(F_SF);
1554f7df2e56Smrg        CLEAR_FLAG(F_PF);
155505b261ecSmrg    }
1556f7df2e56Smrg    return (u16) res;
155705b261ecSmrg}
155805b261ecSmrg
155905b261ecSmrg/****************************************************************************
156005b261ecSmrgREMARKS:
156105b261ecSmrgImplements the SHR instruction and side effects.
156205b261ecSmrg****************************************************************************/
1563f7df2e56Smrgu32
1564f7df2e56Smrgshr_long(u32 d, u8 s)
156505b261ecSmrg{
1566f7df2e56Smrg    unsigned int cnt, res, cf;
156705b261ecSmrg
1568f7df2e56Smrg    if (s < 32) {
1569f7df2e56Smrg        cnt = s % 32;
1570f7df2e56Smrg        if (cnt > 0) {
1571f7df2e56Smrg            cf = d & (1 << (cnt - 1));
1572f7df2e56Smrg            res = d >> cnt;
1573f7df2e56Smrg            CONDITIONAL_SET_FLAG(cf, F_CF);
1574f7df2e56Smrg            CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1575f7df2e56Smrg            CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1576f7df2e56Smrg            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1577f7df2e56Smrg        }
1578f7df2e56Smrg        else {
157905b261ecSmrg            res = d;
158005b261ecSmrg        }
158105b261ecSmrg        if (cnt == 1) {
1582f7df2e56Smrg            CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1583f7df2e56Smrg        }
1584f7df2e56Smrg        else {
1585f7df2e56Smrg            CLEAR_FLAG(F_OF);
158605b261ecSmrg        }
1587f7df2e56Smrg    }
1588f7df2e56Smrg    else {
158905b261ecSmrg        res = 0;
1590f7df2e56Smrg        CLEAR_FLAG(F_CF);
1591f7df2e56Smrg        CLEAR_FLAG(F_OF);
1592f7df2e56Smrg        SET_FLAG(F_ZF);
1593f7df2e56Smrg        CLEAR_FLAG(F_SF);
1594f7df2e56Smrg        CLEAR_FLAG(F_PF);
159505b261ecSmrg    }
159605b261ecSmrg    return res;
159705b261ecSmrg}
159805b261ecSmrg
159905b261ecSmrg/****************************************************************************
160005b261ecSmrgREMARKS:
160105b261ecSmrgImplements the SAR instruction and side effects.
160205b261ecSmrg****************************************************************************/
1603f7df2e56Smrgu8
1604f7df2e56Smrgsar_byte(u8 d, u8 s)
160505b261ecSmrg{
1606f7df2e56Smrg    unsigned int cnt, res, cf, mask, sf;
160705b261ecSmrg
1608f7df2e56Smrg    res = d;
1609f7df2e56Smrg    sf = d & 0x80;
161005b261ecSmrg    cnt = s % 8;
1611f7df2e56Smrg    if (cnt > 0 && cnt < 8) {
1612f7df2e56Smrg        mask = (1 << (8 - cnt)) - 1;
1613f7df2e56Smrg        cf = d & (1 << (cnt - 1));
1614f7df2e56Smrg        res = (d >> cnt) & mask;
1615f7df2e56Smrg        CONDITIONAL_SET_FLAG(cf, F_CF);
1616f7df2e56Smrg        if (sf) {
1617f7df2e56Smrg            res |= ~mask;
1618f7df2e56Smrg        }
1619f7df2e56Smrg        CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1620f7df2e56Smrg        CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1621f7df2e56Smrg        CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1622f7df2e56Smrg    }
1623f7df2e56Smrg    else if (cnt >= 8) {
162405b261ecSmrg        if (sf) {
162505b261ecSmrg            res = 0xff;
1626f7df2e56Smrg            SET_FLAG(F_CF);
1627f7df2e56Smrg            CLEAR_FLAG(F_ZF);
1628f7df2e56Smrg            SET_FLAG(F_SF);
1629f7df2e56Smrg            SET_FLAG(F_PF);
1630f7df2e56Smrg        }
1631f7df2e56Smrg        else {
1632f7df2e56Smrg            res = 0;
1633f7df2e56Smrg            CLEAR_FLAG(F_CF);
1634f7df2e56Smrg            SET_FLAG(F_ZF);
1635f7df2e56Smrg            CLEAR_FLAG(F_SF);
1636f7df2e56Smrg            CLEAR_FLAG(F_PF);
1637f7df2e56Smrg        }
1638f7df2e56Smrg    }
1639f7df2e56Smrg    return (u8) res;
164005b261ecSmrg}
164105b261ecSmrg
164205b261ecSmrg/****************************************************************************
164305b261ecSmrgREMARKS:
164405b261ecSmrgImplements the SAR instruction and side effects.
164505b261ecSmrg****************************************************************************/
1646f7df2e56Smrgu16
1647f7df2e56Smrgsar_word(u16 d, u8 s)
164805b261ecSmrg{
164905b261ecSmrg    unsigned int cnt, res, cf, mask, sf;
165005b261ecSmrg
165105b261ecSmrg    sf = d & 0x8000;
165205b261ecSmrg    cnt = s % 16;
1653f7df2e56Smrg    res = d;
1654f7df2e56Smrg    if (cnt > 0 && cnt < 16) {
165505b261ecSmrg        mask = (1 << (16 - cnt)) - 1;
165605b261ecSmrg        cf = d & (1 << (cnt - 1));
165705b261ecSmrg        res = (d >> cnt) & mask;
1658f7df2e56Smrg        CONDITIONAL_SET_FLAG(cf, F_CF);
165905b261ecSmrg        if (sf) {
166005b261ecSmrg            res |= ~mask;
166105b261ecSmrg        }
1662f7df2e56Smrg        CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1663f7df2e56Smrg        CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1664f7df2e56Smrg        CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1665f7df2e56Smrg    }
1666f7df2e56Smrg    else if (cnt >= 16) {
166705b261ecSmrg        if (sf) {
166805b261ecSmrg            res = 0xffff;
1669f7df2e56Smrg            SET_FLAG(F_CF);
1670f7df2e56Smrg            CLEAR_FLAG(F_ZF);
1671f7df2e56Smrg            SET_FLAG(F_SF);
1672f7df2e56Smrg            SET_FLAG(F_PF);
1673f7df2e56Smrg        }
1674f7df2e56Smrg        else {
167505b261ecSmrg            res = 0;
1676f7df2e56Smrg            CLEAR_FLAG(F_CF);
1677f7df2e56Smrg            SET_FLAG(F_ZF);
1678f7df2e56Smrg            CLEAR_FLAG(F_SF);
1679f7df2e56Smrg            CLEAR_FLAG(F_PF);
168005b261ecSmrg        }
168105b261ecSmrg    }
1682f7df2e56Smrg    return (u16) res;
168305b261ecSmrg}
168405b261ecSmrg
168505b261ecSmrg/****************************************************************************
168605b261ecSmrgREMARKS:
168705b261ecSmrgImplements the SAR instruction and side effects.
168805b261ecSmrg****************************************************************************/
1689f7df2e56Smrgu32
1690f7df2e56Smrgsar_long(u32 d, u8 s)
169105b261ecSmrg{
169205b261ecSmrg    u32 cnt, res, cf, mask, sf;
169305b261ecSmrg
169405b261ecSmrg    sf = d & 0x80000000;
169505b261ecSmrg    cnt = s % 32;
1696f7df2e56Smrg    res = d;
1697f7df2e56Smrg    if (cnt > 0 && cnt < 32) {
169805b261ecSmrg        mask = (1 << (32 - cnt)) - 1;
1699f7df2e56Smrg        cf = d & (1 << (cnt - 1));
170005b261ecSmrg        res = (d >> cnt) & mask;
1701f7df2e56Smrg        CONDITIONAL_SET_FLAG(cf, F_CF);
170205b261ecSmrg        if (sf) {
170305b261ecSmrg            res |= ~mask;
170405b261ecSmrg        }
1705f7df2e56Smrg        CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1706f7df2e56Smrg        CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1707f7df2e56Smrg        CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1708f7df2e56Smrg    }
1709f7df2e56Smrg    else if (cnt >= 32) {
171005b261ecSmrg        if (sf) {
171105b261ecSmrg            res = 0xffffffff;
1712f7df2e56Smrg            SET_FLAG(F_CF);
1713f7df2e56Smrg            CLEAR_FLAG(F_ZF);
1714f7df2e56Smrg            SET_FLAG(F_SF);
1715f7df2e56Smrg            SET_FLAG(F_PF);
1716f7df2e56Smrg        }
1717f7df2e56Smrg        else {
1718f7df2e56Smrg            res = 0;
1719f7df2e56Smrg            CLEAR_FLAG(F_CF);
1720f7df2e56Smrg            SET_FLAG(F_ZF);
1721f7df2e56Smrg            CLEAR_FLAG(F_SF);
1722f7df2e56Smrg            CLEAR_FLAG(F_PF);
1723f7df2e56Smrg        }
1724f7df2e56Smrg    }
1725f7df2e56Smrg    return res;
172605b261ecSmrg}
172705b261ecSmrg
172805b261ecSmrg/****************************************************************************
172905b261ecSmrgREMARKS:
173005b261ecSmrgImplements the SHLD instruction and side effects.
173105b261ecSmrg****************************************************************************/
1732f7df2e56Smrgu16
1733f7df2e56Smrgshld_word(u16 d, u16 fill, u8 s)
1734f7df2e56Smrg{
1735f7df2e56Smrg    unsigned int cnt, res, cf;
1736f7df2e56Smrg
1737f7df2e56Smrg    if (s < 16) {
1738f7df2e56Smrg        cnt = s % 16;
1739f7df2e56Smrg        if (cnt > 0) {
1740f7df2e56Smrg            res = (d << cnt) | (fill >> (16 - cnt));
1741f7df2e56Smrg            cf = d & (1 << (16 - cnt));
1742f7df2e56Smrg            CONDITIONAL_SET_FLAG(cf, F_CF);
1743f7df2e56Smrg            CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1744f7df2e56Smrg            CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1745f7df2e56Smrg            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1746f7df2e56Smrg        }
1747f7df2e56Smrg        else {
1748f7df2e56Smrg            res = d;
1749f7df2e56Smrg        }
1750f7df2e56Smrg        if (cnt == 1) {
1751f7df2e56Smrg            CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
1752f7df2e56Smrg                                  (ACCESS_FLAG(F_CF) != 0)), F_OF);
1753f7df2e56Smrg        }
1754f7df2e56Smrg        else {
1755f7df2e56Smrg            CLEAR_FLAG(F_OF);
1756f7df2e56Smrg        }
1757f7df2e56Smrg    }
1758f7df2e56Smrg    else {
1759f7df2e56Smrg        res = 0;
1760f7df2e56Smrg        CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
1761f7df2e56Smrg        CLEAR_FLAG(F_OF);
1762f7df2e56Smrg        CLEAR_FLAG(F_SF);
1763f7df2e56Smrg        SET_FLAG(F_PF);
1764f7df2e56Smrg        SET_FLAG(F_ZF);
1765f7df2e56Smrg    }
1766f7df2e56Smrg    return (u16) res;
176705b261ecSmrg}
176805b261ecSmrg
176905b261ecSmrg/****************************************************************************
177005b261ecSmrgREMARKS:
177105b261ecSmrgImplements the SHLD instruction and side effects.
177205b261ecSmrg****************************************************************************/
1773f7df2e56Smrgu32
1774f7df2e56Smrgshld_long(u32 d, u32 fill, u8 s)
1775f7df2e56Smrg{
1776f7df2e56Smrg    unsigned int cnt, res, cf;
1777f7df2e56Smrg
1778f7df2e56Smrg    if (s < 32) {
1779f7df2e56Smrg        cnt = s % 32;
1780f7df2e56Smrg        if (cnt > 0) {
1781f7df2e56Smrg            res = (d << cnt) | (fill >> (32 - cnt));
1782f7df2e56Smrg            cf = d & (1 << (32 - cnt));
1783f7df2e56Smrg            CONDITIONAL_SET_FLAG(cf, F_CF);
1784f7df2e56Smrg            CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1785f7df2e56Smrg            CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1786f7df2e56Smrg            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1787f7df2e56Smrg        }
1788f7df2e56Smrg        else {
1789f7df2e56Smrg            res = d;
1790f7df2e56Smrg        }
1791f7df2e56Smrg        if (cnt == 1) {
1792f7df2e56Smrg            CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1793f7df2e56Smrg                                  (ACCESS_FLAG(F_CF) != 0)), F_OF);
1794f7df2e56Smrg        }
1795f7df2e56Smrg        else {
1796f7df2e56Smrg            CLEAR_FLAG(F_OF);
1797f7df2e56Smrg        }
1798f7df2e56Smrg    }
1799f7df2e56Smrg    else {
1800f7df2e56Smrg        res = 0;
1801f7df2e56Smrg        CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
1802f7df2e56Smrg        CLEAR_FLAG(F_OF);
1803f7df2e56Smrg        CLEAR_FLAG(F_SF);
1804f7df2e56Smrg        SET_FLAG(F_PF);
1805f7df2e56Smrg        SET_FLAG(F_ZF);
1806f7df2e56Smrg    }
1807f7df2e56Smrg    return res;
180805b261ecSmrg}
180905b261ecSmrg
181005b261ecSmrg/****************************************************************************
181105b261ecSmrgREMARKS:
181205b261ecSmrgImplements the SHRD instruction and side effects.
181305b261ecSmrg****************************************************************************/
1814f7df2e56Smrgu16
1815f7df2e56Smrgshrd_word(u16 d, u16 fill, u8 s)
181605b261ecSmrg{
1817f7df2e56Smrg    unsigned int cnt, res, cf;
181805b261ecSmrg
1819f7df2e56Smrg    if (s < 16) {
1820f7df2e56Smrg        cnt = s % 16;
1821f7df2e56Smrg        if (cnt > 0) {
1822f7df2e56Smrg            cf = d & (1 << (cnt - 1));
1823f7df2e56Smrg            res = (d >> cnt) | (fill << (16 - cnt));
1824f7df2e56Smrg            CONDITIONAL_SET_FLAG(cf, F_CF);
1825f7df2e56Smrg            CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1826f7df2e56Smrg            CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1827f7df2e56Smrg            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1828f7df2e56Smrg        }
1829f7df2e56Smrg        else {
1830f7df2e56Smrg            res = d;
1831f7df2e56Smrg        }
183205b261ecSmrg
1833f7df2e56Smrg        if (cnt == 1) {
1834f7df2e56Smrg            CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1835f7df2e56Smrg        }
1836f7df2e56Smrg        else {
1837f7df2e56Smrg            CLEAR_FLAG(F_OF);
183805b261ecSmrg        }
183905b261ecSmrg    }
1840f7df2e56Smrg    else {
1841f7df2e56Smrg        res = 0;
1842f7df2e56Smrg        CLEAR_FLAG(F_CF);
1843f7df2e56Smrg        CLEAR_FLAG(F_OF);
1844f7df2e56Smrg        SET_FLAG(F_ZF);
1845f7df2e56Smrg        CLEAR_FLAG(F_SF);
1846f7df2e56Smrg        CLEAR_FLAG(F_PF);
1847f7df2e56Smrg    }
1848f7df2e56Smrg    return (u16) res;
184905b261ecSmrg}
185005b261ecSmrg
185105b261ecSmrg/****************************************************************************
185205b261ecSmrgREMARKS:
185305b261ecSmrgImplements the SHRD instruction and side effects.
185405b261ecSmrg****************************************************************************/
1855f7df2e56Smrgu32
1856f7df2e56Smrgshrd_long(u32 d, u32 fill, u8 s)
185705b261ecSmrg{
1858f7df2e56Smrg    unsigned int cnt, res, cf;
185905b261ecSmrg
1860f7df2e56Smrg    if (s < 32) {
1861f7df2e56Smrg        cnt = s % 32;
1862f7df2e56Smrg        if (cnt > 0) {
1863f7df2e56Smrg            cf = d & (1 << (cnt - 1));
1864f7df2e56Smrg            res = (d >> cnt) | (fill << (32 - cnt));
1865f7df2e56Smrg            CONDITIONAL_SET_FLAG(cf, F_CF);
1866f7df2e56Smrg            CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1867f7df2e56Smrg            CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1868f7df2e56Smrg            CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
186905b261ecSmrg        }
1870f7df2e56Smrg        else {
1871f7df2e56Smrg            res = d;
1872f7df2e56Smrg        }
1873f7df2e56Smrg        if (cnt == 1) {
1874f7df2e56Smrg            CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1875f7df2e56Smrg        }
1876f7df2e56Smrg        else {
1877f7df2e56Smrg            CLEAR_FLAG(F_OF);
1878f7df2e56Smrg        }
1879f7df2e56Smrg    }
1880f7df2e56Smrg    else {
1881f7df2e56Smrg        res = 0;
1882f7df2e56Smrg        CLEAR_FLAG(F_CF);
1883f7df2e56Smrg        CLEAR_FLAG(F_OF);
1884f7df2e56Smrg        SET_FLAG(F_ZF);
1885f7df2e56Smrg        CLEAR_FLAG(F_SF);
1886f7df2e56Smrg        CLEAR_FLAG(F_PF);
188705b261ecSmrg    }
1888f7df2e56Smrg    return res;
188905b261ecSmrg}
189005b261ecSmrg
189105b261ecSmrg/****************************************************************************
189205b261ecSmrgREMARKS:
189305b261ecSmrgImplements the SBB instruction and side effects.
189405b261ecSmrg****************************************************************************/
1895f7df2e56Smrgu8
1896f7df2e56Smrgsbb_byte(u8 d, u8 s)
189705b261ecSmrg{
1898f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
189905b261ecSmrg    register u32 bc;
190005b261ecSmrg
1901f7df2e56Smrg    if (ACCESS_FLAG(F_CF))
1902f7df2e56Smrg        res = d - s - 1;
1903f7df2e56Smrg    else
1904f7df2e56Smrg        res = d - s;
1905f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1906f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1907f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
190805b261ecSmrg
1909f7df2e56Smrg    /* calculate the borrow chain.  See note at top */
1910f7df2e56Smrg    bc = (res & (~d | s)) | (~d & s);
1911f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1912f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1913f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1914f7df2e56Smrg    return (u8) res;
191505b261ecSmrg}
191605b261ecSmrg
191705b261ecSmrg/****************************************************************************
191805b261ecSmrgREMARKS:
191905b261ecSmrgImplements the SBB instruction and side effects.
192005b261ecSmrg****************************************************************************/
1921f7df2e56Smrgu16
1922f7df2e56Smrgsbb_word(u16 d, u16 s)
192305b261ecSmrg{
1924f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
192505b261ecSmrg    register u32 bc;
192605b261ecSmrg
1927f7df2e56Smrg    if (ACCESS_FLAG(F_CF))
192805b261ecSmrg        res = d - s - 1;
192905b261ecSmrg    else
193005b261ecSmrg        res = d - s;
1931f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1932f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1933f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
193405b261ecSmrg
1935f7df2e56Smrg    /* calculate the borrow chain.  See note at top */
1936f7df2e56Smrg    bc = (res & (~d | s)) | (~d & s);
1937f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1938f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1939f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1940f7df2e56Smrg    return (u16) res;
194105b261ecSmrg}
194205b261ecSmrg
194305b261ecSmrg/****************************************************************************
194405b261ecSmrgREMARKS:
194505b261ecSmrgImplements the SBB instruction and side effects.
194605b261ecSmrg****************************************************************************/
1947f7df2e56Smrgu32
1948f7df2e56Smrgsbb_long(u32 d, u32 s)
194905b261ecSmrg{
1950f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
1951f7df2e56Smrg    register u32 bc;
195205b261ecSmrg
1953f7df2e56Smrg    if (ACCESS_FLAG(F_CF))
195405b261ecSmrg        res = d - s - 1;
195505b261ecSmrg    else
195605b261ecSmrg        res = d - s;
1957f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1958f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1959f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
196005b261ecSmrg
1961f7df2e56Smrg    /* calculate the borrow chain.  See note at top */
1962f7df2e56Smrg    bc = (res & (~d | s)) | (~d & s);
1963f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1964f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1965f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1966f7df2e56Smrg    return res;
196705b261ecSmrg}
196805b261ecSmrg
196905b261ecSmrg/****************************************************************************
197005b261ecSmrgREMARKS:
197105b261ecSmrgImplements the SUB instruction and side effects.
197205b261ecSmrg****************************************************************************/
1973f7df2e56Smrgu8
1974f7df2e56Smrgsub_byte(u8 d, u8 s)
197505b261ecSmrg{
1976f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
1977f7df2e56Smrg    register u32 bc;
197805b261ecSmrg
1979f7df2e56Smrg    res = d - s;
1980f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1981f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1982f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
198305b261ecSmrg
1984f7df2e56Smrg    /* calculate the borrow chain.  See note at top */
1985f7df2e56Smrg    bc = (res & (~d | s)) | (~d & s);
1986f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1987f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1988f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1989f7df2e56Smrg    return (u8) res;
199005b261ecSmrg}
199105b261ecSmrg
199205b261ecSmrg/****************************************************************************
199305b261ecSmrgREMARKS:
199405b261ecSmrgImplements the SUB instruction and side effects.
199505b261ecSmrg****************************************************************************/
1996f7df2e56Smrgu16
1997f7df2e56Smrgsub_word(u16 d, u16 s)
199805b261ecSmrg{
1999f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
200005b261ecSmrg    register u32 bc;
200105b261ecSmrg
200205b261ecSmrg    res = d - s;
2003f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
2004f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
2005f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
200605b261ecSmrg
2007f7df2e56Smrg    /* calculate the borrow chain.  See note at top */
2008f7df2e56Smrg    bc = (res & (~d | s)) | (~d & s);
2009f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
2010f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
2011f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
2012f7df2e56Smrg    return (u16) res;
201305b261ecSmrg}
201405b261ecSmrg
201505b261ecSmrg/****************************************************************************
201605b261ecSmrgREMARKS:
201705b261ecSmrgImplements the SUB instruction and side effects.
201805b261ecSmrg****************************************************************************/
2019f7df2e56Smrgu32
2020f7df2e56Smrgsub_long(u32 d, u32 s)
202105b261ecSmrg{
2022f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
2023f7df2e56Smrg    register u32 bc;
202405b261ecSmrg
2025f7df2e56Smrg    res = d - s;
2026f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
2027f7df2e56Smrg    CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
2028f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
202905b261ecSmrg
2030f7df2e56Smrg    /* calculate the borrow chain.  See note at top */
2031f7df2e56Smrg    bc = (res & (~d | s)) | (~d & s);
2032f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
2033f7df2e56Smrg    CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
2034f7df2e56Smrg    CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
2035f7df2e56Smrg    return res;
203605b261ecSmrg}
203705b261ecSmrg
203805b261ecSmrg/****************************************************************************
203905b261ecSmrgREMARKS:
204005b261ecSmrgImplements the TEST instruction and side effects.
204105b261ecSmrg****************************************************************************/
2042f7df2e56Smrgvoid
2043f7df2e56Smrgtest_byte(u8 d, u8 s)
204405b261ecSmrg{
2045f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
204605b261ecSmrg
204705b261ecSmrg    res = d & s;
204805b261ecSmrg
2049f7df2e56Smrg    CLEAR_FLAG(F_OF);
2050f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
2051f7df2e56Smrg    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2052f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
20535a112b11Smrg    /* AF == don't care */
2054f7df2e56Smrg    CLEAR_FLAG(F_CF);
205505b261ecSmrg}
205605b261ecSmrg
205705b261ecSmrg/****************************************************************************
205805b261ecSmrgREMARKS:
205905b261ecSmrgImplements the TEST instruction and side effects.
206005b261ecSmrg****************************************************************************/
2061f7df2e56Smrgvoid
2062f7df2e56Smrgtest_word(u16 d, u16 s)
206305b261ecSmrg{
2064f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
206505b261ecSmrg
2066f7df2e56Smrg    res = d & s;
206705b261ecSmrg
2068f7df2e56Smrg    CLEAR_FLAG(F_OF);
2069f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
2070f7df2e56Smrg    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2071f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
20725a112b11Smrg    /* AF == don't care */
2073f7df2e56Smrg    CLEAR_FLAG(F_CF);
207405b261ecSmrg}
207505b261ecSmrg
207605b261ecSmrg/****************************************************************************
207705b261ecSmrgREMARKS:
207805b261ecSmrgImplements the TEST instruction and side effects.
207905b261ecSmrg****************************************************************************/
2080f7df2e56Smrgvoid
2081f7df2e56Smrgtest_long(u32 d, u32 s)
208205b261ecSmrg{
2083f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
208405b261ecSmrg
2085f7df2e56Smrg    res = d & s;
208605b261ecSmrg
2087f7df2e56Smrg    CLEAR_FLAG(F_OF);
2088f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
2089f7df2e56Smrg    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2090f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
20915a112b11Smrg    /* AF == don't care */
2092f7df2e56Smrg    CLEAR_FLAG(F_CF);
209305b261ecSmrg}
209405b261ecSmrg
209505b261ecSmrg/****************************************************************************
209605b261ecSmrgREMARKS:
209705b261ecSmrgImplements the XOR instruction and side effects.
209805b261ecSmrg****************************************************************************/
2099f7df2e56Smrgu8
2100f7df2e56Smrgxor_byte(u8 d, u8 s)
210105b261ecSmrg{
2102f7df2e56Smrg    register u8 res;            /* all operands in native machine order */
210305b261ecSmrg
2104f7df2e56Smrg    res = d ^ s;
2105f7df2e56Smrg    CLEAR_FLAG(F_OF);
2106f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
2107f7df2e56Smrg    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2108f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
2109f7df2e56Smrg    CLEAR_FLAG(F_CF);
2110f7df2e56Smrg    CLEAR_FLAG(F_AF);
2111f7df2e56Smrg    return res;
211205b261ecSmrg}
211305b261ecSmrg
211405b261ecSmrg/****************************************************************************
211505b261ecSmrgREMARKS:
211605b261ecSmrgImplements the XOR instruction and side effects.
211705b261ecSmrg****************************************************************************/
2118f7df2e56Smrgu16
2119f7df2e56Smrgxor_word(u16 d, u16 s)
212005b261ecSmrg{
2121f7df2e56Smrg    register u16 res;           /* all operands in native machine order */
212205b261ecSmrg
2123f7df2e56Smrg    res = d ^ s;
2124f7df2e56Smrg    CLEAR_FLAG(F_OF);
2125f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
2126f7df2e56Smrg    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2127f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2128f7df2e56Smrg    CLEAR_FLAG(F_CF);
2129f7df2e56Smrg    CLEAR_FLAG(F_AF);
2130f7df2e56Smrg    return res;
213105b261ecSmrg}
213205b261ecSmrg
213305b261ecSmrg/****************************************************************************
213405b261ecSmrgREMARKS:
213505b261ecSmrgImplements the XOR instruction and side effects.
213605b261ecSmrg****************************************************************************/
2137f7df2e56Smrgu32
2138f7df2e56Smrgxor_long(u32 d, u32 s)
213905b261ecSmrg{
2140f7df2e56Smrg    register u32 res;           /* all operands in native machine order */
214105b261ecSmrg
2142f7df2e56Smrg    res = d ^ s;
2143f7df2e56Smrg    CLEAR_FLAG(F_OF);
2144f7df2e56Smrg    CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
2145f7df2e56Smrg    CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2146f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2147f7df2e56Smrg    CLEAR_FLAG(F_CF);
2148f7df2e56Smrg    CLEAR_FLAG(F_AF);
2149f7df2e56Smrg    return res;
215005b261ecSmrg}
215105b261ecSmrg
215205b261ecSmrg/****************************************************************************
215305b261ecSmrgREMARKS:
215405b261ecSmrgImplements the IMUL instruction and side effects.
215505b261ecSmrg****************************************************************************/
2156f7df2e56Smrgvoid
2157f7df2e56Smrgimul_byte(u8 s)
215805b261ecSmrg{
2159f7df2e56Smrg    s16 res = (s16) ((s8) M.x86.R_AL * (s8) s);
216005b261ecSmrg
2161f7df2e56Smrg    M.x86.R_AX = res;
2162f7df2e56Smrg    if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
2163f7df2e56Smrg        ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
2164f7df2e56Smrg        CLEAR_FLAG(F_CF);
2165f7df2e56Smrg        CLEAR_FLAG(F_OF);
2166f7df2e56Smrg    }
2167f7df2e56Smrg    else {
2168f7df2e56Smrg        SET_FLAG(F_CF);
2169f7df2e56Smrg        SET_FLAG(F_OF);
2170f7df2e56Smrg    }
217105b261ecSmrg}
217205b261ecSmrg
217305b261ecSmrg/****************************************************************************
217405b261ecSmrgREMARKS:
217505b261ecSmrgImplements the IMUL instruction and side effects.
217605b261ecSmrg****************************************************************************/
2177f7df2e56Smrgvoid
2178f7df2e56Smrgimul_word(u16 s)
217905b261ecSmrg{
2180f7df2e56Smrg    s32 res = (s16) M.x86.R_AX * (s16) s;
218105b261ecSmrg
2182f7df2e56Smrg    M.x86.R_AX = (u16) res;
2183f7df2e56Smrg    M.x86.R_DX = (u16) (res >> 16);
2184f7df2e56Smrg    if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x00) ||
2185f7df2e56Smrg        ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFF)) {
2186f7df2e56Smrg        CLEAR_FLAG(F_CF);
2187f7df2e56Smrg        CLEAR_FLAG(F_OF);
2188f7df2e56Smrg    }
2189f7df2e56Smrg    else {
2190f7df2e56Smrg        SET_FLAG(F_CF);
2191f7df2e56Smrg        SET_FLAG(F_OF);
2192f7df2e56Smrg    }
219305b261ecSmrg}
219405b261ecSmrg
219505b261ecSmrg/****************************************************************************
219605b261ecSmrgREMARKS:
219705b261ecSmrgImplements the IMUL instruction and side effects.
219805b261ecSmrg****************************************************************************/
2199f7df2e56Smrgvoid
2200f7df2e56Smrgimul_long_direct(u32 * res_lo, u32 * res_hi, u32 d, u32 s)
220105b261ecSmrg{
220205b261ecSmrg#ifdef	__HAS_LONG_LONG__
2203f7df2e56Smrg    s64 res = (s64) (s32) d * (s32) s;
220405b261ecSmrg
2205f7df2e56Smrg    *res_lo = (u32) res;
2206f7df2e56Smrg    *res_hi = (u32) (res >> 32);
220705b261ecSmrg#else
2208f7df2e56Smrg    u32 d_lo, d_hi, d_sign;
2209f7df2e56Smrg    u32 s_lo, s_hi, s_sign;
2210f7df2e56Smrg    u32 rlo_lo, rlo_hi, rhi_lo;
2211f7df2e56Smrg
2212f7df2e56Smrg    if ((d_sign = d & 0x80000000) != 0)
2213f7df2e56Smrg        d = -d;
2214f7df2e56Smrg    d_lo = d & 0xFFFF;
2215f7df2e56Smrg    d_hi = d >> 16;
2216f7df2e56Smrg    if ((s_sign = s & 0x80000000) != 0)
2217f7df2e56Smrg        s = -s;
2218f7df2e56Smrg    s_lo = s & 0xFFFF;
2219f7df2e56Smrg    s_hi = s >> 16;
2220f7df2e56Smrg    rlo_lo = d_lo * s_lo;
2221f7df2e56Smrg    rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
2222f7df2e56Smrg    rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
2223f7df2e56Smrg    *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2224f7df2e56Smrg    *res_hi = rhi_lo;
2225f7df2e56Smrg    if (d_sign != s_sign) {
2226f7df2e56Smrg        d = ~*res_lo;
2227f7df2e56Smrg        s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
2228f7df2e56Smrg        *res_lo = ~*res_lo + 1;
2229f7df2e56Smrg        *res_hi = ~*res_hi + (s >> 16);
2230f7df2e56Smrg    }
223105b261ecSmrg#endif
223205b261ecSmrg}
223305b261ecSmrg
223405b261ecSmrg/****************************************************************************
223505b261ecSmrgREMARKS:
223605b261ecSmrgImplements the IMUL instruction and side effects.
223705b261ecSmrg****************************************************************************/
2238f7df2e56Smrgvoid
2239f7df2e56Smrgimul_long(u32 s)
224005b261ecSmrg{
2241f7df2e56Smrg    imul_long_direct(&M.x86.R_EAX, &M.x86.R_EDX, M.x86.R_EAX, s);
2242f7df2e56Smrg    if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00) ||
2243f7df2e56Smrg        ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFF)) {
2244f7df2e56Smrg        CLEAR_FLAG(F_CF);
2245f7df2e56Smrg        CLEAR_FLAG(F_OF);
2246f7df2e56Smrg    }
2247f7df2e56Smrg    else {
2248f7df2e56Smrg        SET_FLAG(F_CF);
2249f7df2e56Smrg        SET_FLAG(F_OF);
2250f7df2e56Smrg    }
225105b261ecSmrg}
225205b261ecSmrg
225305b261ecSmrg/****************************************************************************
225405b261ecSmrgREMARKS:
225505b261ecSmrgImplements the MUL instruction and side effects.
225605b261ecSmrg****************************************************************************/
2257f7df2e56Smrgvoid
2258f7df2e56Smrgmul_byte(u8 s)
225905b261ecSmrg{
2260f7df2e56Smrg    u16 res = (u16) (M.x86.R_AL * s);
226105b261ecSmrg
2262f7df2e56Smrg    M.x86.R_AX = res;
2263f7df2e56Smrg    if (M.x86.R_AH == 0) {
2264f7df2e56Smrg        CLEAR_FLAG(F_CF);
2265f7df2e56Smrg        CLEAR_FLAG(F_OF);
2266f7df2e56Smrg    }
2267f7df2e56Smrg    else {
2268f7df2e56Smrg        SET_FLAG(F_CF);
2269f7df2e56Smrg        SET_FLAG(F_OF);
2270f7df2e56Smrg    }
227105b261ecSmrg}
227205b261ecSmrg
227305b261ecSmrg/****************************************************************************
227405b261ecSmrgREMARKS:
227505b261ecSmrgImplements the MUL instruction and side effects.
227605b261ecSmrg****************************************************************************/
2277f7df2e56Smrgvoid
2278f7df2e56Smrgmul_word(u16 s)
227905b261ecSmrg{
2280f7df2e56Smrg    u32 res = M.x86.R_AX * s;
228105b261ecSmrg
2282f7df2e56Smrg    M.x86.R_AX = (u16) res;
2283f7df2e56Smrg    M.x86.R_DX = (u16) (res >> 16);
2284f7df2e56Smrg    if (M.x86.R_DX == 0) {
2285f7df2e56Smrg        CLEAR_FLAG(F_CF);
2286f7df2e56Smrg        CLEAR_FLAG(F_OF);
2287f7df2e56Smrg    }
2288f7df2e56Smrg    else {
2289f7df2e56Smrg        SET_FLAG(F_CF);
2290f7df2e56Smrg        SET_FLAG(F_OF);
229105b261ecSmrg    }
229205b261ecSmrg}
229305b261ecSmrg
229405b261ecSmrg/****************************************************************************
229505b261ecSmrgREMARKS:
229605b261ecSmrgImplements the MUL instruction and side effects.
229705b261ecSmrg****************************************************************************/
2298f7df2e56Smrgvoid
2299f7df2e56Smrgmul_long(u32 s)
230005b261ecSmrg{
230105b261ecSmrg#ifdef	__HAS_LONG_LONG__
2302f7df2e56Smrg    u64 res = (u64) M.x86.R_EAX * s;
230305b261ecSmrg
2304f7df2e56Smrg    M.x86.R_EAX = (u32) res;
2305f7df2e56Smrg    M.x86.R_EDX = (u32) (res >> 32);
230605b261ecSmrg#else
2307f7df2e56Smrg    u32 a, a_lo, a_hi;
2308f7df2e56Smrg    u32 s_lo, s_hi;
2309f7df2e56Smrg    u32 rlo_lo, rlo_hi, rhi_lo;
2310f7df2e56Smrg
2311f7df2e56Smrg    a = M.x86.R_EAX;
2312f7df2e56Smrg    a_lo = a & 0xFFFF;
2313f7df2e56Smrg    a_hi = a >> 16;
2314f7df2e56Smrg    s_lo = s & 0xFFFF;
2315f7df2e56Smrg    s_hi = s >> 16;
2316f7df2e56Smrg    rlo_lo = a_lo * s_lo;
2317f7df2e56Smrg    rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
2318f7df2e56Smrg    rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
2319f7df2e56Smrg    M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2320f7df2e56Smrg    M.x86.R_EDX = rhi_lo;
232105b261ecSmrg#endif
232205b261ecSmrg
2323f7df2e56Smrg    if (M.x86.R_EDX == 0) {
2324f7df2e56Smrg        CLEAR_FLAG(F_CF);
2325f7df2e56Smrg        CLEAR_FLAG(F_OF);
2326f7df2e56Smrg    }
2327f7df2e56Smrg    else {
2328f7df2e56Smrg        SET_FLAG(F_CF);
2329f7df2e56Smrg        SET_FLAG(F_OF);
233005b261ecSmrg    }
233105b261ecSmrg}
233205b261ecSmrg
233305b261ecSmrg/****************************************************************************
233405b261ecSmrgREMARKS:
233505b261ecSmrgImplements the IDIV instruction and side effects.
233605b261ecSmrg****************************************************************************/
2337f7df2e56Smrgvoid
2338f7df2e56Smrgidiv_byte(u8 s)
233905b261ecSmrg{
234005b261ecSmrg    s32 dvd, div, mod;
234105b261ecSmrg
2342f7df2e56Smrg    dvd = (s16) M.x86.R_AX;
2343f7df2e56Smrg    if (s == 0) {
2344f7df2e56Smrg        x86emu_intr_raise(0);
2345f7df2e56Smrg        return;
2346f7df2e56Smrg    }
2347f7df2e56Smrg    div = dvd / (s8) s;
2348f7df2e56Smrg    mod = dvd % (s8) s;
2349f7df2e56Smrg    if (abs(div) > 0x7f) {
2350f7df2e56Smrg        x86emu_intr_raise(0);
235105b261ecSmrg        return;
2352f7df2e56Smrg    }
2353f7df2e56Smrg    M.x86.R_AL = (s8) div;
2354f7df2e56Smrg    M.x86.R_AH = (s8) mod;
235505b261ecSmrg}
235605b261ecSmrg
235705b261ecSmrg/****************************************************************************
235805b261ecSmrgREMARKS:
235905b261ecSmrgImplements the IDIV instruction and side effects.
236005b261ecSmrg****************************************************************************/
2361f7df2e56Smrgvoid
2362f7df2e56Smrgidiv_word(u16 s)
236305b261ecSmrg{
2364f7df2e56Smrg    s32 dvd, div, mod;
236505b261ecSmrg
2366f7df2e56Smrg    dvd = (((s32) M.x86.R_DX) << 16) | M.x86.R_AX;
2367f7df2e56Smrg    if (s == 0) {
2368f7df2e56Smrg        x86emu_intr_raise(0);
2369f7df2e56Smrg        return;
2370f7df2e56Smrg    }
2371f7df2e56Smrg    div = dvd / (s16) s;
2372f7df2e56Smrg    mod = dvd % (s16) s;
2373f7df2e56Smrg    if (abs(div) > 0x7fff) {
2374f7df2e56Smrg        x86emu_intr_raise(0);
2375f7df2e56Smrg        return;
2376f7df2e56Smrg    }
2377f7df2e56Smrg    CLEAR_FLAG(F_CF);
2378f7df2e56Smrg    CLEAR_FLAG(F_SF);
2379f7df2e56Smrg    CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2380f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
238105b261ecSmrg
2382f7df2e56Smrg    M.x86.R_AX = (u16) div;
2383f7df2e56Smrg    M.x86.R_DX = (u16) mod;
238405b261ecSmrg}
238505b261ecSmrg
238605b261ecSmrg/****************************************************************************
238705b261ecSmrgREMARKS:
238805b261ecSmrgImplements the IDIV instruction and side effects.
238905b261ecSmrg****************************************************************************/
2390f7df2e56Smrgvoid
2391f7df2e56Smrgidiv_long(u32 s)
239205b261ecSmrg{
239305b261ecSmrg#ifdef	__HAS_LONG_LONG__
2394f7df2e56Smrg    s64 dvd, div, mod;
2395f7df2e56Smrg
2396f7df2e56Smrg    dvd = (((s64) M.x86.R_EDX) << 32) | M.x86.R_EAX;
2397f7df2e56Smrg    if (s == 0) {
2398f7df2e56Smrg        x86emu_intr_raise(0);
2399f7df2e56Smrg        return;
2400f7df2e56Smrg    }
2401f7df2e56Smrg    div = dvd / (s32) s;
2402f7df2e56Smrg    mod = dvd % (s32) s;
2403f7df2e56Smrg    if (abs(div) > 0x7fffffff) {
2404f7df2e56Smrg        x86emu_intr_raise(0);
2405f7df2e56Smrg        return;
2406f7df2e56Smrg    }
240705b261ecSmrg#else
2408f7df2e56Smrg    s32 div = 0, mod;
2409f7df2e56Smrg    s32 h_dvd = M.x86.R_EDX;
2410f7df2e56Smrg    u32 l_dvd = M.x86.R_EAX;
2411f7df2e56Smrg    u32 abs_s = s & 0x7FFFFFFF;
2412f7df2e56Smrg    u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
2413f7df2e56Smrg    u32 h_s = abs_s >> 1;
2414f7df2e56Smrg    u32 l_s = abs_s << 31;
2415f7df2e56Smrg    int counter = 31;
2416f7df2e56Smrg    int carry;
2417f7df2e56Smrg
2418f7df2e56Smrg    if (s == 0) {
2419f7df2e56Smrg        x86emu_intr_raise(0);
2420f7df2e56Smrg        return;
2421f7df2e56Smrg    }
2422f7df2e56Smrg    do {
2423f7df2e56Smrg        div <<= 1;
2424f7df2e56Smrg        carry = (l_dvd >= l_s) ? 0 : 1;
2425f7df2e56Smrg
2426f7df2e56Smrg        if (abs_h_dvd < (h_s + carry)) {
2427f7df2e56Smrg            h_s >>= 1;
2428f7df2e56Smrg            l_s = abs_s << (--counter);
2429f7df2e56Smrg            continue;
2430f7df2e56Smrg        }
2431f7df2e56Smrg        else {
2432f7df2e56Smrg            abs_h_dvd -= (h_s + carry);
2433f7df2e56Smrg            l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2434f7df2e56Smrg                : (l_dvd - l_s);
2435f7df2e56Smrg            h_s >>= 1;
2436f7df2e56Smrg            l_s = abs_s << (--counter);
2437f7df2e56Smrg            div |= 1;
2438f7df2e56Smrg            continue;
2439f7df2e56Smrg        }
2440f7df2e56Smrg
2441f7df2e56Smrg    } while (counter > -1);
2442f7df2e56Smrg    /* overflow */
2443f7df2e56Smrg    if (abs_h_dvd || (l_dvd > abs_s)) {
2444f7df2e56Smrg        x86emu_intr_raise(0);
2445f7df2e56Smrg        return;
2446f7df2e56Smrg    }
2447f7df2e56Smrg    /* sign */
2448f7df2e56Smrg    div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
2449f7df2e56Smrg    mod = l_dvd;
245005b261ecSmrg
245105b261ecSmrg#endif
2452f7df2e56Smrg    CLEAR_FLAG(F_CF);
2453f7df2e56Smrg    CLEAR_FLAG(F_AF);
2454f7df2e56Smrg    CLEAR_FLAG(F_SF);
2455f7df2e56Smrg    SET_FLAG(F_ZF);
2456f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
245705b261ecSmrg
2458f7df2e56Smrg    M.x86.R_EAX = (u32) div;
2459f7df2e56Smrg    M.x86.R_EDX = (u32) mod;
246005b261ecSmrg}
246105b261ecSmrg
246205b261ecSmrg/****************************************************************************
246305b261ecSmrgREMARKS:
246405b261ecSmrgImplements the DIV instruction and side effects.
246505b261ecSmrg****************************************************************************/
2466f7df2e56Smrgvoid
2467f7df2e56Smrgdiv_byte(u8 s)
246805b261ecSmrg{
2469f7df2e56Smrg    u32 dvd, div, mod;
247005b261ecSmrg
2471f7df2e56Smrg    dvd = M.x86.R_AX;
247205b261ecSmrg    if (s == 0) {
2473f7df2e56Smrg        x86emu_intr_raise(0);
247405b261ecSmrg        return;
247505b261ecSmrg    }
2476f7df2e56Smrg    div = dvd / (u8) s;
2477f7df2e56Smrg    mod = dvd % (u8) s;
2478f7df2e56Smrg    if (div > 0xff) {
2479f7df2e56Smrg        x86emu_intr_raise(0);
248005b261ecSmrg        return;
2481f7df2e56Smrg    }
2482f7df2e56Smrg    M.x86.R_AL = (u8) div;
2483f7df2e56Smrg    M.x86.R_AH = (u8) mod;
248405b261ecSmrg}
248505b261ecSmrg
248605b261ecSmrg/****************************************************************************
248705b261ecSmrgREMARKS:
248805b261ecSmrgImplements the DIV instruction and side effects.
248905b261ecSmrg****************************************************************************/
2490f7df2e56Smrgvoid
2491f7df2e56Smrgdiv_word(u16 s)
249205b261ecSmrg{
2493f7df2e56Smrg    u32 dvd, div, mod;
249405b261ecSmrg
2495f7df2e56Smrg    dvd = (((u32) M.x86.R_DX) << 16) | M.x86.R_AX;
2496f7df2e56Smrg    if (s == 0) {
2497f7df2e56Smrg        x86emu_intr_raise(0);
249805b261ecSmrg        return;
249905b261ecSmrg    }
2500f7df2e56Smrg    div = dvd / (u16) s;
2501f7df2e56Smrg    mod = dvd % (u16) s;
2502f7df2e56Smrg    if (div > 0xffff) {
2503f7df2e56Smrg        x86emu_intr_raise(0);
2504f7df2e56Smrg        return;
2505f7df2e56Smrg    }
2506f7df2e56Smrg    CLEAR_FLAG(F_CF);
2507f7df2e56Smrg    CLEAR_FLAG(F_SF);
2508f7df2e56Smrg    CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2509f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
251005b261ecSmrg
2511f7df2e56Smrg    M.x86.R_AX = (u16) div;
2512f7df2e56Smrg    M.x86.R_DX = (u16) mod;
251305b261ecSmrg}
251405b261ecSmrg
251505b261ecSmrg/****************************************************************************
251605b261ecSmrgREMARKS:
251705b261ecSmrgImplements the DIV instruction and side effects.
251805b261ecSmrg****************************************************************************/
2519f7df2e56Smrgvoid
2520f7df2e56Smrgdiv_long(u32 s)
252105b261ecSmrg{
252205b261ecSmrg#ifdef	__HAS_LONG_LONG__
2523f7df2e56Smrg    u64 dvd, div, mod;
2524f7df2e56Smrg
2525f7df2e56Smrg    dvd = (((u64) M.x86.R_EDX) << 32) | M.x86.R_EAX;
2526f7df2e56Smrg    if (s == 0) {
2527f7df2e56Smrg        x86emu_intr_raise(0);
2528f7df2e56Smrg        return;
2529f7df2e56Smrg    }
2530f7df2e56Smrg    div = dvd / (u32) s;
2531f7df2e56Smrg    mod = dvd % (u32) s;
2532f7df2e56Smrg    if (abs(div) > 0xffffffff) {
2533f7df2e56Smrg        x86emu_intr_raise(0);
2534f7df2e56Smrg        return;
2535f7df2e56Smrg    }
253605b261ecSmrg#else
2537f7df2e56Smrg    s32 div = 0, mod;
2538f7df2e56Smrg    s32 h_dvd = M.x86.R_EDX;
2539f7df2e56Smrg    u32 l_dvd = M.x86.R_EAX;
2540f7df2e56Smrg
2541f7df2e56Smrg    u32 h_s = s;
2542f7df2e56Smrg    u32 l_s = 0;
2543f7df2e56Smrg    int counter = 32;
2544f7df2e56Smrg    int carry;
2545f7df2e56Smrg
2546f7df2e56Smrg    if (s == 0) {
2547f7df2e56Smrg        x86emu_intr_raise(0);
2548f7df2e56Smrg        return;
2549f7df2e56Smrg    }
2550f7df2e56Smrg    do {
2551f7df2e56Smrg        div <<= 1;
2552f7df2e56Smrg        carry = (l_dvd >= l_s) ? 0 : 1;
2553f7df2e56Smrg
2554f7df2e56Smrg        if (h_dvd < (h_s + carry)) {
2555f7df2e56Smrg            h_s >>= 1;
2556f7df2e56Smrg            l_s = s << (--counter);
2557f7df2e56Smrg            continue;
2558f7df2e56Smrg        }
2559f7df2e56Smrg        else {
2560f7df2e56Smrg            h_dvd -= (h_s + carry);
2561f7df2e56Smrg            l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2562f7df2e56Smrg                : (l_dvd - l_s);
2563f7df2e56Smrg            h_s >>= 1;
2564f7df2e56Smrg            l_s = s << (--counter);
2565f7df2e56Smrg            div |= 1;
2566f7df2e56Smrg            continue;
2567f7df2e56Smrg        }
2568f7df2e56Smrg
2569f7df2e56Smrg    } while (counter > -1);
2570f7df2e56Smrg    /* overflow */
2571f7df2e56Smrg    if (h_dvd || (l_dvd > s)) {
2572f7df2e56Smrg        x86emu_intr_raise(0);
2573f7df2e56Smrg        return;
2574f7df2e56Smrg    }
2575f7df2e56Smrg    mod = l_dvd;
257605b261ecSmrg#endif
2577f7df2e56Smrg    CLEAR_FLAG(F_CF);
2578f7df2e56Smrg    CLEAR_FLAG(F_AF);
2579f7df2e56Smrg    CLEAR_FLAG(F_SF);
2580f7df2e56Smrg    SET_FLAG(F_ZF);
2581f7df2e56Smrg    CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
258205b261ecSmrg
2583f7df2e56Smrg    M.x86.R_EAX = (u32) div;
2584f7df2e56Smrg    M.x86.R_EDX = (u32) mod;
258505b261ecSmrg}
258605b261ecSmrg
258705b261ecSmrg/****************************************************************************
258805b261ecSmrgREMARKS:
258905b261ecSmrgImplements the IN string instruction and side effects.
259005b261ecSmrg****************************************************************************/
2591f7df2e56Smrgvoid
2592f7df2e56Smrgins(int size)
259305b261ecSmrg{
2594f7df2e56Smrg    int inc = size;
259505b261ecSmrg
2596f7df2e56Smrg    if (ACCESS_FLAG(F_DF)) {
2597f7df2e56Smrg        inc = -size;
2598f7df2e56Smrg    }
2599f7df2e56Smrg    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
26005a112b11Smrg        /* don't care whether REPE or REPNE */
260105b261ecSmrg        /* in until CX is ZERO. */
2602f7df2e56Smrg        u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2603f7df2e56Smrg                     M.x86.R_ECX : M.x86.R_CX);
260405b261ecSmrg        switch (size) {
2605f7df2e56Smrg        case 1:
260605b261ecSmrg            while (count--) {
2607f7df2e56Smrg                store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
2608f7df2e56Smrg                                    (*sys_inb) (M.x86.R_DX));
2609f7df2e56Smrg                M.x86.R_DI += inc;
261005b261ecSmrg            }
261105b261ecSmrg            break;
261205b261ecSmrg
2613f7df2e56Smrg        case 2:
261405b261ecSmrg            while (count--) {
2615f7df2e56Smrg                store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
2616f7df2e56Smrg                                    (*sys_inw) (M.x86.R_DX));
2617f7df2e56Smrg                M.x86.R_DI += inc;
261805b261ecSmrg            }
261905b261ecSmrg            break;
2620f7df2e56Smrg        case 4:
262105b261ecSmrg            while (count--) {
2622f7df2e56Smrg                store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
2623f7df2e56Smrg                                    (*sys_inl) (M.x86.R_DX));
2624f7df2e56Smrg                M.x86.R_DI += inc;
262505b261ecSmrg                break;
262605b261ecSmrg            }
262705b261ecSmrg        }
2628f7df2e56Smrg        M.x86.R_CX = 0;
2629f7df2e56Smrg        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2630f7df2e56Smrg            M.x86.R_ECX = 0;
263105b261ecSmrg        }
2632f7df2e56Smrg        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2633f7df2e56Smrg    }
2634f7df2e56Smrg    else {
263505b261ecSmrg        switch (size) {
2636f7df2e56Smrg        case 1:
2637f7df2e56Smrg            store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
2638f7df2e56Smrg                                (*sys_inb) (M.x86.R_DX));
263905b261ecSmrg            break;
2640f7df2e56Smrg        case 2:
2641f7df2e56Smrg            store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
2642f7df2e56Smrg                                (*sys_inw) (M.x86.R_DX));
264305b261ecSmrg            break;
2644f7df2e56Smrg        case 4:
2645f7df2e56Smrg            store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
2646f7df2e56Smrg                                (*sys_inl) (M.x86.R_DX));
264705b261ecSmrg            break;
264805b261ecSmrg        }
2649f7df2e56Smrg        M.x86.R_DI += inc;
265005b261ecSmrg    }
265105b261ecSmrg}
265205b261ecSmrg
265305b261ecSmrg/****************************************************************************
265405b261ecSmrgREMARKS:
265505b261ecSmrgImplements the OUT string instruction and side effects.
265605b261ecSmrg****************************************************************************/
2657f7df2e56Smrgvoid
2658f7df2e56Smrgouts(int size)
265905b261ecSmrg{
266005b261ecSmrg    int inc = size;
266105b261ecSmrg
2662f7df2e56Smrg    if (ACCESS_FLAG(F_DF)) {
266305b261ecSmrg        inc = -size;
266405b261ecSmrg    }
2665f7df2e56Smrg    if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
26665a112b11Smrg        /* don't care whether REPE or REPNE */
266705b261ecSmrg        /* out until CX is ZERO. */
2668f7df2e56Smrg        u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2669f7df2e56Smrg                     M.x86.R_ECX : M.x86.R_CX);
267005b261ecSmrg        switch (size) {
2671f7df2e56Smrg        case 1:
267205b261ecSmrg            while (count--) {
2673f7df2e56Smrg                (*sys_outb) (M.x86.R_DX,
2674f7df2e56Smrg                             fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2675f7df2e56Smrg                M.x86.R_SI += inc;
267605b261ecSmrg            }
267705b261ecSmrg            break;
267805b261ecSmrg
2679f7df2e56Smrg        case 2:
268005b261ecSmrg            while (count--) {
2681f7df2e56Smrg                (*sys_outw) (M.x86.R_DX,
2682f7df2e56Smrg                             fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2683f7df2e56Smrg                M.x86.R_SI += inc;
268405b261ecSmrg            }
268505b261ecSmrg            break;
2686f7df2e56Smrg        case 4:
268705b261ecSmrg            while (count--) {
2688f7df2e56Smrg                (*sys_outl) (M.x86.R_DX,
2689f7df2e56Smrg                             fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2690f7df2e56Smrg                M.x86.R_SI += inc;
269105b261ecSmrg                break;
269205b261ecSmrg            }
269305b261ecSmrg        }
2694f7df2e56Smrg        M.x86.R_CX = 0;
2695f7df2e56Smrg        if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2696f7df2e56Smrg            M.x86.R_ECX = 0;
269705b261ecSmrg        }
2698f7df2e56Smrg        M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2699f7df2e56Smrg    }
2700f7df2e56Smrg    else {
270105b261ecSmrg        switch (size) {
2702f7df2e56Smrg        case 1:
2703f7df2e56Smrg            (*sys_outb) (M.x86.R_DX,
2704f7df2e56Smrg                         fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
270505b261ecSmrg            break;
2706f7df2e56Smrg        case 2:
2707f7df2e56Smrg            (*sys_outw) (M.x86.R_DX,
2708f7df2e56Smrg                         fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
270905b261ecSmrg            break;
2710f7df2e56Smrg        case 4:
2711f7df2e56Smrg            (*sys_outl) (M.x86.R_DX,
2712f7df2e56Smrg                         fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
271305b261ecSmrg            break;
271405b261ecSmrg        }
2715f7df2e56Smrg        M.x86.R_SI += inc;
271605b261ecSmrg    }
271705b261ecSmrg}
271805b261ecSmrg
271905b261ecSmrg/****************************************************************************
272005b261ecSmrgPARAMETERS:
272105b261ecSmrgaddr	- Address to fetch word from
272205b261ecSmrg
272305b261ecSmrgREMARKS:
272405b261ecSmrgFetches a word from emulator memory using an absolute address.
272505b261ecSmrg****************************************************************************/
2726f7df2e56Smrgu16
2727f7df2e56Smrgmem_access_word(int addr)
272805b261ecSmrg{
2729f7df2e56Smrg    DB(if (CHECK_MEM_ACCESS())
2730f7df2e56Smrg       x86emu_check_mem_access(addr);)
2731f7df2e56Smrg        return (*sys_rdw) (addr);
273205b261ecSmrg}
273305b261ecSmrg
273405b261ecSmrg/****************************************************************************
273505b261ecSmrgREMARKS:
273605b261ecSmrgPushes a word onto the stack.
273705b261ecSmrg
273805b261ecSmrgNOTE: Do not inline this, as (*sys_wrX) is already inline!
273905b261ecSmrg****************************************************************************/
2740f7df2e56Smrgvoid
2741f7df2e56Smrgpush_word(u16 w)
274205b261ecSmrg{
2743f7df2e56Smrg    DB(if (CHECK_SP_ACCESS())
2744f7df2e56Smrg       x86emu_check_sp_access();)
2745f7df2e56Smrg        M.x86.R_SP -= 2;
2746f7df2e56Smrg    (*sys_wrw) (((u32) M.x86.R_SS << 4) + M.x86.R_SP, w);
274705b261ecSmrg}
274805b261ecSmrg
274905b261ecSmrg/****************************************************************************
275005b261ecSmrgREMARKS:
275105b261ecSmrgPushes a long onto the stack.
275205b261ecSmrg
275305b261ecSmrgNOTE: Do not inline this, as (*sys_wrX) is already inline!
275405b261ecSmrg****************************************************************************/
2755f7df2e56Smrgvoid
2756f7df2e56Smrgpush_long(u32 w)
275705b261ecSmrg{
2758f7df2e56Smrg    DB(if (CHECK_SP_ACCESS())
2759f7df2e56Smrg       x86emu_check_sp_access();)
2760f7df2e56Smrg        M.x86.R_SP -= 4;
2761f7df2e56Smrg    (*sys_wrl) (((u32) M.x86.R_SS << 4) + M.x86.R_SP, w);
276205b261ecSmrg}
276305b261ecSmrg
276405b261ecSmrg/****************************************************************************
276505b261ecSmrgREMARKS:
276605b261ecSmrgPops a word from the stack.
276705b261ecSmrg
276805b261ecSmrgNOTE: Do not inline this, as (*sys_rdX) is already inline!
276905b261ecSmrg****************************************************************************/
2770f7df2e56Smrgu16
2771f7df2e56Smrgpop_word(void)
277205b261ecSmrg{
2773f7df2e56Smrg    register u16 res;
277405b261ecSmrg
2775f7df2e56Smrg    DB(if (CHECK_SP_ACCESS())
2776f7df2e56Smrg       x86emu_check_sp_access();)
2777f7df2e56Smrg        res = (*sys_rdw) (((u32) M.x86.R_SS << 4) + M.x86.R_SP);
2778f7df2e56Smrg    M.x86.R_SP += 2;
2779f7df2e56Smrg    return res;
278005b261ecSmrg}
278105b261ecSmrg
278205b261ecSmrg/****************************************************************************
278305b261ecSmrgREMARKS:
278405b261ecSmrgPops a long from the stack.
278505b261ecSmrg
278605b261ecSmrgNOTE: Do not inline this, as (*sys_rdX) is already inline!
278705b261ecSmrg****************************************************************************/
2788f7df2e56Smrgu32
2789f7df2e56Smrgpop_long(void)
279005b261ecSmrg{
279105b261ecSmrg    register u32 res;
279205b261ecSmrg
2793f7df2e56Smrg    DB(if (CHECK_SP_ACCESS())
2794f7df2e56Smrg       x86emu_check_sp_access();)
2795f7df2e56Smrg        res = (*sys_rdl) (((u32) M.x86.R_SS << 4) + M.x86.R_SP);
2796f7df2e56Smrg    M.x86.R_SP += 4;
279705b261ecSmrg    return res;
279805b261ecSmrg}
279905b261ecSmrg
28004642e01fSmrg/****************************************************************************
28014642e01fSmrgREMARKS:
28024642e01fSmrgCPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output
28034642e01fSmrg****************************************************************************/
2804f7df2e56Smrgvoid
2805f7df2e56Smrgcpuid(void)
28064642e01fSmrg{
28074642e01fSmrg    u32 feature = M.x86.R_EAX;
28084642e01fSmrg
28094642e01fSmrg#ifdef X86EMU_HAS_HW_CPUID
28104642e01fSmrg    /* If the platform allows it, we will base our values on the real
28114642e01fSmrg     * results from the CPUID instruction.  We limit support to the
28124642e01fSmrg     * first two features, and the results of those are sanitized.
28134642e01fSmrg     */
28144642e01fSmrg    if (feature <= 1)
2815f7df2e56Smrg        hw_cpuid(&M.x86.R_EAX, &M.x86.R_EBX, &M.x86.R_ECX, &M.x86.R_EDX);
28164642e01fSmrg#endif
28174642e01fSmrg
28184642e01fSmrg    switch (feature) {
28194642e01fSmrg    case 0:
28204642e01fSmrg        /* Regardless if we have real data from the hardware, the emulator
28215a112b11Smrg         * will only support up to feature 1, which we set in register EAX.
2822f7df2e56Smrg         * Registers EBX:EDX:ECX contain a string identifying the CPU.
2823f7df2e56Smrg         */
28244642e01fSmrg        M.x86.R_EAX = 1;
28254642e01fSmrg#ifndef X86EMU_HAS_HW_CPUID
28264642e01fSmrg        /* EBX:EDX:ECX = "GenuineIntel" */
28274642e01fSmrg        M.x86.R_EBX = 0x756e6547;
28284642e01fSmrg        M.x86.R_EDX = 0x49656e69;
28294642e01fSmrg        M.x86.R_ECX = 0x6c65746e;
28304642e01fSmrg#endif
28314642e01fSmrg        break;
28324642e01fSmrg    case 1:
28334642e01fSmrg#ifndef X86EMU_HAS_HW_CPUID
28344642e01fSmrg        /* If we don't have x86 compatible hardware, we return values from an
2835f7df2e56Smrg         * Intel 486dx4; which was one of the first processors to have CPUID.
2836f7df2e56Smrg         */
28374642e01fSmrg        M.x86.R_EAX = 0x00000480;
28384642e01fSmrg        M.x86.R_EBX = 0x00000000;
28394642e01fSmrg        M.x86.R_ECX = 0x00000000;
2840f7df2e56Smrg        M.x86.R_EDX = 0x00000002;       /* VME */
28414642e01fSmrg#else
28424642e01fSmrg        /* In the case that we have hardware CPUID instruction, we make sure
2843f7df2e56Smrg         * that the features reported are limited to TSC and VME.
2844f7df2e56Smrg         */
28454642e01fSmrg        M.x86.R_EDX &= 0x00000012;
28464642e01fSmrg#endif
28474642e01fSmrg        break;
28484642e01fSmrg    default:
28494642e01fSmrg        /* Finally, we don't support any additional features.  Most CPUs
2850f7df2e56Smrg         * return all zeros when queried for invalid or unsupported feature
2851f7df2e56Smrg         * numbers.
2852f7df2e56Smrg         */
28534642e01fSmrg        M.x86.R_EAX = 0;
28544642e01fSmrg        M.x86.R_EBX = 0;
28554642e01fSmrg        M.x86.R_ECX = 0;
28564642e01fSmrg        M.x86.R_EDX = 0;
28574642e01fSmrg        break;
28584642e01fSmrg    }
28594642e01fSmrg}
2860