Annotation of tme/ic/sparc/sparc-rc-chain.c, revision 1.1

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

unix.superglobalmegacorp.com

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