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

1.1       root        1: #! /bin/sh
                      2: 
1.1.1.3 ! root        3: # $Id: m68k-insns-auto.sh,v 1.23 2005/03/10 13:26:23 fredette Exp $
1.1       root        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! */
1.1.1.3 ! root       51: _TME_RCSID("\$Id: m68k-insns-auto.sh,v 1.23 2005/03/10 13:26:23 fredette Exp $");
1.1       root       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= ;;
1.1.1.2   root      424:            asl) echo "  tme_uint${size}_t sign_bits, sign_bits_mask;" ;;
1.1       root      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
1.1.1.3 ! root      450:            lsr)
1.1       root      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:                ;;
1.1.1.3 ! root      461:            asr)
        !           462:                echo "    if (63 > SHIFTMAX_INT${size}_T"
        !           463:                echo "        && count > ${size}) {"
        !           464:                echo "      res = 0 - (res < 0);"
        !           465:                echo "    }"
        !           466:                echo "#ifdef SHIFTSIGNED_INT${size}_T"
        !           467:                echo "    res >>= (count - 1);"
        !           468:                echo "#else  /* !SHIFTSIGNED_INT${size}_T */"
        !           469:                echo "    for (; --count > 0; ) {"
        !           470:                echo "      res = (res & ~((tme_${sign}int${size}_t) 1)) / 2;"
        !           471:                echo "    }"
        !           472:                echo "#endif /* !SHIFTSIGNED_INT${size}_T */"
        !           473:                echo "    flags = (res & 1);"
        !           474:                echo "    flags *= TME_M68K_FLAG_C;"
        !           475:                echo "    flags |= (flags * TME_M68K_FLAG_X);"
        !           476:                echo "#ifdef SHIFTSIGNED_INT${size}_T"
        !           477:                echo "    res >>= 1;"
        !           478:                echo "#else  /* !SHIFTSIGNED_INT${size}_T */"
        !           479:                echo "    res = (res & ~((tme_${sign}int${size}_t) 1)) / 2;"
        !           480:                echo "#endif /* !SHIFTSIGNED_INT${size}_T */"
        !           481:                ;;
1.1       root      482:            [al]sl)
                    483:                if test ${name} = asl; then
                    484:                    echo ""
                    485:                    echo "    /* we need to see how the sign of the result will change during"
                    486:                    echo "       shifting in order to generate V."
                    487:                    echo ""
                    488:                    echo "       in general, the idea is to get all of the bits that will ever"
1.1.1.2   root      489:                    echo "       appear in the sign position into sign_bits, with a mask in"
                    490:                    echo "       sign_bits_mask.  if (sign_bits & sign_bits_mask) is zero or"
                    491:                    echo "       sign_bits_mask, clear V, else set V."
1.1       root      492:                    echo ""
1.1.1.2   root      493:                    echo "       start by loading the operand into sign_bits and setting"
                    494:                    echo "       sign_bits_mask to all-bits-one."
1.1       root      495:                    echo ""
                    496:                    echo "       if the shift count is exactly ${size} - 1, then all of the bits"
                    497:                    echo "       of the operand will appear in the sign position."
                    498:                    echo ""
                    499:                    echo "       if the shift count is less than ${size} - 1, then some of the"
                    500:                    echo "       less significant bits of the operand will never appear in the"
1.1.1.2   root      501:                    echo "       sign position, so we can shift sign_bits_mask to ignore them."
1.1       root      502:                    echo ""
                    503:                    echo "       if the shift count is greater than ${size} - 1, then all of the"
                    504:                    echo "       bits in the operand, plus at least one zero bit, will appear in"
                    505:                    echo "       the sign position.  the only way that the sign bit will never"
                    506:                    echo "       change during the shift is if the operand was zero to begin with."
1.1.1.2   root      507:                    echo "       without any changes to sign_bits or sign_bits_mask, the final"
                    508:                    echo "       test will always work, except when sign_bits is all-bits-one."
                    509:                    echo "       the magic below clears the least-significant bit of sign_bits"
                    510:                    echo "       iff sign_bits is all-bits-one: */"
1.1       root      511:                    echo "    sign_bits = res;"
                    512:                fi
                    513:                echo "    if (63 > SHIFTMAX_INT${size}_T"
                    514:                echo "        && count > ${size}) {"
                    515:                echo "      res = 0;"
                    516:                echo "    }"
                    517:                echo "    res <<= (count - 1);"
                    518:                echo "    flags = (res >> (${size} - 1));"
                    519:                echo "    flags *= TME_M68K_FLAG_C;"
                    520:                echo "    flags |= (flags * TME_M68K_FLAG_X);"
                    521:                echo "    res <<= 1;"
                    522:                if test ${name} = asl; then             
1.1.1.2   root      523:                    echo "    sign_bits_mask = (tme_uint${size}_t) -1;"
1.1       root      524:                    echo "    if (count != ${size} - 1) {"
                    525:                    echo "      if (count < ${size}) {"
1.1.1.2   root      526:                    echo "        sign_bits_mask <<= ((${size} - 1) - count);"
1.1       root      527:                    echo "      }"
                    528:                    echo "      else {"
1.1.1.2   root      529:                    echo "        sign_bits ^= !(sign_bits + 1);"
1.1       root      530:                    echo "      }"
                    531:                    echo "    }"                    
1.1.1.2   root      532:                    echo "    sign_bits &= sign_bits_mask;"
                    533:                    echo "    if (sign_bits != 0 && sign_bits != sign_bits_mask) {"
1.1       root      534:                    echo "      flags |= TME_M68K_FLAG_V;"
                    535:                    echo "    }"
                    536:                fi
                    537:                ;;
                    538:            ro[lr])
                    539:                echo "    count &= (${size} - 1);"
                    540:                if test $dir = l; then
                    541:                    echo "    res = (res << count) | (res >> (${size} - count));"
                    542:                    echo "    flags |= ((res & 1) * TME_M68K_FLAG_C);"
                    543:                else
                    544:                    echo "    res = (res << (${size} - count)) | (res >> count);"
                    545:                    echo "    flags |= ((res >> (${size} - 1)) * TME_M68K_FLAG_C);"
                    546:                fi
                    547:                ;;
                    548:            rox[lr])
                    549:                echo "    count %= (${size} + 1);"
                    550:                echo "    flags = xbit;"
                    551:                echo "    if (count > 0) {"
                    552:                if test $dir = l; then
                    553:                    echo "      flags = (res >> (${size} - count)) & 1;"
                    554:                    echo "      if (${size} > SHIFTMAX_INT${size}_T"
                    555:                    echo "          && count == ${size}) {"
                    556:                    echo "        res = 0 | (xbit << (${size} - 1)) | (res >> ((${size} + 1) - ${size}));"
                    557:                    echo "      }"
                    558:                    echo "      else if (${size} > SHIFTMAX_INT${size}_T"
                    559:                    echo "               && count == 1) {"
                    560:                    echo "        res = (res << 1) | (xbit << (1 - 1)) | 0;"
                    561:                    echo "      }"
                    562:                    echo "      else {"
                    563:                    echo "        res = (res << count) | (xbit << (count - 1)) | (res >> ((${size} + 1) - count));"
                    564:                    echo "      }"
                    565:                else
                    566:                    echo "      flags = (res >> (count - 1)) & 1;"
                    567:                    echo "      if (${size} > SHIFTMAX_INT${size}_T"
                    568:                    echo "          && count == ${size}) {"
                    569:                    echo "        res = (res << ((${size} + 1) - ${size})) | (xbit << (${size} - ${size})) | 0;"
                    570:                    echo "      }"
                    571:                    echo "      else if (${size} > SHIFTMAX_INT${size}_T"
                    572:                    echo "               && count == 1) {"
                    573:                    echo "        res = 0 | (xbit << (${size} - 1)) | (res >> 1);"
                    574:                    echo "      }"
                    575:                    echo "      else {"
                    576:                    echo "        res = (res << ((${size} + 1) - count)) | (xbit << (${size} - count)) | (res >> count);"
                    577:                    echo "      }"
                    578:                fi
                    579:                echo "    }"
                    580:                echo "    flags *= TME_M68K_FLAG_C;"
                    581:                echo "    flags |= (flags * TME_M68K_FLAG_X);"
                    582:                ;;
                    583:            esac
                    584:                echo "  }"
                    585: 
                    586:            echo ""
                    587:            echo "  /* store the result: */"
                    588:            echo "  TME_M68K_INSN_OP1(tme_${sign}int${size}_t) = res;"
                    589: 
                    590:            echo ""
                    591:            echo "  /* generate the N flag.  we cast to tme_uint8_t as soon as we"
                    592:            echo "     know the bit we want is within the range of the type, to try"
                    593:            echo "     to affect the generated assembly: */"
                    594:            echo "  flags |= ((tme_uint8_t) (((tme_uint${size}_t) res) >> (${size} - 1))) * TME_M68K_FLAG_N;"
                    595:            
                    596:            echo ""
                    597:            echo "  /* generate the Z flag: */"
                    598:            echo "  if (res == 0) flags |= TME_M68K_FLAG_Z;"
                    599: 
                    600:            echo ""
                    601:            echo "  /* store the flags: */"
                    602:            echo "  ic->tme_m68k_ireg_ccr = flags;"
                    603:            echo "  TME_M68K_INSN_OK;"
                    604:            echo "}"
                    605:        done
                    606:     done
                    607: 
                    608:     # movep_rm, movep_mr, movem_rm, and movem_mr:
                    609:     for name in rm mr; do
                    610:     
                    611:        # movep and movem don't need 8-bit versions:
                    612:        if test ${size} = 8; then continue; fi
                    613: 
                    614:        # if we're making the header, just emit declarations:
                    615:        if $header; then
                    616:            echo "TME_M68K_INSN_DECL(tme_m68k_movep_${name}${size});"
                    617:            echo "TME_M68K_INSN_DECL(tme_m68k_movem_${name}${size});"
                    618:            continue
                    619:        fi
                    620: 
                    621:        # emit the movep function:
                    622:        echo ""
                    623:        echo "/* the movep_${name} function on a ${size}-bit dreg: */"
                    624:        echo "TME_M68K_INSN(tme_m68k_movep_${name}${size})"
                    625:        echo "{"
                    626:        echo "  unsigned int function_code;"
                    627:        echo "  tme_uint32_t linear_address;"
                    628:        if test $name = rm; then
                    629:            echo "  tme_uint${size}_t value;"
                    630:        fi
                    631:        echo "  int dreg;"
                    632:        echo ""
                    633:        echo "  TME_M68K_INSN_CANFAULT;"
                    634:        echo ""
                    635:        echo "  function_code = TME_M68K_FUNCTION_CODE_DATA(ic);"
                    636:        echo "  linear_address = TME_M68K_INSN_OP1(tme_uint32_t);"
                    637:        echo "  linear_address += (tme_int32_t) ((tme_int16_t) TME_M68K_INSN_SPECOP);"
                    638:        echo "  dreg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);"
                    639: 
                    640:        # set value:
                    641:        if test $name = rm; then
                    642:            echo "  value = ic->tme_m68k_ireg_uint${size}(dreg${reg_size_shift});"
                    643:             value="value"
                    644:         else
                    645:             value="ic->tme_m68k_ireg_uint${size}(dreg${reg_size_shift})"
                    646:        fi
                    647:        
                    648:        # transfer the bytes:
                    649:        pos=${size}
                    650:        while test $pos != 0; do
                    651:            pos=`expr ${pos} - 8`
                    652:            echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
                    653:            echo "    ic->_tme_m68k_ea_function_code = function_code;"
                    654:            echo "    ic->_tme_m68k_ea_address = linear_address;"
                    655:            if test $name = rm; then
                    656:                echo "    ic->tme_m68k_ireg_memx8 = TME_FIELD_EXTRACTU(${value}, ${pos}, 8);"
                    657:                echo "  }"
                    658:                echo "  tme_m68k_write_memx8(ic);"
                    659:            else
                    660:                echo "  }"
                    661:                echo "  tme_m68k_read_memx8(ic);"
                    662:                echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
                    663:                echo "    TME_FIELD_DEPOSIT${size}(${value}, ${pos}, 8, ic->tme_m68k_ireg_memx8);"
                    664:                echo "  }"
                    665:            fi
                    666:            echo "  linear_address += 2;"
                    667:        done
                    668: 
                    669:        echo "  TME_M68K_INSN_OK;"
                    670:        echo "}"
                    671: 
                    672:        # emit the movem function:
                    673:        echo ""
                    674:        echo "/* the movem_${name} function on ${size}-bit registers: */"
                    675:        echo "TME_M68K_INSN(tme_m68k_movem_${name}${size})"
                    676:        echo "{"
                    677:        echo "  int ireg, direction;"
                    678:        echo "  tme_uint16_t mask, bit;"
                    679:        echo "  unsigned int ea_mode;"
                    680:        echo "  tme_uint32_t addend;"
                    681: 
                    682:        echo ""
                    683:        echo "  /* figure out what direction to move in, and where to start from: */"
                    684:        echo "  ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3);"
                    685:        echo "  direction = 1;"
                    686:        echo "  ireg = TME_M68K_IREG_D0;"
                    687:        if test $name = rm; then
                    688:            echo "  if (ea_mode == 4) {"
                    689:            echo "    direction = -1;"
                    690:            echo "    ireg = TME_M68K_IREG_A7;"
                    691:            echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
                    692:            echo "      ic->_tme_m68k_ea_address -= sizeof(tme_uint${size}_t);"
                    693:            echo "    }"
                    694:            echo "  }"
                    695:        fi
                    696:        echo "  addend = (tme_uint32_t) (direction * sizeof(tme_uint${size}_t));"
                    697: 
                    698:        echo ""
                    699:        echo "  /* do the transfer: */"
                    700:        echo "  mask = TME_M68K_INSN_SPECOP;"
