|
|
1.1 ! root 1: /* $Id: sparc-rc-chain.c,v 1.2 2010/02/14 15:17:56 fredette Exp $ */ ! 2: ! 3: /* ic/sparc/sparc-rc-chain.c - SPARC recode chain support: */ ! 4: ! 5: /* ! 6: * Copyright (c) 2009 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: #if TME_SPARC_RECODE_SIZE(ic) == TME_RECODE_SIZE_32 ! 37: ! 38: _TME_RCSID("$Id: sparc-rc-chain.c,v 1.2 2010/02/14 15:17:56 fredette Exp $"); ! 39: ! 40: /* macros: */ ! 41: ! 42: /* rename various things by the architecture size: */ ! 43: #define _tme_sparc_recode_chain_src_key _TME_SPARC_RECODE_SIZE(_tme_sparc,_recode_chain_src_key) ! 44: #define _tme_sparc_recode_chain_insns_thunk _TME_SPARC_RECODE_SIZE(_tme_sparc,_recode_chain_insns_thunk) ! 45: #define _tme_sparc_recode_chain_fixup _TME_SPARC_RECODE_SIZE(_tme_sparc,_recode_chain_fixup) ! 46: #define tme_sparc_recode_chain_tlb_update _TME_SPARC_RECODE_SIZE(tme_sparc,_recode_chain_tlb_update) ! 47: #define _tme_sparc_recode_chain_init _TME_SPARC_RECODE_SIZE(_tme_sparc,_recode_chain_init) ! 48: ! 49: #endif /* TME_SPARC_RECODE_SIZE(ic) == TME_RECODE_SIZE_32 */ ! 50: ! 51: /* if the given PC can be converted into a source key on a cache-valid ! 52: page, this returns the source key, otherwise this returns ! 53: TME_SPARC_RECODE_SRC_KEY_UNDEF: */ ! 54: static tme_sparc_recode_src_key_t ! 55: _tme_sparc_recode_chain_src_key(const struct tme_sparc * const ic, ! 56: tme_sparc_ireg_t address) ! 57: { ! 58: tme_uint32_t tlb_hash; ! 59: const struct tme_sparc_tlb *itlb; ! 60: const tme_shared tme_uint8_t *src; ! 61: tme_bus_context_t context; ! 62: const struct tme_sparc_recode_cacheable *cacheable; ! 63: tme_sparc_recode_src_key_t src_key; ! 64: tme_uint32_t pstate; ! 65: unsigned long page_index; ! 66: ! 67: /* hash the address into an instruction TLB entry: */ ! 68: tlb_hash ! 69: = TME_SPARC_TLB_HASH(ic, ! 70: ic->tme_sparc_memory_context_default, ! 71: address); ! 72: itlb = &ic->tme_sparc_tlbs[TME_SPARC_ITLB_ENTRY(ic, tlb_hash)]; ! 73: ! 74: /* if this instruction TLB entry doesn't cover the address: */ ! 75: if (__tme_predict_false(address < (tme_sparc_ireg_t) itlb->tme_sparc_tlb_addr_first ! 76: || address > (tme_sparc_ireg_t) itlb->tme_sparc_tlb_addr_last)) { ! 77: ! 78: /* this PC has no source key: */ ! 79: return (TME_SPARC_RECODE_SRC_KEY_UNDEF); ! 80: } ! 81: ! 82: /* if this instruction TLB entry doesn't allow fast reading: */ ! 83: src = itlb->tme_sparc_tlb_emulator_off_read; ! 84: if (__tme_predict_false(src == TME_EMULATOR_OFF_UNDEF)) { ! 85: ! 86: /* this PC has no source key: */ ! 87: return (TME_SPARC_RECODE_SRC_KEY_UNDEF); ! 88: } ! 89: ! 90: /* assume that this instruction TLB entry is valid and covers, and ! 91: make a pointer to the instruction: */ ! 92: src += address; ! 93: ! 94: /* if this instruction TLB entry isn't valid: */ ! 95: /* NB: here, we check validity without busying the TLB entry first, ! 96: to keep things simple (since this may be the current instruction ! 97: TLB entry, and already busy). this is OK because we don't really ! 98: depend on the entry being valid - we only check for validity on ! 99: the off chance that an invalid TLB entry appears to cover this ! 100: address, context and ASI. ! 101: ! 102: the instruction TLB entry could become immediately invalid after ! 103: this point, without affecting correctness, since we're only using ! 104: the translated address to check the cache-valid bit and maybe do ! 105: a lookup in the source key hash. if this instruction TLB entry ! 106: isn't already busy, before doing anything with the result of this ! 107: lookup, the instruction TLB entry will be busied and checked for ! 108: validity as normal: */ ! 109: if (tme_bus_tlb_is_invalid(&itlb->tme_sparc_tlb_bus_tlb)) { ! 110: ! 111: /* this PC has no source key: */ ! 112: return (TME_SPARC_RECODE_SRC_KEY_UNDEF); ! 113: } ! 114: ! 115: /* if this instruction TLB entry doesn't cover this context or ! 116: ASI: */ ! 117: context = itlb->tme_sparc_tlb_context; ! 118: if (__tme_predict_false((context <= ic->tme_sparc_memory_context_max ! 119: && context != ic->tme_sparc_memory_context_default) ! 120: || !TME_SPARC_TLB_ASI_MASK_OK(itlb, ic->tme_sparc_asi_mask_insn))) { ! 121: ! 122: /* this PC has no source key: */ ! 123: return (TME_SPARC_RECODE_SRC_KEY_UNDEF); ! 124: } ! 125: ! 126: /* search for a cacheable that contains this source address: */ ! 127: cacheable = ic->tme_sparc_recode_cacheable_first; ! 128: for (;;) { ! 129: ! 130: /* assume that this cacheable contains this source address, and get the ! 131: source address key relative to the start of the cacheable: */ ! 132: src_key = src - cacheable->tme_sparc_recode_cacheable_contents; ! 133: ! 134: /* if this cacheable doesn't contain this source address: */ ! 135: if (__tme_predict_false(src_key ! 136: >= cacheable->tme_sparc_recode_cacheable_size)) { ! 137: ! 138: /* if we have run out of cacheables: */ ! 139: if (__tme_predict_false(cacheable != &ic->tme_sparc_recode_cacheables[0])) { ! 140: ! 141: /* this PC has no source key: */ ! 142: return (TME_SPARC_RECODE_SRC_KEY_UNDEF); ! 143: } ! 144: ! 145: /* try the next cacheable: */ ! 146: cacheable--; ! 147: continue; ! 148: } ! 149: ! 150: break; ! 151: } ! 152: ! 153: /* make the absolute source address key by adding in the first ! 154: source address key in this cacheable: */ ! 155: src_key += cacheable->tme_sparc_recode_cacheable_src_key_first; ! 156: assert ((src_key % sizeof(tme_uint32_t)) == 0); ! 157: ! 158: /* make the index for the page containing this source address: */ ! 159: page_index = src_key >> ic->tme_sparc_tlb_page_size_log2; ! 160: ! 161: /* if the valid bit for this page is no longer set: */ ! 162: /* NB: this isn't needed by _tme_sparc_recode_chain_fixup(), because ! 163: each instructions thunk checks its own page valid bit, but this ! 164: is needed by tme_sparc_recode_insn_assist_redispatch(): */ ! 165: if (__tme_predict_false(((cacheable->tme_sparc_recode_cacheable_valids[page_index / 8]) ! 166: & TME_BIT(page_index % 8)) == 0)) { ! 167: ! 168: /* this PC has no source key: */ ! 169: return (TME_SPARC_RECODE_SRC_KEY_UNDEF); ! 170: } ! 171: ! 172: /* if this is a v9 CPU: */ ! 173: if (TME_SPARC_VERSION(ic) >= 9) { ! 174: ! 175: /* add PSTATE.AM and PSTATE.CLE to the source address key: */ ! 176: pstate = ic->tme_sparc64_ireg_pstate; ! 177: if (pstate & TME_SPARC64_PSTATE_AM) { ! 178: src_key += TME_SPARC64_RECODE_SRC_KEY_FLAG_AM; ! 179: } ! 180: if (pstate & TME_SPARC64_PSTATE_CLE) { ! 181: src_key += TME_SPARC64_RECODE_SRC_KEY_FLAG_CLE; ! 182: } ! 183: } ! 184: ! 185: /* the source address key must be defined: */ ! 186: assert (src_key != TME_SPARC_RECODE_SRC_KEY_UNDEF); ! 187: return (src_key); ! 188: } ! 189: ! 190: /* this looks up an instructions thunk for a PC: */ ! 191: static tme_recode_thunk_off_t ! 192: _tme_sparc_recode_chain_insns_thunk(const struct tme_sparc * const ic, ! 193: tme_sparc_ireg_t address) ! 194: { ! 195: tme_sparc_recode_src_key_t src_key; ! 196: unsigned long src_hash_i; ! 197: signed int src_hash_probe; ! 198: tme_sparc_recode_src_key_t src_key_other; ! 199: tme_recode_thunk_off_t insns_thunk; ! 200: ! 201: /* if this PC has no source key: */ ! 202: src_key = _tme_sparc_recode_chain_src_key(ic, address); ! 203: if (__tme_predict_false(src_key == TME_SPARC_RECODE_SRC_KEY_UNDEF)) { ! 204: ! 205: /* the lookup fails: */ ! 206: return (0); ! 207: } ! 208: ! 209: /* hash the source address key: */ ! 210: src_hash_i ! 211: = ((((src_key ! 212: / sizeof(tme_uint32_t)) ! 213: % TME_SPARC_RECODE_SRC_HASH_MODULUS) ! 214: * TME_SPARC_RECODE_SRC_HASH_SIZE_SET) ! 215: + (TME_SPARC_RECODE_SRC_HASH_SIZE_SET ! 216: - 1)); ! 217: ! 218: /* search for the source address key in the hash: */ ! 219: src_hash_probe = TME_SPARC_RECODE_SRC_HASH_SIZE_PROBE; ! 220: for (;;) { ! 221: ! 222: /* get the source address key at this position: */ ! 223: src_key_other ! 224: = (ic->tme_sparc_recode_src_hash ! 225: [src_hash_i / TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT] ! 226: .tme_sparc_recode_src_hash_keys ! 227: [src_hash_i % TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT]); ! 228: ! 229: /* if we found the source address key, stop now: */ ! 230: if (src_key_other == src_key) { ! 231: break; ! 232: } ! 233: ! 234: /* if this position in the hash is free: */ ! 235: if (src_key_other == TME_SPARC_RECODE_SRC_KEY_UNDEF) { ! 236: ! 237: /* the lookup fails: */ ! 238: return (0); ! 239: } ! 240: ! 241: /* if we have searched enough: */ ! 242: if (__tme_predict_false(--src_hash_probe < 0)) { ! 243: ! 244: /* XXX FIXME - add a counter here? */ ! 245: ! 246: /* the lookup fails: */ ! 247: return (0); ! 248: } ! 249: ! 250: /* move to the next position to search: */ ! 251: if (__tme_predict_false(((signed long) --src_hash_i) < 0)) { ! 252: src_hash_i ! 253: = ((TME_SPARC_RECODE_SRC_HASH_MODULUS ! 254: * TME_SPARC_RECODE_SRC_HASH_SIZE_SET) ! 255: - 1); ! 256: } ! 257: } ! 258: ! 259: /* assume that this source address has been recoded, and get the ! 260: instructions thunk: */ ! 261: insns_thunk ! 262: = (ic->tme_sparc_recode_src_hash ! 263: [src_hash_i / TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT] ! 264: .tme_sparc_recode_src_hash_values ! 265: [src_hash_i % TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT]); ! 266: ! 267: /* if the source address has not been recoded yet: */ ! 268: if (__tme_predict_false(insns_thunk & TME_BIT(0))) { ! 269: ! 270: /* the lookup fails: */ ! 271: return (0); ! 272: } ! 273: ! 274: /* the lookup succeeds: */ ! 275: return (insns_thunk); ! 276: } ! 277: ! 278: /* this tries to fix up a chain: */ ! 279: static tme_recode_thunk_off_t ! 280: _tme_sparc_recode_chain_fixup(struct tme_ic * const _ic, ! 281: tme_recode_thunk_off_t const chain_fixup, ! 282: tme_uint32_t const chain_info) ! 283: { ! 284: struct tme_sparc *ic; ! 285: tme_recode_thunk_off_t insns_thunk_next; ! 286: tme_recode_thunk_off_t insns_thunk_return; ! 287: ! 288: /* we can't chain if we're verifying: */ ! 289: if (_tme_sparc_recode_verify_on) { ! 290: ! 291: /* the fixup fails: */ ! 292: return (0); ! 293: } ! 294: ! 295: /* recover our ic: */ ! 296: ic = (struct tme_sparc *) _ic; ! 297: ! 298: /* if the next PC has not been recoded: */ ! 299: insns_thunk_next ! 300: = _tme_sparc_recode_chain_insns_thunk(ic, ! 301: ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT)); ! 302: if (insns_thunk_next == 0) { ! 303: ! 304: /* the fixup fails: */ ! 305: return (0); ! 306: } ! 307: ! 308: /* if this chain is a call: */ ! 309: if (chain_info & TME_RECODE_CHAIN_INFO_CALL) { ! 310: ! 311: /* if the standard return address has not been recoded: */ ! 312: /* NB: PC currently points to the branch delay slot after the ! 313: call. the standard return address is the next instruction ! 314: after that: */ ! 315: insns_thunk_return ! 316: = _tme_sparc_recode_chain_insns_thunk(ic, ! 317: (ic->tme_sparc_ireg(TME_SPARC_IREG_PC) ! 318: + sizeof(tme_uint32_t))); ! 319: if (insns_thunk_return == 0) { ! 320: ! 321: /* the fixup fails: */ ! 322: return (0); ! 323: } ! 324: } ! 325: ! 326: /* otherwise, this chain is not a call: */ ! 327: else { ! 328: ! 329: /* silence uninitialized variable warnings: */ ! 330: insns_thunk_return = 0; ! 331: } ! 332: ! 333: /* fix up the chain: */ ! 334: return (tme_recode_chain_fixup(ic->tme_sparc_recode_ic, ! 335: chain_fixup, ! 336: chain_info, ! 337: insns_thunk_next, ! 338: insns_thunk_return)); ! 339: } ! 340: ! 341: /* this updates a recode ITLB entry: */ ! 342: void ! 343: tme_sparc_recode_chain_tlb_update(struct tme_sparc *ic, ! 344: const struct tme_sparc_ls *ls) ! 345: { ! 346: struct tme_sparc_tlb *itlb; ! 347: struct _TME_SPARC_RECODE_SIZE(tme_recode_tlb_c16_a,/**/) *recode_itlb; ! 348: tme_uint32_t tlb_flags_chain; ! 349: tme_uint32_t itlb_page_size; ! 350: tme_sparc_ireg_t recode_itlb_page; ! 351: ! 352: /* get the sparc ITLB entry: */ ! 353: itlb = ls->tme_sparc_ls_tlb; ! 354: ! 355: /* get the recode ITLB entry: */ ! 356: recode_itlb = &ic->_TME_SPARC_RECODE_SIZE(tme_sparc_recode_tlb,s)[ls->tme_sparc_ls_tlb_i]; ! 357: ! 358: /* assume that this recode ITLB entry will assist all fetches ! 359: (this mask includes at least ! 360: TME_SPARC_RECODE_TLB_FLAG_CHAIN_USER(ic), and ! 361: TME_SPARC_RECODE_TLB_FLAG_CHAIN_PRIV(ic): */ ! 362: tlb_flags_chain = TME_RECODE_TLB_FLAGS_MASK(ic->tme_sparc_recode_ic); ! 363: ! 364: /* get our ITLB page size: */ ! 365: itlb_page_size = (1 << ic->tme_sparc_tlb_page_size_log2); ! 366: ! 367: /* update the recode ITLB entry page: */ ! 368: recode_itlb_page = ls->_TME_SPARC_RECODE_SIZE(tme_sparc_ls_address,/**/) & (0 - (tme_sparc_ireg_t) itlb_page_size); ! 369: recode_itlb->_TME_SPARC_RECODE_SIZE(tme_recode_tlb_c16_a,_page) = recode_itlb_page; ! 370: ! 371: /* if the sparc ITLB entry covers an entire page for one or more ! 372: normal ASIs and allows fast reading: */ ! 373: /* NB: we don't check if verification is on, like ! 374: tme_sparc_recode_ls_tlb_update() does, because instruction ! 375: fetches aren't verified: */ ! 376: if ((((tme_sparc_ireg_t) itlb->tme_sparc_tlb_addr_first) ! 377: <= recode_itlb_page) ! 378: && ((recode_itlb_page | (itlb_page_size - 1)) ! 379: <= ((tme_sparc_ireg_t) itlb->tme_sparc_tlb_addr_last)) ! 380: && (itlb->tme_sparc_tlb_asi_mask & TME_SPARC_ASI_MASK_FLAG_SPECIAL) == 0 ! 381: && itlb->tme_sparc_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF) { ! 382: ! 383: /* limit the sparc ITLB entry to covering only the single recode ! 384: page, like the recode ITLB entry does. this only affects ! 385: large-page sparc ITLB entries. ! 386: ! 387: if we didn't do this, and left a large-page sparc ITLB entry ! 388: covering more than the one recode page, when a chain far would ! 389: take a recode ITLB miss on an address actually covered by the ! 390: large-page corresponding sparc ITLB entry (i.e., miss for an ! 391: address that aliases to the same sparc/recode ITLB entries for ! 392: the address we're handling now, where both are in the large ! 393: page), _TME_SPARC_EXECUTE_NAME() would refuse to do an ITLB ! 394: refill, and would just try to run the recode instructions thunk ! 395: again, which would miss again, leading to an endless loop. ! 396: ! 397: limiting the sparc ITLB entry like this somewhat hurts the ! 398: performance of the regular _TME_SPARC_EXECUTE_NAME() executor, ! 399: which normally would stick with a large-page ITLB entry for as ! 400: long as possible (even for PCs that wouldn't hash to that ! 401: entry), but this will only be felt when not running recode ! 402: instruction thunks, which hopefully won't be often: */ ! 403: itlb->tme_sparc_tlb_addr_first = recode_itlb_page; ! 404: itlb->tme_sparc_tlb_addr_last = (recode_itlb_page | (itlb_page_size - 1)); ! 405: ! 406: /* update the recode ITLB entry page memory pointer: */ ! 407: recode_itlb->_TME_SPARC_RECODE_SIZE(tme_recode_tlb_c16_a,_memory) ! 408: = (itlb->tme_sparc_tlb_emulator_off_read ! 409: + recode_itlb_page); ! 410: ! 411: /* if this sparc ITLB entry allows user fetches: */ ! 412: if (TME_SPARC_TLB_ASI_MASK_OK(itlb, ! 413: (TME_SPARC_VERSION(ic) >= 9 ! 414: ? TME_SPARC64_ASI_MASK_REQUIRED_UNRESTRICTED(TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER) ! 415: : TME_SPARC32_ASI_MASK_UI))) { ! 416: ! 417: /* this recode ITLB entry won't need an assist for user ! 418: fetches: */ ! 419: tlb_flags_chain -= TME_SPARC_RECODE_TLB_FLAG_CHAIN_USER(ic); ! 420: } ! 421: ! 422: /* if this sparc ITLB entry allows privileged/supervisor ! 423: fetches: */ ! 424: if (TME_SPARC_TLB_ASI_MASK_OK(itlb, ! 425: (TME_SPARC_VERSION(ic) >= 9 ! 426: ? TME_SPARC64_ASI_MASK_REQUIRED_UNRESTRICTED(!TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER) ! 427: : TME_SPARC32_ASI_MASK_SI))) { ! 428: ! 429: /* this recode ITLB entry won't need an assist for ! 430: privileged/supervisor fetches: */ ! 431: tlb_flags_chain -= TME_SPARC_RECODE_TLB_FLAG_CHAIN_PRIV(ic); ! 432: } ! 433: ! 434: /* update the recode ITLB entry context: */ ! 435: recode_itlb->_TME_SPARC_RECODE_SIZE(tme_recode_tlb_c16_a,_context) ! 436: = itlb->tme_sparc_tlb_context; ! 437: ! 438: /* if this sparc ITLB entry matches any context: */ ! 439: if (itlb->tme_sparc_tlb_context > ic->tme_sparc_memory_context_max) { ! 440: ! 441: /* this recode ITLB entry doesn't need an assist for fetches ! 442: whose context mismatches the recode ITLB entry: */ ! 443: tlb_flags_chain -= TME_RECODE_TLB_FLAG_CONTEXT_MISMATCH(ic); ! 444: } ! 445: } ! 446: ! 447: /* update the recode ITLB entry flags: */ ! 448: recode_itlb->_TME_SPARC_RECODE_SIZE(tme_recode_tlb_c16_a,_flags) = tlb_flags_chain; ! 449: } ! 450: ! 451: /* this initializes for chaining: */ ! 452: static void ! 453: _tme_sparc_recode_chain_init(struct tme_sparc *ic) ! 454: { ! 455: struct tme_recode_chain chain; ! 456: struct tme_recode_address_type *chain_address_type; ! 457: ! 458: /* set the offset of the pointer to the token for the current ! 459: instruction TLB entry: */ ! 460: ic->tme_sparc_recode_ic->tme_recode_ic_itlb_current_token_offset ! 461: = (((char *) &ic->_tme_sparc_itlb_current_token) ! 462: - (char *) ic); ! 463: ! 464: /* set the chain fixup function: */ ! 465: ic->tme_sparc_recode_ic->tme_recode_ic_chain_fixup ! 466: = _tme_sparc_recode_chain_fixup; ! 467: ! 468: /* set the offset of the chain counter: */ ! 469: ic->tme_sparc_recode_ic->tme_recode_ic_chain_counter_offset ! 470: = (((char *) &ic->_tme_sparc_instruction_burst_remaining) ! 471: - (char *) ic); ! 472: ! 473: /* set the size of the chain return address stack: */ ! 474: ic->tme_sparc_recode_ic->tme_recode_ic_chain_ras_size ! 475: = TME_ARRAY_ELS(ic->_tme_sparc_recode_chain_ras); ! 476: ! 477: /* set the offset of the chain return address stack: */ ! 478: ic->tme_sparc_recode_ic->tme_recode_ic_chain_ras_offset ! 479: = (((char *) &ic->_tme_sparc_recode_chain_ras) ! 480: - (char *) ic); ! 481: ! 482: /* set the offset of the chain return address stack pointer: */ ! 483: ic->tme_sparc_recode_ic->tme_recode_ic_chain_ras_pointer_offset ! 484: = (((char *) &ic->_tme_sparc_recode_chain_ras_pointer) ! 485: - (char *) ic); ! 486: ! 487: /* make the chain thunk: */ ! 488: chain.tme_recode_chain_reg_guest = TME_SPARC_IREG_PC_NEXT; ! 489: chain_address_type = &chain.tme_recode_chain_address_type; ! 490: chain_address_type->tme_recode_address_type_context_ic_offset ! 491: = (((char *) &ic->tme_sparc_memory_context_default) - ((char *) ic)); ! 492: chain_address_type->tme_recode_address_type_context_size = TME_RECODE_SIZE_16; ! 493: chain_address_type->tme_recode_address_type_size = TME_SPARC_RECODE_SIZE(ic); ! 494: chain_address_type->tme_recode_address_type_signed = FALSE; ! 495: chain_address_type->tme_recode_address_type_align_min = sizeof(tme_uint32_t); ! 496: /* NB: TME_RECODE_RW_FLAG_CONTEXT_MISMATCH() will get set ! 497: automatically as needed by the chain thunk; there's no need to ! 498: set it here: */ ! 499: chain_address_type->tme_recode_address_type_tlb_flags ! 500: = (TME_SPARC_RECODE_TLB_FLAG_CHAIN_USER(ic) ! 501: | TME_SPARC_RECODE_TLB_FLAG_CHAIN_PRIV(ic)); ! 502: chain_address_type->tme_recode_address_type_tlb_flags_ic_offset ! 503: = (((char *) &ic->tme_sparc_recode_chain_tlb_flags) - ((char *) ic)); ! 504: chain_address_type->tme_recode_address_type_mask_tlb_index ! 505: = ((_TME_SPARC_ITLB_HASH_SIZE - 1) ! 506: * ic->tme_sparc_recode_ic->tme_recode_ic_tlb_page_size); ! 507: chain_address_type->tme_recode_address_type_tlb0_ic_offset ! 508: = (((char *) &ic->_TME_SPARC_RECODE_SIZE(tme_sparc_recode_tlb,s)[TME_SPARC_ITLB_ENTRY(ic, 0)]) ! 509: - (char *) ic); ! 510: ic->tme_sparc_recode_insns_group.tme_recode_insns_group_chain_thunk ! 511: = tme_recode_chain_thunk(ic->tme_sparc_recode_ic, &chain); ! 512: ! 513: /* clear the return address stack: */ ! 514: tme_recode_chain_ras_clear(ic->tme_sparc_recode_ic, ! 515: &ic->tme_sparc_ic); ! 516: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.