]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libc/arm/vlrt.c
vt: but not too fast :-)
[plan9front.git] / sys / src / libc / arm / vlrt.c
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   lo;
13         ulong   hi;
14 };
15
16 void    abort(void);
17
18 void
19 _d2v(Vlong *y, double d)
20 {
21         union { double d; struct Vlong; } x;
22         ulong xhi, xlo, ylo, yhi;
23         int sh;
24
25         x.d = d;
26
27         xhi = (x.hi & 0xfffff) | 0x100000;
28         xlo = x.lo;
29         sh = 1075 - ((x.hi >> 20) & 0x7ff);
30
31         ylo = 0;
32         yhi = 0;
33         if(sh >= 0) {
34                 /* v = (hi||lo) >> sh */
35                 if(sh < 32) {
36                         if(sh == 0) {
37                                 ylo = xlo;
38                                 yhi = xhi;
39                         } else {
40                                 ylo = (xlo >> sh) | (xhi << (32-sh));
41                                 yhi = xhi >> sh;
42                         }
43                 } else {
44                         if(sh == 32) {
45                                 ylo = xhi;
46                         } else
47                         if(sh < 64) {
48                                 ylo = xhi >> (sh-32);
49                         }
50                 }
51         } else {
52                 /* v = (hi||lo) << -sh */
53                 sh = -sh;
54                 if(sh <= 10) {
55                         ylo = xlo << sh;
56                         yhi = (xhi << sh) | (xlo >> (32-sh));
57                 } else {
58                         /* overflow */
59                         yhi = d;        /* causes something awful */
60                 }
61         }
62         if(x.hi & SIGN(32)) {
63                 if(ylo != 0) {
64                         ylo = -ylo;
65                         yhi = ~yhi;
66                 } else
67                         yhi = -yhi;
68         }
69
70         y->hi = yhi;
71         y->lo = ylo;
72 }
73
74 void
75 _f2v(Vlong *y, float f)
76 {
77         _d2v(y, f);
78 }
79
80 double
81 _v2d(Vlong x)
82 {
83         if(x.hi & SIGN(32)) {
84                 if(x.lo) {
85                         x.lo = -x.lo;
86                         x.hi = ~x.hi;
87                 } else
88                         x.hi = -x.hi;
89                 return -((long)x.hi*4294967296. + x.lo);
90         }
91         return (long)x.hi*4294967296. + x.lo;
92 }
93
94 float
95 _v2f(Vlong x)
96 {
97         return _v2d(x);
98 }
99
100 double
101 _uv2d(Vlong x)
102 {
103         return x.hi*4294967296. + x.lo;
104 }
105
106 float
107 _uv2f(Vlong x)
108 {
109         return _uv2d(x);
110 }
111
112 void
113 _vasaddd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
114 {
115         _d2v(lv, v2d(*lv)+rv);
116         *ret = *lv;
117 }
118 void
119 _vassubd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
120 {
121         _d2v(lv, v2d(*lv)-rv);
122         *ret = *lv;
123 }
124 void
125 _vasmuld(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
126 {
127         _d2v(lv, v2d(*lv)*rv);
128         *ret = *lv;
129 }
130 void
131 _vasdivd(Vlong *ret, Vlong *lv, double v2d(Vlong), double rv)
132 {
133         _d2v(lv, v2d(*lv)/rv);
134         *ret = *lv;
135 }
136
137 /* too many of these are also needed by profiler; leave them out */
138 #pragma profile off
139
140 static void
141 dodiv(Vlong num, Vlong den, Vlong *q, Vlong *r)
142 {
143         ulong numlo, numhi, denhi, denlo, quohi, quolo, t;
144         int i;
145
146         numhi = num.hi;
147         numlo = num.lo;
148         denhi = den.hi;
149         denlo = den.lo;
150         /*
151          * get a divide by zero
152          */
153         if(denlo==0 && denhi==0) {
154                 numlo = numlo / denlo;
155         }
156
157         /*
158          * set up the divisor and find the number of iterations needed
159          */
160         if(numhi >= SIGN(32)) {
161                 quohi = SIGN(32);
162                 quolo = 0;
163         } else {
164                 quohi = numhi;
165                 quolo = numlo;
166         }
167         i = 0;
168         while(denhi < quohi || (denhi == quohi && denlo < quolo)) {
169                 denhi = (denhi<<1) | (denlo>>31);
170                 denlo <<= 1;
171                 i++;
172         }
173
174         quohi = 0;
175         quolo = 0;
176         for(; i >= 0; i--) {
177                 quohi = (quohi<<1) | (quolo>>31);
178                 quolo <<= 1;
179                 if(numhi > denhi || (numhi == denhi && numlo >= denlo)) {
180                         t = numlo;
181                         numlo -= denlo;
182                         if(numlo > t)
183                                 numhi--;
184                         numhi -= denhi;
185                         quolo |= 1;
186                 }
187                 denlo = (denlo>>1) | (denhi<<31);
188                 denhi >>= 1;
189         }
190
191         if(q) {
192                 q->lo = quolo;
193                 q->hi = quohi;
194         }
195         if(r) {
196                 r->lo = numlo;
197                 r->hi = numhi;
198         }
199 }
200
201 void
202 _divvu(Vlong *q, Vlong n, Vlong d)
203 {
204         if(n.hi == 0 && d.hi == 0) {
205                 q->hi = 0;
206                 q->lo = n.lo / d.lo;
207                 return;
208         }
209         dodiv(n, d, q, 0);
210 }
211
212 void
213 _modvu(Vlong *r, Vlong n, Vlong d)
214 {
215
216         if(n.hi == 0 && d.hi == 0) {
217                 r->hi = 0;
218                 r->lo = n.lo % d.lo;
219                 return;
220         }
221         dodiv(n, d, 0, r);
222 }
223
224 static void
225 vneg(Vlong *v)
226 {
227
228         if(v->lo == 0) {
229                 v->hi = -v->hi;
230                 return;
231         }
232         v->lo = -v->lo;
233         v->hi = ~v->hi;
234 }
235
236 void
237 _divv(Vlong *q, Vlong n, Vlong d)
238 {
239         long nneg, dneg;
240
241         if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
242                 q->lo = (long)n.lo / (long)d.lo;
243                 q->hi = ((long)q->lo) >> 31;
244                 return;
245         }
246         nneg = n.hi >> 31;
247         if(nneg)
248                 vneg(&n);
249         dneg = d.hi >> 31;
250         if(dneg)
251                 vneg(&d);
252         dodiv(n, d, q, 0);
253         if(nneg != dneg)
254                 vneg(q);
255 }
256
257 void
258 _modv(Vlong *r, Vlong n, Vlong d)
259 {
260         long nneg, dneg;
261
262         if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) {
263                 r->lo = (long)n.lo % (long)d.lo;
264                 r->hi = ((long)r->lo) >> 31;
265                 return;
266         }
267         nneg = n.hi >> 31;
268         if(nneg)
269                 vneg(&n);
270         dneg = d.hi >> 31;
271         if(dneg)
272                 vneg(&d);
273         dodiv(n, d, 0, r);
274         if(nneg)
275                 vneg(r);
276 }
277
278 void
279 _rshav(Vlong *r, Vlong a, int b)
280 {
281         long t;
282
283         t = a.hi;
284         if(b >= 32) {
285                 r->hi = t>>31;
286                 if(b >= 64) {
287                         /* this is illegal re C standard */
288                         r->lo = t>>31;
289                         return;
290                 }
291                 r->lo = t >> (b-32);
292                 return;
293         }
294         if(b <= 0) {
295                 r->hi = t;
296                 r->lo = a.lo;
297                 return;
298         }
299         r->hi = t >> b;
300         r->lo = (t << (32-b)) | (a.lo >> b);
301 }
302
303 void
304 _rshlv(Vlong *r, Vlong a, int b)
305 {
306         ulong t;
307
308         t = a.hi;
309         if(b >= 32) {
310                 r->hi = 0;
311                 if(b >= 64) {
312                         /* this is illegal re C standard */
313                         r->lo = 0;
314                         return;
315                 }
316                 r->lo = t >> (b-32);
317                 return;
318         }
319         if(b <= 0) {
320                 r->hi = t;
321                 r->lo = a.lo;
322                 return;
323         }
324         r->hi = t >> b;
325         r->lo = (t << (32-b)) | (a.lo >> b);
326 }
327
328 void
329 _lshv(Vlong *r, Vlong a, int b)
330 {
331         ulong t;
332
333         t = a.lo;
334         if(b >= 32) {
335                 r->lo = 0;
336                 if(b >= 64) {
337                         /* this is illegal re C standard */
338                         r->hi = 0;
339                         return;
340                 }
341                 r->hi = t << (b-32);
342                 return;
343         }
344         if(b <= 0) {
345                 r->lo = t;
346                 r->hi = a.hi;
347                 return;
348         }
349         r->lo = t << b;
350         r->hi = (t >> (32-b)) | (a.hi << b);
351 }
352
353 void
354 _andv(Vlong *r, Vlong a, Vlong b)
355 {
356         r->hi = a.hi & b.hi;
357         r->lo = a.lo & b.lo;
358 }
359
360 void
361 _orv(Vlong *r, Vlong a, Vlong b)
362 {
363         r->hi = a.hi | b.hi;
364         r->lo = a.lo | b.lo;
365 }
366
367 void
368 _xorv(Vlong *r, Vlong a, Vlong b)
369 {
370         r->hi = a.hi ^ b.hi;
371         r->lo = a.lo ^ b.lo;
372 }
373
374 void
375 _vpp(Vlong *l, Vlong *r)
376 {
377
378         l->hi = r->hi;
379         l->lo = r->lo;
380         r->lo++;
381         if(r->lo == 0)
382                 r->hi++;
383 }
384
385 void
386 _vmm(Vlong *l, Vlong *r)
387 {
388
389         l->hi = r->hi;
390         l->lo = r->lo;
391         if(r->lo == 0)
392                 r->hi--;
393         r->lo--;
394 }
395
396 void
397 _ppv(Vlong *l, Vlong *r)
398 {
399
400         r->lo++;
401         if(r->lo == 0)
402                 r->hi++;
403         l->hi = r->hi;
404         l->lo = r->lo;
405 }
406
407 void
408 _mmv(Vlong *l, Vlong *r)
409 {
410
411         if(r->lo == 0)
412                 r->hi--;
413         r->lo--;
414         l->hi = r->hi;
415         l->lo = r->lo;
416 }
417
418 void
419 _vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv)
420 {
421         Vlong t, u;
422
423         u = *ret;
424         switch(type) {
425         default:
426                 abort();
427                 break;
428
429         case 1: /* schar */
430                 t.lo = *(schar*)lv;
431                 t.hi = t.lo >> 31;
432                 fn(&u, t, rv);
433                 *(schar*)lv = u.lo;
434                 break;
435
436         case 2: /* uchar */
437                 t.lo = *(uchar*)lv;
438                 t.hi = 0;
439                 fn(&u, t, rv);
440                 *(uchar*)lv = u.lo;
441                 break;
442
443         case 3: /* short */
444                 t.lo = *(short*)lv;
445                 t.hi = t.lo >> 31;
446                 fn(&u, t, rv);
447                 *(short*)lv = u.lo;
448                 break;
449
450         case 4: /* ushort */
451                 t.lo = *(ushort*)lv;
452                 t.hi = 0;
453                 fn(&u, t, rv);
454                 *(ushort*)lv = u.lo;
455                 break;
456
457         case 9: /* int */
458                 t.lo = *(int*)lv;
459                 t.hi = t.lo >> 31;
460                 fn(&u, t, rv);
461                 *(int*)lv = u.lo;
462                 break;
463
464         case 10:        /* uint */
465                 t.lo = *(uint*)lv;
466                 t.hi = 0;
467                 fn(&u, t, rv);
468                 *(uint*)lv = u.lo;
469                 break;
470
471         case 5: /* long */
472                 t.lo = *(long*)lv;
473                 t.hi = t.lo >> 31;
474                 fn(&u, t, rv);
475                 *(long*)lv = u.lo;
476                 break;
477
478         case 6: /* ulong */
479                 t.lo = *(ulong*)lv;
480                 t.hi = 0;
481                 fn(&u, t, rv);
482                 *(ulong*)lv = u.lo;
483                 break;
484
485         case 7: /* vlong */
486         case 8: /* uvlong */
487                 fn(&u, *(Vlong*)lv, rv);
488                 *(Vlong*)lv = u;
489                 break;
490         }
491         *ret = u;
492 }
493
494 void
495 _p2v(Vlong *ret, void *p)
496 {
497         long t;
498
499         t = (ulong)p;
500         ret->lo = t;
501         ret->hi = 0;
502 }
503
504 void
505 _sl2v(Vlong *ret, long sl)
506 {
507         long t;
508
509         t = sl;
510         ret->lo = t;
511         ret->hi = t >> 31;
512 }
513
514
515 void
516 _ul2v(Vlong *ret, ulong ul)
517 {
518         long t;
519
520         t = ul;
521         ret->lo = t;
522         ret->hi = 0;
523 }
524
525 void
526 _si2v(Vlong *ret, int si)
527 {
528         long t;
529
530         t = si;
531         ret->lo = t;
532         ret->hi = t >> 31;
533 }
534
535 void
536 _ui2v(Vlong *ret, uint ui)
537 {
538         long t;
539
540         t = ui;
541         ret->lo = t;
542         ret->hi = 0;
543 }
544
545 void
546 _sh2v(Vlong *ret, long sh)
547 {
548         long t;
549
550         t = (sh << 16) >> 16;
551         ret->lo = t;
552         ret->hi = t >> 31;
553 }
554
555 void
556 _uh2v(Vlong *ret, ulong ul)
557 {
558         long t;
559
560         t = ul & 0xffff;
561         ret->lo = t;
562         ret->hi = 0;
563 }
564
565 void
566 _sc2v(Vlong *ret, long uc)
567 {
568         long t;
569
570         t = (uc << 24) >> 24;
571         ret->lo = t;
572         ret->hi = t >> 31;
573 }
574
575 void
576 _uc2v(Vlong *ret, ulong ul)
577 {
578         long t;
579
580         t = ul & 0xff;
581         ret->lo = t;
582         ret->hi = 0;
583 }
584
585 long
586 _v2sc(Vlong rv)
587 {
588         long t;
589
590         t = rv.lo & 0xff;
591         return (t << 24) >> 24;
592 }
593
594 long
595 _v2uc(Vlong rv)
596 {
597
598         return rv.lo & 0xff;
599 }
600
601 long
602 _v2sh(Vlong rv)
603 {
604         long t;
605
606         t = rv.lo & 0xffff;
607         return (t << 16) >> 16;
608 }
609
610 long
611 _v2uh(Vlong rv)
612 {
613
614         return rv.lo & 0xffff;
615 }
616
617 long
618 _v2sl(Vlong rv)
619 {
620
621         return rv.lo;
622 }
623
624 long
625 _v2ul(Vlong rv)
626 {
627
628         return rv.lo;
629 }
630
631 long
632 _v2si(Vlong rv)
633 {
634
635         return rv.lo;
636 }
637
638 long
639 _v2ui(Vlong rv)
640 {
641
642         return rv.lo;
643 }
644
645 int
646 _testv(Vlong rv)
647 {
648         return rv.lo || rv.hi;
649 }
650
651 int
652 _eqv(Vlong lv, Vlong rv)
653 {
654         return lv.lo == rv.lo && lv.hi == rv.hi;
655 }
656
657 int
658 _nev(Vlong lv, Vlong rv)
659 {
660         return lv.lo != rv.lo || lv.hi != rv.hi;
661 }
662
663 int
664 _ltv(Vlong lv, Vlong rv)
665 {
666         return (long)lv.hi < (long)rv.hi ||
667                 (lv.hi == rv.hi && lv.lo < rv.lo);
668 }
669
670 int
671 _lev(Vlong lv, Vlong rv)
672 {
673         return (long)lv.hi < (long)rv.hi ||
674                 (lv.hi == rv.hi && lv.lo <= rv.lo);
675 }
676
677 int
678 _gtv(Vlong lv, Vlong rv)
679 {
680         return (long)lv.hi > (long)rv.hi ||
681                 (lv.hi == rv.hi && lv.lo > rv.lo);
682 }
683
684 int
685 _gev(Vlong lv, Vlong rv)
686 {
687         return (long)lv.hi > (long)rv.hi ||
688                 (lv.hi == rv.hi && lv.lo >= rv.lo);
689 }
690
691 int
692 _lov(Vlong lv, Vlong rv)
693 {
694         return lv.hi < rv.hi ||
695                 (lv.hi == rv.hi && lv.lo < rv.lo);
696 }
697
698 int
699 _lsv(Vlong lv, Vlong rv)
700 {
701         return lv.hi < rv.hi ||
702                 (lv.hi == rv.hi && lv.lo <= rv.lo);
703 }
704
705 int
706 _hiv(Vlong lv, Vlong rv)
707 {
708         return lv.hi > rv.hi ||
709                 (lv.hi == rv.hi && lv.lo > rv.lo);
710 }
711
712 int
713 _hsv(Vlong lv, Vlong rv)
714 {
715         return lv.hi > rv.hi ||
716                 (lv.hi == rv.hi && lv.lo >= rv.lo);
717 }