1.1.1.2   root      701:        echo "  if (mask != 0) {"
                    702:        echo "    TME_M68K_INSN_CANFAULT;"
                    703:        echo "  }"
1.1       root      704:        echo "  for (bit = 1; bit != 0; bit <<= 1) {"
                    705:        echo "    if (mask & bit) {"
                    706:        if test $name = rm; then
                    707:            echo "      if (!TME_M68K_SEQUENCE_RESTARTING) {"
                    708:            echo "        ic->tme_m68k_ireg_memx${size} = ic->tme_m68k_ireg_uint${size}(ireg${reg_size_shift});"
                    709:            echo "      }"
                    710:            echo "      tme_m68k_write_memx${size}(ic);"
                    711:            echo "      if (!TME_M68K_SEQUENCE_RESTARTING) {"
                    712:        else
                    713:            echo "      tme_m68k_read_memx${size}(ic);"
                    714:            echo "      if (!TME_M68K_SEQUENCE_RESTARTING) {"
                    715:            echo -n "        ic->tme_m68k_ireg_uint32(ireg) = "
                    716:            if test $size = 32; then
                    717:                echo "ic->tme_m68k_ireg_memx${size};"
                    718:            else
                    719:                echo "TME_EXT_S${size}_U32((tme_int${size}_t) ic->tme_m68k_ireg_memx${size});"
                    720:            fi
                    721:        fi
                    722:        echo "        ic->_tme_m68k_ea_address += addend;"
                    723:        echo "      }"
                    724:        echo "    }"
                    725:        echo "    ireg += direction;"
                    726:        echo "  }"
                    727:        echo ""
                    728: 
                    729:        # for the predecrement and postincrement modes, update the
                    730:        # address register:
                    731:        if test $name = rm; then 
                    732:            echo "  /* if this is the predecrement mode, update the address register: */"
                    733:            echo "  if (ea_mode == 4) {"
                    734:            echo "    ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0"
                    735:            echo "                              + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3))"
                    736:            echo "      = (ic->_tme_m68k_ea_address + sizeof(tme_uint${size}_t));"
                    737:            echo "  }"
                    738:        else
                    739:            echo "  /* if this is the postincrement mode, update the address register: */"
                    740:            echo "  if (ea_mode == 3) {"
                    741:            echo "    ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0"
                    742:            echo "                              + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3))"
                    743:            echo "      = ic->_tme_m68k_ea_address;"
                    744:            echo "  }"
                    745:        fi
                    746:        
                    747:        echo "  TME_M68K_INSN_OK;"
                    748:        echo "}"
                    749:     done
                    750: 
                    751:     # chk32 and chk16:
                    752:     if test $size != 8; then
                    753: 
                    754:        # if we're making the header, just emit a declaration:
                    755:        if $header; then
                    756:            echo "TME_M68K_INSN_DECL(tme_m68k_chk${size});"
                    757:        else
                    758:            echo ""
                    759:            echo "/* chk${size}: */"
                    760:            echo "TME_M68K_INSN(tme_m68k_chk${size})"
                    761:            echo "{"
                    762:            echo "  if (*((tme_int${size}_t *) _op0) < 0) {"
                    763:            echo "    ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_N;"
1.1.1.3 ! root      764:            echo "    ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;"
1.1       root      765:            echo "    ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;"
1.1.1.3 ! root      766:            echo "    TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK));"
1.1       root      767:            echo "  }"
                    768:            echo "  if (*((tme_int${size}_t *) _op0) > *((tme_int${size}_t *) _op1)) {"
                    769:            echo "    ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_N;"
1.1.1.3 ! root      770:            echo "    ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;"
1.1       root      771:            echo "    ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;"
1.1.1.3 ! root      772:            echo "    TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK));"
1.1       root      773:            echo "  }"
                    774:            echo "  TME_M68K_INSN_OK;"
                    775:            echo "}"
                    776:        fi
                    777:     fi
                    778: 
                    779:     # cas and cas2:
                    780:     for name in cas cas2_; do
                    781:     
                    782:        # cas2 doesn't do byte operands:
                    783:        buffers=x
                    784:        if test $name = cas2_; then
                    785:            if test $size = 8; then continue; fi
                    786:            buffers="x y"
                    787:        fi
                    788: 
                    789:        if $header; then
                    790:            echo "TME_M68K_INSN_DECL(tme_m68k_${name}${size});"
                    791:        else
                    792:            echo ""
                    793:            echo "/* ${name}${size}: */"
                    794:            echo "TME_M68K_INSN(tme_m68k_${name}${size})"
                    795:            echo "{"
                    796:            echo "  struct tme_m68k_tlb *tlb;"
                    797:            echo "  int ireg_dc, ireg_du;"
                    798:            echo "  int do_write;"
                    799:            echo "  tme_uint16_t specopx = ic->_tme_m68k_insn_specop;"
                    800:            if test $name = cas2_; then
