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

1.1       root        1: #! /bin/sh
                      2: 
1.1.1.5 ! root        3: # $Id: m68k-insns-auto.sh,v 1.26 2009/08/29 19:38: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.5 ! root       51: _TME_RCSID("\$Id: m68k-insns-auto.sh,v 1.26 2009/08/29 19:38: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_src);"
                    166:                    echo "    ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) += ireg_src_adjust;"
                    167:                    echo "  }"
                    168:                    echo "  tme_m68k_read_mem${size}(ic, TME_M68K_IREG_MEMY${size});"
1.1.1.4   root      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_dst);"
                    172:                    echo "    ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) += ireg_dst_adjust;"
                    173:                    echo "  }"
                    174:                    echo "  tme_m68k_read_memx${size}(ic);"
1.1       root      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_src) -= ireg_src_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_src);"
                    191:                    echo "    }"
                    192:                    echo "    tme_m68k_read_mem${size}(ic, TME_M68K_IREG_MEMY${size});"
1.1.1.4   root      193:                    echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
                    194:                    echo "      ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) -= ireg_dst_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_dst);"
                    197:                    echo "    }"
                    198:                    echo "    tme_m68k_read_memx${size}(ic);"
1.1       root      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: 
1.1.1.4   root      344:     # generate the wrapper functions for a move of an address register
                    345:     # to a predecrement or postincrement EA with that same address
                    346:     # register:
                    347:     for name in pd pi; do
                    348: 
                    349:        # a move of an address registers are only word and long:
                    350:        if test $size = 8; then continue; fi
                    351: 
                    352:        # if we're making the header, just emit a declaration:
                    353:        if $header; then
                    354:            echo "TME_M68K_INSN_DECL(tme_m68k_move_sr${name}${size});"
                    355:            continue
                    356:        fi
                    357: 
                    358:        echo ""
                    359:        echo "/* a move of an address register to a predecrement or"
                    360:        echo "   postincrement EA with that same address register, must"
                    361:        echo "   store the original value of the address register.  since the"
                    362:        echo "   predecrement and postincrement code in the executer updates"
                    363:        echo "   the address register before the move has happened, we wrap"
                    364:        echo "   the normal move function in this one, that gives an op1"
                    365:        echo "   argument that is the original value of the address register: */"
                    366:        echo "TME_M68K_INSN(tme_m68k_move_sr${name}${size})"
                    367:        echo "{"
                    368:        if test ${name} = pd; then op='+'; else op='-'; fi
                    369:        echo "  /* NB: both this function and tme_m68k_move${size}()"
                    370:        echo "     get the source operand as _op1, and the destination"
                    371:        echo "     operand as _op0: */"
                    372:        echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
                    373:        echo "    *((tme_uint${size}_t *) _op0)"
                    374:        echo "      = (*((tme_uint${size}_t *) _op1)"
                    375:        echo "         ${op} sizeof(tme_uint${size}_t));"
                    376:        echo "  }"
                    377:        echo "  tme_m68k_move${size}(ic, _op0, _op0);"
                    378:        echo "}"
                    379:     done
                    380: 
1.1       root      381:     # generate the address math functions:
                    382:     for name in suba adda movea; do
                    383: 
                    384:        # the address math functions don't need an 8-bit version:
                    385:        if test $size = 8; then continue; fi
                    386: 
                    387:        # if we're making the header, just emit a declaration:
                    388:        if $header; then
                    389:            echo "TME_M68K_INSN_DECL(tme_m68k_${name}${size});"
                    390:            continue
                    391:        fi
                    392: 
                    393:        echo ""
                    394:        echo "/* the ${name} function on a ${size}-byte EA: */"
                    395:        echo "TME_M68K_INSN(tme_m68k_${name}${size})"
                    396:        echo "{"
                    397:        case $name in
                    398:        suba) op='-' ; src="_op0" ; dst="_op1" ;;
                    399:        adda) op='+' ; src="_op0" ; dst="_op1" ;;
                    400:        movea) op='' ; src="_op1" ; dst="_op0" ;;
                    401:        esac
                    402:        echo "  *((tme_int32_t *) ${dst}) ${op}= *((tme_int${size}_t *) ${src});"
                    403:        echo "  TME_M68K_INSN_OK;"
                    404:        echo "}"
                    405:     done
                    406:            
                    407:     # generate the bit functions:
                    408:     for name in btst bchg bclr bset; do
                    409:        
                    410:        # the bit functions don't need a 16-bit version:
                    411:        if test $size = 16; then continue; fi
                    412: 
                    413:        # if we're making the header, just emit a declaration:
                    414:        if $header; then
                    415:            echo "TME_M68K_INSN_DECL(tme_m68k_${name}${size});"
                    416:            continue
                    417:        fi
                    418: 
                    419:        echo ""
                    420:        echo "/* the ${name} function on a ${size}-byte EA: */"
                    421:        echo "TME_M68K_INSN(tme_m68k_${name}${size})"
                    422:        echo "{"
                    423:        echo "  tme_uint${size}_t value, bit;"
                    424:        echo "  bit = _TME_BIT(tme_uint${size}_t, TME_M68K_INSN_OP0(tme_uint8_t) & (${size} - 1));"
                    425:        echo "  value = TME_M68K_INSN_OP1(tme_uint${size}_t);"
                    426:        echo "  if (value & bit) {"
                    427:        echo "    ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z;"
                    428:        echo "  }"
                    429:        echo "  else {"
                    430:        echo "    ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z;"
                    431:        echo "  }"
                    432:        case ${name} in
                    433:        btst) ;;
                    434:        bchg) echo "  TME_M68K_INSN_OP1(tme_uint${size}_t) = value ^ bit;" ;;
                    435:        bclr) echo "  TME_M68K_INSN_OP1(tme_uint${size}_t) = value & ~bit;" ;;
                    436:        bset) echo "  TME_M68K_INSN_OP1(tme_uint${size}_t) = value | bit;" ;;
                    437:        esac
                    438:        echo "  TME_M68K_INSN_OK;"
                    439:        echo "}"
                    440:     done
                    441: 
                    442:     # generate the shift/rotate functions:
                    443:     for func in as ls ro rox; do
                    444:        for dir in l r; do
                    445:            name="${func}${dir}"
                    446: 
                    447:            # if we're making the header, just emit a declaration:
                    448:            if $header; then
                    449:                echo "TME_M68K_INSN_DECL(tme_m68k_${name}${size});"
                    450:                continue
                    451:            fi
                    452: 
                    453:            echo ""
                    454:            echo "/* the ${name} function on a ${size}-byte EA: */"
                    455:            echo "TME_M68K_INSN(tme_m68k_${name}${size})"
                    456:            echo "{"
                    457:            echo "  unsigned int count;"
                    458:            sign=u
                    459:            case "${name}" in
                    460:            asr) sign= ;;
1.1.1.2   root      461:            asl) echo "  tme_uint${size}_t sign_bits, sign_bits_mask;" ;;
1.1       root      462:            rox[lr]) echo "  tme_uint8_t xbit;" ;;
                    463:            *) ;;
                    464:            esac
                    465:            echo "  tme_${sign}int${size}_t res;"
                    466:            echo "  tme_uint8_t flags;"
                    467:            echo ""
                    468:            echo "  /* get the count and operand: */"
                    469:            echo "  count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;"
                    470:            echo "  res = TME_M68K_INSN_OP1(tme_${sign}int${size}_t);"
                    471: 
                    472:            echo ""
                    473:            echo "  /* generate the X, V, and C flags assuming the count is zero: */"
                    474:            echo "  flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;"
                    475:            case "${name}" in
                    476:            rox[lr])
                    477:                echo "  xbit = (flags / TME_M68K_FLAG_X);"
                    478:                echo "  flags |= (xbit * TME_M68K_FLAG_C);"
                    479:                ;;
                    480:            esac
                    481: 
                    482:            echo ""
                    483:            echo "  /* if the count is nonzero, update the result and"
                    484:            echo "     generate the X, V, and C flags: */"
                    485:            echo "  if (count > 0) {"
                    486:            case "${name}" in
1.1.1.3   root      487:            lsr)
1.1       root      488:                echo "    if (63 > SHIFTMAX_INT${size}_T"
                    489:                echo "        && count > ${size}) {"
                    490:                echo "      res = 0;"
                    491:                echo "    }"
                    492:                echo "    res >>= (count - 1);"
                    493:                echo "    flags = (res & 1);"
                    494:                echo "    flags *= TME_M68K_FLAG_C;"
                    495:                echo "    flags |= (flags * TME_M68K_FLAG_X);"
                    496:                echo "    res >>= 1;"
                    497:                ;;
1.1.1.3   root      498:            asr)
                    499:                echo "    if (63 > SHIFTMAX_INT${size}_T"
                    500:                echo "        && count > ${size}) {"
                    501:                echo "      res = 0 - (res < 0);"
                    502:                echo "    }"
                    503:                echo "#ifdef SHIFTSIGNED_INT${size}_T"
                    504:                echo "    res >>= (count - 1);"
                    505:                echo "#else  /* !SHIFTSIGNED_INT${size}_T */"
                    506:                echo "    for (; --count > 0; ) {"
                    507:                echo "      res = (res & ~((tme_${sign}int${size}_t) 1)) / 2;"
                    508:                echo "    }"
                    509:                echo "#endif /* !SHIFTSIGNED_INT${size}_T */"
                    510:                echo "    flags = (res & 1);"
                    511:                echo "    flags *= TME_M68K_FLAG_C;"
                    512:                echo "    flags |= (flags * TME_M68K_FLAG_X);"
                    513:                echo "#ifdef SHIFTSIGNED_INT${size}_T"
                    514:                echo "    res >>= 1;"
                    515:                echo "#else  /* !SHIFTSIGNED_INT${size}_T */"
                    516:                echo "    res = (res & ~((tme_${sign}int${size}_t) 1)) / 2;"
                    517:                echo "#endif /* !SHIFTSIGNED_INT${size}_T */"
                    518:                ;;
1.1       root      519:            [al]sl)
                    520:                if test ${name} = asl; then
                    521:                    echo ""
                    522:                    echo "    /* we need to see how the sign of the result will change during"
                    523:                    echo "       shifting in order to generate V."
                    524:                    echo ""
                    525:                    echo "       in general, the idea is to get all of the bits that will ever"
1.1.1.2   root      526:                    echo "       appear in the sign position into sign_bits, with a mask in"
                    527:                    echo "       sign_bits_mask.  if (sign_bits & sign_bits_mask) is zero or"
                    528:                    echo "       sign_bits_mask, clear V, else set V."
1.1       root      529:                    echo ""
1.1.1.2   root      530:                    echo "       start by loading the operand into sign_bits and setting"
                    531:                    echo "       sign_bits_mask to all-bits-one."
1.1       root      532:                    echo ""
                    533:                    echo "       if the shift count is exactly ${size} - 1, then all of the bits"
                    534:                    echo "       of the operand will appear in the sign position."
                    535:                    echo ""
                    536:                    echo "       if the shift count is less than ${size} - 1, then some of the"
                    537:                    echo "       less significant bits of the operand will never appear in the"
1.1.1.2   root      538:                    echo "       sign position, so we can shift sign_bits_mask to ignore them."
1.1       root      539:                    echo ""
                    540:                    echo "       if the shift count is greater than ${size} - 1, then all of the"
                    541:                    echo "       bits in the operand, plus at least one zero bit, will appear in"
                    542:                    echo "       the sign position.  the only way that the sign bit will never"
                    543:                    echo "       change during the shift is if the operand was zero to begin with."
1.1.1.2   root      544:                    echo "       without any changes to sign_bits or sign_bits_mask, the final"
                    545:                    echo "       test will always work, except when sign_bits is all-bits-one."
                    546:                    echo "       the magic below clears the least-significant bit of sign_bits"
                    547:                    echo "       iff sign_bits is all-bits-one: */"
1.1       root      548:                    echo "    sign_bits = res;"
                    549:                fi
                    550:                echo "    if (63 > SHIFTMAX_INT${size}_T"
                    551:                echo "        && count > ${size}) {"
                    552:                echo "      res = 0;"
                    553:                echo "    }"
                    554:                echo "    res <<= (count - 1);"
                    555:                echo "    flags = (res >> (${size} - 1));"
                    556:                echo "    flags *= TME_M68K_FLAG_C;"
                    557:                echo "    flags |= (flags * TME_M68K_FLAG_X);"
                    558:                echo "    res <<= 1;"
                    559:                if test ${name} = asl; then             
1.1.1.2   root      560:                    echo "    sign_bits_mask = (tme_uint${size}_t) -1;"
1.1       root      561:                    echo "    if (count != ${size} - 1) {"
                    562:                    echo "      if (count < ${size}) {"
