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_sun3.sh
26#
27# AUTHOR		Joachim Schimpf
28#
29# DESCRIPTION		A postprocessor to optimize the assembler source
30#			that the SUN-3 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 ... -S emu.c
38#
39#			-DNO_ESCAPE is not allowed!
40#
41#			Haven't tried with GNU yet.
42#
43# USAGE			opt_sun3.sh <infile> <outfile>
44#
45# NOTE	Since the C compiler generates switch tables with relative offsets,
46#	it cannot be used directly as the op_addr[] array. Therefore
47#	we insert the label _opswitch_addr for the switch table.
48#	When sepia is booted, the op_addr[] array must be computed from
49#	the switch table (function opaddr_init()). This function is dependent
50#	of the offset size (16 or 32 bit, according to cc's -J option)
51#	and must be updated accordingly. This postprocessor can handle both.
52
53trap 'rm -f /tmp/opt?.$$' 0 2
54
55#
56# Optimizer pass 1 (analysis)
57#
58# find:
59#	- the code labels of the opcode switch
60#	- the label of the switch table
61#	- the register that holds PP
62#
63
64cat > /tmp/opt1.$$ <<\'PASS1\'
65
66/L.+:/ {
67	thislabel = $1
68	words = 0			# check if a table follows
69	getline
70	while ($0 ~ /^\t\.(short|long)/) {
71		words++
72		getline
73	}
74	if (words == 0) {		# not a table
75	    line1 = thislabel		# this might be the switch label
76	} else if (words > 200) {	# switch table found
77	    loop1 = line1		# remember all the information
78	    optable = thislabel
79	}
80}
81
82/^\tmovl\t.*_bip_error_code_.*/ {	# an assignment to pp, remember the register
83	pp = substr($2, length($2)-1, 2)
84}
85
86END {
87	print pp			# pass results to pass2
88	print loop1
89	print optable
90}
91'PASS1'
92
93#
94# Optimizer pass 2 (transformation)
95#
96# - replace jumps to the switch labels by threaded code jumps
97# - add the op_addr label to the switch table
98#
99
100cat > /tmp/opt2.$$ <<\'PASS2\'
101
102BEGIN	{
103	getline
104	pp = $0					# e.g. "a5"
105	getline
106	loop1def = $0
107	loop1 = substr($0,1,length($0)-1)	# e.g. "L504"
108	getline
109	optable = $0				# e.g. "L2000118:"
110}
111
112{
113	if ($2 == loop1) {
114	    if ($1 == "jra") {
115		print "\tmovl\t" pp "@+,a0"
116		print "\tjmp\ta0@"
117	    } else {
118		print "\t" $1 "\tLnewloop1"
119	    }
120	} else if ($1 == loop1def) {
121	    print "Lnewloop1:"
122	    print "\tmovl\t" pp "@+,a0"
123	    print "\tjmp\ta0@"
124	    print
125	} else if ($1 == optable) {
126	    print "_opswitch_table:"
127	    print
128	} else if (!already_printed && $1 == ".globl" && $2 == "_emulc") {
129	    already_printed = 1
130	    print "\t.globl\t_opswitch_table"
131	    print
132	} else
133	    print
134}
135'PASS2'
136
137# echo pass1
138awk -f /tmp/opt1.$$ $1 > $1.par
139# echo pass2
140awk -f /tmp/opt2.$$ $1.par $1 > $2
141# echo done
142