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

1.1       root        1: #! /bin/sh
                      2: 
1.1.1.2 ! root        3: # $Id: sparc-insns-auto.sh,v 1.10 2010/06/05 16:13:41 fredette Exp $
1.1       root        4: 
                      5: # ic/sparc/sparc-insns-auto.sh - automatically generates C code 
                      6: # for many SPARC emulation instructions:
                      7: 
                      8: #
                      9: # Copyright (c) 2005 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: sparc-insns-auto.sh,v 1.10 2010/06/05 16:13:41 fredette Exp $");
1.1       root       52: 
                     53: EOF
                     54: if $header; then :; else
                     55:     cat <<EOF
                     56: #include "sparc-impl.h"
1.1.1.2 ! root       57: 
        !            58: /* an all-bits-zero float for use with _tme_sparc*_fpu_mem_fpreg(): */
        !            59: #if TME_FLOAT_FORMAT_NULL != 0
        !            60: #error "TME_FLOAT_FORMAT_NULL changed"
        !            61: #endif
        !            62: static struct tme_float _tme_sparc_float_null;
1.1       root       63: EOF
                     64: fi
                     65: 
                     66: # permute over architecture:
                     67: #
1.1.1.2 ! root       68: for arch in 32 64; do
1.1       root       69: 
                     70:     # the sparc64 support depends on a 64-bit integer type:
                     71:     #
                     72:     if test ${arch} = 64; then
                     73:        echo ""
                     74:        echo "#ifdef TME_HAVE_INT64_T"
                     75:     fi
                     76: 
                     77:     # get the name of the register with the integer condition codes, a
                     78:     # shift value for 32-bit registers, and the architecture version:
                     79:     #
                     80:     if test ${arch} = 32; then 
                     81:        ccr=32_PSR
                     82:        ccr_ireg='tme_sparc32_ireg_psr'
                     83:        reg32_shift=''
                     84:        version=8
                     85:     else
                     86:        ccr=64_CCR
                     87:        ccr_ireg='tme_sparc64_ireg_ccr'
                     88:        reg32_shift=' << 1'
                     89:        version=9
                     90:     fi
                     91: 
                     92:     # fix the architecture version:
                     93:     #
                     94:     if $header; then :; else
                     95:        echo ""
                     96:        echo "#undef TME_SPARC_VERSION"
                     97:        echo "#define TME_SPARC_VERSION(ic) (${version})"
                     98:     fi
                     99: 
                    100:     # the alternate ASI function:
                    101:     #
                    102:     if $header; then :; else
1.1.1.2 ! root      103:        echo ""
1.1       root      104:        echo "static tme_uint32_t"
                    105:        echo "_tme_sparc${arch}_alternate_asi_mask(struct tme_sparc *ic)"
                    106:        echo "{"
                    107:        echo "  unsigned int asi_data;"
1.1.1.2 ! root      108:        echo "  unsigned int asi_mask_flags;"
1.1       root      109:        echo "  tme_uint32_t asi_mask_data;"
                    110:        echo ""
                    111:        echo "  /* get the ASI, assuming that the i bit is zero: */"
                    112:        echo "  asi_data = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, (0xff << 5));"
                    113:        if test ${arch} = 32; then
                    114:            echo ""
                    115:            echo "  /* this is a privileged instruction: */"
                    116:            echo "  TME_SPARC_INSN_PRIV;"
                    117:            echo ""
                    118:            echo "  /* if the i bit is one, this is an illegal instruction: */"
                    119:            echo "  if (__tme_predict_false(TME_SPARC_INSN & TME_BIT(13))) {"
1.1.1.2 ! root      120:            echo "    TME_SPARC_INSN_ILL(ic);"
1.1       root      121:            echo "  }"
                    122:            echo ""
1.1.1.2 ! root      123:            echo "  /* get the flags for this ASI: */"
        !           124:            echo "  asi_mask_flags = ic->tme_sparc_asis[asi_data].tme_sparc_asi_mask_flags;"
        !           125:            echo ""
        !           126:            echo "  /* make the ASI mask: */"
        !           127:            echo "  if (asi_mask_flags & TME_SPARC32_ASI_MASK_FLAG_SPECIAL) {"
        !           128:            echo "    asi_mask_data"
        !           129:            echo "      = TME_SPARC_ASI_MASK_SPECIAL(asi_data, TRUE);"
        !           130:            echo "  }"
        !           131:            echo "  else {"
        !           132:            echo "    asi_mask_data = TME_SPARC32_ASI_MASK(asi_data, asi_data);"
1.1       root      133:            echo "  }"
                    134:        else
                    135:            echo ""
                    136:            echo "  /* if the i bit is one, use the address space in the ASI register: */"
                    137:            echo "  if (TME_SPARC_INSN & TME_BIT(13)) {"
1.1.1.2 ! root      138:            echo "    asi_data = ic->tme_sparc64_ireg_asi;"
1.1       root      139:            echo "  }"
                    140:            echo ""
1.1.1.2 ! root      141:            echo "  /* get the flags for this ASI: */"
        !           142:            echo "  asi_mask_flags = ic->tme_sparc_asis[asi_data].tme_sparc_asi_mask_flags;"
1.1       root      143:            
                    144:            echo ""
1.1.1.2 ! root      145:            echo "  /* if this is a nonprivileged access: */"
1.1       root      146:            echo "  if (!TME_SPARC_PRIV(ic)) {"
                    147:            echo ""
1.1.1.2 ! root      148:            echo "    /* if this is a restricted ASI: */"
        !           149:            echo "    if (__tme_predict_false((asi_data & TME_SPARC64_ASI_FLAG_UNRESTRICTED) == 0)) {"
        !           150:            echo ""
        !           151:            echo "      /* force a slow load or store, which will generate the"
        !           152:            echo "         privileged_action trap: */"
        !           153:            echo "      asi_mask_flags |= TME_SPARC_ASI_MASK_FLAG_UNDEF;"
1.1       root      154:            echo "    }"
1.1.1.2 ! root      155:            echo ""
        !           156:            echo "    /* force a nonprivileged access with the ASI: */"
        !           157:            echo "    asi_mask_flags |= TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER;"
        !           158:            echo "  }"
        !           159:            echo ""
        !           160:            echo "  /* make the ASI mask: */"
        !           161:            echo "  if (asi_mask_flags & TME_SPARC64_ASI_MASK_FLAG_SPECIAL) {"
        !           162:            echo "    asi_mask_data"
        !           163:            echo "      = (asi_mask_flags"
        !           164:            echo "         + TME_SPARC_ASI_MASK_SPECIAL(asi_data,"
        !           165:            echo "                                      ((asi_mask_flags & TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER) == 0)));"
        !           166:            echo "  }"
        !           167:            echo "  else {"
        !           168:            echo "    asi_mask_data = TME_SPARC64_ASI_MASK(asi_data, asi_mask_flags);"
1.1       root      169:            echo "  }"
                    170:        fi
                    171:        echo ""
1.1.1.2 ! root      172:        echo "  /* if this ASI has a special handler: */"
        !           173:        echo "  if (__tme_predict_false(ic->tme_sparc_asis[TME_SPARC_ASI_MASK_WHICH(asi_mask_data)].tme_sparc_asi_handler != 0)) {"
        !           174:        echo ""
        !           175:        echo "    /* force a slow load or store, which will call the special handler: */"
        !           176:        echo "    asi_mask_data |= TME_SPARC_ASI_MASK_FLAG_UNDEF;"
        !           177:        echo "  }"
        !           178:        echo ""
1.1       root      179:        echo "  return (asi_mask_data);"
                    180:        echo "}"
                    181:     fi
                    182: 
1.1.1.2 ! root      183:     # the FPU load and store common function:
        !           184:     #
        !           185:     if $header; then :; else
        !           186:        echo ""
        !           187:        echo "static struct tme_float *"
        !           188:        echo "_tme_sparc${arch}_fpu_mem_fpreg(struct tme_sparc *ic,"
        !           189:        echo "                           tme_uint32_t misaligned,"
        !           190:        echo "                           struct tme_float *float_buffer)"
        !           191:        echo "{"
        !           192:        echo "  unsigned int float_format;"
        !           193:        echo "  unsigned int fpreg_format;"
        !           194:        echo "  tme_uint32_t fp_store;"
        !           195:        echo "  unsigned int fpu_mode;"
        !           196:        echo "  unsigned int fpreg_number;"
        !           197:        echo ""
        !           198:        echo "  /* NB: this checks for various traps by their priority order: */"
        !           199:        echo ""
        !           200:        echo "  TME_SPARC_INSN_FPU_ENABLED;"
        !           201:        echo ""
        !           202:        echo "  /* get the floating-point format: */"
        !           203:        echo "  float_format = float_buffer->tme_float_format;"
        !           204:        echo ""
        !           205:        echo "  /* convert the floating-point format into the ieee754"
        !           206:        echo "     floating-point register file format: */"
        !           207:        echo "#if (TME_FLOAT_FORMAT_NULL | TME_IEEE754_FPREG_FORMAT_NULL) != 0"
        !           208:        echo "#error \"TME_FLOAT_FORMAT_ or TME_IEEE754_FPREG_FORMAT_ values changed\""
        !           209:        echo "#endif"
        !           210:        echo "#if TME_FLOAT_FORMAT_IEEE754_SINGLE < TME_IEEE754_FPREG_FORMAT_SINGLE"
        !           211:        echo "#error \"TME_FLOAT_FORMAT_ or TME_IEEE754_FPREG_FORMAT_ values changed\""
        !           212:        echo "#endif"
        !           213:        echo "#if (TME_FLOAT_FORMAT_IEEE754_SINGLE / TME_IEEE754_FPREG_FORMAT_SINGLE) != (TME_FLOAT_FORMAT_IEEE754_DOUBLE / TME_IEEE754_FPREG_FORMAT_DOUBLE)"
        !           214:        echo "#error \"TME_FLOAT_FORMAT_ or TME_IEEE754_FPREG_FORMAT_ values changed\""
        !           215:        echo "#endif"
        !           216:        echo "  assert (float_format == TME_FLOAT_FORMAT_NULL"
        !           217:        echo "          || float_format == TME_FLOAT_FORMAT_IEEE754_SINGLE"
        !           218:        echo "          || float_format == TME_FLOAT_FORMAT_IEEE754_DOUBLE);"
        !           219:        echo "  fpreg_format = float_format / (TME_FLOAT_FORMAT_IEEE754_SINGLE / TME_IEEE754_FPREG_FORMAT_SINGLE);"
        !           220:        echo ""
        !           221:        echo "  /* if the memory address is misaligned, return the"
        !           222:        echo "     float buffer now.  the eventual load or store will"
        !           223:        echo "     cause the mem_address_not_aligned trap: */"
        !           224:        echo ""
        !           225:        echo "  /* if the memory address is misaligned: */"
        !           226:        echo "#if TME_IEEE754_FPREG_FORMAT_NULL != 0 || TME_IEEE754_FPREG_FORMAT_SINGLE != 1 || TME_IEEE754_FPREG_FORMAT_DOUBLE != 2 || TME_IEEE754_FPREG_FORMAT_QUAD != 4"
        !           227:        echo "#error \"TME_IEEE754_FPREG_FORMAT_ values changed\""
        !           228:        echo "#endif"
        !           229:        echo "  assert (fpreg_format == TME_IEEE754_FPREG_FORMAT_NULL"
        !           230:        echo "          || fpreg_format == TME_IEEE754_FPREG_FORMAT_SINGLE"
        !           231:        echo "          || fpreg_format == TME_IEEE754_FPREG_FORMAT_DOUBLE"
        !           232:        echo "          || fpreg_format == TME_IEEE754_FPREG_FORMAT_QUAD);"
        !           233:        echo "  misaligned &= ((sizeof(tme_uint32_t) * fpreg_format) - 1);"
        !           234:        echo "  if (__tme_predict_false(misaligned)) {"
        !           235:        echo ""
        !           236:        if test ${arch} = 32; then
        !           237:            echo "    return (float_buffer);"
        !           238:        else
        !           239:            echo "    /* if the memory address is not even 32-bit aligned, or"
        !           240:            echo "       if this SPARC doesn't support loads and stores of this"
        !           241:            echo "       size at 32-bit alignment: */"
        !           242:            echo "    if (misaligned != sizeof(tme_uint32_t)"
        !           243:            echo "#if TME_IEEE754_FPREG_FORMAT_SINGLE != 1 || (TME_SPARC_MEMORY_FLAG_HAS_LDDF_STDF_32 * TME_IEEE754_FPREG_FORMAT_DOUBLE) != TME_SPARC_MEMORY_FLAG_HAS_LDQF_STQF_32"
        !           244:            echo "#error \"TME_IEEE754_FPREG_FORMAT_ or TME_SPARC_MEMORY_FLAG_ values changed\""
        !           245:            echo "#endif"
        !           246:            echo "        || (TME_SPARC_MEMORY_FLAGS(ic)"
        !           247:            echo "            & (TME_SPARC_MEMORY_FLAG_HAS_LDDF_STDF_32 * fpreg_format)) == 0) {"
        !           248:            echo ""
        !           249:            echo "      return (float_buffer);"
        !           250:            echo "    }"
        !           251:        fi
        !           252:         echo "  }"
        !           253:        echo ""
        !           254:        echo "  /* see if this is a floating-point load or store: */"
        !           255:        echo "  /* NB: all of the floating-point instructions that use"
        !           256:        echo "     this preamble have bit two of op3 clear for a load,"
        !           257:        echo "     and set for a store: */"
        !           258:        echo "  fp_store = (TME_SPARC_INSN & TME_BIT(19 + 2));"
        !           259:        echo ""
        !           260:        echo "  /* if the FPU isn't in execute mode: */"
        !           261:        echo "  fpu_mode = ic->tme_sparc_fpu_mode;"
        !           262:        echo "  if (__tme_predict_false(fpu_mode != TME_SPARC_FPU_MODE_EXECUTE)) {"
        !           263:        echo ""
        !           264:        echo "    /* if this is a floating-point load, or if this is a"
        !           265:        echo "       floating-point store and a floating-point exception"
        !           266:        echo "       is pending: */"
        !           267:        echo "    if (!fp_store"
        !           268:        echo "        || fpu_mode == TME_SPARC_FPU_MODE_EXCEPTION_PENDING) {"
        !           269:        echo ""
        !           270:        echo "      /* do an FPU exception check: */"
        !           271:        echo "      tme_sparc_fpu_exception_check(ic);"
        !           272:        echo "    }"
        !           273:        echo "  }"
        !           274:        echo ""
        !           275:        echo "  /* if this is not a load or store of a floating-point register: */"
        !           276:        echo "  if (fpreg_format == TME_IEEE754_FPREG_FORMAT_NULL) {"
        !           277:        echo "    return (float_buffer);"
        !           278:        echo "  }"
        !           279:        echo ""
        !           280:        echo "  /* decode rd: */"
        !           281:        echo "  fpreg_number"
        !           282:        echo "    = tme_sparc_fpu_fpreg_decode(ic,"
        !           283:        echo "                                 TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN,"
        !           284:        echo "                                                         TME_SPARC_FORMAT3_MASK_RD),"
        !           285:        echo "                                 fpreg_format);"
        !           286:        echo ""
        !           287:        echo "  /* make sure this floating-point register has the right precision: */"
        !           288:        echo "  tme_sparc_fpu_fpreg_format(ic, fpreg_number, fpreg_format | TME_IEEE754_FPREG_FORMAT_BUILTIN);"
        !           289:        echo ""
        !           290:        echo "  /* if this is a floating-point load: */"
        !           291:        echo "  if (!fp_store) {"
        !           292:        echo ""
        !           293:        echo "    /* mark rd as dirty: */"
        !           294:        echo "    TME_SPARC_FPU_DIRTY(ic, fpreg_number);"
        !           295:        echo "  }"
        !           296:        echo ""
        !           297:        echo "  /* return the floating-point register: */"
        !           298:        echo "  return (&ic->tme_sparc_fpu_fpregs[fpreg_number]);"
        !           299:        echo "}"
        !           300:        echo "#define _tme_sparc${arch}_fpu_mem(ic) \\"
        !           301:        echo "  do { _tme_sparc${arch}_fpu_mem_fpreg(ic, 0, &_tme_sparc_float_null); } while (/* CONSTCOND */ 0)"
        !           302:     fi
        !           303: 
1.1       root      304:     # permute over instruction:
                    305:     #
1.1.1.2 ! root      306:     case ${arch} in
        !           307:     32) insns_arch= ;;
        !           308:     64) insns_arch="ldx stx ldqf stqf ldxa stxa ldfa lddfa stfa stdfa ldqfa stqfa casa casxa mulx sdivx udivx" ;;
        !           309:     esac
1.1       root      310:     for insn in \
                    311:        add \
                    312:        addcc \
                    313:        sub \
                    314:        subcc \
                    315:        or \
                    316:        orcc \
                    317:        orn \
                    318:        orncc \
                    319:        and \
                    320:        andcc \
                    321:        andn \
                    322:        andncc \
                    323:        xor \
                    324:        xorcc \
                    325:        xnor \
                    326:        xnorcc \
                    327:        addx \
                    328:        addxcc \
                    329:        subx \
                    330:        subxcc \
                    331:        taddcc taddcctv \
                    332:        tsubcc tsubcctv \
                    333:        umul umulcc smul smulcc \
                    334:        udiv udivcc sdiv sdivcc \
                    335:        sll \
                    336:        srl \
                    337:        sra \
                    338:        ldb stb \
                    339:        ldh sth \
                    340:        ld st \
                    341:        ldd std \
                    342:        ldstub ldstuba swap swapa \
                    343:        ldba stba \
                    344:        ldha stha \
                    345:        lda sta \
                    346:        ldda stda \
                    347:        jmpl \
                    348:        ldf lddf ldfsr \
                    349:        stf stdf stfsr \
1.1.1.2 ! root      350:        fpop1 fpop2 \
1.1       root      351:        mulscc \
1.1.1.2 ! root      352:        ${insns_arch} \
1.1       root      353:        ; do
                    354: 
                    355:        # if we're making the header, just emit declarations:
                    356:        #
                    357:        if $header; then
                    358:            echo "TME_SPARC_FORMAT3_DECL(tme_sparc${arch}_${insn}, tme_uint${arch}_t);"
                    359:            continue
                    360:        fi
                    361: 
                    362:        # an ALU instruction:
                    363:        #
                    364:        case ${insn} in
                    365:        add | sub | or | orn | and | andn | xor | xnor | \
                    366:        addx | subx | umul | smul | udiv | sdiv)
                    367:            cc=false
                    368:            ;;
                    369:        addcc | subcc | orcc | orncc | andcc | andncc | xorcc | xnorcc | \
                    370:        addxcc | subxcc | umulcc | smulcc | udivcc | sdivcc | \
                    371:        taddcc | tsubcc | taddcctv | tsubcctv | \
                    372:        mulscc)
                    373:            cc=true
                    374:            ;;
                    375:        *)
                    376:            cc=
                    377:            ;;
                    378:        esac
                    379:        if test "x${cc}" != x; then
                    380: 
                    381:            # characterize each function:
                    382:            #
                    383:            sign=u ; size_src=${arch} ; size_dst=${arch} ; arith=logical ; with_c= ; tagged=
                    384:            case "${insn}" in
                    385:            add  | addcc)   op='src1 + src2' ; arith=add ;;
                    386:            sub  | subcc)   op='src1 - src2' ; arith=sub ;;
                    387:            or   | orcc)    op='src1 | src2' ;;
                    388:            orn  | orncc)   op='src1 | ~src2' ;;
                    389:            and  | andcc)   op='src1 & src2' ;;
                    390:            andn | andncc)  op='src1 & ~src2' ;;
                    391:            xor  | xorcc)   op='src1 ^ src2' ;;
                    392:            xnor | xnorcc)  op='src1 ^ ~src2' ;;
                    393:            addx | addxcc)  op='src1 + src2' ; arith=add ; with_c=+ ;;
                    394:            subx | subxcc)  op='src1 - src2' ; arith=sub ; with_c=- ;;
                    395:            taddcc)         op='src1 + src2' ; arith=add ; tagged=x ;;
                    396:            taddcctv)       op='src1 + src2' ; arith=add ; tagged=tv ;;
                    397:            tsubcc)         op='src1 - src2' ; arith=sub ; tagged=x ;;
                    398:            tsubcctv)       op='src1 - src2' ; arith=sub ; tagged=tv ;;
                    399:            umul | umulcc)  arith=mul ; size_src=32 ;;
                    400:            smul | smulcc)  arith=mul ; size_src=32 ; sign= ;;
                    401:            udiv | udivcc)  arith=udiv ; size_src=32 ; size_dst=32 ;;
