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

1.1       root        1: #! /bin/sh
                      2: 
1.1.1.4 ! root        3: # $Id: m68k-insns-auto.sh,v 1.25 2007/08/25 21:47:00 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.4 ! root       51: _TME_RCSID("\$Id: m68k-insns-auto.sh,v 1.25 2007/08/25 21:47:00 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=""
                   1096:                tlb="TME_M68K_TLB_ENTRY(ic, function_code, linear_address${_first})"
                   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.4 ! root     1150:                    tlb="tme_memory_atomic_pointer_read(struct tme_m68k_tlb *, ic->_tme_m68k_itlb, &ic->_tme_m68k_tlbs_rwlock)";
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:
                   1172:                echo -n "  unsigned int function_code = "
                   1173:                if test "x${fc}" != x; then
                   1174:                    echo "${fc};"
                   1175:                    fc="function_code"
                   1176:                    fcptr="&function_code"
                   1177:                else
                   1178:                    fc=`echo ${fcptr} | sed -e 's,^&,,'`
                   1179:                    echo "${fc};"
                   1180:                fi
                   1181:                echo -n "  tme_uint32_t linear_address${_first} = "
                   1182:                if test "x${addr}" != x; then
                   1183:                    echo "${addr};"
                   1184:                    addr="linear_address${_first}"
                   1185:                    addrptr="&linear_address${_first}"
                   1186:                else
                   1187:                    addr=`echo ${addrptr} | sed -e 's,^&,,'`
                   1188:                    echo "${addr};"
                   1189:                fi
                   1190:                if test "x${count}" = x; then
                   1191:                    if test $size = any; then count=count; else count="sizeof(tme_uint${size}_t)"; fi
                   1192:                fi
                   1193:                if test x$_last != x; then
                   1194:                    echo "  tme_uint32_t linear_address${_last} = linear_address_first + ${count} - 1;";
                   1195:                fi
                   1196:                echo "  struct tme_m68k_tlb *tlb = ${tlb};"
1.1.1.4 ! root     1197:                if test $size != any; then
        !          1198:                    memtype="tme_uint${size}_t"
        !          1199:                    echo "  ${memtype} mem_value;"
        !          1200:                    memtype="tme_shared ${memtype} *"
        !          1201:                    if test $name = read; then memtype="const ${memtype}"; fi
        !          1202:                    echo "  ${memtype}mem;"
        !          1203:                fi
1.1       root     1204:                case "$what" in
                   1205:                inst)
1.1.1.4 ! root     1206:                    echo "  unsigned int fetch_slow_next = ic->_tme_m68k_insn_fetch_slow_next;"
        !          1207:                    regptr="((tme_uint${size}_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next))"
1.1       root     1208:                    reg="*${regptr}"
                   1209:                    ;;
                   1210:                esac
                   1211: 
1.1.1.3   root     1212:                # track statistics:
                   1213:                echo ""
                   1214:                echo "#ifdef _TME_M68K_STATS"
                   1215:                echo "  ic->tme_m68k_stats.tme_m68k_stats_memory_total++;"
                   1216:                echo "#endif /* _TME_M68K_STATS */"
                   1217: 
1.1       root     1218:                # if this is a write, log the value written:
                   1219:                if test $name = write; then
                   1220:                    echo ""
                   1221:                    echo "  /* log the value written: */"
                   1222:                    if test $size != any; then
                   1223:                        echo "  tme_m68k_verify_mem${size}(ic, ${fc}, ${addr}, ${reg}, TME_BUS_CYCLE_WRITE);"
                   1224:                        echo "  tme_m68k_log(ic, 1000, TME_OK, "
                   1225:                        echo "               (TME_M68K_LOG_HANDLE(ic),"
                   1226:                        echo "                _(\"${action}\t%d:0x%08x:\t0x%0"`expr ${size} / 4`"x\"),"
                   1227:                        echo "                ${fc},"
                   1228:                        echo "                ${addr},"
                   1229:                        echo "                ${reg}));"
                   1230:                    else
                   1231:                        echo "  tme_m68k_verify_mem_any(ic, ${fc}, ${addr}, ${regptr}, ${count}, TME_BUS_CYCLE_WRITE);"
                   1232:                        echo "  tme_m68k_log_start(ic, 1000, TME_OK) {"
                   1233:                        echo "    unsigned int byte_i;"
                   1234:                        echo "    tme_log_part(TME_M68K_LOG_HANDLE(ic),"
                   1235:                        echo "                 _(\"${action} %d:0x%08x count %d:\"),"
                   1236:                        echo "                 ${fc},"
                   1237:                        echo "                 ${addr},"
                   1238:                        echo "                 ${count});"
                   1239:                        echo "    for (byte_i = 0; byte_i < count ; byte_i++) {"
                   1240:                        echo "      tme_log_part(TME_M68K_LOG_HANDLE(ic), \" 0x%02x\", (${regptr})[byte_i]);"
                   1241:                        echo "    }"
                   1242:                        echo "  } tme_m68k_log_finish(ic);"
                   1243:                    fi
                   1244:                fi
                   1245: 
                   1246:                echo ""
1.1.1.4 ! root     1247:                echo "  /* busy this TLB entry: */"
        !          1248:                echo "  tme_m68k_tlb_busy(tlb);"
1.1       root     1249: 
1.1.1.4 ! root     1250:                # if this is an any-transfer:
        !          1251:                #
        !          1252:                if test $size = any; then
        !          1253:                    echo ""
        !          1254:                    echo "  /* call the full ${name} function: */"
        !          1255:                    echo "  tme_m68k_${name}(ic, tlb, ${fcptr}, ${addrptr}, ${regptr}, ${count}, TME_M68K_BUS_CYCLE_RAW);"
        !          1256: 
        !          1257:                # otherwise, this is not an any-transfer:
        !          1258:                #
1.1       root     1259:                else
                   1260: 
