|
|
1.1 root 1: #! /bin/sh
2:
3: # $Id: m68k-misc-auto.sh,v 1.7 2003/05/10 15:19:00 fredette Exp $
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:
80: # the current and next program counter:
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`
87:
88: # the status register and ccr:
89: echo "#define tme_m68k_ireg_sr tme_m68k_ireg_uint16(${ireg32_next} << 1)"
90: echo "#define tme_m68k_ireg_ccr tme_m68k_ireg_uint8(${ireg32_next} << 2)"
91: ireg32_next=`expr ${ireg32_next} + 1`
92:
93: # the shadow status register and format/offset word:
94: echo "#define TME_M68K_IREG_SHADOW_SR (${ireg32_next} << 1)"
95: echo "#define tme_m68k_ireg_shadow_sr tme_m68k_ireg_uint16(TME_M68K_IREG_SHADOW_SR)"
96: echo "#define TME_M68K_IREG_FORMAT_OFFSET ((${ireg32_next} << 1) + 1)"
97: echo "#define tme_m68k_ireg_format_offset tme_m68k_ireg_uint16(TME_M68K_IREG_FORMAT_OFFSET)"
98: ireg32_next=`expr ${ireg32_next} + 1`
99:
100: # the memory buffers:
101: for mem_which in x y z; do
102: cap_mem_which=`echo ${mem_which} | tr a-z A-Z`
103: echo "#define TME_M68K_IREG_MEM${cap_mem_which}32 (${ireg32_next})"
104: echo "#define tme_m68k_ireg_mem${mem_which}32 tme_m68k_ireg_uint32(TME_M68K_IREG_MEM${cap_mem_which}32)"
105: echo "#define TME_M68K_IREG_MEM${cap_mem_which}16 (${ireg32_next} << 1)"
106: echo "#define tme_m68k_ireg_mem${mem_which}16 tme_m68k_ireg_uint16(TME_M68K_IREG_MEM${cap_mem_which}16)"
107: echo "#define TME_M68K_IREG_MEM${cap_mem_which}8 (${ireg32_next} << 2)"
108: echo "#define tme_m68k_ireg_mem${mem_which}8 tme_m68k_ireg_uint8(TME_M68K_IREG_MEM${cap_mem_which}8)"
109: ireg32_next=`expr ${ireg32_next} + 1`
110: done
111:
112: # the control registers:
113: for reg in usp isp msp sfc dfc vbr; do
114: capreg=`echo $reg | tr a-z A-Z`
115: echo "#define TME_M68K_IREG_${capreg} (${ireg32_next})"
116: echo "#define tme_m68k_ireg_${reg} tme_m68k_ireg_uint32(TME_M68K_IREG_${capreg})"
117: ireg32_next=`expr ${ireg32_next} + 1`
118: done
119:
120: echo "#define TME_M68K_IREG32_COUNT (${ireg32_next})"
121: fi
122:
123: # emit the flags->conditions mapping. note that the nesting of the
124: # flag variables is deliberate, to make this array indexable with the
125: # condition code register:
126: if $header; then :; else
127: echo ""
128: echo "/* the flags->conditions mapping: */"
129: echo "const tme_uint16_t _tme_m68k_conditions[32] = {"
130: for xflag in 0 1; do
131: for nflag in 0 1; do
132: for zflag in 0 1; do
133: for vflag in 0 1; do
134: for cflag in 0 1; do
135:
136: # the True condition:
137: echo -n "TME_BIT(TME_M68K_C_T)"
138:
139: # the High condition:
140: if test $cflag != 1 && test $zflag != 1; then
141: echo -n " | TME_BIT(TME_M68K_C_HI)"
142: fi
143:
144: # the Low or Same condition:
145: if test $cflag = 1 || test $zflag = 1; then
146: echo -n " | TME_BIT(TME_M68K_C_LS)"
147: fi
148:
149: # the Carry Clear and Carry Set conditions:
150: if test $cflag != 1; then
151: echo -n " | TME_BIT(TME_M68K_C_CC)"
152: else
153: echo -n " | TME_BIT(TME_M68K_C_CS)"
154: fi
155:
156: # the Not Equal and Equal conditions:
157: if test $zflag != 1; then
158: echo -n " | TME_BIT(TME_M68K_C_NE)"
159: else
160: echo -n " | TME_BIT(TME_M68K_C_EQ)"
161: fi
162:
163: # the Overflow Clear and Overflow Set conditions:
164: if test $vflag != 1; then
165: echo -n " | TME_BIT(TME_M68K_C_VC)"
166: else
167: echo -n " | TME_BIT(TME_M68K_C_VS)"
168: fi
169:
170: # the Plus and Minus conditions:
171: if test $nflag != 1; then
172: echo -n " | TME_BIT(TME_M68K_C_PL)"
173: else
174: echo -n " | TME_BIT(TME_M68K_C_MI)"
175: fi
176:
177: # the Greater or Equal condition:
178: if (test $nflag = 1 && test $vflag = 1) || \
179: (test $nflag != 1 && test $vflag != 1); then
180: echo -n " | TME_BIT(TME_M68K_C_GE)"
181: fi
182:
183: # the Less Than condition:
184: if (test $nflag = 1 && test $vflag != 1) || \
185: (test $nflag != 1 && test $vflag = 1); then
186: echo -n " | TME_BIT(TME_M68K_C_LT)"
187: fi
188:
189: # the Greater Than condition:
190: if (test $nflag = 1 && test $vflag = 1 && test $zflag != 1) || \
191: (test $nflag != 1 && test $vflag != 1 && test $zflag != 1); then
192: echo -n " | TME_BIT(TME_M68K_C_GT)"
193: fi
194:
195: # the Less Than or Equal condition:
196: if test $zflag = 1 || \
197: (test $nflag = 1 && test $vflag != 1) || \
198: (test $nflag != 1 && test $vflag = 1); then
199: echo -n " | TME_BIT(TME_M68K_C_LE)"
200: fi
201:
202: echo ","
203: done
204: done
205: done
206: done
207: done
208: echo "};"
209: fi
210:
211: # emit the instruction word fetch macros:
212: if $header; then
213:
214: echo ""
215: echo "#endif /* _IC_M68K_MISC_H */"
216:
217: # permute for the fast vs. slow executors:
218: for executor in fast slow; do
219:
220: echo ""
221: echo -n "#if"
222: if test $executor = slow; then echo -n "n"; fi
223: echo "def _TME_M68K_EXECUTE_FAST"
224: echo ""
225: echo "/* these macros are for the ${executor} executor: */"
226:
227: # permute for any-alignment vs. strict-alignment:
228: for alignment in any strict; do
229:
230: # permute for the two different sizes we need to handle:
231: for size in 16 32; do
232:
233: # permute for big-endian vs. little-endian:
234: for endian in little big; do
235:
236: # permute for signed or unsigned:
237: for capsign in U S; do
238: if test $capsign = U; then sign=u ; un=un ; else sign= ; un= ; fi
239:
240: # the slow executor has only one possible
241: # version of each macro, no matter what the
242: # endianness or alignment or atomic requirements
243: # of the host, since the tme_m68k_fetch${size}
244: # functions take care of all of that:
245: if test $executor = slow; then
246: if test $endian = big && test $alignment = any; then
247: echo ""
248: echo "/* on all hosts, this fetches a ${size}-bit ${un}signed value for the slow executor: */"
249: echo "#undef _TME_M68K_EXECUTE_FETCH_${capsign}${size}"
250: echo "#define _TME_M68K_EXECUTE_FETCH_${capsign}${size}(v) \\"
251: echo " (v) = (tme_${sign}int${size}_t) tme_m68k_fetch${size}(ic, linear_pc); \\"
252: if test ${size} = 16; then
253: echo " insn_fetch_sizes <<= 1; \\"
254: else
255: echo " insn_fetch_sizes = (insn_fetch_sizes << 1) | 1; \\"
256: fi
257: echo " linear_pc += sizeof(tme_${sign}int${size}_t)"
258: fi
259: continue
260: fi
261:
262: # assume we'll be universal:
263: macro_comment="ll hosts"
264: macro_test=
265:
266: # if this is a 16-bit fetch:
267: if test $size = 16; then
268:
269: # we don't need a strict alignment version, since
270: # we're guaranteed to be reading from emulator
271: # addresses that are 16-bit aligned - for the fast
272: # executor, tme_m68k_go_slow guarantees that
273: # emulator_load is 16-bit aligned:
274: if test $alignment = strict; then continue; fi
275:
276: # we also don't need a little-endian version, since
277: # the fast macros we emit will always use tme_betoh_u16:
278: if test $endian = little; then continue; fi
279:
280: # if this is a 32-bit fetch:
281: else
282:
283: # while the emulator address we'll be reading
284: # from is 16-bit aligned as explained above,
285: # we still need a strict-alignment version of
286: # the 32-bit fetcher on hosts that require 32-bit
287: # values to be more aligned than 16-bit values.
288: #
289: # on a host that does not have this further
290: # requirement, we also don't need a little-endian
291: # version, since the fast macros we emit will always
292: # use tme_betoh_u32:
293: macro_comment=" host with ${alignment} alignment"
294: if test $alignment = strict; then
295: macro_comment=" ${endian}-endian${macro_comment}"
296: if test ${endian} = little; then macro_test="!"; fi
297: macro_test="(ALIGNOF_INT${size}_T > ALIGNOF_INT16_T) && ${macro_test}defined(WORDS_BIGENDIAN)"
298: else
299: macro_test="ALIGNOF_INT${size}_T <= ALIGNOF_INT16_T"
300: if test ${endian} = little; then continue; fi
301: fi
302: fi
303:
304: # open the macro:
305: echo ""
306: echo "/* on a${macro_comment}, "
307: echo " this loads a ${size}-bit ${un}signed value for the ${executor} instruction executor: */"
308: if test "x${macro_test}" != x; then echo "#if ${macro_test}"; fi
309: echo "#undef _TME_M68K_EXECUTE_FETCH_${capsign}${size}"
310: echo "#define _TME_M68K_EXECUTE_FETCH_${capsign}${size}(v) \\"
311:
312: # assume we'll be converting:
313: conv="tme_betoh_u${size}"
314:
315: # prepare the buffer to read out of:
316: if test ${executor} = fast; then
317:
318: # if we're doing a 32-bit read and the
319: # emulator address is not 32-bit aligned,
320: # on a strict-alignment host we will have
321: # to do a sequence of two 16-bit memory
322: # reads:
323: buffer="emulator_load"
324: misaligned="((unsigned long) emulator_load) & (sizeof(tme_uint32_t) - 1)"
325: update="emulator_load += sizeof(tme_${sign}int${size}_t)"
326:
327: # if we can't do the fast read, bail:
328: echo " if ((emulator_load + (sizeof(tme_uint${size}_t) - 1)) > emulator_load_last) \\"
329: echo " goto _tme_m68k_fast_fetch_failed; \\"
330: fi
331:
332: single="(v) = (tme_${sign}int${size}_t) ${conv}(*((tme_uint${size}_t *) ${buffer}));"
333:
334: # if this is a 16-bit read, the host can always
335: # do a simple assignment.
336: #
337: # we need the rdlock if we're on an architecture
338: # where an aligned access may not be atomic:
339: if test $size = 16; then
340: echo " tme_memory_aligned_rdlock(tlb->tme_m68k_tlb_bus_rwlock); \\"
341: echo " ${single} \\"
342: echo " tme_memory_aligned_unlock(tlb->tme_m68k_tlb_bus_rwlock); \\"
343:
344: # if this is a 32-bit read on an any-alignment host,
345: # do a simple assignment.
346: #
347: # we need the rdlock if this is an aligned access and
348: # we're on an architecture where an aligned access may
349: # not be atomic, or if this is an unaligned access and
350: # we're on an architecture where an unaligned access
351: # may not be atomic:
352: elif test $alignment = any; then
353: echo " if (${misaligned}) { \\"
354: echo " tme_memory_unaligned_rdlock(tlb->tme_m68k_tlb_bus_rwlock); \\"
355: echo " ${single} \\"
356: echo " tme_memory_unaligned_unlock(tlb->tme_m68k_tlb_bus_rwlock); \\"
357: echo " } \\"
358: echo " else { \\"
359: echo " tme_memory_aligned_rdlock(tlb->tme_m68k_tlb_bus_rwlock); \\"
360: echo " ${single} \\"
361: echo " tme_memory_aligned_unlock(tlb->tme_m68k_tlb_bus_rwlock); \\"
362: echo " } \\"
363:
364: # otherwise, this is a 32-bit read on a strict-alignment
365: # host.
366: #
367: # if doing a sequence access is not costlier than deciding
368: # whether to do a sequence or aligned access and then doing
369: # the chosen access, or if the buffer is misaligned,
370: # acquire the rdlock for a sequence and do the sequence
371: # of reads, else acquire the rdlock for an aligned access
372: # and do the single read:
373: else
374: echo " if (TME_SEQUENCE_ACCESS_NOT_COSTLIER || ${misaligned}) { \\";
375: if test $endian = little; then
376: word_lo=0 ; word_hi=1 ;
377: else
378: word_lo=1 ; word_hi=0 ; conv=
379: fi
380: echo " tme_memory_sequence_rdlock(tlb->tme_m68k_bus_tlb_rwlock); \\"
381: echo " (v) = (tme_${sign}int${size}_t) \\"
382: echo " ${conv}((((tme_uint32_t) ((tme_uint16_t *) ${buffer})[${word_hi}]) << 16) | \\"
383: echo " ((tme_uint32_t) ((tme_uint16_t *) ${buffer})[${word_lo}])); \\"
384: echo " tme_memory_sequence_unlock(tlb->tme_m68k_bus_tlb_rwlock); \\"
385: echo " } else { \\"
386: echo " tme_memory_aligned_rdlock(tlb->tme_m68k_tlb_bus_rwlock); \\"
387: echo " ${single} \\"
388: echo " tme_memory_aligned_unlock(tlb->tme_m68k_tlb_bus_rwlock); \\"
389: echo " } \\"
390: fi
391:
392: # remember if we did a 16-bit or 32-bit fetch, and update:
393: if test ${size} = 16; then
394: echo " insn_fetch_sizes <<= 1; \\"
395: else
396: echo " insn_fetch_sizes = (insn_fetch_sizes << 1) | 1; \\"
397: fi
398: echo " ${update}"
399:
400: # close the conditional:
401: if test "x${macro_test}" != x; then echo "#endif /* ${macro_test} */"; fi
402: done
403: done
404: done
405: done
406:
407: echo ""
408: echo -n "#endif /* "
409: if test $executor = slow; then echo -n "!"; fi
410: echo "_TME_M68K_EXECUTE_FAST */"
411: done
412: fi
413:
414: # done:
415: exit 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.