1.1.1.3 ! root      801:                echo "  tme_uint16_t specopy = TME_M68K_INSN_OP0(tme_uint16_t);"
1.1       root      802:                echo "  tme_uint32_t addrx;"
                    803:                echo "  tme_uint32_t addry;"
                    804:                echo ""
                    805:                echo "  /* get the function code and addresses we'll be dealing with: */"
                    806:                echo "  ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic);"
                    807:                echo "  addrx = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0"
                    808:                echo "                                   + TME_FIELD_EXTRACTU(specopx, 12, 4));"
                    809:                echo "  addry = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0"
                    810:                echo "                                   + TME_FIELD_EXTRACTU(specopy, 12, 4));"
                    811:            fi
                    812:            echo ""
                    813:            echo "  /* start the read/modify/write cycle: */"
                    814:            echo "  tlb = tme_m68k_rmw_start(ic);"
                    815:            echo "  if (tlb == NULL) {"
                    816:            echo "    TME_M68K_INSN_OK;"
                    817:            echo "  }"
                    818:            echo ""
                    819:            echo "  /* read: */"
                    820:            for buffer in $buffers; do
                    821:                if test $name = cas2_; then
                    822:                    echo "  ic->_tme_m68k_ea_address = addr${buffer};"
                    823:                fi
                    824:                echo "  tme_m68k_read${size}(ic, tlb,"
                    825:                echo "                  &ic->_tme_m68k_ea_function_code,"
                    826:                echo "                  &ic->_tme_m68k_ea_address,"
                    827:                echo "                  &ic->tme_m68k_ireg_mem${buffer}${size},"
                    828:                echo "                  TME_M68K_BUS_CYCLE_RMW);"
                    829:            done
                    830: 
                    831:            echo ""
                    832:            echo "  /* modify: */"
                    833:            for buffer in $buffers; do
                    834:                i=
                    835:                if test $buffer = y; then
                    836:                    echo "  if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) {"
                    837:                    i="  "
                    838:                fi
                    839:                echo "${i}  ireg_dc = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop${buffer}, 0, 3);"
                    840:                echo "${i}  tme_m68k_cmp${size}(ic, &ic->tme_m68k_ireg_uint${size}(ireg_dc), &ic->tme_m68k_ireg_mem${buffer}${size});"
                    841:                if test $buffer = y; then
                    842:                    echo "  }"
                    843:                fi
                    844:            done
                    845: 
                    846:            echo ""
                    847:            echo "  /* write: */"
                    848:            echo "  if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) {"
                    849:            for buffer in $buffers; do
                    850:                if test $name = cas2_; then
                    851:                    echo "    ic->_tme_m68k_ea_address = addr${buffer};"
                    852:                fi
                    853:                echo "    ireg_du = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop${buffer}, 6, 3);"
                    854:                echo "    ic->tme_m68k_ireg_mem${buffer}${size} = ic->tme_m68k_ireg_uint${size}(ireg_du);"
                    855:                echo "    tme_m68k_write${size}(ic, tlb,"
                    856:                echo "                     &ic->_tme_m68k_ea_function_code,"
                    857:                echo "                     &ic->_tme_m68k_ea_address,"
                    858:                echo "                     &ic->tme_m68k_ireg_mem${buffer}${size},"
                    859:                echo "                     TME_M68K_BUS_CYCLE_RMW);"
                    860:            done
                    861:            echo "  }"
                    862:            echo "  else {"
                    863:            echo "    /* XXX the 68040 always does a write to finish its cycle: */"
                    864:            echo "    do_write = FALSE;"
                    865:            for buffer in $buffers; do
                    866:                echo "    ireg_dc = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop${buffer}, 0, 3);"
                    867:                echo -n "    if (do_write"
                    868:                if test $name = cas2_; then
                    869:                    echo ""
                    870:                    echo "        && ic->tme_m68k_ireg_mem${buffer}${size} != ic->tme_m68k_ireg_uint${size}(ireg_dc)) {"
                    871:                    echo "      ic->_tme_m68k_ea_address = addr${buffer};"
                    872:                else 
                    873:                    echo ") {"
                    874:                fi
                    875:                echo "      tme_m68k_write${size}(ic, tlb,"
                    876:                echo "                       &ic->_tme_m68k_ea_function_code,"
                    877:                echo "                       &ic->_tme_m68k_ea_address,"
                    878:                echo "                       &ic->tme_m68k_ireg_mem${buffer}${size},"
                    879:                echo "                       TME_M68K_BUS_CYCLE_RMW);"
                    880:                echo "      do_write = FALSE;"
                    881:                echo "    }"
                    882:                echo "    ic->tme_m68k_ireg_uint${size}(ireg_dc) = ic->tme_m68k_ireg_mem${buffer}${size};"
                    883:            done
                    884:            echo "  }"
                    885:            echo ""
                    886:            echo "  /* finish the read/modify/write cycle: */"
                    887:            echo "  tme_m68k_rmw_finish(ic, tlb);"
                    888:            echo ""
                    889:            echo "  TME_M68K_INSN_OK;"
                    890:            echo "}"
                    891:        fi
                    892:     done
                    893: 
                    894:     # moves:
                    895:     if $header; then
                    896:        echo "TME_M68K_INSN_DECL(tme_m68k_moves${size});"
                    897:     else
                    898:        echo ""
                    899:        echo "/* moves${size}: */"
                    900:        echo "TME_M68K_INSN(tme_m68k_moves${size})"
                    901:        echo "{"
                    902:        echo "  int ireg;"
1.1.1.3 ! root      903:        echo "  unsigned int ea_reg;"
        !           904:        echo "  unsigned int increment;"
        !           905:        echo "  TME_M68K_INSN_PRIV;"
        !           906:        echo "  TME_M68K_INSN_CANFAULT;"
1.1       root      907:        echo "  ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4);"
1.1.1.3 ! root      908:        echo ""
        !           909:        echo "  /* we have to handle postincrement and predecrement ourselves: */"
        !           910:        echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !           911:        echo "    ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);"
        !           912:        echo "    increment = TME_M68K_SIZE_${size};"
        !           913:        echo "    if (increment == TME_M68K_SIZE_8 && ea_reg == TME_M68K_IREG_A7) {"
        !           914:        echo "      increment = TME_M68K_SIZE_16;"
        !           915:        echo "    }"
        !           916:        echo "    switch (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3)) {"
        !           917:        echo "    case 3: ic->tme_m68k_ireg_uint32(ea_reg) += increment; break;"
        !           918:        echo "    case 4: ic->_tme_m68k_ea_address = (ic->tme_m68k_ireg_uint32(ea_reg) -= increment); break;"
        !           919:        echo "    default: break;"
        !           920:        echo "    }"
        !           921:        echo "  }"
        !           922:        echo ""
1.1       root      923:        echo "  if (TME_M68K_INSN_SPECOP & TME_BIT(11)) {"
1.1.1.3 ! root      924:        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !           925:        echo "      ic->tme_m68k_ireg_memx${size} = ic->tme_m68k_ireg_uint${size}(ireg${reg_size_shift});"
        !           926:        echo "      ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_dfc;"
        !           927:        echo "    }"
        !           928:        echo "    tme_m68k_write_memx${size}(ic);"
1.1       root      929:        echo "  }"
                    930:        echo "  else {"
1.1.1.3 ! root      931:        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !           932:        echo "      ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_sfc;"
        !           933:        echo "    }"
        !           934:        echo "    tme_m68k_read_memx${size}(ic);"
1.1       root      935:        if test ${size} != 32; then
                    936:            echo "    if (ireg >= TME_M68K_IREG_A0) {"
                    937:            echo "      ic->tme_m68k_ireg_uint32(ireg) = "
                    938:            echo "        TME_EXT_S${size}_U32((tme_int${size}_t) ic->tme_m68k_ireg_memx${size});"
                    939:            echo "    }"
                    940:            echo "    else"
                    941:            echo -n "  "
                    942:        fi
                    943:        echo "    ic->tme_m68k_ireg_uint${size}(ireg${reg_size_shift}) = ic->tme_m68k_ireg_memx${size};"
                    944:        echo "  }"
                    945:        echo "  TME_M68K_INSN_OK;"
                    946:        echo "}"
                    947:     fi
                    948: done
                    949: 
                    950: # generate the memory read and write functions:
                    951: 
                    952: # permute on size:
                    953: for size in 8 16 32 any; do
                    954: 
                    955:     # permute on read or write:
                    956:     for name in read write; do
                    957:        capname=`echo $name | tr a-z A-Z`
                    958:        if test $name = read; then 
                    959:            lockname="rd"
                    960:            from="from"
                    961:        else
                    962:            lockname="wr"
                    963:            from="to"
                    964:        fi
                    965: 
                    966:        # permute on the special-purpose what:
                    967:        for what in memx mem inst stack; do
                    968: 
                    969:            # placeholder for another permutation:
                    970:            :
                    971: 
                    972:                # dispatch on the size:
                    973:                _first=_first ; _last=_last
                    974:                case "$size" in
                    975:                8) _first= ; _last= ;;
                    976:                esac
                    977: 
                    978:                # set up the details of each special purpose:
                    979:                rval="void"
                    980:                args=""
                    981:                args_proto=""
                    982:                fc=""
                    983:                addr=""
                    984:                count=""
                    985:                tlb="TME_M68K_TLB_ENTRY(ic, function_code, linear_address${_first})"
                    986:                flags="TME_M68K_BUS_CYCLE_NORMAL"
                    987:                case "${name}-${what}-${size}" in
                    988:                *-memx-8 | *-memx-16 | *-memx-32)
                    989:                    action="${name}_${what}${size}"
                    990:                    fcptr="&ic->_tme_m68k_ea_function_code"
                    991:                    addrptr="&ic->_tme_m68k_ea_address"
                    992:                    reg="ic->tme_m68k_ireg_memx${size}"
                    993:                    regptr="&${reg}"
                    994:                    ;;
                    995:                *-mem-any)
                    996:                    action="${name}_${what}"
                    997:                    args_proto=", tme_uint8_t *, unsigned int"
                    998:                    args=", tme_uint8_t *buffer, unsigned int count"
                    999:                    fcptr="&ic->_tme_m68k_ea_function_code"
                   1000:                    addrptr="&ic->_tme_m68k_ea_address"
                   1001:                    reg=
                   1002:                    regptr="buffer"
                   1003:                    ;;
                   1004:                *-mem-8 | *-mem-16 | *-mem-32)
                   1005:                    action="${name}_${what}${size}"
                   1006:                    args_proto=", int"
                   1007:                    args="${args_proto} ireg"
                   1008:                    fcptr="&ic->_tme_m68k_ea_function_code"
                   1009:                    addrptr="&ic->_tme_m68k_ea_address"
                   1010:                    reg="ic->tme_m68k_ireg_uint${size}(ireg)"
                   1011:                    regptr="&${reg}"
                   1012:                    ;;
                   1013:                read-stack-16 | read-stack-32)
                   1014:                    action="pop${size}"
                   1015:                    args_proto=", tme_uint${size}_t *"
                   1016:                    args="${args_proto}_value"
                   1017:                    fc="TME_M68K_FUNCTION_CODE_DATA(ic)"
                   1018:                    addrptr="&ic->tme_m68k_ireg_a7"
                   1019:                    regptr="_value"
                   1020:                    reg="*${regptr}"
                   1021:                    ;;
                   1022:                write-stack-16 | write-stack-32)
                   1023:                    action="push${size}"
                   1024:                    args_proto=", tme_uint${size}_t "
                   1025:                    args="${args_proto}value"
                   1026:                    fc="TME_M68K_FUNCTION_CODE_DATA(ic)"
                   1027:                    addr="ic->tme_m68k_ireg_a7 - sizeof(tme_uint${size}_t)"
                   1028:                    reg="value"
                   1029:                    regptr="&${reg}"
                   1030:                    ;;
                   1031:                read-inst-16 | read-inst-32)
                   1032:                    rval="tme_uint${size}_t"
                   1033:                    action="fetch${size}"
                   1034:                    args_proto=", tme_uint32_t"
                   1035:                    args="${args_proto} pc"
                   1036:                    fc="TME_M68K_FUNCTION_CODE_PROGRAM(ic)"
                   1037:                    addrptr="&pc"
                   1038:                    tlb="TME_ATOMIC_READ(struct tme_m68k_tlb *, ic->_tme_m68k_itlb)";
                   1039:                    flags="TME_M68K_BUS_CYCLE_FETCH"
                   1040:                    ;;
                   1041:                *)
                   1042:                    continue
                   1043:                    ;;
                   1044:                esac
                   1045: 
                   1046:                # if we're making the header, just emit a declaration:
                   1047:                if $header; then
                   1048:                    echo "${rval} tme_m68k_${action} _TME_P((struct tme_m68k *${args_proto}));"
                   1049:                    continue
                   1050:                fi
                   1051: 
                   1052:                # start the function:
                   1053:                echo ""
                   1054:                echo "/* this ${name}s a ${size}-bit ${what} value: */"
                   1055:                echo "${rval}"
                   1056:                echo "tme_m68k_${action}(struct tme_m68k *ic${args}) "
                   1057:                echo "{"
                   1058: 
                   1059:                # our locals:
                   1060:                echo -n "  unsigned int function_code = "
                   1061:                if test "x${fc}" != x; then
                   1062:                    echo "${fc};"
                   1063:                    fc="function_code"
                   1064:                    fcptr="&function_code"
                   1065:                else
                   1066:                    fc=`echo ${fcptr} | sed -e 's,^&,,'`
                   1067:                    echo "${fc};"
                   1068:                fi
                   1069:                echo -n "  tme_uint32_t linear_address${_first} = "
                   1070:                if test "x${addr}" != x; then
                   1071:                    echo "${addr};"
                   1072:                    addr="linear_address${_first}"
                   1073:                    addrptr="&linear_address${_first}"
                   1074:                else
                   1075:                    addr=`echo ${addrptr} | sed -e 's,^&,,'`
                   1076:                    echo "${addr};"
                   1077:                fi
                   1078:                if test "x${count}" = x; then
                   1079:                    if test $size = any; then count=count; else count="sizeof(tme_uint${size}_t)"; fi
                   1080:                fi
                   1081:                if test x$_last != x; then
                   1082:                    echo "  tme_uint32_t linear_address${_last} = linear_address_first + ${count} - 1;";
                   1083:                fi
                   1084:                echo "  struct tme_m68k_tlb *tlb = ${tlb};"
                   1085:                case "$what" in
                   1086:                inst)
                   1087:                    echo "  unsigned int insn_buffer_off = TME_ALIGN(ic->_tme_m68k_insn_buffer_off, sizeof(tme_uint${size}_t));"
                   1088:                    regptr="((tme_uint${size}_t *) &ic->_tme_m68k_insn_buffer[insn_buffer_off])"
                   1089:                    reg="*${regptr}"
                   1090:                    ;;
                   1091:                esac
                   1092: 