1.1.1.2   root      563:                    echo "        sign_bits_mask <<= ((${size} - 1) - count);"
1.1       root      564:                    echo "      }"
                    565:                    echo "      else {"
1.1.1.2   root      566:                    echo "        sign_bits ^= !(sign_bits + 1);"
1.1       root      567:                    echo "      }"
                    568:                    echo "    }"                    
1.1.1.2   root      569:                    echo "    sign_bits &= sign_bits_mask;"
                    570:                    echo "    if (sign_bits != 0 && sign_bits != sign_bits_mask) {"
1.1       root      571:                    echo "      flags |= TME_M68K_FLAG_V;"
                    572:                    echo "    }"
                    573:                fi
                    574:                ;;
                    575:            ro[lr])
                    576:                echo "    count &= (${size} - 1);"
                    577:                if test $dir = l; then
                    578:                    echo "    res = (res << count) | (res >> (${size} - count));"
                    579:                    echo "    flags |= ((res & 1) * TME_M68K_FLAG_C);"
                    580:                else
                    581:                    echo "    res = (res << (${size} - count)) | (res >> count);"
                    582:                    echo "    flags |= ((res >> (${size} - 1)) * TME_M68K_FLAG_C);"
                    583:                fi
                    584:                ;;
                    585:            rox[lr])
                    586:                echo "    count %= (${size} + 1);"
                    587:                echo "    flags = xbit;"
                    588:                echo "    if (count > 0) {"
                    589:                if test $dir = l; then
                    590:                    echo "      flags = (res >> (${size} - count)) & 1;"
                    591:                    echo "      if (${size} > SHIFTMAX_INT${size}_T"
                    592:                    echo "          && count == ${size}) {"
                    593:                    echo "        res = 0 | (xbit << (${size} - 1)) | (res >> ((${size} + 1) - ${size}));"
                    594:                    echo "      }"
                    595:                    echo "      else if (${size} > SHIFTMAX_INT${size}_T"
                    596:                    echo "               && count == 1) {"
                    597:                    echo "        res = (res << 1) | (xbit << (1 - 1)) | 0;"
                    598:                    echo "      }"
                    599:                    echo "      else {"
                    600:                    echo "        res = (res << count) | (xbit << (count - 1)) | (res >> ((${size} + 1) - count));"
                    601:                    echo "      }"
                    602:                else
                    603:                    echo "      flags = (res >> (count - 1)) & 1;"
                    604:                    echo "      if (${size} > SHIFTMAX_INT${size}_T"
                    605:                    echo "          && count == ${size}) {"
                    606:                    echo "        res = (res << ((${size} + 1) - ${size})) | (xbit << (${size} - ${size})) | 0;"
                    607:                    echo "      }"
                    608:                    echo "      else if (${size} > SHIFTMAX_INT${size}_T"
                    609:                    echo "               && count == 1) {"
                    610:                    echo "        res = 0 | (xbit << (${size} - 1)) | (res >> 1);"
                    611:                    echo "      }"
                    612:                    echo "      else {"
                    613:                    echo "        res = (res << ((${size} + 1) - count)) | (xbit << (${size} - count)) | (res >> count);"
                    614:                    echo "      }"
                    615:                fi
                    616:                echo "    }"
                    617:                echo "    flags *= TME_M68K_FLAG_C;"
                    618:                echo "    flags |= (flags * TME_M68K_FLAG_X);"
                    619:                ;;
                    620:            esac
                    621:                echo "  }"
                    622: 
                    623:            echo ""
                    624:            echo "  /* store the result: */"
                    625:            echo "  TME_M68K_INSN_OP1(tme_${sign}int${size}_t) = res;"
                    626: 
                    627:            echo ""
                    628:            echo "  /* generate the N flag.  we cast to tme_uint8_t as soon as we"
                    629:            echo "     know the bit we want is within the range of the type, to try"
                    630:            echo "     to affect the generated assembly: */"
                    631:            echo "  flags |= ((tme_uint8_t) (((tme_uint${size}_t) res) >> (${size} - 1))) * TME_M68K_FLAG_N;"
                    632:            
                    633:            echo ""
                    634:            echo "  /* generate the Z flag: */"
                    635:            echo "  if (res == 0) flags |= TME_M68K_FLAG_Z;"
                    636: 
                    637:            echo ""
                    638:            echo "  /* store the flags: */"
                    639:            echo "  ic->tme_m68k_ireg_ccr = flags;"
                    640:            echo "  TME_M68K_INSN_OK;"
                    641:            echo "}"
                    642:        done
                    643:     done
                    644: 
                    645:     # movep_rm, movep_mr, movem_rm, and movem_mr:
                    646:     for name in rm mr; do
                    647:     
                    648:        # movep and movem don't need 8-bit versions:
                    649:        if test ${size} = 8; then continue; fi
                    650: 
                    651:        # if we're making the header, just emit declarations:
                    652:        if $header; then
                    653:            echo "TME_M68K_INSN_DECL(tme_m68k_movep_${name}${size});"
                    654:            echo "TME_M68K_INSN_DECL(tme_m68k_movem_${name}${size});"
                    655:            continue
                    656:        fi
                    657: 
                    658:        # emit the movep function:
                    659:        echo ""
                    660:        echo "/* the movep_${name} function on a ${size}-bit dreg: */"
                    661:        echo "TME_M68K_INSN(tme_m68k_movep_${name}${size})"
                    662:        echo "{"
                    663:        echo "  unsigned int function_code;"
                    664:        echo "  tme_uint32_t linear_address;"
                    665:        if test $name = rm; then
                    666:            echo "  tme_uint${size}_t value;"
                    667:        fi
                    668:        echo "  int dreg;"
                    669:        echo ""
                    670:        echo "  TME_M68K_INSN_CANFAULT;"
                    671:        echo ""
                    672:        echo "  function_code = TME_M68K_FUNCTION_CODE_DATA(ic);"
                    673:        echo "  linear_address = TME_M68K_INSN_OP1(tme_uint32_t);"
                    674:        echo "  linear_address += (tme_int32_t) ((tme_int16_t) TME_M68K_INSN_SPECOP);"
                    675:        echo "  dreg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);"
                    676: 
                    677:        # set value:
                    678:        if test $name = rm; then
                    679:            echo "  value = ic->tme_m68k_ireg_uint${size}(dreg${reg_size_shift});"
                    680:             value="value"
                    681:         else
                    682:             value="ic->tme_m68k_ireg_uint${size}(dreg${reg_size_shift})"
                    683:        fi
                    684:        
                    685:        # transfer the bytes:
                    686:        pos=${size}
                    687:        while test $pos != 0; do
                    688:            pos=`expr ${pos} - 8`
                    689:            echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
                    690:            echo "    ic->_tme_m68k_ea_function_code = function_code;"
                    691:            echo "    ic->_tme_m68k_ea_address = linear_address;"
                    692:            if test $name = rm; then
                    693:                echo "    ic->tme_m68k_ireg_memx8 = TME_FIELD_EXTRACTU(${value}, ${pos}, 8);"
                    694:                echo "  }"
                    695:                echo "  tme_m68k_write_memx8(ic);"
                    696:            else
                    697:                echo "  }"
                    698:                echo "  tme_m68k_read_memx8(ic);"
                    699:                echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
                    700:                echo "    TME_FIELD_DEPOSIT${size}(${value}, ${pos}, 8, ic->tme_m68k_ireg_memx8);"
                    701:                echo "  }"
                    702:            fi
                    703:            echo "  linear_address += 2;"
                    704:        done
                    705: 
                    706:        echo "  TME_M68K_INSN_OK;"
                    707:        echo "}"
                    708: 
                    709:        # emit the movem function:
                    710:        echo ""
                    711:        echo "/* the movem_${name} function on ${size}-bit registers: */"
                    712:        echo "TME_M68K_INSN(tme_m68k_movem_${name}${size})"
                    713:        echo "{"
                    714:        echo "  int ireg, direction;"
                    715:        echo "  tme_uint16_t mask, bit;"
                    716:        echo "  unsigned int ea_mode;"
                    717:        echo "  tme_uint32_t addend;"
1.1.1.4   root      718:        echo "  tme_uint32_t total_size;"
                    719: 
                    720:        echo "  /* get the register mask, and figure out the total size"
                    721:        echo "     of the transfer: */"
                    722:        echo "  mask = TME_M68K_INSN_SPECOP;"
                    723:        echo "  total_size = 0;"
                    724:        echo "  if (mask != 0) {"
                    725:        echo "    TME_M68K_INSN_CANFAULT;"
                    726:        echo "    bit = mask;"
                    727:        echo "    do {"
                    728:        echo "      total_size += sizeof(tme_uint${size}_t);"
                    729:        echo "      bit &= (bit - 1);"
                    730:        echo "    } while (bit != 0);"
                    731:        echo "  }"
1.1       root      732: 
                    733:        echo ""
                    734:        echo "  /* figure out what direction to move in, and where to start from: */"
                    735:        echo "  ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3);"
                    736:        echo "  direction = 1;"
                    737:        echo "  ireg = TME_M68K_IREG_D0;"
                    738:        if test $name = rm; then
                    739:            echo "  if (ea_mode == 4) {"
                    740:            echo "    direction = -1;"
                    741:            echo "    ireg = TME_M68K_IREG_A7;"
                    742:            echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
1.1.1.4   root      743:            echo ""
                    744:            echo "      /* \"For the MC68020, MC68030, MC68040, and CPU32, if"
                    745:            echo "         the addressing register is also moved to memory, the"
                    746:            echo "         value written is the initial register value decremented "
                    747:            echo "         by the size of the operation. The MC68000 and MC68010 "
                    748:            echo "         write the initial register value (not decremented).\" */"
                    749:            echo "      if (ic->tme_m68k_type >= TME_M68K_M68020) {"
                    750:            echo "        ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0"
                    751:            echo "                                 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3))"
                    752:            echo "          = (ic->_tme_m68k_ea_address - total_size);"
                    753:            echo "      }"
                    754:            echo ""
                    755:            echo "      /* predecrement the effective address for the first transfer: */"
1.1       root      756:            echo "      ic->_tme_m68k_ea_address -= sizeof(tme_uint${size}_t);"
                    757:            echo "    }"
                    758:            echo "  }"
                    759:        fi
                    760:        echo "  addend = (tme_uint32_t) (direction * sizeof(tme_uint${size}_t));"
                    761: 
                    762:        echo ""
                    763:        echo "  /* do the transfer: */"
                    764:        echo "  for (bit = 1; bit != 0; bit <<= 1) {"
                    765:        echo "    if (mask & bit) {"
                    766:        if test $name = rm; then
                    767:            echo "      if (!TME_M68K_SEQUENCE_RESTARTING) {"
                    768:            echo "        ic->tme_m68k_ireg_memx${size} = ic->tme_m68k_ireg_uint${size}(ireg${reg_size_shift});"
                    769:            echo "      }"
                    770:            echo "      tme_m68k_write_memx${size}(ic);"
                    771:            echo "      if (!TME_M68K_SEQUENCE_RESTARTING) {"
                    772:        else
                    773:            echo "      tme_m68k_read_memx${size}(ic);"
                    774:            echo "      if (!TME_M68K_SEQUENCE_RESTARTING) {"
                    775:            echo -n "        ic->tme_m68k_ireg_uint32(ireg) = "
                    776:            if test $size = 32; then
                    777:                echo "ic->tme_m68k_ireg_memx${size};"
                    778:            else
                    779:                echo "TME_EXT_S${size}_U32((tme_int${size}_t) ic->tme_m68k_ireg_memx${size});"
                    780:            fi
                    781:        fi
                    782:        echo "        ic->_tme_m68k_ea_address += addend;"
                    783:        echo "      }"
                    784:        echo "    }"
                    785:        echo "    ireg += direction;"
                    786:        echo "  }"
                    787:        echo ""
                    788: 
                    789:        # for the predecrement and postincrement modes, update the
                    790:        # address register:
                    791:        if test $name = rm; then 
                    792:            echo "  /* if this is the predecrement mode, update the address register: */"
1.1.1.4   root      793:            echo "  /* \"For the MC68020, MC68030, MC68040, and CPU32, if"
                    794:            echo "     the addressing register is also moved to memory, the"
                    795:            echo "     value written is the initial register value decremented "
                    796:            echo "     by the size of the operation. The MC68000 and MC68010 "
                    797:            echo "     write the initial register value (not decremented).\" */"
                    798:            echo "  if (ea_mode == 4"
                    799:            echo "      && ic->tme_m68k_type < TME_M68K_M68020) {"