1.1.1.2 ! root      402:            sdiv | sdivcc)  arith=sdiv ; size_src=32 ; sign= ;;
1.1       root      403:            mulscc)         arith=add ; size_src=32 ; size_dst=32 ;;
                    404:            *) echo "$0 internal error: unknown ALU function ${insn}" 1>&2 ; exit 1 ;;
                    405:            esac
                    406: 
                    407:            # open the function:
                    408:            #
                    409:            echo ""
                    410:            echo "/* this does a sparc${arch} \"${insn} SRC1, SRC2, DST\": */"
                    411:            echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
                    412:            echo "{"
                    413: 
                    414:            # declare our locals:
                    415:            #
                    416:            echo "  tme_${sign}int${size_src}_t src1;"
                    417:            echo "  tme_${sign}int${size_src}_t src2;"
                    418:            echo "  tme_${sign}int${size_dst}_t dst;"
                    419:            case "${insn}" in
                    420:            umul* | smul* | udiv* | sdiv*)
                    421:                echo "  tme_${sign}int64_t val64;"
                    422:                ;;
                    423:            mulscc)
                    424:                echo "  tme_uint32_t y;"
                    425:                ;;
                    426:            esac
                    427:            if ${cc}; then
                    428:                echo "  tme_uint32_t cc;"
                    429:            fi
1.1.1.2 ! root      430:            cc_plus=
1.1       root      431: 
                    432:            echo ""
                    433:            echo "  /* get the operands: */"
                    434:            echo "  src1 = (tme_${sign}int${arch}_t) TME_SPARC_FORMAT3_RS1;"
                    435:            echo "  src2 = (tme_${sign}int${arch}_t) TME_SPARC_FORMAT3_RS2;"
                    436: 
                    437:            echo ""
                    438:            echo "  /* perform the operation: */"
                    439:            case "${insn}" in
                    440:            umul | umulcc | smul | smulcc)
                    441:                echo "  val64 = (((tme_${sign}int64_t) src1) * src2);"
                    442:                echo "  ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_Y${reg32_shift}) = (((tme_uint64_t) val64) >> 32);"
                    443:                echo "  dst = ((tme_${sign}int64_t) val64);"
                    444:                ;;
                    445:            udiv | udivcc | sdiv | sdivcc)
1.1.1.2 ! root      446:                echo "  val64 = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_Y${reg32_shift});"
        !           447:                echo "  val64 = (val64 << 32) + (tme_uint32_t) src1;"
        !           448:                echo "  if (__tme_predict_false(src2 == 0)) {"
        !           449:                echo "    tme_sparc${arch}_trap(ic, TME_SPARC${arch}_TRAP_division_by_zero);"
        !           450:                echo "  }"
1.1       root      451:                echo "  val64 /= src2;"
1.1.1.2 ! root      452:                echo "  dst = (tme_${sign}int32_t) val64;"
        !           453:                echo ""
        !           454:                echo "  /* if the division overflowed: */"
        !           455:                echo "  if (dst != val64) {"
        !           456:                echo ""
        !           457:                echo "    /* return the largest appropriate value: */"
        !           458:                if test "x${sign}" = xu; then
        !           459:                    echo "    dst = 0xffffffff;"
        !           460:                else
        !           461:                    echo "    dst = (tme_int32_t) ((val64 < 0) + (tme_uint32_t) 0x7fffffff);"
        !           462:                fi
        !           463:                if ${cc}; then
        !           464:                    echo ""
        !           465:                    echo "    /* set V: */"
        !           466:                    echo "    cc = TME_SPARC${ccr}_ICC_V;"
        !           467:                fi
        !           468:                echo "  }"
        !           469:                if ${cc}; then
        !           470:                    echo ""
        !           471:                    echo "  /* otherwise, the division didn't overflow: */"
        !           472:                    echo "  else {"
        !           473:                    echo ""
        !           474:                    echo "    /* clear V: */"
        !           475:                    echo "    cc = !TME_SPARC${ccr}_ICC_V;"
        !           476:                    echo "  }"
        !           477:                    cc_plus='+'
        !           478:                fi
1.1       root      479:                ;;
                    480:            mulscc)
                    481:                echo ""
                    482:                echo "  /* \"(1) The multiplier is established as r[rs2] if the i field is zero, or "
                    483:                echo "     sign_ext(simm13) if the i field is one.\""
                    484:                echo ""
                    485:                echo "     \"(3) If the least significant bit of the Y register = 1, the shifted"
                    486:                echo "     value from step (2) is added to the multiplier. If the LSB of the"
                    487:                echo "     Y register = 0, then 0 is added to the shifted value from step (2).\" */"
                    488:                echo "  y = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_Y${reg32_shift});"
                    489:                echo "  if ((y & 1) == 0) {"
                    490:                echo "    src2 = 0;"
                    491:                echo "  }"
                    492:                echo ""
                    493:                echo "  /* \"(6) The Y register is shifted right by one bit, with the LSB of the"
                    494:                echo "     unshifted r[rs1] replacing the MSB of Y.\" */"
                    495:                echo "  y >>= 1;"
                    496:                echo "  if (src1 & 1) {"
                    497:                echo "    y += 0x80000000;"
                    498:                echo "  }"
                    499:                echo "  ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_Y${reg32_shift}) = y;"
                    500:                echo ""
                    501:                echo "  /* \"(2) A 32-bit value is computed by shifting r[rs1] right by one"
                    502:                echo "     bit with (N xor V) from the PSR replacing the high-order bit."
                    503:                echo "     (This is the proper sign for the previous partial product.)\" */"
                    504:                echo "  src1 >>= 1;"
                    505:                echo "  if (((ic->${ccr_ireg} ^ (ic->${ccr_ireg} * (TME_SPARC${ccr}_ICC_N / TME_SPARC${ccr}_ICC_V))) & TME_SPARC${ccr}_ICC_N) != 0) {"
                    506:                echo "    src1 += 0x80000000;"
                    507:                echo "  }"
                    508:                echo ""
                    509:                echo "  /* \"(4) The sum from step (3) is written into r[rd].\" */"
                    510:                echo "  dst = src1 + src2;"
                    511:                echo ""
                    512:                echo "  /* \"(5) The integer condition codes, icc, are updated according to the"
                    513:                echo "     addition performed in step (3).\" */"
                    514:                ;;
                    515:            *)
                    516:                echo "  dst = ${op};"
                    517:                if test "x${with_c}" != x; then
                    518:                    echo "  dst ${with_c}= ((ic->${ccr_ireg} & TME_SPARC${ccr}_ICC_C) != 0);"
                    519:                fi
                    520:            esac
                    521: 
                    522:            # unless this is a tagged-and-trap-on-overflow operation:
                    523:            #
                    524:            if test "x${tagged}" != xtv; then
                    525:                echo ""
                    526:                echo "  /* store the destination: */"
                    527:                echo "  TME_SPARC_FORMAT3_RD = (tme_${sign}int${arch}_t) dst;"
                    528:            fi
                    529: 
                    530:            # if this instruction modifies the condition codes:
                    531:            #
                    532:            if ${cc}; then
                    533: 
                    534:                # set the 32-bit, and possibly the 64-bit, condition codes:
                    535:                #
                    536:                arch_cc=16
                    537:                while test `expr ${arch_cc} \< ${arch}` = 1; do
                    538:                    arch_cc=`expr ${arch_cc} \* 2`
                    539: 
                    540:                    case ${arch_cc} in
                    541:                    32) xcc=ICC ;;
                    542:                    64) xcc=XCC ;;
                    543:                    esac
                    544: 
1.1.1.2 ! root      545:                    echo ""
        !           546:                    echo "  /* set Z if the destination is zero: */"
        !           547:                    echo "  cc ${cc_plus}= ((((tme_int${arch_cc}_t) dst) == 0) * TME_SPARC${ccr}_${xcc}_Z);"
        !           548:                    cc_plus='+'
        !           549: 
        !           550:                    if test `expr ${arch_cc} \<= ${size_dst}` = 1; then
1.1       root      551:                        echo ""
                    552:                        echo "  /* set N if the destination is negative: */"
                    553:                        echo "  cc += ((((tme_int${arch_cc}_t) dst) < 0) * TME_SPARC${ccr}_${xcc}_N);"
                    554:                    fi
                    555: 
                    556:                    case $arith in
                    557:                    add)
                    558:                        ones="(((tme_${sign}int${arch_cc}_t) 0) - 1)"
                    559: 
                    560:                        echo ""
                    561:                        echo "  /* if the operands are the same sign, and the destination has"
                    562:                        echo "     a different sign, set V: */"
                    563:                        echo "  cc += ((((tme_int${arch_cc}_t) ((src2 ^ dst) & (src1 ^ (src2 ^ ${ones})))) < 0) * TME_SPARC${ccr}_${xcc}_V);"
                    564: 
                    565:                        echo ""
                    566:                        echo "  /* if src1 and src2 both have the high bit set, or if dst does"
                    567:                        echo "     not have the high bit set and either src1 or src2 does, set C: */"
                    568:                        echo "  cc += (((tme_int${arch_cc}_t) (((tme_uint${arch_cc}_t) (src1 & src2)) | ((((tme_uint${arch_cc}_t) dst) ^ ${ones}) & ((tme_uint${arch_cc}_t) (src1 | src2))))) < 0) * TME_SPARC${ccr}_${xcc}_C;"
                    569:                        ;;
                    570:                    sub) 
                    571: 
                    572:                        echo ""
                    573:                        echo "  /* if the operands are different signs, and the destination has"
                    574:                        echo "     a different sign from the first operand, set V: */"
                    575:                        echo "  cc += ((((tme_int${arch_cc}_t) ((src1 ^ src2) & (src1 ^ dst))) < 0) * TME_SPARC${ccr}_${xcc}_V);"
                    576: 
                    577:                        echo ""
                    578:                        echo "  /* if src2 is greater than src1, set C: */"
                    579:                        echo -n "  cc += ((((tme_uint${arch_cc}_t) src2) > ((tme_uint${arch_cc}_t) src1))"
                    580:                        if test "x${with_c}" != x; then
                    581:                            echo -n " || (((tme_uint${arch_cc}_t) src2) == ((tme_uint${arch_cc}_t) src1) && (ic->${ccr_ireg} & TME_SPARC${ccr}_ICC_C))"
                    582:                        fi
                    583:                        echo ") * TME_SPARC${ccr}_${xcc}_C;"
                    584:                        ;;
                    585:                    logical | mul)
                    586:                        ;;
1.1.1.2 ! root      587:                    udiv | sdiv)
        !           588:                        # the udivcc and sdivcc V are handled in the operation code
1.1       root      589:                        ;;
                    590:                    *) echo "$0 internal error: unknown arithmetic type ${arith}" 1>&2 ; exit 1 ;;
                    591:                    esac
                    592:                done
                    593:                
                    594:                # if this is a tagged operation:
                    595:                #
                    596:                if test "x${tagged}" != x; then
                    597: 
                    598:                    echo ""
                    599:                    echo "  /* set V if bits zero or one of src1 or src2 are set: */"
                    600:                    echo "  cc |= ((((src1 | src2) & 3) != 0) * TME_SPARC${ccr}_ICC_V);"
                    601: 
                    602:                    # if this is a tagged-and-trap-on-overflow operation:
                    603:                    #
                    604:                    if test "x${tagged}" = xtv; then
                    605: 
                    606:                        echo ""
                    607:                        echo "  /* trap on a tagged overflow: */"
                    608:                        echo "  if (cc & TME_SPARC${ccr}_ICC_V) {"
1.1.1.2 ! root      609:                        echo "    tme_sparc${arch}_trap(ic, TME_SPARC${arch}_TRAP_tag_overflow);"
1.1       root      610:                        echo "  }"
                    611: 
                    612:                        echo "  /* store the destination: */"
                    613:                        echo "  TME_SPARC_FORMAT3_RD = (tme_${sign}int${arch}_t) dst;"
                    614:                    fi
                    615:                fi
                    616: 
                    617:                echo ""
                    618:                echo "  /* set the condition codes: */"
                    619:                echo -n "  ic->${ccr_ireg} = "
                    620:                if test ${arch} = 32; then
                    621:                    echo -n "(ic->${ccr_ireg} & ~TME_SPARC32_PSR_ICC) | "
                    622:                fi
                    623:                echo "cc;"
                    624:            fi
                    625: 
                    626:            echo ""
                    627:            echo "  TME_SPARC_INSN_OK;"
                    628:            echo "}"
                    629:        fi
                    630: 
                    631:        # a shift instruction:
                    632:        #
                    633:        case ${insn} in
                    634:        sll | srl | sra)
                    635: 
                    636:            # get the sign of this shift:
                    637:            #
                    638:            if test ${insn} = sra; then sign= ; else sign=u; fi
                    639: 
                    640:            echo ""
                    641:            echo "/* the sparc${arch} ${insn} function: */"
                    642:            echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
                    643:            echo "{"
                    644:            echo "  tme_${sign}int${arch}_t dst;"
                    645:            echo "  unsigned int count;"
                    646:            echo ""
                    647:            echo "  /* get the value and the shift count: */"
                    648:            echo "  dst = TME_SPARC_FORMAT3_RS1;"
                    649:            echo "  count = TME_SPARC_FORMAT3_RS2;"
                    650: 
                    651:            # if we're on sparc64:
                    652:            #
                    653:            if test ${arch} = 64; then
                    654: 
                    655:                echo ""
                    656:                echo "  /* if the X bit is clear: */"
                    657:                echo "  if ((TME_SPARC_INSN & TME_BIT(12)) == 0) {"
                    658:                echo ""
                    659:                echo "    /* limit the count: */"
                    660:                echo "    count %= 32;"
                    661:                if test ${insn} != sll; then
                    662:                    echo ""
1.1.1.2 ! root      663:                    echo "    /* clip the value to 32 bits: */"
        !           664:                    echo "    dst = (tme_${sign}int32_t) dst;"
1.1       root      665:                fi
                    666:                echo "  }"
                    667:            fi
                    668: 
                    669:            echo ""
                    670:            echo "  /* limit the count: */"
                    671:            echo "  count %= ${arch};"
                    672:            echo ""
                    673:            echo "  /* do the shift: */"
                    674:            if test "${insn}" = sra; then
                    675:                echo "#ifdef SHIFTSIGNED_INT${arch}_T"
                    676:            fi
1.1.1.2 ! root      677:            echo "#if defined(SHIFTMAX_INT${arch}_T) && (SHIFTMAX_INT${arch}_T < (${arch} - 1))"
1.1       root      678:            echo "#error \"cannot do full shifts of a tme_int${arch}_t\""
                    679:            echo "#endif /* (SHIFTMAX_INT${arch}_T < (${arch} - 1)) */"
                    680:            if test ${insn} = sll; then
                    681:                echo "  dst <<= count;"
                    682:            else
                    683:                echo "  dst >>= count;"
                    684:            fi
                    685:            if test "${insn}" = sra; then
                    686:                echo "#else  /* !SHIFTSIGNED_INT${arch}_T */"
                    687:                echo "  for (; count-- > 0; ) {"
                    688:                echo "    dst = (dst & ~((tme_${sign}int${arch}_t) 1)) / 2;"
                    689:                echo "  }"
                    690:                echo "#endif /* !SHIFTSIGNED_INT${arch}_T */"
                    691:            fi
                    692:            
                    693:            echo ""
                    694:            echo "  /* store the destination: */"
                    695:            echo "  TME_SPARC_FORMAT3_RD = dst;"
                    696:            echo ""
                    697:            echo "  TME_SPARC_INSN_OK;"
                    698:            echo "}"
                    699:            ;;
                    700:        esac
                    701: 
1.1.1.2 ! root      702:        # the sdivx, udivx, and mulx instructions:
        !           703:        #
        !           704:        case ${insn} in
        !           705:        sdivx) sign= ;;
        !           706:        udivx | mulx) sign=u ;;
        !           707:        *) sign=x ;;
        !           708:        esac
        !           709:        if test "x${sign}" != xx; then
        !           710:            echo ""
        !           711:            echo "/* the sparc${arch} ${insn} function: */"
        !           712:            echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
        !           713:            echo "{"
        !           714:            echo "  tme_${sign}int64_t src1;"
        !           715:            echo "  tme_${sign}int64_t src2;"
        !           716:            echo "  tme_${sign}int64_t dst;"
        !           717:            echo ""
        !           718:            echo "  /* get the operands: */"
        !           719:            echo "  src1 = TME_SPARC_FORMAT3_RS1;"
        !           720:            echo "  src2 = TME_SPARC_FORMAT3_RS2;"
        !           721:            echo ""
        !           722:            echo "  /* do the ${insn}: */"
        !           723:            if test ${insn} = mulx; then
        !           724:                echo "  dst = src1 * src2;"
        !           725:            else
        !           726:                echo "  if (__tme_predict_false(src2 == 0)) {"
        !           727:                echo "    tme_sparc${arch}_trap(ic, TME_SPARC${arch}_TRAP_division_by_zero);"
        !           728:                echo "  }"
        !           729:                if test ${insn} = sdivx; then
        !           730:                    echo "  dst = (src2 == -1 && src1 == (((tme_int64_t) 1) << 63) ? src1 : src1 / src2);"
        !           731:                else
        !           732:                    echo "  dst = src1 / src2;"
        !           733:                fi
        !           734:            fi
        !           735:            echo ""
        !           736:            echo "  TME_SPARC_FORMAT3_RD = dst;"
        !           737:            echo "  TME_SPARC_INSN_OK;"
        !           738:            echo "}"
        !           739:        fi
        !           740: 
1.1       root      741:        # a load or store instruction:
                    742:        #
                    743:        size=
                    744:        case "${insn}" in
                    745:        ldb | stb | ldstub | ldba | stba | ldstuba) size=8 ;;
                    746:        ldh | sth | ldha | stha) size=16 ;;
                    747:        ld | st | swap | lda | sta | swapa) size=32 ;;
                    748:        ldd | std | ldda | stda) size=32 ;;
1.1.1.2 ! root      749:        ldx | stx | ldxa | stxa | casxa) size=64 ;;
        !           750:        casa) size=32 ;;
1.1       root      751:        esac
                    752:        if test "x${size}" != x; then
                    753: 
                    754:            # set the alternate space indication:
                    755:            #
                    756:            case "${insn}" in
                    757:            *a) alternate=true ;;
                    758:            *) alternate=false ;;
                    759:            esac
                    760: 
                    761:            # set the atomic and double indications:
                    762:            #
                    763:            atomic=false
                    764:            double=false
                    765:            case "${insn}" in