1.1.1.4 ! root     1261:                    # dispatch on the what:
        !          1262:                    #
        !          1263:                    i=
        !          1264:                    case "$what" in
        !          1265:                    inst)
        !          1266:                        echo ""
        !          1267:                        echo "  /* if this fetch was done by the fast executor: */"
        !          1268:                        echo "  if (__tme_predict_true(fetch_slow_next < ic->_tme_m68k_insn_fetch_slow_count_fast)) {"
        !          1269:                        echo ""
        !          1270:                        echo "    /* the entire fetch must be in the instruction buffer, and"
        !          1271:                        echo "       we must be restarting: */"
        !          1272:                        echo "    assert ((fetch_slow_next + sizeof(tme_uint${size}_t))"
        !          1273:                        echo "            <= ic->_tme_m68k_insn_fetch_slow_count_fast);"
        !          1274:                        echo "    assert (TME_M68K_SEQUENCE_RESTARTING);"
        !          1275:                        echo "    mem_value = tme_memory_read${size}(${regptr}, sizeof(tme_uint16_t));"
        !          1276:                        echo "  }"
        !          1277:                        echo ""
        !          1278:                        echo "  /* otherwise, this fetch was not done by the fast executor: */"
        !          1279:                        echo "  else {"
        !          1280:                        echo ""
        !          1281:                        echo "    /* if we're restarting, but the offset in the instruction buffer"
        !          1282:                        echo "       to fetch into is at the instruction buffer total, this must be"
        !          1283:                        echo "       a fake fault caused by the fast executor.  we confirm this by"
        !          1284:                        echo "       checking that this transfer \"caused\" the fault, and that this"
        !          1285:                        echo "       transfer will be the first slow one after any fast fetches."
        !          1286:                        echo "       in this case, we can cancel the restart for now: */"
        !          1287:                        echo "    if (TME_M68K_SEQUENCE_RESTARTING"
        !          1288:                        echo "        && (fetch_slow_next"
        !          1289:                        echo "            == ic->_tme_m68k_insn_fetch_slow_count_total)) {"
        !          1290:                        echo "      assert ((ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next"
        !          1291:                        echo "               == ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted)"
        !          1292:                        echo "              && (fetch_slow_next"
        !          1293:                        echo "                  == ic->_tme_m68k_insn_fetch_slow_count_fast));"
        !          1294:                        echo "      ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted--;"
        !          1295:                        echo "    }"
        !          1296:                        echo ""
        !          1297:                        echo "    /* if we're not restarting: */"
        !          1298:                        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
        !          1299:                        echo ""
        !          1300:                        echo "      /* we advance the instruction buffer total *before* we do"
        !          1301:                        echo "         what may be a slow fetch, because we may transfer a few"
        !          1302:                        echo "         bytes and then fault.  without this, those few bytes"
        !          1303:                        echo "         would not get saved in the exception stack frame and"
        !          1304:                        echo "         restored later before the continuation of the fetch: */"
        !          1305:                        echo "      ic->_tme_m68k_insn_fetch_slow_count_total += sizeof(tme_uint${size}_t);"
        !          1306:                        echo "    }"
        !          1307:                        echo ""
        !          1308:                        echo "    /* make sure that if this is a new transfer or if this"
        !          1309:                        echo "       transfer faulted, that we're fetching for the current"
        !          1310:                        echo "       last positions in the instruction buffer: */"
        !          1311:                        echo "    assert ((ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next"
        !          1312:                        echo "             < ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted)"
        !          1313:                        echo "            || ((fetch_slow_next + sizeof(tme_uint${size}_t))"
        !          1314:                        echo "                == ic->_tme_m68k_insn_fetch_slow_count_total));"
        !          1315:                        i="  "
        !          1316:                        ;;
        !          1317:                    esac
        !          1318: 
        !          1319:                    echo ""
        !          1320:                    echo "${i}  /* if we aren't restarting, and this address is properly aligned,"
        !          1321:                    echo "${i}     and this TLB entry covers the operand and allows fast ${name}s: */"
        !          1322:                    echo "${i}  if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING"
        !          1323:                    align_min="sizeof(tme_uint8_t)"
        !          1324:                    if test $size != 8; then
        !          1325:                        echo -n "${i}                         && ("
        !          1326:                        if test $what = inst; then
        !          1327:                            align_min="sizeof(tme_uint16_t)"
        !          1328:                            echo -n "(${align_min} - 1)"
        !          1329:                        else
        !          1330:                            echo -n "ic->_tme_m68k_bus_16bit"
        !          1331:                        fi
        !          1332:                        echo " & linear_address${_first}) == 0"
1.1       root     1333:                    fi
1.1.1.4 ! root     1334:                    echo "${i}                         && TME_M68K_TLB_OK_FAST_${capname}(tlb,"
        !          1335:                    echo "${i}                                                      function_code,"
        !          1336:                    echo "${i}                                                      linear_address${_first},"
        !          1337:                    echo "${i}                                                      linear_address${_last}))) {"
        !          1338: 
1.1       root     1339:                    echo ""
1.1.1.4 ! root     1340:                    echo "${i}    /* make the emulator memory pointer: */"
        !          1341:                    echo "${i}    mem = (${memtype}) (tlb->tme_m68k_tlb_emulator_off_${name} + linear_address${_first});"
        !          1342: 
        !          1343:                    if test $name = write; then
        !          1344:                        if test $size = 8; then
        !          1345:                            echo ""
        !          1346:                            echo "${i}    /* get the value to write: */"
        !          1347:                            echo "${i}    mem_value = ${reg};"
        !          1348:                        else
        !          1349:                            echo ""
        !          1350:                            echo "${i}    /* get the value to write, in big-endian byte order: */"
        !          1351:                            echo "${i}    mem_value = tme_htobe_u${size}(${reg});"
        !          1352:                        fi
        !          1353:                    fi
        !          1354: 
1.1       root     1355:                    echo ""
1.1.1.4 ! root     1356:                    echo "${i}    /* do the ${size}-bit bus ${name}: */"
1.1       root     1357:                    if test $name = read; then
1.1.1.4 ! root     1358:                        echo -n "${i}    mem_value = tme_memory_bus_${name}${size}(mem"
1.1       root     1359:                    else
1.1.1.4 ! root     1360:                        echo -n "${i}    tme_memory_bus_${name}${size}(mem, mem_value"
1.1       root     1361:                    fi
1.1.1.4 ! root     1362:                    echo ", tlb->tme_m68k_tlb_bus_rwlock, ${align_min}, sizeof(tme_uint32_t));"
        !          1363: 
1.1       root     1364:                    if test $name = read; then
1.1.1.4 ! root     1365:                        if test $what = inst; then
        !          1366:                            echo ""
        !          1367:                            echo "${i}    /* put the value read, in host byte order: */"
        !          1368:                            echo "${i}    mem_value = tme_betoh_u${size}(mem_value);"
        !          1369:                            echo "${i}    tme_memory_write${size}(${regptr}, mem_value, sizeof(tme_uint16_t));"
        !          1370:                        elif test $size = 8; then
        !          1371:                            echo ""
        !          1372:                            echo "${i}    /* put the value read: */"
        !          1373:                            echo "${i}    ${reg} = mem_value;"
        !          1374:                        else
        !          1375:                            echo ""
        !          1376:                            echo "${i}    /* put the value read, in host byte order: */"
        !          1377:                            echo "${i}    ${reg} = tme_betoh_u${size}(mem_value);"
        !          1378:                        fi
1.1       root     1379:                    fi
                   1380: 
1.1.1.4 ! root     1381:                    echo ""
        !          1382:                    echo "${i}    /* step the transfer count: */"
        !          1383:                    echo "${i}    TME_M68K_SEQUENCE_TRANSFER_STEP;"
        !          1384:                    echo "${i}  }"
        !          1385: 
        !          1386:                    echo ""
        !          1387:                    echo "${i}  /* otherwise, do the bus cycles the slow way: */"
        !          1388:                    echo "${i}  else {"
        !          1389:                    echo "${i}    tme_m68k_${name}${size}(ic, tlb,"
        !          1390:                    echo "${i}                    ${fcptr},"
        !          1391:                    echo "${i}                    ${addrptr},"
        !          1392:                    echo "${i}                    ${regptr},"
        !          1393:                    echo "${i}                    ${flags});"
        !          1394:                    if test ${what} = inst; then
        !          1395:                        echo "${i}    mem_value = tme_memory_read${size}(${regptr}, sizeof(tme_uint16_t));"
        !          1396:                    fi
        !          1397:                    echo "${i}  }"
        !          1398:                fi
        !          1399:                if test "x${i}" != x; then
        !          1400:                    echo "  }"
