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