Annotation of tme/ic/sparc/sparc-vis-auto.sh, revision 1.1

1.1     ! root        1: #! /bin/sh
        !             2: 
        !             3: # $Id: sparc-vis-auto.sh,v 1.4 2010/02/20 22:01:40 fredette Exp $
        !             4: 
        !             5: # ic/sparc-vis-auto.sh - automatically generates C code for many SPARC VIS
        !             6: # emulation instructions:
        !             7: 
        !             8: #
        !             9: # Copyright (c) 2009 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! */
        !            51: _TME_RCSID("\$Id: sparc-vis-auto.sh,v 1.4 2010/02/20 22:01:40 fredette Exp $");
        !            52: EOF
        !            53: 
        !            54: echo ""
        !            55: echo "/* this handles VIS instructions: */"
        !            56: echo "void"
        !            57: echo "tme_sparc_vis(struct tme_sparc *ic)"
        !            58: echo "{"
        !            59: echo "  unsigned int opf;"
        !            60: echo "  unsigned int fpreg_rd_number_encoded;"
        !            61: echo "  const struct tme_float *fpreg_rs1;"
        !            62: echo "  const struct tme_float *fpreg_rs2;"
        !            63: echo "  unsigned int fpreg_rd_format;"
        !            64: echo "  unsigned int fpreg_rd_number;"
        !            65: echo "  struct tme_float fpreg_rd;"
        !            66: echo "  tme_uint64_t value_fpreg_rs1;"
        !            67: echo "  tme_uint64_t value_fpreg_rs2;"
        !            68: echo "  unsigned int compare_result;"
        !            69: echo "  unsigned int reg_rd;"
        !            70: echo "  unsigned int alignaddr_off;"
        !            71: echo ""
        !            72: echo "  TME_SPARC_INSN_FPU;"
        !            73: echo ""
        !            74: echo "  /* extract the opf field: */"
        !            75: echo "  opf = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, (0x1ff << 5));"
        !            76: echo ""
        !            77: echo "  /* extract the encoded rd: */"
        !            78: echo "  fpreg_rd_number_encoded = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);"
        !            79: 
        !            80: echo ""
        !            81: echo "#ifdef _TME_SPARC_RECODE_VERIFY"
        !            82: echo "  /* clear the rd buffer: */"
        !            83: echo "  memset(&fpreg_rd, 0, sizeof(fpreg_rd));"
        !            84: echo "#endif /* _TME_SPARC_RECODE_VERIFY */"
        !            85: 
        !            86: echo ""
        !            87: echo "  /* dispatch on the opf field: */"
        !            88: echo "  switch (opf) {"
        !            89: echo "#define _TME_SPARC_FPU_FORMAT_RS1(format) fpreg_rs1 = tme_sparc_fpu_fpreg_read(ic, TME_SPARC_FORMAT3_MASK_RS1, (format))"
        !            90: echo "#define _TME_SPARC_FPU_FORMAT_RS2(format) fpreg_rs2 = tme_sparc_fpu_fpreg_read(ic, TME_SPARC_FORMAT3_MASK_RS2, (format))"
        !            91: echo "#define _TME_SPARC_FPU_FORMAT_RD(format) do { fpreg_rd_format = (format) | TME_IEEE754_FPREG_FORMAT_BUILTIN; fpreg_rd_number = tme_sparc_fpu_fpreg_decode(ic, fpreg_rd_number_encoded, fpreg_rd_format); } while (/* CONSTCOND */ 0)"
        !            92: echo ""
        !            93: 
        !            94: # permute over the opf field:
        !            95: #
        !            96: opf_decimal=-1
        !            97: while test ${opf_decimal} != 511; do
        !            98:     opf_decimal=`expr ${opf_decimal} + 1`
        !            99: 
        !           100:     # make the binary version of the opf field:
        !           101:     #
        !           102:     bits=9
        !           103:     opf=
        !           104:     opf_shifted=${opf_decimal}
        !           105:     while test ${bits} != 0; do
        !           106:        bits=`expr ${bits} - 1`
        !           107:        opf_shifted_next=`expr ${opf_shifted} / 2`
        !           108:        opf_test=`expr ${opf_shifted_next} \* 2`
        !           109:        if test ${opf_test} = ${opf_shifted}; then
        !           110:            opf="0${opf}"
        !           111:        else
        !           112:            opf="1${opf}"
        !           113:        fi
        !           114:        opf_shifted=${opf_shifted_next}
        !           115:     done
        !           116: 
        !           117:     # dispatch on opf:
        !           118:     #
        !           119:     default=false
        !           120:     case "${opf}" in
        !           121: 
        !           122:     00010???0)
        !           123:        compareopf=`echo ${opf} | sed -e 's/^00010\(.*\)0$/\1/'`
        !           124:        case "${compareopf}" in
        !           125:        ?1?) compareopsize=32 ;;
        !           126:        ?0?) compareopsize=16 ;;
        !           127:        esac
        !           128:        case "${compareopf}" in
        !           129:        1?0) compareopname="GT" ; compareop=">" ;;
        !           130:        0?0) compareopname="LE" ; compareop="<=" ;;
        !           131:        0?1) compareopname="NE" ; compareop="!=" ;;
        !           132:        1?1) compareopname="EQ" ; compareop="==" ;;
        !           133:        esac
        !           134:        echo "  case ${opf_decimal}:  /* ${opf} FCMP${compareopname}${compareopsize}: */"
        !           135:        echo "    _TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);"
        !           136:        echo "    _TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);"
        !           137:        echo "    value_fpreg_rs1 = fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint;"
        !           138:        echo "    value_fpreg_rs2 = fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint;"
        !           139:        echo "    compare_result = 0;"
        !           140:        compare_off=0
        !           141:        while test ${compare_off} != 64; do
        !           142:            echo "    if (((tme_uint${compareopsize}_t) value_fpreg_rs1)"
        !           143:            echo "        ${compareop} (tme_uint${compareopsize}_t) value_fpreg_rs2) {"
        !           144:            echo "      compare_result += (1 << (${compare_off} / ${compareopsize}));"
        !           145:            echo "    }"
        !           146:            echo "    value_fpreg_rs1 >>= ${compareopsize};"
        !           147:            echo "    value_fpreg_rs2 >>= ${compareopsize};"
        !           148:            compare_off=`expr ${compare_off} + ${compareopsize}`
        !           149:        done
        !           150:        echo "    reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);"
        !           151:        echo "    TME_SPARC_REG_INDEX(ic, reg_rd);"
        !           152:        echo "    ic->tme_sparc_ireg_uint64(reg_rd) = compare_result;"
        !           153:        echo "    fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;"
        !           154:        echo "    fpreg_rd_number = 0;"
        !           155:        ;;
        !           156: 
        !           157:     001001000)
        !           158:        echo "  case ${opf_decimal}:  /* ${opf} FALIGNDATA: */"
        !           159:        echo "    _TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);"
        !           160:        echo "    _TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);"
        !           161:        echo "    _TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);"
        !           162:        echo "    fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;"
        !           163:        echo "    fpreg_rd.tme_float_value_ieee754_double = fpreg_rs1->tme_float_value_ieee754_double;"
        !           164:        echo "    alignaddr_off = TME_FIELD_MASK_EXTRACTU(ic->tme_sparc_vis_gsr, TME_SPARC_VIS_GSR_ALIGNADDR_OFF);"
        !           165:        echo "    if (alignaddr_off) {"
        !           166:        echo "      fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint"
        !           167:        echo "        = ((fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint"
        !           168:        echo "            << (8 * alignaddr_off))"
        !           169:        echo "           + (fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint"
        !           170:        echo "              >> (64 - (8 * alignaddr_off))));"
        !           171:        echo "    }"
        !           172:        ;;
        !           173: 
        !           174:     0011?????)
        !           175:         logicalopf=`echo ${opf} | sed -e 's/^0011\(.*\)[01]$/\1/'`
        !           176:        logicalopname=
        !           177:        logicalop=
        !           178:         case "${logicalopf}" in
        !           179:        0000)
        !           180:            logicalopname="ZERO"
        !           181:            logicalop="0"
        !           182:            ;;
        !           183:        1111)
        !           184:            logicalopname="ONE"
        !           185:            logicalop="(0 - (type) 1)"
        !           186:            ;;
        !           187:        1010)
        !           188:            logicalopname="SRC1"
        !           189:            logicalop="src1"
        !           190:            ;;
        !           191:        1100)
        !           192:            logicalopname="SRC2"
        !           193:            logicalop="src2"
        !           194:            ;;
        !           195:        0101)
        !           196:            logicalopname="NOT1"
        !           197:            logicalop="~src1"
        !           198:            ;;
        !           199:        0011)
        !           200:            logicalopname="NOT2"
        !           201:            logicalop="~src2"
        !           202:            ;;
        !           203:        1110)
        !           204:            logicalopname="OR"
        !           205:            logicalop="(src1 | src2)"
        !           206:            ;;
        !           207:        0001)
        !           208:            logicalopname="NOR"
        !           209:            logicalop="~(src1 | src2)"
        !           210:            ;;
        !           211:        1000)
        !           212:            logicalopname="AND"
        !           213:            logicalop="(src1 & src2)"
        !           214:            ;;
        !           215:        0111)
        !           216:            logicalopname="NAND"
        !           217:            logicalop="~(src1 & src2)"
        !           218:            ;;
        !           219:        0110)
        !           220:            logicalopname="XOR"
        !           221:            logicalop="(src1 ^ src2)"
        !           222:            ;;
        !           223:        1001)
        !           224:            logicalopname="XNOR"
        !           225:            logicalop="~(src1 ^ src2)"
        !           226:            ;;
        !           227:        1101)
        !           228:            logicalopname="ORNOT1"
        !           229:            logicalop="(src2 | ~src1)"
        !           230:            ;;
        !           231:        1011)
        !           232:            logicalopname="ORNOT2"
        !           233:            logicalop="(src1 | ~src2)"
        !           234:            ;;
        !           235:        0100)
        !           236:            logicalopname="ANDNOT1"
        !           237:            logicalop="(src2 & ~src1)"
        !           238:            ;;
        !           239:        0010)
        !           240:            logicalopname="ANDNOT2"
        !           241:            logicalop="(src1 & ~src2)"
        !           242:            ;;
        !           243:        *) echo "$0 internal error: unknown VIS logical op ${logicalopf}" 1>&2 ; exit 1 ;;
        !           244:        esac
        !           245: 
        !           246:        case "${opf}" in
        !           247:        *1) capprecision="SINGLE"; size="32" ; value="single" ; logicalopname="${logicalopname}S" ;;
        !           248:        *0) capprecision="DOUBLE"; size="64" ; value="double.tme_value64_uint" ;;
        !           249:        esac
        !           250: 
        !           251:        echo "  case ${opf_decimal}:  /* ${opf} (${logicalopf}) F${logicalopname}: */"
        !           252: 
        !           253:        logicalop=`echo "${logicalop}" | sed -e "s/type/tme_uint${size}_t/g"`
        !           254: 
        !           255:        logicalop_next=`echo "${logicalop}" | sed -e "s/src1/fpreg_rs1->tme_float_value_ieee754_${value}/"`
        !           256:        if test "${logicalop_next}" != "${logicalop}"; then
        !           257:                echo "    _TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_${capprecision});"
        !           258:                logicalop="${logicalop_next}"
        !           259:        fi
        !           260: 
        !           261:        logicalop_next=`echo "${logicalop}" | sed -e "s/src2/fpreg_rs2->tme_float_value_ieee754_${value}/"`
        !           262:        if test "${logicalop_next}" != "${logicalop}"; then
        !           263:                echo "    _TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_${capprecision});"
        !           264:                logicalop="${logicalop_next}"
        !           265:        fi
        !           266: 
        !           267:        echo "    _TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_${capprecision});"
        !           268:        echo "    _TME_SPARC_FPU_BEGIN;"
        !           269:        echo "    fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_${capprecision};"
        !           270:        echo "    fpreg_rd.tme_float_value_ieee754_${value} = ${logicalop};"
        !           271:        ;;
        !           272:       
        !           273:     *) default=true ;;
        !           274:     esac
        !           275:     if $default; then :; else echo "    break;"; echo ""; fi
        !           276: done
        !           277: echo "  default:"
        !           278: echo "    _TME_SPARC_FPU_UNIMPL;"
        !           279: echo "    fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;"
        !           280: echo "    fpreg_rd_number = 0;"
        !           281: echo "    break;"
        !           282: echo ""
        !           283: echo "#undef _TME_SPARC_FPU_FORMAT_RS1"
        !           284: echo "#undef _TME_SPARC_FPU_FORMAT_RS2"
        !           285: echo "#undef _TME_SPARC_FPU_FORMAT_RD"
        !           286: echo "  }"
        !           287: 
        !           288: echo ""
        !           289: echo "  /* store any destination: */"
        !           290: echo "  if (fpreg_rd_format != TME_IEEE754_FPREG_FORMAT_NULL) {"
        !           291: echo "    tme_sparc_fpu_fpreg_format(ic, fpreg_rd_number, fpreg_rd_format);"
        !           292: echo "    ic->tme_sparc_fpu_fpregs[fpreg_rd_number] = fpreg_rd;"
        !           293: echo "    TME_SPARC_FPU_DIRTY(ic, fpreg_rd_number);"
        !           294: echo "  }"
        !           295: 
        !           296: echo ""
        !           297: echo "}"
        !           298: 
        !           299: # permute over architecture:
        !           300: #
        !           301: for arch in 64; do
        !           302: 
        !           303:     # permute over partial store word size:
        !           304:     #
        !           305:     for size in 64; do
        !           306: 
        !           307:        case "${arch}:${size}" in 
        !           308:        *:64) insn="d" ; format="DOUBLE" ; value="double.tme_value64_uint" ;;
        !           309:        *) echo "$0 internal error: unknown architecture PST word size ${arch}:${size}" 1>&2 ; exit 1 ;;
        !           310:        esac
        !           311: 
        !           312:        cat <<EOF
        !           313: 
        !           314: /* the sparc${arch} cycle handler for st${insn}fa ASI_PST*: */
        !           315: static void
        !           316: _tme_sparc${arch}_vis_ls_cycle_pst${insn}(struct tme_sparc *ic, struct tme_sparc_ls *ls)
        !           317: {
        !           318:   unsigned int reg_rs2;
        !           319:   tme_uint32_t mask_raw;
        !           320:   unsigned int asi;
        !           321:   tme_uint32_t mask_0_31;
        !           322:   tme_uint32_t mask_32_63;
        !           323:   tme_uint${size}_t mask;
        !           324:   const struct tme_float *fpreg_rd;
        !           325:   tme_uint${size}_t value_written;
        !           326:   const struct tme_sparc_tlb *tlb;
        !           327:   tme_uint${arch}_t address;
        !           328:   tme_shared tme_uint8_t *emulator_off;
        !           329:   tme_shared tme_uint${size}_t *memory;
        !           330:   tme_uint${size}_t value_read;
        !           331:   tme_uint${size}_t value_cmp;
        !           332: 
        !           333:   /* decode rs2: */
        !           334:   reg_rs2 = TME_FIELD_MASK_EXTRACTU(ic->_tme_sparc_insn, TME_SPARC_FORMAT3_MASK_RS2);
        !           335:   TME_SPARC_REG_INDEX(ic, reg_rs2);
        !           336: 
        !           337:   /* get the raw mask: */
        !           338:   mask_raw = ic->tme_sparc_ireg_uint${arch}(reg_rs2);
        !           339: 
        !           340:   /* get the ASI: */
        !           341:   asi
        !           342:     = (TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask)
        !           343:        & ~(TME_SPARC${arch}_ASI_FLAG_SECONDARY
        !           344:           | TME_SPARC${arch}_ASI_FLAG_LITTLE));
        !           345: 
        !           346:   /* assume that this is ASI_PST32*: */
        !           347:   mask_0_31 = 0 - (mask_raw & TME_BIT(0));
        !           348:   mask_raw >>= 1;
        !           349:   mask_32_63 = 0 - (mask_raw & TME_BIT(0));
        !           350:   mask_raw >>= 1;
        !           351: 
        !           352:   /* if this is ASI_PST16*: */
        !           353:   if (asi == TME_SPARC_VIS_ASI_PST16) {
        !           354: 
        !           355:     /* convert the ASI_PST32* mask into bits 0..31 of the ASI_PST16* mask: */
        !           356:     mask_0_31
        !           357:       = ((mask_0_31 & (((tme_uint32_t) 0xffff) << 0))
        !           358:         + (mask_32_63 & (((tme_uint32_t) 0xffff) << 16)));
        !           359: 
        !           360:     /* make bits 32..63 of the ASI_PST16* mask: */
        !           361:     mask_32_63
        !           362:       = (((0 - (mask_raw & TME_BIT(0))) & (((tme_uint32_t) 0xffff) << 0))
        !           363:         + ((0 - (mask_raw & TME_BIT(1))) & (((tme_uint32_t) 0xffff) << 16)));
        !           364:   }
        !           365: 
        !           366:   /* otherwise, if this is ASI_PST8*: */
        !           367:   else if (asi == TME_SPARC_VIS_ASI_PST8) {
        !           368: 
        !           369:     /* convert the ASI_PST32* mask into bits 0..15 of the ASI_PST8*
        !           370:        mask, and make bits 16..31: */
        !           371:     mask_0_31
        !           372:       = ((mask_0_31 & (((tme_uint32_t) 0xff) << 0))
        !           373:         + (mask_32_63 & (((tme_uint32_t) 0xff) << 8))
        !           374:         + ((0 - (mask_raw & TME_BIT(0))) & (((tme_uint32_t) 0xff) << 16))
        !           375:         + ((0 - (mask_raw & TME_BIT(1))) & (((tme_uint32_t) 0xff) << 24)));
        !           376: 
        !           377:     /* make bits 32..63 of the ASI_PST8* mask: */
        !           378:     mask_raw >>= 2;
        !           379:     mask_32_63
        !           380:       = (((0 - (mask_raw & TME_BIT(0))) & (((tme_uint32_t) 0xff) << 0))
        !           381:         + ((0 - (mask_raw & TME_BIT(1))) & (((tme_uint32_t) 0xff) << 8))
        !           382:         + ((0 - (mask_raw & TME_BIT(2))) & (((tme_uint32_t) 0xff) << 16))
        !           383:         + ((0 - (mask_raw & TME_BIT(3))) & (((tme_uint32_t) 0xff) << 24)));
        !           384:   }
        !           385: 
        !           386:   /* make the full mask: */
        !           387:   mask = 0;
        !           388:   mask |= (((tme_uint64_t) mask_32_63) << 32);
        !           389:   mask |= mask_0_31;
        !           390: 
        !           391:   /* get the value to store from the double-precision fp register: */
        !           392:   fpreg_rd = tme_sparc_fpu_fpreg_read(ic, TME_SPARC_FORMAT3_MASK_RD, TME_IEEE754_FPREG_FORMAT_${format});
        !           393:   value_written = fpreg_rd->tme_float_value_ieee754_${value};
        !           394: 
        !           395:   /* get the TLB entry: */
        !           396:   tlb = ls->tme_sparc_ls_tlb;
        !           397: 
        !           398:   /* swap the mask and the value to store: */
        !           399:   if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_ENDIAN_LITTLE) {
        !           400:     value_written = tme_htole_u${size}(value_written);
        !           401:     mask = tme_htole_u${size}(mask);
        !           402:   }
        !           403:   else {
        !           404:     value_written = tme_htobe_u${size}(value_written);
        !           405:     mask = tme_htobe_u${size}(mask);
        !           406:   }
        !           407: 
        !           408:   /* get the current address: */
        !           409:   address = ls->tme_sparc_ls_address${arch};
        !           410: 
        !           411:   /* if this is the first transfer, and the TLB entry allows fast
        !           412:      transfer of all of the addresses: */
        !           413:   emulator_off = tlb->tme_sparc_tlb_emulator_off_write;
        !           414:   if (__tme_predict_true(ls->tme_sparc_ls_state == 0
        !           415:                         && ((tme_bus_addr${arch}_t) tlb->tme_sparc_tlb_addr_last) >= (address + sizeof(tme_uint${size}_t) - 1)
        !           416:                         && emulator_off != TME_EMULATOR_OFF_UNDEF
        !           417:                         && emulator_off == tlb->tme_sparc_tlb_emulator_off_read)) {
        !           418: 
        !           419:     /* make the pointer to the memory to store: */
        !           420:     memory = (tme_shared tme_uint${size}_t *) (emulator_off + address);
        !           421: 
        !           422:     /* loop until we can do the atomic partial store: */
        !           423:     value_read = tme_memory_bus_read${size}(memory,
        !           424:                                       tlb->tme_sparc_tlb_bus_rwlock,
        !           425:                                       sizeof(tme_uint${size}_t),
        !           426:                                       sizeof(tme_uint${arch}_t));
        !           427:     do {
        !           428: 
        !           429:       /* make the value to write: */
        !           430:       value_written
        !           431:        = ((value_written & mask)
        !           432:           + (value_read & ~mask));
        !           433: 
        !           434:       /* try an atomic compare-and-exchange: */
        !           435:       value_cmp = value_read;
        !           436:       value_read
        !           437:        = tme_memory_atomic_cx${size}(memory,
        !           438:                                 value_cmp,
        !           439:                                 value_written,
        !           440:                                 tlb->tme_sparc_tlb_bus_rwlock,
        !           441:                                 sizeof(tme_uint${size}_t));
        !           442: 
        !           443:       /* loop while the atomic compare-and-exchange failed: */
        !           444:     } while (value_read != value_cmp);
        !           445: 
        !           446:     /* we finished this transfer: */
        !           447:     ls->tme_sparc_ls_size = 0;
        !           448:     return;
        !           449:   }
        !           450: 
        !           451:   /* otherwise, we have to do a slow transfer: */
        !           452:   ls->tme_sparc_ls_buffer_offset = 0;
        !           453:   /* XXX WRITEME: */
        !           454:   abort();
        !           455: }
        !           456: EOF
        !           457:     done
        !           458: 
        !           459:     cat <<EOF
        !           460: 
        !           461: /* the sparc${arch} ASI handler for ASI_PST*: */
        !           462: void
        !           463: tme_sparc${arch}_vis_ls_asi_pst(struct tme_sparc *ic, struct tme_sparc_ls *ls)
        !           464: {
        !           465:   tme_uint32_t insn;
        !           466:   unsigned int reg_rs1;
        !           467:   tme_uint${arch}_t address_first;
        !           468: 
        !           469:   /* NB: this checks for various traps in priority order: */
        !           470: 
        !           471:   /* the only faults that may have been set so far are an alignment
        !           472:      fault, which is probably wrong because the address checked was
        !           473:      (rs1 + rs2), instead of just rs1, and any ldd/std rd-odd fault.
        !           474:      we will override both faults: */
        !           475:   assert ((ls->tme_sparc_ls_faults
        !           476:           | TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED
        !           477:           | TME_SPARC_LS_FAULT_LDD_STD_RD_ODD)
        !           478:          == (TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED
        !           479:              | TME_SPARC_LS_FAULT_LDD_STD_RD_ODD));
        !           480: 
        !           481:   /* we need to do the complete transfer: */
        !           482:   ls->tme_sparc_ls_faults = TME_SPARC_LS_FAULT_NONE;
        !           483:   ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_SLOW_CYCLES;
        !           484:   ls->tme_sparc_ls_state = 0;
        !           485: 
        !           486:   /* get the instruction: */
        !           487:   insn = ic->_tme_sparc_insn;
        !           488: 
        !           489:   /* NB: the exception for a non-stdfa opcode appears to be explicitly
        !           490:      prioritized above an illegal_instruction trap for an immediate
        !           491:      instruction: */
        !           492: 
        !           493:   /* if this is an stdfa: */
        !           494:   if (__tme_predict_true((insn
        !           495:                          & (0x3f << 19))
        !           496:                         == (0x37 << 19))) {
        !           497: 
        !           498:     /* set the slow cycle function: */
        !           499:     assert (ls->tme_sparc_ls_size == sizeof(tme_uint64_t));
        !           500:     ls->tme_sparc_ls_cycle = _tme_sparc${arch}_vis_ls_cycle_pstd;
        !           501:   }
        !           502: 
        !           503:   /* any other instruction is illegal: */
        !           504:   else {
        !           505:     ls->tme_sparc_ls_faults = ic->tme_sparc_vis_ls_fault_illegal;
        !           506:     return;
        !           507:   }
        !           508: 
        !           509:   /* immediate instruction forms are illegal: */
        !           510:   if (__tme_predict_false(insn & TME_BIT(13))) {
        !           511:     tme_sparc_tlb_unbusy(ls->tme_sparc_ls_tlb);
        !           512:     TME_SPARC_INSN_ILL(ic);
        !           513:   }
        !           514: 
        !           515:   /* the stdfa instruction handler must have already checked that the
        !           516:      FPU is enabled: */
        !           517:   assert (!TME_SPARC_FPU_IS_DISABLED(ic));
        !           518: 
        !           519:   /* decode rs1: */
        !           520:   reg_rs1 = TME_FIELD_MASK_EXTRACTU(insn, TME_SPARC_FORMAT3_MASK_RS1);
        !           521:   TME_SPARC_REG_INDEX(ic, reg_rs1);
        !           522: 
        !           523:   /* get the address: */
        !           524:   address_first = ic->tme_sparc_ireg_uint${arch}(reg_rs1);
        !           525:   ls->tme_sparc_ls_address${arch} = address_first;
        !           526: 
        !           527:   /* the address must be aligned: */
        !           528:   if (__tme_predict_false((((tme_uint32_t) address_first)
        !           529:                           & (ls->tme_sparc_ls_size - 1)) != 0)) {
        !           530:     ls->tme_sparc_ls_faults = TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED;
        !           531:     return;
        !           532:   }
        !           533: 
        !           534:   /* the stdfa instruction handler must have already checked that the
        !           535:      FPU mode is not exception_pending: */
        !           536:   assert (ic->tme_sparc_fpu_mode != TME_SPARC_FPU_MODE_EXCEPTION_PENDING);
        !           537: }
        !           538: 
        !           539: /* the sparc${arch} cycle handler for lddfa and stdfa ASI_FL*: */
        !           540: static void
        !           541: _tme_sparc${arch}_vis_ls_cycle_fld(struct tme_sparc *ic, struct tme_sparc_ls *ls)
        !           542: {
        !           543:   tme_uint64_t value;
        !           544:   unsigned int buffer_offset;
        !           545: 
        !           546:   /* if this is an stdfa: */
        !           547:   if (ic->_tme_sparc_insn & (4 << 19)) {
        !           548: 
        !           549:     /* the actual store cycles will be done directly: */
        !           550:     ls->tme_sparc_ls_cycle = tme_sparc${arch}_store;
        !           551: 
        !           552:     /* initialize the memory buffer with the value to store: */
        !           553:     value = *ls->tme_sparc_ls_rd${arch};
        !           554:   }
        !           555: 
        !           556:   /* otherwise, this is an lddfa: */
        !           557:   else {
        !           558: 
        !           559:     /* the actual load cycles will be done directly: */
        !           560:     ls->tme_sparc_ls_cycle = tme_sparc${arch}_load;
        !           561: 
        !           562:     /* initialize the memory buffer with zero: */
        !           563:     value = 0;
        !           564:   }
        !           565: 
        !           566:   /* initialize the memory buffer: */
        !           567:   if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_ENDIAN_LITTLE) {
        !           568:     value = tme_htole_u64(value);
        !           569:     buffer_offset = 0;
        !           570:   }
        !           571:   else {
        !           572:     value = tme_htobe_u64(value);
        !           573:     buffer_offset = sizeof(value) - ls->tme_sparc_ls_size;
        !           574:   }
        !           575:   ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer64s[0] = value;
        !           576:   ls->tme_sparc_ls_buffer_offset = buffer_offset;
        !           577: 
        !           578:   /* do the (first) actual cycle: */
        !           579:   (*ls->tme_sparc_ls_cycle)(ic, ls);
        !           580: }
        !           581: 
        !           582: /* the sparc${arch} ASI handler for ASI_FL*: */
        !           583: void
        !           584: tme_sparc${arch}_vis_ls_asi_fl(struct tme_sparc *ic, struct tme_sparc_ls *ls)
        !           585: {
        !           586:   tme_uint32_t insn;
        !           587: 
        !           588:   /* NB: this checks for various traps in priority order: */
        !           589: 
        !           590:   /* the only faults that may have been set so far are an alignment
        !           591:      fault, which is probably wrong because the size used for the
        !           592:      alignment check was wrong, and any ldd/std rd-odd fault.  we will
        !           593:      override both faults: */
        !           594:   assert ((ls->tme_sparc_ls_faults
        !           595:           | TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED
        !           596:           | TME_SPARC_LS_FAULT_LDD_STD_RD_ODD)
        !           597:          == (TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED
        !           598:              | TME_SPARC_LS_FAULT_LDD_STD_RD_ODD));
        !           599: 
        !           600:   /* get the instruction: */
        !           601:   insn = ic->_tme_sparc_insn;
        !           602: 
        !           603:   /* we need to do the complete transfer: */
        !           604:   ls->tme_sparc_ls_faults = TME_SPARC_LS_FAULT_NONE;
        !           605:   ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_SLOW_CYCLES;
        !           606:   ls->tme_sparc_ls_state = 0;
        !           607: 
        !           608:   /* set the cycle size: */
        !           609: #if (TME_SPARC_VIS_ASI_FL16 & (TME_SPARC_VIS_ASI_FL16 - 1)) != TME_SPARC_VIS_ASI_FL8
        !           610: #error "TME_SPARC_VIS_ASI_FL values changed"
        !           611: #endif
        !           612:   ls->tme_sparc_ls_size
        !           613:     = (sizeof(tme_uint8_t)
        !           614:        + ((TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask)
        !           615:           / (TME_SPARC_VIS_ASI_FL16
        !           616:              ^ TME_SPARC_VIS_ASI_FL8))
        !           617:          & 1));
        !           618: 
        !           619:   /* if this is an stdfa or an lddfa: */
        !           620:   if (__tme_predict_true((insn
        !           621:                          & (0x3b << 19))
        !           622:                         == (0x33 << 19))) {
        !           623: 
        !           624:     /* set the slow cycle function: */
        !           625:     ls->tme_sparc_ls_cycle = _tme_sparc${arch}_vis_ls_cycle_fld;
        !           626: 
        !           627:     /* the stdfa or lddfa instruction handler must have already
        !           628:        checked that the FPU is enabled: */
        !           629:     assert (!TME_SPARC_FPU_IS_DISABLED(ic));
        !           630:   }
        !           631: 
        !           632:   /* any other instruction is illegal: */
        !           633:   /* XXX FIXME - is this correct?  the UltraSPARC User's Manual
        !           634:      doesn't document data_access_exception for an illegal opcode: */
        !           635:   else {
        !           636:     ls->tme_sparc_ls_faults = ic->tme_sparc_vis_ls_fault_illegal;
        !           637:     return;
        !           638:   }
        !           639: 
        !           640:   /* the address must be aligned: */
        !           641:   if (__tme_predict_false((((tme_uint32_t) ls->tme_sparc_ls_address${arch})
        !           642:                           & (ls->tme_sparc_ls_size - 1)) != 0)) {
        !           643:     ls->tme_sparc_ls_faults = TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED;
        !           644:     return;
        !           645:   }
        !           646: 
        !           647:   /* the stdfa or lddfa instruction handler must have already checked
        !           648:      that the FPU mode is execute: */
        !           649:   assert (ic->tme_sparc_fpu_mode == TME_SPARC_FPU_MODE_EXECUTE);
        !           650: }
        !           651: 
        !           652: /* the sparc${arch} VIS alternate ASI misalignment function: */
        !           653: tme_uint32_t
        !           654: tme_sparc${arch}_vis_ls_asi_misaligned(struct tme_sparc *ic,
        !           655:                                   tme_uint32_t misaligned)
        !           656: {
        !           657:   tme_uint32_t insn;
        !           658:   tme_uint32_t asi;
        !           659:   tme_uint32_t asi_base;
        !           660:   unsigned int reg_rs1;
        !           661: 
        !           662:   /* get the instruction: */
        !           663:   insn = TME_SPARC_INSN;
        !           664: 
        !           665:   /* get the ASI, assuming that the i bit is zero: */
        !           666:   asi = TME_FIELD_MASK_EXTRACTU(insn, (0xff << 5));
        !           667: 
        !           668:   /* if the i bit is one, use the ASI register: */
        !           669:   if (insn & TME_BIT(13)) {
        !           670:     asi = ic->tme_sparc${arch}_ireg_asi;
        !           671:   }
        !           672: 
        !           673:   /* make a base version of the ASI, with the secondary and
        !           674:      little-endian flags cleared: */
        !           675:   asi_base = (asi & ~(TME_SPARC64_ASI_FLAG_SECONDARY | TME_SPARC64_ASI_FLAG_LITTLE));
        !           676: 
        !           677:   /* ASI_FL8* requires 8-bit alignment: */
        !           678:   if (asi_base == TME_SPARC_VIS_ASI_FL8) {
        !           679:     misaligned %= sizeof(tme_uint8_t);
        !           680:   }
        !           681: 
        !           682:   /* ASI_FL16* requires 16-bit alignment: */
        !           683:   else if (asi_base == TME_SPARC_VIS_ASI_FL16) {
        !           684:     misaligned %= sizeof(tme_uint16_t);
        !           685:   }
        !           686: 
        !           687:   /* if this is an ASI_PST*: */
        !           688:   else if (asi_base == TME_SPARC_VIS_ASI_PST8
        !           689:           || asi_base == TME_SPARC_VIS_ASI_PST16
        !           690:           || asi_base == TME_SPARC_VIS_ASI_PST32) {
        !           691: 
        !           692:     /* decode rs1: */
        !           693:     reg_rs1 = TME_FIELD_MASK_EXTRACTU(insn, TME_SPARC_FORMAT3_MASK_RS1);
        !           694:     TME_SPARC_REG_INDEX(ic, reg_rs1);
        !           695: 
        !           696:     /* if this is not a register mode stdfa: */
        !           697:     if (__tme_predict_false((insn
        !           698:                             & ((0x3f << 19)
        !           699:                                + TME_BIT(13)))
        !           700:                            != (0x37 << 19))) {
        !           701: 
        !           702:       /* start a slow load/store, which will call the ASI handler,
        !           703:         which will cause the appropriate fault: */
        !           704:       tme_sparc${arch}_ls(ic,
        !           705:                     ic->tme_sparc_ireg_uint${arch}(reg_rs1),
        !           706:                     (tme_uint${arch}_t *) NULL, /* _rd */
        !           707:                     (TME_SPARC_LSINFO_SIZE(1)
        !           708:                      | TME_SPARC_LSINFO_ASI(asi)
        !           709:                      | TME_SPARC_LSINFO_A));
        !           710:       assert(FALSE);
        !           711:     }
        !           712: 
        !           713:     /* get the least-significant 32 bits of the address: */
        !           714:     misaligned = ic->tme_sparc_ireg_uint${arch}(reg_rs1);
        !           715: 
        !           716:     /* ASI_PST* require 64-bit alignment, which the stdfa instruction
        !           717:        handler is already checking: */
        !           718:   }
        !           719: 
        !           720:   /* return a possibly updated misalignment: */
        !           721:   return (misaligned);
        !           722: }
        !           723: EOF
        !           724: 
        !           725: done
        !           726: 
        !           727: # done:
        !           728: #
        !           729: exit 0

unix.superglobalmegacorp.com

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