|
|
1.1 ! root 1: /* $Id: sparc-recode.c,v 1.6 2010/06/05 18:42:35 fredette Exp $ */ ! 2: ! 3: /* ic/sparc/sparc-recode.c - recodes SPARC instructions: */ ! 4: ! 5: /* ! 6: * Copyright (c) 2008 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-recode.c,v 1.6 2010/06/05 18:42:35 fredette Exp $"); ! 40: ! 41: #if TME_HAVE_RECODE ! 42: ! 43: /* macros: */ ! 44: ! 45: /* this gives the number of recode page bitmap bits needed to cover ! 46: the given number of bytes. this is always a multiple of eight: */ ! 47: #define TME_SPARC_RECODE_PAGE_BITMAP_BITS(ic, size_bytes) \ ! 48: ((((size_bytes) >> (ic)->tme_sparc_tlb_page_size_log2) \ ! 49: + 7) \ ! 50: & (0 - (unsigned long) 8)) ! 51: ! 52: /* this returns a read/write thunk index for an opcode: */ ! 53: #define TME_SPARC_RECODE_RW_THUNK_INDEX(ic, address_size, endian, no_fault, opcode_0_3) \ ! 54: ((opcode_0_3) \ ! 55: + ((TME_SPARC_VERSION(ic) >= 9) \ ! 56: * ((16 * ((no_fault) != 0)) \ ! 57: + (32 * ((endian) == TME_ENDIAN_LITTLE)) \ ! 58: + (64 * (TME_SPARC_RECODE_SIZE(ic) - (address_size)))))) ! 59: ! 60: /* how many source address hash positions are probed: */ ! 61: #define TME_SPARC_RECODE_SRC_HASH_SIZE_PROBE (TME_SPARC_RECODE_SRC_HASH_SIZE_SET * 2) ! 62: ! 63: /* the undefined source address hash key: */ ! 64: #define TME_SPARC_RECODE_SRC_KEY_UNDEF ((tme_sparc_recode_src_key_t) (0 - (tme_sparc_recode_src_key_t) 1)) ! 65: ! 66: /* flags in a source address hash key: */ ! 67: /* NB: an architecture can't have more than two flags, since those are ! 68: the only bits available in a source address hash key (because PCs ! 69: are 32-bit aligned): */ ! 70: #define TME_SPARC64_RECODE_SRC_KEY_FLAG_AM (1 << 0) ! 71: #define TME_SPARC64_RECODE_SRC_KEY_FLAG_CLE (1 << 1) ! 72: ! 73: /* the hit count threshold for recoding a source address: */ ! 74: #define TME_SPARC_RECODE_HIT_COUNT_THRESHOLD (512) ! 75: ! 76: /* this returns the recode size for the architecture size: */ ! 77: #define TME_SPARC_RECODE_SIZE(ic) (TME_RECODE_SIZE_32 + (TME_SPARC_VERSION(ic) >= 9)) ! 78: ! 79: /* fix certain things based on the architecture size: */ ! 80: #undef TME_SPARC_VERSION ! 81: #define TME_SPARC_VERSION(ic) (8 + (_TME_SPARC_RECODE_SIZE(/**/,/**/) == 64)) ! 82: #define tme_sparc_ireg_t _TME_SPARC_RECODE_SIZE(tme_uint,_t) ! 83: #define tme_sparc_ireg _TME_SPARC_RECODE_SIZE(tme_sparc_ireg_uint,/**/) ! 84: #define TME_SPARC_IREG_MSBIT (((tme_sparc_ireg_t) 1) << (sizeof(tme_sparc_ireg_t) * 8 - 1)) ! 85: ! 86: /* the current verify state: */ ! 87: #ifdef _TME_SPARC_RECODE_VERIFY ! 88: static int _tme_sparc_recode_off; ! 89: static int _tme_sparc_recode_verify_on; ! 90: #else /* !_TME_SPARC_RECODE_VERIFY */ ! 91: #define _tme_sparc_recode_off (FALSE) ! 92: #define _tme_sparc_recode_verify_on (FALSE) ! 93: #endif /* !_TME_SPARC_RECODE_VERIFY */ ! 94: ! 95: /* make the sparc32 recode support: */ ! 96: #define _TME_SPARC_RECODE_SIZE(x,y) _TME_CONCAT(_TME_CONCAT(x,32),y) ! 97: #include "sparc-rc-cc.c" ! 98: #include "sparc-rc-chain.c" ! 99: #include "sparc-rc-insns.c" ! 100: #include "sparc-rc-ls.c" ! 101: #undef _TME_SPARC_RECODE_SIZE ! 102: ! 103: #if TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 ! 104: ! 105: /* make the sparc64 recode support: */ ! 106: #define _TME_SPARC_RECODE_SIZE(x,y) _TME_CONCAT(_TME_CONCAT(x,64),y) ! 107: #include "sparc-rc-cc.c" ! 108: #include "sparc-rc-chain.c" ! 109: #include "sparc-rc-insns.c" ! 110: #include "sparc-rc-ls.c" ! 111: #undef _TME_SPARC_RECODE_SIZE ! 112: ! 113: #endif /* TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 */ ! 114: ! 115: /* unfix certain things: */ ! 116: #undef TME_SPARC_VERSION ! 117: #define TME_SPARC_VERSION(ic) _TME_SPARC_VERSION(ic) ! 118: #undef tme_sparc_ireg_t ! 119: #undef tme_sparc_ireg ! 120: #undef TME_SPARC_IREG_MSBIT ! 121: ! 122: /* this invalidates pages in the source address hash: */ ! 123: static void ! 124: _tme_sparc_recode_src_hash_invalidate(struct tme_sparc *ic, ! 125: tme_sparc_recode_src_key_t src_key_mask, ! 126: tme_sparc_recode_src_key_t src_key_match) ! 127: { ! 128: signed long src_hash_i; ! 129: tme_sparc_recode_src_key_t src_key; ! 130: tme_recode_thunk_off_t insns_thunk; ! 131: ! 132: /* walk all of the positions in the source address hash: */ ! 133: src_hash_i ! 134: = ((TME_SPARC_RECODE_SRC_HASH_MODULUS ! 135: * TME_SPARC_RECODE_SRC_HASH_SIZE_SET) ! 136: - 1); ! 137: do { ! 138: ! 139: /* if the source address key in this position matches: */ ! 140: src_key ! 141: = (ic->tme_sparc_recode_src_hash ! 142: [src_hash_i / TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT] ! 143: .tme_sparc_recode_src_hash_keys ! 144: [src_hash_i % TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT]); ! 145: if (((src_key ^ src_key_match) & src_key_mask) == 0) { ! 146: ! 147: /* invalidate this source address key: */ ! 148: (ic->tme_sparc_recode_src_hash ! 149: [src_hash_i / TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT] ! 150: .tme_sparc_recode_src_hash_keys ! 151: [src_hash_i % TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT]) ! 152: = TME_SPARC_RECODE_SRC_KEY_UNDEF; ! 153: ! 154: /* if this source address key has an instructions thunk: */ ! 155: insns_thunk ! 156: = (ic->tme_sparc_recode_src_hash ! 157: [src_hash_i / TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT] ! 158: .tme_sparc_recode_src_hash_values ! 159: [src_hash_i % TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT]); ! 160: if ((insns_thunk & TME_BIT(0)) == 0 ! 161: && insns_thunk != 0) { ! 162: ! 163: /* invalidate the instructions thunk: */ ! 164: tme_recode_insns_thunk_invalidate(ic->tme_sparc_recode_ic, ! 165: insns_thunk); ! 166: } ! 167: ! 168: /* reset the value for this position to a hit count of zero: */ ! 169: (ic->tme_sparc_recode_src_hash ! 170: [src_hash_i / TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT] ! 171: .tme_sparc_recode_src_hash_values ! 172: [src_hash_i % TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT]) ! 173: = TME_BIT(0); ! 174: } ! 175: } while (--src_hash_i >= 0); ! 176: } ! 177: ! 178: /* this invalidates our entire source hash and all instructions ! 179: thunks: */ ! 180: void ! 181: tme_sparc_recode_invalidate_all(struct tme_sparc *ic) ! 182: { ! 183: ! 184: /* invalidate our entire source hash: */ ! 185: _tme_sparc_recode_src_hash_invalidate(ic, 0, 0); ! 186: ! 187: /* invalidate all instructions thunks: */ ! 188: tme_recode_insns_thunk_invalidate_all(ic->tme_sparc_recode_ic); ! 189: ! 190: /* clear the return address stack: */ ! 191: tme_recode_chain_ras_clear(ic->tme_sparc_recode_ic, ! 192: &ic->tme_sparc_ic); ! 193: } ! 194: ! 195: /* include the verify support: */ ! 196: #ifdef _TME_SPARC_RECODE_VERIFY ! 197: #include "sparc-rc-verify.c" ! 198: #endif /* _TME_SPARC_RECODE_VERIFY */ ! 199: ! 200: /* this adds a new cacheable: */ ! 201: static struct tme_sparc_recode_cacheable * ! 202: _tme_sparc_recode_cacheable_new(struct tme_sparc *ic, ! 203: const struct tme_sparc_tlb *itlb, ! 204: const tme_shared tme_uint32_t *src) ! 205: { ! 206: unsigned int page_size_log2; ! 207: tme_uint32_t page_size; ! 208: tme_uint32_t page_byte_offset; ! 209: struct tme_sparc_recode_cacheable *cacheable; ! 210: const struct tme_bus_cacheable *bus_cacheable; ! 211: unsigned long bitmap_bytes_old; ! 212: unsigned long bitmap_bytes; ! 213: ! 214: /* get the page size: */ ! 215: page_size_log2 = ic->tme_sparc_tlb_page_size_log2; ! 216: page_size = (((tme_uint32_t) 1) << page_size_log2); ! 217: ! 218: /* get the offset of the current PC into this page: */ ! 219: page_byte_offset ! 220: = ( ! 221: #if TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 ! 222: TME_SPARC_VERSION(ic) >= 9 ! 223: ? ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC) ! 224: : ! 225: #endif /* TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 */ ! 226: ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC)); ! 227: page_byte_offset %= page_size; ! 228: ! 229: /* if we have run out of cacheables, return failure: */ ! 230: cacheable = ic->tme_sparc_recode_cacheable_first; ! 231: if (cacheable == &ic->tme_sparc_recode_cacheables[TME_SPARC_RECODE_CACHEABLES_MAX - 1]) { ! 232: return (NULL); ! 233: } ! 234: cacheable += (ic->tme_sparc_recode_cacheables[0].tme_sparc_recode_cacheable_size != 0); ! 235: ! 236: /* if this instruction TLB entry isn't for cacheable memory, return ! 237: failure: */ ! 238: bus_cacheable = itlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_cacheable; ! 239: if (bus_cacheable == NULL) { ! 240: return (NULL); ! 241: } ! 242: ! 243: /* if the cacheable memory doesn't cover some whole number of ! 244: aligned pages, return failure: */ ! 245: assert (bus_cacheable->tme_bus_cacheable_size > 0); ! 246: if ((((((tme_uint8_t *) src) ! 247: - bus_cacheable->tme_bus_cacheable_contents) ! 248: % page_size) ! 249: != page_byte_offset) ! 250: || ((bus_cacheable->tme_bus_cacheable_size ! 251: % page_size) ! 252: != 0)) { ! 253: return (NULL); ! 254: } ! 255: ! 256: /* initialize our cacheable: */ ! 257: /* NB: we round up the first source address key for this cacheable ! 258: so that its page index is a multiple of eight, which will be used ! 259: to index the least-significant bit in the first byte of the ! 260: valids bitmap we allocate below: */ ! 261: cacheable->tme_sparc_recode_cacheable_contents = bus_cacheable->tme_bus_cacheable_contents; ! 262: cacheable->tme_sparc_recode_cacheable_size = bus_cacheable->tme_bus_cacheable_size; ! 263: cacheable->tme_sparc_recode_cacheable_src_key_first ! 264: = (cacheable == &ic->tme_sparc_recode_cacheables[0] ! 265: ? 0 ! 266: : ((cacheable - 1)->tme_sparc_recode_cacheable_src_key_first ! 267: ! 268: + (TME_SPARC_RECODE_PAGE_BITMAP_BITS(ic, (cacheable - 1)->tme_sparc_recode_cacheable_size) ! 269: * page_size))); ! 270: ! 271: /* allocate the valids bitmap, and adjust the pointer to account ! 272: for the first source key in this cacheable: */ ! 273: cacheable->tme_sparc_recode_cacheable_valids ! 274: = ((*bus_cacheable->tme_bus_cacheable_valids_new) ! 275: (bus_cacheable->tme_bus_cacheable_private, ! 276: page_size_log2) ! 277: - ((cacheable->tme_sparc_recode_cacheable_src_key_first ! 278: / page_size) ! 279: / 8)); ! 280: ! 281: /* allocate or reallocate the active recode pages bitmap, and zero ! 282: the new parts of the bitmap: */ ! 283: bitmap_bytes_old ! 284: = (cacheable->tme_sparc_recode_cacheable_src_key_first ! 285: / (page_size * 8)); ! 286: bitmap_bytes ! 287: = (bitmap_bytes_old ! 288: + (TME_SPARC_RECODE_PAGE_BITMAP_BITS(ic, cacheable->tme_sparc_recode_cacheable_size) ! 289: / 8)); ! 290: ic->tme_sparc_recode_cacheable_actives ! 291: = (cacheable == &ic->tme_sparc_recode_cacheables[0] ! 292: ? tme_new(tme_uint8_t, bitmap_bytes) ! 293: : tme_renew(tme_uint8_t, ic->tme_sparc_recode_cacheable_actives, bitmap_bytes)); ! 294: memset((ic->tme_sparc_recode_cacheable_actives + bitmap_bytes_old), ! 295: 0, ! 296: (bitmap_bytes - bitmap_bytes_old)); ! 297: ! 298: /* finish allocating this cacheable: */ ! 299: ic->tme_sparc_recode_cacheable_first = cacheable; ! 300: ! 301: /* return success: */ ! 302: return (cacheable); ! 303: } ! 304: ! 305: tme_recode_thunk_off_t ! 306: tme_sparc_recode(struct tme_sparc *ic, ! 307: const struct tme_sparc_tlb *itlb, ! 308: const tme_shared tme_uint32_t *src) ! 309: { ! 310: ! 311: const struct tme_sparc_recode_cacheable *cacheable; ! 312: tme_sparc_recode_src_key_t src_key; ! 313: tme_uint32_t pstate; ! 314: unsigned long page_index; ! 315: tme_uint8_t page_invalid; ! 316: const tme_shared tme_uint8_t *cacheable_valid_byte; ! 317: unsigned int cacheable_valid_mask; ! 318: signed long src_hash_i; ! 319: signed int src_hash_probe; ! 320: tme_sparc_recode_src_key_t src_key_other; ! 321: tme_recode_thunk_off_t insns_thunk; ! 322: tme_recode_thunk_off_t hit_count; ! 323: ! 324: TME_SPARC_STAT(ic, tme_sparc_stats_recode_calls); ! 325: ! 326: /* if recoding is off: */ ! 327: if (_tme_sparc_recode_off) { ! 328: ! 329: /* we can't recode this source address: */ ! 330: return (0); ! 331: } ! 332: ! 333: /* if this instruction TLB entry doesn't extend to the end of the ! 334: page: */ ! 335: /* XXX FIXME - this isn't right, since it will reject all itlb ! 336: entries that don't end right at a recode page boundary, instead ! 337: of only those that end before the end of the page containing the ! 338: current PC. maybe this check should move to sparc-rc-insns.c or ! 339: sparc-execute.c, where we have the current PC? */ ! 340: if (__tme_predict_false((~itlb->tme_sparc_tlb_addr_last) ! 341: & ((1 << ic->tme_sparc_tlb_page_size_log2) ! 342: - sizeof(tme_uint32_t)))) { ! 343: ! 344: /* we can't recode this source address: */ ! 345: return (0); ! 346: } ! 347: ! 348: /* assume that we will recode at this source address, and save it: */ ! 349: ic->tme_sparc_recode_insns_group.tme_recode_insns_group_src ! 350: = (const tme_shared tme_uint8_t *) src; ! 351: ! 352: /* search for a cacheable that contains this source address: */ ! 353: cacheable = ic->tme_sparc_recode_cacheable_first; ! 354: for (;;) { ! 355: ! 356: /* assume that this cacheable contains this source address, and get the ! 357: source address key relative to the start of the cacheable: */ ! 358: src_key = ((tme_uint8_t *) src) - cacheable->tme_sparc_recode_cacheable_contents; ! 359: ! 360: /* if this cacheable contains this source address: */ ! 361: if (__tme_predict_true(src_key ! 362: < cacheable->tme_sparc_recode_cacheable_size)) { ! 363: ! 364: /* stop now: */ ! 365: break; ! 366: } ! 367: ! 368: /* if we have not run out of cacheables: */ ! 369: if (__tme_predict_true(--cacheable != (&ic->tme_sparc_recode_cacheables[0] - 1))) { ! 370: continue; ! 371: } ! 372: ! 373: /* if this instruction TLB entry isn't for a cacheable, or if we ! 374: can't add this cacheable: */ ! 375: cacheable = _tme_sparc_recode_cacheable_new(ic, itlb, src); ! 376: if (cacheable == NULL) { ! 377: ! 378: /* we can't recode this source address: */ ! 379: return (0); ! 380: } ! 381: } ! 382: ! 383: /* make the absolute source address key by adding in the first ! 384: source address key in this cacheable: */ ! 385: src_key += cacheable->tme_sparc_recode_cacheable_src_key_first; ! 386: assert ((src_key % sizeof(tme_uint32_t)) == 0); ! 387: ! 388: /* if this is a v9 CPU: */ ! 389: if (TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 ! 390: && TME_SPARC_VERSION(ic) >= 9) { ! 391: ! 392: /* add PSTATE.AM and PSTATE.CLE to the source address key: */ ! 393: pstate = ic->tme_sparc64_ireg_pstate; ! 394: if (pstate & TME_SPARC64_PSTATE_AM) { ! 395: src_key += TME_SPARC64_RECODE_SRC_KEY_FLAG_AM; ! 396: } ! 397: if (pstate & TME_SPARC64_PSTATE_CLE) { ! 398: src_key += TME_SPARC64_RECODE_SRC_KEY_FLAG_CLE; ! 399: } ! 400: } ! 401: ! 402: /* the source address key must be defined: */ ! 403: assert (src_key != TME_SPARC_RECODE_SRC_KEY_UNDEF); ! 404: ! 405: /* make the index for the page containing this source address: */ ! 406: page_index = src_key >> ic->tme_sparc_tlb_page_size_log2; ! 407: ! 408: /* assume that this recode page is still valid: */ ! 409: page_invalid = FALSE; ! 410: ! 411: /* get the cacheable valid byte and mask for this page: */ ! 412: cacheable_valid_byte = &cacheable->tme_sparc_recode_cacheable_valids[page_index / 8]; ! 413: cacheable_valid_mask = TME_BIT(page_index % 8); ! 414: ! 415: /* assume that we will recode at this source address, and save the ! 416: cacheable valid byte and mask for this page: */ ! 417: ic->tme_sparc_recode_insns_group.tme_recode_insns_group_valid_byte = cacheable_valid_byte; ! 418: ic->tme_sparc_recode_insns_group.tme_recode_insns_group_valid_mask = cacheable_valid_mask; ! 419: ! 420: /* if the valid bit for this page is no longer set: */ ! 421: if (__tme_predict_false(((*cacheable_valid_byte) & cacheable_valid_mask) == 0)) { ! 422: ! 423: /* this page is invalid: */ ! 424: page_invalid = TRUE; ! 425: ! 426: /* if this page was active: */ ! 427: if (__tme_predict_false(ic->tme_sparc_recode_cacheable_actives[page_index / 8] ! 428: & TME_BIT(page_index % 8))) { ! 429: ! 430: TME_SPARC_STAT(ic, tme_sparc_stats_recode_page_invalids); ! 431: ! 432: /* mark this page as inactive: */ ! 433: ic->tme_sparc_recode_cacheable_actives[page_index / 8] &= ~TME_BIT(page_index % 8); ! 434: ! 435: /* re-set the valid bit for the page containing this ! 436: source address: */ ! 437: /* NB: we cheat and pass our ! 438: page-index-base-greater-than-zero-relative valids bitmap ! 439: pointer instead of the original pointer returned by the ! 440: allocator. this only works if the re-set function will work ! 441: given arbitrary valids bitmap pointers and page indices: */ ! 442: (*itlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_cacheable->tme_bus_cacheable_valids_set) ! 443: (itlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_cacheable->tme_bus_cacheable_private, ! 444: cacheable->tme_sparc_recode_cacheable_valids, ! 445: page_index); ! 446: ! 447: /* invalidate this page in the source address hash: */ ! 448: _tme_sparc_recode_src_hash_invalidate(ic, ! 449: (0 ! 450: - ((tme_sparc_recode_src_key_t) ! 451: (1 << ic->tme_sparc_tlb_page_size_log2))), ! 452: src_key); ! 453: } ! 454: } ! 455: ! 456: /* hash the source address key: */ ! 457: src_hash_i ! 458: = ((((src_key ! 459: / sizeof(tme_uint32_t)) ! 460: % TME_SPARC_RECODE_SRC_HASH_MODULUS) ! 461: * TME_SPARC_RECODE_SRC_HASH_SIZE_SET) ! 462: + (TME_SPARC_RECODE_SRC_HASH_SIZE_SET ! 463: - 1)); ! 464: ! 465: /* search for the source address key in the hash: */ ! 466: src_hash_probe = TME_SPARC_RECODE_SRC_HASH_SIZE_PROBE; ! 467: for (;;) { ! 468: ! 469: TME_SPARC_STAT(ic, tme_sparc_stats_recode_source_hash_probes); ! 470: ! 471: /* get the source address key at this position: */ ! 472: src_key_other ! 473: = (ic->tme_sparc_recode_src_hash ! 474: [src_hash_i / TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT] ! 475: .tme_sparc_recode_src_hash_keys ! 476: [src_hash_i % TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT]); ! 477: ! 478: /* if we found the source address key, stop now: */ ! 479: if (__tme_predict_true(src_key_other == src_key)) { ! 480: break; ! 481: } ! 482: ! 483: /* if this position in the hash is free: */ ! 484: if (src_key_other == TME_SPARC_RECODE_SRC_KEY_UNDEF) { ! 485: ! 486: /* allocate this position in the hash: */ ! 487: (ic->tme_sparc_recode_src_hash ! 488: [src_hash_i / TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT] ! 489: .tme_sparc_recode_src_hash_keys ! 490: [src_hash_i % TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT]) ! 491: = src_key; ! 492: ! 493: /* stop now: */ ! 494: break; ! 495: } ! 496: ! 497: /* if we have searched enough: */ ! 498: if (__tme_predict_false(--src_hash_probe < 0)) { ! 499: ! 500: TME_SPARC_STAT(ic, tme_sparc_stats_recode_source_hash_misses); ! 501: ! 502: /* we won't recode this source address: */ ! 503: return (0); ! 504: } ! 505: ! 506: /* move to the next position to search: */ ! 507: if (__tme_predict_false(--src_hash_i < 0)) { ! 508: src_hash_i ! 509: = ((TME_SPARC_RECODE_SRC_HASH_MODULUS ! 510: * TME_SPARC_RECODE_SRC_HASH_SIZE_SET) ! 511: - 1); ! 512: } ! 513: } ! 514: ! 515: /* assume that this source address has been recoded, and get the ! 516: instructions thunk: */ ! 517: insns_thunk ! 518: = (ic->tme_sparc_recode_src_hash ! 519: [src_hash_i / TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT] ! 520: .tme_sparc_recode_src_hash_values ! 521: [src_hash_i % TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT]); ! 522: ! 523: /* if the source address has not been recoded yet: */ ! 524: if (__tme_predict_false(insns_thunk & TME_BIT(0))) { ! 525: ! 526: /* update the hit count for this source address: */ ! 527: hit_count = insns_thunk + 2; ! 528: ! 529: /* if the hit count for this source address is still less than the ! 530: recode threshold: */ ! 531: if (__tme_predict_true(hit_count ! 532: < ((TME_SPARC_RECODE_HIT_COUNT_THRESHOLD * 2) ! 533: + 1))) { ! 534: ! 535: /* update the hit count for this source address: */ ! 536: (ic->tme_sparc_recode_src_hash ! 537: [src_hash_i / TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT] ! 538: .tme_sparc_recode_src_hash_values ! 539: [src_hash_i % TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT]) ! 540: = hit_count; ! 541: ! 542: /* we won't recode this source address now: */ ! 543: return (0); ! 544: } ! 545: ! 546: /* mark this page as active: */ ! 547: ic->tme_sparc_recode_cacheable_actives[page_index / 8] |= TME_BIT(page_index % 8); ! 548: ! 549: /* if this page is invalid: */ ! 550: if (page_invalid) { ! 551: ! 552: /* return now and interpret instructions normally - the next ! 553: time we encounter this page again, we will mark this ! 554: page as inactive, re-set the page's valid bit and ! 555: invalidate the page in the source address hash. ! 556: ! 557: this somewhat limits the work we do for pages that are ! 558: both executed from and written to frequently. we will only ! 559: recode an instructions thunk when its page was valid for the ! 560: entire time it took for its hit count to go from zero to the ! 561: threshold, and we will only invalidate an invalid page in the ! 562: source address hash when any hit count in the page reaches ! 563: the threshold: */ ! 564: return (0); ! 565: } ! 566: ! 567: /* recode starting from this source address: */ ! 568: insns_thunk ! 569: = ( ! 570: #if TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 ! 571: TME_SPARC_VERSION(ic) >= 9 ! 572: ? _tme_sparc64_recode_recode(ic, itlb) ! 573: : ! 574: #endif /* TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 */ ! 575: _tme_sparc32_recode_recode(ic, itlb)); ! 576: ! 577: /* if we couldn't recode at this source address: */ ! 578: if (__tme_predict_false(insns_thunk < 0)) { ! 579: ! 580: /* the only time we can't recode is when the host runs out of ! 581: memory for instructions thunks. when this happens, the host ! 582: invalidates all previous instructions thunks, so we have to ! 583: invalidate our entire source hash: */ ! 584: tme_sparc_recode_invalidate_all(ic); ! 585: return (0); ! 586: } ! 587: ! 588: /* set the instructions thunk for this source address: */ ! 589: assert ((insns_thunk & TME_BIT(0)) == 0); ! 590: (ic->tme_sparc_recode_src_hash ! 591: [src_hash_i / TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT] ! 592: .tme_sparc_recode_src_hash_values ! 593: [src_hash_i % TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT]) ! 594: = insns_thunk; ! 595: ! 596: /* we can't run the new instructions thunk without re-checking the ! 597: valid bit for the page containing this source address ! 598: first - if it wasn't set for the entire time we were recoding, ! 599: the instructions thunk might not be consistent with the source ! 600: memory. ! 601: ! 602: to keep things simple, we just return now and interpret ! 603: instructions normally - the next time we get to this source ! 604: address, we'll check the valid bit and either run the ! 605: instructions thunk for the first time, or we'll do the ! 606: invalidate: */ ! 607: return (0); ! 608: } ! 609: ! 610: /* return the instructions thunk offset: */ ! 611: return (insns_thunk); ! 612: } ! 613: ! 614: #ifdef TME_RECODE_DEBUG ! 615: #include <stdio.h> ! 616: ! 617: void tme_sparc_recode_dump_ic _TME_P((const struct tme_sparc *)); ! 618: void ! 619: tme_sparc_recode_dump_ic(const struct tme_sparc *ic) ! 620: { ! 621: const char *conds_integer[] = { ! 622: "n", "e", "le", "l", "leu", "cs", "neg", "vs", ! 623: NULL ! 624: }; ! 625: ! 626: printf("sparc%u add flags thunk %p:\n", ! 627: (1 << TME_SPARC_RECODE_SIZE(ic)), ! 628: ic->tme_sparc_recode_flags_thunk_add); ! 629: tme_recode_flags_thunk_dump(ic->tme_sparc_recode_ic, ! 630: ic->tme_sparc_recode_flags_thunk_add); ! 631: printf("sparc%u sub flags thunk %p:\n", ! 632: (1 << TME_SPARC_RECODE_SIZE(ic)), ! 633: ic->tme_sparc_recode_flags_thunk_sub); ! 634: tme_recode_flags_thunk_dump(ic->tme_sparc_recode_ic, ! 635: ic->tme_sparc_recode_flags_thunk_sub); ! 636: printf("sparc%u logical flags thunk %p:\n", ! 637: (1 << TME_SPARC_RECODE_SIZE(ic)), ! 638: ic->tme_sparc_recode_flags_thunk_logical); ! 639: tme_recode_flags_thunk_dump(ic->tme_sparc_recode_ic, ! 640: ic->tme_sparc_recode_flags_thunk_logical); ! 641: ! 642: if (TME_SPARC_VERSION(ic) >= 9) { ! 643: printf("sparc%u rcc flags thunk %p:\n", ! 644: (1 << TME_SPARC_RECODE_SIZE(ic)), ! 645: ic->tme_sparc_recode_flags_thunk_rcc); ! 646: tme_recode_flags_thunk_dump(ic->tme_sparc_recode_ic, ! 647: ic->tme_sparc_recode_flags_thunk_rcc); ! 648: } ! 649: printf("sparc%u %%icc conds thunk %p:\n", ! 650: (1 << TME_SPARC_RECODE_SIZE(ic)), ! 651: ic->tme_sparc_recode_conds_thunk_icc); ! 652: tme_recode_conds_thunk_dump(ic->tme_sparc_recode_ic, ! 653: ic->tme_sparc_recode_conds_thunk_icc, ! 654: conds_integer); ! 655: if (TME_SPARC_VERSION(ic) >= 9) { ! 656: printf("sparc%u %%xcc conds thunk %p:\n", ! 657: (1 << TME_SPARC_RECODE_SIZE(ic)), ! 658: ic->tme_sparc_recode_conds_thunk_xcc); ! 659: tme_recode_conds_thunk_dump(ic->tme_sparc_recode_ic, ! 660: ic->tme_sparc_recode_conds_thunk_xcc, ! 661: conds_integer); ! 662: printf("sparc%u %%rcc conds thunk %p:\n", ! 663: (1 << TME_SPARC_RECODE_SIZE(ic)), ! 664: ic->tme_sparc_recode_conds_thunk_rcc); ! 665: tme_recode_conds_thunk_dump(ic->tme_sparc_recode_ic, ! 666: ic->tme_sparc_recode_conds_thunk_rcc, ! 667: conds_integer); ! 668: } ! 669: } ! 670: ! 671: void tme_sparc_recode_dump_insns _TME_P((const struct tme_sparc *)); ! 672: void ! 673: tme_sparc_recode_dump_insns(const struct tme_sparc *ic) ! 674: { ! 675: const struct tme_recode_insn *insns; ! 676: const struct tme_recode_insn *insns_end; ! 677: unsigned int insn_i; ! 678: const char *s; ! 679: unsigned int insn_size; ! 680: unsigned int operands_mask; ! 681: unsigned int thunk_i; ! 682: unsigned int operand_i; ! 683: int delim; ! 684: const char *regcs = "goli"; ! 685: const char *conds_integer[] = { ! 686: "n", "e", "le", "l", "leu", "cs", "neg", "vs", ! 687: "a", "ne", "g", "ge", "gu", "cc", "pos", "vc", ! 688: }; ! 689: tme_uint32_t chain_info; ! 690: ! 691: printf("%%pc = "); ! 692: tme_recode_uguest_dump( ! 693: #if TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 ! 694: TME_SPARC_VERSION(ic) >= 9 ! 695: ? ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC) ! 696: : ! 697: #endif /* TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 */ ! 698: ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC)); ! 699: printf("\n"); ! 700: ! 701: insns = ic->tme_sparc_recode_insns_group.tme_recode_insns_group_insns; ! 702: insns_end = ic->tme_sparc_recode_insns_group.tme_recode_insns_group_insns_end; ! 703: for (insn_i = 0; insns < insns_end; insns++, insn_i++) { ! 704: ! 705: printf("%2u: ", insn_i); ! 706: ! 707: s = tme_recode_opcode_dump(insns->tme_recode_insn_opcode); ! 708: insn_size = insns->tme_recode_insn_size; ! 709: switch (insns->tme_recode_insn_opcode) { ! 710: case TME_RECODE_OPCODE_EXTZ: ! 711: case TME_RECODE_OPCODE_EXTS: ! 712: printf("ext%u%c", ! 713: (1 << insns->tme_recode_insn_operand_src[1]), ! 714: (insns->tme_recode_insn_opcode == TME_RECODE_OPCODE_EXTZ ? 'z' : 's')); ! 715: s = ""; ! 716: operands_mask = (1 << 0) | (1 << 2); ! 717: break; ! 718: case TME_RECODE_OPCODE_DEFC: ! 719: printf("defc\t %%%ccc:%s, %%c%u\n", ! 720: (insns->tme_recode_insn_conds_thunk == ic->tme_sparc_recode_conds_thunk_icc ! 721: ? 'i' ! 722: : insns->tme_recode_insn_conds_thunk == ic->tme_sparc_recode_conds_thunk_xcc ! 723: ? 'x' ! 724: : 'r'), ! 725: conds_integer ! 726: [insns->tme_recode_insn_operand_src[0] ! 727: + (TME_SPARC_COND_NOT ! 728: * (insns->tme_recode_insn_operand_src[1] != 0))], ! 729: insns->tme_recode_insn_operand_dst); ! 730: continue; ! 731: case TME_RECODE_OPCODE_IF: ! 732: printf("%s\t %%c%u\n", s, insns->tme_recode_insn_operand_src[0]); ! 733: continue; ! 734: case TME_RECODE_OPCODE_ELSE: ! 735: case TME_RECODE_OPCODE_ENDIF: ! 736: printf("%s\n", s); ! 737: continue; ! 738: case TME_RECODE_OPCODE_RW: ! 739: for (thunk_i = 0;; thunk_i++) { ! 740: assert (thunk_i < TME_ARRAY_ELS(ic->tme_sparc_recode_rw_thunks)); ! 741: if (insns->tme_recode_insn_rw_thunk == ic->tme_sparc_recode_rw_thunks[thunk_i]) { ! 742: break; ! 743: } ! 744: } ! 745: s = "?rw?"; ! 746: switch (thunk_i % 0x10) { ! 747: case 0x0: s = (TME_SPARC_VERSION(ic) >= 9 ? "lduw" : "ld"); break; ! 748: case 0x1: s = "ldub"; break; ! 749: case 0x2: s = "lduh"; break; ! 750: case 0x4: s = (TME_SPARC_VERSION(ic) >= 9 ? "stw" : "st"); break; ! 751: case 0x5: s = "stb"; break; ! 752: case 0x6: s = "sth"; break; ! 753: case 0x8: if (TME_SPARC_VERSION(ic) >= 9) { s = "ldsw"; } break; ! 754: case 0x9: s = "ldsb"; break; ! 755: case 0xa: s = "ldsh"; break; ! 756: case 0xb: if (TME_SPARC_VERSION(ic) >= 9) { s = "ldx"; } break; ! 757: case 0xe: if (TME_SPARC_VERSION(ic) >= 9) { s = "stx"; } break; ! 758: } ! 759: if (thunk_i & 16) { ! 760: printf("%s", s); ! 761: s = ".nf"; ! 762: } ! 763: if (thunk_i & 32) { ! 764: printf("%s", s); ! 765: s = ".el"; ! 766: } ! 767: if (thunk_i & 64) { ! 768: printf("%s", s); ! 769: s = ".am"; ! 770: } ! 771: insn_size = 0; ! 772: operands_mask = (1 << 0); ! 773: if (insns->tme_recode_insn_rw_thunk->tme_recode_rw_thunk_write) { ! 774: operands_mask |= (1 << 1); ! 775: } ! 776: else { ! 777: operands_mask |= (1 << 2); ! 778: } ! 779: break; ! 780: default: ! 781: operands_mask = (1 << 0) | (1 << 1) | (1 << 2); ! 782: break; ! 783: } ! 784: ! 785: printf("%s", s); ! 786: if (insn_size > 0) { ! 787: printf("%u", (1 << insns->tme_recode_insn_size)); ! 788: } ! 789: delim = '\t'; ! 790: for (operand_i = 0; operand_i <= 2; operand_i++) { ! 791: if (operands_mask & (1 << operand_i)) { ! 792: putchar(delim); ! 793: putchar(' '); ! 794: delim = ','; ! 795: switch (insns->tme_recode_insn_operands[operand_i]) { ! 796: case TME_RECODE_OPERAND_UNDEF: ! 797: s = "undef"; ! 798: break; ! 799: case TME_RECODE_OPERAND_IMM: ! 800: tme_recode_uguest_dump(insns->tme_recode_insn_imm_uguest); ! 801: continue; ! 802: #if TME_RECODE_OPERAND_NULL != TME_RECODE_OPERAND_ZERO ! 803: #error "TME_RECODE_OPERAND_ values changed" ! 804: #endif ! 805: case TME_RECODE_OPERAND_ZERO: ! 806: s = "g0"; ! 807: if (operand_i == 2 ! 808: && insns->tme_recode_insn_opcode == TME_RECODE_OPCODE_GUEST) { ! 809: s = "null"; ! 810: } ! 811: break; ! 812: case TME_SPARC_IREG_PC: s = "pc"; break; ! 813: case TME_SPARC_IREG_PC_NEXT: s = "pc_next"; break; ! 814: case TME_SPARC_IREG_PC_NEXT_NEXT: s = "pc_next_next"; break; ! 815: case TME_SPARC_IREG_INSN: s = "insn"; break; ! 816: case TME_SPARC_IREG_TMP(0): s = "tmp0"; break; ! 817: case TME_SPARC_IREG_TMP(1): s = "tmp1"; break; ! 818: case TME_SPARC_IREG_TMP(2): s = "tmp2"; break; ! 819: default: ! 820: if (insns->tme_recode_insn_operands[operand_i] < 32) { ! 821: printf("%%%c%u", ! 822: regcs[insns->tme_recode_insn_operands[operand_i] / 8], ! 823: (insns->tme_recode_insn_operands[operand_i] % 8)); ! 824: continue; ! 825: } ! 826: s = "??"; ! 827: break; ! 828: } ! 829: printf("%%%s", s); ! 830: } ! 831: } ! 832: ! 833: if (insns->tme_recode_insn_opcode < TME_RECODE_OPCODES_INTEGER ! 834: && insns->tme_recode_insn_flags_thunk != NULL) { ! 835: printf(", %%%s", ! 836: (TME_SPARC_VERSION(ic) < 9 ! 837: ? "icc" ! 838: : insns->tme_recode_insn_flags_thunk == ic->tme_sparc_recode_flags_thunk_rcc ! 839: ? "rcc" ! 840: : "ccr")); ! 841: } ! 842: ! 843: putchar('\n'); ! 844: } ! 845: ! 846: chain_info = ic->tme_sparc_recode_insns_group.tme_recode_insns_group_chain_info; ! 847: printf("chain %s %s ", ! 848: ((chain_info & TME_RECODE_CHAIN_INFO_JUMP) ! 849: ? "jump" ! 850: : (chain_info & TME_RECODE_CHAIN_INFO_RETURN) ! 851: ? "return" ! 852: : "call"), ! 853: (((chain_info ! 854: & (TME_RECODE_CHAIN_INFO_NEAR ! 855: | TME_RECODE_CHAIN_INFO_FAR)) ! 856: == TME_RECODE_CHAIN_INFO_NEAR) ! 857: ? "near" ! 858: : "far")); ! 859: if ((chain_info ! 860: & (TME_RECODE_CHAIN_INFO_UNCONDITIONAL ! 861: | TME_RECODE_CHAIN_INFO_CONDITIONAL)) ! 862: == TME_RECODE_CHAIN_INFO_UNCONDITIONAL) { ! 863: printf("unconditional\n"); ! 864: } ! 865: else { ! 866: printf("conditional alternate %s\n", ! 867: (((chain_info ! 868: & (TME_RECODE_CHAIN_INFO_ALTERNATE_NEAR ! 869: | TME_RECODE_CHAIN_INFO_ALTERNATE_FAR)) ! 870: == TME_RECODE_CHAIN_INFO_ALTERNATE_NEAR) ! 871: ? "near" ! 872: : "far")); ! 873: } ! 874: } ! 875: ! 876: #endif /* TME_RECODE_DEBUG */ ! 877: ! 878: #endif /* TME_HAVE_RECODE */ ! 879: ! 880: /* this initializes sparc recoding: */ ! 881: void ! 882: tme_sparc_recode_init(struct tme_sparc *ic) ! 883: { ! 884: #if TME_HAVE_RECODE ! 885: unsigned long reg_guest_count; ! 886: unsigned long reg_guest; ! 887: struct tme_recode_ic *recode_ic; ! 888: ! 889: /* get the number of guest registers: */ ! 890: reg_guest_count = TME_SPARC_IREG_TMP(3); ! 891: ! 892: /* allocate the recode ic: */ ! 893: recode_ic ! 894: = tme_malloc0(sizeof(struct tme_recode_ic) ! 895: + (sizeof(union tme_recode_reginfo) ! 896: * reg_guest_count)); ! 897: ic->tme_sparc_recode_ic = recode_ic; ! 898: ! 899: /* set the register size: */ ! 900: recode_ic->tme_recode_ic_reg_size = TME_SPARC_RECODE_SIZE(ic); ! 901: ! 902: /* set the register count: */ ! 903: recode_ic->tme_recode_ic_reg_count = reg_guest_count; ! 904: ! 905: /* allocate some number of read-uses records: */ ! 906: /* XXX FIXME - this can be anything, and doesn't affect correctness, ! 907: just performance. should it be tunable? */ ! 908: recode_ic->tme_recode_ic_reg_guest_ruses_record_count = 512; ! 909: recode_ic->tme_recode_ic_reg_guest_ruses_records ! 910: = tme_new(tme_uint16_t, ! 911: recode_ic->tme_recode_ic_reg_guest_ruses_record_count + 1); ! 912: recode_ic->tme_recode_ic_reg_guest_ruses_records ! 913: [recode_ic->tme_recode_ic_reg_guest_ruses_record_count] ! 914: = TME_RECODE_REG_RUSES_RECORD_UNDEF; ! 915: ! 916: /* assume that all registers use flat addressing: */ ! 917: for (reg_guest = 0; ! 918: reg_guest < reg_guest_count; ! 919: reg_guest++) { ! 920: (recode_ic->tme_recode_ic_reginfo ! 921: + reg_guest)->tme_recode_reginfo_all = TME_RECODE_REGINFO_TYPE_FLAT; ! 922: } ! 923: ! 924: /* %g0 is fixed: */ ! 925: (recode_ic->tme_recode_ic_reginfo ! 926: + TME_RECODE_REG_GUEST(TME_SPARC_IREG_G0))->tme_recode_reginfo_all ! 927: |= TME_RECODE_REGINFO_TYPE_FIXED; ! 928: ! 929: /* %r8 through %r23 are addressed through window zero, and %r24 ! 930: through %r31 are addressed through window one: */ ! 931: reg_guest = TME_RECODE_REG_GUEST(8); ! 932: do { ! 933: (recode_ic->tme_recode_ic_reginfo ! 934: + reg_guest)->tme_recode_reginfo_all = TME_RECODE_REGINFO_TYPE_WINDOW(0); ! 935: } while (++reg_guest <= TME_RECODE_REG_GUEST(23)); ! 936: do { ! 937: (recode_ic->tme_recode_ic_reginfo ! 938: + reg_guest)->tme_recode_reginfo_all = TME_RECODE_REGINFO_TYPE_WINDOW(1); ! 939: } while (++reg_guest <= TME_RECODE_REG_GUEST(31)); ! 940: ! 941: /* on a v9 CPU, %r1 through %r7 are addressed through window two: */ ! 942: if (TME_SPARC_VERSION(ic) >= 9) { ! 943: reg_guest = TME_RECODE_REG_GUEST(1); ! 944: do { ! 945: (recode_ic->tme_recode_ic_reginfo ! 946: + reg_guest)->tme_recode_reginfo_all = TME_RECODE_REGINFO_TYPE_WINDOW(2); ! 947: } while (++reg_guest <= TME_RECODE_REG_GUEST(7)); ! 948: } ! 949: ! 950: /* the temporary registers are temporary: */ ! 951: reg_guest = TME_RECODE_REG_GUEST(TME_SPARC_IREG_TMP(0)); ! 952: do { ! 953: (recode_ic->tme_recode_ic_reginfo ! 954: + reg_guest)->tme_recode_reginfo_all ! 955: |= TME_RECODE_REGINFO_TYPE_TEMPORARY; ! 956: } while (++reg_guest <= TME_RECODE_REG_GUEST(TME_SPARC_IREG_TMP(2))); ! 957: ! 958: /* set the window base offsets: */ ! 959: recode_ic->tme_recode_ic_window_base_offsets[0] ! 960: = (((char *) &ic->tme_sparc_recode_window_base_offsets[0]) - ((char *) ic)); ! 961: recode_ic->tme_recode_ic_window_base_offsets[1] ! 962: = (((char *) &ic->tme_sparc_recode_window_base_offsets[1]) - ((char *) ic)); ! 963: recode_ic->tme_recode_ic_window_base_offsets[2] ! 964: = (((char *) &ic->tme_sparc_recode_window_base_offsets[2]) - ((char *) ic)); ! 965: ! 966: /* initialize the cacheables: */ ! 967: ic->tme_sparc_recode_cacheables[0].tme_sparc_recode_cacheable_size = 0; ! 968: ic->tme_sparc_recode_cacheable_first = &ic->tme_sparc_recode_cacheables[0]; ! 969: ! 970: /* invalidate the entire source hash: */ ! 971: _tme_sparc_recode_src_hash_invalidate(ic, 0, 0); ! 972: ! 973: /* set the TLB page size: */ ! 974: recode_ic->tme_recode_ic_tlb_page_size ! 975: = (((tme_uint32_t) 1) << ic->tme_sparc_tlb_page_size_log2); ! 976: ! 977: /* set the pointer to the first instruction in a group: */ ! 978: ic->tme_sparc_recode_insns_group.tme_recode_insns_group_insns ! 979: = &ic->tme_sparc_recode_insns[0]; ! 980: ! 981: /* initialize the recode ic: */ ! 982: /* XXX FIXME - this run size should be passed in as an argument. it ! 983: needs to be big enough for the maximum number of non-variable ! 984: thunks (flags, conds, chain, etc.) that we will make, probably ! 985: TME_RECODE_HOST_THUNK_SIZE_MAX times some n? */ ! 986: tme_recode_ic_new(recode_ic, 4 * 1024 * 1024); ! 987: ! 988: /* call the architecture-specific init functions: */ ! 989: if (TME_SPARC_VERSION(ic) >= 9) { ! 990: #if TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 ! 991: _tme_sparc64_recode_cc_init(ic); ! 992: _tme_sparc64_recode_chain_init(ic); ! 993: _tme_sparc64_recode_ls_init(ic); ! 994: #endif /* TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 */ ! 995: } ! 996: else { ! 997: _tme_sparc32_recode_cc_init(ic); ! 998: _tme_sparc32_recode_chain_init(ic); ! 999: _tme_sparc32_recode_ls_init(ic); ! 1000: } ! 1001: ! 1002: #ifdef _TME_SPARC_RECODE_VERIFY ! 1003: ! 1004: /* initialize the verifier: */ ! 1005: _tme_sparc_recode_verify_init(ic); ! 1006: ! 1007: #endif /* _TME_SPARC_RECODE_VERIFY */ ! 1008: ! 1009: #else /* !TME_HAVE_RECODE */ ! 1010: /* unused: */ ! 1011: ic = 0; ! 1012: #endif /* !TME_HAVE_RECODE */ ! 1013: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.