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

1.1     ! root        1: /* $Id: sparc-misc.c,v 1.7 2007/08/24 01:21:50 fredette Exp $ */
        !             2: 
        !             3: /* ic/sparc/sparc-misc.c - miscellaneous things for the SPARC emulator: */
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 2005 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-misc.c,v 1.7 2007/08/24 01:21:50 fredette Exp $");
        !            40: 
        !            41: /* our bus signal handler: */
        !            42: static int
        !            43: _tme_sparc_bus_signal(struct tme_bus_connection *conn_bus, unsigned int signal)
        !            44: {
        !            45:   struct tme_sparc *ic;
        !            46:   unsigned int level_edge;
        !            47: 
        !            48:   /* recover our IC: */
        !            49:   ic = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
        !            50: 
        !            51:   /* take out the level and edge: */
        !            52:   level_edge = signal;
        !            53:   signal = TME_BUS_SIGNAL_WHICH(signal);
        !            54:   level_edge ^= signal;
        !            55: 
        !            56:   /* lock the external mutex: */
        !            57:   tme_mutex_lock(&ic->tme_sparc_external_mutex);
        !            58: 
        !            59:   /* on the falling edge of HALT or RESET, halt the processor: */
        !            60:   if (((level_edge & TME_BUS_SIGNAL_LEVEL_MASK)
        !            61:        == TME_BUS_SIGNAL_LEVEL_ASSERTED)
        !            62:       && (signal == TME_BUS_SIGNAL_HALT
        !            63:          || signal == TME_BUS_SIGNAL_RESET)) {
        !            64:     ic->tme_sparc_external_halt = TRUE;
        !            65:   }
        !            66: 
        !            67:   /* on the rising edge of RESET, reset the processor: */
        !            68:   else if (signal == TME_BUS_SIGNAL_RESET
        !            69:           && ((level_edge & TME_BUS_SIGNAL_LEVEL_MASK)
        !            70:               == TME_BUS_SIGNAL_LEVEL_NEGATED)) {
        !            71:     ic->tme_sparc_external_reset = TRUE;
        !            72:   }
        !            73: 
        !            74:   /* on any other HALT or RESET, do nothing: */
        !            75:   else if (signal == TME_BUS_SIGNAL_RESET
        !            76:           || signal == TME_BUS_SIGNAL_HALT) {
        !            77:     /* nothing */
        !            78:   }
        !            79: 
        !            80:   /* anything else: */
        !            81:   else {
        !            82:     abort();
        !            83:   }
        !            84: 
        !            85:   /* unlock the external mutex: */
        !            86:   tme_mutex_unlock(&ic->tme_sparc_external_mutex);
        !            87: 
        !            88:   /* notify any threads waiting on the external condition: */
        !            89:   tme_cond_notify(&ic->tme_sparc_external_cond, TRUE);
        !            90:   return (TME_OK);
        !            91: }
        !            92: 
        !            93: /* our interrupt handler: */
        !            94: static int
        !            95: _tme_sparc_bus_interrupt(struct tme_sparc_bus_connection *conn_sparc, unsigned int ipl)
        !            96: {
        !            97:   struct tme_sparc *ic;
        !            98: 
        !            99:   /* recover our IC: */
        !           100:   ic = conn_sparc->tme_sparc_bus_connection.tme_bus_connection.tme_connection_element->tme_element_private;
        !           101: 
        !           102:   /* lock the external mutex: */
        !           103:   tme_mutex_lock(&ic->tme_sparc_external_mutex);
        !           104: 
        !           105:   /* set the interrupt line: */
        !           106:   ic->tme_sparc_external_ipl = ipl;
        !           107: 
        !           108:   /* unlock the external mutex: */
        !           109:   tme_mutex_unlock(&ic->tme_sparc_external_mutex);
        !           110: 
        !           111:   /* notify any threads waiting on the external condition: */
        !           112:   tme_cond_notify(&ic->tme_sparc_external_cond, TRUE);
        !           113:   return (TME_OK);
        !           114: }
        !           115: 
        !           116: /* the idle function, used when the processor is halted or stopped: */
        !           117: static void
        !           118: tme_sparc_idle(struct tme_sparc *ic)
        !           119: {  
        !           120:   /* lock the external mutex: */
        !           121:   tme_mutex_lock(&ic->tme_sparc_external_mutex);
        !           122: 
        !           123:   /* loop forever: */
        !           124:   for (;;) {
        !           125: 
        !           126:     /* check for any external signal: */
        !           127:     tme_sparc32_external_check(ic);
        !           128: 
        !           129:     /* await an external condition: */
        !           130:     tme_cond_wait_yield(&ic->tme_sparc_external_cond, &ic->tme_sparc_external_mutex);
        !           131:   }
        !           132: }
        !           133: 
        !           134: /* the sparc thread: */
        !           135: static void
        !           136: tme_sparc_thread(struct tme_sparc *ic)
        !           137: {
        !           138: 
        !           139:   /* we use longjmp to redispatch: */
        !           140:   do { } while (setjmp(ic->_tme_sparc_dispatcher));
        !           141: 
        !           142:   /* we must not have a busy instruction TLB entry: */
        !           143:   assert (ic->_tme_sparc_itlb_busy == NULL);
        !           144: 
        !           145:   /* dispatch on the current mode: */
        !           146:   switch (ic->_tme_sparc_mode) {
        !           147: 
        !           148:   case TME_SPARC_MODE_EXECUTION:
        !           149:     (*ic->_tme_sparc_execute)(ic);
        !           150:     /* NOTREACHED */
        !           151: 
        !           152:   case TME_SPARC_MODE_STOP:
        !           153:   case TME_SPARC_MODE_HALT:
        !           154:     tme_sparc_idle(ic);
        !           155:     /* NOTREACHED */
        !           156: 
        !           157:   default:
        !           158:     abort();
        !           159:   }
        !           160:   /* NOTREACHED */
        !           161: }
        !           162: 
        !           163: /* the TLB filler for when we are on a generic bus: */
        !           164: static int
        !           165: _tme_sparc_generic_tlb_fill(struct tme_sparc_bus_connection *conn_sparc, 
        !           166:                            struct tme_sparc_tlb *tlb,
        !           167:                            unsigned int address_space, 
        !           168:                            tme_bus_addr_t external_address, 
        !           169:                            unsigned int cycles)
        !           170: {
        !           171:   struct tme_sparc *ic;
        !           172: 
        !           173:   /* recover our IC: */
        !           174:   ic = conn_sparc->tme_sparc_bus_connection.tme_bus_connection.tme_connection_element->tme_element_private;
        !           175: 
        !           176:   /* call the generic bus TLB filler: */
        !           177:   (ic->_tme_sparc_bus_generic->tme_bus_tlb_fill)
        !           178:     (ic->_tme_sparc_bus_generic,
        !           179:      &tlb->tme_sparc_tlb_bus_tlb,
        !           180:      external_address,
        !           181:      cycles);
        !           182:   
        !           183:   /* when we're on a generic bus a TLB entry is valid for all address spaces: */
        !           184:   tlb->tme_sparc_tlb_asi_mask = ((tme_uint32_t) 0) - 1;
        !           185: 
        !           186:   return (TME_OK);
        !           187: }
        !           188: 
        !           189: /* the sparc command function: */
        !           190: static int
        !           191: _tme_sparc_command(struct tme_element *element, const char * const * args, char **_output)
        !           192: {
        !           193:   struct tme_sparc *ic;
        !           194:   unsigned int idle_type_saved;
        !           195: 
        !           196:   /* recover our IC: */
        !           197:   ic = (struct tme_sparc *) element->tme_element_private;
        !           198: 
        !           199:   /* the "idle-type" command: */
        !           200:   if (TME_ARG_IS(args[1], "idle-type")) {
        !           201: 
        !           202:     /* save the current idle type and set it to none: */
        !           203:     idle_type_saved = ic->tme_sparc_idle_type;
        !           204:     ic->tme_sparc_idle_type = TME_SPARC_IDLE_TYPE_NULL;
        !           205: 
        !           206:     /* if we're not setting the idle type to none: */
        !           207:     if (!TME_ARG_IS(args[2], "none")) {
        !           208: 
        !           209:       /* check for a supported idle type: */
        !           210: #define _TME_SPARC_IDLE_TYPE(x, s)             \
        !           211:   do {                                         \
        !           212:     if ((TME_SPARC_IDLE_TYPES_SUPPORTED                \
        !           213:          & (x))                                        \
        !           214:       && TME_ARG_IS(args[2], s)) {             \
        !           215:       ic->tme_sparc_idle_type = (x);           \
        !           216:     }                                          \
        !           217:   } while (/* CONSTCOND */ 0)
        !           218:       _TME_SPARC_IDLE_TYPE(TME_SPARC_IDLE_TYPE_NETBSD32_TYPE_0, "netbsd32-type-0");
        !           219:       _TME_SPARC_IDLE_TYPE(TME_SPARC_IDLE_TYPE_SUNOS32_TYPE_0, "sunos32-type-0");
        !           220: #undef _TME_SPARC_IDLE_TYPE
        !           221: 
        !           222:       /* if the idle type isn't supported: */
        !           223:       if (ic->tme_sparc_idle_type == TME_SPARC_IDLE_TYPE_NULL) {
        !           224: 
        !           225:        /* restore the idle type and return a usage: */
        !           226:        ic->tme_sparc_idle_type = idle_type_saved;
        !           227:     
        !           228:        tme_output_append_error(_output,
        !           229:                                "%s %s idle-type { none",
        !           230:                                _("usage:"),
        !           231:                                args[0]);
        !           232: 
        !           233:       /* add in the supported idle types: */
        !           234: #define _TME_SPARC_IDLE_TYPE(x, s)             \
        !           235:   do {                                         \
        !           236:     if (TME_SPARC_IDLE_TYPES_SUPPORTED         \
        !           237:        & (x)) {                                \
        !           238:       tme_output_append_error(_output, " | %s",        \
        !           239:                              s);               \
        !           240:     }                                          \
        !           241:   } while (/* CONSTCOND */ 0)
        !           242:        _TME_SPARC_IDLE_TYPE(TME_SPARC_IDLE_TYPE_NETBSD32_TYPE_0, "netbsd32-type-0");
        !           243:        _TME_SPARC_IDLE_TYPE(TME_SPARC_IDLE_TYPE_SUNOS32_TYPE_0, "sunos32-type-0");
        !           244: #undef _TME_SPARC_IDLE_TYPE
        !           245: 
        !           246:        tme_output_append_error(_output, " }");
        !           247:        return (EINVAL);
        !           248:       }
        !           249:     }
        !           250: 
        !           251:     /* poison all idle type state: */
        !           252:     ic->tme_sparc_idle_type_pc32 = TME_SPARC_IDLE_TYPE_PC_STATE(1);
        !           253:   }
        !           254: 
        !           255:   /* any other command: */
        !           256:   else {
        !           257:     if (args[1] != NULL) {
        !           258:       tme_output_append_error(_output,
        !           259:                              "%s '%s', ",
        !           260:                              _("unknown command"),
        !           261:                              args[1]);
        !           262:     }
        !           263:     tme_output_append_error(_output,
        !           264:                            _("available %s commands:%s"),
        !           265:                            args[0],
        !           266:                            (TME_SPARC_IDLE_TYPES_SUPPORTED != 0
        !           267:                             ? " idle-type"
        !           268:                             : ""));
        !           269:     return (EINVAL);
        !           270:   }
        !           271: 
        !           272:   return (TME_OK);
        !           273: }
        !           274: 
        !           275: /* the connection scorer: */
        !           276: static int
        !           277: _tme_sparc_connection_score(struct tme_connection *conn, unsigned int *_score)
        !           278: {
        !           279:   struct tme_sparc_bus_connection *conn_sparc;
        !           280:   struct tme_bus_connection *conn_bus;
        !           281:   unsigned int score;
        !           282: 
        !           283:   /* assume that this connection is useless: */
        !           284:   score = 0;
        !           285: 
        !           286:   /* dispatch on the connection type: */
        !           287:   conn_sparc = (struct tme_sparc_bus_connection *) conn->tme_connection_other;
        !           288:   conn_bus = (struct tme_bus_connection *) conn->tme_connection_other;
        !           289:   switch (conn->tme_connection_type) {
        !           290: 
        !           291:     /* this must be a bus, and not another sparc chip: */
        !           292:   case TME_CONNECTION_BUS_SPARC:
        !           293:     if (conn_bus->tme_bus_tlb_set_allocate != NULL
        !           294:        && conn_sparc->tme_sparc_bus_tlb_fill != NULL
        !           295:        && conn_sparc->tme_sparc_bus_fpu_strict == NULL) {
        !           296:       score = 10;
        !           297:     }
        !           298:     break;
        !           299: 
        !           300:     /* this must be a bus, and not another chip: */
        !           301:   case TME_CONNECTION_BUS_GENERIC:
        !           302:     if (conn_bus->tme_bus_tlb_set_allocate != NULL
        !           303:        && conn_bus->tme_bus_tlb_fill != NULL) {
        !           304:       score = 1;
        !           305:     }
        !           306:     break;
        !           307: 
        !           308:   default: abort();
        !           309:   }
        !           310: 
        !           311:   *_score = score;
        !           312:   return (TME_OK);
        !           313: }
        !           314: 
        !           315: /* this makes a new connection: */
        !           316: static int
        !           317: _tme_sparc_connection_make(struct tme_connection *conn, unsigned int state)
        !           318: {
        !           319:   struct tme_sparc *ic;
        !           320:   struct tme_sparc_bus_connection *conn_sparc;
        !           321:   struct tme_bus_connection *conn_bus;
        !           322:   struct tme_connection *conn_other;
        !           323: 
        !           324:   /* since the CPU is halted, it won't be making any connection calls,
        !           325:      so we only have to do work when the connection is fully made: */
        !           326:   if (state == TME_CONNECTION_FULL) {
        !           327: 
        !           328:     /* recover our IC: */
        !           329:     ic = conn->tme_connection_element->tme_element_private;
        !           330:     
        !           331:     /* dispatch on the connection type: */
        !           332:     conn_other = conn->tme_connection_other;
        !           333:     conn_sparc = (struct tme_sparc_bus_connection *) conn_other;
        !           334:     conn_bus = (struct tme_bus_connection *) conn_other;
        !           335:     switch (conn->tme_connection_type) {
        !           336:       
        !           337:     case TME_CONNECTION_BUS_SPARC:
        !           338:       ic->_tme_sparc_bus_connection = conn_sparc;
        !           339:       break;
        !           340:       
        !           341:       /* we need an adaptation layer: */
        !           342:     case TME_CONNECTION_BUS_GENERIC:
        !           343:       conn_sparc = tme_new0(struct tme_sparc_bus_connection, 1);
        !           344:       conn_sparc->tme_sparc_bus_connection.tme_bus_connection.tme_connection_element = conn->tme_connection_element;
        !           345:       conn_sparc->tme_sparc_bus_tlb_fill = _tme_sparc_generic_tlb_fill;
        !           346:       ic->_tme_sparc_bus_connection = conn_sparc;
        !           347:       ic->_tme_sparc_bus_generic = conn_bus;
        !           348:       break;
        !           349:       
        !           350:     default: abort();
        !           351:     }
        !           352: 
        !           353:     /* allocate the DTLB hash set: */
        !           354:     (*ic->_tme_sparc_bus_connection->tme_sparc_bus_connection.tme_bus_tlb_set_allocate)
        !           355:       (&ic->_tme_sparc_bus_connection->tme_sparc_bus_connection, 
        !           356:        _TME_SPARC_DTLB_HASH_SIZE, 
        !           357:        sizeof(struct tme_sparc_tlb),
        !           358:        &ic->_tme_sparc_dtlb_array_bus,
        !           359:        &ic->_tme_sparc_tlb_rwlock);
        !           360: 
        !           361:     /* allocate the ITLB hash set: */
        !           362:     (*ic->_tme_sparc_bus_connection->tme_sparc_bus_connection.tme_bus_tlb_set_allocate)
        !           363:       (&ic->_tme_sparc_bus_connection->tme_sparc_bus_connection, 
        !           364:        _TME_SPARC_ITLB_HASH_SIZE, 
        !           365:        sizeof(struct tme_sparc_tlb),
        !           366:        &ic->_tme_sparc_itlb_array_bus,
        !           367:        &ic->_tme_sparc_tlb_rwlock);
        !           368:   }
        !           369: 
        !           370:   /* NB: the machine needs to issue a reset to bring the CPU out of halt. */
        !           371:   return (TME_OK);
        !           372: }
        !           373: 
        !           374: /* this breaks a connection: */
        !           375: static int 
        !           376: _tme_sparc_connection_break(struct tme_connection *conn, unsigned int state)
        !           377: {
        !           378:   abort();
        !           379:   return (0);
        !           380: }
        !           381: 
        !           382: /* this makes new connection sides: */
        !           383: static int
        !           384: _tme_sparc_connections_new(struct tme_element *element, const char * const *args, struct tme_connection **_conns, char **_output)
        !           385: {
        !           386:   struct tme_sparc_bus_connection *conn_sparc;
        !           387:   struct tme_bus_connection *conn_bus;
        !           388:   struct tme_connection *conn;
        !           389: 
        !           390:   /* if we already have a bus connection, we can take no more connections: */
        !           391:   if (((struct tme_sparc *) element->tme_element_private)->_tme_sparc_bus_connection != NULL) {
        !           392:     return (TME_OK);
        !           393:   }
        !           394: 
        !           395:   /* create our side of an sparc bus connection: */
        !           396:   conn_sparc = tme_new0(struct tme_sparc_bus_connection, 1);
        !           397:   conn_bus = &conn_sparc->tme_sparc_bus_connection;
        !           398:   conn = &conn_bus->tme_bus_connection;
        !           399: 
        !           400:   /* fill in the generic connection: */
        !           401:   conn->tme_connection_next = *_conns;
        !           402:   conn->tme_connection_type = TME_CONNECTION_BUS_SPARC;
        !           403:   conn->tme_connection_score = _tme_sparc_connection_score;
        !           404:   conn->tme_connection_make = _tme_sparc_connection_make;
        !           405:   conn->tme_connection_break = _tme_sparc_connection_break;
        !           406: 
        !           407:   /* fill in the generic bus connection: */
        !           408:   conn_bus->tme_bus_signal = _tme_sparc_bus_signal;
        !           409:   conn_bus->tme_bus_tlb_set_allocate = NULL;
        !           410: 
        !           411:   /* full in the sparc bus connection: */
        !           412:   conn_sparc->tme_sparc_bus_interrupt = _tme_sparc_bus_interrupt;
        !           413:   conn_sparc->tme_sparc_bus_tlb_fill = NULL;
        !           414:   conn_sparc->tme_sparc_bus_fpu_strict = tme_sparc_fpu_strict;
        !           415: 
        !           416:   /* add this connection to the set of possibilities: */
        !           417:   *_conns = conn;
        !           418: 
        !           419:   /* create our side of a generic bus connection: */
        !           420:   conn_bus = tme_new0(struct tme_bus_connection, 1);
        !           421:   conn = &conn_bus->tme_bus_connection;
        !           422: 
        !           423:   /* fill in the generic connection: */
        !           424:   conn->tme_connection_next = *_conns;
        !           425:   conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC;
        !           426:   conn->tme_connection_score = _tme_sparc_connection_score;
        !           427:   conn->tme_connection_make = _tme_sparc_connection_make;
        !           428:   conn->tme_connection_break = _tme_sparc_connection_break;
        !           429: 
        !           430:   /* fill in the generic bus connection: */
        !           431:   conn_bus->tme_bus_signal = _tme_sparc_bus_signal;
        !           432:   conn_bus->tme_bus_tlb_set_allocate = NULL;
        !           433:   conn_bus->tme_bus_tlb_fill = NULL;
        !           434: 
        !           435:   /* add this connection to the set of possibilities: */
        !           436:   *_conns = conn;
        !           437: 
        !           438:   /* done: */
        !           439:   return (TME_OK);
        !           440: }
        !           441: 
        !           442: /* the common sparc new function: */
        !           443: int
        !           444: tme_sparc_new(struct tme_sparc *ic, const char * const *args, const void *extra, char **_output)
        !           445: {
        !           446:   struct tme_element *element;
        !           447:   int arg_i;
        !           448:   int usage;
        !           449: 
        !           450:   /* assume that we have no FPU: */
        !           451:   ic->tme_sparc_fpu_fsr = TME_SPARC_FSR_VER_missing;
        !           452: 
        !           453:   /* check our arguments: */
        !           454:   arg_i = 1;
        !           455:   usage = FALSE;
        !           456:   for (;;) {
        !           457:     
        !           458:     if (0) {
        !           459: 
        !           460:     }
        !           461: 
        !           462:     /* if we've run out of arguments: */
        !           463:     else if (args[arg_i + 0] == NULL) {
        !           464:       break;
        !           465:     }
        !           466: 
        !           467:     /* this is either a bad argument or an FPU argument: */
        !           468:     else {
        !           469: 
        !           470:       /* if this is not an FPU argument: */
        !           471:       if (!tme_sparc_fpu_new(ic, args, &arg_i, &usage, _output)) {
        !           472:        tme_output_append_error(_output,
        !           473:                                "%s %s, ",
        !           474:                                args[arg_i],
        !           475:                                _("unexpected"));
        !           476:        usage = TRUE;
        !           477:       }
        !           478:       
        !           479:       if (usage) {
        !           480:        break;
        !           481:       }
        !           482:     }
        !           483:   }
        !           484: 
        !           485:   if (usage) {
        !           486:     tme_output_append_error(_output, 
        !           487:                            "%s %s",
        !           488:                            _("usage:"),
        !           489:                            args[0]);
        !           490:     tme_sparc_fpu_usage(ic, _output);
        !           491:     tme_free(ic);
        !           492:     return (EINVAL);
        !           493:   }
        !           494: 
        !           495:   /* initialize the verifier: */
        !           496:   tme_sparc_verify_init();
        !           497: 
        !           498:   /* we have no bus connection yet: */
        !           499:   ic->_tme_sparc_bus_connection = NULL;
        !           500: 
        !           501:   /* fill the element: */
        !           502:   element = ic->tme_sparc_element;
        !           503:   element->tme_element_private = ic;
        !           504:   element->tme_element_connections_new = _tme_sparc_connections_new;
        !           505:   element->tme_element_command = _tme_sparc_command;
        !           506: 
        !           507:   /* calculate the instruction burst size: */
        !           508:   /* XXX TBD: */
        !           509:   ic->_tme_sparc_instruction_burst = 800;
        !           510:   ic->_tme_sparc_instruction_burst_remaining
        !           511:     = ic->_tme_sparc_instruction_burst;
        !           512: 
        !           513:   /* force the processor to be halted: */
        !           514:   ic->_tme_sparc_mode = TME_SPARC_MODE_HALT;
        !           515: 
        !           516:   /* poison all idle type state: */
        !           517:   ic->tme_sparc_idle_type_pc32 = TME_SPARC_IDLE_TYPE_PC_STATE(1);
        !           518: 
        !           519:   /* start the sparc thread: */
        !           520:   tme_thread_create((tme_thread_t) tme_sparc_thread, ic);
        !           521: 
        !           522:   return (TME_OK);
        !           523: }  
        !           524: 
        !           525: /* this redispatches: */
        !           526: void
        !           527: tme_sparc_redispatch(struct tme_sparc *ic)
        !           528: {
        !           529:   struct tme_sparc_tlb *tlb;
        !           530: 
        !           531:   /* if we have a busy instruction TLB entry: */
        !           532:   tlb = ic->_tme_sparc_itlb_busy;
        !           533:   if (__tme_predict_true(tlb != NULL)) {
        !           534: 
        !           535:     /* unbusy and forget the instruction TLB entry: */
        !           536:     tme_sparc_tlb_unbusy(tlb);
        !           537:     ic->_tme_sparc_itlb_busy = NULL;
        !           538:   }
        !           539: 
        !           540:   /* do the redispatch: */
        !           541: #ifdef _TME_SPARC_STATS
        !           542:   ic->tme_sparc_stats.tme_sparc_stats_redispatches++;
        !           543: #endif /* _TME_SPARC_STATS */
        !           544:   longjmp(ic->_tme_sparc_dispatcher, 1);
        !           545: }
        !           546: 
        !           547: /* our global verify hook function: */
        !           548: #undef tme_sparc_verify_hook
        !           549: void
        !           550: tme_sparc_verify_hook(void)
        !           551: {
        !           552: }
        !           553: 
        !           554: /* the common sparc reset function: */
        !           555: void
        !           556: tme_sparc_do_reset(struct tme_sparc *ic)
        !           557: {
        !           558: 
        !           559:   /* if this is a v7 or v8 CPU: */
        !           560:   if (ic->tme_sparc_version < 9) {
        !           561: 
        !           562:     /* set the initial PCs: */
        !           563:     ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT) = 0;
        !           564:     ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT_NEXT) = sizeof(tme_uint32_t);
        !           565:     
        !           566:     /* force supervisor mode, traps disabled: */
        !           567:     ic->tme_sparc32_ireg_psr
        !           568:       = ((ic->tme_sparc32_ireg_psr
        !           569:          & ~TME_SPARC32_PSR_ET)
        !           570:         | TME_SPARC32_PSR_S);
        !           571:   }
        !           572: 
        !           573:   /* otherwise, this is a v9 CPU: */
        !           574:   else {
        !           575: 
        !           576:     /* XXX WRITEME */
        !           577:     abort();
        !           578:   }
        !           579: 
        !           580:   /* reset the FPU: */
        !           581:   tme_sparc_fpu_reset(ic);
        !           582: 
        !           583:   /* poison all idle type state, to force the idle type to retrain: */
        !           584:   ic->tme_sparc_idle_type_pc32 = TME_SPARC_IDLE_TYPE_PC_STATE(1);
        !           585: 
        !           586:   /* start execution: */
        !           587:   ic->_tme_sparc_mode = TME_SPARC_MODE_EXECUTION;
        !           588:   tme_sparc_redispatch(ic);
        !           589: }
        !           590: 
        !           591: /* the common sparc idle function: */
        !           592: void
        !           593: tme_sparc_do_idle(struct tme_sparc *ic)
        !           594: {
        !           595: 
        !           596:   /* NB: since the interrupt that causes us to leave stop mode will
        !           597:      call tme_sparc32_trap_preinstruction(), this function can only be
        !           598:      called on a preinstruction boundary (i.e., while PC still points
        !           599:      to the (completed!) instruction that triggered the idle
        !           600:      condition): */
        !           601: 
        !           602:   /* redispatch into stop mode: */
        !           603:   ic->_tme_sparc_mode = TME_SPARC_MODE_STOP;
        !           604:   tme_sparc_redispatch(ic);
        !           605: }
        !           606: 
        !           607: /* this checks for external signals.  this must be called with the
        !           608:    external mutex held: */
        !           609: void
        !           610: tme_sparc32_external_check(struct tme_sparc *ic)
        !           611: {
        !           612:   unsigned int ipl;
        !           613:   int vector;
        !           614: 
        !           615:   /* if an external reset has been requested, start reset trap
        !           616:      processing: */
        !           617:   if (ic->tme_sparc_external_reset) {
        !           618:     ic->tme_sparc_external_reset = FALSE;
        !           619:     tme_mutex_unlock(&ic->tme_sparc_external_mutex);
        !           620:     tme_sparc32_trap_preinstruction(ic, TME_SPARC_TRAP_reset);
        !           621:   }
        !           622: 
        !           623:   /* if an external halt has been requested, halt: */
        !           624:   if (ic->tme_sparc_external_halt) {
        !           625:     ic->tme_sparc_external_halt = FALSE;
        !           626:     tme_mutex_unlock(&ic->tme_sparc_external_mutex);
        !           627:     ic->_tme_sparc_mode = TME_SPARC_MODE_HALT;
        !           628:     tme_sparc_redispatch(ic);
        !           629:   }
        !           630: 
        !           631:   /* if we are not halted and an interrupt can be serviced, start
        !           632:      interrupt trap processing: */
        !           633:   ipl = ic->tme_sparc_external_ipl;
        !           634:   if (ic->_tme_sparc_mode != TME_SPARC_MODE_HALT
        !           635:       && (ic->tme_sparc32_ireg_psr & TME_SPARC32_PSR_ET)
        !           636:       && ipl >= TME_SPARC_IPL_MIN
        !           637:       && ipl <= TME_SPARC_IPL_MAX
        !           638:       && (ipl == TME_SPARC_IPL_NMI
        !           639:          || ipl > TME_FIELD_MASK_EXTRACTU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_PIL))) {
        !           640:     
        !           641:     tme_mutex_unlock(&ic->tme_sparc_external_mutex);
        !           642: 
        !           643:     /* acknowledge the interrupt: */
        !           644:     (*ic->_tme_sparc_bus_connection->tme_sparc_bus_connection.tme_bus_intack)
        !           645:       (&ic->_tme_sparc_bus_connection->tme_sparc_bus_connection,
        !           646:        ipl, &vector);
        !           647: 
        !           648:     /* dispatch the trap: */
        !           649:     tme_sparc32_trap_preinstruction(ic, TME_SPARC_TRAP_interrupt_level(ipl));
        !           650:   }
        !           651: 
        !           652:   /* there are no traps to process: */
        !           653: }
        !           654: 
        !           655: /* this triggers sparc32 trap processing on a preinstruction boundary: */
        !           656: void
        !           657: tme_sparc32_trap_preinstruction(struct tme_sparc *ic, tme_uint32_t trap)
        !           658: {
        !           659: 
        !           660:   /* shift the next instruction's PC and next-next PC up: */
        !           661:   ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC) = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT);
        !           662:   ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT) = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT_NEXT);
        !           663: 
        !           664:   /* do the rest of the sparc32 trap processing: */
        !           665:   tme_sparc32_trap(ic, trap);
        !           666: }
        !           667: 
        !           668: /* this triggers sparc32 trap processing by an instruction: */
        !           669: void
        !           670: tme_sparc32_trap(struct tme_sparc *ic, tme_uint32_t trap)
        !           671: {
        !           672:   unsigned int cwp;
        !           673:   unsigned int cwp_offset;
        !           674: 
        !           675:   /* reset traps are handled specially: */
        !           676:   if (__tme_predict_false(trap == TME_SPARC_TRAP_reset)) {
        !           677:     tme_sparc_do_reset(ic);
        !           678:     /* NOTREACHED */
        !           679:   }  
        !           680: 
        !           681:   /* "The processor enters error_mode state when a trap occurs while
        !           682:      ET = 0. An implementation should preserve as much processor state
        !           683:      as possible when this happens. Standard trap actions (such as
        !           684:      decrementing CWP and saving state information in locals) should
        !           685:      not occur when entering error_mode. In particular, the tt field
        !           686:      of the TBR is only written during a transition into error_mode
        !           687:      state in the singular case of a RETT instruction that traps while
        !           688:      ET = 0. In this case, tt is written to indicate the type of
        !           689:      exception that was induced by the RETT instruction.
        !           690: 
        !           691:      What occurs after error_mode is entered is
        !           692:      implementation-dependent; typically the processor triggers an
        !           693:      external reset, causing a reset trap (see below). */
        !           694:   if (__tme_predict_false((ic->tme_sparc32_ireg_psr & TME_SPARC32_PSR_ET) == 0)) {
        !           695: 
        !           696:     /* if we were executing a RETT instruction: */
        !           697:     assert (ic->_tme_sparc_mode == TME_SPARC_MODE_EXECUTION);
        !           698:     if ((ic->_tme_sparc_insn
        !           699:         & ((3 << 30) | (0x3f << 19)))
        !           700:        == ((tme_uint32_t) (2 << 30) | (0x39 << 19))) {
        !           701:       
        !           702:       /* update the TBR register: */
        !           703:       TME_FIELD_MASK_DEPOSITU(ic->tme_sparc32_ireg_tbr, 0xff, trap);
        !           704:     }
        !           705: 
        !           706:     /* reset the processor: */
        !           707:     tme_log(TME_SPARC_LOG_HANDLE(ic), 0, EPERM,
        !           708:            (TME_SPARC_LOG_HANDLE(ic),
        !           709:             _("took a trap while traps disabled, processor reset")));
        !           710:     tme_sparc32_trap(ic, TME_SPARC_TRAP_reset);
        !           711:   }
        !           712: 
        !           713:   /* "Traps are disabled: ET <- 0.
        !           714:      The existing user/supervisor mode is preserved: PS <- S.
        !           715:      The user/supervisor mode is changed to supervisor: S <- 1." */
        !           716:   ic->tme_sparc32_ireg_psr
        !           717:     = ((ic->tme_sparc32_ireg_psr
        !           718:        & ~(TME_SPARC32_PSR_ET
        !           719:            | TME_SPARC32_PSR_PS))
        !           720:        | ((ic->tme_sparc32_ireg_psr
        !           721:           & TME_SPARC32_PSR_S)
        !           722:          / (TME_SPARC32_PSR_S
        !           723:             / TME_SPARC32_PSR_PS))
        !           724:        | TME_SPARC32_PSR_S);
        !           725: 
        !           726:   /* "The register window is advanced to a new window: 
        !           727:      CWP <- ((CWP - 1) modulo NWINDOWS) 
        !           728:      [note: without test for window overflow]." */
        !           729:   cwp = TME_FIELD_MASK_EXTRACTU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_CWP);
        !           730:   cwp -= 1;
        !           731:   cwp %= ic->tme_sparc_nwindows;
        !           732:   TME_FIELD_MASK_DEPOSITU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_CWP, cwp);
        !           733:   cwp_offset = TME_SPARC_CWP_OFFSET(cwp);
        !           734:   ic->tme_sparc_cwp_offset = cwp_offset;
        !           735: 
        !           736:   /* "The trapped program counters are saved in local registers 1 and
        !           737:      2 of the new window: r[17] <- PC, r[18] <- nPC." */
        !           738:   ic->tme_sparc_ireg_uint32(cwp_offset + 17) = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC);
        !           739:   ic->tme_sparc_ireg_uint32(cwp_offset + 18) = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT);
        !           740: 
        !           741:   /* "The tt field is written to the particular value that identifies
        !           742:      the exception or interrupt request, except as defined for `Reset
        !           743:      Trap' and `Error Mode' above." */
        !           744:   TME_FIELD_MASK_DEPOSITU(ic->tme_sparc32_ireg_tbr, 0x00000ff0, trap);
        !           745: 
        !           746:   /* "If the trap is not a reset trap, control is transferred into the
        !           747:      trap table: PC <- TBR, nPC <- TBR + 4." */
        !           748:   ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT) = ic->tme_sparc32_ireg_tbr;
        !           749:   ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT_NEXT) = ic->tme_sparc32_ireg_tbr + sizeof(tme_uint32_t);
        !           750: 
        !           751:   /* redispatch: */
        !           752:   ic->_tme_sparc_mode = TME_SPARC_MODE_EXECUTION;
        !           753:   tme_sparc_redispatch(ic);
        !           754: }
        !           755: 
        !           756: /* the default slow instruction fetcher: */
        !           757: tme_uint32_t
        !           758: tme_sparc32_fetch_slow(struct tme_sparc *ic, int annulled)
        !           759: {
        !           760:   tme_uint32_t pc;
        !           761:   const tme_shared tme_uint8_t *memory;
        !           762:   struct tme_sparc_tlb *dtlb;
        !           763:   tme_uint32_t insn;
        !           764: 
        !           765:   /* get the PC of the instruction: */
        !           766:   pc = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC);
        !           767: 
        !           768:   /* XXX FIXME - unfortunately, using tme_sparc32_load() means that we
        !           769:      we have to pollute the DTLB here: */
        !           770:   /* get and busy the DTLB entry: */
        !           771:   dtlb = TME_SPARC_DTLB_ENTRY(ic, pc);
        !           772:   tme_sparc_tlb_busy(dtlb);
        !           773: 
        !           774:   /* do a load for an instruction: */
        !           775:   memory
        !           776:     = tme_sparc32_load(ic,
        !           777:                       pc,
        !           778:                       (sizeof(tme_uint32_t)
        !           779:                        | TME_SPARC_SLOW_FLAG_INSN
        !           780:                        | (annulled
        !           781:                           ? TME_SPARC_SLOW_FLAG_NO_FAULTS
        !           782:                           : 0)));
        !           783: 
        !           784:   /* if this instruction is annulled: */
        !           785:   if (annulled) {
        !           786: 
        !           787:     /* we can return anything: */
        !           788:     insn = 0;
        !           789:   }
        !           790: 
        !           791:   /* otherwise, this instruction is not annulled: */
        !           792:   else {
        !           793: 
        !           794:     /* XXX FIXME - we don't currently finish a real slow load: */
        !           795:     abort();
        !           796:   }
        !           797: 
        !           798:   /* unbusy the DTLB entry: */
        !           799:   tme_sparc_tlb_unbusy(dtlb);
        !           800: 
        !           801:   /* return the instruction: */
        !           802:   return (insn);
        !           803: }
        !           804: 
        !           805: /* the default bus fault to trap mapping function: */
        !           806: tme_uint32_t
        !           807: tme_sparc32_bus_fault(struct tme_sparc *ic,
        !           808:                      const struct tme_bus_cycle *cycle,
        !           809:                      unsigned int flags,
        !           810:                      int err)
        !           811: {
        !           812:   switch (err) {
        !           813:   case EFAULT:
        !           814:   case ENOENT:
        !           815:   case EIO: 
        !           816:     if (flags & TME_SPARC_SLOW_FLAG_INSN) {
        !           817:       return ((flags & TME_SPARC_SLOW_FLAG_NO_FAULTS)
        !           818:              ? TME_SPARC_TRAP_none
        !           819:              : TME_SPARC_TRAP_instruction_access_exception);
        !           820:     }
        !           821:     assert (!(flags & TME_SPARC_SLOW_FLAG_NO_FAULTS));
        !           822:     return (TME_SPARC_TRAP_data_access_exception);
        !           823:   default: abort();
        !           824:   }
        !           825: }
        !           826: 
        !           827: /* this triggers sparc64 trap processing by an instruction: */
        !           828: void
        !           829: tme_sparc64_trap(struct tme_sparc *ic, tme_uint32_t trap)
        !           830: {
        !           831:   abort();
        !           832: }
        !           833: 
        !           834: /* this fetches an instruction close enough to the current instruction
        !           835:    that it should be within the current instruction TLB entry.  it
        !           836:    returns all-bits-one if the instruction isn't within the current
        !           837:    instruction TLB entry: */
        !           838: tme_uint32_t
        !           839: tme_sparc_fetch_nearby(struct tme_sparc *ic, long offset_in_insns)
        !           840: {
        !           841:   struct tme_sparc_tlb *itlb_current;
        !           842:   tme_bus_addr_t pc;
        !           843:   tme_uint32_t insn;
        !           844: 
        !           845:   /* get the address of the current instruction: */
        !           846:   pc = (
        !           847: #ifdef TME_HAVE_INT64_T
        !           848:        (TME_SPARC_VERSION(ic) >= 9)
        !           849:        ? ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC)
        !           850:        :
        !           851: #endif /* TME_HAVE_INT64_T */
        !           852:        ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC));
        !           853: 
        !           854:   /* assume that we can't fetch the nearby instruction: */
        !           855:   insn = 0xffffffff;
        !           856: 
        !           857:   /* there must be a current instruction TLB entry, and it must be
        !           858:      busy, cover this ASI and address, and allow fast reading: */
        !           859:   itlb_current = ic->_tme_sparc_itlb_busy;
        !           860:   assert (itlb_current != NULL);
        !           861:   /* XXX FIXME - there should be a tme_bus_tlb_assert_busy(): */
        !           862:   assert (TME_SPARC_TLB_ASI_MASK_OK(itlb_current, ic->tme_sparc_asi_mask_insn));
        !           863:   assert (itlb_current->tme_sparc_tlb_addr_first <= pc
        !           864:          && pc <= itlb_current->tme_sparc_tlb_addr_last);
        !           865:   assert (itlb_current->tme_sparc_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF);
        !           866: 
        !           867:   /* adjust the address to point to the nearby instruction: */
        !           868:   pc += offset_in_insns * sizeof(tme_uint32_t);
        !           869: 
        !           870:   /* if the instruction TLB entry is valid and also covers this address: */
        !           871:   if (tme_bus_tlb_is_valid(&itlb_current->tme_sparc_tlb_bus_tlb)
        !           872:       && itlb_current->tme_sparc_tlb_addr_first <= pc
        !           873:       && pc <= itlb_current->tme_sparc_tlb_addr_last) {
        !           874:     
        !           875:     /* fetch the nearby instruction: */
        !           876:     insn = tme_memory_bus_read32((const tme_shared tme_uint32_t *) (itlb_current->tme_sparc_tlb_emulator_off_read + pc),
        !           877:                                 itlb_current->tme_sparc_tlb_bus_rwlock,
        !           878:                                 sizeof(tme_uint32_t),
        !           879:                                 (TME_SPARC_VERSION(ic) < 9
        !           880:                                  ? sizeof(tme_uint32_t)
        !           881:                                  : sizeof(tme_uint32_t) * 2));
        !           882:     insn = tme_betoh_u32(insn);
        !           883:   }
        !           884: 
        !           885:   return (insn);
        !           886: }
        !           887: 
        !           888: /* this unlocks data structures before a callout: */
        !           889: void
        !           890: tme_sparc_callout_unlock(struct tme_sparc *ic)
        !           891: {
        !           892:   struct tme_sparc_tlb *tlb;
        !           893: 
        !           894:   assert ((ic->_tme_sparc_mode == TME_SPARC_MODE_EXECUTION)
        !           895:          || (ic->_tme_sparc_itlb_busy == NULL));
        !           896: 
        !           897:   /* if we have a busy instruction TLB entry: */
        !           898:   tlb = ic->_tme_sparc_itlb_busy;
        !           899:   if (__tme_predict_true(tlb != NULL)) {
        !           900: 
        !           901:     /* unbusy the instruction TLB entry: */
        !           902:     tme_sparc_tlb_unbusy(tlb);
        !           903:   }
        !           904: }
        !           905: 
        !           906: /* this relocks data structures after a callout: */
        !           907: void
        !           908: tme_sparc_callout_relock(struct tme_sparc *ic)
        !           909: {
        !           910:   struct tme_sparc_tlb *tlb;
        !           911: 
        !           912:   assert ((ic->_tme_sparc_mode == TME_SPARC_MODE_EXECUTION)
        !           913:          || (ic->_tme_sparc_itlb_busy == NULL));
        !           914: 
        !           915:   /* if we have a busy instruction TLB entry: */
        !           916:   tlb = ic->_tme_sparc_itlb_busy;
        !           917:   if (__tme_predict_true(tlb != NULL)) {
        !           918: 
        !           919:     /* rebusy the instruction TLB entry: */
        !           920:     tme_sparc_tlb_busy(tlb);
        !           921:       
        !           922:     /* if this instruction TLB entry is invalid: */
        !           923:     if (tme_bus_tlb_is_invalid(&tlb->tme_sparc_tlb_bus_tlb)) {
        !           924: 
        !           925:       /* poison this instruction TLB entry, so we won't try to do any
        !           926:         fast fetches with it: */
        !           927:       tlb->tme_sparc_tlb_addr_first = 1;
        !           928:       tlb->tme_sparc_tlb_addr_last = 0;
        !           929:     }
        !           930:   }
        !           931: }
        !           932: 
        !           933: #if 0
        !           934: #include <stdio.h>
        !           935: 
        !           936: /* this dumps out the sparc state: */
        !           937: void
        !           938: tme_sparc32_dump(const struct tme_sparc *ic)
        !           939: {
        !           940:   unsigned int cwp_first;
        !           941:   unsigned int cwp;
        !           942:   unsigned int reg_i;
        !           943:   unsigned int reg_base;
        !           944:   unsigned int ireg;
        !           945: 
        !           946:   /* dump out the windowed integer registers, finishing with the
        !           947:      current window: */
        !           948:   cwp_first = TME_FIELD_MASK_EXTRACTU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_CWP);
        !           949:   cwp_first += TME_SPARC_NWINDOWS(ic) - 1;
        !           950:   cwp_first %= TME_SPARC_NWINDOWS(ic);
        !           951:   cwp = cwp_first;
        !           952:   do {
        !           953:     for (reg_i = 0; reg_i < 8; reg_i++) {
        !           954:       for (reg_base = 24; reg_base > 8; reg_base -= 8) {
        !           955:        
        !           956:        ireg = reg_base + reg_i + TME_SPARC_CWP_OFFSET(cwp);
        !           957:        if (ireg > (TME_SPARC_CWP_OFFSET(TME_SPARC_NWINDOWS(ic)) + 7)) {
        !           958:          ireg -= TME_SPARC_CWP_OFFSET(TME_SPARC_NWINDOWS(ic));
        !           959:        }
        !           960: 
        !           961:        fprintf(stderr,
        !           962:                "w%u.%%%c%u[%p] = 0x%08x ",
        !           963:                cwp,
        !           964:                (reg_base == 24
        !           965:                 ? 'i'
        !           966:                 : 'l'),
        !           967:                reg_i,
        !           968:                &ic->tme_sparc_ireg_uint32(ireg),
        !           969:                ic->tme_sparc_ireg_uint32(ireg));
        !           970:       }
        !           971:       fprintf(stderr, "\n");
        !           972:     }
        !           973:     cwp--;
        !           974:     cwp %= TME_SPARC_NWINDOWS(ic);
        !           975:   } while (cwp != cwp_first);
        !           976: 
        !           977:   /* dump out the global registers and the current window's output
        !           978:      registers: */
        !           979:   cwp = TME_FIELD_MASK_EXTRACTU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_CWP);
        !           980:   for (reg_i = 0; reg_i < 8; reg_i++) {
        !           981: 
        !           982:     ireg = reg_i;
        !           983:     fprintf(stderr,
        !           984:            "   %%g%u[%p] = 0x%08x ",
        !           985:            ireg,
        !           986:            &ic->tme_sparc_ireg_uint32(ireg),
        !           987:            ic->tme_sparc_ireg_uint32(ireg));
        !           988: 
        !           989:     ireg = 8 + reg_i + TME_SPARC_CWP_OFFSET(cwp);
        !           990:     if (ireg > (TME_SPARC_CWP_OFFSET(TME_SPARC_NWINDOWS(ic)) + 7)) {
        !           991:       ireg -= TME_SPARC_CWP_OFFSET(TME_SPARC_NWINDOWS(ic));
        !           992:     }
        !           993: 
        !           994:     fprintf(stderr,
        !           995:            "w%u.%%o%u[%p] = 0x%08x ",
        !           996:            cwp,
        !           997:            reg_i,
        !           998:            &ic->tme_sparc_ireg_uint32(ireg),
        !           999:            ic->tme_sparc_ireg_uint32(ireg));
        !          1000:     fprintf(stderr, "\n");
        !          1001:   }
        !          1002: 
        !          1003:   /* dump out the PCs: */
        !          1004:   fprintf(stderr, "%%pc = 0x%08x  %%pc_next = 0x%08x  %%pc_next_next = 0x%08x\n",
        !          1005:          ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC),
        !          1006:          ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT),
        !          1007:          ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC_NEXT_NEXT));
        !          1008: 
        !          1009:   /* dump out the PSR: */
        !          1010:   fprintf(stderr, "%%psr = 0x%08x", ic->tme_sparc32_ireg_psr);
        !          1011:   fprintf(stderr, "  cwp = %u",
        !          1012:          TME_FIELD_MASK_EXTRACTU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_CWP));
        !          1013:   fprintf(stderr, "  pil = 0x%x",
        !          1014:          TME_FIELD_MASK_EXTRACTU(ic->tme_sparc32_ireg_psr, TME_SPARC32_PSR_PIL));
        !          1015:   if (ic->tme_sparc32_ireg_psr & TME_SPARC32_PSR_ET) {
        !          1016:     fprintf(stderr, " ET");
        !          1017:   }
        !          1018:   fprintf(stderr, "  %c",
        !          1019:          (ic->tme_sparc32_ireg_psr & TME_SPARC32_PSR_S
        !          1020:           ? 'S'
        !          1021:           : 'U'));
        !          1022:   fprintf(stderr, "  flags:");
        !          1023:   if (ic->tme_sparc32_ireg_psr & TME_SPARC32_PSR_ICC_N) {
        !          1024:     fprintf(stderr, " N");
        !          1025:   }
        !          1026:   if (ic->tme_sparc32_ireg_psr & TME_SPARC32_PSR_ICC_Z) {
        !          1027:     fprintf(stderr, " Z");
        !          1028:   }
        !          1029:   if (ic->tme_sparc32_ireg_psr & TME_SPARC32_PSR_ICC_V) {
        !          1030:     fprintf(stderr, " V");
        !          1031:   }
        !          1032:   if (ic->tme_sparc32_ireg_psr & TME_SPARC32_PSR_ICC_C) {
        !          1033:     fprintf(stderr, " C");
        !          1034:   }
        !          1035:   fprintf(stderr, "\n");
        !          1036: 
        !          1037:   /* dump out the instruction and the WIM: */
        !          1038:   fprintf(stderr, "insn = 0x%08x %%wim = 0x%08x\n",
        !          1039:          ic->_tme_sparc_insn,
        !          1040:          ic->tme_sparc32_ireg_wim);
        !          1041: }
        !          1042: 
        !          1043: void
        !          1044: tme_sparc32_dump_memory(struct tme_sparc *ic, tme_uint32_t address, tme_uint32_t resid)
        !          1045: {
        !          1046:   tme_uint32_t address_display;
        !          1047:   struct tme_sparc_tlb *dtlb;
        !          1048:   tme_memory_atomic_flag_t tlb_busy_old;
        !          1049:   const tme_shared tme_uint8_t *memory;
        !          1050:   tme_uint32_t count;
        !          1051:   tme_uint32_t byte_i;
        !          1052: 
        !          1053:   /* we always display aligned rows: */
        !          1054:   address_display = address & (((tme_uint32_t) 0) - (sizeof(tme_uint32_t) * 2));
        !          1055:   resid += (address - address_display);
        !          1056: 
        !          1057:   /* while we have memory to dump: */
        !          1058:   for (; resid > 0; ) {
        !          1059: 
        !          1060:     /* get the DTLB entry, and busy it if it isn't already: */
        !          1061:     dtlb = TME_SPARC_DTLB_ENTRY(ic, address_display);
        !          1062:     tlb_busy_old = dtlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_busy;
        !          1063:     dtlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_busy = TRUE;
        !          1064: 
        !          1065:     /* read more data: */
        !          1066:     count = TME_MIN(resid, sizeof(tme_uint32_t) * 2);
        !          1067:     memory
        !          1068:       = tme_sparc32_load(ic,
        !          1069:                         address_display,
        !          1070:                         (sizeof(tme_uint32_t) * 2));
        !          1071: 
        !          1072:     /* restore the DTLB busy flag: */
        !          1073:     dtlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_busy = tlb_busy_old;
        !          1074: 
        !          1075:     /* display the row: */
        !          1076:     fprintf(stderr, "0x%08x ", address_display);
        !          1077:     for (byte_i = 0;
        !          1078:         byte_i < count;
        !          1079:         byte_i++, address_display++) {
        !          1080:       if (address_display < address) {
        !          1081:        fprintf(stderr, "   ");
        !          1082:       }
        !          1083:       else {
        !          1084:        fprintf(stderr, " %02x",
        !          1085:                memory[address_display]);
        !          1086:        address++;
        !          1087:       }
        !          1088:       resid--;
        !          1089:     }
        !          1090:     fputc('\n', stderr);
        !          1091:   }
        !          1092: }
        !          1093: #endif /* 1 */

unix.superglobalmegacorp.com

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