1.1       root     1401:                fi
                   1402: 
                   1403:                echo ""
1.1.1.4 ! root     1404:                echo "  /* unbusy this TLB entry: */"
        !          1405:                echo "  tme_m68k_tlb_unbusy(tlb);"
1.1       root     1406:                
                   1407:                # if this is a read, log the value read:
                   1408:                if test $name = read; then
                   1409:                    echo ""
                   1410:                    echo "  /* log the value read: */"
                   1411:                    if test $size != any; then
                   1412:                        echo "  tme_m68k_verify_mem${size}(ic, ${fc}, ${addr}, ${reg}, TME_BUS_CYCLE_READ);"
                   1413:                        echo "  tme_m68k_log(ic, 1000, TME_OK,"
                   1414:                        echo "               (TME_M68K_LOG_HANDLE(ic),"
                   1415:                        echo "                _(\"${action}\t%d:0x%08x:\t0x%0"`expr ${size} / 4`"x\"),"
                   1416:                        echo "                ${fc},"
                   1417:                        echo "                ${addr},"
                   1418:                        echo "                ${reg}));"
                   1419:                    else
                   1420:                        echo "  tme_m68k_verify_mem_any(ic, ${fc}, ${addr}, ${regptr}, ${count}, TME_BUS_CYCLE_READ);"
                   1421:                        echo "  tme_m68k_log_start(ic, 1000, TME_OK) {"
                   1422:                        echo "    unsigned int byte_i;"
                   1423:                        echo "    tme_log_part(TME_M68K_LOG_HANDLE(ic),"
                   1424:                        echo "                 _(\"${action} %d:0x%08x count %d:\"),"
                   1425:                        echo "                 ${fc},"
                   1426:                        echo "                 ${addr},"
                   1427:                        echo "                 ${count});"
                   1428:                        echo "    for (byte_i = 0; byte_i < count ; byte_i++) {"
                   1429:                        echo "      tme_log_part(TME_M68K_LOG_HANDLE(ic), \" 0x%02x\", (${regptr})[byte_i]);"
                   1430:                        echo "    }"
                   1431:                        echo "  } tme_m68k_log_finish(ic);"
                   1432:                    fi
                   1433:                fi
                   1434: 
                   1435:                # perform any updating and value returning:
                   1436:                case "$what" in
                   1437:                stack)
                   1438:                    if test $name = read; then dir="+"; else dir="-"; fi
                   1439:                    echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
                   1440:                    echo "    ic->tme_m68k_ireg_a7 ${dir}= sizeof(tme_uint${size}_t);"
                   1441:                    echo "  }"
                   1442:                    ;;
                   1443:                inst)
1.1.1.4 ! root     1444:                    echo ""
        !          1445:                    echo "  /* advance the offset in the instruction buffer for the next slow fetch: */"
        !          1446:                    echo "  fetch_slow_next += sizeof(tme_uint${size}_t);"
        !          1447:                    echo "  ic->_tme_m68k_insn_fetch_slow_next = fetch_slow_next;"
        !          1448:                    echo ""
        !          1449:                    echo "  /* return the fetched value: */"
        !          1450:                    echo "  return(mem_value);"
1.1       root     1451:                    ;;
                   1452:                esac
                   1453: 
                   1454:                echo "}"
                   1455:            :
                   1456:        done
                   1457: 
                   1458:        # the general-purpose cycle-making read and write macros:
                   1459:        if test ${size} != any; then
                   1460: 
                   1461:            # if we're making the header, emit a macro:
                   1462:            if $header; then
                   1463:                echo "#define tme_m68k_${name}${size}(ic, t, fc, la, _v, f) \\"
                   1464:                echo "  tme_m68k_${name}(ic, t, fc, la, (tme_uint8_t *) (_v), sizeof(tme_uint${size}_t), f)"
                   1465:            fi
                   1466:        else
                   1467: 
                   1468:            # if we're making the header, just emit a declaration:
                   1469:            if $header; then
                   1470:                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));"
                   1471:                continue
                   1472:            fi
                   1473: 
                   1474:            echo ""
                   1475:            echo "/* this ${name}s a region of address space using actual bus cycles: */"
                   1476:            echo "void"
                   1477:            echo "tme_m68k_${name}(struct tme_m68k *ic, "
                   1478:            echo "              struct tme_m68k_tlb *tlb,"
                   1479:            echo "              unsigned int *_function_code, "
                   1480:            echo "              tme_uint32_t *_linear_address, "
                   1481:            echo "              tme_uint8_t *reg,"
                   1482:            echo "              unsigned int reg_size,"
                   1483:            echo "              unsigned int flags)"
                   1484:            echo "{"
                   1485: 
                   1486:            # our locals:
                   1487:            echo "  unsigned int function_code;"
                   1488:            echo "  tme_uint32_t linear_address;"
                   1489:            echo "  tme_bus_addr_t physical_address;"
                   1490:            echo "  int shift;"
                   1491:            echo "  struct tme_bus_cycle cycle;"
                   1492:            echo "  unsigned int transferred, resid, cycle_size;"
                   1493:            echo "  int exception;"
                   1494:            echo "  int err;"
                   1495:            echo "  tme_uint8_t *reg_p;"
                   1496:            echo "  unsigned int buffer_i;"
1.1.1.4 ! root     1497:            echo "  tme_uint8_t reg_buffer[sizeof(tme_uint32_t) * 2];"
        !          1498:            if test ${name} = read; then name_const_mem="const "; else name_const_mem= ; fi
        !          1499:            echo "  ${name_const_mem}tme_shared tme_uint8_t *mem;"