1.1       root      800:            echo "    ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0"
                    801:            echo "                              + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3))"
                    802:            echo "      = (ic->_tme_m68k_ea_address + sizeof(tme_uint${size}_t));"
                    803:            echo "  }"
                    804:        else
                    805:            echo "  /* if this is the postincrement mode, update the address register: */"
                    806:            echo "  if (ea_mode == 3) {"
                    807:            echo "    ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0"
                    808:            echo "                              + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3))"
                    809:            echo "      = ic->_tme_m68k_ea_address;"
                    810:            echo "  }"
                    811:        fi
                    812:        
                    813:        echo "  TME_M68K_INSN_OK;"
                    814:        echo "}"
                    815:     done
                    816: 
                    817:     # chk32 and chk16:
                    818:     if test $size != 8; then
                    819: 
                    820:        # if we're making the header, just emit a declaration:
                    821:        if $header; then
                    822:            echo "TME_M68K_INSN_DECL(tme_m68k_chk${size});"
                    823:        else
                    824:            echo ""
                    825:            echo "/* chk${size}: */"
                    826:            echo "TME_M68K_INSN(tme_m68k_chk${size})"
                    827:            echo "{"
                    828:            echo "  if (*((tme_int${size}_t *) _op0) < 0) {"
                    829:            echo "    ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_N;"
1.1.1.3   root      830:            echo "    ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;"
1.1       root      831:            echo "    ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;"
1.1.1.3   root      832:            echo "    TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK));"
1.1       root      833:            echo "  }"
                    834:            echo "  if (*((tme_int${size}_t *) _op0) > *((tme_int${size}_t *) _op1)) {"
                    835:            echo "    ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_N;"
1.1.1.3   root      836:            echo "    ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;"
1.1       root      837:            echo "    ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;"
1.1.1.3   root      838:            echo "    TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK));"
1.1       root      839:            echo "  }"
                    840:            echo "  TME_M68K_INSN_OK;"
                    841:            echo "}"
                    842:        fi
                    843:     fi
                    844: 
1.1.1.4   root      845:     # cas:
                    846:     name=cas
                    847:     if $header; then
                    848:        echo "TME_M68K_INSN_DECL(tme_m68k_${name}${size});"
                    849:     else
                    850:        echo ""
                    851:        echo "/* ${name}${size}: */"
                    852:        echo "TME_M68K_INSN(tme_m68k_${name}${size})"
                    853:        echo "{"
                    854:        echo "  struct tme_m68k_rmw rmw;"
                    855:        echo "  struct tme_m68k_tlb *tlb;"
                    856:        echo "  int ireg_dc, ireg_du;"
                    857:        echo "  tme_uint${size}_t value_dc, value_du, value_mem;"
                    858:        echo ""
                    859:        echo "  /* start the read/modify/write cycle: */"
                    860:        echo "  rmw.tme_m68k_rmw_addresses[0] = ic->_tme_m68k_ea_address;"
                    861:        echo "  rmw.tme_m68k_rmw_address_count = 1;"
                    862:        echo "  rmw.tme_m68k_rmw_size = sizeof(tme_uint${size}_t);"
                    863:        echo "  if (tme_m68k_rmw_start(ic,"
                    864:        echo "                         &rmw)) {"
                    865:        echo "    TME_M68K_INSN_OK;"
                    866:        echo "  }"
                    867:        echo ""
                    868:        echo "  /* get the compare and update registers: */"
                    869:        echo "  ireg_dc = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3);"
                    870:        echo "  ireg_du = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 6, 3);"
                    871:        echo ""
                    872:        echo "  /* if we can do the fast compare-and-exchange: */"
                    873:        echo "  if (!rmw.tme_m68k_rmw_slow_reads[0]) {"
                    874:        echo ""
                    875:        echo "    /* get the compare and update values in big-endian byte order: */"
                    876:        echo "    value_dc = ic->tme_m68k_ireg_uint${size}(ireg_dc${reg_size_shift});"
                    877:        echo "    value_du = ic->tme_m68k_ireg_uint${size}(ireg_du${reg_size_shift});"
                    878:        if test ${size} != 8; then
                    879:            echo "    value_dc = tme_htobe_u${size}(value_dc);"
                    880:            echo "    value_du = tme_htobe_u${size}(value_du);"
                    881:        fi
                    882:        echo ""
                    883:        echo "    /* get this TLB entry: */"
                    884:        echo "    tlb = rmw.tme_m68k_rmw_tlbs[0];"
                    885:        echo ""
                    886:        echo "    /* this TLB entry must allow fast reading and fast writing"
                    887:        echo "       to the same memory: */"
                    888:        echo "    assert (tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF"
                    889:        echo "            && tlb->tme_m68k_tlb_emulator_off_write == tlb->tme_m68k_tlb_emulator_off_read);"
                    890:        echo ""
                    891:        echo "    /* do the compare-and-exchange: */"
                    892:        echo "    value_mem ="
                    893:        echo "      tme_memory_atomic_cx${size}(((tme_shared tme_uint${size}_t *)"
                    894:        echo "                                   (tlb->tme_m68k_tlb_emulator_off_read"
                    895:        echo "                                    + ic->_tme_m68k_ea_address)),"
                    896:        echo "                                  value_dc,"
                    897:        echo "                                  value_du,"
                    898:        echo "                                  tlb->tme_m68k_tlb_bus_rwlock,"
                    899:        echo "                                  sizeof(tme_uint8_t));"
                    900:        echo -n "    ic->tme_m68k_ireg_memx${size} = "
                    901:        if test ${size} != 8; then echo -n "tme_betoh_u${size}"; fi
                    902:        echo "(value_mem);"
                    903:        echo "  }"
                    904:        echo ""
                    905:        echo "  /* compare the compare operand to the effective address operand: */"
                    906:        echo "  tme_m68k_cmp${size}(ic, &ic->tme_m68k_ireg_uint${size}(ireg_dc${reg_size_shift}), &ic->tme_m68k_ireg_memx${size});"
                    907:        echo ""
                    908:        echo "  /* if the comparison succeeded: */"
                    909:        echo "  if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) {"
                    910:        echo ""
                    911:        echo "    /* write the update operand to the effective address operand: */"
                    912:        echo "    ic->tme_m68k_ireg_memx${size} = ic->tme_m68k_ireg_uint${size}(ireg_du${reg_size_shift});"
                    913:        echo "  }"
                    914:        echo ""
                    915:        echo "  /* otherwise, the comparison failed: */"
                    916:        echo "  else {"
                    917:        echo ""
                    918:        echo "    /* write the effective address operand to the compare operand: */"
                    919:        echo "    ic->tme_m68k_ireg_uint${size}(ireg_dc${reg_size_shift}) = ic->tme_m68k_ireg_memx${size};"
                    920:        echo "  }"
                    921:        echo ""
                    922:        echo "  /* finish the read/modify/write cycle: */"
                    923:        echo "  tme_m68k_rmw_finish(ic,"
                    924:        echo "                      &rmw,"
                    925:        echo "                      (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) != 0);"
                    926:        echo "  TME_M68K_INSN_OK;"
                    927:        echo "}"
                    928:     fi
                    929: 
                    930:     # cas2:
                    931:     name=cas2_
                    932:     if test $size != 8; then
1.1       root      933: 
                    934:        if $header; then
                    935:            echo "TME_M68K_INSN_DECL(tme_m68k_${name}${size});"
                    936:        else
                    937:            echo ""
                    938:            echo "/* ${name}${size}: */"
                    939:            echo "TME_M68K_INSN(tme_m68k_${name}${size})"
                    940:            echo "{"
1.1.1.4   root      941:            echo "  struct tme_m68k_rmw rmw;"
                    942:            echo "  int ireg_dcx, ireg_dux;"
                    943:            echo "  int ireg_dcy, ireg_duy;"
                    944:            echo "  const tme_uint16_t specopx = TME_M68K_INSN_SPECOP;"
                    945:            echo "  const tme_uint16_t specopy = TME_M68K_INSN_OP0(tme_uint16_t);"
1.1       root      946:            echo ""
                    947:            echo "  /* start the read/modify/write cycle: */"
1.1.1.4   root      948:            echo "  ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic);"
                    949:            echo "  rmw.tme_m68k_rmw_addresses[0] = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0"
                    950:            echo "                                                           + TME_FIELD_EXTRACTU(specopx, 12, 4));"
                    951:            echo "  rmw.tme_m68k_rmw_addresses[1] = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0"
                    952:            echo "                                                           + TME_FIELD_EXTRACTU(specopy, 12, 4));"
                    953:            echo "  rmw.tme_m68k_rmw_address_count = 2;"
                    954:            echo "  rmw.tme_m68k_rmw_size = sizeof(tme_uint${size}_t);"
                    955:            echo "  if (tme_m68k_rmw_start(ic,"
                    956:            echo "                         &rmw)) {"
1.1       root      957:            echo "    TME_M68K_INSN_OK;"
                    958:            echo "  }"
                    959:            echo ""
1.1.1.4   root      960:            echo "  /* do the comparisons: */"
                    961:            echo "  ireg_dcx = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopx, 0, 3);"
                    962:            echo "  ireg_dcy = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopy, 0, 3);"
                    963:            echo "  tme_m68k_cmp${size}(ic,"
                    964:            echo "                 &ic->tme_m68k_ireg_uint${size}(ireg_dcx${reg_size_shift}),"
                    965:            echo "                 &ic->tme_m68k_ireg_memx${size});"
                    966:            echo "  if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) {"
                    967:            echo "    tme_m68k_cmp${size}(ic,"
                    968:            echo "                   &ic->tme_m68k_ireg_uint${size}(ireg_dcy${reg_size_shift}),"
                    969:            echo "                   &ic->tme_m68k_ireg_memy${size});"
                    970:            echo "  }"
1.1       root      971:            echo ""
1.1.1.4   root      972:            echo "  /* if the comparisons succeeded: */"
1.1       root      973:            echo "  if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) {"
1.1.1.4   root      974:            echo ""
                    975:            echo "    /* write the update operands to the effective address operands: */"
                    976:            echo "    ireg_dux = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopx, 6, 3);"
                    977:            echo "    ireg_duy = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopy, 6, 3);"
                    978:            echo "    ic->tme_m68k_ireg_memx${size} = ic->tme_m68k_ireg_uint${size}(ireg_dux${reg_size_shift});"
                    979:            echo "    ic->tme_m68k_ireg_memy${size} = ic->tme_m68k_ireg_uint${size}(ireg_duy${reg_size_shift});"
1.1       root      980:            echo "  }"
1.1.1.4   root      981:            echo ""
                    982:            echo "  /* otherwise, the comparisons failed: */"
1.1       root      983:            echo "  else {"
1.1.1.4   root      984:            echo ""
                    985:            echo "    /* write the effective address operands to the compare operands."
                    986:            echo "       \"If Dc1 and Dc2 specify the same data register and the comparison"
                    987:            echo "        fails, memory operand 1 is stored in the data register.\" */"
                    988:            echo "    ic->tme_m68k_ireg_uint${size}(ireg_dcy${reg_size_shift}) = ic->tme_m68k_ireg_memy${size};"
                    989:            echo "    ic->tme_m68k_ireg_uint${size}(ireg_dcx${reg_size_shift}) = ic->tme_m68k_ireg_memx${size};"
1.1       root      990:            echo "  }"
                    991:            echo ""
                    992:            echo "  /* finish the read/modify/write cycle: */"
1.1.1.4   root      993:            echo "  tme_m68k_rmw_finish(ic,"
                    994:            echo "                      &rmw,"
                    995:            echo "                      (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) != 0);"
1.1       root      996:            echo "  TME_M68K_INSN_OK;"
                    997:            echo "}"
                    998:        fi
1.1.1.4   root      999:     fi
1.1       root     1000: 
                   1001:     # moves:
                   1002:     if $header; then
                   1003:        echo "TME_M68K_INSN_DECL(tme_m68k_moves${size});"
                   1004:     else
                   1005:        echo ""
                   1006:        echo "/* moves${size}: */"
                   1007:        echo "TME_M68K_INSN(tme_m68k_moves${size})"
                   1008:        echo "{"
                   1009:        echo "  int ireg;"
1.1.1.4   root     1010:        echo "  tme_uint${size}_t ireg_value;"
1.1.1.3   root     1011:        echo "  unsigned int ea_reg;"
                   1012:        echo "  unsigned int increment;"
                   1013:        echo "  TME_M68K_INSN_PRIV;"
                   1014:        echo "  TME_M68K_INSN_CANFAULT;"
1.1       root     1015:        echo "  ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4);"
1.1.1.3   root     1016:        echo ""
1.1.1.4   root     1017:        echo "  /* in case we're storing the same address register used in a"
                   1018:        echo "     postincrement or predecrement EA, save the current value"
                   1019:        echo "     of the register now: */"
                   1020:        echo "  ireg_value = ic->tme_m68k_ireg_uint${size}(ireg${reg_size_shift});"
                   1021:        echo ""
