#!/bin/sh # # BEGIN LICENSE BLOCK # Version: CMPL 1.1 # # The contents of this file are subject to the Cisco-style Mozilla Public # License Version 1.1 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License # at www.eclipse-clp.org/license. # # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See # the License for the specific language governing rights and limitations # under the License. # # The Original Code is The ECLiPSe Constraint Logic Programming System. # The Initial Developer of the Original Code is Cisco Systems, Inc. # Portions created by the Initial Developer are # Copyright (C) 1992-2006 Cisco Systems, Inc. All Rights Reserved. # # Contributor(s): ___________________________________. # # END LICENSE BLOCK # # IDENTIFICATION opt_sun4.sh # # AUTHOR Joachim Schimpf # # DESCRIPTION A postprocessor to optimize the assembler source # that the SUN-4 C compiler generates from emu.c. # The main purpose is to turn the normal emulator # into a threaded code emulator. # # In order to make this postprocessor work, # emu.c must be compiled with # # cc [-O[12]] -DTHREADED -DPOSTPRO -S emu.c # # -DNO_ESCAPE is not allowed! # # USAGE opt_sun4.sh emu.s # trap 'rm -f /tmp/opt?.$$' 0 # # Optimizer pass 0 (analysis) # # finds: # - the label of the switch table # cat > /tmp/opt0.$$ <<\'PASS1a\' /L.+:/ { thislabel = $1 words = 0 # check if a table follows getline while ($0 ~ /^ \.word/) { words++ getline } if (words > 200) { # switch table found optable = thislabel } } END { print optable # pass table label to pass1 } 'PASS1a' # # Optimizer pass 1 (analysis) # # finds: # - the 2 code labels of the opcode switch # - the register that holds PP # cat > /tmp/opt1.$$ <<\'PASS1b\' BEGIN { getline optable = $0 # e.g. "L2000118:" table_label = substr($0,1,length($0)-1) } $1 ~ /L.+:/ { line1 = $1 getline line2 = $0 getline if ($1 ~ /L.+:/) { label1 = line1 instr = line2 label2 = $1 } } $2 ~ /L.+/ { if (index($2, table_label)) { loop1 = label1 slot = instr loop2 = label2 } } /^\tld\t.*bip_error_code_.*/ { # an assignment to pp, remember the register pp = substr($2, length($2)-2, 3) } END { print pp # pass results to pass2 print loop1 print slot print loop2 print optable } 'PASS1b' # # Optimizer pass 2 (transformation) # # - replace jumps to the switch labels by threaded code jumps # - add the op_addr label to the switch table # cat > /tmp/opt2.$$ <<\'PASS2\' BEGIN { getline pp = $0 # e.g. "%i0" getline loop1def = $0 loop1 = substr($0,1,length($0)-1) # e.g. "L504" getline slot = $0 # add or mov instruction getline loop2 = substr($0,1,length($0)-1) # e.g. "LY224" or "no label" getline optable = $0 # e.g. "L2000118:" } { if ($2 == loop1) { if ($1 == "b") { getline if ($1 != "nop") { if ($2 ~ /%o0/ || substr($2,length($2)-2,3) == pp) { print print "\tld\t[" pp "],%o0" } else { print "\tld\t[" pp "],%o0" print } } else { print "\tld\t[" pp "],%o0" } print "\tjmpl\t%o0,%g0" print "\tadd\t" pp ",4," pp } else { print "\t" $1 "\tLnewloop1" # works even for .word } } else if ($2 == loop2) { if ($1 == "b") { print "\tld\t[" pp "],%o0" print "\tjmpl\t%o0,%g0" print "\tadd\t" pp ",4," pp } else { if ($1 !~ /,a$/) { print "OPTIMIZER: anull flag expected in " $0 exit } print "\t" $1 "\tLnewloop2" print "\tld\t[" pp "],%o0" } getline # skip the useless delay slot instruction if (!index($0, slot)) { print "OPTIMIZER: unexpected instruction " $0 exit } } else if ($1 == loop1def) { print "Lnewloop1:" print "\tld\t[" pp "],%o0" print "Lnewloop2:" print "\tjmpl\t%o0,%g0" print "\tadd\t" pp ",4," pp print } else if ($1 == optable) { print "_op_addr:" print } else if ($1 == ".global" && !already_printed) { already_printed = 1 print "\t.global\t_op_addr" print } else print } 'PASS2' #echo pass0 awk -f /tmp/opt0.$$ $1 > /tmp/opt9.$$ #echo pass1 awk -f /tmp/opt1.$$ /tmp/opt9.$$ $1 > $1.par #echo pass2 #awk -f /tmp/opt2.$$ $1.par $1 > $2 awk -f /tmp/opt2.$$ $1.par $1 | sed -e "s/`head -1 $1.par`/%g6/g" > $2 # # The sed script above replaces the register that holds pp by # a global sparc register (good choices are g5, g6 or g7). # # Now create 2 functions to set and return the value of this register. # cat >> $2 <<\'EOF\' .seg "text" .proc 04 .global _get_pp _get_pp: retl mov %g6,%o0 .proc 04 .global _set_pp _set_pp: retl mov %o0,%g6 .seg "data" 'EOF' #echo done