Files
Run-Sun3-SunOS-4.1.1/tme-0.8_up/ic/m68k/m68k-misc-auto.sh
Amberelle Mason ac30ff9032 Initial import
Initial import of SunOS 4.1.1 and TME 0.8
2023-05-01 12:16:40 -04:00

357 lines
13 KiB
Bash

#! /bin/sh
# $Id: m68k-misc-auto.sh,v 1.11 2007/02/16 02:50:23 fredette Exp $
# ic/m68k/m68k-misc-auto.sh - automatically generates C code
# for miscellaneous m68k emulation support:
#
# Copyright (c) 2002, 2003 Matt Fredette
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by Matt Fredette.
# 4. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
header=false
for option
do
case $option in
--header) header=true ;;
esac
done
PROG=`basename $0`
cat <<EOF
/* automatically generated by $PROG, do not edit! */
EOF
# we need our own inclusion protection, since the instruction word
# fetch macros need to be multiply included:
if $header; then
echo ""
echo "#ifndef _IC_M68K_MISC_H"
echo "#define _IC_M68K_MISC_H"
fi
# emit the register mapping macros:
if $header; then
echo ""
echo "/* the register mapping: */"
echo "#define TME_M68K_IREG_UNDEF (-1)"
ireg32_next=0
# NB: these are in a deliberate order, matching the order of
# registers in instruction encodings:
for regtype in d a; do
capregtype=`echo ${regtype} | tr a-z A-Z`
for regnum in 0 1 2 3 4 5 6 7; do
echo "#define TME_M68K_IREG_${capregtype}${regnum} (${ireg32_next})"
echo "#define tme_m68k_ireg_${regtype}${regnum} tme_m68k_ireg_uint32(TME_M68K_IREG_${capregtype}${regnum})"
ireg32_next=`expr ${ireg32_next} + 1`
done
done
# the current, next, and last program counter:
echo "#define TME_M68K_IREG_PC (${ireg32_next})"
echo "#define tme_m68k_ireg_pc tme_m68k_ireg_uint32(TME_M68K_IREG_PC)"
ireg32_next=`expr ${ireg32_next} + 1`
echo "#define TME_M68K_IREG_PC_NEXT (${ireg32_next})"
echo "#define tme_m68k_ireg_pc_next tme_m68k_ireg_uint32(TME_M68K_IREG_PC_NEXT)"
ireg32_next=`expr ${ireg32_next} + 1`
echo "#define TME_M68K_IREG_PC_LAST (${ireg32_next})"
echo "#define tme_m68k_ireg_pc_last tme_m68k_ireg_uint32(TME_M68K_IREG_PC_LAST)"
ireg32_next=`expr ${ireg32_next} + 1`
# the status register and ccr:
echo "#define tme_m68k_ireg_sr tme_m68k_ireg_uint16(${ireg32_next} << 1)"
echo "#define tme_m68k_ireg_ccr tme_m68k_ireg_uint8(${ireg32_next} << 2)"
ireg32_next=`expr ${ireg32_next} + 1`
# the shadow status register and format/offset word:
echo "#define TME_M68K_IREG_SHADOW_SR (${ireg32_next} << 1)"
echo "#define tme_m68k_ireg_shadow_sr tme_m68k_ireg_uint16(TME_M68K_IREG_SHADOW_SR)"
echo "#define TME_M68K_IREG_FORMAT_OFFSET ((${ireg32_next} << 1) + 1)"
echo "#define tme_m68k_ireg_format_offset tme_m68k_ireg_uint16(TME_M68K_IREG_FORMAT_OFFSET)"
ireg32_next=`expr ${ireg32_next} + 1`
# the memory buffers:
for mem_which in x y z; do
cap_mem_which=`echo ${mem_which} | tr a-z A-Z`
echo "#define TME_M68K_IREG_MEM${cap_mem_which}32 (${ireg32_next})"
echo "#define tme_m68k_ireg_mem${mem_which}32 tme_m68k_ireg_uint32(TME_M68K_IREG_MEM${cap_mem_which}32)"
echo "#define TME_M68K_IREG_MEM${cap_mem_which}16 (${ireg32_next} << 1)"
echo "#define tme_m68k_ireg_mem${mem_which}16 tme_m68k_ireg_uint16(TME_M68K_IREG_MEM${cap_mem_which}16)"
echo "#define TME_M68K_IREG_MEM${cap_mem_which}8 (${ireg32_next} << 2)"
echo "#define tme_m68k_ireg_mem${mem_which}8 tme_m68k_ireg_uint8(TME_M68K_IREG_MEM${cap_mem_which}8)"
ireg32_next=`expr ${ireg32_next} + 1`
done
# the control registers:
for reg in usp isp msp sfc dfc vbr cacr caar; do
capreg=`echo $reg | tr a-z A-Z`
echo "#define TME_M68K_IREG_${capreg} (${ireg32_next})"
echo "#define tme_m68k_ireg_${reg} tme_m68k_ireg_uint32(TME_M68K_IREG_${capreg})"
ireg32_next=`expr ${ireg32_next} + 1`
done
# this is the count of variable 32-bit registers:
echo "#define TME_M68K_IREG32_COUNT (${ireg32_next})"
# the immediate register. there are actually three 32-bit
# registers in a row, to allow the fpgen specop to fetch up to a
# 96-bit immediate:
echo "#define TME_M68K_IREG_IMM32 (${ireg32_next})"
echo "#define tme_m68k_ireg_imm32 tme_m68k_ireg_uint32(TME_M68K_IREG_IMM32)"
ireg32_next=`expr ${ireg32_next} + 3`
# the effective address register:
echo "#define TME_M68K_IREG_EA (${ireg32_next})"
echo "#define tme_m68k_ireg_ea tme_m68k_ireg_uint32(TME_M68K_IREG_EA)"
ireg32_next=`expr ${ireg32_next} + 1`
# the constant registers:
for reg in zero one two three four five six seven eight; do
capreg=`echo $reg | tr a-z A-Z`
echo "#define TME_M68K_IREG_${capreg} (${ireg32_next})"
ireg32_next=`expr ${ireg32_next} + 1`
done
fi
# emit the flags->conditions mapping. note that the nesting of the
# flag variables is deliberate, to make this array indexable with the
# condition code register:
if $header; then :; else
echo ""
echo "/* the flags->conditions mapping: */"
echo "const tme_uint16_t _tme_m68k_conditions[32] = {"
for xflag in 0 1; do
for nflag in 0 1; do
for zflag in 0 1; do
for vflag in 0 1; do
for cflag in 0 1; do
# the True condition:
echo -n "TME_BIT(TME_M68K_C_T)"
# the High condition:
if test $cflag != 1 && test $zflag != 1; then
echo -n " | TME_BIT(TME_M68K_C_HI)"
fi
# the Low or Same condition:
if test $cflag = 1 || test $zflag = 1; then
echo -n " | TME_BIT(TME_M68K_C_LS)"
fi
# the Carry Clear and Carry Set conditions:
if test $cflag != 1; then
echo -n " | TME_BIT(TME_M68K_C_CC)"
else
echo -n " | TME_BIT(TME_M68K_C_CS)"
fi
# the Not Equal and Equal conditions:
if test $zflag != 1; then
echo -n " | TME_BIT(TME_M68K_C_NE)"
else
echo -n " | TME_BIT(TME_M68K_C_EQ)"
fi
# the Overflow Clear and Overflow Set conditions:
if test $vflag != 1; then
echo -n " | TME_BIT(TME_M68K_C_VC)"
else
echo -n " | TME_BIT(TME_M68K_C_VS)"
fi
# the Plus and Minus conditions:
if test $nflag != 1; then
echo -n " | TME_BIT(TME_M68K_C_PL)"
else
echo -n " | TME_BIT(TME_M68K_C_MI)"
fi
# the Greater or Equal condition:
if (test $nflag = 1 && test $vflag = 1) || \
(test $nflag != 1 && test $vflag != 1); then
echo -n " | TME_BIT(TME_M68K_C_GE)"
fi
# the Less Than condition:
if (test $nflag = 1 && test $vflag != 1) || \
(test $nflag != 1 && test $vflag = 1); then
echo -n " | TME_BIT(TME_M68K_C_LT)"
fi
# the Greater Than condition:
if (test $nflag = 1 && test $vflag = 1 && test $zflag != 1) || \
(test $nflag != 1 && test $vflag != 1 && test $zflag != 1); then
echo -n " | TME_BIT(TME_M68K_C_GT)"
fi
# the Less Than or Equal condition:
if test $zflag = 1 || \
(test $nflag = 1 && test $vflag != 1) || \
(test $nflag != 1 && test $vflag = 1); then
echo -n " | TME_BIT(TME_M68K_C_LE)"
fi
echo ","
done
done
done
done
done
echo "};"
fi
# emit the instruction word fetch macros:
if $header; then
# emit the simple signed and unsigned fetch macros:
#
echo ""
echo "/* the simple signed and unsigned fetch macros: */"
# permute over size:
#
for size in 16 32; do
# permute for signed or unsigned:
#
for capsign in U S; do
if test $capsign = U; then sign=u ; un=un ; else sign= ; un= ; fi
echo "#define _TME_M68K_EXECUTE_FETCH_${capsign}${size}(v) \\"
echo " _TME_M68K_EXECUTE_FETCH_${size}(tme_${sign}int${size}_t, v)"
if test ${size} = 16 && test ${capsign} = U; then
echo "#define _TME_M68K_EXECUTE_FETCH_${capsign}${size}_FIXED(v, field) \\"
echo " _TME_M68K_EXECUTE_FETCH_${size}_FIXED(tme_${sign}int${size}_t, v, field)"
fi
done
done
echo ""
echo "#endif /* _IC_M68K_MISC_H */"
# permute for the fast vs. slow executors:
for executor in fast slow; do
echo ""
echo -n "#if"
if test $executor = slow; then echo -n "n"; fi
echo "def _TME_M68K_EXECUTE_FAST"
echo ""
echo "/* these macros are for the ${executor} executor: */"
# permute over size:
#
for size in 16 32; do
echo ""
echo "/* this fetches a ${size}-bit value for the ${executor} executor: */"
echo "#undef _TME_M68K_EXECUTE_FETCH_${size}"
echo "#define _TME_M68K_EXECUTE_FETCH_${size}(type, v) \\"
if test $executor = slow; then
# this expression gives the current fetch offset in the instruction:
#
offset_fetch="ic->_tme_m68k_insn_fetch_slow_next"
echo " /* macros for the ${executor} executor are simple, because \\"
echo " tme_m68k_fetch${size}() takes care of all endianness, alignment, \\"
echo " and atomic issues, and also stores the fetched value in the \\"
echo " instruction fetch buffer (if a previous fetch before a fault \\"
echo " didn't store all or part of it there already): */ \\"
echo " (v) = (type) tme_m68k_fetch${size}(ic, linear_pc); \\"
echo " linear_pc += sizeof(tme_uint${size}_t)"
else
# this expression gives the current fetch offset in the instruction:
#
offset_fetch="(fetch_fast_next - ic->_tme_m68k_insn_fetch_fast_start)"
echo " /* use the raw fetch macro to fetch the value into the variable, \\"
echo " and then save it in the instruction buffer. the save doesn't \\"
echo " need to be atomic; no one else can see the instruction buffer. \\"
echo " however, the raw fetch macro has already advanced fetch_fast_next, \\"
echo " so we need to compensate for that here: */ \\"
echo " __TME_M68K_EXECUTE_FETCH_${size}(type, v); \\"
echo " tme_memory_write${size}(((tme_uint${size}_t *) ((((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) - sizeof(tme_uint${size}_t)) + ${offset_fetch})), (tme_uint${size}_t) (v), sizeof(tme_uint16_t))"
echo ""
echo "/* this does a raw fetch of a ${size}-bit value for the ${executor} executor: */"
echo "#undef __TME_M68K_EXECUTE_FETCH_${size}"
echo "#define __TME_M68K_EXECUTE_FETCH_${size}(type, v) \\"
echo " /* if we can't do the fast read, we need to redispatch: */ \\"
echo " /* NB: checks in tme_m68k_go_slow(), and proper setting of \\"
echo " ic->_tme_m68k_insn_fetch_fast_last in _TME_M68K_EXECUTE_NAME(), \\"
echo " allow us to do a simple pointer comparison here, for \\"
echo " any fetch size: */ \\"
echo " if (__tme_predict_false(fetch_fast_next > ic->_tme_m68k_insn_fetch_fast_last)) \\"
echo " goto _tme_m68k_fast_fetch_failed; \\"
echo " (v) = ((type) \\"
echo " tme_betoh_u${size}(tme_memory_bus_read${size}((const tme_shared tme_uint${size}_t *) fetch_fast_next, \\"
echo " tlb->tme_m68k_tlb_bus_rwlock, \\"
echo " sizeof(tme_uint16_t), \\"
echo " sizeof(tme_uint32_t)))); \\"
echo " fetch_fast_next += sizeof(tme_uint${size}_t)"
fi
# if this size doesn't get a fixed fetch macro, continue now:
#
if test ${size} != 16; then
continue
fi
echo ""
echo "/* this fetches a ${size}-bit value at a fixed instruction position"
echo " for the ${executor} executor: */"
echo "#undef _TME_M68K_EXECUTE_FETCH_${size}_FIXED"
echo "#define _TME_M68K_EXECUTE_FETCH_${size}_FIXED(type, v, field) \\"
echo " assert(&((struct tme_m68k *) 0)->field \\"
echo " == (type *) (((tme_uint8_t *) &((struct tme_m68k *) 0)->_tme_m68k_insn_fetch_buffer[0]) + ${offset_fetch})); \\"
echo -n " "
if test ${executor} = fast; then echo -n _ ; fi
echo "_TME_M68K_EXECUTE_FETCH_${size}(type, v)"
done
echo ""
echo -n "#endif /* "
if test $executor = slow; then echo -n "!"; fi
echo "_TME_M68K_EXECUTE_FAST */"
done
fi
# done:
exit 0