1.1.1.3   root     1022:        echo "  /* we have to handle postincrement and predecrement ourselves: */"
                   1023:        echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
                   1024:        echo "    ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);"
                   1025:        echo "    increment = TME_M68K_SIZE_${size};"
                   1026:        echo "    if (increment == TME_M68K_SIZE_8 && ea_reg == TME_M68K_IREG_A7) {"
                   1027:        echo "      increment = TME_M68K_SIZE_16;"
                   1028:        echo "    }"
                   1029:        echo "    switch (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3)) {"
                   1030:        echo "    case 3: ic->tme_m68k_ireg_uint32(ea_reg) += increment; break;"
                   1031:        echo "    case 4: ic->_tme_m68k_ea_address = (ic->tme_m68k_ireg_uint32(ea_reg) -= increment); break;"
                   1032:        echo "    default: break;"
                   1033:        echo "    }"
                   1034:        echo "  }"
                   1035:        echo ""
1.1       root     1036:        echo "  if (TME_M68K_INSN_SPECOP & TME_BIT(11)) {"
1.1.1.3   root     1037:        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
1.1.1.4   root     1038:        echo "      ic->tme_m68k_ireg_memx${size} = ireg_value;"
1.1.1.3   root     1039:        echo "      ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_dfc;"
                   1040:        echo "    }"
                   1041:        echo "    tme_m68k_write_memx${size}(ic);"
1.1       root     1042:        echo "  }"
                   1043:        echo "  else {"
1.1.1.3   root     1044:        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
                   1045:        echo "      ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_sfc;"
                   1046:        echo "    }"
                   1047:        echo "    tme_m68k_read_memx${size}(ic);"
1.1       root     1048:        if test ${size} != 32; then
                   1049:            echo "    if (ireg >= TME_M68K_IREG_A0) {"
                   1050:            echo "      ic->tme_m68k_ireg_uint32(ireg) = "
                   1051:            echo "        TME_EXT_S${size}_U32((tme_int${size}_t) ic->tme_m68k_ireg_memx${size});"
                   1052:            echo "    }"
                   1053:            echo "    else"
                   1054:            echo -n "  "
                   1055:        fi
                   1056:        echo "    ic->tme_m68k_ireg_uint${size}(ireg${reg_size_shift}) = ic->tme_m68k_ireg_memx${size};"
                   1057:        echo "  }"
                   1058:        echo "  TME_M68K_INSN_OK;"
                   1059:        echo "}"
                   1060:     fi
                   1061: done
                   1062: 
                   1063: # generate the memory read and write functions:
                   1064: 
                   1065: # permute on size:
                   1066: for size in 8 16 32 any; do
                   1067: 
                   1068:     # permute on read or write:
                   1069:     for name in read write; do
                   1070:        capname=`echo $name | tr a-z A-Z`
                   1071:        if test $name = read; then 
                   1072:            from="from"
                   1073:        else
                   1074:            from="to"
                   1075:        fi
                   1076: 
                   1077:        # permute on the special-purpose what:
                   1078:        for what in memx mem inst stack; do
                   1079: 
                   1080:            # placeholder for another permutation:
                   1081:            :
                   1082: 
                   1083:                # dispatch on the size:
                   1084:                _first=_first ; _last=_last
                   1085:                case "$size" in
                   1086:                8) _first= ; _last= ;;
                   1087:                esac
                   1088: 
                   1089:                # set up the details of each special purpose:
                   1090:                rval="void"
                   1091:                args=""
                   1092:                args_proto=""
                   1093:                fc=""
                   1094:                addr=""
                   1095:                count=""
1.1.1.5 ! root     1096:                tlb="TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address${_first})"
1.1       root     1097:                flags="TME_M68K_BUS_CYCLE_NORMAL"
                   1098:                case "${name}-${what}-${size}" in
                   1099:                *-memx-8 | *-memx-16 | *-memx-32)
                   1100:                    action="${name}_${what}${size}"
                   1101:                    fcptr="&ic->_tme_m68k_ea_function_code"
                   1102:                    addrptr="&ic->_tme_m68k_ea_address"
                   1103:                    reg="ic->tme_m68k_ireg_memx${size}"
                   1104:                    regptr="&${reg}"
                   1105:                    ;;
                   1106:                *-mem-any)
                   1107:                    action="${name}_${what}"
                   1108:                    args_proto=", tme_uint8_t *, unsigned int"
                   1109:                    args=", tme_uint8_t *buffer, unsigned int count"
                   1110:                    fcptr="&ic->_tme_m68k_ea_function_code"
                   1111:                    addrptr="&ic->_tme_m68k_ea_address"
1.1.1.4   root     1112:                    _last=
1.1       root     1113:                    reg=
                   1114:                    regptr="buffer"
                   1115:                    ;;
                   1116:                *-mem-8 | *-mem-16 | *-mem-32)
                   1117:                    action="${name}_${what}${size}"
                   1118:                    args_proto=", int"
                   1119:                    args="${args_proto} ireg"
                   1120:                    fcptr="&ic->_tme_m68k_ea_function_code"
                   1121:                    addrptr="&ic->_tme_m68k_ea_address"
                   1122:                    reg="ic->tme_m68k_ireg_uint${size}(ireg)"
                   1123:                    regptr="&${reg}"
                   1124:                    ;;
                   1125:                read-stack-16 | read-stack-32)
                   1126:                    action="pop${size}"
                   1127:                    args_proto=", tme_uint${size}_t *"
                   1128:                    args="${args_proto}_value"
                   1129:                    fc="TME_M68K_FUNCTION_CODE_DATA(ic)"
                   1130:                    addrptr="&ic->tme_m68k_ireg_a7"
                   1131:                    regptr="_value"
                   1132:                    reg="*${regptr}"
                   1133:                    ;;
                   1134:                write-stack-16 | write-stack-32)
                   1135:                    action="push${size}"
                   1136:                    args_proto=", tme_uint${size}_t "
                   1137:                    args="${args_proto}value"
                   1138:                    fc="TME_M68K_FUNCTION_CODE_DATA(ic)"
                   1139:                    addr="ic->tme_m68k_ireg_a7 - sizeof(tme_uint${size}_t)"
                   1140:                    reg="value"
                   1141:                    regptr="&${reg}"
                   1142:                    ;;
                   1143:                read-inst-16 | read-inst-32)
                   1144:                    rval="tme_uint${size}_t"
                   1145:                    action="fetch${size}"
                   1146:                    args_proto=", tme_uint32_t"
                   1147:                    args="${args_proto} pc"
                   1148:                    fc="TME_M68K_FUNCTION_CODE_PROGRAM(ic)"
                   1149:                    addrptr="&pc"
1.1.1.5 ! root     1150:                    tlb="&ic->_tme_m68k_itlb"
1.1       root     1151:                    flags="TME_M68K_BUS_CYCLE_FETCH"
                   1152:                    ;;
                   1153:                *)
                   1154:                    continue
                   1155:                    ;;
                   1156:                esac
                   1157: 
                   1158:                # if we're making the header, just emit a declaration:
                   1159:                if $header; then
                   1160:                    echo "${rval} tme_m68k_${action} _TME_P((struct tme_m68k *${args_proto}));"
                   1161:                    continue
                   1162:                fi
                   1163: 
                   1164:                # start the function:
                   1165:                echo ""
                   1166:                echo "/* this ${name}s a ${size}-bit ${what} value: */"
                   1167:                echo "${rval}"
                   1168:                echo "tme_m68k_${action}(struct tme_m68k *ic${args}) "
                   1169:                echo "{"
                   1170: 
                   1171:                # our locals:
1.1.1.5 ! root     1172:                echo "  tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;"
1.1       root     1173:                echo -n "  unsigned int function_code = "
                   1174:                if test "x${fc}" != x; then
                   1175:                    echo "${fc};"
                   1176:                    fc="function_code"
                   1177:                    fcptr="&function_code"
                   1178:                else
                   1179:                    fc=`echo ${fcptr} | sed -e 's,^&,,'`
                   1180:                    echo "${fc};"
                   1181:                fi
                   1182:                echo -n "  tme_uint32_t linear_address${_first} = "
                   1183:                if test "x${addr}" != x; then
                   1184:                    echo "${addr};"
                   1185:                    addr="linear_address${_first}"
                   1186:                    addrptr="&linear_address${_first}"
                   1187:                else
                   1188:                    addr=`echo ${addrptr} | sed -e 's,^&,,'`
                   1189:                    echo "${addr};"
                   1190:                fi
                   1191:                if test "x${count}" = x; then
                   1192:                    if test $size = any; then count=count; else count="sizeof(tme_uint${size}_t)"; fi
                   1193:                fi
                   1194:                if test x$_last != x; then
                   1195:                    echo "  tme_uint32_t linear_address${_last} = linear_address_first + ${count} - 1;";
                   1196:                fi
                   1197:                echo "  struct tme_m68k_tlb *tlb = ${tlb};"
1.1.1.4   root     1198:                if test $size != any; then
                   1199:                    memtype="tme_uint${size}_t"
                   1200:                    echo "  ${memtype} mem_value;"
                   1201:                    memtype="tme_shared ${memtype} *"
                   1202:                    if test $name = read; then memtype="const ${memtype}"; fi
                   1203:                    echo "  ${memtype}mem;"
                   1204:                fi
1.1       root     1205:                case "$what" in
                   1206:                inst)
1.1.1.4   root     1207:                    echo "  unsigned int fetch_slow_next = ic->_tme_m68k_insn_fetch_slow_next;"
                   1208:                    regptr="((tme_uint${size}_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next))"
1.1       root     1209:                    reg="*${regptr}"
                   1210:                    ;;
                   1211:                esac
                   1212: 
1.1.1.3   root     1213:                # track statistics:
                   1214:                echo ""
                   1215:                echo "#ifdef _TME_M68K_STATS"
                   1216:                echo "  ic->tme_m68k_stats.tme_m68k_stats_memory_total++;"
                   1217:                echo "#endif /* _TME_M68K_STATS */"
                   1218: 
1.1       root     1219:                # if this is a write, log the value written:
                   1220:                if test $name = write; then
                   1221:                    echo ""
                   1222:                    echo "  /* log the value written: */"
                   1223:                    if test $size != any; then
                   1224:                        echo "  tme_m68k_verify_mem${size}(ic, ${fc}, ${addr}, ${reg}, TME_BUS_CYCLE_WRITE);"
                   1225:                        echo "  tme_m68k_log(ic, 1000, TME_OK, "
                   1226:                        echo "               (TME_M68K_LOG_HANDLE(ic),"
                   1227:                        echo "                _(\"${action}\t%d:0x%08x:\t0x%0"`expr ${size} / 4`"x\"),"
                   1228:                        echo "                ${fc},"
                   1229:                        echo "                ${addr},"
                   1230:                        echo "                ${reg}));"
                   1231:                    else
                   1232:                        echo "  tme_m68k_verify_mem_any(ic, ${fc}, ${addr}, ${regptr}, ${count}, TME_BUS_CYCLE_WRITE);"
                   1233:                        echo "  tme_m68k_log_start(ic, 1000, TME_OK) {"
                   1234:                        echo "    unsigned int byte_i;"
                   1235:                        echo "    tme_log_part(TME_M68K_LOG_HANDLE(ic),"
                   1236:                        echo "                 _(\"${action} %d:0x%08x count %d:\"),"
                   1237:                        echo "                 ${fc},"
                   1238:                        echo "                 ${addr},"
                   1239:                        echo "                 ${count});"
                   1240:                        echo "    for (byte_i = 0; byte_i < count ; byte_i++) {"
                   1241:                        echo "      tme_log_part(TME_M68K_LOG_HANDLE(ic), \" 0x%02x\", (${regptr})[byte_i]);"
                   1242:                        echo "    }"
                   1243:                        echo "  } tme_m68k_log_finish(ic);"
                   1244:                    fi
                   1245:                fi
                   1246: 
                   1247:                echo ""
1.1.1.4   root     1248:                echo "  /* busy this TLB entry: */"
                   1249:                echo "  tme_m68k_tlb_busy(tlb);"
1.1       root     1250: 
1.1.1.4   root     1251:                # if this is an any-transfer:
                   1252:                #
                   1253:                if test $size = any; then
                   1254:                    echo ""
                   1255:                    echo "  /* call the full ${name} function: */"
                   1256:                    echo "  tme_m68k_${name}(ic, tlb, ${fcptr}, ${addrptr}, ${regptr}, ${count}, TME_M68K_BUS_CYCLE_RAW);"
                   1257: 
                   1258:                # otherwise, this is not an any-transfer:
                   1259:                #
1.1       root     1260:                else
                   1261: 
