|
|
1.1 ! root 1: /* $Id: sparc-insns.c,v 1.5 2007/03/29 01:07:46 fredette Exp $ */ ! 2: ! 3: /* ic/sparc/sparc-insns.c - SPARC instruction functions: */ ! 4: ! 5: /* ! 6: * Copyright (c) 2005 Matt Fredette ! 7: * All rights reserved. ! 8: * ! 9: * Redistribution and use in source and binary forms, with or without ! 10: * modification, are permitted provided that the following conditions ! 11: * are met: ! 12: * 1. Redistributions of source code must retain the above copyright ! 13: * notice, this list of conditions and the following disclaimer. ! 14: * 2. Redistributions in binary form must reproduce the above copyright ! 15: * notice, this list of conditions and the following disclaimer in the ! 16: * documentation and/or other materials provided with the distribution. ! 17: * 3. All advertising materials mentioning features or use of this software ! 18: * must display the following acknowledgement: ! 19: * This product includes software developed by Matt Fredette. ! 20: * 4. The name of the author may not be used to endorse or promote products ! 21: * derived from this software without specific prior written permission. ! 22: * ! 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ! 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ! 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ! 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ! 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ! 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ! 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ! 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ! 33: * POSSIBILITY OF SUCH DAMAGE. ! 34: */ ! 35: ! 36: /* includes: */ ! 37: #include "sparc-impl.h" ! 38: ! 39: _TME_RCSID("$Id: sparc-insns.c,v 1.5 2007/03/29 01:07:46 fredette Exp $"); ! 40: ! 41: #include "sparc-bus-auto.c" ! 42: ! 43: TME_SPARC_FORMAT3(tme_sparc32_illegal, tme_uint32_t) ! 44: { ! 45: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction); ! 46: } ! 47: ! 48: /* the coprocessor instructions are all illegal for now: */ ! 49: TME_SPARC_FORMAT3(tme_sparc32_cpop1, tme_uint32_t) ! 50: { ! 51: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction); ! 52: } ! 53: TME_SPARC_FORMAT3(tme_sparc32_cpop2, tme_uint32_t) ! 54: { ! 55: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction); ! 56: } ! 57: TME_SPARC_FORMAT3(tme_sparc32_ldc, tme_uint32_t) ! 58: { ! 59: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction); ! 60: } ! 61: TME_SPARC_FORMAT3(tme_sparc32_ldcsr, tme_uint32_t) ! 62: { ! 63: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction); ! 64: } ! 65: TME_SPARC_FORMAT3(tme_sparc32_lddc, tme_uint32_t) ! 66: { ! 67: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction); ! 68: } ! 69: TME_SPARC_FORMAT3(tme_sparc32_stc, tme_uint32_t) ! 70: { ! 71: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction); ! 72: } ! 73: TME_SPARC_FORMAT3(tme_sparc32_stcsr, tme_uint32_t) ! 74: { ! 75: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction); ! 76: } ! 77: TME_SPARC_FORMAT3(tme_sparc32_stdc, tme_uint32_t) ! 78: { ! 79: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction); ! 80: } ! 81: TME_SPARC_FORMAT3(tme_sparc32_stdcq, tme_uint32_t) ! 82: { ! 83: TME_SPARC_INSN_PRIV; ! 84: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction); ! 85: } ! 86: ! 87: TME_SPARC_FORMAT3(tme_sparc32_rdasr, tme_uint32_t) ! 88: { ! 89: unsigned int reg_rs1; ! 90: unsigned int reg_rd; ! 91: tme_uint32_t value; ! 92: ! 93: reg_rs1 = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, (0x1f << 14)); ! 94: reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD); ! 95: ! 96: /* rdy: */ ! 97: if (reg_rs1 == 0) { ! 98: value = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_Y); ! 99: } ! 100: ! 101: /* stbar: */ ! 102: else if (reg_rs1 == 15 && reg_rd == 0) { ! 103: TME_SPARC_INSN_OK; ! 104: } ! 105: ! 106: else { ! 107: ! 108: /* all other rdasr instructions are privileged: */ ! 109: TME_SPARC_INSN_PRIV; ! 110: ! 111: value = 0; ! 112: abort(); ! 113: } ! 114: ! 115: TME_SPARC_FORMAT3_RD = value; ! 116: TME_SPARC_INSN_OK; ! 117: } ! 118: ! 119: TME_SPARC_FORMAT3(tme_sparc32_rdpsr, tme_uint32_t) ! 120: { ! 121: TME_SPARC_INSN_PRIV; ! 122: TME_SPARC_FORMAT3_RD = ic->tme_sparc32_ireg_psr; ! 123: ! 124: /* the sunos32-type-0 idle type is detected when a "rd %psr, %l0" ! 125: instruction is followed three instructions later (in disassembly ! 126: order, not execution order) by a "mov %g1, %psr" that sets PIL ! 127: to 0xa, and the next write to %psr is a "mov %g1, %psr" that sets ! 128: PIL to 0x0 and is followed by a branch (to the idle loop): */ ! 129: if (__tme_predict_false((TME_SPARC_INSN ! 130: & ~((31 << 14) /* rs1 (reserved) */ ! 131: | (1 << 13) /* i (reserved) */ ! 132: | 0x1fff)) /* imm13 (reserved) */ ! 133: == ((tme_uint32_t) ! 134: (2 << 30) /* format */ ! 135: | (0x10 << 25) /* rd (%l0) */ ! 136: | (0x29 << 19)))) { /* op3 (rdpsr) */ ! 137: /* if we haven't detected the idle loop yet, remember the address ! 138: of this "rd %psr, %l0" instruction and enter state one: */ ! 139: if (__tme_predict_false(TME_SPARC_IDLE_TYPE_PC_STATE(ic->tme_sparc_idle_type_pc32) != 0)) { ! 140: if (TME_SPARC_IDLE_TYPE_IS(ic, TME_SPARC_IDLE_TYPE_SUNOS32_TYPE_0)) { ! 141: ic->tme_sparc_idle_type_pc32 ! 142: = (ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC) ! 143: + TME_SPARC_IDLE_TYPE_PC_STATE(1)); ! 144: } ! 145: } ! 146: } ! 147: ! 148: TME_SPARC_INSN_OK; ! 149: } ! 150: ! 151: TME_SPARC_FORMAT3(tme_sparc32_rdwim, tme_uint32_t) ! 152: { ! 153: TME_SPARC_INSN_PRIV; ! 154: TME_SPARC_FORMAT3_RD = ic->tme_sparc32_ireg_wim; ! 155: TME_SPARC_INSN_OK; ! 156: } ! 157: ! 158: TME_SPARC_FORMAT3(tme_sparc32_rdtbr, tme_uint32_t) ! 159: { ! 160: TME_SPARC_INSN_PRIV; ! 161: TME_SPARC_FORMAT3_RD = ic->tme_sparc32_ireg_tbr; ! 162: TME_SPARC_INSN_OK; ! 163: } ! 164: ! 165: TME_SPARC_FORMAT3(tme_sparc32_wrasr, tme_uint32_t) ! 166: { ! 167: unsigned int reg_rd; ! 168: tme_uint32_t value_xor; ! 169: ! 170: reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD); ! 171: value_xor = TME_SPARC_FORMAT3_RS1 ^ TME_SPARC_FORMAT3_RS2; ! 172: ! 173: /* "WRY ... writes r[rs1] xor r[rs2] if the i field is zero, or ! 174: r[rs1] xor sign_ext(simm13) if the i field is one, to the ! 175: writable fields of the specified IU state register. (Note the ! 176: exclusive-or operation.) Note that WRY is distinguished from ! 177: WRASR only by the rd field. The rd field must be zero and op3 = ! 178: 0x30 to write the Y register." */ ! 179: if (reg_rd == 0) { ! 180: ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_Y) = value_xor; ! 181: } ! 182: ! 183: else { ! 184: ! 185: /* all other wrasr instructions are privileged: */ ! 186: TME_SPARC_INSN_PRIV; ! 187: ! 188: abort(); ! 189: } ! 190: ! 191: TME_SPARC_INSN_OK; ! 192: } ! 193: ! 194: TME_SPARC_FORMAT3(tme_sparc32_wrpsr, tme_uint32_t) ! 195: { ! 196: tme_uint32_t value; ! 197: tme_uint32_t mask_writable; ! 198: tme_uint32_t insn; ! 199: unsigned int cwp; ! 200: ! 201: TME_SPARC_INSN_PRIV; ! 202: ! 203: /* "WRPSR ... writes r[rs1] xor r[rs2] if the i field is zero, or ! 204: r[rs1] xor sign_ext(simm13) if the i field is one, to the ! 205: writable fields of the specified IU state register. (Note the ! 206: exclusive-or operation.)" */ ! 207: value = TME_SPARC_FORMAT3_RS1 ^ TME_SPARC_FORMAT3_RS2; ! 208: ! 209: /* "If the result of a WRPSR instruction would cause the CWP field ! 210: of the PSR to point to an unimplemented window, it causes an ! 211: illegal_instruction trap and does not write the PSR." */ ! 212: cwp = TME_FIELD_MASK_EXTRACTU(value, TME_SPARC32_PSR_CWP); ! 213: if (__tme_predict_false(cwp >= ic->tme_sparc_nwindows)) { ! 214: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction); ! 215: } ! 216: ! 217: /* set the new CWP offset: */ ! 218: ic->tme_sparc_cwp_offset = TME_SPARC_CWP_OFFSET(cwp); ! 219: ! 220: /* set the new PSR value: */ ! 221: mask_writable = (TME_SPARC32_PSR_ICC ! 222: | TME_SPARC32_PSR_EC ! 223: | TME_SPARC32_PSR_EF ! 224: | TME_SPARC32_PSR_PIL ! 225: | TME_SPARC32_PSR_S ! 226: | TME_SPARC32_PSR_PS ! 227: | TME_SPARC32_PSR_ET ! 228: | TME_SPARC32_PSR_CWP); ! 229: value = (value & mask_writable) | (ic->tme_sparc32_ireg_psr & ~mask_writable); ! 230: ic->tme_sparc32_ireg_psr = value; ! 231: ! 232: /* the netbsd32-type-0 idle type is detected when an annulled "wr ! 233: %g1, PSR_PIL, %psr" or "wr %l1, (IPL_SCHED << 8), %psr" ! 234: instruction is found four instructions after (in disassembly ! 235: order, not execution order) a "wr %g1, 0, %psr" or "wr %l1, 0, ! 236: %psr" instruction that sets PIL to 0x0: */ ! 237: if (__tme_predict_false((TME_SPARC_INSN ! 238: & ~((31 << 25) /* rd (reserved) */ ! 239: | (0x10 << 14))) /* rs1 (mask %ln to %gn) */ ! 240: == ((tme_uint32_t) ! 241: (2 << 30) /* format */ ! 242: | (0x31 << 19) /* op3 (wrpsr) */ ! 243: | (0x01 << 14) /* rs1 (%g1) */ ! 244: | (1 << 13) /* i */ ! 245: | 0x0000))) { /* imm13 (0) */ ! 246: if (__tme_predict_false(TME_SPARC_IDLE_TYPE_PC_STATE(ic->tme_sparc_idle_type_pc32) != 0)) { ! 247: if (TME_SPARC_IDLE_TYPE_IS(ic, TME_SPARC_IDLE_TYPE_NETBSD32_TYPE_0) ! 248: && ((value & TME_SPARC32_PSR_PIL) ! 249: == (0x0 * _TME_FIELD_MASK_FACTOR(TME_SPARC32_PSR_PIL)))) { ! 250: ic->tme_sparc_idle_type_pc32 ! 251: = (ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC) ! 252: + TME_SPARC_IDLE_TYPE_PC_STATE(1)); ! 253: } ! 254: } ! 255: } ! 256: ! 257: /* the sunos32-type-0 idle type is detected when a "rd %psr, %l0" ! 258: instruction is followed three instructions later (in disassembly ! 259: order, not execution order) by a "mov %g1, %psr" that sets PIL ! 260: to 0xa, and the next write to %psr is a "mov %g1, %psr" that sets ! 261: PIL to 0x0 and is followed by a branch (to the idle loop): */ ! 262: if (__tme_predict_false(TME_SPARC_IDLE_TYPE_IS(ic, TME_SPARC_IDLE_TYPE_SUNOS32_TYPE_0))) { ! 263: ! 264: /* if we haven't detected the idle loop yet: */ ! 265: if (__tme_predict_false(TME_SPARC_IDLE_TYPE_PC_STATE(ic->tme_sparc_idle_type_pc32) != 0)) { ! 266: ! 267: /* if this is a "mov %g1, %psr" instruction: */ ! 268: if (__tme_predict_false((TME_SPARC_INSN ! 269: & ~((31 << 25) /* rd (reserved) */ ! 270: | 255 << 5)) /* unused (zero) */ ! 271: == ((tme_uint32_t) ! 272: (2 << 30) /* format */ ! 273: | (0x31 << 19) /* op3 (wrpsr) */ ! 274: | (0x01 << 14) /* rs1 (%g1) */ ! 275: | (0 << 13) /* i */ ! 276: | (0 << 0)))) { /* rs2 (%g0) */ ! 277: ! 278: /* if this "mov %g1, %psr" instruction is three instructions ! 279: in disassembly order after a "rd %psr, %l0" instruction and ! 280: sets PIL to 0xa: */ ! 281: if ((ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC) ! 282: == (ic->tme_sparc_idle_type_pc32 ! 283: - TME_SPARC_IDLE_TYPE_PC_STATE(1) ! 284: + (sizeof(tme_uint32_t) * 3))) ! 285: && ((value & TME_SPARC32_PSR_PIL) ! 286: == (0xa * _TME_FIELD_MASK_FACTOR(TME_SPARC32_PSR_PIL)))) { ! 287: ! 288: /* advance to the next state: */ ! 289: ic->tme_sparc_idle_type_pc32 = TME_SPARC_IDLE_TYPE_PC_STATE(3); ! 290: } ! 291: ! 292: /* otherwise, if we detected a "mov %g1, %psr" instruction ! 293: three instructions in disassembly order after a "rd %psr, ! 294: %l0" instruction, and this "mov %g1, %psr" instruction sets ! 295: PIL to 0x0, and the next instruction is an unconditional ! 296: branch with an annulled delay slot: */ ! 297: else if (ic->tme_sparc_idle_type_pc32 == TME_SPARC_IDLE_TYPE_PC_STATE(3) ! 298: && ((value & TME_SPARC32_PSR_PIL) ! 299: == (0x0 * _TME_FIELD_MASK_FACTOR(TME_SPARC32_PSR_PIL))) ! 300: && (((insn = tme_sparc_fetch_nearby(ic, 1)) ! 301: & ~((0x3fffff << 0))) /* disp22 */ ! 302: == ((0 << 30) /* format */ ! 303: | (1 << 29) /* a */ ! 304: | (8 << 25) /* cond (Always) */ ! 305: | (2 << 22)))) { /* op2 (bicc) */ ! 306: ! 307: /* we have detected the address of the idle loop: */ ! 308: ic->tme_sparc_idle_type_pc32 ! 309: = (ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC) ! 310: + sizeof(tme_uint32_t) ! 311: + (TME_FIELD_MASK_EXTRACTS(insn, (tme_uint32_t) 0x003fffff) << 2)); ! 312: } ! 313: ! 314: /* otherwise, this is some other "mov %g1, %psr" instruction, ! 315: or we couldn't fetch the next instruction or it isn't the ! 316: expected branch: */ ! 317: else { ! 318: ! 319: /* poison the idle type state: */ ! 320: ic->tme_sparc_idle_type_pc32 = TME_SPARC_IDLE_TYPE_PC_STATE(1); ! 321: } ! 322: } ! 323: ! 324: /* otherwise, this is some other wrpsr instruction: */ ! 325: else { ! 326: ! 327: /* poison the idle type state: */ ! 328: ic->tme_sparc_idle_type_pc32 = TME_SPARC_IDLE_TYPE_PC_STATE(1); ! 329: } ! 330: } ! 331: } ! 332: ! 333: /* redispatch, since the executor may have cached information ! 334: derived from the PSR (for example, default data ASI, ITLB, etc.) ! 335: that we need to invalidate: */ ! 336: tme_sparc_redispatch(ic); ! 337: /* NOTREACHED */ ! 338: } ! 339: ! 340: TME_SPARC_FORMAT3(tme_sparc32_wrwim, tme_uint32_t) ! 341: { ! 342: tme_uint32_t value; ! 343: ! 344: TME_SPARC_INSN_PRIV; ! 345: ! 346: /* "WRWIM ... writes r[rs1] xor r[rs2] if the i field is zero, or ! 347: r[rs1] xor sign_ext(simm13) if the i field is one, to the ! 348: writable fields of the specified IU state register. (Note the ! 349: exclusive-or operation.)" */ ! 350: value = TME_SPARC_FORMAT3_RS1 ^ TME_SPARC_FORMAT3_RS2; ! 351: ! 352: /* "A WRWIM with all bits set to 1, followed by a RDWIM, yields a ! 353: bit vector in which the imple- mented windows (and only the ! 354: implemented windows) are indicated by 1s." */ ! 355: value &= (0xffffffff >> (32 - ic->tme_sparc_nwindows)); ! 356: ! 357: ic->tme_sparc32_ireg_wim = value; ! 358: ! 359: TME_SPARC_INSN_OK; ! 360: } ! 361: ! 362: TME_SPARC_FORMAT3(tme_sparc32_wrtbr, tme_uint32_t) ! 363: { ! 364: tme_uint32_t value; ! 365: ! 366: TME_SPARC_INSN_PRIV; ! 367: ! 368: /* "WRTBR ... writes r[rs1] xor r[rs2] if the i field is zero, or ! 369: r[rs1] xor sign_ext(simm13) if the i field is one, to the ! 370: writable fields of the specified IU state register. (Note the ! 371: exclusive-or operation.)" */ ! 372: value = TME_SPARC_FORMAT3_RS1 ^ TME_SPARC_FORMAT3_RS2; ! 373: ! 374: /* "Bits 11 through 4 comprise the trap type (tt) field. This 8-bit ! 375: field is written by the hardware when a trap occurs, and retains ! 376: its value until the next trap. It provides an offset into the ! 377: trap table. The WRTBR instruction does not affect the tt ! 378: field. TBR_zero (0) Bits 3 through 0 are zeroes. The WRTBR ! 379: instruction does not affect this field. For future compatibility, ! 380: supervisor software should only issue a WRTBR instruction with a ! 381: zero value in this field." */ ! 382: value = (value & 0xfffff000) | (ic->tme_sparc32_ireg_tbr & 0x00000ff0); ! 383: ic->tme_sparc32_ireg_tbr = value; ! 384: ! 385: TME_SPARC_INSN_OK; ! 386: } ! 387: ! 388: TME_SPARC_FORMAT3(tme_sparc32_flush, tme_uint32_t) ! 389: { ! 390: /* nothing to do */ ! 391: TME_SPARC_INSN_OK; ! 392: } ! 393: ! 394: TME_SPARC_FORMAT3(tme_sparc32_rett, tme_uint32_t) ! 395: { ! 396: tme_uint32_t psr; ! 397: unsigned int cwp; ! 398: tme_uint32_t pc_next_next; ! 399: ! 400: /* "One of several traps may occur when an RETT is executed. These ! 401: are described in priority order (highest priority first): ! 402: ! 403: If traps are enabled (ET=1) and the processor is in user mode ! 404: (S=0), a privileged_instruction trap occurs. ! 405: ! 406: If traps are enabled (ET=1) and the processor is in supervisor ! 407: mode (S=1), an illegal_instruction trap occurs. ! 408: ! 409: If traps are disabled (ET=0), and (a) the processor is in user ! 410: mode (S=0), or (b) a window_underflow condition is detected (WIM ! 411: and 2^new_CWP ) = 1, or (c) either of the low-order two bits of ! 412: the target address is nonzero, then the processor indicates a ! 413: trap condition of (a) privileged_instruction, (b) ! 414: window_underflow, or (c) mem_address_not_aligned (respectively) ! 415: in the tt field of the TBR register, and enters the error_mode ! 416: state." */ ! 417: psr = ic->tme_sparc32_ireg_psr; ! 418: ! 419: if (__tme_predict_false((psr & TME_SPARC32_PSR_S) == 0)) { ! 420: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_privileged_instruction); ! 421: } ! 422: ! 423: if (__tme_predict_false((psr & TME_SPARC32_PSR_ET) != 0)) { ! 424: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction); ! 425: } ! 426: ! 427: cwp = TME_FIELD_MASK_EXTRACTU(psr, TME_SPARC32_PSR_CWP); ! 428: cwp += 1; ! 429: cwp %= ic->tme_sparc_nwindows; ! 430: if (ic->tme_sparc32_ireg_wim & (((tme_uint32_t) 1) << cwp)) { ! 431: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_window_underflow); ! 432: } ! 433: ! 434: pc_next_next = TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2; ! 435: if (__tme_predict_false((pc_next_next % sizeof(tme_uint32_t)) != 0)) { ! 436: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_mem_address_not_aligned); ! 437: } ! 438: ! 439: /* set the new PSR: */ ! 440: TME_FIELD_MASK_DEPOSITU(psr, TME_SPARC32_PSR_CWP, cwp); ! 441: psr |= TME_SPARC32_PSR_ET; ! 442: psr &= ~TME_SPARC32_PSR_S; ! 443: psr |= ((psr & TME_SPARC32_PSR_PS) * (TME_SPARC32_PSR_S / TME_SPARC32_PSR_PS)); ! 444: ic->tme_sparc32_ireg_psr = psr; ! 445: ! 446: /* set the new CWP offset: */ ! 447: ic->tme_sparc_cwp_offset = TME_SPARC_CWP_OFFSET(cwp); ! 448: ! 449: /* set the delayed control transfer: */ ! 450: ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT_NEXT) = pc_next_next; ! 451: ! 452: /* redispatch, since the executor may have cached information ! 453: derived from the PSR (for example, default data ASI, ITLB, etc.) ! 454: that we need to invalidate: */ ! 455: tme_sparc_redispatch(ic); ! 456: } ! 457: ! 458: TME_SPARC_FORMAT3(tme_sparc32_save_restore, tme_uint32_t) ! 459: { ! 460: int direction; ! 461: tme_uint32_t psr; ! 462: unsigned int cwp; ! 463: unsigned int cwp_offset; ! 464: unsigned int reg_rd; ! 465: ! 466: /* calculate the window direction: */ ! 467: direction = -1 + (((TME_SPARC_INSN & TME_BIT(19)) != 0) * 2); ! 468: ! 469: /* calculate the new CWP: */ ! 470: psr = ic->tme_sparc32_ireg_psr; ! 471: cwp = TME_FIELD_MASK_EXTRACTU(psr, TME_SPARC32_PSR_CWP); ! 472: cwp += direction; ! 473: cwp %= ic->tme_sparc_nwindows; ! 474: ! 475: /* if the new window is invalid: */ ! 476: if (__tme_predict_false((ic->tme_sparc32_ireg_wim & (((tme_uint32_t) 1) << cwp)) != 0)) { ! 477: TME_SPARC_INSN_TRAP((direction < 0) ! 478: ? TME_SPARC_TRAP_window_overflow ! 479: : TME_SPARC_TRAP_window_underflow); ! 480: } ! 481: ! 482: /* write the new PSR: */ ! 483: TME_FIELD_MASK_DEPOSITU(psr, TME_SPARC32_PSR_CWP, cwp); ! 484: ic->tme_sparc32_ireg_psr = psr; ! 485: ! 486: /* set the new CWP offset: */ ! 487: cwp_offset = TME_SPARC_CWP_OFFSET(cwp); ! 488: ic->tme_sparc_cwp_offset = cwp_offset; ! 489: ! 490: /* decode rd: */ ! 491: reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD); ! 492: TME_SPARC_REG_INDEX(ic, reg_rd); ! 493: ! 494: /* do the add: */ ! 495: ic->tme_sparc_ireg_uint32(reg_rd) = TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2; ! 496: ! 497: TME_SPARC_INSN_OK; ! 498: } ! 499: ! 500: TME_SPARC_FORMAT3(tme_sparc32_ticc, tme_uint32_t) ! 501: { ! 502: tme_uint8_t conds_mask_icc; ! 503: tme_uint16_t conds_mask; ! 504: unsigned int cond; ! 505: ! 506: conds_mask_icc = _tme_sparc_conds_icc[TME_FIELD_MASK_EXTRACTU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_ICC)]; ! 507: ! 508: /* add the not-conditions to the conditions mask: */ ! 509: conds_mask = conds_mask_icc ^ 0xff; ! 510: conds_mask = (conds_mask << 8) | conds_mask_icc; ! 511: ! 512: /* get the condition field: */ ! 513: cond = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, (0xf << 25)); ! 514: ! 515: /* if this condition is true: */ ! 516: if (conds_mask & TME_BIT(cond)) { ! 517: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_trap_instruction((TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2) & 0x7f)); ! 518: } ! 519: ! 520: TME_SPARC_INSN_OK; ! 521: } ! 522: ! 523: TME_SPARC_FORMAT3(tme_sparc32_fpop1, tme_uint32_t) ! 524: { ! 525: tme_sparc_fpu_fpop1(ic); ! 526: TME_SPARC_INSN_OK; ! 527: } ! 528: TME_SPARC_FORMAT3(tme_sparc32_fpop2, tme_uint32_t) ! 529: { ! 530: tme_sparc_fpu_fpop2(ic); ! 531: TME_SPARC_INSN_OK; ! 532: } ! 533: ! 534: #include "sparc-insns-auto.c"
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.