1.1.1.2 ! root      766:            ldstub | ldstuba | swap | swapa | casa | casxa) atomic=true ;;
1.1       root      767:            ldd* | std*) double=true ; size=64 ;;
                    768:            esac
                    769: 
                    770:            # if this is only a load, we are reading, otherwise we are writing:
                    771:            #
                    772:            cycle=write
                    773:            capcycle=WRITE
                    774:            slow=store
                    775:            case "${insn}" in
                    776:            ldstub*) ;;
                    777:            ld*) 
                    778:                cycle=read
                    779:                capcycle=READ
                    780:                slow=load
                    781:                ;;
                    782:            esac
                    783: 
                    784:            # start the instruction:
                    785:            #
                    786:            echo ""
                    787:            echo "/* this does a sparc${arch} ${insn}: */"
                    788:            echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
                    789:            echo "{"
                    790: 
                    791:            # our locals:
                    792:            #
                    793:            if ${alternate}; then
                    794:                echo "  tme_uint32_t asi_mask_data;"
                    795:                asi_mask_data=asi_mask_data
                    796:            else
                    797:                asi_mask_data="ic->tme_sparc_asi_mask_data"
                    798:            fi
                    799:            echo "  tme_uint${arch}_t address;"
1.1.1.2 ! root      800:            if test ${arch} = 64 && ${alternate}; then
        !           801:                echo "  tme_bus_context_t context;"
        !           802:                context=context
        !           803:            else
        !           804:                context="ic->tme_sparc_memory_context_default"
        !           805:            fi
        !           806:            echo "  tme_uint32_t asi_mask_flags_slow;"
1.1       root      807:            echo "  struct tme_sparc_tlb *dtlb;"
                    808:            echo -n "  "
                    809:            if test ${slow} = load; then echo -n "const "; fi
                    810:            echo "tme_shared tme_uint8_t *memory;"
1.1.1.2 ! root      811:            echo "  tme_bus_context_t dtlb_context;"
        !           812:            echo "  tme_uint32_t endian_little;"
        !           813:            case "${insn}" in
        !           814:            ldd* | std* | swap*) echo "  tme_uint32_t value32;" ;;
        !           815:            ldstub*) ;;
        !           816:            cas*a)
        !           817:                echo "  unsigned int reg_rs2;"
        !           818:                echo "  tme_uint${size}_t value_compare${size};"
        !           819:                echo "  tme_uint${size}_t value_swap${size};"
        !           820:                echo "  tme_uint${size}_t value_read${size};"
        !           821:                ;;
        !           822:            ld*)
        !           823:                echo "  tme_uint${size}_t value${size};"
        !           824:                size_extend=${arch}
        !           825:                if test `expr ${size} \< ${arch}` = 1; then
        !           826:                    if test `expr ${size} \< 32` = 1; then size_extend=32; fi
        !           827:                    echo "  tme_uint${size_extend}_t value${size_extend};"
        !           828:                fi
        !           829:                ;;
        !           830:            st*) echo "  tme_uint${size}_t value${size};" ;;
        !           831:            esac
1.1       root      832: 
                    833:            if ${alternate}; then
                    834:                echo ""
                    835:                echo "  /* get the alternate ASI mask: */"
                    836:                echo "  asi_mask_data = _tme_sparc${arch}_alternate_asi_mask(ic);"
                    837:            fi
                    838: 
                    839:            echo ""
                    840:            echo "  /* get the address: */"
1.1.1.2 ! root      841:            case "${insn}" in
        !           842:            cas*a) echo "  address = TME_SPARC_FORMAT3_RS1;" ;;
        !           843:            *) echo "  address = TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2;" ;;
        !           844:            esac
        !           845:            if test ${arch} = 64; then
        !           846:                echo "  address &= ic->tme_sparc_address_mask;"
        !           847:            fi
1.1       root      848:                
                    849:            echo ""
                    850:            echo "#ifdef _TME_SPARC_STATS"
                    851:            echo "  /* track statistics: */"
                    852:            echo "  ic->tme_sparc_stats.tme_sparc_stats_memory_total++;"
                    853:            echo "#endif /* _TME_SPARC_STATS */"
                    854: 
1.1.1.2 ! root      855:            echo ""
        !           856:            echo "  /* verify and maybe replay this transfer: */"
        !           857:            if ${double}; then verify_size=32; else verify_size=${size}; fi
        !           858:            case "${insn}" in
        !           859:            ld*) verify_flags=TME_SPARC_RECODE_VERIFY_MEM_LOAD ;;
        !           860:            swap* | cas*a) verify_flags="TME_SPARC_RECODE_VERIFY_MEM_LOAD | TME_SPARC_RECODE_VERIFY_MEM_STORE" ;;
        !           861:            st*) verify_flags=TME_SPARC_RECODE_VERIFY_MEM_STORE ;;
        !           862:            *) verify_flags= ;;
        !           863:            esac
        !           864:            echo "  tme_sparc_recode_verify_mem(ic, &TME_SPARC_FORMAT3_RD,"
        !           865:            echo "                              ${asi_mask_data}, address,"
        !           866:            echo "                              (TME_RECODE_SIZE_${verify_size}"
        !           867:            echo "                               | ${verify_flags}));"
        !           868:            if ${double}; then
        !           869:                echo "  tme_sparc_recode_verify_mem(ic, &TME_SPARC_FORMAT3_RD_ODD(tme_ic_ireg_uint${arch}),"
        !           870:                echo "                              ${asi_mask_data}, address + sizeof(tme_uint32_t),"
        !           871:                echo "                              (TME_RECODE_SIZE_${verify_size}"
        !           872:                echo "                               | ${verify_flags}));"
        !           873:            fi
        !           874:            echo "  if (tme_sparc_recode_verify_replay_last_pc(ic) != 0) {"
        !           875:            echo "    TME_SPARC_INSN_OK;"
        !           876:            echo "  }"
        !           877: 
1.1       root      878:            # if this is some kind of a store, except for an ldstub:
                    879:            #
                    880:            case "${insn}" in
                    881:            std*)
                    882:                echo ""
                    883:                echo "  /* log the values stored: */"
                    884:                echo "  tme_sparc_log(ic, 1000, TME_OK, "
                    885:                echo "               (TME_SPARC_LOG_HANDLE(ic),"
1.1.1.2 ! root      886:                echo "                _(\"${insn}\t0x%02x:0x%0"`expr ${arch} / 4`"\" TME_PRIx${arch} \":\t0x%08\" TME_PRIx32 \" 0x%08\" TME_PRIx32),"
        !           887:                echo "                TME_SPARC_ASI_MASK_WHICH(${asi_mask_data} & ~TME_SPARC_ASI_MASK_FLAG_UNDEF),"
1.1       root      888:                echo "                address,"
                    889:                echo "                (tme_uint32_t) TME_SPARC_FORMAT3_RD,"
1.1.1.2 ! root      890:                echo "                (tme_uint32_t) TME_SPARC_FORMAT3_RD_ODD(tme_ic_ireg_uint${arch})));"
1.1       root      891:                ;;
1.1.1.2 ! root      892:            st* | swap* | cas*a)
1.1       root      893:                echo ""
                    894:                echo "  /* log the value stored: */"
                    895:                echo "  tme_sparc_log(ic, 1000, TME_OK, "
                    896:                echo "               (TME_SPARC_LOG_HANDLE(ic),"
1.1.1.2 ! root      897:                echo "                _(\"${insn}\t0x%02x:0x%0"`expr ${arch} / 4`"\" TME_PRIx${arch} \":\t0x%0"`expr ${size} / 4`"\" TME_PRIx${size}),"
        !           898:                echo "                TME_SPARC_ASI_MASK_WHICH(${asi_mask_data} & ~TME_SPARC_ASI_MASK_FLAG_UNDEF),"
1.1       root      899:                echo "                address,"
                    900:                echo "                (tme_uint${size}_t) TME_SPARC_FORMAT3_RD));"
                    901:                ;;
                    902:            esac
                    903: 
1.1.1.2 ! root      904:            if test "${context}" = context; then
        !           905:                echo ""
        !           906:                echo "  /* get the context: */"
        !           907:                if test ${arch} = 64; then
        !           908:                    echo "  context = ic->tme_sparc_memory_context_primary;"
        !           909:                    echo "  if (__tme_predict_false(${asi_mask_data}"
        !           910:                    echo "                          & (TME_SPARC64_ASI_FLAG_SECONDARY"
        !           911:                    echo "                             + TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS))) {"
        !           912:                    echo "    if (${asi_mask_data} & TME_SPARC64_ASI_FLAG_SECONDARY) {"
        !           913:                    echo "      context = ic->tme_sparc_memory_context_secondary;"
        !           914:                    echo "    }"
        !           915:                    echo "    else if (TME_SPARC_MEMORY_FLAGS(ic) & TME_SPARC_MEMORY_FLAG_HAS_NUCLEUS) {"
        !           916:                    echo "      context = 0;"
        !           917:                    echo "    }"
        !           918:                    echo "  }"
        !           919:                fi
        !           920:            fi
        !           921: 
        !           922:            echo ""
        !           923:            echo "  /* assume that no DTLB ASI mask flags will require a slow ${slow}: */"
        !           924:            echo "  asi_mask_flags_slow = 0;"
        !           925:            if test ${arch} = 64; then
        !           926: 
        !           927:                echo ""
        !           928:                if test ${slow} != load || ${atomic}; then
        !           929:                    echo "  /* a ${insn} traps on no-fault addresses: */"
        !           930:                else
        !           931:                    echo "  /* a ${insn} without a no-fault ASI traps on no-fault addresses: */"
        !           932:                fi
        !           933:                echo "  asi_mask_flags_slow |= TME_SPARC64_ASI_FLAG_NO_FAULT;"
        !           934:                if ${atomic}; then
        !           935:                    echo ""
        !           936:                    echo "  /* a ${insn} traps on uncacheable addresses with side-effects: */"
        !           937:                    echo "  asi_mask_flags_slow |= TME_SPARC64_ASI_MASK_FLAG_TLB_UNCACHEABLE;"
        !           938:                fi
        !           939: 
        !           940:                if ${alternate}; then
        !           941:                    echo ""
        !           942:                    echo "  /* if this ${insn} is using a no-fault ASI: */"
        !           943:                    echo "  if (__tme_predict_false(${asi_mask_data} & TME_SPARC64_ASI_FLAG_NO_FAULT)) {"
        !           944:                    echo ""
        !           945:                    if test ${slow} != load || ${atomic}; then
        !           946:                        echo "    /* a ${insn} with a no-fault ASI traps: */"
        !           947:                        echo "    asi_mask_flags_slow = 0 - (tme_uint32_t) 1;"
        !           948:                    else
        !           949:                        echo "    /* a ${insn} with a no-fault ASI traps on addresses with side-effects: */"
        !           950:                        echo "    asi_mask_flags_slow = TME_SPARC64_ASI_MASK_FLAG_TLB_SIDE_EFFECTS;"
        !           951:                    fi
        !           952:                    echo "  }"
        !           953:                fi
        !           954:            fi
        !           955: 
1.1       root      956:            echo ""
                    957:            echo "  /* get and busy the DTLB entry: */"
1.1.1.2 ! root      958:            echo "  dtlb = &ic->tme_sparc_tlbs[TME_SPARC_DTLB_ENTRY(ic, TME_SPARC_TLB_HASH(ic, ${context}, address))];"
1.1       root      959:            echo "  tme_sparc_tlb_busy(dtlb);"
                    960: 
                    961:            echo ""
                    962:            echo "  /* assume that this DTLB applies and allows fast transfers: */"
                    963:            echo "  memory = dtlb->tme_sparc_tlb_emulator_off_${cycle};"
                    964: 
                    965:            echo ""
1.1.1.2 ! root      966:            echo "  /* if this DTLB matches any context, it matches this context: */"
        !           967:            echo "  dtlb_context = dtlb->tme_sparc_tlb_context;"
        !           968:            echo "  if (dtlb_context > ic->tme_sparc_memory_context_max) {"
        !           969:            echo "    dtlb_context = ${context};"
        !           970:            echo "  }"
        !           971: 
        !           972:            echo ""
1.1       root      973:            echo "  /* we must call the slow ${slow} function if: */"
                    974:            echo "  if (__tme_predict_false("
                    975:            echo ""
                    976:            echo "                          /* the DTLB entry is invalid: */"
                    977:            echo "                          tme_bus_tlb_is_invalid(&dtlb->tme_sparc_tlb_bus_tlb)"
                    978:            echo ""
1.1.1.2 ! root      979:            echo "                          /* the DTLB entry does not match the context: */"
        !           980:            echo "                          || dtlb_context != ${context}"
        !           981:            echo ""
1.1       root      982:            echo "                          /* the DTLB entry does not cover the needed addresses: */"
1.1.1.2 ! root      983:            echo "                          || (address < (tme_bus_addr${arch}_t) dtlb->tme_sparc_tlb_addr_first)"
        !           984:            echo "                          || ((address + ((${size} / 8) - 1)) > (tme_bus_addr${arch}_t) dtlb->tme_sparc_tlb_addr_last)"
1.1       root      985:            echo ""
                    986:            echo "                          /* the DTLB entry does not cover the needed address space: */"
                    987:            echo "                          || (!TME_SPARC_TLB_ASI_MASK_OK(dtlb, ${asi_mask_data}))"
                    988:            echo ""
1.1.1.2 ! root      989:            echo "                          /* the DTLB entry can't be used for a fast ${insn}: */"
        !           990:            echo "                          || (dtlb->tme_sparc_tlb_asi_mask & asi_mask_flags_slow) != 0"
        !           991:            echo ""
1.1       root      992:            echo "                          /* the DTLB entry does not allow fast transfers: */"
                    993:            if $atomic; then
                    994:                echo "                          || (memory != dtlb->tme_sparc_tlb_emulator_off_read)"
                    995:            fi
                    996:            echo "                          || (memory == TME_EMULATOR_OFF_UNDEF)"
                    997:            if test ${size} != 8; then
                    998:                echo ""
                    999:                echo "                          /* the address is misaligned: */"
                   1000:                echo "                          || ((address % (${size} / 8)) != 0)"
                   1001:            fi
                   1002:            if ${double}; then
                   1003:                echo ""
                   1004:                echo "                          /* the destination register number is odd: */"
                   1005:                echo "                          || ((TME_SPARC_INSN & TME_BIT(25)) != 0)"
                   1006:            fi
                   1007:            echo ""
                   1008:            echo "                          )) {"
                   1009: 
                   1010:            echo ""
                   1011:            echo "    /* call the slow ${slow} function: */"
1.1.1.2 ! root     1012:            echo "    memory = tme_sparc${arch}_ls(ic,"
        !          1013:            echo "                            address,"
        !          1014:            echo "                            &TME_SPARC_FORMAT3_RD,"
        !          1015:            echo -n "                            (TME_SPARC_LSINFO_OP_"
1.1       root     1016:            if ${atomic}; then
1.1.1.2 ! root     1017:                echo "ATOMIC"
        !          1018:            elif test ${slow} = store; then
        !          1019:                echo "ST"
        !          1020:            else
        !          1021:                echo "LD"
1.1       root     1022:            fi
1.1.1.2 ! root     1023:            echo -n "                             | "
        !          1024:            case ${insn} in
        !          1025:            ldd* | std*)
        !          1026:                echo "TME_SPARC_LSINFO_LDD_STD"
        !          1027:                echo -n "                             | "
        !          1028:                ;;
        !          1029:            esac
1.1       root     1030:            if ${alternate}; then
1.1.1.2 ! root     1031:                echo "TME_SPARC_LSINFO_ASI(TME_SPARC_ASI_MASK_WHICH(${asi_mask_data} & ~TME_SPARC_ASI_MASK_FLAG_UNDEF))"
        !          1032:                echo "                             | TME_SPARC_LSINFO_A"
        !          1033:                echo -n "                             | "
1.1       root     1034:            fi
                   1035:            echo "(${size} / 8)));"
                   1036:            
1.1.1.2 ! root     1037:            if test ${slow} = store || ${alternate}; then
1.1       root     1038:                echo ""
1.1.1.2 ! root     1039:                echo "    /* if the slow ${slow} function did the transfer: */"
1.1       root     1040:                echo "    if (__tme_predict_false(memory == TME_EMULATOR_OFF_UNDEF)) {"
1.1.1.2 ! root     1041:                echo ""
        !          1042:                echo "      /* unbusy the TLB entry; */"
1.1       root     1043:                echo "      tme_sparc_tlb_unbusy(dtlb);"
1.1.1.2 ! root     1044: 
        !          1045:                # if this is some kind of a load, log the value loaded:
        !          1046:                #
        !          1047:                case ${insn} in
        !          1048:                ldd*)
        !          1049:                    echo ""
        !          1050:                    echo "      /* log the value loaded: */"
        !          1051:                    echo "      tme_sparc_recode_verify_mem_load(ic, &TME_SPARC_FORMAT3_RD);"
        !          1052:                    echo "      tme_sparc_recode_verify_mem_load(ic, &TME_SPARC_FORMAT3_RD_ODD(tme_ic_ireg_uint${arch}));"
        !          1053:                    echo "      tme_sparc_log(ic, 1000, TME_OK,"
        !          1054:                    echo "                   (TME_SPARC_LOG_HANDLE(ic),"
        !          1055:                    echo "                    _(\"${insn}\t0x%02x:0x%0"`expr ${arch} / 4`"\" TME_PRIx${arch} \":\t0x%0"`expr ${arch} / 4`"\" TME_PRIx${arch} \" 0x%0"`expr ${arch} / 4`"\" TME_PRIx${arch} \"\"),"
        !          1056:                    echo "                    TME_SPARC_ASI_MASK_WHICH(${asi_mask_data} & ~TME_SPARC_ASI_MASK_FLAG_UNDEF),"
        !          1057:                    echo "                    address,"
        !          1058:                    echo "                    TME_SPARC_FORMAT3_RD,"
        !          1059:                    echo "                    TME_SPARC_FORMAT3_RD_ODD(tme_ic_ireg_uint${arch})));"
        !          1060:                    ;;
        !          1061:                ld* | ldstub* | swap* | cas*a)
        !          1062:                    echo ""
        !          1063:                    echo "      /* log the value loaded: */"
        !          1064:                    echo "      tme_sparc_recode_verify_mem_load(ic, &TME_SPARC_FORMAT3_RD);"
        !          1065:                    echo "      tme_sparc_log(ic, 1000, TME_OK,"
        !          1066:                    echo "                   (TME_SPARC_LOG_HANDLE(ic),"
        !          1067:                    echo "                    _(\"${insn}\t0x%02x:0x%0"`expr ${arch} / 4`"\" TME_PRIx${arch} \":\t0x%0"`expr ${size} / 4`"\" TME_PRIx${arch}),"
        !          1068:                    echo "                    TME_SPARC_ASI_MASK_WHICH(${asi_mask_data} & ~TME_SPARC_ASI_MASK_FLAG_UNDEF),"
        !          1069:                    echo "                    address,"
        !          1070:                    echo "                    TME_SPARC_FORMAT3_RD));"
        !          1071:                    ;;
        !          1072:                esac
        !          1073:                echo ""
1.1       root     1074:                echo "      TME_SPARC_INSN_OK;"
                   1075:                echo "    }"
                   1076:            fi
                   1077:            echo "  }"
                   1078: 
                   1079:            echo ""
