Pristine Ack-5.5
[Ack-5.5.git] / util / int / do_unsar.c
1 /*
2  * Sources of the "UNSIGNED ARITHMETIC" group instructions
3  */
4
5 /* $Id: do_unsar.c,v 2.5 1994/06/24 10:47:04 ceriel Exp $ */
6
7 #include        <em_abs.h>
8 #include        "logging.h"
9 #include        "global.h"
10 #include        "log.h"
11 #include        "mem.h"
12 #include        "trap.h"
13 #include        "warn.h"
14 #include        "text.h"
15 #include        "fra.h"
16
17 /************************************************************************
18  *      No checking is performed, except for division by zero.          *
19  *      The operands popped from the stack are put in unsigned          *
20  *      longs. Now the required operation can be performed              *
21  *      immediately. Whether the wordsize is two or four bytes          *
22  *      doesn't matter. Alas, arithmetic is performed modulo            *
23  *      the highest unsigned number for the given size plus 1.          *
24  ************************************************************************/
25
26 #ifdef  LOGGING
27 extern int must_test;
28 #endif  /* LOGGING */
29
30 #define adu(w1,w2)      (unsigned long)(w1 + w2)
31 #define sbu(w1,w2)      (unsigned long)(w1 - w2)
32 #define mlu(w1,w2)      (unsigned long)(w1 * w2)
33
34 PRIVATE unsigned long dvu(), rmu(), slu(), sru();
35
36 DoADU(l)
37         register size l;
38 {
39         /* ADU w: Addition */
40         register unsigned long t = upop(arg_wi(l));
41
42         LOG(("@U6 DoADU(%ld)", l));
43         spoilFRA();
44         npush((long) adu(upop(l), t), l);
45 }
46
47 DoSBU(l)
48         register size l;
49 {
50         /* SBU w: Subtraction */
51         register unsigned long t = upop(arg_wi(l));
52
53         LOG(("@U6 DoSBU(%ld)", l));
54         spoilFRA();
55         npush((long) sbu(upop(l), t), l);
56 }
57
58 DoMLU(l)
59         register size l;
60 {
61         /* MLU w: Multiplication */
62         register unsigned long t = upop(arg_wi(l));
63
64         LOG(("@U6 DoMLU(%ld)", l));
65         spoilFRA();
66         npush((long) mlu(upop(l), t), l);
67 }
68
69 DoDVU(l)
70         register size l;
71 {
72         /* DVU w: Division */
73         register unsigned long t = upop(arg_wi(l));
74
75         LOG(("@U6 DoDVU(%ld)", l));
76         spoilFRA();
77         npush((long) dvu(upop(l), t), l);
78 }
79
80 DoRMU(l)
81         register size l;
82 {
83         /* RMU w: Remainder */
84         register unsigned long t = upop(arg_wi(l));
85
86         LOG(("@U6 DoRMU(%ld)", l));
87         spoilFRA();
88         npush((long) rmu(upop(l), t), l);
89 }
90
91 DoSLU(l)
92         register size l;
93 {
94         /* SLU w: Shift left */
95         register unsigned long t = uwpop();
96
97         LOG(("@U6 DoSLU(%ld)", l));
98         spoilFRA();
99         l = arg_wi(l);
100         npush((long) slu(upop(l), t, l), l);
101 }
102
103 DoSRU(l)
104         register size l;
105 {
106         /* SRU w: Shift right */
107         register unsigned long t = uwpop();
108
109         LOG(("@U6 DoSRU(%ld)", l));
110         spoilFRA();
111         l = arg_wi(l);
112         npush((long) sru(upop(l), t, l), l);
113 }
114
115 PRIVATE unsigned long dvu(w1, w2)
116         unsigned long w1, w2;
117 {
118         if (w2 == 0) {
119                 if (!(IgnMask&BIT(EIDIVZ))) {
120                         trap(EIDIVZ);
121                 }
122                 else    return (0L);
123         }
124         return (w1 / w2);
125 }
126
127 PRIVATE unsigned long rmu(w1, w2)
128         unsigned long w1, w2;
129 {
130         if (w2 == 0) {
131                 if (!(IgnMask&BIT(EIDIVZ))) {
132                         trap(EIDIVZ);
133                 }
134                 else    return (0L);
135         }
136         return (w1 % w2);
137 }
138
139 /*ARGSUSED*/
140 PRIVATE unsigned long slu(w1, w2, nbytes)       /* w1 << w2 */
141         unsigned long w1, w2;
142         size nbytes;
143 {
144 #ifdef  LOGGING
145         if (must_test) {
146                 /* check shift distance */
147                 if (w2 >= nbytes*8)     {
148                         warning(WSHLARGE);
149                         w2 = nbytes*8 - 1;
150                 }
151         }
152 #endif  /* LOGGING */
153
154         /* calculate result */
155         return (w1 << w2);
156 }
157
158 /*ARGSUSED*/
159 PRIVATE unsigned long sru(w1, w2, nbytes)       /* w1 >> w2 */
160         unsigned long w1, w2;
161         size nbytes;
162 {
163 #ifdef  LOGGING
164         if (must_test) {
165                 /* check shift distance */
166                 if (w2 >= nbytes*8)     {
167                         warning(WSHLARGE);
168                         w2 = nbytes*8 - 1;
169                 }
170         }
171 #endif  /* LOGGING */
172
173         /* calculate result */
174         return (w1 >> w2);
175 }
176