Annotation of tme/ic/sparc/sparc-vis-auto.sh, revision 1.1.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.