1 /* Id: local2.c,v 1.40 2008/11/22 16:12:24 ragge Exp */ 2 /* $NetBSD: local2.c,v 1.1.1.3 2010/06/03 18:57:17 plunky Exp $ */ 3 /* 4 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 31 # include "pass2.h" 32 # include <ctype.h> 33 34 void acon(NODE *p); 35 int argsize(NODE *p); 36 void genargs(NODE *p); 37 38 static int ftlab1, ftlab2; 39 40 void 41 deflab(int label) 42 { 43 printf(LABFMT ":\n", label); 44 } 45 46 static TWORD ftype; 47 static int addto; 48 49 void 50 prologue(struct interpass_prolog *ipp) 51 { 52 ftype = ipp->ipp_type; 53 54 #if 0 55 if (ipp->ipp_regs > 0 && ipp->ipp_regs != MINRVAR) 56 comperr("fix prologue register savings", ipp->ipp_regs); 57 #endif 58 59 printf(" RSEG CODE:CODE:REORDER:NOROOT(0)\n"); 60 if (ipp->ipp_vis) 61 printf(" PUBLIC %s\n", ipp->ipp_name); 62 printf("%s:\n", ipp->ipp_name); 63 64 #if 0 65 if (xsaveip) { 66 /* Optimizer running, save space on stack */ 67 addto = (p2maxautooff - AUTOINIT)/SZCHAR; 68 printf(" enter #%d\n", addto); 69 } else { 70 #endif 71 72 /* non-optimized code, jump to epilogue for code generation */ 73 ftlab1 = getlab2(); 74 ftlab2 = getlab2(); 75 printf(" jmp.w " LABFMT "\n", ftlab1); 76 deflab(ftlab2); 77 } 78 79 /* 80 * End of block. 81 */ 82 void 83 eoftn(struct interpass_prolog *ipp) 84 { 85 #if 0 86 if (ipp->ipp_regs != MINRVAR) 87 comperr("fix eoftn register savings %x", ipp->ipp_regs); 88 #endif 89 90 // if (xsaveip == 0) 91 addto = (p2maxautooff - AUTOINIT)/SZCHAR; 92 93 /* return from function code */ 94 //deflab(ipp->ipp_ip.ip_lbl); //XXX - is this necessary? 95 96 /* If retval is a pointer and not a function pointer, put in A0 */ 97 if (ISPTR(DECREF(ipp->ipp_type)) && 98 !ISFTN(DECREF(DECREF(ipp->ipp_type)))) 99 printf(" mov.w r0,a0\n"); 100 101 /* struct return needs special treatment */ 102 if (ftype == STRTY || ftype == UNIONTY) { 103 comperr("fix struct return in eoftn"); 104 } else 105 printf(" exitd\n"); 106 107 /* Prolog code */ 108 // if (xsaveip == 0) { 109 deflab(ftlab1); 110 printf(" enter #%d\n", addto); 111 printf(" jmp.w " LABFMT "\n", ftlab2); 112 //} 113 } 114 115 /* 116 * add/sub/... 117 * 118 * Param given: 119 */ 120 void 121 hopcode(int f, int o) 122 { 123 char *str; 124 125 switch (o) { 126 case PLUS: 127 str = "add"; 128 break; 129 case MINUS: 130 str = "sub"; 131 break; 132 case AND: 133 str = "and"; 134 break; 135 case OR: 136 str = "or"; 137 break; 138 case ER: 139 str = "xor"; 140 break; 141 default: 142 comperr("hopcode2: %d", o); 143 str = 0; /* XXX gcc */ 144 } 145 printf("%s.%c", str, f); 146 } 147 148 char * 149 rnames[] = { /* keyed to register number tokens */ 150 "r0", "r2", "r1", "r3", "a0", "a1", "fb", "sp", "r0h", "r0l", 151 "r1h", "r1l", 152 }; 153 154 /* 155 * Return the size (in bytes) of some types. 156 */ 157 int 158 tlen(p) NODE *p; 159 { 160 switch(p->n_type) { 161 case CHAR: 162 case UCHAR: 163 return(1); 164 165 case INT: 166 case UNSIGNED: 167 case FLOAT: 168 return 2; 169 170 case DOUBLE: 171 case LONG: 172 case ULONG: 173 return 4; 174 175 default: 176 if (!ISPTR(p->n_type)) 177 comperr("tlen type %d not pointer"); 178 return SZPOINT(p->n_type)/SZCHAR; 179 } 180 } 181 182 /* 183 * Emit code to compare two longlong numbers. 184 */ 185 static void 186 twollcomp(NODE *p) 187 { 188 int o = p->n_op; 189 int s = getlab2(); 190 int e = p->n_label; 191 int cb1, cb2; 192 193 if (o >= ULE) 194 o -= (ULE-LE); 195 switch (o) { 196 case NE: 197 cb1 = 0; 198 cb2 = NE; 199 break; 200 case EQ: 201 cb1 = NE; 202 cb2 = 0; 203 break; 204 case LE: 205 case LT: 206 cb1 = GT; 207 cb2 = LT; 208 break; 209 case GE: 210 case GT: 211 cb1 = LT; 212 cb2 = GT; 213 break; 214 215 default: 216 cb1 = cb2 = 0; /* XXX gcc */ 217 } 218 if (p->n_op >= ULE) 219 cb1 += 4, cb2 += 4; 220 expand(p, 0, " cmp.w UR,UL\n"); 221 if (cb1) cbgen(cb1, s); 222 if (cb2) cbgen(cb2, e); 223 expand(p, 0, " cmp.w AR,AL\n"); 224 cbgen(p->n_op, e); 225 deflab(s); 226 } 227 228 229 void 230 zzzcode(NODE *p, int c) 231 { 232 NODE *l; 233 234 switch (c) { 235 case 'A': /* print negative shift constant */ 236 p = getlr(p, 'R'); 237 if (p->n_op != ICON) 238 comperr("ZA bad use"); 239 p->n_lval = -p->n_lval; 240 adrput(stdout, p); 241 p->n_lval = -p->n_lval; 242 break; 243 244 case 'B': 245 if (p->n_rval) 246 printf(" add.b #%d,%s\n", 247 p->n_rval, rnames[STKREG]); 248 break; 249 250 case 'C': /* Print label address */ 251 p = p->n_left; 252 if (p->n_lval) 253 printf(LABFMT, (int)p->n_lval); 254 else 255 printf("%s", p->n_name); 256 break; 257 258 case 'D': /* copy function pointers */ 259 l = p->n_left; 260 printf("\tmov.w #HWRD(%s),%s\n\tmov.w #LWRD(%s),%s\n", 261 p->n_right->n_name, rnames[l->n_rval+1], 262 p->n_right->n_name, rnames[l->n_rval]); 263 break; 264 265 case 'E': /* double-reg printout */ 266 /* XXX - always r0r2 here */ 267 printf("%s%s", rnames[R0], rnames[R2]); 268 break; 269 270 case 'F': /* long comparisions */ 271 twollcomp(p); 272 break; 273 274 case 'G': 275 printf("R0R2"); 276 break; 277 278 case 'H': /* push 32-bit address (for functions) */ 279 printf("\tpush.w #HWRD(%s)\n\tpush.w #LWRD(%s)\n", 280 p->n_left->n_name, p->n_left->n_name); 281 break; 282 283 case 'I': /* push 32-bit address (for functions) */ 284 l = p->n_left; 285 printf("\tpush.w %d[%s]\n\tpush.w %d[%s]\n", 286 (int)l->n_lval, rnames[l->n_rval], 287 (int)l->n_lval+2, rnames[l->n_rval]); 288 break; 289 290 default: 291 comperr("bad zzzcode %c", c); 292 } 293 } 294 295 /*ARGSUSED*/ 296 int 297 rewfld(NODE *p) 298 { 299 return(1); 300 } 301 302 int canaddr(NODE *); 303 int 304 canaddr(NODE *p) 305 { 306 int o = p->n_op; 307 308 if (o==NAME || o==REG || o==ICON || o==OREG || 309 (o==UMUL && shumul(p->n_left, SOREG) == SRDIR)) 310 return(1); 311 return(0); 312 } 313 314 int 315 fldexpand(NODE *p, int cookie, char **cp) 316 { 317 return 0; 318 } 319 320 /* 321 * Does the bitfield shape match? 322 */ 323 int 324 flshape(NODE *p) 325 { 326 int o = p->n_op; 327 328 if (o == OREG || o == REG || o == NAME) 329 return SRDIR; /* Direct match */ 330 if (o == UMUL && shumul(p->n_left, SOREG)) 331 return SROREG; /* Convert into oreg */ 332 return SRREG; /* put it into a register */ 333 } 334 335 /* INTEMP shapes must not contain any temporary registers */ 336 /* XXX should this go away now? */ 337 int 338 shtemp(NODE *p) 339 { 340 return 0; 341 } 342 343 void 344 adrcon(CONSZ val) 345 { 346 printf("$" CONFMT, val); 347 } 348 349 void 350 conput(FILE *fp, NODE *p) 351 { 352 int val = p->n_lval; 353 354 switch (p->n_op) { 355 case ICON: 356 if (p->n_name[0] != '\0') { 357 fprintf(fp, "%s", p->n_name); 358 if (val) 359 fprintf(fp, "+%d", val); 360 } else 361 fprintf(fp, "%d", val); 362 return; 363 364 default: 365 comperr("illegal conput"); 366 } 367 } 368 369 /*ARGSUSED*/ 370 void 371 insput(NODE *p) 372 { 373 comperr("insput"); 374 } 375 376 /* 377 * Write out the upper address, like the upper register of a 2-register 378 * reference, or the next memory location. 379 */ 380 void 381 upput(NODE *p, int size) 382 { 383 384 size /= SZINT; 385 switch (p->n_op) { 386 case REG: 387 fputs(rnames[p->n_rval + 1], stdout); 388 break; 389 390 case NAME: 391 case OREG: 392 p->n_lval += size; 393 adrput(stdout, p); 394 p->n_lval -= size; 395 break; 396 case ICON: 397 fprintf(stdout, "#" CONFMT, p->n_lval >> 16); 398 break; 399 default: 400 comperr("upput bad op %d size %d", p->n_op, size); 401 } 402 } 403 404 void 405 adrput(FILE *io, NODE *p) 406 { 407 /* output an address, with offsets, from p */ 408 409 if (p->n_op == FLD) 410 p = p->n_left; 411 412 switch (p->n_op) { 413 414 case NAME: 415 if (p->n_name[0] != '\0') 416 fputs(p->n_name, io); 417 if (p->n_lval != 0) 418 fprintf(io, "+" CONFMT, p->n_lval); 419 return; 420 421 case OREG: 422 if (p->n_lval) 423 fprintf(io, "%d", (int)p->n_lval); 424 fprintf(io, "[%s]", rnames[p->n_rval]); 425 return; 426 case ICON: 427 /* addressable value of the constant */ 428 fputc('#', io); 429 conput(io, p); 430 return; 431 432 case REG: 433 /*if (DEUNSIGN(p->n_type) == CHAR) { 434 fprintf(io, "R%c%c", p->n_rval < 2 ? '0' : '1', 435 (p->n_rval & 1) ? 'H' : 'L'); 436 } else*/ 437 fprintf(io, "%s", rnames[p->n_rval]); 438 return; 439 440 default: 441 comperr("illegal address, op %d, node %p", p->n_op, p); 442 return; 443 444 } 445 } 446 447 static char * 448 ccbranches[] = { 449 "jeq", /* jumpe */ 450 "jne", /* jumpn */ 451 "jle", /* jumple */ 452 "jlt", /* jumpl */ 453 "jge", /* jumpge */ 454 "jgt", /* jumpg */ 455 "jleu", /* jumple (jlequ) */ 456 "jltu", /* jumpl (jlssu) */ 457 "jgeu", /* jumpge (jgequ) */ 458 "jgtu", /* jumpg (jgtru) */ 459 }; 460 461 462 /* printf conditional and unconditional branches */ 463 void 464 cbgen(int o, int lab) 465 { 466 if (o < EQ || o > UGT) 467 comperr("bad conditional branch: %s", opst[o]); 468 printf(" %s " LABFMT "\n", ccbranches[o-EQ], lab); 469 } 470 471 void 472 mycanon(NODE *p) 473 { 474 } 475 476 void 477 myoptim(struct interpass *ip) 478 { 479 } 480 481 #if 0 482 void 483 mygenregs(NODE *p) 484 { 485 486 if (p->n_op == MINUS && p->n_type == DOUBLE && 487 (p->n_su & (LMASK|RMASK)) == (LREG|RREG)) { 488 p->n_su |= DORIGHT; 489 } 490 /* Must walk down correct node first for logops to work */ 491 if (p->n_op != CBRANCH) 492 return; 493 p = p->n_left; 494 if ((p->n_su & (LMASK|RMASK)) != (LREG|RREG)) 495 return; 496 p->n_su &= ~DORIGHT; 497 498 } 499 #endif 500 501 struct hardops hardops[] = { 502 { PLUS, FLOAT, "?F_ADD_L04" }, 503 { MUL, LONG, "?L_MUL_L03" }, 504 { MUL, ULONG, "?L_MUL_L03" }, 505 { DIV, LONG, "?SL_DIV_L03" }, 506 { DIV, ULONG, "?UL_DIV_L03" }, 507 { MOD, LONG, "?SL_MOD_L03" }, 508 { MOD, ULONG, "?UL_MOD_L03" }, 509 { RS, LONGLONG, "__ashrdi3" }, 510 { RS, ULONGLONG, "__lshrdi3" }, 511 { LS, LONGLONG, "__ashldi3" }, 512 { LS, ULONGLONG, "__ashldi3" }, 513 { 0 }, 514 }; 515 516 int 517 special(NODE *p, int shape) 518 { 519 switch (shape) { 520 case SFTN: 521 if (ISPTR(p->n_type) && ISFTN(DECREF(p->n_type))) { 522 if (p->n_op == NAME || p->n_op == OREG) 523 return SRDIR; 524 else 525 return SRREG; 526 } 527 break; 528 } 529 return SRNOPE; 530 } 531 532 void 533 myreader(NODE *p) 534 { 535 NODE *q, *r, *s, *right; 536 537 if (optype(p->n_op) == LTYPE) 538 return; 539 if (optype(p->n_op) != UTYPE) 540 myreader(p->n_right); 541 myreader(p->n_left); 542 543 switch (p->n_op) { 544 case PLUS: 545 case MINUS: 546 if (p->n_type != LONG && p->n_type != ULONG) 547 break; 548 if (p->n_right->n_op == NAME || p->n_right->n_op == OREG) 549 break; 550 /* Must convert right into OREG */ 551 right = p->n_right; 552 q = mklnode(OREG, BITOOR(freetemp(szty(right->n_type))), 553 FPREG, right->n_type); 554 s = mkbinode(ASSIGN, q, right, right->n_type); 555 r = talloc(); 556 *r = *q; 557 p->n_right = r; 558 pass2_compile(ipnode(s)); 559 break; 560 } 561 } 562 563 564 void 565 rmove(int s, int d, TWORD t) 566 { 567 switch (t) { 568 case CHAR: 569 case UCHAR: 570 printf(" mov.b %s,%s\n", rnames[s], rnames[d]); 571 break; 572 default: 573 printf(" mov.w %s,%s\n", rnames[s], rnames[d]); 574 } 575 } 576 577 /* 578 * For class c, find worst-case displacement of the number of 579 * registers in the array r[] indexed by class. 580 */ 581 int 582 COLORMAP(int c, int *r) 583 { 584 int num; 585 586 switch (c) { 587 case CLASSA: 588 num = r[CLASSA]; 589 num += r[CLASSC]; 590 return num < 4; 591 case CLASSB: 592 num = r[CLASSB]; 593 return num < 2; 594 case CLASSC: 595 num = 2*r[CLASSA]; 596 num += r[CLASSC]; 597 return num < 4; 598 } 599 return 0; /* XXX gcc */ 600 } 601 602 /* 603 * Return a class suitable for a specific type. 604 */ 605 int 606 gclass(TWORD t) 607 { 608 if (t == CHAR || t == UCHAR) 609 return CLASSC; 610 611 if(ISPTR(t)) 612 return CLASSB; 613 614 return CLASSA; 615 } 616 617 static int sizen; 618 619 /* XXX: Fix this. */ 620 static int 621 argsiz(NODE *p) 622 { 623 TWORD t = p->n_type; 624 625 if (t < LONGLONG || t > MAXTYPES) 626 return 4; 627 if (t == LONGLONG || t == ULONGLONG || t == DOUBLE) 628 return 8; 629 if (t == LDOUBLE) 630 return 12; 631 if (t == STRTY) 632 return p->n_stsize; 633 comperr("argsiz"); 634 return 0; 635 } 636 637 /* 638 * Calculate argument sizes. 639 * XXX: Fix this. 640 */ 641 void 642 lastcall(NODE *p) 643 { 644 sizen = 0; 645 for (p = p->n_right; p->n_op == CM; p = p->n_left) 646 sizen += argsiz(p->n_right); 647 sizen += argsiz(p); 648 } 649 650 /* 651 * Target-dependent command-line options. 652 */ 653 void 654 mflags(char *str) 655 { 656 } 657 /* 658 * Do something target-dependent for xasm arguments. 659 * Supposed to find target-specific constraints and rewrite them. 660 */ 661 int 662 myxasm(struct interpass *ip, NODE *p) 663 { 664 return 0; 665 } 666