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