1.1       root     1500: 
                   1501:            echo ""
                   1502:            echo "  /* if we're not restarting, everything is fresh: */"
                   1503:            echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
                   1504:            echo "    function_code = *_function_code;"
                   1505:            echo "    linear_address = *_linear_address;"
                   1506:            echo "    transferred = 0;"
                   1507:            echo "  }"
                   1508: 
                   1509:            echo ""
                   1510:            echo "  /* otherwise, if this is the transfer that faulted, restore"
                   1511:            echo "     our state to the cycle that faulted, then take into account"
                   1512:            echo "     any data provided by a software rerun of the faulted cycle: */"
                   1513:            echo "  else if (ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted"
                   1514:            echo "           == ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next) {"
                   1515:            echo "    function_code = *_function_code = ic->_tme_m68k_group0_function_code;"
                   1516:            echo "    linear_address = ic->_tme_m68k_group0_address;"
                   1517:            echo "    transferred = ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted_after;"
                   1518:            echo "    if (transferred >= reg_size) abort();"
                   1519:            echo "    *_linear_address = linear_address - transferred;"
                   1520:            echo "    resid = reg_size - transferred;"
                   1521:            echo "    if (ic->_tme_m68k_group0_buffer_${name}_size > resid) abort();"
                   1522:            echo "    if (ic->_tme_m68k_group0_buffer_${name}_softrr > resid) abort();"
                   1523:            if test $name = read; then cmp=">"; else cmp="=="; fi
                   1524:            echo "    if (ic->_tme_m68k_group0_buffer_${name}_softrr ${cmp} 0) {"
                   1525:            echo "#ifdef WORDS_BIGENDIAN"
                   1526:            echo "      memcpy(reg + transferred, "
                   1527:            echo "             ic->_tme_m68k_group0_buffer_${name},"
                   1528:            echo "             ic->_tme_m68k_group0_buffer_${name}_size);"
                   1529:            echo "#else  /* !WORDS_BIGENDIAN */"
                   1530:            echo "      reg_p = (reg + reg_size - 1) - transferred;"
                   1531:            echo "      for (buffer_i = 0;"
                   1532:            echo "           buffer_i < ic->_tme_m68k_group0_buffer_${name}_size;"
                   1533:            echo "           buffer_i++) {"
                   1534:            echo "        *(reg_p--) = ic->_tme_m68k_group0_buffer_${name}[buffer_i];"
                   1535:            echo "      }"
                   1536:            echo "#endif /* !WORDS_BIGENDIAN */"
                   1537:            echo "    }"
                   1538:            echo "    transferred += ic->_tme_m68k_group0_buffer_${name}_softrr;"
                   1539:            echo "  }"
                   1540: 
                   1541:            echo ""
                   1542:            echo "  /* otherwise, a later transfer has faulted.  just step the"
                   1543:            echo "     transfer number and return: */"
                   1544:            echo "  else {"
                   1545:            echo "    TME_M68K_SEQUENCE_TRANSFER_STEP;"
                   1546:            echo "    return;"
                   1547:            echo "  }"
                   1548: 
                   1549:            echo ""
                   1550:            echo "  /* do as many bus cycles as needed to complete the transfer: */"
                   1551:            echo "  exception = TME_M68K_EXCEPTION_NONE;"
                   1552:            echo "  cycle_size = 0;"
                   1553:            echo "  for(; transferred < reg_size; ) {"
                   1554:            echo "    resid = reg_size - transferred;"
                   1555: 
                   1556:            echo ""
                   1557:            echo "    /* start the bus cycle structure: */"
                   1558:            echo "    cycle.tme_bus_cycle_type = TME_BUS_CYCLE_${capname};"
                   1559:            echo "    if (TME_ENDIAN_NATIVE == TME_ENDIAN_BIG"
                   1560:            echo "        || (flags & TME_M68K_BUS_CYCLE_RAW)) {"
                   1561:            echo "      cycle.tme_bus_cycle_buffer = reg + transferred;"
                   1562:            echo "      cycle.tme_bus_cycle_buffer_increment = 1;"
                   1563:            echo "    }"
                   1564:            echo "    else {"
                   1565:            echo "      cycle.tme_bus_cycle_buffer = reg + reg_size - (1 + transferred);"
                   1566:            echo "      cycle.tme_bus_cycle_buffer_increment = -1;"
                   1567:            echo "    }"
                   1568: 
                   1569:            echo ""
                   1570:            echo "    /* if we're emulating a CPU with a 16-bit bus interface: */"
                   1571:            echo "    if (ic->_tme_m68k_bus_16bit) {"
                   1572:            echo ""
                   1573:            echo "      /* if we're trying to transfer a non-power-of-two"
                   1574:            echo "         number of bytes, either the CPU is broken (no"
                   1575:            echo "         instructions ever transfer a non-power-of-two"
                   1576:            echo "         number of bytes), or this function allowed an"
                   1577:            echo "         unaligned transfer: */"
                   1578:            echo "      assert((resid & (resid - 1)) == 0"
                   1579:            echo "             || (flags & TME_M68K_BUS_CYCLE_RAW));"
                   1580:            echo ""
                   1581:            echo "      /* only byte transfers can be unaligned: */"
                   1582:            echo "      if (resid > sizeof(tme_uint8_t)"
                   1583:            echo "          && (linear_address & 1)) {"
1.1.1.3   root     1584:            echo "          exception = TME_M68K_EXCEPTION_AERR;"
1.1       root     1585:            echo "          break;"
                   1586:            echo "      }"
                   1587:            echo ""
                   1588:            echo "      /* set the bus-size specific parts of the bus cycle structure: */"
                   1589:            echo "      cycle_size = TME_MIN(resid, sizeof(tme_uint16_t));"
                   1590:            echo "      cycle.tme_bus_cycle_size = cycle_size;"
                   1591:            echo "      cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS16_LOG2);"
                   1592:            echo "      cycle.tme_bus_cycle_lane_routing = "
                   1593:            echo "        &tme_m68k_router_16[TME_M68K_BUS_ROUTER_INDEX(TME_BUS16_LOG2, cycle_size, linear_address)];"
                   1594:            echo "    }"
                   1595:            echo ""
                   1596:            echo "    /* otherwise we're emulating a CPU with a 32-bit bus interface: */"
                   1597:            echo "    else {"
                   1598:            if test $name = read; then
                   1599:                echo ""
                   1600:                echo "      /* an instruction fetch must be aligned: */"
                   1601:                echo "      if (flags & TME_M68K_BUS_CYCLE_FETCH) {"
                   1602:                echo "        if (linear_address & 1) {"
1.1.1.3   root     1603:                echo "          exception = TME_M68K_EXCEPTION_AERR;"
1.1       root     1604:                echo "          break;"
                   1605:                echo "        }"
                   1606:                echo "        assert(!(resid & 1));"
                   1607:                echo "      }"
                   1608:            fi
                   1609:            echo ""
                   1610:            echo "      /* set the bus-size specific parts of the bus cycle structure: */"
                   1611:            echo "      cycle_size = TME_MIN(resid, sizeof(tme_uint32_t) - (linear_address & (sizeof(tme_uint32_t) - 1)));"
                   1612:            echo "      cycle.tme_bus_cycle_size = cycle_size;"
                   1613:            echo "      cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS32_LOG2);"
                   1614:            echo "      cycle.tme_bus_cycle_lane_routing = "
                   1615:            echo "        &tme_m68k_router_32[TME_M68K_BUS_ROUTER_INDEX(TME_BUS32_LOG2, cycle_size, linear_address)];"
                   1616:            echo "    }"
                   1617:        
                   1618:            echo ""
1.1.1.4 ! root     1619:            echo "    /* loop while this TLB entry is invalid or does not apply: */"
        !          1620:            echo "    for (; __tme_predict_false(tme_bus_tlb_is_invalid(&tlb->tme_m68k_tlb_bus_tlb)"
        !          1621:            echo "                               || (tlb->tme_m68k_tlb_function_codes_mask & TME_BIT(function_code)) == 0"
        !          1622:            echo "                               || linear_address < tlb->tme_m68k_tlb_linear_first"
        !          1623:            echo "                               || linear_address > tlb->tme_m68k_tlb_linear_last"
        !          1624:            echo "                               || (tlb->tme_m68k_tlb_emulator_off_${name} == TME_EMULATOR_OFF_UNDEF"
        !          1625:            echo "                                   && (tlb->tme_m68k_tlb_cycles_ok & TME_BUS_CYCLE_${capname}) == 0)); ) {"
        !          1626:            echo ""
        !          1627:            echo "      /* this must not be part of a read/modify/write cycle: */"
        !          1628:            echo "      assert(!(flags & TME_M68K_BUS_CYCLE_RMW));"
        !          1629:            echo ""
        !          1630:            echo "      /* fill this TLB entry: */"
1.1       root     1631:            echo "      tme_m68k_tlb_fill(ic, tlb,"
                   1632:            echo "                        function_code,"
                   1633:            echo "                        linear_address,"
                   1634:            echo "                        TME_BUS_CYCLE_${capname});"
                   1635:            echo "    }"
                   1636:            echo ""
