github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/5c/txt.c (about) 1 // Inferno utils/5c/txt.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/5c/txt.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 32 #include "gc.h" 33 34 void 35 ginit(void) 36 { 37 Type *t; 38 39 thechar = '5'; 40 thestring = "arm"; 41 exregoffset = REGEXT; 42 exfregoffset = FREGEXT; 43 listinit(); 44 nstring = 0; 45 mnstring = 0; 46 nrathole = 0; 47 pc = 0; 48 breakpc = -1; 49 continpc = -1; 50 cases = C; 51 firstp = P; 52 lastp = P; 53 tfield = types[TLONG]; 54 55 zprog.link = P; 56 zprog.as = AGOK; 57 zprog.reg = NREG; 58 zprog.from.type = D_NONE; 59 zprog.from.name = D_NONE; 60 zprog.from.reg = NREG; 61 zprog.to = zprog.from; 62 zprog.scond = 0xE; 63 64 regnode.op = OREGISTER; 65 regnode.class = CEXREG; 66 regnode.reg = REGTMP; 67 regnode.complex = 0; 68 regnode.addable = 11; 69 regnode.type = types[TLONG]; 70 71 constnode.op = OCONST; 72 constnode.class = CXXX; 73 constnode.complex = 0; 74 constnode.addable = 20; 75 constnode.type = types[TLONG]; 76 77 fconstnode.op = OCONST; 78 fconstnode.class = CXXX; 79 fconstnode.complex = 0; 80 fconstnode.addable = 20; 81 fconstnode.type = types[TDOUBLE]; 82 83 nodsafe = new(ONAME, Z, Z); 84 nodsafe->sym = slookup(".safe"); 85 nodsafe->type = types[TINT]; 86 nodsafe->etype = types[TINT]->etype; 87 nodsafe->class = CAUTO; 88 complex(nodsafe); 89 90 t = typ(TARRAY, types[TCHAR]); 91 symrathole = slookup(".rathole"); 92 symrathole->class = CGLOBL; 93 symrathole->type = t; 94 95 nodrat = new(ONAME, Z, Z); 96 nodrat->sym = symrathole; 97 nodrat->type = types[TIND]; 98 nodrat->etype = TVOID; 99 nodrat->class = CGLOBL; 100 complex(nodrat); 101 nodrat->type = t; 102 103 nodret = new(ONAME, Z, Z); 104 nodret->sym = slookup(".ret"); 105 nodret->type = types[TIND]; 106 nodret->etype = TIND; 107 nodret->class = CPARAM; 108 nodret = new(OIND, nodret, Z); 109 complex(nodret); 110 111 com64init(); 112 113 memset(reg, 0, sizeof(reg)); 114 } 115 116 void 117 gclean(void) 118 { 119 int i; 120 Sym *s; 121 122 for(i=0; i<NREG; i++) 123 if(reg[i]) 124 diag(Z, "reg %d left allocated", i); 125 for(i=NREG; i<NREG+NFREG; i++) 126 if(reg[i]) 127 diag(Z, "freg %d left allocated", i-NREG); 128 while(mnstring) 129 outstring("", 1L); 130 symstring->type->width = nstring; 131 symrathole->type->width = nrathole; 132 for(i=0; i<NHASH; i++) 133 for(s = hash[i]; s != S; s = s->link) { 134 if(s->type == T) 135 continue; 136 if(s->type->width == 0) 137 continue; 138 if(s->class != CGLOBL && s->class != CSTATIC) 139 continue; 140 if(s->type == types[TENUM]) 141 continue; 142 gpseudo(AGLOBL, s, nodconst(s->type->width)); 143 } 144 nextpc(); 145 p->as = AEND; 146 outcode(); 147 } 148 149 void 150 nextpc(void) 151 { 152 153 p = alloc(sizeof(*p)); 154 *p = zprog; 155 p->lineno = nearln; 156 pc++; 157 if(firstp == P) { 158 firstp = p; 159 lastp = p; 160 return; 161 } 162 lastp->link = p; 163 lastp = p; 164 } 165 166 void 167 gargs(Node *n, Node *tn1, Node *tn2) 168 { 169 int32 regs; 170 Node fnxargs[20], *fnxp; 171 172 regs = cursafe; 173 174 fnxp = fnxargs; 175 garg1(n, tn1, tn2, 0, &fnxp); /* compile fns to temps */ 176 177 curarg = 0; 178 fnxp = fnxargs; 179 garg1(n, tn1, tn2, 1, &fnxp); /* compile normal args and temps */ 180 181 cursafe = regs; 182 } 183 184 void 185 garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp) 186 { 187 Node nod; 188 189 if(n == Z) 190 return; 191 if(n->op == OLIST) { 192 garg1(n->left, tn1, tn2, f, fnxp); 193 garg1(n->right, tn1, tn2, f, fnxp); 194 return; 195 } 196 if(f == 0) { 197 if(n->complex >= FNX) { 198 regsalloc(*fnxp, n); 199 nod = znode; 200 nod.op = OAS; 201 nod.left = *fnxp; 202 nod.right = n; 203 nod.type = n->type; 204 cgen(&nod, Z); 205 (*fnxp)++; 206 } 207 return; 208 } 209 if(typesuv[n->type->etype]) { 210 regaalloc(tn2, n); 211 if(n->complex >= FNX) { 212 sugen(*fnxp, tn2, n->type->width); 213 (*fnxp)++; 214 } else 215 sugen(n, tn2, n->type->width); 216 return; 217 } 218 if(REGARG >= 0 && curarg == 0 && typechlp[n->type->etype]) { 219 regaalloc1(tn1, n); 220 if(n->complex >= FNX) { 221 cgen(*fnxp, tn1); 222 (*fnxp)++; 223 } else 224 cgen(n, tn1); 225 return; 226 } 227 regalloc(tn1, n, Z); 228 if(n->complex >= FNX) { 229 cgen(*fnxp, tn1); 230 (*fnxp)++; 231 } else 232 cgen(n, tn1); 233 regaalloc(tn2, n); 234 gopcode(OAS, tn1, Z, tn2); 235 regfree(tn1); 236 } 237 238 Node* 239 nodconst(int32 v) 240 { 241 constnode.vconst = v; 242 return &constnode; 243 } 244 245 Node* 246 nod32const(vlong v) 247 { 248 constnode.vconst = v & MASK(32); 249 return &constnode; 250 } 251 252 Node* 253 nodfconst(double d) 254 { 255 fconstnode.fconst = d; 256 return &fconstnode; 257 } 258 259 void 260 nodreg(Node *n, Node *nn, int reg) 261 { 262 *n = regnode; 263 n->reg = reg; 264 n->type = nn->type; 265 n->lineno = nn->lineno; 266 } 267 268 void 269 regret(Node *n, Node *nn) 270 { 271 int r; 272 273 r = REGRET; 274 if(typefd[nn->type->etype]) 275 r = FREGRET+NREG; 276 nodreg(n, nn, r); 277 reg[r]++; 278 } 279 280 int 281 tmpreg(void) 282 { 283 int i; 284 285 for(i=REGRET+1; i<NREG; i++) 286 if(reg[i] == 0) 287 return i; 288 diag(Z, "out of fixed registers"); 289 return 0; 290 } 291 292 void 293 regalloc(Node *n, Node *tn, Node *o) 294 { 295 int i; 296 297 switch(tn->type->etype) { 298 case TCHAR: 299 case TUCHAR: 300 case TSHORT: 301 case TUSHORT: 302 case TINT: 303 case TUINT: 304 case TLONG: 305 case TULONG: 306 case TIND: 307 if(o != Z && o->op == OREGISTER) { 308 i = o->reg; 309 if(i >= 0 && i < NREG) 310 goto out; 311 } 312 for(i=REGRET+1; i<=REGEXT-2; i++) 313 if(reg[i] == 0) 314 goto out; 315 diag(tn, "out of fixed registers"); 316 goto err; 317 318 case TFLOAT: 319 case TDOUBLE: 320 case TVLONG: 321 if(o != Z && o->op == OREGISTER) { 322 i = o->reg; 323 if(i >= NREG && i < NREG+NFREG) 324 goto out; 325 } 326 for(i=NREG; i<NREG+NFREG; i++) 327 if(reg[i] == 0) 328 goto out; 329 diag(tn, "out of float registers"); 330 goto err; 331 } 332 diag(tn, "unknown type in regalloc: %T", tn->type); 333 err: 334 nodreg(n, tn, 0); 335 return; 336 out: 337 reg[i]++; 338 nodreg(n, tn, i); 339 } 340 341 void 342 regialloc(Node *n, Node *tn, Node *o) 343 { 344 Node nod; 345 346 nod = *tn; 347 nod.type = types[TIND]; 348 regalloc(n, &nod, o); 349 } 350 351 void 352 regfree(Node *n) 353 { 354 int i; 355 356 i = 0; 357 if(n->op != OREGISTER && n->op != OINDREG) 358 goto err; 359 i = n->reg; 360 if(i < 0 || i >= nelem(reg)) 361 goto err; 362 if(reg[i] <= 0) 363 goto err; 364 reg[i]--; 365 return; 366 err: 367 diag(n, "error in regfree: %d", i); 368 } 369 370 void 371 regsalloc(Node *n, Node *nn) 372 { 373 cursafe = align(cursafe, nn->type, Aaut3, nil); 374 maxargsafe = maxround(maxargsafe, cursafe+curarg); 375 *n = *nodsafe; 376 n->xoffset = -(stkoff + cursafe); 377 n->type = nn->type; 378 n->etype = nn->type->etype; 379 n->lineno = nn->lineno; 380 } 381 382 void 383 regaalloc1(Node *n, Node *nn) 384 { 385 if(REGARG < 0) { 386 fatal(n, "regaalloc1 and REGARG<0"); 387 return; 388 } 389 nodreg(n, nn, REGARG); 390 reg[REGARG]++; 391 curarg = align(curarg, nn->type, Aarg1, nil); 392 curarg = align(curarg, nn->type, Aarg2, nil); 393 maxargsafe = maxround(maxargsafe, cursafe+curarg); 394 } 395 396 void 397 regaalloc(Node *n, Node *nn) 398 { 399 curarg = align(curarg, nn->type, Aarg1, nil); 400 *n = *nn; 401 n->op = OINDREG; 402 n->reg = REGSP; 403 n->xoffset = curarg + SZ_LONG; 404 n->complex = 0; 405 n->addable = 20; 406 curarg = align(curarg, nn->type, Aarg2, nil); 407 maxargsafe = maxround(maxargsafe, cursafe+curarg); 408 } 409 410 void 411 regind(Node *n, Node *nn) 412 { 413 414 if(n->op != OREGISTER) { 415 diag(n, "regind not OREGISTER"); 416 return; 417 } 418 n->op = OINDREG; 419 n->type = nn->type; 420 } 421 422 void 423 raddr(Node *n, Prog *p) 424 { 425 Adr a; 426 427 naddr(n, &a); 428 if(R0ISZERO && a.type == D_CONST && a.offset == 0) { 429 a.type = D_REG; 430 a.reg = 0; 431 } 432 if(a.type != D_REG && a.type != D_FREG) { 433 if(n) 434 diag(n, "bad in raddr: %O", n->op); 435 else 436 diag(n, "bad in raddr: <null>"); 437 p->reg = NREG; 438 } else 439 p->reg = a.reg; 440 } 441 442 void 443 naddr(Node *n, Adr *a) 444 { 445 int32 v; 446 447 a->type = D_NONE; 448 if(n == Z) 449 return; 450 switch(n->op) { 451 default: 452 bad: 453 diag(n, "bad in naddr: %O", n->op); 454 break; 455 456 case OREGISTER: 457 a->type = D_REG; 458 a->sym = S; 459 a->reg = n->reg; 460 if(a->reg >= NREG) { 461 a->type = D_FREG; 462 a->reg -= NREG; 463 } 464 break; 465 466 case OIND: 467 naddr(n->left, a); 468 if(a->type == D_REG) { 469 a->type = D_OREG; 470 break; 471 } 472 if(a->type == D_CONST) { 473 a->type = D_OREG; 474 break; 475 } 476 goto bad; 477 478 case OINDREG: 479 a->type = D_OREG; 480 a->sym = S; 481 a->offset = n->xoffset; 482 a->reg = n->reg; 483 break; 484 485 case ONAME: 486 a->etype = n->etype; 487 a->type = D_OREG; 488 a->name = D_STATIC; 489 a->sym = n->sym; 490 a->offset = n->xoffset; 491 if(n->class == CSTATIC) 492 break; 493 if(n->class == CEXTERN || n->class == CGLOBL) { 494 a->name = D_EXTERN; 495 break; 496 } 497 if(n->class == CAUTO) { 498 a->name = D_AUTO; 499 break; 500 } 501 if(n->class == CPARAM) { 502 a->name = D_PARAM; 503 break; 504 } 505 goto bad; 506 507 case OCONST: 508 a->sym = S; 509 a->reg = NREG; 510 if(typefd[n->type->etype]) { 511 a->type = D_FCONST; 512 a->dval = n->fconst; 513 } else { 514 a->type = D_CONST; 515 a->offset = n->vconst; 516 } 517 break; 518 519 case OADDR: 520 naddr(n->left, a); 521 if(a->type == D_OREG) { 522 a->type = D_CONST; 523 break; 524 } 525 goto bad; 526 527 case OADD: 528 if(n->left->op == OCONST) { 529 naddr(n->left, a); 530 v = a->offset; 531 naddr(n->right, a); 532 } else { 533 naddr(n->right, a); 534 v = a->offset; 535 naddr(n->left, a); 536 } 537 a->offset += v; 538 break; 539 540 } 541 } 542 543 void 544 fop(int as, int f1, int f2, Node *t) 545 { 546 Node nod1, nod2, nod3; 547 548 nodreg(&nod1, t, NREG+f1); 549 nodreg(&nod2, t, NREG+f2); 550 regalloc(&nod3, t, t); 551 gopcode(as, &nod1, &nod2, &nod3); 552 gmove(&nod3, t); 553 regfree(&nod3); 554 } 555 556 void 557 gmovm(Node *f, Node *t, int w) 558 { 559 gins(AMOVM, f, t); 560 p->scond |= C_UBIT; 561 if(w) 562 p->scond |= C_WBIT; 563 } 564 565 void 566 gmove(Node *f, Node *t) 567 { 568 int ft, tt, a; 569 Node nod, nod1; 570 Prog *p1; 571 572 ft = f->type->etype; 573 tt = t->type->etype; 574 575 if(ft == TDOUBLE && f->op == OCONST) { 576 } 577 if(ft == TFLOAT && f->op == OCONST) { 578 } 579 580 /* 581 * a load -- 582 * put it into a register then 583 * worry what to do with it. 584 */ 585 if(f->op == ONAME || f->op == OINDREG || f->op == OIND) { 586 switch(ft) { 587 default: 588 a = AMOVW; 589 break; 590 case TFLOAT: 591 a = AMOVF; 592 break; 593 case TDOUBLE: 594 a = AMOVD; 595 break; 596 case TCHAR: 597 a = AMOVBS; 598 break; 599 case TUCHAR: 600 a = AMOVBU; 601 break; 602 case TSHORT: 603 a = AMOVHS; 604 break; 605 case TUSHORT: 606 a = AMOVHU; 607 break; 608 } 609 if(typechlp[ft] && typeilp[tt]) 610 regalloc(&nod, t, t); 611 else 612 regalloc(&nod, f, t); 613 gins(a, f, &nod); 614 gmove(&nod, t); 615 regfree(&nod); 616 return; 617 } 618 619 /* 620 * a store -- 621 * put it into a register then 622 * store it. 623 */ 624 if(t->op == ONAME || t->op == OINDREG || t->op == OIND) { 625 switch(tt) { 626 default: 627 a = AMOVW; 628 break; 629 case TUCHAR: 630 a = AMOVBU; 631 break; 632 case TCHAR: 633 a = AMOVBS; 634 break; 635 case TUSHORT: 636 a = AMOVHU; 637 break; 638 case TSHORT: 639 a = AMOVHS; 640 break; 641 case TFLOAT: 642 a = AMOVF; 643 break; 644 case TVLONG: 645 case TDOUBLE: 646 a = AMOVD; 647 break; 648 } 649 if(ft == tt) 650 regalloc(&nod, t, f); 651 else 652 regalloc(&nod, t, Z); 653 gmove(f, &nod); 654 gins(a, &nod, t); 655 regfree(&nod); 656 return; 657 } 658 659 /* 660 * type x type cross table 661 */ 662 a = AGOK; 663 switch(ft) { 664 case TDOUBLE: 665 case TVLONG: 666 case TFLOAT: 667 switch(tt) { 668 case TDOUBLE: 669 case TVLONG: 670 a = AMOVD; 671 if(ft == TFLOAT) 672 a = AMOVFD; 673 break; 674 case TFLOAT: 675 a = AMOVDF; 676 if(ft == TFLOAT) 677 a = AMOVF; 678 break; 679 case TINT: 680 case TUINT: 681 case TLONG: 682 case TULONG: 683 case TIND: 684 a = AMOVDW; 685 if(ft == TFLOAT) 686 a = AMOVFW; 687 break; 688 case TSHORT: 689 case TUSHORT: 690 case TCHAR: 691 case TUCHAR: 692 a = AMOVDW; 693 if(ft == TFLOAT) 694 a = AMOVFW; 695 break; 696 } 697 break; 698 case TUINT: 699 case TULONG: 700 if(tt == TFLOAT || tt == TDOUBLE) { 701 // ugly and probably longer than necessary, 702 // but vfp has a single instruction for this, 703 // so hopefully it won't last long. 704 // 705 // tmp = f 706 // tmp1 = tmp & 0x80000000 707 // tmp ^= tmp1 708 // t = float(int32(tmp)) 709 // if(tmp1) 710 // t += 2147483648. 711 // 712 regalloc(&nod, f, Z); 713 regalloc(&nod1, f, Z); 714 gins(AMOVW, f, &nod); 715 gins(AMOVW, &nod, &nod1); 716 gins(AAND, nodconst(0x80000000), &nod1); 717 gins(AEOR, &nod1, &nod); 718 if(tt == TFLOAT) 719 gins(AMOVWF, &nod, t); 720 else 721 gins(AMOVWD, &nod, t); 722 gins(ACMP, nodconst(0), Z); 723 raddr(&nod1, p); 724 gins(ABEQ, Z, Z); 725 regfree(&nod); 726 regfree(&nod1); 727 p1 = p; 728 regalloc(&nod, t, Z); 729 gins(AMOVF, nodfconst(2147483648.), &nod); 730 gins(AADDF, &nod, t); 731 regfree(&nod); 732 patch(p1, pc); 733 return; 734 } 735 // fall through 736 737 case TINT: 738 case TLONG: 739 case TIND: 740 switch(tt) { 741 case TDOUBLE: 742 gins(AMOVWD, f, t); 743 return; 744 case TFLOAT: 745 gins(AMOVWF, f, t); 746 return; 747 case TINT: 748 case TUINT: 749 case TLONG: 750 case TULONG: 751 case TIND: 752 case TSHORT: 753 case TUSHORT: 754 case TCHAR: 755 case TUCHAR: 756 a = AMOVW; 757 break; 758 } 759 break; 760 case TSHORT: 761 switch(tt) { 762 case TDOUBLE: 763 regalloc(&nod, f, Z); 764 gins(AMOVHS, f, &nod); 765 gins(AMOVWD, &nod, t); 766 regfree(&nod); 767 return; 768 case TFLOAT: 769 regalloc(&nod, f, Z); 770 gins(AMOVHS, f, &nod); 771 gins(AMOVWF, &nod, t); 772 regfree(&nod); 773 return; 774 case TUINT: 775 case TINT: 776 case TULONG: 777 case TLONG: 778 case TIND: 779 a = AMOVHS; 780 break; 781 case TSHORT: 782 case TUSHORT: 783 case TCHAR: 784 case TUCHAR: 785 a = AMOVW; 786 break; 787 } 788 break; 789 case TUSHORT: 790 switch(tt) { 791 case TDOUBLE: 792 regalloc(&nod, f, Z); 793 gins(AMOVHU, f, &nod); 794 gins(AMOVWD, &nod, t); 795 regfree(&nod); 796 return; 797 case TFLOAT: 798 regalloc(&nod, f, Z); 799 gins(AMOVHU, f, &nod); 800 gins(AMOVWF, &nod, t); 801 regfree(&nod); 802 return; 803 case TINT: 804 case TUINT: 805 case TLONG: 806 case TULONG: 807 case TIND: 808 a = AMOVHU; 809 break; 810 case TSHORT: 811 case TUSHORT: 812 case TCHAR: 813 case TUCHAR: 814 a = AMOVW; 815 break; 816 } 817 break; 818 case TCHAR: 819 switch(tt) { 820 case TDOUBLE: 821 regalloc(&nod, f, Z); 822 gins(AMOVBS, f, &nod); 823 gins(AMOVWD, &nod, t); 824 regfree(&nod); 825 return; 826 case TFLOAT: 827 regalloc(&nod, f, Z); 828 gins(AMOVBS, f, &nod); 829 gins(AMOVWF, &nod, t); 830 regfree(&nod); 831 return; 832 case TINT: 833 case TUINT: 834 case TLONG: 835 case TULONG: 836 case TIND: 837 case TSHORT: 838 case TUSHORT: 839 a = AMOVBS; 840 break; 841 case TCHAR: 842 case TUCHAR: 843 a = AMOVW; 844 break; 845 } 846 break; 847 case TUCHAR: 848 switch(tt) { 849 case TDOUBLE: 850 regalloc(&nod, f, Z); 851 gins(AMOVBU, f, &nod); 852 gins(AMOVWD, &nod, t); 853 regfree(&nod); 854 return; 855 case TFLOAT: 856 regalloc(&nod, f, Z); 857 gins(AMOVBU, f, &nod); 858 gins(AMOVWF, &nod, t); 859 regfree(&nod); 860 return; 861 case TINT: 862 case TUINT: 863 case TLONG: 864 case TULONG: 865 case TIND: 866 case TSHORT: 867 case TUSHORT: 868 a = AMOVBU; 869 break; 870 case TCHAR: 871 case TUCHAR: 872 a = AMOVW; 873 break; 874 } 875 break; 876 } 877 if(a == AGOK) 878 diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type); 879 if(a == AMOVW || a == AMOVF || a == AMOVD) 880 if(samaddr(f, t)) 881 return; 882 gins(a, f, t); 883 } 884 885 void 886 gmover(Node *f, Node *t) 887 { 888 int ft, tt, a; 889 890 ft = f->type->etype; 891 tt = t->type->etype; 892 a = AGOK; 893 if(typechlp[ft] && typechlp[tt] && ewidth[ft] >= ewidth[tt]){ 894 switch(tt){ 895 case TSHORT: 896 a = AMOVHS; 897 break; 898 case TUSHORT: 899 a = AMOVHU; 900 break; 901 case TCHAR: 902 a = AMOVBS; 903 break; 904 case TUCHAR: 905 a = AMOVBU; 906 break; 907 } 908 } 909 if(a == AGOK) 910 gmove(f, t); 911 else 912 gins(a, f, t); 913 } 914 915 void 916 gins(int a, Node *f, Node *t) 917 { 918 919 nextpc(); 920 p->as = a; 921 if(f != Z) 922 naddr(f, &p->from); 923 if(t != Z) 924 naddr(t, &p->to); 925 if(debug['g']) 926 print("%P\n", p); 927 } 928 929 void 930 gopcode(int o, Node *f1, Node *f2, Node *t) 931 { 932 int a, et; 933 Adr ta; 934 935 et = TLONG; 936 if(f1 != Z && f1->type != T) 937 et = f1->type->etype; 938 a = AGOK; 939 switch(o) { 940 case OAS: 941 gmove(f1, t); 942 return; 943 944 case OASADD: 945 case OADD: 946 a = AADD; 947 if(et == TFLOAT) 948 a = AADDF; 949 else 950 if(et == TDOUBLE || et == TVLONG) 951 a = AADDD; 952 break; 953 954 case OASSUB: 955 case OSUB: 956 if(f2 && f2->op == OCONST) { 957 Node *t = f1; 958 f1 = f2; 959 f2 = t; 960 a = ARSB; 961 } else 962 a = ASUB; 963 if(et == TFLOAT) 964 a = ASUBF; 965 else 966 if(et == TDOUBLE || et == TVLONG) 967 a = ASUBD; 968 break; 969 970 case OASOR: 971 case OOR: 972 a = AORR; 973 break; 974 975 case OASAND: 976 case OAND: 977 a = AAND; 978 break; 979 980 case OASXOR: 981 case OXOR: 982 a = AEOR; 983 break; 984 985 case OASLSHR: 986 case OLSHR: 987 a = ASRL; 988 break; 989 990 case OASASHR: 991 case OASHR: 992 a = ASRA; 993 break; 994 995 case OASASHL: 996 case OASHL: 997 a = ASLL; 998 break; 999 1000 case OFUNC: 1001 a = ABL; 1002 break; 1003 1004 case OASMUL: 1005 case OMUL: 1006 a = AMUL; 1007 if(et == TFLOAT) 1008 a = AMULF; 1009 else 1010 if(et == TDOUBLE || et == TVLONG) 1011 a = AMULD; 1012 break; 1013 1014 case OASDIV: 1015 case ODIV: 1016 a = ADIV; 1017 if(et == TFLOAT) 1018 a = ADIVF; 1019 else 1020 if(et == TDOUBLE || et == TVLONG) 1021 a = ADIVD; 1022 break; 1023 1024 case OASMOD: 1025 case OMOD: 1026 a = AMOD; 1027 break; 1028 1029 case OASLMUL: 1030 case OLMUL: 1031 a = AMULU; 1032 break; 1033 1034 case OASLMOD: 1035 case OLMOD: 1036 a = AMODU; 1037 break; 1038 1039 case OASLDIV: 1040 case OLDIV: 1041 a = ADIVU; 1042 break; 1043 1044 case OCASE: 1045 case OEQ: 1046 case ONE: 1047 case OLT: 1048 case OLE: 1049 case OGE: 1050 case OGT: 1051 case OLO: 1052 case OLS: 1053 case OHS: 1054 case OHI: 1055 a = ACMP; 1056 if(et == TFLOAT) 1057 a = ACMPF; 1058 else 1059 if(et == TDOUBLE || et == TVLONG) 1060 a = ACMPD; 1061 nextpc(); 1062 p->as = a; 1063 naddr(f1, &p->from); 1064 if(a == ACMP && f1->op == OCONST && p->from.offset < 0) { 1065 p->as = ACMN; 1066 p->from.offset = -p->from.offset; 1067 } 1068 raddr(f2, p); 1069 switch(o) { 1070 case OEQ: 1071 a = ABEQ; 1072 break; 1073 case ONE: 1074 a = ABNE; 1075 break; 1076 case OLT: 1077 a = ABLT; 1078 break; 1079 case OLE: 1080 a = ABLE; 1081 break; 1082 case OGE: 1083 a = ABGE; 1084 break; 1085 case OGT: 1086 a = ABGT; 1087 break; 1088 case OLO: 1089 a = ABLO; 1090 break; 1091 case OLS: 1092 a = ABLS; 1093 break; 1094 case OHS: 1095 a = ABHS; 1096 break; 1097 case OHI: 1098 a = ABHI; 1099 break; 1100 case OCASE: 1101 nextpc(); 1102 p->as = ACASE; 1103 p->scond = 0x9; 1104 naddr(f2, &p->from); 1105 a = ABHI; 1106 break; 1107 } 1108 f1 = Z; 1109 f2 = Z; 1110 break; 1111 } 1112 if(a == AGOK) 1113 diag(Z, "bad in gopcode %O", o); 1114 nextpc(); 1115 p->as = a; 1116 if(f1 != Z) 1117 naddr(f1, &p->from); 1118 if(f2 != Z) { 1119 naddr(f2, &ta); 1120 p->reg = ta.reg; 1121 } 1122 if(t != Z) 1123 naddr(t, &p->to); 1124 if(debug['g']) 1125 print("%P\n", p); 1126 } 1127 1128 int 1129 samaddr(Node *f, Node *t) 1130 { 1131 1132 if(f->op != t->op) 1133 return 0; 1134 switch(f->op) { 1135 1136 case OREGISTER: 1137 if(f->reg != t->reg) 1138 break; 1139 return 1; 1140 } 1141 return 0; 1142 } 1143 1144 void 1145 gbranch(int o) 1146 { 1147 int a; 1148 1149 a = AGOK; 1150 switch(o) { 1151 case ORETURN: 1152 a = ARET; 1153 break; 1154 case OGOTO: 1155 a = AB; 1156 break; 1157 } 1158 nextpc(); 1159 if(a == AGOK) { 1160 diag(Z, "bad in gbranch %O", o); 1161 nextpc(); 1162 } 1163 p->as = a; 1164 } 1165 1166 void 1167 patch(Prog *op, int32 pc) 1168 { 1169 1170 op->to.offset = pc; 1171 op->to.type = D_BRANCH; 1172 } 1173 1174 void 1175 gpseudo(int a, Sym *s, Node *n) 1176 { 1177 nextpc(); 1178 p->as = a; 1179 p->from.type = D_OREG; 1180 p->from.sym = s; 1181 p->from.name = D_EXTERN; 1182 1183 switch(a) { 1184 case ATEXT: 1185 p->reg = textflag; 1186 textflag = 0; 1187 break; 1188 case AGLOBL: 1189 p->reg = s->dataflag; 1190 break; 1191 } 1192 1193 if(s->class == CSTATIC) 1194 p->from.name = D_STATIC; 1195 naddr(n, &p->to); 1196 if(a == ADATA || a == AGLOBL) 1197 pc--; 1198 } 1199 1200 void 1201 gpcdata(int index, int value) 1202 { 1203 Node n1; 1204 1205 n1 = *nodconst(index); 1206 gins(APCDATA, &n1, nodconst(value)); 1207 } 1208 1209 void 1210 gprefetch(Node *n) 1211 { 1212 Node n1; 1213 1214 regalloc(&n1, n, Z); 1215 gmove(n, &n1); 1216 n1.op = OINDREG; 1217 gins(APLD, &n1, Z); 1218 regfree(&n1); 1219 } 1220 1221 int 1222 sconst(Node *n) 1223 { 1224 vlong vv; 1225 1226 if(n->op == OCONST) { 1227 if(!typefd[n->type->etype]) { 1228 vv = n->vconst; 1229 if(vv >= (vlong)(-32766) && vv < (vlong)32766) 1230 return 1; 1231 /* 1232 * should be specialised for constant values which will 1233 * fit in different instructionsl; for now, let 5l 1234 * sort it out 1235 */ 1236 return 1; 1237 } 1238 } 1239 return 0; 1240 } 1241 1242 int 1243 sval(int32 v) 1244 { 1245 int i; 1246 1247 for(i=0; i<16; i++) { 1248 if((v & ~0xff) == 0) 1249 return 1; 1250 if((~v & ~0xff) == 0) 1251 return 1; 1252 v = (v<<2) | ((uint32)v>>30); 1253 } 1254 return 0; 1255 } 1256 1257 int32 1258 exreg(Type *t) 1259 { 1260 int32 o; 1261 1262 if(typechlp[t->etype]) { 1263 if(exregoffset <= REGEXT-4) 1264 return 0; 1265 o = exregoffset; 1266 exregoffset--; 1267 return o; 1268 } 1269 if(typefd[t->etype]) { 1270 if(exfregoffset <= NFREG-1) 1271 return 0; 1272 o = exfregoffset + NREG; 1273 exfregoffset--; 1274 return o; 1275 } 1276 return 0; 1277 } 1278 1279 schar ewidth[NTYPE] = 1280 { 1281 -1, /* [TXXX] */ 1282 SZ_CHAR, /* [TCHAR] */ 1283 SZ_CHAR, /* [TUCHAR] */ 1284 SZ_SHORT, /* [TSHORT] */ 1285 SZ_SHORT, /* [TUSHORT] */ 1286 SZ_INT, /* [TINT] */ 1287 SZ_INT, /* [TUINT] */ 1288 SZ_LONG, /* [TLONG] */ 1289 SZ_LONG, /* [TULONG] */ 1290 SZ_VLONG, /* [TVLONG] */ 1291 SZ_VLONG, /* [TUVLONG] */ 1292 SZ_FLOAT, /* [TFLOAT] */ 1293 SZ_DOUBLE, /* [TDOUBLE] */ 1294 SZ_IND, /* [TIND] */ 1295 0, /* [TFUNC] */ 1296 -1, /* [TARRAY] */ 1297 0, /* [TVOID] */ 1298 -1, /* [TSTRUCT] */ 1299 -1, /* [TUNION] */ 1300 SZ_INT, /* [TENUM] */ 1301 }; 1302 1303 int32 ncast[NTYPE] = 1304 { 1305 0, /* [TXXX] */ 1306 BCHAR|BUCHAR, /* [TCHAR] */ 1307 BCHAR|BUCHAR, /* [TUCHAR] */ 1308 BSHORT|BUSHORT, /* [TSHORT] */ 1309 BSHORT|BUSHORT, /* [TUSHORT] */ 1310 BINT|BUINT|BLONG|BULONG|BIND, /* [TINT] */ 1311 BINT|BUINT|BLONG|BULONG|BIND, /* [TUINT] */ 1312 BINT|BUINT|BLONG|BULONG|BIND, /* [TLONG] */ 1313 BINT|BUINT|BLONG|BULONG|BIND, /* [TULONG] */ 1314 BVLONG|BUVLONG, /* [TVLONG] */ 1315 BVLONG|BUVLONG, /* [TUVLONG] */ 1316 BFLOAT, /* [TFLOAT] */ 1317 BDOUBLE, /* [TDOUBLE] */ 1318 BLONG|BULONG|BIND, /* [TIND] */ 1319 0, /* [TFUNC] */ 1320 0, /* [TARRAY] */ 1321 0, /* [TVOID] */ 1322 BSTRUCT, /* [TSTRUCT] */ 1323 BUNION, /* [TUNION] */ 1324 0, /* [TENUM] */ 1325 };