|
|
1.1 ! root 1: /* @(#) local.c: 1.5 6/26/84 */ ! 2: ! 3: /* # include <ctype.h> -- optim.h takes care of this */ ! 4: # include "optim.h" ! 5: # include "sgs.h" ! 6: # include "paths.h" ! 7: ! 8: # define ASDATE "" ! 9: # define LINELEN 400 ! 10: ! 11: # define FATAL(S) fatal((S), (char *) 0) ! 12: ! 13: char fixstr[256]; ! 14: char line[LINELEN]; ! 15: char * linptr; /* pointer to current line */ ! 16: int fixlen; ! 17: char * deflab; ! 18: int opn; ! 19: int m; ! 20: int numauto; /* number of bytes of automatic vars. */ ! 21: int numnreg; /* number of registers */ ! 22: boolean indata; ! 23: int lineno = IDVAL; ! 24: int nusel = 0; /* semantically useless instructions */ ! 25: int nspinc = 0; /* useless sp increments */ ! 26: int nmc = 0; /* move followed by compare */ ! 27: int nmal = 0; /* move followed by arithmetic or logical */ ! 28: int nredcmp = 0; /* redundant compares */ ! 29: int nadpsh = 0; /* addw3 or subw3 followed by push */ ! 30: int nadmsh = 0; /* addw3 or subw3 followed by mov */ ! 31: int nadmv = 0; /* replace addw3 or subw3 by mov */ ! 32: extern int ndisc; ! 33: ! 34: #ifdef IMPIL ! 35: zflag = false; /* debug flag for in--line expansion */ ! 36: #endif /* IMPIL */ ! 37: ! 38: # define numops 151 ! 39: ! 40: char *optbl[numops] = { ! 41: "acjl","acjle","acjleu","acjlu", ! 42: "addb2","addb3","addh2","addh3","addw2", ! 43: "addw3","alsw2","alsw3","andb2","andb3", ! 44: "andh2","andh3","andw2","andw3","arsw2", ! 45: "arsw3","atjnzb","atjnzh","atjnzw","bitw", ! 46: "call","cmpb","cmph","cmpw", ! 47: "decpth","decptw","divw2", ! 48: "divw3","extzv","faddd2","faddd3","fadds2", ! 49: "fadds3","fcmpd","fdivd2","fdivd3","fdivs2", ! 50: "fdivs3","fmuld2","fmuld3","fmuls2","fmuls3", ! 51: "fsubd2","fsubd3","fsubs2","fsubs3", ! 52: "incpth","incptw","inctst","insv", ! 53: "jbc","jbs","je","jg","jge", ! 54: "jgeu","jgu","jl","jle","jleu", ! 55: "jlu","jmp","jne","jneg","jnneg", ! 56: "jnpos","jnz","jpos","jsb","jz", ! 57: "llsw2","llsw3","lrsw2","lrsw3","mcomb", ! 58: "mcomh","mcomw","mnegb","mnegh","mnegw", ! 59: "modw2","modw3","movab","movah","movaw", ! 60: "movb","movbbh","movbbw","movbhw","movblb", ! 61: "movblh","movblw","movd","movdd","movds","movdw","movh", ! 62: "movsd","movsw","movtdw","movthb","movtsw", ! 63: "movtwb","movtwh","movw","movwd","movws", ! 64: "movzbh","movzbw","movzhw","mulw2","mulw3", ! 65: "orb2","orb3","orh2","orh3","orw2", ! 66: "orw3","pushaw","pushbb","pushbh", ! 67: "pushd","pushw","pushzb","pushzh","ret","save","subb2", ! 68: "subb3","subh2","subh3","subw2","subw3", ! 69: "switch","switcht", ! 70: "udivw2","udivw3","umodw2","umodw3","umulw2", ! 71: "umulw3","xorb2","xorb3","xorh2","xorh3", ! 72: "xorw2","xorw3" ! 73: }; ! 74: ! 75: FILE *stmpfile; /* Temporary storage for strings which are in the text ! 76: * section. The strings are collected and printed at ! 77: * the end of a function. Requirement for field update */ ! 78: extern char *mktemp(); ! 79: FILE *tmpopen(); ! 80: char tmpname[50]; /* name of file for storing string */ ! 81: FILE *atmpfile; /* Temporary storage for input while scanning for presence of ! 82: * #ASM in function */ ! 83: char atmpname[50]; ! 84: int asmflag = false; /* indicates whether an 'asm' has been encountered */ ! 85: long asmotell; /* location in the output file where the last function ended */ ! 86: int oaflag = false; /* indicates whether -OA flag was entered */ ! 87: boolean instring = false; ! 88: boolean inswitch = false; ! 89: #ifdef IMPIL ! 90: boolean swflag = false; /* switch table appears in function */ ! 91: NODE *lblnode = NULL; /* pointer to last label node */ ! 92: char *pcdecode(); ! 93: #endif /* IMPIL */ ! 94: ! 95: yylex() ! 96: { ! 97: extern char * strchr(); ! 98: ! 99: register char * s; /* temporary string ptr */ ! 100: register char * start; /* another temporary string ptr */ ! 101: register int i; /* temporary int */ ! 102: ! 103: #ifdef IMPIL ! 104: ilinit(); ! 105: #endif /* IMPIL */ ! 106: ! 107: asmopen(); /* open temp file for asm treatment */ ! 108: linptr = NULL; /* start off with no line */ ! 109: ! 110: while (linptr != NULL || ! 111: ((linptr = fgets(line,LINELEN,stdin)) != NULL && putasm(line))) ! 112: { ! 113: switch (*linptr) /* dispatch on first char in line */ ! 114: { ! 115: case '\n': /* ignore new line */ ! 116: break; ! 117: ! 118: case '#': /* check for special comments */ ! 119: s = linptr + 1; /* look at comment only, not # */ ! 120: ! 121: if (strncmp(s,"STRBEG",6) == 0) ! 122: instring = true; /* declare we're in a string */ ! 123: else if (strncmp(s,"STREND",6) == 0) ! 124: instring = false; /* now out of string-ness */ ! 125: else if (strncmp(s,"SWBEG",5) == 0) ! 126: inswitch = swflag = true; /* now in a switch table */ ! 127: else if (strncmp(s,"SWEND",5) == 0) ! 128: inswitch = false; /* out of switch table */ ! 129: else if (strncmp(s,"ASM",3) == 0) ! 130: asmflag = true; /* 'asm' appears in function */ ! 131: #ifdef IMPREGAL ! 132: else if (strncmp(s,"REGAL",5) == 0) ! 133: ratable( line ); /* register allocation opt */ ! 134: #endif /* IMPREGAL */ ! 135: ! 136: break; /* in any case, ignore line further */ ! 137: ! 138: case '.': /* compiler label */ ! 139: default: /* ordinary label */ ! 140: if (indata) /* in data section, just print */ ! 141: { ! 142: printf("%s",linptr); ! 143: break; ! 144: } ! 145: ! 146: /* reach here on labels in text space */ ! 147: ! 148: s = strchr(linptr,':'); /* find : */ ! 149: if (s == NULL) /* error if not found */ ! 150: { FATAL("Bad input format\n"); } ! 151: ! 152: *s++ = '\0'; /* change : to null, skip past */ ! 153: ! 154: /* for N3B (DMERT), switch code and jump tables are in text space, ! 155: ** but SWBEG, SWEND bracket just the table. For m32 and u3b, jump tables are ! 156: ** always in data space. ! 157: ** Write labels found when "inswitch" to special file for N3B only. ! 158: */ ! 159: ! 160: #ifdef N3B ! 161: if (instring || inswitch) /* inside special string or switch... */ ! 162: #else ! 163: if (instring) /* inside special string?... */ ! 164: #endif /* def N3B */ ! 165: { ! 166: putstr(linptr); /* write label to special file */ ! 167: putstr(":\n"); /* put : back in */ ! 168: } ! 169: else /* normal text space label */ ! 170: { ! 171: applbl(linptr,s-linptr); /* append label node */ ! 172: lastnode->uniqid = IDVAL; ! 173: } ! 174: linptr = s; /* continue processing past label */ ! 175: continue; /* next iteration */ ! 176: /* handle more usual case of line beginning with space/tab */ ! 177: case ' ': ! 178: case '\t': ! 179: for (s = linptr; isspace(*s); s++) /* skip white space */ ! 180: ; ! 181: ! 182: switch(*s) /* dispatch on next character */ ! 183: { ! 184: case '\0': /* line of white space */ ! 185: case '#': /* comment */ ! 186: case '\n': /* new line */ ! 187: break; /* ignore */ ! 188: ! 189: case '.': /* start of pseudo-op */ ! 190: pseudo(s); /* do pseudo-ops */ ! 191: break; ! 192: ! 193: default: /* normal instruction */ ! 194: if (indata) /* in data section this is weird case */ ! 195: printf("%s",linptr); /* just write line */ ! 196: else /* normal instruction in text */ ! 197: { ! 198: for (start = s; ! isspace(*s); s++) ! 199: ; /* skip over instruction mnemonic */ ! 200: ! 201: *s++ = '\0'; /* demarcate with null */ ! 202: ! 203: if ((opn = lookup(start)) == OTHER) ! 204: saveop(0,start,s-start,opn); ! 205: /* save funny instruction */ ! 206: else ! 207: saveop(0,optbl[m],0,opn); ! 208: /* save normal inst. (m set by ! 209: ** lookup) ! 210: */ ! 211: for ( ; isspace(*s); s++ ) ! 212: ; /* span white space */ ! 213: opn = 1; /* now save operands */ ! 214: op(s); /* skip intervening spaces/tabs */ ! 215: } ! 216: /* remember program name */ ! 217: #ifdef IMPIL ! 218: if( ntail.back->op == SAVE ) lblnode = ntail.back->back; ! 219: #endif /* IMPIL */ ! 220: break; ! 221: } /* end space/tab case */ ! 222: break; ! 223: } /* end first character switch */ ! 224: ! 225: linptr = NULL; /* indicate we're done with line */ ! 226: } /* end while */ ! 227: return; /* just exit */ ! 228: } ! 229: op (s) ! 230: register char *s; ! 231: { ! 232: register char *t; ! 233: ! 234: while (*s) ! 235: { ! 236: /* scan over leading space/tabs */ ! 237: while (*s == ' ' || *s == '\t') ! 238: s++; ! 239: ! 240: t = s; /* remember effective operand start */ ! 241: while(*s != ',' && *s != '\n') /* find end of operand */ ! 242: s++; ! 243: *s++ = '\0'; ! 244: saveop(opn++, t, s-t, 0); ! 245: if (*t == '.') /* operand is a label */ ! 246: if (inswitch) ! 247: addref(t, s-t); ! 248: } ! 249: lastnode->uniqid = lineno; ! 250: lineno = IDVAL; ! 251: } ! 252: ! 253: ! 254: pseudo (s) ! 255: register char *s; /* points at pseudo-op */ ! 256: { ! 257: void peep(); /* peephole improver */ ! 258: extern int cflag; /* independent part -c flag: ! 259: ** enable/disable common tail ! 260: */ ! 261: register int pop; /* pseudo-op code */ ! 262: char savechar; /* saved char that follows pseudo */ ! 263: char * word = s; /* pointer to beginning of pseudo */ ! 264: ! 265: /* The idea here is to stick in a NUL after the pseudo-op, then replace ! 266: ** the character we clobbered, rather than copy the pseudo-op somewhere else. ! 267: */ ! 268: ! 269: for ( ; ! isspace(*s); s++ ) ! 270: ; /* scan to white space char */ ! 271: savechar = *s; /* mark end of pseudo-op */ ! 272: *s = '\0'; ! 273: ! 274: /* if we're in a data section, we write all pseudo-ops to output, ! 275: ** except for .word's, which we must examine, and .text . ! 276: */ ! 277: ! 278: pop = plookup(word); /* identify pseudo-op */ ! 279: *s = savechar; /* restore saved character */ ! 280: if (indata) { /* check pseudo-op possibilities */ ! 281: if (pop == TEXT) { ! 282: indata = false; /* not in data section anymore */ ! 283: return; ! 284: } ! 285: else if (pop != WORD) { ! 286: printf("%s",linptr); /* output the line */ ! 287: return; ! 288: } ! 289: } ! 290: ! 291: switch (pop) { /* dispatch on pseudo-op in text */ ! 292: case BYTE: ! 293: putstr(linptr); ! 294: break; ! 295: case GLOBL: ! 296: case TV: ! 297: line[(m=length(line))-2] = '\0'; /* remove newline */ ! 298: appfl(line, m-1); ! 299: break; ! 300: case TEXT: ! 301: indata = false; ! 302: break; ! 303: case FIL: ! 304: case BSS: ! 305: printf("%s", line); ! 306: break; ! 307: case LN: ! 308: getln(line); ! 309: break; ! 310: case ALIGN: ! 311: line[(m=length(line))-2] = '\0'; /* remove NL */ ! 312: if (inswitch) { ! 313: #ifdef N3B /* for DMERT, put aligns in switch to special ! 314: ** output file with switch table ! 315: */ ! 316: line[m-2] = '\n'; /* restore new line */ ! 317: putstr(linptr); ! 318: #else ! 319: saveop(0, line+1, m-2, OTHER); ! 320: opn = 1; ! 321: lastnode->uniqid = lineno; ! 322: lineno = IDVAL; ! 323: #endif /* def N3B */ ! 324: } ! 325: else ! 326: appfl(line, m-1); ! 327: break; ! 328: case SET: ! 329: if (*++s == '.' && *++s == 'F') { ! 330: printf("\t.text\n"); ! 331: setauto(line); ! 332: printf("%s", line); ! 333: } ! 334: else if (s--, *s == '.' && *++s == 'R') { ! 335: setnreg(line); ! 336: line[(m=length(line))-2] = '\0'; ! 337: appfl(line,m-1); ! 338: } ! 339: else { ! 340: line[(m=length(line))-2] = '\0'; ! 341: appfl(line, m-1); ! 342: } ! 343: break; ! 344: case DATA: ! 345: printf("%s", line); ! 346: indata = true; ! 347: break; ! 348: case DEF: { ! 349: int found; ! 350: ! 351: line[(m=length(line))-2] = '\0'; /* remove newline */ ! 352: #ifdef IMPIL ! 353: while( isspace( *s ) ) s++; ! 354: if (*s++ == '.' && *s++ == 'e' && ! 355: *s++ == 'f') { /* .ef */ ! 356: appfl( "*", 2 ); ! 357: if( lblnode == NULL ) ! 358: { FATAL( "No label preceeding .bf pseudo op, file may already be optimized\n" ); } ! 359: appfl( lblnode->ops[0], ! 360: length( lblnode->ops[0])); ! 361: } ! 362: s--; ! 363: #endif /* IMPIL */ ! 364: found = 0; ! 365: while (true) { ! 366: while (*s++ != ';'); ! 367: if (*(s += 2) == 'e') /* endef */ ! 368: break; ! 369: /* There are two special cases for ".val". The first is ! 370: ** ".val ." . Since we're going to move the .def line, we need ! 371: ** to replace the '.' with a real label (which we make a hard label) ! 372: ** first. The second special case is ".val .Lxxx" (a local label). ! 373: ** This arises in the compiler from a user-defined label. The ! 374: ** problem here is that if the optimizer discards the local label, ! 375: ** there will be a reference to a non-existent label which will only ! 376: ** show up at link time. To avoid this, we delete (ignore) the whole ! 377: ** line. ! 378: */ ! 379: else if (*s++ == 'v') { /* .val */ ! 380: if (s[3] == '.') ! 381: { ! 382: if (s[4] == ';') /* first case */ ! 383: found = 1; ! 384: else if (s[4] == 'L') ! 385: found = 3; /* second */ ! 386: } ! 387: } ! 388: else if (*s == 'c') /* .scl */ ! 389: if (*(s+3) == '-' && *(s+4) == '1') { ! 390: found = 2; ! 391: break; ! 392: } ! 393: } ! 394: switch(found) ! 395: { ! 396: case 1: /* .val . */ ! 397: deflab = (char *) newlab(); ! 398: deffix(line, deflab); ! 399: appfl(fixstr, fixlen+1); ! 400: fixlbl(deflab); ! 401: applbl(deflab, length(deflab)); ! 402: lastnode->op = HLABEL; ! 403: lastnode-> uniqid = IDVAL; ! 404: break; ! 405: case 2: /* end of function */ ! 406: cflag = -1; /* turn off common tail ! 407: ** merging: improve speed, ! 408: ** not space. ! 409: */ ! 410: if( !asmflag || oaflag ) { ! 411: #ifdef IMPREGAL ! 412: numnreg = raoptim(numnreg, numauto); ! 413: numauto = raautos(numauto); ! 414: #endif /* IMPREGAL */ ! 415: #ifdef IMPIL ! 416: ilmark(); ! 417: #endif /* IMPIL */ ! 418: filter(); ! 419: optim(); ! 420: peep(); /* do peephole improvements */ ! 421: #ifdef IMPIL ! 422: ilstat(numnreg, numauto); ! 423: #endif /* IMPIL */ ! 424: chkauto(); ! 425: } ! 426: prtext(); ! 427: prstr(); ! 428: printf("%s", line); ! 429: printf("\n"); ! 430: asmchk(); ! 431: init(); ! 432: break; ! 433: case 3: /* .val .Lxxx */ ! 434: break; /* ignore line */ ! 435: default: /* other .defs */ ! 436: appfl(line, m-1); ! 437: break; ! 438: } ! 439: } ! 440: break; ! 441: case WORD: ! 442: s++; /* point past tab/nl */ ! 443: ! 444: /* we have to deal with whether .word is within a switch (SWBEG/SWEND) or ! 445: ** not, and whether or not it appears in a data section. ! 446: */ ! 447: ! 448: if (inswitch) { /* always add reference */ ! 449: register char * t = strchr(s,'\n'); ! 450: ! 451: *t = '\0'; /* change NL to null */ ! 452: addref(s,t+1-s); /* add the reference */ ! 453: *t = '\n'; /* restore NL */ ! 454: } ! 455: ! 456: if (indata) /* in data, flush to output */ ! 457: printf("%s",linptr); /* print line */ ! 458: else if (inswitch) /* text (implicit) and switch */ ! 459: putstr(linptr); /* flush to special file */ ! 460: else { /* text, not in switch */ ! 461: saveop(0,".word",6,OTHER); ! 462: opn = 1; /* doing first operand */ ! 463: op(s); ! 464: } ! 465: break; ! 466: ! 467: default: /* all unrecognized text ! 468: ** pseudo-ops ! 469: */ ! 470: if (! (instring || inswitch)) ! 471: printf("%s", linptr); /* flush to output */ ! 472: else ! 473: putstr(linptr); /* in(switch|string): to ! 474: ** special file ! 475: */ ! 476: break; ! 477: } ! 478: } ! 479: ! 480: int ! 481: plookup(s) /* look up pseudo op code */ ! 482: char *s; ! 483: ! 484: { ! 485: /* Note: to improve the linear search speed, these pseudo-ops ! 486: ** are ordered by frequency of occurrence in a sample of C programs. ! 487: */ ! 488: ! 489: static char *pops[numpops] = ! 490: { ! 491: ".word", ".byte", ".set", ".def", ".align", ! 492: ".data", ".text", ".globl", ".ln", ".bss", ! 493: ".file", ".tv" ! 494: }; ! 495: ! 496: static int popcode[numpops] = ! 497: { ! 498: WORD, BYTE, SET, DEF, ALIGN, ! 499: DATA, TEXT, GLOBL, LN, BSS, ! 500: FIL, TV ! 501: }; ! 502: ! 503: register int i; ! 504: ! 505: for (i = 0; i < numpops; i++) ! 506: if (!strcmp(s, pops[i])) ! 507: return(popcode[i]); ! 508: return(POTHER); ! 509: } ! 510: ! 511: ! 512: yyinit(flags) char * flags; { ! 513: ! 514: indata = false; ! 515: for (; *flags != '\0'; flags++) { ! 516: switch( *flags ) { ! 517: case 'V': ! 518: fprintf(stderr,"%s: optimizer - %s %s\n", ! 519: SGSNAME,RELEASE,ASDATE); ! 520: break; ! 521: case 'A': ! 522: oaflag = true; ! 523: break; ! 524: #ifdef IMPIL ! 525: case 'z': ! 526: zflag = true; ! 527: break; ! 528: #endif /* IMPIL */ ! 529: default: ! 530: fprintf(stderr,"Optimizer: invalid flag '%c'\n",*flags); ! 531: } ! 532: } ! 533: } ! 534: ! 535: char * ! 536: yysflgs( p ) char *p; { /* parse flags with sub fields */ ! 537: ! 538: switch( *p ) { ! 539: #ifdef IMPIL ! 540: case 'y': ! 541: p++; /* skip over 'y' to sub option */ ! 542: p = pcdecode( p ); ! 543: return( p ); ! 544: #endif /* IMPIL */ ! 545: default: ! 546: return( p ); ! 547: } ! 548: } ! 549: ! 550: int ! 551: lookup(op) char *op; { /* look up op code ordinal */ ! 552: ! 553: register int f,l,om,x; ! 554: static unsigned char ocode[numops] = { ! 555: ACJL,ACJLE,ACJLEU,ACJLU, ! 556: ADDB2,ADDB3,ADDH2,ADDH3,ADDW2, ! 557: ADDW3,ALSW2,ALSW3,ANDB2,ANDB3, ! 558: ANDH2,ANDH3,ANDW2,ANDW3,ARSW2, ! 559: ARSW3,ATJNZB,ATJNZH,ATJNZW,BITW, ! 560: CALL,CMPB,CMPH,CMPW, ! 561: DECPTH,DECPTW,DIVW2, ! 562: DIVW3,EXTZV,FADDD2,FADDD3,FADDS2, ! 563: FADDS3,FCMPD,FDIVD2,FDIVD3,FDIVS2, ! 564: FDIVS3,FMULD2,FMULD3,FMULS2,FMULS3, ! 565: FSUBD2,FSUBD3,FSUBS2,FSUBS3, ! 566: INCPTH,INCPTW,INCTST,INSV, ! 567: JBC,JBS,JE,JG,JGE, ! 568: JGEU,JGU,JL,JLE,JLEU, ! 569: JLU,JMP,JNE,JNEG,JNNEG, ! 570: JNPOS,JNZ,JPOS,JSB,JZ, ! 571: LLSW2,LLSW3,LRSW2,LRSW3,MCOMB, ! 572: MCOMH,MCOMW,MNEGB,MNEGH,MNEGW, ! 573: MODW2,MODW3,MOVAB,MOVAH,MOVAW, ! 574: MOVB,MOVBBH,MOVBBW,MOVBHW,MOVBLB, ! 575: MOVBLH,MOVBLW,MOVD,MOVDD,MOVDS,MOVDW,MOVH, ! 576: MOVSD,MOVSW,MOVTDW,MOVTHB,MOVTSW, ! 577: MOVTWB,MOVTWH,MOVW,MOVWD,MOVWS, ! 578: MOVZBH,MOVZBW,MOVZHW,MULW2,MULW3, ! 579: ORB2,ORB3,ORH2,ORH3,ORW2, ! 580: ORW3,PUSHAW,PUSHBB,PUSHBH, ! 581: PUSHD,PUSHW,PUSHZB,PUSHZH,RET,SAVE,SUBB2, ! 582: SUBB3,SUBH2,SUBH3,SUBW2,SUBW3, ! 583: SWITCH,SWITCHT, ! 584: UDIVW2,UDIVW3,UMODW2,UMODW3,UMULW2, ! 585: UMULW3,XORB2,XORB3,XORH2,XORH3, ! 586: XORW2,XORW3 ! 587: }; ! 588: ! 589: f = 0; ! 590: l = numops; ! 591: om = 0; ! 592: m = (f+l)/2; ! 593: while (m != om) { ! 594: x = strcmp(op,optbl[m]); ! 595: if (x == 0) ! 596: return((int) ocode[m]); ! 597: else if (x < 0) ! 598: l = m-1; ! 599: else ! 600: f = m+1; ! 601: om = m; ! 602: m = (f+l)/2; ! 603: } ! 604: return(OTHER); ! 605: } ! 606: ! 607: deffix(str,lbl) register char * str, * lbl; { /*change "val .;" to "val ..n;"*/ ! 608: ! 609: register char * nc; ! 610: register boolean scanning; ! 611: ! 612: scanning = true; ! 613: nc = fixstr; ! 614: fixlen = 0; ! 615: while (scanning) ! 616: if (*str == '.' && *(str+1) == ';') { ! 617: str++; ! 618: scanning = false; ! 619: } ! 620: else { ! 621: *nc++ = *str++; ! 622: fixlen++; ! 623: } ! 624: while (*nc++ = *lbl++) ! 625: fixlen++; ! 626: nc--; ! 627: while (*nc++ = *str++) ! 628: fixlen++; ! 629: } ! 630: ! 631: fixlbl(str) register char * str; { /* add colon to end of label */ ! 632: ! 633: while (*str++); ! 634: *--str = ':'; ! 635: *++str = '\0'; ! 636: } ! 637: ! 638: int ! 639: length(str) register char * str; { /* return length of string (including \0) */ ! 640: ! 641: register int l; ! 642: ! 643: l = 1; ! 644: while (*str++) ! 645: l++; ! 646: return (l); ! 647: } ! 648: ! 649: getln(str) register char * str; { /* extract line number */ ! 650: ! 651: while (!isdigit(*str)) ! 652: str++; ! 653: lineno = 0; ! 654: while (isdigit(*str)) { ! 655: lineno = lineno * 10 + *str - '0'; ! 656: str++; ! 657: } ! 658: } ! 659: ! 660: prinst(p) register NODE *p; { /* print instruction */ ! 661: if (p->uniqid != IDVAL) ! 662: printf(" .ln %d\n", p->uniqid); ! 663: #ifdef IMPIL ! 664: if (p->op == CALL ) { ! 665: printf("@ %d %s %s\n", ! 666: numauto + ( int ) p->ops[MAXOPS], p->op1 + 1, p->op2 ); ! 667: p->ops[MAXOPS] = NULL; ! 668: } ! 669: #endif /* IMPIL */ ! 670: switch (p->op) { ! 671: case LABEL: ! 672: printf("%s:\n", p->opcode); ! 673: break; ! 674: case HLABEL: ! 675: printf("%s\n", p->opcode); ! 676: break; ! 677: case MISC: ! 678: printf(" %s\n", p->opcode); ! 679: break; ! 680: case RET: ! 681: if (*(p->op1 + 1) == '-') { ! 682: printf(" RET\n"); ! 683: break; ! 684: } ! 685: default: ! 686: printf(" %s ", p->opcode); ! 687: if (p->op1 != NULL) ! 688: printf("%s", p->op1); ! 689: if (p->op2 != NULL) ! 690: printf(",%s", p->op2); ! 691: if (p->op3 != NULL) ! 692: printf(",%s", p->op3); ! 693: if (p->op4 != NULL) ! 694: printf(",%s", p->op4); ! 695: printf("\n"); ! 696: break; ! 697: } ! 698: } ! 699: ! 700: boolean ! 701: ishlp(p) register NODE *p; { /* return true if a fixed label present */ ! 702: ! 703: for (; (p->op == LABEL || p->op == HLABEL); p=p->forw) ! 704: if (ishl(p)) ! 705: return(true); ! 706: return(false); ! 707: } ! 708: ! 709: FILE * ! 710: tmpopen() { ! 711: strcpy( tmpname, TMPDIR ); ! 712: strcat( tmpname, "/25ccXXXXXX" ); ! 713: return( fopen( mktemp( tmpname ), "w" ) ); ! 714: } ! 715: ! 716: putstr(string) char *string; { ! 717: /* Place string from the text section into a temporary file ! 718: * to be output at the end of the function */ ! 719: ! 720: if( stmpfile == NULL ) ! 721: stmpfile = tmpopen(); ! 722: fprintf(stmpfile,"%s",string); ! 723: } ! 724: ! 725: prstr() { ! 726: /* print the strings stored in stmpfile at the end of the function */ ! 727: ! 728: if( stmpfile != NULL ) { ! 729: register int c; ! 730: ! 731: stmpfile = freopen( tmpname, "r", stmpfile ); ! 732: if( stmpfile != NULL ) ! 733: while( (c=getc(stmpfile)) != EOF ) ! 734: putchar( c ); ! 735: else ! 736: { ! 737: fprintf( stderr, "optimizer error: "); ! 738: fprintf( stderr, "lost temp file\n"); ! 739: } ! 740: (void) fclose( stmpfile ); /* close and delete file */ ! 741: unlink( tmpname ); ! 742: stmpfile = NULL; ! 743: } ! 744: } ! 745: ! 746: /* opens the temp file for storing input while looking for 'asm' */ ! 747: asmopen() { ! 748: strcpy( atmpname, TMPDIR ); ! 749: strcat( atmpname, "/asmXXXXXX" ); ! 750: atmpfile = fopen( mktemp( atmpname ), "w" ); ! 751: asmotell = ftell( stdout ); ! 752: } ! 753: ! 754: /* writes to temp file for 'asm' processing */ ! 755: int ! 756: putasm( line ) ! 757: char *line; ! 758: { ! 759: return( fputs( line, atmpfile ) != EOF ); ! 760: } ! 761: ! 762: /* checks for 'asm' in files and undoes code movement */ ! 763: asmchk() ! 764: { ! 765: register c; ! 766: long endotell; ! 767: extern int vars; ! 768: ! 769: if( asmflag && !oaflag ) { ! 770: if( freopen( atmpname, "r", atmpfile ) != NULL ) { ! 771: endotell = ftell( stdout ); ! 772: fseek( stdout, asmotell, 0 ); /* This is okay as long ! 773: as IMPIL is defined because it ! 774: is not really stdout, it is the file used by ! 775: in-line expansion. That file is still used, ! 776: even when in-line expansion is suppressed. ! 777: If IMPIL is not defined, optim will not work ! 778: correctly to a terminal, but it will work ! 779: correctly to a file. ! 780: This should be fixed. (fbw) */ ! 781: while( ( c = getc( atmpfile ) ) != EOF ) putchar( c ); ! 782: while( ftell( stdout ) < endotell ) printf( "!\n" ); ! 783: } ! 784: else fprintf( stderr, "optimizer error: asm temp file lost\n" ); ! 785: } ! 786: freopen( atmpname, "w", atmpfile ); ! 787: asmotell = ftell( stdout ); ! 788: asmflag = false; ! 789: vars=0; /* reinitialize for global reg allocation */ ! 790: } ! 791: ! 792: putp(p,c) register NODE *p; char *c; { /* insert pointer into jump node */ ! 793: ! 794: if (p->op == CALL) ! 795: p->op2 = c; ! 796: else if (p->op == JBC || p->op == JBS) ! 797: p->op3 = c; ! 798: else if (p->op == RET) { ! 799: p->op1 = NULL; ! 800: p->op2 = c; ! 801: } ! 802: else ! 803: p->op1 = c; ! 804: } ! 805: ! 806: revbr(p) NODE *p; { /* reverse jump in node p */ ! 807: ! 808: switch (p->op) { ! 809: case JZ: p->op = JNZ; p->opcode = "jnz"; break; ! 810: case JNZ: p->op = JZ; p->opcode = "jz"; break; ! 811: case JPOS: p->op = JNPOS; p->opcode = "jnpos"; break; ! 812: case JNPOS: p->op = JPOS; p->opcode = "jpos"; break; ! 813: case JNEG: p->op = JNNEG; p->opcode = "jnneg"; break; ! 814: case JNNEG: p->op = JNEG; p->opcode = "jneg"; break; ! 815: case JE: p->op = JNE; p->opcode = "jne"; break; ! 816: case JNE: p->op = JE; p->opcode = "je"; break; ! 817: case JL: p->op = JGE; p->opcode = "jge"; break; ! 818: case JLE: p->op = JG; p->opcode = "jg"; break; ! 819: case JG: p->op = JLE; p->opcode = "jle"; break; ! 820: case JGE: p->op = JL; p->opcode = "jl"; break; ! 821: case JLU: p->op = JGEU; p->opcode = "jgeu"; break; ! 822: case JLEU: p->op = JGU; p->opcode = "jgu"; break; ! 823: case JGU: p->op = JLEU; p->opcode = "jleu"; break; ! 824: case JGEU: p->op = JLU; p->opcode = "jlu"; break; ! 825: case JBC: p->op = JBS; p->opcode = "jbs"; break; ! 826: case JBS: p->op = JBC; p->opcode = "jbc"; break; ! 827: } ! 828: } ! 829: ! 830: char * ! 831: dst(p) NODE *p; { /* return pointer to dst operand string */ ! 832: ! 833: switch (p->op) { ! 834: case ACJL: case ACJLU: case ACJLEU: case ATJNZB: case ATJNZH: ! 835: case ATJNZW: case INCTST: ! 836: case INCPTH: case INCPTW: case DECPTH: case DECPTW: ! 837: return (p->op1); ! 838: case MCOMB: case MCOMH: case MCOMW: case MOVZBH: case MOVZBW: ! 839: case MOVZHW: case MOVAB: case MOVAH: case MOVAW: case ANDB2: ! 840: case ANDH2: case ANDW2: case ORB2: case ORH2: case ORW2: ! 841: case XORB2: case XORH2: case XORW2: case MOVB: case MOVH: ! 842: case MOVW: case MOVBBH: case MOVBBW: case MOVBHW: case MOVTHB: ! 843: case MOVTWB: case MOVTWH: case MNEGB: case MNEGH: case MNEGW: ! 844: case ADDB2: case ADDH2: case ADDW2: case SUBB2: case SUBH2: ! 845: case SUBW2: case MULW2: case UMULW2: case DIVW2: case UDIVW2: ! 846: case MODW2: case UMODW2: case LLSW2: case LRSW2: case ALSW2: ! 847: case ARSW2: case FADDD2: case FSUBD2: case FMULD2: case FDIVD2: ! 848: case FADDS2: case FSUBS2: case FMULS2: case FDIVS2: ! 849: case MOVWS: case MOVWD: case MOVTSW: case MOVTDW: ! 850: case MOVSW: case MOVDW: case MOVSD: case MOVDS: case MOVDD: ! 851: case MOVD: ! 852: return(p->op2); ! 853: case ANDB3: case ANDH3: case ANDW3: case ORB3: case ORH3: ! 854: case ORW3: case XORB3: case XORH3: case XORW3: case LLSW3: ! 855: case LRSW3: case ADDB3: case ADDH3: case ADDW3: case SUBB3: ! 856: case SUBH3: case SUBW3: case MULW3: case UMULW3: case DIVW3: ! 857: case UDIVW3: case MODW3: case UMODW3: case ALSW3: case ARSW3: ! 858: case FADDD3: case FSUBD3: case FMULD3: case FDIVD3: ! 859: case FADDS3: case FSUBS3: case FMULS3: case FDIVS3: ! 860: return(p->op3); ! 861: case INSV: case EXTZV: ! 862: return(p->op4); ! 863: default: ! 864: return (NULL); ! 865: } ! 866: } ! 867: ! 868: int ! 869: stype(cop) int cop; { /* return implied type of op code */ ! 870: ! 871: switch (cop) { ! 872: case MCOMB: case ANDB2: case ANDB3: case ORB2: case ORB3: ! 873: case XORB2: case XORB3: case MOVB: case MOVTHB: case MOVTWB: ! 874: case MNEGB: case ADDB2: case ADDB3: case SUBB2: case SUBB3: ! 875: case CMPB: ! 876: return (1); ! 877: case MCOMH: case MOVZBH: case ANDH2: case ANDH3: case ORH2: ! 878: case ORH3: case XORH2: case XORH3: case MOVH: case MOVBBH: ! 879: case MOVTWH: case MNEGH: case ADDH2: case ADDH3: case SUBH2: ! 880: case SUBH3: case CMPH: ! 881: return (2); ! 882: default: ! 883: return (4); ! 884: ! 885: case FADDD2: case FSUBD2: case FMULD2: case FDIVD2: ! 886: case FADDD3: case FSUBD3: case FMULD3: case FDIVD3: ! 887: case FCMPD: case MOVSD: case MOVWD: case MOVDD: ! 888: return(8); ! 889: } ! 890: } ! 891: ! 892: boolean ! 893: samereg(cp1,cp2) char *cp1, *cp2; { /* return true if same register */ ! 894: ! 895: if (*cp1 == '%' && *cp1 == *cp2 && *++cp1 == *++cp2 && *++cp1 == *++cp2) ! 896: return(true); ! 897: else ! 898: return(false); ! 899: } ! 900: ! 901: boolean ! 902: usesreg(cp1,cp2) register char *cp1, *cp2; { /*return true if cp2 used in cp1*/ ! 903: ! 904: while(*cp1 != '\0') { ! 905: if (*cp1 == *cp2 && *(cp1+1) == *(cp2+1) && ! 906: *(cp1+2) == *(cp2+2)) ! 907: return(true); ! 908: cp1++; ! 909: } ! 910: return(false); ! 911: } ! 912: ! 913: dstats() { /* print stats on machine dependent optimizations */ ! 914: ! 915: fprintf(stderr,"%d semantically useless instructions(s)\n", nusel); ! 916: fprintf(stderr,"%d useless move(s) before compare(s)\n", nmc); ! 917: fprintf(stderr,"%d merged move-arithmetic/logical(s)\n", nmal); ! 918: fprintf(stderr,"%d useless sp increment(s)\n", nspinc); ! 919: fprintf(stderr,"%d redundant compare(s)\n", nredcmp); ! 920: } ! 921: ! 922: wrapup() { /* print unprocessed text and update statistics file */ ! 923: ! 924: FILE *fopen(), *sp; ! 925: int mc,mal,usel,spinc,redcmp,disc,inst; ! 926: ! 927: if (n0.forw != NULL) { ! 928: printf(" .text\n"); ! 929: filter(); ! 930: prtext(); ! 931: prstr(); ! 932: } ! 933: #ifdef IMPIL ! 934: ilfile(); ! 935: #endif /* IMPIL */ ! 936: ! 937: (void) fclose( atmpfile ); /* close and delete file */ ! 938: unlink( atmpname ); ! 939: ! 940: sp = fopen("/g1/dap/optim/stats/statfile","r"); ! 941: if (sp != NULL) { ! 942: fscanf(sp, "%d %d %d %d %d %d %d", ! 943: &mc,&mal,&usel,&spinc,&redcmp,&disc,&inst); ! 944: fclose(sp); ! 945: mc += nmc; ! 946: mal += nmal; ! 947: usel += nusel; ! 948: spinc += nspinc; ! 949: redcmp += nredcmp; ! 950: disc += ndisc; ! 951: inst += ninst; ! 952: sp = fopen("/g1/dap/optim/stats/statfile","w"); ! 953: if (sp != NULL) { ! 954: fprintf(sp, "%d %d %d %d %d %d %d \n", ! 955: mc,mal,usel,spinc,redcmp,disc,inst); ! 956: fclose(sp); ! 957: } ! 958: } ! 959: } ! 960: ! 961: setauto(str) char *str; { /* set indicator for number of autos */ ! 962: ! 963: while (*str++ != ',') ! 964: ; ! 965: numauto = atoi(str); /* remember # of bytes */ ! 966: return; ! 967: } ! 968: ! 969: setnreg(str) char *str; { /* set indicator for number of registers */ ! 970: ! 971: while (*str++ != ',') ! 972: ; ! 973: numnreg = atoi(str); /* remember number of registers */ ! 974: return; ! 975: } ! 976: chkauto() /* delete sp increment if no autos, or fewer than 15 words */ ! 977: { ! 978: NODE *p; ! 979: ! 980: /* 5.0 UNIX microcode on the 3B20 supports a "save" instruction that ! 981: ** can also allocate temporary space on the stack (up to 15 words). ! 982: ** Standard IS25 "save" does not do the stack allocation. ! 983: */ ! 984: ! 985: #ifndef IMPREGAL ! 986: #ifdef UCODE50 ! 987: if (numauto <= 4*15) /* save handles up to 15 words */ ! 988: #else ! 989: if (numauto == 0) /* if no auto's allocated */ ! 990: #endif /* def UCODE50 */ ! 991: { ! 992: p = n0.forw; ! 993: while (islabel( p )) ! 994: p = p->forw; ! 995: if ( strcmp(p->opcode,"save") == 0 ! 996: && p->forw->op == ADDW2 ! 997: ) /* save followed by addw2 */ ! 998: { ! 999: #ifdef UCODE50 /* must add second operand to save */ ! 1000: p->op2 = getspace(1+2+1); /* for "&dd\0" */ ! 1001: (void) sprintf(p->op2,"&%d",numauto/4); ! 1002: /* append operand with # of autos */ ! 1003: #endif /* def UCODE50 */ ! 1004: p = p->forw; /* point at ADDW2 */ ! 1005: DELNODE( p ); /* delete it */ ! 1006: nspinc++; /* discarded sp increment */ ! 1007: ndisc++; /* discarded instruction */ ! 1008: } ! 1009: } ! 1010: #endif /* der IMPREGAL */ ! 1011: #ifndef IMPIL ! 1012: numauto = 0; /* reset for next routine */ ! 1013: #endif /* IMPIL */ ! 1014: return; ! 1015: } ! 1016: ! 1017: uses(p) NODE *p; { /* set register use bits */ ! 1018: ! 1019: switch (p->op) { ! 1020: case MOVBLB: case MOVBLH: case MOVBLW: ! 1021: return (0x7); ! 1022: case MCOMB: case MCOMH: case MCOMW: case MOVZBH: case MOVZBW: ! 1023: case MOVZHW: case MOVAB: case MOVAH: case MOVAW: case MOVB: ! 1024: case MOVH: case MOVW: case MOVBBH: case MOVBBW: case MOVBHW: ! 1025: case MOVTHB: case MOVTWB: case MOVTWH: case MNEGB: case MNEGH: ! 1026: case MNEGW: ! 1027: case MOVWS: case MOVTSW: case MOVSW: ! 1028: return (scanreg(p->op1,false) | scanreg(p->op2,true) | ! 1029: scanreg(p->op3,false) | scanreg(p->op4,false)); ! 1030: case ANDB3: case ANDH3: case ANDW3: case ORB3: case ORH3: ! 1031: case ORW3: case XORB3: case XORH3: case XORW3: case LLSW3: ! 1032: case LRSW3: case ADDB3: case ADDH3: case ADDW3: case SUBB3: ! 1033: case SUBH3: case SUBW3: case MULW3: case UMULW3: case DIVW3: ! 1034: case UDIVW3: case MODW3: case UMODW3: case ALSW3: case ARSW3: ! 1035: return (scanreg(p->op1,false) | scanreg(p->op2,false) | ! 1036: scanreg(p->op3,true) | scanreg(p->op4,false)); ! 1037: case INSV: case EXTZV: ! 1038: return (scanreg(p->op1,false) | scanreg(p->op2,false) | ! 1039: scanreg(p->op3,false) | scanreg(p->op4,true)); ! 1040: case CALL: ! 1041: return (scanreg(p->op1,false) | scanreg(p->op2,false) | ! 1042: scanreg(p->op3,false) | scanreg(p->op4,false) | ! 1043: ( 1 << 2 )); /* call must preserve %r2; ! 1044: ptr to returned structure */ ! 1045: case RET: ! 1046: return (scanreg(p->op1,false) | scanreg(p->op2,false) | ! 1047: scanreg(p->op3,false) | scanreg(p->op4,false) | ! 1048: RETREG); /* function return values */ ! 1049: case JSB: ! 1050: return (scanreg(p->op1,false) | scanreg(p->op2,false) | ! 1051: scanreg(p->op3,false) | scanreg(p->op4,false) | ! 1052: 1 ); /* cludge for profiler: %r0 is used to pass ! 1053: an argument to _mcount */ ! 1054: case FADDD2: case FSUBD2: case FMULD2: case FDIVD2: ! 1055: case FCMPD: ! 1056: return( dscanreg(p->op1,false) | dscanreg(p->op2,false) | ! 1057: scanreg(p->op3,false) | scanreg(p->op4,false) ); ! 1058: ! 1059: case FADDD3: case FSUBD3: case FMULD3: case FDIVD3: ! 1060: return( dscanreg(p->op1,false) | dscanreg(p->op2,false) | ! 1061: dscanreg(p->op3,true) | scanreg(p->op4,false) ); ! 1062: ! 1063: case MOVWD: case MOVSD: ! 1064: return( scanreg(p->op1,false) | dscanreg(p->op2,true) | ! 1065: scanreg(p->op3,false) | scanreg(p->op4,false) ); ! 1066: ! 1067: case MOVDW: case MOVTDW: case MOVDS: ! 1068: return( dscanreg(p->op1,false) | scanreg(p->op2,true) | ! 1069: scanreg(p->op3,false) | scanreg(p->op4,false) ); ! 1070: ! 1071: case MOVDD: case MOVD: ! 1072: return( dscanreg(p->op1,false) | dscanreg(p->op2,true) | ! 1073: scanreg(p->op3,false) | scanreg(p->op4,false) ); ! 1074: ! 1075: default: ! 1076: return (scanreg(p->op1,false) | scanreg(p->op2,false) | ! 1077: scanreg(p->op3,false) | scanreg(p->op4,false) | ! 1078: ( iscbr( p ) ? CONCODES : 0 ) ); ! 1079: } ! 1080: } ! 1081: ! 1082: scanreg(cp,flag) register char *cp; int flag; { /* determine registers ! 1083: referenced in operand */ ! 1084: ! 1085: int reg,set; ! 1086: ! 1087: if (cp == NULL) ! 1088: return (0); ! 1089: if (flag && *cp == '%') ! 1090: return (0); ! 1091: set = 0; ! 1092: while (*cp != '\0') { ! 1093: if (*cp == '%') { ! 1094: cp++; ! 1095: switch (*cp) { ! 1096: case 'r': ! 1097: cp++; ! 1098: reg = *cp - '0'; ! 1099: break; ! 1100: case 'a': ! 1101: cp++; ! 1102: reg = 9; ! 1103: break; ! 1104: case 'f': ! 1105: cp++; ! 1106: reg = 10; ! 1107: break; ! 1108: case 's': ! 1109: cp++; ! 1110: reg = 11; ! 1111: break; ! 1112: } ! 1113: set = set | 1 << reg; ! 1114: } ! 1115: cp++; ! 1116: } ! 1117: return(set); ! 1118: } ! 1119: ! 1120: /* determine registers used for double operand */ ! 1121: ! 1122: int ! 1123: dscanreg(cp,flag) ! 1124: char * cp; /* operand string */ ! 1125: boolean flag; /* true if register is destination */ ! 1126: { ! 1127: int temp = scanreg(cp,flag); /* do normal scan */ ! 1128: ! 1129: if (*cp == '%') /* if direct register reference... */ ! 1130: temp = 3*temp; /* set bit and its left neighbor (reg+1) */ ! 1131: ! 1132: return(temp); ! 1133: } ! 1134: ! 1135: sets(p) NODE *p; { /* set register destination bits */ ! 1136: ! 1137: char *cp, *dst(); ! 1138: int o; ! 1139: boolean dblflag = false; /* true if register double operand */ ! 1140: ! 1141: switch (o = p->op) { ! 1142: case MOVBLB: case MOVBLH: case MOVBLW: ! 1143: return (0x0007); ! 1144: ! 1145: /* Procedure calls could potentially clobber all of the scratch registers. ! 1146: ** We would like call to "kill" all of them, but we can only be reasonably ! 1147: ** safe by saying it kills those registers in which it returns values. ! 1148: */ ! 1149: ! 1150: case CALL: ! 1151: return(RETREG | CONCODES); ! 1152: ! 1153: /* Register doubles set two registers at a time: r and r+1 */ ! 1154: ! 1155: case FADDD2: case FSUBD2: case FMULD2: case FDIVD2: ! 1156: case FADDD3: case FSUBD3: case FMULD3: case FDIVD3: ! 1157: case MOVWD: case MOVSD: case MOVDD: case MOVD: ! 1158: dblflag = true; ! 1159: ! 1160: default: ! 1161: cp = dst(p); ! 1162: if (cp != NULL) ! 1163: return((dblflag ? 3*setreg(cp) : setreg(cp)) | CONCODES ); ! 1164: /* return reg bit and its left ! 1165: ** neighbor on double ! 1166: */ ! 1167: else ! 1168: return ( ( ( o == RET ) ! 1169: || ( CMPB <= o && o <= ATJNZW ) ! 1170: || ( PUSHAW <= o && o <= PUSHBH ) ) ? CONCODES : 0 ); ! 1171: } ! 1172: } ! 1173: ! 1174: setreg(cp) char *cp; { /* set index of register destination (if one) */ ! 1175: ! 1176: if (*cp == '%') ! 1177: switch (*++cp) { ! 1178: case 'r': ! 1179: cp++; ! 1180: return (1 << (*cp - '0')); ! 1181: case 'a': ! 1182: return (1 << 9); ! 1183: case 'f': ! 1184: return (1 << 10); ! 1185: case 's': ! 1186: return (1 << 11); ! 1187: default: /* unrecognized name */ ! 1188: break; ! 1189: } ! 1190: return(0); /* for non-register or unrecognized */ ! 1191: } ! 1192: ! 1193: boolean ! 1194: isdead(cp,p) char *cp; NODE *p; { /* true iff *cp is dead after p */ ! 1195: ! 1196: int reg; ! 1197: ! 1198: if (*cp != '%') ! 1199: return(false); ! 1200: switch(*++cp) { ! 1201: case 'r': ! 1202: reg = *++cp - '0'; ! 1203: break; ! 1204: case 'a': ! 1205: reg = 9; ! 1206: break; ! 1207: case 'f': ! 1208: reg = 10; ! 1209: break; ! 1210: case 's': ! 1211: reg = 11; ! 1212: break; ! 1213: default: /* unrecognized name */ ! 1214: return(false); ! 1215: } ! 1216: if ((p->nlive & (1 << reg)) == 0) ! 1217: return(true); ! 1218: else ! 1219: return(false); ! 1220: } ! 1221: char * ! 1222: getp(p) NODE *p; { /* return pointer to jump destination operand */ ! 1223: ! 1224: switch (p->op) { ! 1225: case JMP: case JSB: case JZ: case JNZ: ! 1226: case JPOS: case JNPOS: case JNEG: case JNNEG: case JE: ! 1227: case JNE: case JL: case JLE: case JG: case JGE: ! 1228: case JLU: case JLEU: case JGU: case JGEU: ! 1229: return(p->op1); ! 1230: case RET: ! 1231: case SWITCH: ! 1232: case SWITCHT: ! 1233: return(NULL); ! 1234: case JBC: case JBS: ! 1235: return(p->op3); ! 1236: } ! 1237: } ! 1238: ! 1239: char * ! 1240: newlab() { /* generate a new label */ ! 1241: ! 1242: static int lbn = 0; ! 1243: char *c; ! 1244: ! 1245: c = (char *)getspace(lbn < 100 ? 6 : (lbn < 1000 ? 7 : 8)); ! 1246: sprintf(c, "..%d\0", lbn); ! 1247: lbn++; ! 1248: return(c); ! 1249: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.