1.1.1.4   root     1262:                    # dispatch on the what:
                   1263:                    #
                   1264:                    i=
                   1265:                    case "$what" in
                   1266:                    inst)
                   1267:                        echo ""
                   1268:                        echo "  /* if this fetch was done by the fast executor: */"
                   1269:                        echo "  if (__tme_predict_true(fetch_slow_next < ic->_tme_m68k_insn_fetch_slow_count_fast)) {"
                   1270:                        echo ""
                   1271:                        echo "    /* the entire fetch must be in the instruction buffer, and"
                   1272:                        echo "       we must be restarting: */"
                   1273:                        echo "    assert ((fetch_slow_next + sizeof(tme_uint${size}_t))"
                   1274:                        echo "            <= ic->_tme_m68k_insn_fetch_slow_count_fast);"
                   1275:                        echo "    assert (TME_M68K_SEQUENCE_RESTARTING);"
                   1276:                        echo "    mem_value = tme_memory_read${size}(${regptr}, sizeof(tme_uint16_t));"
                   1277:                        echo "  }"
                   1278:                        echo ""
                   1279:                        echo "  /* otherwise, this fetch was not done by the fast executor: */"
                   1280:                        echo "  else {"
                   1281:                        echo ""
                   1282:                        echo "    /* if we're restarting, but the offset in the instruction buffer"
                   1283:                        echo "       to fetch into is at the instruction buffer total, this must be"
                   1284:                        echo "       a fake fault caused by the fast executor.  we confirm this by"
                   1285:                        echo "       checking that this transfer \"caused\" the fault, and that this"
                   1286:                        echo "       transfer will be the first slow one after any fast fetches."
                   1287:                        echo "       in this case, we can cancel the restart for now: */"
                   1288:                        echo "    if (TME_M68K_SEQUENCE_RESTARTING"
                   1289:                        echo "        && (fetch_slow_next"
                   1290:                        echo "            == ic->_tme_m68k_insn_fetch_slow_count_total)) {"
                   1291:                        echo "      assert ((ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next"
                   1292:                        echo "               == ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted)"
                   1293:                        echo "              && (fetch_slow_next"
                   1294:                        echo "                  == ic->_tme_m68k_insn_fetch_slow_count_fast));"
                   1295:                        echo "      ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted--;"
                   1296:                        echo "    }"
                   1297:                        echo ""
                   1298:                        echo "    /* if we're not restarting: */"
                   1299:                        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
                   1300:                        echo ""
                   1301:                        echo "      /* we advance the instruction buffer total *before* we do"
                   1302:                        echo "         what may be a slow fetch, because we may transfer a few"
                   1303:                        echo "         bytes and then fault.  without this, those few bytes"
                   1304:                        echo "         would not get saved in the exception stack frame and"
                   1305:                        echo "         restored later before the continuation of the fetch: */"
                   1306:                        echo "      ic->_tme_m68k_insn_fetch_slow_count_total += sizeof(tme_uint${size}_t);"
                   1307:                        echo "    }"
                   1308:                        echo ""
                   1309:                        echo "    /* make sure that if this is a new transfer or if this"
                   1310:                        echo "       transfer faulted, that we're fetching for the current"
                   1311:                        echo "       last positions in the instruction buffer: */"
                   1312:                        echo "    assert ((ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next"
                   1313:                        echo "             < ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted)"
                   1314:                        echo "            || ((fetch_slow_next + sizeof(tme_uint${size}_t))"
                   1315:                        echo "                == ic->_tme_m68k_insn_fetch_slow_count_total));"
                   1316:                        i="  "
                   1317:                        ;;
                   1318:                    esac
                   1319: 
                   1320:                    echo ""
                   1321:                    echo "${i}  /* if we aren't restarting, and this address is properly aligned,"
                   1322:                    echo "${i}     and this TLB entry covers the operand and allows fast ${name}s: */"
                   1323:                    echo "${i}  if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING"
                   1324:                    align_min="sizeof(tme_uint8_t)"
                   1325:                    if test $size != 8; then
                   1326:                        echo -n "${i}                         && ("
                   1327:                        if test $what = inst; then
                   1328:                            align_min="sizeof(tme_uint16_t)"
                   1329:                            echo -n "(${align_min} - 1)"
                   1330:                        else
                   1331:                            echo -n "ic->_tme_m68k_bus_16bit"
                   1332:                        fi
                   1333:                        echo " & linear_address${_first}) == 0"
1.1       root     1334:                    fi
1.1.1.5 ! root     1335:                    echo "${i}                         && tme_m68k_tlb_is_valid(tlb)"
        !          1336:                    echo "${i}                         && tlb->tme_m68k_tlb_bus_context == bus_context"
        !          1337:                    echo "${i}                         && (tlb->tme_m68k_tlb_function_codes_mask"
        !          1338:                    echo "${i}                             & TME_BIT(function_code))"
        !          1339:                    echo "${i}                         && linear_address${_first} >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first"
        !          1340:                    echo "${i}                         && linear_address${_last} <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last"
        !          1341:                    echo "${i}                         && tlb->tme_m68k_tlb_emulator_off_${name} != TME_EMULATOR_OFF_UNDEF)) {"
1.1.1.4   root     1342: 
1.1       root     1343:                    echo ""
1.1.1.4   root     1344:                    echo "${i}    /* make the emulator memory pointer: */"
                   1345:                    echo "${i}    mem = (${memtype}) (tlb->tme_m68k_tlb_emulator_off_${name} + linear_address${_first});"
                   1346: 
                   1347:                    if test $name = write; then
                   1348:                        if test $size = 8; then
                   1349:                            echo ""
                   1350:                            echo "${i}    /* get the value to write: */"
                   1351:                            echo "${i}    mem_value = ${reg};"
                   1352:                        else
                   1353:                            echo ""
                   1354:                            echo "${i}    /* get the value to write, in big-endian byte order: */"
                   1355:                            echo "${i}    mem_value = tme_htobe_u${size}(${reg});"
                   1356:                        fi
                   1357:                    fi
                   1358: 
1.1       root     1359:                    echo ""
1.1.1.4   root     1360:                    echo "${i}    /* do the ${size}-bit bus ${name}: */"
1.1       root     1361:                    if test $name = read; then
1.1.1.4   root     1362:                        echo -n "${i}    mem_value = tme_memory_bus_${name}${size}(mem"
1.1       root     1363:                    else
1.1.1.4   root     1364:                        echo -n "${i}    tme_memory_bus_${name}${size}(mem, mem_value"
1.1       root     1365:                    fi
1.1.1.4   root     1366:                    echo ", tlb->tme_m68k_tlb_bus_rwlock, ${align_min}, sizeof(tme_uint32_t));"
                   1367: 
1.1       root     1368:                    if test $name = read; then
1.1.1.4   root     1369:                        if test $what = inst; then
                   1370:                            echo ""
                   1371:                            echo "${i}    /* put the value read, in host byte order: */"
                   1372:                            echo "${i}    mem_value = tme_betoh_u${size}(mem_value);"
                   1373:                            echo "${i}    tme_memory_write${size}(${regptr}, mem_value, sizeof(tme_uint16_t));"
                   1374:                        elif test $size = 8; then
                   1375:                            echo ""
                   1376:                            echo "${i}    /* put the value read: */"
                   1377:                            echo "${i}    ${reg} = mem_value;"
                   1378:                        else
                   1379:                            echo ""
                   1380:                            echo "${i}    /* put the value read, in host byte order: */"
                   1381:                            echo "${i}    ${reg} = tme_betoh_u${size}(mem_value);"
                   1382:                        fi
1.1       root     1383:                    fi
                   1384: 
1.1.1.4   root     1385:                    echo ""
                   1386:                    echo "${i}    /* step the transfer count: */"
                   1387:                    echo "${i}    TME_M68K_SEQUENCE_TRANSFER_STEP;"
                   1388:                    echo "${i}  }"
                   1389: 
                   1390:                    echo ""
                   1391:                    echo "${i}  /* otherwise, do the bus cycles the slow way: */"
                   1392:                    echo "${i}  else {"
                   1393:                    echo "${i}    tme_m68k_${name}${size}(ic, tlb,"
                   1394:                    echo "${i}                    ${fcptr},"
                   1395:                    echo "${i}                    ${addrptr},"
                   1396:                    echo "${i}                    ${regptr},"
                   1397:                    echo "${i}                    ${flags});"
                   1398:                    if test ${what} = inst; then
                   1399:                        echo "${i}    mem_value = tme_memory_read${size}(${regptr}, sizeof(tme_uint16_t));"
                   1400:                    fi
                   1401:                    echo "${i}  }"
                   1402:                fi
                   1403:                if test "x${i}" != x; then
                   1404:                    echo "  }"
1.1       root     1405:                fi
                   1406: 
                   1407:                echo ""
1.1.1.4   root     1408:                echo "  /* unbusy this TLB entry: */"
                   1409:                echo "  tme_m68k_tlb_unbusy(tlb);"
1.1       root     1410:                
                   1411:                # if this is a read, log the value read:
                   1412:                if test $name = read; then
                   1413:                    echo ""
                   1414:                    echo "  /* log the value read: */"
                   1415:                    if test $size != any; then
                   1416:                        echo "  tme_m68k_verify_mem${size}(ic, ${fc}, ${addr}, ${reg}, TME_BUS_CYCLE_READ);"
                   1417:                        echo "  tme_m68k_log(ic, 1000, TME_OK,"
                   1418:                        echo "               (TME_M68K_LOG_HANDLE(ic),"
                   1419:                        echo "                _(\"${action}\t%d:0x%08x:\t0x%0"`expr ${size} / 4`"x\"),"
                   1420:                        echo "                ${fc},"
                   1421:                        echo "                ${addr},"
                   1422:                        echo "                ${reg}));"
                   1423:                    else
                   1424:                        echo "  tme_m68k_verify_mem_any(ic, ${fc}, ${addr}, ${regptr}, ${count}, TME_BUS_CYCLE_READ);"
                   1425:                        echo "  tme_m68k_log_start(ic, 1000, TME_OK) {"
                   1426:                        echo "    unsigned int byte_i;"
                   1427:                        echo "    tme_log_part(TME_M68K_LOG_HANDLE(ic),"
                   1428:                        echo "                 _(\"${action} %d:0x%08x count %d:\"),"
                   1429:                        echo "                 ${fc},"
                   1430:                        echo "                 ${addr},"
                   1431:                        echo "                 ${count});"
                   1432:                        echo "    for (byte_i = 0; byte_i < count ; byte_i++) {"
                   1433:                        echo "      tme_log_part(TME_M68K_LOG_HANDLE(ic), \" 0x%02x\", (${regptr})[byte_i]);"
                   1434:                        echo "    }"
                   1435:                        echo "  } tme_m68k_log_finish(ic);"
                   1436:                    fi
                   1437:                fi
                   1438: 
                   1439:                # perform any updating and value returning:
                   1440:                case "$what" in
                   1441:                stack)
                   1442:                    if test $name = read; then dir="+"; else dir="-"; fi
                   1443:                    echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
                   1444:                    echo "    ic->tme_m68k_ireg_a7 ${dir}= sizeof(tme_uint${size}_t);"
                   1445:                    echo "  }"
                   1446:                    ;;
                   1447:                inst)
1.1.1.4   root     1448:                    echo ""
                   1449:                    echo "  /* advance the offset in the instruction buffer for the next slow fetch: */"
                   1450:                    echo "  fetch_slow_next += sizeof(tme_uint${size}_t);"
                   1451:                    echo "  ic->_tme_m68k_insn_fetch_slow_next = fetch_slow_next;"
                   1452:                    echo ""
                   1453:                    echo "  /* return the fetched value: */"
                   1454:                    echo "  return(mem_value);"
1.1       root     1455:                    ;;
                   1456:                esac
                   1457: 
                   1458:                echo "}"
                   1459:            :
                   1460:        done
                   1461: 
                   1462:        # the general-purpose cycle-making read and write macros:
                   1463:        if test ${size} != any; then
                   1464: 
                   1465:            # if we're making the header, emit a macro:
                   1466:            if $header; then
                   1467:                echo "#define tme_m68k_${name}${size}(ic, t, fc, la, _v, f) \\"
                   1468:                echo "  tme_m68k_${name}(ic, t, fc, la, (tme_uint8_t *) (_v), sizeof(tme_uint${size}_t), f)"
                   1469:            fi
                   1470:        else
                   1471: 
                   1472:            # if we're making the header, just emit a declaration:
                   1473:            if $header; then
                   1474:                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));"
                   1475:                continue
                   1476:            fi
                   1477: 
                   1478:            echo ""
                   1479:            echo "/* this ${name}s a region of address space using actual bus cycles: */"
                   1480:            echo "void"
                   1481:            echo "tme_m68k_${name}(struct tme_m68k *ic, "
                   1482:            echo "              struct tme_m68k_tlb *tlb,"
                   1483:            echo "              unsigned int *_function_code, "
                   1484:            echo "              tme_uint32_t *_linear_address, "
                   1485:            echo "              tme_uint8_t *reg,"
                   1486:            echo "              unsigned int reg_size,"
                   1487:            echo "              unsigned int flags)"
                   1488:            echo "{"
                   1489: 
                   1490:            # our locals:
                   1491:            echo "  unsigned int function_code;"
                   1492:            echo "  tme_uint32_t linear_address;"
                   1493:            echo "  tme_bus_addr_t physical_address;"
                   1494:            echo "  int shift;"
                   1495:            echo "  struct tme_bus_cycle cycle;"
                   1496:            echo "  unsigned int transferred, resid, cycle_size;"
                   1497:            echo "  int exception;"
                   1498:            echo "  int err;"
                   1499:            echo "  tme_uint8_t *reg_p;"
                   1500:            echo "  unsigned int buffer_i;"
