|
|
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.