Annotation of researchv9/jerq/sgs/optim/local.c, revision 1.1.1.1

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:        }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.