1.1.1.4   root     1501:            echo "  tme_uint8_t reg_buffer[sizeof(tme_uint32_t) * 2];"
                   1502:            if test ${name} = read; then name_const_mem="const "; else name_const_mem= ; fi
                   1503:            echo "  ${name_const_mem}tme_shared tme_uint8_t *mem;"
1.1       root     1504: 
                   1505:            echo ""
                   1506:            echo "  /* if we're not restarting, everything is fresh: */"
                   1507:            echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
                   1508:            echo "    function_code = *_function_code;"
                   1509:            echo "    linear_address = *_linear_address;"
                   1510:            echo "    transferred = 0;"
                   1511:            echo "  }"
                   1512: 
                   1513:            echo ""
                   1514:            echo "  /* otherwise, if this is the transfer that faulted, restore"
                   1515:            echo "     our state to the cycle that faulted, then take into account"
                   1516:            echo "     any data provided by a software rerun of the faulted cycle: */"
                   1517:            echo "  else if (ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted"
                   1518:            echo "           == ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next) {"
                   1519:            echo "    function_code = *_function_code = ic->_tme_m68k_group0_function_code;"
                   1520:            echo "    linear_address = ic->_tme_m68k_group0_address;"
                   1521:            echo "    transferred = ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted_after;"
                   1522:            echo "    if (transferred >= reg_size) abort();"
                   1523:            echo "    *_linear_address = linear_address - transferred;"
                   1524:            echo "    resid = reg_size - transferred;"
                   1525:            echo "    if (ic->_tme_m68k_group0_buffer_${name}_size > resid) abort();"
                   1526:            echo "    if (ic->_tme_m68k_group0_buffer_${name}_softrr > resid) abort();"
                   1527:            if test $name = read; then cmp=">"; else cmp="=="; fi
                   1528:            echo "    if (ic->_tme_m68k_group0_buffer_${name}_softrr ${cmp} 0) {"
                   1529:            echo "#ifdef WORDS_BIGENDIAN"
                   1530:            echo "      memcpy(reg + transferred, "
                   1531:            echo "             ic->_tme_m68k_group0_buffer_${name},"
                   1532:            echo "             ic->_tme_m68k_group0_buffer_${name}_size);"
                   1533:            echo "#else  /* !WORDS_BIGENDIAN */"
                   1534:            echo "      reg_p = (reg + reg_size - 1) - transferred;"
                   1535:            echo "      for (buffer_i = 0;"
                   1536:            echo "           buffer_i < ic->_tme_m68k_group0_buffer_${name}_size;"
                   1537:            echo "           buffer_i++) {"
                   1538:            echo "        *(reg_p--) = ic->_tme_m68k_group0_buffer_${name}[buffer_i];"
                   1539:            echo "      }"
                   1540:            echo "#endif /* !WORDS_BIGENDIAN */"
                   1541:            echo "    }"
                   1542:            echo "    transferred += ic->_tme_m68k_group0_buffer_${name}_softrr;"
                   1543:            echo "  }"
                   1544: 
                   1545:            echo ""
                   1546:            echo "  /* otherwise, a later transfer has faulted.  just step the"
                   1547:            echo "     transfer number and return: */"
                   1548:            echo "  else {"
                   1549:            echo "    TME_M68K_SEQUENCE_TRANSFER_STEP;"
                   1550:            echo "    return;"
                   1551:            echo "  }"
                   1552: 
                   1553:            echo ""
                   1554:            echo "  /* do as many bus cycles as needed to complete the transfer: */"
                   1555:            echo "  exception = TME_M68K_EXCEPTION_NONE;"
                   1556:            echo "  cycle_size = 0;"
                   1557:            echo "  for(; transferred < reg_size; ) {"
                   1558:            echo "    resid = reg_size - transferred;"
                   1559: 
                   1560:            echo ""
                   1561:            echo "    /* start the bus cycle structure: */"
                   1562:            echo "    cycle.tme_bus_cycle_type = TME_BUS_CYCLE_${capname};"
                   1563:            echo "    if (TME_ENDIAN_NATIVE == TME_ENDIAN_BIG"
                   1564:            echo "        || (flags & TME_M68K_BUS_CYCLE_RAW)) {"
                   1565:            echo "      cycle.tme_bus_cycle_buffer = reg + transferred;"
                   1566:            echo "      cycle.tme_bus_cycle_buffer_increment = 1;"
                   1567:            echo "    }"
                   1568:            echo "    else {"
                   1569:            echo "      cycle.tme_bus_cycle_buffer = reg + reg_size - (1 + transferred);"
                   1570:            echo "      cycle.tme_bus_cycle_buffer_increment = -1;"
                   1571:            echo "    }"
                   1572: 
                   1573:            echo ""
                   1574:            echo "    /* if we're emulating a CPU with a 16-bit bus interface: */"
                   1575:            echo "    if (ic->_tme_m68k_bus_16bit) {"
                   1576:            echo ""
                   1577:            echo "      /* if we're trying to transfer a non-power-of-two"
                   1578:            echo "         number of bytes, either the CPU is broken (no"
                   1579:            echo "         instructions ever transfer a non-power-of-two"
                   1580:            echo "         number of bytes), or this function allowed an"
                   1581:            echo "         unaligned transfer: */"
                   1582:            echo "      assert((resid & (resid - 1)) == 0"
                   1583:            echo "             || (flags & TME_M68K_BUS_CYCLE_RAW));"
                   1584:            echo ""
                   1585:            echo "      /* only byte transfers can be unaligned: */"
                   1586:            echo "      if (resid > sizeof(tme_uint8_t)"
                   1587:            echo "          && (linear_address & 1)) {"
1.1.1.3   root     1588:            echo "          exception = TME_M68K_EXCEPTION_AERR;"
1.1       root     1589:            echo "          break;"
                   1590:            echo "      }"
                   1591:            echo ""
                   1592:            echo "      /* set the bus-size specific parts of the bus cycle structure: */"
                   1593:            echo "      cycle_size = TME_MIN(resid, sizeof(tme_uint16_t));"
                   1594:            echo "      cycle.tme_bus_cycle_size = cycle_size;"
                   1595:            echo "      cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS16_LOG2);"
                   1596:            echo "      cycle.tme_bus_cycle_lane_routing = "
                   1597:            echo "        &tme_m68k_router_16[TME_M68K_BUS_ROUTER_INDEX(TME_BUS16_LOG2, cycle_size, linear_address)];"
                   1598:            echo "    }"
                   1599:            echo ""
                   1600:            echo "    /* otherwise we're emulating a CPU with a 32-bit bus interface: */"
                   1601:            echo "    else {"
                   1602:            if test $name = read; then
                   1603:                echo ""
                   1604:                echo "      /* an instruction fetch must be aligned: */"
                   1605:                echo "      if (flags & TME_M68K_BUS_CYCLE_FETCH) {"
                   1606:                echo "        if (linear_address & 1) {"
1.1.1.3   root     1607:                echo "          exception = TME_M68K_EXCEPTION_AERR;"
1.1       root     1608:                echo "          break;"
                   1609:                echo "        }"
                   1610:                echo "        assert(!(resid & 1));"
                   1611:                echo "      }"
                   1612:            fi
                   1613:            echo ""
                   1614:            echo "      /* set the bus-size specific parts of the bus cycle structure: */"
                   1615:            echo "      cycle_size = TME_MIN(resid, sizeof(tme_uint32_t) - (linear_address & (sizeof(tme_uint32_t) - 1)));"
                   1616:            echo "      cycle.tme_bus_cycle_size = cycle_size;"
                   1617:            echo "      cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS32_LOG2);"
                   1618:            echo "      cycle.tme_bus_cycle_lane_routing = "
                   1619:            echo "        &tme_m68k_router_32[TME_M68K_BUS_ROUTER_INDEX(TME_BUS32_LOG2, cycle_size, linear_address)];"
                   1620:            echo "    }"
                   1621:        
                   1622:            echo ""
1.1.1.4   root     1623:            echo "    /* loop while this TLB entry is invalid or does not apply: */"
1.1.1.5 ! root     1624:            echo "    for (; __tme_predict_false(tme_m68k_tlb_is_invalid(tlb)"
        !          1625:            echo "                               || tlb->tme_m68k_tlb_bus_context != ic->_tme_m68k_bus_context"
1.1.1.4   root     1626:            echo "                               || (tlb->tme_m68k_tlb_function_codes_mask & TME_BIT(function_code)) == 0"
1.1.1.5 ! root     1627:            echo "                               || linear_address < (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first"
        !          1628:            echo "                               || linear_address > (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last"
1.1.1.4   root     1629:            echo "                               || (tlb->tme_m68k_tlb_emulator_off_${name} == TME_EMULATOR_OFF_UNDEF"
                   1630:            echo "                                   && (tlb->tme_m68k_tlb_cycles_ok & TME_BUS_CYCLE_${capname}) == 0)); ) {"
                   1631:            echo ""
                   1632:            echo "      /* this must not be part of a read/modify/write cycle: */"
                   1633:            echo "      assert(!(flags & TME_M68K_BUS_CYCLE_RMW));"
                   1634:            echo ""
                   1635:            echo "      /* fill this TLB entry: */"
1.1       root     1636:            echo "      tme_m68k_tlb_fill(ic, tlb,"
                   1637:            echo "                        function_code,"
                   1638:            echo "                        linear_address,"
                   1639:            echo "                        TME_BUS_CYCLE_${capname});"
                   1640:            echo "    }"
                   1641:            echo ""
1.1.1.4   root     1642:            echo "    /* if this TLB entry allows for fast ${name}s: */"
                   1643:            echo "    mem = tlb->tme_m68k_tlb_emulator_off_${name};"
                   1644:            echo "    if (__tme_predict_true(mem != TME_EMULATOR_OFF_UNDEF)) {"
                   1645:            echo ""
                   1646:            echo "      /* make the emulator memory pointer: */"
                   1647:            echo "      mem += linear_address;"
                   1648:            echo ""
                   1649:            echo "      /* limit the cycle size to addresses covered by the TLB entry: */"
                   1650:            echo "      if (__tme_predict_false((cycle_size - 1)"
1.1.1.5 ! root     1651:            echo "                              > (((tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last) - linear_address))) {"
        !          1652:            echo "        cycle_size = (((tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last) - linear_address) + 1;"
1.1       root     1653:            echo "      }"
                   1654:            echo ""
1.1.1.4   root     1655:            echo "      /* if this is a little-endian host, and this isn't a raw ${name}: */"
                   1656:            echo "      if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE"
                   1657:            echo "          && (flags & TME_M68K_BUS_CYCLE_RAW) == 0) {"
                   1658:            if test ${name} = write; then
                   1659:                echo ""
                   1660:                echo "        /* byteswap the data to write in the intermediate buffer: */"
                   1661:                echo "        reg_p = cycle.tme_bus_cycle_buffer;"
                   1662:                echo "        buffer_i = 0;"
                   1663:                echo "        do {"
                   1664:                echo "          reg_buffer[buffer_i] = *(reg_p--);"
                   1665:                echo "        } while (++buffer_i != cycle_size);"
                   1666:            fi
                   1667:            echo ""
                   1668:            echo "        /* use the intermediate buffer for the ${name}: */"
                   1669:            echo "        cycle.tme_bus_cycle_buffer = &reg_buffer[0];"