1.1.1.2 ! root     1080:            echo "  /* get the byte order of this transfer: */"
        !          1081:            if test ${arch} = 32; then
        !          1082:                echo "  endian_little = FALSE;"
        !          1083:            elif test ${arch} = 64; then
        !          1084:                echo "  endian_little = ${asi_mask_data} & TME_SPARC64_ASI_FLAG_LITTLE;"
        !          1085:                echo "  if (__tme_predict_false(dtlb->tme_sparc_tlb_asi_mask & TME_SPARC64_ASI_FLAG_LITTLE)) {"
        !          1086:                echo "    if (TME_SPARC_MEMORY_FLAGS(ic) & TME_SPARC_MEMORY_FLAG_HAS_INVERT_ENDIAN) {"
        !          1087:                echo "      endian_little ^= TME_SPARC64_ASI_FLAG_LITTLE;"
        !          1088:                echo "    }"
        !          1089:                echo "    else {"
        !          1090:                echo "      assert (FALSE);"
        !          1091:                echo "    }"
        !          1092:                echo "  }"
        !          1093:            fi
        !          1094: 
        !          1095:            echo ""
1.1       root     1096:            echo "  /* do the fast transfer: */"
                   1097:            echo "  memory += address;"
                   1098: 
                   1099:            # dispatch on the instruction:
                   1100:            #
                   1101:            case "${insn}" in
                   1102:            ldd*)
1.1.1.2 ! root     1103:                echo "  value32 = tme_memory_bus_read32(((const tme_shared tme_uint32_t *) memory) + 0, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint32_t) * 2, sizeof(tme_uint${arch}_t));"
        !          1104:                echo "  value32 = (endian_little ? tme_letoh_u32(value32) : tme_betoh_u32(value32));"
        !          1105:                echo "  TME_SPARC_FORMAT3_RD = value32;"
        !          1106:                echo "  value32 = tme_memory_bus_read32(((const tme_shared tme_uint32_t *) memory) + 1, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint32_t) * 1, sizeof(tme_uint${arch}_t));"
        !          1107:                echo "  value32 = (endian_little ? tme_letoh_u32(value32) : tme_betoh_u32(value32));"
        !          1108:                echo "  TME_SPARC_FORMAT3_RD_ODD(tme_ic_ireg_uint${arch}) = value32;"
1.1       root     1109:                ;;
                   1110:            std*)
1.1.1.2 ! root     1111:                echo "  value32 = TME_SPARC_FORMAT3_RD;"
        !          1112:                echo "  value32 = (endian_little ? tme_htole_u32(value32) : tme_htobe_u32(value32));"
        !          1113:                echo "  tme_memory_bus_write32(((tme_shared tme_uint32_t *) memory) + 0, value32, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint32_t) * 2, sizeof(tme_uint${arch}_t));"
        !          1114:                echo "  value32 = TME_SPARC_FORMAT3_RD_ODD(tme_ic_ireg_uint${arch});"
        !          1115:                echo "  value32 = (endian_little ? tme_htole_u32(value32) : tme_htobe_u32(value32));"
        !          1116:                echo "  tme_memory_bus_write32(((tme_shared tme_uint32_t *) memory) + 1, value32, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint32_t) * 1, sizeof(tme_uint${arch}_t));"
1.1       root     1117:                ;;
                   1118:            ldstub*)
1.1.1.2 ! root     1119:                echo "  TME_SPARC_FORMAT3_RD = tme_memory_atomic_xchg8(memory, 0xff, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint8_t));"
1.1       root     1120:                ;;
                   1121:            swap*)
1.1.1.2 ! root     1122:                echo "  value32 = TME_SPARC_FORMAT3_RD;"
        !          1123:                echo "  value32 = (endian_little ? tme_htole_u32(value32) : tme_htobe_u32(value32));"
        !          1124:                echo "  value32 = tme_memory_atomic_xchg32((tme_shared tme_uint${size}_t *) memory, value32, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint8_t));"
        !          1125:                echo "  value32 = (endian_little ? tme_letoh_u32(value32) : tme_betoh_u32(value32));"
        !          1126:                echo "  TME_SPARC_FORMAT3_RD = value32;"
        !          1127:                ;;
        !          1128:            cas*a)
        !          1129:                echo "  reg_rs2 = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RS2);"
        !          1130:                echo "  TME_SPARC_REG_INDEX(ic, reg_rs2);"
        !          1131:                echo "  value_compare${size} = ic->tme_sparc_ireg_uint${arch}(reg_rs2);"
        !          1132:                echo "  value_compare${size} = (endian_little ? tme_htole_u${size}(value_compare${size}) : tme_htobe_u${size}(value_compare${size}));"
        !          1133:                echo "  value_swap${size} = TME_SPARC_FORMAT3_RD;"
        !          1134:                echo "  value_swap${size} = (endian_little ? tme_htole_u${size}(value_swap${size}) : tme_htobe_u${size}(value_swap${size}));"
        !          1135:                echo "  value_read${size} = tme_memory_atomic_cx${size}((tme_shared tme_uint${size}_t *) memory, value_compare${size}, value_swap${size}, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint${size}_t));"
        !          1136:                echo "  value_read${size} = (endian_little ? tme_letoh_u${size}(value_read${size}) : tme_betoh_u${size}(value_read${size}));"
        !          1137:                echo "  TME_SPARC_FORMAT3_RD = value_read${size};"
1.1       root     1138:                ;;
                   1139:            ld*)
1.1.1.2 ! root     1140:                echo "  value${size} = tme_memory_bus_read${size}((const tme_shared tme_uint${size}_t *) memory, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint${size}_t), sizeof(tme_uint${arch}_t));"
1.1       root     1141:                if test ${size} != 8; then
1.1.1.2 ! root     1142:                    echo "  value${size} = (endian_little ? tme_letoh_u${size}(value${size}) : tme_betoh_u${size}(value${size}));"
1.1       root     1143:                fi
1.1.1.2 ! root     1144:                if test `expr ${size} \< ${arch}` = 1; then
        !          1145:                    echo ""
        !          1146:                    echo "  /* possibly sign-extend the loaded value: */"
        !          1147:                    echo "  value${size_extend} = value${size};"
        !          1148:                    echo "  if (TME_SPARC_INSN & TME_BIT(22)) {"
        !          1149:                    echo "    value${size_extend} = (tme_uint${size_extend}_t) (tme_int${size_extend}_t) (tme_int${size}_t) value${size_extend};"
        !          1150:                    echo "  }"
        !          1151:                fi
        !          1152:                echo "  TME_SPARC_FORMAT3_RD = (tme_uint${arch}_t) (tme_int${arch}_t) (tme_int${size_extend}_t) value${size_extend};"
1.1       root     1153:                ;;
                   1154:            st*)
1.1.1.2 ! root     1155:                echo "  value${size} = TME_SPARC_FORMAT3_RD;"
        !          1156:                if test ${size} != 8; then
        !          1157:                    echo "  value${size} = (endian_little ? tme_htole_u${size}(value${size}) : tme_htobe_u${size}(value${size}));"
        !          1158:                fi
        !          1159:                echo "  tme_memory_bus_write${size}((tme_shared tme_uint${size}_t *) memory, value${size}, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint${size}_t), sizeof(tme_uint${arch}_t));"
1.1       root     1160:                ;;
                   1161:            *) echo "$PROG internal error: unknown memory insn ${insn}" 1>&2 ; exit 1 ;;
                   1162:            esac
                   1163: 
                   1164:            echo ""
                   1165:            echo "  /* unbusy the DTLB entry: */"
                   1166:            echo "  tme_sparc_tlb_unbusy(dtlb);"
                   1167:                
                   1168:            # if this is some kind of a load, log the value loaded:
                   1169:            #
                   1170:            case ${insn} in
                   1171:            ldd*)
                   1172:                echo ""
                   1173:                echo "  /* log the value loaded: */"
1.1.1.2 ! root     1174:                echo "  tme_sparc_recode_verify_mem_load(ic, &TME_SPARC_FORMAT3_RD);"
        !          1175:                echo "  tme_sparc_recode_verify_mem_load(ic, &TME_SPARC_FORMAT3_RD_ODD(tme_ic_ireg_uint${arch}));"
1.1       root     1176:                echo "  tme_sparc_log(ic, 1000, TME_OK,"
                   1177:                echo "               (TME_SPARC_LOG_HANDLE(ic),"
1.1.1.2 ! root     1178:                echo "                _(\"${insn}\t0x%02x:0x%0"`expr ${arch} / 4`"\" TME_PRIx${arch} \":\t0x%0"`expr ${arch} / 4`"\" TME_PRIx${arch} \" 0x%0"`expr ${arch} / 4`"\" TME_PRIx${arch} \"\"),"
        !          1179:                echo "                TME_SPARC_ASI_MASK_WHICH(${asi_mask_data} & ~TME_SPARC_ASI_MASK_FLAG_UNDEF),"
1.1       root     1180:                echo "                address,"
1.1.1.2 ! root     1181:                echo "                TME_SPARC_FORMAT3_RD,"
        !          1182:                echo "                TME_SPARC_FORMAT3_RD_ODD(tme_ic_ireg_uint${arch})));"
1.1       root     1183:                ;;
1.1.1.2 ! root     1184:            ld* | ldstub* | swap* | cas*a)
1.1       root     1185:                echo ""
                   1186:                echo "  /* log the value loaded: */"
1.1.1.2 ! root     1187:                echo "  tme_sparc_recode_verify_mem_load(ic, &TME_SPARC_FORMAT3_RD);"
1.1       root     1188:                echo "  tme_sparc_log(ic, 1000, TME_OK,"
                   1189:                echo "               (TME_SPARC_LOG_HANDLE(ic),"
1.1.1.2 ! root     1190:                echo "                _(\"${insn}\t0x%02x:0x%0"`expr ${arch} / 4`"\" TME_PRIx${arch} \":\t0x%0"`expr ${size} / 4`"\" TME_PRIx${arch}),"
        !          1191:                echo "                TME_SPARC_ASI_MASK_WHICH(${asi_mask_data} & ~TME_SPARC_ASI_MASK_FLAG_UNDEF),"
1.1       root     1192:                echo "                address,"
                   1193:                echo "                TME_SPARC_FORMAT3_RD));"
                   1194:                ;;
                   1195:            esac
                   1196: 
                   1197:            echo ""
                   1198:            echo "  TME_SPARC_INSN_OK;"
                   1199:            echo "}"
                   1200:        fi
                   1201: 
                   1202:        # the jmpl instruction:
                   1203:        #
                   1204:        if test ${insn} = jmpl; then
                   1205: 
                   1206:            echo ""
                   1207:            echo "/* this does a sparc${arch} ${insn}: */"
                   1208:            echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
                   1209:            echo "{"
                   1210:            echo "  tme_uint${arch}_t pc_next_next;"
1.1.1.2 ! root     1211:            echo "  tme_uint32_t ls_faults;"
1.1       root     1212:            echo ""
                   1213:            echo "  /* \"The JMPL instruction causes a register-indirect delayed control"
                   1214:            echo "     transfer to the address given by r[rs1] + r[rs2] if the i field is"
                   1215:            echo "     zero, or r[rs1] + sign_ext(simm13) if the i field is one. The JMPL"
                   1216:            echo "     instruction copies the PC, which contains the address of the JMPL"
                   1217:            echo "     instruction, into register r[rd]. If either of the low-order two"
                   1218:            echo "     bits of the jump address is nonzero, a mem_address_not_aligned"
                   1219:            echo "     trap occurs.\" */"
                   1220:            echo ""
1.1.1.2 ! root     1221:            echo "  /* get the target address: */"
1.1       root     1222:            echo "  pc_next_next = TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2;"
1.1.1.2 ! root     1223:            if test ${arch} = 64; then
        !          1224:                echo "  pc_next_next &= ic->tme_sparc_address_mask;"
        !          1225:            fi
        !          1226:            echo ""
        !          1227:            echo "  /* set the delayed control transfer: */"
        !          1228:            echo "  ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_PC_NEXT_NEXT) = pc_next_next;"
        !          1229:            echo ""
        !          1230:            echo "  /* check the target address: */"
        !          1231:            echo "  ls_faults = TME_SPARC_LS_FAULT_NONE;"
        !          1232:            if test ${arch} = 64; then
        !          1233:                echo "  if (__tme_predict_false((pc_next_next"
        !          1234:                echo "                           + ic->tme_sparc${arch}_ireg_va_hole_start)"
        !          1235:                echo "                          > ((ic->tme_sparc${arch}_ireg_va_hole_start * 2) - 1))) {"
        !          1236:                echo "    ls_faults += TME_SPARC64_LS_FAULT_VA_RANGE_NNPC;"
        !          1237:                echo "  }"
        !          1238:            fi
1.1       root     1239:            echo "  if (__tme_predict_false((pc_next_next % sizeof(tme_uint32_t)) != 0)) {"
1.1.1.2 ! root     1240:            echo "    ls_faults += TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED;"
        !          1241:            echo "  }"
        !          1242:            echo "  if (__tme_predict_false(ls_faults != TME_SPARC_LS_FAULT_NONE)) {"
        !          1243:            echo "    tme_sparc_nnpc_trap(ic, ls_faults);"
1.1       root     1244:            echo "  }"
                   1245:            echo ""
                   1246:            echo "  /* write the PC of the jmpl into r[rd]: */"
                   1247:            echo "  TME_SPARC_FORMAT3_RD = ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_PC);"
                   1248:            echo ""
                   1249:            echo "  /* log an indirect call instruction, which has 15 (%o7) for rd: */"
                   1250:            echo "  if (TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD) == 15) {"
                   1251:            echo "    tme_sparc_log(ic, 250, TME_OK,"
                   1252:            echo "                  (TME_SPARC_LOG_HANDLE(ic),"
1.1.1.2 ! root     1253:            echo "                   _(\"call 0x%0"`expr ${arch} / 4`"\" TME_PRIx${arch}),"
1.1       root     1254:            echo "                   pc_next_next));"
                   1255:            echo "  }"
                   1256:            echo ""
                   1257:            echo "  /* log a ret or retl instruction, which has 0 (%g0) for rd,"
                   1258:            echo "     either 31 (%i7) or 15 (%o7) for rs1, and 8 for simm13: */"
                   1259:            echo "  else if ((TME_SPARC_INSN | (16 << 14))"
                   1260:            echo "           == ((tme_uint32_t) (0x2 << 30) | (0 << 25) | (0x38 << 19) | (31 << 14) | (0x1 << 13) | 8)) {"
                   1261:            echo "    tme_sparc_log(ic, 250, TME_OK,"
                   1262:            echo "                  (TME_SPARC_LOG_HANDLE(ic),"
1.1.1.2 ! root     1263:            echo "                   _(\"retl 0x%0"`expr ${arch} / 4`"\" TME_PRIx${arch}),"
1.1       root     1264:            echo "                   pc_next_next));"
                   1265:            echo "  }"
                   1266:            echo ""
                   1267:            echo "  TME_SPARC_INSN_OK;"
                   1268:            echo "}"
                   1269:        fi
                   1270: 
1.1.1.2 ! root     1271:        # this may be an alternate-space version of a floating-point
        !          1272:        # load or store instruction:
        !          1273:        #
        !          1274:        case ${insn} in *a) alternate=a ;; *) alternate= ;; esac
        !          1275: 
1.1       root     1276:        # the ldf instruction:
                   1277:        #
1.1.1.2 ! root     1278:        if test ${insn} = "ldf${alternate}"; then
1.1       root     1279: 
                   1280:            echo ""
                   1281:            echo "/* this does a sparc${arch} ${insn}: */"
                   1282:            echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
                   1283:            echo "{"
1.1.1.2 ! root     1284:            echo "  tme_uint32_t misaligned;"
        !          1285:            echo "  struct tme_float float_buffer;"
        !          1286:            echo "  struct tme_float *fpreg;"
        !          1287:            echo ""
        !          1288:            echo "  /* get the least significant 32 bits of the address: */"
        !          1289:            echo "  misaligned = TME_SPARC_FORMAT3_RS1;"
        !          1290:            echo "  misaligned += (tme_uint32_t) TME_SPARC_FORMAT3_RS2;"
        !          1291:            if test "${arch}${alternate}" = 64a; then
        !          1292:                echo ""
        !          1293:                echo "  /* see if the address is misaligned for the ASI: */"
        !          1294:                echo "  misaligned = (*ic->_tme_sparc_ls_asi_misaligned)(ic, misaligned);"
        !          1295:            fi
1.1       root     1296:            echo ""
                   1297:            echo "  /* decode rd: */"
1.1.1.2 ! root     1298:            echo "  float_buffer.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;"
        !          1299:            echo "  fpreg"
        !          1300:            echo "    = _tme_sparc${arch}_fpu_mem_fpreg(ic,"
        !          1301:            echo "                                 misaligned,"
        !          1302:            echo "                                 &float_buffer);"
1.1       root     1303:            echo ""
                   1304:            echo "  /* do the load: */"
1.1.1.2 ! root     1305:            echo "  tme_sparc${arch}_ld${alternate}(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_FPX));"
1.1       root     1306:            echo ""
                   1307:            echo "  /* set the floating-point register value: */"
1.1.1.2 ! root     1308:            echo "  assert (fpreg != &float_buffer);"
        !          1309:            echo "  fpreg->tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;"
        !          1310:            echo "  fpreg->tme_float_value_ieee754_single"
1.1       root     1311:            echo "    = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift});"
                   1312:            echo ""
                   1313:            echo "  TME_SPARC_INSN_OK;"
                   1314:            echo "}"
                   1315:        fi
                   1316: 
                   1317:        # the stf instruction:
                   1318:        #
1.1.1.2 ! root     1319:        if test ${insn} = "stf${alternate}"; then
1.1       root     1320: 
                   1321:            echo ""
                   1322:            echo "/* this does a sparc${arch} ${insn}: */"
                   1323:            echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
                   1324:            echo "{"
1.1.1.2 ! root     1325:            echo "  tme_uint32_t misaligned;"
        !          1326:            echo "  struct tme_float float_buffer;"
        !          1327:            echo "  const struct tme_float *fpreg;"
1.1       root     1328:            echo "  const tme_uint32_t *value_single;"
                   1329:            echo ""
1.1.1.2 ! root     1330:            echo "  /* get the least significant 32 bits of the address: */"
        !          1331:            echo "  misaligned = TME_SPARC_FORMAT3_RS1;"
        !          1332:            echo "  misaligned += (tme_uint32_t) TME_SPARC_FORMAT3_RS2;"
        !          1333:            if test "${arch}${alternate}" = 64a; then
        !          1334:                echo ""
        !          1335:                echo "  /* see if the address is misaligned for the ASI: */"
        !          1336:                echo "  misaligned = (*ic->_tme_sparc_ls_asi_misaligned)(ic, misaligned);"
        !          1337:            fi
1.1       root     1338:            echo ""
                   1339:            echo "  /* decode rd: */"
1.1.1.2 ! root     1340:            echo "  float_buffer.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;"
        !          1341:            echo "  fpreg"
        !          1342:            echo "    = _tme_sparc${arch}_fpu_mem_fpreg(ic,"
        !          1343:            echo "                                 misaligned,"
        !          1344:            echo "                                 &float_buffer);"
1.1       root     1345:            echo ""
                   1346:            echo "  /* get this single floating-point register in IEEE754 single-precision format: */"
1.1.1.2 ! root     1347:            echo "  value_single = tme_ieee754_single_value_get(fpreg, &float_buffer.tme_float_value_ieee754_single);"
1.1       root     1348:            echo ""
                   1349:            echo "  /* set the floating-point register value: */"
                   1350:            echo "  ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}) = *value_single;"
                   1351:            echo ""
                   1352:            echo "  /* do the store: */"
