|
|
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: && ¬_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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.