|
|
1.1 ! root 1: #! /bin/sh ! 2: ! 3: # $Id: sparc-insns-auto.sh,v 1.5 2007/03/29 01:16:09 fredette Exp $ ! 4: ! 5: # ic/sparc/sparc-insns-auto.sh - automatically generates C code ! 6: # for many SPARC emulation instructions: ! 7: ! 8: # ! 9: # Copyright (c) 2005 Matt Fredette ! 10: # All rights reserved. ! 11: # ! 12: # Redistribution and use in source and binary forms, with or without ! 13: # modification, are permitted provided that the following conditions ! 14: # are met: ! 15: # 1. Redistributions of source code must retain the above copyright ! 16: # notice, this list of conditions and the following disclaimer. ! 17: # 2. Redistributions in binary form must reproduce the above copyright ! 18: # notice, this list of conditions and the following disclaimer in the ! 19: # documentation and/or other materials provided with the distribution. ! 20: # 3. All advertising materials mentioning features or use of this software ! 21: # must display the following acknowledgement: ! 22: # This product includes software developed by Matt Fredette. ! 23: # 4. The name of the author may not be used to endorse or promote products ! 24: # derived from this software without specific prior written permission. ! 25: # ! 26: # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ! 27: # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ! 28: # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ! 29: # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ! 30: # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ! 31: # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ! 32: # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 33: # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ! 34: # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ! 35: # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ! 36: # POSSIBILITY OF SUCH DAMAGE. ! 37: # ! 38: ! 39: header=false ! 40: ! 41: for option ! 42: do ! 43: case $option in ! 44: --header) header=true ;; ! 45: esac ! 46: done ! 47: ! 48: PROG=`basename $0` ! 49: cat <<EOF ! 50: /* automatically generated by $PROG, do not edit! */ ! 51: _TME_RCSID("\$Id: sparc-insns-auto.sh,v 1.5 2007/03/29 01:16:09 fredette Exp $"); ! 52: ! 53: EOF ! 54: if $header; then :; else ! 55: cat <<EOF ! 56: #include "sparc-impl.h" ! 57: EOF ! 58: fi ! 59: ! 60: # permute over architecture: ! 61: # ! 62: for arch in 32; do ! 63: ! 64: # the sparc64 support depends on a 64-bit integer type: ! 65: # ! 66: if test ${arch} = 64; then ! 67: echo "" ! 68: echo "#ifdef TME_HAVE_INT64_T" ! 69: fi ! 70: ! 71: # get the name of the register with the integer condition codes, a ! 72: # shift value for 32-bit registers, and the architecture version: ! 73: # ! 74: if test ${arch} = 32; then ! 75: ccr=32_PSR ! 76: ccr_ireg='tme_sparc32_ireg_psr' ! 77: reg32_shift='' ! 78: version=8 ! 79: else ! 80: ccr=64_CCR ! 81: ccr_ireg='tme_sparc64_ireg_ccr' ! 82: reg32_shift=' << 1' ! 83: version=9 ! 84: fi ! 85: ! 86: # fix the architecture version: ! 87: # ! 88: if $header; then :; else ! 89: echo "" ! 90: echo "#undef TME_SPARC_VERSION" ! 91: echo "#define TME_SPARC_VERSION(ic) (${version})" ! 92: fi ! 93: ! 94: # the alternate ASI function: ! 95: # ! 96: if $header; then :; else ! 97: echo "static tme_uint32_t" ! 98: echo "_tme_sparc${arch}_alternate_asi_mask(struct tme_sparc *ic)" ! 99: echo "{" ! 100: echo " unsigned int asi_data;" ! 101: echo " tme_uint32_t asi_mask_data;" ! 102: echo "" ! 103: echo " /* get the ASI, assuming that the i bit is zero: */" ! 104: echo " asi_data = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, (0xff << 5));" ! 105: if test ${arch} = 32; then ! 106: echo "" ! 107: echo " /* this is a privileged instruction: */" ! 108: echo " TME_SPARC_INSN_PRIV;" ! 109: echo "" ! 110: echo " /* if the i bit is one, this is an illegal instruction: */" ! 111: echo " if (__tme_predict_false(TME_SPARC_INSN & TME_BIT(13))) {" ! 112: echo " TME_SPARC_INSN_ILL;" ! 113: echo " }" ! 114: echo "" ! 115: echo " /* map the ASI into an ASI mask: */" ! 116: echo " switch (asi_data) {" ! 117: echo " case TME_SPARC32_ASI_UI: asi_mask_data = TME_SPARC32_ASI_MASK_UI; break;" ! 118: echo " case TME_SPARC32_ASI_UD: asi_mask_data = TME_SPARC32_ASI_MASK_UD; break;" ! 119: echo " case TME_SPARC32_ASI_SI: asi_mask_data = TME_SPARC32_ASI_MASK_SI; break;" ! 120: echo " case TME_SPARC32_ASI_SD: asi_mask_data = TME_SPARC32_ASI_MASK_SD; break;" ! 121: echo " default: asi_mask_data = TME_SPARC_ASI_MASK(asi_data); break;" ! 122: echo " }" ! 123: else ! 124: echo "" ! 125: echo " /* if the i bit is one, use the address space in the ASI register: */" ! 126: echo " if (TME_SPARC_INSN & TME_BIT(13)) {" ! 127: echo " asi_data = ic->tme_sparc_ireg_asi;" ! 128: echo " }" ! 129: echo "" ! 130: echo " /* start the ASI mask: */" ! 131: echo " asi_mask_data = TME_SPARC_ASI_MASK(asi_data);" ! 132: ! 133: echo "" ! 134: echo " /* if this is an unpriviledged access: */" ! 135: echo " if (!TME_SPARC_PRIV(ic)) {" ! 136: echo "" ! 137: echo " /* this is a priviledge violation if bit 7 of the ASI is zero: */" ! 138: echo " if (asi_data < 0x80) {" ! 139: echo " TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_privileged_instruction);" ! 140: echo " }" ! 141: echo " }" ! 142: fi ! 143: echo "" ! 144: echo " return (asi_mask_data);" ! 145: echo "}" ! 146: fi ! 147: ! 148: # permute over instruction: ! 149: # ! 150: for insn in \ ! 151: add \ ! 152: addcc \ ! 153: sub \ ! 154: subcc \ ! 155: or \ ! 156: orcc \ ! 157: orn \ ! 158: orncc \ ! 159: and \ ! 160: andcc \ ! 161: andn \ ! 162: andncc \ ! 163: xor \ ! 164: xorcc \ ! 165: xnor \ ! 166: xnorcc \ ! 167: addx \ ! 168: addxcc \ ! 169: subx \ ! 170: subxcc \ ! 171: taddcc taddcctv \ ! 172: tsubcc tsubcctv \ ! 173: umul umulcc smul smulcc \ ! 174: udiv udivcc sdiv sdivcc \ ! 175: sll \ ! 176: srl \ ! 177: sra \ ! 178: ldb stb \ ! 179: ldh sth \ ! 180: ld st \ ! 181: ldd std \ ! 182: ldstub ldstuba swap swapa \ ! 183: ldba stba \ ! 184: ldha stha \ ! 185: lda sta \ ! 186: ldda stda \ ! 187: jmpl \ ! 188: ldf lddf ldfsr \ ! 189: stf stdf stfsr \ ! 190: mulscc \ ! 191: ; do ! 192: ! 193: # if we're making the header, just emit declarations: ! 194: # ! 195: if $header; then ! 196: echo "TME_SPARC_FORMAT3_DECL(tme_sparc${arch}_${insn}, tme_uint${arch}_t);" ! 197: continue ! 198: fi ! 199: ! 200: # an ALU instruction: ! 201: # ! 202: case ${insn} in ! 203: add | sub | or | orn | and | andn | xor | xnor | \ ! 204: addx | subx | umul | smul | udiv | sdiv) ! 205: cc=false ! 206: ;; ! 207: addcc | subcc | orcc | orncc | andcc | andncc | xorcc | xnorcc | \ ! 208: addxcc | subxcc | umulcc | smulcc | udivcc | sdivcc | \ ! 209: taddcc | tsubcc | taddcctv | tsubcctv | \ ! 210: mulscc) ! 211: cc=true ! 212: ;; ! 213: *) ! 214: cc= ! 215: ;; ! 216: esac ! 217: if test "x${cc}" != x; then ! 218: ! 219: # characterize each function: ! 220: # ! 221: sign=u ; size_src=${arch} ; size_dst=${arch} ; arith=logical ; with_c= ; tagged= ! 222: case "${insn}" in ! 223: add | addcc) op='src1 + src2' ; arith=add ;; ! 224: sub | subcc) op='src1 - src2' ; arith=sub ;; ! 225: or | orcc) op='src1 | src2' ;; ! 226: orn | orncc) op='src1 | ~src2' ;; ! 227: and | andcc) op='src1 & src2' ;; ! 228: andn | andncc) op='src1 & ~src2' ;; ! 229: xor | xorcc) op='src1 ^ src2' ;; ! 230: xnor | xnorcc) op='src1 ^ ~src2' ;; ! 231: addx | addxcc) op='src1 + src2' ; arith=add ; with_c=+ ;; ! 232: subx | subxcc) op='src1 - src2' ; arith=sub ; with_c=- ;; ! 233: taddcc) op='src1 + src2' ; arith=add ; tagged=x ;; ! 234: taddcctv) op='src1 + src2' ; arith=add ; tagged=tv ;; ! 235: tsubcc) op='src1 - src2' ; arith=sub ; tagged=x ;; ! 236: tsubcctv) op='src1 - src2' ; arith=sub ; tagged=tv ;; ! 237: umul | umulcc) arith=mul ; size_src=32 ;; ! 238: smul | smulcc) arith=mul ; size_src=32 ; sign= ;; ! 239: udiv | udivcc) arith=udiv ; size_src=32 ; size_dst=32 ;; ! 240: sdiv | sdivcc) arith=sdiv ; size_src=32 ; size_dst=32 ; sign= ;; ! 241: mulscc) arith=add ; size_src=32 ; size_dst=32 ;; ! 242: *) echo "$0 internal error: unknown ALU function ${insn}" 1>&2 ; exit 1 ;; ! 243: esac ! 244: ! 245: # open the function: ! 246: # ! 247: echo "" ! 248: echo "/* this does a sparc${arch} \"${insn} SRC1, SRC2, DST\": */" ! 249: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)" ! 250: echo "{" ! 251: ! 252: # declare our locals: ! 253: # ! 254: echo " tme_${sign}int${size_src}_t src1;" ! 255: echo " tme_${sign}int${size_src}_t src2;" ! 256: echo " tme_${sign}int${size_dst}_t dst;" ! 257: case "${insn}" in ! 258: umul* | smul* | udiv* | sdiv*) ! 259: echo " tme_${sign}int64_t val64;" ! 260: ;; ! 261: mulscc) ! 262: echo " tme_uint32_t y;" ! 263: ;; ! 264: esac ! 265: if ${cc}; then ! 266: echo " tme_uint32_t cc;" ! 267: fi ! 268: ! 269: echo "" ! 270: echo " /* get the operands: */" ! 271: echo " src1 = (tme_${sign}int${arch}_t) TME_SPARC_FORMAT3_RS1;" ! 272: echo " src2 = (tme_${sign}int${arch}_t) TME_SPARC_FORMAT3_RS2;" ! 273: ! 274: echo "" ! 275: echo " /* perform the operation: */" ! 276: case "${insn}" in ! 277: umul | umulcc | smul | smulcc) ! 278: echo " val64 = (((tme_${sign}int64_t) src1) * src2);" ! 279: echo " ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_Y${reg32_shift}) = (((tme_uint64_t) val64) >> 32);" ! 280: echo " dst = ((tme_${sign}int64_t) val64);" ! 281: ;; ! 282: udiv | udivcc | sdiv | sdivcc) ! 283: echo " val64 = ((((tme_uint64_t) ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_Y${reg32_shift})) << 32) | ((tme_uint32_t) src1));" ! 284: echo " val64 /= src2;" ! 285: echo " /* XXX FIXME - overflow handling is missing here: */" ! 286: echo " dst = val64;" ! 287: ;; ! 288: mulscc) ! 289: echo "" ! 290: echo " /* \"(1) The multiplier is established as r[rs2] if the i field is zero, or " ! 291: echo " sign_ext(simm13) if the i field is one.\"" ! 292: echo "" ! 293: echo " \"(3) If the least significant bit of the Y register = 1, the shifted" ! 294: echo " value from step (2) is added to the multiplier. If the LSB of the" ! 295: echo " Y register = 0, then 0 is added to the shifted value from step (2).\" */" ! 296: echo " y = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_Y${reg32_shift});" ! 297: echo " if ((y & 1) == 0) {" ! 298: echo " src2 = 0;" ! 299: echo " }" ! 300: echo "" ! 301: echo " /* \"(6) The Y register is shifted right by one bit, with the LSB of the" ! 302: echo " unshifted r[rs1] replacing the MSB of Y.\" */" ! 303: echo " y >>= 1;" ! 304: echo " if (src1 & 1) {" ! 305: echo " y += 0x80000000;" ! 306: echo " }" ! 307: echo " ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_Y${reg32_shift}) = y;" ! 308: echo "" ! 309: echo " /* \"(2) A 32-bit value is computed by shifting r[rs1] right by one" ! 310: echo " bit with (N xor V) from the PSR replacing the high-order bit." ! 311: echo " (This is the proper sign for the previous partial product.)\" */" ! 312: echo " src1 >>= 1;" ! 313: echo " if (((ic->${ccr_ireg} ^ (ic->${ccr_ireg} * (TME_SPARC${ccr}_ICC_N / TME_SPARC${ccr}_ICC_V))) & TME_SPARC${ccr}_ICC_N) != 0) {" ! 314: echo " src1 += 0x80000000;" ! 315: echo " }" ! 316: echo "" ! 317: echo " /* \"(4) The sum from step (3) is written into r[rd].\" */" ! 318: echo " dst = src1 + src2;" ! 319: echo "" ! 320: echo " /* \"(5) The integer condition codes, icc, are updated according to the" ! 321: echo " addition performed in step (3).\" */" ! 322: ;; ! 323: *) ! 324: echo " dst = ${op};" ! 325: if test "x${with_c}" != x; then ! 326: echo " dst ${with_c}= ((ic->${ccr_ireg} & TME_SPARC${ccr}_ICC_C) != 0);" ! 327: fi ! 328: esac ! 329: ! 330: # unless this is a tagged-and-trap-on-overflow operation: ! 331: # ! 332: if test "x${tagged}" != xtv; then ! 333: echo "" ! 334: echo " /* store the destination: */" ! 335: echo " TME_SPARC_FORMAT3_RD = (tme_${sign}int${arch}_t) dst;" ! 336: fi ! 337: ! 338: # if this instruction modifies the condition codes: ! 339: # ! 340: if ${cc}; then ! 341: ! 342: echo "" ! 343: echo " /* set Z if the destination is zero: */" ! 344: echo -n " cc = ((dst == 0) * (TME_SPARC${ccr}_ICC_Z" ! 345: if test ${arch} = 64; then ! 346: echo -n " + TME_SPARC${ccr}_XCC_Z" ! 347: fi ! 348: echo "));" ! 349: ! 350: # set the 32-bit, and possibly the 64-bit, condition codes: ! 351: # ! 352: arch_cc=16 ! 353: while test `expr ${arch_cc} \< ${arch}` = 1; do ! 354: arch_cc=`expr ${arch_cc} \* 2` ! 355: ! 356: case ${arch_cc} in ! 357: 32) xcc=ICC ;; ! 358: 64) xcc=XCC ;; ! 359: esac ! 360: ! 361: if test `expr ${arch_cc} \<= ${size_dst}` = 1 || test "x${sign}" = xs; then ! 362: echo "" ! 363: echo " /* set N if the destination is negative: */" ! 364: echo " cc += ((((tme_int${arch_cc}_t) dst) < 0) * TME_SPARC${ccr}_${xcc}_N);" ! 365: fi ! 366: ! 367: case $arith in ! 368: add) ! 369: ones="(((tme_${sign}int${arch_cc}_t) 0) - 1)" ! 370: ! 371: echo "" ! 372: echo " /* if the operands are the same sign, and the destination has" ! 373: echo " a different sign, set V: */" ! 374: echo " cc += ((((tme_int${arch_cc}_t) ((src2 ^ dst) & (src1 ^ (src2 ^ ${ones})))) < 0) * TME_SPARC${ccr}_${xcc}_V);" ! 375: ! 376: echo "" ! 377: echo " /* if src1 and src2 both have the high bit set, or if dst does" ! 378: echo " not have the high bit set and either src1 or src2 does, set C: */" ! 379: echo " cc += (((tme_int${arch_cc}_t) (((tme_uint${arch_cc}_t) (src1 & src2)) | ((((tme_uint${arch_cc}_t) dst) ^ ${ones}) & ((tme_uint${arch_cc}_t) (src1 | src2))))) < 0) * TME_SPARC${ccr}_${xcc}_C;" ! 380: ;; ! 381: sub) ! 382: ! 383: echo "" ! 384: echo " /* if the operands are different signs, and the destination has" ! 385: echo " a different sign from the first operand, set V: */" ! 386: echo " cc += ((((tme_int${arch_cc}_t) ((src1 ^ src2) & (src1 ^ dst))) < 0) * TME_SPARC${ccr}_${xcc}_V);" ! 387: ! 388: echo "" ! 389: echo " /* if src2 is greater than src1, set C: */" ! 390: echo -n " cc += ((((tme_uint${arch_cc}_t) src2) > ((tme_uint${arch_cc}_t) src1))" ! 391: if test "x${with_c}" != x; then ! 392: echo -n " || (((tme_uint${arch_cc}_t) src2) == ((tme_uint${arch_cc}_t) src1) && (ic->${ccr_ireg} & TME_SPARC${ccr}_ICC_C))" ! 393: fi ! 394: echo ") * TME_SPARC${ccr}_${xcc}_C;" ! 395: ;; ! 396: logical | mul) ! 397: ;; ! 398: udiv) ! 399: ;; ! 400: sdiv) ! 401: ;; ! 402: *) echo "$0 internal error: unknown arithmetic type ${arith}" 1>&2 ; exit 1 ;; ! 403: esac ! 404: done ! 405: ! 406: # if this is a tagged operation: ! 407: # ! 408: if test "x${tagged}" != x; then ! 409: ! 410: echo "" ! 411: echo " /* set V if bits zero or one of src1 or src2 are set: */" ! 412: echo " cc |= ((((src1 | src2) & 3) != 0) * TME_SPARC${ccr}_ICC_V);" ! 413: ! 414: # if this is a tagged-and-trap-on-overflow operation: ! 415: # ! 416: if test "x${tagged}" = xtv; then ! 417: ! 418: echo "" ! 419: echo " /* trap on a tagged overflow: */" ! 420: echo " if (cc & TME_SPARC${ccr}_ICC_V) {" ! 421: echo " tme_sparc${arch}_trap(ic, TME_SPARC_TRAP_tag_overflow);" ! 422: echo " }" ! 423: ! 424: echo " /* store the destination: */" ! 425: echo " TME_SPARC_FORMAT3_RD = (tme_${sign}int${arch}_t) dst;" ! 426: fi ! 427: fi ! 428: ! 429: echo "" ! 430: echo " /* set the condition codes: */" ! 431: echo -n " ic->${ccr_ireg} = " ! 432: if test ${arch} = 32; then ! 433: echo -n "(ic->${ccr_ireg} & ~TME_SPARC32_PSR_ICC) | " ! 434: fi ! 435: echo "cc;" ! 436: fi ! 437: ! 438: echo "" ! 439: echo " TME_SPARC_INSN_OK;" ! 440: echo "}" ! 441: fi ! 442: ! 443: # a shift instruction: ! 444: # ! 445: case ${insn} in ! 446: sll | srl | sra) ! 447: ! 448: # get the sign of this shift: ! 449: # ! 450: if test ${insn} = sra; then sign= ; else sign=u; fi ! 451: ! 452: echo "" ! 453: echo "/* the sparc${arch} ${insn} function: */" ! 454: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)" ! 455: echo "{" ! 456: echo " tme_${sign}int${arch}_t dst;" ! 457: echo " unsigned int count;" ! 458: echo "" ! 459: echo " /* get the value and the shift count: */" ! 460: echo " dst = TME_SPARC_FORMAT3_RS1;" ! 461: echo " count = TME_SPARC_FORMAT3_RS2;" ! 462: ! 463: # if we're on sparc64: ! 464: # ! 465: if test ${arch} = 64; then ! 466: ! 467: echo "" ! 468: echo " /* if the X bit is clear: */" ! 469: echo " if ((TME_SPARC_INSN & TME_BIT(12)) == 0) {" ! 470: echo "" ! 471: echo " /* limit the count: */" ! 472: echo " count %= 32;" ! 473: if test ${insn} != sll; then ! 474: echo "" ! 475: echo " /* clip the value to 32 bits: */" ! 476: echo " dst = (tme_${sign}int32_t) dst;" ! 477: fi ! 478: echo " }" ! 479: fi ! 480: ! 481: echo "" ! 482: echo " /* limit the count: */" ! 483: echo " count %= ${arch};" ! 484: echo "" ! 485: echo " /* do the shift: */" ! 486: if test "${insn}" = sra; then ! 487: echo "#ifdef SHIFTSIGNED_INT${arch}_T" ! 488: fi ! 489: echo "#if (SHIFTMAX_INT${arch}_T < (${arch} - 1))" ! 490: echo "#error \"cannot do full shifts of a tme_int${arch}_t\"" ! 491: echo "#endif /* (SHIFTMAX_INT${arch}_T < (${arch} - 1)) */" ! 492: if test ${insn} = sll; then ! 493: echo " dst <<= count;" ! 494: else ! 495: echo " dst >>= count;" ! 496: fi ! 497: if test "${insn}" = sra; then ! 498: echo "#else /* !SHIFTSIGNED_INT${arch}_T */" ! 499: echo " for (; count-- > 0; ) {" ! 500: echo " dst = (dst & ~((tme_${sign}int${arch}_t) 1)) / 2;" ! 501: echo " }" ! 502: echo "#endif /* !SHIFTSIGNED_INT${arch}_T */" ! 503: fi ! 504: ! 505: echo "" ! 506: echo " /* store the destination: */" ! 507: echo " TME_SPARC_FORMAT3_RD = dst;" ! 508: echo "" ! 509: echo " TME_SPARC_INSN_OK;" ! 510: echo "}" ! 511: ;; ! 512: esac ! 513: ! 514: # a load or store instruction: ! 515: # ! 516: size= ! 517: case "${insn}" in ! 518: ldb | stb | ldstub | ldba | stba | ldstuba) size=8 ;; ! 519: ldh | sth | ldha | stha) size=16 ;; ! 520: ld | st | swap | lda | sta | swapa) size=32 ;; ! 521: ldd | std | ldda | stda) size=32 ;; ! 522: esac ! 523: if test "x${size}" != x; then ! 524: ! 525: # set the alternate space indication: ! 526: # ! 527: case "${insn}" in ! 528: *a) alternate=true ;; ! 529: *) alternate=false ;; ! 530: esac ! 531: ! 532: # set the atomic and double indications: ! 533: # ! 534: atomic=false ! 535: double=false ! 536: case "${insn}" in ! 537: ldstub | ldstuba | swap | swapa) atomic=true ;; ! 538: ldd* | std*) double=true ; size=64 ;; ! 539: esac ! 540: ! 541: # if this is only a load, we are reading, otherwise we are writing: ! 542: # ! 543: cycle=write ! 544: capcycle=WRITE ! 545: slow=store ! 546: case "${insn}" in ! 547: ldstub*) ;; ! 548: ld*) ! 549: cycle=read ! 550: capcycle=READ ! 551: slow=load ! 552: ;; ! 553: esac ! 554: ! 555: # start the instruction: ! 556: # ! 557: echo "" ! 558: echo "/* this does a sparc${arch} ${insn}: */" ! 559: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)" ! 560: echo "{" ! 561: ! 562: # our locals: ! 563: # ! 564: if ${alternate}; then ! 565: echo " tme_uint32_t asi_mask_data;" ! 566: asi_mask_data=asi_mask_data ! 567: else ! 568: asi_mask_data="ic->tme_sparc_asi_mask_data" ! 569: fi ! 570: echo " tme_uint${arch}_t address;" ! 571: echo " struct tme_sparc_tlb *dtlb;" ! 572: echo -n " " ! 573: if test ${slow} = load; then echo -n "const "; fi ! 574: echo "tme_shared tme_uint8_t *memory;" ! 575: echo " tme_uint${arch}_t value;" ! 576: ! 577: if ${alternate}; then ! 578: echo "" ! 579: echo " /* get the alternate ASI mask: */" ! 580: echo " asi_mask_data = _tme_sparc${arch}_alternate_asi_mask(ic);" ! 581: fi ! 582: ! 583: echo "" ! 584: echo " /* get the address: */" ! 585: echo " address = TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2;" ! 586: ! 587: echo "" ! 588: echo "#ifdef _TME_SPARC_STATS" ! 589: echo " /* track statistics: */" ! 590: echo " ic->tme_sparc_stats.tme_sparc_stats_memory_total++;" ! 591: echo "#endif /* _TME_SPARC_STATS */" ! 592: ! 593: # if this is some kind of a store, except for an ldstub: ! 594: # ! 595: case "${insn}" in ! 596: std*) ! 597: echo "" ! 598: echo " /* log the values stored: */" ! 599: # XXX FIXME - we can't verify a std yet: ! 600: # ! 601: echo " tme_sparc_log(ic, 1000, TME_OK, " ! 602: echo " (TME_SPARC_LOG_HANDLE(ic)," ! 603: echo " _(\"${insn}\t0x%02x:0x%0"`expr ${arch} / 4`"x:\t0x%08x 0x%08x\")," ! 604: echo " TME_SPARC_ASI_MASK_WHICH(${asi_mask_data})," ! 605: echo " address," ! 606: echo " (tme_uint32_t) TME_SPARC_FORMAT3_RD," ! 607: echo " (tme_uint32_t) TME_SPARC_FORMAT3_RD_ODD));" ! 608: ;; ! 609: st* | swap*) ! 610: echo "" ! 611: echo " /* log the value stored: */" ! 612: echo " tme_sparc_verify_mem${size}(ic, ${asi_mask_data}, address, (tme_uint${size}_t) TME_SPARC_FORMAT3_RD, TME_BUS_CYCLE_WRITE);" ! 613: echo " tme_sparc_log(ic, 1000, TME_OK, " ! 614: echo " (TME_SPARC_LOG_HANDLE(ic)," ! 615: echo " _(\"${insn}\t0x%02x:0x%0"`expr ${arch} / 4`"x:\t0x%0"`expr ${size} / 4`"x\")," ! 616: echo " TME_SPARC_ASI_MASK_WHICH(${asi_mask_data})," ! 617: echo " address," ! 618: echo " (tme_uint${size}_t) TME_SPARC_FORMAT3_RD));" ! 619: ;; ! 620: esac ! 621: ! 622: echo "" ! 623: echo " /* get and busy the DTLB entry: */" ! 624: echo " dtlb = TME_SPARC_DTLB_ENTRY(ic, address);" ! 625: echo " tme_sparc_tlb_busy(dtlb);" ! 626: ! 627: echo "" ! 628: echo " /* assume that this DTLB applies and allows fast transfers: */" ! 629: echo " memory = dtlb->tme_sparc_tlb_emulator_off_${cycle};" ! 630: ! 631: echo "" ! 632: echo " /* we must call the slow ${slow} function if: */" ! 633: echo " if (__tme_predict_false(" ! 634: echo "" ! 635: echo " /* the DTLB entry is invalid: */" ! 636: echo " tme_bus_tlb_is_invalid(&dtlb->tme_sparc_tlb_bus_tlb)" ! 637: echo "" ! 638: echo " /* the DTLB entry does not cover the needed addresses: */" ! 639: echo " || (dtlb->tme_sparc_tlb_addr_first > address)" ! 640: echo " || (dtlb->tme_sparc_tlb_addr_last < (address + ((${size} / 8) - 1)))" ! 641: echo "" ! 642: echo " /* the DTLB entry does not cover the needed address space: */" ! 643: echo " || (!TME_SPARC_TLB_ASI_MASK_OK(dtlb, ${asi_mask_data}))" ! 644: echo "" ! 645: echo " /* the DTLB entry does not allow fast transfers: */" ! 646: if $atomic; then ! 647: echo " || (memory != dtlb->tme_sparc_tlb_emulator_off_read)" ! 648: fi ! 649: echo " || (memory == TME_EMULATOR_OFF_UNDEF)" ! 650: if test ${size} != 8; then ! 651: echo "" ! 652: echo " /* the address is misaligned: */" ! 653: echo " || ((address % (${size} / 8)) != 0)" ! 654: fi ! 655: if ${double}; then ! 656: echo "" ! 657: echo " /* the destination register number is odd: */" ! 658: echo " || ((TME_SPARC_INSN & TME_BIT(25)) != 0)" ! 659: fi ! 660: echo "" ! 661: echo " )) {" ! 662: ! 663: echo "" ! 664: echo " /* call the slow ${slow} function: */" ! 665: echo " memory = tme_sparc${arch}_${slow}(ic," ! 666: echo " address," ! 667: if test ${slow} = store; then ! 668: echo " &TME_SPARC_FORMAT3_RD," ! 669: fi ! 670: echo -n " (" ! 671: if ${atomic}; then ! 672: echo "TME_SPARC_SLOW_FLAG_ATOMIC" ! 673: echo -n " | " ! 674: fi ! 675: if ${alternate}; then ! 676: echo "TME_SPARC_SLOW_FLAG_A" ! 677: echo -n " | " ! 678: fi ! 679: echo "(${size} / 8)));" ! 680: ! 681: if test ${slow} = store; then ! 682: echo "" ! 683: echo " /* if the slow ${slow} function did the transfer, return now: */" ! 684: echo " if (__tme_predict_false(memory == TME_EMULATOR_OFF_UNDEF)) {" ! 685: echo " tme_sparc_tlb_unbusy(dtlb);" ! 686: echo " TME_SPARC_INSN_OK;" ! 687: echo " }" ! 688: fi ! 689: echo " }" ! 690: ! 691: echo "" ! 692: echo " /* do the fast transfer: */" ! 693: echo " memory += address;" ! 694: ! 695: # dispatch on the instruction: ! 696: # ! 697: case "${insn}" in ! 698: ldd*) ! 699: if test ${arch} = 32; then ! 700: echo " value = tme_memory_bus_read32(((const tme_shared tme_uint32_t *) memory) + 0, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint32_t) * 2, sizeof(tme_uint${arch}_t));" ! 701: echo " TME_SPARC_FORMAT3_RD = tme_betoh_u32(value);" ! 702: echo " value = tme_memory_bus_read32(((const tme_shared tme_uint32_t *) memory) + 1, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint32_t), sizeof(tme_uint${arch}_t));" ! 703: echo " TME_SPARC_FORMAT3_RD_ODD = tme_betoh_u32(value);" ! 704: else ! 705: echo "$PROG fatal: need ${insn} support for sparc${arch}" 1>&2 ! 706: exit 1 ! 707: fi ! 708: ;; ! 709: std*) ! 710: if test ${arch} = 32; then ! 711: echo " value = tme_htobe_u32(TME_SPARC_FORMAT3_RD);" ! 712: echo " tme_memory_bus_write32(((tme_shared tme_uint32_t *) memory) + 0, value, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint32_t) * 2, sizeof(tme_uint${arch}_t));" ! 713: echo " value = tme_htobe_u32(TME_SPARC_FORMAT3_RD_ODD);" ! 714: echo " tme_memory_bus_write32(((tme_shared tme_uint32_t *) memory) + 1, value, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint32_t), sizeof(tme_uint${arch}_t));" ! 715: else ! 716: echo "$PROG fatal: need ${insn} support for sparc${arch}" 1>&2 ! 717: exit 1 ! 718: fi ! 719: ;; ! 720: ldstub*) ! 721: echo " value = tme_memory_atomic_xchg8(memory, 0xff, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint8_t));" ! 722: ;; ! 723: swap*) ! 724: echo " value = tme_htobe_u32(TME_SPARC_FORMAT3_RD);" ! 725: echo " value = tme_memory_atomic_xchg32((tme_shared tme_uint${size}_t *) memory, value, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint8_t));" ! 726: ;; ! 727: ld*) ! 728: echo " value = tme_memory_bus_read${size}((const tme_shared tme_uint${size}_t *) memory, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint${size}_t), sizeof(tme_uint${arch}_t));" ! 729: if test ${size} != 8; then ! 730: echo " value = tme_betoh_u${size}(value);" ! 731: fi ! 732: ;; ! 733: st*) ! 734: if test ${size} = 8; then swap_st= ; else swap_st="tme_htobe_u${size}"; fi ! 735: echo " value = ${swap_st}(TME_SPARC_FORMAT3_RD);" ! 736: echo " tme_memory_bus_write${size}((tme_shared tme_uint${size}_t *) memory, value, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint${size}_t), sizeof(tme_uint${arch}_t));" ! 737: ;; ! 738: *) echo "$PROG internal error: unknown memory insn ${insn}" 1>&2 ; exit 1 ;; ! 739: esac ! 740: ! 741: echo "" ! 742: echo " /* unbusy the DTLB entry: */" ! 743: echo " tme_sparc_tlb_unbusy(dtlb);" ! 744: ! 745: case "${insn}" in ! 746: ldd*) ;; ! 747: ld* | swap*) ! 748: if test `expr ${size} \< ${arch}` = 1; then ! 749: echo "" ! 750: echo " /* possibly sign-extend the loaded value: */" ! 751: echo " if (TME_SPARC_INSN & TME_BIT(22)) {" ! 752: echo " value = (tme_uint${arch}_t) (tme_int${arch}_t) (tme_int${size}_t) value;" ! 753: echo " }" ! 754: fi ! 755: echo "" ! 756: echo " /* set the loaded value: */" ! 757: echo " TME_SPARC_FORMAT3_RD = value;" ! 758: ;; ! 759: esac ! 760: ! 761: # if this is some kind of a load, log the value loaded: ! 762: # ! 763: case ${insn} in ! 764: ldd*) ! 765: echo "" ! 766: echo " /* log the value loaded: */" ! 767: # XXX FIXME - we can't verify a ldd yet: ! 768: # ! 769: echo " tme_sparc_log(ic, 1000, TME_OK," ! 770: echo " (TME_SPARC_LOG_HANDLE(ic)," ! 771: echo " _(\"${insn}\t0x%02x:0x%0"`expr ${arch} / 4`"x:\t0x%08x 0x%08x\")," ! 772: echo " TME_SPARC_ASI_MASK_WHICH(${asi_mask_data})," ! 773: echo " address," ! 774: echo " (tme_uint32_t) TME_SPARC_FORMAT3_RD," ! 775: echo " (tme_uint32_t) TME_SPARC_FORMAT3_RD_ODD));" ! 776: ;; ! 777: ld* | ldstub* | swap*) ! 778: echo "" ! 779: echo " /* log the value loaded: */" ! 780: echo " tme_sparc_verify_mem${size}(ic, ${asi_mask_data}, address, (tme_uint${size}_t) TME_SPARC_FORMAT3_RD, TME_BUS_CYCLE_READ);" ! 781: echo " tme_sparc_log(ic, 1000, TME_OK," ! 782: echo " (TME_SPARC_LOG_HANDLE(ic)," ! 783: echo " _(\"${insn}\t0x%02x:0x%0"`expr ${arch} / 4`"x:\t0x%0"`expr ${arch} / 4`"x\")," ! 784: echo " TME_SPARC_ASI_MASK_WHICH(${asi_mask_data})," ! 785: echo " address," ! 786: echo " TME_SPARC_FORMAT3_RD));" ! 787: ;; ! 788: esac ! 789: ! 790: echo "" ! 791: echo " TME_SPARC_INSN_OK;" ! 792: echo "}" ! 793: fi ! 794: ! 795: # the jmpl instruction: ! 796: # ! 797: if test ${insn} = jmpl; then ! 798: ! 799: echo "" ! 800: echo "/* this does a sparc${arch} ${insn}: */" ! 801: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)" ! 802: echo "{" ! 803: echo " tme_uint${arch}_t pc_next_next;" ! 804: echo "" ! 805: echo " /* \"The JMPL instruction causes a register-indirect delayed control" ! 806: echo " transfer to the address given by r[rs1] + r[rs2] if the i field is" ! 807: echo " zero, or r[rs1] + sign_ext(simm13) if the i field is one. The JMPL" ! 808: echo " instruction copies the PC, which contains the address of the JMPL" ! 809: echo " instruction, into register r[rd]. If either of the low-order two" ! 810: echo " bits of the jump address is nonzero, a mem_address_not_aligned" ! 811: echo " trap occurs.\" */" ! 812: echo "" ! 813: echo " pc_next_next = TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2;" ! 814: echo " if (__tme_predict_false((pc_next_next % sizeof(tme_uint32_t)) != 0)) {" ! 815: echo " TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_mem_address_not_aligned);" ! 816: echo " }" ! 817: echo "" ! 818: echo " /* write the PC of the jmpl into r[rd]: */" ! 819: echo " TME_SPARC_FORMAT3_RD = ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_PC);" ! 820: echo "" ! 821: echo " /* log an indirect call instruction, which has 15 (%o7) for rd: */" ! 822: echo " if (TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD) == 15) {" ! 823: echo " tme_sparc_log(ic, 250, TME_OK," ! 824: echo " (TME_SPARC_LOG_HANDLE(ic)," ! 825: echo " _(\"call 0x%08x\")," ! 826: echo " pc_next_next));" ! 827: echo " }" ! 828: echo "" ! 829: echo " /* log a ret or retl instruction, which has 0 (%g0) for rd," ! 830: echo " either 31 (%i7) or 15 (%o7) for rs1, and 8 for simm13: */" ! 831: echo " else if ((TME_SPARC_INSN | (16 << 14))" ! 832: echo " == ((tme_uint32_t) (0x2 << 30) | (0 << 25) | (0x38 << 19) | (31 << 14) | (0x1 << 13) | 8)) {" ! 833: echo " tme_sparc_log(ic, 250, TME_OK," ! 834: echo " (TME_SPARC_LOG_HANDLE(ic)," ! 835: echo " _(\"retl 0x%08x\")," ! 836: echo " pc_next_next));" ! 837: echo " }" ! 838: echo "" ! 839: echo " /* set the delayed control transfer: */" ! 840: echo " ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_PC_NEXT_NEXT) = pc_next_next;" ! 841: echo "" ! 842: echo " TME_SPARC_INSN_OK;" ! 843: echo "}" ! 844: fi ! 845: ! 846: # the ldf instruction: ! 847: # ! 848: if test ${insn} = ldf; then ! 849: ! 850: echo "" ! 851: echo "/* this does a sparc${arch} ${insn}: */" ! 852: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)" ! 853: echo "{" ! 854: echo " unsigned int fpreg_number;" ! 855: echo "" ! 856: echo " TME_SPARC_INSN_FPU;" ! 857: echo "" ! 858: echo " /* decode rd: */" ! 859: echo " fpreg_number = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);" ! 860: echo "" ! 861: echo " /* make sure this floating-point register is single-precision: */" ! 862: echo " tme_sparc_fpu_fpreg_format(ic, fpreg_number, TME_IEEE754_FPREG_FORMAT_SINGLE | TME_IEEE754_FPREG_FORMAT_BUILTIN);" ! 863: echo "" ! 864: echo " /* do the load: */" ! 865: echo " tme_sparc${arch}_ld(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}));" ! 866: echo "" ! 867: echo " /* set the floating-point register value: */" ! 868: echo " ic->tme_sparc_fpu_fpregs[fpreg_number].tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;" ! 869: echo " ic->tme_sparc_fpu_fpregs[fpreg_number].tme_float_value_ieee754_single" ! 870: echo " = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift});" ! 871: echo "" ! 872: echo " TME_SPARC_INSN_OK;" ! 873: echo "}" ! 874: fi ! 875: ! 876: # the stf instruction: ! 877: # ! 878: if test ${insn} = stf; then ! 879: ! 880: echo "" ! 881: echo "/* this does a sparc${arch} ${insn}: */" ! 882: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)" ! 883: echo "{" ! 884: echo " unsigned int fpreg_number;" ! 885: echo " const tme_uint32_t *value_single;" ! 886: echo " tme_uint32_t value_single_buffer;" ! 887: echo "" ! 888: echo " TME_SPARC_INSN_FPU_STORE(sizeof(tme_uint32_t));" ! 889: echo "" ! 890: echo " /* decode rd: */" ! 891: echo " fpreg_number = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);" ! 892: echo "" ! 893: echo " /* make sure this floating-point register is single-precision: */" ! 894: echo " tme_sparc_fpu_fpreg_format(ic, fpreg_number, TME_IEEE754_FPREG_FORMAT_SINGLE | TME_IEEE754_FPREG_FORMAT_BUILTIN);" ! 895: echo "" ! 896: echo " /* get this single floating-point register in IEEE754 single-precision format: */" ! 897: echo " value_single = tme_ieee754_single_value_get(&ic->tme_sparc_fpu_fpregs[fpreg_number], &value_single_buffer);" ! 898: echo "" ! 899: echo " /* set the floating-point register value: */" ! 900: echo " ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}) = *value_single;" ! 901: echo "" ! 902: echo " /* do the store: */" ! 903: echo " tme_sparc${arch}_st(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}));" ! 904: echo "" ! 905: echo " TME_SPARC_INSN_OK;" ! 906: echo "}" ! 907: fi ! 908: ! 909: # the lddf instruction: ! 910: # ! 911: if test ${insn} = lddf; then ! 912: ! 913: echo "" ! 914: echo "/* this does a sparc${arch} ${insn}: */" ! 915: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)" ! 916: echo "{" ! 917: echo " unsigned int fpreg_number;" ! 918: echo "" ! 919: echo " TME_SPARC_INSN_FPU;" ! 920: echo "" ! 921: echo " /* decode rd: */" ! 922: echo " fpreg_number = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);" ! 923: echo "" ! 924: echo " /* make sure rd is aligned: */" ! 925: echo " if (!tme_sparc_fpu_fpreg_aligned(ic, fpreg_number, TME_IEEE754_FPREG_FORMAT_DOUBLE)) {" ! 926: echo " fpreg_number -= 1;" ! 927: echo " }" ! 928: echo "" ! 929: echo " /* make sure that the double floating-point register is double-precision: */" ! 930: echo " tme_sparc_fpu_fpreg_format(ic, fpreg_number, TME_IEEE754_FPREG_FORMAT_DOUBLE | TME_IEEE754_FPREG_FORMAT_BUILTIN);" ! 931: echo "" ! 932: echo " /* do the load: */" ! 933: echo " tme_sparc${arch}_ldd(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}));" ! 934: echo "" ! 935: echo " /* set the double floating-point register value: */" ! 936: echo " ic->tme_sparc_fpu_fpregs[fpreg_number].tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;" ! 937: echo " ic->tme_sparc_fpu_fpregs[fpreg_number].tme_float_value_ieee754_double.tme_value64_uint32_hi" ! 938: echo " = ic->tme_sparc_ireg_uint32((TME_SPARC_IREG_FPX${reg32_shift}) + 0);" ! 939: echo " ic->tme_sparc_fpu_fpregs[fpreg_number].tme_float_value_ieee754_double.tme_value64_uint32_lo" ! 940: echo " = ic->tme_sparc_ireg_uint32((TME_SPARC_IREG_FPX${reg32_shift}) + 1);" ! 941: echo "" ! 942: echo " TME_SPARC_INSN_OK;" ! 943: echo "}" ! 944: fi ! 945: ! 946: # the stdf instruction: ! 947: # ! 948: if test ${insn} = stdf; then ! 949: ! 950: echo "" ! 951: echo "/* this does a sparc${arch} ${insn}: */" ! 952: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)" ! 953: echo "{" ! 954: echo " unsigned int fpreg_number;" ! 955: echo " const union tme_value64 *value_double;" ! 956: echo " union tme_value64 value_double_buffer;" ! 957: echo "" ! 958: echo " TME_SPARC_INSN_FPU_STORE(sizeof(tme_uint32_t) * 2);" ! 959: echo "" ! 960: echo " /* decode rd: */" ! 961: echo " fpreg_number = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);" ! 962: echo "" ! 963: echo " /* make sure rd is aligned: */" ! 964: echo " if (!tme_sparc_fpu_fpreg_aligned(ic, fpreg_number, TME_IEEE754_FPREG_FORMAT_DOUBLE)) {" ! 965: echo " fpreg_number -= 1;" ! 966: echo " }" ! 967: echo "" ! 968: echo " /* make sure the double floating-point register is double-precision: */" ! 969: echo " tme_sparc_fpu_fpreg_format(ic, fpreg_number, TME_IEEE754_FPREG_FORMAT_DOUBLE | TME_IEEE754_FPREG_FORMAT_BUILTIN);" ! 970: echo "" ! 971: echo " /* get this double floating-point register in IEEE754 double-precision format: */" ! 972: echo " value_double = tme_ieee754_double_value_get(&ic->tme_sparc_fpu_fpregs[fpreg_number], &value_double_buffer);" ! 973: echo "" ! 974: echo " /* set the floating-point register value: */" ! 975: echo " ic->tme_sparc_ireg_uint32((TME_SPARC_IREG_FPX${reg32_shift}) + 0)" ! 976: echo " = value_double->tme_value64_uint32_hi;" ! 977: echo " ic->tme_sparc_ireg_uint32((TME_SPARC_IREG_FPX${reg32_shift}) + 1)" ! 978: echo " = value_double->tme_value64_uint32_lo;" ! 979: echo "" ! 980: echo " /* do the store: */" ! 981: echo " tme_sparc${arch}_std(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}));" ! 982: echo "" ! 983: echo " TME_SPARC_INSN_OK;" ! 984: echo "}" ! 985: fi ! 986: ! 987: # the ldfsr instruction: ! 988: # ! 989: if test ${insn} = ldfsr; then ! 990: ! 991: echo "" ! 992: echo "/* this does a sparc${arch} ${insn}: */" ! 993: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)" ! 994: echo "{" ! 995: echo " tme_uint32_t fsr;" ! 996: echo "" ! 997: echo " TME_SPARC_INSN_FPU;" ! 998: echo "" ! 999: echo " /* do the load: */" ! 1000: echo " tme_sparc${arch}_ld(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}));" ! 1001: echo "" ! 1002: echo " /* update the FSR: */" ! 1003: echo " fsr = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift});" ! 1004: echo " /* \"An LDFSR instruction does not affect ftt.\" */" ! 1005: echo " /* \"The LDFSR instruction does not affect qne.\" */" ! 1006: echo " fsr &= ~(TME_SPARC_FSR_VER | TME_SPARC_FSR_FTT | TME_SPARC_FSR_QNE);" ! 1007: echo " ic->tme_sparc_fpu_fsr = (ic->tme_sparc_fpu_fsr & (TME_SPARC_FSR_VER | TME_SPARC_FSR_FTT | TME_SPARC_FSR_QNE)) | fsr;" ! 1008: echo "" ! 1009: echo " TME_SPARC_INSN_OK;" ! 1010: echo "}" ! 1011: fi ! 1012: ! 1013: # the stfsr instruction: ! 1014: # ! 1015: if test ${insn} = stfsr; then ! 1016: ! 1017: echo "" ! 1018: echo "/* this does a sparc${arch} ${insn}: */" ! 1019: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)" ! 1020: echo "{" ! 1021: echo "" ! 1022: echo " TME_SPARC_INSN_FPU_STORE(sizeof(ic->tme_sparc_fpu_fsr));" ! 1023: echo "" ! 1024: echo " /* set the FSR value to store: */" ! 1025: echo " ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}) = ic->tme_sparc_fpu_fsr;" ! 1026: echo "" ! 1027: echo " /* do the store: */" ! 1028: echo " tme_sparc${arch}_st(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}));" ! 1029: echo "" ! 1030: echo " TME_SPARC_INSN_OK;" ! 1031: echo "}" ! 1032: fi ! 1033: ! 1034: # the fpop1 and fpop2 instructions: ! 1035: # ! 1036: if test ${insn} = fpop1 || test ${insn} = fpop2; then ! 1037: ! 1038: echo "" ! 1039: echo "/* this does a sparc${arch} ${insn}: */" ! 1040: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)" ! 1041: echo "{" ! 1042: echo " TME_SPARC_INSN_FPU;" ! 1043: echo " tme_sparc_fpu_${insn}(ic);" ! 1044: echo " TME_SPARC_INSN_OK;" ! 1045: echo "}" ! 1046: fi ! 1047: ! 1048: done ! 1049: ! 1050: # the slow load and store functions: ! 1051: # ! 1052: for slow in load store; do ! 1053: ! 1054: if test ${slow} = load; then ! 1055: cycle="read" ! 1056: capcycle="READ" ! 1057: if $header; then ! 1058: echo "const tme_shared tme_uint8_t *tme_sparc${arch}_${slow} _TME_P((struct tme_sparc *, tme_uint${arch}_t, unsigned int));" ! 1059: continue ! 1060: fi ! 1061: else ! 1062: cycle="write" ! 1063: capcycle="WRITE" ! 1064: if $header; then ! 1065: echo "tme_shared tme_uint8_t *tme_sparc${arch}_${slow} _TME_P((struct tme_sparc *, tme_uint${arch}_t, const tme_uint${arch}_t *, unsigned int));" ! 1066: continue ! 1067: fi ! 1068: fi ! 1069: ! 1070: echo "" ! 1071: echo "/* this does a slow ${slow}: */" ! 1072: if test ${slow} = load; then echo -n "const "; fi ! 1073: echo "tme_shared tme_uint8_t *" ! 1074: echo "tme_sparc${arch}_${slow}(struct tme_sparc *ic, " ! 1075: echo " tme_uint${arch}_t address, " ! 1076: if test ${slow} = store; then ! 1077: echo " const tme_uint${arch}_t * const _rd," ! 1078: fi ! 1079: echo " const unsigned int flags)" ! 1080: echo "{" ! 1081: ! 1082: # our locals: ! 1083: # ! 1084: echo " unsigned int size;" ! 1085: echo " tme_uint32_t asi_mask_data;" ! 1086: echo " struct tme_sparc_tlb *dtlb;" ! 1087: echo " tme_bus_addr_t physical_address;" ! 1088: echo " int shift;" ! 1089: echo " struct tme_bus_cycle cycle;" ! 1090: echo " unsigned int transferred, resid, cycle_size;" ! 1091: echo " unsigned int trap;" ! 1092: echo " int err;" ! 1093: if test ${slow} = store; then ! 1094: echo " tme_uint${arch}_t stored_registers[2];" ! 1095: echo " const tme_uint8_t *buffer;" ! 1096: buffer=buffer ! 1097: else ! 1098: buffer="&ic->tme_sparc_memory_buffer[0]" ! 1099: fi ! 1100: ! 1101: echo "" ! 1102: echo " /* get the transfer size. we can do at most a 64-bit transfer: */" ! 1103: echo " size = (flags % (sizeof(tme_uint64_t) * 2));" ! 1104: ! 1105: echo "" ! 1106: echo " /* get the DTLB entry. our caller has already busied it: */" ! 1107: echo " dtlb = TME_SPARC_DTLB_ENTRY(ic, address);" ! 1108: ! 1109: echo "" ! 1110: echo " /* if the address is not aligned: */" ! 1111: echo " if (__tme_predict_false((address & (size - 1)) != 0)) {" ! 1112: echo " tme_sparc_tlb_unbusy(dtlb);" ! 1113: echo " tme_sparc${arch}_trap(ic, TME_SPARC_TRAP_mem_address_not_aligned);" ! 1114: echo " }" ! 1115: ! 1116: echo "" ! 1117: echo " /* if this is a ldd or a std (and not an lddf or an stdf)" ! 1118: echo " and the destination register address is odd: */" ! 1119: echo " /* NB: we detect lddf and stdf by testing bit 24 in the" ! 1120: echo " instruction word: */" ! 1121: echo " if (__tme_predict_false(size == (sizeof(tme_uint32_t) * 2)" ! 1122: echo " && (TME_SPARC_INSN & TME_BIT(25)) != 0" ! 1123: echo " && (TME_SPARC_INSN & TME_BIT(24)) == 0)) {" ! 1124: echo " tme_sparc_tlb_unbusy(dtlb);" ! 1125: echo " tme_sparc${arch}_trap(ic, TME_SPARC_TRAP_illegal_instruction);" ! 1126: echo " }" ! 1127: ! 1128: echo "" ! 1129: echo " /* get the ASI and its mask: */" ! 1130: echo " asi_mask_data = ic->tme_sparc_asi_mask_data;" ! 1131: echo " if (__tme_predict_false((flags & TME_SPARC_SLOW_FLAG_INSN) != 0)) {" ! 1132: echo " asi_mask_data = ic->tme_sparc_asi_mask_insn;" ! 1133: echo " }" ! 1134: echo " if (__tme_predict_false((flags & TME_SPARC_SLOW_FLAG_A) != 0)) {" ! 1135: echo " asi_mask_data = _tme_sparc${arch}_alternate_asi_mask(ic);" ! 1136: echo " }" ! 1137: ! 1138: if test ${slow} = store; then ! 1139: echo "" ! 1140: echo " /* store big-endian versions of the registers to store in" ! 1141: echo " a buffer. we always assume that this is a std and copy" ! 1142: echo " r[rd] and r[rd + 1] into the buffer: */" ! 1143: echo " stored_registers[0] = tme_htobe_u${arch}(TME_SPARC_FORMAT3_RD);" ! 1144: echo " stored_registers[1] = tme_htobe_u${arch}(TME_SPARC_FORMAT3_RD_ODD);" ! 1145: echo "" ! 1146: echo " /* make the initial pointer into the buffer: */" ! 1147: echo " buffer = (const tme_uint8_t *) stored_registers;" ! 1148: echo " if (size < sizeof(tme_uint32_t)) {" ! 1149: echo " buffer += sizeof(tme_uint32_t) - size;" ! 1150: echo " }" ! 1151: fi ! 1152: echo "" ! 1153: echo " /* loop until the ${slow} is completed: */" ! 1154: echo " trap = TME_SPARC_TRAP_none;" ! 1155: echo " transferred = 0;" ! 1156: echo " do {" ! 1157: echo "" ! 1158: echo " /* while the DTLB entry is invalid, or does not cover this address" ! 1159: echo " and address space, or if it does not allow for slow or fast ${cycle}s: */" ! 1160: echo " for (; (tme_bus_tlb_is_invalid(&dtlb->tme_sparc_tlb_bus_tlb)" ! 1161: echo " || (dtlb->tme_sparc_tlb_addr_first > address)" ! 1162: echo " || (dtlb->tme_sparc_tlb_addr_last < address)" ! 1163: echo " || (!TME_SPARC_TLB_ASI_MASK_OK(dtlb, asi_mask_data))" ! 1164: echo " || (dtlb->tme_sparc_tlb_emulator_off_${cycle} == TME_EMULATOR_OFF_UNDEF" ! 1165: echo " && (dtlb->tme_sparc_tlb_cycles_ok & TME_BUS_CYCLE_${capcycle}) == 0)); ) {" ! 1166: echo "" ! 1167: echo " /* unbusy this DTLB entry for filling: */" ! 1168: echo " tme_bus_tlb_unbusy_fill(&dtlb->tme_sparc_tlb_bus_tlb);" ! 1169: echo "" ! 1170: echo " /* we never fill TLB entries on the stack because we never" ! 1171: echo " callout multiple fills at the same time, so the global TLB" ! 1172: echo " entry pointer always points back to the TLB entry. this" ! 1173: echo " also means that we do not have to call tme_bus_tlb_back()" ! 1174: echo " after the fill: */" ! 1175: echo " dtlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_global = &dtlb->tme_sparc_tlb_bus_tlb;" ! 1176: echo "" ! 1177: echo " /* reload the DTLB entry: */" ! 1178: echo " tme_sparc_callout_unlock(ic);" ! 1179: echo "#ifdef _TME_SPARC_STATS" ! 1180: echo " ic->tme_sparc_stats.tme_sparc_stats_dtlb_fill++;" ! 1181: echo "#endif /* _TME_SPARC_STATS */" ! 1182: echo " err = (*ic->_tme_sparc_bus_connection->tme_sparc_bus_tlb_fill)" ! 1183: echo " (ic->_tme_sparc_bus_connection," ! 1184: echo " dtlb," ! 1185: echo " asi_mask_data," ! 1186: echo " address," ! 1187: echo " TME_BUS_CYCLE_${capcycle});" ! 1188: echo " assert (err == TME_OK);" ! 1189: echo " tme_sparc_callout_relock(ic);" ! 1190: echo "" ! 1191: echo " /* rebusy the DTLB entry: */" ! 1192: echo " tme_sparc_tlb_busy(dtlb);" ! 1193: echo " }" ! 1194: ! 1195: echo "" ! 1196: echo " /* if this DTLB entry allows fast ${cycle}s: */" ! 1197: echo " if (__tme_predict_true(dtlb->tme_sparc_tlb_emulator_off_${cycle} != TME_EMULATOR_OFF_UNDEF)) {" ! 1198: echo "" ! 1199: echo " /* if we have not transferred anything yet, and this" ! 1200: echo " DTLB entry covers all of the addresses and allows" ! 1201: echo " fast transfers: */" ! 1202: echo " if (__tme_predict_true(transferred == 0" ! 1203: echo " && dtlb->tme_sparc_tlb_addr_last >= address + (size - 1)" ! 1204: if test ${slow} = store; then ! 1205: echo "" ! 1206: echo " && ((flags & TME_SPARC_SLOW_FLAG_ATOMIC) == 0" ! 1207: echo -n " || dtlb->tme_sparc_tlb_emulator_off_read == dtlb->tme_sparc_tlb_emulator_off_${cycle})" ! 1208: fi ! 1209: echo ")) {" ! 1210: ! 1211: echo "" ! 1212: echo " /* return and let our caller do the transfer: */" ! 1213: echo " return (dtlb->tme_sparc_tlb_emulator_off_${cycle});" ! 1214: echo " }" ! 1215: echo "" ! 1216: echo " /* calculate the cycle size: */" ! 1217: echo " cycle_size = (dtlb->tme_sparc_tlb_addr_last - address) + 1;" ! 1218: echo " cycle_size = TME_MIN(cycle_size, sizeof(tme_uint${arch}_t) - (address % sizeof(tme_uint${arch}_t)));" ! 1219: echo " cycle_size = TME_MIN(cycle_size, size - transferred);" ! 1220: echo " cycle.tme_bus_cycle_size = cycle_size;" ! 1221: echo "" ! 1222: echo " /* do a ${cycle}: */" ! 1223: echo " tme_memory_bus_${cycle}_buffer((dtlb->tme_sparc_tlb_emulator_off_${cycle} + address)," ! 1224: echo " (${buffer} + transferred)," ! 1225: echo " cycle_size," ! 1226: echo " dtlb->tme_sparc_tlb_bus_rwlock," ! 1227: echo " sizeof(tme_uint8_t)," ! 1228: echo " sizeof(tme_uint32_t));" ! 1229: echo " }" ! 1230: echo "" ! 1231: echo " /* otherwise, this DTLB entry does not allow fast ${cycle}s: */" ! 1232: echo " else {" ! 1233: echo "" ! 1234: echo " /* make the bus cycle structure: */" ! 1235: echo " resid = size - transferred;" ! 1236: echo " cycle.tme_bus_cycle_type = TME_BUS_CYCLE_${capcycle};" ! 1237: echo " cycle.tme_bus_cycle_buffer = (tme_uint8_t *) (${buffer} + transferred);" ! 1238: echo " cycle.tme_bus_cycle_buffer_increment = 1;" ! 1239: echo " cycle_size = TME_MIN(resid, sizeof(tme_uint${arch}_t) - (address % sizeof(tme_uint${arch}_t)));" ! 1240: echo " cycle.tme_bus_cycle_size = cycle_size;" ! 1241: echo " cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS${arch}_LOG2);" ! 1242: echo " cycle.tme_bus_cycle_lane_routing = " ! 1243: echo " &tme_sparc${arch}_router[TME_SPARC_BUS_ROUTER_INDEX(TME_BUS${arch}_LOG2, cycle_size, address)];" ! 1244: echo "" ! 1245: echo " /* form the physical address for the bus cycle handler: */" ! 1246: echo " physical_address = dtlb->tme_sparc_tlb_addr_offset + address;" ! 1247: echo " shift = dtlb->tme_sparc_tlb_addr_shift;" ! 1248: echo " if (shift < 0) {" ! 1249: echo " physical_address <<= (0 - shift);" ! 1250: echo " }" ! 1251: echo " else if (shift > 0) {" ! 1252: echo " physical_address >>= shift;" ! 1253: echo " }" ! 1254: echo " cycle.tme_bus_cycle_address = physical_address;" ! 1255: ! 1256: echo "" ! 1257: echo " /* callout the bus cycle: */" ! 1258: echo " tme_sparc_tlb_unbusy(dtlb);" ! 1259: echo " tme_sparc_callout_unlock(ic);" ! 1260: echo " err = (*dtlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_cycle)" ! 1261: echo " (dtlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_cycle_private, &cycle);" ! 1262: echo " tme_sparc_callout_relock(ic);" ! 1263: echo " tme_sparc_tlb_busy(dtlb);" ! 1264: echo "" ! 1265: echo " /* if the TLB entry was invalidated before the ${slow}: */" ! 1266: echo " if (err == EBADF" ! 1267: echo " && tme_bus_tlb_is_invalid(&dtlb->tme_sparc_tlb_bus_tlb)) {" ! 1268: echo " cycle.tme_bus_cycle_size = 0;" ! 1269: echo " }" ! 1270: echo "" ! 1271: echo " /* otherwise, any other error might be a bus error: */" ! 1272: echo " else if (err != TME_OK) {" ! 1273: echo "" ! 1274: echo " /* if a real bus error may have happened, instead of" ! 1275: echo " some synchronous event: */" ! 1276: echo " if (err != TME_BUS_CYCLE_SYNCHRONOUS_EVENT) {" ! 1277: echo "" ! 1278: echo " /* call the bus fault handlers: */" ! 1279: echo " err = tme_bus_tlb_fault(&dtlb->tme_sparc_tlb_bus_tlb, &cycle, err);" ! 1280: echo " }" ! 1281: echo "" ! 1282: echo " /* if some synchronous event has happened: */" ! 1283: echo " if (err == TME_BUS_CYCLE_SYNCHRONOUS_EVENT) {" ! 1284: echo "" ! 1285: echo " /* after the currently executing instruction finishes, check" ! 1286: echo " for external resets, halts, or interrupts: */" ! 1287: echo " ic->_tme_sparc_instruction_burst_remaining = 0;" ! 1288: echo " }" ! 1289: echo "" ! 1290: echo " /* otherwise, if a real bus fault happened: */" ! 1291: echo " else if (err != TME_OK) {" ! 1292: echo " trap = (*ic->_tme_sparc_bus_fault)(ic, &cycle, flags, err);" ! 1293: echo " if (trap != TME_SPARC_TRAP_none) {" ! 1294: echo " break;" ! 1295: echo " }" ! 1296: echo " }" ! 1297: echo " }" ! 1298: ! 1299: if test ${slow} = store; then ! 1300: echo "" ! 1301: echo " /* if this was an atomic operation, and data was transferred: */" ! 1302: echo " if (__tme_predict_false((flags & TME_SPARC_SLOW_FLAG_ATOMIC) != 0" ! 1303: echo " && cycle.tme_bus_cycle_size > 0)) {" ! 1304: echo "" ! 1305: echo " /* we do not support atomic operations in TLB entries that" ! 1306: echo " do not support both fast reads and fast writes. assuming" ! 1307: echo " that all atomic operations are to regular memory, we" ! 1308: echo " should always get fast read and fast write TLBs. when" ! 1309: echo " we do not, it should only be because the memory has been" ! 1310: echo " made read-only in the MMU. the write above was supposed" ! 1311: echo " to cause a fault (with the instruction rerun later with" ! 1312: echo " a fast read and fast write TLB entry), but instead it" ! 1313: echo " succeeded and transferred some data. we have modified" ! 1314: echo " memory and cannot recover: */" ! 1315: echo " abort();" ! 1316: echo " }" ! 1317: fi ! 1318: echo " }" ! 1319: ! 1320: echo "" ! 1321: echo " /* update: */" ! 1322: echo " address += cycle.tme_bus_cycle_size;" ! 1323: echo " transferred += cycle.tme_bus_cycle_size;" ! 1324: echo " } while (transferred < size);" ! 1325: ! 1326: echo "" ! 1327: echo " /* if we faulted, start trap processing: */" ! 1328: echo " if (__tme_predict_false(trap != TME_SPARC_TRAP_none)) {" ! 1329: echo " tme_sparc_tlb_unbusy(dtlb);" ! 1330: echo " tme_sparc${arch}_trap(ic, trap);" ! 1331: echo " }" ! 1332: ! 1333: echo "" ! 1334: if test ${slow} = load; then ! 1335: echo " return (ic->tme_sparc_memory_buffer - (address - size));" ! 1336: else ! 1337: echo " return ((tme_uint8_t *) TME_EMULATOR_OFF_UNDEF);" ! 1338: fi ! 1339: echo "}" ! 1340: done ! 1341: ! 1342: # unfix the architecture version: ! 1343: # ! 1344: if $header; then :; else ! 1345: echo "" ! 1346: echo "#undef TME_SPARC_VERSION" ! 1347: echo "#define TME_SPARC_VERSION(ic) _TME_SPARC_VERSION(ic)" ! 1348: fi ! 1349: ! 1350: # the sparc64 support depends on a 64-bit integer type: ! 1351: # ! 1352: if test ${arch} = 64; then ! 1353: echo "" ! 1354: echo "#endif /* TME_HAVE_INT64_T */" ! 1355: fi ! 1356: done ! 1357: ! 1358: # done: ! 1359: # ! 1360: exit 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.