Annotation of tme/ic/m68k/m68k-misc-auto.sh, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.