1.1.1.2 ! root     1353:            echo "  tme_sparc${arch}_st${alternate}(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_FPX));"
1.1       root     1354:            echo ""
1.1.1.2 ! root     1355:            echo "  assert (fpreg != &float_buffer);"
1.1       root     1356:            echo "  TME_SPARC_INSN_OK;"
                   1357:            echo "}"
                   1358:        fi
                   1359: 
                   1360:        # the lddf instruction:
                   1361:        #
1.1.1.2 ! root     1362:        if test ${insn} = "lddf${alternate}"; then
1.1       root     1363: 
                   1364:            echo ""
                   1365:            echo "/* this does a sparc${arch} ${insn}: */"
                   1366:            echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
                   1367:            echo "{"
1.1.1.2 ! root     1368:            echo "  tme_uint${arch}_t address;"
        !          1369:            echo "  tme_uint32_t misaligned;"
        !          1370:            echo "  struct tme_float float_buffer;"
        !          1371:            echo "  struct tme_float *fpreg;"
        !          1372:            if test ${arch} != 32; then
        !          1373:                echo "  tme_uint${arch}_t offset;"
        !          1374:            fi
1.1       root     1375:            echo ""
1.1.1.2 ! root     1376:            echo "  /* get the address: */"
        !          1377:            echo "  address = TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2;"
1.1       root     1378:            echo ""
1.1.1.2 ! root     1379:            echo "  /* get the least significant 32 bits of the address: */"
        !          1380:            echo "  misaligned = address;"
        !          1381:            if test "${arch}${alternate}" = 64a; then
        !          1382:                echo ""
        !          1383:                echo "  /* see if the address is misaligned for the ASI: */"
        !          1384:                echo "  misaligned = (*ic->_tme_sparc_ls_asi_misaligned)(ic, misaligned);"
        !          1385:            fi
1.1       root     1386:            echo ""
1.1.1.2 ! root     1387:            echo "  /* decode rd: */"
        !          1388:            echo "  float_buffer.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;"
        !          1389:            echo "  fpreg"
        !          1390:            echo "    = _tme_sparc${arch}_fpu_mem_fpreg(ic,"
        !          1391:            echo "                                 misaligned,"
        !          1392:            echo "                                 &float_buffer);"
        !          1393:            echo ""
        !          1394:            if test ${arch} = 32; then
        !          1395:                echo "  /* do the load: */"
        !          1396:                echo "  tme_sparc${arch}_ldd(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}));"
        !          1397:                echo ""
        !          1398:                echo "  /* set the double floating-point register value: */"
        !          1399:                echo "  assert (fpreg != &float_buffer);"
        !          1400:                echo "  fpreg->tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;"
        !          1401:                echo "  fpreg->tme_float_value_ieee754_double.tme_value64_uint32_hi"
        !          1402:                echo "    = ic->tme_sparc_ireg_uint32((TME_SPARC_IREG_FPX${reg32_shift}) + 0);"
        !          1403:                echo "  fpreg->tme_float_value_ieee754_double.tme_value64_uint32_lo"
        !          1404:                echo "    = ic->tme_sparc_ireg_uint32((TME_SPARC_IREG_FPX${reg32_shift}) + 1);"
        !          1405:            else
        !          1406:                echo "  /* if bit two of the address is set, and this SPARC supports"
        !          1407:                echo "     32-bit-aligned ${insn} instructions: */"
        !          1408:                echo "  if ((misaligned & sizeof(tme_uint32_t))"
        !          1409:                echo "      && fpreg != &float_buffer) {"
        !          1410:                echo ""
        !          1411:                echo "    /* do two 32-bit loads: */"
        !          1412:                echo "    offset = sizeof(tme_uint32_t) * 0;"
        !          1413:                echo "    tme_sparc${arch}_ld${alternate}(ic, &address, &offset, &ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_FPX + 0));"
        !          1414:                echo "    offset = sizeof(tme_uint32_t) * 1;"
        !          1415:                echo "    tme_sparc${arch}_ld${alternate}(ic, &address, &offset, &ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_FPX + 1));"
        !          1416:                echo ""
        !          1417:                echo "    /* set the double floating-point register value: */"
        !          1418:                echo "    fpreg->tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;"
        !          1419:                echo "    fpreg->tme_float_value_ieee754_double.tme_value64_uint32_hi"
        !          1420:                echo "      = ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_FPX + 0);"
        !          1421:                echo "    fpreg->tme_float_value_ieee754_double.tme_value64_uint32_lo"
        !          1422:                echo "      = ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_FPX + 1);"
        !          1423:                echo "  }"
        !          1424:                echo ""
        !          1425:                echo "  /* otherwise, bit two of the address is not set, or this SPARC"
        !          1426:                echo "     doesn't support 32-bit-aligned ${insn} instructions: */"
        !          1427:                echo "  else {"
        !          1428:                echo ""
        !          1429:                echo "    /* do an ldx${alternate}-style load: */"
        !          1430:                echo "    tme_sparc${arch}_ldx${alternate}(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_FPX));"
        !          1431:                echo ""
        !          1432:                echo "    /* set the double floating-point register value: */"
        !          1433:                echo "    assert (fpreg != &float_buffer);"
        !          1434:                echo "    fpreg->tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;"
        !          1435:                echo "    fpreg->tme_float_value_ieee754_double.tme_value64_uint"
        !          1436:                echo "      = ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_FPX);"
        !          1437:                echo "  }"
        !          1438:            fi
1.1       root     1439:            echo ""
                   1440:            echo "  TME_SPARC_INSN_OK;"
                   1441:            echo "}"
                   1442:        fi
                   1443: 
                   1444:        # the stdf instruction:
                   1445:        #
1.1.1.2 ! root     1446:        if test ${insn} = "stdf${alternate}"; then
1.1       root     1447: 
                   1448:            echo ""
                   1449:            echo "/* this does a sparc${arch} ${insn}: */"
                   1450:            echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
                   1451:            echo "{"
1.1.1.2 ! root     1452:            echo "  tme_uint${arch}_t address;"
        !          1453:            echo "  tme_uint32_t misaligned;"
        !          1454:            echo "  struct tme_float float_buffer;"
        !          1455:            echo "  struct tme_float *fpreg;"
1.1       root     1456:            echo "  const union tme_value64 *value_double;"
1.1.1.2 ! root     1457:            if test ${arch} != 32; then
        !          1458:                echo "  tme_uint${arch}_t offset;"
        !          1459:            fi
1.1       root     1460:            echo ""
1.1.1.2 ! root     1461:            echo "  /* get the address: */"
        !          1462:            echo "  address = TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2;"
1.1       root     1463:            echo ""
1.1.1.2 ! root     1464:            echo "  /* get the least significant 32 bits of the address: */"
        !          1465:            echo "  misaligned = address;"
        !          1466:            if test "${arch}${alternate}" = 64a; then
        !          1467:                echo ""
        !          1468:                echo "  /* see if the address is misaligned for the ASI: */"
        !          1469:                echo "  misaligned = (*ic->_tme_sparc_ls_asi_misaligned)(ic, misaligned);"
        !          1470:            fi
1.1       root     1471:            echo ""
1.1.1.2 ! root     1472:            echo "  /* decode rd: */"
        !          1473:            echo "  float_buffer.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;"
        !          1474:            echo "  fpreg"
        !          1475:            echo "    = _tme_sparc${arch}_fpu_mem_fpreg(ic,"
        !          1476:            echo "                                 misaligned,"
        !          1477:            echo "                                 &float_buffer);"
1.1       root     1478:            echo ""
                   1479:            echo "  /* get this double floating-point register in IEEE754 double-precision format: */"
1.1.1.2 ! root     1480:            echo "  value_double = tme_ieee754_double_value_get(fpreg, &float_buffer.tme_float_value_ieee754_double);"
1.1       root     1481:            echo ""
1.1.1.2 ! root     1482:            if test ${arch} = 32; then
        !          1483:                echo "  /* set the floating-point register value: */"
        !          1484:                echo "  ic->tme_sparc_ireg_uint32((TME_SPARC_IREG_FPX${reg32_shift}) + 0)"
        !          1485:                echo "    = value_double->tme_value64_uint32_hi;"
        !          1486:                echo "  ic->tme_sparc_ireg_uint32((TME_SPARC_IREG_FPX${reg32_shift}) + 1)"
        !          1487:                echo "    = value_double->tme_value64_uint32_lo;"
        !          1488:                echo ""
        !          1489:                echo "  /* do the store: */"
        !          1490:                echo "  tme_sparc${arch}_std(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}));"
        !          1491:            else
        !          1492:                echo "  /* if bit two of the address is set, and this SPARC supports"
        !          1493:                echo "     32-bit-aligned ${insn} instructions: */"
        !          1494:                echo "  if ((misaligned & sizeof(tme_uint32_t))"
        !          1495:                echo "      && fpreg != &float_buffer) {"
        !          1496:                echo ""
        !          1497:                echo "    /* set the floating-point register value: */"
        !          1498:                echo "    ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_FPX + 0)"
        !          1499:                echo "      = value_double->tme_value64_uint32_hi;"
        !          1500:                echo "    ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX + 1)"
        !          1501:                echo "      = value_double->tme_value64_uint32_lo;"
        !          1502:                echo ""
        !          1503:                echo "    /* do two 32-bit stores: */"
        !          1504:                echo "    offset = sizeof(tme_uint32_t) * 0;"
        !          1505:                echo "    tme_sparc${arch}_st${alternate}(ic, &address, &offset, &ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_FPX + 0));"
        !          1506:                echo "    offset = sizeof(tme_uint32_t) * 1;"
        !          1507:                echo "    tme_sparc${arch}_st${alternate}(ic, &address, &offset, &ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_FPX + 1));"
        !          1508:                echo "  }"
        !          1509:                echo ""
        !          1510:                echo "  /* otherwise, bit two of the address is not set, or this SPARC"
        !          1511:                echo "     doesn't support 32-bit-aligned ${insn} instructions: */"
        !          1512:                echo "  else {"
        !          1513:                echo ""
        !          1514:                echo "    /* set the floating-point register value: */"
        !          1515:                echo "    ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_FPX)"
        !          1516:                echo "      = value_double->tme_value64_uint;"
        !          1517:                echo ""
        !          1518:                echo "    /* do an stx${alternate}-style store: */"
        !          1519:                echo "    tme_sparc${arch}_stx${alternate}(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_FPX));"
        !          1520:                echo "  }"
        !          1521:            fi
1.1       root     1522:            echo ""
1.1.1.2 ! root     1523:            echo "  assert (fpreg != &float_buffer);"
1.1       root     1524:            echo "  TME_SPARC_INSN_OK;"
                   1525:            echo "}"
                   1526:        fi
                   1527: 
                   1528:        # the ldfsr instruction:
                   1529:        #
                   1530:        if test ${insn} = ldfsr; then
                   1531: 
                   1532:            echo ""
                   1533:            echo "/* this does a sparc${arch} ${insn}: */"
                   1534:            echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
                   1535:            echo "{"
                   1536:            echo "  tme_uint32_t fsr;"
1.1.1.2 ! root     1537:            if test ${arch} != 32; then
        !          1538:                echo "  tme_uint32_t reg_rd;"
        !          1539:                echo ""
        !          1540:                echo "  /* see if this is an ldfsr or an ldxfsr: */"
        !          1541:                echo "  reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);"
        !          1542:                echo "  if (__tme_predict_false(reg_rd > 1)) {"
        !          1543:                echo "    TME_SPARC_INSN_ILL(ic);"
        !          1544:                echo "  }"
        !          1545:            fi
1.1       root     1546:            echo ""
1.1.1.2 ! root     1547:            echo "  _tme_sparc${arch}_fpu_mem(ic);"
1.1       root     1548:            echo ""
1.1.1.2 ! root     1549:            if test ${arch} = 32; then
        !          1550:                echo "  /* do the load: */"
        !          1551:            else
        !          1552:                echo "  /* if this is an ldxfsr: */"
        !          1553:                echo "  if (reg_rd == 1) {"
        !          1554:                echo ""
        !          1555:                echo "    /* do the load: */"
        !          1556:                echo "    tme_sparc${arch}_ldx(ic, _rs1, _rs2,  &ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_FPX));"
        !          1557:                echo ""
        !          1558:                echo "    /* update the extended FSR: */"
        !          1559:                echo "    ic->tme_sparc_fpu_xfsr"
        !          1560:                echo "      = (ic->tme_sparc_ireg_uint32((TME_SPARC_IREG_FPX${reg32_shift}) + 1)"
        !          1561:                echo "         & 0x3f /* fcc3 .. fcc1 */);"
        !          1562:                echo "  }"
        !          1563:                echo ""
        !          1564:                echo "  /* otherwise, this is an ldfsr.  do the load: */"
        !          1565:                echo "  else"
        !          1566:                echo -n "  "
        !          1567:            fi
        !          1568:            echo "  tme_sparc${arch}_ld(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_FPX));"
1.1       root     1569:            echo ""
                   1570:            echo "  /* update the FSR: */"
                   1571:            echo "  fsr = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift});"
                   1572:            echo "  /* \"An LDFSR instruction does not affect ftt.\" */"
                   1573:            echo "  /* \"The LDFSR instruction does not affect qne.\" */"
                   1574:            echo "  fsr &= ~(TME_SPARC_FSR_VER | TME_SPARC_FSR_FTT | TME_SPARC_FSR_QNE);"
                   1575:            echo "  ic->tme_sparc_fpu_fsr = (ic->tme_sparc_fpu_fsr & (TME_SPARC_FSR_VER | TME_SPARC_FSR_FTT | TME_SPARC_FSR_QNE)) | fsr;"
                   1576:            echo ""
                   1577:            echo "  TME_SPARC_INSN_OK;"
                   1578:            echo "}"
                   1579:        fi
                   1580: 
                   1581:        # the stfsr instruction:
                   1582:        #
                   1583:        if test ${insn} = stfsr; then
                   1584: 
                   1585:            echo ""
                   1586:            echo "/* this does a sparc${arch} ${insn}: */"
                   1587:            echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
                   1588:            echo "{"
1.1.1.2 ! root     1589:            if test ${arch} = 64; then
        !          1590:                echo "  tme_uint32_t reg_rd;"
        !          1591:                echo ""
        !          1592:                echo "  /* see if this is an stfsr or an stxfsr: */"
        !          1593:                echo "  reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);"
        !          1594:                echo "  if (__tme_predict_false(reg_rd > 1)) {"
        !          1595:                echo "    TME_SPARC_INSN_ILL(ic);"
        !          1596:                echo "  }"
        !          1597:            fi
1.1       root     1598:            echo ""
1.1.1.2 ! root     1599:            echo "  _tme_sparc${arch}_fpu_mem(ic);"
1.1       root     1600:            echo ""
                   1601:            echo "  /* set the FSR value to store: */"
                   1602:            echo "  ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}) = ic->tme_sparc_fpu_fsr;"
                   1603:            echo ""
1.1.1.2 ! root     1604:            if test ${arch} = 32; then
        !          1605:                echo "  /* do the store: */"
        !          1606:            else
        !          1607:                echo "  /* if this is an stxfsr: */"
        !          1608:                echo "  if (reg_rd == 1) {"
        !          1609:                echo ""
        !          1610:                echo "    /* set in the extended FSR to store and do the store: */"
        !          1611:                echo "    ic->tme_sparc_ireg_uint32((TME_SPARC_IREG_FPX${reg32_shift}) + 1) = ic->tme_sparc_fpu_xfsr;"
        !          1612:                echo "    tme_sparc${arch}_stx(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_FPX));"
        !          1613:                echo "  }"
        !          1614:                echo ""
        !          1615:                echo "  /* otherwise, this is a stfsr.  do the store: */"
        !          1616:                echo "  else"
        !          1617:                echo -n "  "
        !          1618:            fi
        !          1619:            echo "  tme_sparc${arch}_st(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_FPX));"
1.1       root     1620:            echo ""
                   1621:            echo "  TME_SPARC_INSN_OK;"
                   1622:            echo "}"
                   1623:        fi
                   1624: 
                   1625:        # the fpop1 and fpop2 instructions:
                   1626:        #
                   1627:        if test ${insn} = fpop1 || test ${insn} = fpop2; then
                   1628: 
                   1629:            echo ""
                   1630:            echo "/* this does a sparc${arch} ${insn}: */"
                   1631:            echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
                   1632:            echo "{"
                   1633:            echo "  TME_SPARC_INSN_FPU;"
                   1634:            echo "  tme_sparc_fpu_${insn}(ic);"
                   1635:            echo "  TME_SPARC_INSN_OK;"
                   1636:            echo "}"
                   1637:        fi
                   1638: 
                   1639:     done
                   1640: 
