|
|
1.1.1.2 ! root 1: /* $Id: sparc-execute.c,v 1.10 2010/02/20 21:58:15 fredette Exp $ */ 1.1 root 2: 3: /* ic/sparc/sparc-execute.c - executes SPARC instructions: */ 4: 5: /* 1.1.1.2 ! root 6: * Copyright (c) 2005, 2009 Matt Fredette 1.1 root 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: 1.1.1.2 ! root 36: _TME_RCSID("$Id: sparc-execute.c,v 1.10 2010/02/20 21:58:15 fredette Exp $"); 1.1 root 37: 38: /* includes: */ 39: #include "sparc-auto.h" 40: 41: #if (TME_SPARC_VERSION(ic) < 9) 42: #define tme_sparc_ireg_t tme_uint32_t 43: #define tme_sparc_ireg(x) tme_sparc_ireg_uint32(x) 1.1.1.2 ! root 44: #define tme_sparc_idle_pcs tme_sparc_idle_pcs_32 ! 45: #define TME_PRIxSPARCREG "0x%08" TME_PRIx32 1.1 root 46: #else /* TME_SPARC_VERSION(ic) >= 9 */ 47: #define tme_sparc_ireg_t tme_uint64_t 48: #define tme_sparc_ireg(x) tme_sparc_ireg_uint64(x) 1.1.1.2 ! root 49: #define tme_sparc_idle_pcs tme_sparc_idle_pcs_64 ! 50: #define TME_PRIxSPARCREG "0x%016" TME_PRIx64 1.1 root 51: #endif /* TME_SPARC_VERSION(ic) >= 9 */ 52: 53: /* the sparc instruction executor: */ 54: static void 55: _TME_SPARC_EXECUTE_NAME(struct tme_sparc *ic) 56: { 57: tme_uint32_t asi_mask_insn; 58: tme_uint32_t asi_mask_data; 59: struct tme_sparc_tlb *itlb_current; 60: struct tme_sparc_tlb itlb_invalid; 1.1.1.2 ! root 61: struct tme_token token_invalid; ! 62: tme_sparc_ireg_t pc_previous; 1.1 root 63: tme_sparc_ireg_t pc; 64: tme_uint32_t insn; 1.1.1.2 ! root 65: tme_uint32_t tlb_hash; ! 66: const tme_shared tme_uint8_t *emulator_off; 1.1 root 67: unsigned int opcode; 68: unsigned int reg_rs1; 69: unsigned int reg_rs2; 70: unsigned int reg_rd; 71: int annulled; 1.1.1.2 ! root 72: int branch_dot; ! 73: tme_uint32_t branch_dot_burst; ! 74: #if TME_SPARC_VERSION(ic) >= 9 ! 75: unsigned int cc; ! 76: tme_uint64_t value_rs1; ! 77: #endif /* TME_SPARC_VERSION(ic) >= 9 */ 1.1 root 78: tme_uint8_t conds_mask_icc; 79: tme_uint8_t conds_mask_fcc; 80: tme_uint16_t conds_mask; 81: unsigned int cond; 1.1.1.2 ! root 82: tme_int32_t disp; ! 83: tme_sparc_ireg_t pc_next_next; ! 84: unsigned int reg_o0; 1.1 root 85: 86: /* get the default address space identifiers and masks: */ 87: if (TME_SPARC_VERSION(ic) < 9) { 88: if (TME_SPARC_PRIV(ic)) { 89: asi_mask_insn = TME_SPARC32_ASI_MASK_SI; 90: asi_mask_data = TME_SPARC32_ASI_MASK_SD; 91: } 92: else { 93: asi_mask_insn = TME_SPARC32_ASI_MASK_UI; 94: asi_mask_data = TME_SPARC32_ASI_MASK_UD; 95: } 96: } 97: else { 1.1.1.2 ! root 98: if (__tme_predict_false((TME_SPARC_MEMORY_FLAGS(ic) & TME_SPARC_MEMORY_FLAG_HAS_NUCLEUS) ! 99: && ic->tme_sparc64_ireg_tl > 0)) { ! 100: asi_mask_insn ! 101: = TME_SPARC64_ASI_MASK_NUCLEUS(!TME_SPARC64_ASI_FLAG_LITTLE); ! 102: ic->tme_sparc_memory_context_default = 0; ! 103: } ! 104: else { ! 105: asi_mask_insn ! 106: = TME_SPARC64_ASI_MASK_REQUIRED_UNRESTRICTED((TME_SPARC_PRIV(ic) ! 107: ? !TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER ! 108: : TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER) ! 109: + !TME_SPARC64_ASI_FLAG_SECONDARY ! 110: + !TME_SPARC64_ASI_FLAG_NO_FAULT ! 111: + !TME_SPARC64_ASI_FLAG_LITTLE); ! 112: ic->tme_sparc_memory_context_default = ic->tme_sparc_memory_context_primary; ! 113: } ! 114: asi_mask_data = asi_mask_insn; ! 115: if (__tme_predict_false(ic->tme_sparc64_ireg_pstate & TME_SPARC64_PSTATE_CLE)) { ! 116: assert ((TME_SPARC64_ASI_MASK_NUCLEUS(!TME_SPARC64_ASI_FLAG_LITTLE) ! 117: ^ TME_SPARC64_ASI_MASK_NUCLEUS(TME_SPARC64_ASI_FLAG_LITTLE)) ! 118: == (TME_SPARC64_ASI_MASK_REQUIRED_UNRESTRICTED(!TME_SPARC64_ASI_FLAG_LITTLE) ! 119: ^ TME_SPARC64_ASI_MASK_REQUIRED_UNRESTRICTED(TME_SPARC64_ASI_FLAG_LITTLE))); ! 120: asi_mask_data ! 121: ^= (TME_SPARC64_ASI_MASK_NUCLEUS(!TME_SPARC64_ASI_FLAG_LITTLE) ! 122: ^ TME_SPARC64_ASI_MASK_NUCLEUS(TME_SPARC64_ASI_FLAG_LITTLE)); ! 123: } 1.1 root 124: } 125: ic->tme_sparc_asi_mask_insn = asi_mask_insn; 126: ic->tme_sparc_asi_mask_data = asi_mask_data; 127: 1.1.1.2 ! root 128: #if TME_SPARC_HAVE_RECODE(ic) ! 129: ! 130: /* set the recode read/write TLB flags mask to and with the flags ! 131: from a read/write thunk, before being tested against the flags in ! 132: a recode DTLB entry. this TLB flags mask must clear flags that ! 133: do not apply, based on the current state: */ ! 134: ic->tme_sparc_recode_rw_tlb_flags ! 135: = (TME_RECODE_TLB_FLAGS_MASK(ic->tme_sparc_recode_ic) ! 136: - ( ! 137: ! 138: /* the load and store flags for the other privilege level do ! 139: not apply, because we're not at that privilege level: */ ! 140: (TME_SPARC_PRIV(ic) ! 141: ? (TME_SPARC_RECODE_TLB_FLAG_LD_USER(ic) ! 142: + TME_SPARC_RECODE_TLB_FLAG_ST_USER(ic)) ! 143: : (TME_SPARC_RECODE_TLB_FLAG_LD_PRIV(ic) ! 144: + TME_SPARC_RECODE_TLB_FLAG_ST_PRIV(ic))) ! 145: ! 146: /* on a v9 CPU, if the ASI register has the default data ! 147: ASI, but with the no-fault bit set, the ASI register is ! 148: correct for no-fault loads, and the no-fault load bit ! 149: doesn't apply: */ ! 150: + ((TME_SPARC_VERSION(ic) >= 9 ! 151: && ((TME_SPARC_MEMORY_FLAGS(ic) & TME_SPARC_MEMORY_FLAG_HAS_NUCLEUS) == 0 ! 152: || ic->tme_sparc64_ireg_tl == 0) ! 153: && (ic->tme_sparc64_ireg_asi ! 154: == (TME_SPARC_ASI_MASK_WHICH(asi_mask_data) ! 155: + TME_SPARC64_ASI_FLAG_NO_FAULT))) ! 156: ? TME_SPARC_RECODE_TLB_FLAG_LD_NF(ic) ! 157: : 0))); ! 158: ! 159: /* set the recode chain TLB flags mask to and with the flags from ! 160: the chain thunk, before being tested against the flags in a ! 161: recode ITLB entry. this TLB flags mask must clear flags that do ! 162: not apply, based on the current state: */ ! 163: ic->tme_sparc_recode_chain_tlb_flags ! 164: = (TME_RECODE_TLB_FLAGS_MASK(ic->tme_sparc_recode_ic) ! 165: - ( ! 166: ! 167: /* the fetch flags for the other privilege level do not ! 168: apply, because we're not at that privilege level: */ ! 169: (TME_SPARC_PRIV(ic) ! 170: ? TME_SPARC_RECODE_TLB_FLAG_CHAIN_USER(ic) ! 171: : TME_SPARC_RECODE_TLB_FLAG_CHAIN_PRIV(ic)) ! 172: )); ! 173: ! 174: #endif /* TME_SPARC_HAVE_RECODE(ic) */ ! 175: 1.1 root 176: /* create an invalid instruction TLB entry, and use it as the initial 177: current instruction TLB entry: */ 1.1.1.2 ! root 178: tme_token_init(&token_invalid); 1.1 root 179: itlb_invalid.tme_sparc_tlb_addr_first = 1; 180: itlb_invalid.tme_sparc_tlb_addr_last = 0; 1.1.1.2 ! root 181: itlb_invalid.tme_sparc_tlb_bus_tlb.tme_bus_tlb_token = &token_invalid; 1.1 root 182: itlb_current = &itlb_invalid; 183: 184: /* busy the invalid instruction TLB entry: */ 1.1.1.2 ! root 185: assert (ic->_tme_sparc_itlb_current_token == NULL); ! 186: tme_token_busy(&token_invalid); ! 187: ic->_tme_sparc_itlb_current_token = &token_invalid; 1.1 root 188: 189: /* the first instruction will not be annulled: */ 190: annulled = FALSE; 191: 1.1.1.2 ! root 192: /* the last instruction was not a taken branch to .: */ ! 193: branch_dot = FALSE; ! 194: branch_dot_burst = 0; ! 195: 1.1 root 196: for (;;) { 197: 198: /* if we have used up our instruction burst: */ 199: if (__tme_predict_false(ic->_tme_sparc_instruction_burst_remaining == 0)) { 200: 1.1.1.2 ! root 201: /* if the last instruction was a taken branch to .: */ ! 202: if (__tme_predict_false(branch_dot)) { 1.1 root 203: 1.1.1.2 ! root 204: /* clear the taken branch to . flag and restore the ! 205: instruction burst that had been remaining: */ ! 206: branch_dot = FALSE; ! 207: ic->_tme_sparc_instruction_burst_remaining = branch_dot_burst; ! 208: ! 209: /* if the next instruction will be annulled: */ ! 210: if (__tme_predict_false(annulled)) { ! 211: ! 212: /* a taken branch to . that annuls its branch delay slot ! 213: must be a "ba,a .", since taken conditional branches ! 214: never annul. "ba,a ." makes an infinite loop. ! 215: ! 216: we can just go idle here, but we must make sure that any ! 217: trap sees %pc on the branch to ., and not its branch ! 218: delay slot (since we don't track the annulled bit in the ! 219: processor structure), and we must make sure that %pc_next ! 220: is the branch to . delay slot (because otherwise it would ! 221: look like we didn't loop even once): */ ! 222: ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT) ! 223: = ic->tme_sparc_ireg(TME_SPARC_IREG_PC); ! 224: ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT_NEXT) ! 225: = (ic->tme_sparc_ireg(TME_SPARC_IREG_PC) ! 226: + sizeof(tme_uint32_t)); ! 227: if (TME_SPARC_VERSION(ic) >= 9) { ! 228: ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT_NEXT) &= ic->tme_sparc_address_mask; ! 229: } ! 230: tme_sparc_do_idle(ic); ! 231: /* NOTREACHED */ ! 232: } ! 233: ! 234: /* if the branch delay instruction immediately follows the ! 235: branch to .: */ ! 236: if (ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT) ! 237: == (ic->tme_sparc_ireg(TME_SPARC_IREG_PC) ! 238: + sizeof(tme_uint32_t))) { ! 239: ! 240: /* if this branch to . is not a timing loop, this will ! 241: return. if it's a timing loop that doesn't sleep, this ! 242: will return. otherwise, this won't return: */ ! 243: tme_sparc_timing_loop_start(ic); ! 244: } ! 245: ! 246: /* continue now, to finish the instruction burst that ! 247: had been remaining: */ ! 248: continue; ! 249: } ! 250: ! 251: /* if this was a full instruction burst: */ ! 252: if (!ic->_tme_sparc_instruction_burst_other) { ! 253: ! 254: /* if it's time to update the runlength: */ ! 255: if (ic->tme_sparc_runlength_update_next == 0) { ! 256: ! 257: /* update the runlength: */ ! 258: #ifndef _TME_SPARC_RECODE_VERIFY ! 259: tme_runlength_update(&ic->tme_sparc_runlength); ! 260: #endif /* !_TME_SPARC_RECODE_VERIFY */ ! 261: ! 262: /* start another runlength update period: */ ! 263: ic->tme_sparc_runlength_update_next = ic->tme_sparc_runlength_update_period; ! 264: } ! 265: ! 266: /* advance in the runlength update period: */ ! 267: ic->tme_sparc_runlength_update_next--; ! 268: ! 269: /* we are not in a full instruction burst: */ ! 270: ic->_tme_sparc_instruction_burst_other = TRUE; ! 271: } ! 272: ! 273: /* if the next instruction will be annulled: */ ! 274: if (__tme_predict_false(annulled)) { ! 275: ! 276: /* NB that we have to handle the next instruction now, in the ! 277: immediate next iteration of the execution loop, since we ! 278: don't track the annulled bit in the processor structure, ! 279: and we want to do good emulation and actually fetch the ! 280: instruction (as opposed to just advancing the PCs now). ! 281: start an instruction burst of one instruction: */ ! 282: ic->_tme_sparc_instruction_burst_remaining = 1; ! 283: continue; ! 284: } ! 285: ! 286: /* if we need to do an external check: */ ! 287: if (tme_memory_atomic_read_flag(&ic->tme_sparc_external_flag)) { ! 288: ! 289: /* do an external check: */ ! 290: tme_memory_atomic_write_flag(&ic->tme_sparc_external_flag, FALSE); ! 291: tme_memory_barrier(ic, sizeof(*ic), TME_MEMORY_BARRIER_READ_BEFORE_READ); ! 292: (*ic->_tme_sparc_external_check)(ic, TME_SPARC_EXTERNAL_CHECK_NULL); 1.1 root 293: } 294: 295: /* start a new instruction burst: */ 296: ic->_tme_sparc_instruction_burst_remaining 297: = ic->_tme_sparc_instruction_burst; 1.1.1.2 ! root 298: ic->_tme_sparc_instruction_burst_other = FALSE; ! 299: ! 300: /* if the next PC might be in an idle PC range: */ ! 301: pc = ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT); ! 302: if (__tme_predict_false(pc < ic->tme_sparc_idle_pcs[1])) { ! 303: ! 304: /* if we haven't detected the idle PC yet: */ ! 305: if (__tme_predict_false(TME_SPARC_IDLE_TYPE_PC_STATE(ic->tme_sparc_idle_pcs[0]) != 0)) { ! 306: /* nothing to do */ ! 307: } ! 308: ! 309: /* if the next PC and the delay PC are both in the idle PC ! 310: range, and this idle type has an idle PC range: */ ! 311: else if (__tme_predict_false(pc >= ic->tme_sparc_idle_pcs[0])) { ! 312: if (TME_SPARC_IDLE_TYPE_IS(ic, TME_SPARC_IDLE_TYPES_PC_RANGE) ! 313: && ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT_NEXT) >= ic->tme_sparc_idle_pcs[0] ! 314: && ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT_NEXT) < ic->tme_sparc_idle_pcs[1]) { ! 315: ! 316: /* if we haven't marked any idles yet, or if we have ! 317: marked one and the next PC is at or behind that PC: */ ! 318: if (ic->tme_sparc_idle_marks == 0 ! 319: || (ic->tme_sparc_idle_marks == 1 ! 320: && pc <= ic->tme_sparc_idle_pcs[2])) { ! 321: ! 322: /* mark the idle: */ ! 323: ic->tme_sparc_idle_marks++; ! 324: ! 325: /* we won't mark another idle until we detect a ! 326: backwards control transfer in the idle PC range, ! 327: indicating another iteration of the idle loop: */ ! 328: ic->tme_sparc_idle_pcs[2] = pc; ! 329: } ! 330: } ! 331: } ! 332: } ! 333: ! 334: /* if we have marked any idles: */ ! 335: if (__tme_predict_false(ic->tme_sparc_idle_marks != 0)) { ! 336: ! 337: /* if we have marked one idle: */ ! 338: if (ic->tme_sparc_idle_marks == 1) { ! 339: ! 340: /* start a new idle instruction burst: */ ! 341: ic->_tme_sparc_instruction_burst_remaining ! 342: = ic->_tme_sparc_instruction_burst_idle; ! 343: ic->_tme_sparc_instruction_burst_other = TRUE; ! 344: } ! 345: ! 346: /* otherwise, we have marked two consecutive idles without a ! 347: trap: */ ! 348: else { ! 349: assert (ic->tme_sparc_idle_marks == 2); 1.1 root 350: 1.1.1.2 ! root 351: /* idle: */ ! 352: tme_sparc_do_idle(ic); ! 353: } 1.1 root 354: } 355: 356: /* if this is a cooperative threading system: */ 357: #if TME_THREADS_COOPERATIVE 358: 359: /* unbusy the current instruction TLB entry: */ 1.1.1.2 ! root 360: assert (ic->_tme_sparc_itlb_current_token ! 361: == itlb_current->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token); 1.1 root 362: tme_sparc_tlb_unbusy(itlb_current); 1.1.1.2 ! root 363: ic->_tme_sparc_itlb_current_token = NULL; 1.1 root 364: 365: /* yield: */ 366: tme_thread_yield(); 367: #endif /* TME_THREADS_COOPERATIVE */ 1.1.1.2 ! root 368: ! 369: /* if we may update the runlength with this instruction burst, ! 370: note its start time: */ ! 371: if (ic->tme_sparc_runlength_update_next == 0) { ! 372: ic->tme_sparc_runlength.tme_runlength_cycles_start = tme_misc_cycles(); ! 373: } 1.1 root 374: } 375: 1.1.1.2 ! root 376: /* we can't know that this instruction is a taken branch to .: */ ! 377: assert (!branch_dot); ! 378: 1.1 root 379: /* we are going to use one instruction in the burst: */ 380: ic->_tme_sparc_instruction_burst_remaining--; 381: #ifdef _TME_SPARC_STATS 382: ic->tme_sparc_stats.tme_sparc_stats_insns_total++; 383: #endif /* _TME_SPARC_STATS */ 384: 1.1.1.2 ! root 385: /* save the previous PC: */ ! 386: pc_previous = ic->tme_sparc_ireg(TME_SPARC_IREG_PC); ! 387: ! 388: /* if we're replaying recoded instructions: */ ! 389: if (tme_sparc_recode_verify_replay_last_pc(ic) != 0) { ! 390: ! 391: /* if the previous instruction was the last instruction to ! 392: verify, return now: */ ! 393: if (__tme_predict_false(tme_sparc_recode_verify_replay_last_pc(ic) == pc_previous)) { ! 394: assert (ic->_tme_sparc_itlb_current_token != &token_invalid); ! 395: return; ! 396: } ! 397: ! 398: /* poison pc_previous to prevent all recoding: */ ! 399: pc_previous = ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT) - sizeof(tme_uint32_t); ! 400: } ! 401: 1.1 root 402: /* update the PCs and get the PC of the instruction to execute: */ 403: pc = ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT); 404: ic->tme_sparc_ireg(TME_SPARC_IREG_PC) = pc; 1.1.1.2 ! root 405: pc_next_next = ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT_NEXT); ! 406: ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT) = pc_next_next; ! 407: pc_next_next += sizeof(tme_uint32_t); ! 408: if (TME_SPARC_VERSION(ic) >= 9) { ! 409: pc_next_next &= ic->tme_sparc_address_mask; ! 410: assert ((pc | ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT)) ! 411: < ic->tme_sparc_address_mask); ! 412: } ! 413: ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT_NEXT) = pc_next_next; 1.1 root 414: 415: /* NB that we only save instruction TLB entries that allow fast 416: reading, and we also change tme_sparc_tlb_addr_last to be the 417: last PC covered by the entry (it's normally the last address 418: covered by the entry). this allows us to do minimal checking 419: of the current instruction TLB entry at itlb_current: */ 420: 421: /* if the current instruction TLB entry covers this address: */ 1.1.1.2 ! root 422: if (__tme_predict_true(((tme_sparc_ireg_t) itlb_current->tme_sparc_tlb_addr_first) <= pc ! 423: && pc <= ((tme_sparc_ireg_t) itlb_current->tme_sparc_tlb_addr_last))) { ! 424: ! 425: /* the current instruction TLB entry must cover this ! 426: address and allow reading: */ ! 427: assert (TME_SPARC_TLB_ASI_MASK_OK(itlb_current, asi_mask_insn) ! 428: && (itlb_current->tme_sparc_tlb_context > ic->tme_sparc_memory_context_max ! 429: || itlb_current->tme_sparc_tlb_context == ic->tme_sparc_memory_context_default) ! 430: && itlb_current->tme_sparc_tlb_addr_first <= pc ! 431: && pc <= itlb_current->tme_sparc_tlb_addr_last); 1.1 root 432: 433: /* fetch the instruction: */ 434: insn = tme_memory_bus_read32((const tme_shared tme_uint32_t *) (itlb_current->tme_sparc_tlb_emulator_off_read + pc), 435: itlb_current->tme_sparc_tlb_bus_rwlock, 436: sizeof(tme_uint32_t), 437: sizeof(tme_sparc_ireg_t)); 438: insn = tme_betoh_u32(insn); 439: } 440: 441: /* otherwise, our current TLB entry doesn't cover this address: */ 442: else { 443: 444: /* unbusy the current instruction TLB entry: */ 1.1.1.2 ! root 445: assert (ic->_tme_sparc_itlb_current_token ! 446: == itlb_current->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token); 1.1 root 447: tme_sparc_tlb_unbusy(itlb_current); 448: 449: /* rehash the current instruction TLB entry: */ 1.1.1.2 ! root 450: tlb_hash = TME_SPARC_TLB_HASH(ic, ic->tme_sparc_memory_context_default, pc); ! 451: itlb_current = &ic->tme_sparc_tlbs[TME_SPARC_ITLB_ENTRY(ic, tlb_hash)]; 1.1 root 452: 453: /* busy the current instruction TLB entry: */ 454: tme_sparc_tlb_busy(itlb_current); 1.1.1.2 ! root 455: ic->_tme_sparc_itlb_current_token = itlb_current->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token; 1.1 root 456: 457: /* if the new current instruction TLB entry is valid and covers 458: this address: */ 459: if (tme_bus_tlb_is_valid(&itlb_current->tme_sparc_tlb_bus_tlb) 460: && __tme_predict_true(TME_SPARC_TLB_ASI_MASK_OK(itlb_current, asi_mask_insn) 1.1.1.2 ! root 461: && (itlb_current->tme_sparc_tlb_context > ic->tme_sparc_memory_context_max ! 462: || itlb_current->tme_sparc_tlb_context == ic->tme_sparc_memory_context_default) ! 463: && pc >= (tme_sparc_ireg_t) itlb_current->tme_sparc_tlb_addr_first ! 464: && pc <= (tme_sparc_ireg_t) itlb_current->tme_sparc_tlb_addr_last)) { 1.1 root 465: 466: /* fetch the instruction: */ 467: insn = tme_memory_bus_read32((const tme_shared tme_uint32_t *) (itlb_current->tme_sparc_tlb_emulator_off_read + pc), 468: itlb_current->tme_sparc_tlb_bus_rwlock, 469: sizeof(tme_uint32_t), 470: sizeof(tme_sparc_ireg_t)); 471: insn = tme_betoh_u32(insn); 472: } 473: 474: /* otherwise, the new current instruction TLB entry is not valid 475: or does not cover this address: */ 476: else { 477: 1.1.1.2 ! root 478: /* the slow fetch will manage unbusying and busying the ! 479: current instruction TLB entry, so make sure that doesn't ! 480: happen at unlock and relock time: */ ! 481: ic->_tme_sparc_itlb_current_token = NULL; 1.1 root 482: 1.1.1.2 ! root 483: /* fetch the instruction: */ ! 484: emulator_off = ! 485: #if TME_SPARC_VERSION(ic) < 9 ! 486: tme_sparc32_ls ! 487: #else /* TME_SPARC_VERSION(ic) >= 9 */ ! 488: tme_sparc64_ls ! 489: #endif /* TME_SPARC_VERSION(ic) >= 9 */ ! 490: (ic, ! 491: pc, ! 492: (tme_sparc_ireg_t *) NULL, ! 493: (TME_SPARC_LSINFO_SIZE(sizeof(tme_uint32_t)) ! 494: + TME_SPARC_LSINFO_ASI(TME_SPARC_ASI_MASK_WHICH(asi_mask_insn)) ! 495: + TME_SPARC_LSINFO_A ! 496: + TME_SPARC_LSINFO_OP_FETCH ! 497: + (annulled ! 498: ? TME_SPARC_LSINFO_NO_FAULT ! 499: : 0))); ! 500: assert (emulator_off != TME_EMULATOR_OFF_UNDEF); ! 501: ! 502: /* unbusy and busy the current instruction TLB entry at unlock ! 503: and relock time again: */ ! 504: ic->_tme_sparc_itlb_current_token = itlb_current->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token; 1.1 root 505: 506: /* if this current instruction TLB entry covers the entire 507: instruction and allows fast reading: */ 1.1.1.2 ! root 508: if (__tme_predict_true(emulator_off == itlb_current->tme_sparc_tlb_emulator_off_read)) { ! 509: ! 510: /* the current instruction TLB entry must now cover this ! 511: address and allow reading: */ ! 512: /* NB that tme_sparc_tlb_addr_last has not been changed yet: */ ! 513: assert (TME_SPARC_TLB_ASI_MASK_OK(itlb_current, asi_mask_insn) ! 514: && (itlb_current->tme_sparc_tlb_context > ic->tme_sparc_memory_context_max ! 515: || itlb_current->tme_sparc_tlb_context == ic->tme_sparc_memory_context_default) ! 516: && itlb_current->tme_sparc_tlb_addr_first <= pc ! 517: && (pc + sizeof(tme_uint32_t) - 1) <= itlb_current->tme_sparc_tlb_addr_last); 1.1 root 518: 519: /* fetch the instruction: */ 520: insn = tme_memory_bus_read32((const tme_shared tme_uint32_t *) (itlb_current->tme_sparc_tlb_emulator_off_read + pc), 521: itlb_current->tme_sparc_tlb_bus_rwlock, 522: sizeof(tme_uint32_t), 523: sizeof(tme_sparc_ireg_t)); 524: insn = tme_betoh_u32(insn); 525: 526: /* modify tme_sparc_tlb_addr_last of this first to represent the last valid 527: PC covered by the entry: */ 528: itlb_current->tme_sparc_tlb_addr_last 529: &= (((tme_bus_addr_t) 0) - sizeof(tme_uint32_t)); 530: } 531: 532: /* otherwise, this instruction TLB entry does not cover the 533: entire instruction and/or it does not allow fast reading. 1.1.1.2 ! root 534: the instruction has already been loaded into the memory ! 535: buffer: */ 1.1 root 536: else { 537: 538: /* unbusy the current instruction TLB entry and poison it, 539: so we won't try to do any fast fetches with it: */ 1.1.1.2 ! root 540: assert (ic->_tme_sparc_itlb_current_token ! 541: == itlb_current->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token); 1.1 root 542: tme_sparc_tlb_unbusy(itlb_current); 543: itlb_current->tme_sparc_tlb_addr_first = 1; 544: itlb_current->tme_sparc_tlb_addr_last = 0; 1.1.1.2 ! root 545: ic->_tme_sparc_itlb_current_token = NULL; 1.1 root 546: 1.1.1.2 ! root 547: /* fetch the instruction from the memory buffer: */ ! 548: assert ((emulator_off + pc) == ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer8s); ! 549: insn = ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer32s[0]; ! 550: insn = tme_betoh_u32(insn); 1.1 root 551: #ifdef _TME_SPARC_STATS 552: ic->tme_sparc_stats.tme_sparc_stats_insns_slow++; 553: #endif /* _TME_SPARC_STATS */ 554: 555: /* busy the invalid instruction TLB entry: */ 556: itlb_current = &itlb_invalid; 1.1.1.2 ! root 557: assert (ic->_tme_sparc_itlb_current_token == NULL); 1.1 root 558: tme_sparc_tlb_busy(itlb_current); 1.1.1.2 ! root 559: ic->_tme_sparc_itlb_current_token = itlb_current->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token; 1.1 root 560: } 561: } 562: 563: /* if this instruction has been annulled: */ 564: if (__tme_predict_false(annulled)) { 565: 566: /* make this instruction a nop: */ 567: insn = 0x01000000; 1.1.1.2 ! root 568: ! 569: /* when an annulled instruction also happens to be a branch ! 570: target, we can't run or make an instructions thunk ! 571: associated with its PC, since instructions thunks don't ! 572: take the annulled bit as any kind of parameter. we poison ! 573: pc_previous to prevent this from happening. annulled ! 574: instructions that are also branch targets should be pretty ! 575: rare anyways: */ ! 576: pc_previous = pc - sizeof(tme_uint32_t); 1.1 root 577: } 578: 579: /* the next instruction will not be annulled: */ 580: annulled = FALSE; 581: } 582: 583: /* start this instruction: */ 584: ic->_tme_sparc_insn = insn; 585: 586: /* set %g0 to zero: */ 1.1.1.2 ! root 587: ic->tme_sparc_ireg(TME_SPARC_G0_OFFSET(ic) + TME_SPARC_IREG_G0) = 0; ! 588: ! 589: #if TME_SPARC_HAVE_RECODE(ic) ! 590: ! 591: /* if this is the idle PC, and the idle type marks the idle when ! 592: control reaches the idle PC: */ ! 593: if (__tme_predict_false(pc == ic->tme_sparc_idle_pcs[0])) { ! 594: if (TME_SPARC_IDLE_TYPE_IS(ic, ! 595: (TME_SPARC_IDLE_TYPES_TARGET_CALL ! 596: | TME_SPARC_IDLE_TYPES_TARGET_BRANCH ! 597: ))) { ! 598: ! 599: /* mark the idle: */ ! 600: TME_SPARC_IDLE_MARK(ic); ! 601: ! 602: /* poison the previous PC to prevent all recoding, to ! 603: guarantee that we always see the idle PC (if we allowed the ! 604: idle PC to be recoded, it might get chained to): */ ! 605: pc_previous = pc - sizeof(tme_uint32_t); ! 606: } ! 607: } ! 608: ! 609: /* if this PC does not follow the previous PC, but the next PC ! 610: follows this PC, this PC is a simple control transfer target: */ ! 611: if (__tme_predict_false(((tme_sparc_ireg_t) (pc - sizeof(tme_uint32_t))) ! 612: != pc_previous)) { ! 613: if (__tme_predict_true(((tme_sparc_ireg_t) (pc + sizeof(tme_uint32_t))) ! 614: == ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT))) { ! 615: tme_recode_thunk_off_t insns_thunk; ! 616: ! 617: /* if the current instruction TLB entry is not the invalid TLB ! 618: entry, and there is an instructions thunk for this PC: */ ! 619: if (__tme_predict_true(itlb_current != &itlb_invalid ! 620: && (insns_thunk ! 621: = tme_sparc_recode(ic, ! 622: itlb_current, ! 623: ((const tme_shared tme_uint32_t *) ! 624: (itlb_current->tme_sparc_tlb_emulator_off_read ! 625: + pc)))) != 0)) { ! 626: ! 627: /* begin verifying this instructions thunk: */ ! 628: tme_sparc_recode_verify_begin(ic); ! 629: ! 630: /* like this execution loop, the recode instructions thunks ! 631: expect PC_next to be the next instruction to execute. ! 632: we've already updated the PCs above, so we have to undo ! 633: the update of PC_next. NB that we don't have to undo PC ! 634: or PC_next_next, since the instructions thunks don't read ! 635: them: */ ! 636: pc = ic->tme_sparc_ireg(TME_SPARC_IREG_PC); ! 637: ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT) = pc; ! 638: ! 639: /* run the recode instructions thunk: */ ! 640: TME_SPARC_STAT_N(ic, tme_sparc_stats_insns_total, -1); ! 641: tme_recode_insns_thunk_run(&ic->tme_sparc_ic, ! 642: ic->tme_sparc_recode_insns_group.tme_recode_insns_group_chain_thunk, ! 643: insns_thunk); ! 644: ! 645: /* set PC_next_next from PC_next, since the recode ! 646: instructions thunks usually don't. (this won't destroy ! 647: any specially set PC_next_next, because any instruction ! 648: that sets one is supposed to redispatch.) */ ! 649: pc = ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT); ! 650: ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT_NEXT) = pc + sizeof(tme_uint32_t); ! 651: ! 652: /* end verifying this instructions thunk: */ ! 653: tme_sparc_recode_verify_end(ic, TME_SPARC_TRAP_none); ! 654: ! 655: /* we force a PC to make it look like a control transfer has ! 656: happened (one probably has), to encourage creation of ! 657: another instructions thunk. this is something like the ! 658: opposite of poisoning: */ ! 659: ic->tme_sparc_ireg(TME_SPARC_IREG_PC) = pc; ! 660: ! 661: /* instead of figuring out what the currently busy ! 662: instruction TLB entry is, we simply unbusy the currently ! 663: busy instruction TLB token and make the current ! 664: instruction TLB entry invalid: */ ! 665: assert (ic->_tme_sparc_itlb_current_token != NULL); ! 666: tme_token_unbusy(ic->_tme_sparc_itlb_current_token); ! 667: itlb_current = &itlb_invalid; ! 668: tme_token_busy(&token_invalid); ! 669: ic->_tme_sparc_itlb_current_token = &token_invalid; ! 670: ! 671: /* restart the loop: */ ! 672: continue; ! 673: } ! 674: } ! 675: } ! 676: ! 677: #endif /* TME_SPARC_HAVE_RECODE(ic) */ 1.1 root 678: 679: /* if this is a format three instruction (op is two or three): */ 680: if (__tme_predict_true(insn >= 0x80000000)) { 681: 682: /* if the i bit is zero: */ 683: if (__tme_predict_true((insn & TME_BIT(13)) == 0)) { 684: 685: /* decode rs2: */ 686: reg_rs2 = TME_FIELD_MASK_EXTRACTU(insn, TME_SPARC_FORMAT3_MASK_RS2); 687: TME_SPARC_REG_INDEX(ic, reg_rs2); 688: } 689: 690: /* otherwise, the i bit is one: */ 691: else { 692: 693: /* decode simm13: */ 1.1.1.2 ! root 694: ic->tme_sparc_ireg(TME_SPARC_IREG_TMP(0)) = TME_FIELD_MASK_EXTRACTS(insn, (tme_sparc_ireg_t) 0x1fff); ! 695: reg_rs2 = TME_SPARC_IREG_TMP(0); 1.1 root 696: } 697: 698: /* decode rs1: */ 699: reg_rs1 = TME_FIELD_MASK_EXTRACTU(insn, TME_SPARC_FORMAT3_MASK_RS1); 700: TME_SPARC_REG_INDEX(ic, reg_rs1); 701: 702: /* decode rd: */ 703: reg_rd = TME_FIELD_MASK_EXTRACTU(insn, TME_SPARC_FORMAT3_MASK_RD); 704: TME_SPARC_REG_INDEX(ic, reg_rd); 705: 706: /* form the opcode index: */ 707: opcode = TME_FIELD_MASK_EXTRACTU(insn, (0x3f << 19)); 708: opcode += ((insn >> (30 - 6)) & 0x40); 709: 710: /* run the instruction: */ 711: (*_TME_SPARC_EXECUTE_OPMAP[opcode]) 712: (ic, 713: &ic->tme_sparc_ireg(reg_rs1), 714: &ic->tme_sparc_ireg(reg_rs2), 715: &ic->tme_sparc_ireg(reg_rd)); 716: } 717: 718: /* otherwise, if this is a format two instruction: */ 719: else if (__tme_predict_true(insn < 0x40000000)) { 720: 721: /* dispatch on op2: */ 722: switch (TME_FIELD_MASK_EXTRACTU(insn, (0x7 << 22))) { 1.1.1.2 ! root 723: ! 724: #if TME_SPARC_VERSION(ic) >= 9 ! 725: case 1: /* BPcc */ ! 726: ! 727: /* if cc0 is set, this is an illegal instruction: */ ! 728: if (__tme_predict_false(insn & TME_BIT(20))) { ! 729: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP(ic,illegal_instruction)); ! 730: } ! 731: ! 732: /* get %icc or %xcc: */ ! 733: cc = ic->tme_sparc64_ireg_ccr; ! 734: if (insn & TME_BIT(21)) { ! 735: cc /= (TME_SPARC64_CCR_XCC / TME_SPARC64_CCR_ICC); ! 736: } ! 737: cc = TME_FIELD_MASK_EXTRACTU(cc, TME_SPARC64_CCR_ICC); ! 738: ! 739: /* get the conditions mask: */ ! 740: conds_mask = _tme_sparc_conds_icc[cc]; ! 741: ! 742: /* add the not-conditions to the conditions mask: */ ! 743: conds_mask += ((conds_mask ^ 0xff) << 8); ! 744: ! 745: /* clear cc1, cc0, and p: */ ! 746: insn &= ~(TME_BIT(21) + TME_BIT(20) + TME_BIT(19)); ! 747: ! 748: /* flip the most significant bit of the disp19: */ ! 749: insn ^= TME_BIT(18); ! 750: ! 751: /* sign-extend the disp19 to a disp22: */ ! 752: /* NB: this potentially destroys op2: */ ! 753: insn += TME_BIT(22) - TME_BIT(18); ! 754: break; ! 755: ! 756: case 3: /* BPr */ ! 757: ! 758: /* if bit 28 is set, or if the least significant two bits of ! 759: cond are clear, this is an illegal instruction: */ ! 760: if (__tme_predict_false((insn & TME_BIT(28)) ! 761: || (insn & (0x3 << 25)) == TME_SPARC_COND_N)) { ! 762: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP(ic,illegal_instruction)); ! 763: } ! 764: ! 765: /* decode rs1: */ ! 766: reg_rs1 = TME_FIELD_MASK_EXTRACTU(insn, TME_SPARC_FORMAT3_MASK_RS1); ! 767: TME_SPARC_REG_INDEX(ic, reg_rs1); ! 768: ! 769: /* make a conditions mask, with the E and LE conditions if the ! 770: register is zero, and with the L and LE conditions if the ! 771: register is less than zero: */ ! 772: value_rs1 = ic->tme_sparc_ireg(reg_rs1); ! 773: conds_mask ! 774: = (((value_rs1 == 0) ! 775: * (TME_BIT(TME_SPARC_COND_E) ! 776: + TME_BIT(TME_SPARC_COND_LE))) ! 777: | ((((tme_int64_t) value_rs1) < 0) ! 778: * (TME_BIT(TME_SPARC_COND_L) ! 779: + TME_BIT(TME_SPARC_COND_LE)))); ! 780: ! 781: /* add the not-conditions to the conditions mask: */ ! 782: conds_mask += ((conds_mask ^ 0xf) << 4); ! 783: ! 784: /* clear rs1 and p, move d16hi down, and clear d16hi: */ ! 785: insn ! 786: = ((insn & ~((2 << 21) - (1 << 14))) ! 787: + ((insn & (3 << 20)) >> (20 - 14))); ! 788: ! 789: /* flip the most significant bit of the disp16: */ ! 790: insn ^= TME_BIT(15); ! 791: ! 792: /* sign-extend the disp16 to a disp22: */ ! 793: /* NB: this potentially destroys op2: */ ! 794: insn += TME_BIT(22) - TME_BIT(15); ! 795: break; ! 796: ! 797: case 5: /* FBPfcc: */ ! 798: TME_SPARC_INSN_FPU; ! 799: ! 800: /* get the right %fcc: */ ! 801: cc = TME_FIELD_MASK_EXTRACTU(insn, (0x3 << 20)); ! 802: if (cc == 0) { ! 803: cc = ic->tme_sparc_fpu_fsr / _TME_FIELD_MASK_FACTOR(TME_SPARC_FSR_FCC); ! 804: } ! 805: else { ! 806: cc = ic->tme_sparc_fpu_xfsr >> (2 * (cc - 1)); ! 807: } ! 808: cc &= (TME_SPARC_FSR_FCC / _TME_FIELD_MASK_FACTOR(TME_SPARC_FSR_FCC)); ! 809: ! 810: /* get the conditions mask: */ ! 811: conds_mask = _tme_sparc_conds_fcc[cc]; ! 812: ! 813: /* add the not-conditions to the conditions mask: */ ! 814: conds_mask += ((conds_mask ^ 0xff) << 8); ! 815: ! 816: /* clear cc1, cc0, and p: */ ! 817: insn &= ~(TME_BIT(21) + TME_BIT(20) + TME_BIT(19)); ! 818: ! 819: /* flip the most significant bit of the disp19: */ ! 820: insn ^= TME_BIT(18); ! 821: ! 822: /* sign-extend the disp19 to a disp22: */ ! 823: /* NB: this potentially destroys op2: */ ! 824: insn += TME_BIT(22) - TME_BIT(18); ! 825: break; ! 826: ! 827: #endif /* TME_SPARC_VERSION(ic) >= 9 */ ! 828: 1.1 root 829: default: 830: 831: case 0: /* UNIMP: */ 1.1.1.2 ! root 832: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP(ic,illegal_instruction)); 1.1 root 833: continue; 834: 835: case 2: /* Bicc: */ 836: conds_mask_icc = _tme_sparc_conds_icc[ 837: #if TME_SPARC_VERSION(ic) < 9 838: TME_FIELD_MASK_EXTRACTU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_ICC) 839: #else /* TME_SPARC_VERSION(ic) >= 9 */ 840: TME_FIELD_MASK_EXTRACTU(ic->tme_sparc64_ireg_ccr, TME_SPARC64_CCR_ICC) 841: #endif /* TME_SPARC_VERSION(ic) >= 9 */ 842: ]; 843: 844: /* add the not-conditions to the conditions mask: */ 845: conds_mask = conds_mask_icc ^ 0xff; 846: conds_mask = (conds_mask << 8) | conds_mask_icc; 847: break; 848: 849: case 4: /* SETHI: */ 850: 851: /* decode rd: */ 852: reg_rd = TME_FIELD_MASK_EXTRACTU(insn, TME_SPARC_FORMAT3_MASK_RD); 853: TME_SPARC_REG_INDEX(ic, reg_rd); 854: ic->tme_sparc_ireg(reg_rd) = (insn << 10); 855: continue; 856: 857: case 6: /* FBfcc: */ 858: TME_SPARC_INSN_FPU; 859: conds_mask_fcc = _tme_sparc_conds_fcc[TME_FIELD_MASK_EXTRACTU(ic->tme_sparc_fpu_fsr, TME_SPARC_FSR_FCC)]; 860: 861: /* add the not-conditions to the conditions mask: */ 862: conds_mask = conds_mask_fcc ^ 0xff; 863: conds_mask = (conds_mask << 8) | conds_mask_fcc; 864: break; 865: } 866: 867: /* get the condition field: */ 868: cond = TME_FIELD_MASK_EXTRACTU(insn, (0xf << 25)); 869: 870: /* if this conditional branch is taken: */ 871: if (conds_mask & TME_BIT(cond)) { 872: 1.1.1.2 ! root 873: /* get the raw displacement: */ ! 874: disp = TME_FIELD_MASK_EXTRACTS(insn, 0x003fffff); ! 875: ! 876: /* if there is no recode support, and the raw displacement is zero: */ ! 877: if (__tme_predict_false(!TME_SPARC_HAVE_RECODE(ic) ! 878: && disp == 0)) { ! 879: ! 880: /* a taken branch to . is probably a timing loop. instead ! 881: of handling that here, which would involve function calls ! 882: that would probably hurt register allocation, instead we ! 883: just set a flag and pretend that this is the last ! 884: instruction in the burst. when we start a new burst ! 885: above, we will find the flag set and do the handling ! 886: then: */ ! 887: branch_dot = TRUE; ! 888: branch_dot_burst = ic->_tme_sparc_instruction_burst_remaining; ! 889: ic->_tme_sparc_instruction_burst_remaining = 0; ! 890: ! 891: /* the raw displacement is zero: */ ! 892: /* NB: this is not necessary for correctness, but is an ! 893: attempt to encourage better register allocation: */ ! 894: disp = 0; ! 895: } ! 896: 1.1 root 897: /* do the delayed control transfer: */ 1.1.1.2 ! root 898: pc_next_next 1.1 root 899: = (ic->tme_sparc_ireg(TME_SPARC_IREG_PC) 1.1.1.2 ! root 900: + (disp << 2)); ! 901: if (TME_SPARC_VERSION(ic) >= 9) { ! 902: pc_next_next &= ic->tme_sparc_address_mask; ! 903: } ! 904: ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT_NEXT) = pc_next_next; ! 905: ! 906: /* if there is no recode support, and the delayed control ! 907: transfer target is the idle PC, and this idle type marks ! 908: the idle on a branch to the idle PC: */ ! 909: if (__tme_predict_false(!TME_SPARC_HAVE_RECODE(ic) ! 910: && pc_next_next == ic->tme_sparc_idle_pcs[0])) { ! 911: if (TME_SPARC_IDLE_TYPE_IS(ic, TME_SPARC_IDLE_TYPES_TARGET_BRANCH)) { 1.1 root 912: 1.1.1.2 ! root 913: /* mark the idle: */ ! 914: TME_SPARC_IDLE_MARK(ic); 1.1 root 915: } 916: } 917: 918: /* if this was a conditional branch, clear the annul bit in 919: the instruction image: */ 920: if (cond & 7) { 921: insn &= ~TME_BIT(29); 922: } 923: } 924: 925: /* if the annul bit it set: */ 926: if (insn & TME_BIT(29)) { 927: 928: /* the next instruction will be annulled. to get the 929: execution loop to pay attention to the annulled bit, 930: make the current instruction TLB entry invalid: */ 931: annulled = TRUE; 1.1.1.2 ! root 932: assert (ic->_tme_sparc_itlb_current_token ! 933: == itlb_current->tme_sparc_tlb_bus_tlb.tme_bus_tlb_token); 1.1 root 934: tme_sparc_tlb_unbusy(itlb_current); 935: itlb_current = &itlb_invalid; 1.1.1.2 ! root 936: tme_token_busy(&token_invalid); ! 937: ic->_tme_sparc_itlb_current_token = &token_invalid; 1.1 root 938: } 939: } 940: 941: /* otherwise, this is a format one instruction: */ 942: else { 943: 944: /* get the current PC: */ 945: pc = ic->tme_sparc_ireg(TME_SPARC_IREG_PC); 946: 947: /* write the PC of the CALL into r[15]: */ 1.1.1.2 ! root 948: ic->tme_sparc_ireg(((ic)->tme_sparc_reg8_offset[15 / 8] * 8) + 15) = pc; ! 949: ! 950: /* get the delayed control transfer target: */ ! 951: pc_next_next = pc + (tme_int32_t) (insn << 2); ! 952: if (TME_SPARC_VERSION(ic) >= 9) { ! 953: pc_next_next &= ic->tme_sparc_address_mask; ! 954: } ! 955: ! 956: /* if there is no recode support, and the delayed control ! 957: transfer target is the idle PC, and this idle type marks ! 958: the idle on a call to the idle PC: */ ! 959: if (__tme_predict_false(!TME_SPARC_HAVE_RECODE(ic) ! 960: && pc_next_next == ic->tme_sparc_idle_pcs[0])) { ! 961: if (TME_SPARC_IDLE_TYPE_IS(ic, TME_SPARC_IDLE_TYPES_TARGET_CALL)) { ! 962: ! 963: /* mark the idle: */ ! 964: TME_SPARC_IDLE_MARK(ic); ! 965: } ! 966: } 1.1 root 967: 968: /* log the call: */ 1.1.1.2 ! root 969: reg_o0 = 8; ! 970: TME_SPARC_REG_INDEX(ic, reg_o0); 1.1 root 971: tme_sparc_log(ic, 250, TME_OK, 972: (TME_SPARC_LOG_HANDLE(ic), 1.1.1.2 ! root 973: _("call " TME_PRIxSPARCREG " %%o0 " TME_PRIxSPARCREG " %%o1 " TME_PRIxSPARCREG " %%o2 " TME_PRIxSPARCREG " %%o3 " TME_PRIxSPARCREG " %%o4 " TME_PRIxSPARCREG " %%o5 " TME_PRIxSPARCREG), ! 974: pc_next_next, ! 975: ic->tme_sparc_ireg(reg_o0 + 0), ! 976: ic->tme_sparc_ireg(reg_o0 + 1), ! 977: ic->tme_sparc_ireg(reg_o0 + 2), ! 978: ic->tme_sparc_ireg(reg_o0 + 3), ! 979: ic->tme_sparc_ireg(reg_o0 + 4), ! 980: ic->tme_sparc_ireg(reg_o0 + 5))); 1.1 root 981: 982: /* do the delayed control transfer: */ 1.1.1.2 ! root 983: ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT_NEXT) = pc_next_next; 1.1 root 984: } 985: } 986: 987: /* NOTREACHED */ 988: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.