|
|
uae-0.6.8
#!/bin/perl
#
# Usage: $0 <cpu?.s
#
# Small perl script to optimise cpu?.s
# Note: some optimisations done here are not safe! It is a chance
# if everything works fine...
#
# (c) By Samuel Devulder, 01/97.
#
#while(<>) { print; }
#exit 0;
###############################################################################
if($#ARGV >= $[) {
&usage;
}
###############################################################################
while(<>) {
print;
last if /^_op_[0-9a-f]+:$/;
}
###############################################################################
chop;
print STDERR "$_\r";
$num_opt = 0;
while($last_func = &analyse_function) {
while(&optimize_function) {}
&dump_function;
print $last_func;$_ = $last_func;chop;
print STDERR "$_\r";
}
while(&optimize_function) {}
&dump_function;
print STDERR "$num_opt optimisations\n";
exit 0;
###############################################################################
sub delete_line {
local($i) = @_;
for(; $i < $lineno; ++$i) {
$line[$i] = $line[1+$i];
}
$line[--$lineno] = "";
}
###############################################################################
sub optimize_function {
local($i, $j, $ext, $adr, $reg, $opt, $tmp);
$opt = $num_opt;
for($i = 0; $i < $lineno; ++$i) {
#################################################################
# INST.x X,Dn => INST.x X,Dn
# TST.x Dn <deleted>
#################################################################
if(($line[$i] =~/(mov[e]?|or|and|add|sub|tst)([bwl])\s+.+,(d[0-7])$/)
&& ($line[$i+1]=~ /tst$2\s+$3/)) {
&delete_line($i+1);
++$num_opt;
}
#################################################################
# MOVE.x Dn,X => MOVE.x Dn,X
# TST.x Dn <deleted>
#################################################################
if(($line[$i] =~ /mov[e]?([bwl])\s+(d[0-7]),(.+)$/)
&& ($line[$i+1]=~ /tst$1\s+$2/)) {
&delete_line($i+1);
++$num_opt;
}
#################################################################
# MOVE.B 1(An),Dr => MOVE.W (An)+,Dr
# ADDQ.x #2,AN <deleted>
# This is allowed since An always points on (B1,B2) With B1==0
#################################################################
if(($line[$i] =~ /moveb\s+(a[0-7])@\(1\),(d[0-7])$/)
&& ($line[$i+1] =~ /addq.\s+#2,$1/)) {
$line[$i] = "\tmovew $1@+,$2\n";
&delete_line($i+1);
++$num_opt;
#################################################################
# CLR.W Dn => <deleted>
# MOVE.W X,Dn MOVE.W X,Dn
#################################################################
if(($i>1) && ($line[$i-1] =~ /clrw\s+$2/)) {
&delete_line($i-1);
++$num_opt;
}
}
#################################################################
# INST.x X,Dn => INST.x Dn,X
# ..(Dn not used).. ..(Dn not used)..
# MOVE.x Dn,X <deleted>
# ..Dn dead..
# INST = or | and | add
#################################################################
# too much unsafe
# if(($line[$i] =~ /(or|and|add)([bwl])\s+(.+),(d[2-7])$/)) {
# $ext = $2; $adr = $3; $reg = $4;
# $adr =~s/([()])/\\\1/g;
# $tmp = "$reg|\sj.+\s|rts|(^.+:)";
# # ^ ^ ^
# # No jump nor rts nor label
# for($j = $i+1; $line[$j] !~ /$tmp/; ++$j) {}
# if($line[$j] =~ /mov[e]?$ext\s+$reg,$adr$/) {
# $line[$i] =~ s/($adr),($reg)$/ \2,\1/;
# &delete_line($j);
# ++$num_opt;
# }
# }
#################################################################
# MOVE.x X,Dn => MOVE.x X,Y
# ..(Dn not used).. ..(Dn not used)..
# MOVE.x Dn,Y <deleted>
# The ..(Dn ...).. part must not modify regs of Y
#################################################################
# if(($line[$i] =~ /mov[e]?([bwl])\s+.+,(d[2-7])$/)) {
# $ext = $1; $reg = $2;
# $tmp = "$reg|(^\sj.+\s)|rts|(^.+:)";
# for($j = $i+1; $line[$j] !~ /$tmp/; ++$j) {}
# if($line[$j] =~ /mov[e]?$ext\s+$reg,(.+)$/) {
# $adr = $1;
# $tmp = "";
# if($adr =~ /(a[0-7])/) {if($tmp eq "") {$tmp = "$1";} else {$tmp = "$tmp|$1"}}
# if($adr =~ /(d[0-7])/) {if($tmp eq "") {$tmp = "$1";} else {$tmp = "$tmp|$1"}}
# if(!($tmp eq "")) {
# for($k = $i+1; $k<$j && ($line[$k]!~/$tmp/); ++$k) {}
# } else {$k = $j;}
# if($k == $j) {
# $line[$i] =~ s/,$reg$/,$adr/;
# &delete_line($j);
# ++$num_opt;
# }
# }
# }
#################################################################
# TST.x Dn => MOVE.x Dn,X
# ..(Dn not used).. ..(Dn not used)..
# MOVE.x Dn,X <deleted>
#################################################################
if(($line[$i] =~ /tst([bwl])\s+(d[0-7])$/)) {
$ext = $1; $reg = $2;
$line[$lineno] = "rts"; # sentinel
$tmp = "(^.+:)|rts|\sj.+\s|$reg";
for($j = $i+1; $line[$j] !~ /$tmp/; ++$j) {}
if($line[$j] =~ /mov[e]?$ext\s+$reg,(.+)$/) {
$adr = $1;
$tmp = "";
if($adr =~ /(a[0-7])/) {if($tmp eq "") {$tmp = "$1";} else {$tmp = "$tmp|$1"}}
if($adr =~ /(d[0-7])/) {if($tmp eq "") {$tmp = "$1";} else {$tmp = "$tmp|$1"}}
if(!($tmp eq "")) {
for($k = $i+1; $k<$j && ($line[$k]!~/$tmp/); ++$k) {}
} else {$k = $j;}
if($k == $j) {
$line[$i] = $line[$j];
&delete_line($j);
++$num_opt;
}
}
}
if($line[$i] =~ /_regs/) { # some speedup
#################################################################
# movel X,_regs+N1 => <deleted>
# ...no refs to _regs+N1.. ..stuff..
# movel Y,_regs+N1 movel Y,_regs+N1
#################################################################
if($line[$i] =~ /movel\s+.+,_regs(.*)$/) {
$N1 = $1; $N1 =~ s/^[+]/\\+/;
$line[$lineno] = "_regs$1"; # sentinel
$tmp = "_regs$N1|\sj.+\s|rts|(^.+:)";
for($k=$i+1;$line[$k] !~ /$tmp/;++$k) {}
if($line[$k] =~ /movel\s+.+,_regs$N1$/) {
&delete_line($i);
++$num_opt;
}
}
#################################################################
# INST .._regs+N1.. => lea _regs+N2,An
# ..(no refs to _regs).. INST ..N1-N2(An)..
# lea _regs+N2,An ..(no refs to _regs)..
#################################################################
if($line[$i] =~ /_regs(\+\d+)?/) {
$N1 = $1;
$line[$lineno] = "rts"; # sentinel
$tmp = "_regs|rts|\s+j.+\s|(^.+:)";
for($j = $i+1; $line[$j] !~ /$tmp/; ++$j) {}
if($line[$j] =~ /lea\s+_regs(\+\d+)?,(a[0-7])$/) {
$N2 = $1; $An = $2;
for($k = $i; $line[$k] !~ /$An/; $k++) {}
if($k == $j) {
$N1 =~ s/^\+//; $N2 =~ y/+/-/;
$line[$i] =~ s/_regs(\+?)$N1/$An@\($N1$N2\)/g;
$ext = $line[$j];
for($k=$j; $k>$i; --$k) {$line[$k] = $line[$k-1];}
$line[$i] = $ext;
++$num_opt;
}
}
}
#################################################################
# LEA _regs+N1,An => LEA _regs+N1,An
# ..An not modified.. ...
# INST .._regs+N2.. INST ..(N2-N1)An..
#################################################################
if($line[$i] =~ /lea\s+_regs(\+\d+)?,(a[0-7])/) {
$N1 = $1;$An = $2;
$line[$lineno] = "rts"; # sentinel
$tmp = "_regs|$An@[-+]|,$An|\sj.+\s|rts|(^.+:)";
for($j = $i+1; $line[$j] !~ /$tmp/; ++$j) {}
if($line[$j] =~ /_regs(\+\d+)?/) {
$N2 = $1; $N1 =~ y/+/-/;
$tmp = $N2; $tmp =~ s/[+]/\\+/;
$line[$j] =~ s/_regs$tmp/$An@\($N2$N1\)/g;
$line[$j] =~ s/\(\)//g;
++$num_opt;
}
}
#################################################################
# ..<A1> not used.. ..<A1> not used..
# MOVE.L _regs+N1,A0 => MOVE.L _regs+N1,A1
# MOVE.x (A0)+,Dp MOVE.x (A1)+,Dp
# MOVE.L A0,_regs+N MOVE.L A1,_regs+N1
# LEA _regs+N2,A0 LEA _regs+N2,A0
#################################################################
if(($line[$i] =~ /mov[e]?l\s+_regs(\+\d+)?,a0$/)
&& ¬_used_before($i,"a1")) {
if(($line[$i+1] =~ /mov[e]?[bwl]\s+a0@\+,d[0-7]$/)
&& ($line[$i+2] =~ /mov[e]?l\s+a0,_regs(\+\d+)?/)
&& ($line[$i+3] =~ /lea\s+_regs(\+\d+)?,a0/)) {
$line[$i] =~ s/a0/a1/;
$line[$i+1] =~ s/a0/a1/;
$line[$i+2] =~ s/a0/a1/;
++$num_opt;
}
}
}
#################################################################
# MOVE.x X,Dp => MOVE.x X,Dp
# ..Dp not used.. MOVE.W CCR,Y
# TST.x Dp ..Dp not used..
# movew ccr,Y
#################################################################
if($line[$i] =~ /mov[e]?([bwl])\s+.+,(d[0-7])$/) {
$ext = $1;$reg = $2;
$line[$lineno] = "rts"; # sentinel
$tmp = "$reg|rts|\sj.+\s|(^.+:)";
for($j = $i+1; $line[$j] !~ /$tmp/; $j++) {}
if(($line[$j] =~ /tst$ext\s+$reg$/)
&& ($line[$j+1] =~ /mov[e]?w\s+ccr,/)) {
&delete_line($j);
$ext = $line[$j];
for($k=$j;$k>$i+1;--$k) {$line[$k] = $line[$k-1];}
$line[$i+1] = $ext;
++$num_opt;
}
}
}
return $num_opt-$opt;
}
###############################################################################
sub not_used {
local($i, $reg) = @_;
while($i < $lineno) {
$line[$i]=~/$reg/ && return 0;
++$i;
}
return 1;
}
###############################################################################
sub not_used_before {
local($i, $reg) = @_;
while($i--) {
$line[$i]=~/$reg/ && return 0;
}
return 1;
}
###############################################################################
sub analyse_function {
$lineno = 0;
while(<>) {
next if /^#(NO_)?APP/;
last if /^_op_[0-9a-f]+:$/;
$line[$lineno++] = $_;
}
return $_;
}
###############################################################################
sub dump_function {
local($i);
for($i=0;$i < $lineno; ++$i) {
print $line[$i];
}
}
###############################################################################
sub usage {
open(FILE,__FILE__);
open(OUT,"|less");
<FILE>;
while(<FILE>) {
last if !/^#/;
s/^#[ ]?//;
s/\$0/$0/;
print OUT;
}
close OUT;
exit;
}
###############################################################################
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.