Annotation of uae/src/md-amiga/cpuopti, revision 1.1.1.1

1.1       root        1: #!/bin/perl
                      2: #
                      3: # Usage: $0 <cpu?.s
                      4: #
                      5: # Small perl script to optimise cpu?.s
                      6: # Note: some optimisations done here are not safe! It is a chance
                      7: # if everything works fine...
                      8: #
                      9: # (c) By Samuel Devulder, 01/97.
                     10: #
                     11: 
                     12: #while(<>) { print; }
                     13: #exit 0;
                     14: 
                     15: ###############################################################################
                     16: 
                     17: if($#ARGV >= $[) {
                     18:     &usage;
                     19: } 
                     20: 
                     21: ###############################################################################
                     22: 
                     23: while(<>) {
                     24:     print;
                     25:     last if /^_op_[0-9a-f]+:$/;
                     26: }
                     27: 
                     28: ###############################################################################
                     29: 
                     30: chop;
                     31: print STDERR "$_\r";
                     32: $num_opt = 0;
                     33: while($last_func = &analyse_function) {
                     34:     while(&optimize_function) {}
                     35:     &dump_function;
                     36:     print $last_func;$_ = $last_func;chop;
                     37:     print STDERR "$_\r";
                     38: }
                     39: while(&optimize_function) {}
                     40: &dump_function;
                     41: 
                     42: print STDERR "$num_opt optimisations\n";
                     43: 
                     44: exit 0;
                     45: 
                     46: ###############################################################################
                     47: 
                     48: sub delete_line {
                     49:     local($i) = @_;
                     50:     for(; $i < $lineno; ++$i) {
                     51:         $line[$i] = $line[1+$i];
                     52:     }
                     53:     $line[--$lineno] = "";
                     54: }
                     55:     
                     56: ###############################################################################
                     57: 
                     58: sub optimize_function {
                     59:     local($i, $j, $ext, $adr, $reg, $opt, $tmp);
                     60:     $opt = $num_opt;
                     61:     for($i = 0; $i < $lineno; ++$i) {
                     62:         #################################################################
                     63:         #   INST.x  X,Dn            =>  INST.x  X,Dn
                     64:         #   TST.x   Dn                  <deleted>
                     65:         #################################################################
                     66:         if(($line[$i] =~/(mov[e]?|or|and|add|sub|tst)([bwl])\s+.+,(d[0-7])$/)
                     67:         && ($line[$i+1]=~ /tst$2\s+$3/)) {
                     68:             &delete_line($i+1);
                     69:             ++$num_opt;
                     70:         } 
                     71:         #################################################################
                     72:         #   MOVE.x  Dn,X            =>  MOVE.x  Dn,X
                     73:         #   TST.x   Dn                  <deleted>
                     74:         #################################################################
                     75:         if(($line[$i]  =~ /mov[e]?([bwl])\s+(d[0-7]),(.+)$/)
                     76:         && ($line[$i+1]=~ /tst$1\s+$2/)) {
                     77:             &delete_line($i+1);
                     78:             ++$num_opt;
                     79:         }
                     80:         #################################################################
                     81:         #   MOVE.B  1(An),Dr        =>  MOVE.W  (An)+,Dr
                     82:         #   ADDQ.x  #2,AN               <deleted>
                     83:         # This is allowed since An always points on (B1,B2) With B1==0
                     84:         #################################################################
                     85:         if(($line[$i]   =~ /moveb\s+(a[0-7])@\(1\),(d[0-7])$/)
                     86:         && ($line[$i+1] =~ /addq.\s+#2,$1/)) {
                     87:             $line[$i] = "\tmovew $1@+,$2\n";
                     88:             &delete_line($i+1);
                     89:             ++$num_opt;
                     90:         #################################################################
                     91:         #   CLR.W   Dn              =>  <deleted>
                     92:         #   MOVE.W  X,Dn                MOVE.W  X,Dn
                     93:         #################################################################
                     94:             if(($i>1) && ($line[$i-1] =~ /clrw\s+$2/)) {
                     95:                 &delete_line($i-1);
                     96:                 ++$num_opt;
                     97:             }
                     98:         }       
                     99:         #################################################################
                    100:         #   INST.x  X,Dn            =>  INST.x  Dn,X
                    101:         #   ..(Dn not used)..           ..(Dn not used)..
                    102:         #   MOVE.x  Dn,X                <deleted>
                    103:         #   ..Dn dead..
                    104:         # INST = or | and | add
                    105:         #################################################################
                    106: # too much unsafe
                    107: #        if(($line[$i] =~ /(or|and|add)([bwl])\s+(.+),(d[2-7])$/)) {
                    108: #            $ext = $2; $adr = $3; $reg = $4;
                    109: #            $adr =~s/([()])/\\\1/g;
                    110: #            $tmp = "$reg|\sj.+\s|rts|(^.+:)";
                    111: #            #            ^       ^   ^
                    112: #            #         No jump nor rts nor label
                    113: #            for($j = $i+1; $line[$j] !~ /$tmp/; ++$j) {}
                    114: #            if($line[$j] =~ /mov[e]?$ext\s+$reg,$adr$/) {
                    115: #                $line[$i] =~ s/($adr),($reg)$/ \2,\1/;
                    116: #                &delete_line($j);
                    117: #                ++$num_opt;
                    118: #            }
                    119: #        }
                    120:         #################################################################
                    121:         #   MOVE.x  X,Dn            =>  MOVE.x  X,Y
                    122:         #   ..(Dn not used)..           ..(Dn not used)..
                    123:         #   MOVE.x  Dn,Y                <deleted>
                    124:         # The ..(Dn ...).. part must not modify regs of Y
                    125:         #################################################################
                    126: #        if(($line[$i] =~ /mov[e]?([bwl])\s+.+,(d[2-7])$/)) {
                    127: #            $ext = $1; $reg = $2;
                    128: #            $tmp = "$reg|(^\sj.+\s)|rts|(^.+:)";
                    129: #            for($j = $i+1; $line[$j] !~ /$tmp/; ++$j) {}
                    130: #            if($line[$j] =~ /mov[e]?$ext\s+$reg,(.+)$/) {
                    131: #                $adr = $1;
                    132: #                $tmp = "";
                    133: #                if($adr =~ /(a[0-7])/) {if($tmp eq "") {$tmp = "$1";} else {$tmp = "$tmp|$1"}}
                    134: #                if($adr =~ /(d[0-7])/) {if($tmp eq "") {$tmp = "$1";} else {$tmp = "$tmp|$1"}}
                    135: #                if(!($tmp eq "")) {
                    136: #                    for($k = $i+1; $k<$j && ($line[$k]!~/$tmp/); ++$k) {}
                    137: #                } else {$k = $j;}
                    138: #                if($k == $j) {
                    139: #                    $line[$i] =~ s/,$reg$/,$adr/;
                    140: #                    &delete_line($j);
                    141: #                    ++$num_opt;
                    142: #                }
                    143: #            }
                    144: #        }
                    145:         #################################################################
                    146:         #   TST.x   Dn              =>  MOVE.x  Dn,X
                    147:         #   ..(Dn not used)..           ..(Dn not used)..
                    148:         #   MOVE.x  Dn,X                <deleted>
                    149:         #################################################################
                    150:         if(($line[$i] =~ /tst([bwl])\s+(d[0-7])$/)) {
                    151:             $ext = $1; $reg = $2;
                    152:             $line[$lineno] = "rts"; # sentinel
                    153:             $tmp = "(^.+:)|rts|\sj.+\s|$reg";
                    154:             for($j = $i+1; $line[$j] !~ /$tmp/; ++$j) {}
                    155:             if($line[$j] =~ /mov[e]?$ext\s+$reg,(.+)$/) {
                    156:                 $adr = $1;
                    157:                 $tmp = "";
                    158:                 if($adr =~ /(a[0-7])/) {if($tmp eq "") {$tmp = "$1";} else {$tmp = "$tmp|$1"}}
                    159:                 if($adr =~ /(d[0-7])/) {if($tmp eq "") {$tmp = "$1";} else {$tmp = "$tmp|$1"}}
                    160:                 if(!($tmp eq "")) {
                    161:                     for($k = $i+1; $k<$j && ($line[$k]!~/$tmp/); ++$k) {}
                    162:                 } else {$k = $j;}
                    163:                 if($k == $j) {
                    164:                     $line[$i] = $line[$j];
                    165:                     &delete_line($j);
                    166:                     ++$num_opt;
                    167:                 }
                    168:             }
                    169:         }
                    170:         if($line[$i] =~ /_regs/) { # some speedup
                    171:         #################################################################
                    172:         #   movel   X,_regs+N1      => <deleted>
                    173:         #   ...no refs to _regs+N1..   ..stuff..
                    174:         #   movel   Y,_regs+N1         movel    Y,_regs+N1
                    175:         #################################################################
                    176:         if($line[$i] =~ /movel\s+.+,_regs(.*)$/) {
                    177:             $N1 = $1; $N1 =~ s/^[+]/\\+/;
                    178:             $line[$lineno] = "_regs$1"; # sentinel
                    179:             $tmp = "_regs$N1|\sj.+\s|rts|(^.+:)";
                    180:             for($k=$i+1;$line[$k] !~ /$tmp/;++$k) {}
                    181:             if($line[$k] =~ /movel\s+.+,_regs$N1$/) {
                    182:                 &delete_line($i);
                    183:                 ++$num_opt;
                    184:             }
                    185:         }
                    186:         #################################################################
                    187:         #   INST   .._regs+N1..     =>  lea     _regs+N2,An
                    188:         #   ..(no refs to _regs)..      INST    ..N1-N2(An)..
                    189:         #   lea     _regs+N2,An         ..(no refs to _regs)..
                    190:         #################################################################
                    191:         if($line[$i] =~ /_regs(\+\d+)?/) {
                    192:             $N1 = $1;
                    193:             $line[$lineno] = "rts"; # sentinel
                    194:             $tmp = "_regs|rts|\s+j.+\s|(^.+:)";
                    195:             for($j = $i+1; $line[$j] !~ /$tmp/; ++$j) {}
                    196:             if($line[$j] =~ /lea\s+_regs(\+\d+)?,(a[0-7])$/) {
                    197:                 $N2 = $1; $An = $2;
                    198:                 for($k = $i; $line[$k] !~ /$An/; $k++) {}
                    199:                 if($k == $j) {
                    200:                     $N1 =~ s/^\+//; $N2 =~ y/+/-/;
                    201:                     $line[$i] =~ s/_regs(\+?)$N1/$An@\($N1$N2\)/g;
                    202:                     $ext = $line[$j];
                    203:                     for($k=$j; $k>$i; --$k) {$line[$k] = $line[$k-1];}
                    204:                     $line[$i] = $ext;
                    205:                     ++$num_opt;
                    206:                 }
                    207:             }
                    208:         }
                    209:         #################################################################
                    210:         #   LEA     _regs+N1,An     =>  LEA     _regs+N1,An
                    211:         #   ..An not modified..         ...
                    212:         #   INST    .._regs+N2..        INST    ..(N2-N1)An..
                    213:         #################################################################
                    214:         if($line[$i] =~ /lea\s+_regs(\+\d+)?,(a[0-7])/) {
                    215:             $N1 = $1;$An = $2;
                    216:             $line[$lineno] = "rts"; # sentinel
                    217:             $tmp = "_regs|$An@[-+]|,$An|\sj.+\s|rts|(^.+:)";
                    218:             for($j = $i+1; $line[$j] !~ /$tmp/; ++$j) {}
                    219:             if($line[$j] =~ /_regs(\+\d+)?/) {
                    220:                 $N2 = $1; $N1 =~ y/+/-/;
                    221:                 $tmp = $N2; $tmp =~ s/[+]/\\+/;
                    222:                 $line[$j] =~ s/_regs$tmp/$An@\($N2$N1\)/g;
                    223:                 $line[$j] =~ s/\(\)//g;
                    224:                 ++$num_opt;
                    225:             }
                    226:         }
                    227:         #################################################################
                    228:         #   ..<A1> not used..           ..<A1> not used..
                    229:         #   MOVE.L  _regs+N1,A0     =>  MOVE.L  _regs+N1,A1
                    230:         #   MOVE.x  (A0)+,Dp            MOVE.x  (A1)+,Dp
                    231:         #   MOVE.L  A0,_regs+N          MOVE.L  A1,_regs+N1
                    232:         #   LEA     _regs+N2,A0          LEA     _regs+N2,A0
                    233:         #################################################################
                    234:         if(($line[$i] =~ /mov[e]?l\s+_regs(\+\d+)?,a0$/)
                    235:         && &not_used_before($i,"a1")) {
                    236:             if(($line[$i+1] =~ /mov[e]?[bwl]\s+a0@\+,d[0-7]$/)
                    237:             && ($line[$i+2] =~ /mov[e]?l\s+a0,_regs(\+\d+)?/)
                    238:             && ($line[$i+3] =~ /lea\s+_regs(\+\d+)?,a0/)) {
                    239:                 $line[$i]   =~ s/a0/a1/;
                    240:                 $line[$i+1] =~ s/a0/a1/;
                    241:                 $line[$i+2] =~ s/a0/a1/;
                    242:                 ++$num_opt;
                    243:             }
                    244:         }
                    245:         }
                    246:         #################################################################
                    247:         #   MOVE.x  X,Dp            =>  MOVE.x  X,Dp
                    248:         #   ..Dp not used..             MOVE.W  CCR,Y
                    249:         #   TST.x   Dp                  ..Dp not used..
                    250:         #   movew   ccr,Y
                    251:         #################################################################
                    252:         if($line[$i] =~ /mov[e]?([bwl])\s+.+,(d[0-7])$/) {
                    253:             $ext = $1;$reg = $2;
                    254:             $line[$lineno] = "rts"; # sentinel
                    255:             $tmp = "$reg|rts|\sj.+\s|(^.+:)";
                    256:             for($j = $i+1; $line[$j] !~ /$tmp/; $j++) {}
                    257:             if(($line[$j] =~ /tst$ext\s+$reg$/)
                    258:             && ($line[$j+1] =~ /mov[e]?w\s+ccr,/)) {
                    259:                 &delete_line($j);
                    260:                 $ext = $line[$j];
                    261:                 for($k=$j;$k>$i+1;--$k) {$line[$k] = $line[$k-1];}
                    262:                 $line[$i+1] = $ext;
                    263:                 ++$num_opt;
                    264:             }
                    265:         }
                    266:     }
                    267:     return $num_opt-$opt;
                    268: }
                    269: 
                    270: ###############################################################################
                    271: 
                    272: sub not_used {
                    273:     local($i, $reg) = @_;
                    274: 
                    275:     while($i < $lineno) {
                    276:         $line[$i]=~/$reg/ && return 0;
                    277:         ++$i;
                    278:     }
                    279:     return 1;
                    280: }
                    281: 
                    282: ###############################################################################
                    283: 
                    284: sub not_used_before {
                    285:     local($i, $reg) = @_;
                    286: 
                    287:     while($i--) {
                    288:         $line[$i]=~/$reg/ && return 0;
                    289:     }
                    290:     return 1;
                    291: }
                    292: 
                    293: ###############################################################################
                    294: 
                    295: sub analyse_function {
                    296:     $lineno = 0;
                    297:     while(<>) {
                    298:         next if /^#(NO_)?APP/;
                    299:         last if /^_op_[0-9a-f]+:$/;
                    300:         $line[$lineno++] = $_;
                    301:     }
                    302:     return $_;
                    303: }
                    304: 
                    305: ###############################################################################
                    306: 
                    307: sub dump_function {
                    308:     local($i);
                    309:     for($i=0;$i < $lineno; ++$i) {
                    310:         print $line[$i];
                    311:     }
                    312: }
                    313: 
                    314: ###############################################################################
                    315: 
                    316: sub usage {
                    317:     open(FILE,__FILE__);
                    318:     open(OUT,"|less");
                    319:     <FILE>;
                    320:     while(<FILE>) {
                    321:         last if !/^#/;
                    322:         s/^#[ ]?//;
                    323:         s/\$0/$0/;
                    324:         print OUT;
                    325:     }
                    326:     close OUT;
                    327:     exit;
                    328: }
                    329:     
                    330: ###############################################################################
                    331:     

unix.superglobalmegacorp.com

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