1.1.1.3 ! root     1093:                # track statistics:
        !          1094:                echo ""
        !          1095:                echo "#ifdef _TME_M68K_STATS"
        !          1096:                echo "  ic->tme_m68k_stats.tme_m68k_stats_memory_total++;"
        !          1097:                echo "#endif /* _TME_M68K_STATS */"
        !          1098: 
1.1       root     1099:                # if this is a write, log the value written:
                   1100:                if test $name = write; then
                   1101:                    echo ""
                   1102:                    echo "  /* log the value written: */"
                   1103:                    if test $size != any; then
                   1104:                        echo "  tme_m68k_verify_mem${size}(ic, ${fc}, ${addr}, ${reg}, TME_BUS_CYCLE_WRITE);"
                   1105:                        echo "  tme_m68k_log(ic, 1000, TME_OK, "
                   1106:                        echo "               (TME_M68K_LOG_HANDLE(ic),"
                   1107:                        echo "                _(\"${action}\t%d:0x%08x:\t0x%0"`expr ${size} / 4`"x\"),"
                   1108:                        echo "                ${fc},"
                   1109:                        echo "                ${addr},"
                   1110:                        echo "                ${reg}));"
                   1111:                    else
                   1112:                        echo "  tme_m68k_verify_mem_any(ic, ${fc}, ${addr}, ${regptr}, ${count}, TME_BUS_CYCLE_WRITE);"
                   1113:                        echo "  tme_m68k_log_start(ic, 1000, TME_OK) {"
                   1114:                        echo "    unsigned int byte_i;"
                   1115:                        echo "    tme_log_part(TME_M68K_LOG_HANDLE(ic),"
                   1116:                        echo "                 _(\"${action} %d:0x%08x count %d:\"),"
                   1117:                        echo "                 ${fc},"
                   1118:                        echo "                 ${addr},"
                   1119:                        echo "                 ${count});"
                   1120:                        echo "    for (byte_i = 0; byte_i < count ; byte_i++) {"
                   1121:                        echo "      tme_log_part(TME_M68K_LOG_HANDLE(ic), \" 0x%02x\", (${regptr})[byte_i]);"
                   1122:                        echo "    }"
                   1123:                        echo "  } tme_m68k_log_finish(ic);"
                   1124:                    fi
                   1125:                fi
                   1126: 
                   1127:                echo ""
                   1128:                echo "  /* do the bus cycle(s) ourselves from emulator memory if we can."
                   1129:                echo "     the emulator memory allocator and TLB filler must guarantee"
                   1130:                echo "     that all tme_m68k_tlb_emulator_off_${name} pointers be 32-bit"
                   1131:                echo "     aligned, so that a 16-bit-aligned linear address gets a"
                   1132:                echo "     16-bit-aligned emulator address: */"
                   1133:                echo "  if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING"
                   1134:                if test $size != 8; then
                   1135:                    echo "                         && !(linear_address${_first} & 1)"
                   1136:                fi
                   1137:                echo "                         && TME_M68K_TLB_OK_FAST_${capname}(tlb,"
                   1138:                echo "                                                      function_code,"
                   1139:                echo "                                                      linear_address${_first},"
                   1140:                echo "                                                      linear_address${_last}))) {"
                   1141: 
                   1142:                memptr="(tlb->tme_m68k_tlb_emulator_off_${name} + linear_address${_first})"
                   1143:                mem="*((tme_uint${size}_t *) ${memptr})"
                   1144:                if test $name = read; then
                   1145:                    simple="${reg} = tme_betoh_u${size}(${mem});"
                   1146:                else
                   1147:                    simple="${mem} = tme_htobe_u${size}(${reg});"
                   1148:                fi
                   1149: 
                   1150:                echo ""
                   1151:                
                   1152:                # if this is an 8-bit transfer:
                   1153:                if test $size = 8; then
                   1154:                    echo "    /* for an 8-bit transfer we can always do a simple "
                   1155:                    echo "       assignment.  the ${lockname}lock is unnecessary, since we assume"
                   1156:                    echo "       that 8-bit accesses are always atomic: */"
                   1157:                    if test $name = read; then
                   1158:                        echo "    ${reg} = ${mem};"
                   1159:                    else
                   1160:                        echo "    ${mem} = ${reg};"
                   1161:                    fi
                   1162:                
                   1163:                # if this is a 16-bit transfer:
                   1164:                elif test $size = 16; then
                   1165:                    echo "    /* for a 16-bit transfer we can always do a simple"
                   1166:                    echo "       assignment - we tested that the linear address"
                   1167:                    echo "       is 16-bit aligned, which, since the TLB emulator"
                   1168:                    echo "       offset is guaranteed to be 32-bit aligned, guarantees"
                   1169:                    echo "       that the final emulator address is 16-bit aligned."
                   1170:                    echo ""
                   1171:                    echo "       we need the ${lockname}lock if we're on an architecture"
                   1172:                    echo "       where an aligned access may not be atomic: */"
                   1173:                    echo "    tme_memory_aligned_${lockname}lock(tlb->tme_m68k_tlb_bus_rwlock);"
                   1174:                    echo "    ${simple}"
                   1175:                    echo "    tme_memory_aligned_unlock(tlb->tme_m68k_tlb_bus_rwlock);"
                   1176:                    
                   1177:                # if this is a 32-bit transfer:
                   1178:                elif test $size = 32; then
                   1179: 
                   1180:                    echo "    /* if the emulator host allows ${size}-bit quantities to be"
                   1181:                    echo "       transferred ${from} 16-bit aligned addresses, or if this"
                   1182:                    echo "       address is ${size}-bit aligned, do the transfer as a simple"
                   1183:                    echo "       assignment, otherwise transfer two 16-bit words."
                   1184:                    echo ""
                   1185:                    echo "       we need the ${lockname}lock if we're on an architecture where"
                   1186:                    echo "       an aligned access may not be atomic, or if we're doing"
                   1187:                    echo "       an unaligned access on an architecture where they may"
                   1188:                    echo "       not be atomic: */"
                   1189:                    misaligned="(linear_address${_first} & (sizeof(tme_uint${size}_t) - 1))"
                   1190:                    echo "#if ALIGNOF_INT${size}_T <= ALIGNOF_INT16_T"
                   1191:                    echo "#ifdef TME_UNALIGNED_ACCESS_ATOMIC"
                   1192:                    echo "    ${simple}"
                   1193:                    echo "#else  /* !TME_UNALIGNED_ACCESS_ATOMIC */"
                   1194:                    echo "    if (${misaligned}) {"
                   1195:                    echo "      tme_memory_unaligned_${lockname}lock(tlb->tme_m68k_tlb_bus_rwlock);"
                   1196:                    echo "      ${simple}"
                   1197:                    echo "      tme_memory_unaligned_unlock(tlb->tme_m68k_tlb_bus_rwlock);"
                   1198:                    echo "    }"
                   1199:                    echo "    else {"
                   1200:                    echo "      tme_memory_aligned_${lockname}lock(tlb->tme_m68k_tlb_bus_rwlock);"
                   1201:                    echo "      ${simple}"
                   1202:                    echo "      tme_memory_aligned_unlock(tlb->tme_m68k_tlb_bus_rwlock);"
                   1203:                    echo "    }"
                   1204:                    echo "#endif /* !TME_UNALIGNED_ACCESS_ATOMIC */"
                   1205:                    echo "#else  /* ALIGNOF_INT${size}_T > ALIGNOF_INT16_T */"
                   1206:                    echo "    if (TME_SEQUENCE_ACCESS_NOT_COSTLIER || ${misaligned}) {"
                   1207:                    echo "      tme_memory_sequence_${lockname}lock(tlb->tme_m68k_tlb_bus_rwlock); "
                   1208:                    if test $name = read; then
                   1209:                        echo "#ifdef WORDS_BIGENDIAN"
                   1210:                        echo "      ${reg} = (((tme_uint${size}_t) ((tme_uint16_t *) ${memptr})[0]) << 16) | ((tme_uint16_t *) ${memptr})[1];"
                   1211:                        echo "#else  /* !WORDS_BIGENDIAN */"
                   1212:                        echo "      ${reg} = tme_betoh_u32((((tme_uint${size}_t) ((tme_uint16_t *) ${memptr})[1]) << 16) | ((tme_uint16_t *) ${memptr})[0]);"
                   1213:                        echo "#endif /* !WORDS_BIGENDIAN */"
                   1214:                    else
                   1215:                        echo "      ((tme_uint16_t *) ${memptr})[0] = tme_htobe_u16(${reg} >> 16);"
                   1216:                        echo "      ((tme_uint16_t *) ${memptr})[1] = tme_htobe_u16(${reg} & 0xffff);"
                   1217:                    fi
                   1218:                    echo "      tme_memory_sequence_unlock(tlb->tme_m68k_tlb_bus_rwlock); "
                   1219:                    echo "    }"
                   1220:                    echo "    else {"
                   1221:                    echo "      tme_memory_aligned_${lockname}lock(tlb->tme_m68k_tlb_bus_rwlock); "
                   1222:                    echo "      ${simple}"
                   1223:                    echo "      tme_memory_aligned_unlock(tlb->tme_m68k_tlb_bus_rwlock); "
                   1224:                    echo "    }"
                   1225:                    echo "#endif /* ALIGNOF_INT${size}_T != 1 */"
                   1226:                    
                   1227:                # if this is an any-transfer:
                   1228:                elif test $size = any; then
                   1229:                    echo "    tme_memory_sequence_${lockname}lock(tlb->tme_m68k_tlb_bus_rwlock);"
                   1230:                    if test $name = read; then
                   1231:                        echo "    memcpy(${regptr}, ${memptr}, ${count});"
                   1232:                    else
                   1233:                        echo "    memcpy(${memptr}, ${regptr}, ${count});"
                   1234:                    fi
                   1235:                    echo "    tme_memory_sequence_unlock(tlb->tme_m68k_tlb_bus_rwlock);"
                   1236: 
                   1237:                fi
                   1238:                echo "    TME_M68K_SEQUENCE_TRANSFER_STEP;"
                   1239:                echo "  }"
                   1240: 
                   1241:                echo ""
                   1242:                echo "  /* otherwise, do the bus cycles the slow way: */"
                   1243:                echo "  else {"
                   1244:                if test $size != any; then
                   1245:                    echo "    tme_m68k_${name}${size}(ic, tlb,"
                   1246:                    echo "                    ${fcptr},"
                   1247:                    echo "                    ${addrptr},"
                   1248:                    echo "                    ${regptr},"
                   1249:                    echo "                    ${flags});"
                   1250:                else
                   1251:                    echo "    tme_m68k_${name}(ic, tlb, ${fcptr}, ${addrptr}, ${regptr}, ${count}, TME_M68K_BUS_CYCLE_RAW);"
                   1252:                fi
                   1253:                echo "  }"
                   1254:                
                   1255:                # if this is a read, log the value read:
                   1256:                if test $name = read; then
                   1257:                    echo ""
                   1258:                    echo "  /* log the value read: */"
                   1259:                    if test $size != any; then
                   1260:                        echo "  tme_m68k_verify_mem${size}(ic, ${fc}, ${addr}, ${reg}, TME_BUS_CYCLE_READ);"
                   1261:                        echo "  tme_m68k_log(ic, 1000, TME_OK,"
                   1262:                        echo "               (TME_M68K_LOG_HANDLE(ic),"
                   1263:                        echo "                _(\"${action}\t%d:0x%08x:\t0x%0"`expr ${size} / 4`"x\"),"
                   1264:                        echo "                ${fc},"
                   1265:                        echo "                ${addr},"
                   1266:                        echo "                ${reg}));"
                   1267:                    else
                   1268:                        echo "  tme_m68k_verify_mem_any(ic, ${fc}, ${addr}, ${regptr}, ${count}, TME_BUS_CYCLE_READ);"
                   1269:                        echo "  tme_m68k_log_start(ic, 1000, TME_OK) {"
                   1270:                        echo "    unsigned int byte_i;"
                   1271:                        echo "    tme_log_part(TME_M68K_LOG_HANDLE(ic),"
                   1272:                        echo "                 _(\"${action} %d:0x%08x count %d:\"),"
                   1273:                        echo "                 ${fc},"
                   1274:                        echo "                 ${addr},"
                   1275:                        echo "                 ${count});"
                   1276:                        echo "    for (byte_i = 0; byte_i < count ; byte_i++) {"
                   1277:                        echo "      tme_log_part(TME_M68K_LOG_HANDLE(ic), \" 0x%02x\", (${regptr})[byte_i]);"
                   1278:                        echo "    }"
                   1279:                        echo "  } tme_m68k_log_finish(ic);"
                   1280:                    fi
                   1281:                fi
                   1282: 
                   1283:                # perform any updating and value returning:
                   1284:                case "$what" in
                   1285:                stack)
                   1286:                    if test $name = read; then dir="+"; else dir="-"; fi
                   1287:                    echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
                   1288:                    echo "    ic->tme_m68k_ireg_a7 ${dir}= sizeof(tme_uint${size}_t);"
                   1289:                    echo "  }"
                   1290:                    ;;
                   1291:                inst)
                   1292:                    echo "  ic->_tme_m68k_insn_buffer_off = insn_buffer_off + sizeof(tme_uint${size}_t);"
                   1293:                    echo "  return(${reg});"
                   1294:                    ;;
                   1295:                esac
                   1296: 
                   1297:                echo "}"
                   1298:            :
                   1299:        done
                   1300: 
                   1301:        # the general-purpose cycle-making read and write macros:
                   1302:        if test ${size} != any; then
                   1303: 
                   1304:            # if we're making the header, emit a macro:
                   1305:            if $header; then
                   1306:                echo "#define tme_m68k_${name}${size}(ic, t, fc, la, _v, f) \\"
                   1307:                echo "  tme_m68k_${name}(ic, t, fc, la, (tme_uint8_t *) (_v), sizeof(tme_uint${size}_t), f)"
                   1308:            fi
                   1309:        else
                   1310: 
                   1311:            # if we're making the header, just emit a declaration:
                   1312:            if $header; then
                   1313:                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));"
                   1314:                continue
                   1315:            fi
                   1316: 
                   1317:            echo ""
                   1318:            echo "/* this ${name}s a region of address space using actual bus cycles: */"
                   1319:            echo "void"
                   1320:            echo "tme_m68k_${name}(struct tme_m68k *ic, "
                   1321:            echo "              struct tme_m68k_tlb *tlb,"
                   1322:            echo "              unsigned int *_function_code, "
                   1323:            echo "              tme_uint32_t *_linear_address, "
                   1324:            echo "              tme_uint8_t *reg,"
                   1325:            echo "              unsigned int reg_size,"
                   1326:            echo "              unsigned int flags)"
                   1327:            echo "{"
                   1328: 
                   1329:            # our locals:
                   1330:            echo "  unsigned int function_code;"
                   1331:            echo "  tme_uint32_t linear_address;"
                   1332:            echo "  tme_bus_addr_t physical_address;"
                   1333:            echo "  int shift;"
                   1334:            echo "  struct tme_bus_cycle cycle;"
                   1335:            echo "  unsigned int transferred, resid, cycle_size;"
                   1336:            echo "  int exception;"
                   1337:            echo "  tme_rwlock_t *rmw_rwlock;"
                   1338:            echo "  int err;"
                   1339:            echo "#ifndef WORDS_BIGENDIAN"
                   1340:            echo "  tme_uint8_t *reg_p;"
                   1341:            echo "  unsigned int buffer_i;"
                   1342:            echo "#endif /* !WORDS_BIGENDIAN */"
                   1343: 
                   1344:            echo ""
                   1345:            echo "  /* if we're not restarting, everything is fresh: */"
                   1346:            echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
                   1347:            echo "    function_code = *_function_code;"
                   1348:            echo "    linear_address = *_linear_address;"
                   1349:            echo "    transferred = 0;"
                   1350:            echo "  }"
                   1351: 
                   1352:            echo ""
                   1353:            echo "  /* otherwise, if this is the transfer that faulted, restore"
                   1354:            echo "     our state to the cycle that faulted, then take into account"
                   1355:            echo "     any data provided by a software rerun of the faulted cycle: */"
                   1356:            echo "  else if (ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted"
                   1357:            echo "           == ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next) {"
                   1358:            echo "    function_code = *_function_code = ic->_tme_m68k_group0_function_code;"
                   1359:            echo "    linear_address = ic->_tme_m68k_group0_address;"
                   1360:            echo "    transferred = ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted_after;"
                   1361:            echo "    if (transferred >= reg_size) abort();"
                   1362:            echo "    *_linear_address = linear_address - transferred;"
                   1363:            echo "    resid = reg_size - transferred;"
                   1364:            echo "    if (ic->_tme_m68k_group0_buffer_${name}_size > resid) abort();"
                   1365:            echo "    if (ic->_tme_m68k_group0_buffer_${name}_softrr > resid) abort();"
                   1366:            if test $name = read; then cmp=">"; else cmp="=="; fi
                   1367:            echo "    if (ic->_tme_m68k_group0_buffer_${name}_softrr ${cmp} 0) {"
                   1368:            echo "#ifdef WORDS_BIGENDIAN"
                   1369:            echo "      memcpy(reg + transferred, "
                   1370:            echo "             ic->_tme_m68k_group0_buffer_${name},"
                   1371:            echo "             ic->_tme_m68k_group0_buffer_${name}_size);"
                   1372:            echo "#else  /* !WORDS_BIGENDIAN */"
                   1373:            echo "      reg_p = (reg + reg_size - 1) - transferred;"
                   1374:            echo "      for (buffer_i = 0;"
                   1375:            echo "           buffer_i < ic->_tme_m68k_group0_buffer_${name}_size;"
                   1376:            echo "           buffer_i++) {"
                   1377:            echo "        *(reg_p--) = ic->_tme_m68k_group0_buffer_${name}[buffer_i];"
                   1378:            echo "      }"
                   1379:            echo "#endif /* !WORDS_BIGENDIAN */"
                   1380:            echo "    }"
                   1381:            echo "    transferred += ic->_tme_m68k_group0_buffer_${name}_softrr;"
                   1382:            echo "  }"
                   1383: 
                   1384:            echo ""
                   1385:            echo "  /* otherwise, a later transfer has faulted.  just step the"
                   1386:            echo "     transfer number and return: */"
                   1387:            echo "  else {"
                   1388:            echo "    TME_M68K_SEQUENCE_TRANSFER_STEP;"
                   1389:            echo "    return;"
                   1390:            echo "  }"
                   1391: 
                   1392:            echo ""
                   1393:            echo "  /* do as many bus cycles as needed to complete the transfer: */"
                   1394:            echo "  rmw_rwlock = tlb->tme_m68k_tlb_bus_rwlock;"
                   1395:            echo "  exception = TME_M68K_EXCEPTION_NONE;"
                   1396:            echo "  cycle_size = 0;"
                   1397:            echo "  for(; transferred < reg_size; ) {"
                   1398:            echo "    resid = reg_size - transferred;"
                   1399: 
                   1400:            echo ""
                   1401:            echo "    /* start the bus cycle structure: */"
                   1402:            echo "    cycle.tme_bus_cycle_type = TME_BUS_CYCLE_${capname};"
                   1403:            echo "    if (TME_ENDIAN_NATIVE == TME_ENDIAN_BIG"
                   1404:            echo "        || (flags & TME_M68K_BUS_CYCLE_RAW)) {"
                   1405:            echo "      cycle.tme_bus_cycle_buffer = reg + transferred;"
                   1406:            echo "      cycle.tme_bus_cycle_buffer_increment = 1;"
                   1407:            echo "    }"
                   1408:            echo "    else {"
                   1409:            echo "      cycle.tme_bus_cycle_buffer = reg + reg_size - (1 + transferred);"
                   1410:            echo "      cycle.tme_bus_cycle_buffer_increment = -1;"
                   1411:            echo "    }"
                   1412: 
                   1413:            echo ""
                   1414:            echo "    /* if we're emulating a CPU with a 16-bit bus interface: */"
                   1415:            echo "    if (ic->_tme_m68k_bus_16bit) {"
                   1416:            echo ""
                   1417:            echo "      /* if we're trying to transfer a non-power-of-two"
                   1418:            echo "         number of bytes, either the CPU is broken (no"
                   1419:            echo "         instructions ever transfer a non-power-of-two"
                   1420:            echo "         number of bytes), or this function allowed an"
                   1421:            echo "         unaligned transfer: */"
                   1422:            echo "      assert((resid & (resid - 1)) == 0"
                   1423:            echo "             || (flags & TME_M68K_BUS_CYCLE_RAW));"
                   1424:            echo ""
                   1425:            echo "      /* only byte transfers can be unaligned: */"
                   1426:            echo "      if (resid > sizeof(tme_uint8_t)"
                   1427:            echo "          && (linear_address & 1)) {"
