Annotation of tme/ic/m68k/m68k-misc.c, revision 1.1.1.2

1.1.1.2 ! root        1: /* $Id: m68k-misc.c,v 1.15 2003/10/25 17:08:01 fredette Exp $ */
1.1       root        2: 
1.1.1.2 ! root        3: /* ic/m68k/m68k-misc.c - miscellaneous things for the m68k emulator: */
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 2002, 2003 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:  */
1.1       root       35: 
                     36: /* includes: */
                     37: #include "m68k-impl.h"
                     38: 
1.1.1.2 ! root       39: _TME_RCSID("$Id: m68k-misc.c,v 1.15 2003/10/25 17:08:01 fredette Exp $");
1.1       root       40: 
                     41: /* small immediates: */
                     42: const tme_uint32_t _tme_m68k_imm32[9] = {
                     43:   0, 1, 2, 3, 4, 5, 6, 7, 8
                     44: };
                     45: const tme_uint16_t _tme_m68k_imm16[9] = {
                     46:   0, 1, 2, 3, 4, 5, 6, 7, 8
                     47: };
                     48: const tme_uint8_t _tme_m68k_imm8[9] = {
                     49:   0, 1, 2, 3, 4, 5, 6, 7, 8
                     50: };
                     51: 
                     52: /* the memory buffer read and write functions: */
                     53: #if TME_M68K_SIZE_8 != 1
                     54: #error "TME_M68K_SIZE_8 must be 1"
                     55: #endif
                     56: #if TME_M68K_SIZE_16 != 2
                     57: #error "TME_M68K_SIZE_16 must be 2"
                     58: #endif
                     59: #if TME_M68K_SIZE_32 != 4
                     60: #error "TME_M68K_SIZE_32 must be 4"
                     61: #endif
                     62: const _tme_m68k_xfer_memx _tme_m68k_read_memx[5] = {
                     63:   NULL,
                     64:   tme_m68k_read_memx8,
                     65:   tme_m68k_read_memx16,
                     66:   NULL,
                     67:   tme_m68k_read_memx32
                     68: };
                     69: const _tme_m68k_xfer_memx _tme_m68k_write_memx[5] = {
                     70:   NULL,
                     71:   tme_m68k_write_memx8,
                     72:   tme_m68k_write_memx16,
                     73:   NULL,
                     74:   tme_m68k_write_memx32
                     75: };
                     76: const _tme_m68k_xfer_mem _tme_m68k_read_mem[5] = {
                     77:   NULL,
                     78:   tme_m68k_read_mem8,
                     79:   tme_m68k_read_mem16,
                     80:   NULL,
                     81:   tme_m68k_read_mem32
                     82: };
                     83: const _tme_m68k_xfer_mem _tme_m68k_write_mem[5] = {
                     84:   NULL,
                     85:   tme_m68k_write_mem8,
                     86:   tme_m68k_write_mem16,
                     87:   NULL,
                     88:   tme_m68k_write_mem32
                     89: };
                     90: 
                     91: /* our bus signal handler: */
                     92: static int
                     93: _tme_m68k_bus_signal(struct tme_bus_connection *conn_bus, unsigned int signal)
                     94: {
                     95:   struct tme_m68k *ic;
                     96:   unsigned int level_edge;
                     97: 
                     98:   /* recover our IC: */
                     99:   ic = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
                    100: 
                    101:   /* take out the level and edge: */
                    102:   level_edge = signal & (TME_BUS_SIGNAL_LEVEL_MASK
                    103:                         | TME_BUS_SIGNAL_EDGE);
                    104:   signal &= ~(TME_BUS_SIGNAL_LEVEL_MASK
                    105:              | TME_BUS_SIGNAL_EDGE);
                    106: 
                    107:   /* lock the external mutex: */
                    108:   tme_mutex_lock(&ic->tme_m68k_external_mutex);
                    109: 
                    110:   /* on the falling edge of HALT or RESET, halt the processor: */
                    111:   if (level_edge == (TME_BUS_SIGNAL_LEVEL_ASSERTED
                    112:                     | TME_BUS_SIGNAL_EDGE)
                    113:       && (signal == TME_BUS_SIGNAL_HALT
                    114:          || signal == TME_BUS_SIGNAL_RESET)) {
                    115:     ic->tme_m68k_external_halt = TRUE;
                    116:   }
                    117: 
                    118:   /* on the rising edge of RESET, reset the processor: */
                    119:   else if (signal == TME_BUS_SIGNAL_RESET
                    120:           && level_edge == (TME_BUS_SIGNAL_LEVEL_NEGATED
                    121:                             | TME_BUS_SIGNAL_EDGE)) {
                    122:     ic->tme_m68k_external_reset = TRUE;
                    123:   }
                    124: 
                    125:   /* on any other HALT or RESET, do nothing: */
                    126:   else if (signal == TME_BUS_SIGNAL_RESET
                    127:           || signal == TME_BUS_SIGNAL_HALT) {
                    128:     /* nothing */
                    129:   }
                    130: 
                    131:   /* anything else: */
                    132:   else {
                    133:     abort();
                    134:   }
                    135: 
                    136:   /* unlock the external mutex: */
                    137:   tme_mutex_unlock(&ic->tme_m68k_external_mutex);
                    138: 
                    139:   /* notify any threads waiting on the external condition: */
                    140:   tme_cond_notify(&ic->tme_m68k_external_cond, TRUE);
                    141:   return (TME_OK);
                    142: }
                    143: 
                    144: /* our interrupt handler: */
                    145: static int
                    146: _tme_m68k_bus_interrupt(struct tme_m68k_bus_connection *conn_m68k, unsigned int ipl)
                    147: {
                    148:   struct tme_m68k *ic;
                    149: 
                    150:   /* recover our IC: */
                    151:   ic = conn_m68k->tme_m68k_bus_connection.tme_bus_connection.tme_connection_element->tme_element_private;
                    152: 
                    153:   /* lock the external mutex: */
                    154:   tme_mutex_lock(&ic->tme_m68k_external_mutex);
                    155: 
                    156:   /* set the interrupt line: */
                    157:   ic->tme_m68k_external_ipl = ipl;
                    158: 
                    159:   /* unlock the external mutex: */
                    160:   tme_mutex_unlock(&ic->tme_m68k_external_mutex);
                    161: 
                    162:   /* notify any threads waiting on the external condition: */
                    163:   tme_cond_notify(&ic->tme_m68k_external_cond, TRUE);
                    164:   return (TME_OK);
                    165: }
                    166: 
                    167: /* this checks for external signals.  this must be called with the
                    168:    external mutex held: */
                    169: void
                    170: tme_m68k_external_check(struct tme_m68k *ic, tme_uint32_t internal_exceptions)
                    171: {
                    172:   unsigned int ipl;
                    173:   int vector;
                    174:   int rc;
                    175: 
                    176:   /* if an external reset has been requested, start reset exception
                    177:      processing: */
                    178:   if (ic->tme_m68k_external_reset) {
                    179:     ic->tme_m68k_external_reset = FALSE;
                    180:     tme_mutex_unlock(&ic->tme_m68k_external_mutex);
                    181:     tme_m68k_exception(ic, TME_M68K_EXCEPTION_GROUP0_RESET);
                    182:   }
                    183: 
                    184:   /* if an external halt has been requested, halt: */
                    185:   if (ic->tme_m68k_external_halt) {
                    186:     ic->tme_m68k_external_halt = FALSE;
                    187:     tme_mutex_unlock(&ic->tme_m68k_external_mutex);
                    188:     ic->_tme_m68k_mode = TME_M68K_MODE_HALT;
                    189:     TME_M68K_SEQUENCE_START;
                    190:     tme_m68k_redispatch(ic);
                    191:   }
                    192: 
                    193:   /* if we are not halted, and an interrupt can be serviced, start
                    194:      interrupt exception processing: */
                    195:   ipl = ic->tme_m68k_external_ipl;
                    196:   if (ic->_tme_m68k_mode != TME_M68K_MODE_HALT
                    197:       && ipl >= TME_M68K_IPL_MIN
                    198:       && ipl <= TME_M68K_IPL_MAX
                    199:       && (ipl == TME_M68K_IPL_NMI
                    200:          || ipl > TME_M68K_FLAG_IPM(ic->tme_m68k_ireg_sr))) {
                    201:     tme_mutex_unlock(&ic->tme_m68k_external_mutex);
                    202:     
                    203:     /* acknowledge the interrupt and get the vector: */
                    204:     rc = (*ic->_tme_m68k_bus_connection->tme_m68k_bus_connection.tme_bus_intack)
                    205:       (&ic->_tme_m68k_bus_connection->tme_m68k_bus_connection,
                    206:        ipl, &vector);
                    207:     if (rc == TME_EDEADLK) {
                    208:       abort();
                    209:     }
                    210: 
                    211:     /* if the interrupt acknowledge failed, this is a spurious interrupt: */
                    212:     if (rc == ENOENT) {
                    213:       vector = 24;
                    214:     }
                    215: 
                    216:     /* if no vector is given, use the autovector: */
                    217:     else if (vector == TME_BUS_INTERRUPT_VECTOR_UNDEF) {
                    218:       vector = 24 + ipl;
                    219:     }
                    220: 
                    221:     /* dispatch the exceptions: */
                    222:     tme_m68k_exception(ic, internal_exceptions | TME_M68K_EXCEPTION_GROUP1_INT(ipl, vector));
                    223:   }
                    224: 
                    225:   /* if there are internal exceptions to process, do so: */
                    226:   if (internal_exceptions != 0) {
                    227:     tme_mutex_unlock(&ic->tme_m68k_external_mutex);
                    228:     tme_m68k_exception(ic, internal_exceptions);
                    229:   }
                    230: 
                    231:   /* there are no exceptions to process: */
                    232: }
                    233: 
                    234: /* the idle function, used when the processor is halted or stopped: */
                    235: static void
                    236: tme_m68k_idle(struct tme_m68k *ic)
                    237: {  
                    238:   /* lock the external mutex: */
                    239:   tme_mutex_lock(&ic->tme_m68k_external_mutex);
                    240: 
                    241:   /* loop forever: */
                    242:   for (;;) {
                    243: 
                    244:     /* check for any external signal: */
                    245:     tme_m68k_external_check(ic, 0);
                    246: 
                    247:     /* await an external condition: */
                    248:     tme_cond_wait_yield(&ic->tme_m68k_external_cond, &ic->tme_m68k_external_mutex);
                    249:   }
                    250: }
                    251: 
                    252: /* the m68k thread: */
                    253: static void
                    254: tme_m68k_thread(struct tme_m68k *ic)
                    255: {
                    256: 
                    257:   /* we use longjmp to redispatch: */
                    258:   do { } while (setjmp(ic->_tme_m68k_dispatcher));
                    259: 
                    260:   /* dispatch on the current mode: */
                    261:   switch (ic->_tme_m68k_mode) {
                    262: 
                    263:   case TME_M68K_MODE_EXECUTION:
                    264:     (*ic->_tme_m68k_mode_execute)(ic);
                    265:     /* NOTREACHED */
                    266: 
                    267:   case TME_M68K_MODE_EXCEPTION:
                    268:     (*ic->_tme_m68k_mode_exception)(ic);
                    269:     /* NOTREACHED */
                    270: 
                    271:   case TME_M68K_MODE_RTE:
                    272:     (*ic->_tme_m68k_mode_rte)(ic);
                    273:     /* NOTREACHED */
                    274: 
                    275:   case TME_M68K_MODE_STOP:
                    276:   case TME_M68K_MODE_HALT:
                    277:     tme_m68k_idle(ic);
                    278:     /* NOTREACHED */
                    279: 
                    280:   default:
                    281:     abort();
                    282:   }
                    283:   /* NOTREACHED */
                    284: }
                    285: 
                    286: /* the TLB filler for when we are on a generic bus: */
                    287: static int
                    288: _tme_m68k_generic_tlb_fill(struct tme_m68k_bus_connection *conn_m68k, 
                    289:                           struct tme_m68k_tlb *tlb,
                    290:                           unsigned int function_code, 
                    291:                           tme_uint32_t external_address, 
                    292:                           unsigned int cycles)
                    293: {
                    294:   struct tme_m68k *ic;
                    295: 
                    296:   /* recover our IC: */
                    297:   ic = conn_m68k->tme_m68k_bus_connection.tme_bus_connection.tme_connection_element->tme_element_private;
                    298: 
                    299:   /* call the generic bus TLB filler: */
                    300:   (ic->_tme_m68k_bus_generic->tme_bus_tlb_fill)
                    301:     (ic->_tme_m68k_bus_generic,
                    302:      &tlb->tme_m68k_tlb_bus_tlb,
                    303:      external_address,
                    304:      cycles);
                    305:   
                    306:   /* when we're on a generic bus a TLB entry is valid for all function codes: */
                    307:   tlb->tme_m68k_tlb_function_codes_mask = -1;
                    308: 
                    309:   return (TME_OK);
                    310: }
                    311: 
                    312: /* the connection scorer: */
                    313: static int
                    314: _tme_m68k_connection_score(struct tme_connection *conn, unsigned int *_score)
                    315: {
                    316:   struct tme_m68k_bus_connection *conn_m68k;
                    317:   struct tme_bus_connection *conn_bus;
                    318:   unsigned int score;
                    319: 
                    320:   /* assume that this connection is useless: */
                    321:   score = 0;
                    322: 
                    323:   /* dispatch on the connection type: */
                    324:   conn_m68k = (struct tme_m68k_bus_connection *) conn->tme_connection_other;
                    325:   conn_bus = (struct tme_bus_connection *) conn->tme_connection_other;
                    326:   switch (conn->tme_connection_type) {
                    327: 
                    328:     /* this must be a bus, and not another m68k chip: */
                    329:   case TME_CONNECTION_BUS_M68K:
                    330:     if (conn_bus->tme_bus_tlb_set_allocate != NULL
                    331:        && conn_m68k->tme_m68k_bus_tlb_fill != NULL) {
                    332:       score = 10;
                    333:     }
                    334:     break;
                    335: 
                    336:     /* this must be a bus, and not another chip: */
                    337:   case TME_CONNECTION_BUS_GENERIC:
                    338:     if (conn_bus->tme_bus_tlb_set_allocate != NULL
                    339:        && conn_bus->tme_bus_tlb_fill != NULL) {
                    340:       score = 1;
                    341:     }
                    342:     break;
                    343: 
                    344:   default: abort();
                    345:   }
                    346: 
                    347:   *_score = score;
                    348:   return (TME_OK);
                    349: }
                    350: 
                    351: /* this makes a new connection: */
                    352: static int
                    353: _tme_m68k_connection_make(struct tme_connection *conn, unsigned int state)
                    354: {
                    355:   struct tme_m68k *ic;
                    356:   struct tme_m68k_bus_connection *conn_m68k;
                    357:   struct tme_bus_connection *conn_bus;
                    358:   struct tme_connection *conn_other;
                    359: 
                    360:   /* since the CPU is halted, it won't be making any connection calls,
                    361:      so we only have to do work when the connection is fully made: */
                    362:   if (state == TME_CONNECTION_FULL) {
                    363: 
                    364:     /* recover our IC: */
                    365:     ic = conn->tme_connection_element->tme_element_private;
                    366:     
                    367:     /* dispatch on the connection type: */
                    368:     conn_other = conn->tme_connection_other;
                    369:     conn_m68k = (struct tme_m68k_bus_connection *) conn_other;
                    370:     conn_bus = (struct tme_bus_connection *) conn_other;
                    371:     switch (conn->tme_connection_type) {
                    372:       
                    373:     case TME_CONNECTION_BUS_M68K:
                    374:       ic->_tme_m68k_bus_connection = conn_m68k;
                    375:       break;
                    376:       
                    377:       /* we need an adaptation layer: */
                    378:     case TME_CONNECTION_BUS_GENERIC:
                    379:       conn_m68k = tme_new0(struct tme_m68k_bus_connection, 1);
                    380:       conn_m68k->tme_m68k_bus_connection.tme_bus_connection.tme_connection_element = conn->tme_connection_element;
                    381:       conn_m68k->tme_m68k_bus_tlb_fill = _tme_m68k_generic_tlb_fill;
                    382:       ic->_tme_m68k_bus_connection = conn_m68k;
                    383:       ic->_tme_m68k_bus_generic = conn_bus;
                    384:       break;
                    385:       
                    386:     default: abort();
                    387:     }
                    388: 
                    389:     /* allocate the TLB hash set: */
                    390:     (*ic->_tme_m68k_bus_connection->tme_m68k_bus_connection.tme_bus_tlb_set_allocate)
                    391:       (&ic->_tme_m68k_bus_connection->tme_m68k_bus_connection, 
                    392:        _TME_M68K_TLB_HASH_SIZE, 
                    393:        sizeof(struct tme_m68k_tlb),
                    394:        TME_ATOMIC_POINTER((struct tme_bus_tlb **) &ic->_tme_m68k_tlb_array));
                    395: 
                    396:     /* allocate the ITLB set: */
                    397:     (*ic->_tme_m68k_bus_connection->tme_m68k_bus_connection.tme_bus_tlb_set_allocate)
                    398:       (&ic->_tme_m68k_bus_connection->tme_m68k_bus_connection, 
                    399:        1, 
                    400:        sizeof(struct tme_m68k_tlb),
                    401:        TME_ATOMIC_POINTER((struct tme_bus_tlb **) &ic->_tme_m68k_itlb));
                    402:   }
                    403: 
                    404:   /* NB: the machine needs to issue a reset to bring the CPU out of halt. */
                    405:   return (TME_OK);
                    406: }
                    407: 
                    408: /* this breaks a connection: */
                    409: static int 
                    410: _tme_m68k_connection_break(struct tme_connection *conn, unsigned int state)
                    411: {
                    412:   abort();
                    413: }
                    414: 
                    415: /* this makes new connection sides: */
                    416: static int
                    417: _tme_m68k_connections_new(struct tme_element *element, const char * const *args, struct tme_connection **_conns, char **_output)
                    418: {
                    419:   struct tme_m68k_bus_connection *conn_m68k;
                    420:   struct tme_bus_connection *conn_bus;
                    421:   struct tme_connection *conn;
                    422: 
                    423:   /* if we already have a bus connection, we can take no more connections: */
                    424:   if (((struct tme_m68k *) element->tme_element_private)->_tme_m68k_bus_connection != NULL) {
                    425:     return (TME_OK);
                    426:   }
                    427: 
                    428:   /* create our side of an m68k bus connection: */
                    429:   conn_m68k = tme_new0(struct tme_m68k_bus_connection, 1);
                    430:   conn_bus = &conn_m68k->tme_m68k_bus_connection;
                    431:   conn = &conn_bus->tme_bus_connection;
                    432: 
                    433:   /* fill in the generic connection: */
                    434:   conn->tme_connection_next = *_conns;
                    435:   conn->tme_connection_type = TME_CONNECTION_BUS_M68K;
                    436:   conn->tme_connection_score = _tme_m68k_connection_score;
                    437:   conn->tme_connection_make = _tme_m68k_connection_make;
                    438:   conn->tme_connection_break = _tme_m68k_connection_break;
                    439: 
                    440:   /* fill in the generic bus connection: */
                    441:   conn_bus->tme_bus_signal = _tme_m68k_bus_signal;
                    442:   conn_bus->tme_bus_tlb_set_allocate = NULL;
                    443: 
                    444:   /* full in the m68k bus connection: */
                    445:   conn_m68k->tme_m68k_bus_interrupt = _tme_m68k_bus_interrupt;
                    446:   conn_m68k->tme_m68k_bus_tlb_fill = NULL;
                    447: 
                    448:   /* add this connection to the set of possibilities: */
                    449:   *_conns = conn;
                    450: 
                    451:   /* create our side of a generic bus connection: */
                    452:   conn_bus = tme_new0(struct tme_bus_connection, 1);
                    453:   conn = &conn_bus->tme_bus_connection;
                    454: 
                    455:   /* fill in the generic connection: */
                    456:   conn->tme_connection_next = *_conns;
                    457:   conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC;
                    458:   conn->tme_connection_score = _tme_m68k_connection_score;
                    459:   conn->tme_connection_make = _tme_m68k_connection_make;
                    460:   conn->tme_connection_break = _tme_m68k_connection_break;
                    461: 
                    462:   /* fill in the generic bus connection: */
                    463:   conn_bus->tme_bus_signal = _tme_m68k_bus_signal;
                    464:   conn_bus->tme_bus_tlb_set_allocate = NULL;
                    465:   conn_bus->tme_bus_tlb_fill = NULL;
                    466: 
                    467:   /* add this connection to the set of possibilities: */
                    468:   *_conns = conn;
                    469: 
                    470:   /* done: */
                    471:   return (TME_OK);
                    472: }
                    473: 
                    474: /* the common m68k new function: */
                    475: int
                    476: tme_m68k_new(struct tme_m68k *ic, const char * const *args, const void *extra, char **_output)
                    477: {
                    478:   struct tme_element *element;
                    479: 
                    480:   /* we take no arguments: */
                    481:   if (args[1] != NULL) {
                    482:     tme_output_append_error(_output,
                    483:                            "%s %s, %s %s",
                    484:                            args[1],
                    485:                            _("unexpected"),
                    486:                            _("usage:"),
                    487:                            args[0]);
                    488:     tme_free(ic);
                    489:     return (EINVAL);
                    490:   }
                    491: 
                    492:   /* initialize the verifier: */
                    493:   tme_m68k_verify_init();
                    494: 
                    495:   /* dispatch on the type: */
                    496:   switch (ic->tme_m68k_type) {
                    497:   case TME_M68K_M68000:
                    498:     ic->_tme_m68k_bus_16bit = TRUE;
                    499:     break;
                    500:   case TME_M68K_M68010:
                    501:     ic->_tme_m68k_bus_16bit = TRUE;
                    502:     break;
                    503:   case TME_M68K_M68020:
                    504:     ic->_tme_m68k_bus_16bit = FALSE;
                    505:     break;
                    506:   default:
                    507:     abort();
                    508:   }
                    509: 
                    510:   /* we have no bus connection yet: */
                    511:   ic->_tme_m68k_bus_connection = NULL;
                    512: 
                    513:   /* fill the element: */
                    514:   element = ic->tme_m68k_element;
                    515:   element->tme_element_private = ic;
                    516:   element->tme_element_connections_new = _tme_m68k_connections_new;
                    517: 
                    518:   /* calculate the instruction burst size: */
                    519:   /* XXX TBD: */
                    520:   ic->_tme_m68k_instruction_burst = 20;
1.1.1.2 ! root      521:   ic->_tme_m68k_instruction_burst_remaining
        !           522:     = ic->_tme_m68k_instruction_burst;
1.1       root      523: 
                    524:   /* force the processor to be halted: */
                    525:   ic->_tme_m68k_mode = TME_M68K_MODE_HALT;
                    526:   TME_M68K_SEQUENCE_START;
                    527: 
                    528:   /* start the m68k thread: */
                    529:   tme_thread_create((tme_thread_t) tme_m68k_thread, ic);
                    530: 
                    531:   return (TME_OK);
                    532: }  
                    533: 
                    534: /* the common m68k reset function: */
                    535: void
                    536: tme_m68k_do_reset(struct tme_m68k *ic)
                    537: {
                    538:   
                    539:   /* force the VBR to zero: */
                    540:   ic->tme_m68k_ireg_vbr = 0;
                    541: 
                    542:   /* force supervisor mode, interrupts disabled: */
                    543:   tme_m68k_change_sr(ic, TME_M68K_FLAG_S | (7 << 8));
                    544: 
                    545:   /* load the initial SSP and PC: */
                    546:   ic->_tme_m68k_ea_function_code = TME_M68K_FC_SD;
                    547:   ic->_tme_m68k_ea_address = 0;
                    548:   tme_m68k_read_mem32(ic, TME_M68K_IREG_A7);
                    549:   ic->_tme_m68k_ea_address += sizeof(ic->tme_m68k_ireg_a7);
                    550:   tme_m68k_read_mem32(ic, TME_M68K_IREG_PC);
                    551: 
                    552:   /* clear all exceptions: */
                    553:   ic->_tme_m68k_exceptions = 0;
                    554: 
                    555:   /* start execution: */
                    556:   ic->_tme_m68k_mode = TME_M68K_MODE_EXECUTION;
                    557:   TME_M68K_SEQUENCE_START;
                    558:   tme_m68k_redispatch(ic);
                    559: }
                    560: 
                    561: /* this returns nonzero iff the slow instruction executor must be
                    562:    used: */
                    563: int
                    564: tme_m68k_go_slow(const struct tme_m68k *ic)
                    565: {
                    566:   struct tme_m68k_tlb *tlb;
                    567:   tme_uint32_t linear_pc;
                    568: 
                    569:   tlb = TME_ATOMIC_READ(struct tme_m68k_tlb *, ic->_tme_m68k_itlb);
                    570:   linear_pc = ic->tme_m68k_ireg_pc;
                    571:   return (
                    572:          
                    573:          /* the ITLB entry must support reads from emulator memory: */
                    574:          !TME_M68K_TLB_OK_FAST_READ(tlb, 
                    575:                                     TME_M68K_FUNCTION_CODE_PROGRAM(ic),
                    576:                                     linear_pc,
                    577:                                     linear_pc)
                    578: 
                    579:          /* the ITLB emulator memory must be 32-bit aligned for the
                    580:             benefit of the fast instruction word fetch macros, so
                    581:             that emulator address alignment goes with linear address
                    582:             alignment: */
                    583:          || (((unsigned long) tlb->tme_m68k_tlb_emulator_off_read)
                    584:              & (sizeof(tme_uint32_t) - 1))
                    585: 
                    586:          /* the linear PC must be 16-bit aligned: */
                    587:          || (linear_pc & 1)
                    588: 
                    589:          /* there must be no tracing: */
                    590:          || TME_M68K_FLAG_T(ic->tme_m68k_ireg_sr) != 0);
                    591: }
                    592: 
                    593: /* this redispatches: */
                    594: void
                    595: tme_m68k_redispatch(struct tme_m68k *ic)
                    596: {
                    597:   longjmp(ic->_tme_m68k_dispatcher, 1);
                    598: }
                    599: 
                    600: /* this fills a TLB entry: */
                    601: void
                    602: tme_m68k_tlb_fill(struct tme_m68k *ic, struct tme_m68k_tlb *tlb, 
                    603:                  unsigned int function_code, 
                    604:                  tme_uint32_t linear_address, 
                    605:                  unsigned int cycles)
                    606: {
                    607:   tme_uint32_t external_address;
                    608:   struct tme_bus_tlb tlb_internal;
                    609:   
                    610:   /* when emulating a CPU with a 16-bit bus, only 24 bits of address
                    611:      are external: */
                    612:   external_address = linear_address;
                    613:   if (ic->_tme_m68k_bus_16bit) {
                    614:     external_address &= 0x00ffffff;
                    615:   }
                    616: 
                    617:   /* fill the TLB entry: */
                    618:   (*ic->_tme_m68k_bus_connection->tme_m68k_bus_tlb_fill)
                    619:     (ic->_tme_m68k_bus_connection, tlb,
                    620:      function_code,
                    621:      external_address,
                    622:      cycles);
                    623: 
                    624:   /* if this code isn't 32-bit clean, we have to deal: */
                    625:   if (external_address != linear_address) {
                    626:     TME_ATOMIC_WRITE(tme_bus_addr_t, tlb_internal.tme_bus_tlb_addr_first,
                    627:                     TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_m68k_tlb_linear_first)
                    628:                     | (linear_address ^ external_address));
                    629:     TME_ATOMIC_WRITE(tme_bus_addr_t, tlb_internal.tme_bus_tlb_addr_last,
                    630:                     TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_m68k_tlb_linear_last)
                    631:                     | (linear_address ^ external_address));
                    632:     tlb_internal.tme_bus_tlb_cycles_ok = tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycles_ok;
                    633:     tme_bus_tlb_map(&tlb->tme_m68k_tlb_bus_tlb, external_address,
                    634:                    &tlb_internal, linear_address);
                    635:   }
                    636: }
                    637: 
                    638: /* this triggers exception processing: */
                    639: void
                    640: tme_m68k_exception(struct tme_m68k *ic, tme_uint32_t new_exceptions)
                    641: {
                    642:   assert(new_exceptions != 0);
                    643: 
                    644:   /* if the set of new exceptions includes a group zero exception: */
                    645:   if (new_exceptions & 
                    646:       (TME_M68K_EXCEPTION_GROUP0_RESET
                    647:        | TME_M68K_EXCEPTION_GROUP0_AERR
                    648:        | TME_M68K_EXCEPTION_GROUP0_BERR)) {
                    649:     
                    650:     /* there must be only one exception - you cannot trigger a group 0
                    651:        exception simultaneously with any other group 0, 1, or 2
                    652:        exception: */
                    653:     assert((new_exceptions & (new_exceptions - 1)) == 0);
                    654:     
                    655:     /* if this is a reset exception, it clears all other exceptions: */
                    656:     if (new_exceptions == TME_M68K_EXCEPTION_GROUP0_RESET) {
                    657:       ic->_tme_m68k_exceptions = 0;
                    658:     }
                    659: 
                    660:     /* otherwise, this is an address error or a bus error.  if we were
                    661:        already processing a group 0 exception, this is a
                    662:        double fault, and the processor enters the halted state: */
                    663:     else if (ic->_tme_m68k_exceptions &
                    664:             (TME_M68K_EXCEPTION_GROUP0_RESET
                    665:              | TME_M68K_EXCEPTION_GROUP0_AERR
                    666:              | TME_M68K_EXCEPTION_GROUP0_BERR)) {
                    667:       ic->_tme_m68k_mode = TME_M68K_MODE_HALT;
                    668:       TME_M68K_SEQUENCE_START;
                    669:       tme_m68k_redispatch(ic);
                    670:     }
                    671:   }
                    672: 
                    673:   /* otherwise, exception processing must not already be happening: */
                    674:   else {
                    675:     assert(ic->_tme_m68k_exceptions == 0);
                    676:   }
                    677: 
                    678:   /* begin exception processing: */
                    679:   ic->_tme_m68k_exceptions |= new_exceptions;
                    680:   ic->_tme_m68k_mode = TME_M68K_MODE_EXCEPTION;
                    681:   TME_M68K_SEQUENCE_START;
                    682:   tme_m68k_redispatch(ic);
                    683: }
                    684: 
                    685: /* this changes SR, and swaps %a7 as needed: */
                    686: void
                    687: tme_m68k_change_sr(struct tme_m68k *ic, tme_uint16_t sr)
                    688: {
                    689:   
                    690:   /* save %a7 in the proper stack pointer control register: */
                    691:   switch (ic->tme_m68k_ireg_sr & (TME_M68K_FLAG_S | TME_M68K_FLAG_M)) {
                    692:   case 0:
                    693:   case TME_M68K_FLAG_M:
                    694:     ic->tme_m68k_ireg_usp = ic->tme_m68k_ireg_a7;
                    695:     break;
                    696:   case TME_M68K_FLAG_S:
                    697:     ic->tme_m68k_ireg_msp = ic->tme_m68k_ireg_a7;
                    698:     break;
                    699:   case (TME_M68K_FLAG_S | TME_M68K_FLAG_M):
                    700:     ic->tme_m68k_ireg_isp = ic->tme_m68k_ireg_a7;
                    701:     break;
                    702:   }
                    703: 
                    704:   /* load %a7 from the proper stack pointer control register: */
                    705:   ic->tme_m68k_ireg_sr = sr;
                    706:   switch (ic->tme_m68k_ireg_sr & (TME_M68K_FLAG_S | TME_M68K_FLAG_M)) {
                    707:   case 0:
                    708:   case TME_M68K_FLAG_M:
                    709:     ic->tme_m68k_ireg_a7 = ic->tme_m68k_ireg_usp;
                    710:     break;
                    711:   case TME_M68K_FLAG_S:
                    712:     ic->tme_m68k_ireg_a7 = ic->tme_m68k_ireg_msp;
                    713:     break;
                    714:   case (TME_M68K_FLAG_S | TME_M68K_FLAG_M):
                    715:     ic->tme_m68k_ireg_a7 = ic->tme_m68k_ireg_isp;
                    716:     break;
                    717:   }
                    718: }
                    719: 
                    720: /* this starts processing an m68k exception: */
                    721: void
                    722: tme_m68k_exception_process_start(struct tme_m68k *ic, unsigned int ipl)
                    723: {
                    724:   tme_uint16_t sr;
                    725: 
                    726:   /* make an internal copy of the status register, then set S, clear
                    727:      T, and update I: */
                    728:   if (!TME_M68K_SEQUENCE_RESTARTING) {
                    729:     ic->tme_m68k_ireg_shadow_sr = ic->tme_m68k_ireg_sr;
1.1.1.2 ! root      730:     sr = (ic->tme_m68k_ireg_sr | TME_M68K_FLAG_S) & ~(0x3 << 14);
1.1       root      731:     if (ipl > TME_M68K_IPL_NONE) {
                    732:       assert(ipl == TME_M68K_IPL_NMI
                    733:             || ipl > TME_M68K_FLAG_IPM(sr));
                    734:       sr = (sr & ~(TME_M68K_IPL_MAX << 8)) | (ipl << 8);
                    735:     }
                    736:     tme_m68k_change_sr(ic, sr);
                    737:   }
                    738: }
                    739: 
                    740: /* this finishes processing an m68k exception: */
                    741: void
                    742: tme_m68k_exception_process_finish(struct tme_m68k *ic, tme_uint8_t format, tme_uint8_t vector)
                    743: {
                    744:   tme_uint16_t vector_offset;
                    745: 
                    746:   /* stack the frame format and vector offset, unless this is a 68000: */
                    747:   vector_offset = ((tme_uint16_t) vector) << 2;
                    748:   if (ic->tme_m68k_type != TME_M68K_M68000) {
                    749:     tme_m68k_push16(ic, (((tme_uint16_t) format) << 12) | vector_offset);
                    750:   }
                    751: 
                    752:   /* stack the program counter: */
                    753:   tme_m68k_push32(ic, ic->tme_m68k_ireg_pc);
                    754:   
                    755:   /* stack the internal copy of the status register: */
                    756:   tme_m68k_push16(ic, ic->tme_m68k_ireg_shadow_sr);
                    757: 
                    758:   /* do a bus cycle to read the vector into the program counter: */
                    759:   if (!TME_M68K_SEQUENCE_RESTARTING) {
                    760:     ic->_tme_m68k_ea_function_code = TME_M68K_FC_SD; /* XXX is this right? */
                    761:     ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_vbr + vector_offset;
                    762:   }
                    763:   tme_m68k_read_mem32(ic, TME_M68K_IREG_PC);
                    764: }
                    765: 
                    766: /* common m68k exception processing: */
                    767: void
                    768: tme_m68k_exception_process(struct tme_m68k *ic)
                    769: {
                    770:   tme_uint32_t exceptions;
                    771: 
                    772:   /* get the set of exceptions.  we must have no group 0 exceptions: */
                    773:   exceptions = ic->_tme_m68k_exceptions;
                    774:   assert((exceptions & (TME_M68K_EXCEPTION_GROUP0_RESET
                    775:                        | TME_M68K_EXCEPTION_GROUP0_AERR
                    776:                        | TME_M68K_EXCEPTION_GROUP0_BERR)) == 0);
                    777: 
                    778:   /* these if statements are ordered to implement the priority
                    779:      relationship between the different exceptions as outlined in 
                    780:      the 68000 user's manual (pp 93 in my copy): */
                    781:   
                    782:   if (TME_M68K_EXCEPTION_IS_GROUP2(exceptions)) {
                    783:     tme_m68k_exception_process_start(ic, 0);
                    784:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, TME_M68K_EXCEPTION_IS_GROUP2(exceptions));
                    785:   }
                    786:   
                    787:   if (exceptions & TME_M68K_EXCEPTION_GROUP1_TRACE) {
                    788:     tme_m68k_exception_process_start(ic, 0);
                    789:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, 0x09);
                    790:   }
                    791:   
                    792:   if (TME_M68K_EXCEPTION_IS_GROUP1_INT(exceptions)) {
                    793:     tme_m68k_exception_process_start(ic, TME_M68K_EXCEPTION_IS_GROUP1_INT(exceptions));
                    794:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, TME_M68K_EXCEPTION_GROUP1_INT_VEC(exceptions));
                    795:   }
                    796:   
                    797:   if (exceptions & TME_M68K_EXCEPTION_GROUP1_ILL) {
                    798:     tme_m68k_exception_process_start(ic, 0);
                    799:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, 0x04);
                    800:   }
                    801:   
                    802:   if (exceptions & TME_M68K_EXCEPTION_GROUP1_PRIV) {
                    803:     tme_m68k_exception_process_start(ic, 0);
                    804:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, 0x08);
                    805:   }
                    806:   
                    807:   /* we have processed all exceptions - resume execution: */
                    808:   ic->_tme_m68k_exceptions = 0;
                    809:   ic->_tme_m68k_mode = TME_M68K_MODE_EXECUTION;
                    810:   TME_M68K_SEQUENCE_START;
                    811:   tme_m68k_redispatch(ic);
                    812: }
                    813: 
                    814: /* this starts an m68k RTE: */
                    815: tme_uint16_t
                    816: tme_m68k_rte_start(struct tme_m68k *ic)
                    817: {
                    818: 
                    819:   /* set up to read from the stack frame: */
                    820:   ic->_tme_m68k_ea_function_code = TME_M68K_FC_SD;
                    821:   ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_a7;
                    822: 
                    823:   /* read the stacked status register: */
                    824:   tme_m68k_read_mem16(ic, TME_M68K_IREG_SHADOW_SR);
                    825:   ic->_tme_m68k_ea_address += sizeof(ic->tme_m68k_ireg_shadow_sr);
                    826: 
                    827:   /* read the stacked PC: */
                    828:   tme_m68k_read_mem32(ic, TME_M68K_IREG_PC_NEXT);
                    829:   ic->_tme_m68k_ea_address += sizeof(ic->tme_m68k_ireg_pc_next);
                    830: 
                    831:   /* read the stacked format/offset word, unless this is a 68000: */
                    832:   if (ic->tme_m68k_type != TME_M68K_M68000) {
                    833:     tme_m68k_read_mem16(ic, TME_M68K_IREG_FORMAT_OFFSET);
                    834:     ic->_tme_m68k_ea_address += sizeof(ic->tme_m68k_ireg_format_offset);
                    835:   }
                    836:   else {
                    837:     ic->tme_m68k_ireg_format_offset = 0;
                    838:   }
                    839: 
                    840:   /* return the frame format: */
                    841:   return (ic->tme_m68k_ireg_format_offset >> 12);
                    842: }
                    843: 
                    844: /* this finishes an m68k RTE: */
                    845: void
                    846: tme_m68k_rte_finish(struct tme_m68k *ic, tme_uint32_t format_extra)
                    847: {
                    848:   tme_uint32_t frame_size;
                    849: 
                    850:   /* calculate the total frame size.  the 68000 doesn't have a
                    851:      format/status word: */
                    852:   frame_size = (sizeof(ic->tme_m68k_ireg_shadow_sr)
                    853:                + sizeof(ic->tme_m68k_ireg_pc_next)
                    854:                + (ic->tme_m68k_type != TME_M68K_M68000
                    855:                   ? sizeof(ic->tme_m68k_ireg_format_offset)
                    856:                   : 0)
                    857:                + format_extra);
                    858:   assert((frame_size & 1) == 0);
                    859: 
                    860:   /* adjust the stack: */
                    861:   ic->tme_m68k_ireg_a7 += frame_size;
                    862:   
                    863:   /* set the status register: */
                    864:   tme_m68k_change_sr(ic, ic->tme_m68k_ireg_shadow_sr);
                    865:                     
                    866:   /* set the PC: */
                    867:   ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
                    868:   
                    869:   /* redispatch: */
                    870:   tme_m68k_redispatch(ic);
                    871: }
                    872: 
                    873: /* this stores the group 0 sequence into a region of host memory.
                    874:    this is used when preparing the state information to be stored
                    875:    on the stack for a bus or address error: */
                    876: int
                    877: tme_m68k_sequence_empty(const struct tme_m68k *ic, tme_uint8_t *raw, unsigned int raw_avail)
                    878: {
                    879:   const struct _tme_m68k_sequence *sequence;
                    880:   unsigned int raw_used;
                    881:   
                    882:   /* get the group 0 sequence: */
                    883:   sequence = &ic->_tme_m68k_group0_sequence;
                    884:   raw_used = 0;
                    885: 
                    886:   /* we use 8 bits for the mode (2 bits) and flags (6 bits): */
                    887:   raw_used += sizeof(tme_uint8_t);
                    888:   assert(raw_avail >= raw_used);
                    889:   assert(sequence->_tme_m68k_sequence_mode < TME_BIT(2));
                    890:   assert(sequence->_tme_m68k_sequence_mode_flags < TME_BIT(6));
                    891:   *(raw++) = ((sequence->_tme_m68k_sequence_mode << 6)
                    892:              | sequence->_tme_m68k_sequence_mode_flags);
                    893:   
                    894: 
                    895:   /* we use 16 bits for the faulted memory transfer ordinal
                    896:      (12 bits) and already-transferred byte count (4 bits): */
                    897:   raw_used += sizeof(tme_uint16_t);
                    898:   assert(raw_avail >= raw_used);
                    899:   assert(sequence->_tme_m68k_sequence_transfer_faulted < TME_BIT(12));
                    900:   assert(sequence->_tme_m68k_sequence_transfer_faulted_after < TME_BIT(4));
                    901:   *(raw++) = sequence->_tme_m68k_sequence_transfer_faulted >> 4;
                    902:   *(raw++) = ((sequence->_tme_m68k_sequence_transfer_faulted << 4)
                    903:              | sequence->_tme_m68k_sequence_transfer_faulted_after);
                    904: 
                    905: #ifdef _TME_M68K_VERIFY
                    906:   /* we use sizeof(_tme_m68k_sequence_uid) bytes for the sequence UID: */
                    907:   raw_used += sizeof(sequence->_tme_m68k_sequence_uid);
                    908:   assert(raw_avail >= raw_used);
                    909:   memcpy(raw,
                    910:         &sequence->_tme_m68k_sequence_uid,
                    911:         sizeof(sequence->_tme_m68k_sequence_uid));
                    912:   raw += sizeof(sequence->_tme_m68k_sequence_uid);
                    913: #endif /* _TME_M68K_VERIFY */
                    914: 
                    915:   /* done: */
                    916:   return (raw_used);
                    917: }
                    918: 
                    919: /* this restores the group 0 sequence from a region of host memory.
                    920:    this is used when reading the state information stored on the
                    921:    stack for a bus or address error: */
                    922: int
                    923: tme_m68k_sequence_fill(struct tme_m68k *ic, const tme_uint8_t *raw, unsigned int raw_avail)
                    924: {
                    925:   struct _tme_m68k_sequence *sequence;
                    926:   unsigned int raw_used;
                    927:   
                    928:   /* get the group 0 sequence: */
                    929:   sequence = &ic->_tme_m68k_group0_sequence;
                    930:   raw_used = 0;
                    931: 
                    932:   /* we used 8 bits for the mode (2 bits) and flags (6 bits): */
                    933:   raw_used += sizeof(tme_uint8_t);
                    934:   if (raw_avail < raw_used) {
                    935:     return (-1);
                    936:   }
                    937:   sequence->_tme_m68k_sequence_mode = *raw >> 6;
                    938:   sequence->_tme_m68k_sequence_mode_flags = (*(raw++) & (TME_BIT(6) - 1));
                    939: 
                    940:   /* we used 16 bits for the faulted memory transfer ordinal
                    941:      (12 bits) and already-transferred byte count (4 bits): */
                    942:   raw_used += sizeof(tme_uint16_t);
                    943:   if (raw_avail < raw_used) {
                    944:     return (-1);
                    945:   }
                    946:   sequence->_tme_m68k_sequence_transfer_faulted = 
                    947:     (((tme_uint16_t) raw[0]) << 4)
                    948:     | (raw[1] >> 4);
                    949:   sequence->_tme_m68k_sequence_transfer_faulted_after = raw[1] & (TME_BIT(4) - 1);
                    950:   raw += sizeof(tme_uint16_t);
                    951: 
                    952: #ifdef _TME_M68K_VERIFY
                    953:   /* we used sizeof(_tme_m68k_sequence_uid) bytes for the sequence UID: */
                    954:   raw_used += sizeof(sequence->_tme_m68k_sequence_uid);
                    955:   if (raw_avail < raw_used) {
                    956:     return (-1);
                    957:   }
                    958:   memcpy(&sequence->_tme_m68k_sequence_uid,
                    959:         raw,
                    960:         sizeof(sequence->_tme_m68k_sequence_uid));
                    961:   raw += sizeof(sequence->_tme_m68k_sequence_uid);
                    962: #endif /* _TME_M68K_VERIFY */
                    963: 
                    964:   /* initialize this to one: */
                    965:   sequence->_tme_m68k_sequence_transfer_next = 1;
                    966: 
                    967:   /* done: */
                    968:   return (raw_used);
                    969: }
                    970: 
                    971: /* this transfers the instruction buffer to or from a region of host
                    972:    memory.  unlike the raw region in host memory, where the 16- and
                    973:    32-bit parts of the instruction are contiguous and therefore
                    974:    potentially misaligned, in the instruction buffer these instruction
                    975:    parts are all properly aligned.  given the instruction buffer, a
                    976:    contiguous host memory buffer, a count of instruction bytes and the
                    977:    sizes of the instruction fetches, this transfers from one buffer to
                    978:    the other.
                    979: 
                    980:    this is used to fill the instruction buffer when we're restoring
                    981:    our state from an exception stack or when we fault anywhere inside
                    982:    the fast executor, and it's used to empty the instruction buffer
                    983:    into an exception stack when we fault: */
                    984: int
                    985: tme_m68k_insn_buffer_xfer(struct tme_m68k *ic, tme_uint8_t *raw, unsigned int raw_avail, int what)
                    986: {
                    987:   int fill, sanity_assert;
                    988:   tme_uint16_t fetch_total;
                    989:   tme_uint16_t fetch_sizes;
                    990:   unsigned int fetch_sizes_bits;
                    991:   unsigned int insn_buffer_off, fetch_off, fetch_size, resid;
                    992: #define _FETCH_SIZES_BITS (8 * sizeof(ic->_tme_m68k_insn_buffer_fetch_sizes))
                    993: #define _FETCH_SIZE_BIT (1 << (_FETCH_SIZES_BITS - 1))
                    994: #define _FETCH_SANITY(e) \
                    995: do { \
                    996:   if (sanity_assert) \
                    997:     assert(e); \
                    998:   else if (!(e)) \
                    999:     return (-1); \
                   1000: } while (/* CONSTCOND */ 0)
                   1001:   
                   1002:   /* if what is zero, we faulted somewhere inside the fast executor
                   1003:      and we need to fill the instruction buffer from raw host memory: */
                   1004:   if (what == 0) {
                   1005:     fill = TRUE;
                   1006:     sanity_assert = TRUE;
                   1007: 
                   1008:     /* the fetch total and sizes are in the state: */
                   1009:     fetch_total = ic->_tme_m68k_insn_buffer_fetch_total;
                   1010:     fetch_sizes = ic->_tme_m68k_insn_buffer_fetch_sizes;
                   1011:     raw_avail = fetch_total;
                   1012:   }
                   1013: 
                   1014:   /* else, if what is one, we're emptying the instruction buffer into
                   1015:      an exception frame: */
                   1016:   else if (what == 1) {
                   1017:     fill = FALSE;
                   1018:     sanity_assert = TRUE;
                   1019: 
                   1020:     /* the fetch total and sizes are in the state: */
                   1021:     fetch_total = ic->_tme_m68k_insn_buffer_fetch_total;
                   1022:     fetch_sizes = ic->_tme_m68k_insn_buffer_fetch_sizes;
                   1023: 
                   1024:     /* the first word we place into the exception frame is
                   1025:        (fetch_sizes << 4) | (fetch_total >> 1): */
                   1026:     _FETCH_SANITY(raw_avail >= sizeof(tme_uint16_t));
                   1027:     raw[1] = (fetch_sizes << 4) | (fetch_total >> 1);
                   1028:     raw[0] = (fetch_sizes >> 4);
                   1029:     raw += sizeof(tme_uint16_t);
                   1030:     raw_avail -= sizeof(tme_uint16_t);
                   1031:   }
                   1032: 
                   1033:   /* otherwise, we're filling the instruction buffer from an exception
                   1034:      frame: */
                   1035:   else {
                   1036:     fill = TRUE;
                   1037:     sanity_assert = FALSE;
                   1038: 
                   1039:     /* this function previously emptied the instruction buffer into
                   1040:        this exception frame, and the first big-endian word placed
                   1041:        there is (fetch_sizes << 4) | (fetch_total >> 1): */
                   1042:     _FETCH_SANITY(raw_avail >= sizeof(tme_uint16_t));
                   1043:     fetch_total = (raw[1] & 0x0f) << 1;
                   1044:     fetch_sizes = (raw[0] << 4) | (raw[1] >> 4);
                   1045:     raw += sizeof(tme_uint16_t);
                   1046:     raw_avail -= sizeof(tme_uint16_t);
                   1047:   }
                   1048: 
                   1049:   /* fetch_total must be even, because we only fetch some multiple of
                   1050:      16-bit words: */
                   1051:   _FETCH_SANITY((fetch_total & (sizeof(tme_uint16_t) - 1)) == 0);
                   1052: 
                   1053:   /* fetch_sizes is a bitmask, with a one bit representing a 32-bit
                   1054:      fetch and a zero bit representing a 16-bit fetch, and the least
                   1055:      significant bit is the *last* fetch performed.  count the number
                   1056:      of significant bits in fetch_sizes and confirm that it makes
                   1057:      sense with fetch_total: */
                   1058:   fetch_sizes_bits = 0;
                   1059:   for (fetch_off = 0; fetch_off < fetch_total; ) {
                   1060:     _FETCH_SANITY(fetch_sizes_bits < _FETCH_SIZES_BITS);
                   1061:     fetch_off += ((fetch_sizes & (1 << fetch_sizes_bits))
                   1062:                  /* a 32-bit fetch: */
                   1063:                  ? sizeof(tme_uint32_t)
                   1064:                  /* a 16-bit fetch: */
                   1065:                  : sizeof(tme_uint16_t));
                   1066:     fetch_sizes_bits++;
                   1067:   }
                   1068:   _FETCH_SANITY(fetch_off == fetch_total);
                   1069: 
                   1070:   /* we must have enough raw space available: */
                   1071:   _FETCH_SANITY(raw_avail >= fetch_total);
                   1072: 
                   1073:   /* shift fetch_sizes up so the bit for the first transfer
                   1074:      is the most significant bit: */
                   1075:   fetch_sizes <<= (_FETCH_SIZES_BITS - fetch_sizes_bits);
                   1076: 
                   1077:   /* now fill or empty the instruction buffer: */
                   1078:   insn_buffer_off = 0;
                   1079:   for (fetch_off = 0; fetch_off < fetch_total; ) {
                   1080: 
                   1081:     /* get the size of this fetch: */
                   1082:     fetch_size = ((fetch_sizes & _FETCH_SIZE_BIT)
                   1083:                  /* a 32-bit fetch: */
                   1084:                  ? sizeof(tme_uint32_t)
                   1085:                  /* a 16-bit fetch: */
                   1086:                  : sizeof(tme_uint16_t));
                   1087:     fetch_sizes <<= 1;
                   1088: 
                   1089:     /* do one transfer.  the insn buffer is kept in host byte
                   1090:        order, like the internal registers are: */
                   1091:     insn_buffer_off = TME_ALIGN(insn_buffer_off, fetch_size);
                   1092:     if (fill) {
                   1093:       for (resid = fetch_size; resid-- > 0; ) {
                   1094:        ic->_tme_m68k_insn_buffer[(insn_buffer_off
                   1095:                                   + (resid
                   1096: #ifndef WORDS_BIGENDIAN
                   1097:                                      ^ (fetch_size - 1)
                   1098: #endif /* !WORDS_BIGENDIAN */
                   1099:                                      ))] 
                   1100:          = raw[fetch_off + resid];
                   1101:       }
                   1102:     }
                   1103:     else {
                   1104:       for (resid = fetch_size; resid-- > 0; ) {
                   1105:        raw[fetch_off + resid] = 
                   1106:          ic->_tme_m68k_insn_buffer[(insn_buffer_off
                   1107:                                     + (resid
                   1108: #ifndef WORDS_BIGENDIAN
                   1109:                                        ^ (fetch_size - 1)
                   1110: #endif /* !WORDS_BIGENDIAN */
                   1111:                                        ))];
                   1112:       }
                   1113:     }
                   1114:     insn_buffer_off += fetch_size;
                   1115:     fetch_off += fetch_size;
                   1116: 
                   1117:     /* if we faulted somewhere in the fast executor, we need to
                   1118:        account for the instruction fetches in the group0 sequence: */
                   1119:     if (what == 0) {
                   1120:       ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_next++;
                   1121:     }
                   1122:   }
                   1123: 
                   1124:   /* NB: for total consistency we might want to store the fetch total
                   1125:      and sizes into the state when we're filling the instruction
                   1126:      buffer from an execution frame.  however this isn't really needed
                   1127:      because the fetch pattern from the restarting slow executor
                   1128:      should be exactly the same and it doesn't care anyways. 
                   1129:      if the user bashes the exception frame all bets are off. */
                   1130: 
                   1131:   /* return the number of bytes we put in an exception frame: */
                   1132:   return (sizeof(tme_uint16_t) + fetch_total);
                   1133: }
                   1134: 
                   1135: /* this is the group 0 fault hook for the fast executor: */
                   1136: void
                   1137: tme_m68k_group0_hook_fast(struct tme_m68k *ic)
                   1138: {
                   1139:   struct tme_m68k_tlb *tlb;
                   1140:   tme_uint8_t *raw;
                   1141: 
                   1142:   /* fill the instruction buffer and increase the transfer count
                   1143:      as if the slow executor had been doing the fetching: */
                   1144:   tlb = TME_ATOMIC_READ(struct tme_m68k_tlb *, ic->_tme_m68k_itlb);
                   1145:   raw = tlb->tme_m68k_tlb_emulator_off_read + ic->tme_m68k_ireg_pc;
                   1146:   tme_m68k_insn_buffer_xfer(ic, raw, 0, 0);
                   1147: }
                   1148: 
                   1149: /* this starts a read/modify/write cycle.  this works in conjunction
                   1150:    with the tme_m68k_readSIZE() and tme_m68k_writeSIZE() functions to
                   1151:    aggregate many bus transactions into a larger transaction: */
                   1152: struct tme_m68k_tlb *
                   1153: tme_m68k_rmw_start(struct tme_m68k *ic)
                   1154: {
                   1155:   struct tme_m68k_tlb *tlb;
                   1156: 
                   1157:   /* if the user reran the cycle, do nothing: */
                   1158:   if (TME_M68K_SEQUENCE_RESTARTING
                   1159:       && (ic->_tme_m68k_group0_buffer_read_softrr > 0
                   1160:          || ic->_tme_m68k_group0_buffer_write_softrr > 0)) {
                   1161:     return (NULL);
                   1162:   }
                   1163: 
                   1164:   /* we always rerun read/modify/write cycles in their entirety: */
                   1165:   ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted
                   1166:     = ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next - 1;
                   1167: 
                   1168:   /* get an applicable TLB entry: */
                   1169:   tlb = TME_M68K_TLB_ENTRY(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address);
                   1170: 
                   1171:   /* we *must* guarantee that a read/modify/write cycle be atomic.
                   1172:      unfortunately, the only way we can really do that is to acquire a
                   1173:      single lock, now, that somehow protects all of the things we want
                   1174:      to do, and hold that lock for the duration.
                   1175: 
                   1176:      the only way we can do this is to require that read/modify/write
                   1177:      cycles always involve TLB entries that allow fast reads and
                   1178:      writes.  this gives us a single rwlock that we can lock for
                   1179:      writing now and hold until we're done: */
                   1180: 
                   1181:   /* we invalidate the TLB entry so we can set the TLB rwlock to NULL,
                   1182:      which is seen by the first tme_m68k_readSIZE (or
                   1183:      tme_m68k_writeSIZE, in the bizarre case that that's called first)
                   1184:      as a signal that, after it reloads the TLB entry, it has to lock
                   1185:      the rwlock: */
                   1186:   tme_bus_tlb_invalidate(&tlb->tme_m68k_tlb_bus_tlb);
                   1187:   tlb->tme_m68k_tlb_bus_rwlock = NULL;
                   1188: 
                   1189:   return (tlb);
                   1190: }
                   1191: 
                   1192: /* this finishes a read/modify/write cycle.  this works in conjunction
                   1193:    with the tme_m68k_readSIZE() and tme_m68k_writeSIZE() functions to
                   1194:    aggregate many bus transactions into a larger transaction: */
                   1195: void
                   1196: tme_m68k_rmw_finish(struct tme_m68k *ic, struct tme_m68k_tlb *tlb)
                   1197: {
                   1198:   
                   1199:   /* if we didn't acquire the rwlock, something is wrong: */
                   1200:   assert(tlb->tme_m68k_tlb_bus_rwlock != NULL);
                   1201:   
                   1202:   /* unlock the lock: */
                   1203:   tme_rwlock_unlock(tlb->tme_m68k_tlb_bus_rwlock);
                   1204: }
                   1205: 
                   1206: /* this handles a bitfield offset.  if the bitfield is in memory,
                   1207:    and it hasn't already been done, this adjusts the effective
                   1208:    address to point to the beginning of the bitfield.  this always
                   1209:    returns a nonnegative bitfield offset: */
                   1210: unsigned int
                   1211: tme_m68k_bitfield_offset(struct tme_m68k *ic, int adjust)
                   1212: {
                   1213:   tme_int16_t specop;
                   1214:   tme_int32_t bf_offset;
                   1215:   tme_int32_t bf_ea_offset;
                   1216:     
                   1217:   /* get the bitfield offset from a data register or as an immediate: */
                   1218:   specop = ic->_tme_m68k_insn_specop;
                   1219:   bf_offset = ((specop & TME_BIT(11))
                   1220:               ? ic->tme_m68k_ireg_int32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop, 6, 3))
                   1221:               : (tme_int32_t) TME_FIELD_EXTRACTU(specop, 6, 5));
                   1222: 
                   1223:   /* if this bitfield is in a register (EA mode field is zero): */
                   1224:   if (TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 3, 3) == 0) {
                   1225: 
                   1226:     /* adjust the bitfield offset to be nonnegative: */
                   1227:     bf_offset &= 31;
                   1228:   }
                   1229: 
                   1230:   /* otherwise, this bitfield is in memory: */
                   1231:   else {
                   1232: 
                   1233:     /* calculate the effective address offset and adjust the bitfield
                   1234:        offset to be nonnegative: */
                   1235:     bf_ea_offset = ((bf_offset < 0)
                   1236:                    ? ((bf_offset + 1) / 8) - 1
                   1237:                    : bf_offset / 8);
                   1238:     bf_offset &= 7;
                   1239: 
                   1240:     /* if this is our first call to this function for this instruction
                   1241:        and we're not restarting, adjust the effective address: */
                   1242:     if (adjust
                   1243:        && !TME_M68K_SEQUENCE_RESTARTING) {
                   1244:       ic->_tme_m68k_ea_address += bf_ea_offset;
                   1245:     }
                   1246:   }
                   1247: 
                   1248:   /* return the nonnegative bitfield offset: */
                   1249:   return ((unsigned int) bf_offset);
                   1250: }
                   1251: 
                   1252: /* this returns a bitfield width: */
                   1253: unsigned int
                   1254: tme_m68k_bitfield_width(struct tme_m68k *ic)
                   1255: {
                   1256:   unsigned int bf_width;
                   1257:   tme_int16_t specop;
                   1258: 
                   1259:   /* get the bitfield width from a register or as an immediate: */
                   1260:   specop = ic->_tme_m68k_insn_specop;
                   1261:   if (specop & TME_BIT(5)) {
                   1262:     bf_width = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop, 0, 3));
                   1263:   }
                   1264:   else {
                   1265:     bf_width = TME_FIELD_EXTRACTU(specop, 0, 5);
                   1266:   }
                   1267:   bf_width &= 31;
                   1268:   if (bf_width == 0) bf_width = 32;
                   1269:   return (bf_width);
                   1270: }
                   1271: 
                   1272: /* this reads a bitfield: */
                   1273: tme_uint32_t
                   1274: _tme_m68k_bitfield_read(struct tme_m68k *ic, int is_signed)
                   1275: {
                   1276:   unsigned int bf_offset, bf_width;
                   1277:   unsigned int shift;
                   1278:   tme_uint8_t *bf_bytes;
                   1279:   tme_uint32_t bf_value;
                   1280:   int ireg;
                   1281: 
                   1282:   /* get the bitfield offset and width: */
                   1283:   bf_offset = tme_m68k_bitfield_offset(ic, TRUE);
                   1284:   bf_width = tme_m68k_bitfield_width(ic);
                   1285: 
                   1286:   /* if this expression is > 32, in a register this means the bitfield
                   1287:      wraps, and in memory this means the bitfield is 5-bytes wide: */
                   1288:   shift = (bf_offset + bf_width);
                   1289: 
                   1290:   /* if this bitfield is in a register (EA mode field is zero): */
                   1291:   if (TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 3, 3) == 0) {
                   1292:     ireg = (TME_M68K_IREG_D0
                   1293:            + TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 0, 3));
                   1294: 
                   1295:     /* get the raw 32-bit word containing the bitfield: */
                   1296:     bf_value = ic->tme_m68k_ireg_uint32(ireg);
                   1297: 
                   1298:     /* if this bitfield wraps the register, shift in the wrapped part
                   1299:        on the right: */
                   1300:     if (shift > 32) {
                   1301:       shift -= 32;
                   1302:       bf_value = (bf_value << shift) | (bf_value >> (32 - shift));
                   1303:       bf_offset -= shift;
                   1304:     }
                   1305:   }
                   1306: 
                   1307:   /* otherwise, this bitfield is in memory: */
                   1308:   else {
                   1309: 
                   1310:     /* read in the bytes covering the bitfield: */
                   1311:     bf_bytes = (tme_uint8_t *) &ic->tme_m68k_ireg_memx32;
                   1312:     tme_m68k_read_mem(ic, bf_bytes, (bf_offset + bf_width + 7) >> 3);
                   1313: 
                   1314:     /* get the raw 32-bit word containing the bitfield: */
                   1315:     bf_value = tme_betoh_u32(ic->tme_m68k_ireg_memx32);
                   1316: 
                   1317:     /* if this bitfield is 5 bytes wide, shift in the part from the fifth byte
                   1318:        (actually in memy32!) on the right: */
                   1319:     if (shift > 32) {
                   1320:       shift -= 32;
                   1321:       bf_value = (bf_value << shift) | (bf_bytes[4] >> (8 - shift));
                   1322:       bf_offset -= shift;
                   1323:     }
                   1324:   }
                   1325:   
                   1326:   /* shift the value: */
                   1327:   shift = (32 - (bf_offset + bf_width));
                   1328:   bf_value >>= shift;
                   1329: 
                   1330:   /* mask the value: */
                   1331:   bf_value &= TME_BIT(bf_width) - 1;
                   1332: 
                   1333:   /* if this is a signed value, sign-extend it: */
                   1334:   if (is_signed
                   1335:       && (bf_value & TME_BIT(bf_width - 1))) {
                   1336:     bf_value |= (0xffffffff ^ (TME_BIT(bf_width) - 1));
                   1337:   }
                   1338: 
                   1339:   /* all bitfield instructions that read the bitfield set the flags: */
                   1340:   if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1341:     ic->tme_m68k_ireg_ccr = ((ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X)
                   1342:                             | ((bf_value & TME_BIT(bf_width - 1))
                   1343:                                ? TME_M68K_FLAG_N
                   1344:                                : 0)
                   1345:                             | (bf_value
                   1346:                                ? 0
                   1347:                                : TME_M68K_FLAG_Z));
                   1348:   }
                   1349: 
                   1350:   /* return the bitfield value: */
                   1351:   return (bf_value);
                   1352: }
                   1353: 
                   1354: /* this writes a bitfield to memory: */
                   1355: void
                   1356: tme_m68k_bitfield_write_unsigned(struct tme_m68k *ic, tme_uint32_t bf_value, int set_flags)
                   1357: {
                   1358:   unsigned int bf_offset, bf_width;
                   1359:   unsigned int shift;
                   1360:   tme_uint8_t *bf_bytes;
                   1361:   unsigned int count;
                   1362:   int ireg;
                   1363: 
                   1364:   /* for bitfields in memory, we want to know if the memory covering
                   1365:      the bitfield is already in our memory buffer, so we can avoid
                   1366:      reading that memory again.  all bitfield instructions set flags
                   1367:      based on a bitfield value; if set_flags is FALSE our caller
                   1368:      must have tested the old bitfield value, and so the bitfield
                   1369:      memory must be in our buffer, otherwise assume that this is our
                   1370:      first access to the bitfield memory: */
                   1371: #define first_memory set_flags
                   1372:   
                   1373:   /* get the bitfield offset and width: */
                   1374:   bf_offset = tme_m68k_bitfield_offset(ic, first_memory);
                   1375:   bf_width = tme_m68k_bitfield_width(ic);
                   1376: 
                   1377:   /* if this expression is > 32, in a register this means the bitfield
                   1378:      wraps, and in memory this means the bitfield is 5-bytes wide: */
                   1379:   shift = (bf_offset + bf_width);
                   1380: 
                   1381:   /* if we're supposed to, set the flags: */
                   1382:   if (set_flags
                   1383:       && !TME_M68K_SEQUENCE_RESTARTING) {
                   1384:     ic->tme_m68k_ireg_ccr = ((ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X)
                   1385:                             | ((bf_value & TME_BIT(bf_width - 1))
                   1386:                                ? TME_M68K_FLAG_N
                   1387:                                : 0)
                   1388:                             | (bf_value
                   1389:                                ? 0
                   1390:                                : TME_M68K_FLAG_Z));
                   1391:   }
                   1392: 
                   1393:   /* mask the value: */
                   1394:   bf_value &= TME_BIT(bf_width) - 1;
                   1395: 
                   1396:   /* if this bitfield is in a register (EA mode field is zero): */
                   1397:   if (TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 3, 3) == 0) {
                   1398:     ireg = (TME_M68K_IREG_D0
                   1399:            + TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 0, 3));
                   1400:     
                   1401:     /* if this bitfield wraps the register, put the wrapped
                   1402:        part in the left: */
                   1403:     if (shift > 32) {
                   1404:       shift -= 32;
                   1405:       ic->tme_m68k_ireg_uint32(ireg) = ((ic->tme_m68k_ireg_uint32(ireg)
                   1406:                                         & (0xffffffffUL >> shift))
                   1407:                                        | (bf_value << (32 - shift)));
                   1408:       bf_value >>= shift;
                   1409:       bf_width -= shift;
                   1410:     }
                   1411:     
                   1412:     /* update the register: */
                   1413:     shift = (32 - (bf_offset + bf_width));
                   1414:     ic->tme_m68k_ireg_uint32(ireg) = ((ic->tme_m68k_ireg_uint32(ireg)
                   1415:                                       & ((TME_BIT(bf_width) - 1) << shift))
                   1416:                                      | (bf_value << shift));
                   1417:   }
                   1418: 
                   1419:   /* otherwise, this bitfield is in memory: */
                   1420:   else {
                   1421: 
                   1422:     /* read in the bytes covering the bitfield if we haven't yet: */
                   1423:     bf_bytes = (tme_uint8_t *) &ic->tme_m68k_ireg_memx32;
                   1424:     count = (bf_offset + bf_width + 7) >> 3;
                   1425:     if (first_memory) {
                   1426:       tme_m68k_read_mem(ic, bf_bytes, count);
                   1427:     }
                   1428: 
                   1429:     /* if this bitfield is 5 bytes wide, put the part for the fifth
                   1430:        byte (actually in memy32!) in on the left: */
                   1431:     if (shift > 32) {
                   1432:       shift -= 32;
                   1433:       if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1434:        bf_bytes[4] = ((bf_bytes[4]
                   1435:                        & (0xff >> shift))
                   1436:                       | ((bf_value & 0xff) << (8 - shift)));
                   1437:       }
                   1438:       bf_value >>= shift;
                   1439:       bf_width -= shift;
                   1440:     }
                   1441: 
                   1442:     /* update the memory buffer: */
                   1443:     if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1444:       shift = (32 - (bf_offset + bf_width));
                   1445:       ic->tme_m68k_ireg_memx32 =
                   1446:        tme_htobe_u32((tme_betoh_u32(ic->tme_m68k_ireg_memx32)
                   1447:                       & ((TME_BIT(bf_width) - 1) << shift))
                   1448:                      | (bf_value << shift));
                   1449:     }
                   1450: 
                   1451:     /* write out the bytes covering bitfield to memory: */
                   1452:     tme_m68k_write_mem(ic, bf_bytes, count);
                   1453:   }
                   1454: #undef first_memory
                   1455: }
                   1456: 
                   1457: /* our global verify hook function: */
