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

1.1     ! root        1: /* $Id: sparc-timing.c,v 1.3 2010/02/14 15:57:09 fredette Exp $ */
        !             2: 
        !             3: /* ic/sparc/sparc-timing.c - SPARC instruction timing 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: /* includes: */
        !            37: #include "sparc-impl.h"
        !            38: 
        !            39: _TME_RCSID("$Id: sparc-timing.c,v 1.3 2010/02/14 15:57:09 fredette Exp $");
        !            40: 
        !            41: /* macros: */
        !            42: 
        !            43: /* at or below this maximum number of microseconds, we will spin
        !            44:    instead of yield: */
        !            45: #define TME_SPARC_TIMING_SPIN_USEC_MAX         (4096)
        !            46: 
        !            47: /* normally, when we yield we do a plain yield so we are immediately
        !            48:    runnable again.  this makes timing loops more accurate, at the
        !            49:    expense of consuming the host CPU.  if this is nonzero, when we
        !            50:    yield we will instead do a sleep or wait on an external event: */
        !            51: #define TME_SPARC_TIMING_YIELD_BLOCK           (FALSE)
        !            52: 
        !            53: /* this does a timing loop update: */
        !            54: static void
        !            55: _tme_sparc_timing_loop_update(struct tme_sparc *ic,
        !            56:                              tme_sparc_ireg_umax_t update_count_m1)
        !            57: {
        !            58:   tme_uint32_t insn_update;
        !            59:   unsigned long opcode;
        !            60:   unsigned int reg_rd;
        !            61:   signed int immediate;
        !            62:   tme_sparc_ireg_umax_t addend_total_m1;
        !            63: 
        !            64:   /* get the update instruction: */
        !            65:   insn_update = ic->_tme_sparc_insn;
        !            66: 
        !            67:   /* get the opcode: */
        !            68:   opcode = TME_FIELD_MASK_EXTRACTU(insn_update, (0x3f << 19));
        !            69: 
        !            70:   /* get the rd register: */
        !            71:   reg_rd = TME_FIELD_MASK_EXTRACTU(insn_update, TME_SPARC_FORMAT3_MASK_RD);
        !            72:   TME_SPARC_REG_INDEX(ic, reg_rd);
        !            73: 
        !            74:   /* get the immediate: */
        !            75:   immediate = insn_update & 2;
        !            76:   immediate = 1 - immediate;
        !            77: 
        !            78:   /* get the total addend: */
        !            79:   addend_total_m1 = update_count_m1;
        !            80:   if (ic->tme_sparc_timing_loop_addend < 0) {
        !            81:     addend_total_m1 = -addend_total_m1;
        !            82:   }
        !            83: 
        !            84:   /* if this is a v9 CPU: */
        !            85:   if (TME_SPARC_VERSION(ic) >= 9) {
        !            86: #ifdef TME_HAVE_INT64_T
        !            87: 
        !            88:     /* save the immediate: */
        !            89:     ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_TMP(0)) = immediate;
        !            90: 
        !            91:     /* do all but one of the updates of the rd register directly: */
        !            92:     ic->tme_sparc_ireg_uint64(reg_rd) += addend_total_m1;
        !            93: 
        !            94:     /* do the final update, including setting any condition codes: */
        !            95:     (*(ic->_tme_sparc64_execute_opmap[opcode]))
        !            96:       (ic, 
        !            97:        &ic->tme_sparc_ireg_uint64(reg_rd),
        !            98:        &ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_TMP(0)),
        !            99:        &ic->tme_sparc_ireg_uint64(reg_rd));
        !           100: 
        !           101: #endif /* TME_HAVE_INT64_T */
        !           102:   }
        !           103: 
        !           104:   /* otherwise, this is a v7 or v8 CPU: */
        !           105:   else {
        !           106: 
        !           107:     /* save the immediate: */
        !           108:     ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_TMP(0)) = immediate;
        !           109: 
        !           110:     /* do all but one of the updates of the rd register directly: */
        !           111:     ic->tme_sparc_ireg_uint32(reg_rd) += addend_total_m1;
        !           112: 
        !           113:     /* do the final update, including setting any condition codes: */
        !           114:     (*(ic->_tme_sparc32_execute_opmap[opcode]))
        !           115:       (ic, 
        !           116:        &ic->tme_sparc_ireg_uint32(reg_rd),
        !           117:        &ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_TMP(0)),
        !           118:        &ic->tme_sparc_ireg_uint32(reg_rd));
        !           119:   }
        !           120: }
        !           121: 
        !           122: /* this returns nonzero if the branch to . instruction and the update
        !           123:    instruction in its delay slot are a supported timing loop: */
        !           124: int
        !           125: tme_sparc_timing_loop_ok(tme_uint32_t insn_branch_dot,
        !           126:                         tme_uint32_t insn_update)
        !           127: {
        !           128:   unsigned int op2;
        !           129:   tme_uint32_t conds_mask;
        !           130:   unsigned int cond;
        !           131: 
        !           132:   /* if the update instruction is not an add, addcc, sub, or subcc
        !           133:      with the i bit set: */
        !           134:   if ((insn_update
        !           135:        & ((tme_uint32_t)
        !           136:          ((0x3 << 30)          /* format */
        !           137:           + (0x2b << 19)       /* op3 (mask addcc to add, sub to add) */
        !           138:           + (1 << 13))))       /* i */
        !           139:       != ((tme_uint32_t)
        !           140:          ((0x2 << 30)          /* format */
        !           141:           + (0x00 << 19)       /* op3 (add) */
        !           142:           + (1 << 13)))) {     /* i */
        !           143: 
        !           144:     /* we only support timing loops with plain add or subtract
        !           145:        update instructions: */
        !           146:     return (FALSE);
        !           147:   }
        !           148: 
        !           149:   /* if the simm13 is not 1 or -1: */
        !           150:   if (((insn_update
        !           151:        + (insn_update & 2))
        !           152:        & 0x1fff)
        !           153:       != 1) {
        !           154: 
        !           155:     /* we only support timing loops with plain add or subtract update
        !           156:        instructions with immediates of 1 or -1: */
        !           157:     return (FALSE);
        !           158:   }
        !           159: 
        !           160:   /* if rd is %g0: */
        !           161: #if TME_SPARC_IREG_G0 != 0
        !           162: #error "TME_SPARC_IREG_G0 changed"
        !           163: #endif
        !           164:   if ((insn_update & TME_SPARC_FORMAT3_MASK_RD) == 0) {
        !           165: 
        !           166:     /* we only support timing loops with plain add or subtract update
        !           167:        instructions with destination registers other than %g0: */
        !           168:     return (FALSE);
        !           169:   }
        !           170: 
        !           171:   /* if rs1 and rd are not the same: */
        !           172: #if TME_SPARC_FORMAT3_MASK_RD < TME_SPARC_FORMAT3_MASK_RS1
        !           173: #error "TME_SPARC_FORMAT3_MASK_ values changed"
        !           174: #endif
        !           175:   if ((((insn_update
        !           176:         / (TME_SPARC_FORMAT3_MASK_RD
        !           177:            / TME_SPARC_FORMAT3_MASK_RS1))
        !           178:        ^ insn_update)
        !           179:        & TME_SPARC_FORMAT3_MASK_RS1) != 0) {
        !           180: 
        !           181:     /* we only support timing loops with plain add or subtract update
        !           182:        instructions where the source register and destination register
        !           183:        are the same: */
        !           184:     return (FALSE);
        !           185:   }
        !           186: 
        !           187:   /* all branch instructions are format two instructions: */
        !           188:   assert ((insn_branch_dot & (tme_uint32_t) (0x3 << 30)) == 0);
        !           189: 
        !           190:   /* if this isn't a Bicc or a v9 BPcc instruction: */
        !           191:   op2 = TME_FIELD_MASK_EXTRACTU(insn_branch_dot, (0x7 << 22));
        !           192:   if (__tme_predict_false(op2 != 2 && op2 != 1)) {
        !           193: 
        !           194:     /* we support all timing loops with a branch to . instructions
        !           195:        that don't depend on the integer condition codes: */
        !           196:     return (TRUE);
        !           197:   }
        !           198: 
        !           199:   /* otherwise, this is a Bicc or a v9 BPcc instruction: */
        !           200:   else {
        !           201: 
        !           202:     /* if this is not an addcc or subcc instruction: */
        !           203:     if (__tme_predict_false((insn_update & (0x10 << 19)) == 0)) {
        !           204: 
        !           205:       /* we support timing loops with Bicc and BPcc instructions even
        !           206:         when the update instruction doesn't change the integer
        !           207:         condition codes: */
        !           208:       return (TRUE);
        !           209:     }
        !           210: 
        !           211:     /* if this is a subcc instruction: */
        !           212:     if (insn_update & (0x04 << 19)) {
        !           213: 
        !           214:       /* we support timing loops that use subcc with all conditions
        !           215:         except for vc and vs (the overflow conditions) and never: */
        !           216:       conds_mask
        !           217:        = ((1 << (TME_SPARC_COND_NOT + TME_SPARC_COND_N))
        !           218:           + (1 << (TME_SPARC_COND_NOT + TME_SPARC_COND_E))
        !           219:           + (1 << (TME_SPARC_COND_NOT + TME_SPARC_COND_LE))
        !           220:           + (1 << (TME_SPARC_COND_NOT + TME_SPARC_COND_L))
        !           221:           + (1 << (TME_SPARC_COND_NOT + TME_SPARC_COND_LEU))
        !           222:           + (1 << (TME_SPARC_COND_NOT + TME_SPARC_COND_CS))
        !           223:           + (1 << (TME_SPARC_COND_NOT + TME_SPARC_COND_NEG))
        !           224:           + (1 << TME_SPARC_COND_E)
        !           225:           + (1 << TME_SPARC_COND_LE)
        !           226:           + (1 << TME_SPARC_COND_L)
        !           227:           + (1 << TME_SPARC_COND_LEU)
        !           228:           + (1 << TME_SPARC_COND_CS)
        !           229:           + (1 << TME_SPARC_COND_NEG)
        !           230:           );
        !           231:     }
        !           232: 
        !           233:     /* otherwise, this is an addcc instruction: */
        !           234:     else {
        !           235: 
        !           236:       /* we support timing loops that use addcc with only these
        !           237:         conditions: */
        !           238:       conds_mask
        !           239:        = ((1 << (TME_SPARC_COND_NOT + TME_SPARC_COND_N))
        !           240:           + (1 << (TME_SPARC_COND_NOT + TME_SPARC_COND_E))
        !           241:           + (1 << (TME_SPARC_COND_NOT + TME_SPARC_COND_CS))
        !           242:           + (1 << (TME_SPARC_COND_NOT + TME_SPARC_COND_NEG))
        !           243:           + (1 << TME_SPARC_COND_E)
        !           244:           + (1 << TME_SPARC_COND_CS)
        !           245:           + (1 << TME_SPARC_COND_NEG)
        !           246:           );
        !           247:     }
        !           248: 
        !           249:     /* if we don't support the condition: */
        !           250:     cond = TME_FIELD_MASK_EXTRACTU(insn_branch_dot, (0xf << 25));
        !           251:     if ((conds_mask & TME_BIT(cond)) == 0) {
        !           252: 
        !           253:       /* we don't support this timing loop: */
        !           254:       return (FALSE);
        !           255:     }
        !           256: 
        !           257:     /* otherwise, we support this timing loop: */
        !           258:     return (TRUE);
        !           259:   }
        !           260: }
        !           261: 
        !           262: /* this starts a timing loop: */
        !           263: static void
        !           264: _tme_sparc_timing_loop_start(struct tme_sparc *ic,
        !           265:                             tme_uint32_t insn_update)
        !           266: {
        !           267:   unsigned int reg_rd;
        !           268:   tme_sparc_ireg_umax_t value_rd;
        !           269:   signed int addend;
        !           270:   tme_uint32_t insn_branch_dot;
        !           271:   const struct timeval *sleep;
        !           272:   unsigned int op2;
        !           273:   unsigned int cond;
        !           274:   tme_sparc_ireg_umax_t value_sign;
        !           275:   tme_sparc_ireg_umax_t value_zero;
        !           276:   tme_sparc_ireg_umax_t value_true_greatest;
        !           277:   tme_sparc_ireg_umax_t value_test;
        !           278:   tme_sparc_ireg_umax_t branch_taken_count_max_m1;
        !           279:   unsigned int loop_cycles_each;
        !           280:   tme_sparc_ireg_umax_t cycles_scaled_max;
        !           281:   union tme_value64 cycles_finish;
        !           282:   tme_sparc_ireg_umax_t usec;
        !           283:   tme_uint32_t usec32;
        !           284:   static struct timeval sleep_buffer;
        !           285: 
        !           286:   /* at this point, the timing loop branch to . has been taken, and
        !           287:      the PCs have been updated, so both PC and PC_next_next point to
        !           288:      the timing loop update instruction (in insn_update), and PC_next
        !           289:      points to the timing loop branch to . instruction again.
        !           290: 
        !           291:      a taken conditional branch never annuls, and sparc-execute.c and
        !           292:      sparc-rc-insns.c handle a "ba,a ." instruction specially, so we
        !           293:      know that the update instruction must execute at least as many
        !           294:      times as the timing loop branch to . is taken.
        !           295: 
        !           296:      the timing loop branch to . has just been taken (this is why
        !           297:      PC_next_next is the same as PC).  this first take was when the
        !           298:      branch to . was detected in sparc-execute.c, or when
        !           299:      tme_sparc_timing_loop_assist() determined that the recode
        !           300:      instructions thunk that called it did so after a taken branch.
        !           301: 
        !           302:      this very first take is implicit in the taken branch count that
        !           303:      we compute and store in
        !           304:      ic->tme_sparc_timing_loop_branch_taken_count_max_m1 and/or pass
        !           305:      to _tme_sparc_timing_loop_update() - i.e., we always compute the
        !           306:      taken branch count minus one.
        !           307: 
        !           308:      this is good because it is possible for the timing loop update
        !           309:      instruction to be executed 2^cc_width times.  if initially %o3 is
        !           310:      zero and %icc.Z is clear, this bne will be taken 2^32 times:
        !           311: 
        !           312:      bne .
        !           313:      deccc %o3
        !           314: 
        !           315:      NB that in this specific case, where the timing loop branch to
        !           316:      . does not annul, the timing loop update instruction will
        !           317:      actually be run a total of (2^32)+1 times: 2^32 times
        !           318:      corresponding to the 2^32 times that the branch is taken, plus
        !           319:      one final time when the branch is *not* taken, but the update
        !           320:      instruction is not annulled.
        !           321: 
        !           322:      this function only counts and performs the updates corresponding
        !           323:      to the times that the branch is *taken*.
        !           324:      _tme_sparc_timing_loop_update() does the count minus one updates
        !           325:      directly in the destination register, followed by a true
        !           326:      instruction execution for the last (to update any condition
        !           327:      codes).
        !           328: 
        !           329:      whether or not the branch to . instruction annuls, and any needed
        !           330:      "one final time" update instruction will be handled either by
        !           331:      sparc-execute.c, or by a combination of the recode instructions
        !           332:      thunk and tme_sparc_timing_loop_assist(): */
        !           333: 
        !           334:   /* NB: our caller has already saved the current host cycles counter
        !           335:      in ic->tme_sparc_timing_loop_start: */
        !           336: 
        !           337:   /* get the rd register: */
        !           338:   reg_rd = TME_FIELD_MASK_EXTRACTU(insn_update, TME_SPARC_FORMAT3_MASK_RD);
        !           339:   TME_SPARC_REG_INDEX(ic, reg_rd);
        !           340: 
        !           341:   /* if this is a v9 CPU: */
        !           342:   if (TME_SPARC_VERSION(ic) >= 9) {
        !           343: #ifdef TME_HAVE_INT64_T
        !           344: 
        !           345:     /* get the rd register value: */
        !           346:     value_rd = ic->tme_sparc_ireg_uint64(reg_rd);
        !           347: 
        !           348: #else  /* !TME_HAVE_INT64_T */
        !           349: 
        !           350:     /* silence uninitialized variable warnings: */
        !           351:     value_rd = 0;
        !           352: 
        !           353: #endif /* !TME_HAVE_INT64_T */
        !           354:   }
        !           355: 
        !           356:   /* otherwise, this is not a v9 CPU: */
        !           357:   else {
        !           358: 
        !           359:     /* get the rd register value: */
        !           360:     value_rd = (tme_int32_t) ic->tme_sparc_ireg_uint32(reg_rd);
        !           361:   }
        !           362: 
        !           363:   /* assume that this is an add or addcc instruction: */
        !           364:   addend = insn_update & 2;
        !           365:   addend = 1 - addend;
        !           366: 
        !           367:   /* if this is a sub or subcc instruction: */
        !           368:   if (insn_update & (0x04 << 19)) {
        !           369: 
        !           370:     /* complement the addend: */
        !           371:     addend = -addend;
        !           372:   }
        !           373: 
        !           374:   /* get the branch to . instruction: */
        !           375:   insn_branch_dot = ic->_tme_sparc_insn;
        !           376: 
        !           377:   /* save the update instruction: */
        !           378:   ic->_tme_sparc_insn = insn_update;
        !           379: 
        !           380:   /* save the addend: */
        !           381:   ic->tme_sparc_timing_loop_addend = addend;
        !           382: 
        !           383:   /* assume that there isn't a maximum number of times that the branch
        !           384:      to . can be taken (i.e., that the branch to . doesn't depend on
        !           385:      the value of rd), as if the branch condition were always: */
        !           386:   cond = TME_SPARC_COND_NOT + TME_SPARC_COND_N;
        !           387: 
        !           388:   /* assume that if the branch does depend on the value of rd, that
        !           389:      the sign bit in values of rd is the last bit: */
        !           390:   value_sign = 1;
        !           391:   value_sign <<= ((sizeof(value_sign) * 8) - 1);
        !           392: 
        !           393:   /* silence uninitialized variable warnings: */
        !           394:   value_zero = 0;
        !           395:   value_true_greatest = 0;
        !           396: 
        !           397:   /* get the op2 field of the branch to . instruction: */
        !           398:   op2 = TME_FIELD_MASK_EXTRACTU(insn_branch_dot, (0x7 << 22));
        !           399: 
        !           400:   /* if this is a v9 BPr: */
        !           401:   if (op2 == 3) {
        !           402: 
        !           403:     /* if this BPr tests rd: */
        !           404:     if (((insn_branch_dot
        !           405:          ^ insn_update)
        !           406:         & TME_SPARC_FORMAT3_MASK_RS1) == 0) {
        !           407: 
        !           408:       /* get the condition field, and shift the "not" bit from bit two
        !           409:         to bit three, to match the other branches: */
        !           410:       cond = TME_FIELD_MASK_EXTRACTU(insn_branch_dot, (0x7 << 25));
        !           411:       cond = (cond + 4) & (TME_SPARC_COND_NOT | 3);
        !           412:       
        !           413:       /* dispatch on the condition: */
        !           414:       if ((cond % TME_SPARC_COND_NOT) == TME_SPARC_COND_E) {
        !           415:        value_zero = -addend;
        !           416:        value_true_greatest = 0;
        !           417:       }
        !           418:       else {
        !           419:        assert ((cond % TME_SPARC_COND_NOT) == TME_SPARC_COND_LE
        !           420:                || (cond % TME_SPARC_COND_NOT) == TME_SPARC_COND_L);
        !           421:        value_zero = value_sign - addend;
        !           422: #if (TME_SPARC_COND_L & 1) == 0 || (TME_SPARC_COND_LE & 1) != 0
        !           423: #error "TME_SPARC_COND_ values changed"
        !           424: #endif
        !           425:        value_true_greatest = value_sign - (cond & 1);
        !           426:       }
        !           427:     }
        !           428:   }
        !           429: 
        !           430:   /* otherwise, if this is a Bicc or a v9 BPcc: */
        !           431:   else if (op2 == 2 || op2 == 1) {
        !           432: 
        !           433:     /* if this is an addcc or subcc instruction: */
        !           434:     if (insn_update & (0x10 << 19)) {
        !           435: 
        !           436:       /* get the condition: */
        !           437:       cond = TME_FIELD_MASK_EXTRACTU(insn_branch_dot, (0xf << 25));
        !           438: 
        !           439:       /* if this is a Bicc, or a BPcc with the cc1 bit clear, the
        !           440:         sign bit in values of rd is bit 31: */
        !           441:       if (sizeof(value_sign) > sizeof(tme_uint32_t)
        !           442:          && ((insn_branch_dot >> 21) & op2 & 1) == 0) {
        !           443:        value_sign = (((tme_uint32_t) 1) << 31);
        !           444:       }
        !           445: 
        !           446:       /* if this is a subcc instruction: */
        !           447:       if (insn_update & (0x04 << 19)) {
        !           448: 
        !           449:        /* dispatch on the condition: */
        !           450:        switch (cond % TME_SPARC_COND_NOT) {
        !           451:        default:
        !           452:          /* we should have caught this unsupported condition in
        !           453:             tme_sparc_timing_loop_ok(): */
        !           454:          assert (FALSE);
        !           455:          /* FALLTHROUGH */
        !           456:        case TME_SPARC_COND_N:
        !           457:          /* nothing to do */
        !           458:          break;
        !           459:        case TME_SPARC_COND_E:
        !           460:          value_zero = -addend;
        !           461:          value_true_greatest = 0;
        !           462:          break;
        !           463:        case TME_SPARC_COND_LE:
        !           464:          value_zero = value_sign;
        !           465:          value_true_greatest = value_sign - addend;
        !           466:          break;
        !           467:        case TME_SPARC_COND_L:
        !           468:          value_zero = value_sign;
        !           469:          value_true_greatest = (value_sign - 1) - addend;
        !           470:          break;
        !           471:        case TME_SPARC_COND_LEU:
        !           472:          value_zero = 0;
        !           473:          value_true_greatest = (value_sign * 2) - addend;
        !           474:          break;
        !           475:        case TME_SPARC_COND_CS:
        !           476:          value_zero = 0;
        !           477:          value_true_greatest = (value_sign * 2) - (addend + 1);
        !           478:          break;
        !           479:        case TME_SPARC_COND_NEG:
        !           480:          value_zero = value_sign - addend;
        !           481:          value_true_greatest = value_sign - 1;
        !           482:          break;
        !           483:        }
        !           484:       }
        !           485: 
        !           486:       /* otherwise, this is an addcc instruction: */
        !           487:       else {
        !           488: 
        !           489:        /* dispatch on the condition: */
        !           490:        switch (cond % TME_SPARC_COND_NOT) {
        !           491:        default:
        !           492:          /* we should have caught this unsupported condition in
        !           493:             tme_sparc_timing_loop_ok(): */
        !           494:          assert (FALSE);
        !           495:          /* FALLTHROUGH */
        !           496:        case TME_SPARC_COND_N:
        !           497:          /* nothing to do */
        !           498:          break;
        !           499:        case TME_SPARC_COND_E:
        !           500:          value_zero = -addend;
        !           501:          value_true_greatest = 0;
        !           502:          break;
        !           503:        case TME_SPARC_COND_CS:
        !           504:          value_zero = -addend;
        !           505:          value_true_greatest = (value_sign * 2) - (addend - 1);
        !           506:          break;
        !           507:        case TME_SPARC_COND_NEG:
        !           508:          value_zero = value_sign - addend;
        !           509:          value_true_greatest = value_sign - 1;
        !           510:          break;
        !           511:        }
        !           512:       }
        !           513:     }
        !           514:   }
        !           515: 
        !           516:   /* the condition can't be never: */
        !           517:   assert (cond != TME_SPARC_COND_N);
        !           518: 
        !           519:   /* assume that, if we block, we will block forever: */
        !           520:   sleep = (const struct timeval *) NULL;
        !           521: 
        !           522:   /* if the condition is always, there is no maximum number of times
        !           523:      that the branch to . can be taken: */
        !           524: #if TME_SPARC_COND_N != 0
        !           525: #error "TME_SPARC_COND_ values changed"
        !           526: #endif
        !           527:   ic->tme_sparc_timing_loop_branch_taken_max = (cond % TME_SPARC_COND_NOT);
        !           528:   if (cond == (TME_SPARC_COND_NOT + TME_SPARC_COND_N)) {
        !           529: 
        !           530:     /* we may never finish: */
        !           531:     ic->tme_sparc_timing_loop_finish.tme_value64_uint32_lo = (0 - (tme_uint32_t) 1);
        !           532:     ic->tme_sparc_timing_loop_finish.tme_value64_uint32_hi = (0 - (tme_uint32_t) 1);
        !           533:   }
        !           534: 
        !           535:   /* otherwise, the condition isn't always, so there is a maximum
        !           536:      number of times that the branch to . can be taken: */
        !           537:   else {
        !           538: 
        !           539:     /* it's not possible for all (adjusted-to-zero) values to be true.
        !           540:        at least all-bits-one must be false: */
        !           541:     assert (value_true_greatest <= ((value_sign - 1) * 2));
        !           542: 
        !           543:     /* test the initial value of rd: */
        !           544:     value_test = (value_rd - value_zero) & ((value_sign * 2) - 1);
        !           545: 
        !           546:     /* if the initial value of rd will make the condition (ignoring
        !           547:        TME_SPARC_COND_NOT) true after the first rd update
        !           548:        instruction: */
        !           549:     if (value_test <= value_true_greatest) {
        !           550: 
        !           551:       /* if this condition has TME_SPARC_COND_NOT: */
        !           552:       if (cond & TME_SPARC_COND_NOT) {
        !           553: 
        !           554:        /* the branch to . will only be taken the first time: */
        !           555:        branch_taken_count_max_m1 = 1 - 1;
        !           556:       }
        !           557: 
        !           558:       /* otherwise, if the addend is -1: */
        !           559:       else if (addend < 0) {
        !           560: 
        !           561:        /* the branch to . will be taken the first time, followed by
        !           562:           at most (value_test + 1) more times when the value of rd
        !           563:           makes the condition true: */
        !           564:        branch_taken_count_max_m1 = (1 + (value_test + 1)) - 1;
        !           565:       }
        !           566: 
        !           567:       /* otherwise, the addend is 1: */
        !           568:       else {
        !           569: 
        !           570:        /* the branch to . will be taken the first time, followed by
        !           571:           at most ((value_true_greatest - value_test) + 1) more times
        !           572:           when the value of rd makes the condition true: */
        !           573:        branch_taken_count_max_m1 = (1 + ((value_true_greatest - value_test) + 1)) - 1;
        !           574:       }
        !           575:     }
        !           576: 
        !           577:     /* otherwise, the initial value of rd will make the condition
        !           578:        (ignoring TME_SPARC_COND_NOT) false after the first update
        !           579:        instruction: */
        !           580:     else {
        !           581: 
        !           582:       /* if this condition doesn't have TME_SPARC_COND_NOT: */
        !           583:       if ((cond & TME_SPARC_COND_NOT) == 0) {
        !           584: 
        !           585:        /* the branch to . will only be taken the first time: */
        !           586:        branch_taken_count_max_m1 = 1 - 1;
        !           587:       }
        !           588: 
        !           589:       /* otherwise, if the addend is -1: */
        !           590:       else if (addend < 0) {
        !           591: 
        !           592:        /* the branch to . will be taken the first time, followed by
        !           593:           at most (value_test - value_true_greatest) more times when
        !           594:           the value of rd makes the condition false: */
        !           595:        branch_taken_count_max_m1 = (1 + (value_test - value_true_greatest)) - 1;
        !           596:       }
        !           597: 
        !           598:       /* otherwise, the addend is 1: */
        !           599:       else {
        !           600: 
        !           601:        /* the branch to . will be taken the first time, followed by
        !           602:           at most (~value_test + 1) more times when the value of rd
        !           603:           makes the condition false: */
        !           604:        branch_taken_count_max_m1 = ((1 + (~value_test + 1)) - 1) & ((value_sign * 2) - 1);
        !           605:       }
        !           606:     }
        !           607: 
        !           608:     /* set the maximum number of times the branch to . can be taken: */
        !           609:     ic->tme_sparc_timing_loop_branch_taken_count_max_m1 = branch_taken_count_max_m1;
        !           610: 
        !           611:     /* if each loop iteration takes more than one cycle: */
        !           612:     loop_cycles_each = ic->tme_sparc_timing_loop_cycles_each;
        !           613:     if (__tme_predict_false(loop_cycles_each != 1)) {
        !           614: 
        !           615:       /* get the maximum number of cycles to loop: */
        !           616:       /* NB: we try to deal with overflow: */
        !           617:       if (__tme_predict_false(loop_cycles_each != 2)) {
        !           618:        cycles_scaled_max
        !           619:          = (branch_taken_count_max_m1
        !           620:             * loop_cycles_each);
        !           621:       }
        !           622:       else {
        !           623:        cycles_scaled_max = branch_taken_count_max_m1 * 2;
        !           624:       }
        !           625:       cycles_scaled_max += loop_cycles_each;
        !           626:       if (__tme_predict_false(cycles_scaled_max < ic->tme_sparc_timing_loop_branch_taken_count_max_m1)) {
        !           627:        cycles_scaled_max = 0 - (tme_sparc_ireg_umax_t) 1;
        !           628:       }
        !           629:     }
        !           630: 
        !           631:     /* otherwise, each loop iteration takes one cycle: */
        !           632:     else {
        !           633: 
        !           634:       /* get the maximum number of cycles to loop: */
        !           635:       /* NB: we try to deal with overflow: */
        !           636:       cycles_scaled_max = branch_taken_count_max_m1 + 1;
        !           637:       cycles_scaled_max -= (cycles_scaled_max == 0);
        !           638:     }
        !           639: 
        !           640:     /* we can't be looping for zero cycles: */
        !           641:     assert (cycles_scaled_max > 0);
        !           642: 
        !           643:     /* get the latest host cycle counter when the timing loop must
        !           644:        finish, if it doesn't finish sooner: */
        !           645: #ifdef TME_HAVE_INT64_T
        !           646:     cycles_finish.tme_value64_uint = cycles_scaled_max;
        !           647: #else  /* !TME_HAVE_INT64_T */
        !           648:     cycles_finish.tme_value64_uint32_lo = cycles_scaled_max;
        !           649:     cycles_finish.tme_value64_uint32_hi = 0;
        !           650: #endif /* !TME_HAVE_INT64_T */
        !           651:     cycles_finish
        !           652:       = tme_misc_cycles_scaled(&ic->tme_sparc_cycles_unscaling,
        !           653:                               &cycles_finish);
        !           654:     (void) tme_value64_add(&cycles_finish, &ic->tme_sparc_timing_loop_start);
        !           655:     ic->tme_sparc_timing_loop_finish = cycles_finish;
        !           656: 
        !           657:     /* if the number of cycles to spin is small enough that we should
        !           658:        truly spin, instead of yield: */
        !           659:     if (cycles_scaled_max
        !           660:        <= (ic->tme_sparc_cycles_scaled_per_usec
        !           661:            * TME_SPARC_TIMING_SPIN_USEC_MAX)) {
        !           662: 
        !           663:       /* spin: */
        !           664:       tme_misc_cycles_spin_until(&ic->tme_sparc_timing_loop_finish);
        !           665: 
        !           666:       /* do the timing loop update: */
        !           667:       _tme_sparc_timing_loop_update(ic,
        !           668:                                    ic->tme_sparc_timing_loop_branch_taken_count_max_m1);
        !           669: 
        !           670:       /* unwind back to instruction execution: */
        !           671:       return;
        !           672:     }
        !           673: 
        !           674:     /* if we will block until an external event: */
        !           675:     if (TME_SPARC_TIMING_YIELD_BLOCK) {
        !           676: 
        !           677:       /* if the number of cycles to loop doesn't fit in 32 bits: */
        !           678:       if (__tme_predict_false(cycles_scaled_max
        !           679:                              & ~ (tme_sparc_ireg_umax_t) (tme_uint32_t) (0 - (tme_uint32_t) 1))) {
        !           680: 
        !           681:        /* convert cycles into microseconds: */
        !           682:        usec = cycles_scaled_max / ic->tme_sparc_cycles_scaled_per_usec;
        !           683: 
        !           684:        /* set the sleep time: */
        !           685:        sleep_buffer.tv_sec = (usec / 1000000);
        !           686:        sleep_buffer.tv_usec = (usec % 1000000);
        !           687:       }
        !           688: 
        !           689:       /* otherwise, the number of cycles to loop fits in 32 bits: */
        !           690:       else {
        !           691: 
        !           692:        /* convert cycles into microseconds: */
        !           693:        usec32 = ((tme_uint32_t) cycles_scaled_max) / ic->tme_sparc_cycles_scaled_per_usec;
        !           694: 
        !           695:        /* assume that we will sleep for less than one second: */
        !           696:        sleep_buffer.tv_sec = 0;
        !           697: 
        !           698:        /* if the sleep time is one second or more: */
        !           699:        if (__tme_predict_false(usec32 >= 1000000)) {
        !           700: 
        !           701:          /* set the sleep time seconds: */
        !           702:          sleep_buffer.tv_sec = (usec32 / 1000000);
        !           703: 
        !           704:          /* get the microseconds: */
        !           705:          usec32 = (usec32 % 1000000);
        !           706:        }
        !           707: 
        !           708:        /* set the sleep time microseconds: */
        !           709:        sleep_buffer.tv_usec = usec32;
        !           710:       }
        !           711: 
        !           712:       /* we won't block forever: */
        !           713:       sleep = &sleep_buffer;
        !           714:     }
        !           715:   }
        !           716: 
        !           717:   /* unbusy the instruction TLB entry: */
        !           718:   assert (ic->_tme_sparc_itlb_current_token != NULL);
        !           719:   tme_token_unbusy(ic->_tme_sparc_itlb_current_token);
        !           720: 
        !           721:   /* if threads are cooperative: */
        !           722:   if (TME_THREADS_COOPERATIVE) {
        !           723: 
        !           724:     /* forget the instruction TLB entry: */
        !           725:     ic->_tme_sparc_itlb_current_token = NULL;
        !           726: 
        !           727:     /* we will redispatch into timing mode: */
        !           728:     ic->_tme_sparc_mode = TME_SPARC_MODE_TIMING_LOOP;
        !           729:   }
        !           730: 
        !           731:   /* if we're blocking: */
        !           732:   if (TME_SPARC_TIMING_YIELD_BLOCK) {
        !           733: 
        !           734:     /* lock the external mutex: */
        !           735:     tme_mutex_lock(&ic->tme_sparc_external_mutex);
        !           736: 
        !           737:     /* check one last time for any external signal: */
        !           738:     if (tme_memory_atomic_read_flag(&ic->tme_sparc_external_flag)) {
        !           739:       tme_memory_atomic_write_flag(&ic->tme_sparc_external_flag, FALSE);
        !           740:       (*ic->_tme_sparc_external_check)(ic, TME_SPARC_EXTERNAL_CHECK_MUTEX_LOCKED);
        !           741:     }
        !           742: 
        !           743:     /* block on the external signal condition: */
        !           744:     if (sleep != NULL) {
        !           745:       tme_cond_sleep_yield(&ic->tme_sparc_external_cond,
        !           746:                           &ic->tme_sparc_external_mutex,
        !           747:                           sleep);
        !           748:     }
        !           749:     else {
        !           750:       tme_cond_wait_yield(&ic->tme_sparc_external_cond,
        !           751:                          &ic->tme_sparc_external_mutex);
        !           752:     }
        !           753: 
        !           754:     /* unlock the external mutex: */
        !           755:     tme_mutex_unlock(&ic->tme_sparc_external_mutex);
        !           756:   }
        !           757:   
        !           758:   /* otherwise, we're not blocking: */
        !           759:   else {
        !           760: 
        !           761:     /* do the simple yield: */
        !           762:     tme_thread_yield();
        !           763:   }
        !           764: 
        !           765:   /* finish the timing loop: */
        !           766:   tme_sparc_timing_loop_finish(ic);
        !           767: 
        !           768:   /* relock the instruction TLB entry: */
        !           769:   tme_sparc_callout_relock(ic);
        !           770: 
        !           771:   /* unwind back to instruction execution: */
        !           772:   return;
        !           773: }
        !           774: 
        !           775: /* this possibly starts a timing loop from the instruction
        !           776:    executor: */
        !           777: void
        !           778: tme_sparc_timing_loop_start(struct tme_sparc *ic)
        !           779: {
        !           780:   tme_uint32_t insn_update;
        !           781:   tme_uint32_t insn_branch_dot;
        !           782:   tme_sparc_ireg_umax_t pc;
        !           783: 
        !           784:   /* save the current host cycles counter: */
        !           785:   ic->tme_sparc_timing_loop_start = tme_misc_cycles();
        !           786: 
        !           787:   /* get the update instruction from the branch delay slot: */
        !           788:   insn_update = tme_sparc_fetch_nearby(ic, 1);
        !           789: 
        !           790:   /* get the branch to . instruction: */
        !           791:   insn_branch_dot = ic->_tme_sparc_insn;
        !           792: 
        !           793:   /* if we don't support this timing loop: */
        !           794:   if (!tme_sparc_timing_loop_ok(insn_branch_dot,
        !           795:                                insn_update)) {
        !           796:     return;
        !           797:   }
        !           798: 
        !           799:   /* at this point, PC and PC_next_next both point to the branch to .,
        !           800:      and PC_next points to the update instruction.  we have to advance
        !           801:      the PCs, because _tme_sparc_timing_loop_update() expects PC and
        !           802:      PC_next_next to point to the update instruction, PC_next to point
        !           803:      to the branch to .: */
        !           804: 
        !           805:   /* if this is a v9 CPU: */
        !           806:   if (TME_SPARC_VERSION(ic) >= 9) {
        !           807: #ifdef TME_HAVE_INT64_T
        !           808: 
        !           809:     /* advance the PCs: */
        !           810:     pc = ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT);
        !           811:     assert (ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC)
        !           812:            == ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT_NEXT));
        !           813:     assert (((ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC)
        !           814:              + sizeof(tme_uint32_t))
        !           815:             & ic->tme_sparc_address_mask)
        !           816:            == pc);
        !           817:     ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT)
        !           818:       = ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT_NEXT);
        !           819:     ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC) = pc;
        !           820:     ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT_NEXT) = pc;
        !           821: 
        !           822: #endif /* TME_HAVE_INT64_T */
        !           823:   }
        !           824: 
        !           825:   /* otherwise, this is a v7 or v8 CPU: */
        !           826:   else {
        !           827: 
        !           828:     /* advance the PCs: */
        !           829:     pc = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT);
        !           830:     assert (ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC)
        !           831:            == ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT_NEXT));
        !           832:     assert ((ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC)
        !           833:              + sizeof(tme_uint32_t))
        !           834:            == pc);
        !           835:     ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT)
        !           836:       = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT_NEXT);
        !           837:     ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC) = pc;
        !           838:     ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT_NEXT) = pc;
        !           839:   }
        !           840: 
        !           841:   /* start the timing loop: */
        !           842:   _tme_sparc_timing_loop_start(ic,
        !           843:                               insn_update);
        !           844: }
        !           845: 
        !           846: #if TME_HAVE_RECODE
        !           847: 
        !           848: /* the recode assist function for timing loops: */
        !           849: tme_recode_uguest_t
        !           850: tme_sparc_timing_loop_assist(struct tme_ic *_ic,
        !           851:                             tme_recode_uguest_t insn_branch_dot,
        !           852:                             tme_recode_uguest_t junk)
        !           853: {
        !           854:   struct tme_sparc *ic;
        !           855:   tme_sparc_ireg_umax_t pc_next_next;
        !           856:   int branch_dot_taken;
        !           857:   tme_uint32_t insn_update;
        !           858: 
        !           859:   /* recover our ic: */
        !           860:   ic = (struct tme_sparc *) _ic;
        !           861: 
        !           862:   /* save the branch to . instruction in the normal instruction
        !           863:      position: */
        !           864:   /* NB: we do this even though PC currently points to the timing loop
        !           865:      update instruction: */
        !           866:   ic->_tme_sparc_insn = insn_branch_dot;
        !           867: 
        !           868:   /* save the current host cycles counter: */
        !           869:   ic->tme_sparc_timing_loop_start = tme_misc_cycles();
        !           870: 
        !           871:   /* NB: unlike tme_sparc_timing_loop_start(), this function may be
        !           872:      called after the branch to . has *not* been taken.  this happens
        !           873:      when the branch to . is conditional and does not annul - this is
        !           874:      the "one final time" update instruction discussed in
        !           875:      _tme_sparc_timing_loop_start().
        !           876: 
        !           877:      at this point, PC points to the update instruction, PC_next
        !           878:      points to the branch to . (if the branch to . was taken) or to
        !           879:      the instruction following the update instruction (if the branch
        !           880:      to . was not taken and does not annul): */
        !           881: 
        !           882:   /* if this is a v9 CPU: */
        !           883:   if (TME_SPARC_VERSION(ic) >= 9) {
        !           884: #ifdef TME_HAVE_INT64_T
        !           885: 
        !           886:     /* set PC_next_next from PC_next: */
        !           887:     pc_next_next
        !           888:       = ((ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT)
        !           889:          + sizeof(tme_uint32_t))
        !           890:         & ic->tme_sparc_address_mask);
        !           891:     ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC_NEXT_NEXT) = pc_next_next;
        !           892: 
        !           893:     /* see if the timing loop branch to . instruction was taken: */
        !           894:     branch_dot_taken = (ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC) == pc_next_next);
        !           895: 
        !           896:     /* get the timing loop update instruction: */
        !           897:     insn_update = ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_INSN);
        !           898: 
        !           899: #else  /* !TME_HAVE_INT64_T */
        !           900: 
        !           901:     /* silence uninitialized variable warnings: */
        !           902:     branch_dot_taken = 0;
        !           903:     insn_update = 0;
        !           904: 
        !           905: #endif /* !TME_HAVE_INT64_T */
        !           906:   }
        !           907: 
        !           908:   /* otherwise, this is not a v9 CPU: */
        !           909:   else {
        !           910: 
        !           911:     /* set PC_next_next from PC_next: */
        !           912:     pc_next_next
        !           913:       = (ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT)
        !           914:         + sizeof(tme_uint32_t));
        !           915:     ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT_NEXT) = pc_next_next;
        !           916: 
        !           917:     /* see if the timing loop branch to . instruction was taken: */
        !           918:     branch_dot_taken = (ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC) == (tme_uint32_t) pc_next_next);
        !           919: 
        !           920:     /* get the timing loop update instruction: */
        !           921:     insn_update = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_INSN);
        !           922:   }
        !           923: 
        !           924:   /* if the timing loop branch to . instruction was taken: */
        !           925:   if (branch_dot_taken) {
        !           926: 
        !           927:     /* end any recode verifying: */
        !           928:     tme_sparc_recode_verify_end_preinstruction(ic);
        !           929: 
        !           930:     /* start the timing loop: */
        !           931:     _tme_sparc_timing_loop_start(ic,
        !           932:                                 insn_update);
        !           933:   }
        !           934: 
        !           935:   /* otherwise, the timing loop branch to . instruction was not
        !           936:      taken, and it does not annul: */
        !           937:   else {
        !           938: 
        !           939:     /* do the one final update: */
        !           940:     ic->_tme_sparc_insn = insn_update;
        !           941:     _tme_sparc_timing_loop_update(ic, 0);
        !           942:   }
        !           943: 
        !           944:   /* unwind back to instruction execution: */
        !           945:   return (0);
        !           946: }
        !           947: 
        !           948: #endif /* TME_HAVE_RECODE */
        !           949: 
        !           950: /* this finishes a timing loop: */
        !           951: void
        !           952: tme_sparc_timing_loop_finish(struct tme_sparc *ic)
        !           953: {
        !           954:   union tme_value64 cycles_finish;
        !           955:   union tme_value64 cycles_scaled_u;
        !           956:   tme_sparc_ireg_umax_t cycles_scaled;
        !           957:   unsigned int loop_cycles_each;
        !           958:   tme_sparc_ireg_umax_t branch_taken_count_m1;
        !           959: 
        !           960:   /* loop forever: */
        !           961:   for (;;) {
        !           962: 
        !           963:     /* get the current host cycle counter: */
        !           964:     cycles_finish = tme_misc_cycles();
        !           965: 
        !           966:     /* if the timing loop has finished: */
        !           967:     if (tme_value64_cmp(&cycles_finish, >=, &ic->tme_sparc_timing_loop_finish)) {
        !           968:       break;
        !           969:     }
        !           970: 
        !           971:     /* if an external event has happened: */
        !           972:     if (tme_memory_atomic_read_flag(&ic->tme_sparc_external_flag)) {
        !           973:       break;
        !           974:     }
        !           975: 
        !           976:     /* if we block, we were supposed to block until an external event
        !           977:        happened: */
        !           978:     assert (!TME_SPARC_TIMING_YIELD_BLOCK);
        !           979: 
        !           980:     /* yield: */
        !           981:     tme_thread_yield();
        !           982:   }
        !           983: 
        !           984:   /* get the number of cycles elapsed: */
        !           985:   /* NB: we try to deal with overflow: */
        !           986:   (void) tme_value64_sub(&cycles_finish, &ic->tme_sparc_timing_loop_start);
        !           987:   cycles_scaled_u
        !           988:     = tme_misc_cycles_scaled(&ic->tme_sparc_cycles_scaling,
        !           989:                             &cycles_finish);
        !           990: #ifdef TME_HAVE_INT64_T
        !           991:   cycles_scaled = cycles_scaled_u.tme_value64_uint;
        !           992: #else  /* !TME_HAVE_INT64_T */
        !           993:   cycles_scaled
        !           994:     = (cycles_scaled_u.tme_value64_uint32_hi
        !           995:        ? (tme_uint32_t) (0 - (tme_uint32_t) 1)
        !           996:        : cycles_scaled_u.tme_value64_uint32_lo);
        !           997: #endif /* !TME_HAVE_INT64_T */
        !           998: 
        !           999:   /* NB: it's unusual, but actually okay if no cycles have elapsed.
        !          1000:      this just means that the branch to . will only be taken that
        !          1001:      first time.  since we need the count of times the branch to .
        !          1002:      was taken, minus one, dividing the elapsed cycles by the number
        !          1003:      of cycles per loop gets exactly what we need: */
        !          1004: 
        !          1005:   /* get the count of times the branch to . was taken, minus one: */
        !          1006:   loop_cycles_each = ic->tme_sparc_timing_loop_cycles_each;
        !          1007:   if (__tme_predict_false(loop_cycles_each != 1)) {
        !          1008:     if (__tme_predict_false(loop_cycles_each != 2)) {
        !          1009:       branch_taken_count_m1 = cycles_scaled / loop_cycles_each;
        !          1010:     }
        !          1011:     else {
        !          1012:       branch_taken_count_m1 = cycles_scaled / 2;
        !          1013:     }
        !          1014:   }
        !          1015:   else {
        !          1016:     branch_taken_count_m1 = cycles_scaled;
        !          1017:   }
        !          1018: 
        !          1019:   /* if there is a maximum count of times the branch to . could be taken: */
        !          1020:   if (ic->tme_sparc_timing_loop_branch_taken_max) {
        !          1021: 
        !          1022:     /* make sure that the branch to . isn't taken any more than the
        !          1023:        maximum: */
        !          1024:     if (branch_taken_count_m1 > ic->tme_sparc_timing_loop_branch_taken_count_max_m1) {
        !          1025:       branch_taken_count_m1 = ic->tme_sparc_timing_loop_branch_taken_count_max_m1;
        !          1026:     }
        !          1027:   }
        !          1028: 
        !          1029:   /* do the timing loop update: */
        !          1030:   _tme_sparc_timing_loop_update(ic,
        !          1031:                                branch_taken_count_m1);
        !          1032: 
        !          1033:   /* zero the instruction burst: */
        !          1034:   ic->_tme_sparc_instruction_burst_remaining = 0;
        !          1035:   ic->_tme_sparc_instruction_burst_other = TRUE;
        !          1036: 
        !          1037:   /* if threads are cooperative: */
        !          1038:   if (TME_THREADS_COOPERATIVE) {
        !          1039: 
        !          1040:     /* we will chain into execution mode: */
        !          1041:     ic->_tme_sparc_mode = TME_SPARC_MODE_EXECUTION;
        !          1042: 
        !          1043:     /* save a redispatch and resume execution directly: */
        !          1044:     (*ic->_tme_sparc_execute)(ic);
        !          1045:     abort();
        !          1046:   }
        !          1047: 
        !          1048:   /* otherwise, threads are preemptive: */
        !          1049: 
        !          1050:   /* unwind back to instruction execution: */
        !          1051:   return;
        !          1052: }

unix.superglobalmegacorp.com

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