|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.