1.1.1.4 ! root     1637:            echo "    /* if this TLB entry allows for fast ${name}s: */"
        !          1638:            echo "    mem = tlb->tme_m68k_tlb_emulator_off_${name};"
        !          1639:            echo "    if (__tme_predict_true(mem != TME_EMULATOR_OFF_UNDEF)) {"
        !          1640:            echo ""
        !          1641:            echo "      /* make the emulator memory pointer: */"
        !          1642:            echo "      mem += linear_address;"
        !          1643:            echo ""
        !          1644:            echo "      /* limit the cycle size to addresses covered by the TLB entry: */"
        !          1645:            echo "      if (__tme_predict_false((cycle_size - 1)"
        !          1646:            echo "                              > (tlb->tme_m68k_tlb_linear_last - linear_address))) {"
        !          1647:            echo "        cycle_size = (tlb->tme_m68k_tlb_linear_last - linear_address) + 1;"
1.1       root     1648:            echo "      }"
                   1649:            echo ""
1.1.1.4 ! root     1650:            echo "      /* if this is a little-endian host, and this isn't a raw ${name}: */"
        !          1651:            echo "      if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE"
        !          1652:            echo "          && (flags & TME_M68K_BUS_CYCLE_RAW) == 0) {"
        !          1653:            if test ${name} = write; then
        !          1654:                echo ""
        !          1655:                echo "        /* byteswap the data to write in the intermediate buffer: */"
        !          1656:                echo "        reg_p = cycle.tme_bus_cycle_buffer;"
        !          1657:                echo "        buffer_i = 0;"
        !          1658:                echo "        do {"
        !          1659:                echo "          reg_buffer[buffer_i] = *(reg_p--);"
        !          1660:                echo "        } while (++buffer_i != cycle_size);"
        !          1661:            fi
        !          1662:            echo ""
        !          1663:            echo "        /* use the intermediate buffer for the ${name}: */"
        !          1664:            echo "        cycle.tme_bus_cycle_buffer = &reg_buffer[0];"
1.1       root     1665:            echo "      }"
1.1.1.4 ! root     1666:            echo ""
        !          1667:            echo "      /* do the bus ${name}: */"
        !          1668:            echo "      tme_memory_bus_${name}_buffer(mem,"
        !          1669:            echo "                                 cycle.tme_bus_cycle_buffer,"
        !          1670:            echo "                                 cycle_size,"
        !          1671:            echo "                                 tlb->tme_m68k_tlb_bus_rwlock,"
        !          1672:            echo "                                 sizeof(tme_uint8_t),"
        !          1673:            echo "                                 sizeof(tme_uint32_t));"
        !          1674:            if test ${name} = read; then
        !          1675:                echo ""
        !          1676:                echo "      /* if this is a little-endian host, and this isn't a raw ${name}: */"
        !          1677:                echo "      if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE"
        !          1678:                echo "          && (flags & TME_M68K_BUS_CYCLE_RAW) == 0) {"
        !          1679:                echo ""
        !          1680:                echo "        /* byteswap the read data in the intermediate buffer: */"
        !          1681:                echo "        reg_p = reg + reg_size - (1 + transferred);"
        !          1682:                echo "        buffer_i = 0;"
        !          1683:                echo "        do {"
        !          1684:                echo "          *(reg_p--) = reg_buffer[buffer_i];"
        !          1685:                echo "        } while (++buffer_i != cycle_size);"
        !          1686:                echo "      }"
        !          1687:            fi
        !          1688:            echo ""
        !          1689:            echo "      /* update: */"
        !          1690:            echo "      linear_address += cycle_size;"
        !          1691:            echo "      transferred += cycle_size;"
        !          1692:            echo "      continue;"
        !          1693:            echo "    }"
        !          1694:            echo ""
        !          1695:            echo "    /* otherwise, this TLB entry does not allow for fast ${name}s: */"
        !          1696:            echo ""
        !          1697:            echo "    /* if this is a part of a read/modify/write cycle: */"
        !          1698:            echo "    if (flags & TME_M68K_BUS_CYCLE_RMW) {"
        !          1699:            echo ""
        !          1700:            if test ${name} = read; then
        !          1701:                echo "      /* if this is the first cycle in this read,"
        !          1702:                echo "         we will establish the new lock, otherwise"
        !          1703:                echo "         we will continue using the existing lock: */"
        !          1704:            else
        !          1705:                echo "      /* we will continue using the existing lock."
        !          1706:                echo "         the device will automatically unlock after"
        !          1707:                echo "         the last cycle of this write: */"
        !          1708:            fi
        !          1709:            echo "      cycle.tme_bus_cycle_type"
        !          1710:            echo "        |= (TME_BUS_CYCLE_LOCK"
        !          1711:            echo -n "            | ("
        !          1712:            if test ${name} = read; then
        !          1713:                echo -n "transferred == 0 ? 0 : "
        !          1714:            fi
        !          1715:            echo "TME_BUS_CYCLE_UNLOCK));"
1.1       root     1716:            echo "    }"
                   1717: 
                   1718:            echo ""
                   1719:            echo "    /* form the physical address for the bus cycle handler: */"
                   1720:            echo "    physical_address = tlb->tme_m68k_tlb_addr_offset + linear_address;"
                   1721:            echo "    shift = tlb->tme_m68k_tlb_addr_shift;"
                   1722:            echo "    if (shift < 0) {"
                   1723:            echo "      physical_address <<= (0 - shift);"
                   1724:            echo "    }"
                   1725:            echo "    else if (shift > 0) {"
                   1726:            echo "      physical_address >>= shift;"
                   1727:            echo "    }"
                   1728:            echo "    cycle.tme_bus_cycle_address = physical_address;"
                   1729: 
                   1730:            echo ""
                   1731:            echo "    /* run the bus cycle: */"
1.1.1.4 ! root     1732:            echo "    tme_m68k_tlb_unbusy(tlb);"
        !          1733:            echo "    tme_m68k_callout_unlock(ic);"
1.1       root     1734:            echo "    err = (*tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycle)"
                   1735:            echo "         (tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycle_private, &cycle);"
1.1.1.4 ! root     1736:            echo "    tme_m68k_callout_relock(ic);"
        !          1737:            echo "    tme_m68k_tlb_busy(tlb);"
1.1       root     1738:            echo ""
1.1.1.4 ! root     1739:            echo "    /* if the TLB entry was invalidated before the ${name}: */"
        !          1740:            echo "    if (err == EBADF"
        !          1741:            echo "        && tme_bus_tlb_is_invalid(&tlb->tme_m68k_tlb_bus_tlb)) {"
        !          1742:            echo "      cycle.tme_bus_cycle_size = 0;"
1.1       root     1743:            echo "    }"
                   1744:            echo ""
1.1.1.3   root     1745:            echo "    /* otherwise, if we didn't get a bus error, but some"
                   1746:            echo "       synchronous event has happened: */"
                   1747:            echo "    else if (err == TME_BUS_CYCLE_SYNCHRONOUS_EVENT) {"
                   1748:            echo ""
                   1749:            echo "      /* after the currently executing instruction finishes, check"
                   1750:            echo "         for external resets, halts, or interrupts: */"
                   1751:            echo "      ic->_tme_m68k_instruction_burst_remaining = 0;"
                   1752:            echo "    }"
                   1753:            echo ""