1.1.1.3 ! root     1428:            echo "          exception = TME_M68K_EXCEPTION_AERR;"
1.1       root     1429:            echo "          break;"
                   1430:            echo "      }"
                   1431:            echo ""
                   1432:            echo "      /* set the bus-size specific parts of the bus cycle structure: */"
                   1433:            echo "      cycle_size = TME_MIN(resid, sizeof(tme_uint16_t));"
                   1434:            echo "      cycle.tme_bus_cycle_size = cycle_size;"
                   1435:            echo "      cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS16_LOG2);"
                   1436:            echo "      cycle.tme_bus_cycle_lane_routing = "
                   1437:            echo "        &tme_m68k_router_16[TME_M68K_BUS_ROUTER_INDEX(TME_BUS16_LOG2, cycle_size, linear_address)];"
                   1438:            echo "    }"
                   1439:            echo ""
                   1440:            echo "    /* otherwise we're emulating a CPU with a 32-bit bus interface: */"
                   1441:            echo "    else {"
                   1442:            if test $name = read; then
                   1443:                echo ""
                   1444:                echo "      /* an instruction fetch must be aligned: */"
                   1445:                echo "      if (flags & TME_M68K_BUS_CYCLE_FETCH) {"
                   1446:                echo "        if (linear_address & 1) {"
