Annotation of researchv9/jerq/sgs/optim/local.c, revision 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.