1.1       root     1754:            echo "    /* otherwise, any other error might be a bus error: */"
                   1755:            echo "    else if (err != TME_OK) {"
                   1756:            echo "      err = tme_bus_tlb_fault(&tlb->tme_m68k_tlb_bus_tlb, &cycle, err);"
                   1757:            echo "      if (err != TME_OK) {"
1.1.1.3   root     1758:            echo "        exception = TME_M68K_EXCEPTION_BERR;"
1.1       root     1759:            echo "        break;"
                   1760:            echo "      }"
                   1761:            echo "    }"
                   1762:            echo ""
                   1763:            echo "    /* update: */"
                   1764:            echo "    linear_address += cycle.tme_bus_cycle_size;"
                   1765:            echo "    transferred += cycle.tme_bus_cycle_size;"
                   1766:            echo "  }"
                   1767:        
                   1768:            echo ""
1.1.1.4 ! root     1769:            echo "  /* NB: there is no need to explicitly unlock"
        !          1770:            echo "     a device.  if a locked bus cycle to a device"
        !          1771:            echo "     faults, the lock must be automatically unlocked: */"
1.1       root     1772: 
                   1773:            echo ""
                   1774:            echo "  /* if we faulted, stash the information the fault stacker"
                   1775:            echo "     will need and start exception processing: */"
                   1776:            echo "  if (exception != TME_M68K_EXCEPTION_NONE) {"
                   1777:            echo -n "    ic->_tme_m68k_group0_flags = flags"
                   1778:            if test $name = read; then
                   1779:                echo -n " | TME_M68K_BUS_CYCLE_READ"
                   1780:            fi
                   1781:            echo ";"
                   1782:            echo "    ic->_tme_m68k_group0_function_code = function_code;"
                   1783:            echo "    ic->_tme_m68k_group0_address = linear_address;"
                   1784:            echo "    ic->_tme_m68k_group0_sequence = ic->_tme_m68k_sequence;"
                   1785:            echo "    ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted_after = transferred;"
                   1786:            echo "    ic->_tme_m68k_group0_buffer_${name}_size = cycle_size;"
                   1787:            if test $name = write; then
                   1788:                echo "#ifdef WORDS_BIGENDIAN"
                   1789:                echo "    memcpy(ic->_tme_m68k_group0_buffer_${name},"
                   1790:                echo "           reg + transferred,"
                   1791:                echo "           ic->_tme_m68k_group0_buffer_${name}_size);"
                   1792:                echo "#else  /* !WORDS_BIGENDIAN */"
                   1793:                echo "      reg_p = (reg + reg_size - 1) - transferred;"
                   1794:                echo "      for (buffer_i = 0;"
                   1795:                echo "           buffer_i < ic->_tme_m68k_group0_buffer_${name}_size;"
                   1796:                echo "           buffer_i++) {"
                   1797:                echo "        ic->_tme_m68k_group0_buffer_${name}[buffer_i] = *(reg_p--);"
                   1798:                echo "      }"
                   1799:                echo "#endif /* !WORDS_BIGENDIAN */"
                   1800:            fi
                   1801:            echo "    if (ic->_tme_m68k_group0_hook != NULL) {"
                   1802:            echo "      (*ic->_tme_m68k_group0_hook)(ic);"
                   1803:            echo "    }"
                   1804:            echo "    ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted = ";
                   1805:            echo "      ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_next;"
1.1.1.4 ! root     1806:            echo "    tme_m68k_tlb_unbusy(tlb);"
1.1       root     1807:            echo "    tme_m68k_exception(ic, exception);"
                   1808:            echo "  }"
                   1809: 
                   1810:            echo ""
                   1811:            echo "  /* otherwise, this transfer has now completed: */"
                   1812:            echo "  TME_M68K_SEQUENCE_TRANSFER_STEP;"
                   1813: 
                   1814:            echo "}"
                   1815:        fi
                   1816:     done
                   1817: 
                   1818: done
                   1819: 
                   1820: # generate the BCD math functions:
                   1821: for name in abcd sbcd nbcd; do
                   1822: 
                   1823:     # if we're making the header, just emit a declaration:
                   1824:     if $header; then
                   1825:        echo "TME_M68K_INSN_DECL(tme_m68k_${name});"
                   1826:        continue
                   1827:     fi
                   1828: 
                   1829:     # emit the function:
                   1830:     echo ""
                   1831:     echo "TME_M68K_INSN(tme_m68k_${name})"
                   1832:     echo "{"
                   1833:     echo "  tme_uint8_t dst, dst_msd, dst_lsd;"
                   1834:     echo "  tme_uint8_t src, src_msd, src_lsd;"
                   1835:     echo "  tme_uint8_t res, res_msd, res_lsd;"
                   1836:     echo "  tme_uint8_t flags;"
                   1837: 
                   1838:     # get the operands:
                   1839:     if test $name != nbcd; then
                   1840:        echo "  int memory;"
                   1841:        echo "  int rx, ry, function_code;"
                   1842:        echo ""
                   1843:        echo "  /* load the operands: */"
                   1844:        echo "  rx = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);"
                   1845:        echo "  ry = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);"
                   1846:        echo "  memory = (TME_M68K_INSN_OPCODE & TME_BIT(3)) != 0;"
                   1847:        echo "  function_code = TME_M68K_FUNCTION_CODE_DATA(ic);"
                   1848:        echo "  if (memory) {"
1.1.1.4 ! root     1849:        echo "    TME_M68K_INSN_CANFAULT;"
1.1       root     1850:        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
1.1.1.4 ! root     1851:        # the stack pointer must always be decremented by a multiple of two.
        !          1852:        # assuming rx < 8, ((rx + 1) >> 3) == 1 iff rx == 7, meaning %a7:
        !          1853:        echo "      ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + rx) -= sizeof(tme_uint8_t) + ((rx + 1) >> 3);"
1.1       root     1854:        echo "      ic->_tme_m68k_ea_function_code = function_code;"
                   1855:        echo "      ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + rx);"
                   1856:        echo "    }"
                   1857:        echo "    tme_m68k_read_memx8(ic);"
                   1858:        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
1.1.1.4 ! root     1859:        # the stack pointer must always be incremented by a multiple of two.
        !          1860:        # assuming rx < 8, ((rx + 1) >> 3) == 1 iff rx == 7, meaning %a7:
        !          1861:        echo "      ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry) -= sizeof(tme_uint8_t) + ((ry + 1) >> 3);"