1.1.1.2 ! root     1458: #undef tme_m68k_verify_hook
1.1       root     1459: void
                   1460: tme_m68k_verify_hook(void)
                   1461: {
                   1462: }
                   1463: 
                   1464: #if 1
                   1465: #include <stdio.h>
                   1466: 
                   1467: /* this dumps out the m68k state: */
                   1468: void
                   1469: tme_m68k_dump(struct tme_m68k *ic)
                   1470: {
                   1471:   int ireg;
                   1472:   int count;
                   1473: 
                   1474:   /* dump out the integer registers: */
                   1475:   count = 0;
                   1476:   for (ireg = TME_M68K_IREG_D0;
                   1477:        ireg <= TME_M68K_IREG_A7;
                   1478:        ireg++) {
                   1479:     fprintf(stderr,
                   1480:            "%%%c%d[%p] = 0x%08x",
                   1481:            (ireg < TME_M68K_IREG_A0
                   1482:             ? 'd'
                   1483:             : 'a'),
                   1484:            ireg - (ireg < TME_M68K_IREG_A0
                   1485:                    ? TME_M68K_IREG_D0
                   1486:                    : TME_M68K_IREG_A0),
                   1487:            &ic->tme_m68k_ireg_uint32(ireg),
                   1488:            ic->tme_m68k_ireg_uint32(ireg));
                   1489:     if (++count == 2) {
                   1490:       fprintf(stderr, "\n");
                   1491:       count = 0;
                   1492:     }
                   1493:     else {
                   1494:       fprintf(stderr, "  ");
                   1495:     }
                   1496:   }
                   1497: 
                   1498:   /* dump out the PC and next PC: */
                   1499:   fprintf(stderr, "%%pc = 0x%08x  %%pc_next = 0x%08x\n",
                   1500:          ic->tme_m68k_ireg_pc,
                   1501:          ic->tme_m68k_ireg_pc_next);
                   1502: 
                   1503:   /* dump out the status register: */
                   1504:   fprintf(stderr, "%%sr = 0x%04x", ic->tme_m68k_ireg_sr);
                   1505:   fprintf(stderr, "  flags:");
                   1506:   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X) {
                   1507:     fprintf(stderr, " X");
                   1508:   }
                   1509:   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_N) {
                   1510:     fprintf(stderr, " N");
                   1511:   }
                   1512:   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) {
                   1513:     fprintf(stderr, " Z");
                   1514:   }
                   1515:   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_V) {
                   1516:     fprintf(stderr, " V");
                   1517:   }
                   1518:   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_C) {
                   1519:     fprintf(stderr, " C");
                   1520:   }
                   1521:   fprintf(stderr, "\n");
                   1522: 
                   1523:   /* dump out the effective address and memory buffers: */
                   1524:   fprintf(stderr, "\n");
                   1525:   fprintf(stderr, "EA = %d:0x%08x\n",
                   1526:          ic->_tme_m68k_ea_function_code,
                   1527:          ic->_tme_m68k_ea_address);
                   1528:   fprintf(stderr, "%%memx[%p] = 0x%08x  %%memy[%p] = 0x%08x\n",
                   1529:          &ic->tme_m68k_ireg_memx32,
                   1530:          ic->tme_m68k_ireg_memx32,
                   1531:          &ic->tme_m68k_ireg_memy32,
                   1532:          ic->tme_m68k_ireg_memy32);
                   1533: 
                   1534:   /* dump out the control registers: */
                   1535:   fprintf(stderr, "\n");
                   1536:   fprintf(stderr, "%%usp = 0x%08x\n", ic->tme_m68k_ireg_usp);
                   1537:   fprintf(stderr, "%%isp = 0x%08x\n", ic->tme_m68k_ireg_isp);
                   1538:   fprintf(stderr, "%%msp = 0x%08x\n", ic->tme_m68k_ireg_msp);
                   1539:   fprintf(stderr, "%%sfc = 0x%08x\n", ic->tme_m68k_ireg_sfc);
                   1540:   fprintf(stderr, "%%dfc = 0x%08x\n", ic->tme_m68k_ireg_dfc);
                   1541:   fprintf(stderr, "%%vbr = 0x%08x\n", ic->tme_m68k_ireg_vbr);
                   1542:   
                   1543:   /* dump out instruction decoding information: */
                   1544:   fprintf(stderr, "\n");
                   1545:   fprintf(stderr, "opcode = 0x%04x  specop = 0x%04x  specop2 = 0x%04x\n",
                   1546:          ic->_tme_m68k_insn_opcode,
                   1547:          ic->_tme_m68k_insn_specop,
                   1548:          ic->_tme_m68k_insn_specop2);
                   1549: }
                   1550: #endif /* 1 */

unix.superglobalmegacorp.com

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