Annotation of uae/src/cpuopti.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  * UAE - The Un*x Amiga Emulator
                      3:  *
                      4:  * cpuopti.c - Small optimizer for cpu*.s files
                      5:  *             Based on work by Tauno Taipaleenmaki
                      6:  *
                      7:  * Copyright 1996 Bernd Schmidt
                      8:  */
                      9: 
                     10: #include "sysconfig.h"
                     11: #include "sysdeps.h"
                     12: #include <ctype.h>
                     13: 
                     14: #include "options.h"
                     15: 
                     16: struct line {
                     17:     struct line *next, *prev;
1.1.1.3 ! root       18:     int delet;
1.1       root       19:     char *data;
                     20: };
                     21: 
                     22: struct func {
                     23:     struct line *first_line, *last_line;
                     24:     int initial_offset;
                     25: };
                     26: 
                     27: static void oops(void)
                     28: {
                     29:     fprintf(stderr, "Corrupted assembly file!\n");
                     30:     abort();
                     31: }
                     32: 
                     33: static char * match(struct line *l, const char *m)
                     34: {
                     35:     char *str = l->data;
                     36:     int len = strlen(m);
                     37:     while (isspace(*str))
                     38:        str++;
1.1.1.3 ! root       39: 
        !            40:     if (strncmp(str, m, len) != 0)
1.1       root       41:        return NULL;
                     42:     return str + len;
                     43: }
                     44: 
1.1.1.3 ! root       45: static int insn_references_reg (struct line *l, char *reg)
        !            46: {
        !            47:     if (reg[0] != 'e') {
        !            48:        fprintf(stderr, "Unknown register?!?\n");
        !            49:        abort();
        !            50:     }
        !            51:     if (strstr (l->data, reg) != 0)
        !            52:        return 1;
        !            53:     if (strstr (l->data, reg+1) != 0)
        !            54:        return 1;
        !            55:     if (strcmp (reg, "eax") == 0
        !            56:        && (strstr (l->data, "%al") != 0 || strstr (l->data, "%ah") != 0))
        !            57:        return 1;
        !            58:     if (strcmp (reg, "ebx") == 0
        !            59:        && (strstr (l->data, "%bl") != 0 || strstr (l->data, "%bh") != 0))
        !            60:        return 1;
        !            61:     if (strcmp (reg, "ecx") == 0
        !            62:        && (strstr (l->data, "%cl") != 0 || strstr (l->data, "%ch") != 0))
        !            63:        return 1;
        !            64:     if (strcmp (reg, "edx") == 0
        !            65:        && (strstr (l->data, "%dl") != 0 || strstr (l->data, "%dh") != 0))
        !            66:        return 1;
        !            67:     return 0;
        !            68: }
        !            69: 