1.1       root     1862:        echo "      ic->_tme_m68k_ea_function_code = function_code;"
                   1863:        echo "      ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry);"
                   1864:        echo "    }"
                   1865:        echo "    tme_m68k_read_mem8(ic, TME_M68K_IREG_MEMY32);"
                   1866:        echo "    src = ic->tme_m68k_ireg_memx8;"
                   1867:        echo "    dst = ic->tme_m68k_ireg_memy8;"
                   1868:        echo "  }"
                   1869:        echo "  else {"
                   1870:        echo "    src = ic->tme_m68k_ireg_uint8(rx << 2);"
                   1871:        echo "    dst = ic->tme_m68k_ireg_uint8(ry << 2);"
                   1872:        echo "  }"
                   1873:     else
                   1874:        echo ""
                   1875:        echo "  dst = 0x00;"
                   1876:        echo "  src = TME_M68K_INSN_OP1(tme_uint8_t);"
                   1877:     fi
                   1878:     echo "  dst_lsd = TME_FIELD_EXTRACTU(dst, 0, 4);"
                   1879:     echo "  dst_msd = TME_FIELD_EXTRACTU(dst, 4, 4);"
                   1880:     echo "  src_lsd = TME_FIELD_EXTRACTU(src, 0, 4);"
                   1881:     echo "  src_msd = TME_FIELD_EXTRACTU(src, 4, 4);"
                   1882: 
                   1883:     # perform the operation:
                   1884:     echo ""
                   1885:     echo "  /* perform the operation: */"
                   1886:     if test $name = abcd; then op='+' ; opc='-' ; else op='-' ; opc='+' ; fi
                   1887:     echo "  res_lsd = dst_lsd ${op} src_lsd ${op} ((ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X) != 0);"
                   1888:     echo "  res_msd = dst_msd ${op} src_msd;"
                   1889:     echo "  flags = 0;"
                   1890:     echo "  if (res_lsd > 9) {"
                   1891:     echo "    res_lsd ${opc}= 10;"
                   1892:     echo "    res_msd ${op}= 1;"
                   1893:     echo "  }"
                   1894:     echo "  if (res_msd > 9) {"
                   1895:     echo "    res_msd ${opc}= 10;"
                   1896:     echo "    flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;"
                   1897:     echo "  }"
                   1898:     echo "  res = (res_msd << 4) + (res_lsd & 0xf);"
                   1899:     echo "  if (res == 0) flags |= TME_M68K_FLAG_N;"
                   1900:     echo ""
                   1901: 
                   1902:     # store the result
                   1903:     echo "  /* store the result and set the flags: */"
                   1904:     if test $name != nbcd; then
                   1905:        echo "  if (memory) {"
                   1906:        echo "    if (!TME_M68K_SEQUENCE_RESTARTING) {"
                   1907:        echo "      ic->tme_m68k_ireg_memx8 = res;"
                   1908:        echo "      ic->_tme_m68k_ea_function_code = function_code;"
                   1909:        echo "      ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry);"
                   1910:        echo "      ic->tme_m68k_ireg_ccr = flags;"
                   1911:        echo "     }"
                   1912:        echo "     tme_m68k_write_memx8(ic);"
                   1913:        echo "  }"
                   1914:        echo "  else {"
                   1915:        echo "    ic->tme_m68k_ireg_uint8(ry << 2) = res;"
                   1916:        echo "    ic->tme_m68k_ireg_ccr = flags;"
                   1917:        echo "  }"
                   1918:     else
                   1919:        echo "  TME_M68K_INSN_OP1(tme_uint8_t) = res;"
                   1920:        echo "  ic->tme_m68k_ireg_ccr = flags;"
                   1921:     fi
                   1922:     echo ""
                   1923:     echo "  TME_M68K_INSN_OK;"
                   1924:     echo "}"
                   1925: done
                   1926: 
                   1927: # generate the ccr and sr functions:
                   1928: for reg in ccr sr; do
                   1929:     for name in ori andi eori move_to; do
                   1930:        if test $reg = ccr; then size=8 ; else size=16 ; fi
                   1931: 
                   1932:        # if we're making the header, just emit a declaration:
                   1933:        if $header; then
                   1934:            echo "TME_M68K_INSN_DECL(tme_m68k_${name}_${reg});"
                   1935:            continue
                   1936:        fi
                   1937: 
                   1938:        # emit the function:
                   1939:        echo ""
                   1940:        echo "TME_M68K_INSN(tme_m68k_${name}_${reg})"
                   1941:        echo "{"
                   1942:        echo "  tme_uint${size}_t reg;"
                   1943: 
                   1944:        # form the new register value:
                   1945:        src=0
                   1946:        echo -n "  reg = "
                   1947:        case $name in
                   1948:        ori) echo -n "ic->tme_m68k_ireg_${reg} | " ;;
                   1949:        andi) echo -n "ic->tme_m68k_ireg_${reg} & " ;;
                   1950:        eori) echo -n "ic->tme_m68k_ireg_${reg} ^ " ;;
                   1951:        move_to) size=16 ; src=1 ;;
                   1952:        esac
                   1953:        echo "(TME_M68K_INSN_OP${src}(tme_uint${size}_t) & TME_M68K_FLAG_"`echo $reg | tr a-z A-Z`");"
                   1954:        
                   1955:        # sr changes are special:
                   1956:        if test $reg = sr; then
                   1957:            echo "  TME_M68K_INSN_PRIV;"
                   1958:            echo "  TME_M68K_INSN_CHANGE_SR(reg);"
                   1959:        else
                   1960:            echo "  ic->tme_m68k_ireg_${reg} = reg;"
                   1961:        fi
                   1962: 
                   1963:        echo "  TME_M68K_INSN_OK;"
                   1964:        echo "}"
                   1965:     done
                   1966: done
                   1967: 
                   1968: # generate the multiply and divide instructions:
                   1969: 
                   1970: # permute on signed vs. unsigned:
                   1971: for _sign in u s; do
                   1972:     if test $_sign = u; then sign=u; else sign=; fi
                   1973: 
                   1974:     # permute on short vs. long:
                   1975:     for size in s l; do
                   1976:        if test $size = s; then 
                   1977:            _size=
                   1978:            small=16
                   1979:            large=32
                   1980:            reg_size_shift=' << 1'
                   1981:        else
                   1982:            _size=l
                   1983:            small=32
                   1984:            large=64
                   1985:            reg_size_shift=
                   1986:        fi
                   1987: 
                   1988:        # if we're making the header, just emit declarations:
                   1989:        if $header; then
                   1990:            echo "TME_M68K_INSN_DECL(tme_m68k_mul${_sign}${_size});"
                   1991:            echo "TME_M68K_INSN_DECL(tme_m68k_div${_sign}${_size});"
                   1992:            continue
                   1993:        fi
                   1994: 
                   1995:        # emit the multiply function:
                   1996:        echo ""
                   1997:        echo "TME_M68K_INSN(tme_m68k_mul${_sign}${_size})"
                   1998:        echo "{"
                   1999:        if test $large = 64; then