1.1.1.2 ! root     1641:     # the slow atomic function:
        !          1642:     #
        !          1643:     if $header; then
        !          1644:        echo "void tme_sparc${arch}_atomic _TME_P((struct tme_sparc *, struct tme_sparc_ls *));"
        !          1645:     else
        !          1646:        echo ""
        !          1647:        echo "/* this does a slow atomic operation: */"
        !          1648:        echo "void"
        !          1649:        echo "tme_sparc${arch}_atomic(struct tme_sparc *ic, struct tme_sparc_ls *ls)"
        !          1650:        echo "{"
        !          1651:        echo "  tme_uint32_t endian_little;"
        !          1652:        echo "  tme_uint32_t insn;"
        !          1653:        if test ${arch} = 64; then
        !          1654:            echo "  tme_uint${arch}_t value${arch};"
        !          1655:            echo "  tme_uint${arch}_t value_swap${arch};"
        !          1656:            echo "  unsigned int reg_rs2;"
        !          1657:        fi
        !          1658:        echo "  tme_uint32_t value32;"
        !          1659:        echo "  tme_uint32_t value_swap32;"
        !          1660:        echo "  tme_uint32_t size;"
        !          1661:        echo ""
        !          1662:        echo "  /* if this is the beginning of the operation: */"
        !          1663:        echo "  if (ls->tme_sparc_ls_state == 0) {"
        !          1664:        echo ""
        !          1665:        echo "    /* start the load part of the operation: */"
        !          1666:        echo "    ls->tme_sparc_ls_state = ls->tme_sparc_ls_size;"
        !          1667:        echo "    assert (ls->tme_sparc_ls_state != 0"
        !          1668:        echo "            && (ls->tme_sparc_ls_state & TME_BIT(7)) == 0);"
        !          1669:        echo ""
        !          1670:        echo "    /* the load must start at the beginning of the buffer: */"
        !          1671:        echo "    assert (ls->tme_sparc_ls_buffer_offset == 0);"
        !          1672:        echo "  }"
        !          1673:        echo ""
        !          1674:        echo "  /* if this is the load part of the operation: */"
        !          1675:        echo "  if ((ls->tme_sparc_ls_state & TME_BIT(7)) == 0) {"
        !          1676:        echo ""
        !          1677:        echo "    /* do one slow load cycle: */"
        !          1678:        echo "    tme_sparc${arch}_load(ic, ls);"
        !          1679:        echo ""
        !          1680:        echo "    /* if the slow load cycle did not load all of the data: */"
        !          1681:        echo "    if (__tme_predict_false(ls->tme_sparc_ls_size != 0)) {"
        !          1682:        echo "      return;"
        !          1683:        echo "    }"
        !          1684:        echo ""
        !          1685:        echo "    /* get the byte order of this transfer: */"
        !          1686:        if test ${arch} = 32; then
        !          1687:            echo "    endian_little = FALSE;"
        !          1688:        else
        !          1689:            echo "    endian_little = ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_ENDIAN_LITTLE;"
        !          1690:        fi
        !          1691:        echo ""
        !          1692:        echo "    /* dispatch on the op3 of the instruction: */"
        !          1693:        echo "    insn = TME_SPARC_INSN;"
        !          1694:        echo "    switch ((insn >> 19) & 0x3f) {"
        !          1695:        if test ${arch} = 64; then
        !          1696:            for size in 32 64; do
        !          1697:                echo ""
        !          1698:                if test ${size} = 32; then
        !          1699:                    echo "    case 0x3c: /* casa */"
        !          1700:                else
        !          1701:                    echo "    case 0x3e: /* casxa */"
        !          1702:                fi
        !          1703:                echo ""
        !          1704:                echo "      /* finish the load part of the compare and swap: */"
        !          1705:                echo "      assert (ls->tme_sparc_ls_state == sizeof(tme_uint${size}_t));"
        !          1706:                echo "      value${size} = ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer${size}s[0];"
        !          1707:                echo "      value_swap${size} = *ls->tme_sparc_ls_rd64;"
        !          1708:                echo "      if (endian_little) {"
        !          1709:                echo "        value${size} = tme_letoh_u${size}(value${size});"
        !          1710:                echo "        value_swap${size} = tme_htole_u${size}(value_swap${size});"
        !          1711:                echo "      }"
        !          1712:                echo "      else {"
        !          1713:                echo "        value${size} = tme_betoh_u${size}(value${size});"
        !          1714:                echo "        value_swap${size} = tme_htobe_u${size}(value_swap${size});"
        !          1715:                echo "      }"
        !          1716:                echo "      *ls->tme_sparc_ls_rd64 = value${size};"
        !          1717:                echo ""
        !          1718:                echo "      /* if the comparison fails: */"
        !          1719:                echo "      reg_rs2 = TME_FIELD_MASK_EXTRACTU(insn, TME_SPARC_FORMAT3_MASK_RS2);"
        !          1720:                echo "      TME_SPARC_REG_INDEX(ic, reg_rs2);"
        !          1721:                echo "      if (value${size} != (tme_uint${size}_t) ic->tme_sparc_ireg_uint${arch}(reg_rs2)) {"
        !          1722:                echo "        return;"
        !          1723:                echo "      }"
        !          1724:                echo ""
        !          1725:                echo "      /* start the store part of the compare and swap: */"
        !          1726:                echo "      ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer${size}s[0] = value_swap${size};"
        !          1727:                echo "      break;"
        !          1728:            done
        !          1729:        fi
        !          1730:        echo ""
        !          1731:        echo "    case 0x0d: /* ldstub */"
        !          1732:        echo "    case 0x1d: /* ldstuba */"
        !          1733:        echo ""
        !          1734:        echo "      /* finish the load part of the ldstub: */"
        !          1735:        echo "      assert (ls->tme_sparc_ls_state == sizeof(tme_uint8_t));"
        !          1736:        echo "      *ls->tme_sparc_ls_rd${arch} = ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer8s[0];"
        !          1737:        echo ""
        !          1738:        echo "      /* start the store part of the ldstub: */"
        !          1739:        echo "      ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer8s[0] = 0xff;"
        !          1740:        echo "      break;"
        !          1741:        echo ""
        !          1742:        echo "    /* otherwise, this must be swap: */"
        !          1743:        echo "    default:"
        !          1744:        echo "      assert (((insn >> 19) & 0x2f) == 0x0f /* swap, swapa */);"
        !          1745:        echo ""
        !          1746:        echo "      /* finish the load part of the swap: */"
        !          1747:        echo "      assert (ls->tme_sparc_ls_state == sizeof(tme_uint32_t));"
        !          1748:        echo "      value32 = ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer32s[0];"
        !          1749:        echo "      value_swap32 = *ls->tme_sparc_ls_rd${arch};"
        !          1750:        echo "      if (endian_little) {"
        !          1751:        echo "        value32 = tme_letoh_u32(value32);"
        !          1752:        echo "        value_swap32 = tme_htole_u32(value32);"
        !          1753:        echo "      }"
        !          1754:        echo "      else {"
        !          1755:        echo "        value32 = tme_betoh_u32(value32);"
        !          1756:        echo "        value_swap32 = tme_htobe_u32(value32);"
        !          1757:        echo "      }"
        !          1758:        echo "      *ls->tme_sparc_ls_rd${arch} = value32;"
        !          1759:        echo ""
        !          1760:        echo "      /* start the store part of the swap: */"
        !          1761:        echo "      ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer32s[0] = value_swap32;"
        !          1762:        echo "      break;"
        !          1763:        echo "    }"
        !          1764:        echo ""
        !          1765:        echo "    /* start the store part of the operation: */"
        !          1766:        echo "    size = ls->tme_sparc_ls_state;"
        !          1767:        echo "    ls->tme_sparc_ls_address${arch} -= size;"
        !          1768:        echo "    ls->tme_sparc_ls_size = size;"
        !          1769:        echo "    ls->tme_sparc_ls_buffer_offset = 0;"
        !          1770:        echo "    ls->tme_sparc_ls_state = size | TME_BIT(7);"
        !          1771:        echo "  }"
        !          1772:        echo ""
        !          1773:        echo "  /* this is the store part of the operation: */"
        !          1774:        echo ""
        !          1775:        echo "  /* do one slow store cycle: */"
        !          1776:        echo "  tme_sparc${arch}_store(ic, ls);"
        !          1777:        echo ""
        !          1778:        echo "  /* if the slow store cycle did not store all of the data: */"
        !          1779:        echo "  if (__tme_predict_false(ls->tme_sparc_ls_size != 0)) {"
        !          1780:        echo "    return;"
        !          1781:        echo "  }"
        !          1782:        echo "}"
        !          1783:     fi
        !          1784: 
1.1       root     1785:     # the slow load and store functions:
                   1786:     #
                   1787:     for slow in load store; do
                   1788: 
                   1789:        if test ${slow} = load; then
                   1790:            cycle="read"
                   1791:            capcycle="READ"
                   1792:        else
                   1793:            cycle="write"
                   1794:            capcycle="WRITE"
1.1.1.2 ! root     1795:        fi
        !          1796:        if $header; then
        !          1797:            echo "void tme_sparc${arch}_${slow} _TME_P((struct tme_sparc *, struct tme_sparc_ls *));"
        !          1798:            continue
1.1       root     1799:        fi
                   1800: 
                   1801:        echo ""
1.1.1.2 ! root     1802:        echo "/* this does one slow ${slow} cycle: */"
        !          1803:        echo "void"
1.1       root     1804:        echo "tme_sparc${arch}_${slow}(struct tme_sparc *ic, "
1.1.1.2 ! root     1805:        echo "                  struct tme_sparc_ls *ls)"
1.1       root     1806:        echo "{"
                   1807: 
                   1808:        # our locals:
                   1809:        #
1.1.1.2 ! root     1810:        echo "  struct tme_sparc_tlb *tlb;"
        !          1811:        echo "  tme_uint${arch}_t address;"
        !          1812:        echo "  unsigned int cycle_size;"
1.1       root     1813:        echo "  tme_bus_addr_t physical_address;"
                   1814:        echo "  int shift;"
                   1815:        echo "  int err;"
1.1.1.2 ! root     1816: 
        !          1817:        echo ""
        !          1818:        echo "  /* get the TLB entry: */"
        !          1819:        echo "  tlb = ls->tme_sparc_ls_tlb;"
        !          1820:        echo ""
        !          1821:        echo "  /* the TLB entry must be busy and valid: */"
        !          1822:        echo "  assert (tme_bus_tlb_is_valid(&tlb->tme_sparc_tlb_bus_tlb));"
        !          1823:        echo ""
        !          1824:        echo "  /* start the bus cycle structure: */"
        !          1825:        echo "  ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_type = TME_BUS_CYCLE_${capcycle};"
        !          1826:        echo ""
        !          1827:        echo "  /* get the buffer: */"
        !          1828:        echo "  ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_buffer = &ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer8s[ls->tme_sparc_ls_buffer_offset];"
        !          1829:        echo "  ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_buffer_increment = 1;"
        !          1830:        echo ""
        !          1831:        echo "  /* get the current address: */"
        !          1832:        echo "  address = ls->tme_sparc_ls_address${arch};"
        !          1833:        echo "  ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_address = address;"
        !          1834:        echo ""
        !          1835:        echo "  /* start the cycle size: */"
        !          1836:        echo "  cycle_size = ls->tme_sparc_ls_size;"
        !          1837:        echo "  assert (cycle_size > 0);"
        !          1838:        echo "  cycle_size--;"
        !          1839:        echo "  cycle_size = TME_MIN(cycle_size, (((tme_bus_addr${arch}_t) tlb->tme_sparc_tlb_addr_last) - address)) + 1;"
        !          1840:        echo ""
        !          1841:        echo "  /* if this TLB entry allows fast ${cycle}s: */"
        !          1842:        echo "  if (__tme_predict_true(tlb->tme_sparc_tlb_emulator_off_${cycle} != TME_EMULATOR_OFF_UNDEF)) {"
        !          1843:        echo ""
        !          1844:        echo "    /* do a ${cycle}: */"
        !          1845:        echo "    ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_size = cycle_size;"
        !          1846:        echo "    tme_memory_bus_${cycle}_buffer((tlb->tme_sparc_tlb_emulator_off_${cycle} + (tme_uint${arch}_t) ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_address),"
        !          1847:        echo "                                  ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_buffer,"
        !          1848:        echo "                                  ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_size,"
        !          1849:        echo "                                  tlb->tme_sparc_tlb_bus_rwlock,"
        !          1850:        echo "                                  sizeof(tme_uint8_t),"
        !          1851:        echo "                                  sizeof(tme_uint${arch}_t));"
        !          1852:        echo "  }"
        !          1853:        echo ""
        !          1854:        echo "  /* otherwise, this TLB entry does not allow fast ${cycle}s: */"
        !          1855:        echo "  else {"
        !          1856:        echo ""
        !          1857:        echo "    /* finish the cycle size: */"
        !          1858:        echo "    cycle_size = TME_MIN(cycle_size, 1 + ((~ (unsigned int) address) % sizeof(tme_uint${arch}_t)));"
        !          1859:        echo "    ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_size = cycle_size;"
        !          1860:        echo ""
        !          1861:        echo "    /* form the physical address for the bus cycle handler: */"
        !          1862:        echo "    physical_address = ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_address;"
        !          1863:        echo "    physical_address += tlb->tme_sparc_tlb_addr_offset;"
        !          1864:        echo "    shift = tlb->tme_sparc_tlb_addr_shift;"
        !          1865:        echo "    if (shift < 0) {"
        !          1866:        echo "      physical_address <<= (0 - shift);"
        !          1867:        echo "    }"
        !          1868:        echo "    else if (shift > 0) {"
        !          1869:        echo "      physical_address >>= shift;"
        !          1870:        echo "    }"
        !          1871:        echo "    ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_address = physical_address;"
        !          1872:        echo ""
        !          1873:        echo "    /* finish the bus cycle structure: */"
        !          1874:        echo "    (*ic->_tme_sparc_ls_bus_cycle)(ic, ls);"
        !          1875: 
        !          1876:        echo "    tme_sparc_log(ic, 10000, TME_OK,"
        !          1877:        echo "                 (TME_SPARC_LOG_HANDLE(ic),"
        !          1878:        echo "                  _(\"cycle-${slow}%u\t0x%0"`expr ${arch} / 4`"\" TME_PRIx${arch}),"
        !          1879:        echo "                  (unsigned int) (ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_size * 8),"
        !          1880:        echo "                  (tme_bus_addr${arch}_t) ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_address));"
        !          1881: 
        !          1882:        echo ""
        !          1883:        echo "    /* callout the bus cycle: */"
        !          1884:        echo "    tme_sparc_tlb_unbusy(tlb);"
        !          1885:        echo "    tme_sparc_callout_unlock(ic);"
        !          1886:        echo "    err = (*tlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_cycle)"
        !          1887:        echo "           (tlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_cycle_private,"
        !          1888:        echo "            &ls->tme_sparc_ls_bus_cycle);"
        !          1889:        echo "    tme_sparc_callout_relock(ic);"
        !          1890:        echo "    tme_sparc_tlb_busy(tlb);"
        !          1891:        echo ""
        !          1892:        echo "    /* the TLB entry can't have been invalidated before the ${slow}: */"
        !          1893:        echo "    assert (err != EBADF);"
        !          1894:        echo ""
        !          1895:        echo "    /* if the bus cycle didn't complete normally: */"
        !          1896:        echo "    if (err != TME_OK) {"
        !          1897:        echo ""
        !          1898:        echo "      /* if a real bus fault may have happened, instead of"
        !          1899:        echo "         some synchronous event: */"
        !          1900:        echo "      if (err != TME_BUS_CYCLE_SYNCHRONOUS_EVENT) {"
        !          1901:        echo ""
        !          1902:        echo "        /* call the bus fault handlers: */"
        !          1903:        echo "        err = tme_bus_tlb_fault(&tlb->tme_sparc_tlb_bus_tlb, &ls->tme_sparc_ls_bus_cycle, err);"
        !          1904:        echo "      }"
        !          1905:        echo ""
        !          1906:        echo "      /* if some synchronous event has happened: */"
        !          1907:        echo "      if (err == TME_BUS_CYCLE_SYNCHRONOUS_EVENT) {"
        !          1908:        echo ""
        !          1909:        echo "        /* after the currently executing instruction finishes, check"
        !          1910:        echo "           for external resets, halts, or interrupts: */"
        !          1911:        echo "        ic->_tme_sparc_instruction_burst_remaining = 0;"
        !          1912:        echo "        ic->_tme_sparc_instruction_burst_other = TRUE;"
        !          1913:        echo "      }"
        !          1914:        echo ""
        !          1915:        echo "      /* otherwise, if no real bus fault happened: */"
        !          1916:        echo "      else if (err == TME_OK) {"
        !          1917:        echo ""
        !          1918:        echo "        /* nothing to do */"
        !          1919:        echo "      }"
        !          1920:        echo ""
        !          1921:        echo "      /* otherwise, a real bus fault happened: */"
        !          1922:        echo "      else {"
        !          1923:        echo "        (*ic->_tme_sparc_ls_bus_fault)(ic, ls, err);"
        !          1924:        echo "        return;"
        !          1925:        echo "      }"
        !          1926:        echo "    }"
        !          1927:        echo "  }"
        !          1928: 
        !          1929:        echo ""
        !          1930:        echo "  /* some data must have been transferred: */"
        !          1931:        echo "  assert (ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_size > 0);"
        !          1932:        
1.1       root     1933:        if test ${slow} = store; then
1.1.1.2 ! root     1934:            echo ""
        !          1935:            echo "  /* if this was an atomic operation: */"
        !          1936:            echo "  if (__tme_predict_false(ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_ATOMIC)) {"
        !          1937:            echo ""
        !          1938:            echo "    /* we do not support atomic operations in TLB entries that"
        !          1939:            echo "       do not support both fast reads and fast writes.  assuming"
        !          1940:            echo "       that all atomic operations are to regular memory, we"
        !          1941:            echo "       should always get fast read and fast write TLBs.  when"
        !          1942:            echo "       we do not, it should only be because the memory has been"
        !          1943:            echo "       made read-only in the MMU.  the write above was supposed"
        !          1944:            echo "       to cause a fault (with the instruction rerun later with"
        !          1945:            echo "       a fast read and fast write TLB entry), but instead it"
        !          1946:            echo "       succeeded and transferred some data.  we have modified"
        !          1947:            echo "       memory and cannot recover: */"
        !          1948:            echo "    abort();"
        !          1949:            echo "  }"
1.1       root     1950:        fi
                   1951: 
                   1952:        echo ""
1.1.1.2 ! root     1953:        echo "  /* update: */"
        !          1954:        echo "  cycle_size = ls->tme_sparc_ls_bus_cycle.tme_bus_cycle_size;"
        !          1955:        echo "  ls->tme_sparc_ls_address${arch} += cycle_size;"
        !          1956:        echo "  ls->tme_sparc_ls_buffer_offset += cycle_size;"
        !          1957:        echo "  ls->tme_sparc_ls_size -= cycle_size;"
        !          1958:        echo "}"
        !          1959:     done
1.1       root     1960: 
1.1.1.2 ! root     1961:     # the load/store function:
        !          1962:     #
        !          1963:     if $header; then
        !          1964:        echo "tme_shared tme_uint8_t *tme_sparc${arch}_ls _TME_P((struct tme_sparc *, tme_uint${arch}_t, tme_uint${arch}_t *, tme_uint32_t));"
        !          1965:     else
1.1       root     1966: 
                   1967:        echo ""
1.1.1.2 ! root     1968:        echo "/* this does a slow load or store: */"
        !          1969:        echo "tme_shared tme_uint8_t *"
        !          1970:        echo "tme_sparc${arch}_ls(struct tme_sparc *ic,"
        !          1971:        echo "               tme_uint${arch}_t const address_first,"
        !          1972:        echo "               tme_uint${arch}_t *_rd,"
        !          1973:        echo "               tme_uint32_t lsinfo)"
        !          1974:        echo "{"
        !          1975:        echo "  struct tme_sparc_ls ls;"
        !          1976:        echo "  tme_uint32_t size;"
        !          1977:        echo "  tme_uint32_t asi;"
        !          1978:        echo "  tme_uint32_t asi_mask_flags;"
        !          1979:        echo "  tme_uint32_t asi_mask;"
        !          1980:        echo "  tme_bus_context_t context;"
        !          1981:        echo "  tme_uint32_t tlb_hash;"
        !          1982:        echo "  unsigned long tlb_i;"
        !          1983:        echo "  unsigned long handler_i;"
        !          1984:        echo "  struct tme_sparc_tlb *tlb;"
        !          1985:        echo "  unsigned int cycle_type;"
        !          1986:        echo "  tme_uint${arch}_t address;"
        !          1987:        echo "  void (*address_map) _TME_P((struct tme_sparc *, struct tme_sparc_ls *));"
        !          1988:        echo "  tme_bus_addr_t address_bus;"
        !          1989:        echo "  int rc;"
        !          1990:        echo "  const tme_shared tme_uint8_t *emulator_off;"
        !          1991:        echo "  unsigned int buffer_offset;"
        !          1992:        echo "  tme_uint${arch}_t value;"
        !          1993:        echo "  tme_uint32_t value32;"
        !          1994:        echo ""
        !          1995:        echo "  /* we must not be replaying instructions: */"
        !          1996:        echo "  assert (tme_sparc_recode_verify_replay_last_pc(ic) == 0);"
        !          1997:        echo ""
        !          1998:        echo "  /* initialize the pointer to the rd register: */"
        !          1999:        echo "  ls.tme_sparc_ls_rd${arch} = _rd;"
        !          2000:        echo ""
        !          2001:        echo "#ifndef NDEBUG"
        !          2002:        echo ""
        !          2003:        echo "  /* initialize the cycle function: */"
        !          2004:        echo "  ls.tme_sparc_ls_cycle = NULL;"
        !          2005:        echo ""
        !          2006:        echo "  /* initialize the TLB entry pointer: */"
        !          2007:        echo "  ls.tme_sparc_ls_tlb = NULL;"
        !          2008:        echo ""
        !          2009:        echo "#endif /* NDEBUG */"
        !          2010:        echo ""
        !          2011:        echo "  /* initialize the faults: */"
        !          2012:        echo "  ls.tme_sparc_ls_faults = TME_SPARC_LS_FAULT_NONE;"
        !          2013:        echo ""
        !          2014:        echo "  /* initialize the address: */"
        !          2015:        echo "  ls.tme_sparc_ls_address${arch} = address_first;"
        !          2016:        echo ""
        !          2017:        echo "  /* initialize the size: */"
        !          2018:        echo "  size = TME_SPARC_LSINFO_WHICH_SIZE(lsinfo);"
        !          2019:        echo "  ls.tme_sparc_ls_size = size;"
        !          2020:        echo ""
        !          2021:        echo "  /* initialize the info: */"
        !          2022:        echo "  ls.tme_sparc_ls_lsinfo = lsinfo;"
        !          2023:        echo ""
