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

1.1     ! root        1: /* $Id: sparc-rc-ls.c,v 1.6 2010/06/05 17:08:57 fredette Exp $ */
        !             2: 
        !             3: /* ic/sparc/sparc-rc-cc.c - SPARC recode ld/st support: */
        !             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: #if TME_SPARC_RECODE_SIZE(ic) == TME_RECODE_SIZE_32
        !            37: 
        !            38: _TME_RCSID("$Id: sparc-rc-ls.c,v 1.6 2010/06/05 17:08:57 fredette Exp $");
        !            39: 
        !            40: /* macros: */
        !            41: 
        !            42: /* rename various things by the architecture size: */
        !            43: #define _tme_sparc_recode_ls_assist_check _TME_SPARC_RECODE_SIZE(_tme_sparc,_recode_ls_assist_check)
        !            44: #define _tme_sparc_recode_ls_assist_ld _TME_SPARC_RECODE_SIZE(_tme_sparc,_recode_ls_assist_ld)
        !            45: #define _tme_sparc_recode_ls_assist_st _TME_SPARC_RECODE_SIZE(_tme_sparc,_recode_ls_assist_st)
        !            46: #define tme_sparc_recode_ls_tlb_update _TME_SPARC_RECODE_SIZE(tme_sparc,_recode_ls_tlb_update)
        !            47: #define _tme_sparc_recode_ls_init _TME_SPARC_RECODE_SIZE(_tme_sparc,_recode_ls_init)
        !            48: 
        !            49: #endif /* TME_SPARC_RECODE_SIZE(ic) == TME_RECODE_SIZE_32 */
        !            50: 
        !            51: /* this checks whether a load or store needs an assist: */
        !            52: void
        !            53: _tme_sparc_recode_ls_assist_check(const struct tme_sparc *ic,
        !            54:                                  tme_recode_uguest_t recode_address,
        !            55:                                  int assisted)
        !            56: {
        !            57:   tme_uint32_t sparc_insn;
        !            58:   unsigned int reg_rs2;
        !            59:   tme_sparc_ireg_t sparc_address;
        !            60:   unsigned int reg_rs1;
        !            61:   tme_uint32_t sparc_opcode;
        !            62:   tme_bus_context_t context;
        !            63:   tme_uint32_t asi_mask_flags_assist;
        !            64:   unsigned int asi;
        !            65:   tme_uint32_t asi_mask_flags;
        !            66:   const struct tme_sparc_tlb *dtlb;
        !            67:   tme_uint32_t asi_mask;
        !            68:   tme_uint32_t dtlb_page_size;
        !            69:   tme_sparc_ireg_t sparc_page;
        !            70: 
        !            71:   /* get the instruction: */
        !            72:   sparc_insn = ic->_tme_sparc_insn;
        !            73: 
        !            74:   /* if the i bit is zero: */
        !            75:   if ((sparc_insn & TME_BIT(13)) == 0) {
        !            76: 
        !            77:     /* decode rs2: */
        !            78:     reg_rs2 = TME_FIELD_MASK_EXTRACTU(sparc_insn, TME_SPARC_FORMAT3_MASK_RS2);
        !            79:     TME_SPARC_REG_INDEX(ic, reg_rs2);
        !            80:     sparc_address = ic->tme_sparc_ireg(reg_rs2);
        !            81:   }
        !            82: 
        !            83:   /* otherwise, the i bit is one: */
        !            84:   else {
        !            85: 
        !            86:     /* decode simm13: */
        !            87:     sparc_address = TME_FIELD_MASK_EXTRACTS(sparc_insn, (tme_sparc_ireg_t) 0x1fff);
        !            88:   }
        !            89: 
        !            90:   /* decode rs1: */
        !            91:   reg_rs1 = TME_FIELD_MASK_EXTRACTU(sparc_insn, TME_SPARC_FORMAT3_MASK_RS1);
        !            92:   TME_SPARC_REG_INDEX(ic, reg_rs1);
        !            93:   sparc_address += ic->tme_sparc_ireg(reg_rs1);
        !            94: 
        !            95:   /* mask the addresses: */
        !            96:   if (TME_SPARC_VERSION(ic) >= 9) {
        !            97:     sparc_address &= ic->tme_sparc_address_mask;
        !            98:     recode_address &= ic->tme_sparc_address_mask;
        !            99:   }
        !           100: 
        !           101:   /* check the address: */
        !           102:   assert (sparc_address == (tme_sparc_ireg_t) recode_address);
        !           103: 
        !           104:   /* if this instruction is being assisted, return now: */
        !           105:   if (assisted) {
        !           106:     return;
        !           107:   }
        !           108: 
        !           109:   /* the verifier must not be on: */
        !           110:   assert (!_tme_sparc_recode_verify_on);
        !           111: 
        !           112:   /* get the instruction opcode: */
        !           113:   sparc_opcode = TME_FIELD_MASK_EXTRACTU(sparc_insn, (0x3f << 19));
        !           114: 
        !           115:   /* the address must be aligned: */
        !           116:   assert ((sparc_address
        !           117:           & ((TME_SPARC_VERSION(ic) >= 9
        !           118:               && (sparc_opcode == 0x0b /* v9: ldx */
        !           119:                   || sparc_opcode == 0x0e))
        !           120:              ? (sizeof(tme_sparc_ireg_t) - 1)
        !           121:              : ((sparc_opcode - 1)
        !           122:                 & (sizeof(tme_uint32_t) - 1)))) == 0);
        !           123: 
        !           124:   /* assume that this load or store uses the default context: */
        !           125:   context = ic->tme_sparc_memory_context_default;
        !           126:   
        !           127:   /* assume that only DTLB ASI mask flags for special ASIs must be assisted: */
        !           128:   asi_mask_flags_assist = TME_SPARC_ASI_MASK_FLAG_SPECIAL;
        !           129: 
        !           130:   /* if this is a v9 CPU, assume that a load or store to a no-fault
        !           131:      address must be assisted: */
        !           132:   if (TME_SPARC_VERSION(ic) >= 9) {
        !           133:     asi_mask_flags_assist += TME_SPARC64_ASI_FLAG_NO_FAULT;
        !           134:   }
        !           135: 
        !           136:   /* if this is a load or store with an alternate space: */
        !           137:   if (__tme_predict_false(sparc_insn & TME_BIT(19 + 4))) {
        !           138: 
        !           139:     /* get the ASI: */
        !           140:     asi = ((TME_SPARC_VERSION(ic) >= 9
        !           141:            && (sparc_insn & TME_BIT(13)))
        !           142:           ? ic->tme_sparc64_ireg_asi
        !           143:           : TME_FIELD_MASK_EXTRACTU(sparc_insn, (0xff << 5)));
        !           144: 
        !           145:     /* get the flags for this ASI: */
        !           146:     asi_mask_flags = ic->tme_sparc_asis[asi].tme_sparc_asi_mask_flags;
        !           147: 
        !           148:     /* if this is a v9 CPU: */
        !           149:     if (TME_SPARC_VERSION(ic) >= 9) {
        !           150: 
        !           151:       /* get the context: */
        !           152:       context
        !           153:        = (((TME_SPARC_MEMORY_FLAGS(ic) & TME_SPARC_MEMORY_FLAG_HAS_NUCLEUS)
        !           154:            && (asi_mask_flags & TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS))
        !           155:           ? 0
        !           156:           : (asi_mask_flags & TME_SPARC64_ASI_FLAG_SECONDARY)
        !           157:           ? ic->tme_sparc_memory_context_secondary
        !           158:           : ic->tme_sparc_memory_context_primary);
        !           159:     }
        !           160: 
        !           161:     /* this must be a load from an alternate space: */
        !           162:     assert ((sparc_insn & TME_BIT(19 + 2)) == 0);
        !           163: 
        !           164:     /* this must be a v9 CPU: */
        !           165:     assert (TME_SPARC_VERSION(ic) >= 9);
        !           166: 
        !           167:     /* this v9 CPU must not be in nucleus context: */
        !           168:     /* NB: this implies that when a v9 CPU is in nucleus context, even
        !           169:        loads that specify an immediate no-fault ASI are assisted: */
        !           170:     assert ((TME_SPARC_MEMORY_FLAGS(ic) & TME_SPARC_MEMORY_FLAG_HAS_NUCLEUS) == 0
        !           171:            || ic->tme_sparc64_ireg_tl == 0);
        !           172: 
        !           173:     /* this ASI must be the default data ASI with the no-fault bit
        !           174:        set: */
        !           175:     assert (asi 
        !           176:            == (TME_SPARC_ASI_MASK_WHICH(ic->tme_sparc_asi_mask_data)
        !           177:                + TME_SPARC64_ASI_FLAG_NO_FAULT));
        !           178: 
        !           179:     /* this load doesn't necessarily need an assist if it's to a
        !           180:        no-fault address: */
        !           181:     asi_mask_flags_assist -= TME_SPARC64_ASI_FLAG_NO_FAULT;
        !           182:   }
        !           183: 
        !           184:   /* get the DTLB entry: */
        !           185:   dtlb = &ic->tme_sparc_tlbs[TME_SPARC_DTLB_ENTRY(ic, TME_SPARC_TLB_HASH(ic, context, sparc_address))];
        !           186: 
        !           187:   /* the DTLB entry must be valid: */
        !           188:   assert (!tme_bus_tlb_is_invalid(&dtlb->tme_sparc_tlb_bus_tlb));
        !           189: 
        !           190:   /* the DTLB entry must match the context: */
        !           191:   assert (dtlb->tme_sparc_tlb_context == context
        !           192:          || dtlb->tme_sparc_tlb_context > ic->tme_sparc_memory_context_max);
        !           193: 
        !           194:   /* the DTLB entry must cover the page: */
        !           195:   dtlb_page_size = (1 << ic->tme_sparc_tlb_page_size_log2);
        !           196:   sparc_page = sparc_address & (0 - (tme_sparc_ireg_t) dtlb_page_size);
        !           197:   assert ((((tme_sparc_ireg_t) dtlb->tme_sparc_tlb_addr_first)
        !           198:           <= sparc_page)
        !           199:          && (((tme_sparc_ireg_t) dtlb->tme_sparc_tlb_addr_last)
        !           200:              >= (sparc_page + dtlb_page_size - 1)));
        !           201: 
        !           202:   /* if the DTLB entry doesn't allow this privilege load or store: */
        !           203:   asi_mask
        !           204:     = (TME_SPARC_VERSION(ic) >= 9
        !           205:        ? (TME_SPARC_PRIV(ic)
        !           206:          ? TME_SPARC64_ASI_MASK_REQUIRED_UNRESTRICTED(!TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER)
        !           207:          : TME_SPARC64_ASI_MASK_REQUIRED_UNRESTRICTED(TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER))
        !           208:        : (TME_SPARC_PRIV(ic)
        !           209:          ? TME_SPARC32_ASI_MASK_SD
        !           210:          : TME_SPARC32_ASI_MASK_UD));
        !           211:   assert (TME_SPARC_TLB_ASI_MASK_OK(dtlb, asi_mask));
        !           212: 
        !           213:   /* the DTLB entry ASI flags must not require an assist: */
        !           214:   assert ((dtlb->tme_sparc_tlb_asi_mask
        !           215:           & asi_mask_flags_assist) == 0);
        !           216: 
        !           217:   /* the DTLB entry must allow the fast load or store, and if this is
        !           218:      a store, it must not allow fast loads, or it must allow both to
        !           219:      the same memory: */
        !           220:   assert ((sparc_insn & TME_BIT(19 + 2))
        !           221:          ? (dtlb->tme_sparc_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF
        !           222:             && (dtlb->tme_sparc_tlb_emulator_off_read == TME_EMULATOR_OFF_UNDEF
        !           223:                 || dtlb->tme_sparc_tlb_emulator_off_read == dtlb->tme_sparc_tlb_emulator_off_write))
        !           224:          : (dtlb->tme_sparc_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF));
        !           225: }
        !           226: 
        !           227: /* the assist function for ld instructions: */
        !           228: static tme_recode_uguest_t
        !           229: _tme_sparc_recode_ls_assist_ld(struct tme_ic *_ic,
        !           230:                               tme_recode_uguest_t address)
        !           231: {
        !           232:   struct tme_sparc *ic;
        !           233:   tme_uint32_t sparc_insn;
        !           234:   tme_uint32_t sparc_opcode;
        !           235:   int insn_is_ld;
        !           236:   unsigned int reg_rd;
        !           237: #if TME_RECODE_SIZE_GUEST_MAX > TME_SPARC_RECODE_SIZE(ic)
        !           238:   tme_sparc_ireg_t rs1_buffer;
        !           239: #endif /* TME_RECODE_SIZE_GUEST_MAX > TME_SPARC_RECODE_SIZE(ic) */
        !           240:   tme_sparc_ireg_t rs2;
        !           241:   tme_sparc_ireg_t *_rs1;
        !           242: 
        !           243:   /* recover our ic: */
        !           244:   ic = (struct tme_sparc *) _ic;
        !           245: 
        !           246:   TME_SPARC_STAT(ic, tme_sparc_stats_recode_assist_ld);
        !           247: 
        !           248:   /* set PC_next_next from PC_next: */
        !           249:   ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT_NEXT)
        !           250:     = (ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT)
        !           251:        + sizeof(tme_uint32_t));
        !           252: 
        !           253:   /* get the instruction: */
        !           254:   sparc_insn = tme_sparc_recode_insn_current(ic);
        !           255:   ic->_tme_sparc_insn = sparc_insn;
        !           256: 
        !           257:   /* see if this instruction is a load: */
        !           258:   sparc_opcode = 0x40 + TME_FIELD_MASK_EXTRACTU(sparc_insn, (0x3f << 19));
        !           259:   insn_is_ld
        !           260:     = (sparc_insn >= 0xc0000000
        !           261:        && _tme_sparc_recode_insn_opmap[sparc_opcode] == TME_SPARC_RECODE_INSN_LD);
        !           262: 
        !           263:   /* if this is a cooperative threading system: */
        !           264:   if (TME_THREADS_COOPERATIVE) {
        !           265: 
        !           266:     /* this instruction must be the original load instruction from
        !           267:        when the instructions thunk was recoded.  we have no way to
        !           268:        confirm this.  if it's not, because this is a cooperative
        !           269:        threading system, that means that either
        !           270:        tme_sparc_recode_insn_assist_redispatch(), or
        !           271:        tme_sparc_recode(), or the host chain in failed to detect that
        !           272:        the page containing this PC is no longer cache-valid: */
        !           273:     assert (insn_is_ld);
        !           274:   }
        !           275: 
        !           276:   /* otherwise, this isn't a cooperative threading system: */
        !           277:   else {
        !           278: 
        !           279:     /* if this isn't a load instruction: */
        !           280:     if (__tme_predict_false(!insn_is_ld)) {
        !           281:       abort();
        !           282:     }
        !           283: 
        !           284:     /* otherwise, this is a load instruction: */
        !           285: 
        !           286:     /* NB: it's possible that this load instruction is not the
        !           287:        original load instruction from when the instructions thunk was
        !           288:        recoded.  we have no way of knowing if it is or isn't.  if it
        !           289:        isn't, this new load instruction may have different rs1, rs2,
        !           290:        and rd fields than the original load instruction: */
        !           291:     abort();
        !           292:   }
        !           293: 
        !           294:   TME_SPARC_STAT(ic, tme_sparc_stats_recode_assist_opcode[sparc_opcode]);
        !           295: 
        !           296:   /* decode rd: */
        !           297:   reg_rd = TME_FIELD_MASK_EXTRACTU(sparc_insn, TME_SPARC_FORMAT3_MASK_RD);
        !           298:   TME_SPARC_REG_INDEX(ic, reg_rd);
        !           299: 
        !           300:   /* run the instruction: */
        !           301:   rs2 = 0;
        !           302: #if TME_RECODE_SIZE_GUEST_MAX > TME_SPARC_RECODE_SIZE(ic)
        !           303:   rs1_buffer = address;
        !           304:   _rs1 = &rs1_buffer;
        !           305: #else  /* TME_RECODE_SIZE_GUEST_MAX == TME_SPARC_RECODE_SIZE(ic) */
        !           306:   _rs1 = &address;
        !           307: #endif /* TME_RECODE_SIZE_GUEST_MAX == TME_SPARC_RECODE_SIZE(ic) */
        !           308: #ifdef _TME_SPARC_RECODE_VERIFY
        !           309:   _tme_sparc_recode_ls_assist_check(ic, *_rs1, TRUE);
        !           310: #endif /* _TME_SPARC_RECODE_VERIFY */
        !           311:   (*ic->_tme_sparc_execute_opmap[sparc_opcode])
        !           312:     (ic,
        !           313:      _rs1,
        !           314:      &rs2,
        !           315:      &ic->tme_sparc_ireg(reg_rd));
        !           316: 
        !           317:   /* set %g0 to zero, in case the instruction changed it: */
        !           318:   ic->tme_sparc_ireg(TME_SPARC_G0_OFFSET(ic) + TME_SPARC_IREG_G0) = 0;
        !           319: 
        !           320:   /* do any required redispatch: */
        !           321:   /* NB: in a noncooperative threading system, this will do any needed
        !           322:      redispatch after we executed a new load instruction that is
        !           323:      different from the original load instruction from when the
        !           324:      instructions thunk was recoded.  in that case, we can't return to
        !           325:      the instructions thunk since it will take our return value for
        !           326:      the rd register in the original instruction, not for the rd
        !           327:      register in the new instruction: */
        !           328:   /* NB: in any threading system, this will do any needed redispatch
        !           329:      after a load instruction changes the state of the system such
        !           330:      that we can't return to the instructions thunk.  this is very
        !           331:      unusual: */
        !           332:   tme_sparc_recode_insn_assist_redispatch(ic);
        !           333: 
        !           334:   /* return the result: */
        !           335:   return (ic->tme_sparc_ireg(reg_rd));
        !           336: }
        !           337: 
        !           338: /* the assist function for st instructions: */
        !           339: static void
        !           340: _tme_sparc_recode_ls_assist_st(struct tme_ic *_ic,
        !           341:                               tme_recode_uguest_t address,
        !           342:                               tme_recode_uguest_t rd)
        !           343: {
        !           344:   struct tme_sparc *ic;
        !           345:   tme_uint32_t sparc_insn;
        !           346:   tme_uint32_t sparc_opcode;
        !           347:   int insn_is_st;
        !           348: #if TME_RECODE_SIZE_GUEST_MAX > TME_SPARC_RECODE_SIZE(ic)
        !           349:   tme_sparc_ireg_t rs1_buffer;
        !           350:   tme_sparc_ireg_t rd_buffer;
        !           351: #endif /* TME_RECODE_SIZE_GUEST_MAX > TME_SPARC_RECODE_SIZE(ic) */
        !           352:   tme_sparc_ireg_t *_rs1;
        !           353:   tme_sparc_ireg_t rs2;
        !           354:   tme_sparc_ireg_t *_rd;
        !           355: 
        !           356:   /* recover our ic: */
        !           357:   ic = (struct tme_sparc *) _ic;
        !           358: 
        !           359:   TME_SPARC_STAT(ic, tme_sparc_stats_recode_assist_st);
        !           360: 
        !           361:   /* set PC_next_next from PC_next: */
        !           362:   ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT_NEXT)
        !           363:     = (ic->tme_sparc_ireg(TME_SPARC_IREG_PC_NEXT)
        !           364:        + sizeof(tme_uint32_t));
        !           365: 
        !           366:   /* get the instruction: */
        !           367:   sparc_insn = tme_sparc_recode_insn_current(ic);
        !           368:   ic->_tme_sparc_insn = sparc_insn;
        !           369: 
        !           370:   /* see if this instruction is a store: */
        !           371:   sparc_opcode = (0x40 + TME_FIELD_MASK_EXTRACTU(sparc_insn, (0x3f << 19)));
        !           372:   insn_is_st
        !           373:     = (sparc_insn >= 0xc0000000
        !           374:        && _tme_sparc_recode_insn_opmap[sparc_opcode] == TME_SPARC_RECODE_INSN_ST);
        !           375: 
        !           376:   /* if this is a cooperative threading system: */
        !           377:   if (TME_THREADS_COOPERATIVE) {
        !           378: 
        !           379:     /* this instruction must be the original store instruction from
        !           380:        when the instructions thunk was recoded.  we have no way to
        !           381:        confirm this.  if it's not, because this is a cooperative
        !           382:        threading system, that means that either
        !           383:        tme_sparc_recode_insn_assist_redispatch(), or
        !           384:        tme_sparc_recode(), or the host chain in failed to detect that
        !           385:        the page containing this PC is no longer cache-valid: */
        !           386:     assert (insn_is_st);
        !           387:   }
        !           388: 
        !           389:   /* otherwise, this isn't a cooperative threading system: */
        !           390:   else {
        !           391: 
        !           392:     /* if this isn't a store instruction: */
        !           393:     if (__tme_predict_false(!insn_is_st)) {
        !           394:       abort();
        !           395:     }
        !           396: 
        !           397:     /* otherwise, this is a store instruction: */
        !           398: 
        !           399:     /* NB: it's possible that this store instruction is not the
        !           400:        original store instruction from when the instructions thunk was
        !           401:        recoded.  we have no way of knowing if it is or isn't.  if it
        !           402:        isn't, this new store instruction may have different rs1, rs2,
        !           403:        and rd fields than the original store instruction: */
        !           404:     abort();
        !           405:   }
        !           406: 
        !           407:   TME_SPARC_STAT(ic, tme_sparc_stats_recode_assist_opcode[sparc_opcode]);
        !           408: 
        !           409:   /* run the store instruction: */
        !           410:   rs2 = 0;
        !           411: #if TME_RECODE_SIZE_GUEST_MAX > TME_SPARC_RECODE_SIZE(ic)
        !           412:   rs1_buffer = address;
        !           413:   rd_buffer = rd;
        !           414:   _rs1 = &rs1_buffer;
        !           415:   _rd = &rd_buffer;
        !           416: #else  /* TME_RECODE_SIZE_GUEST_MAX == TME_SPARC_RECODE_SIZE(ic) */
        !           417:   _rs1 = &address;
        !           418:   _rd = &rd;
        !           419: #endif /* TME_RECODE_SIZE_GUEST_MAX == TME_SPARC_RECODE_SIZE(ic) */
        !           420: #ifdef _TME_SPARC_RECODE_VERIFY
        !           421:   _tme_sparc_recode_ls_assist_check(ic, *_rs1, TRUE);
        !           422: #endif /* _TME_SPARC_RECODE_VERIFY */
        !           423:   (*ic->_tme_sparc_execute_opmap[sparc_opcode])
        !           424:     (ic, _rs1, &rs2, _rd);
        !           425: 
        !           426:   /* return no result: */
        !           427:   tme_sparc_recode_insn_assist_redispatch(ic);
        !           428: }
        !           429: 
        !           430: /* this updates a recode DTLB entry: */
        !           431: void
        !           432: tme_sparc_recode_ls_tlb_update(struct tme_sparc *ic,
        !           433:                               const struct tme_sparc_ls *ls)
        !           434: {
        !           435:   const struct tme_sparc_tlb *dtlb;
        !           436:   tme_uint32_t dtlb_page_size;
        !           437:   struct _TME_SPARC_RECODE_SIZE(tme_recode_tlb_c16_a,/**/) *recode_tlb;
        !           438:   tme_uint32_t rw_flags_tlb;
        !           439:   tme_sparc_ireg_t recode_tlb_page;
        !           440: 
        !           441:   /* get the sparc DTLB entry: */
        !           442:   dtlb = ls->tme_sparc_ls_tlb;
        !           443: 
        !           444:   /* get the recode DTLB entry: */
        !           445:   recode_tlb = &ic->_TME_SPARC_RECODE_SIZE(tme_sparc_recode_tlb,s)[ls->tme_sparc_ls_tlb_i];
        !           446: 
        !           447:   /* assume that this recode DTLB entry will assist all loads and
        !           448:      stores (this mask includes at least
        !           449:      TME_SPARC_RECODE_TLB_FLAG_LD_USER(ic),
        !           450:      TME_SPARC_RECODE_TLB_FLAG_LD_PRIV(ic),
        !           451:      TME_SPARC_RECODE_TLB_FLAG_ST_USER(ic), and
        !           452:      TME_SPARC_RECODE_TLB_FLAG_ST_PRIV(ic)): */
        !           453:   rw_flags_tlb = TME_RECODE_TLB_FLAGS_MASK(ic->tme_sparc_recode_ic);
        !           454: 
        !           455:   /* get our DTLB page size: */
        !           456:   dtlb_page_size = (1 << ic->tme_sparc_tlb_page_size_log2);
        !           457: 
        !           458:   /* update the recode DTLB entry page: */
        !           459:   recode_tlb_page = ls->_TME_SPARC_RECODE_SIZE(tme_sparc_ls_address,/**/) & (0 - (tme_sparc_ireg_t) dtlb_page_size);
        !           460:   recode_tlb->_TME_SPARC_RECODE_SIZE(tme_recode_tlb_c16_a,_page) = recode_tlb_page;
        !           461: 
        !           462:   /* if the sparc DTLB entry covers an entire page for one or more
        !           463:      normal ASIs, and verification isn't on: */
        !           464:   if ((((tme_sparc_ireg_t) dtlb->tme_sparc_tlb_addr_first)
        !           465:        <= recode_tlb_page)
        !           466:       && ((recode_tlb_page | (dtlb_page_size - 1))
        !           467:          <= ((tme_sparc_ireg_t) dtlb->tme_sparc_tlb_addr_last))
        !           468:       && (dtlb->tme_sparc_tlb_asi_mask & TME_SPARC_ASI_MASK_FLAG_SPECIAL) == 0
        !           469:       && !_tme_sparc_recode_verify_on) {
        !           470: 
        !           471:     /* if the sparc DTLB entry allows fast reading: */
        !           472:     if (dtlb->tme_sparc_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF) {
        !           473: 
        !           474:       /* update the recode DTLB entry page memory pointer: */
        !           475:       recode_tlb->_TME_SPARC_RECODE_SIZE(tme_recode_tlb_c16_a,_memory)
        !           476:        = (dtlb->tme_sparc_tlb_emulator_off_read
        !           477:           + recode_tlb_page);
        !           478: 
        !           479:       /* if this sparc DTLB entry allows user loads: */
        !           480:       if (TME_SPARC_TLB_ASI_MASK_OK(dtlb, 
        !           481:                                    (TME_SPARC_VERSION(ic) >= 9
        !           482:                                     ? TME_SPARC64_ASI_MASK_REQUIRED_UNRESTRICTED(TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER)
        !           483:                                     : TME_SPARC32_ASI_MASK_UD))) {
        !           484: 
        !           485:        /* this recode DTLB entry probably won't need an assist for
        !           486:           user loads (a sparc DTLB entry with side-effects will
        !           487:           override this): */
        !           488:        rw_flags_tlb
        !           489:          -= TME_SPARC_RECODE_TLB_FLAG_LD_USER(ic);
        !           490:       }
        !           491: 
        !           492:       /* if this sparc DTLB entry allows privileged/supervisor
        !           493:         loads: */
        !           494:       if (TME_SPARC_TLB_ASI_MASK_OK(dtlb, 
        !           495:                                    (TME_SPARC_VERSION(ic) >= 9
        !           496:                                     ? TME_SPARC64_ASI_MASK_REQUIRED_UNRESTRICTED(!TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER)
        !           497:                                     : TME_SPARC32_ASI_MASK_SD))) {
        !           498: 
        !           499:        /* this recode DTLB entry probably won't need an assist for
        !           500:           privileged/supervisor loads (a sparc DTLB entry with
        !           501:           side-effects will override this): */
        !           502:        rw_flags_tlb
        !           503:          -= TME_SPARC_RECODE_TLB_FLAG_LD_PRIV(ic);
        !           504:       }
        !           505:     }
        !           506: 
        !           507:     /* if the sparc DTLB entry allows fast writing, and it either
        !           508:        doesn't allow fast reading or the fast read and write pointers
        !           509:        are the same: */
        !           510:     if (dtlb->tme_sparc_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF
        !           511:        && (dtlb->tme_sparc_tlb_emulator_off_read == TME_EMULATOR_OFF_UNDEF
        !           512:            || dtlb->tme_sparc_tlb_emulator_off_write == dtlb->tme_sparc_tlb_emulator_off_read)) {
        !           513: 
        !           514:       /* update the recode DTLB entry page memory pointer: */
        !           515:       recode_tlb->_TME_SPARC_RECODE_SIZE(tme_recode_tlb_c16_a,_memory)
        !           516:        = (dtlb->tme_sparc_tlb_emulator_off_write
        !           517:           + recode_tlb_page);
        !           518: 
        !           519:       /* if this sparc DTLB entry allows user stores: */
        !           520:       if (TME_SPARC_TLB_ASI_MASK_OK(dtlb, 
        !           521:                                    (TME_SPARC_VERSION(ic) >= 9
        !           522:                                     ? TME_SPARC64_ASI_MASK_REQUIRED_UNRESTRICTED(TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER)
        !           523:                                     : TME_SPARC32_ASI_MASK_UD))) {
        !           524: 
        !           525:        /* this recode DTLB entry probably won't need an assist for
        !           526:           user stores (a sparc DTLB entry with side-effects will
        !           527:           override this): */
        !           528:        rw_flags_tlb
        !           529:          -= TME_SPARC_RECODE_TLB_FLAG_ST_USER(ic);
        !           530:       }
        !           531: 
        !           532:       /* if this sparc DTLB entry allows privileged/supervisor
        !           533:         stores: */
        !           534:       if (TME_SPARC_TLB_ASI_MASK_OK(dtlb, 
        !           535:                                    (TME_SPARC_VERSION(ic) >= 9
        !           536:                                     ? TME_SPARC64_ASI_MASK_REQUIRED_UNRESTRICTED(!TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER)
        !           537:                                     : TME_SPARC32_ASI_MASK_SD))) {
        !           538: 
        !           539:        /* this recode DTLB entry probably won't need an assist for
        !           540:           privileged/supervisor stores (a sparc DTLB entry with
        !           541:           side-effects will override this): */
        !           542:        rw_flags_tlb
        !           543:          -= TME_SPARC_RECODE_TLB_FLAG_ST_PRIV(ic);
        !           544:       }
        !           545:     }
        !           546: 
        !           547:     /* this recode DTLB entry needs an assist for no-fault loads when
        !           548:        the ASI register is not loaded with the correct default
        !           549:        no-fault ASI: */
        !           550:     assert (rw_flags_tlb & TME_SPARC_RECODE_TLB_FLAG_LD_NF(ic));
        !           551: 
        !           552:     /* if this sparc DTLB entry does not only allow no-fault loads: */
        !           553:     if (TME_SPARC_VERSION(ic) < 9
        !           554:        || (dtlb->tme_sparc_tlb_asi_mask & TME_SPARC64_ASI_FLAG_NO_FAULT) == 0) {
        !           555: 
        !           556:       /* this recode DTLB entry doesn't need an assist for faulting
        !           557:         loads: */
        !           558:       rw_flags_tlb -= TME_SPARC_RECODE_TLB_FLAG_LD_F(ic);
        !           559:     }
        !           560: 
        !           561:     /* if this sparc DTLB entry is for addresses with side-effects
        !           562:        (regardless of whether or not the sparc DTLB entry allows fast
        !           563:        reads and/or writes): */
        !           564:     if (TME_SPARC_VERSION(ic) >= 9
        !           565:        && (dtlb->tme_sparc_tlb_asi_mask & TME_SPARC64_ASI_MASK_FLAG_TLB_SIDE_EFFECTS)) {
        !           566: 
        !           567:       /* this recode DTLB entry needs an assist for all loads and stores: */
        !           568:       rw_flags_tlb
        !           569:        |= (TME_SPARC_RECODE_TLB_FLAG_LD_USER(ic)
        !           570:            | TME_SPARC_RECODE_TLB_FLAG_LD_PRIV(ic)
        !           571:            | TME_SPARC_RECODE_TLB_FLAG_ST_USER(ic)
        !           572:            | TME_SPARC_RECODE_TLB_FLAG_ST_PRIV(ic));
        !           573:     }
        !           574: 
        !           575:     /* if this is sparc32, or if this sparc64 MMU has an invert-endian bit: */
        !           576:     if (TME_SPARC_VERSION(ic) < 9
        !           577:        || (TME_SPARC_MEMORY_FLAGS(ic) & TME_SPARC_MEMORY_FLAG_HAS_INVERT_ENDIAN)) {
        !           578: 
        !           579:       /* this recode DTLB entry doesn't need an assist for loads and
        !           580:         stores based on their explicit endianness: */
        !           581:       rw_flags_tlb
        !           582:        -= (TME_SPARC_RECODE_TLB_FLAG_LS_ENDIAN_BIG(ic)
        !           583:            + TME_SPARC_RECODE_TLB_FLAG_LS_ENDIAN_LITTLE(ic));
        !           584: 
        !           585:       /* if this is sparc32, or if this sparc64 DTLB entry's
        !           586:         invert-endian bit is not set: */
        !           587:       if (TME_SPARC_VERSION(ic) < 9
        !           588:          || (dtlb->tme_sparc_tlb_asi_mask & TME_SPARC64_ASI_FLAG_LITTLE) == 0) {
        !           589: 
        !           590:        /* this recode DTLB entry doesn't need an assist for loads and
        !           591:           stores to invert their endianness: */
        !           592:        rw_flags_tlb
        !           593:          -= TME_SPARC_RECODE_TLB_FLAG_LS_ENDIAN_INVERT(ic);
        !           594:       }
        !           595:     }
        !           596: 
        !           597:     /* otherwise, we don't know how this v9 MMU affects endianness: */
        !           598:     else {
        !           599:       assert (FALSE);
        !           600:     }
        !           601: 
        !           602:     /* update the recode DTLB entry context: */
        !           603:     recode_tlb->_TME_SPARC_RECODE_SIZE(tme_recode_tlb_c16_a,_context)
        !           604:       = dtlb->tme_sparc_tlb_context;
        !           605: 
        !           606:     /* if this sparc DTLB entry matches any context: */
        !           607:     if (dtlb->tme_sparc_tlb_context > ic->tme_sparc_memory_context_max) {
        !           608: 
        !           609:       /* this recode DTLB entry doesn't need an assist for loads and
        !           610:         stores whose context mismatches the recode DTLB entry: */
        !           611:       rw_flags_tlb
        !           612:        -= TME_RECODE_TLB_FLAG_CONTEXT_MISMATCH(ic);
        !           613:     }
        !           614:   }
        !           615: 
        !           616:   /* update the recode DTLB entry read/write flags: */
        !           617:   recode_tlb->_TME_SPARC_RECODE_SIZE(tme_recode_tlb_c16_a,_flags) = rw_flags_tlb;
        !           618: }
        !           619: 
        !           620: /* this initializes for ld and st instructions: */
        !           621: static void
        !           622: _tme_sparc_recode_ls_init(struct tme_sparc *ic)
        !           623: {
        !           624:   signed long rw_thunk_index;
        !           625:   struct tme_recode_rw rw;
        !           626:   tme_uint32_t sparc_opcode_ldu;
        !           627:   tme_uint32_t sparc_opcode_st;
        !           628:   tme_uint32_t rw_flags_insn_common;
        !           629:   tme_uint32_t rw_flags_insn;
        !           630:   unsigned int other_signed;
        !           631:   unsigned int no_fault;
        !           632: 
        !           633:   /* initialize the array of read/write thunks: */
        !           634:   for (rw_thunk_index = 0;
        !           635:        rw_thunk_index < TME_ARRAY_ELS(ic->tme_sparc_recode_rw_thunks);
        !           636:        rw_thunk_index++) {
        !           637:     ic->tme_sparc_recode_rw_thunks[rw_thunk_index] = NULL;
        !           638:   }
        !           639: 
        !           640:   /* make the common read/write structure for all sizes: */
        !           641:   rw.tme_recode_rw_bus_boundary = TME_BIT(TME_SPARC_RECODE_SIZE(ic) - TME_RECODE_SIZE_8);
        !           642:   rw.tme_recode_rw_address_type.tme_recode_address_type_context_ic_offset
        !           643:     = (((char *) &ic->tme_sparc_memory_context_default) - (char *) ic);
        !           644:   rw.tme_recode_rw_address_type.tme_recode_address_type_context_size
        !           645:     = TME_RECODE_SIZE_16;
        !           646:   rw.tme_recode_rw_address_type.tme_recode_address_type_signed = FALSE;
        !           647:   rw.tme_recode_rw_address_type.tme_recode_address_type_tlb_flags_ic_offset
        !           648:     = (((char *) &ic->tme_sparc_recode_rw_tlb_flags) - (char *) ic);
        !           649:   rw.tme_recode_rw_address_type.tme_recode_address_type_mask_tlb_index
        !           650:     = ((_TME_SPARC_DTLB_HASH_SIZE - 1)
        !           651:        * ic->tme_sparc_recode_ic->tme_recode_ic_tlb_page_size);
        !           652:   rw.tme_recode_rw_address_type.tme_recode_address_type_tlb0_ic_offset
        !           653:     = (((char *) &ic->_tme_sparc_tlb_tokens_u) - (char *) ic);
        !           654: 
        !           655:   /* initialize the read/write structure for the first ld and st
        !           656:      instructions: */
        !           657:   rw.tme_recode_rw_address_type.tme_recode_address_type_size = TME_SPARC_RECODE_SIZE(ic);
        !           658:   rw.tme_recode_rw_memory_endian = TME_ENDIAN_BIG;
        !           659:   rw.tme_recode_rw_memory_size = TME_RECODE_SIZE_8;
        !           660:   for (;;) {
        !           661: 
        !           662:     /* get the sparc ld/st opcodes for this size: */
        !           663:     sparc_opcode_ldu = TME_BIT(rw.tme_recode_rw_memory_size - TME_RECODE_SIZE_8) % sizeof(tme_uint32_t);
        !           664:     sparc_opcode_st = sparc_opcode_ldu + 4;
        !           665:     if (TME_SPARC_VERSION(ic) >= 9
        !           666:        && rw.tme_recode_rw_memory_size == TME_SPARC_RECODE_SIZE(ic)) {
        !           667:       sparc_opcode_ldu = 0x0b; /* v9: ldx */
        !           668:       sparc_opcode_st = 0x0e; /* v9: stx */
        !           669:     }
        !           670: 
        !           671:     /* make the common read/write structure for this size: */
        !           672:     rw.tme_recode_rw_address_type.tme_recode_address_type_align_min
        !           673:       = TME_BIT(rw.tme_recode_rw_memory_size - TME_RECODE_SIZE_8);
        !           674: 
        !           675:     /* start the common read/write structure flags: */
        !           676:     rw_flags_insn_common = 0;
        !           677: 
        !           678:     /* all loads and stores will need an assist when they encounter a
        !           679:        recode TLB entry from the wrong context: */
        !           680:     /* NB: TME_RECODE_TLB_FLAG_CONTEXT_MISMATCH() will get set
        !           681:        automatically as needed by the read/write thunk; there's no
        !           682:        need to set it here: */
        !           683: 
        !           684:     /* all loads and stores will need an assist when they encounter a
        !           685:        recode TLB entry that inverts their endianness: */
        !           686:     rw_flags_insn_common |= TME_SPARC_RECODE_TLB_FLAG_LS_ENDIAN_INVERT(ic);
        !           687: 
        !           688:     /* all loads and stores will need an assist when they encounter a
        !           689:        recode TLB entry that doesn't allow their endianness: */
        !           690:     rw_flags_insn_common
        !           691:       |= (rw.tme_recode_rw_memory_endian == TME_ENDIAN_BIG
        !           692:          ? TME_SPARC_RECODE_TLB_FLAG_LS_ENDIAN_BIG(ic)
        !           693:          : TME_SPARC_RECODE_TLB_FLAG_LS_ENDIAN_LITTLE(ic));
        !           694: 
        !           695:     /* make the common structure for loads: */
        !           696:     rw.tme_recode_rw_write = FALSE;
        !           697:     rw.tme_recode_rw_reg_size = TME_SPARC_RECODE_SIZE(ic);
        !           698:     rw.tme_recode_rw_guest_func_read = _tme_sparc_recode_ls_assist_ld;
        !           699: 
        !           700:     /* set the signedness of the (first) ld instructions at this size
        !           701:        that we will make a read thunk for: */
        !           702:     /* NB: we assume that 8- and 32-bit loads are signed more often
        !           703:        than not (because we assume that the C char and int types are
        !           704:        used more often than the unsigned char and unsigned int types),
        !           705:        so we make their thunks first, assuming that if we made them
        !           706:        second, that they might reuse an unsigned thunk and then
        !           707:        require extra sign-extension instructions in an instructions
        !           708:        thunk: */
        !           709:     rw.tme_recode_rw_memory_signed
        !           710:       = (rw.tme_recode_rw_memory_size < TME_SPARC_RECODE_SIZE(ic)
        !           711:         && (rw.tme_recode_rw_memory_size == TME_RECODE_SIZE_8
        !           712:             || rw.tme_recode_rw_memory_size == TME_RECODE_SIZE_32));
        !           713: 
        !           714:     /* permute over signedness and no-fault, making the read thunk(s)
        !           715:        for the ld instruction(s) with this size and endianness: */
        !           716:     for (other_signed = 0;
        !           717:         other_signed <= (rw.tme_recode_rw_memory_size < TME_SPARC_RECODE_SIZE(ic));
        !           718:         other_signed++, rw.tme_recode_rw_memory_signed = !rw.tme_recode_rw_memory_signed) {
        !           719:       for (no_fault = 0;
        !           720:           no_fault <= (TME_SPARC_VERSION(ic) >= 9);
        !           721:           no_fault++) {
        !           722: 
        !           723:        /* start the read structure flags: */
        !           724:        rw_flags_insn = rw_flags_insn_common;
        !           725: 
        !           726:        /* this load will need an assist when it encounters a recode
        !           727:           TLB entry that needs an assist on all loads (because the
        !           728:           sparc TLB entry doesn't allow fast reads, or has
        !           729:           side-effects) or doesn't allow loads at the current
        !           730:           privilege level (at load instruction time, the and of the
        !           731:           recode ic read/write flags will leave only one of these
        !           732:           flags set): */
        !           733:        rw_flags_insn
        !           734:          |= (TME_SPARC_RECODE_TLB_FLAG_LD_USER(ic)
        !           735:              | TME_SPARC_RECODE_TLB_FLAG_LD_PRIV(ic));
        !           736: 
        !           737:        /* if this is a no-fault load: */
        !           738:        if (no_fault) {
        !           739: 
        !           740:          /* this no-fault load will need an assist when the ASI
        !           741:             register is not loaded with the correct default no-fault
        !           742:             ASI (at load instruction time, the and of the recode ic
        !           743:             read/write flags will clear this bit if the ASI register
        !           744:             is correct, and recode TLB entries always need this
        !           745:             assist): */
        !           746:          rw_flags_insn |= TME_SPARC_RECODE_TLB_FLAG_LD_NF(ic);
        !           747:        }
        !           748: 
        !           749:        /* otherwise, this is a faulting load: */
        !           750:        else {
        !           751: 
        !           752:          /* this faulting load will need an assist when it encounters
        !           753:             a recode TLB entry that doesn't allow faulting loads
        !           754:             (i.e., it only allows non-faulting loads): */
        !           755:          rw_flags_insn |= TME_SPARC_RECODE_TLB_FLAG_LD_F(ic);
        !           756:        }
        !           757: 
        !           758:        /* make the read thunk for this ld instruction: */
        !           759:        rw.tme_recode_rw_address_type.tme_recode_address_type_tlb_flags = rw_flags_insn;
        !           760:        ic->tme_sparc_recode_rw_thunks
        !           761:          [TME_SPARC_RECODE_RW_THUNK_INDEX(ic,
        !           762:                                           rw.tme_recode_rw_address_type.tme_recode_address_type_size,
        !           763:                                           rw.tme_recode_rw_memory_endian,
        !           764:                                           no_fault,
        !           765:                                           (sparc_opcode_ldu
        !           766:                                            + (8 * rw.tme_recode_rw_memory_signed)))]
        !           767:          /* NB: for an 8-bit little-endian ld instructions, we reuse
        !           768:             the 8-bit big-endian read thunk: */
        !           769:          = ((rw.tme_recode_rw_memory_size == TME_RECODE_SIZE_8
        !           770:              && rw.tme_recode_rw_memory_endian == TME_ENDIAN_LITTLE)
        !           771:             ? (ic->tme_sparc_recode_rw_thunks
        !           772:                [TME_SPARC_RECODE_RW_THUNK_INDEX(ic,
        !           773:                                                 rw.tme_recode_rw_address_type.tme_recode_address_type_size,
        !           774:                                                 TME_ENDIAN_BIG,
        !           775:                                                 no_fault,
        !           776:                                                 (sparc_opcode_ldu
        !           777:                                                  + (8 * rw.tme_recode_rw_memory_signed)))])
        !           778:             : tme_recode_rw_thunk(ic->tme_sparc_recode_ic, &rw));
        !           779:       }
        !           780:     }
        !           781: 
        !           782:     /* make the common structure for reads: */
        !           783:     rw.tme_recode_rw_write = TRUE;
        !           784:     rw.tme_recode_rw_reg_size = rw.tme_recode_rw_memory_size;
        !           785:     rw.tme_recode_rw_guest_func_write = _tme_sparc_recode_ls_assist_st;
        !           786: 
        !           787:     /* start the write structure flags: */
        !           788:     rw_flags_insn = rw_flags_insn_common;
        !           789: 
        !           790:     /* this store will need an assist when it encounters a recode TLB
        !           791:        entry that needs an assist on all store (because the sparc TLB
        !           792:        entry doesn't allow fast stores, or has side-effects, or only
        !           793:        allows no-fault loads) or doesn't allow stores at the current
        !           794:        privilege level (at store instruction time, the and of the
        !           795:        recode ic read/write flags will leave only one of these flags
        !           796:        set): */
        !           797:     rw_flags_insn
        !           798:       |= (TME_SPARC_RECODE_TLB_FLAG_ST_USER(ic)
        !           799:          | TME_SPARC_RECODE_TLB_FLAG_ST_PRIV(ic));
        !           800: 
        !           801:     /* make the write thunk for this st instruction: */
        !           802:     rw.tme_recode_rw_address_type.tme_recode_address_type_tlb_flags = rw_flags_insn;
        !           803:     ic->tme_sparc_recode_rw_thunks
        !           804:       [TME_SPARC_RECODE_RW_THUNK_INDEX(ic,
        !           805:                                       rw.tme_recode_rw_address_type.tme_recode_address_type_size,
        !           806:                                       rw.tme_recode_rw_memory_endian,
        !           807:                                       FALSE,
        !           808:                                       sparc_opcode_st)]
        !           809:       /* NB: for an 8-bit little-endian st instruction, we reuse the
        !           810:         8-bit big-endian write thunk: */
        !           811:       = ((rw.tme_recode_rw_memory_size == TME_RECODE_SIZE_8
        !           812:          && rw.tme_recode_rw_memory_endian == TME_ENDIAN_LITTLE)
        !           813:         ? (ic->tme_sparc_recode_rw_thunks
        !           814:            [TME_SPARC_RECODE_RW_THUNK_INDEX(ic,
        !           815:                                             rw.tme_recode_rw_address_type.tme_recode_address_type_size,
        !           816:                                             TME_ENDIAN_BIG,
        !           817:                                             FALSE,
        !           818:                                             sparc_opcode_st)])
        !           819:         : tme_recode_rw_thunk(ic->tme_sparc_recode_ic, &rw));
        !           820:   
        !           821:     /* advance: */
        !           822:     if (++rw.tme_recode_rw_memory_size > TME_SPARC_RECODE_SIZE(ic)) {
        !           823:       rw.tme_recode_rw_memory_size = TME_RECODE_SIZE_8;
        !           824:       if (rw.tme_recode_rw_memory_endian == TME_ENDIAN_BIG
        !           825:          && TME_SPARC_VERSION(ic) >= 9) {
        !           826:        rw.tme_recode_rw_memory_endian = TME_ENDIAN_LITTLE;
        !           827:       }
        !           828:       else {
        !           829:        rw.tme_recode_rw_memory_endian = TME_ENDIAN_BIG;
        !           830:        if (--rw.tme_recode_rw_address_type.tme_recode_address_type_size
        !           831:            < (TME_SPARC_RECODE_SIZE(ic) - (TME_SPARC_VERSION(ic) >= 9))) {
        !           832:          break;
        !           833:        }
        !           834:       }
        !           835:     }
        !           836:   }
        !           837: }

unix.superglobalmegacorp.com

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