1.1.1.3 ! root     1447:                echo "          exception = TME_M68K_EXCEPTION_AERR;"
1.1       root     1448:                echo "          break;"
                   1449:                echo "        }"
                   1450:                echo "        assert(!(resid & 1));"
                   1451:                echo "      }"
                   1452:            fi
                   1453:            echo ""
                   1454:            echo "      /* set the bus-size specific parts of the bus cycle structure: */"
                   1455:            echo "      cycle_size = TME_MIN(resid, sizeof(tme_uint32_t) - (linear_address & (sizeof(tme_uint32_t) - 1)));"
                   1456:            echo "      cycle.tme_bus_cycle_size = cycle_size;"
                   1457:            echo "      cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS32_LOG2);"
                   1458:            echo "      cycle.tme_bus_cycle_lane_routing = "
                   1459:            echo "        &tme_m68k_router_32[TME_M68K_BUS_ROUTER_INDEX(TME_BUS32_LOG2, cycle_size, linear_address)];"
                   1460:            echo "    }"
                   1461:        
                   1462:            echo ""
                   1463:            echo "    /* reload the TLB entry: */"
                   1464:            echo "    if (!TME_M68K_TLB_OK_SLOW_${capname}(tlb, function_code, linear_address)) {"
                   1465:            echo "      tme_m68k_tlb_fill(ic, tlb,"
                   1466:            echo "                        function_code,"
                   1467:            echo "                        linear_address,"
                   1468:            echo "                        TME_BUS_CYCLE_${capname});"
                   1469:            echo "    }"
                   1470:            echo ""
                   1471:            echo "    /* if this is a part of a read/modify/write cycle: */"
                   1472:            echo "    if (flags & TME_M68K_BUS_CYCLE_RMW) {"
                   1473:            echo ""
                   1474:            echo "      /* if this TLB entry doesn't support fast ${name}s, or"
                   1475:            echo "         if the TLB lock has changed, that's a bus error."
                   1476:            echo "         see the discussion in tme_m68k_rmw_start: */"
                   1477:            echo "      if (!TME_M68K_TLB_OK_FAST_${capname}(tlb, function_code, linear_address, linear_address)"
                   1478:            echo "          || (rmw_rwlock != NULL"
                   1479:            echo "              && rmw_rwlock != tlb->tme_m68k_tlb_bus_rwlock)) {"
1.1.1.3 ! root     1480:            echo "        exception = TME_M68K_EXCEPTION_BERR;"
1.1       root     1481:            echo "        break;"
                   1482:            echo "      }"
                   1483:            echo ""
                   1484:            echo "      /* if we haven't locked this memory yet, do so: */"
                   1485:            echo "      if (rmw_rwlock == NULL) {"
                   1486:            echo "        rmw_rwlock = tlb->tme_m68k_tlb_bus_rwlock;"
                   1487:            echo "        tme_rwlock_wrlock(rmw_rwlock);"
                   1488:            echo "      }"
                   1489:            echo "    }"
                   1490: 
                   1491:            echo ""
                   1492:            echo "    /* form the physical address for the bus cycle handler: */"
                   1493:            echo "    physical_address = tlb->tme_m68k_tlb_addr_offset + linear_address;"
                   1494:            echo "    shift = tlb->tme_m68k_tlb_addr_shift;"
                   1495:            echo "    if (shift < 0) {"
                   1496:            echo "      physical_address <<= (0 - shift);"
                   1497:            echo "    }"
                   1498:            echo "    else if (shift > 0) {"
                   1499:            echo "      physical_address >>= shift;"
                   1500:            echo "    }"
                   1501:            echo "    cycle.tme_bus_cycle_address = physical_address;"
                   1502: 
                   1503:            echo ""
                   1504:            echo "    /* run the bus cycle: */"
                   1505:            echo "    err = (*tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycle)"
                   1506:            echo "         (tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycle_private, &cycle);"
                   1507:            echo ""
                   1508:            echo "    /* if we deadlocked, we have no locks to release"
                   1509:            echo "       ourselves, so sleep a while waiting for things"
                   1510:            echo "       to clear up, then try again: */"
                   1511:            echo "    if (err == TME_EDEADLK) {"
                   1512:            echo "      TME_THREAD_DEADLOCK_SLEEP();"
                   1513:            echo "      cycle.tme_bus_cycle_address = physical_address;"
                   1514:            echo "    }"
                   1515:            echo ""
1.1.1.3 ! root     1516:            echo "    /* otherwise, if we didn't get a bus error, but some"
        !          1517:            echo "       synchronous event has happened: */"
        !          1518:            echo "    else if (err == TME_BUS_CYCLE_SYNCHRONOUS_EVENT) {"
        !          1519:            echo ""
        !          1520:            echo "      /* after the currently executing instruction finishes, check"
        !          1521:            echo "         for external resets, halts, or interrupts: */"
        !          1522:            echo "      ic->_tme_m68k_instruction_burst_remaining = 0;"
        !          1523:            echo "    }"
        !          1524:            echo ""
1.1       root     1525:            echo "    /* otherwise, any other error might be a bus error: */"
                   1526:            echo "    else if (err != TME_OK) {"
                   1527:            echo "      err = tme_bus_tlb_fault(&tlb->tme_m68k_tlb_bus_tlb, &cycle, err);"
                   1528:            echo "      if (err != TME_OK) {"
