|
|
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: # 05/04/97: Modified to make it work with perl5.
10: # 25/10/97: Removed some optimisations suspected to introduce bugs.
11: #
12: # (c) By Samuel Devulder, 04/97.
13: #
14:
15: # uncomment the next 2 lines if you experience problems with the
16: # optimized code:
17: #while(<>) { print; }
18: #exit 0;
19:
20: ###############################################################################
21:
22: if($#ARGV >= $[) {
23: &usage;
24: }
25:
26: ###############################################################################
27:
28: while(<>) {
29: print;
30: last if /^_op_[0-9a-f]+:$/;
31: }
32:
33: ###############################################################################
34:
35: chop;
36: print STDERR "$_\r";
37: $num_opt = 0;
38: while($last_func = &analyse_function) {
39: while(&optimize_function) {}
40: &dump_function;
41: print $last_func;$_ = $last_func;chop;
42: print STDERR "$_\r";
43: }
44: while(&optimize_function) {}
45: &dump_function;
46:
47: print STDERR "$num_opt optimisations\n";
48:
49: exit 0;
50:
51: ###############################################################################
52:
53: sub delete_line {
54: local($i) = @_;
55: for(; $i < $lineno; ++$i) {
56: $line[$i] = $line[1+$i];
57: }
58: $line[--$lineno] = "";
59: }
60:
61: ###############################################################################
62:
63: sub optimize_function {
64: local($i, $j, $ext, $adr, $reg, $opt, $tmp);
65: $opt = $num_opt;
66: for($i = 0; $i < $lineno; ++$i) {
67: study($line[$i]);
68: #################################################################
69: # INST.x X,Dn => INST.x X,Dn
70: # TST.x Dn <deleted>
71: #################################################################
72: if(($line[$i] =~/(mov[e]?|or|and|add|sub|tst)([bwl])\s+.+,(d[0-7])$/)
73: && ($line[$i+1]=~ /tst$2\s+$3/)) {
74: &delete_line($i+1);
75: ++$num_opt;
76: }
77: #################################################################
78: # MOVE.x Dn,X => MOVE.x Dn,X
79: # TST.x Dn <deleted>
80: #################################################################
81: if(($line[$i] =~ /mov[e]?([bwl])\s+(d[0-7]),(.+)$/)
82: && ($line[$i+1]=~ /tst$1\s+$2/)) {
83: &delete_line($i+1);
84: ++$num_opt;
85: }
86: #################################################################
87: # MOVE.B 1(An),Dr => MOVE.W (An)+,Dr
88: # ADDQ.x #2,AN <deleted>
89: # This is allowed since An always points on (B1,B2) With B1==0
90: #################################################################
91: if($line[$i] =~ /moveb\s+(a[0-7])@\(1\),(d[0-7])$/) {
92: $adr=$1; $reg=$2;
93: if($line[$i+1] =~ /addq.\s+#2,$adr/) {
94: $line[$i] = "\tmovew $adr@+,$reg\n";
95: &delete_line($i+1);
96: ++$num_opt;
97: #################################################################
98: # CLR.W Dn => <deleted>
99: # MOVE.W X,Dn MOVE.W X,Dn
100: #################################################################
101: if(($i>1) && ($line[$i-1] =~ /clrw\s+$reg/)) {
102: &delete_line($i-1);
103: ++$num_opt;
104: }
105: }
106: }
107: #################################################################
108: # TST.x Dn => MOVE.x Dn,X
109: # ..(Dn not used).. ..(Dn not used)..
110: # MOVE.x Dn,X <deleted>
111: #################################################################
112: # if(($line[$i] =~ /tst([bwl])\s+(d[0-7])$/)) {
113: # $ext = $1; $reg = $2;
114: # $line[$lineno] = "rts"; # sentinel
115: # $tmp = "(^.+:)|rts|\sj.+\s|$reg";
116: # for($j = $i+1; $line[$j] !~ /$tmp/; ++$j) {}
117: # if($line[$j] =~ /mov[e]?$ext\s+$reg,(.+)$/) {
118: # $adr = $1;
119: # $tmp = "";
120: # if($adr =~ /(a[0-7])/) {if($tmp eq "") {$tmp = "$1";} else {$tmp = "$tmp|$1"}}
121: # if($adr =~ /(d[0-7])/) {if($tmp eq "") {$tmp = "$1";} else {$tmp = "$tmp|$1"}}
122: # if(!($tmp eq "")) {
123: # for($k = $i+1; $k<$j && ($line[$k]!~/$tmp/); ++$k) {}
124: # } else {$k = $j;}
125: # if($k == $j) {
126: # $line[$i] = $line[$j];
127: # &delete_line($j);
128: # ++$num_opt;
129: # }
130: # }
131: # }
132: if($line[$i] =~ /_regs/) { # some speedup
133: #################################################################
134: # INST .._regs+N1.. => lea _regs+N2,An
135: # ..(no refs to _regs).. INST ..N1-N2(An)..
136: # lea _regs+N2,An ..(no refs to _regs)..
137: #################################################################
138: if($line[$i] =~ /_regs(\+\d+)?/) {
139: $N1 = $1;
140: $line[$lineno] = "rts"; # sentinel
141: $tmp = "_regs|rts|\s+j.+\s|(^.+:)";
142: for($j = $i+1; $line[$j] !~ /$tmp/; ++$j) {}
143: if($line[$j] =~ /lea\s+_regs(\+\d+)?,(a[0-7])$/) {
144: $N2 = $1; $An = $2;
145: for($k = $i; $line[$k] !~ /$An/; $k++) {}
146: if($k == $j) {
147: $N1 =~ s/^\+//; $N2 =~ y/+/-/;
148: $line[$i] =~ s/_regs(\+?)$N1/$An@\($N1$N2\)/g;
149: $ext = $line[$j];
150: for($k=$j; $k>$i; --$k) {$line[$k] = $line[$k-1];}
151: $line[$i] = $ext;
152: ++$num_opt;
153: }
154: }
155: }
156: #################################################################
157: # LEA _regs+N1,An => LEA _regs+N1,An
158: # ..An not modified.. ...
159: # INST .._regs+N2.. INST ..(N2-N1)An..
160: #################################################################
161: if($line[$i] =~ /lea\s+_regs(\+\d+)?,(a[0-7])/) {
162: $N1 = $1;$An = $2;
163: $line[$lineno] = "rts"; # sentinel
164: $tmp = "_regs|$An@[-+]|,$An|\sj.+\s|rts|(^.+:)";
165: for($j = $i+1; $line[$j] !~ /$tmp/; ++$j) {}
166: if($line[$j] =~ /_regs(\+\d+)?/) {
167: $N2 = $1; $N1 =~ y/+/-/;
168: $tmp = $N2; $tmp =~ s/[+]/\\+/;
169: $line[$j] =~ s/_regs$tmp/$An@\($N2$N1\)/g;
170: $line[$j] =~ s/\(\)//g;
171: ++$num_opt;
172: }
173: }
174: }
175: #################################################################
176: # MOVE.x X,Dp => MOVE.x X,Dp
177: # ..Dp not used.. MOVE.W CCR,Y
178: # TST.x Dp ..Dp not used..
179: # MOVE.W ccr,Y
180: #################################################################
181: # if($line[$i] =~ /mov[e]?([bwl])\s+.+,(d[0-7])$/) {
182: # $ext = $1;$reg = $2;
183: # $line[$lineno] = "rts"; # sentinel
184: # $tmp = "$reg|rts|\sj.+\s|(^.+:)";
185: # for($j = $i+1; $line[$j] !~ /$tmp/; $j++) {}
186: # if(($line[$j] =~ /tst$ext\s+$reg$/)
187: # && ($line[$j+1] =~ /mov[e]?w\s+ccr,/)) {
188: # &delete_line($j);
189: # $ext = $line[$j];
190: # for($k=$j;$k>$i+1;--$k) {$line[$k] = $line[$k-1];}
191: # $line[$i+1] = $ext;
192: # ++$num_opt;
193: # }
194: # }
195: #################################################################
196: # General instruction scheduling optimisation:
197: # INST1 <memory op> => INST1 <memory op>
198: # INST2 <memory op> INST3 [R1,]R2
199: # INST3 [R1,]R2 INST2 <memory op>
200: #################################################################
201: if(($i>=2)
202: && ($line[$i] =~ /\s+(([ad][0-7]),)?([ad][0-7])$/)
203: && ($line[$i] !~ /^.+:/)
204: && ($line[$i+1] !~ /ccr|jb[^s]/)) {
205: $adr = $2?$2:"a8"; # unused register
206: $reg = $3;
207: study($line[$i-1]);
208: study($line[$i-2]);
209: if(($line[$i-1] =~ /@|_regflags/)
210: && ($line[$i-2] =~ /@|_regflags/)
211: && ($line[$i-1] !~ /(^[^\s]+:)|$adr|$reg|jb|ccr|lea|pea/)
212: && ($line[$i-2] !~ /$adr|$reg|lea|pea/)) {
213: $tmp = $line[$i-1];
214: $line[$i-1] = $line[$i];
215: $line[$i] = $tmp;
216: ++$num_opt;
217: }
218: }
219: }
220: return $num_opt-$opt;
221: }
222:
223: ###############################################################################
224:
225: sub not_used {
226: local($i, $reg) = @_;
227:
228: while($i < $lineno) {
229: $line[$i]=~/$reg/ && return 0;
230: ++$i;
231: }
232: return 1;
233: }
234:
235: ###############################################################################
236:
237: sub not_used_before {
238: local($i, $reg) = @_;
239:
240: while($i--) {
241: $line[$i]=~/$reg/ && return 0;
242: }
243: return 1;
244: }
245:
246: ###############################################################################
247:
248: sub analyse_function {
249: $lineno = 0;
250: while(<>) {
251: next if /^#(NO_)?APP/;
252: last if /^_op_[0-9a-f]+:$/;
253: $line[$lineno++] = $_;
254: }
255: return $_;
256: }
257:
258: ###############################################################################
259:
260: sub dump_function {
261: local($i);
262: for($i=0;$i < $lineno; ++$i) {
263: print $line[$i];
264: }
265: }
266:
267: ###############################################################################
268:
269: sub usage {
270: open(FILE,__FILE__);
271: open(OUT,"|less");
272: <FILE>;
273: while(<FILE>) {
274: last if !/^#/;
275: s/^#[ ]?//;
276: s/\$0/$0/;
277: print OUT;
278: }
279: close OUT;
280: exit;
281: }
282:
283: ###############################################################################
284:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.