Annotation of tme/ic/sparc/sparc-recode.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.