1/* Id: local2.c,v 1.31 2015/01/04 19:17:23 ragge Exp */ 2/* $NetBSD: local2.c,v 1.1.1.5 2016/02/09 20:28:14 plunky Exp $ */ 3 4/* 5 * Copyright (c) 2007 Michael Shalayeff 6 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 33# include "pass2.h" 34# include <ctype.h> 35# include <string.h> 36 37void acon(NODE *p); 38void prtprolog(struct interpass_prolog *, int); 39int countargs(NODE *p, int *); 40void fixcalls(NODE *p, void *); 41 42static int stkpos; 43int p2calls; 44 45static const int rl[] = 46 { R0, R1, R1, R1, R1, R1, R31, R31, R31, R31, 47 R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, 48 T1, T4, T3, T2, ARG3, ARG1, RET1 }; 49static const int rh[] = 50 { R0, R31, T4, T3, T2, T1, T4, T3, T2, T1, 51 R18, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, 52 T4, T3, T2, T1, ARG2, ARG0, RET0 }; 53 54void 55deflab(int label) 56{ 57 printf("\t.label\t" LABFMT "\n", label); 58} 59 60static int regoff[MAXREGS]; 61static TWORD ftype; 62 63/* 64 * Print out the prolog assembler. 65 * addto and regoff are already calculated. 66 */ 67void 68prtprolog(struct interpass_prolog *ipp, int addto) 69{ 70 int i; 71 72 /* if this functions calls nothing -- no frame is needed */ 73 if (p2calls || p2maxautooff > 4) { 74 printf("\tcopy\t%%r3,%%r1\n\tcopy\t%%sp,%%r3\n"); 75 if (addto < 0x2000) 76 printf("\tstw,ma\t%%r1,%d(%%sp)\n", addto); 77 else if (addto < 0x802000) 78 printf("\tstw,ma\t%%r1,8192(%%sp)\n" 79 "\taddil\t%d-8192,%%sp\n" 80 "\tcopy\t%%r1,%%sp\n", addto); 81 else 82 comperr("too much local allocation"); 83 if (p2calls) 84 printf("\tstw\t%%rp,-20(%%r3)\n"); 85 } 86 87 for (i = 0; i < MAXREGS; i++) 88 if (TESTBIT(ipp->ipp_regs, i)) { 89 if (i <= R31) 90 printf("\tstw\t%s,%d(%%r3)\n", 91 rnames[i], regoff[i]); 92 else if (i <= RETD0) 93 printf("\tstw\t%s,%d(%%r3)\n" 94 "\tstw\t%s,%d(%%r3)\n", 95 rnames[rl[i - RD0]], regoff[i] + 0, 96 rnames[rh[i - RD0]], regoff[i] + 4); 97 else if (i <= FR31) 98 printf("\tfstws\t%s,%d(%%r3)\n", 99 rnames[i], regoff[i]); 100 else 101 printf("\tfstds\t%s,%d(%%r3)\n", 102 rnames[i], regoff[i]); 103 } 104} 105 106/* 107 * calculate stack size and offsets 108 */ 109static int 110offcalc(struct interpass_prolog *ipp) 111{ 112 int i, addto, off; 113 114 addto = 32; 115 if (p2calls) { 116 i = p2calls - 1; 117 /* round up to 4 args */ 118 if (i < 4) 119 i = 4; 120 addto += i * 4; 121 } 122 123 for (off = 4, i = 0; i < MAXREGS; i++) 124 if (TESTBIT(ipp->ipp_regs, i)) { 125 regoff[i] = off; 126 off += szty(PERMTYPE(i)) * SZINT/SZCHAR; 127 } 128 addto += off + p2maxautooff; 129 return (addto + 63) & ~63; 130} 131 132void 133prologue(struct interpass_prolog *ipp) 134{ 135 int addto; 136 137 ftype = ipp->ipp_type; 138 139 /* 140 * We here know what registers to save and how much to 141 * add to the stack. 142 */ 143 addto = offcalc(ipp); 144 printf("\t.proc\ncallinfo frame=%d, save_rp, save_sp\n\t.entry\n", 145 addto); 146 prtprolog(ipp, addto); 147} 148 149void 150eoftn(struct interpass_prolog *ipp) 151{ 152 int i; 153 154 if (ipp->ipp_ip.ip_lbl == 0) 155 return; /* no code needs to be generated */ 156 157 /* return from function code */ 158 for (i = 0; i < MAXREGS; i++) 159 if (TESTBIT(ipp->ipp_regs, i)) { 160 if (i <= R31) 161 printf("\tldw\t%d(%%r3),%s\n", 162 regoff[i], rnames[i]); 163 else if (i <= RETD0) 164 printf("\tldw\t%d(%%r3),%s\n" 165 "\tldw\t%d(%%r3),%s\n", 166 regoff[i] + 0, rnames[rl[i - RD0]], 167 regoff[i] + 4, rnames[rh[i - RD0]]); 168 else if (i <= FR31) 169 printf("\tfldws\t%d(%%r3),%s\n", 170 regoff[i], rnames[i]); 171 else 172 printf("\tfldds\t%d(%%r3),%s\n", 173 regoff[i], rnames[i]); 174 } 175 176 if (p2calls || p2maxautooff > 4) { 177 if (p2calls) 178 printf("\tldw\t-20(%%r3),%%rp\n"); 179 printf("\tcopy\t%%r3,%%r1\n" 180 "\tldw\t0(%%r3),%%r3\n" 181 "\tbv\t%%r0(%%rp)\n" 182 "\tcopy\t%%r1,%%sp\n"); 183 } else 184 printf("\tbv\t%%r0(%%rp)\n\tnop\n"); 185 186 printf("\t.exit\n\t.procend\n\t.size\t%s, .-%s\n", 187 ipp->ipp_name, ipp->ipp_name); 188} 189 190/* 191 * add/sub/... 192 * 193 * Param given: 194 */ 195void 196hopcode(int f, int o) 197{ 198 char *str; 199 200 switch (o) { 201 case PLUS: 202 str = "add"; 203 break; 204 case MINUS: 205 str = "sub"; 206 break; 207 case AND: 208 str = "and"; 209 break; 210 case OR: 211 str = "or"; 212 break; 213 case ER: 214 str = "xor"; 215 break; 216 case EQ: 217 str = "="; 218 break; 219 case NE: 220 str = "<>"; 221 break; 222 case LE: 223 str = "<"; 224 break; 225 case LT: 226 str = "<="; 227 break; 228 case ULE: 229 str = "<<"; 230 break; 231 case ULT: 232 str = "<<="; 233 break; 234 case GE: 235 str = ">="; 236 break; 237 case GT: 238 str = ">"; 239 break; 240 case UGE: 241 str = ">>"; 242 break; 243 case UGT: 244 str = ">>="; 245 break; 246 default: 247 comperr("hopcode2: %d", o); 248 str = 0; /* XXX gcc */ 249 } 250 printf("%s%c", str, f); 251} 252 253/* 254 * Return type size in bytes. Used by R2REGS, arg 2 to offset(). 255 */ 256int 257tlen(p) NODE *p; 258{ 259 switch(p->n_type) { 260 case CHAR: 261 case UCHAR: 262 return(1); 263 264 case SHORT: 265 case USHORT: 266 return(SZSHORT/SZCHAR); 267 268 case FLOAT: 269 return(SZFLOAT/SZCHAR); 270 271 case DOUBLE: 272 return(SZDOUBLE/SZCHAR); 273 274 case INT: 275 case UNSIGNED: 276 case LONG: 277 case ULONG: 278 return(SZINT/SZCHAR); 279 280 case LONGLONG: 281 case ULONGLONG: 282 return SZLONGLONG/SZCHAR; 283 284 default: 285 if (!ISPTR(p->n_type)) 286 comperr("tlen type %d not pointer", p->n_type); 287 return SZPOINT(p->n_type)/SZCHAR; 288 } 289} 290 291static int 292argsiz(NODE *p) 293{ 294 NODE *q; 295 TWORD t = p->n_type; 296 297 if (t < LONGLONG || t == FLOAT || t > BTMASK) 298 return 4; 299 if (t == LONGLONG || t == ULONGLONG || t == DOUBLE) 300 return 8; 301 if (t == LDOUBLE) 302 return 8; /* LDOUBLE is 16 */ 303 if ((t == STRTY || t == UNIONTY) && p->n_right->n_op == STARG) 304 return 4 + attr_find(p->n_right->n_ap, ATTR_P2STRUCT)->iarg(0); 305 /* perhaps it's down there somewhere -- let me take another look! */ 306 if ((t == STRTY || t == UNIONTY) && p->n_right->n_op == CALL) { 307 q = p->n_right->n_right->n_left->n_left->n_right; 308 if (q->n_op == STARG) 309 return 4 + attr_find(q->n_ap, ATTR_P2STRUCT)->iarg(0); 310 } 311 comperr("argsiz %p", p); 312 return 0; 313} 314 315/* 316 * Emit code to compare two longlong numbers. 317 */ 318static void 319twollcomp(NODE *p) 320{ 321 int o = p->n_op; 322 int s = getlab2(); 323 int e = p->n_label; 324 int cb1, cb2; 325 326 if (o >= ULE) 327 o -= (ULE-LE); 328 switch (o) { 329 case NE: 330 cb1 = 0; 331 cb2 = NE; 332 break; 333 case EQ: 334 cb1 = NE; 335 cb2 = 0; 336 break; 337 case LE: 338 case LT: 339 cb1 = GT; 340 cb2 = LT; 341 break; 342 case GE: 343 case GT: 344 cb1 = LT; 345 cb2 = GT; 346 break; 347 348 default: 349 cb1 = cb2 = 0; /* XXX gcc */ 350 } 351 if (p->n_op >= ULE) 352 cb1 += 4, cb2 += 4; 353 if (cb1) { 354 p->n_op = cb1; 355 p->n_label = s; 356 expand(p, 0, "\tcomb,O\tUR,UL,LC\n\tnop\n"); 357 p->n_label = e; 358 p->n_op = o; 359 } 360 if (cb2) { 361 p->n_op = cb2; 362 expand(p, 0, "\tcomb,O\tUR,UL,LC\n\tnop\n"); 363 p->n_op = o; 364 } 365 expand(p, 0, "\tcomb,O\tAR,AL,LC\n\tnop\n"); 366 deflab(s); 367} 368 369void 370zzzcode(NODE *p, int c) 371{ 372 int n; 373 374 switch (c) { 375 376 case 'C': /* after-call fixup */ 377 n = p->n_qual; /* args */ 378 break; 379 380 case 'P': /* returning struct-call setup */ 381 n = p->n_qual; /* args */ 382 break; 383 384 case 'D': /* Long long comparision */ 385 twollcomp(p); 386 break; 387 388 case 'F': /* struct as an arg */ 389 390 default: 391 comperr("zzzcode %c", c); 392 } 393} 394 395int canaddr(NODE *); 396int 397canaddr(NODE *p) 398{ 399 int o = p->n_op; 400 401 if (o == NAME || o == REG || o == ICON || o == OREG || 402 (o == UMUL && shumul(p->n_left, SOREG))) 403 return(1); 404 return(0); 405} 406 407int 408fldexpand(NODE *p, int cookie, char **cp) 409{ 410 return 0; 411} 412 413/* 414 * Does the bitfield shape match? 415 */ 416int 417flshape(NODE *p) 418{ 419 if (isreg(p)) 420 return SRDIR; /* Direct match */ 421 422 return SRREG; /* put it into a register */ 423} 424 425/* INTEMP shapes must not contain any temporary registers */ 426/* XXX should this go away now? */ 427int 428shtemp(NODE *p) 429{ 430 return 0; 431#if 0 432 int r; 433 434 if (p->n_op == STARG ) 435 p = p->n_left; 436 437 switch (p->n_op) { 438 case REG: 439 return (!istreg(p->n_rval)); 440 441 case OREG: 442 r = p->n_rval; 443 if (R2TEST(r)) { 444 if (istreg(R2UPK1(r))) 445 return(0); 446 r = R2UPK2(r); 447 } 448 return (!istreg(r)); 449 450 case UMUL: 451 p = p->n_left; 452 return (p->n_op != UMUL && shtemp(p)); 453 } 454 455 if (optype(p->n_op) != LTYPE) 456 return(0); 457 return(1); 458#endif 459} 460 461void 462adrcon(CONSZ val) 463{ 464 /* fix for L% and R% */ 465 printf(CONFMT, val); 466} 467 468void 469conput(FILE *fp, NODE *p) 470{ 471 CONSZ val = p->n_lval; 472 473 switch (p->n_op) { 474 case ICON: 475 if (p->n_name[0] != '\0') { 476 fprintf(fp, "RR'%s-$global$", p->n_name); 477 if (val) 478 fprintf(fp, "+" CONFMT, val); 479 } else 480 fprintf(fp, CONFMT, val); 481 return; 482 483 default: 484 comperr("illegal conput, p %p", p); 485 } 486} 487 488/*ARGSUSED*/ 489void 490insput(NODE *p) 491{ 492 comperr("insput"); 493} 494 495/* 496 * Write out the upper address, like the upper register of a 2-register 497 * reference, or the next memory location. 498 */ 499void 500upput(NODE *p, int size) 501{ 502 503 size /= SZCHAR; 504 switch (p->n_op) { 505 case REG: 506 printf("%s", rnames[rh[p->n_rval - RD0]]); 507 break; 508 509 case OREG: 510 p->n_lval += size; 511 adrput(stdout, p); 512 p->n_lval -= size; 513 break; 514 515 case ICON: 516 case NAME: 517 if (p->n_name[0] != '\0') { 518 printf("LR'%s-$global$", p->n_name); 519 if (p->n_lval != 0) 520 printf("+" CONFMT, p->n_lval); 521 } else 522 printf("L%%" CONFMT, p->n_lval >> 32); 523 break; 524 default: 525 comperr("upput bad op %d size %d", p->n_op, size); 526 } 527} 528 529void 530adrput(FILE *io, NODE *p) 531{ 532 int r; 533 /* output an address, with offsets, from p */ 534 535 if (p->n_op == FLD) 536 p = p->n_left; 537 538 switch (p->n_op) { 539 540 case ICON: 541 case NAME: 542 if (p->n_name[0] != '\0') { 543 fprintf(io, "RR'%s-$global$", p->n_name); 544 if (p->n_lval != 0) 545 fprintf(io, "+" CONFMT, p->n_lval); 546 } else 547 fprintf(io, "R%%" CONFMT, p->n_lval); 548 return; 549 550 case OREG: 551 r = p->n_rval; 552 if (p->n_name[0] != '\0') { 553 fprintf(io, "RR'%s-$global$", p->n_name); 554 if (p->n_lval != 0) 555 fprintf(io, "+" CONFMT, p->n_lval); 556 } else 557 fprintf(io, "%d", (int)p->n_lval); 558 if (R2TEST(r)) { 559 fprintf(io, "%s(%s)", rnames[R2UPK1(r)], 560 rnames[R2UPK2(r)]); 561 } else 562 fprintf(io, "(%s)", rnames[p->n_rval]); 563 return; 564 case REG: 565 if (RD0 <= p->n_rval && p->n_rval <= RETD0) 566 fprintf(io, "%s", rnames[rl[p->n_rval - RD0]]); 567 else 568 fprintf(io, "%s", rnames[p->n_rval]); 569 return; 570 571 default: 572 comperr("illegal address, op %d, node %p", p->n_op, p); 573 return; 574 575 } 576} 577 578/* not used */ 579void 580cbgen(int o, int lab) 581{ 582} 583 584int 585countargs(NODE *p, int *n) 586{ 587 int sz; 588 589 if (p->n_op == CM) { 590 countargs(p->n_left, n); 591 countargs(p->n_right, n); 592 return *n; 593 } 594 595 sz = argsiz(p) / 4; 596 if (*n % (sz > 4? 4 : sz)) 597 (*n)++; /* XXX */ 598 599 return *n += sz; 600} 601 602void 603fixcalls(NODE *p, void *arg) 604{ 605 int n, o; 606 607 /* Prepare for struct return by allocating bounce space on stack */ 608 switch (o = p->n_op) { 609 case STCALL: 610 case USTCALL: 611 if (attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0) 612 + p2autooff > stkpos) 613 stkpos = attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0) + p2autooff; 614 /* FALLTHROGH */ 615 case CALL: 616 case UCALL: 617 n = 0; 618 n = 1 + countargs(p->n_right, &n); 619 if (n > p2calls) 620 p2calls = n; 621 break; 622 } 623} 624 625void 626myreader(struct interpass *ipole) 627{ 628 struct interpass *ip; 629 630 stkpos = p2autooff; 631 DLIST_FOREACH(ip, ipole, qelem) { 632 switch (ip->type) { 633 case IP_PROLOG: 634 p2calls = 0; 635 break; 636 637 case IP_NODE: 638 walkf(ip->ip_node, fixcalls, 0); 639 break; 640 } 641 } 642 if (stkpos > p2autooff) 643 p2autooff = stkpos; 644 if (stkpos > p2maxautooff) 645 p2maxautooff = stkpos; 646 if (x2debug) 647 printip(ipole); 648} 649 650/* 651 * Remove some PCONVs after OREGs are created. 652 */ 653static void 654pconv2(NODE *p, void *arg) 655{ 656 NODE *q; 657 658 if (p->n_op == PLUS) { 659 if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) { 660 if (p->n_right->n_op != ICON) 661 return; 662 if (p->n_left->n_op != PCONV) 663 return; 664 if (p->n_left->n_left->n_op != OREG) 665 return; 666 q = p->n_left->n_left; 667 nfree(p->n_left); 668 p->n_left = q; 669 /* 670 * This will be converted to another OREG later. 671 */ 672 } 673 } 674} 675 676void 677mycanon(NODE *p) 678{ 679 walkf(p, pconv2, 0); 680} 681 682void 683myoptim(struct interpass *ipole) 684{ 685} 686 687void 688rmove(int s, int d, TWORD t) 689{ 690 int sl, sh, dl, dh; 691 692 switch (t) { 693 case LONGLONG: 694 case ULONGLONG: 695 sl = rl[s-RD0]; 696 sh = rh[s-RD0]; 697 dl = rl[d-RD0]; 698 dh = rh[d-RD0]; 699 700#define SW(x,y) { int i = x; x = y; y = i; } 701 if (sl == dh || sh == dl) { 702 /* Swap if moving to itself */ 703 SW(sl, sh); 704 SW(dl, dh); 705 } 706 if (sl != dl) 707 printf("\tcopy\t%s,%s\n", rnames[sl], rnames[dl]); 708 if (sh != dh) 709 printf("\tcopy\t%s,%s\n", rnames[sh], rnames[dh]); 710 break; 711 case FLOAT: 712 printf("\tfcpy,sgl\t%s,%s\n", rnames[s], rnames[d]); 713 break; 714 case DOUBLE: 715 case LDOUBLE: 716 printf("\tfcpy,dbl\t%s,%s\n", rnames[s], rnames[d]); 717 break; 718 default: 719 printf("\tcopy\t%s,%s\n", rnames[s], rnames[d]); 720 } 721} 722 723/* 724 * For class c, find worst-case displacement of the number of 725 * registers in the array r[] indexed by class. 726 */ 727int 728COLORMAP(int c, int *r) 729{ 730 int num; 731 732 switch (c) { 733 case CLASSA: 734 num = 2 * r[CLASSB]; 735 num += r[CLASSA]; 736 return num < 28; 737 case CLASSB: 738 num = r[CLASSA]; 739 num += r[CLASSB] * 2; 740 return num < 28; 741 case CLASSC: 742 num = (r[CLASSD] > 8? 8 : r[CLASSD]) * 2; 743 num += r[CLASSC]; 744 return num < 28; 745 case CLASSD: 746 num = (r[CLASSC] + 1) / 2; 747 num += r[CLASSD]; 748 return num < 28; 749 } 750 return 0; /* XXX gcc */ 751} 752 753char * rnames[MAXREGS] = { 754 "%r0", "%r1", "%rp", "%r3", "%r4", "%r5", "%r6", "%r7", "%r8", "%r9", 755 "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%r16", "%r17", "%r18", 756 "%t4", "%t3", "%t2", "%t1", "%arg3", "%arg2", "%arg1", "%arg0", "%dp", 757 "%ret0", "%ret1", "%sp", "%r31", 758 "%rd0", "%rd1", "%rd2", "%rd3", "%rd4", "%rd5", "%rd6", "%rd7", 759 "%rd8", "%rd9", "%rd10", "%rd11", "%rd12", "%rd13", "%rd14", "%rd15", 760 "%rd16", "%rd17", "%rd18", "%rd19", "%rd20", "%rd21", "%rd22", "%rd23", 761 "%rd24", "%td4", "%td3", "%td2", "%td1", "%ad1", "%ad0", "%retd0", 762 "%fr0", "%fr4", "%fr5", "%fr6", "%fr7", "%fr8", "%fr9", "%fr10", 763 "%fr11", "%fr12", "%fr13", "%fr14", "%fr15", "%fr16", "%fr17", "%fr18", 764 "%fr19", "%fr20", "%fr21", "%fr22", "%fr23", "%fr24", "%fr25", "%fr26", 765 "%fr27", "%fr28", "%fr29", "%fr30", "%fr31", 766 "%fr0l", "%fr0r", "%fr4l", "%fr4r", "%fr5l", "%fr5r", "%fr6l", "%fr6r", 767 "%fr7l", "%fr7r", "%fr8l", "%fr8r", "%fr9l", "%fr9r", 768 "%fr10l", "%fr10r", "%fr11l", "%fr11r", "%fr12l", "%fr12r", 769 "%fr13l", "%fr13r", "%fr14l", "%fr14r", "%fr15l", "%fr15r", 770 "%fr16l", "%fr16r", "%fr17l", "%fr17r", "%fr18l", "%fr18r", 771#ifdef __hppa64__ 772 "%fr19l", "%fr19r", 773 "%fr20l", "%fr20r", "%fr21l", "%fr21r", "%fr22l", "%fr22r", 774 "%fr23l", "%fr23r", "%fr24l", "%fr24r", "%fr25l", "%fr25r", 775 "%fr26l", "%fr26r", "%fr27l", "%fr27r", "%fr28l", "%fr28r", 776 "%fr29l", "%fr29r", "%fr30l", "%fr30r", "%fr31l", "%fr31r", 777#endif 778}; 779 780/* 781 * Return a class suitable for a specific type. 782 */ 783int 784gclass(TWORD t) 785{ 786 switch (t) { 787 case LONGLONG: 788 case ULONGLONG: 789 return CLASSB; 790 case FLOAT: 791 return CLASSC; 792 case DOUBLE: 793 case LDOUBLE: 794 return CLASSD; 795 default: 796 return CLASSA; 797 } 798} 799 800/* 801 * Calculate argument sizes. 802 */ 803void 804lastcall(NODE *p) 805{ 806 NODE *op = p; 807 int size = 64; 808 809 p->n_qual = size; 810 if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL) 811 return; 812 for (p = p->n_right; p->n_op == CM; p = p->n_left) 813 size += argsiz(p->n_right); 814 size += argsiz(p); 815 op->n_qual = size; /* XXX */ 816} 817 818/* 819 * Special shapes. 820 */ 821int 822special(NODE *p, int shape) 823{ 824 int o = p->n_op; 825 826 switch (shape) { 827 case SFUNCALL: 828 if (o == STCALL || o == USTCALL) 829 return SRREG; 830 break; 831 case SPIMM: 832 if (o != ICON || p->n_name[0] || 833 p->n_lval < -31 || p->n_lval >= 32) 834 break; 835 return SRDIR; 836 case SPICON: 837 if (o != ICON || p->n_name[0] || 838 p->n_lval < -1024 || p->n_lval >= 1024) 839 break; 840 return SRDIR; 841 case SPCNHW: 842 if (o != ICON || p->n_name[0] || (p->n_lval & 0xffffffffLL)) 843 break; 844 return SRDIR; 845 case SPCNLW: 846 if (o != ICON || p->n_name[0] || (p->n_lval & ~0xffffffffLL)) 847 break; 848 return SRDIR; 849 case SPCNHI: 850 if (o != ICON || p->n_name[0] || (p->n_lval & ~0xfffff800LL)) 851 break; 852 return SRDIR; 853 case SPCON: 854 if (o != ICON || p->n_name[0] || 855 p->n_lval < -8192 || p->n_lval >= 8192) 856 break; 857 return SRDIR; 858 case SPNAME: 859 if (o != ICON || !p->n_name[0]) 860 break; 861 return SRDIR; 862 } 863 return SRNOPE; 864} 865 866/* 867 * Target-dependent command-line options. 868 */ 869void 870mflags(char *str) 871{ 872} 873/* 874 * Do something target-dependent for xasm arguments. 875 * Supposed to find target-specific constraints and rewrite them. 876 */ 877int 878myxasm(struct interpass *ip, NODE *p) 879{ 880 return 0; 881} 882