1.1       root     2024:        echo "  /* if the address is not aligned: */"
1.1.1.2 ! root     2025:        echo "  if (__tme_predict_false(((size - 1) & (tme_uint32_t) address_first) != 0)) {"
        !          2026:        echo "    ls.tme_sparc_ls_faults |= TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED;"
1.1       root     2027:        echo "  }"
                   2028:        echo ""
1.1.1.2 ! root     2029:        echo "  /* otherwise, the address is aligned: */"
        !          2030:        echo "  else {"
1.1       root     2031:        echo ""
1.1.1.2 ! root     2032:        echo "    /* the transfer must not cross a 32-bit boundary: */"
        !          2033:        echo "    assert ((size - 1) <= (tme_uint32_t) ~address_first);"
1.1       root     2034:        echo "  }"
1.1.1.2 ! root     2035:        echo ""
        !          2036:        echo "  /* initialize the address map: */"
        !          2037:        echo "  ls.tme_sparc_ls_address_map = ic->_tme_sparc_ls_address_map;"
        !          2038:        echo ""
        !          2039:        echo "  /* if this is a ldd, ldda, std, or stda, or an instruction"
        !          2040:        echo "     that loads or stores in the same way: */"
        !          2041:        echo "  if (lsinfo & TME_SPARC_LSINFO_LDD_STD) {"
        !          2042:        echo ""
        !          2043:        echo "    /* if the rd register is odd: */"
        !          2044:        echo "    /* NB: we don't check the rd field in the instruction,"
        !          2045:        echo "       because the register number there might be encoded"
        !          2046:        echo "       in some way, or the architecture might ignore bit"
        !          2047:        echo "       zero in the rd field (for example, the sparc32 lddf)."
        !          2048:        echo "       instead, we test the rd register pointer: */"
        !          2049:        echo "    if (__tme_predict_false((ls.tme_sparc_ls_rd${arch}"
        !          2050:        echo "                             - ic->tme_sparc_ic.tme_ic_iregs.tme_ic_iregs_uint${arch}s)"
        !          2051:        echo "                            % 2)) {"
        !          2052:        echo "      ls.tme_sparc_ls_faults |= TME_SPARC_LS_FAULT_LDD_STD_RD_ODD;"
        !          2053:        echo "    }"
1.1       root     2054:        echo "  }"
1.1.1.2 ! root     2055:        
        !          2056:        echo ""
        !          2057:        echo "  /* if the ASI has been specified: */"
        !          2058:        echo "  if (lsinfo & TME_SPARC_LSINFO_A) {"
        !          2059:        echo ""
        !          2060:        echo "    /* get the ASI: */"
        !          2061:        echo "    asi = TME_SPARC_LSINFO_WHICH_ASI(lsinfo);"
        !          2062:        echo ""
        !          2063:        echo "    /* get the flags for this ASI: */"
        !          2064:        echo "    asi_mask_flags = ic->tme_sparc_asis[asi].tme_sparc_asi_mask_flags;"
        !          2065:        echo ""
        !          2066:        if test ${arch} = 32; then
        !          2067:            echo "    /* make the ASI mask: */"
        !          2068:            echo "    if (asi_mask_flags & TME_SPARC32_ASI_MASK_FLAG_SPECIAL) {"
        !          2069:            echo "      asi_mask"
        !          2070:            echo "        = TME_SPARC_ASI_MASK_SPECIAL(asi, TRUE);"
        !          2071:            echo "    }"
        !          2072:            echo "    else {"
        !          2073:            echo "      asi_mask = TME_SPARC32_ASI_MASK(asi, asi);"
        !          2074:            echo "    }"
        !          2075:        elif test ${arch} = 64; then
        !          2076:            echo "    /* if this is a nonprivileged access: */"
        !          2077:            echo "    if (!TME_SPARC_PRIV(ic)) {"
        !          2078:            echo ""
        !          2079:            echo "      /* if this is a restricted ASI: */"
        !          2080:            echo "      if (__tme_predict_false((asi & TME_SPARC64_ASI_FLAG_UNRESTRICTED) == 0)) {"
        !          2081:            echo "        ls.tme_sparc_ls_faults |= TME_SPARC64_LS_FAULT_PRIVILEGED_ASI;"
        !          2082:            echo "      }"
1.1       root     2083:            echo ""
1.1.1.2 ! root     2084:            echo "      /* force a nonprivileged access with the ASI: */"
        !          2085:            echo "      asi_mask_flags |= TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER;"
        !          2086:            echo "    }"
        !          2087:            echo ""
        !          2088:            echo "    /* make the ASI mask: */"
        !          2089:            echo "    if (asi_mask_flags & TME_SPARC64_ASI_MASK_FLAG_SPECIAL) {"
        !          2090:            echo "      asi_mask"
        !          2091:            echo "        = (asi_mask_flags"
        !          2092:            echo "           + TME_SPARC_ASI_MASK_SPECIAL(asi,"
        !          2093:            echo "                                        (asi_mask_flags & TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER) == 0));"
        !          2094:            echo "    }"
        !          2095:            echo "    else {"
        !          2096:            echo "      asi_mask = TME_SPARC64_ASI_MASK(asi, asi_mask_flags);"
        !          2097:            echo "    }"
        !          2098:        fi
        !          2099:        echo "    ls.tme_sparc_ls_asi_mask = asi_mask;"
        !          2100:        if test ${arch} = 64; then
        !          2101:            echo ""
        !          2102:            echo "    /* if this is a no-fault ASI with a non-load instruction: */"
        !          2103:            echo "    if (asi_mask & TME_SPARC64_ASI_FLAG_NO_FAULT) {"
        !          2104:            echo "      if (__tme_predict_false(lsinfo & (TME_SPARC_LSINFO_OP_ST | TME_SPARC_LSINFO_OP_ATOMIC))) {"
        !          2105:            echo "        ls.tme_sparc_ls_faults |= TME_SPARC64_LS_FAULT_NO_FAULT_NON_LOAD;"
        !          2106:            echo "      }"
        !          2107:            echo "    }"
1.1       root     2108:        fi
                   2109:        echo ""
1.1.1.2 ! root     2110:        echo "    /* get the context for the alternate address space: */"
        !          2111:        if test ${arch} = 32; then
        !          2112:            echo "    context = ic->tme_sparc_memory_context_default;"
        !          2113:        elif test ${arch} = 64; then
        !          2114:            echo "    context = ic->tme_sparc_memory_context_primary;"
        !          2115:            echo "    if (asi_mask & TME_SPARC64_ASI_FLAG_SECONDARY) {"
        !          2116:            echo "      context = ic->tme_sparc_memory_context_secondary;"
        !          2117:            echo "    }"
        !          2118:            echo "    if (__tme_predict_false(asi_mask & TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS)) {"
        !          2119:            echo "      if (TME_SPARC_MEMORY_FLAGS(ic) & TME_SPARC_MEMORY_FLAG_HAS_NUCLEUS) {"
        !          2120:            echo "        context = 0;"
        !          2121:            echo "      }"
        !          2122:            echo "    }"
        !          2123:        fi
        !          2124:        echo "    ls.tme_sparc_ls_context = context;"
1.1       root     2125:        echo ""
1.1.1.2 ! root     2126:        echo "    /* get the default TLB entry index: */"
        !          2127:        echo "    tlb_hash = TME_SPARC_TLB_HASH(ic, context, address_first);"
        !          2128:        echo "    if (lsinfo & TME_SPARC_LSINFO_OP_FETCH) {"
        !          2129:        echo "      tlb_i = TME_SPARC_ITLB_ENTRY(ic, tlb_hash);"
        !          2130:        echo "    }"
        !          2131:        echo "    else {"
        !          2132:        echo "      tlb_i = TME_SPARC_DTLB_ENTRY(ic, tlb_hash);"
        !          2133:        echo "    }"
        !          2134:        echo "    ls.tme_sparc_ls_tlb_i = tlb_i;"
1.1       root     2135:        echo ""
1.1.1.2 ! root     2136:        echo "    /* call any special handler for this ASI: */"
        !          2137:        echo "    handler_i = ic->tme_sparc_asis[TME_SPARC_ASI_MASK_WHICH(asi_mask)].tme_sparc_asi_handler;"
        !          2138:        echo "    if (__tme_predict_false(handler_i != 0)) {"
        !          2139:        echo "      (*ic->_tme_sparc_ls_asi_handlers[handler_i])(ic, &ls);"
1.1       root     2140:        echo "    }"
1.1.1.2 ! root     2141:        echo ""
        !          2142:        echo "    /* get the final TLB entry index: */"
        !          2143:        echo "    tlb_i = ls.tme_sparc_ls_tlb_i;"
        !          2144:        echo "  }"
1.1       root     2145: 
                   2146:        echo ""
1.1.1.2 ! root     2147:        echo "  /* otherwise, the ASI has not been specified: */"
        !          2148:        echo "  else {"
1.1       root     2149:        echo ""
1.1.1.2 ! root     2150:        echo "    /* get the ASI mask: */"
        !          2151:        echo "    asi_mask = ic->tme_sparc_asi_mask_data;"
        !          2152:        echo ""
        !          2153:        echo "    /* add in any ASI mask flags from the instruction: */"
        !          2154:        if test ${arch} = 64; then
        !          2155:            echo "    /* NB: initially, TME_SPARC64_ASI_FLAG_NO_FAULT is the"
        !          2156:            echo "       only flag allowed, and only the flush instruction"
        !          2157:            echo "       can use it: */"
1.1       root     2158:        fi
1.1.1.2 ! root     2159:        echo "    assert (TME_SPARC_LSINFO_WHICH_ASI_FLAGS(lsinfo) == 0"
        !          2160:        if test ${arch} = 64; then
        !          2161:            echo "            || (TME_SPARC_LSINFO_WHICH_ASI_FLAGS(lsinfo) == TME_SPARC64_ASI_FLAG_NO_FAULT"
        !          2162:            echo "                && ((ic->_tme_sparc_insn >> 19) & 0x3f) == 0x3b)"
        !          2163:        fi
        !          2164:        echo "            );"
        !          2165:        echo "    asi_mask |= TME_SPARC_LSINFO_WHICH_ASI_FLAGS(lsinfo);"
1.1       root     2166:        echo ""
1.1.1.2 ! root     2167:        echo "    /* set the ASI mask: */"
        !          2168:        echo "    ls.tme_sparc_ls_asi_mask = asi_mask;"
        !          2169:        echo ""
        !          2170:        echo "    /* get the context: */"
        !          2171:        echo "    context = ic->tme_sparc_memory_context_default;"
        !          2172:        echo "    ls.tme_sparc_ls_context = context;"
        !          2173:        echo ""
        !          2174:        echo "    /* this must not be a fetch: */"
        !          2175:        echo "    assert ((lsinfo & TME_SPARC_LSINFO_OP_FETCH) == 0);"
        !          2176:        echo ""
        !          2177:        echo "    /* get the TLB entry index: */"
        !          2178:        echo "    tlb_hash = TME_SPARC_TLB_HASH(ic, context, address_first);"
        !          2179:        echo "    tlb_i = TME_SPARC_DTLB_ENTRY(ic, tlb_hash);"
        !          2180:        echo "    ls.tme_sparc_ls_tlb_i = tlb_i;"
        !          2181:        echo "  }"
        !          2182: 
        !          2183:        echo ""
        !          2184:        echo "  /* get the TLB entry pointer: */"
        !          2185:        echo "  tlb = &ic->tme_sparc_tlbs[tlb_i];"
        !          2186:        echo "  ls.tme_sparc_ls_tlb = tlb;"
        !          2187: 
        !          2188:        echo ""
        !          2189:        echo "  /* get the cycle type: */"
        !          2190:        echo "  /* NB: we deliberately set this once, now, since the lsinfo"
        !          2191:        echo "     may change once we start transferring: */"
        !          2192:        echo "  cycle_type"
        !          2193:        echo "    = ((lsinfo"
        !          2194:        echo "        & (TME_SPARC_LSINFO_OP_ST"
        !          2195:        echo "           | TME_SPARC_LSINFO_OP_ATOMIC))"
        !          2196:        echo "       ? TME_BUS_CYCLE_WRITE"
        !          2197:        echo "       : TME_BUS_CYCLE_READ);"
        !          2198: 
        !          2199:        echo ""
        !          2200:        echo "  /* loop until the transfer is complete: */"
        !          2201:        echo "  for (;;) {"
        !          2202: 
        !          2203:        echo ""
        !          2204:        echo "    /* if we have faulted: */"
        !          2205:        echo "    if (__tme_predict_false(ls.tme_sparc_ls_faults != TME_SPARC_LS_FAULT_NONE)) {"
        !          2206:        echo ""
        !          2207:        echo "      /* unbusy this TLB, since the trap function may not return: */"
        !          2208:        echo "      tme_bus_tlb_unbusy(&tlb->tme_sparc_tlb_bus_tlb);"
        !          2209:        echo ""
        !          2210:        echo "      /* call the trap function, which will not return if it traps: */"
        !          2211:        echo "      (*ic->_tme_sparc_ls_trap)(ic, &ls);"
        !          2212:        echo ""
        !          2213:        echo "      /* rebusy this TLB: */"
        !          2214:        echo "      tme_bus_tlb_busy(&tlb->tme_sparc_tlb_bus_tlb);"
1.1       root     2215:        echo ""
1.1.1.2 ! root     2216:        echo "      /* since the trap function returned, it must have cleared the fault: */"
        !          2217:        echo "      assert (ls.tme_sparc_ls_faults == TME_SPARC_LS_FAULT_NONE);"
1.1       root     2218:        echo "    }"
1.1.1.2 ! root     2219: 
1.1       root     2220:        echo ""
1.1.1.2 ! root     2221:        echo "    /* if the transfer is complete, stop now: */"
        !          2222:        echo "    if (__tme_predict_false(ls.tme_sparc_ls_size == 0)) {"
        !          2223:        echo "      break;"
        !          2224:        echo "    }"
        !          2225: 
        !          2226:        echo ""
        !          2227:        echo "    /* get the current address: */"
        !          2228:        echo "    address = ls.tme_sparc_ls_address${arch};"
        !          2229: 
        !          2230:        echo ""
        !          2231:        echo "    /* if this TLB entry does not apply or is invalid: */"
        !          2232:        echo "    if ((tlb->tme_sparc_tlb_context != ls.tme_sparc_ls_context"
        !          2233:        echo "         && tlb->tme_sparc_tlb_context <= ic->tme_sparc_memory_context_max)"
        !          2234:        echo "        || address < (tme_bus_addr${arch}_t) tlb->tme_sparc_tlb_addr_first"
        !          2235:        echo "        || address > (tme_bus_addr${arch}_t) tlb->tme_sparc_tlb_addr_last"
        !          2236:        echo "        || !TME_SPARC_TLB_ASI_MASK_OK(tlb, ls.tme_sparc_ls_asi_mask)"
        !          2237:        echo "        || ((tlb->tme_sparc_tlb_cycles_ok & cycle_type) == 0"
        !          2238:        echo "            && (cycle_type == TME_BUS_CYCLE_READ"
        !          2239:        echo "                ? tlb->tme_sparc_tlb_emulator_off_read"
        !          2240:        echo "                : tlb->tme_sparc_tlb_emulator_off_write) == TME_EMULATOR_OFF_UNDEF)"
        !          2241:        echo "        || tme_bus_tlb_is_invalid(&tlb->tme_sparc_tlb_bus_tlb)) {"
        !          2242:        echo ""
        !          2243:        echo "      /* unbusy this TLB entry for filling: */"
        !          2244:        echo "      tme_bus_tlb_unbusy_fill(&tlb->tme_sparc_tlb_bus_tlb);"
        !          2245:        echo ""
        !          2246:        echo "      /* if we haven't mapped this address yet: */"
        !          2247:        echo "      address_map = ls.tme_sparc_ls_address_map;"
        !          2248:        echo "      if (address_map != NULL) {"
        !          2249:        echo "        ls.tme_sparc_ls_address_map = NULL;"
        !          2250:        echo ""
        !          2251:        echo "        /* count this mapping: */"
        !          2252:        echo "        if (ls.tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_FETCH) {"
        !          2253:        echo "          TME_SPARC_STAT(ic, tme_sparc_stats_itlb_map);"
        !          2254:        echo "        }"
        !          2255:        echo "        else {"
        !          2256:        echo "          TME_SPARC_STAT(ic, tme_sparc_stats_dtlb_map);"
        !          2257:        echo "        }"
        !          2258:        echo ""
        !          2259:        echo "        /* initialize the ASI mask and context on this TLB entry: */"
        !          2260:        echo "        /* NB that the ASI mask will likely be updated by either the"
        !          2261:        echo "           address mapping or the TLB fill: */"
        !          2262:        echo "        tlb->tme_sparc_tlb_asi_mask"
        !          2263:        echo "          = (ls.tme_sparc_ls_asi_mask"
        !          2264:        echo "             & ~TME_SPARC_ASI_MASK_FLAGS_AVAIL);"
        !          2265:        echo "        tlb->tme_sparc_tlb_context = ls.tme_sparc_ls_context;"
        !          2266:        echo ""
        !          2267:        echo "        /* NB: if the address mapping traps, we won't get a chance"
        !          2268:        echo "           to finish updating this TLB entry, which is currently in"
        !          2269:        echo "           an inconsistent state - but not necessarily an unusable"
        !          2270:        echo "           state.  poison it to be unusable, including any recode"
        !          2271:        echo "           TLB entry: */"
        !          2272:        echo "        tlb->tme_sparc_tlb_addr_first = 1;"
        !          2273:        echo "        tlb->tme_sparc_tlb_addr_last = 0;"
        !          2274:        echo "#if TME_SPARC_HAVE_RECODE(ic)"
        !          2275:        echo "        if (ls.tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_FETCH) {"
        !          2276:        echo "          tme_sparc${arch}_recode_chain_tlb_update(ic, &ls);"
        !          2277:        echo "        }"
        !          2278:        echo "        else {"
        !          2279:        echo "          tme_sparc${arch}_recode_ls_tlb_update(ic, &ls);"
        !          2280:        echo "        }"
        !          2281:        echo "#endif /* TME_SPARC_HAVE_RECODE(ic) */"
        !          2282:        echo ""
        !          2283:        echo "#ifndef NDEBUG"
        !          2284:        echo ""
        !          2285:        echo "        /* initialize the mapping TLB entry: */"
        !          2286:        echo "        ls.tme_sparc_ls_tlb_map.tme_bus_tlb_addr_first = 0 - (tme_bus_addr_t) 1;"
        !          2287:        echo "        ls.tme_sparc_ls_tlb_map.tme_bus_tlb_addr_last = 0 - (tme_bus_addr_t) 2;"
        !          2288:        echo "        ls.tme_sparc_ls_tlb_map.tme_bus_tlb_cycles_ok = 0;"
        !          2289:        echo "        ls.tme_sparc_ls_tlb_map.tme_bus_tlb_addr_offset = 0 - (tme_bus_addr_t) 1;"
        !          2290:        echo ""
        !          2291:        echo "#endif /* !NDEBUG */"
