Annotation of tme/ic/m68k/m68k-insns-auto.sh, revision 1.1

1.1     ! root        1: #! /bin/sh
        !             2: 
        !             3: # $Id: m68k-insns-auto.sh,v 1.19 2003/05/16 21:48:11 fredette Exp $
        !             4: 
        !             5: # ic/m68k/m68k-insns-auto.sh - automatically generates C code 
        !             6: # for many m68k emulation instructions:
        !             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: _TME_RCSID("\$Id: m68k-insns-auto.sh,v 1.19 2003/05/16 21:48:11 fredette Exp $");
        !            52: 
        !            53: EOF
        !            54: if $header; then :; else
        !            55:     cat <<EOF
        !            56: #include "m68k-impl.h"
        !            57: 
        !            58: EOF
        !            59: fi
        !            60: 
        !            61: # permute for the three different operand sizes we need to handle:
        !            62: for size in 8 16 32; do
        !            63:     
        !            64:     # the shifts needed to get register contents of a specific size:
        !            65:     case ${size} in
        !            66:     8)  reg_size_shift=' << 2' ;;
        !            67:     16) reg_size_shift=' << 1' ;;
        !            68:     32) reg_size_shift='' ;;
        !            69:     esac
        !            70: 
        !            71:     # generate the ALU functions:
        !            72:     for name in add sub cmp neg or and eor not tst move moveq clr cmpa negx addx subx cmpm; do
        !            73: 
        !            74:        # characterize each operation:
        !            75:        optype=normal ; src=op0 ; dst=op1 ; res=op1 ; arith=no ; with_x=false ; store_res=true
        !            76:        case "$name" in
        !            77:        add) op=' + ' ; arith=add ;;
        !            78:        sub) op=' - ' ; arith=sub ;;
        !            79:        cmp) op=' - ' ; arith=sub ; store_res=false ;;
        !            80:        neg) op=' - ' ; arith=sub ; dst=0 ; src=op1 ;;
        !            81:        or)  op=' | ' ;;
        !            82:        and) op=' & ' ;;
        !            83:        eor) op=' ^ ' ;;
        !            84:        not) op='~ ' ; dst= ; src=op1 ;;
        !            85:        tst) op='' ; dst= ; src=op1 ; store_res=false ;;
        !            86:        move) op='' ; dst= ; src=op1 ; res=op0 ;;
        !            87:        moveq) op='' ; dst= ; src=opc8 ; if test ${size} != 32; then continue; fi ;;
        !            88:        clr) op='' ; dst= ; src=0 ;; 
        !            89:        cmpa) op=' - ' ; arith=sub ; src=op0.16s32 ; store_res=false
        !            90:            if test $size != 16; then continue; fi ;;
        !            91:        negx) op=' - ' ; arith=sub ; with_x=true ; dst=0 ; src=op1 ;;
        !            92:        addx) op=' + ' ; arith=add ; optype=mathx ; with_x=true ;;
        !            93:        subx) op=' - ' ; arith=sub ; optype=mathx ; with_x=true ;;
        !            94:        cmpm) op=' - ' ; arith=sub ; optype=mathx ; store_res=false ;;
        !            95:        *) echo "$0 internal error: unknown ALU function $name" 1>&2 ; exit 1 ;;
        !            96:        esac
        !            97: 
        !            98:        # placeholder for another permutation:
        !            99:        :
        !           100: 
        !           101:            # if we're making the header, just emit a declaration:
        !           102:            if $header; then
        !           103:                echo "TME_M68K_INSN_DECL(tme_m68k_${name}${size});"
        !           104:                continue
        !           105:            fi
        !           106: 
        !           107:            # open the function:
        !           108:            echo ""
        !           109:            echo -n "/* this does a ${size}-bit \"$name "
        !           110:            case "${src}/${dst}" in *op0*) echo -n "SRC, " ;; esac
        !           111:            echo "DST\": */"
        !           112:            echo "TME_M68K_INSN(tme_m68k_${name}${size})"
        !           113:            echo "{"
        !           114: 
        !           115:            # declare our locals:
        !           116:            if test $name = cmpa; then size=32; fi
        !           117:            echo -n "  tme_uint${size}_t res"
        !           118:            case "${src}/${dst}" in *op0*) echo -n ", op0" ;; esac
        !           119:            case "${src}/${dst}" in *op1*) echo -n ", op1" ;; esac
        !           120:            echo ";"
        !           121:            echo "  tme_uint8_t flags;"
        !           122: 
        !           123:            # load the operand(s):
        !           124:            echo ""
        !           125:            echo "  /* load the operand(s): */"
        !           126:            case ${optype} in
        !           127:            mathx)
        !           128:                echo "  unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic);"
        !           129: 
        !           130:                # NB: in my 68000 Programmer's Manual, the description
        !           131:                # of subx is a little backwards from addx and cmpm. in
        !           132:                # subx, the reg field at bits 0-2 is called the "x"
        !           133:                # field, where in addx and cmpm it's called the "y"
        !           134:                # field, and similarly for the reg field at bits 9-11.
        !           135:                # fortunately, the meanings of the two reg fields is
        !           136:                # always the same despite this - the reg field at bits
        !           137:                # 0-2 always identifies the source operand, and the
        !           138:                # reg field at bits 9-11 always identifies the
        !           139:                # destination operand:
        !           140:                echo "  int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);"
        !           141:                echo "  int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);"
        !           142: 
        !           143:                # the stack pointer must always be adjusted by a multiple of two.
        !           144:                # assuming ireg < 8, ((ireg + 1) >> 3) == 1 iff ireg == 7, meaning %a7:
        !           145:                echo -n "  tme_uint32_t ireg_src_adjust = sizeof(tme_uint${size}_t)";
        !           146:                if test ${size} = 8; then
        !           147:                    echo -n " + ((ireg_src + 1) >> 3)"
        !           148:                fi
        !           149:                echo ";"
        !           150:                echo -n "  tme_uint32_t ireg_dst_adjust = sizeof(tme_uint${size}_t)";
        !           151:                if test ${size} = 8; then
        !           152:                    echo -n " + ((ireg_dst + 1) >> 3)"
        !           153:                fi
        !           154:                echo ";"
        !           155: 
        !           156:                case ${name} in
        !           157: 
        !           158:                # cmpm always uses memory and is always postincrement:
        !           159:                cmpm)
        !           160:                    echo ""
        !           161:                    echo "  TME_M68K_INSN_CANFAULT;"
        !           162:                    echo ""
        !           163:                    echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !           164:                    echo "    ic->_tme_m68k_ea_function_code = function_code;"
        !           165:                    echo "    ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);"
        !           166:                    echo "    ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) += ireg_dst_adjust;"
        !           167:                    echo "  }"
        !           168:                    echo "  tme_m68k_read_memx${size}(ic);"
        !           169:                    echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !           170:                    echo "    ic->_tme_m68k_ea_function_code = function_code;"
        !           171:                    echo "    ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src);"
        !           172:                    echo "    ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) += ireg_src_adjust;"
        !           173:                    echo "  }"
        !           174:                    echo "  tme_m68k_read_mem${size}(ic, TME_M68K_IREG_MEMY${size});"
        !           175:                    echo "  ${dst} = ic->tme_m68k_ireg_memx${size};"
        !           176:                    echo "  ${src} = ic->tme_m68k_ireg_memy${size};"
        !           177:                    ;;
        !           178: 
        !           179:                # addx and subx use either registers or memory.  if they use memory,
        !           180:                # they always predecrement:
        !           181:                addx|subx)
        !           182:                    echo "  tme_uint16_t memory;"
        !           183:                    echo ""
        !           184:                    echo "  memory = (TME_M68K_INSN_OPCODE & TME_BIT(3));"
        !           185:                    echo "  if (memory) {"
        !           186:                    echo "    TME_M68K_INSN_CANFAULT;"
        !           187:                    echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !           188:                    echo "      ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) -= ireg_dst_adjust;"
        !           189:                    echo "      ic->_tme_m68k_ea_function_code = function_code;"
        !           190:                    echo "      ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);"
        !           191:                    echo "    }"
        !           192:                    echo "    tme_m68k_read_memx${size}(ic);"
        !           193:                    echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !           194:                    echo "      ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) -= ireg_src_adjust;"
        !           195:                    echo "      ic->_tme_m68k_ea_function_code = function_code;"
        !           196:                    echo "      ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src);"
        !           197:                    echo "    }"
        !           198:                    echo "    tme_m68k_read_mem${size}(ic, TME_M68K_IREG_MEMY${size});"
        !           199:                    echo "    ${dst} = ic->tme_m68k_ireg_memx${size};"
        !           200:                    echo "    ${src} = ic->tme_m68k_ireg_memy${size};"
        !           201:                    echo "  }"
        !           202:                    echo "  else {"
        !           203:                    echo "    ${src} = ic->tme_m68k_ireg_uint${size}((TME_M68K_IREG_D0 + ireg_src)${reg_size_shift});"
        !           204:                    echo "    ${dst} = ic->tme_m68k_ireg_uint${size}((TME_M68K_IREG_D0 + ireg_dst)${reg_size_shift});"
        !           205:                    echo "  }"
        !           206:                    ;;
        !           207:                *) echo "$0 internal error: unknown mathx ${name}" 1>&2 ; exit 1 ;;
        !           208:                esac
        !           209:                ;;
        !           210:            normal)
        !           211:                for which in src dst; do
        !           212:                    eval 'what=$'${which}
        !           213:                    case "x${what}" in
        !           214:                    x|x0) ;;
        !           215:                    xop[01].16s32)
        !           216:                        what=`echo ${what} | sed -e 's/\..*//'`
        !           217:                        eval ${which}"=${what}"
        !           218:                        echo "  ${what} = (tme_uint32_t) ((tme_int32_t) *((tme_int16_t *) _${what}));"
        !           219:                        ;;
        !           220:                    xop[01])
        !           221:                        echo "  ${what} = *((tme_uint${size}_t *) _${what});"
        !           222:                        ;;
        !           223:                    xopc8)
        !           224:                        eval ${which}"='TME_EXT_S8_U${size}((tme_int8_t) (TME_M68K_INSN_OPCODE & 0xff))'"
        !           225:                        ;;
        !           226:                    *) echo "$0 internal error: unknown what ${what}" 1>&2 ; exit 1 ;;
        !           227:                    esac
        !           228:                done
        !           229:                ;;
        !           230:            *) echo "$0 internal error: unknown optype ${optype}" 1>&2 ; exit 1 ;;
        !           231:            esac
        !           232: 
        !           233:            # perform the operation:
        !           234:            echo ""
        !           235:            echo "  /* perform the operation: */"
        !           236:            echo -n "  res = ${dst}${op}${src}"
        !           237:            if $with_x; then
        !           238:                echo -n "${op}((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1)"
        !           239:            fi
        !           240:            echo ";"
        !           241: 
        !           242:            # store the result:
        !           243:            if $store_res; then
        !           244:                echo ""
        !           245:                echo "  /* store the result: */"
        !           246:                case ${optype} in
        !           247:                mathx)
        !           248:                    echo "  if (memory) {"
        !           249:                    echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !           250:                    echo "      ic->tme_m68k_ireg_memx${size} = res;"
        !           251:                    echo "      ic->_tme_m68k_ea_function_code = function_code;"
        !           252:                    echo "      ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);"
        !           253:                    echo "    }"
        !           254:                    echo "    tme_m68k_write_memx${size}(ic);"
        !           255:                    echo "  }"
        !           256:                    echo "  else {"
        !           257:                    echo "    ic->tme_m68k_ireg_uint${size}((TME_M68K_IREG_D0 + ireg_dst)${reg_size_shift}) = res;"
        !           258:                    echo "  }"
        !           259:                    ;;
        !           260:                normal)
        !           261:                    echo "  *((tme_uint${size}_t *) _${res}) = res;"
        !           262:                    ;;
        !           263:                *) echo "$0 internal error: unknown optype ${optype}" 1>&2 ; exit 1 ;;
        !           264:                esac
        !           265:            fi
        !           266: 
        !           267:            # start the status flags, maybe preserving X:
        !           268:            echo ""
        !           269:            echo "  /* set the flags: */"
        !           270:            case "${name}:${arith}" in
        !           271:            cmp*|*:no)
        !           272:                flag_x=
        !           273:                ;;
        !           274:            *)
        !           275:                flag_x=" | TME_M68K_FLAG_X"
        !           276:                ;;
        !           277:            esac
        !           278: 
        !           279:            # set N.  we cast to tme_uint8_t as soon as we know the
        !           280:            # bit we want is within the range of the type, to try
        !           281:            # to affect the generated assembly:
        !           282:            echo "  flags = ((tme_uint8_t) (((tme_uint${size}_t) res) >> (${size} - 1))) * TME_M68K_FLAG_N;"
        !           283:            
        !           284:            # set Z:
        !           285:            if $with_x; then
        !           286:                echo "  if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z);"
        !           287:            else
        !           288:                echo "  if (res == 0) flags |= TME_M68K_FLAG_Z;"
        !           289:            fi
        !           290: 
        !           291:            # set V and C and maybe X:
        !           292:            case $arith in
        !           293:            add)
        !           294:                case $size in
        !           295:                8) ones="0xff" ;;
        !           296:                16) ones="0xffff" ;;
        !           297:                32) ones="0xffffffff" ;;
        !           298:                esac
        !           299:                # if the operands are the same sign, and the result has
        !           300:                # a different sign, set V.   we cast to tme_uint8_t as 
        !           301:                # soon as we know the bit we want is within the range 
        !           302:                # of the type, to try to affect the generated assembly:
        !           303:                echo "  flags |= ((tme_uint8_t) (((${src} ^ ${dst} ^ ${ones}) & (${dst} ^ res)) >> (${size} - 1))) * TME_M68K_FLAG_V;"
        !           304:                # if src is greater than the logical inverse of dst, set C:
        !           305:                echo -n "  if (${src} > (${dst} ^ ${ones})"
        !           306:                if $with_x; then
        !           307:                    echo -n " || (${src} == (${dst} ^ ${ones}) && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))"
        !           308:                fi
        !           309:                echo ") flags |= TME_M68K_FLAG_C${flag_x};"
        !           310:                ;;
        !           311:            sub) 
        !           312:                # if the operands are different signs, and the result has
        !           313:                # a different sign from the first operand, set V.  we
        !           314:                # cast to tme_uint8_t as soon as we know the bit we want
        !           315:                # is within the range of the type, to try to affect the
        !           316:                # generated assembly:
        !           317:                echo "  flags |= ((tme_uint8_t) (((${src} ^ ${dst}) & (${dst} ^ res)) >> (${size} - 1))) * TME_M68K_FLAG_V;"
        !           318:                # if src is greater than dst, set C:
        !           319:                echo -n "  if (${src} > ${dst}"
        !           320:                if $with_x; then
        !           321:                    echo -n " || (${src} == ${dst} && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))"
        !           322:                fi
        !           323:                echo ") flags |= TME_M68K_FLAG_C${flag_x};"
        !           324:                ;;
        !           325:            no) ;;
        !           326:            esac
        !           327: 
        !           328:            # preserve X:
        !           329:            if test "x${flag_x}" = x; then
        !           330:                echo "  flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);"
        !           331:            fi
        !           332: 
        !           333:            # set the flags:
        !           334:            echo "  ic->tme_m68k_ireg_ccr = flags;"
        !           335:            
        !           336:            # done:
        !           337:            echo ""
        !           338:            echo "  TME_M68K_INSN_OK;"
        !           339:            echo "}"
        !           340: 
        !           341:            if test $name = cmpa; then size=16; fi
        !           342:     done
        !           343: 
        !           344:     # generate the address math functions:
        !           345:     for name in suba adda movea; do
        !           346: 
        !           347:        # the address math functions don't need an 8-bit version:
        !           348:        if test $size = 8; then continue; fi
        !           349: 
        !           350:        # if we're making the header, just emit a declaration:
        !           351:        if $header; then
        !           352:            echo "TME_M68K_INSN_DECL(tme_m68k_${name}${size});"
        !           353:            continue
        !           354:        fi
        !           355: 
        !           356:        echo ""
        !           357:        echo "/* the ${name} function on a ${size}-byte EA: */"
        !           358:        echo "TME_M68K_INSN(tme_m68k_${name}${size})"
        !           359:        echo "{"
        !           360:        case $name in
        !           361:        suba) op='-' ; src="_op0" ; dst="_op1" ;;
        !           362:        adda) op='+' ; src="_op0" ; dst="_op1" ;;
        !           363:        movea) op='' ; src="_op1" ; dst="_op0" ;;
        !           364:        esac
        !           365:        echo "  *((tme_int32_t *) ${dst}) ${op}= *((tme_int${size}_t *) ${src});"
        !           366:        echo "  TME_M68K_INSN_OK;"
        !           367:        echo "}"
        !           368:     done
        !           369:            
        !           370:     # generate the bit functions:
        !           371:     for name in btst bchg bclr bset; do
        !           372:        
        !           373:        # the bit functions don't need a 16-bit version:
        !           374:        if test $size = 16; then continue; fi
        !           375: 
        !           376:        # if we're making the header, just emit a declaration:
        !           377:        if $header; then
        !           378:            echo "TME_M68K_INSN_DECL(tme_m68k_${name}${size});"
        !           379:            continue
        !           380:        fi
        !           381: 
        !           382:        echo ""
        !           383:        echo "/* the ${name} function on a ${size}-byte EA: */"
        !           384:        echo "TME_M68K_INSN(tme_m68k_${name}${size})"
        !           385:        echo "{"
        !           386:        echo "  tme_uint${size}_t value, bit;"
        !           387:        echo "  bit = _TME_BIT(tme_uint${size}_t, TME_M68K_INSN_OP0(tme_uint8_t) & (${size} - 1));"
        !           388:        echo "  value = TME_M68K_INSN_OP1(tme_uint${size}_t);"
        !           389:        echo "  if (value & bit) {"
        !           390:        echo "    ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z;"
        !           391:        echo "  }"
        !           392:        echo "  else {"
        !           393:        echo "    ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z;"
        !           394:        echo "  }"
        !           395:        case ${name} in
        !           396:        btst) ;;
        !           397:        bchg) echo "  TME_M68K_INSN_OP1(tme_uint${size}_t) = value ^ bit;" ;;
        !           398:        bclr) echo "  TME_M68K_INSN_OP1(tme_uint${size}_t) = value & ~bit;" ;;
        !           399:        bset) echo "  TME_M68K_INSN_OP1(tme_uint${size}_t) = value | bit;" ;;
        !           400:        esac
        !           401:        echo "  TME_M68K_INSN_OK;"
        !           402:        echo "}"
        !           403:     done
        !           404: 
        !           405:     # generate the shift/rotate functions:
        !           406:     for func in as ls ro rox; do
        !           407:        for dir in l r; do
        !           408:            name="${func}${dir}"
        !           409: 
        !           410:            # if we're making the header, just emit a declaration:
        !           411:            if $header; then
        !           412:                echo "TME_M68K_INSN_DECL(tme_m68k_${name}${size});"
        !           413:                continue
        !           414:            fi
        !           415: 
        !           416:            echo ""
        !           417:            echo "/* the ${name} function on a ${size}-byte EA: */"
        !           418:            echo "TME_M68K_INSN(tme_m68k_${name}${size})"
        !           419:            echo "{"
        !           420:            echo "  unsigned int count;"
        !           421:            sign=u
        !           422:            case "${name}" in
        !           423:            asr) sign= ;;
        !           424:            asl) echo "  tme_uint${size}_t sign_bits;" ;;
        !           425:            rox[lr]) echo "  tme_uint8_t xbit;" ;;
        !           426:            *) ;;
        !           427:            esac
        !           428:            echo "  tme_${sign}int${size}_t res;"
        !           429:            echo "  tme_uint8_t flags;"
        !           430:            echo ""
        !           431:            echo "  /* get the count and operand: */"
        !           432:            echo "  count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;"
        !           433:            echo "  res = TME_M68K_INSN_OP1(tme_${sign}int${size}_t);"
        !           434: 
        !           435:            echo ""
        !           436:            echo "  /* generate the X, V, and C flags assuming the count is zero: */"
        !           437:            echo "  flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;"
        !           438:            case "${name}" in
        !           439:            rox[lr])
        !           440:                echo "  xbit = (flags / TME_M68K_FLAG_X);"
        !           441:                echo "  flags |= (xbit * TME_M68K_FLAG_C);"
        !           442:                ;;
        !           443:            esac
        !           444: 
        !           445:            echo ""
        !           446:            echo "  /* if the count is nonzero, update the result and"
        !           447:            echo "     generate the X, V, and C flags: */"
        !           448:            echo "  if (count > 0) {"
        !           449:            case "${name}" in
        !           450:            [al]sr)
        !           451:                echo "    if (63 > SHIFTMAX_INT${size}_T"
        !           452:                echo "        && count > ${size}) {"
        !           453:                echo "      res = 0;"
        !           454:                echo "    }"
        !           455:                echo "    res >>= (count - 1);"
        !           456:                echo "    flags = (res & 1);"
        !           457:                echo "    flags *= TME_M68K_FLAG_C;"
        !           458:                echo "    flags |= (flags * TME_M68K_FLAG_X);"
        !           459:                echo "    res >>= 1;"
        !           460:                ;;
        !           461:            [al]sl)
        !           462:                if test ${name} = asl; then
        !           463:                    echo ""
        !           464:                    echo "    /* we need to see how the sign of the result will change during"
        !           465:                    echo "       shifting in order to generate V."
        !           466:                    echo ""
        !           467:                    echo "       in general, the idea is to get all of the bits that will ever"
        !           468:                    echo "       appear in the sign position into sign_bits; if sign_bits is"
        !           469:                    echo "       all-bits-one or all-bits zero, clear V, else set V.  a good trick"
        !           470:                    echo "       is that ((sign_bits + 1) & sign_bits) is nonzero iff all of the"
        !           471:                    echo "       bits in sign_bits are the same."
        !           472:                    echo ""
        !           473:                    echo "       start by loading all of the operand into sign_bits."
        !           474:                    echo ""
        !           475:                    echo "       if the shift count is exactly ${size} - 1, then all of the bits"
        !           476:                    echo "       of the operand will appear in the sign position."
        !           477:                    echo ""
        !           478:                    echo "       if the shift count is less than ${size} - 1, then some of the"
        !           479:                    echo "       less significant bits of the operand will never appear in the"
        !           480:                    echo "       sign position, so we can shift them off of sign_bits now."
        !           481:                    echo ""
        !           482:                    echo "       if the shift count is greater than ${size} - 1, then all of the"
        !           483:                    echo "       bits in the operand, plus at least one zero bit, will appear in"
        !           484:                    echo "       the sign position.  the only way that the sign bit will never"
        !           485:                    echo "       change during the shift is if the operand was zero to begin with."
        !           486:                    echo "       we need to change sign_bits such that ((sign_bits + 1) &"
        !           487:                    echo "       sign_bits) will be zero iff the operand was zero to begin with."
        !           488:                    echo "       the magic below does just that: */"
        !           489:                    echo "    sign_bits = res;"
        !           490:                fi
        !           491:                echo "    if (63 > SHIFTMAX_INT${size}_T"
        !           492:                echo "        && count > ${size}) {"
        !           493:                echo "      res = 0;"
        !           494:                echo "    }"
        !           495:                echo "    res <<= (count - 1);"
        !           496:                echo "    flags = (res >> (${size} - 1));"
        !           497:                echo "    flags *= TME_M68K_FLAG_C;"
        !           498:                echo "    flags |= (flags * TME_M68K_FLAG_X);"
        !           499:                echo "    res <<= 1;"
        !           500:                if test ${name} = asl; then             
        !           501:                    echo "    if (count != ${size} - 1) {"
        !           502:                    echo "      if (count < ${size}) {"
        !           503:                    echo "        sign_bits >>= ((${size} - 1) - count);"
        !           504:                    echo "      }"
        !           505:                    echo "      else {"
        !           506:                    echo "        sign_bits |= (sign_bits << 1);"
        !           507:                    echo "        sign_bits &= -2;"
        !           508:                    echo "      }"
        !           509:                    echo "    }"                    
        !           510:                    echo "    if ((sign_bits + 1) & sign_bits) {"
        !           511:                    echo "      flags |= TME_M68K_FLAG_V;"
        !           512:                    echo "    }"
        !           513:                fi
        !           514:                ;;
        !           515:            ro[lr])
        !           516:                echo "    count &= (${size} - 1);"
        !           517:                if test $dir = l; then
        !           518:                    echo "    res = (res << count) | (res >> (${size} - count));"
        !           519:                    echo "    flags |= ((res & 1) * TME_M68K_FLAG_C);"
        !           520:                else
        !           521:                    echo "    res = (res << (${size} - count)) | (res >> count);"
        !           522:                    echo "    flags |= ((res >> (${size} - 1)) * TME_M68K_FLAG_C);"
        !           523:                fi
        !           524:                ;;
        !           525:            rox[lr])
        !           526:                echo "    count %= (${size} + 1);"
        !           527:                echo "    flags = xbit;"
        !           528:                echo "    if (count > 0) {"
        !           529:                if test $dir = l; then
        !           530:                    echo "      flags = (res >> (${size} - count)) & 1;"
        !           531:                    echo "      if (${size} > SHIFTMAX_INT${size}_T"
        !           532:                    echo "          && count == ${size}) {"
        !           533:                    echo "        res = 0 | (xbit << (${size} - 1)) | (res >> ((${size} + 1) - ${size}));"
        !           534:                    echo "      }"
        !           535:                    echo "      else if (${size} > SHIFTMAX_INT${size}_T"
        !           536:                    echo "               && count == 1) {"
        !           537:                    echo "        res = (res << 1) | (xbit << (1 - 1)) | 0;"
        !           538:                    echo "      }"
        !           539:                    echo "      else {"
        !           540:                    echo "        res = (res << count) | (xbit << (count - 1)) | (res >> ((${size} + 1) - count));"
        !           541:                    echo "      }"
        !           542:                else
        !           543:                    echo "      flags = (res >> (count - 1)) & 1;"
        !           544:                    echo "      if (${size} > SHIFTMAX_INT${size}_T"
        !           545:                    echo "          && count == ${size}) {"
        !           546:                    echo "        res = (res << ((${size} + 1) - ${size})) | (xbit << (${size} - ${size})) | 0;"
        !           547:                    echo "      }"
        !           548:                    echo "      else if (${size} > SHIFTMAX_INT${size}_T"
        !           549:                    echo "               && count == 1) {"
        !           550:                    echo "        res = 0 | (xbit << (${size} - 1)) | (res >> 1);"
        !           551:                    echo "      }"
        !           552:                    echo "      else {"
        !           553:                    echo "        res = (res << ((${size} + 1) - count)) | (xbit << (${size} - count)) | (res >> count);"
        !           554:                    echo "      }"
        !           555:                fi
        !           556:                echo "    }"
        !           557:                echo "    flags *= TME_M68K_FLAG_C;"
        !           558:                echo "    flags |= (flags * TME_M68K_FLAG_X);"
        !           559:                ;;
        !           560:            esac
        !           561:                echo "  }"
        !           562: 
        !           563:            echo ""
        !           564:            echo "  /* store the result: */"
        !           565:            echo "  TME_M68K_INSN_OP1(tme_${sign}int${size}_t) = res;"
        !           566: 
        !           567:            echo ""
        !           568:            echo "  /* generate the N flag.  we cast to tme_uint8_t as soon as we"
        !           569:            echo "     know the bit we want is within the range of the type, to try"
        !           570:            echo "     to affect the generated assembly: */"
        !           571:            echo "  flags |= ((tme_uint8_t) (((tme_uint${size}_t) res) >> (${size} - 1))) * TME_M68K_FLAG_N;"
        !           572:            
        !           573:            echo ""
        !           574:            echo "  /* generate the Z flag: */"
        !           575:            echo "  if (res == 0) flags |= TME_M68K_FLAG_Z;"
        !           576: 
        !           577:            echo ""
        !           578:            echo "  /* store the flags: */"
        !           579:            echo "  ic->tme_m68k_ireg_ccr = flags;"
        !           580:            echo "  TME_M68K_INSN_OK;"
        !           581:            echo "}"
        !           582:        done
        !           583:     done
        !           584: 
        !           585:     # movep_rm, movep_mr, movem_rm, and movem_mr:
        !           586:     for name in rm mr; do
        !           587:     
        !           588:        # movep and movem don't need 8-bit versions:
        !           589:        if test ${size} = 8; then continue; fi
        !           590: 
        !           591:        # if we're making the header, just emit declarations:
        !           592:        if $header; then
        !           593:            echo "TME_M68K_INSN_DECL(tme_m68k_movep_${name}${size});"
        !           594:            echo "TME_M68K_INSN_DECL(tme_m68k_movem_${name}${size});"
        !           595:            continue
        !           596:        fi
        !           597: 
        !           598:        # emit the movep function:
        !           599:        echo ""
        !           600:        echo "/* the movep_${name} function on a ${size}-bit dreg: */"
        !           601:        echo "TME_M68K_INSN(tme_m68k_movep_${name}${size})"
        !           602:        echo "{"
        !           603:        echo "  unsigned int function_code;"
        !           604:        echo "  tme_uint32_t linear_address;"
        !           605:        if test $name = rm; then
        !           606:            echo "  tme_uint${size}_t value;"
        !           607:        fi
        !           608:        echo "  int dreg;"
        !           609:        echo ""
        !           610:        echo "  TME_M68K_INSN_CANFAULT;"
        !           611:        echo ""
        !           612:        echo "  function_code = TME_M68K_FUNCTION_CODE_DATA(ic);"
        !           613:        echo "  linear_address = TME_M68K_INSN_OP1(tme_uint32_t);"
        !           614:        echo "  linear_address += (tme_int32_t) ((tme_int16_t) TME_M68K_INSN_SPECOP);"
        !           615:        echo "  dreg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);"
        !           616: 
        !           617:        # set value:
        !           618:        if test $name = rm; then
        !           619:            echo "  value = ic->tme_m68k_ireg_uint${size}(dreg${reg_size_shift});"
        !           620:             value="value"
        !           621:         else
        !           622:             value="ic->tme_m68k_ireg_uint${size}(dreg${reg_size_shift})"
        !           623:        fi
        !           624:        
        !           625:        # transfer the bytes:
        !           626:        pos=${size}
        !           627:        while test $pos != 0; do
        !           628:            pos=`expr ${pos} - 8`
        !           629:            echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !           630:            echo "    ic->_tme_m68k_ea_function_code = function_code;"
        !           631:            echo "    ic->_tme_m68k_ea_address = linear_address;"
        !           632:            if test $name = rm; then
        !           633:                echo "    ic->tme_m68k_ireg_memx8 = TME_FIELD_EXTRACTU(${value}, ${pos}, 8);"
        !           634:                echo "  }"
        !           635:                echo "  tme_m68k_write_memx8(ic);"
        !           636:            else
        !           637:                echo "  }"
        !           638:                echo "  tme_m68k_read_memx8(ic);"
        !           639:                echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !           640:                echo "    TME_FIELD_DEPOSIT${size}(${value}, ${pos}, 8, ic->tme_m68k_ireg_memx8);"
        !           641:                echo "  }"
        !           642:            fi
        !           643:            echo "  linear_address += 2;"
        !           644:        done
        !           645: 
        !           646:        echo "  TME_M68K_INSN_OK;"
        !           647:        echo "}"
        !           648: 
        !           649:        # emit the movem function:
        !           650:        echo ""
        !           651:        echo "/* the movem_${name} function on ${size}-bit registers: */"
        !           652:        echo "TME_M68K_INSN(tme_m68k_movem_${name}${size})"
        !           653:        echo "{"
        !           654:        echo "  int ireg, direction;"
        !           655:        echo "  tme_uint16_t mask, bit;"
        !           656:        echo "  unsigned int ea_mode;"
        !           657:        echo "  tme_uint32_t addend;"
        !           658: 
        !           659:        echo ""
        !           660:        echo "  TME_M68K_INSN_CANFAULT;"
        !           661:        echo ""
        !           662:        echo "  /* figure out what direction to move in, and where to start from: */"
        !           663:        echo "  ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3);"
        !           664:        echo "  direction = 1;"
        !           665:        echo "  ireg = TME_M68K_IREG_D0;"
        !           666:        if test $name = rm; then
        !           667:            echo "  if (ea_mode == 4) {"
        !           668:            echo "    direction = -1;"
        !           669:            echo "    ireg = TME_M68K_IREG_A7;"
        !           670:            echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !           671:            echo "      ic->_tme_m68k_ea_address -= sizeof(tme_uint${size}_t);"
        !           672:            echo "    }"
        !           673:            echo "  }"
        !           674:        fi
        !           675:        echo "  addend = (tme_uint32_t) (direction * sizeof(tme_uint${size}_t));"
        !           676: 
        !           677:        echo ""
        !           678:        echo "  /* do the transfer: */"
        !           679:        echo "  mask = TME_M68K_INSN_SPECOP;"
        !           680:        echo "  for (bit = 1; bit != 0; bit <<= 1) {"
        !           681:        echo "    if (mask & bit) {"
        !           682:        if test $name = rm; then
        !           683:            echo "      if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !           684:            echo "        ic->tme_m68k_ireg_memx${size} = ic->tme_m68k_ireg_uint${size}(ireg${reg_size_shift});"
        !           685:            echo "      }"
        !           686:            echo "      tme_m68k_write_memx${size}(ic);"
        !           687:            echo "      if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !           688:        else
        !           689:            echo "      tme_m68k_read_memx${size}(ic);"
        !           690:            echo "      if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !           691:            echo -n "        ic->tme_m68k_ireg_uint32(ireg) = "
        !           692:            if test $size = 32; then
        !           693:                echo "ic->tme_m68k_ireg_memx${size};"
        !           694:            else
        !           695:                echo "TME_EXT_S${size}_U32((tme_int${size}_t) ic->tme_m68k_ireg_memx${size});"
        !           696:            fi
        !           697:        fi
        !           698:        echo "        ic->_tme_m68k_ea_address += addend;"
        !           699:        echo "      }"
        !           700:        echo "    }"
        !           701:        echo "    ireg += direction;"
        !           702:        echo "  }"
        !           703:        echo ""
        !           704: 
        !           705:        # for the predecrement and postincrement modes, update the
        !           706:        # address register:
        !           707:        if test $name = rm; then 
        !           708:            echo "  /* if this is the predecrement mode, update the address register: */"
        !           709:            echo "  if (ea_mode == 4) {"
        !           710:            echo "    ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0"
        !           711:            echo "                              + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3))"
        !           712:            echo "      = (ic->_tme_m68k_ea_address + sizeof(tme_uint${size}_t));"
        !           713:            echo "  }"
        !           714:        else
        !           715:            echo "  /* if this is the postincrement mode, update the address register: */"
        !           716:            echo "  if (ea_mode == 3) {"
        !           717:            echo "    ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0"
        !           718:            echo "                              + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3))"
        !           719:            echo "      = ic->_tme_m68k_ea_address;"
        !           720:            echo "  }"
        !           721:        fi
        !           722:        
        !           723:        echo "  TME_M68K_INSN_OK;"
        !           724:        echo "}"
        !           725:     done
        !           726: 
        !           727:     # chk32 and chk16:
        !           728:     if test $size != 8; then
        !           729: 
        !           730:        # if we're making the header, just emit a declaration:
        !           731:        if $header; then
        !           732:            echo "TME_M68K_INSN_DECL(tme_m68k_chk${size});"
        !           733:        else
        !           734:            echo ""
        !           735:            echo "/* chk${size}: */"
        !           736:            echo "TME_M68K_INSN(tme_m68k_chk${size})"
        !           737:            echo "{"
        !           738:            echo "  if (*((tme_int${size}_t *) _op0) < 0) {"
        !           739:            echo "    ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_N;"
        !           740:            echo "    ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;"
        !           741:            echo "    TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_GROUP2(6));"
        !           742:            echo "  }"
        !           743:            echo "  if (*((tme_int${size}_t *) _op0) > *((tme_int${size}_t *) _op1)) {"
        !           744:            echo "    ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_N;"
        !           745:            echo "    ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;"
        !           746:            echo "    TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_GROUP2(6));"
        !           747:            echo "  }"
        !           748:            echo "  TME_M68K_INSN_OK;"
        !           749:            echo "}"
        !           750:        fi
        !           751:     fi
        !           752: 
        !           753:     # cas and cas2:
        !           754:     for name in cas cas2_; do
        !           755:     
        !           756:        # cas2 doesn't do byte operands:
        !           757:        buffers=x
        !           758:        if test $name = cas2_; then
        !           759:            if test $size = 8; then continue; fi
        !           760:            buffers="x y"
        !           761:        fi
        !           762: 
        !           763:        if $header; then
        !           764:            echo "TME_M68K_INSN_DECL(tme_m68k_${name}${size});"
        !           765:        else
        !           766:            echo ""
        !           767:            echo "/* ${name}${size}: */"
        !           768:            echo "TME_M68K_INSN(tme_m68k_${name}${size})"
        !           769:            echo "{"
        !           770:            echo "  struct tme_m68k_tlb *tlb;"
        !           771:            echo "  int ireg_dc, ireg_du;"
        !           772:            echo "  int do_write;"
        !           773:            echo "  tme_uint16_t specopx = ic->_tme_m68k_insn_specop;"
        !           774:            if test $name = cas2_; then
        !           775:                echo "  tme_uint16_t specopy = ic->_tme_m68k_insn_specop2;"
        !           776:                echo "  tme_uint32_t addrx;"
        !           777:                echo "  tme_uint32_t addry;"
        !           778:                echo ""
        !           779:                echo "  /* get the function code and addresses we'll be dealing with: */"
        !           780:                echo "  ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic);"
        !           781:                echo "  addrx = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0"
        !           782:                echo "                                   + TME_FIELD_EXTRACTU(specopx, 12, 4));"
        !           783:                echo "  addry = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0"
        !           784:                echo "                                   + TME_FIELD_EXTRACTU(specopy, 12, 4));"
        !           785:            fi
        !           786:            echo ""
        !           787:            echo "  /* start the read/modify/write cycle: */"
        !           788:            echo "  tlb = tme_m68k_rmw_start(ic);"
        !           789:            echo "  if (tlb == NULL) {"
        !           790:            echo "    TME_M68K_INSN_OK;"
        !           791:            echo "  }"
        !           792:            echo ""
        !           793:            echo "  /* read: */"
        !           794:            for buffer in $buffers; do
        !           795:                if test $name = cas2_; then
        !           796:                    echo "  ic->_tme_m68k_ea_address = addr${buffer};"
        !           797:                fi
        !           798:                echo "  tme_m68k_read${size}(ic, tlb,"
        !           799:                echo "                  &ic->_tme_m68k_ea_function_code,"
        !           800:                echo "                  &ic->_tme_m68k_ea_address,"
        !           801:                echo "                  &ic->tme_m68k_ireg_mem${buffer}${size},"
        !           802:                echo "                  TME_M68K_BUS_CYCLE_RMW);"
        !           803:            done
        !           804: 
        !           805:            echo ""
        !           806:            echo "  /* modify: */"
        !           807:            for buffer in $buffers; do
        !           808:                i=
        !           809:                if test $buffer = y; then
        !           810:                    echo "  if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) {"
        !           811:                    i="  "
        !           812:                fi
        !           813:                echo "${i}  ireg_dc = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop${buffer}, 0, 3);"
        !           814:                echo "${i}  tme_m68k_cmp${size}(ic, &ic->tme_m68k_ireg_uint${size}(ireg_dc), &ic->tme_m68k_ireg_mem${buffer}${size});"
        !           815:                if test $buffer = y; then
        !           816:                    echo "  }"
        !           817:                fi
        !           818:            done
        !           819: 
        !           820:            echo ""
        !           821:            echo "  /* write: */"
        !           822:            echo "  if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) {"
        !           823:            for buffer in $buffers; do
        !           824:                if test $name = cas2_; then
        !           825:                    echo "    ic->_tme_m68k_ea_address = addr${buffer};"
        !           826:                fi
        !           827:                echo "    ireg_du = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop${buffer}, 6, 3);"
        !           828:                echo "    ic->tme_m68k_ireg_mem${buffer}${size} = ic->tme_m68k_ireg_uint${size}(ireg_du);"
        !           829:                echo "    tme_m68k_write${size}(ic, tlb,"
        !           830:                echo "                     &ic->_tme_m68k_ea_function_code,"
        !           831:                echo "                     &ic->_tme_m68k_ea_address,"
        !           832:                echo "                     &ic->tme_m68k_ireg_mem${buffer}${size},"
        !           833:                echo "                     TME_M68K_BUS_CYCLE_RMW);"
        !           834:            done
        !           835:            echo "  }"
        !           836:            echo "  else {"
        !           837:            echo "    /* XXX the 68040 always does a write to finish its cycle: */"
        !           838:            echo "    do_write = FALSE;"
        !           839:            for buffer in $buffers; do
        !           840:                echo "    ireg_dc = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop${buffer}, 0, 3);"
        !           841:                echo -n "    if (do_write"
        !           842:                if test $name = cas2_; then
        !           843:                    echo ""
        !           844:                    echo "        && ic->tme_m68k_ireg_mem${buffer}${size} != ic->tme_m68k_ireg_uint${size}(ireg_dc)) {"
        !           845:                    echo "      ic->_tme_m68k_ea_address = addr${buffer};"
        !           846:                else 
        !           847:                    echo ") {"
        !           848:                fi
        !           849:                echo "      tme_m68k_write${size}(ic, tlb,"
        !           850:                echo "                       &ic->_tme_m68k_ea_function_code,"
        !           851:                echo "                       &ic->_tme_m68k_ea_address,"
        !           852:                echo "                       &ic->tme_m68k_ireg_mem${buffer}${size},"
        !           853:                echo "                       TME_M68K_BUS_CYCLE_RMW);"
        !           854:                echo "      do_write = FALSE;"
        !           855:                echo "    }"
        !           856:                echo "    ic->tme_m68k_ireg_uint${size}(ireg_dc) = ic->tme_m68k_ireg_mem${buffer}${size};"
        !           857:            done
        !           858:            echo "  }"
        !           859:            echo ""
        !           860:            echo "  /* finish the read/modify/write cycle: */"
        !           861:            echo "  tme_m68k_rmw_finish(ic, tlb);"
        !           862:            echo ""
        !           863:            echo "  TME_M68K_INSN_OK;"
        !           864:            echo "}"
        !           865:        fi
        !           866:     done
        !           867: 
        !           868:     # moves:
        !           869:     if $header; then
        !           870:        echo "TME_M68K_INSN_DECL(tme_m68k_moves${size});"
        !           871:     else
        !           872:        echo ""
        !           873:        echo "/* moves${size}: */"
        !           874:        echo "TME_M68K_INSN(tme_m68k_moves${size})"
        !           875:        echo "{"
        !           876:        echo "  int ireg;"
        !           877:        echo "  ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4);"
        !           878:        echo "  if (TME_M68K_INSN_SPECOP & TME_BIT(11)) {"
        !           879:        echo "    ic->tme_m68k_ireg_memx${size} = ic->tme_m68k_ireg_uint${size}(ireg${reg_size_shift});"
        !           880:        echo "  }"
        !           881:        echo "  else {"
        !           882:        if test ${size} != 32; then
        !           883:            echo "    if (ireg >= TME_M68K_IREG_A0) {"
        !           884:            echo "      ic->tme_m68k_ireg_uint32(ireg) = "
        !           885:            echo "        TME_EXT_S${size}_U32((tme_int${size}_t) ic->tme_m68k_ireg_memx${size});"
        !           886:            echo "    }"
        !           887:            echo "    else"
        !           888:            echo -n "  "
        !           889:        fi
        !           890:        echo "    ic->tme_m68k_ireg_uint${size}(ireg${reg_size_shift}) = ic->tme_m68k_ireg_memx${size};"
        !           891:        echo "  }"
        !           892:        echo "  TME_M68K_INSN_OK;"
        !           893:        echo "}"
        !           894:     fi
        !           895: done
        !           896: 
        !           897: # generate the memory read and write functions:
        !           898: 
        !           899: # permute on size:
        !           900: for size in 8 16 32 any; do
        !           901: 
        !           902:     # permute on read or write:
        !           903:     for name in read write; do
        !           904:        capname=`echo $name | tr a-z A-Z`
        !           905:        if test $name = read; then 
        !           906:            lockname="rd"
        !           907:            from="from"
        !           908:        else
        !           909:            lockname="wr"
        !           910:            from="to"
        !           911:        fi
        !           912: 
        !           913:        # permute on the special-purpose what:
        !           914:        for what in memx mem inst stack; do
        !           915: 
        !           916:            # placeholder for another permutation:
        !           917:            :
        !           918: 
        !           919:                # dispatch on the size:
        !           920:                _first=_first ; _last=_last
        !           921:                case "$size" in
        !           922:                8) _first= ; _last= ;;
        !           923:                esac
        !           924: 
        !           925:                # set up the details of each special purpose:
        !           926:                rval="void"
        !           927:                args=""
        !           928:                args_proto=""
        !           929:                fc=""
        !           930:                addr=""
        !           931:                count=""
        !           932:                tlb="TME_M68K_TLB_ENTRY(ic, function_code, linear_address${_first})"
        !           933:                flags="TME_M68K_BUS_CYCLE_NORMAL"
        !           934:                case "${name}-${what}-${size}" in
        !           935:                *-memx-8 | *-memx-16 | *-memx-32)
        !           936:                    action="${name}_${what}${size}"
        !           937:                    fcptr="&ic->_tme_m68k_ea_function_code"
        !           938:                    addrptr="&ic->_tme_m68k_ea_address"
        !           939:                    reg="ic->tme_m68k_ireg_memx${size}"
        !           940:                    regptr="&${reg}"
        !           941:                    ;;
        !           942:                *-mem-any)
        !           943:                    action="${name}_${what}"
        !           944:                    args_proto=", tme_uint8_t *, unsigned int"
        !           945:                    args=", tme_uint8_t *buffer, unsigned int count"
        !           946:                    fcptr="&ic->_tme_m68k_ea_function_code"
        !           947:                    addrptr="&ic->_tme_m68k_ea_address"
        !           948:                    reg=
        !           949:                    regptr="buffer"
        !           950:                    ;;
        !           951:                *-mem-8 | *-mem-16 | *-mem-32)
        !           952:                    action="${name}_${what}${size}"
        !           953:                    args_proto=", int"
        !           954:                    args="${args_proto} ireg"
        !           955:                    fcptr="&ic->_tme_m68k_ea_function_code"
        !           956:                    addrptr="&ic->_tme_m68k_ea_address"
        !           957:                    reg="ic->tme_m68k_ireg_uint${size}(ireg)"
        !           958:                    regptr="&${reg}"
        !           959:                    ;;
        !           960:                read-stack-16 | read-stack-32)
        !           961:                    action="pop${size}"
        !           962:                    args_proto=", tme_uint${size}_t *"
        !           963:                    args="${args_proto}_value"
        !           964:                    fc="TME_M68K_FUNCTION_CODE_DATA(ic)"
        !           965:                    addrptr="&ic->tme_m68k_ireg_a7"
        !           966:                    regptr="_value"
        !           967:                    reg="*${regptr}"
        !           968:                    ;;
        !           969:                write-stack-16 | write-stack-32)
        !           970:                    action="push${size}"
        !           971:                    args_proto=", tme_uint${size}_t "
        !           972:                    args="${args_proto}value"
        !           973:                    fc="TME_M68K_FUNCTION_CODE_DATA(ic)"
        !           974:                    addr="ic->tme_m68k_ireg_a7 - sizeof(tme_uint${size}_t)"
        !           975:                    reg="value"
        !           976:                    regptr="&${reg}"
        !           977:                    ;;
        !           978:                read-inst-16 | read-inst-32)
        !           979:                    rval="tme_uint${size}_t"
        !           980:                    action="fetch${size}"
        !           981:                    args_proto=", tme_uint32_t"
        !           982:                    args="${args_proto} pc"
        !           983:                    fc="TME_M68K_FUNCTION_CODE_PROGRAM(ic)"
        !           984:                    addrptr="&pc"
        !           985:                    tlb="TME_ATOMIC_READ(struct tme_m68k_tlb *, ic->_tme_m68k_itlb)";
        !           986:                    flags="TME_M68K_BUS_CYCLE_FETCH"
        !           987:                    ;;
        !           988:                *)
        !           989:                    continue
        !           990:                    ;;
        !           991:                esac
        !           992: 
        !           993:                # if we're making the header, just emit a declaration:
        !           994:                if $header; then
        !           995:                    echo "${rval} tme_m68k_${action} _TME_P((struct tme_m68k *${args_proto}));"
        !           996:                    continue
        !           997:                fi
        !           998: 
        !           999:                # start the function:
        !          1000:                echo ""
        !          1001:                echo "/* this ${name}s a ${size}-bit ${what} value: */"
        !          1002:                echo "${rval}"
        !          1003:                echo "tme_m68k_${action}(struct tme_m68k *ic${args}) "
        !          1004:                echo "{"
        !          1005: 
        !          1006:                # our locals:
        !          1007:                echo -n "  unsigned int function_code = "
        !          1008:                if test "x${fc}" != x; then
        !          1009:                    echo "${fc};"
        !          1010:                    fc="function_code"
        !          1011:                    fcptr="&function_code"
        !          1012:                else
        !          1013:                    fc=`echo ${fcptr} | sed -e 's,^&,,'`
        !          1014:                    echo "${fc};"
        !          1015:                fi
        !          1016:                echo -n "  tme_uint32_t linear_address${_first} = "
        !          1017:                if test "x${addr}" != x; then
        !          1018:                    echo "${addr};"
        !          1019:                    addr="linear_address${_first}"
        !          1020:                    addrptr="&linear_address${_first}"
        !          1021:                else
        !          1022:                    addr=`echo ${addrptr} | sed -e 's,^&,,'`
        !          1023:                    echo "${addr};"
        !          1024:                fi
        !          1025:                if test "x${count}" = x; then
        !          1026:                    if test $size = any; then count=count; else count="sizeof(tme_uint${size}_t)"; fi
        !          1027:                fi
        !          1028:                if test x$_last != x; then
        !          1029:                    echo "  tme_uint32_t linear_address${_last} = linear_address_first + ${count} - 1;";
        !          1030:                fi
        !          1031:                echo "  struct tme_m68k_tlb *tlb = ${tlb};"
        !          1032:                case "$what" in
        !          1033:                inst)
        !          1034:                    echo "  unsigned int insn_buffer_off = TME_ALIGN(ic->_tme_m68k_insn_buffer_off, sizeof(tme_uint${size}_t));"
        !          1035:                    regptr="((tme_uint${size}_t *) &ic->_tme_m68k_insn_buffer[insn_buffer_off])"
        !          1036:                    reg="*${regptr}"
        !          1037:                    ;;
        !          1038:                esac
        !          1039: 
        !          1040:                # if this is a write, log the value written:
        !          1041:                if test $name = write; then
        !          1042:                    echo ""
        !          1043:                    echo "  /* log the value written: */"
        !          1044:                    if test $size != any; then
        !          1045:                        echo "  tme_m68k_verify_mem${size}(ic, ${fc}, ${addr}, ${reg}, TME_BUS_CYCLE_WRITE);"
        !          1046:                        echo "  tme_m68k_log(ic, 1000, TME_OK, "
        !          1047:                        echo "               (TME_M68K_LOG_HANDLE(ic),"
        !          1048:                        echo "                _(\"${action}\t%d:0x%08x:\t0x%0"`expr ${size} / 4`"x\"),"
        !          1049:                        echo "                ${fc},"
        !          1050:                        echo "                ${addr},"
        !          1051:                        echo "                ${reg}));"
        !          1052:                    else
        !          1053:                        echo "  tme_m68k_verify_mem_any(ic, ${fc}, ${addr}, ${regptr}, ${count}, TME_BUS_CYCLE_WRITE);"
        !          1054:                        echo "  tme_m68k_log_start(ic, 1000, TME_OK) {"
        !          1055:                        echo "    unsigned int byte_i;"
        !          1056:                        echo "    tme_log_part(TME_M68K_LOG_HANDLE(ic),"
        !          1057:                        echo "                 _(\"${action} %d:0x%08x count %d:\"),"
        !          1058:                        echo "                 ${fc},"
        !          1059:                        echo "                 ${addr},"
        !          1060:                        echo "                 ${count});"
        !          1061:                        echo "    for (byte_i = 0; byte_i < count ; byte_i++) {"
        !          1062:                        echo "      tme_log_part(TME_M68K_LOG_HANDLE(ic), \" 0x%02x\", (${regptr})[byte_i]);"
        !          1063:                        echo "    }"
        !          1064:                        echo "  } tme_m68k_log_finish(ic);"
        !          1065:                    fi
        !          1066:                fi
        !          1067: 
        !          1068:                echo ""
        !          1069:                echo "  /* do the bus cycle(s) ourselves from emulator memory if we can."
        !          1070:                echo "     the emulator memory allocator and TLB filler must guarantee"
        !          1071:                echo "     that all tme_m68k_tlb_emulator_off_${name} pointers be 32-bit"
        !          1072:                echo "     aligned, so that a 16-bit-aligned linear address gets a"
        !          1073:                echo "     16-bit-aligned emulator address: */"
        !          1074:                echo "  if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING"
        !          1075:                if test $size != 8; then
        !          1076:                    echo "                         && !(linear_address${_first} & 1)"
        !          1077:                fi
        !          1078:                echo "                         && TME_M68K_TLB_OK_FAST_${capname}(tlb,"
        !          1079:                echo "                                                      function_code,"
        !          1080:                echo "                                                      linear_address${_first},"
        !          1081:                echo "                                                      linear_address${_last}))) {"
        !          1082: 
        !          1083:                memptr="(tlb->tme_m68k_tlb_emulator_off_${name} + linear_address${_first})"
        !          1084:                mem="*((tme_uint${size}_t *) ${memptr})"
        !          1085:                if test $name = read; then
        !          1086:                    simple="${reg} = tme_betoh_u${size}(${mem});"
        !          1087:                else
        !          1088:                    simple="${mem} = tme_htobe_u${size}(${reg});"
        !          1089:                fi
        !          1090: 
        !          1091:                echo ""
        !          1092:                
        !          1093:                # if this is an 8-bit transfer:
        !          1094:                if test $size = 8; then
        !          1095:                    echo "    /* for an 8-bit transfer we can always do a simple "
        !          1096:                    echo "       assignment.  the ${lockname}lock is unnecessary, since we assume"
        !          1097:                    echo "       that 8-bit accesses are always atomic: */"
        !          1098:                    if test $name = read; then
        !          1099:                        echo "    ${reg} = ${mem};"
        !          1100:                    else
        !          1101:                        echo "    ${mem} = ${reg};"
        !          1102:                    fi
        !          1103:                
        !          1104:                # if this is a 16-bit transfer:
        !          1105:                elif test $size = 16; then
        !          1106:                    echo "    /* for a 16-bit transfer we can always do a simple"
        !          1107:                    echo "       assignment - we tested that the linear address"
        !          1108:                    echo "       is 16-bit aligned, which, since the TLB emulator"
        !          1109:                    echo "       offset is guaranteed to be 32-bit aligned, guarantees"
        !          1110:                    echo "       that the final emulator address is 16-bit aligned."
        !          1111:                    echo ""
        !          1112:                    echo "       we need the ${lockname}lock if we're on an architecture"
        !          1113:                    echo "       where an aligned access may not be atomic: */"
        !          1114:                    echo "    tme_memory_aligned_${lockname}lock(tlb->tme_m68k_tlb_bus_rwlock);"
        !          1115:                    echo "    ${simple}"
        !          1116:                    echo "    tme_memory_aligned_unlock(tlb->tme_m68k_tlb_bus_rwlock);"
        !          1117:                    
        !          1118:                # if this is a 32-bit transfer:
        !          1119:                elif test $size = 32; then
        !          1120: 
        !          1121:                    echo "    /* if the emulator host allows ${size}-bit quantities to be"
        !          1122:                    echo "       transferred ${from} 16-bit aligned addresses, or if this"
        !          1123:                    echo "       address is ${size}-bit aligned, do the transfer as a simple"
        !          1124:                    echo "       assignment, otherwise transfer two 16-bit words."
        !          1125:                    echo ""
        !          1126:                    echo "       we need the ${lockname}lock if we're on an architecture where"
        !          1127:                    echo "       an aligned access may not be atomic, or if we're doing"
        !          1128:                    echo "       an unaligned access on an architecture where they may"
        !          1129:                    echo "       not be atomic: */"
        !          1130:                    misaligned="(linear_address${_first} & (sizeof(tme_uint${size}_t) - 1))"
        !          1131:                    echo "#if ALIGNOF_INT${size}_T <= ALIGNOF_INT16_T"
        !          1132:                    echo "#ifdef TME_UNALIGNED_ACCESS_ATOMIC"
        !          1133:                    echo "    ${simple}"
        !          1134:                    echo "#else  /* !TME_UNALIGNED_ACCESS_ATOMIC */"
        !          1135:                    echo "    if (${misaligned}) {"
        !          1136:                    echo "      tme_memory_unaligned_${lockname}lock(tlb->tme_m68k_tlb_bus_rwlock);"
        !          1137:                    echo "      ${simple}"
        !          1138:                    echo "      tme_memory_unaligned_unlock(tlb->tme_m68k_tlb_bus_rwlock);"
        !          1139:                    echo "    }"
        !          1140:                    echo "    else {"
        !          1141:                    echo "      tme_memory_aligned_${lockname}lock(tlb->tme_m68k_tlb_bus_rwlock);"
        !          1142:                    echo "      ${simple}"
        !          1143:                    echo "      tme_memory_aligned_unlock(tlb->tme_m68k_tlb_bus_rwlock);"
        !          1144:                    echo "    }"
        !          1145:                    echo "#endif /* !TME_UNALIGNED_ACCESS_ATOMIC */"
        !          1146:                    echo "#else  /* ALIGNOF_INT${size}_T > ALIGNOF_INT16_T */"
        !          1147:                    echo "    if (TME_SEQUENCE_ACCESS_NOT_COSTLIER || ${misaligned}) {"
        !          1148:                    echo "      tme_memory_sequence_${lockname}lock(tlb->tme_m68k_tlb_bus_rwlock); "
        !          1149:                    if test $name = read; then
        !          1150:                        echo "#ifdef WORDS_BIGENDIAN"
        !          1151:                        echo "      ${reg} = (((tme_uint${size}_t) ((tme_uint16_t *) ${memptr})[0]) << 16) | ((tme_uint16_t *) ${memptr})[1];"
        !          1152:                        echo "#else  /* !WORDS_BIGENDIAN */"
        !          1153:                        echo "      ${reg} = tme_betoh_u32((((tme_uint${size}_t) ((tme_uint16_t *) ${memptr})[1]) << 16) | ((tme_uint16_t *) ${memptr})[0]);"
        !          1154:                        echo "#endif /* !WORDS_BIGENDIAN */"
        !          1155:                    else
        !          1156:                        echo "      ((tme_uint16_t *) ${memptr})[0] = tme_htobe_u16(${reg} >> 16);"
        !          1157:                        echo "      ((tme_uint16_t *) ${memptr})[1] = tme_htobe_u16(${reg} & 0xffff);"
        !          1158:                    fi
        !          1159:                    echo "      tme_memory_sequence_unlock(tlb->tme_m68k_tlb_bus_rwlock); "
        !          1160:                    echo "    }"
        !          1161:                    echo "    else {"
        !          1162:                    echo "      tme_memory_aligned_${lockname}lock(tlb->tme_m68k_tlb_bus_rwlock); "
        !          1163:                    echo "      ${simple}"
        !          1164:                    echo "      tme_memory_aligned_unlock(tlb->tme_m68k_tlb_bus_rwlock); "
        !          1165:                    echo "    }"
        !          1166:                    echo "#endif /* ALIGNOF_INT${size}_T != 1 */"
        !          1167:                    
        !          1168:                # if this is an any-transfer:
        !          1169:                elif test $size = any; then
        !          1170:                    echo "    tme_memory_sequence_${lockname}lock(tlb->tme_m68k_tlb_bus_rwlock);"
        !          1171:                    if test $name = read; then
        !          1172:                        echo "    memcpy(${regptr}, ${memptr}, ${count});"
        !          1173:                    else
        !          1174:                        echo "    memcpy(${memptr}, ${regptr}, ${count});"
        !          1175:                    fi
        !          1176:                    echo "    tme_memory_sequence_unlock(tlb->tme_m68k_tlb_bus_rwlock);"
        !          1177: 
        !          1178:                fi
        !          1179:                echo "    TME_M68K_SEQUENCE_TRANSFER_STEP;"
        !          1180:                echo "  }"
        !          1181: 
        !          1182:                echo ""
        !          1183:                echo "  /* otherwise, do the bus cycles the slow way: */"
        !          1184:                echo "  else {"
        !          1185:                if test $size != any; then
        !          1186:                    echo "    tme_m68k_${name}${size}(ic, tlb,"
        !          1187:                    echo "                    ${fcptr},"
        !          1188:                    echo "                    ${addrptr},"
        !          1189:                    echo "                    ${regptr},"
        !          1190:                    echo "                    ${flags});"
        !          1191:                else
        !          1192:                    echo "    tme_m68k_${name}(ic, tlb, ${fcptr}, ${addrptr}, ${regptr}, ${count}, TME_M68K_BUS_CYCLE_RAW);"
        !          1193:                fi
        !          1194:                echo "  }"
        !          1195:                
        !          1196:                # if this is a read, log the value read:
        !          1197:                if test $name = read; then
        !          1198:                    echo ""
        !          1199:                    echo "  /* log the value read: */"
        !          1200:                    if test $size != any; then
        !          1201:                        echo "  tme_m68k_verify_mem${size}(ic, ${fc}, ${addr}, ${reg}, TME_BUS_CYCLE_READ);"
        !          1202:                        echo "  tme_m68k_log(ic, 1000, TME_OK,"
        !          1203:                        echo "               (TME_M68K_LOG_HANDLE(ic),"
        !          1204:                        echo "                _(\"${action}\t%d:0x%08x:\t0x%0"`expr ${size} / 4`"x\"),"
        !          1205:                        echo "                ${fc},"
        !          1206:                        echo "                ${addr},"
        !          1207:                        echo "                ${reg}));"
        !          1208:                    else
        !          1209:                        echo "  tme_m68k_verify_mem_any(ic, ${fc}, ${addr}, ${regptr}, ${count}, TME_BUS_CYCLE_READ);"
        !          1210:                        echo "  tme_m68k_log_start(ic, 1000, TME_OK) {"
        !          1211:                        echo "    unsigned int byte_i;"
        !          1212:                        echo "    tme_log_part(TME_M68K_LOG_HANDLE(ic),"
        !          1213:                        echo "                 _(\"${action} %d:0x%08x count %d:\"),"
        !          1214:                        echo "                 ${fc},"
        !          1215:                        echo "                 ${addr},"
        !          1216:                        echo "                 ${count});"
        !          1217:                        echo "    for (byte_i = 0; byte_i < count ; byte_i++) {"
        !          1218:                        echo "      tme_log_part(TME_M68K_LOG_HANDLE(ic), \" 0x%02x\", (${regptr})[byte_i]);"
        !          1219:                        echo "    }"
        !          1220:                        echo "  } tme_m68k_log_finish(ic);"
        !          1221:                    fi
        !          1222:                fi
        !          1223: 
        !          1224:                # perform any updating and value returning:
        !          1225:                case "$what" in
        !          1226:                stack)
        !          1227:                    if test $name = read; then dir="+"; else dir="-"; fi
        !          1228:                    echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !          1229:                    echo "    ic->tme_m68k_ireg_a7 ${dir}= sizeof(tme_uint${size}_t);"
        !          1230:                    echo "  }"
        !          1231:                    ;;
        !          1232:                inst)
        !          1233:                    echo "  ic->_tme_m68k_insn_buffer_off = insn_buffer_off + sizeof(tme_uint${size}_t);"
        !          1234:                    echo "  return(${reg});"
        !          1235:                    ;;
        !          1236:                esac
        !          1237: 
        !          1238:                echo "}"
        !          1239:            :
        !          1240:        done
        !          1241: 
        !          1242:        # the general-purpose cycle-making read and write macros:
        !          1243:        if test ${size} != any; then
        !          1244: 
        !          1245:            # if we're making the header, emit a macro:
        !          1246:            if $header; then
        !          1247:                echo "#define tme_m68k_${name}${size}(ic, t, fc, la, _v, f) \\"
        !          1248:                echo "  tme_m68k_${name}(ic, t, fc, la, (tme_uint8_t *) (_v), sizeof(tme_uint${size}_t), f)"
        !          1249:            fi
        !          1250:        else
        !          1251: 
        !          1252:            # if we're making the header, just emit a declaration:
        !          1253:            if $header; then
        !          1254:                echo "void tme_m68k_${name} _TME_P((struct tme_m68k *, struct tme_m68k_tlb *, unsigned int *, tme_uint32_t *, tme_uint8_t *, unsigned int, unsigned int));"
        !          1255:                continue
        !          1256:            fi
        !          1257: 
        !          1258:            echo ""
        !          1259:            echo "/* this ${name}s a region of address space using actual bus cycles: */"
        !          1260:            echo "void"
        !          1261:            echo "tme_m68k_${name}(struct tme_m68k *ic, "
        !          1262:            echo "              struct tme_m68k_tlb *tlb,"
        !          1263:            echo "              unsigned int *_function_code, "
        !          1264:            echo "              tme_uint32_t *_linear_address, "
        !          1265:            echo "              tme_uint8_t *reg,"
        !          1266:            echo "              unsigned int reg_size,"
        !          1267:            echo "              unsigned int flags)"
        !          1268:            echo "{"
        !          1269: 
        !          1270:            # our locals:
        !          1271:            echo "  unsigned int function_code;"
        !          1272:            echo "  tme_uint32_t linear_address;"
        !          1273:            echo "  tme_bus_addr_t physical_address;"
        !          1274:            echo "  int shift;"
        !          1275:            echo "  struct tme_bus_cycle cycle;"
        !          1276:            echo "  unsigned int transferred, resid, cycle_size;"
        !          1277:            echo "  int exception;"
        !          1278:            echo "  tme_rwlock_t *rmw_rwlock;"
        !          1279:            echo "  int err;"
        !          1280:            echo "#ifndef WORDS_BIGENDIAN"
        !          1281:            echo "  tme_uint8_t *reg_p;"
        !          1282:            echo "  unsigned int buffer_i;"
        !          1283:            echo "#endif /* !WORDS_BIGENDIAN */"
        !          1284: 
        !          1285:            echo ""
        !          1286:            echo "  /* if we're not restarting, everything is fresh: */"
        !          1287:            echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !          1288:            echo "    function_code = *_function_code;"
        !          1289:            echo "    linear_address = *_linear_address;"
        !          1290:            echo "    transferred = 0;"
        !          1291:            echo "  }"
        !          1292: 
        !          1293:            echo ""
        !          1294:            echo "  /* otherwise, if this is the transfer that faulted, restore"
        !          1295:            echo "     our state to the cycle that faulted, then take into account"
        !          1296:            echo "     any data provided by a software rerun of the faulted cycle: */"
        !          1297:            echo "  else if (ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted"
        !          1298:            echo "           == ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next) {"
        !          1299:            echo "    function_code = *_function_code = ic->_tme_m68k_group0_function_code;"
        !          1300:            echo "    linear_address = ic->_tme_m68k_group0_address;"
        !          1301:            echo "    transferred = ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted_after;"
        !          1302:            echo "    if (transferred >= reg_size) abort();"
        !          1303:            echo "    *_linear_address = linear_address - transferred;"
        !          1304:            echo "    resid = reg_size - transferred;"
        !          1305:            echo "    if (ic->_tme_m68k_group0_buffer_${name}_size > resid) abort();"
        !          1306:            echo "    if (ic->_tme_m68k_group0_buffer_${name}_softrr > resid) abort();"
        !          1307:            if test $name = read; then cmp=">"; else cmp="=="; fi
        !          1308:            echo "    if (ic->_tme_m68k_group0_buffer_${name}_softrr ${cmp} 0) {"
        !          1309:            echo "#ifdef WORDS_BIGENDIAN"
        !          1310:            echo "      memcpy(reg + transferred, "
        !          1311:            echo "             ic->_tme_m68k_group0_buffer_${name},"
        !          1312:            echo "             ic->_tme_m68k_group0_buffer_${name}_size);"
        !          1313:            echo "#else  /* !WORDS_BIGENDIAN */"
        !          1314:            echo "      reg_p = (reg + reg_size - 1) - transferred;"
        !          1315:            echo "      for (buffer_i = 0;"
        !          1316:            echo "           buffer_i < ic->_tme_m68k_group0_buffer_${name}_size;"
        !          1317:            echo "           buffer_i++) {"
        !          1318:            echo "        *(reg_p--) = ic->_tme_m68k_group0_buffer_${name}[buffer_i];"
        !          1319:            echo "      }"
        !          1320:            echo "#endif /* !WORDS_BIGENDIAN */"
        !          1321:            echo "    }"
        !          1322:            echo "    transferred += ic->_tme_m68k_group0_buffer_${name}_softrr;"
        !          1323:            echo "  }"
        !          1324: 
        !          1325:            echo ""
        !          1326:            echo "  /* otherwise, a later transfer has faulted.  just step the"
        !          1327:            echo "     transfer number and return: */"
        !          1328:            echo "  else {"
        !          1329:            echo "    TME_M68K_SEQUENCE_TRANSFER_STEP;"
        !          1330:            echo "    return;"
        !          1331:            echo "  }"
        !          1332: 
        !          1333:            echo ""
        !          1334:            echo "  /* do as many bus cycles as needed to complete the transfer: */"
        !          1335:            echo "  rmw_rwlock = tlb->tme_m68k_tlb_bus_rwlock;"
        !          1336:            echo "  exception = TME_M68K_EXCEPTION_NONE;"
        !          1337:            echo "  cycle_size = 0;"
        !          1338:            echo "  for(; transferred < reg_size; ) {"
        !          1339:            echo "    resid = reg_size - transferred;"
        !          1340: 
        !          1341:            echo ""
        !          1342:            echo "    /* start the bus cycle structure: */"
        !          1343:            echo "    cycle.tme_bus_cycle_type = TME_BUS_CYCLE_${capname};"
        !          1344:            echo "    if (TME_ENDIAN_NATIVE == TME_ENDIAN_BIG"
        !          1345:            echo "        || (flags & TME_M68K_BUS_CYCLE_RAW)) {"
        !          1346:            echo "      cycle.tme_bus_cycle_buffer = reg + transferred;"
        !          1347:            echo "      cycle.tme_bus_cycle_buffer_increment = 1;"
        !          1348:            echo "    }"
        !          1349:            echo "    else {"
        !          1350:            echo "      cycle.tme_bus_cycle_buffer = reg + reg_size - (1 + transferred);"
        !          1351:            echo "      cycle.tme_bus_cycle_buffer_increment = -1;"
        !          1352:            echo "    }"
        !          1353: 
        !          1354:            echo ""
        !          1355:            echo "    /* if we're emulating a CPU with a 16-bit bus interface: */"
        !          1356:            echo "    if (ic->_tme_m68k_bus_16bit) {"
        !          1357:            echo ""
        !          1358:            echo "      /* if we're trying to transfer a non-power-of-two"
        !          1359:            echo "         number of bytes, either the CPU is broken (no"
        !          1360:            echo "         instructions ever transfer a non-power-of-two"
        !          1361:            echo "         number of bytes), or this function allowed an"
        !          1362:            echo "         unaligned transfer: */"
        !          1363:            echo "      assert((resid & (resid - 1)) == 0"
        !          1364:            echo "             || (flags & TME_M68K_BUS_CYCLE_RAW));"
        !          1365:            echo ""
        !          1366:            echo "      /* only byte transfers can be unaligned: */"
        !          1367:            echo "      if (resid > sizeof(tme_uint8_t)"
        !          1368:            echo "          && (linear_address & 1)) {"
        !          1369:            echo "          exception = TME_M68K_EXCEPTION_GROUP0_AERR;"
        !          1370:            echo "          break;"
        !          1371:            echo "      }"
        !          1372:            echo ""
        !          1373:            echo "      /* set the bus-size specific parts of the bus cycle structure: */"
        !          1374:            echo "      cycle_size = TME_MIN(resid, sizeof(tme_uint16_t));"
        !          1375:            echo "      cycle.tme_bus_cycle_size = cycle_size;"
        !          1376:            echo "      cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS16_LOG2);"
        !          1377:            echo "      cycle.tme_bus_cycle_lane_routing = "
        !          1378:            echo "        &tme_m68k_router_16[TME_M68K_BUS_ROUTER_INDEX(TME_BUS16_LOG2, cycle_size, linear_address)];"
        !          1379:            echo "    }"
        !          1380:            echo ""
        !          1381:            echo "    /* otherwise we're emulating a CPU with a 32-bit bus interface: */"
        !          1382:            echo "    else {"
        !          1383:            if test $name = read; then
        !          1384:                echo ""
        !          1385:                echo "      /* an instruction fetch must be aligned: */"
        !          1386:                echo "      if (flags & TME_M68K_BUS_CYCLE_FETCH) {"
        !          1387:                echo "        if (linear_address & 1) {"
        !          1388:                echo "          exception = TME_M68K_EXCEPTION_GROUP0_AERR;"
        !          1389:                echo "          break;"
        !          1390:                echo "        }"
        !          1391:                echo "        assert(!(resid & 1));"
        !          1392:                echo "      }"
        !          1393:            fi
        !          1394:            echo ""
        !          1395:            echo "      /* set the bus-size specific parts of the bus cycle structure: */"
        !          1396:            echo "      cycle_size = TME_MIN(resid, sizeof(tme_uint32_t) - (linear_address & (sizeof(tme_uint32_t) - 1)));"
        !          1397:            echo "      cycle.tme_bus_cycle_size = cycle_size;"
        !          1398:            echo "      cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS32_LOG2);"
        !          1399:            echo "      cycle.tme_bus_cycle_lane_routing = "
        !          1400:            echo "        &tme_m68k_router_32[TME_M68K_BUS_ROUTER_INDEX(TME_BUS32_LOG2, cycle_size, linear_address)];"
        !          1401:            echo "    }"
        !          1402:        
        !          1403:            echo ""
        !          1404:            echo "    /* reload the TLB entry: */"
        !          1405:            echo "    if (!TME_M68K_TLB_OK_SLOW_${capname}(tlb, function_code, linear_address)) {"
        !          1406:            echo "      tme_m68k_tlb_fill(ic, tlb,"
        !          1407:            echo "                        function_code,"
        !          1408:            echo "                        linear_address,"
        !          1409:            echo "                        TME_BUS_CYCLE_${capname});"
        !          1410:            echo "    }"
        !          1411:            echo ""
        !          1412:            echo "    /* if this is a part of a read/modify/write cycle: */"
        !          1413:            echo "    if (flags & TME_M68K_BUS_CYCLE_RMW) {"
        !          1414:            echo ""
        !          1415:            echo "      /* if this TLB entry doesn't support fast ${name}s, or"
        !          1416:            echo "         if the TLB lock has changed, that's a bus error."
        !          1417:            echo "         see the discussion in tme_m68k_rmw_start: */"
        !          1418:            echo "      if (!TME_M68K_TLB_OK_FAST_${capname}(tlb, function_code, linear_address, linear_address)"
        !          1419:            echo "          || (rmw_rwlock != NULL"
        !          1420:            echo "              && rmw_rwlock != tlb->tme_m68k_tlb_bus_rwlock)) {"
        !          1421:            echo "        exception = TME_M68K_EXCEPTION_GROUP0_BERR;"
        !          1422:            echo "        break;"
        !          1423:            echo "      }"
        !          1424:            echo ""
        !          1425:            echo "      /* if we haven't locked this memory yet, do so: */"
        !          1426:            echo "      if (rmw_rwlock == NULL) {"
        !          1427:            echo "        rmw_rwlock = tlb->tme_m68k_tlb_bus_rwlock;"
        !          1428:            echo "        tme_rwlock_wrlock(rmw_rwlock);"
        !          1429:            echo "      }"
        !          1430:            echo "    }"
        !          1431: 
        !          1432:            echo ""
        !          1433:            echo "    /* form the physical address for the bus cycle handler: */"
        !          1434:            echo "    physical_address = tlb->tme_m68k_tlb_addr_offset + linear_address;"
        !          1435:            echo "    shift = tlb->tme_m68k_tlb_addr_shift;"
        !          1436:            echo "    if (shift < 0) {"
        !          1437:            echo "      physical_address <<= (0 - shift);"
        !          1438:            echo "    }"
        !          1439:            echo "    else if (shift > 0) {"
        !          1440:            echo "      physical_address >>= shift;"
        !          1441:            echo "    }"
        !          1442:            echo "    cycle.tme_bus_cycle_address = physical_address;"
        !          1443: 
        !          1444:            echo ""
        !          1445:            echo "    /* run the bus cycle: */"
        !          1446:            echo "    err = (*tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycle)"
        !          1447:            echo "         (tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycle_private, &cycle);"
        !          1448:            echo ""
        !          1449:            echo "    /* if we deadlocked, we have no locks to release"
        !          1450:            echo "       ourselves, so sleep a while waiting for things"
        !          1451:            echo "       to clear up, then try again: */"
        !          1452:            echo "    if (err == TME_EDEADLK) {"
        !          1453:            echo "      TME_THREAD_DEADLOCK_SLEEP();"
        !          1454:            echo "      cycle.tme_bus_cycle_address = physical_address;"
        !          1455:            echo "    }"
        !          1456:            echo ""
        !          1457:            echo "    /* otherwise, any other error might be a bus error: */"
        !          1458:            echo "    else if (err != TME_OK) {"
        !          1459:            echo "      err = tme_bus_tlb_fault(&tlb->tme_m68k_tlb_bus_tlb, &cycle, err);"
        !          1460:            echo "      if (err != TME_OK) {"
        !          1461:            echo "        exception = TME_M68K_EXCEPTION_GROUP0_BERR;"
        !          1462:            echo "        break;"
        !          1463:            echo "      }"
        !          1464:            echo "    }"
        !          1465:            echo ""
        !          1466:            echo "    /* update: */"
        !          1467:            echo "    linear_address += cycle.tme_bus_cycle_size;"
        !          1468:            echo "    transferred += cycle.tme_bus_cycle_size;"
        !          1469:            echo "  }"
        !          1470:        
        !          1471:            echo ""
        !          1472:            echo "  /* if we got an exception and there is a locked"
        !          1473:            echo "     read/modify/write rwlock, unlock it: */"
        !          1474:            echo "  if (exception != TME_M68K_EXCEPTION_NONE"
        !          1475:            echo "      && (flags & TME_M68K_BUS_CYCLE_RMW)"
        !          1476:            echo "      && rmw_rwlock != NULL) {"
        !          1477:            echo "    tme_rwlock_unlock(rmw_rwlock);"
        !          1478:            echo "  }"
        !          1479: 
        !          1480:            echo ""
        !          1481:            echo "  /* if we faulted, stash the information the fault stacker"
        !          1482:            echo "     will need and start exception processing: */"
        !          1483:            echo "  if (exception != TME_M68K_EXCEPTION_NONE) {"
        !          1484:            echo -n "    ic->_tme_m68k_group0_flags = flags"
        !          1485:            if test $name = read; then
        !          1486:                echo -n " | TME_M68K_BUS_CYCLE_READ"
        !          1487:            fi
        !          1488:            echo ";"
        !          1489:            echo "    ic->_tme_m68k_group0_function_code = function_code;"
        !          1490:            echo "    ic->_tme_m68k_group0_address = linear_address;"
        !          1491:            echo "    ic->_tme_m68k_group0_sequence = ic->_tme_m68k_sequence;"
        !          1492:            echo "    ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted_after = transferred;"
        !          1493:            echo "    ic->_tme_m68k_group0_buffer_${name}_size = cycle_size;"
        !          1494:            if test $name = write; then
        !          1495:                echo "#ifdef WORDS_BIGENDIAN"
        !          1496:                echo "    memcpy(ic->_tme_m68k_group0_buffer_${name},"
        !          1497:                echo "           reg + transferred,"
        !          1498:                echo "           ic->_tme_m68k_group0_buffer_${name}_size);"
        !          1499:                echo "#else  /* !WORDS_BIGENDIAN */"
        !          1500:                echo "      reg_p = (reg + reg_size - 1) - transferred;"
        !          1501:                echo "      for (buffer_i = 0;"
        !          1502:                echo "           buffer_i < ic->_tme_m68k_group0_buffer_${name}_size;"
        !          1503:                echo "           buffer_i++) {"
        !          1504:                echo "        ic->_tme_m68k_group0_buffer_${name}[buffer_i] = *(reg_p--);"
        !          1505:                echo "      }"
        !          1506:                echo "#endif /* !WORDS_BIGENDIAN */"
        !          1507:            fi
        !          1508:            echo "    if (ic->_tme_m68k_group0_hook != NULL) {"
        !          1509:            echo "      (*ic->_tme_m68k_group0_hook)(ic);"
        !          1510:            echo "    }"
        !          1511:            echo "    ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted = ";
        !          1512:            echo "      ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_next;"
        !          1513:            echo "    tme_m68k_exception(ic, exception);"
        !          1514:            echo "  }"
        !          1515: 
        !          1516:            echo ""
        !          1517:            echo "  /* otherwise, this transfer has now completed: */"
        !          1518:            echo "  TME_M68K_SEQUENCE_TRANSFER_STEP;"
        !          1519: 
        !          1520:            echo "}"
        !          1521:        fi
        !          1522:     done
        !          1523: 
        !          1524: done
        !          1525: 
        !          1526: # generate the BCD math functions:
        !          1527: for name in abcd sbcd nbcd; do
        !          1528: 
        !          1529:     # if we're making the header, just emit a declaration:
        !          1530:     if $header; then
        !          1531:        echo "TME_M68K_INSN_DECL(tme_m68k_${name});"
        !          1532:        continue
        !          1533:     fi
        !          1534: 
        !          1535:     # emit the function:
        !          1536:     echo ""
        !          1537:     echo "TME_M68K_INSN(tme_m68k_${name})"
        !          1538:     echo "{"
        !          1539:     echo "  tme_uint8_t dst, dst_msd, dst_lsd;"
        !          1540:     echo "  tme_uint8_t src, src_msd, src_lsd;"
        !          1541:     echo "  tme_uint8_t res, res_msd, res_lsd;"
        !          1542:     echo "  tme_uint8_t flags;"
        !          1543: 
        !          1544:     # get the operands:
        !          1545:     if test $name != nbcd; then
        !          1546:        echo "  int memory;"
        !          1547:        echo "  int rx, ry, function_code;"
        !          1548:        echo ""
        !          1549:        echo "  TME_M68K_INSN_CANFAULT;"
        !          1550:        echo ""
        !          1551:        echo "  /* load the operands: */"
        !          1552:        echo "  rx = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);"
        !          1553:        echo "  ry = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);"
        !          1554:        echo "  memory = (TME_M68K_INSN_OPCODE & TME_BIT(3)) != 0;"
        !          1555:        echo "  function_code = TME_M68K_FUNCTION_CODE_DATA(ic);"
        !          1556:        echo "  if (memory) {"
        !          1557:        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !          1558:        echo "      ic->_tme_m68k_ea_function_code = function_code;"
        !          1559:        echo "      ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + rx);"
        !          1560:        echo "    }"
        !          1561:        echo "    tme_m68k_read_memx8(ic);"
        !          1562:        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !          1563:        echo "      ic->_tme_m68k_ea_function_code = function_code;"
        !          1564:        echo "      ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry);"
        !          1565:        echo "    }"
        !          1566:        echo "    tme_m68k_read_mem8(ic, TME_M68K_IREG_MEMY32);"
        !          1567:        echo "    src = ic->tme_m68k_ireg_memx8;"
        !          1568:        echo "    dst = ic->tme_m68k_ireg_memy8;"
        !          1569:        echo "  }"
        !          1570:        echo "  else {"
        !          1571:        echo "    src = ic->tme_m68k_ireg_uint8(rx << 2);"
        !          1572:        echo "    dst = ic->tme_m68k_ireg_uint8(ry << 2);"
        !          1573:        echo "  }"
        !          1574:     else
        !          1575:        echo ""
        !          1576:        echo "  dst = 0x00;"
        !          1577:        echo "  src = TME_M68K_INSN_OP1(tme_uint8_t);"
        !          1578:     fi
        !          1579:     echo "  dst_lsd = TME_FIELD_EXTRACTU(dst, 0, 4);"
        !          1580:     echo "  dst_msd = TME_FIELD_EXTRACTU(dst, 4, 4);"
        !          1581:     echo "  src_lsd = TME_FIELD_EXTRACTU(src, 0, 4);"
        !          1582:     echo "  src_msd = TME_FIELD_EXTRACTU(src, 4, 4);"
        !          1583: 
        !          1584:     # perform the operation:
        !          1585:     echo ""
        !          1586:     echo "  /* perform the operation: */"
        !          1587:     if test $name = abcd; then op='+' ; opc='-' ; else op='-' ; opc='+' ; fi
        !          1588:     echo "  res_lsd = dst_lsd ${op} src_lsd ${op} ((ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X) != 0);"
        !          1589:     echo "  res_msd = dst_msd ${op} src_msd;"
        !          1590:     echo "  flags = 0;"
        !          1591:     echo "  if (res_lsd > 9) {"
        !          1592:     echo "    res_lsd ${opc}= 10;"
        !          1593:     echo "    res_msd ${op}= 1;"
        !          1594:     echo "  }"
        !          1595:     echo "  if (res_msd > 9) {"
        !          1596:     echo "    res_msd ${opc}= 10;"
        !          1597:     echo "    flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;"
        !          1598:     echo "  }"
        !          1599:     echo "  res = (res_msd << 4) + (res_lsd & 0xf);"
        !          1600:     echo "  if (res == 0) flags |= TME_M68K_FLAG_N;"
        !          1601:     echo ""
        !          1602: 
        !          1603:     # store the result
        !          1604:     echo "  /* store the result and set the flags: */"
        !          1605:     if test $name != nbcd; then
        !          1606:        echo "  if (memory) {"
        !          1607:        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !          1608:        echo "      ic->tme_m68k_ireg_memx8 = res;"
        !          1609:        echo "      ic->_tme_m68k_ea_function_code = function_code;"
        !          1610:        echo "      ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry);"
        !          1611:        # the stack pointer must always be incremented by a multiple of two.
        !          1612:        # assuming rx < 8, ((rx + 1) >> 3) == 1 iff rx == 7, meaning %a7:
        !          1613:        echo "      ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + rx) += sizeof(tme_uint8_t) + ((rx + 1) >> 3);"
        !          1614:        echo "      ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry) += sizeof(tme_uint8_t) + ((ry + 1) >> 3);"
        !          1615:        echo "      ic->tme_m68k_ireg_ccr = flags;"
        !          1616:        echo "     }"
        !          1617:        echo "     tme_m68k_write_memx8(ic);"
        !          1618:        echo "  }"
        !          1619:        echo "  else {"
        !          1620:        echo "    ic->tme_m68k_ireg_uint8(ry << 2) = res;"
        !          1621:        echo "    ic->tme_m68k_ireg_ccr = flags;"
        !          1622:        echo "  }"
        !          1623:     else
        !          1624:        echo "  TME_M68K_INSN_OP1(tme_uint8_t) = res;"
        !          1625:        echo "  ic->tme_m68k_ireg_ccr = flags;"
        !          1626:     fi
        !          1627:     echo ""
        !          1628:     echo "  TME_M68K_INSN_OK;"
        !          1629:     echo "}"
        !          1630: done
        !          1631: 
        !          1632: # generate the ccr and sr functions:
        !          1633: for reg in ccr sr; do
        !          1634:     for name in ori andi eori move_to; do
        !          1635:        if test $reg = ccr; then size=8 ; else size=16 ; fi
        !          1636: 
        !          1637:        # if we're making the header, just emit a declaration:
        !          1638:        if $header; then
        !          1639:            echo "TME_M68K_INSN_DECL(tme_m68k_${name}_${reg});"
        !          1640:            continue
        !          1641:        fi
        !          1642: 
        !          1643:        # emit the function:
        !          1644:        echo ""
        !          1645:        echo "TME_M68K_INSN(tme_m68k_${name}_${reg})"
        !          1646:        echo "{"
        !          1647:        echo "  tme_uint${size}_t reg;"
        !          1648: 
        !          1649:        # form the new register value:
        !          1650:        src=0
        !          1651:        echo -n "  reg = "
        !          1652:        case $name in
        !          1653:        ori) echo -n "ic->tme_m68k_ireg_${reg} | " ;;
        !          1654:        andi) echo -n "ic->tme_m68k_ireg_${reg} & " ;;
        !          1655:        eori) echo -n "ic->tme_m68k_ireg_${reg} ^ " ;;
        !          1656:        move_to) size=16 ; src=1 ;;
        !          1657:        esac
        !          1658:        echo "(TME_M68K_INSN_OP${src}(tme_uint${size}_t) & TME_M68K_FLAG_"`echo $reg | tr a-z A-Z`");"
        !          1659:        
        !          1660:        # sr changes are special:
        !          1661:        if test $reg = sr; then
        !          1662:            echo "  TME_M68K_INSN_PRIV;"
        !          1663:            echo "  TME_M68K_INSN_CHANGE_SR(reg);"
        !          1664:        else
        !          1665:            echo "  ic->tme_m68k_ireg_${reg} = reg;"
        !          1666:        fi
        !          1667: 
        !          1668:        echo "  TME_M68K_INSN_OK;"
        !          1669:        echo "}"
        !          1670:     done
        !          1671: done
        !          1672: 
        !          1673: # generate the multiply and divide instructions:
        !          1674: 
        !          1675: # permute on signed vs. unsigned:
        !          1676: for _sign in u s; do
        !          1677:     if test $_sign = u; then sign=u; else sign=; fi
        !          1678: 
        !          1679:     # permute on short vs. long:
        !          1680:     for size in s l; do
        !          1681:        if test $size = s; then 
        !          1682:            _size=
        !          1683:            small=16
        !          1684:            large=32
        !          1685:            reg_size_shift=' << 1'
        !          1686:        else
        !          1687:            _size=l
        !          1688:            small=32
        !          1689:            large=64
        !          1690:            reg_size_shift=
        !          1691:        fi
        !          1692: 
        !          1693:        # if we're making the header, just emit declarations:
        !          1694:        if $header; then
        !          1695:            echo "TME_M68K_INSN_DECL(tme_m68k_mul${_sign}${_size});"
        !          1696:            echo "TME_M68K_INSN_DECL(tme_m68k_div${_sign}${_size});"
        !          1697:            continue
        !          1698:        fi
        !          1699: 
        !          1700:        # emit the multiply function:
        !          1701:        echo ""
        !          1702:        echo "TME_M68K_INSN(tme_m68k_mul${_sign}${_size})"
        !          1703:        echo "{"
        !          1704:        if test $large = 64; then
        !          1705:            echo "#ifndef HAVE_UINT${large}_T"
        !          1706:            echo "  abort();"
        !          1707:            echo "#else /* HAVE_UINT${large}_T */"
        !          1708:            echo "  unsigned int flag_v;"
        !          1709:            echo "  int ireg_dh;"
        !          1710:        fi
        !          1711:        echo "  int ireg_dl;"
        !          1712:        echo "  tme_${sign}int${large}_t res;"
        !          1713:        echo "  tme_uint8_t flags;"
        !          1714: 
        !          1715:        echo ""
        !          1716:        echo "  /* get the register containing the factor: */"
        !          1717:        echo -n "  ireg_dl = TME_M68K_IREG_D0 + "
        !          1718:        if test $size = s; then
        !          1719:            echo "TME_M68K_INSN_OP0(tme_uint32_t);"
        !          1720:        else
        !          1721:            echo "TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3);"
        !          1722:        fi
        !          1723: 
        !          1724:        echo ""
        !          1725:        echo "  /* perform the multiplication: */"
        !          1726:        echo "  res = (((tme_${sign}int${large}_t) ic->tme_m68k_ireg_${sign}int${small}(ireg_dl${reg_size_shift}))"
        !          1727:        echo "         * TME_M68K_INSN_OP1(tme_${sign}int${small}_t));"
        !          1728:        
        !          1729:        echo ""
        !          1730:        echo "  /* store the result: */"
        !          1731:        echo "  ic->tme_m68k_ireg_${sign}int32(ireg_dl) = (tme_${sign}int32_t) res;"
        !          1732:        if test $large = 64; then
        !          1733:            echo "  flag_v = TME_M68K_FLAG_V;"
        !          1734:            echo "  if (TME_M68K_INSN_SPECOP & TME_BIT(10)) {"
        !          1735:            echo "    flag_v = 0;"
        !          1736:            echo "    ireg_dh = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3);"
        !          1737:            echo "    ic->tme_m68k_ireg_${sign}int32(ireg_dh) = (tme_${sign}int32_t) (res >> 32);"
        !          1738:            echo "  }"
        !          1739:        fi
        !          1740:        
        !          1741:        echo ""
        !          1742:        echo "  /* set the flags: */"
        !          1743:        echo "  flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;"
        !          1744:        echo "  if (((tme_int${large}_t) res) < 0) flags |= TME_M68K_FLAG_N;"
        !          1745:        echo "  if (res == 0) flags |= TME_M68K_FLAG_Z;"
        !          1746:        if test $large = 64; then
        !          1747:            echo -n "  if (res > 0xffffffff"
        !          1748:            if test $_sign = s; then echo -n " || res < -2147483648"; fi
        !          1749:            echo ") flags |= flag_v;"
        !          1750:        fi
        !          1751:        echo "  ic->tme_m68k_ireg_ccr = flags;"
        !          1752: 
        !          1753:        echo ""
        !          1754:        echo "  TME_M68K_INSN_OK;"
        !          1755:        if test $large = 64; then
        !          1756:            echo "#endif /* HAVE_UINT${large}_T */"
        !          1757:        fi
        !          1758:        echo "}"
        !          1759: 
        !          1760:        # emit the divide function:
        !          1761:        echo ""
        !          1762:        echo "TME_M68K_INSN(tme_m68k_div${_sign}${_size})"
        !          1763:        echo "{"
        !          1764:        if test $large = 64; then
        !          1765:            echo "#ifndef HAVE_UINT${large}_T"
        !          1766:            echo "  abort();"
        !          1767:            echo "#else /* HAVE_UINT${large}_T */"
        !          1768:            echo "  int ireg_dr;"
        !          1769:        fi
        !          1770:        echo "  int ireg_dq;"
        !          1771:        echo "  tme_${sign}int${large}_t dividend, quotient;"
        !          1772:        echo "  tme_${sign}int${small}_t divisor, remainder;"
        !          1773:        echo "  tme_uint8_t flags;"
        !          1774: 
        !          1775:        echo ""
        !          1776:        echo "  /* get the register(s): */"
        !          1777:        echo -n "  ireg_dq = TME_M68K_IREG_D0 + "
        !          1778:        if test $size = s; then
        !          1779:            echo "TME_M68K_INSN_OP0(tme_uint32_t);"
        !          1780:        else
        !          1781:            echo "TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3);"
        !          1782:            echo "  ireg_dr = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3);"
        !          1783:        fi
        !          1784: 
        !          1785:        echo ""
        !          1786:        echo "  /* form the dividend and the divisor: */"
        !          1787:        if test $large = 64; then
        !          1788:            echo "  if (TME_M68K_INSN_SPECOP & TME_BIT(10)) {"
        !          1789:            echo "    dividend = (tme_${sign}int${large}_t)"
        !          1790:            echo "               ((((tme_uint${large}_t) ic->tme_m68k_ireg_uint32(ireg_dr)) << 32)"
        !          1791:            echo "                | ic->tme_m68k_ireg_uint32(ireg_dq));"
        !          1792:            echo "  }"
        !          1793:            echo "  else"
        !          1794:            echo -n "  "
        !          1795:        fi
        !          1796:        echo "  dividend = (tme_${sign}int${large}_t) ic->tme_m68k_ireg_${sign}int32(ireg_dq);"
        !          1797:        echo "  divisor = TME_M68K_INSN_OP1(tme_${sign}int${small}_t);"
        !          1798:        echo "  if (divisor == 0) {"
        !          1799:        echo "    ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;"
        !          1800:        echo "    TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_GROUP2(5));"
        !          1801:        echo "  }"
        !          1802: 
        !          1803:        echo ""
        !          1804:        echo "  /* do the division: */"
        !          1805:        echo "  quotient = dividend / divisor;"
        !          1806:        echo "  remainder = dividend % divisor;"
        !          1807: 
        !          1808:        echo ""
        !          1809:        echo "  /* set the flags and return the quotient and remainder: */"
        !          1810:        echo "  flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;"
        !          1811:        echo -n "  if (quotient > 0xffff"
        !          1812:        if test $small = 16; then
        !          1813:            if test $_sign = s; then echo -n " || quotient < -32768"; fi
        !          1814:        else
        !          1815:            echo -n "ffff"
        !          1816:            if test $_sign = s; then echo -n " || quotient < -2147483648"; fi
        !          1817:        fi
        !          1818:        echo ") {"
        !          1819:        echo "    flags |= TME_M68K_FLAG_V;"
        !          1820:        echo "  }"
        !          1821:        echo "  else {"
        !          1822:        echo "    if (((tme_int${small}_t) quotient) < 0) flags |= TME_M68K_FLAG_N;"
        !          1823:        echo "    if (quotient == 0) flags |= TME_M68K_FLAG_Z;"
        !          1824:        echo "    ic->tme_m68k_ireg_${sign}int${small}(ireg_dq${reg_size_shift}) = (tme_${sign}int${small}_t) quotient;"
        !          1825:        if test $small = 16; then
        !          1826:            echo "    ic->tme_m68k_ireg_${sign}int${small}((ireg_dq${reg_size_shift}) + 1) = remainder;"
        !          1827:        else
        !          1828:            echo "    if (ireg_dr != ireg_dq) {"
        !          1829:            echo "      ic->tme_m68k_ireg_${sign}int${small}(ireg_dr) = remainder;"
        !          1830:            echo "    }"
        !          1831:        fi
        !          1832:        echo "  }"
        !          1833:        echo "  ic->tme_m68k_ireg_ccr = flags;"
        !          1834: 
        !          1835:        echo ""
        !          1836:        echo "  TME_M68K_INSN_OK;"
        !          1837:        if test $large = 64; then
        !          1838:            echo "#endif /* HAVE_UINT${large}_T */"
        !          1839:        fi
        !          1840:        echo "}"
        !          1841: 
        !          1842:     done
        !          1843: done
        !          1844: 
        !          1845: # done:
        !          1846: exit 0

unix.superglobalmegacorp.com

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