1#! /bin/sh 2 3# $Id: sparc-bus-auto.sh,v 1.1 2006/09/30 12:55:59 fredette Exp $ 4 5# ic/sparc/sparc-bus-auto.sh - automatically generates C code 6# for SPARC bus emulation support: 7 8# 9# Copyright (c) 2003, 2005 Matt Fredette 10# All rights reserved. 11# 12# Redistribution and use in source and binary forms, with or without 13# modification, are permitted provided that the following conditions 14# are met: 15# 1. Redistributions of source code must retain the above copyright 16# notice, this list of conditions and the following disclaimer. 17# 2. Redistributions in binary form must reproduce the above copyright 18# notice, this list of conditions and the following disclaimer in the 19# documentation and/or other materials provided with the distribution. 20# 3. All advertising materials mentioning features or use of this software 21# must display the following acknowledgement: 22# This product includes software developed by Matt Fredette. 23# 4. The name of the author may not be used to endorse or promote products 24# derived from this software without specific prior written permission. 25# 26# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 28# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 29# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 30# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 31# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 32# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 34# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 35# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36# POSSIBILITY OF SUCH DAMAGE. 37# 38 39header=false 40 41for option 42do 43 case $option in 44 --header) header=true ;; 45 esac 46done 47 48PROG=`basename $0` 49cat <<EOF 50/* automatically generated by $PROG, do not edit! */ 51_TME_RCSID("\$Id: sparc-bus-auto.sh,v 1.1 2006/09/30 12:55:59 fredette Exp $"); 52 53/* it was easiest, but probably not the most correct, to reuse the 54 m68020 bus router, at least for the early SPARCs. there are 55 probably real differences between the m68020 bus router and the bus 56 router used by the MB89600, for example, but I don't have a 57 datasheet for the latter. the placement of devices in the Sun 58 4/2x0 address space, however, hints that the two probably are very 59 similar. */ 60 61/* we use OP3, OP2, OP1, and OP0 to represent bytes of lesser 62 significance to more significance, respectively, matching Table 5-5 63 in the MC68020 User's Manual (linear page 56 in my .ps copy). 64 65 the Motorola OPn convention numbers bytes by decreasing 66 significance (OP2 is less significant than OP1), and since Motorola 67 CPUs are big-endian, this means that a higher numbered byte is 68 meant to go to a higher address, which is good, because we can then 69 use this to easily form indexes for TME_BUS_LANE_ROUTE, which 70 expects a higher numbered index to correspond to a higher address 71 in memory. 72 73 however, since the same Motorola OPn convention always calls the 74 least significant byte of any value OP3, regardless of the total 75 size of the value, we need to adjust each OPn given the total 76 size of the value, so that OP3 in a 24-bit value means address + 2, 77 but OP3 in a 32-bit value means address + 3: */ 78#define SIZ8_OP(n) ((n) - 3) 79#define SIZ16_OP(n) ((n) - 2) 80#define SIZ24_OP(n) ((n) - 1) 81#define SIZ32_OP(n) ((n) - 0) 82EOF 83 84# emit the 32-bit bus router: 85if $header; then :; else 86 echo "" 87 echo "/* the 32-bit bus router used on the early SPARCs: */" 88 echo "static const tme_bus_lane_t tme_sparc32_router[TME_SPARC_BUS_ROUTER_SIZE(TME_BUS32_LOG2)] = {" 89 90 # permute over maximum cycle size: 91 for transfer in 1 2 3 4; do 92 # these are real 68020 SIZ1 and SIZ0 bits: 93 case ${transfer} in 94 1) transfer_bits="01" ;; 95 2) transfer_bits="10" ;; 96 3) transfer_bits="11" ;; 97 4) transfer_bits="00" ;; 98 esac 99 100 # permute over A1 and A0: 101 for address in 0 1 2 3; do 102 case $address in 103 0) address_bits=00 ;; 104 1) address_bits=01 ;; 105 2) address_bits=10 ;; 106 3) address_bits=11 ;; 107 esac 108 109 # permute over the size of the responding device's port: 110 for port_size in 1 2 4; do 111 112 # permute over the byte lane position of the responding device's port: 113 for port_pos in 0 1 2 3; do 114 115 # get a string describing the byte lanes connected 116 # to this device. NB that the sparc 32-bit bus 117 # router assumes that 8-bit devices are always 118 # connected to D31-D24, and that 16-bit devices 119 # are always connected to D31-D24 and D23-D16, and 120 # cannot dynamically adapt to other 121 # configurations: 122 port_pos_end=`expr ${port_pos} + ${port_size}` 123 port_pos_lane=$port_pos 124 port_lanes="" 125 while test `expr ${port_pos_lane} \< ${port_pos_end}` = 1; do 126 port_lanes=" D"`expr \( \( ${port_pos_lane} + 1 \) \* 8 \) - 1`"-D"`expr ${port_pos_lane} \* 8`"${port_lanes}" 127 port_pos_lane=`expr ${port_pos_lane} + 1` 128 done 129 if test `expr ${port_pos_end} \> 4` = 1; then 130 port_lanes="${port_lanes} - invalid, array placeholder" 131 elif ( test $port_size = 1 && test $port_pos != 3 ) \ 132 || ( test $port_size = 2 && test $port_pos != 2 ); then 133 port_lanes="${port_lanes} - incorrect for 32-bit sparc" 134 fi 135 136 # find the byte lane that would provide OP3. note 137 # that it may not exist (lane < 0), or that it may 138 # not be within the port: 139 opn=`expr 4 - ${transfer}` 140 opn_lane=`expr 3 - \( ${address} % ${port_size} \)` 141 op3_lane=`expr ${opn_lane} - \( 3 - ${opn} \)` 142 143 echo "" 144 echo " /* [sparc] initiator maximum cycle size: "`expr ${transfer} \* 8`" bits" 145 echo " [sparc] initiator A1,A0: ${address_bits}" 146 echo " [gen] responder port size: "`expr ${port_size} \* 8`" bits" 147 echo " [gen] responder port least lane: ${port_pos} (lanes${port_lanes})" 148 echo " (code ${transfer}.${address}.${port_size}.${port_pos}, OP3 lane ${op3_lane}): */" 149 150 # emit the bus router information for each lane: 151 for lane in 0 1 2 3; do 152 lane_warn= 153 154 # if the sparc expects this byte lane to be connected 155 # to the device at this port size: 156 if test `expr ${lane} \< \( 4 - ${port_size} \)` = 0; then 157 158 # if this lane is routed by the sparc when 159 # reading at this transfer size and 160 # address alignment: 161 opn=`expr 3 - \( ${lane} - ${op3_lane} \)` 162 if test `expr ${opn} \> 3` = 0 \ 163 && test `expr ${opn} \< \( 4 - ${transfer} \)` = 0; then 164 lane_read="OP(${opn})" 165 166 # otherwise this lane isn't routed by the 167 # sparc when reading at this transfer size 168 # and address alignment: 169 else 170 lane_read="IGNORE" 171 fi 172 173 # otherwise the sparc does not expect this byte 174 # lane to be connected to the device at this 175 # port size: 176 else 177 lane_read="IGNORE" 178 179 # if this lane is connected to the device 180 # anyways, issue a warning: 181 if test `expr ${lane} \< ${port_pos}` = 0 \ 182 && test `expr ${lane} \< ${port_pos_end}` = 1; then 183 lane_warn=" | TME_BUS_LANE_WARN" 184 fi 185 fi 186 187 # dispatch on how this lane is routed by the 188 # sparc when writing at this transfer size and 189 # address alignment: 190 case "${transfer_bits}${address_bits}.${lane}" in 191 01??.3) lane_write="OP(3)" ;; 192 01??.2) lane_write="OP(3)" ;; 193 01??.1) lane_write="OP(3)" ;; 194 01??.0) lane_write="OP(3)" ;; 195 196 10?0.3) lane_write="OP(2)" ;; 197 10?0.2) lane_write="OP(3)" ;; 198 10?0.1) lane_write="OP(2)" ;; 199 10?0.0) lane_write="OP(3)" ;; 200 201 10?1.3) lane_write="OP(2)" ;; 202 10?1.2) lane_write="OP(2)" ;; 203 10?1.1) lane_write="OP(3)" ;; 204 10?1.0) lane_write="OP(2)" ;; 205 206 1100.3) lane_write="OP(1)" ;; 207 1100.2) lane_write="OP(2)" ;; 208 1100.1) lane_write="OP(3)" ;; 209 1100.0) lane_write="UNDEF" ;; # XXX this is supposed to be OP0, but we can't deal with that 210 211 1101.3) lane_write="OP(1)" ;; 212 1101.2) lane_write="OP(1)" ;; 213 1101.1) lane_write="OP(2)" ;; 214 1101.0) lane_write="OP(3)" ;; 215 216 1110.3) lane_write="OP(1)" ;; 217 1110.2) lane_write="OP(2)" ;; 218 1110.1) lane_write="OP(1)" ;; 219 1110.0) lane_write="OP(2)" ;; 220 221 1111.3) lane_write="OP(1)" ;; 222 1111.2) lane_write="OP(1)" ;; 223 1111.1) lane_write="OP(2)" ;; 224 1111.0) lane_write="OP(1)" ;; 225 226 0000.3) lane_write="OP(0)" ;; 227 0000.2) lane_write="OP(1)" ;; 228 0000.1) lane_write="OP(2)" ;; 229 0000.0) lane_write="OP(3)" ;; 230 231 0001.3) lane_write="OP(0)" ;; 232 0001.2) lane_write="OP(0)" ;; 233 0001.1) lane_write="OP(1)" ;; 234 0001.0) lane_write="OP(2)" ;; 235 236 0010.3) lane_write="OP(0)" ;; 237 0010.2) lane_write="OP(1)" ;; 238 0010.1) lane_write="OP(0)" ;; 239 0010.0) lane_write="OP(1)" ;; 240 241 0011.3) lane_write="OP(0)" ;; 242 0011.2) lane_write="OP(0)" ;; 243 0011.1) lane_write="OP(1)" ;; 244 0011.0) lane_write="OP(0)" ;; 245 246 esac 247 248 # emit the comment for this lane: 249 echo -n " /* D"`expr \( \( ${lane} + 1 \) \* 8 \) - 1`"-D"`expr ${lane} \* 8`" */ " 250 251 # if this port size/position combination is 252 # invalid, override everything and abort if 253 # this router entry is ever touched: 254 if test `expr ${port_pos_end} \> 4` = 1; then 255 echo "TME_BUS_LANE_ABORT," 256 else 257 if test $lane_read != "IGNORE"; then 258 if test $lane_read != $lane_write; then 259 echo "$PROG internal error: code ${transfer}.${address}.${port_size}.${port_pos}, reading $lane_read but writing $lane_write" 1>&2 260 exit 1 261 fi 262 echo -n "TME_BUS_LANE_ROUTE(SIZ"`expr ${transfer} \* 8`"_$lane_read)" 263 elif test $lane_write = "UNDEF"; then 264 echo -n "TME_BUS_LANE_UNDEF" 265 else 266 echo -n "TME_BUS_LANE_ROUTE(SIZ"`expr ${transfer} \* 8`"_$lane_write) | TME_BUS_LANE_ROUTE_WRITE_IGNORE" 267 fi 268 echo "${lane_warn}," 269 fi 270 done 271 done 272 done 273 done 274 done 275 echo "};" 276fi 277 278cat <<EOF 279#undef SIZ8_OP 280#undef SIZ16_OP 281#undef SIZ24_OP 282#undef SIZ32_OP 283EOF 284 285# done: 286exit 0