|
|
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.