1.1.1.2   root     2000:            echo "#ifndef TME_HAVE_INT${large}_T"
1.1       root     2001:            echo "  abort();"
1.1.1.2   root     2002:            echo "#else /* TME_HAVE_INT${large}_T */"
1.1       root     2003:            echo "  unsigned int flag_v;"
                   2004:            echo "  int ireg_dh;"
                   2005:        fi
                   2006:        echo "  int ireg_dl;"
                   2007:        echo "  tme_${sign}int${large}_t res;"
                   2008:        echo "  tme_uint8_t flags;"
                   2009: 
                   2010:        echo ""
                   2011:        echo "  /* get the register containing the factor: */"
                   2012:        echo -n "  ireg_dl = TME_M68K_IREG_D0 + "
                   2013:        if test $size = s; then
                   2014:            echo "TME_M68K_INSN_OP0(tme_uint32_t);"
                   2015:        else
                   2016:            echo "TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3);"
                   2017:        fi
                   2018: 
                   2019:        echo ""
                   2020:        echo "  /* perform the multiplication: */"
                   2021:        echo "  res = (((tme_${sign}int${large}_t) ic->tme_m68k_ireg_${sign}int${small}(ireg_dl${reg_size_shift}))"
                   2022:        echo "         * TME_M68K_INSN_OP1(tme_${sign}int${small}_t));"
                   2023:        
                   2024:        echo ""
                   2025:        echo "  /* store the result: */"
                   2026:        echo "  ic->tme_m68k_ireg_${sign}int32(ireg_dl) = (tme_${sign}int32_t) res;"
                   2027:        if test $large = 64; then
                   2028:            echo "  flag_v = TME_M68K_FLAG_V;"
                   2029:            echo "  if (TME_M68K_INSN_SPECOP & TME_BIT(10)) {"
                   2030:            echo "    flag_v = 0;"
                   2031:            echo "    ireg_dh = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3);"
                   2032:            echo "    ic->tme_m68k_ireg_${sign}int32(ireg_dh) = (tme_${sign}int32_t) (res >> 32);"
                   2033:            echo "  }"
                   2034:        fi
                   2035:        
                   2036:        echo ""
                   2037:        echo "  /* set the flags: */"
                   2038:        echo "  flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;"
                   2039:        echo "  if (((tme_int${large}_t) res) < 0) flags |= TME_M68K_FLAG_N;"
                   2040:        echo "  if (res == 0) flags |= TME_M68K_FLAG_Z;"
                   2041:        if test $large = 64; then
1.1.1.2   root     2042:            if test $_sign = s; then
                   2043:                echo -n "  if (res > 0x7fffffffL || res < ((0L - 0x7fffffffL) - 1L)"
                   2044:            else
                   2045:                echo -n "  if (res > 0xffffffffUL"
                   2046:            fi
1.1       root     2047:            echo ") flags |= flag_v;"
                   2048:        fi
                   2049:        echo "  ic->tme_m68k_ireg_ccr = flags;"
                   2050: 
                   2051:        echo ""
                   2052:        echo "  TME_M68K_INSN_OK;"
                   2053:        if test $large = 64; then
1.1.1.2   root     2054:            echo "#endif /* TME_HAVE_INT${large}_T */"
1.1       root     2055:        fi
                   2056:        echo "}"
                   2057: 
                   2058:        # emit the divide function:
                   2059:        echo ""
                   2060:        echo "TME_M68K_INSN(tme_m68k_div${_sign}${_size})"
                   2061:        echo "{"
                   2062:        if test $large = 64; then
1.1.1.2   root     2063:            echo "#ifndef TME_HAVE_INT${large}_T"
1.1       root     2064:            echo "  abort();"
1.1.1.2   root     2065:            echo "#else /* TME_HAVE_INT${large}_T */"
1.1       root     2066:            echo "  int ireg_dr;"
                   2067:        fi
                   2068:        echo "  int ireg_dq;"
                   2069:        echo "  tme_${sign}int${large}_t dividend, quotient;"
                   2070:        echo "  tme_${sign}int${small}_t divisor, remainder;"
                   2071:        echo "  tme_uint8_t flags;"
                   2072: 
                   2073:        echo ""
                   2074:        echo "  /* get the register(s): */"
                   2075:        echo -n "  ireg_dq = TME_M68K_IREG_D0 + "
                   2076:        if test $size = s; then
                   2077:            echo "TME_M68K_INSN_OP0(tme_uint32_t);"
                   2078:        else
                   2079:            echo "TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3);"
                   2080:            echo "  ireg_dr = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3);"
                   2081:        fi
                   2082: 
                   2083:        echo ""
                   2084:        echo "  /* form the dividend and the divisor: */"
                   2085:        if test $large = 64; then
                   2086:            echo "  if (TME_M68K_INSN_SPECOP & TME_BIT(10)) {"
                   2087:            echo "    dividend = (tme_${sign}int${large}_t)"
                   2088:            echo "               ((((tme_uint${large}_t) ic->tme_m68k_ireg_uint32(ireg_dr)) << 32)"
                   2089:            echo "                | ic->tme_m68k_ireg_uint32(ireg_dq));"
                   2090:            echo "  }"
                   2091:            echo "  else"
                   2092:            echo -n "  "
                   2093:        fi
                   2094:        echo "  dividend = (tme_${sign}int${large}_t) ic->tme_m68k_ireg_${sign}int32(ireg_dq);"
                   2095:        echo "  divisor = TME_M68K_INSN_OP1(tme_${sign}int${small}_t);"
                   2096:        echo "  if (divisor == 0) {"
1.1.1.3   root     2097:        echo "    ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;"
1.1       root     2098:        echo "    ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;"
1.1.1.3   root     2099:        echo "    TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_DIV0));"
1.1       root     2100:        echo "  }"
                   2101: 
                   2102:        echo ""
                   2103:        echo "  /* do the division: */"
                   2104:        echo "  quotient = dividend / divisor;"
                   2105:        echo "  remainder = dividend % divisor;"
                   2106: 
                   2107:        echo ""
                   2108:        echo "  /* set the flags and return the quotient and remainder: */"
                   2109:        echo "  flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;"
1.1.1.2   root     2110:        echo -n "  if ("
                   2111:        case "${small}${_sign}" in
                   2112:        16s) echo -n "quotient > 0x7fff || quotient < -32768" ;;
                   2113:        16u) echo -n "quotient > 0xffff" ;;
                   2114:        32s) echo -n "quotient > 0x7fffffffL || quotient < ((0L - 0x7fffffffL) - 1L)" ;;
                   2115:        32u) echo -n "quotient > 0xffffffffUL" ;;
                   2116:        esac
1.1       root     2117:        echo ") {"
                   2118:        echo "    flags |= TME_M68K_FLAG_V;"
                   2119:        echo "  }"
                   2120:        echo "  else {"
                   2121:        echo "    if (((tme_int${small}_t) quotient) < 0) flags |= TME_M68K_FLAG_N;"
                   2122:        echo "    if (quotient == 0) flags |= TME_M68K_FLAG_Z;"
                   2123:        echo "    ic->tme_m68k_ireg_${sign}int${small}(ireg_dq${reg_size_shift}) = (tme_${sign}int${small}_t) quotient;"
                   2124:        if test $small = 16; then
                   2125:            echo "    ic->tme_m68k_ireg_${sign}int${small}((ireg_dq${reg_size_shift}) + 1) = remainder;"
                   2126:        else
                   2127:            echo "    if (ireg_dr != ireg_dq) {"
                   2128:            echo "      ic->tme_m68k_ireg_${sign}int${small}(ireg_dr) = remainder;"
                   2129:            echo "    }"
                   2130:        fi
                   2131:        echo "  }"
                   2132:        echo "  ic->tme_m68k_ireg_ccr = flags;"
                   2133: 
                   2134:        echo ""
                   2135:        echo "  TME_M68K_INSN_OK;"
                   2136:        if test $large = 64; then
1.1.1.2   root     2137:            echo "#endif /* TME_HAVE_INT${large}_T */"
1.1       root     2138:        fi
                   2139:        echo "}"
                   2140: 
                   2141:     done
                   2142: done
                   2143: 
                   2144: # done:
                   2145: exit 0

unix.superglobalmegacorp.com

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