1.1       root       70: static void do_function(struct func *f)
                     71: {
                     72:     int pops_at_end = 0;
1.1.1.3 ! root       73:     struct line *l, *fl, *l2;
1.1       root       74:     char *s, *s2;
                     75:     int in_pop_area = 1;
1.1.1.3 ! root       76: 
1.1       root       77:     f->initial_offset = 0;
1.1.1.3 ! root       78: 
1.1       root       79:     l = f->last_line;
                     80:     fl = f->first_line;
                     81: 
                     82:     if (!match(l,"ret"))
                     83:        oops();
1.1.1.3 ! root       84: 
1.1       root       85:     while (!match(fl, "op_"))
                     86:        fl = fl->next;
                     87:     fl = fl->next;
1.1.1.3 ! root       88: 
        !            89:     /* Try reordering the insns at the end of the function so that the
        !            90:      * pops are all at the end. */
        !            91:     l2 = l->prev;
        !            92:     /* Tolerate one stack adjustment */
        !            93:     if (match (l2, "addl $") && strstr(l2->data, "esp") != 0)
        !            94:        l2 = l2->prev;
        !            95:     for (;;) {
        !            96:        char *forbidden_reg;
        !            97:        struct line *l3, *l4;
        !            98: 
        !            99:        while (match (l2, "popl %"))
        !           100:            l2 = l2->prev;
        !           101: 
        !           102:        l3 = l2;
        !           103:        for (;;) {
        !           104:            forbidden_reg = match (l3, "popl %");
        !           105:            if (forbidden_reg)
        !           106:                break;
        !           107:            if (l3 == fl)
        !           108:                goto reordered;
        !           109:            /* Jumps and labels put an end to our attempts... */
        !           110:            if (strstr (l3->data, ".L") != 0)
        !           111:                goto reordered;
        !           112:            /* Likewise accesses to the stack pointer... */
        !           113:            if (strstr (l3->data, "esp") != 0)
        !           114:                goto reordered;
        !           115:            /* Function calls... */
        !           116:            if (strstr (l3->data, "call") != 0)
        !           117:                goto reordered;
        !           118:            l3 = l3->prev;
        !           119:        }
        !           120:        if (l3 == l2)
        !           121:            abort();
        !           122:        for (l4 = l2; l4 != l3; l4 = l4->prev) {
        !           123:            /* The register may not be referenced by any of the insns that we
        !           124:             * move the popl past */
        !           125:            if (insn_references_reg (l4, forbidden_reg))
        !           126:                goto reordered;
        !           127:        }
        !           128:        l3->prev->next = l3->next;
        !           129:        l3->next->prev = l3->prev;
        !           130:        l2->next->prev = l3;
        !           131:        l3->next = l2->next;
        !           132:        l2->next = l3;
        !           133:        l3->prev = l2;
        !           134:     }
        !           135: reordered:
        !           136: 
        !           137:     l = l->prev;
        !           138: 
1.1       root      139:     s = match(l, "addl $");
                    140:     s2 = match(fl, "subl $");
1.1.1.3 ! root      141:     if (s && s2) {
        !           142:        if (strcmp(s,s2) == 0) {
        !           143:            int v = 0;
        !           144:            while (isdigit(*s)) {
        !           145:                v = v * 10 + (*s) - '0';
        !           146:                s++;
        !           147:            }
        !           148:            if (strcmp(s, ",%esp") == 0) {
        !           149:                f->initial_offset = v;
        !           150:                l->delet = 2;
        !           151:                fl->delet = 3;
        !           152:                l = l->prev;
        !           153:                fl = fl->next;
        !           154:            } else
        !           155:                in_pop_area = 0;
        !           156:        } else {
        !           157:            fprintf (stderr, "Stack adjustment not matching\n");
1.1       root      158:            in_pop_area = 0;
1.1.1.3 ! root      159:        }
        !           160: 
1.1       root      161:     }
                    162:     while (in_pop_area) {
                    163:        char *popm, *pushm;
                    164:        popm = match(l, "popl %");
                    165:        pushm = match(fl, "pushl %");
                    166:        if (popm && pushm && strcmp(pushm, popm) == 0) {
                    167:            pops_at_end++;
1.1.1.3 ! root      168:            fl->delet = l->delet = 1;
1.1       root      169:        } else
                    170:            in_pop_area = 0;
                    171:        l = l->prev;
                    172:        fl = fl->next;
                    173:     }
                    174:     if (f->initial_offset)
                    175:        f->initial_offset += 4 * pops_at_end;
                    176: }
                    177: 
                    178: static void output_function(struct func *f)
                    179: {
                    180:     struct line *l = f->first_line;
1.1.1.3 ! root      181: 
1.1       root      182:     while (l) {
1.1.1.3 ! root      183:        switch (l->delet) {
1.1       root      184:         case 1:
                    185:            break;
                    186:         case 0:
                    187:            printf("%s\n", l->data);
                    188:            break;
                    189:         case 2:
                    190:            if (f->initial_offset)
                    191:                printf("\taddl $%d,%%esp\n", f->initial_offset);
                    192:            break;
                    193:         case 3:
                    194:            if (f->initial_offset)
                    195:                printf("\tsubl $%d,%%esp\n", f->initial_offset);
                    196:            break;
                    197:        }
                    198:        l = l->next;
                    199:     }
                    200: }
                    201: 
                    202: int main(int argc, char **argv)
                    203: {
1.1.1.3 ! root      204:     FILE *infile = stdin;
1.1       root      205:     char tmp[4096];
                    206: 
1.1.1.3 ! root      207: #ifdef __mc68000__
        !           208:     if(system("perl machdep/cpuopti")==-1) {
        !           209:        perror("perl machdep/cpuopti");
        !           210:        return 10;
        !           211:    } else return 0;
1.1.1.2   root      212: #endif
                    213: 
1.1.1.3 ! root      214:     /* For debugging... */
        !           215:     if (argc == 2)
        !           216:        infile = fopen (argv[1], "r");
        !           217: 
1.1       root      218:     for(;;) {
                    219:        char *s;
1.1.1.3 ! root      220: 
        !           221:        if ((fgets(tmp, 4095, infile)) == NULL)
1.1       root      222:            break;
                    223: 
                    224:        s = strchr (tmp, '\n');
                    225:        if (s != NULL)
                    226:            *s = 0;
                    227: 
                    228:        if (strncmp(tmp, ".globl op_", 10) == 0) {
                    229:            struct line *first_line = NULL, *prev = NULL;
                    230:            struct line **nextp = &first_line;
                    231:            struct func f;
1.1.1.3 ! root      232:            int nr_rets = 0;
        !           233:            int can_opt = 1;
        !           234: 
1.1       root      235:            do {
                    236:                struct line *current;
                    237: 
                    238:                if (strcmp (tmp, "#APP") != 0 && strcmp (tmp, "#NO_APP") != 0) {
                    239:                    current = *nextp = (struct line *)malloc(sizeof (struct line));
                    240:                    nextp = &current->next;
                    241:                    current->prev = prev; prev = current;
                    242:                    current->next = NULL;
1.1.1.3 ! root      243:                    current->delet = 0;
1.1       root      244:                    current->data = my_strdup (tmp);
1.1.1.3 ! root      245:                    if (match (current, "movl %esp,%ebp") || match (current, "enter")) {
        !           246:                        fprintf (stderr, "GCC failed to eliminate fp: %s\n", first_line->data);
        !           247:                        can_opt = 0;
        !           248:                    }
        !           249: 
        !           250:                    if (match (current, "ret"))
        !           251:                        nr_rets++;
1.1       root      252:                }
1.1.1.3 ! root      253:                if ((fgets(tmp, 4095, infile)) == NULL)
1.1       root      254:                    oops();
                    255:                s = strchr (tmp, '\n');
                    256:                if (s != NULL)
                    257:                    *s = 0;
                    258:            } while (strncmp (tmp,".Lfe", 4) != 0);
                    259: 
                    260:            f.first_line = first_line;
                    261:            f.last_line = prev;
                    262: 
1.1.1.3 ! root      263:            if (nr_rets == 1 && can_opt)
        !           264:                do_function(&f);
        !           265:            /*else
        !           266:                fprintf(stderr, "Too many RET instructions: %s\n", first_line->data);*/
1.1       root      267:            output_function(&f);
                    268:        }
                    269:        printf("%s\n", tmp);
                    270:     }
                    271:     return 0;
                    272: }

unix.superglobalmegacorp.com

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