github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/runtime/vlrt_arm.c (about) 1 // Inferno's libkern/vlrt-arm.c 2 // http://code.google.com/p/inferno-os/source/browse/libkern/vlrt-arm.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved. 6 // Portions Copyright 2009 The Go Authors. All rights reserved. 7 // 8 // Permission is hereby granted, free of charge, to any person obtaining a copy 9 // of this software and associated documentation files (the "Software"), to deal 10 // in the Software without restriction, including without limitation the rights 11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 // copies of the Software, and to permit persons to whom the Software is 13 // furnished to do so, subject to the following conditions: 14 // 15 // The above copyright notice and this permission notice shall be included in 16 // all copies or substantial portions of the Software. 17 // 18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 // THE SOFTWARE. 25 26 #include "../../cmd/ld/textflag.h" 27 28 // declared here to avoid include of runtime.h 29 void runtime·panicstring(char*); 30 31 typedef unsigned long ulong; 32 typedef unsigned int uint; 33 typedef unsigned short ushort; 34 typedef unsigned char uchar; 35 typedef signed char schar; 36 37 #define SIGN(n) (1UL<<(n-1)) 38 39 void 40 runtime·panicdivide(void) 41 { 42 runtime·panicstring("integer divide by zero"); 43 } 44 45 typedef struct Vlong Vlong; 46 struct Vlong 47 { 48 union 49 { 50 struct 51 { 52 ulong lo; 53 ulong hi; 54 }; 55 struct 56 { 57 ushort lols; 58 ushort loms; 59 ushort hils; 60 ushort hims; 61 }; 62 }; 63 }; 64 65 void runtime·abort(void); 66 67 #pragma textflag NOSPLIT 68 void 69 _addv(Vlong *r, Vlong a, Vlong b) 70 { 71 r->lo = a.lo + b.lo; 72 r->hi = a.hi + b.hi; 73 if(r->lo < a.lo) 74 r->hi++; 75 } 76 77 #pragma textflag NOSPLIT 78 void 79 _subv(Vlong *r, Vlong a, Vlong b) 80 { 81 r->lo = a.lo - b.lo; 82 r->hi = a.hi - b.hi; 83 if(r->lo > a.lo) 84 r->hi--; 85 } 86 87 void 88 _d2v(Vlong *y, double d) 89 { 90 union { double d; struct Vlong; } x; 91 ulong xhi, xlo, ylo, yhi; 92 int sh; 93 94 x.d = d; 95 96 xhi = (x.hi & 0xfffff) | 0x100000; 97 xlo = x.lo; 98 sh = 1075 - ((x.hi >> 20) & 0x7ff); 99 100 ylo = 0; 101 yhi = 0; 102 if(sh >= 0) { 103 /* v = (hi||lo) >> sh */ 104 if(sh < 32) { 105 if(sh == 0) { 106 ylo = xlo; 107 yhi = xhi; 108 } else { 109 ylo = (xlo >> sh) | (xhi << (32-sh)); 110 yhi = xhi >> sh; 111 } 112 } else { 113 if(sh == 32) { 114 ylo = xhi; 115 } else 116 if(sh < 64) { 117 ylo = xhi >> (sh-32); 118 } 119 } 120 } else { 121 /* v = (hi||lo) << -sh */ 122 sh = -sh; 123 if(sh <= 11) { 124 ylo = xlo << sh; 125 yhi = (xhi << sh) | (xlo >> (32-sh)); 126 } else { 127 /* overflow */ 128 yhi = d; /* causes something awful */ 129 } 130 } 131 if(x.hi & SIGN(32)) { 132 if(ylo != 0) { 133 ylo = -ylo; 134 yhi = ~yhi; 135 } else 136 yhi = -yhi; 137 } 138 139 y->hi = yhi; 140 y->lo = ylo; 141 } 142 143 void 144 _f2v(Vlong *y, float f) 145 { 146 _d2v(y, f); 147 } 148 149 void 150 runtime·float64toint64(double d, Vlong y) 151 { 152 _d2v(&y, d); 153 } 154 155 void 156 runtime·float64touint64(double d, Vlong y) 157 { 158 _d2v(&y, d); 159 } 160 161 double 162 _ul2d(ulong u) 163 { 164 // compensate for bug in c 165 if(u & SIGN(32)) { 166 u ^= SIGN(32); 167 return 2147483648. + u; 168 } 169 return u; 170 } 171 172 double 173 _v2d(Vlong x) 174 { 175 if(x.hi & SIGN(32)) { 176 if(x.lo) { 177 x.lo = -x.lo; 178 x.hi = ~x.hi; 179 } else 180 x.hi = -x.hi; 181 return -(_ul2d(x.hi)*4294967296. + _ul2d(x.lo)); 182 } 183 return x.hi*4294967296. + _ul2d(x.lo); 184 } 185 186 float 187 _v2f(Vlong x) 188 { 189 return _v2d(x); 190 } 191 192 void 193 runtime·int64tofloat64(Vlong y, double d) 194 { 195 d = _v2d(y); 196 USED(&d); // FLUSH 197 } 198 199 void 200 runtime·uint64tofloat64(Vlong y, double d) 201 { 202 d = _ul2d(y.hi)*4294967296. + _ul2d(y.lo); 203 USED(&d); // FLUSH 204 } 205 206 static void 207 dodiv(Vlong num, Vlong den, Vlong *q, Vlong *r) 208 { 209 ulong numlo, numhi, denhi, denlo, quohi, quolo, t; 210 int i; 211 212 numhi = num.hi; 213 numlo = num.lo; 214 denhi = den.hi; 215 denlo = den.lo; 216 217 /* 218 * get a divide by zero 219 */ 220 if(denlo==0 && denhi==0) { 221 runtime·panicdivide(); 222 } 223 224 /* 225 * set up the divisor and find the number of iterations needed 226 */ 227 if(numhi >= SIGN(32)) { 228 quohi = SIGN(32); 229 quolo = 0; 230 } else { 231 quohi = numhi; 232 quolo = numlo; 233 } 234 i = 0; 235 while(denhi < quohi || (denhi == quohi && denlo < quolo)) { 236 denhi = (denhi<<1) | (denlo>>31); 237 denlo <<= 1; 238 i++; 239 } 240 241 quohi = 0; 242 quolo = 0; 243 for(; i >= 0; i--) { 244 quohi = (quohi<<1) | (quolo>>31); 245 quolo <<= 1; 246 if(numhi > denhi || (numhi == denhi && numlo >= denlo)) { 247 t = numlo; 248 numlo -= denlo; 249 if(numlo > t) 250 numhi--; 251 numhi -= denhi; 252 quolo |= 1; 253 } 254 denlo = (denlo>>1) | (denhi<<31); 255 denhi >>= 1; 256 } 257 258 if(q) { 259 q->lo = quolo; 260 q->hi = quohi; 261 } 262 if(r) { 263 r->lo = numlo; 264 r->hi = numhi; 265 } 266 } 267 268 void 269 _divvu(Vlong *q, Vlong n, Vlong d) 270 { 271 272 if(n.hi == 0 && d.hi == 0) { 273 q->hi = 0; 274 q->lo = n.lo / d.lo; 275 return; 276 } 277 dodiv(n, d, q, 0); 278 } 279 280 void 281 runtime·uint64div(Vlong n, Vlong d, Vlong q) 282 { 283 _divvu(&q, n, d); 284 } 285 286 void 287 _modvu(Vlong *r, Vlong n, Vlong d) 288 { 289 290 if(n.hi == 0 && d.hi == 0) { 291 r->hi = 0; 292 r->lo = n.lo % d.lo; 293 return; 294 } 295 dodiv(n, d, 0, r); 296 } 297 298 void 299 runtime·uint64mod(Vlong n, Vlong d, Vlong q) 300 { 301 _modvu(&q, n, d); 302 } 303 304 static void 305 vneg(Vlong *v) 306 { 307 308 if(v->lo == 0) { 309 v->hi = -v->hi; 310 return; 311 } 312 v->lo = -v->lo; 313 v->hi = ~v->hi; 314 } 315 316 void 317 _divv(Vlong *q, Vlong n, Vlong d) 318 { 319 long nneg, dneg; 320 321 if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) { 322 if((long)n.lo == -0x80000000 && (long)d.lo == -1) { 323 // special case: 32-bit -0x80000000 / -1 causes wrong sign 324 q->lo = 0x80000000; 325 q->hi = 0; 326 return; 327 } 328 q->lo = (long)n.lo / (long)d.lo; 329 q->hi = ((long)q->lo) >> 31; 330 return; 331 } 332 nneg = n.hi >> 31; 333 if(nneg) 334 vneg(&n); 335 dneg = d.hi >> 31; 336 if(dneg) 337 vneg(&d); 338 dodiv(n, d, q, 0); 339 if(nneg != dneg) 340 vneg(q); 341 } 342 343 void 344 runtime·int64div(Vlong n, Vlong d, Vlong q) 345 { 346 _divv(&q, n, d); 347 } 348 349 void 350 _modv(Vlong *r, Vlong n, Vlong d) 351 { 352 long nneg, dneg; 353 354 if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) { 355 r->lo = (long)n.lo % (long)d.lo; 356 r->hi = ((long)r->lo) >> 31; 357 return; 358 } 359 nneg = n.hi >> 31; 360 if(nneg) 361 vneg(&n); 362 dneg = d.hi >> 31; 363 if(dneg) 364 vneg(&d); 365 dodiv(n, d, 0, r); 366 if(nneg) 367 vneg(r); 368 } 369 370 void 371 runtime·int64mod(Vlong n, Vlong d, Vlong q) 372 { 373 _modv(&q, n, d); 374 } 375 376 void 377 _rshav(Vlong *r, Vlong a, int b) 378 { 379 long t; 380 381 t = a.hi; 382 if(b >= 32) { 383 r->hi = t>>31; 384 if(b >= 64) { 385 /* this is illegal re C standard */ 386 r->lo = t>>31; 387 return; 388 } 389 r->lo = t >> (b-32); 390 return; 391 } 392 if(b <= 0) { 393 r->hi = t; 394 r->lo = a.lo; 395 return; 396 } 397 r->hi = t >> b; 398 r->lo = (t << (32-b)) | (a.lo >> b); 399 } 400 401 void 402 _rshlv(Vlong *r, Vlong a, int b) 403 { 404 ulong t; 405 406 t = a.hi; 407 if(b >= 32) { 408 r->hi = 0; 409 if(b >= 64) { 410 /* this is illegal re C standard */ 411 r->lo = 0; 412 return; 413 } 414 r->lo = t >> (b-32); 415 return; 416 } 417 if(b <= 0) { 418 r->hi = t; 419 r->lo = a.lo; 420 return; 421 } 422 r->hi = t >> b; 423 r->lo = (t << (32-b)) | (a.lo >> b); 424 } 425 426 #pragma textflag NOSPLIT 427 void 428 _lshv(Vlong *r, Vlong a, int b) 429 { 430 if(b >= 32) { 431 r->lo = 0; 432 if(b >= 64) { 433 /* this is illegal re C standard */ 434 r->hi = 0; 435 return; 436 } 437 r->hi = a.lo << (b-32); 438 return; 439 } 440 if(b <= 0) { 441 r->lo = a.lo; 442 r->hi = a.hi; 443 return; 444 } 445 r->lo = a.lo << b; 446 r->hi = (a.lo >> (32-b)) | (a.hi << b); 447 } 448 449 void 450 _andv(Vlong *r, Vlong a, Vlong b) 451 { 452 r->hi = a.hi & b.hi; 453 r->lo = a.lo & b.lo; 454 } 455 456 void 457 _orv(Vlong *r, Vlong a, Vlong b) 458 { 459 r->hi = a.hi | b.hi; 460 r->lo = a.lo | b.lo; 461 } 462 463 void 464 _xorv(Vlong *r, Vlong a, Vlong b) 465 { 466 r->hi = a.hi ^ b.hi; 467 r->lo = a.lo ^ b.lo; 468 } 469 470 void 471 _vpp(Vlong *l, Vlong *r) 472 { 473 474 l->hi = r->hi; 475 l->lo = r->lo; 476 r->lo++; 477 if(r->lo == 0) 478 r->hi++; 479 } 480 481 void 482 _vmm(Vlong *l, Vlong *r) 483 { 484 485 l->hi = r->hi; 486 l->lo = r->lo; 487 if(r->lo == 0) 488 r->hi--; 489 r->lo--; 490 } 491 492 void 493 _ppv(Vlong *l, Vlong *r) 494 { 495 496 r->lo++; 497 if(r->lo == 0) 498 r->hi++; 499 l->hi = r->hi; 500 l->lo = r->lo; 501 } 502 503 void 504 _mmv(Vlong *l, Vlong *r) 505 { 506 507 if(r->lo == 0) 508 r->hi--; 509 r->lo--; 510 l->hi = r->hi; 511 l->lo = r->lo; 512 } 513 514 void 515 _vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv) 516 { 517 Vlong t, u; 518 519 u = *ret; 520 switch(type) { 521 default: 522 runtime·abort(); 523 break; 524 525 case 1: /* schar */ 526 t.lo = *(schar*)lv; 527 t.hi = t.lo >> 31; 528 fn(&u, t, rv); 529 *(schar*)lv = u.lo; 530 break; 531 532 case 2: /* uchar */ 533 t.lo = *(uchar*)lv; 534 t.hi = 0; 535 fn(&u, t, rv); 536 *(uchar*)lv = u.lo; 537 break; 538 539 case 3: /* short */ 540 t.lo = *(short*)lv; 541 t.hi = t.lo >> 31; 542 fn(&u, t, rv); 543 *(short*)lv = u.lo; 544 break; 545 546 case 4: /* ushort */ 547 t.lo = *(ushort*)lv; 548 t.hi = 0; 549 fn(&u, t, rv); 550 *(ushort*)lv = u.lo; 551 break; 552 553 case 9: /* int */ 554 t.lo = *(int*)lv; 555 t.hi = t.lo >> 31; 556 fn(&u, t, rv); 557 *(int*)lv = u.lo; 558 break; 559 560 case 10: /* uint */ 561 t.lo = *(uint*)lv; 562 t.hi = 0; 563 fn(&u, t, rv); 564 *(uint*)lv = u.lo; 565 break; 566 567 case 5: /* long */ 568 t.lo = *(long*)lv; 569 t.hi = t.lo >> 31; 570 fn(&u, t, rv); 571 *(long*)lv = u.lo; 572 break; 573 574 case 6: /* ulong */ 575 t.lo = *(ulong*)lv; 576 t.hi = 0; 577 fn(&u, t, rv); 578 *(ulong*)lv = u.lo; 579 break; 580 581 case 7: /* vlong */ 582 case 8: /* uvlong */ 583 fn(&u, *(Vlong*)lv, rv); 584 *(Vlong*)lv = u; 585 break; 586 } 587 *ret = u; 588 } 589 590 void 591 _p2v(Vlong *ret, void *p) 592 { 593 long t; 594 595 t = (ulong)p; 596 ret->lo = t; 597 ret->hi = 0; 598 } 599 600 void 601 _sl2v(Vlong *ret, long sl) 602 { 603 long t; 604 605 t = sl; 606 ret->lo = t; 607 ret->hi = t >> 31; 608 } 609 610 void 611 _ul2v(Vlong *ret, ulong ul) 612 { 613 long t; 614 615 t = ul; 616 ret->lo = t; 617 ret->hi = 0; 618 } 619 620 #pragma textflag NOSPLIT 621 void 622 _si2v(Vlong *ret, int si) 623 { 624 ret->lo = (long)si; 625 ret->hi = (long)si >> 31; 626 } 627 628 void 629 _ui2v(Vlong *ret, uint ui) 630 { 631 long t; 632 633 t = ui; 634 ret->lo = t; 635 ret->hi = 0; 636 } 637 638 void 639 _sh2v(Vlong *ret, long sh) 640 { 641 long t; 642 643 t = (sh << 16) >> 16; 644 ret->lo = t; 645 ret->hi = t >> 31; 646 } 647 648 void 649 _uh2v(Vlong *ret, ulong ul) 650 { 651 long t; 652 653 t = ul & 0xffff; 654 ret->lo = t; 655 ret->hi = 0; 656 } 657 658 void 659 _sc2v(Vlong *ret, long uc) 660 { 661 long t; 662 663 t = (uc << 24) >> 24; 664 ret->lo = t; 665 ret->hi = t >> 31; 666 } 667 668 void 669 _uc2v(Vlong *ret, ulong ul) 670 { 671 long t; 672 673 t = ul & 0xff; 674 ret->lo = t; 675 ret->hi = 0; 676 } 677 678 long 679 _v2sc(Vlong rv) 680 { 681 long t; 682 683 t = rv.lo & 0xff; 684 return (t << 24) >> 24; 685 } 686 687 long 688 _v2uc(Vlong rv) 689 { 690 691 return rv.lo & 0xff; 692 } 693 694 long 695 _v2sh(Vlong rv) 696 { 697 long t; 698 699 t = rv.lo & 0xffff; 700 return (t << 16) >> 16; 701 } 702 703 long 704 _v2uh(Vlong rv) 705 { 706 707 return rv.lo & 0xffff; 708 } 709 710 long 711 _v2sl(Vlong rv) 712 { 713 714 return rv.lo; 715 } 716 717 long 718 _v2ul(Vlong rv) 719 { 720 721 return rv.lo; 722 } 723 724 #pragma textflag NOSPLIT 725 long 726 _v2si(Vlong rv) 727 { 728 729 return rv.lo; 730 } 731 732 long 733 _v2ui(Vlong rv) 734 { 735 736 return rv.lo; 737 } 738 739 int 740 _testv(Vlong rv) 741 { 742 return rv.lo || rv.hi; 743 } 744 745 int 746 _eqv(Vlong lv, Vlong rv) 747 { 748 return lv.lo == rv.lo && lv.hi == rv.hi; 749 } 750 751 int 752 _nev(Vlong lv, Vlong rv) 753 { 754 return lv.lo != rv.lo || lv.hi != rv.hi; 755 } 756 757 int 758 _ltv(Vlong lv, Vlong rv) 759 { 760 return (long)lv.hi < (long)rv.hi || 761 (lv.hi == rv.hi && lv.lo < rv.lo); 762 } 763 764 int 765 _lev(Vlong lv, Vlong rv) 766 { 767 return (long)lv.hi < (long)rv.hi || 768 (lv.hi == rv.hi && lv.lo <= rv.lo); 769 } 770 771 int 772 _gtv(Vlong lv, Vlong rv) 773 { 774 return (long)lv.hi > (long)rv.hi || 775 (lv.hi == rv.hi && lv.lo > rv.lo); 776 } 777 778 #pragma textflag NOSPLIT 779 int 780 _gev(Vlong lv, Vlong rv) 781 { 782 return (long)lv.hi > (long)rv.hi || 783 (lv.hi == rv.hi && lv.lo >= rv.lo); 784 } 785 786 int 787 _lov(Vlong lv, Vlong rv) 788 { 789 return lv.hi < rv.hi || 790 (lv.hi == rv.hi && lv.lo < rv.lo); 791 } 792 793 int 794 _lsv(Vlong lv, Vlong rv) 795 { 796 return lv.hi < rv.hi || 797 (lv.hi == rv.hi && lv.lo <= rv.lo); 798 } 799 800 int 801 _hiv(Vlong lv, Vlong rv) 802 { 803 return lv.hi > rv.hi || 804 (lv.hi == rv.hi && lv.lo > rv.lo); 805 } 806 807 int 808 _hsv(Vlong lv, Vlong rv) 809 { 810 return lv.hi > rv.hi || 811 (lv.hi == rv.hi && lv.lo >= rv.lo); 812 }