1 typedef unsigned long ulong;
2 typedef unsigned int uint;
3 typedef unsigned short ushort;
4 typedef unsigned char uchar;
5 typedef signed char schar;
6
7 #define SIGN(n) (1UL<<(n-1))
8
9 typedef struct Vlong Vlong;
10 struct Vlong
11 {
12 ulong hi;
13 ulong lo;
14 };
15
16 void abort(void);
17 void _divu64(Vlong, Vlong, Vlong*, Vlong*);
18
19 void
_d2v(Vlong * y,double d)20 _d2v(Vlong *y, double d)
21 {
22 union { double d; Vlong; } x;
23 ulong xhi, xlo, ylo, yhi;
24 int sh;
25
26 x.d = d;
27
28 xhi = (x.hi & 0xfffff) | 0x100000;
29 xlo = x.lo;
30 sh = 1075 - ((x.hi >> 20) & 0x7ff);
31
32 ylo = 0;
33 yhi = 0;
34 if(sh >= 0) {
35 /* v = (hi||lo) >> sh */
36 if(sh < 32) {
37 if(sh == 0) {
38 ylo = xlo;
39 yhi = xhi;
40 } else {
41 ylo = (xlo >> sh) | (xhi << (32-sh));
42 yhi = xhi >> sh;
43 }
44 } else {
45 if(sh == 32) {
46 ylo = xhi;
47 } else
48 if(sh < 64) {
49 ylo = xhi >> (sh-32);
50 }
51 }
52 } else {
53 /* v = (hi||lo) << -sh */
54 sh = -sh;
55 if(sh <= 10) {
56 ylo = xlo << sh;
57 yhi = (xhi << sh) | (xlo >> (32-sh));
58 } else {
59 /* overflow */
60 yhi = d; /* causes something awful */
61 }
62 }
63 if(x.hi & SIGN(32)) {
64 if(ylo != 0) {
65 ylo = -ylo;
66 yhi = ~yhi;
67 } else
68 yhi = -yhi;
69 }
70
71 y->hi = yhi;
72 y->lo = ylo;
73 }
74
75 void
_f2v(Vlong * y,float f)76 _f2v(Vlong *y, float f)
77 {
78
79 _d2v(y, f);
80 }
81
82 double
_v2d(Vlong x)83 _v2d(Vlong x)
84 {
85 if(x.hi & SIGN(32)) {
86 if(x.lo) {
87 x.lo = -x.lo;
88 x.hi = ~x.hi;
89 } else
90 x.hi = -x.hi;
91 return -((long)x.hi*4294967296. + x.lo);
92 }
93 return (long)x.hi*4294967296. + x.lo;
94 }
95
96 float
_v2f(Vlong x)97 _v2f(Vlong x)
98 {
99 return _v2d(x);
100 }
101
102 void
_divvu(Vlong * q,Vlong n,Vlong d)103 _divvu(Vlong *q, Vlong n, Vlong d)
104 {
105
106 if(n.hi == 0 && d.hi == 0) {
107 q->hi = 0;
108 q->lo = n.lo / d.lo;
109 return;
110 }
111 _divu64(n, d, q, 0);
112 }
113
114 void
_modvu(Vlong * r,Vlong n,Vlong d)115 _modvu(Vlong *r, Vlong n, Vlong d)
116 {
117
118 if(n.hi == 0 && d.hi == 0) {
119 r->hi = 0;
120 r->lo = n.lo % d.lo;
121 return;
122 }
123 _divu64(n, d, 0, r);
124 }
125
126 static void
vneg(Vlong * v)127 vneg(Vlong *v)
128 {
129
130 if(v->lo == 0) {
131 v->hi = -v->hi;
132 return;
133 }
134 v->lo = -v->lo;
135 v->hi = ~v->hi;
136 }
137
138 void
_divv(Vlong * q,Vlong n,Vlong d)139 _divv(Vlong *q, Vlong n, Vlong d)
140 {
141 long nneg, dneg;
142
143 if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
144 q->lo = (long)n.lo / (long)d.lo;
145 q->hi = ((long)q->lo) >> 31;
146 return;
147 }
148 nneg = n.hi >> 31;
149 if(nneg)
150 vneg(&n);
151 dneg = d.hi >> 31;
152 if(dneg)
153 vneg(&d);
154 _divu64(n, d, q, 0);
155 if(nneg != dneg)
156 vneg(q);
157 }
158
159 void
_modv(Vlong * r,Vlong n,Vlong d)160 _modv(Vlong *r, Vlong n, Vlong d)
161 {
162 long nneg, dneg;
163
164 if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
165 r->lo = (long)n.lo % (long)d.lo;
166 r->hi = ((long)r->lo) >> 31;
167 return;
168 }
169 nneg = n.hi >> 31;
170 if(nneg)
171 vneg(&n);
172 dneg = d.hi >> 31;
173 if(dneg)
174 vneg(&d);
175 _divu64(n, d, 0, r);
176 if(nneg)
177 vneg(r);
178 }
179
180 void
_vasop(Vlong * ret,void * lv,void fn (Vlong *,Vlong,Vlong),int type,Vlong rv)181 _vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv)
182 {
183 Vlong t, u;
184
185 u = *ret;
186 switch(type) {
187 default:
188 abort();
189 break;
190
191 case 1: /* schar */
192 t.lo = *(schar*)lv;
193 t.hi = t.lo >> 31;
194 fn(&u, t, rv);
195 *(schar*)lv = u.lo;
196 break;
197
198 case 2: /* uchar */
199 t.lo = *(uchar*)lv;
200 t.hi = 0;
201 fn(&u, t, rv);
202 *(uchar*)lv = u.lo;
203 break;
204
205 case 3: /* short */
206 t.lo = *(short*)lv;
207 t.hi = t.lo >> 31;
208 fn(&u, t, rv);
209 *(short*)lv = u.lo;
210 break;
211
212 case 4: /* ushort */
213 t.lo = *(ushort*)lv;
214 t.hi = 0;
215 fn(&u, t, rv);
216 *(ushort*)lv = u.lo;
217 break;
218
219 case 9: /* int */
220 t.lo = *(int*)lv;
221 t.hi = t.lo >> 31;
222 fn(&u, t, rv);
223 *(int*)lv = u.lo;
224 break;
225
226 case 10: /* uint */
227 t.lo = *(uint*)lv;
228 t.hi = 0;
229 fn(&u, t, rv);
230 *(uint*)lv = u.lo;
231 break;
232
233 case 5: /* long */
234 t.lo = *(long*)lv;
235 t.hi = t.lo >> 31;
236 fn(&u, t, rv);
237 *(long*)lv = u.lo;
238 break;
239
240 case 6: /* ulong */
241 t.lo = *(ulong*)lv;
242 t.hi = 0;
243 fn(&u, t, rv);
244 *(ulong*)lv = u.lo;
245 break;
246
247 case 7: /* vlong */
248 case 8: /* uvlong */
249 fn(&u, *(Vlong*)lv, rv);
250 *(Vlong*)lv = u;
251 break;
252 }
253 *ret = u;
254 }
255