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