|
|
1.1 root 1: #! /bin/sh
2:
1.1.1.3 ! root 3: # $Id: m68k-misc-auto.sh,v 1.11 2007/02/16 02:50:23 fredette Exp $
1.1 root 4:
5: # ic/m68k/m68k-misc-auto.sh - automatically generates C code
6: # for miscellaneous m68k emulation support:
7:
8: #
9: # Copyright (c) 2002, 2003 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:
39: header=false
40:
41: for option
42: do
43: case $option in
44: --header) header=true ;;
45: esac
46: done
47:
48: PROG=`basename $0`
49: cat <<EOF
50: /* automatically generated by $PROG, do not edit! */
51: EOF
52:
53: # we need our own inclusion protection, since the instruction word
54: # fetch macros need to be multiply included:
55: if $header; then
56: echo ""
57: echo "#ifndef _IC_M68K_MISC_H"
58: echo "#define _IC_M68K_MISC_H"
59: fi
60:
61: # emit the register mapping macros:
62: if $header; then
63:
64: echo ""
65: echo "/* the register mapping: */"
66: echo "#define TME_M68K_IREG_UNDEF (-1)"
67: ireg32_next=0
68:
69: # NB: these are in a deliberate order, matching the order of
70: # registers in instruction encodings:
71: for regtype in d a; do
72: capregtype=`echo ${regtype} | tr a-z A-Z`
73: for regnum in 0 1 2 3 4 5 6 7; do
74: echo "#define TME_M68K_IREG_${capregtype}${regnum} (${ireg32_next})"
75: echo "#define tme_m68k_ireg_${regtype}${regnum} tme_m68k_ireg_uint32(TME_M68K_IREG_${capregtype}${regnum})"
76: ireg32_next=`expr ${ireg32_next} + 1`
77: done
78: done
79:
1.1.1.2 root 80: # the current, next, and last program counter:
1.1 root 81: echo "#define TME_M68K_IREG_PC (${ireg32_next})"
82: echo "#define tme_m68k_ireg_pc tme_m68k_ireg_uint32(TME_M68K_IREG_PC)"
83: ireg32_next=`expr ${ireg32_next} + 1`
84: echo "#define TME_M68K_IREG_PC_NEXT (${ireg32_next})"
85: echo "#define tme_m68k_ireg_pc_next tme_m68k_ireg_uint32(TME_M68K_IREG_PC_NEXT)"
86: ireg32_next=`expr ${ireg32_next} + 1`
1.1.1.2 root 87: echo "#define TME_M68K_IREG_PC_LAST (${ireg32_next})"
88: echo "#define tme_m68k_ireg_pc_last tme_m68k_ireg_uint32(TME_M68K_IREG_PC_LAST)"
89: ireg32_next=`expr ${ireg32_next} + 1`
1.1 root 90:
91: # the status register and ccr:
92: echo "#define tme_m68k_ireg_sr tme_m68k_ireg_uint16(${ireg32_next} << 1)"
93: echo "#define tme_m68k_ireg_ccr tme_m68k_ireg_uint8(${ireg32_next} << 2)"
94: ireg32_next=`expr ${ireg32_next} + 1`
95:
96: # the shadow status register and format/offset word:
97: echo "#define TME_M68K_IREG_SHADOW_SR (${ireg32_next} << 1)"
98: echo "#define tme_m68k_ireg_shadow_sr tme_m68k_ireg_uint16(TME_M68K_IREG_SHADOW_SR)"
99: echo "#define TME_M68K_IREG_FORMAT_OFFSET ((${ireg32_next} << 1) + 1)"
100: echo "#define tme_m68k_ireg_format_offset tme_m68k_ireg_uint16(TME_M68K_IREG_FORMAT_OFFSET)"
101: ireg32_next=`expr ${ireg32_next} + 1`
102:
103: # the memory buffers:
104: for mem_which in x y z; do
105: cap_mem_which=`echo ${mem_which} | tr a-z A-Z`
106: echo "#define TME_M68K_IREG_MEM${cap_mem_which}32 (${ireg32_next})"
107: echo "#define tme_m68k_ireg_mem${mem_which}32 tme_m68k_ireg_uint32(TME_M68K_IREG_MEM${cap_mem_which}32)"
108: echo "#define TME_M68K_IREG_MEM${cap_mem_which}16 (${ireg32_next} << 1)"
109: echo "#define tme_m68k_ireg_mem${mem_which}16 tme_m68k_ireg_uint16(TME_M68K_IREG_MEM${cap_mem_which}16)"
110: echo "#define TME_M68K_IREG_MEM${cap_mem_which}8 (${ireg32_next} << 2)"
111: echo "#define tme_m68k_ireg_mem${mem_which}8 tme_m68k_ireg_uint8(TME_M68K_IREG_MEM${cap_mem_which}8)"
112: ireg32_next=`expr ${ireg32_next} + 1`
113: done
114:
115: # the control registers:
1.1.1.2 root 116: for reg in usp isp msp sfc dfc vbr cacr caar; do
1.1 root 117: capreg=`echo $reg | tr a-z A-Z`
118: echo "#define TME_M68K_IREG_${capreg} (${ireg32_next})"
119: echo "#define tme_m68k_ireg_${reg} tme_m68k_ireg_uint32(TME_M68K_IREG_${capreg})"
120: ireg32_next=`expr ${ireg32_next} + 1`
121: done
122:
1.1.1.2 root 123: # this is the count of variable 32-bit registers:
1.1 root 124: echo "#define TME_M68K_IREG32_COUNT (${ireg32_next})"
1.1.1.2 root 125:
126: # the immediate register. there are actually three 32-bit
127: # registers in a row, to allow the fpgen specop to fetch up to a
128: # 96-bit immediate:
129: echo "#define TME_M68K_IREG_IMM32 (${ireg32_next})"
130: echo "#define tme_m68k_ireg_imm32 tme_m68k_ireg_uint32(TME_M68K_IREG_IMM32)"
1.1.1.3 ! root 131: ireg32_next=`expr ${ireg32_next} + 3`
1.1.1.2 root 132:
133: # the effective address register:
134: echo "#define TME_M68K_IREG_EA (${ireg32_next})"
135: echo "#define tme_m68k_ireg_ea tme_m68k_ireg_uint32(TME_M68K_IREG_EA)"
136: ireg32_next=`expr ${ireg32_next} + 1`
137:
138: # the constant registers:
139: for reg in zero one two three four five six seven eight; do
140: capreg=`echo $reg | tr a-z A-Z`
141: echo "#define TME_M68K_IREG_${capreg} (${ireg32_next})"
142: ireg32_next=`expr ${ireg32_next} + 1`
143: done
1.1 root 144: fi
145:
146: # emit the flags->conditions mapping. note that the nesting of the
147: # flag variables is deliberate, to make this array indexable with the
148: # condition code register:
149: if $header; then :; else
150: echo ""
151: echo "/* the flags->conditions mapping: */"
152: echo "const tme_uint16_t _tme_m68k_conditions[32] = {"
153: for xflag in 0 1; do
154: for nflag in 0 1; do
155: for zflag in 0 1; do
156: for vflag in 0 1; do
157: for cflag in 0 1; do
158:
159: # the True condition:
160: echo -n "TME_BIT(TME_M68K_C_T)"
161:
162: # the High condition:
163: if test $cflag != 1 && test $zflag != 1; then
164: echo -n " | TME_BIT(TME_M68K_C_HI)"
165: fi
166:
167: # the Low or Same condition:
168: if test $cflag = 1 || test $zflag = 1; then
169: echo -n " | TME_BIT(TME_M68K_C_LS)"
170: fi
171:
172: # the Carry Clear and Carry Set conditions:
173: if test $cflag != 1; then
174: echo -n " | TME_BIT(TME_M68K_C_CC)"
175: else
176: echo -n " | TME_BIT(TME_M68K_C_CS)"
177: fi
178:
179: # the Not Equal and Equal conditions:
180: if test $zflag != 1; then
181: echo -n " | TME_BIT(TME_M68K_C_NE)"
182: else
183: echo -n " | TME_BIT(TME_M68K_C_EQ)"
184: fi
185:
186: # the Overflow Clear and Overflow Set conditions:
187: if test $vflag != 1; then
188: echo -n " | TME_BIT(TME_M68K_C_VC)"
189: else
190: echo -n " | TME_BIT(TME_M68K_C_VS)"
191: fi
192:
193: # the Plus and Minus conditions:
194: if test $nflag != 1; then
195: echo -n " | TME_BIT(TME_M68K_C_PL)"
196: else
197: echo -n " | TME_BIT(TME_M68K_C_MI)"
198: fi
199:
200: # the Greater or Equal condition:
201: if (test $nflag = 1 && test $vflag = 1) || \
202: (test $nflag != 1 && test $vflag != 1); then
203: echo -n " | TME_BIT(TME_M68K_C_GE)"
204: fi
205:
206: # the Less Than condition:
207: if (test $nflag = 1 && test $vflag != 1) || \
208: (test $nflag != 1 && test $vflag = 1); then
209: echo -n " | TME_BIT(TME_M68K_C_LT)"
210: fi
211:
212: # the Greater Than condition:
213: if (test $nflag = 1 && test $vflag = 1 && test $zflag != 1) || \
214: (test $nflag != 1 && test $vflag != 1 && test $zflag != 1); then
215: echo -n " | TME_BIT(TME_M68K_C_GT)"
216: fi
217:
218: # the Less Than or Equal condition:
219: if test $zflag = 1 || \
220: (test $nflag = 1 && test $vflag != 1) || \
221: (test $nflag != 1 && test $vflag = 1); then
222: echo -n " | TME_BIT(TME_M68K_C_LE)"
223: fi
224:
225: echo ","
226: done
227: done
228: done
229: done
230: done
231: echo "};"
232: fi
233:
234: # emit the instruction word fetch macros:
235: if $header; then
236:
1.1.1.3 ! root 237: # emit the simple signed and unsigned fetch macros:
! 238: #
! 239: echo ""
! 240: echo "/* the simple signed and unsigned fetch macros: */"
! 241:
! 242: # permute over size:
! 243: #
! 244: for size in 16 32; do
! 245:
! 246: # permute for signed or unsigned:
! 247: #
! 248: for capsign in U S; do
! 249: if test $capsign = U; then sign=u ; un=un ; else sign= ; un= ; fi
! 250:
! 251: echo "#define _TME_M68K_EXECUTE_FETCH_${capsign}${size}(v) \\"
! 252: echo " _TME_M68K_EXECUTE_FETCH_${size}(tme_${sign}int${size}_t, v)"
! 253: if test ${size} = 16 && test ${capsign} = U; then
! 254: echo "#define _TME_M68K_EXECUTE_FETCH_${capsign}${size}_FIXED(v, field) \\"
! 255: echo " _TME_M68K_EXECUTE_FETCH_${size}_FIXED(tme_${sign}int${size}_t, v, field)"
! 256: fi
! 257: done
! 258: done
! 259:
1.1 root 260: echo ""
261: echo "#endif /* _IC_M68K_MISC_H */"
262:
263: # permute for the fast vs. slow executors:
264: for executor in fast slow; do
265:
266: echo ""
267: echo -n "#if"
268: if test $executor = slow; then echo -n "n"; fi
269: echo "def _TME_M68K_EXECUTE_FAST"
270: echo ""
271: echo "/* these macros are for the ${executor} executor: */"
272:
1.1.1.3 ! root 273: # permute over size:
! 274: #
! 275: for size in 16 32; do
! 276:
! 277: echo ""
! 278: echo "/* this fetches a ${size}-bit value for the ${executor} executor: */"
! 279: echo "#undef _TME_M68K_EXECUTE_FETCH_${size}"
! 280: echo "#define _TME_M68K_EXECUTE_FETCH_${size}(type, v) \\"
! 281:
! 282: if test $executor = slow; then
! 283:
! 284: # this expression gives the current fetch offset in the instruction:
! 285: #
! 286: offset_fetch="ic->_tme_m68k_insn_fetch_slow_next"
! 287:
! 288: echo " /* macros for the ${executor} executor are simple, because \\"
! 289: echo " tme_m68k_fetch${size}() takes care of all endianness, alignment, \\"
! 290: echo " and atomic issues, and also stores the fetched value in the \\"
! 291: echo " instruction fetch buffer (if a previous fetch before a fault \\"
! 292: echo " didn't store all or part of it there already): */ \\"
! 293: echo " (v) = (type) tme_m68k_fetch${size}(ic, linear_pc); \\"
! 294: echo " linear_pc += sizeof(tme_uint${size}_t)"
! 295:
! 296: else
! 297:
! 298: # this expression gives the current fetch offset in the instruction:
! 299: #
! 300: offset_fetch="(fetch_fast_next - ic->_tme_m68k_insn_fetch_fast_start)"
! 301:
! 302: echo " /* use the raw fetch macro to fetch the value into the variable, \\"
! 303: echo " and then save it in the instruction buffer. the save doesn't \\"
! 304: echo " need to be atomic; no one else can see the instruction buffer. \\"
! 305: echo " however, the raw fetch macro has already advanced fetch_fast_next, \\"
! 306: echo " so we need to compensate for that here: */ \\"
! 307: echo " __TME_M68K_EXECUTE_FETCH_${size}(type, v); \\"
! 308: 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))"
! 309:
! 310: echo ""
! 311: echo "/* this does a raw fetch of a ${size}-bit value for the ${executor} executor: */"
! 312: echo "#undef __TME_M68K_EXECUTE_FETCH_${size}"
! 313: echo "#define __TME_M68K_EXECUTE_FETCH_${size}(type, v) \\"
! 314: echo " /* if we can't do the fast read, we need to redispatch: */ \\"
! 315: echo " /* NB: checks in tme_m68k_go_slow(), and proper setting of \\"
! 316: echo " ic->_tme_m68k_insn_fetch_fast_last in _TME_M68K_EXECUTE_NAME(), \\"
! 317: echo " allow us to do a simple pointer comparison here, for \\"
! 318: echo " any fetch size: */ \\"
! 319: echo " if (__tme_predict_false(fetch_fast_next > ic->_tme_m68k_insn_fetch_fast_last)) \\"
! 320: echo " goto _tme_m68k_fast_fetch_failed; \\"
! 321: echo " (v) = ((type) \\"
! 322: echo " tme_betoh_u${size}(tme_memory_bus_read${size}((const tme_shared tme_uint${size}_t *) fetch_fast_next, \\"
! 323: echo " tlb->tme_m68k_tlb_bus_rwlock, \\"
! 324: echo " sizeof(tme_uint16_t), \\"
! 325: echo " sizeof(tme_uint32_t)))); \\"
! 326: echo " fetch_fast_next += sizeof(tme_uint${size}_t)"
! 327: fi
! 328:
! 329: # if this size doesn't get a fixed fetch macro, continue now:
! 330: #
! 331: if test ${size} != 16; then
! 332: continue
! 333: fi
! 334:
! 335: echo ""
! 336: echo "/* this fetches a ${size}-bit value at a fixed instruction position"
! 337: echo " for the ${executor} executor: */"
! 338: echo "#undef _TME_M68K_EXECUTE_FETCH_${size}_FIXED"
! 339: echo "#define _TME_M68K_EXECUTE_FETCH_${size}_FIXED(type, v, field) \\"
! 340: echo " assert(&((struct tme_m68k *) 0)->field \\"
! 341: echo " == (type *) (((tme_uint8_t *) &((struct tme_m68k *) 0)->_tme_m68k_insn_fetch_buffer[0]) + ${offset_fetch})); \\"
! 342: echo -n " "
! 343: if test ${executor} = fast; then echo -n _ ; fi
! 344: echo "_TME_M68K_EXECUTE_FETCH_${size}(type, v)"
1.1 root 345:
346: done
347:
348: echo ""
349: echo -n "#endif /* "
350: if test $executor = slow; then echo -n "!"; fi
351: echo "_TME_M68K_EXECUTE_FAST */"
352: done
353: fi
354:
355: # done:
356: exit 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.