1.1.1.3 ! root     1529:            echo "        exception = TME_M68K_EXCEPTION_BERR;"
1.1       root     1530:            echo "        break;"
                   1531:            echo "      }"
                   1532:            echo "    }"
                   1533:            echo ""
                   1534:            echo "    /* update: */"
                   1535:            echo "    linear_address += cycle.tme_bus_cycle_size;"
                   1536:            echo "    transferred += cycle.tme_bus_cycle_size;"
                   1537:            echo "  }"
                   1538:        
                   1539:            echo ""
                   1540:            echo "  /* if we got an exception and there is a locked"
                   1541:            echo "     read/modify/write rwlock, unlock it: */"
                   1542:            echo "  if (exception != TME_M68K_EXCEPTION_NONE"
                   1543:            echo "      && (flags & TME_M68K_BUS_CYCLE_RMW)"
                   1544:            echo "      && rmw_rwlock != NULL) {"
                   1545:            echo "    tme_rwlock_unlock(rmw_rwlock);"
                   1546:            echo "  }"
                   1547: 
                   1548:            echo ""
                   1549:            echo "  /* if we faulted, stash the information the fault stacker"
                   1550:            echo "     will need and start exception processing: */"
                   1551:            echo "  if (exception != TME_M68K_EXCEPTION_NONE) {"
                   1552:            echo -n "    ic->_tme_m68k_group0_flags = flags"
                   1553:            if test $name = read; then
                   1554:                echo -n " | TME_M68K_BUS_CYCLE_READ"
                   1555:            fi
                   1556:            echo ";"
                   1557:            echo "    ic->_tme_m68k_group0_function_code = function_code;"
                   1558:            echo "    ic->_tme_m68k_group0_address = linear_address;"
                   1559:            echo "    ic->_tme_m68k_group0_sequence = ic->_tme_m68k_sequence;"
                   1560:            echo "    ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted_after = transferred;"
                   1561:            echo "    ic->_tme_m68k_group0_buffer_${name}_size = cycle_size;"
                   1562:            if test $name = write; then
                   1563:                echo "#ifdef WORDS_BIGENDIAN"
                   1564:                echo "    memcpy(ic->_tme_m68k_group0_buffer_${name},"
                   1565:                echo "           reg + transferred,"
                   1566:                echo "           ic->_tme_m68k_group0_buffer_${name}_size);"
                   1567:                echo "#else  /* !WORDS_BIGENDIAN */"
                   1568:                echo "      reg_p = (reg + reg_size - 1) - transferred;"
                   1569:                echo "      for (buffer_i = 0;"
                   1570:                echo "           buffer_i < ic->_tme_m68k_group0_buffer_${name}_size;"
                   1571:                echo "           buffer_i++) {"
                   1572:                echo "        ic->_tme_m68k_group0_buffer_${name}[buffer_i] = *(reg_p--);"
                   1573:                echo "      }"
                   1574:                echo "#endif /* !WORDS_BIGENDIAN */"
                   1575:            fi
                   1576:            echo "    if (ic->_tme_m68k_group0_hook != NULL) {"
                   1577:            echo "      (*ic->_tme_m68k_group0_hook)(ic);"
                   1578:            echo "    }"
                   1579:            echo "    ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted = ";
                   1580:            echo "      ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_next;"
                   1581:            echo "    tme_m68k_exception(ic, exception);"
                   1582:            echo "  }"
                   1583: 
                   1584:            echo ""
                   1585:            echo "  /* otherwise, this transfer has now completed: */"
                   1586:            echo "  TME_M68K_SEQUENCE_TRANSFER_STEP;"
                   1587: 
                   1588:            echo "}"
                   1589:        fi
                   1590:     done
                   1591: 
                   1592: done
                   1593: 
                   1594: # generate the BCD math functions:
                   1595: for name in abcd sbcd nbcd; do
                   1596: 
                   1597:     # if we're making the header, just emit a declaration:
                   1598:     if $header; then
                   1599:        echo "TME_M68K_INSN_DECL(tme_m68k_${name});"
                   1600:        continue
                   1601:     fi
                   1602: 
                   1603:     # emit the function:
                   1604:     echo ""
                   1605:     echo "TME_M68K_INSN(tme_m68k_${name})"
                   1606:     echo "{"
                   1607:     echo "  tme_uint8_t dst, dst_msd, dst_lsd;"
                   1608:     echo "  tme_uint8_t src, src_msd, src_lsd;"
                   1609:     echo "  tme_uint8_t res, res_msd, res_lsd;"
                   1610:     echo "  tme_uint8_t flags;"
                   1611: 
                   1612:     # get the operands:
                   1613:     if test $name != nbcd; then
                   1614:        echo "  int memory;"
                   1615:        echo "  int rx, ry, function_code;"
                   1616:        echo ""
                   1617:        echo "  TME_M68K_INSN_CANFAULT;"
                   1618:        echo ""
                   1619:        echo "  /* load the operands: */"
                   1620:        echo "  rx = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);"
                   1621:        echo "  ry = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);"
                   1622:        echo "  memory = (TME_M68K_INSN_OPCODE & TME_BIT(3)) != 0;"
                   1623:        echo "  function_code = TME_M68K_FUNCTION_CODE_DATA(ic);"
                   1624:        echo "  if (memory) {"
                   1625:        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
                   1626:        echo "      ic->_tme_m68k_ea_function_code = function_code;"
                   1627:        echo "      ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + rx);"
                   1628:        echo "    }"
                   1629:        echo "    tme_m68k_read_memx8(ic);"
                   1630:        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
                   1631:        echo "      ic->_tme_m68k_ea_function_code = function_code;"
                   1632:        echo "      ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry);"
                   1633:        echo "    }"
                   1634:        echo "    tme_m68k_read_mem8(ic, TME_M68K_IREG_MEMY32);"
                   1635:        echo "    src = ic->tme_m68k_ireg_memx8;"
                   1636:        echo "    dst = ic->tme_m68k_ireg_memy8;"
                   1637:        echo "  }"
                   1638:        echo "  else {"
                   1639:        echo "    src = ic->tme_m68k_ireg_uint8(rx << 2);"
                   1640:        echo "    dst = ic->tme_m68k_ireg_uint8(ry << 2);"
                   1641:        echo "  }"
                   1642:     else
                   1643:        echo ""
                   1644:        echo "  dst = 0x00;"
                   1645:        echo "  src = TME_M68K_INSN_OP1(tme_uint8_t);"
                   1646:     fi
                   1647:     echo "  dst_lsd = TME_FIELD_EXTRACTU(dst, 0, 4);"
                   1648:     echo "  dst_msd = TME_FIELD_EXTRACTU(dst, 4, 4);"
                   1649:     echo "  src_lsd = TME_FIELD_EXTRACTU(src, 0, 4);"
                   1650:     echo "  src_msd = TME_FIELD_EXTRACTU(src, 4, 4);"
                   1651: 
                   1652:     # perform the operation:
                   1653:     echo ""
                   1654:     echo "  /* perform the operation: */"
                   1655:     if test $name = abcd; then op='+' ; opc='-' ; else op='-' ; opc='+' ; fi
                   1656:     echo "  res_lsd = dst_lsd ${op} src_lsd ${op} ((ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X) != 0);"
                   1657:     echo "  res_msd = dst_msd ${op} src_msd;"
                   1658:     echo "  flags = 0;"
                   1659:     echo "  if (res_lsd > 9) {"
                   1660:     echo "    res_lsd ${opc}= 10;"
                   1661:     echo "    res_msd ${op}= 1;"
                   1662:     echo "  }"
                   1663:     echo "  if (res_msd > 9) {"
                   1664:     echo "    res_msd ${opc}= 10;"
                   1665:     echo "    flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;"
                   1666:     echo "  }"
                   1667:     echo "  res = (res_msd << 4) + (res_lsd & 0xf);"
                   1668:     echo "  if (res == 0) flags |= TME_M68K_FLAG_N;"
                   1669:     echo ""
                   1670: 
                   1671:     # store the result
                   1672:     echo "  /* store the result and set the flags: */"
                   1673:     if test $name != nbcd; then
                   1674:        echo "  if (memory) {"
                   1675:        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
                   1676:        echo "      ic->tme_m68k_ireg_memx8 = res;"
                   1677:        echo "      ic->_tme_m68k_ea_function_code = function_code;"
                   1678:        echo "      ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry);"
                   1679:        # the stack pointer must always be incremented by a multiple of two.
                   1680:        # assuming rx < 8, ((rx + 1) >> 3) == 1 iff rx == 7, meaning %a7:
                   1681:        echo "      ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + rx) += sizeof(tme_uint8_t) + ((rx + 1) >> 3);"
                   1682:        echo "      ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry) += sizeof(tme_uint8_t) + ((ry + 1) >> 3);"
                   1683:        echo "      ic->tme_m68k_ireg_ccr = flags;"
                   1684:        echo "     }"
                   1685:        echo "     tme_m68k_write_memx8(ic);"
                   1686:        echo "  }"
                   1687:        echo "  else {"
                   1688:        echo "    ic->tme_m68k_ireg_uint8(ry << 2) = res;"
                   1689:        echo "    ic->tme_m68k_ireg_ccr = flags;"
                   1690:        echo "  }"
                   1691:     else
                   1692:        echo "  TME_M68K_INSN_OP1(tme_uint8_t) = res;"
                   1693:        echo "  ic->tme_m68k_ireg_ccr = flags;"
                   1694:     fi
                   1695:     echo ""
                   1696:     echo "  TME_M68K_INSN_OK;"
                   1697:     echo "}"
                   1698: done
                   1699: 
                   1700: # generate the ccr and sr functions:
                   1701: for reg in ccr sr; do
                   1702:     for name in ori andi eori move_to; do
                   1703:        if test $reg = ccr; then size=8 ; else size=16 ; fi
                   1704: 
                   1705:        # if we're making the header, just emit a declaration:
                   1706:        if $header; then
                   1707:            echo "TME_M68K_INSN_DECL(tme_m68k_${name}_${reg});"
                   1708:            continue
                   1709:        fi
                   1710: 
                   1711:        # emit the function:
                   1712:        echo ""
                   1713:        echo "TME_M68K_INSN(tme_m68k_${name}_${reg})"
                   1714:        echo "{"
                   1715:        echo "  tme_uint${size}_t reg;"
                   1716: 
                   1717:        # form the new register value:
                   1718:        src=0
                   1719:        echo -n "  reg = "
                   1720:        case $name in
                   1721:        ori) echo -n "ic->tme_m68k_ireg_${reg} | " ;;
                   1722:        andi) echo -n "ic->tme_m68k_ireg_${reg} & " ;;
                   1723:        eori) echo -n "ic->tme_m68k_ireg_${reg} ^ " ;;
                   1724:        move_to) size=16 ; src=1 ;;
                   1725:        esac
                   1726:        echo "(TME_M68K_INSN_OP${src}(tme_uint${size}_t) & TME_M68K_FLAG_"`echo $reg | tr a-z A-Z`");"
                   1727:        
                   1728:        # sr changes are special:
                   1729:        if test $reg = sr; then
                   1730:            echo "  TME_M68K_INSN_PRIV;"
                   1731:            echo "  TME_M68K_INSN_CHANGE_SR(reg);"
                   1732:        else
                   1733:            echo "  ic->tme_m68k_ireg_${reg} = reg;"
                   1734:        fi
                   1735: 
                   1736:        echo "  TME_M68K_INSN_OK;"
                   1737:        echo "}"
                   1738:     done
                   1739: done
                   1740: 
                   1741: # generate the multiply and divide instructions:
                   1742: 
                   1743: # permute on signed vs. unsigned:
                   1744: for _sign in u s; do
                   1745:     if test $_sign = u; then sign=u; else sign=; fi
                   1746: 
                   1747:     # permute on short vs. long:
                   1748:     for size in s l; do
                   1749:        if test $size = s; then 
                   1750:            _size=
                   1751:            small=16
                   1752:            large=32
                   1753:            reg_size_shift=' << 1'
                   1754:        else
                   1755:            _size=l
                   1756:            small=32
                   1757:            large=64
                   1758:            reg_size_shift=
                   1759:        fi
                   1760: 
                   1761:        # if we're making the header, just emit declarations:
                   1762:        if $header; then
                   1763:            echo "TME_M68K_INSN_DECL(tme_m68k_mul${_sign}${_size});"
                   1764:            echo "TME_M68K_INSN_DECL(tme_m68k_div${_sign}${_size});"
                   1765:            continue
                   1766:        fi
                   1767: 
                   1768:        # emit the multiply function:
                   1769:        echo ""
                   1770:        echo "TME_M68K_INSN(tme_m68k_mul${_sign}${_size})"
                   1771:        echo "{"
                   1772:        if test $large = 64; then
