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