1: /*
   2:  *		C compiler, part 2
   3:  *
   4:  * (long)btodb(l) produced 'no code table error for op: >>(17) type: 6'
   5:  * allow both long and ulong at line ~341.  1996/6/19
   6: */
   7: 
   8: #if !defined(lint) && defined(DOSCCS)
   9: static  char    sccsid[] = "@(#)c10.c	2.1 (2.11BSD GTE) 10/4/94";
  10: #endif
  11: 
  12: #include "c1.h"
  13: 
  14: #ifdef  DEBUG
  15: #define dbprint(op) printf("	/ %s", opntab[op])
  16: #else
  17: #define dbprint(op) /* */
  18: #endif
  19: 
  20: static int debug = 0;
  21: 
  22: char    maprel[] = {    EQUAL, NEQUAL, GREATEQ, GREAT, LESSEQ,
  23:             LESS, GREATQP, GREATP, LESSEQP, LESSP
  24: };
  25: 
  26: char    notrel[] = {    NEQUAL, EQUAL, GREAT, GREATEQ, LESS,
  27:             LESSEQ, GREATP, GREATQP, LESSP, LESSEQP
  28: };
  29: 
  30: struct tconst czero = { CON, INT, 0};
  31: struct tconst cone  = { CON, INT, 1};
  32: 
  33: struct tname sfuncr = { NAME, STRUCT, STATIC, 0, 0, 0 };
  34: 
  35: struct  table   *cregtab;
  36: 
  37: int nreg    = 3;
  38: int isn = 10000;
  39: 
  40: main(argc, argv)
  41: int argc;
  42: char    *argv[];
  43: {
  44:     char    buf1[BUFSIZ],
  45:         buf2[BUFSIZ];
  46: 
  47:     if (argc<4) {
  48:         error("Arg count");
  49:         exit(1);
  50:     }
  51:     if (freopen(argv[1], "r", stdin)==NULL) {
  52:         error("Missing temp file");
  53:         exit(1);
  54:     }
  55:     setbuf(stdin,buf1); /* sbrk problems */
  56:     if ((freopen(argv[3], "w", stdout)) == NULL) {
  57:         error("Can't create %s", argv[3]);
  58:         exit(1);
  59:     }
  60:     setbuf(stdout,buf2);    /* sbrk problems */
  61:     funcbase = curbase = coremax = sbrk(0);
  62:     getree();
  63:     /*
  64: 	 * If any floating-point instructions
  65: 	 * were used, generate a reference that
  66: 	 * pulls in the floating-point part of printf.
  67: 	 */
  68:     if (nfloat)
  69:         printf(".globl	fltused\n");
  70:     /*
  71: 	 * tack on the string file.
  72: 	 */
  73:     printf(".globl\n.data\n");
  74:     if (*argv[2] != '-') {
  75:         if (freopen(argv[2], "r", stdin)==NULL) {
  76:             error("Missing temp file");
  77:             exit(1);
  78:         }
  79:         setbuf(stdin,buf1); /* sbrk problems */
  80:         getree();
  81:     }
  82:     if (totspace >= (unsigned)56000)
  83:         werror("possibly too much data");
  84:     exit(nerror!=0);
  85: }
  86: 
  87: /*
  88:  * Given a tree, a code table, and a
  89:  * count of available registers, find the code table
  90:  * for the appropriate operator such that the operands
  91:  * are of the right type and the number of registers
  92:  * required is not too large.
  93:  * Return a ptr to the table entry or 0 if none found.
  94:  */
  95: struct optab *
  96: match(tree, table, nrleft, nocvt)
  97: union tree *tree;
  98: struct table *table;
  99: {
 100: #define NOCVL   1
 101: #define NOCVR   2
 102:     int op, d1, d2, dope;
 103:     union tree *p2;
 104:     register union tree *p1;
 105:     register struct optab *opt;
 106: 
 107:     if (tree==NULL)
 108:         return(NULL);
 109:     if (table==lsptab)
 110:         table = sptab;
 111:     if ((op = tree->t.op)==0)
 112:         return(0);
 113:     dope = opdope[op];
 114:     if ((dope&LEAF) == 0)
 115:         p1 = tree->t.tr1;
 116:     else
 117:         p1 = tree;
 118:     d1 = dcalc(p1, nrleft);
 119:     if ((dope&BINARY)!=0) {
 120:         p2 = tree->t.tr2;
 121:         /*
 122: 		 * If a subtree starts off with a conversion operator,
 123: 		 * try for a match with the conversion eliminated.
 124: 		 * E.g. int = double can be done without generating
 125: 		 * the converted int in a register by
 126: 		 * movf double,fr0; movfi fr0,int .
 127: 		 */
 128:         if (opdope[p2->t.op]&CNVRT && (nocvt&NOCVR)==0
 129:              && (opdope[p2->t.tr1->t.op]&CNVRT)==0) {
 130:             tree->t.tr2 = p2->t.tr1;
 131:             if (opt = match(tree, table, nrleft, NOCVL))
 132:                 return(opt);
 133:             tree->t.tr2 = p2;
 134:         } else if (opdope[p1->t.op]&CNVRT && (nocvt&NOCVL)==0
 135:          && (opdope[p1->t.tr1->t.op]&CNVRT)==0) {
 136:             tree->t.tr1 = p1->t.tr1;
 137:             if (opt = match(tree, table, nrleft, NOCVR))
 138:                 return(opt);
 139:             tree->t.tr1 = p1;
 140:         }
 141:         d2 = dcalc(p2, nrleft);
 142:     }
 143:     for (; table->tabop!=op; table++)
 144:         if (table->tabop==0)
 145:             return(0);
 146:     for (opt = table->tabp; opt->tabdeg1!=0; opt++) {
 147:         if (d1 > (opt->tabdeg1&077)
 148:          || (opt->tabdeg1 >= 0100 && (p1->t.op != STAR)))
 149:             continue;
 150:         if (notcompat(p1, opt->tabtyp1, opt->tabdeg1, op))
 151:             continue;
 152:         if ((opdope[op]&BINARY)!=0 && p2!=0) {
 153:             if (d2 > (opt->tabdeg2&077)
 154:              || (opt->tabdeg2 >= 0100) && (p2->t.op != STAR) )
 155:                 continue;
 156:             if (notcompat(p2,opt->tabtyp2, opt->tabdeg2, 0))
 157:                 continue;
 158:             if ((opt->tabdeg2&077)==20 && xdcalc(p2,nrleft)>20)
 159:                 continue;
 160:         }
 161:         return(opt);
 162:     }
 163:     return(0);
 164: }
 165: 
 166: /*
 167:  * Given a tree, a code table, and a register,
 168:  * produce code to evaluate the tree with the appropriate table.
 169:  * Registers reg and upcan be used.
 170:  * If there is a value, it is desired that it appear in reg.
 171:  * The routine returns the register in which the value actually appears.
 172:  * This routine must work or there is an error.
 173:  * If the table called for is cctab, sptab, or efftab,
 174:  * and tree can't be done using the called-for table,
 175:  * another try is made.
 176:  * If the tree can't be compiled using cctab, regtab is
 177:  * used and a "tst" instruction is produced.
 178:  * If the tree can't be compiled using sptab,
 179:  * regtab is used and the register is pushed on the stack.
 180:  * If the tree can't be compiled using efftab,
 181:  * just use regtab.
 182:  * Regtab must succeed or an "op not found" error results.
 183:  *
 184:  * A number of special cases are recognized, and
 185:  * there is an interaction with the optimizer routines.
 186:  */
 187: rcexpr(atree, atable, reg)
 188: union tree *atree;
 189: struct table *atable;
 190: {
 191:     register r;
 192:     int modf, nargs, recurf;
 193:     register union tree *tree;
 194:     register struct table *table;
 195: 
 196:     table = atable;
 197:     recurf = 0;
 198:     if (reg<0) {
 199:         recurf++;
 200:         reg = ~reg;
 201:         if (reg>=020) {
 202:             reg -= 020;
 203:             recurf++;
 204:         }
 205:     }
 206: again:
 207:     if((tree=atree)==0)
 208:         return(0);
 209:     if (tree->t.type==VOID) {
 210:         if (table!=efftab)
 211:             error("Illegal use of void");
 212:         tree->t.type = INT;
 213:     }
 214:     if (opdope[tree->t.op]&RELAT && tree->t.tr2->t.op==CON
 215:         && tree->t.tr2->c.value==0
 216:         && table==cctab)
 217:         tree = atree = tree->t.tr1;
 218:     /*
 219: 	 * fieldselect(...) : in efftab mode,
 220: 	 * ignore the select, otherwise
 221: 	 * do the shift and mask.
 222: 	 */
 223:     if (tree->t.op == FSELT) {
 224:         if (table==efftab)
 225:             atree = tree = tree->t.tr1;
 226:         else {
 227:             tree->t.op = FSEL;
 228:             atree = tree = optim(tree);
 229:         }
 230:     }
 231:     switch (tree->t.op)  {
 232: 
 233:     /*
 234: 	 * Structure assignments
 235: 	 */
 236:     case STRASG:
 237:         strasg(tree);
 238:         return(0);
 239: 
 240:     /*
 241: 	 * An initializing expression
 242: 	 */
 243:     case INIT:
 244:         tree = optim(tree);
 245:         doinit(tree->t.type, tree->t.tr1);
 246:         return(0);
 247: 
 248:     /*
 249: 	 * Put the value of an expression in r0,
 250: 	 * for a switch or a return
 251: 	 */
 252:     case RFORCE:
 253:         tree = tree->t.tr1;
 254:         if((r=rcexpr(tree, regtab, reg)) != 0)
 255:             movreg(r, 0, tree);
 256:         return(0);
 257: 
 258:     /*
 259: 	 * sequential execution
 260: 	 */
 261:     case SEQNC:
 262:         r = nstack;
 263:         rcexpr(tree->t.tr1, efftab, reg);
 264:         nstack = r;
 265:         atree = tree = tree->t.tr2;
 266:         goto again;
 267: 
 268:     /*
 269: 	 * In the generated &~ operator,
 270: 	 * fiddle things so a PDP-11 "bit"
 271: 	 * instruction will be produced when cctab is used.
 272: 	 */
 273:     case ANDN:
 274:         if (table==cctab) {
 275:             tree->t.op = TAND;
 276:             tree->t.tr2 = optim(tnode(COMPL, tree->t.type, tree->t.tr2, TNULL));
 277:         }
 278:         break;
 279: 
 280:     /*
 281: 	 * Handle a subroutine call. It has to be done
 282: 	 * here because if cexpr got called twice, the
 283: 	 * arguments might be compiled twice.
 284: 	 * There is also some fiddling so the
 285: 	 * first argument, in favorable circumstances,
 286: 	 * goes to (sp) instead of -(sp), reducing
 287: 	 * the amount of stack-popping.
 288: 	 */
 289:     case CALL:
 290:         r = 0;
 291:         nargs = 0;
 292:         modf = 0;
 293: #ifdef notdef
 294:         /*
 295: 		 * The following code would catch instances of foo(...) where
 296: 		 * "foo" was anything other than a simple name.  In particular
 297: 		 * f(...), (fp(...))(...) and (ffp(...))(...) where "f" is a
 298: 		 * pointer to a function, "fp" is a function returning a
 299: 		 * pointer to a function and "ffp" is a pointer to a function
 300: 		 * returning a pointer to a function.  The catch would among
 301: 		 * other things cause the (sp)/-(sp) stack optimization to
 302: 		 * stop working.  The compiler has been tested in all these
 303: 		 * different cases with the catch commented out and all the
 304: 		 * code generated was correct.  So what was it here for?
 305: 		 * If a strange error crops up, uncommenting the catch might
 306: 		 * be tried ...
 307: 		 */
 308:         if (tree->t.tr1->t.op!=NAME || tree->t.tr1->n.class!=EXTERN) {
 309:             nargs++;
 310:             nstack++;
 311:         }
 312: #endif
 313:         tree = tree->t.tr2;
 314:         if(tree->t.op) {
 315:             while (tree->t.op==COMMA) {
 316:                 r += comarg(tree->t.tr2, &modf);
 317:                 tree = tree->t.tr1;
 318:                 nargs++;
 319:             }
 320:             r += comarg(tree, &modf);
 321:             nargs++;
 322:         }
 323:         tree = atree;
 324:         tree->t.op = CALL2;
 325:         if (modf && tree->t.tr1->t.op==NAME
 326:            && tree->t.tr1->n.class==EXTERN)
 327:             tree->t.op = CALL1;
 328:         if (cexpr(tree, regtab, reg)<0)
 329:             error("compiler botch: call");
 330:         popstk(r);
 331:         nstack -= nargs;
 332:         if (table==efftab || table==regtab)
 333:             return(0);
 334:         r = 0;
 335:         goto fixup;
 336: 
 337:     /*
 338: 	 * Longs need special treatment.
 339: 	 */
 340:     case ASULSH:    /* 18 */
 341:     case ULSH:  /* 17 */
 342:         if (tree->t.type != LONG && tree->t.type != UNLONG)
 343:             break;
 344:         if (tree->t.tr2->t.op==ITOL)
 345:             tree->t.tr2 = tree->t.tr2->t.tr1;
 346:         else
 347:             tree->t.tr2 = optim(tnode(LTOI,INT,tree->t.tr2,TNULL));
 348:         if (tree->t.op==ASULSH)
 349:             {
 350:             tree->t.op = UASLSHL;
 351:             tree->t.tr1 = tnode(AMPER, LONG+PTR, tree->t.tr1, TNULL);
 352:             }
 353:         else
 354:             tree->t.op = ULLSHIFT;
 355:         break;
 356: 
 357:     case ASLSH:
 358:     case LSHIFT:
 359:         if (tree->t.type==LONG || tree->t.type==UNLONG) {
 360:             if (tree->t.tr2->t.op==ITOL)
 361:                 tree->t.tr2 = tree->t.tr2->t.tr1;
 362:             else
 363:                 tree->t.tr2 = optim(tnode(LTOI,INT,tree->t.tr2,TNULL));
 364:             if (tree->t.op==ASLSH)
 365:                 tree->t.op = ASLSHL;
 366:             else
 367:                 tree->t.op = LLSHIFT;
 368:         }
 369:         break;
 370: 
 371:     /*
 372: 	 * Try to change * to shift.
 373: 	 */
 374:     case TIMES:
 375:     case ASTIMES:
 376:         tree = pow2(tree);
 377:     }
 378:     /*
 379: 	 * Try to find postfix ++ and -- operators that can be
 380: 	 * pulled out and done after the rest of the expression
 381: 	 */
 382:     if (table!=cctab && table!=cregtab && recurf<2
 383:      && (opdope[tree->t.op]&LEAF)==0) {
 384:         if (r=delay(&atree, table, reg)) {
 385:             tree = atree;
 386:             table = efftab;
 387:             reg = r-1;
 388:         }
 389:     }
 390:     /*
 391: 	 * Basically, try to reorder the computation
 392: 	 * so  reg = x+y  is done as  reg = x; reg += y
 393: 	 */
 394:     if (recurf==0 && reorder(&atree, table, reg)) {
 395:         if (table==cctab && atree->t.op==NAME)
 396:             return(reg);
 397:     }
 398:     tree = atree;
 399:     if (table==efftab && tree->t.op==NAME)
 400:         return(reg);
 401:     if ((r=cexpr(tree, table, reg))>=0) {
 402:         if (table==cregtab && (tree->t.op==INCAFT
 403:             || tree->t.op==DECAFT || tree->t.op==TIMES))
 404:             goto fixup;
 405:         return(r);
 406:     }
 407:     if (table!=regtab && (table!=cctab||(opdope[tree->t.op]&RELAT)==0)) {
 408:         if((r=cexpr(tree, regtab, reg))>=0) {
 409:     fixup:
 410:             modf = isfloat(tree);
 411:             dbprint(tree->t.op);
 412:             if (table==sptab || table==lsptab) {
 413:                 if (tree->t.type==LONG || tree->t.type==UNLONG){
 414:                     printf("mov\tr%d,-(sp)\n",r+1);
 415:                     nstack++;
 416:                 }
 417:                 printf("mov%s	r%d,%s(sp)\n", modf=='f'?"f":"", r,
 418:                     table==sptab? "-":"");
 419:                 nstack++;
 420:             }
 421:             if (table==cctab || table==cregtab)
 422:                 printf("tst%s	r%d\n", modf=='f'?"f":"", r);
 423:             return(r);
 424:         }
 425:     }
 426:     /*
 427: 	 * Special grace for unsigned chars as right operands
 428: 	 */
 429:     if (opdope[tree->t.op]&BINARY && tree->t.tr2->t.type==UNCHAR) {
 430:         tree->t.tr2 = tnode(LOAD, UNSIGN, tree->t.tr2, TNULL);
 431:         return(rcexpr(tree, table, reg));
 432:     }
 433:     /*
 434: 	 * There's a last chance for this operator
 435: 	 */
 436:     if (tree->t.op==LTOI) {
 437:         r = rcexpr(tree->t.tr1, regtab, reg);
 438:         if (r >= 0) {
 439:             r++;
 440:             goto fixup;
 441:         }
 442:     }
 443: 
 444:     r = tree->t.op;
 445:     if (tree->t.type == STRUCT)
 446:         error("Illegal operation on structure");
 447:     else if (r > 0 && r < UASLSHL && opntab[r])
 448:         error("No code table for op: %s(%d) type: %d", opntab[r], r,
 449:             tree->t.type);
 450:     else
 451:         error("No code table for op %d", r);
 452:     return(reg);
 453: }
 454: 
 455: /*
 456:  * Try to compile the tree with the code table using
 457:  * registers areg and up.  If successful,
 458:  * return the register where the value actually ended up.
 459:  * If unsuccessful, return -1.
 460:  *
 461:  * Most of the work is the macro-expansion of the
 462:  * code table.
 463:  */
 464: cexpr(tree, table, areg)
 465: register union tree *tree;
 466: struct table *table;
 467: {
 468:     int c, r;
 469:     register union tree *p, *p1;
 470:     struct table *ctable;
 471:     union tree *p2;
 472:     char *string;
 473:     int reg, reg1, rreg, flag, opd;
 474:     struct optab *opt;
 475: 
 476:     reg = areg;
 477:     p1 = tree->t.tr2;
 478:     c = tree->t.op;
 479:     opd = opdope[c];
 480:     /*
 481: 	 * When the value of a relational or a logical expression is
 482: 	 * desired, more work must be done.
 483: 	 */
 484:     if ((opd&RELAT||c==LOGAND||c==LOGOR||c==EXCLA) && table!=cctab) {
 485:         cbranch(tree, c=isn++, 1, reg);
 486:         rcexpr((union tree *)&czero, table, reg);
 487:         branch(isn, 0, 0);
 488:         label(c);
 489:         rcexpr((union tree *)&cone, table, reg);
 490:         label(isn++);
 491:         return(reg);
 492:     }
 493:     if(c==QUEST) {
 494:         if (table==cctab)
 495:             return(-1);
 496:         cbranch(tree->t.tr1, c=isn++, 0, reg);
 497:         flag = nstack;
 498:         rreg = rcexpr(p1->t.tr1, table, reg);
 499:         nstack = flag;
 500:         branch(r=isn++, 0, 0);
 501:         label(c);
 502:         reg = rcexpr(p1->t.tr2, table, rreg);
 503:         if (rreg!=reg)
 504:             movreg(reg, rreg, tree->t.tr2);
 505:         label(r);
 506:         return(rreg);
 507:     }
 508:     reg = oddreg(tree, reg);
 509:     reg1 = reg+1;
 510:     /*
 511: 	 * long values take 2 registers.
 512: 	 */
 513:     if ((tree->t.type==LONG||tree->t.type==UNLONG||opd&RELAT&&(tree->t.tr1->t.type==LONG||tree->t.tr1->t.type==UNLONG))
 514:        && tree->t.op!=ITOL)
 515:         reg1++;
 516:     /*
 517: 	 * Leaves of the expression tree
 518: 	 */
 519:     if ((r = chkleaf(tree, table, reg)) >= 0)
 520:         return(r);
 521:     /*
 522: 	 * x + (-1) is better done as x-1.
 523: 	 */
 524:     if (tree->t.op==PLUS||tree->t.op==ASPLUS) {
 525:         if ((p1=tree->t.tr2)->t.op==CON && p1->c.value==-1) {
 526:             p1->c.value = -p1->c.value;
 527:             tree->t.op += (MINUS-PLUS);
 528:         }
 529:     }
 530:     /*
 531: 	 * Because of a peculiarity of the PDP11 table
 532: 	 * char = *intreg++ and *--intreg cannot go through.
 533:  	 */
 534:     if (tree->t.tr2 && (tree->t.tr2->t.op==AUTOI||tree->t.tr2->t.op==AUTOD)
 535:      && (tree->t.tr1->t.type==CHAR || tree->t.tr1->t.type==UNCHAR)
 536:      && tree->t.tr2->t.type!=CHAR && tree->t.tr2->t.type!=UNCHAR)
 537:         tree->t.tr2 = tnode(LOAD, tree->t.tr2->t.type, tree->t.tr2, TNULL);
 538:     /*
 539: 	 * Another peculiarity of the PDP11 table manifested itself when
 540: 	 * amplifying the move3: table.  The same case which optimizes
 541: 	 * u_char to char moves is used to move a u_char to a register. This
 542: 	 * is wrong, leading to sign extension.  Rather than lose the ability
 543: 	 * to generate better code when moving a u_char to a char, a check
 544: 	 * is made here to prevent sign extension.
 545: 	 *
 546: 	 * If the opcode is assign, the destination is a register and the
 547: 	 * source is u_char then do a conversion.
 548: 	 *
 549: 	 * u_char handling in the compiler is a bit awkward, it would be nice
 550: 	 * if %aub in the tables had a more unique meaning.
 551: 	*/
 552:     if (tree->t.tr2 && tree->t.tr1->t.op == NAME
 553:      && tree->t.tr1->n.class == REG && tree->t.op == ASSIGN
 554:      && tree->t.tr2->t.type == UNCHAR)
 555:         tree->t.tr2 = tnode(LOAD, UNSIGN, tree->t.tr2, TNULL);
 556:     if (table==cregtab)
 557:         table = regtab;
 558:     /*
 559: 	 * The following peculiar code depends on the fact that
 560: 	 * if you just want the codition codes set, efftab
 561: 	 * will generate the right code unless the operator is
 562: 	 * a shift or
 563: 	 * postfix ++ or --. Unravelled, if the table is
 564: 	 * cctab and the operator is not special, try first
 565: 	 * for efftab;  if the table isn't, if the operator is,
 566: 	 * or the first match fails, try to match
 567: 	 * with the table actually asked for.
 568: 	 */
 569:     /*
 570: 	 * Account for longs and oddregs; below is really
 571: 	 * r = nreg - reg - (reg-areg) - (reg1-reg-1);
 572: 	 */
 573:     r = nreg - reg + areg - reg1 + 1;
 574:     if (table!=cctab || c==INCAFT || c==DECAFT || tree->t.type==LONG || tree->t.type==UNLONG
 575: /*	 || c==ASRSH || c==ASLSH || c==ASULSH || tree->t.tr1->t.type==UNCHAR */
 576:      || c==ASRSH || c==ASLSH || c==ASULSH
 577:      || (opt = match(tree, efftab, r, 0)) == 0)
 578:         if ((opt=match(tree, table, r, 0))==0)
 579:             return(-1);
 580:     string = opt->tabstring;
 581:     p1 = tree->t.tr1;
 582:     if (p1->t.op==FCON && p1->f.value>0) {
 583: /* nonportable */
 584:         printf(".data\nL%d:%o;%o;%o;%o\n.text\n", p1->f.value,
 585:             ((unsigned short *)&(p1->f.fvalue))[0],
 586:             ((unsigned short *)&(p1->f.fvalue))[1],
 587:             ((unsigned short *)&(p1->f.fvalue))[2],
 588:             ((unsigned short *)&(p1->f.fvalue))[3] );
 589:         p1->c.value = -p1->c.value;
 590:     }
 591:     p2 = 0;
 592:     if (opdope[tree->t.op]&BINARY) {
 593:         p2 = tree->t.tr2;
 594:         if (p2->t.op==FCON && p2->f.value>0) {
 595: /* nonportable */
 596:             printf(".data\nL%d:%o;%o;%o;%o\n.text\n", p2->f.value,
 597:                 ((unsigned short *)&(p2->f.fvalue))[0],
 598:                 ((unsigned short *)&(p2->f.fvalue))[1],
 599:                 ((unsigned short *)&(p2->f.fvalue))[2],
 600:                 ((unsigned short *)&(p2->f.fvalue))[3] );
 601:             p2->f.value = -p2->f.value;
 602:         }
 603:     }
 604: loop:
 605:     /*
 606: 	 * The 0200 bit asks for a tab.
 607: 	 */
 608:     if ((c = *string++) & 0200) {
 609:         c &= 0177;
 610:         putchar('\t');
 611:     }
 612:     switch (c) {
 613: 
 614:     case '\n':
 615:         dbprint(tree->t.op);
 616:         break;
 617: 
 618:     case '\0':
 619:         if (!isfloat(tree))
 620:             if (tree->t.op==DIVIDE||tree->t.op==ASDIV)
 621:                 reg--;
 622:         if (table==regtab && (opdope[tree->t.op]&ASSGOP)) {
 623:             if (tree->t.tr1->t.type==CHAR)
 624:                 printf("movb	r%d,r%d\n", reg, reg);
 625:         }
 626:         return(reg);
 627: 
 628:     /* A1 */
 629:     case 'A':
 630:         p = p1;
 631:         goto adr;
 632: 
 633:     /* A2 */
 634:     case 'B':
 635:         p = p2;
 636:         goto adr;
 637: 
 638:     adr:
 639:         c = 0;
 640:         while (*string=='\'') {
 641:             c++;
 642:             string++;
 643:         }
 644:         if (*string=='+') {
 645:             c = 100;
 646:             string++;
 647:         }
 648:         pname(p, c);
 649:         goto loop;
 650: 
 651:     /* I */
 652:     case 'M':
 653:         if ((c = *string)=='\'')
 654:             string++;
 655:         else
 656:             c = 0;
 657:         prins(tree->t.op, c, instab, 0);
 658:         goto loop;
 659: 
 660:     /* B1 */
 661:     case 'C':
 662:         if ((opd&LEAF) != 0)
 663:             p = tree;
 664:         else
 665:             p = p1;
 666:         goto pbyte;
 667: 
 668:     /* BF */
 669:     case 'P':
 670:         p = tree;
 671:         goto pb1;
 672: 
 673:     /* B2 */
 674:     case 'D':
 675:         p = p2;
 676:     pbyte:
 677:         if (p->t.type==CHAR || p->t.type==UNCHAR)
 678:             putchar('b');
 679:     pb1:
 680:         if (isfloat(p))
 681:             putchar('f');
 682:         goto loop;
 683: 
 684:     /* BE */
 685:     case 'L':
 686:         if (p1->t.type==CHAR || p2->t.type==CHAR
 687:          || p1->t.type==UNCHAR || p2->t.type==UNCHAR)
 688:             putchar('b');
 689:         p = tree;
 690:         goto pb1;
 691: 
 692:     /* F */
 693:     case 'G':
 694:         p = p1;
 695:         flag = 01;
 696:         goto subtre;
 697: 
 698:     /* S */
 699:     case 'K':
 700:         p = p2;
 701:         flag = 02;
 702:         goto subtre;
 703: 
 704:     /* H */
 705:     case 'H':
 706:         p = tree;
 707:         flag = 04;
 708: 
 709:     subtre:
 710:         ctable = regtab;
 711:         if (flag&04)
 712:             ctable = cregtab;
 713:         c = *string++ - 'A';
 714:         if (*string=='!') {
 715:             string++;
 716:             c |= 020;   /* force right register */
 717:         }
 718:         if (*string=='?') {
 719:             string++;
 720:             c |= 040;   /* force condition codes */
 721:         }
 722:         if ((c&02)!=0)
 723:             ctable = sptab;
 724:         if ((c&04)!=0)
 725:             ctable = cctab;
 726:         if ((flag&01) && ctable==regtab && (c&01)==0
 727:           && ((c&040)||tree->t.op==DIVIDE||tree->t.op==MOD
 728:            || tree->t.op==ASDIV||tree->t.op==ASMOD||tree->t.op==ITOL))
 729:             ctable = cregtab;
 730:         if ((c&01)!=0) {
 731:             p = p->t.tr1;
 732:             if(collcon(p) && ctable!=sptab) {
 733:                 if (p->t.op==STAR)
 734:                     p = p->t.tr1;
 735:                 p = p->t.tr1;
 736:             }
 737:         }
 738:         if (table==lsptab && ctable==sptab)
 739:             ctable = lsptab;
 740:         if (c&010)
 741:             r = reg1;
 742:         else
 743:             if (opdope[p->t.op]&LEAF || p->t.degree < 2)
 744:                 r = reg;
 745:             else
 746:                 r = areg;
 747:         rreg = rcexpr(p, ctable, r);
 748:         if (ctable!=regtab && ctable!=cregtab)
 749:             goto loop;
 750:         if (c&010) {
 751:             if (c&020 && rreg!=reg1)
 752:                 movreg(rreg, reg1, p);
 753:             else
 754:                 reg1 = rreg;
 755:         } else if (rreg!=reg)
 756:             if ((c&020)==0 && oddreg(tree, 0)==0 && tree->t.type!=LONG
 757:             && tree->t.type!=UNLONG
 758:             && (flag&04
 759:               || flag&01&&xdcalc(p2,nreg-rreg-1)<=(opt->tabdeg2&077)
 760:               || flag&02&&xdcalc(p1,nreg-rreg-1)<=(opt->tabdeg1&077))) {
 761:                 reg = rreg;
 762:                 reg1 = rreg+1;
 763:             } else
 764:                 movreg(rreg, reg, p);
 765:         goto loop;
 766: 
 767:     /* R */
 768:     case 'I':
 769:         r = reg;
 770:         if (*string=='-') {
 771:             string++;
 772:             r--;
 773:         }
 774:         goto preg;
 775: 
 776:     /* R1 */
 777:     case 'J':
 778:         r = reg1;
 779:     preg:
 780:         if (*string=='+') {
 781:             string++;
 782:             r++;
 783:         }
 784:         if (r>nreg || r>=4 && tree->t.type==DOUBLE) {
 785:             if (regpanic)
 786:                 error("Register overflow: simplify expression");
 787:             else
 788:                 longjmp(jmpbuf, 1);
 789:         }
 790:         printf("r%d", r);
 791:         goto loop;
 792: 
 793:     case '-':       /* check -(sp) */
 794:         if (*string=='(') {
 795:             nstack++;
 796:             if (table!=lsptab)
 797:                 putchar('-');
 798:             goto loop;
 799:         }
 800:         break;
 801: 
 802:     case ')':       /* check (sp)+ */
 803:         putchar(')');
 804:         if (*string=='+')
 805:             nstack--;
 806:         goto loop;
 807: 
 808:     /* #1 */
 809:     case '#':
 810:         p = p1->t.tr1;
 811:         goto nmbr;
 812: 
 813:     /* #2 */
 814:     case '"':
 815:         p = p2->t.tr1;
 816: 
 817:     nmbr:
 818:         if(collcon(p)) {
 819:             if (p->t.op==STAR) {
 820:                 printf("*");
 821:                 p = p->t.tr1;
 822:             }
 823:             if ((p = p->t.tr2)->t.op == CON) {
 824:                 if (p->c.value)
 825:                     psoct(p->c.value);
 826:             } else if (p->t.op==AMPER)
 827:                 pname(p->t.tr1, 0);
 828:         }
 829:         goto loop;
 830: 
 831:     /*
 832: 	 * Certain adjustments for / %
 833: 	 */
 834:     case 'T':
 835:         c = reg-1;
 836:         if (uns(p1) || uns(p2)) {
 837:             printf("clr	r%d\n", c);
 838:             goto loop;
 839:         }
 840:         if (dcalc(p1, 5)>12 && !match(p1, cctab, 10, 0))
 841:             printf("tst	r%d\n", reg);
 842:         printf("sxt	r%d\n", c);
 843:         goto loop;
 844: 
 845:     case 'V':   /* adc sbc, clr, or sxt as required for longs */
 846:         switch(tree->t.op) {
 847:         case PLUS:
 848:         case ASPLUS:
 849:         case INCBEF:
 850:         case INCAFT:
 851:             printf("adc");
 852:             break;
 853: 
 854:         case MINUS:
 855:         case ASMINUS:
 856:         case NEG:
 857:         case DECBEF:
 858:         case DECAFT:
 859:             printf("sbc");
 860:             break;
 861: 
 862:         case ASSIGN:
 863:             p = tree->t.tr2;
 864:             goto lcasev;
 865: 
 866:         case ASDIV:
 867:         case ASMOD:
 868:         case ASULSH:
 869:             p = tree->t.tr1;
 870:         lcasev:
 871:             if (p->t.type!=LONG && p->t.type!=UNLONG) {
 872:                 if (uns(p) || uns(tree->t.tr2))
 873:                     printf("clr");
 874:                 else
 875:                     printf("sxt");
 876:                 goto loop;
 877:             }
 878:         default:
 879:             while ((c = *string++)!='\n' && c!='\0');
 880:             break;
 881:         }
 882:         goto loop;
 883: 
 884:     /*
 885: 	 * Mask used in field assignments
 886: 	 */
 887:     case 'Z':
 888:         printf("$%o", UNS(tree->F.mask));
 889:         goto loop;
 890: 
 891:     /*
 892: 	 * Relational on long values.
 893: 	 * Might bug out early. E.g.,
 894: 	 * (long<0) can be determined with only 1 test.
 895: 	 */
 896:     case 'X':
 897:         if (xlongrel(*string++ - '0'))
 898:             return(reg);
 899:         goto loop;
 900:     }
 901:     putchar(c);
 902:     goto loop;
 903: }
 904: 
 905: /*
 906:  * This routine just calls sreorder (below)
 907:  * on the subtrees and then on the tree itself.
 908:  * It returns non-zero if anything changed.
 909:  */
 910: reorder(treep, table, reg)
 911: union tree **treep;
 912: struct table *table;
 913: {
 914:     register r, o;
 915:     register union tree *p;
 916: 
 917:     p = *treep;
 918:     o = p->t.op;
 919:     if (opdope[o]&LEAF||o==LOGOR||o==LOGAND||o==SEQNC||o==QUEST||o==COLON)
 920:         return(0);
 921:     while(sreorder(&p->t.tr1, regtab, reg, 1))
 922:         ;
 923:     if (opdope[o]&BINARY)
 924:         while(sreorder(&p->t.tr2, regtab, reg, 1))
 925:             ;
 926:     r = 0;
 927:     if (table!=cctab)
 928:     while (sreorder(treep, table, reg, 0))
 929:         r++;
 930:     *treep = optim(*treep);
 931:     return(r);
 932: }
 933: 
 934: /*
 935:  * Basically this routine carries out two kinds of optimization.
 936:  * First, it observes that "x + (reg = y)" where actually
 937:  * the = is any assignment op is better done as "reg=y; x+reg".
 938:  * In this case rcexpr is called to do the first part and the
 939:  * tree is modified so the name of the register
 940:  * replaces the assignment.
 941:  * Moreover, expressions like "reg = x+y" are best done as
 942:  * "reg = x; reg += y" (so long as "reg" and "y" are not the same!).
 943:  */
 944: sreorder(treep, table, reg, recurf)
 945: union tree **treep;
 946: struct table *table;
 947: {
 948:     register union tree *p, *p1;
 949: 
 950:     p = *treep;
 951:     if (opdope[p->t.op]&LEAF)
 952:         return(0);
 953:     if (p->t.op==PLUS && recurf)
 954:         if (reorder(&p->t.tr2, table, reg))
 955:             *treep = p = optim(p);
 956:     if ((p1 = p->t.tr1)==TNULL)
 957:         return(0);
 958:     if (p->t.op==STAR || p->t.op==PLUS) {
 959:         if (recurf && reorder(&p->t.tr1, table, reg)) {
 960:             *treep = p = optim(p);
 961:             if (opdope[p->t.op]&LEAF)
 962:                 return(0);
 963:         }
 964:         p1 = p->t.tr1;
 965:     }
 966:     if (p1->t.op==NAME) switch(p->t.op) {
 967:         case ASLSH:
 968:         case ASRSH:
 969:         case ASSIGN:
 970:             if (p1->n.class != REG || p1->n.type==CHAR
 971:               || isfloat(p->t.tr2))
 972:                 return(0);
 973:             if (p->t.op==ASSIGN) switch (p->t.tr2->t.op) {
 974:             case RSHIFT:
 975:                 if (p->t.type==UNSIGN)
 976:                     return(0);
 977:                 goto caseGEN;
 978:             case TIMES:
 979:                 if (!ispow2(p->t.tr2))
 980:                     break;
 981:                 p->t.tr2 = pow2(p->t.tr2);
 982:             case PLUS:
 983:             case MINUS:
 984:             case AND:
 985:             case ANDN:
 986:             case OR:
 987:             case EXOR:
 988:             case LSHIFT:
 989:             caseGEN:
 990:                 p1 = p->t.tr2->t.tr2;
 991:                 if (xdcalc(p1, 16) > 12
 992:                  || p1->t.op==NAME
 993:                  &&(p1->n.nloc==p->t.tr1->n.nloc
 994:                   || p1->n.regno==p->t.tr1->n.nloc))
 995:                     return(0);
 996:                 p1 = p->t.tr2;
 997:                 p->t.tr2 = p1->t.tr1;
 998:                 if (p1->t.tr1->t.op!=NAME
 999:                  || p1->t.tr1->n.class!=REG
1000:                  || p1->t.tr1->n.nloc!=p->t.tr1->n.nloc)
1001:                     rcexpr(p, efftab, reg);
1002:                 p->t.tr2 = p1->t.tr2;
1003:                 p->t.op = p1->t.op + ASPLUS - PLUS;
1004:                 *treep = p;
1005:                 return(1);
1006:             }
1007:             goto OK;
1008: 
1009:         case ASTIMES:
1010:             if (!ispow2(p))
1011:                 return(0);
1012:         case ASPLUS:
1013:         case ASMINUS:
1014:         case ASAND:
1015:         case ASANDN:
1016:         case ASOR:
1017:         case ASXOR:
1018:         case INCBEF:
1019:         case DECBEF:
1020:         OK:
1021:             if (table==cctab||table==cregtab)
1022:                 reg += 020;
1023:             rcexpr(optim(p), efftab, ~reg);
1024:             *treep = p1;
1025:             return(1);
1026:     }
1027:     return(0);
1028: }
1029: 
1030: /*
1031:  * Delay handles postfix ++ and --
1032:  * It observes that "x + y++" is better
1033:  * treated as "x + y; y++".
1034:  * If the operator is ++ or -- itself,
1035:  * it calls rcexpr to load the operand, letting
1036:  * the calling instance of rcexpr to do the
1037:  * ++ using efftab.
1038:  * Otherwise it uses sdelay to search for inc/dec
1039:  * among the operands.
1040:  */
1041: delay(treep, table, reg)
1042: union tree **treep;
1043: struct table *table;
1044: {
1045:     register union tree *p, *p1;
1046:     register r;
1047: 
1048:     p = *treep;
1049:     if ((p->t.op==INCAFT||p->t.op==DECAFT)
1050:      && p->t.tr1->t.op==NAME) {
1051:         r = p->t.tr1->n.class;
1052:         if (r == EXTERN || r == OFFS || r == STATIC &&
1053:                 p->t.tr1->t.type == UNCHAR)
1054:             return(1+rcexpr(p->t.tr1, table, reg));
1055:         else
1056:             return(1+rcexpr(paint(p->t.tr1, p->t.type), table,reg));
1057:     }
1058:     p1 = 0;
1059: /*
1060:  * typo fix, original code.
1061:  *	if (opdope[p->t.op]&BINARY) {
1062:  *		if (p->t.op==LOGAND || p->t.op==LOGOR
1063:  *		 || p->t.op==QUEST || p->t.op==COLON || p->t.op==SEQNC)
1064:  *			return(0);
1065:  *		}
1066:  *		p1 = sdelay(&p->t.tr2);
1067:  *	if (p1==0)
1068:  *		p1 = sdelay(&p->t.tr1);
1069:  */
1070:     if (opdope[p->t.op]&BINARY) {
1071:         if (p->t.op==LOGAND || p->t.op==LOGOR
1072:          || p->t.op==QUEST || p->t.op==COLON || p->t.op==SEQNC)
1073:             return(0);
1074:         p1 = sdelay(&p->t.tr2);
1075:     }
1076:     if (p1==0)
1077:         p1 = sdelay(&p->t.tr1);
1078:     if (p1) {
1079:         r = rcexpr(optim(p), table, reg);
1080:         *treep = p1;
1081:         return(r+1);
1082:     }
1083:     return(0);
1084: }
1085: 
1086: union tree *
1087: sdelay(ap)
1088: union tree **ap;
1089: {
1090:     register union tree *p, *p1;
1091: 
1092:     if ((p = *ap)==TNULL)
1093:         return(TNULL);
1094:     if ((p->t.op==INCAFT||p->t.op==DECAFT) && p->t.tr1->t.op==NAME) {
1095:         *ap = paint(ncopy(p->t.tr1), p->t.type);
1096:         return(p);
1097:     }
1098:     if (p->t.op==STAR || p->t.op==PLUS)
1099:         if (p1=sdelay(&p->t.tr1))
1100:             return(p1);
1101:     if (p->t.op==PLUS)
1102:         return(sdelay(&p->t.tr2));
1103:     return(0);
1104: }
1105: 
1106: /*
1107:  * Propagate possible implicit type-changing operation
1108:  */
1109: union tree *
1110: paint(tp, type)
1111: register union tree *tp;
1112: register type;
1113: {
1114: 
1115:     if (tp->t.type==type)
1116:         return(tp);
1117:     if (tp->t.type==CHAR && type==INT)
1118:         return(tp);
1119:     if (tp->t.type==CHAR || tp->t.type==UNCHAR)
1120:         return(optim(tnode(LOAD, type, tp, TNULL)));
1121:     tp->t.type = type;
1122:     if (tp->t.op==AMPER && type&XTYPE)
1123:         tp->t.tr1 = paint(tp->t.tr1, decref(type));
1124:     else if (tp->t.op==STAR)
1125:         tp->t.tr1 = paint(tp->t.tr1, incref(type));
1126:     else if (tp->t.op==ASSIGN) {
1127:         paint(tp->t.tr1, type);
1128:         paint(tp->t.tr2, type);
1129:     }
1130:     return(tp);
1131: }
1132: 
1133: /*
1134:  * Copy a tree node for a register variable.
1135:  * Used by sdelay because if *reg-- is turned
1136:  * into *reg; reg-- the *reg will in turn
1137:  * be changed to some offset class, accidentally
1138:  * modifying the reg--.
1139:  */
1140: union tree *
1141: ncopy(p)
1142: register union tree *p;
1143: {
1144:     register union tree *q;
1145: 
1146:     q = getblk(sizeof(struct xtname));
1147:     q->n.op = p->n.op;
1148:     q->n.type = p->n.type;
1149:     q->n.class = p->n.class;
1150:     q->n.regno = p->n.regno;
1151:     q->n.offset = p->n.offset;
1152:     if (q->n.class==EXTERN || q->n.class==XOFFS)
1153:         q->x.name = p->x.name;
1154:     else
1155:         q->n.nloc = p->n.nloc;
1156:     return(q);
1157: }
1158: 
1159: /*
1160:  * If the tree can be immediately loaded into a register,
1161:  * produce code to do so and return success.
1162:  */
1163: chkleaf(tree, table, reg)
1164: register union tree *tree;
1165: struct table *table;
1166: {
1167:     struct tnode lbuf;
1168: 
1169:     if (tree->t.op!=STAR && dcalc(tree, nreg-reg) > 12)
1170:         return(-1);
1171:     lbuf.op = LOAD;
1172:     lbuf.type = tree->t.type;
1173:     lbuf.degree = tree->t.degree;
1174:     lbuf.tr1 = tree;
1175:     return(rcexpr((union tree *)&lbuf, table, reg));
1176: }
1177: 
1178: /*
1179:  * Compile a function argument.
1180:  * If the stack is currently empty, put it in (sp)
1181:  * rather than -(sp); this will save a pop.
1182:  * Return the number of bytes pushed,
1183:  * for future popping.
1184:  */
1185: comarg(tree, flagp)
1186: register union tree *tree;
1187: int *flagp;
1188: {
1189:     register retval;
1190:     int i;
1191:     int size;
1192: 
1193:     if (tree->t.op==STRASG) {
1194:         size = tree->F.mask;
1195:         tree = tree->t.tr1;
1196:         tree = strfunc(tree);
1197:         if (size <= sizeof(short)) {
1198:             paint(tree, INT);
1199:             goto normal;
1200:         }
1201:         if (size <= sizeof(long)) {
1202:             paint(tree, LONG);
1203:             goto normal;
1204:         }
1205:         if (tree->t.op!=NAME && tree->t.op!=STAR) {
1206:             error("Unimplemented structure assignment");
1207:             return(0);
1208:         }
1209:         tree = tnode(AMPER, STRUCT+PTR, tree, TNULL);
1210:         tree = tnode(PLUS, STRUCT+PTR, tree, tconst(size, INT));
1211:         tree = optim(tree);
1212:         retval = rcexpr(tree, regtab, 0);
1213:         size >>= 1;
1214:         if (size <= 5) {
1215:             for (i=0; i<size; i++)
1216:                 printf("mov	-(r%d),-(sp)\n", retval);
1217:         } else {
1218:             if (retval!=0)
1219:                 printf("mov	r%d,r0\n", retval);
1220:             printf("mov	$%o,r1\n", UNS(size));
1221:             printf("L%d:mov	-(r0),-(sp)\ndec\tr1\njne\tL%d\n", isn, isn);
1222:             isn++;
1223:         }
1224:         nstack++;
1225:         return(size*2);
1226:     }
1227: normal:
1228:     if (nstack || isfloat(tree) || tree->t.type==LONG || tree->t.type==UNLONG) {
1229:         rcexpr(tree, sptab, 0);
1230:         retval = arlength(tree->t.type);
1231:     } else {
1232:         (*flagp)++;
1233:         rcexpr(tree, lsptab, 0);
1234:         retval = 0;
1235:     }
1236:     return(retval);
1237: }
1238: 
1239: union tree *
1240: strfunc(tp)
1241: register union tree *tp;
1242: {
1243:     if (tp->t.op != CALL)
1244:         return(tp);
1245:     paint(tp, STRUCT+PTR);
1246:     return(tnode(STAR, STRUCT, tp, TNULL));
1247: }
1248: 
1249: /*
1250:  * Compile an initializing expression
1251:  */
1252: doinit(type, tree)
1253: register type;
1254: register union tree *tree;
1255: {
1256:     float sfval;
1257:     double fval;
1258:     long lval;
1259: 
1260:     if (type==CHAR || type==UNCHAR) {
1261:         printf(".byte ");
1262:         if (tree->t.type&XTYPE)
1263:             goto illinit;
1264:         type = INT;
1265:     }
1266:     if (type&XTYPE)
1267:         type = INT;
1268:     switch (type) {
1269:     case INT:
1270:     case UNSIGN:
1271:         if (tree->t.op==FTOI) {
1272:             if (tree->t.tr1->t.op!=FCON && tree->t.tr1->t.op!=SFCON)
1273:                 goto illinit;
1274:             tree = tree->t.tr1;
1275:             tree->c.value = tree->f.fvalue;
1276:             tree->t.op = CON;
1277:         } else if (tree->t.op==LTOI) {
1278:             if (tree->t.tr1->t.op!=LCON)
1279:                 goto illinit;
1280:             tree = tree->t.tr1;
1281:             lval = tree->l.lvalue;
1282:             tree->t.op = CON;
1283:             tree->c.value = lval;
1284:         }
1285:         if (tree->t.op == CON)
1286:             printf("%o\n", UNS(tree->c.value));
1287:         else if (tree->t.op==AMPER) {
1288:             pname(tree->t.tr1, 0);
1289:             putchar('\n');
1290:         } else
1291:             goto illinit;
1292:         return;
1293: 
1294:     case DOUBLE:
1295:     case FLOAT:
1296:         if (tree->t.op==ITOF) {
1297:             if (tree->t.tr1->t.op==CON) {
1298:                 fval = tree->t.tr1->c.value;
1299:             } else
1300:                 goto illinit;
1301:         } else if (tree->t.op==FCON || tree->t.op==SFCON)
1302:             fval = tree->f.fvalue;
1303:         else if (tree->t.op==LTOF) {
1304:             if (tree->t.tr1->t.op!=LCON)
1305:                 goto illinit;
1306:             fval = tree->t.tr1->l.lvalue;
1307:         } else
1308:             goto illinit;
1309:         if (type==FLOAT) {
1310:             sfval = fval;
1311: /* nonportable */
1312:             printf("%o; %o\n",
1313:                 ((unsigned short *)&sfval)[0],
1314:                 ((unsigned short *)&sfval)[1] );
1315:         } else
1316:             printf("%o; %o; %o; %o\n",
1317:                 ((unsigned short *)&fval)[0],
1318:                 ((unsigned short *)&fval)[1],
1319:                 ((unsigned short *)&fval)[2],
1320:                 ((unsigned short *)&fval)[3] );
1321:         return;
1322: 
1323:     case UNLONG:
1324:     case LONG:
1325:         if (tree->t.op==FTOL) {
1326:             tree = tree->t.tr1;
1327:             if (tree->t.op==SFCON)
1328:                 tree->t.op = FCON;
1329:             if (tree->t.op!= FCON)
1330:                 goto illinit;
1331:             lval = tree->f.fvalue;
1332:         } else if (tree->t.op==ITOL) {
1333:             if (tree->t.tr1->t.op != CON)
1334:                 goto illinit;
1335:             if (uns(tree->t.tr1))
1336:                 lval = (unsigned)tree->t.tr1->c.value;
1337:             else
1338:                 lval = tree->t.tr1->c.value;
1339:         } else if (tree->t.op==LCON)
1340:             lval = tree->l.lvalue;
1341:         else
1342:             goto illinit;
1343: /* nonportable */
1344:         printf("%o; %o\n", UNS((lval>>16)), UNS(lval));
1345:         return;
1346:     }
1347: illinit:
1348:     error("Illegal initialization");
1349: }
1350: 
1351: movreg(r0, r1, tree)
1352: union tree *tree;
1353: {
1354:     register char *s;
1355:     char c;
1356: 
1357:     if (r0==r1)
1358:         return;
1359:     if (tree->t.type==LONG || tree->t.type == UNLONG) {
1360:         if (r0>=nreg || r1>=nreg) {
1361:             error("register overflow: compiler error");
1362:         }
1363:         s = "mov	r%d,r%d\nmov	r%d,r%d\n";
1364:         if (r0 < r1)
1365:             printf(s, r0+1,r1+1,r0,r1);
1366:         else
1367:             printf(s, r0,r1,r0+1,r1+1);
1368:         return;
1369:     }
1370:     c = isfloat(tree);
1371:     printf("mov%.1s	r%d,r%d\n", &c, r0, r1);
1372: }

Defined functions

cexpr defined in line 464; used 4 times
chkleaf defined in line 1163; used 1 times
comarg defined in line 1185; used 2 times
delay defined in line 1041; used 1 times
doinit defined in line 1252; used 1 times
main defined in line 40; never used
match defined in line 95; used 6 times
movreg defined in line 1351; used 4 times
ncopy defined in line 1140; used 2 times
paint defined in line 1109; used 24 times
rcexpr defined in line 187; used 18 times
reorder defined in line 910; used 4 times
sdelay defined in line 1086; used 5 times
sreorder defined in line 944; used 3 times
strfunc defined in line 1239; used 3 times

Defined variables

cone defined in line 31; used 1 times
cregtab defined in line 35; used 8 times
czero defined in line 30; used 1 times
debug defined in line 20; never used
isn defined in line 38; used 8 times
maprel defined in line 22; never used
notrel defined in line 26; never used
nreg defined in line 37; used 7 times
sccsid defined in line 9; never used
sfuncr defined in line 33; never used

Defined macros

NOCVL defined in line 100; used 2 times
NOCVR defined in line 101; used 2 times
dbprint defined in line 17; used 2 times
Last modified: 1996-06-20
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5823
Valid CSS Valid XHTML 1.0 Strict