xref: /plan9/sys/src/ape/lib/ap/power/vlrt.c (revision 6891d8578618fb7ccda4a131c122d4d0e6580c4b)
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