Annotation of tme/ic/sparc/sparc-misc.c, revision 1.1.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.