1.1       root     1670:            echo "      }"
1.1.1.4   root     1671:            echo ""
                   1672:            echo "      /* do the bus ${name}: */"
                   1673:            echo "      tme_memory_bus_${name}_buffer(mem,"
                   1674:            echo "                                 cycle.tme_bus_cycle_buffer,"
                   1675:            echo "                                 cycle_size,"
                   1676:            echo "                                 tlb->tme_m68k_tlb_bus_rwlock,"
                   1677:            echo "                                 sizeof(tme_uint8_t),"
                   1678:            echo "                                 sizeof(tme_uint32_t));"
                   1679:            if test ${name} = read; then
                   1680:                echo ""
                   1681:                echo "      /* if this is a little-endian host, and this isn't a raw ${name}: */"
                   1682:                echo "      if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE"
                   1683:                echo "          && (flags & TME_M68K_BUS_CYCLE_RAW) == 0) {"
                   1684:                echo ""
                   1685:                echo "        /* byteswap the read data in the intermediate buffer: */"
                   1686:                echo "        reg_p = reg + reg_size - (1 + transferred);"
                   1687:                echo "        buffer_i = 0;"
                   1688:                echo "        do {"
                   1689:                echo "          *(reg_p--) = reg_buffer[buffer_i];"
                   1690:                echo "        } while (++buffer_i != cycle_size);"
                   1691:                echo "      }"
                   1692:            fi
                   1693:            echo ""
                   1694:            echo "      /* update: */"
                   1695:            echo "      linear_address += cycle_size;"
                   1696:            echo "      transferred += cycle_size;"
                   1697:            echo "      continue;"
                   1698:            echo "    }"
                   1699:            echo ""
                   1700:            echo "    /* otherwise, this TLB entry does not allow for fast ${name}s: */"
                   1701:            echo ""
                   1702:            echo "    /* if this is a part of a read/modify/write cycle: */"
                   1703:            echo "    if (flags & TME_M68K_BUS_CYCLE_RMW) {"
                   1704:            echo ""
                   1705:            if test ${name} = read; then
                   1706:                echo "      /* if this is the first cycle in this read,"
                   1707:                echo "         we will establish the new lock, otherwise"
                   1708:                echo "         we will continue using the existing lock: */"
                   1709:            else
                   1710:                echo "      /* we will continue using the existing lock."
                   1711:                echo "         the device will automatically unlock after"
                   1712:                echo "         the last cycle of this write: */"
                   1713:            fi
                   1714:            echo "      cycle.tme_bus_cycle_type"
                   1715:            echo "        |= (TME_BUS_CYCLE_LOCK"
                   1716:            echo -n "            | ("
                   1717:            if test ${name} = read; then
                   1718:                echo -n "transferred == 0 ? 0 : "
                   1719:            fi
                   1720:            echo "TME_BUS_CYCLE_UNLOCK));"
1.1       root     1721:            echo "    }"
                   1722: 
                   1723:            echo ""
                   1724:            echo "    /* form the physical address for the bus cycle handler: */"
                   1725:            echo "    physical_address = tlb->tme_m68k_tlb_addr_offset + linear_address;"
                   1726:            echo "    shift = tlb->tme_m68k_tlb_addr_shift;"
                   1727:            echo "    if (shift < 0) {"
                   1728:            echo "      physical_address <<= (0 - shift);"
                   1729:            echo "    }"
                   1730:            echo "    else if (shift > 0) {"
                   1731:            echo "      physical_address >>= shift;"
                   1732:            echo "    }"
                   1733:            echo "    cycle.tme_bus_cycle_address = physical_address;"
                   1734: 
                   1735:            echo ""
                   1736:            echo "    /* run the bus cycle: */"
1.1.1.4   root     1737:            echo "    tme_m68k_tlb_unbusy(tlb);"
                   1738:            echo "    tme_m68k_callout_unlock(ic);"
1.1       root     1739:            echo "    err = (*tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycle)"
                   1740:            echo "         (tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycle_private, &cycle);"
1.1.1.4   root     1741:            echo "    tme_m68k_callout_relock(ic);"
                   1742:            echo "    tme_m68k_tlb_busy(tlb);"
1.1       root     1743:            echo ""
1.1.1.4   root     1744:            echo "    /* if the TLB entry was invalidated before the ${name}: */"
                   1745:            echo "    if (err == EBADF"
1.1.1.5 ! root     1746:            echo "        && tme_m68k_tlb_is_invalid(tlb)) {"
1.1.1.4   root     1747:            echo "      cycle.tme_bus_cycle_size = 0;"
1.1       root     1748:            echo "    }"
                   1749:            echo ""
1.1.1.3   root     1750:            echo "    /* otherwise, if we didn't get a bus error, but some"
                   1751:            echo "       synchronous event has happened: */"
                   1752:            echo "    else if (err == TME_BUS_CYCLE_SYNCHRONOUS_EVENT) {"
                   1753:            echo ""
                   1754:            echo "      /* after the currently executing instruction finishes, check"
                   1755:            echo "         for external resets, halts, or interrupts: */"
                   1756:            echo "      ic->_tme_m68k_instruction_burst_remaining = 0;"
                   1757:            echo "    }"
                   1758:            echo ""
1.1       root     1759:            echo "    /* otherwise, any other error might be a bus error: */"
                   1760:            echo "    else if (err != TME_OK) {"
                   1761:            echo "      err = tme_bus_tlb_fault(&tlb->tme_m68k_tlb_bus_tlb, &cycle, err);"
                   1762:            echo "      if (err != TME_OK) {"
1.1.1.3   root     1763:            echo "        exception = TME_M68K_EXCEPTION_BERR;"
1.1       root     1764:            echo "        break;"
                   1765:            echo "      }"
                   1766:            echo "    }"
                   1767:            echo ""
                   1768:            echo "    /* update: */"
                   1769:            echo "    linear_address += cycle.tme_bus_cycle_size;"
                   1770:            echo "    transferred += cycle.tme_bus_cycle_size;"
                   1771:            echo "  }"
                   1772:        
                   1773:            echo ""
1.1.1.4   root     1774:            echo "  /* NB: there is no need to explicitly unlock"
                   1775:            echo "     a device.  if a locked bus cycle to a device"
                   1776:            echo "     faults, the lock must be automatically unlocked: */"
1.1       root     1777: 
                   1778:            echo ""
                   1779:            echo "  /* if we faulted, stash the information the fault stacker"
                   1780:            echo "     will need and start exception processing: */"
                   1781:            echo "  if (exception != TME_M68K_EXCEPTION_NONE) {"
                   1782:            echo -n "    ic->_tme_m68k_group0_flags = flags"
                   1783:            if test $name = read; then
                   1784:                echo -n " | TME_M68K_BUS_CYCLE_READ"
                   1785:            fi
                   1786:            echo ";"
                   1787:            echo "    ic->_tme_m68k_group0_function_code = function_code;"
                   1788:            echo "    ic->_tme_m68k_group0_address = linear_address;"
                   1789:            echo "    ic->_tme_m68k_group0_sequence = ic->_tme_m68k_sequence;"
                   1790:            echo "    ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted_after = transferred;"
                   1791:            echo "    ic->_tme_m68k_group0_buffer_${name}_size = cycle_size;"
                   1792:            if test $name = write; then
                   1793:                echo "#ifdef WORDS_BIGENDIAN"
                   1794:                echo "    memcpy(ic->_tme_m68k_group0_buffer_${name},"
                   1795:                echo "           reg + transferred,"
                   1796:                echo "           ic->_tme_m68k_group0_buffer_${name}_size);"
                   1797:                echo "#else  /* !WORDS_BIGENDIAN */"
                   1798:                echo "      reg_p = (reg + reg_size - 1) - transferred;"
                   1799:                echo "      for (buffer_i = 0;"
                   1800:                echo "           buffer_i < ic->_tme_m68k_group0_buffer_${name}_size;"
                   1801:                echo "           buffer_i++) {"
                   1802:                echo "        ic->_tme_m68k_group0_buffer_${name}[buffer_i] = *(reg_p--);"
                   1803:                echo "      }"
                   1804:                echo "#endif /* !WORDS_BIGENDIAN */"
                   1805:            fi
                   1806:            echo "    if (ic->_tme_m68k_group0_hook != NULL) {"
                   1807:            echo "      (*ic->_tme_m68k_group0_hook)(ic);"
                   1808:            echo "    }"
                   1809:            echo "    ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted = ";
                   1810:            echo "      ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_next;"
1.1.1.4   root     1811:            echo "    tme_m68k_tlb_unbusy(tlb);"
1.1       root     1812:            echo "    tme_m68k_exception(ic, exception);"
                   1813:            echo "  }"
                   1814: 
                   1815:            echo ""
                   1816:            echo "  /* otherwise, this transfer has now completed: */"
                   1817:            echo "  TME_M68K_SEQUENCE_TRANSFER_STEP;"
                   1818: 
                   1819:            echo "}"
                   1820:        fi
                   1821:     done
                   1822: 
                   1823: done
                   1824: 
                   1825: # generate the BCD math functions:
                   1826: for name in abcd sbcd nbcd; do
                   1827: 
                   1828:     # if we're making the header, just emit a declaration:
                   1829:     if $header; then
                   1830:        echo "TME_M68K_INSN_DECL(tme_m68k_${name});"
                   1831:        continue
                   1832:     fi
                   1833: 
                   1834:     # emit the function:
                   1835:     echo ""
                   1836:     echo "TME_M68K_INSN(tme_m68k_${name})"
                   1837:     echo "{"
                   1838:     echo "  tme_uint8_t dst, dst_msd, dst_lsd;"
                   1839:     echo "  tme_uint8_t src, src_msd, src_lsd;"
                   1840:     echo "  tme_uint8_t res, res_msd, res_lsd;"
                   1841:     echo "  tme_uint8_t flags;"
                   1842: 
                   1843:     # get the operands:
                   1844:     if test $name != nbcd; then
                   1845:        echo "  int memory;"
                   1846:        echo "  int rx, ry, function_code;"
                   1847:        echo ""
                   1848:        echo "  /* load the operands: */"
                   1849:        echo "  rx = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);"
                   1850:        echo "  ry = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);"
                   1851:        echo "  memory = (TME_M68K_INSN_OPCODE & TME_BIT(3)) != 0;"
                   1852:        echo "  function_code = TME_M68K_FUNCTION_CODE_DATA(ic);"
                   1853:        echo "  if (memory) {"
1.1.1.4   root     1854:        echo "    TME_M68K_INSN_CANFAULT;"
1.1       root     1855:        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
1.1.1.4   root     1856:        # the stack pointer must always be decremented by a multiple of two.
                   1857:        # assuming rx < 8, ((rx + 1) >> 3) == 1 iff rx == 7, meaning %a7:
                   1858:        echo "      ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + rx) -= sizeof(tme_uint8_t) + ((rx + 1) >> 3);"
1.1       root     1859:        echo "      ic->_tme_m68k_ea_function_code = function_code;"
                   1860:        echo "      ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + rx);"
                   1861:        echo "    }"
                   1862:        echo "    tme_m68k_read_memx8(ic);"
                   1863:        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
1.1.1.4   root     1864:        # the stack pointer must always be incremented by a multiple of two.
                   1865:        # assuming rx < 8, ((rx + 1) >> 3) == 1 iff rx == 7, meaning %a7:
                   1866:        echo "      ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry) -= sizeof(tme_uint8_t) + ((ry + 1) >> 3);"
