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