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

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

unix.superglobalmegacorp.com

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