|
|
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;
1.1.1.2 ! root 30: last if /^_op_[0-9a-f_]+:$/;
1.1 root 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;
1.1.1.2 ! root 42: print STDERR "$_ ($num_opt) \r";
1.1 root 43: }
44: while(&optimize_function) {}
45: &dump_function;
46:
1.1.1.2 ! root 47: print STDERR "$num_opt optimisations \n";
1.1 root 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/+/-/;
1.1.1.2 ! root 148: if($N1 + $N2) {
! 149: $line[$i] =~ s/_regs(\+?)$N1/$An@\($N1$N2\)/g;
! 150: } else {
! 151: $line[$i] =~ s/_regs(\+?)$N1/$An@/g;
! 152: }
1.1 root 153: $ext = $line[$j];
154: for($k=$j; $k>$i; --$k) {$line[$k] = $line[$k-1];}
155: $line[$i] = $ext;
156: ++$num_opt;
157: }
158: }
159: }
160: #################################################################
161: # LEA _regs+N1,An => LEA _regs+N1,An
162: # ..An not modified.. ...
163: # INST .._regs+N2.. INST ..(N2-N1)An..
164: #################################################################
165: if($line[$i] =~ /lea\s+_regs(\+\d+)?,(a[0-7])/) {
166: $N1 = $1;$An = $2;
167: $line[$lineno] = "rts"; # sentinel
168: $tmp = "_regs|$An@[-+]|,$An|\sj.+\s|rts|(^.+:)";
169: for($j = $i+1; $line[$j] !~ /$tmp/; ++$j) {}
170: if($line[$j] =~ /_regs(\+\d+)?/) {
171: $N2 = $1; $N1 =~ y/+/-/;
172: $tmp = $N2; $tmp =~ s/[+]/\\+/;
1.1.1.2 ! root 173: if($N1 + $N2) {
! 174: $line[$j] =~ s/_regs$tmp/$An@\($N2$N1\)/g;
! 175: } else {
! 176: $line[$j] =~ s/_regs$tmp/$An@/g;
! 177: }
1.1 root 178: $line[$j] =~ s/\(\)//g;
179: ++$num_opt;
180: }
181: }
182: }
183: #################################################################
184: # MOVE.x X,Dp => MOVE.x X,Dp
185: # ..Dp not used.. MOVE.W CCR,Y
186: # TST.x Dp ..Dp not used..
187: # MOVE.W ccr,Y
188: #################################################################
189: # if($line[$i] =~ /mov[e]?([bwl])\s+.+,(d[0-7])$/) {
190: # $ext = $1;$reg = $2;
191: # $line[$lineno] = "rts"; # sentinel
192: # $tmp = "$reg|rts|\sj.+\s|(^.+:)";
193: # for($j = $i+1; $line[$j] !~ /$tmp/; $j++) {}
194: # if(($line[$j] =~ /tst$ext\s+$reg$/)
195: # && ($line[$j+1] =~ /mov[e]?w\s+ccr,/)) {
196: # &delete_line($j);
197: # $ext = $line[$j];
198: # for($k=$j;$k>$i+1;--$k) {$line[$k] = $line[$k-1];}
199: # $line[$i+1] = $ext;
200: # ++$num_opt;
201: # }
202: # }
203: #################################################################
204: # General instruction scheduling optimisation:
205: # INST1 <memory op> => INST1 <memory op>
206: # INST2 <memory op> INST3 [R1,]R2
207: # INST3 [R1,]R2 INST2 <memory op>
208: #################################################################
209: if(($i>=2)
210: && ($line[$i] =~ /\s+(([ad][0-7]),)?([ad][0-7])$/)
211: && ($line[$i] !~ /^.+:/)
212: && ($line[$i+1] !~ /ccr|jb[^s]/)) {
213: $adr = $2?$2:"a8"; # unused register
214: $reg = $3;
215: study($line[$i-1]);
216: study($line[$i-2]);
217: if(($line[$i-1] =~ /@|_regflags/)
218: && ($line[$i-2] =~ /@|_regflags/)
219: && ($line[$i-1] !~ /(^[^\s]+:)|$adr|$reg|jb|ccr|lea|pea/)
220: && ($line[$i-2] !~ /$adr|$reg|lea|pea/)) {
221: $tmp = $line[$i-1];
222: $line[$i-1] = $line[$i];
223: $line[$i] = $tmp;
224: ++$num_opt;
225: }
226: }
227: }
228: return $num_opt-$opt;
229: }
230:
231: ###############################################################################
232:
233: sub not_used {
234: local($i, $reg) = @_;
235:
236: while($i < $lineno) {
237: $line[$i]=~/$reg/ && return 0;
238: ++$i;
239: }
240: return 1;
241: }
242:
243: ###############################################################################
244:
245: sub not_used_before {
246: local($i, $reg) = @_;
247:
248: while($i--) {
249: $line[$i]=~/$reg/ && return 0;
250: }
251: return 1;
252: }
253:
254: ###############################################################################
255:
256: sub analyse_function {
257: $lineno = 0;
258: while(<>) {
259: next if /^#(NO_)?APP/;
1.1.1.2 ! root 260: last if /^_op_[0-9a-f_]+:$/;
1.1 root 261: $line[$lineno++] = $_;
262: }
263: return $_;
264: }
265:
266: ###############################################################################
267:
268: sub dump_function {
269: local($i);
270: for($i=0;$i < $lineno; ++$i) {
1.1.1.2 ! root 271: $_ = $line[$i];
! 272: s/lea\s(a[0-7])\@\(\),/movel $1,/;
! 273: print;
1.1 root 274: }
275: }
276:
277: ###############################################################################
278:
279: sub usage {
280: open(FILE,__FILE__);
281: open(OUT,"|less");
282: <FILE>;
283: while(<FILE>) {
284: last if !/^#/;
285: s/^#[ ]?//;
286: s/\$0/$0/;
287: print OUT;
288: }
289: close OUT;
290: exit;
291: }
292:
293: ###############################################################################
294:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.