1.1       root     1867:        echo "      ic->_tme_m68k_ea_function_code = function_code;"
                   1868:        echo "      ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry);"
                   1869:        echo "    }"
                   1870:        echo "    tme_m68k_read_mem8(ic, TME_M68K_IREG_MEMY32);"
                   1871:        echo "    src = ic->tme_m68k_ireg_memx8;"
                   1872:        echo "    dst = ic->tme_m68k_ireg_memy8;"
                   1873:        echo "  }"
                   1874:        echo "  else {"
                   1875:        echo "    src = ic->tme_m68k_ireg_uint8(rx << 2);"
                   1876:        echo "    dst = ic->tme_m68k_ireg_uint8(ry << 2);"
                   1877:        echo "  }"
                   1878:     else
                   1879:        echo ""
                   1880:        echo "  dst = 0x00;"
                   1881:        echo "  src = TME_M68K_INSN_OP1(tme_uint8_t);"
                   1882:     fi
                   1883:     echo "  dst_lsd = TME_FIELD_EXTRACTU(dst, 0, 4);"
                   1884:     echo "  dst_msd = TME_FIELD_EXTRACTU(dst, 4, 4);"
                   1885:     echo "  src_lsd = TME_FIELD_EXTRACTU(src, 0, 4);"
                   1886:     echo "  src_msd = TME_FIELD_EXTRACTU(src, 4, 4);"
                   1887: 
                   1888:     # perform the operation:
                   1889:     echo ""
                   1890:     echo "  /* perform the operation: */"
                   1891:     if test $name = abcd; then op='+' ; opc='-' ; else op='-' ; opc='+' ; fi
                   1892:     echo "  res_lsd = dst_lsd ${op} src_lsd ${op} ((ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X) != 0);"
                   1893:     echo "  res_msd = dst_msd ${op} src_msd;"
                   1894:     echo "  flags = 0;"
                   1895:     echo "  if (res_lsd > 9) {"
                   1896:     echo "    res_lsd ${opc}= 10;"
                   1897:     echo "    res_msd ${op}= 1;"
                   1898:     echo "  }"
                   1899:     echo "  if (res_msd > 9) {"
                   1900:     echo "    res_msd ${opc}= 10;"
                   1901:     echo "    flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;"
                   1902:     echo "  }"
                   1903:     echo "  res = (res_msd << 4) + (res_lsd & 0xf);"
                   1904:     echo "  if (res == 0) flags |= TME_M68K_FLAG_N;"
                   1905:     echo ""
                   1906: 
                   1907:     # store the result
                   1908:     echo "  /* store the result and set the flags: */"
                   1909:     if test $name != nbcd; then
                   1910:        echo "  if (memory) {"
                   1911:        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
                   1912:        echo "      ic->tme_m68k_ireg_memx8 = res;"
                   1913:        echo "      ic->_tme_m68k_ea_function_code = function_code;"
                   1914:        echo "      ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry);"
                   1915:        echo "      ic->tme_m68k_ireg_ccr = flags;"
                   1916:        echo "     }"
                   1917:        echo "     tme_m68k_write_memx8(ic);"
                   1918:        echo "  }"
                   1919:        echo "  else {"
                   1920:        echo "    ic->tme_m68k_ireg_uint8(ry << 2) = res;"
                   1921:        echo "    ic->tme_m68k_ireg_ccr = flags;"
                   1922:        echo "  }"
                   1923:     else
                   1924:        echo "  TME_M68K_INSN_OP1(tme_uint8_t) = res;"
                   1925:        echo "  ic->tme_m68k_ireg_ccr = flags;"
                   1926:     fi
                   1927:     echo ""
                   1928:     echo "  TME_M68K_INSN_OK;"
                   1929:     echo "}"
                   1930: done
                   1931: 
                   1932: # generate the ccr and sr functions:
                   1933: for reg in ccr sr; do
                   1934:     for name in ori andi eori move_to; do
                   1935:        if test $reg = ccr; then size=8 ; else size=16 ; fi
                   1936: 
                   1937:        # if we're making the header, just emit a declaration:
                   1938:        if $header; then
                   1939:            echo "TME_M68K_INSN_DECL(tme_m68k_${name}_${reg});"
                   1940:            continue
                   1941:        fi
                   1942: 
                   1943:        # emit the function:
                   1944:        echo ""
                   1945:        echo "TME_M68K_INSN(tme_m68k_${name}_${reg})"
                   1946:        echo "{"
                   1947:        echo "  tme_uint${size}_t reg;"
                   1948: 
                   1949:        # form the new register value:
                   1950:        src=0
                   1951:        echo -n "  reg = "
                   1952:        case $name in
                   1953:        ori) echo -n "ic->tme_m68k_ireg_${reg} | " ;;
                   1954:        andi) echo -n "ic->tme_m68k_ireg_${reg} & " ;;
                   1955:        eori) echo -n "ic->tme_m68k_ireg_${reg} ^ " ;;
                   1956:        move_to) size=16 ; src=1 ;;
                   1957:        esac
                   1958:        echo "(TME_M68K_INSN_OP${src}(tme_uint${size}_t) & TME_M68K_FLAG_"`echo $reg | tr a-z A-Z`");"
                   1959:        
                   1960:        # sr changes are special:
                   1961:        if test $reg = sr; then
                   1962:            echo "  TME_M68K_INSN_PRIV;"
                   1963:            echo "  TME_M68K_INSN_CHANGE_SR(reg);"
                   1964:        else
                   1965:            echo "  ic->tme_m68k_ireg_${reg} = reg;"
                   1966:        fi
                   1967: 
                   1968:        echo "  TME_M68K_INSN_OK;"
                   1969:        echo "}"
                   1970:     done
                   1971: done
                   1972: 
                   1973: # generate the multiply and divide instructions:
                   1974: 
                   1975: # permute on signed vs. unsigned:
                   1976: for _sign in u s; do
                   1977:     if test $_sign = u; then sign=u; else sign=; fi
                   1978: 
                   1979:     # permute on short vs. long:
                   1980:     for size in s l; do
                   1981:        if test $size = s; then 
                   1982:            _size=
                   1983:            small=16
                   1984:            large=32
                   1985:            reg_size_shift=' << 1'
                   1986:        else
                   1987:            _size=l
                   1988:            small=32
                   1989:            large=64
                   1990:            reg_size_shift=
                   1991:        fi
                   1992: 
                   1993:        # if we're making the header, just emit declarations:
                   1994:        if $header; then
                   1995:            echo "TME_M68K_INSN_DECL(tme_m68k_mul${_sign}${_size});"
                   1996:            echo "TME_M68K_INSN_DECL(tme_m68k_div${_sign}${_size});"
                   1997:            continue
                   1998:        fi
                   1999: 
                   2000:        # emit the multiply function:
                   2001:        echo ""
                   2002:        echo "TME_M68K_INSN(tme_m68k_mul${_sign}${_size})"
                   2003:        echo "{"
                   2004:        if test $large = 64; then
1.1.1.2   root     2005:            echo "#ifndef TME_HAVE_INT${large}_T"
1.1       root     2006:            echo "  abort();"
1.1.1.2   root     2007:            echo "#else /* TME_HAVE_INT${large}_T */"
1.1       root     2008:            echo "  unsigned int flag_v;"
                   2009:            echo "  int ireg_dh;"
                   2010:        fi
                   2011:        echo "  int ireg_dl;"
                   2012:        echo "  tme_${sign}int${large}_t res;"
                   2013:        echo "  tme_uint8_t flags;"
                   2014: 
                   2015:        echo ""
                   2016:        echo "  /* get the register containing the factor: */"
                   2017:        echo -n "  ireg_dl = TME_M68K_IREG_D0 + "
                   2018:        if test $size = s; then
                   2019:            echo "TME_M68K_INSN_OP0(tme_uint32_t);"
                   2020:        else
                   2021:            echo "TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3);"
                   2022:        fi
                   2023: 
                   2024:        echo ""
                   2025:        echo "  /* perform the multiplication: */"
                   2026:        echo "  res = (((tme_${sign}int${large}_t) ic->tme_m68k_ireg_${sign}int${small}(ireg_dl${reg_size_shift}))"
                   2027:        echo "         * TME_M68K_INSN_OP1(tme_${sign}int${small}_t));"
                   2028:        
                   2029:        echo ""
                   2030:        echo "  /* store the result: */"
                   2031:        echo "  ic->tme_m68k_ireg_${sign}int32(ireg_dl) = (tme_${sign}int32_t) res;"
                   2032:        if test $large = 64; then
                   2033:            echo "  flag_v = TME_M68K_FLAG_V;"
                   2034:            echo "  if (TME_M68K_INSN_SPECOP & TME_BIT(10)) {"
                   2035:            echo "    flag_v = 0;"
                   2036:            echo "    ireg_dh = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3);"
                   2037:            echo "    ic->tme_m68k_ireg_${sign}int32(ireg_dh) = (tme_${sign}int32_t) (res >> 32);"
                   2038:            echo "  }"
                   2039:        fi
                   2040:        
                   2041:        echo ""
                   2042:        echo "  /* set the flags: */"
                   2043:        echo "  flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;"
                   2044:        echo "  if (((tme_int${large}_t) res) < 0) flags |= TME_M68K_FLAG_N;"
                   2045:        echo "  if (res == 0) flags |= TME_M68K_FLAG_Z;"
                   2046:        if test $large = 64; then
1.1.1.2   root     2047:            if test $_sign = s; then
                   2048:                echo -n "  if (res > 0x7fffffffL || res < ((0L - 0x7fffffffL) - 1L)"
                   2049:            else
                   2050:                echo -n "  if (res > 0xffffffffUL"
                   2051:            fi
1.1       root     2052:            echo ") flags |= flag_v;"
                   2053:        fi
                   2054:        echo "  ic->tme_m68k_ireg_ccr = flags;"
                   2055: 
                   2056:        echo ""
                   2057:        echo "  TME_M68K_INSN_OK;"
                   2058:        if test $large = 64; then
1.1.1.2   root     2059:            echo "#endif /* TME_HAVE_INT${large}_T */"
1.1       root     2060:        fi
                   2061:        echo "}"
                   2062: 
                   2063:        # emit the divide function:
                   2064:        echo ""
                   2065:        echo "TME_M68K_INSN(tme_m68k_div${_sign}${_size})"
                   2066:        echo "{"
                   2067:        if test $large = 64; then
1.1.1.2   root     2068:            echo "#ifndef TME_HAVE_INT${large}_T"
1.1       root     2069:            echo "  abort();"
1.1.1.2   root     2070:            echo "#else /* TME_HAVE_INT${large}_T */"
1.1       root     2071:            echo "  int ireg_dr;"
                   2072:        fi
                   2073:        echo "  int ireg_dq;"
                   2074:        echo "  tme_${sign}int${large}_t dividend, quotient;"
                   2075:        echo "  tme_${sign}int${small}_t divisor, remainder;"
                   2076:        echo "  tme_uint8_t flags;"
                   2077: 
                   2078:        echo ""
                   2079:        echo "  /* get the register(s): */"
                   2080:        echo -n "  ireg_dq = TME_M68K_IREG_D0 + "
                   2081:        if test $size = s; then
                   2082:            echo "TME_M68K_INSN_OP0(tme_uint32_t);"
                   2083:        else
                   2084:            echo "TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3);"
                   2085:            echo "  ireg_dr = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3);"
                   2086:        fi
                   2087: 
                   2088:        echo ""
                   2089:        echo "  /* form the dividend and the divisor: */"
                   2090:        if test $large = 64; then
                   2091:            echo "  if (TME_M68K_INSN_SPECOP & TME_BIT(10)) {"
                   2092:            echo "    dividend = (tme_${sign}int${large}_t)"
                   2093:            echo "               ((((tme_uint${large}_t) ic->tme_m68k_ireg_uint32(ireg_dr)) << 32)"
                   2094:            echo "                | ic->tme_m68k_ireg_uint32(ireg_dq));"
                   2095:            echo "  }"
                   2096:            echo "  else"
                   2097:            echo -n "  "
                   2098:        fi
                   2099:        echo "  dividend = (tme_${sign}int${large}_t) ic->tme_m68k_ireg_${sign}int32(ireg_dq);"
                   2100:        echo "  divisor = TME_M68K_INSN_OP1(tme_${sign}int${small}_t);"
                   2101:        echo "  if (divisor == 0) {"
1.1.1.3   root     2102:        echo "    ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;"
1.1       root     2103:        echo "    ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;"
1.1.1.3   root     2104:        echo "    TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_DIV0));"
1.1       root     2105:        echo "  }"
                   2106: 
                   2107:        echo ""
                   2108:        echo "  /* do the division: */"
                   2109:        echo "  quotient = dividend / divisor;"
                   2110:        echo "  remainder = dividend % divisor;"
                   2111: 
                   2112:        echo ""
                   2113:        echo "  /* set the flags and return the quotient and remainder: */"
                   2114:        echo "  flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;"
1.1.1.2   root     2115:        echo -n "  if ("
                   2116:        case "${small}${_sign}" in
                   2117:        16s) echo -n "quotient > 0x7fff || quotient < -32768" ;;
                   2118:        16u) echo -n "quotient > 0xffff" ;;
                   2119:        32s) echo -n "quotient > 0x7fffffffL || quotient < ((0L - 0x7fffffffL) - 1L)" ;;
                   2120:        32u) echo -n "quotient > 0xffffffffUL" ;;
                   2121:        esac
1.1       root     2122:        echo ") {"
                   2123:        echo "    flags |= TME_M68K_FLAG_V;"
                   2124:        echo "  }"
                   2125:        echo "  else {"
                   2126:        echo "    if (((tme_int${small}_t) quotient) < 0) flags |= TME_M68K_FLAG_N;"
                   2127:        echo "    if (quotient == 0) flags |= TME_M68K_FLAG_Z;"
                   2128:        echo "    ic->tme_m68k_ireg_${sign}int${small}(ireg_dq${reg_size_shift}) = (tme_${sign}int${small}_t) quotient;"
                   2129:        if test $small = 16; then
                   2130:            echo "    ic->tme_m68k_ireg_${sign}int${small}((ireg_dq${reg_size_shift}) + 1) = remainder;"
                   2131:        else
                   2132:            echo "    if (ireg_dr != ireg_dq) {"
                   2133:            echo "      ic->tme_m68k_ireg_${sign}int${small}(ireg_dr) = remainder;"
                   2134:            echo "    }"
                   2135:        fi
                   2136:        echo "  }"
                   2137:        echo "  ic->tme_m68k_ireg_ccr = flags;"
                   2138: 
                   2139:        echo ""
                   2140:        echo "  TME_M68K_INSN_OK;"
                   2141:        if test $large = 64; then
1.1.1.2   root     2142:            echo "#endif /* TME_HAVE_INT${large}_T */"
1.1       root     2143:        fi
                   2144:        echo "}"
                   2145: 
                   2146:     done
                   2147: done
                   2148: 
                   2149: # done:
                   2150: exit 0

unix.superglobalmegacorp.com

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