1.1       root     2292:        echo ""
1.1.1.2 ! root     2293:        echo "        /* map the address: */"
        !          2294:        echo "        (*address_map)(ic, &ls);"
        !          2295:        echo ""
        !          2296:        echo "        /* the address mapping must do any trapping itself: */"
        !          2297:        echo "        assert (ls.tme_sparc_ls_faults == TME_SPARC_LS_FAULT_NONE);"
        !          2298:        echo ""
        !          2299:        echo "        /* if the address mapping completed the transfer: */"
        !          2300:        echo "        if (__tme_predict_false(ls.tme_sparc_ls_size == 0)) {"
        !          2301:        echo ""
        !          2302:        echo "          /* rebusy the TLB entry: */"
        !          2303:        echo "          tme_sparc_tlb_busy(tlb);"
        !          2304:        echo ""
        !          2305:        echo "          /* stop now: */"
        !          2306:        echo "          break;"
        !          2307:        echo "        }"
        !          2308:        echo ""
        !          2309:        echo "        /* the mapping must have actually made a mapping: */"
        !          2310:        echo "        assert (ls.tme_sparc_ls_tlb_map.tme_bus_tlb_addr_first != 0 - (tme_bus_addr_t) 1);"
        !          2311:        echo "        assert (ls.tme_sparc_ls_tlb_map.tme_bus_tlb_addr_last != 0 - (tme_bus_addr_t) 2);"
        !          2312:        echo "        assert (ls.tme_sparc_ls_tlb_map.tme_bus_tlb_cycles_ok != 0);"
        !          2313:        echo "        assert (ls.tme_sparc_ls_tlb_map.tme_bus_tlb_addr_offset != 0 - (tme_bus_addr_t) 1);"
1.1       root     2314:        echo "      }"
1.1.1.2 ! root     2315:        echo ""
        !          2316:        echo "      /* count this fill: */"
        !          2317:        echo "      if (ls.tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_FETCH) {"
        !          2318:        echo "        TME_SPARC_STAT(ic, tme_sparc_stats_itlb_fill);"
1.1       root     2319:        echo "      }"
1.1.1.2 ! root     2320:        echo "      else {"
        !          2321:        echo "        TME_SPARC_STAT(ic, tme_sparc_stats_dtlb_fill);"
        !          2322:        echo "      }"
        !          2323:        echo ""
        !          2324:        echo "      /* get the bus address: */"
        !          2325:        echo "      address_bus = ls.tme_sparc_ls_address${arch} + ls.tme_sparc_ls_tlb_map.tme_bus_tlb_addr_offset;"
1.1       root     2326:        echo ""
1.1.1.2 ! root     2327:        echo "      /* fill the TLB entry: */"
1.1       root     2328:        echo "      tme_sparc_callout_unlock(ic);"
1.1.1.2 ! root     2329:        echo "      rc = (*ic->_tme_sparc_bus_connection->tme_sparc_bus_tlb_fill)"
        !          2330:        echo "        (ic->_tme_sparc_bus_connection,"
        !          2331:        echo "         tlb,"
        !          2332:        echo "         ls.tme_sparc_ls_asi_mask,"
        !          2333:        echo "         address_bus,"
        !          2334:        echo "         cycle_type);"
        !          2335:        echo "      assert (rc == TME_OK);"
1.1       root     2336:        echo "      tme_sparc_callout_relock(ic);"
                   2337:        echo ""
1.1.1.2 ! root     2338:        echo "      /* map the TLB entry: */"
        !          2339:        echo "      tme_bus_tlb_map(&tlb->tme_sparc_tlb_bus_tlb, address_bus,"
        !          2340:        echo "                      &ls.tme_sparc_ls_tlb_map, ls.tme_sparc_ls_address${arch});"
        !          2341:        echo ""
        !          2342:        echo "      /* update any recode TLB entry: */"
        !          2343:        echo "#if TME_SPARC_HAVE_RECODE(ic)"
        !          2344:        echo "      if (ls.tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_OP_FETCH) {"
        !          2345:        echo "        tme_sparc${arch}_recode_chain_tlb_update(ic, &ls);"
        !          2346:        echo "      }"
        !          2347:        echo "      else {"
        !          2348:        echo "        tme_sparc${arch}_recode_ls_tlb_update(ic, &ls);"
        !          2349:        echo "      }"
        !          2350:        echo "#endif /* TME_SPARC_HAVE_RECODE(ic) */"
        !          2351:        echo ""
        !          2352:        echo "      /* rebusy the TLB entry: */"
        !          2353:        echo "      tme_sparc_tlb_busy(tlb);"
        !          2354:        echo ""
        !          2355:        echo "      /* if this TLB entry is already invalid: */"
        !          2356:        echo "      if (tme_bus_tlb_is_invalid(&tlb->tme_sparc_tlb_bus_tlb)) {"
        !          2357:        echo "        continue;"
1.1       root     2358:        echo "      }"
1.1.1.2 ! root     2359:        echo "    }"
        !          2360: 
1.1       root     2361:        echo ""
1.1.1.2 ! root     2362:        echo "    /* this TLB entry must apply: */"
        !          2363:        echo "    assert ((tlb->tme_sparc_tlb_context == ls.tme_sparc_ls_context"
        !          2364:        echo "             || tlb->tme_sparc_tlb_context > ic->tme_sparc_memory_context_max)"
        !          2365:        echo "            && ls.tme_sparc_ls_address${arch} >= (tme_bus_addr${arch}_t) tlb->tme_sparc_tlb_addr_first"
        !          2366:        echo "            && ls.tme_sparc_ls_address${arch} <= (tme_bus_addr${arch}_t) tlb->tme_sparc_tlb_addr_last"
        !          2367:        echo "            && ((tlb->tme_sparc_tlb_cycles_ok & cycle_type)"
        !          2368:        echo "                || (cycle_type == TME_BUS_CYCLE_READ"
        !          2369:        echo "                    ? tlb->tme_sparc_tlb_emulator_off_read"
        !          2370:        echo "                    : tlb->tme_sparc_tlb_emulator_off_write) != TME_EMULATOR_OFF_UNDEF)"
        !          2371:        echo "            && TME_SPARC_TLB_ASI_MASK_OK(tlb, ls.tme_sparc_ls_asi_mask));"
        !          2372: 
        !          2373:        echo ""
        !          2374:        echo "    /* get the current lsinfo: */"
        !          2375:        echo "    lsinfo = ls.tme_sparc_ls_lsinfo;"
        !          2376: 
        !          2377:        echo ""
        !          2378:        echo "    /* if we have to check the TLB: */"
        !          2379:        echo "    if (__tme_predict_true((lsinfo & TME_SPARC_LSINFO_NO_CHECK_TLB) == 0)) {"
        !          2380:        echo ""
        !          2381:        echo "      /* get the ASI mask for this TLB entry: */"
        !          2382:        echo "      asi_mask = tlb->tme_sparc_tlb_asi_mask;"
        !          2383:        if test ${arch} = 64; then
        !          2384:            echo ""
        !          2385:            echo "      /* if this TLB entry is for no-fault accesses only: */"
        !          2386:            echo "      if (__tme_predict_false(asi_mask & TME_SPARC64_ASI_FLAG_NO_FAULT)) {"
        !          2387:            echo ""
        !          2388:            echo "        /* if this access is not using a no-fault ASI: */"
        !          2389:            echo "        if (__tme_predict_false((ls.tme_sparc_ls_asi_mask & TME_SPARC64_ASI_FLAG_NO_FAULT) == 0)) {"
        !          2390:            echo "          ls.tme_sparc_ls_faults |= TME_SPARC64_LS_FAULT_NO_FAULT_FAULT;"
        !          2391:            echo "          continue;"
        !          2392:            echo "        }"
        !          2393:            echo "      }"
        !          2394:            echo ""
        !          2395:            echo "      /* if this TLB entry is for addresses with side effects: */"
        !          2396:            echo "      if (asi_mask & TME_SPARC64_ASI_MASK_FLAG_TLB_SIDE_EFFECTS) {"
        !          2397:            echo ""
        !          2398:            echo "        /* if this access is using a no-fault ASI: */"
        !          2399:            echo "        /* NB: a flush may be implemented as a load with a no-fault ASI: */"
        !          2400:            echo "        if (__tme_predict_false(ls.tme_sparc_ls_asi_mask & TME_SPARC64_ASI_FLAG_NO_FAULT)) {"
        !          2401:            echo "          ls.tme_sparc_ls_faults |= TME_SPARC64_LS_FAULT_SIDE_EFFECTS;"
        !          2402:            echo "          continue;"
        !          2403:            echo "        }"
        !          2404:            echo "      }"
        !          2405:            echo ""
        !          2406:            echo "      /* if this TLB entry is for uncacheable addresses: */"
        !          2407:            echo "      if (asi_mask & TME_SPARC64_ASI_MASK_FLAG_TLB_UNCACHEABLE) {"
        !          2408:            echo ""
        !          2409:            echo "        /* if this is an atomic access: */"
        !          2410:            echo "        if (__tme_predict_false(lsinfo & TME_SPARC_LSINFO_OP_ATOMIC)) {"
        !          2411:            echo "          ls.tme_sparc_ls_faults |= TME_SPARC64_LS_FAULT_UNCACHEABLE;"
        !          2412:            echo "          continue;"
        !          2413:            echo "        }"
        !          2414:            echo "      }"
        !          2415:            echo ""
        !          2416:            echo "      /* see if this is a little-endian instruction: */"
        !          2417:            echo "      lsinfo"
        !          2418:            echo "        = ((lsinfo"
        !          2419:            echo "            & ~TME_SPARC_LSINFO_ENDIAN_LITTLE)"
        !          2420:            echo "           + ((ls.tme_sparc_ls_asi_mask"
        !          2421:            echo "               & TME_SPARC64_ASI_FLAG_LITTLE)"
        !          2422:            echo "#if TME_SPARC_LSINFO_ENDIAN_LITTLE < TME_SPARC64_ASI_FLAG_LITTLE"
        !          2423:            echo "#error \"TME_SPARC_LSINFO_ENDIAN_ values changed\""
        !          2424:            echo "#endif"
        !          2425:            echo "              * (TME_SPARC_LSINFO_ENDIAN_LITTLE"
        !          2426:            echo "                 / TME_SPARC64_ASI_FLAG_LITTLE)));"
        !          2427:            echo ""
        !          2428:            echo "      /* if this TLB entry has its little-endian bit set: */"
        !          2429:            echo "      if (__tme_predict_false(asi_mask & TME_SPARC64_ASI_FLAG_LITTLE)) {"
        !          2430:            echo "        assert (TME_SPARC_MEMORY_FLAGS(ic) & TME_SPARC_MEMORY_FLAG_HAS_INVERT_ENDIAN);"
        !          2431:            echo "        if (TRUE) {"
        !          2432:            echo "          lsinfo ^= TME_SPARC_LSINFO_ENDIAN_LITTLE;"
        !          2433:            echo "        }"
        !          2434:            echo "      }"
        !          2435:        fi
        !          2436:        echo "    }"
        !          2437: 
1.1       root     2438:        echo ""
1.1.1.2 ! root     2439:        echo "    /* if we might not have to call a slow cycle function: */"
        !          2440:        echo "    if (__tme_predict_true((lsinfo & TME_SPARC_LSINFO_SLOW_CYCLES) == 0)) {"
1.1       root     2441:        echo ""
1.1.1.2 ! root     2442:        echo "      /* if this TLB entry allows fast transfer of all of the addresses: */"
        !          2443:        echo "      if (__tme_predict_true(((tme_bus_addr${arch}_t) tlb->tme_sparc_tlb_addr_last) >= (address_first + (ls.tme_sparc_ls_size - 1)))) {"
        !          2444:        echo "        emulator_off = tlb->tme_sparc_tlb_emulator_off_read;"
        !          2445:        echo "        if (lsinfo & TME_SPARC_LSINFO_OP_ST) {"
        !          2446:        echo "          emulator_off = tlb->tme_sparc_tlb_emulator_off_write;"
        !          2447:        echo "        }"
        !          2448:        echo "        if (__tme_predict_true(emulator_off != TME_EMULATOR_OFF_UNDEF"
        !          2449:        echo "                               && (((lsinfo & TME_SPARC_LSINFO_OP_ATOMIC) == 0)"
        !          2450:        echo "                                   || emulator_off == tlb->tme_sparc_tlb_emulator_off_write))) {"
        !          2451:        echo ""
        !          2452:        echo "          /* return and let our caller do the transfer: */"
        !          2453:        echo "          /* NB: we break const here: */"
        !          2454:        echo "          return ((tme_shared tme_uint8_t *) emulator_off);"
1.1       root     2455:        echo "        }"
1.1.1.2 ! root     2456:        echo "      }"
        !          2457:        echo ""
        !          2458:        echo "      /* we have to call a slow cycle function: */"
        !          2459:        echo "      lsinfo |= TME_SPARC_LSINFO_SLOW_CYCLES;"
        !          2460:        echo "      assert (ls.tme_sparc_ls_cycle == NULL);"
        !          2461:        if test ${arch} = 32; then
        !          2462:            endian_little="FALSE"
        !          2463:        else
        !          2464:            endian_little="(lsinfo & TME_SPARC_LSINFO_ENDIAN_LITTLE)"
        !          2465:        fi
        !          2466:        echo ""
        !          2467:        echo "      /* assume that this operation will transfer the start of the buffer: */"
        !          2468:        echo "      buffer_offset = 0;"
1.1       root     2469:        echo ""
1.1.1.2 ! root     2470:        echo "      /* assume that this is a load or a fetch: */"
        !          2471:        echo "      ls.tme_sparc_ls_cycle = tme_sparc${arch}_load;"
1.1       root     2472:        echo ""
1.1.1.2 ! root     2473:        echo "      /* if this is a store: */"
        !          2474:        echo "      if (lsinfo & TME_SPARC_LSINFO_OP_ST) {"
        !          2475:        echo ""
        !          2476:        echo "        /* put the (first) register to store in the memory buffer: */"
        !          2477:        echo "        value = TME_SPARC_FORMAT3_RD;"
        !          2478:        echo "        value = (${endian_little} ? tme_htole_u${arch}(value) : tme_htobe_u${arch}(value));"
        !          2479:        echo "        ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer${arch}s[0] = value;"
        !          2480:        echo ""
        !          2481:        echo "        /* find the offset in the memory buffer corresponding to the"
        !          2482:        echo "           first address: */"
        !          2483:        echo "        buffer_offset = sizeof(tme_uint${arch}_t) - ls.tme_sparc_ls_size;"
        !          2484:        echo "        if (${endian_little}) {"
        !          2485:        echo "          buffer_offset = 0;"
1.1       root     2486:        echo "        }"
1.1.1.2 ! root     2487: 
1.1       root     2488:        echo ""
1.1.1.2 ! root     2489:        echo "        /* if this is a std or stda: */"
        !          2490:        echo "        if (lsinfo & TME_SPARC_LSINFO_LDD_STD) {"
        !          2491:        echo ""
        !          2492:        echo "          /* put the odd 32-bit register to store in the memory buffer"
        !          2493:        echo "             after the even 32-bit register.  exactly where this is depends"
        !          2494:        echo "             on the architecture and on the byte order of the store: */"
        !          2495:        echo "          value32 = TME_SPARC_FORMAT3_RD_ODD(tme_ic_ireg_uint${arch});"
        !          2496:        echo "          if (${endian_little}) {"
        !          2497:        echo "            value32 = tme_htole_u32(value32);"
        !          2498:        echo "            ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer32s[1] = value32;"
        !          2499:        echo "            buffer_offset = 0;"
        !          2500:        echo "          }"
        !          2501:        echo "          else {"
        !          2502:        echo "            value32 = tme_htobe_u32(value32);"
        !          2503:        echo "            ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer32s[(${arch} / 32)] = value32;"
        !          2504:        echo "            buffer_offset = sizeof(tme_uint${arch}_t) - sizeof(tme_uint32_t);"
1.1       root     2505:        echo "          }"
                   2506:        echo "        }"
1.1.1.2 ! root     2507:        echo ""
        !          2508:        echo "        /* set the cycle function: */"
        !          2509:        echo "        ls.tme_sparc_ls_cycle = tme_sparc${arch}_store;"
1.1       root     2510:        echo "      }"
1.1.1.2 ! root     2511:        echo ""
        !          2512:        echo "      /* otherwise, if this is an atomic: */"
        !          2513:        echo "      else if (lsinfo & TME_SPARC_LSINFO_OP_ATOMIC) {"
        !          2514:        echo ""
        !          2515:        echo "        /* set the cycle function: */"
        !          2516:        echo "        ls.tme_sparc_ls_cycle = tme_sparc${arch}_atomic;"
        !          2517:        echo "      }"
        !          2518:        echo ""
        !          2519:        echo "      /* set the buffer offset for the (first) slow cycle: */"
        !          2520:        echo "      ls.tme_sparc_ls_buffer_offset = buffer_offset;"
        !          2521:        echo ""
        !          2522:        echo "      /* clear the state for this operation: */"
        !          2523:        echo "      ls.tme_sparc_ls_state = 0;"
1.1       root     2524:        echo "    }"
                   2525: 
                   2526:        echo ""
1.1.1.2 ! root     2527:        echo "    /* assume that we won't have to check the TLB again: */"
        !          2528:        echo "    ls.tme_sparc_ls_lsinfo = lsinfo | TME_SPARC_LSINFO_NO_CHECK_TLB;"
1.1       root     2529: 
1.1.1.2 ! root     2530:        echo "    /* call the slow cycle function: */"
        !          2531:        echo "    (*ls.tme_sparc_ls_cycle)(ic, &ls);"
        !          2532:        echo "  }"
1.1       root     2533:        echo ""
1.1.1.2 ! root     2534:        echo "  /* if this was a load that has already completed, a store,"
        !          2535:        echo "     or an atomic, make sure our caller doesn't try to complete"
        !          2536:        echo "     a fast transfer: */"
        !          2537:        echo "  if (ls.tme_sparc_ls_lsinfo"
        !          2538:        echo "      & (TME_SPARC_LSINFO_LD_COMPLETED"
        !          2539:        echo "         | TME_SPARC_LSINFO_OP_ST"
        !          2540:        echo "         | TME_SPARC_LSINFO_OP_ATOMIC)) {"
        !          2541:        echo "    return (TME_EMULATOR_OFF_UNDEF);"
        !          2542:        echo "  }"
        !          2543:        echo ""
        !          2544:        echo "  /* otherwise, this was a load that did slow cycles into the"
        !          2545:        echo "     memory buffer and hasn't updated rd yet.  return a pointer"
        !          2546:        echo "     to the memory buffer so our caller can complete the load: */"
        !          2547:        echo "  return (ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer8s"
        !          2548:        echo "          - address_first);"
1.1       root     2549:        echo "}"
1.1.1.2 ! root     2550:     fi
1.1       root     2551: 
                   2552:     # unfix the architecture version:
                   2553:     #
                   2554:     if $header; then :; else
                   2555:        echo ""
                   2556:        echo "#undef TME_SPARC_VERSION"
                   2557:        echo "#define TME_SPARC_VERSION(ic) _TME_SPARC_VERSION(ic)"
                   2558:     fi
                   2559: 
                   2560:     # the sparc64 support depends on a 64-bit integer type:
                   2561:     #
                   2562:     if test ${arch} = 64; then
                   2563:        echo ""
                   2564:        echo "#endif /* TME_HAVE_INT64_T */"
                   2565:     fi
                   2566: done
                   2567: 
                   2568: # done:
                   2569: #
                   2570: exit 0

unix.superglobalmegacorp.com

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