1.1.1.2   root     1773:            echo "#ifndef TME_HAVE_INT${large}_T"
1.1       root     1774:            echo "  abort();"
1.1.1.2   root     1775:            echo "#else /* TME_HAVE_INT${large}_T */"
1.1       root     1776:            echo "  unsigned int flag_v;"
                   1777:            echo "  int ireg_dh;"
                   1778:        fi
                   1779:        echo "  int ireg_dl;"
                   1780:        echo "  tme_${sign}int${large}_t res;"
                   1781:        echo "  tme_uint8_t flags;"
                   1782: 
                   1783:        echo ""
                   1784:        echo "  /* get the register containing the factor: */"
                   1785:        echo -n "  ireg_dl = TME_M68K_IREG_D0 + "
                   1786:        if test $size = s; then
                   1787:            echo "TME_M68K_INSN_OP0(tme_uint32_t);"
                   1788:        else
                   1789:            echo "TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3);"
                   1790:        fi
                   1791: 
                   1792:        echo ""
                   1793:        echo "  /* perform the multiplication: */"
                   1794:        echo "  res = (((tme_${sign}int${large}_t) ic->tme_m68k_ireg_${sign}int${small}(ireg_dl${reg_size_shift}))"
                   1795:        echo "         * TME_M68K_INSN_OP1(tme_${sign}int${small}_t));"
                   1796:        
                   1797:        echo ""
                   1798:        echo "  /* store the result: */"
                   1799:        echo "  ic->tme_m68k_ireg_${sign}int32(ireg_dl) = (tme_${sign}int32_t) res;"
                   1800:        if test $large = 64; then
                   1801:            echo "  flag_v = TME_M68K_FLAG_V;"
                   1802:            echo "  if (TME_M68K_INSN_SPECOP & TME_BIT(10)) {"
                   1803:            echo "    flag_v = 0;"
                   1804:            echo "    ireg_dh = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3);"
                   1805:            echo "    ic->tme_m68k_ireg_${sign}int32(ireg_dh) = (tme_${sign}int32_t) (res >> 32);"
                   1806:            echo "  }"
                   1807:        fi
                   1808:        
                   1809:        echo ""
                   1810:        echo "  /* set the flags: */"
                   1811:        echo "  flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;"
                   1812:        echo "  if (((tme_int${large}_t) res) < 0) flags |= TME_M68K_FLAG_N;"
                   1813:        echo "  if (res == 0) flags |= TME_M68K_FLAG_Z;"
                   1814:        if test $large = 64; then
1.1.1.2   root     1815:            if test $_sign = s; then
                   1816:                echo -n "  if (res > 0x7fffffffL || res < ((0L - 0x7fffffffL) - 1L)"
                   1817:            else
                   1818:                echo -n "  if (res > 0xffffffffUL"
                   1819:            fi
1.1       root     1820:            echo ") flags |= flag_v;"
                   1821:        fi
                   1822:        echo "  ic->tme_m68k_ireg_ccr = flags;"
                   1823: 
                   1824:        echo ""
                   1825:        echo "  TME_M68K_INSN_OK;"
                   1826:        if test $large = 64; then
1.1.1.2   root     1827:            echo "#endif /* TME_HAVE_INT${large}_T */"
1.1       root     1828:        fi
                   1829:        echo "}"
                   1830: 
                   1831:        # emit the divide function:
                   1832:        echo ""
                   1833:        echo "TME_M68K_INSN(tme_m68k_div${_sign}${_size})"
                   1834:        echo "{"
                   1835:        if test $large = 64; then
1.1.1.2   root     1836:            echo "#ifndef TME_HAVE_INT${large}_T"
1.1       root     1837:            echo "  abort();"
1.1.1.2   root     1838:            echo "#else /* TME_HAVE_INT${large}_T */"
1.1       root     1839:            echo "  int ireg_dr;"
                   1840:        fi
                   1841:        echo "  int ireg_dq;"
                   1842:        echo "  tme_${sign}int${large}_t dividend, quotient;"
                   1843:        echo "  tme_${sign}int${small}_t divisor, remainder;"
                   1844:        echo "  tme_uint8_t flags;"
                   1845: 
                   1846:        echo ""
                   1847:        echo "  /* get the register(s): */"
                   1848:        echo -n "  ireg_dq = TME_M68K_IREG_D0 + "
                   1849:        if test $size = s; then
                   1850:            echo "TME_M68K_INSN_OP0(tme_uint32_t);"
                   1851:        else
                   1852:            echo "TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3);"
                   1853:            echo "  ireg_dr = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3);"
                   1854:        fi
                   1855: 
                   1856:        echo ""
                   1857:        echo "  /* form the dividend and the divisor: */"
                   1858:        if test $large = 64; then
                   1859:            echo "  if (TME_M68K_INSN_SPECOP & TME_BIT(10)) {"
                   1860:            echo "    dividend = (tme_${sign}int${large}_t)"
                   1861:            echo "               ((((tme_uint${large}_t) ic->tme_m68k_ireg_uint32(ireg_dr)) << 32)"
                   1862:            echo "                | ic->tme_m68k_ireg_uint32(ireg_dq));"
                   1863:            echo "  }"
                   1864:            echo "  else"
                   1865:            echo -n "  "
                   1866:        fi
                   1867:        echo "  dividend = (tme_${sign}int${large}_t) ic->tme_m68k_ireg_${sign}int32(ireg_dq);"
                   1868:        echo "  divisor = TME_M68K_INSN_OP1(tme_${sign}int${small}_t);"
                   1869:        echo "  if (divisor == 0) {"
1.1.1.3 ! root     1870:        echo "    ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;"
1.1       root     1871:        echo "    ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;"
1.1.1.3 ! root     1872:        echo "    TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_DIV0));"
1.1       root     1873:        echo "  }"
                   1874: 
                   1875:        echo ""
                   1876:        echo "  /* do the division: */"
                   1877:        echo "  quotient = dividend / divisor;"
                   1878:        echo "  remainder = dividend % divisor;"
                   1879: 
                   1880:        echo ""
                   1881:        echo "  /* set the flags and return the quotient and remainder: */"
                   1882:        echo "  flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;"
1.1.1.2   root     1883:        echo -n "  if ("
                   1884:        case "${small}${_sign}" in
                   1885:        16s) echo -n "quotient > 0x7fff || quotient < -32768" ;;
                   1886:        16u) echo -n "quotient > 0xffff" ;;
                   1887:        32s) echo -n "quotient > 0x7fffffffL || quotient < ((0L - 0x7fffffffL) - 1L)" ;;
                   1888:        32u) echo -n "quotient > 0xffffffffUL" ;;
                   1889:        esac
1.1       root     1890:        echo ") {"
                   1891:        echo "    flags |= TME_M68K_FLAG_V;"
                   1892:        echo "  }"
                   1893:        echo "  else {"
                   1894:        echo "    if (((tme_int${small}_t) quotient) < 0) flags |= TME_M68K_FLAG_N;"
                   1895:        echo "    if (quotient == 0) flags |= TME_M68K_FLAG_Z;"
                   1896:        echo "    ic->tme_m68k_ireg_${sign}int${small}(ireg_dq${reg_size_shift}) = (tme_${sign}int${small}_t) quotient;"
                   1897:        if test $small = 16; then
                   1898:            echo "    ic->tme_m68k_ireg_${sign}int${small}((ireg_dq${reg_size_shift}) + 1) = remainder;"
                   1899:        else
                   1900:            echo "    if (ireg_dr != ireg_dq) {"
                   1901:            echo "      ic->tme_m68k_ireg_${sign}int${small}(ireg_dr) = remainder;"
                   1902:            echo "    }"
                   1903:        fi
                   1904:        echo "  }"
                   1905:        echo "  ic->tme_m68k_ireg_ccr = flags;"
                   1906: 
                   1907:        echo ""
                   1908:        echo "  TME_M68K_INSN_OK;"
                   1909:        if test $large = 64; then
1.1.1.2   root     1910:            echo "#endif /* TME_HAVE_INT${large}_T */"
1.1       root     1911:        fi
                   1912:        echo "}"
                   1913: 
                   1914:     done
                   1915: done
                   1916: 
                   1917: # done:
                   1918: exit 0

unix.superglobalmegacorp.com

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