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