1#!/bin/sh 2# 3# BEGIN LICENSE BLOCK 4# Version: CMPL 1.1 5# 6# The contents of this file are subject to the Cisco-style Mozilla Public 7# License Version 1.1 (the "License"); you may not use this file except 8# in compliance with the License. You may obtain a copy of the License 9# at www.eclipse-clp.org/license. 10# 11# Software distributed under the License is distributed on an "AS IS" 12# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 13# the License for the specific language governing rights and limitations 14# under the License. 15# 16# The Original Code is The ECLiPSe Constraint Logic Programming System. 17# The Initial Developer of the Original Code is Cisco Systems, Inc. 18# Portions created by the Initial Developer are 19# Copyright (C) 1992-2006 Cisco Systems, Inc. All Rights Reserved. 20# 21# Contributor(s): ___________________________________. 22# 23# END LICENSE BLOCK 24# 25# IDENTIFICATION opt_sun4.sh 26# 27# AUTHOR Joachim Schimpf 28# 29# DESCRIPTION A postprocessor to optimize the assembler source 30# that the SUN-4 C compiler generates from emu.c. 31# The main purpose is to turn the normal emulator 32# into a threaded code emulator. 33# 34# In order to make this postprocessor work, 35# emu.c must be compiled with 36# 37# cc [-O[12]] -DTHREADED -DPOSTPRO -S emu.c 38# 39# -DNO_ESCAPE is not allowed! 40# 41# USAGE opt_sun4.sh emu.s <infile> <outfile> 42# 43 44trap 'rm -f /tmp/opt?.$$' 0 45 46# 47# Optimizer pass 0 (analysis) 48# 49# finds: 50# - the label of the switch table 51# 52 53cat > /tmp/opt0.$$ <<\'PASS1a\' 54 55/L.+:/ { 56 thislabel = $1 57 words = 0 # check if a table follows 58 getline 59 while ($0 ~ /^ \.word/) { 60 words++ 61 getline 62 } 63 if (words > 200) { # switch table found 64 optable = thislabel 65 } 66} 67 68END { 69 print optable # pass table label to pass1 70} 71'PASS1a' 72 73# 74# Optimizer pass 1 (analysis) 75# 76# finds: 77# - the 2 code labels of the opcode switch 78# - the register that holds PP 79# 80 81cat > /tmp/opt1.$$ <<\'PASS1b\' 82 83BEGIN { 84 getline 85 optable = $0 # e.g. "L2000118:" 86 table_label = substr($0,1,length($0)-1) 87} 88 89$1 ~ /L.+:/ { 90 line1 = $1 91 getline 92 line2 = $0 93 getline 94 if ($1 ~ /L.+:/) { 95 label1 = line1 96 instr = line2 97 label2 = $1 98 } 99} 100 101$2 ~ /L.+/ { 102 if (index($2, table_label)) { 103 loop1 = label1 104 slot = instr 105 loop2 = label2 106 } 107} 108 109/^\tld\t.*bip_error_code_.*/ { # an assignment to pp, remember the register 110 pp = substr($2, length($2)-2, 3) 111} 112 113END { 114 print pp # pass results to pass2 115 print loop1 116 print slot 117 print loop2 118 print optable 119} 120'PASS1b' 121 122# 123# Optimizer pass 2 (transformation) 124# 125# - replace jumps to the switch labels by threaded code jumps 126# - add the op_addr label to the switch table 127# 128 129cat > /tmp/opt2.$$ <<\'PASS2\' 130 131BEGIN { 132 getline 133 pp = $0 # e.g. "%i0" 134 getline 135 loop1def = $0 136 loop1 = substr($0,1,length($0)-1) # e.g. "L504" 137 getline 138 slot = $0 # add or mov instruction 139 getline 140 loop2 = substr($0,1,length($0)-1) # e.g. "LY224" or "no label" 141 getline 142 optable = $0 # e.g. "L2000118:" 143} 144 145{ 146 if ($2 == loop1) { 147 if ($1 == "b") { 148 getline 149 if ($1 != "nop") { 150 if ($2 ~ /%o0/ || substr($2,length($2)-2,3) == pp) { 151 print 152 print "\tld\t[" pp "],%o0" 153 } else { 154 print "\tld\t[" pp "],%o0" 155 print 156 } 157 } else { 158 print "\tld\t[" pp "],%o0" 159 } 160 print "\tjmpl\t%o0,%g0" 161 print "\tadd\t" pp ",4," pp 162 } else { 163 print "\t" $1 "\tLnewloop1" # works even for .word 164 } 165 } else if ($2 == loop2) { 166 if ($1 == "b") { 167 print "\tld\t[" pp "],%o0" 168 print "\tjmpl\t%o0,%g0" 169 print "\tadd\t" pp ",4," pp 170 } else { 171 if ($1 !~ /,a$/) { 172 print "OPTIMIZER: anull flag expected in " $0 173 exit 174 } 175 print "\t" $1 "\tLnewloop2" 176 print "\tld\t[" pp "],%o0" 177 } 178 getline # skip the useless delay slot instruction 179 if (!index($0, slot)) { 180 print "OPTIMIZER: unexpected instruction " $0 181 exit 182 } 183 } else if ($1 == loop1def) { 184 print "Lnewloop1:" 185 print "\tld\t[" pp "],%o0" 186 print "Lnewloop2:" 187 print "\tjmpl\t%o0,%g0" 188 print "\tadd\t" pp ",4," pp 189 print 190 } else if ($1 == optable) { 191 print "_op_addr:" 192 print 193 } else if ($1 == ".global" && !already_printed) { 194 already_printed = 1 195 print "\t.global\t_op_addr" 196 print 197 } else 198 print 199} 200'PASS2' 201 202#echo pass0 203awk -f /tmp/opt0.$$ $1 > /tmp/opt9.$$ 204#echo pass1 205awk -f /tmp/opt1.$$ /tmp/opt9.$$ $1 > $1.par 206 207#echo pass2 208#awk -f /tmp/opt2.$$ $1.par $1 > $2 209awk -f /tmp/opt2.$$ $1.par $1 | sed -e "s/`head -1 $1.par`/%g6/g" > $2 210 211# 212# The sed script above replaces the register that holds pp by 213# a global sparc register (good choices are g5, g6 or g7). 214# 215# Now create 2 functions to set and return the value of this register. 216# 217 218cat >> $2 <<\'EOF\' 219 .seg "text" 220 .proc 04 221 .global _get_pp 222_get_pp: 223 retl 224 mov %g6,%o0 225 226 .proc 04 227 .global _set_pp 228_set_pp: 229 retl 230 mov %o0,%g6 231 .seg "data" 232'EOF' 233 234#echo done 235