1 /* Id: local2.c,v 1.18 2010/05/30 15:32:45 ragge Exp */ 2 /* $NetBSD: local2.c,v 1.1.1.2 2010/06/03 18:57:08 plunky Exp $ */ 3 /* 4 * Copyright (c) 2008 Michael Shalayeff 5 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 # include "pass2.h" 32 # include <ctype.h> 33 # include <string.h> 34 35 static int stkpos; 36 37 void 38 deflab(int label) 39 { 40 printf(LABFMT ":\n", label); 41 } 42 43 static int regoff[MAXREGS]; 44 static TWORD ftype; 45 char *rbyte[], *rshort[], *rlong[]; 46 47 /* 48 * Print out the prolog assembler. 49 * addto and regoff are already calculated. 50 */ 51 static void 52 prtprolog(struct interpass_prolog *ipp, int addto) 53 { 54 int i; 55 56 /* XXX should look if there is any need to emit this */ 57 printf("\tpushq %%rbp\n"); 58 printf("\tmovq %%rsp,%%rbp\n"); 59 addto = (addto+15) & ~15; /* 16-byte aligned */ 60 if (addto) 61 printf("\tsubq $%d,%%rsp\n", addto); 62 63 /* save permanent registers */ 64 for (i = 0; i < MAXREGS; i++) 65 if (TESTBIT(ipp->ipp_regs, i)) 66 fprintf(stdout, "\tmovq %s,-%d(%s)\n", 67 rnames[i], regoff[i], rnames[FPREG]); 68 } 69 70 /* 71 * calculate stack size and offsets 72 */ 73 static int 74 offcalc(struct interpass_prolog *ipp) 75 { 76 int i, addto; 77 78 addto = p2maxautooff; 79 if (addto >= AUTOINIT/SZCHAR) 80 addto -= AUTOINIT/SZCHAR; 81 for (i = 0; i < MAXREGS; i++) 82 if (TESTBIT(ipp->ipp_regs, i)) { 83 addto += SZLONG/SZCHAR; 84 regoff[i] = addto; 85 } 86 return addto; 87 } 88 89 void 90 prologue(struct interpass_prolog *ipp) 91 { 92 int addto; 93 94 ftype = ipp->ipp_type; 95 96 #ifdef LANG_F77 97 if (ipp->ipp_vis) 98 printf(" .globl %s\n", ipp->ipp_name); 99 printf(" .align 16\n"); 100 printf("%s:\n", ipp->ipp_name); 101 #endif 102 /* 103 * We here know what register to save and how much to 104 * add to the stack. 105 */ 106 addto = offcalc(ipp); 107 prtprolog(ipp, addto); 108 } 109 110 void 111 eoftn(struct interpass_prolog *ipp) 112 { 113 int i; 114 115 if (ipp->ipp_ip.ip_lbl == 0) 116 return; /* no code needs to be generated */ 117 118 /* return from function code */ 119 for (i = 0; i < MAXREGS; i++) 120 if (TESTBIT(ipp->ipp_regs, i)) 121 fprintf(stdout, " movq -%d(%s),%s\n", 122 regoff[i], rnames[FPREG], rnames[i]); 123 124 /* struct return needs special treatment */ 125 if (ftype == STRTY || ftype == UNIONTY) { 126 printf(" movl 8(%%ebp),%%eax\n"); 127 printf(" leave\n"); 128 printf(" ret $%d\n", 4); 129 } else { 130 printf(" leave\n"); 131 printf(" ret\n"); 132 } 133 printf("\t.size %s,.-%s\n", ipp->ipp_name, ipp->ipp_name); 134 } 135 136 /* 137 * add/sub/... 138 * 139 * Param given: 140 */ 141 void 142 hopcode(int f, int o) 143 { 144 char *str; 145 146 switch (o) { 147 case PLUS: 148 str = "add"; 149 break; 150 case MINUS: 151 str = "sub"; 152 break; 153 case AND: 154 str = "and"; 155 break; 156 case OR: 157 str = "or"; 158 break; 159 case ER: 160 str = "xor"; 161 break; 162 default: 163 comperr("hopcode2: %d", o); 164 str = 0; /* XXX gcc */ 165 } 166 printf("%s%c", str, f); 167 } 168 169 /* 170 * Return type size in bytes. Used by R2REGS, arg 2 to offset(). 171 */ 172 int 173 tlen(NODE *p) 174 { 175 switch(p->n_type) { 176 case CHAR: 177 case UCHAR: 178 return(1); 179 180 case SHORT: 181 case USHORT: 182 return(SZSHORT/SZCHAR); 183 184 case DOUBLE: 185 return(SZDOUBLE/SZCHAR); 186 187 case INT: 188 case UNSIGNED: 189 return(SZINT/SZCHAR); 190 191 case LONG: 192 case ULONG: 193 case LONGLONG: 194 case ULONGLONG: 195 return SZLONGLONG/SZCHAR; 196 197 default: 198 if (!ISPTR(p->n_type)) 199 comperr("tlen type %d not pointer"); 200 return SZPOINT(p->n_type)/SZCHAR; 201 } 202 } 203 204 #if 0 205 /* 206 * Emit code to compare two longlong numbers. 207 */ 208 static void 209 twollcomp(NODE *p) 210 { 211 int o = p->n_op; 212 int s = getlab2(); 213 int e = p->n_label; 214 int cb1, cb2; 215 216 if (o >= ULE) 217 o -= (ULE-LE); 218 switch (o) { 219 case NE: 220 cb1 = 0; 221 cb2 = NE; 222 break; 223 case EQ: 224 cb1 = NE; 225 cb2 = 0; 226 break; 227 case LE: 228 case LT: 229 cb1 = GT; 230 cb2 = LT; 231 break; 232 case GE: 233 case GT: 234 cb1 = LT; 235 cb2 = GT; 236 break; 237 238 default: 239 cb1 = cb2 = 0; /* XXX gcc */ 240 } 241 if (p->n_op >= ULE) 242 cb1 += 4, cb2 += 4; 243 expand(p, 0, " cmpl UR,UL\n"); 244 if (cb1) cbgen(cb1, s); 245 if (cb2) cbgen(cb2, e); 246 expand(p, 0, " cmpl AR,AL\n"); 247 cbgen(p->n_op, e); 248 deflab(s); 249 } 250 #endif 251 252 int 253 fldexpand(NODE *p, int cookie, char **cp) 254 { 255 CONSZ val; 256 257 if (p->n_op == ASSIGN) 258 p = p->n_left; 259 switch (**cp) { 260 case 'S': 261 printf("%d", UPKFSZ(p->n_rval)); 262 break; 263 case 'H': 264 printf("%d", UPKFOFF(p->n_rval)); 265 break; 266 case 'M': 267 case 'N': 268 val = (CONSZ)1 << UPKFSZ(p->n_rval); 269 --val; 270 val <<= UPKFOFF(p->n_rval); 271 if (p->n_type > UNSIGNED) 272 printf("0x%llx", (**cp == 'M' ? val : ~val)); 273 else 274 printf("0x%llx", (**cp == 'M' ? val : ~val)&0xffffffff); 275 break; 276 default: 277 comperr("fldexpand"); 278 } 279 return 1; 280 } 281 282 static void 283 bfext(NODE *p) 284 { 285 int ch = 0, sz = 0; 286 287 if (ISUNSIGNED(p->n_right->n_type)) 288 return; 289 switch (p->n_right->n_type) { 290 case CHAR: 291 ch = 'b'; 292 sz = 8; 293 break; 294 case SHORT: 295 ch = 'w'; 296 sz = 16; 297 break; 298 case INT: 299 ch = 'l'; 300 sz = 32; 301 break; 302 case LONG: 303 ch = 'q'; 304 sz = 64; 305 break; 306 default: 307 comperr("bfext"); 308 } 309 310 sz -= UPKFSZ(p->n_left->n_rval); 311 printf("\tshl%c $%d,", ch, sz); 312 adrput(stdout, getlr(p, 'D')); 313 printf("\n\tsar%c $%d,", ch, sz); 314 adrput(stdout, getlr(p, 'D')); 315 printf("\n"); 316 } 317 #if 0 318 319 /* 320 * Push a structure on stack as argument. 321 * the scratch registers are already free here 322 */ 323 static void 324 starg(NODE *p) 325 { 326 FILE *fp = stdout; 327 328 fprintf(fp, " subl $%d,%%esp\n", p->n_stsize); 329 fprintf(fp, " pushl $%d\n", p->n_stsize); 330 expand(p, 0, " pushl AL\n"); 331 expand(p, 0, " leal 8(%esp),A1\n"); 332 expand(p, 0, " pushl A1\n"); 333 fprintf(fp, " call memcpy\n"); 334 fprintf(fp, " addl $12,%%esp\n"); 335 } 336 337 #endif 338 /* 339 * Generate code to convert an unsigned long to xmm float/double. 340 */ 341 static void 342 ultofd(NODE *p) 343 { 344 345 #define E(x) expand(p, 0, x) 346 E(" movq AL,A1\n"); 347 E(" testq A1,A1\n"); 348 E(" js 2f\n"); 349 E(" cvtsi2sZfq A1,A3\n"); 350 E(" jmp 3f\n"); 351 E("2:\n"); 352 E(" movq A1,A2\n"); 353 E(" shrq A2\n"); 354 E(" andq $1,A1\n"); 355 E(" orq A1,A2\n"); 356 E(" cvtsi2sZfq A2,A3\n"); 357 E(" addsZf A3,A3\n"); 358 E("3:\n"); 359 #undef E 360 } 361 362 static int 363 argsiz(NODE *p) 364 { 365 TWORD t = p->n_type; 366 367 if (p->n_left->n_op == REG) 368 return 0; /* not on stack */ 369 if (t == LDOUBLE) 370 return 16; 371 if (t == STRTY || t == UNIONTY) 372 return p->n_stsize; 373 return 8; 374 } 375 376 void 377 zzzcode(NODE *p, int c) 378 { 379 NODE *l; 380 int pr, lr, s; 381 char **rt; 382 383 switch (c) { 384 #if 0 385 case 'A': /* swap st0 and st1 if right is evaluated second */ 386 if ((p->n_su & DORIGHT) == 0) { 387 if (logop(p->n_op)) 388 printf(" fxch\n"); 389 else 390 printf("r"); 391 } 392 break; 393 #endif 394 395 case 'C': /* remove from stack after subroutine call */ 396 pr = p->n_qual; 397 if (p->n_op == UCALL) 398 return; /* XXX remove ZC from UCALL */ 399 if (pr) 400 printf(" addq $%d, %s\n", pr, rnames[RSP]); 401 break; 402 403 case 'E': /* Perform bitfield sign-extension */ 404 bfext(p); 405 break; 406 407 #if 0 408 case 'F': /* Structure argument */ 409 if (p->n_stalign != 0) /* already on stack */ 410 starg(p); 411 break; 412 #endif 413 case 'j': /* convert unsigned long to f/d */ 414 ultofd(p); 415 break; 416 417 case 'M': /* Output sconv move, if needed */ 418 l = getlr(p, 'L'); 419 /* XXX fixneed: regnum */ 420 pr = DECRA(p->n_reg, 0); 421 lr = DECRA(l->n_reg, 0); 422 if (pr == lr) 423 break; 424 printf(" movb %s,%s\n", rbyte[lr], rbyte[pr]); 425 l->n_rval = l->n_reg = p->n_reg; /* XXX - not pretty */ 426 break; 427 428 #if 0 429 case 'N': /* output extended reg name */ 430 printf("%s", rnames[getlr(p, '1')->n_rval]); 431 break; 432 #endif 433 434 case 'P': /* Put hidden argument in rdi */ 435 printf("\tleaq -%d(%%rbp),%%rdi\n", stkpos); 436 break; 437 438 #if 0 439 440 case 'S': /* emit eventual move after cast from longlong */ 441 pr = DECRA(p->n_reg, 0); 442 lr = p->n_left->n_rval; 443 switch (p->n_type) { 444 case CHAR: 445 case UCHAR: 446 if (rnames[pr][2] == 'l' && rnames[lr][2] == 'x' && 447 rnames[pr][1] == rnames[lr][1]) 448 break; 449 if (rnames[lr][2] == 'x') { 450 printf("\tmovb %%%cl,%s\n", 451 rnames[lr][1], rnames[pr]); 452 break; 453 } 454 /* Must go via stack */ 455 s = BITOOR(freetemp(1)); 456 printf("\tmovl %%e%ci,%d(%%rbp)\n", rnames[lr][1], s); 457 printf("\tmovb %d(%%rbp),%s\n", s, rnames[pr]); 458 comperr("SCONV1 %s->%s", rnames[lr], rnames[pr]); 459 break; 460 461 case SHORT: 462 case USHORT: 463 if (rnames[lr][1] == rnames[pr][2] && 464 rnames[lr][2] == rnames[pr][3]) 465 break; 466 printf("\tmovw %%%c%c,%%%s\n", 467 rnames[lr][1], rnames[lr][2], rnames[pr]+2); 468 comperr("SCONV2 %s->%s", rnames[lr], rnames[pr]); 469 break; 470 case INT: 471 case UNSIGNED: 472 if (rnames[lr][1] == rnames[pr][2] && 473 rnames[lr][2] == rnames[pr][3]) 474 break; 475 printf("\tmovl %%e%c%c,%s\n", 476 rnames[lr][1], rnames[lr][2], rnames[pr]); 477 comperr("SCONV3 %s->%s", rnames[lr], rnames[pr]); 478 break; 479 480 default: 481 if (rnames[lr][1] == rnames[pr][2] && 482 rnames[lr][2] == rnames[pr][3]) 483 break; 484 comperr("SCONV4 %s->%s", rnames[lr], rnames[pr]); 485 break; 486 } 487 break; 488 #endif 489 case 'Q': /* emit struct assign */ 490 /* XXX - optimize for small structs */ 491 printf("\tmovq $%d,%%rdx\n", p->n_stsize); 492 expand(p, INAREG, "\tmovq AR,%rsi\n"); 493 expand(p, INAREG, "\tleaq AL,%rdi\n\n"); 494 printf("\tcall memcpy\n"); 495 break; 496 497 case 'R': /* print opname based on right type */ 498 case 'L': /* print opname based on left type */ 499 switch (getlr(p, c)->n_type) { 500 case CHAR: case UCHAR: s = 'b'; break; 501 case SHORT: case USHORT: s = 'w'; break; 502 case INT: case UNSIGNED: s = 'l'; break; 503 default: s = 'q'; break; 504 printf("%c", s); 505 } 506 break; 507 508 case '8': /* special reg name printout (64-bit) */ 509 case '1': /* special reg name printout (32-bit) */ 510 l = getlr(p, '1'); 511 rt = c == '8' ? rnames : rlong; 512 printf("%s", rt[l->n_rval]); 513 break; 514 515 case 'g': 516 p = p->n_left; 517 /* FALLTHROUGH */ 518 case 'f': /* float or double */ 519 printf("%c", p->n_type == FLOAT ? 's' : 'd'); 520 break; 521 522 case 'q': /* int or long */ 523 printf("%c", p->n_left->n_type == LONG ? 'q' : ' '); 524 break; 525 526 default: 527 comperr("zzzcode %c", c); 528 } 529 } 530 531 /*ARGSUSED*/ 532 int 533 rewfld(NODE *p) 534 { 535 return(1); 536 } 537 538 int canaddr(NODE *); 539 int 540 canaddr(NODE *p) 541 { 542 int o = p->n_op; 543 544 if (o==NAME || o==REG || o==ICON || o==OREG || 545 (o==UMUL && shumul(p->n_left, SOREG))) 546 return(1); 547 return(0); 548 } 549 550 /* 551 * Does the bitfield shape match? 552 */ 553 int 554 flshape(NODE *p) 555 { 556 int o = p->n_op; 557 558 if (o == OREG || o == REG || o == NAME) 559 return SRDIR; /* Direct match */ 560 if (o == UMUL && shumul(p->n_left, SOREG)) 561 return SROREG; /* Convert into oreg */ 562 return SRREG; /* put it into a register */ 563 } 564 565 /* INTEMP shapes must not contain any temporary registers */ 566 /* XXX should this go away now? */ 567 int 568 shtemp(NODE *p) 569 { 570 return 0; 571 #if 0 572 int r; 573 574 if (p->n_op == STARG ) 575 p = p->n_left; 576 577 switch (p->n_op) { 578 case REG: 579 return (!istreg(p->n_rval)); 580 581 case OREG: 582 r = p->n_rval; 583 if (R2TEST(r)) { 584 if (istreg(R2UPK1(r))) 585 return(0); 586 r = R2UPK2(r); 587 } 588 return (!istreg(r)); 589 590 case UMUL: 591 p = p->n_left; 592 return (p->n_op != UMUL && shtemp(p)); 593 } 594 595 if (optype(p->n_op) != LTYPE) 596 return(0); 597 return(1); 598 #endif 599 } 600 601 void 602 adrcon(CONSZ val) 603 { 604 printf("$" CONFMT, val); 605 } 606 607 void 608 conput(FILE *fp, NODE *p) 609 { 610 long val = p->n_lval; 611 612 switch (p->n_op) { 613 case ICON: 614 if (p->n_name[0] != '\0') { 615 fprintf(fp, "%s", p->n_name); 616 if (val) 617 fprintf(fp, "+%ld", val); 618 } else 619 fprintf(fp, "%ld", val); 620 return; 621 622 default: 623 comperr("illegal conput, p %p", p); 624 } 625 } 626 627 /*ARGSUSED*/ 628 void 629 insput(NODE *p) 630 { 631 comperr("insput"); 632 } 633 634 /* 635 * Write out the upper address, like the upper register of a 2-register 636 * reference, or the next memory location. 637 * XXX - not needed on amd64 638 */ 639 void 640 upput(NODE *p, int size) 641 { 642 643 size /= SZCHAR; 644 switch (p->n_op) { 645 case REG: 646 fprintf(stdout, "%%%s", &rnames[p->n_rval][3]); 647 break; 648 649 case NAME: 650 case OREG: 651 p->n_lval += size; 652 adrput(stdout, p); 653 p->n_lval -= size; 654 break; 655 case ICON: 656 fprintf(stdout, "$" CONFMT, p->n_lval >> 32); 657 break; 658 default: 659 comperr("upput bad op %d size %d", p->n_op, size); 660 } 661 } 662 663 void 664 adrput(FILE *io, NODE *p) 665 { 666 int r; 667 char **rc; 668 /* output an address, with offsets, from p */ 669 670 if (p->n_op == FLD) 671 p = p->n_left; 672 673 switch (p->n_op) { 674 675 case NAME: 676 if (p->n_name[0] != '\0') { 677 fputs(p->n_name, io); 678 if (p->n_lval != 0) 679 fprintf(io, "+" CONFMT, p->n_lval); 680 } else 681 fprintf(io, CONFMT, p->n_lval); 682 return; 683 684 case OREG: 685 r = p->n_rval; 686 if (p->n_name[0]) 687 printf("%s%s", p->n_name, p->n_lval ? "+" : ""); 688 if (p->n_lval) 689 fprintf(io, "%lld", p->n_lval); 690 if (R2TEST(r)) { 691 int r1 = R2UPK1(r); 692 int r2 = R2UPK2(r); 693 int sh = R2UPK3(r); 694 695 fprintf(io, "(%s,%s,%d)", 696 r1 == MAXREGS ? "" : rnames[r1], 697 r2 == MAXREGS ? "" : rnames[r2], sh); 698 } else 699 fprintf(io, "(%s)", rnames[p->n_rval]); 700 return; 701 case ICON: 702 #ifdef PCC_DEBUG 703 /* Sanitycheck for PIC, to catch adressable constants */ 704 if (kflag && p->n_name[0]) { 705 static int foo; 706 707 if (foo++ == 0) { 708 printf("\nfailing...\n"); 709 fwalk(p, e2print, 0); 710 comperr("pass2 conput"); 711 } 712 } 713 #endif 714 /* addressable value of the constant */ 715 fputc('$', io); 716 conput(io, p); 717 return; 718 719 case REG: 720 switch (p->n_type) { 721 case CHAR: 722 case UCHAR: 723 rc = rbyte; 724 break; 725 case SHORT: 726 case USHORT: 727 rc = rshort; 728 break; 729 case INT: 730 case UNSIGNED: 731 rc = rlong; 732 break; 733 default: 734 rc = rnames; 735 break; 736 } 737 fprintf(io, "%s", rc[p->n_rval]); 738 return; 739 740 default: 741 comperr("illegal address, op %d, node %p", p->n_op, p); 742 return; 743 744 } 745 } 746 747 static char * 748 ccbranches[] = { 749 "je", /* jumpe */ 750 "jne", /* jumpn */ 751 "jle", /* jumple */ 752 "jl", /* jumpl */ 753 "jge", /* jumpge */ 754 "jg", /* jumpg */ 755 "jbe", /* jumple (jlequ) */ 756 "jb", /* jumpl (jlssu) */ 757 "jae", /* jumpge (jgequ) */ 758 "ja", /* jumpg (jgtru) */ 759 }; 760 761 762 /* printf conditional and unconditional branches */ 763 void 764 cbgen(int o, int lab) 765 { 766 if (o < EQ || o > UGT) 767 comperr("bad conditional branch: %s", opst[o]); 768 printf(" %s " LABFMT "\n", ccbranches[o-EQ], lab); 769 } 770 771 static void 772 fixcalls(NODE *p, void *arg) 773 { 774 /* Prepare for struct return by allocating bounce space on stack */ 775 switch (p->n_op) { 776 case STCALL: 777 case USTCALL: 778 if (p->n_stsize+p2autooff > stkpos) 779 stkpos = p->n_stsize+p2autooff; 780 break; 781 } 782 } 783 784 void 785 myreader(struct interpass *ipole) 786 { 787 struct interpass *ip; 788 789 stkpos = p2autooff; 790 DLIST_FOREACH(ip, ipole, qelem) { 791 if (ip->type != IP_NODE) 792 continue; 793 walkf(ip->ip_node, fixcalls, 0); 794 } 795 if (stkpos > p2autooff) 796 p2autooff = stkpos; 797 if (stkpos > p2maxautooff) 798 p2maxautooff = stkpos; 799 if (x2debug) 800 printip(ipole); 801 } 802 803 /* 804 * Remove some PCONVs after OREGs are created. 805 */ 806 static void 807 pconv2(NODE *p, void *arg) 808 { 809 NODE *q; 810 811 if (p->n_op == PLUS) { 812 if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) { 813 if (p->n_right->n_op != ICON) 814 return; 815 if (p->n_left->n_op != PCONV) 816 return; 817 if (p->n_left->n_left->n_op != OREG) 818 return; 819 q = p->n_left->n_left; 820 nfree(p->n_left); 821 p->n_left = q; 822 /* 823 * This will be converted to another OREG later. 824 */ 825 } 826 } 827 } 828 829 void 830 mycanon(NODE *p) 831 { 832 walkf(p, pconv2, 0); 833 } 834 835 void 836 myoptim(struct interpass *ip) 837 { 838 } 839 840 void 841 rmove(int s, int d, TWORD t) 842 { 843 844 switch (t) { 845 case INT: 846 case UNSIGNED: 847 printf(" movl %s,%s\n", rlong[s], rlong[d]); 848 break; 849 case CHAR: 850 case UCHAR: 851 printf(" movb %s,%s\n", rbyte[s], rbyte[d]); 852 break; 853 case SHORT: 854 case USHORT: 855 printf(" movw %s,%s\n", rshort[s], rshort[d]); 856 break; 857 case FLOAT: 858 printf(" movss %s,%s\n", rnames[s], rnames[d]); 859 break; 860 case DOUBLE: 861 printf(" movsd %s,%s\n", rnames[s], rnames[d]); 862 break; 863 case LDOUBLE: 864 /* a=b()*c(); will generate this */ 865 comperr("bad float rmove: %d %d", s, d); 866 break; 867 default: 868 printf(" movq %s,%s\n", rnames[s], rnames[d]); 869 break; 870 } 871 } 872 873 /* 874 * For class c, find worst-case displacement of the number of 875 * registers in the array r[] indexed by class. 876 */ 877 int 878 COLORMAP(int c, int *r) 879 { 880 881 switch (c) { 882 case CLASSA: 883 return r[CLASSA] < 14; 884 case CLASSB: 885 return r[CLASSB] < 16; 886 } 887 return 0; /* XXX gcc */ 888 } 889 890 char *rnames[] = { 891 "%rax", "%rdx", "%rcx", "%rbx", "%rsi", "%rdi", "%rbp", "%rsp", 892 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", 893 "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", 894 "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", 895 "%xmm15", 896 }; 897 898 /* register names for shorter sizes */ 899 char *rbyte[] = { 900 "%al", "%dl", "%cl", "%bl", "%sil", "%dil", "%bpl", "%spl", 901 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b", 902 }; 903 char *rshort[] = { 904 "%ax", "%dx", "%cx", "%bx", "%si", "%di", "%bp", "%sp", 905 "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w", 906 }; 907 char *rlong[] = { 908 "%eax", "%edx", "%ecx", "%ebx", "%esi", "%edi", "%ebp", "%esp", 909 "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d", 910 }; 911 912 913 /* 914 * Return a class suitable for a specific type. 915 */ 916 int 917 gclass(TWORD t) 918 { 919 if (t == FLOAT || t == DOUBLE || t == LDOUBLE) 920 return CLASSB; 921 return CLASSA; 922 } 923 924 /* 925 * Calculate argument sizes. 926 */ 927 void 928 lastcall(NODE *p) 929 { 930 NODE *op = p; 931 int size = 0; 932 933 p->n_qual = 0; 934 if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL) 935 return; 936 for (p = p->n_right; p->n_op == CM; p = p->n_left) 937 size += argsiz(p->n_right); 938 size += argsiz(p); 939 size = (size+15) & ~15; 940 if (size) 941 printf(" subq $%d,%s\n", size, rnames[RSP]); 942 op->n_qual = size; /* XXX */ 943 } 944 945 /* 946 * Special shapes. 947 */ 948 int 949 special(NODE *p, int shape) 950 { 951 int o = p->n_op; 952 953 switch (shape) { 954 case SFUNCALL: 955 if (o == STCALL || o == USTCALL) 956 return SRREG; 957 break; 958 case SPCON: 959 if (o != ICON || p->n_name[0] || 960 p->n_lval < 0 || p->n_lval > 0x7fffffff) 961 break; 962 return SRDIR; 963 case SMIXOR: 964 return tshape(p, SZERO); 965 case SMILWXOR: 966 if (o != ICON || p->n_name[0] || 967 p->n_lval == 0 || p->n_lval & 0xffffffff) 968 break; 969 return SRDIR; 970 case SMIHWXOR: 971 if (o != ICON || p->n_name[0] || 972 p->n_lval == 0 || (p->n_lval >> 32) != 0) 973 break; 974 return SRDIR; 975 case SCON32: 976 if (o != ICON || p->n_name[0]) 977 break; 978 if (p->n_lval < MIN_INT || p->n_lval > MAX_INT) 979 break; 980 return SRDIR; 981 default: 982 cerror("special: %x\n", shape); 983 } 984 return SRNOPE; 985 } 986 987 /* 988 * Target-dependent command-line options. 989 */ 990 void 991 mflags(char *str) 992 { 993 } 994 995 /* 996 * Do something target-dependent for xasm arguments. 997 */ 998 int 999 myxasm(struct interpass *ip, NODE *p) 1000 { 1001 return 0; 1002 #if 0 1003 struct interpass *ip2; 1004 NODE *in = 0, *ut = 0; 1005 TWORD t; 1006 char *w; 1007 int reg; 1008 int cw; 1009 1010 cw = xasmcode(p->n_name); 1011 if (cw & (XASMASG|XASMINOUT)) 1012 ut = p->n_left; 1013 if ((cw & XASMASG) == 0) 1014 in = p->n_left; 1015 1016 switch (XASMVAL(cw)) { 1017 case 'D': reg = EDI; break; 1018 case 'S': reg = ESI; break; 1019 case 'a': reg = EAX; break; 1020 case 'b': reg = EBX; break; 1021 case 'c': reg = ECX; break; 1022 case 'd': reg = EDX; break; 1023 case 't': reg = 0; break; 1024 case 'u': reg = 1; break; 1025 case 'A': reg = EAXEDX; break; 1026 case 'q': /* XXX let it be CLASSA as for now */ 1027 p->n_name = tmpstrdup(p->n_name); 1028 w = strchr(p->n_name, 'q'); 1029 *w = 'r'; 1030 return 0; 1031 default: 1032 return 0; 1033 } 1034 p->n_name = tmpstrdup(p->n_name); 1035 for (w = p->n_name; *w; w++) 1036 ; 1037 w[-1] = 'r'; /* now reg */ 1038 t = p->n_left->n_type; 1039 if (reg == EAXEDX) { 1040 p->n_label = CLASSC; 1041 } else { 1042 p->n_label = CLASSA; 1043 if (t == CHAR || t == UCHAR) { 1044 p->n_label = CLASSB; 1045 reg = reg * 2 + 8; 1046 } 1047 } 1048 if (t == FLOAT || t == DOUBLE || t == LDOUBLE) { 1049 p->n_label = CLASSD; 1050 reg += 037; 1051 } 1052 1053 if (in && ut) 1054 in = tcopy(in); 1055 p->n_left = mklnode(REG, 0, reg, t); 1056 if (ut) { 1057 ip2 = ipnode(mkbinode(ASSIGN, ut, tcopy(p->n_left), t)); 1058 DLIST_INSERT_AFTER(ip, ip2, qelem); 1059 } 1060 if (in) { 1061 ip2 = ipnode(mkbinode(ASSIGN, tcopy(p->n_left), in, t)); 1062 DLIST_INSERT_BEFORE(ip, ip2, qelem); 1063 } 1064 #endif 1065 return 1; 1066 } 1067 1068 void 1069 targarg(char *w, void *arg) 1070 { 1071 cerror("targarg"); 1072 #if 0 1073 NODE **ary = arg; 1074 NODE *p, *q; 1075 1076 p = ary[(int)w[1]-'0']->n_left; 1077 if (optype(p->n_op) != LTYPE) 1078 comperr("bad xarg op %d", p->n_op); 1079 q = tcopy(p); 1080 if (q->n_op == REG) { 1081 if (*w == 'k') { 1082 q->n_type = INT; 1083 } else if (*w != 'w') { 1084 if (q->n_type > UCHAR) { 1085 regno(q) = regno(q)*2+8; 1086 if (*w == 'h') 1087 regno(q)++; 1088 } 1089 q->n_type = INT; 1090 } else 1091 q->n_type = SHORT; 1092 } 1093 adrput(stdout, q); 1094 tfree(q); 1095 #endif 1096 } 1097 1098 /* 1099 * target-specific conversion of numeric arguments. 1100 */ 1101 int 1102 numconv(void *ip, void *p1, void *q1) 1103 { 1104 NODE *p = p1, *q = q1; 1105 int cw = xasmcode(q->n_name); 1106 1107 switch (XASMVAL(cw)) { 1108 case 'a': 1109 case 'b': 1110 case 'c': 1111 case 'd': 1112 p->n_name = tmpcalloc(2); 1113 p->n_name[0] = XASMVAL(cw); 1114 return 1; 1115 default: 1116 return 0; 1117 } 1118 } 1119