Annotation of tme/ic/m68k/m68k-misc-auto.sh, revision 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.