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

1.1.1.5   root        1: /* $Id: m68k-misc.c,v 1.27 2009/08/29 19:47:52 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.5   root       39: _TME_RCSID("$Id: m68k-misc.c,v 1.27 2009/08/29 19:47:52 fredette Exp $");
1.1       root       40: 
                     41: /* the memory buffer read and write functions: */
                     42: #if TME_M68K_SIZE_8 != 1
                     43: #error "TME_M68K_SIZE_8 must be 1"
                     44: #endif
                     45: #if TME_M68K_SIZE_16 != 2
                     46: #error "TME_M68K_SIZE_16 must be 2"
                     47: #endif
                     48: #if TME_M68K_SIZE_32 != 4
                     49: #error "TME_M68K_SIZE_32 must be 4"
                     50: #endif
                     51: const _tme_m68k_xfer_memx _tme_m68k_read_memx[5] = {
                     52:   NULL,
                     53:   tme_m68k_read_memx8,
                     54:   tme_m68k_read_memx16,
                     55:   NULL,
                     56:   tme_m68k_read_memx32
                     57: };
                     58: const _tme_m68k_xfer_memx _tme_m68k_write_memx[5] = {
                     59:   NULL,
                     60:   tme_m68k_write_memx8,
                     61:   tme_m68k_write_memx16,
                     62:   NULL,
                     63:   tme_m68k_write_memx32
                     64: };
                     65: const _tme_m68k_xfer_mem _tme_m68k_read_mem[5] = {
                     66:   NULL,
                     67:   tme_m68k_read_mem8,
                     68:   tme_m68k_read_mem16,
                     69:   NULL,
                     70:   tme_m68k_read_mem32
                     71: };
                     72: const _tme_m68k_xfer_mem _tme_m68k_write_mem[5] = {
                     73:   NULL,
                     74:   tme_m68k_write_mem8,
                     75:   tme_m68k_write_mem16,
                     76:   NULL,
                     77:   tme_m68k_write_mem32
                     78: };
                     79: 
                     80: /* our bus signal handler: */
                     81: static int
                     82: _tme_m68k_bus_signal(struct tme_bus_connection *conn_bus, unsigned int signal)
                     83: {
                     84:   struct tme_m68k *ic;
                     85:   unsigned int level_edge;
                     86: 
                     87:   /* recover our IC: */
                     88:   ic = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
                     89: 
                     90:   /* take out the level and edge: */
1.1.1.3   root       91:   level_edge = signal;
                     92:   signal = TME_BUS_SIGNAL_WHICH(signal);
                     93:   level_edge ^= signal;
1.1       root       94: 
                     95:   /* lock the external mutex: */
                     96:   tme_mutex_lock(&ic->tme_m68k_external_mutex);
                     97: 
                     98:   /* on the falling edge of HALT or RESET, halt the processor: */
1.1.1.3   root       99:   if (((level_edge & TME_BUS_SIGNAL_LEVEL_MASK)
                    100:        == TME_BUS_SIGNAL_LEVEL_ASSERTED)
1.1       root      101:       && (signal == TME_BUS_SIGNAL_HALT
                    102:          || signal == TME_BUS_SIGNAL_RESET)) {
                    103:     ic->tme_m68k_external_halt = TRUE;
                    104:   }
                    105: 
                    106:   /* on the rising edge of RESET, reset the processor: */
                    107:   else if (signal == TME_BUS_SIGNAL_RESET
1.1.1.3   root      108:           && ((level_edge & TME_BUS_SIGNAL_LEVEL_MASK)
                    109:               == TME_BUS_SIGNAL_LEVEL_NEGATED)) {
1.1       root      110:     ic->tme_m68k_external_reset = TRUE;
                    111:   }
                    112: 
                    113:   /* on any other HALT or RESET, do nothing: */
                    114:   else if (signal == TME_BUS_SIGNAL_RESET
                    115:           || signal == TME_BUS_SIGNAL_HALT) {
                    116:     /* nothing */
                    117:   }
                    118: 
                    119:   /* anything else: */
                    120:   else {
                    121:     abort();
                    122:   }
                    123: 
                    124:   /* unlock the external mutex: */
                    125:   tme_mutex_unlock(&ic->tme_m68k_external_mutex);
                    126: 
                    127:   /* notify any threads waiting on the external condition: */
                    128:   tme_cond_notify(&ic->tme_m68k_external_cond, TRUE);
                    129:   return (TME_OK);
                    130: }
                    131: 
1.1.1.3   root      132: /* this enables or disables an m6888x: */
                    133: static int
                    134: _tme_m6888x_enable(struct tme_m68k_bus_connection *conn_m68k, int enabled)
                    135: {
                    136:   struct tme_m68k *ic;
                    137: 
                    138:   /* recover our IC: */
                    139:   ic = conn_m68k->tme_m68k_bus_connection.tme_bus_connection.tme_connection_element->tme_element_private;
                    140: 
                    141:   /* NB: we're lazy here and don't bother locking the external mutex: */
                    142:   if (ic->tme_m68k_fpu_type == TME_M68K_FPU_NONE) {
                    143:     return (ENXIO);
                    144:   }
                    145:   ic->tme_m68k_fpu_enabled = enabled;
                    146:   return (TME_OK);
                    147: }
                    148: 
1.1       root      149: /* our interrupt handler: */
                    150: static int
                    151: _tme_m68k_bus_interrupt(struct tme_m68k_bus_connection *conn_m68k, unsigned int ipl)
                    152: {
                    153:   struct tme_m68k *ic;
                    154: 
                    155:   /* recover our IC: */
                    156:   ic = conn_m68k->tme_m68k_bus_connection.tme_bus_connection.tme_connection_element->tme_element_private;
                    157: 
                    158:   /* lock the external mutex: */
                    159:   tme_mutex_lock(&ic->tme_m68k_external_mutex);
                    160: 
                    161:   /* set the interrupt line: */
                    162:   ic->tme_m68k_external_ipl = ipl;
                    163: 
1.1.1.3   root      164:   /* if the IPL has dropped below the NMI level, the next transition
                    165:      to that level will cause an NMI: */
                    166:   if (ipl < TME_M68K_IPL_NMI) {
                    167:     ic->tme_m68k_external_ipl_previous_nmi = FALSE;
                    168:   }
                    169: 
1.1       root      170:   /* unlock the external mutex: */
                    171:   tme_mutex_unlock(&ic->tme_m68k_external_mutex);
                    172: 
                    173:   /* notify any threads waiting on the external condition: */
                    174:   tme_cond_notify(&ic->tme_m68k_external_cond, TRUE);
                    175:   return (TME_OK);
                    176: }
                    177: 
                    178: /* this checks for external signals.  this must be called with the
                    179:    external mutex held: */
                    180: void
                    181: tme_m68k_external_check(struct tme_m68k *ic, tme_uint32_t internal_exceptions)
                    182: {
                    183:   unsigned int ipl;
                    184:   int vector;
                    185:   int rc;
                    186: 
                    187:   /* if an external reset has been requested, start reset exception
                    188:      processing: */
                    189:   if (ic->tme_m68k_external_reset) {
                    190:     ic->tme_m68k_external_reset = FALSE;
                    191:     tme_mutex_unlock(&ic->tme_m68k_external_mutex);
1.1.1.3   root      192:     tme_m68k_exception(ic, TME_M68K_EXCEPTION_RESET);
1.1       root      193:   }
                    194: 
                    195:   /* if an external halt has been requested, halt: */
                    196:   if (ic->tme_m68k_external_halt) {
                    197:     ic->tme_m68k_external_halt = FALSE;
                    198:     tme_mutex_unlock(&ic->tme_m68k_external_mutex);
                    199:     ic->_tme_m68k_mode = TME_M68K_MODE_HALT;
                    200:     TME_M68K_SEQUENCE_START;
                    201:     tme_m68k_redispatch(ic);
                    202:   }
                    203: 
                    204:   /* if we are not halted, and an interrupt can be serviced, start
                    205:      interrupt exception processing: */
                    206:   ipl = ic->tme_m68k_external_ipl;
                    207:   if (ic->_tme_m68k_mode != TME_M68K_MODE_HALT
                    208:       && ipl >= TME_M68K_IPL_MIN
                    209:       && ipl <= TME_M68K_IPL_MAX
1.1.1.3   root      210:       && ((ipl == TME_M68K_IPL_NMI
                    211:           && !ic->tme_m68k_external_ipl_previous_nmi)
1.1       root      212:          || ipl > TME_M68K_FLAG_IPM(ic->tme_m68k_ireg_sr))) {
1.1.1.3   root      213:     
                    214:     /* if this is an NMI, prevent it from being repeatedly accepted: */
                    215:     if (ipl == TME_M68K_IPL_NMI) {
                    216:       ic->tme_m68k_external_ipl_previous_nmi = TRUE;
                    217:     }
                    218: 
1.1       root      219:     tme_mutex_unlock(&ic->tme_m68k_external_mutex);
                    220:     
                    221:     /* acknowledge the interrupt and get the vector: */
1.1.1.4   root      222:     tme_m68k_callout_unlock(ic);
1.1       root      223:     rc = (*ic->_tme_m68k_bus_connection->tme_m68k_bus_connection.tme_bus_intack)
                    224:       (&ic->_tme_m68k_bus_connection->tme_m68k_bus_connection,
                    225:        ipl, &vector);
1.1.1.4   root      226:     tme_m68k_callout_relock(ic);
1.1       root      227:     if (rc == TME_EDEADLK) {
                    228:       abort();
                    229:     }
                    230: 
                    231:     /* if the interrupt acknowledge failed, this is a spurious interrupt: */
                    232:     if (rc == ENOENT) {
1.1.1.3   root      233:       vector = TME_M68K_VECTOR_SPURIOUS;
1.1       root      234:     }
                    235: 
                    236:     /* if no vector is given, use the autovector: */
                    237:     else if (vector == TME_BUS_INTERRUPT_VECTOR_UNDEF) {
1.1.1.3   root      238:       vector = TME_M68K_VECTOR_SPURIOUS + ipl;
1.1       root      239:     }
                    240: 
                    241:     /* dispatch the exceptions: */
1.1.1.3   root      242:     tme_m68k_exception(ic, internal_exceptions | TME_M68K_EXCEPTION_INT(ipl, vector));
1.1       root      243:   }
                    244: 
                    245:   /* if there are internal exceptions to process, do so: */
                    246:   if (internal_exceptions != 0) {
                    247:     tme_mutex_unlock(&ic->tme_m68k_external_mutex);
                    248:     tme_m68k_exception(ic, internal_exceptions);
                    249:   }
                    250: 
                    251:   /* there are no exceptions to process: */
                    252: }
                    253: 
                    254: /* the idle function, used when the processor is halted or stopped: */
                    255: static void
                    256: tme_m68k_idle(struct tme_m68k *ic)
                    257: {  
                    258:   /* lock the external mutex: */
                    259:   tme_mutex_lock(&ic->tme_m68k_external_mutex);
                    260: 
                    261:   /* loop forever: */
                    262:   for (;;) {
                    263: 
                    264:     /* check for any external signal: */
                    265:     tme_m68k_external_check(ic, 0);
                    266: 
                    267:     /* await an external condition: */
                    268:     tme_cond_wait_yield(&ic->tme_m68k_external_cond, &ic->tme_m68k_external_mutex);
                    269:   }
                    270: }
                    271: 
                    272: /* the m68k thread: */
                    273: static void
                    274: tme_m68k_thread(struct tme_m68k *ic)
                    275: {
                    276: 
                    277:   /* we use longjmp to redispatch: */
                    278:   do { } while (setjmp(ic->_tme_m68k_dispatcher));
                    279: 
1.1.1.4   root      280:   /* we must not have a busy fast instruction TLB entry: */
                    281:   assert (ic->_tme_m68k_insn_fetch_fast_itlb == NULL);
                    282: 
                    283:   /* clear the group 0 hook: */
                    284:   ic->_tme_m68k_group0_hook = NULL;
                    285: 
1.1       root      286:   /* dispatch on the current mode: */
                    287:   switch (ic->_tme_m68k_mode) {
                    288: 
                    289:   case TME_M68K_MODE_EXECUTION:
                    290:     (*ic->_tme_m68k_mode_execute)(ic);
                    291:     /* NOTREACHED */
                    292: 
                    293:   case TME_M68K_MODE_EXCEPTION:
                    294:     (*ic->_tme_m68k_mode_exception)(ic);
                    295:     /* NOTREACHED */
                    296: 
                    297:   case TME_M68K_MODE_RTE:
                    298:     (*ic->_tme_m68k_mode_rte)(ic);
                    299:     /* NOTREACHED */
                    300: 
                    301:   case TME_M68K_MODE_STOP:
                    302:   case TME_M68K_MODE_HALT:
                    303:     tme_m68k_idle(ic);
                    304:     /* NOTREACHED */
                    305: 
1.1.1.6 ! root      306:   case TME_M68K_MODE_DIE:
        !           307:     return;
        !           308: 
1.1       root      309:   default:
                    310:     abort();
                    311:   }
                    312:   /* NOTREACHED */
                    313: }
                    314: 
                    315: /* the TLB filler for when we are on a generic bus: */
                    316: static int
                    317: _tme_m68k_generic_tlb_fill(struct tme_m68k_bus_connection *conn_m68k, 
                    318:                           struct tme_m68k_tlb *tlb,
                    319:                           unsigned int function_code, 
                    320:                           tme_uint32_t external_address, 
                    321:                           unsigned int cycles)
                    322: {
                    323:   struct tme_m68k *ic;
                    324: 
                    325:   /* recover our IC: */
                    326:   ic = conn_m68k->tme_m68k_bus_connection.tme_bus_connection.tme_connection_element->tme_element_private;
                    327: 
                    328:   /* call the generic bus TLB filler: */
                    329:   (ic->_tme_m68k_bus_generic->tme_bus_tlb_fill)
                    330:     (ic->_tme_m68k_bus_generic,
                    331:      &tlb->tme_m68k_tlb_bus_tlb,
                    332:      external_address,
                    333:      cycles);
                    334:   
                    335:   /* when we're on a generic bus a TLB entry is valid for all function codes: */
                    336:   tlb->tme_m68k_tlb_function_codes_mask = -1;
                    337: 
                    338:   return (TME_OK);
                    339: }
                    340: 
                    341: /* the connection scorer: */
                    342: static int
                    343: _tme_m68k_connection_score(struct tme_connection *conn, unsigned int *_score)
                    344: {
                    345:   struct tme_m68k_bus_connection *conn_m68k;
                    346:   struct tme_bus_connection *conn_bus;
                    347:   unsigned int score;
                    348: 
                    349:   /* assume that this connection is useless: */
                    350:   score = 0;
                    351: 
                    352:   /* dispatch on the connection type: */
                    353:   conn_m68k = (struct tme_m68k_bus_connection *) conn->tme_connection_other;
                    354:   conn_bus = (struct tme_bus_connection *) conn->tme_connection_other;
                    355:   switch (conn->tme_connection_type) {
                    356: 
                    357:     /* this must be a bus, and not another m68k chip: */
                    358:   case TME_CONNECTION_BUS_M68K:
1.1.1.5   root      359:     if (conn_bus->tme_bus_tlb_set_add != NULL
1.1.1.3   root      360:        && conn_m68k->tme_m68k_bus_tlb_fill != NULL
                    361:        && conn_m68k->tme_m68k_bus_m6888x_enable == NULL) {
1.1       root      362:       score = 10;
                    363:     }
                    364:     break;
                    365: 
                    366:     /* this must be a bus, and not another chip: */
                    367:   case TME_CONNECTION_BUS_GENERIC:
1.1.1.5   root      368:     if (conn_bus->tme_bus_tlb_set_add != NULL
1.1       root      369:        && conn_bus->tme_bus_tlb_fill != NULL) {
                    370:       score = 1;
                    371:     }
                    372:     break;
                    373: 
                    374:   default: abort();
                    375:   }
                    376: 
                    377:   *_score = score;
                    378:   return (TME_OK);
                    379: }
                    380: 
                    381: /* this makes a new connection: */
                    382: static int
                    383: _tme_m68k_connection_make(struct tme_connection *conn, unsigned int state)
                    384: {
                    385:   struct tme_m68k *ic;
                    386:   struct tme_m68k_bus_connection *conn_m68k;
                    387:   struct tme_bus_connection *conn_bus;
                    388:   struct tme_connection *conn_other;
1.1.1.5   root      389:   struct tme_bus_tlb_set_info tlb_set_info;
                    390:   unsigned long tlb_i;
                    391:   struct tme_m68k_tlb *tlb;
                    392:   int rc;
1.1       root      393: 
                    394:   /* since the CPU is halted, it won't be making any connection calls,
                    395:      so we only have to do work when the connection is fully made: */
                    396:   if (state == TME_CONNECTION_FULL) {
                    397: 
                    398:     /* recover our IC: */
                    399:     ic = conn->tme_connection_element->tme_element_private;
                    400:     
                    401:     /* dispatch on the connection type: */
                    402:     conn_other = conn->tme_connection_other;
                    403:     conn_m68k = (struct tme_m68k_bus_connection *) conn_other;
                    404:     conn_bus = (struct tme_bus_connection *) conn_other;
                    405:     switch (conn->tme_connection_type) {
                    406:       
                    407:     case TME_CONNECTION_BUS_M68K:
                    408:       ic->_tme_m68k_bus_connection = conn_m68k;
                    409:       break;
                    410:       
                    411:       /* we need an adaptation layer: */
                    412:     case TME_CONNECTION_BUS_GENERIC:
                    413:       conn_m68k = tme_new0(struct tme_m68k_bus_connection, 1);
                    414:       conn_m68k->tme_m68k_bus_connection.tme_bus_connection.tme_connection_element = conn->tme_connection_element;
                    415:       conn_m68k->tme_m68k_bus_tlb_fill = _tme_m68k_generic_tlb_fill;
                    416:       ic->_tme_m68k_bus_connection = conn_m68k;
                    417:       ic->_tme_m68k_bus_generic = conn_bus;
                    418:       break;
                    419:       
                    420:     default: abort();
                    421:     }
                    422: 
1.1.1.5   root      423:     /* make the TLB set information: */
                    424:     memset(&tlb_set_info, 0, sizeof(tlb_set_info));
                    425:     tlb_set_info.tme_bus_tlb_set_info_token0 = &ic->_tme_m68k_tlb_array[0].tme_m68k_tlb_token;
                    426:     tlb_set_info.tme_bus_tlb_set_info_token_stride = sizeof(struct tme_m68k_tlb);
                    427:     tlb_set_info.tme_bus_tlb_set_info_token_count = TME_ARRAY_ELS(ic->_tme_m68k_tlb_array);
                    428:     tlb_set_info.tme_bus_tlb_set_info_bus_context = &ic->_tme_m68k_bus_context;
                    429: 
                    430:     /* initialize the TLBs in the set: */
                    431:     for (tlb_i = 0; tlb_i < TME_ARRAY_ELS(ic->_tme_m68k_tlb_array); tlb_i++) {
                    432:       tlb = &ic->_tme_m68k_tlb_array[tlb_i];
                    433: 
                    434:       /* initialize this token: */
                    435:       tme_token_init(&tlb->tme_m68k_tlb_token);
                    436: 
                    437:       /* connect this token with this TLB: */
                    438:       tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_token = &tlb->tme_m68k_tlb_token;
                    439:     }
                    440: 
                    441:     /* add the TLB set: */
                    442:     rc = ((*ic->_tme_m68k_bus_connection->tme_m68k_bus_connection.tme_bus_tlb_set_add)
                    443:          (&ic->_tme_m68k_bus_connection->tme_m68k_bus_connection,
                    444:           &tlb_set_info));
                    445:     assert (rc == TME_OK);
1.1       root      446:   }
                    447: 
                    448:   /* NB: the machine needs to issue a reset to bring the CPU out of halt. */
                    449:   return (TME_OK);
                    450: }
                    451: 
                    452: /* this breaks a connection: */
                    453: static int 
                    454: _tme_m68k_connection_break(struct tme_connection *conn, unsigned int state)
                    455: {
                    456:   abort();
1.1.1.3   root      457:   return (0);
1.1       root      458: }
                    459: 
                    460: /* this makes new connection sides: */
                    461: static int
                    462: _tme_m68k_connections_new(struct tme_element *element, const char * const *args, struct tme_connection **_conns, char **_output)
                    463: {
                    464:   struct tme_m68k_bus_connection *conn_m68k;
                    465:   struct tme_bus_connection *conn_bus;
                    466:   struct tme_connection *conn;
                    467: 
                    468:   /* if we already have a bus connection, we can take no more connections: */
                    469:   if (((struct tme_m68k *) element->tme_element_private)->_tme_m68k_bus_connection != NULL) {
                    470:     return (TME_OK);
                    471:   }
                    472: 
                    473:   /* create our side of an m68k bus connection: */
                    474:   conn_m68k = tme_new0(struct tme_m68k_bus_connection, 1);
                    475:   conn_bus = &conn_m68k->tme_m68k_bus_connection;
                    476:   conn = &conn_bus->tme_bus_connection;
                    477: 
                    478:   /* fill in the generic connection: */
                    479:   conn->tme_connection_next = *_conns;
                    480:   conn->tme_connection_type = TME_CONNECTION_BUS_M68K;
                    481:   conn->tme_connection_score = _tme_m68k_connection_score;
                    482:   conn->tme_connection_make = _tme_m68k_connection_make;
                    483:   conn->tme_connection_break = _tme_m68k_connection_break;
                    484: 
                    485:   /* fill in the generic bus connection: */
                    486:   conn_bus->tme_bus_signal = _tme_m68k_bus_signal;
1.1.1.5   root      487:   conn_bus->tme_bus_tlb_set_add = NULL;
1.1       root      488: 
                    489:   /* full in the m68k bus connection: */
                    490:   conn_m68k->tme_m68k_bus_interrupt = _tme_m68k_bus_interrupt;
                    491:   conn_m68k->tme_m68k_bus_tlb_fill = NULL;
1.1.1.3   root      492:   conn_m68k->tme_m68k_bus_m6888x_enable = _tme_m6888x_enable;
1.1       root      493: 
                    494:   /* add this connection to the set of possibilities: */
                    495:   *_conns = conn;
                    496: 
                    497:   /* create our side of a generic bus connection: */
                    498:   conn_bus = tme_new0(struct tme_bus_connection, 1);
                    499:   conn = &conn_bus->tme_bus_connection;
                    500: 
                    501:   /* fill in the generic connection: */
                    502:   conn->tme_connection_next = *_conns;
                    503:   conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC;
                    504:   conn->tme_connection_score = _tme_m68k_connection_score;
                    505:   conn->tme_connection_make = _tme_m68k_connection_make;
                    506:   conn->tme_connection_break = _tme_m68k_connection_break;
                    507: 
                    508:   /* fill in the generic bus connection: */
                    509:   conn_bus->tme_bus_signal = _tme_m68k_bus_signal;
1.1.1.5   root      510:   conn_bus->tme_bus_tlb_set_add = NULL;
1.1       root      511:   conn_bus->tme_bus_tlb_fill = NULL;
                    512: 
                    513:   /* add this connection to the set of possibilities: */
                    514:   *_conns = conn;
                    515: 
                    516:   /* done: */
                    517:   return (TME_OK);
                    518: }
                    519: 
                    520: /* the common m68k new function: */
                    521: int
                    522: tme_m68k_new(struct tme_m68k *ic, const char * const *args, const void *extra, char **_output)
                    523: {
                    524:   struct tme_element *element;
1.1.1.3   root      525:   int arg_i;
                    526:   int usage;
1.1       root      527: 
1.1.1.3   root      528:   /* check our arguments: */
                    529:   arg_i = 1;
                    530:   usage = FALSE;
                    531:   for (;;) {
                    532:     
                    533:     if (0) {
                    534: 
                    535:     }
                    536: 
                    537:     /* if we've run out of arguments: */
                    538:     else if (args[arg_i + 0] == NULL) {
                    539:       break;
                    540:     }
                    541: 
                    542:     /* this is either a bad argument or an FPU argument: */
                    543:     else {
                    544: 
                    545:       /* if this is not an FPU argument: */
                    546:       if (!tme_m68k_fpu_new(ic, args, &arg_i, &usage, _output)) {
                    547:        tme_output_append_error(_output,
                    548:                                "%s %s, ",
                    549:                                args[arg_i],
                    550:                                _("unexpected"));
                    551:        usage = TRUE;
                    552:       }
                    553:       
                    554:       if (usage) {
                    555:        break;
                    556:       }
                    557:     }
                    558:   }
                    559: 
                    560:   if (usage) {
                    561:     tme_output_append_error(_output, 
                    562:                            "%s %s",
1.1       root      563:                            _("usage:"),
                    564:                            args[0]);
1.1.1.3   root      565:     tme_m68k_fpu_usage(_output);
1.1       root      566:     tme_free(ic);
                    567:     return (EINVAL);
                    568:   }
                    569: 
                    570:   /* initialize the verifier: */
                    571:   tme_m68k_verify_init();
                    572: 
                    573:   /* dispatch on the type: */
                    574:   switch (ic->tme_m68k_type) {
                    575:   case TME_M68K_M68000:
1.1.1.4   root      576:     ic->_tme_m68k_bus_16bit = 1;
1.1       root      577:     break;
                    578:   case TME_M68K_M68010:
1.1.1.4   root      579:     ic->_tme_m68k_bus_16bit = 1;
1.1       root      580:     break;
                    581:   case TME_M68K_M68020:
1.1.1.4   root      582:     ic->_tme_m68k_bus_16bit = 0;
1.1       root      583:     break;
                    584:   default:
                    585:     abort();
                    586:   }
                    587: 
                    588:   /* we have no bus connection yet: */
                    589:   ic->_tme_m68k_bus_connection = NULL;
                    590: 
                    591:   /* fill the element: */
                    592:   element = ic->tme_m68k_element;
                    593:   element->tme_element_private = ic;
                    594:   element->tme_element_connections_new = _tme_m68k_connections_new;
                    595: 
                    596:   /* calculate the instruction burst size: */
                    597:   /* XXX TBD: */
1.1.1.3   root      598:   ic->_tme_m68k_instruction_burst = 200;
1.1.1.2   root      599:   ic->_tme_m68k_instruction_burst_remaining
                    600:     = ic->_tme_m68k_instruction_burst;
1.1       root      601: 
1.1.1.3   root      602:   /* set the status register T bits mask: */
                    603:   ic->_tme_m68k_sr_mask_t
                    604:     = (TME_M68K_FLAG_T1
                    605:        | ((ic->tme_m68k_type >= TME_M68K_M68020)
                    606:          * TME_M68K_FLAG_T0));
                    607: 
                    608:   /* initialize the small immediates: */
                    609:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_ZERO) = 0;
                    610:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_ONE) = 1;
                    611:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_TWO) = 2;
                    612:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_THREE) = 3;
                    613:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_FOUR) = 4;
                    614:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_FIVE) = 5;
                    615:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_SIX) = 6;
                    616:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_SEVEN) = 7;
                    617:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_EIGHT) = 8;
                    618: 
1.1       root      619:   /* force the processor to be halted: */
                    620:   ic->_tme_m68k_mode = TME_M68K_MODE_HALT;
                    621:   TME_M68K_SEQUENCE_START;
                    622: 
                    623:   /* start the m68k thread: */
                    624:   tme_thread_create((tme_thread_t) tme_m68k_thread, ic);
                    625: 
                    626:   return (TME_OK);
                    627: }  
                    628: 
                    629: /* the common m68k reset function: */
                    630: void
                    631: tme_m68k_do_reset(struct tme_m68k *ic)
                    632: {
                    633:   
                    634:   /* force the VBR to zero: */
                    635:   ic->tme_m68k_ireg_vbr = 0;
                    636: 
1.1.1.3   root      637:   /* clear the E and F bits in the CACR: */
                    638:   ic->tme_m68k_ireg_cacr = 0;
                    639: 
1.1       root      640:   /* force supervisor mode, interrupts disabled: */
                    641:   tme_m68k_change_sr(ic, TME_M68K_FLAG_S | (7 << 8));
                    642: 
                    643:   /* load the initial SSP and PC: */
1.1.1.3   root      644:   ic->_tme_m68k_ea_function_code = TME_M68K_FC_SP;
1.1       root      645:   ic->_tme_m68k_ea_address = 0;
                    646:   tme_m68k_read_mem32(ic, TME_M68K_IREG_A7);
                    647:   ic->_tme_m68k_ea_address += sizeof(ic->tme_m68k_ireg_a7);
                    648:   tme_m68k_read_mem32(ic, TME_M68K_IREG_PC);
                    649: 
                    650:   /* clear all exceptions: */
                    651:   ic->_tme_m68k_exceptions = 0;
                    652: 
1.1.1.3   root      653:   /* reset the FPU: */
                    654:   tme_m68k_fpu_reset(ic);
                    655: 
1.1       root      656:   /* start execution: */
                    657:   ic->_tme_m68k_mode = TME_M68K_MODE_EXECUTION;
                    658:   TME_M68K_SEQUENCE_START;
                    659:   tme_m68k_redispatch(ic);
                    660: }
                    661: 
                    662: /* this returns nonzero iff the slow instruction executor must be
                    663:    used: */
                    664: int
                    665: tme_m68k_go_slow(const struct tme_m68k *ic)
                    666: {
1.1.1.5   root      667:   tme_bus_context_t bus_context;
                    668:   const struct tme_m68k_tlb *tlb;
1.1       root      669:   tme_uint32_t linear_pc;
1.1.1.4   root      670:   const tme_shared tme_uint8_t *emulator_load;
                    671:   const tme_shared tme_uint8_t *emulator_load_last;
1.1       root      672: 
1.1.1.5   root      673:   bus_context = ic->_tme_m68k_bus_context;
                    674:   tlb = &ic->_tme_m68k_itlb;
1.1.1.4   root      675:   emulator_load = tlb->tme_m68k_tlb_emulator_off_read;
                    676:   emulator_load_last = emulator_load;
                    677:   if (emulator_load != TME_EMULATOR_OFF_UNDEF) {
1.1.1.5   root      678:     emulator_load += (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first;
                    679:     emulator_load_last += (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last;
1.1.1.4   root      680:     assert (emulator_load <= emulator_load_last);
                    681:   }
1.1       root      682:   linear_pc = ic->tme_m68k_ireg_pc;
                    683:   return (
                    684:          
                    685:          /* the ITLB entry must support reads from emulator memory: */
1.1.1.5   root      686:          tme_m68k_tlb_is_invalid(tlb)
                    687:          || tlb->tme_m68k_tlb_bus_context != bus_context
                    688:          || (tlb->tme_m68k_tlb_function_codes_mask
                    689:              & TME_BIT(TME_M68K_FUNCTION_CODE_PROGRAM(ic))) == 0
                    690:          || linear_pc < (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
                    691:          || linear_pc > (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
                    692:          || tlb->tme_m68k_tlb_emulator_off_read == TME_EMULATOR_OFF_UNDEF
1.1       root      693: 
                    694:          /* the ITLB emulator memory must be 32-bit aligned for the
                    695:             benefit of the fast instruction word fetch macros, so
                    696:             that emulator address alignment goes with linear address
                    697:             alignment: */
                    698:          || (((unsigned long) tlb->tme_m68k_tlb_emulator_off_read)
                    699:              & (sizeof(tme_uint32_t) - 1))
                    700: 
1.1.1.4   root      701:          /* the ITLB emulator memory must not be so low that the
                    702:             first valid pointer minus one, or the last valid pointer
                    703:             minus (sizeof(tme_uint32_t) - 1), wraps around, nor so
                    704:             high that the last valid pointer, plus one, wraps around: */
                    705:          /* NB: this enables the fast instruction word fetch macros
                    706:             to simply fetch 16 and 32 bit values until fetch_fast_next
                    707:             is greater than ic->_tme_m68k_insn_fetch_fast_last, and 
                    708:             not have to do any pointer math or ever check for pointer
                    709:             wrapping: */
                    710:          || ((emulator_load
                    711:               - 1)
                    712:              >= emulator_load)
                    713:          || ((emulator_load_last
                    714:               - (sizeof(tme_uint32_t) - 1))
                    715:              >= emulator_load_last)
                    716:          || ((emulator_load_last
                    717:               + 1)
                    718:              <= emulator_load_last)
                    719: 
1.1       root      720:          /* the linear PC must be 16-bit aligned: */
                    721:          || (linear_pc & 1)
                    722: 
                    723:          /* there must be no tracing: */
1.1.1.3   root      724:          || (ic->tme_m68k_ireg_sr & ic->_tme_m68k_sr_mask_t) != 0);
1.1       root      725: }
                    726: 
                    727: /* this redispatches: */
                    728: void
                    729: tme_m68k_redispatch(struct tme_m68k *ic)
                    730: {
1.1.1.4   root      731:   struct tme_m68k_tlb *tlb;
                    732: 
                    733:   /* if we have a busy fast instruction TLB entry: */
                    734:   tlb = ic->_tme_m68k_insn_fetch_fast_itlb;
                    735:   if (__tme_predict_true(tlb != NULL)) {
                    736: 
                    737:     /* unbusy and forget the fast instruction TLB entry: */
                    738:     tme_m68k_tlb_unbusy(tlb);
                    739:     ic->_tme_m68k_insn_fetch_fast_itlb = NULL;
                    740:   }
                    741: 
                    742:   /* do the redispatch: */
1.1.1.3   root      743: #ifdef _TME_M68K_STATS
                    744:   ic->tme_m68k_stats.tme_m68k_stats_redispatches++;
                    745: #endif /* _TME_M68K_STATS */
1.1       root      746:   longjmp(ic->_tme_m68k_dispatcher, 1);
                    747: }
                    748: 
                    749: /* this fills a TLB entry: */
                    750: void
                    751: tme_m68k_tlb_fill(struct tme_m68k *ic, struct tme_m68k_tlb *tlb, 
                    752:                  unsigned int function_code, 
                    753:                  tme_uint32_t linear_address, 
                    754:                  unsigned int cycles)
                    755: {
                    756:   tme_uint32_t external_address;
                    757:   struct tme_bus_tlb tlb_internal;
                    758:   
1.1.1.3   root      759: #ifdef _TME_M68K_STATS
                    760:   if (function_code == TME_M68K_FC_UP
                    761:       || function_code == TME_M68K_FC_SP) {
                    762:     ic->tme_m68k_stats.tme_m68k_stats_itlb_fill++;
                    763:   }
                    764:   else {
                    765:     ic->tme_m68k_stats.tme_m68k_stats_dtlb_fill++;
                    766:   }
                    767: #endif /* _TME_M68K_STATS */
                    768: 
1.1       root      769:   /* when emulating a CPU with a 16-bit bus, only 24 bits of address
                    770:      are external: */
                    771:   external_address = linear_address;
                    772:   if (ic->_tme_m68k_bus_16bit) {
                    773:     external_address &= 0x00ffffff;
                    774:   }
                    775: 
1.1.1.5   root      776:   /* unbusy the TLB entry: */
                    777:   tme_m68k_tlb_unbusy(tlb);
1.1.1.4   root      778: 
1.1.1.5   root      779:   /* clear any invalid token: */
                    780:   tme_token_invalid_clear(&tlb->tme_m68k_tlb_token);
1.1.1.4   root      781: 
                    782:   /* unlock for the callout: */
                    783:   tme_m68k_callout_unlock(ic);
1.1.1.3   root      784: 
1.1       root      785:   /* fill the TLB entry: */
                    786:   (*ic->_tme_m68k_bus_connection->tme_m68k_bus_tlb_fill)
                    787:     (ic->_tme_m68k_bus_connection, tlb,
                    788:      function_code,
                    789:      external_address,
                    790:      cycles);
                    791: 
1.1.1.4   root      792:   /* relock after the callout: */
                    793:   tme_m68k_callout_relock(ic);
                    794: 
1.1.1.5   root      795:   /* set the context on the TLB entry: */
                    796:   tlb->tme_m68k_tlb_bus_context = ic->_tme_m68k_bus_context;
                    797: 
1.1.1.4   root      798:   /* rebusy the TLB entry: */
1.1.1.5   root      799:   tme_m68k_tlb_busy(tlb);
1.1.1.4   root      800: 
1.1       root      801:   /* if this code isn't 32-bit clean, we have to deal: */
                    802:   if (external_address != linear_address) {
1.1.1.4   root      803:     tlb_internal.tme_bus_tlb_addr_first
1.1.1.5   root      804:       = (((tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first)
1.1.1.4   root      805:         | (linear_address ^ external_address));
                    806:     tlb_internal.tme_bus_tlb_addr_last
1.1.1.5   root      807:       = (((tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last)
1.1.1.4   root      808:         | (linear_address ^ external_address));
1.1       root      809:     tlb_internal.tme_bus_tlb_cycles_ok = tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycles_ok;
                    810:     tme_bus_tlb_map(&tlb->tme_m68k_tlb_bus_tlb, external_address,
                    811:                    &tlb_internal, linear_address);
                    812:   }
                    813: }
                    814: 
                    815: /* this triggers exception processing: */
                    816: void
                    817: tme_m68k_exception(struct tme_m68k *ic, tme_uint32_t new_exceptions)
                    818: {
                    819:   assert(new_exceptions != 0);
                    820: 
                    821:   /* if the set of new exceptions includes a group zero exception: */
                    822:   if (new_exceptions & 
1.1.1.3   root      823:       (TME_M68K_EXCEPTION_RESET
                    824:        | TME_M68K_EXCEPTION_AERR
                    825:        | TME_M68K_EXCEPTION_BERR)) {
1.1       root      826:     
                    827:     /* there must be only one exception - you cannot trigger a group 0
                    828:        exception simultaneously with any other group 0, 1, or 2
                    829:        exception: */
                    830:     assert((new_exceptions & (new_exceptions - 1)) == 0);
                    831:     
                    832:     /* if this is a reset exception, it clears all other exceptions: */
1.1.1.3   root      833:     if (new_exceptions == TME_M68K_EXCEPTION_RESET) {
1.1       root      834:       ic->_tme_m68k_exceptions = 0;
                    835:     }
                    836: 
                    837:     /* otherwise, this is an address error or a bus error.  if we were
                    838:        already processing a group 0 exception, this is a
                    839:        double fault, and the processor enters the halted state: */
                    840:     else if (ic->_tme_m68k_exceptions &
1.1.1.3   root      841:             (TME_M68K_EXCEPTION_RESET
                    842:              | TME_M68K_EXCEPTION_AERR
                    843:              | TME_M68K_EXCEPTION_BERR)) {
                    844:       tme_log(TME_M68K_LOG_HANDLE(ic), 0, TME_OK,
                    845:              (TME_M68K_LOG_HANDLE(ic),
                    846:               _("double fault, processor halted")));
1.1       root      847:       ic->_tme_m68k_mode = TME_M68K_MODE_HALT;
                    848:       TME_M68K_SEQUENCE_START;
                    849:       tme_m68k_redispatch(ic);
                    850:     }
                    851:   }
                    852: 
                    853:   /* otherwise, exception processing must not already be happening: */
                    854:   else {
                    855:     assert(ic->_tme_m68k_exceptions == 0);
                    856:   }
                    857: 
                    858:   /* begin exception processing: */
                    859:   ic->_tme_m68k_exceptions |= new_exceptions;
                    860:   ic->_tme_m68k_mode = TME_M68K_MODE_EXCEPTION;
                    861:   TME_M68K_SEQUENCE_START;
                    862:   tme_m68k_redispatch(ic);
                    863: }
                    864: 
                    865: /* this changes SR, and swaps %a7 as needed: */
                    866: void
                    867: tme_m68k_change_sr(struct tme_m68k *ic, tme_uint16_t sr)
                    868: {
1.1.1.3   root      869:   tme_uint16_t flags_mode;
                    870: 
                    871:   /* only recognize the M bit on a 68020 or better: */
                    872:   flags_mode = (TME_M68K_FLAG_S
                    873:                | ((ic->tme_m68k_type >= TME_M68K_M68020)
                    874:                   * TME_M68K_FLAG_M));
1.1       root      875:   
                    876:   /* save %a7 in the proper stack pointer control register: */
1.1.1.3   root      877:   switch (ic->tme_m68k_ireg_sr & flags_mode) {
1.1       root      878:   case 0:
                    879:   case TME_M68K_FLAG_M:
                    880:     ic->tme_m68k_ireg_usp = ic->tme_m68k_ireg_a7;
                    881:     break;
                    882:   case TME_M68K_FLAG_S:
1.1.1.3   root      883:     ic->tme_m68k_ireg_isp = ic->tme_m68k_ireg_a7;
1.1       root      884:     break;
                    885:   case (TME_M68K_FLAG_S | TME_M68K_FLAG_M):
1.1.1.3   root      886:     ic->tme_m68k_ireg_msp = ic->tme_m68k_ireg_a7;
1.1       root      887:     break;
                    888:   }
                    889: 
                    890:   /* load %a7 from the proper stack pointer control register: */
                    891:   ic->tme_m68k_ireg_sr = sr;
1.1.1.3   root      892:   switch (ic->tme_m68k_ireg_sr & flags_mode) {
1.1       root      893:   case 0:
                    894:   case TME_M68K_FLAG_M:
                    895:     ic->tme_m68k_ireg_a7 = ic->tme_m68k_ireg_usp;
                    896:     break;
                    897:   case TME_M68K_FLAG_S:
1.1.1.3   root      898:     ic->tme_m68k_ireg_a7 = ic->tme_m68k_ireg_isp;
1.1       root      899:     break;
                    900:   case (TME_M68K_FLAG_S | TME_M68K_FLAG_M):
1.1.1.3   root      901:     ic->tme_m68k_ireg_a7 = ic->tme_m68k_ireg_msp;
1.1       root      902:     break;
                    903:   }
                    904: }
                    905: 
                    906: /* this starts processing an m68k exception: */
                    907: void
                    908: tme_m68k_exception_process_start(struct tme_m68k *ic, unsigned int ipl)
                    909: {
                    910:   tme_uint16_t sr;
                    911: 
                    912:   /* make an internal copy of the status register, then set S, clear
                    913:      T, and update I: */
                    914:   if (!TME_M68K_SEQUENCE_RESTARTING) {
                    915:     ic->tme_m68k_ireg_shadow_sr = ic->tme_m68k_ireg_sr;
1.1.1.3   root      916:     sr = (ic->tme_m68k_ireg_sr | TME_M68K_FLAG_S) & ~ic->_tme_m68k_sr_mask_t;
1.1       root      917:     if (ipl > TME_M68K_IPL_NONE) {
                    918:       assert(ipl == TME_M68K_IPL_NMI
                    919:             || ipl > TME_M68K_FLAG_IPM(sr));
                    920:       sr = (sr & ~(TME_M68K_IPL_MAX << 8)) | (ipl << 8);
                    921:     }
                    922:     tme_m68k_change_sr(ic, sr);
                    923:   }
                    924: }
                    925: 
                    926: /* this finishes processing an m68k exception: */
                    927: void
                    928: tme_m68k_exception_process_finish(struct tme_m68k *ic, tme_uint8_t format, tme_uint8_t vector)
                    929: {
                    930:   tme_uint16_t vector_offset;
                    931: 
                    932:   /* stack the frame format and vector offset, unless this is a 68000: */
                    933:   vector_offset = ((tme_uint16_t) vector) << 2;
                    934:   if (ic->tme_m68k_type != TME_M68K_M68000) {
                    935:     tme_m68k_push16(ic, (((tme_uint16_t) format) << 12) | vector_offset);
                    936:   }
                    937: 
                    938:   /* stack the program counter: */
                    939:   tme_m68k_push32(ic, ic->tme_m68k_ireg_pc);
                    940:   
                    941:   /* stack the internal copy of the status register: */
                    942:   tme_m68k_push16(ic, ic->tme_m68k_ireg_shadow_sr);
                    943: 
                    944:   /* do a bus cycle to read the vector into the program counter: */
                    945:   if (!TME_M68K_SEQUENCE_RESTARTING) {
1.1.1.3   root      946:     ic->_tme_m68k_ea_function_code = TME_M68K_FC_SD;
1.1       root      947:     ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_vbr + vector_offset;
                    948:   }
                    949:   tme_m68k_read_mem32(ic, TME_M68K_IREG_PC);
                    950: }
                    951: 
1.1.1.3   root      952: /* common m68000 and m68010 exception processing: */
1.1       root      953: void
1.1.1.3   root      954: tme_m68000_exception_process(struct tme_m68k *ic)
1.1       root      955: {
                    956:   tme_uint32_t exceptions;
1.1.1.3   root      957:   tme_uint8_t vector;
1.1       root      958: 
                    959:   /* get the set of exceptions.  we must have no group 0 exceptions: */
                    960:   exceptions = ic->_tme_m68k_exceptions;
1.1.1.3   root      961:   assert((exceptions & (TME_M68K_EXCEPTION_RESET
                    962:                        | TME_M68K_EXCEPTION_AERR
                    963:                        | TME_M68K_EXCEPTION_BERR)) == 0);
1.1       root      964: 
                    965:   /* these if statements are ordered to implement the priority
                    966:      relationship between the different exceptions as outlined in 
                    967:      the 68000 user's manual (pp 93 in my copy): */
                    968:   
1.1.1.3   root      969:   if (TME_M68K_EXCEPTION_IS_INST(exceptions)) {
1.1       root      970:     tme_m68k_exception_process_start(ic, 0);
1.1.1.3   root      971:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, TME_M68K_EXCEPTION_IS_INST(exceptions));
1.1       root      972:   }
                    973:   
1.1.1.3   root      974:   if (exceptions & TME_M68K_EXCEPTION_TRACE) {
1.1       root      975:     tme_m68k_exception_process_start(ic, 0);
1.1.1.3   root      976:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, TME_M68K_VECTOR_TRACE);
                    977:   }
                    978:   
                    979:   if (TME_M68K_EXCEPTION_IS_INT(exceptions)) {
                    980:     tme_m68k_exception_process_start(ic, TME_M68K_EXCEPTION_IS_INT(exceptions));
                    981:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, TME_M68K_EXCEPTION_INT_VEC(exceptions));
1.1       root      982:   }
                    983:   
1.1.1.3   root      984:   if (exceptions & TME_M68K_EXCEPTION_ILL) {
                    985:     if (TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 12, 4) == 0xa) {
                    986:       vector = TME_M68K_VECTOR_LINE_A;
                    987:     }
                    988:     else if (TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 12, 4) == 0xf) {
                    989:       vector = TME_M68K_VECTOR_LINE_F;
                    990:     }
                    991:     else {
                    992:       vector = TME_M68K_VECTOR_ILL;
                    993:     }
                    994:     tme_m68k_exception_process_start(ic, 0);
                    995:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, vector);
1.1       root      996:   }
                    997:   
1.1.1.3   root      998:   if (exceptions & TME_M68K_EXCEPTION_PRIV) {
1.1       root      999:     tme_m68k_exception_process_start(ic, 0);
1.1.1.3   root     1000:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, TME_M68K_VECTOR_TRACE);
1.1       root     1001:   }
                   1002:   
1.1.1.3   root     1003:   /* we have processed all exceptions - resume execution: */
                   1004:   ic->_tme_m68k_exceptions = 0;
                   1005:   ic->_tme_m68k_mode = TME_M68K_MODE_EXECUTION;
                   1006:   TME_M68K_SEQUENCE_START;
                   1007:   tme_m68k_redispatch(ic);
                   1008: }
                   1009: 
                   1010: /* common m68020 and later exception processing: */
                   1011: void
                   1012: tme_m68020_exception_process(struct tme_m68k *ic)
                   1013: {
                   1014:   tme_uint32_t exceptions;
                   1015:   tme_uint8_t vector;
                   1016:   struct {
                   1017:     tme_uint16_t tme_m68k_fmt1_sr;
                   1018:     tme_uint16_t tme_m68k_fmt1_pc_hi;
                   1019:     tme_uint16_t tme_m68k_fmt1_pc_lo;    
                   1020:     tme_uint16_t tme_m68k_fmt1_vector_offset;
                   1021:   } fmt1;
                   1022: 
                   1023:   /* get the set of exceptions.  we must have no group 0 or 1
                   1024:      exceptions: */
                   1025:   exceptions = ic->_tme_m68k_exceptions;
                   1026:   assert((exceptions & (TME_M68K_EXCEPTION_RESET
                   1027:                        | TME_M68K_EXCEPTION_AERR
                   1028:                        | TME_M68K_EXCEPTION_BERR)) == 0);
                   1029: 
                   1030:   /* these if statements are ordered to implement the priority
                   1031:      relationship between the different exceptions as outlined in 
                   1032:      the 68020 user's manual (pp 144 in my copy): */
                   1033:   
                   1034:   /* group 2 exceptions: */
                   1035:   if (TME_M68K_EXCEPTION_IS_INST(exceptions)) {
1.1       root     1036:     tme_m68k_exception_process_start(ic, 0);
1.1.1.3   root     1037: 
                   1038:     /* get the vector number: */
                   1039:     vector = TME_M68K_EXCEPTION_IS_INST(exceptions);
                   1040: 
                   1041:     /* of the group 2 exceptions, only the Format Error and TRAP #N
                   1042:        exceptions generate a format 0 stack frame.  the RTE mode code
                   1043:        and the TRAP instruction code are expected to have left
                   1044:        ic->tme_m68k_ireg_pc as the PC they want stacked: */
                   1045:     if (vector == TME_M68K_VECTOR_FORMAT
                   1046:        || (TME_M68K_VECTOR_TRAP_0 <= vector
                   1047:            && vector < (TME_M68K_VECTOR_TRAP_0 + 16))) {
                   1048:       tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, vector);
                   1049:     }
                   1050: 
                   1051:     /* all other group 2 exceptions generate a format 2 stack frame.
                   1052:        all code that can signal this exception is expected to have
                   1053:        left ic->tme_m68k_ireg_pc *and* ic->tme_m68k_ireg_pc_last as
                   1054:        the PCs they want stacked: */
                   1055:     else {
                   1056:       
                   1057:       /* stack the program counter of the instruction that caused the exception: */
                   1058:       tme_m68k_push32(ic, ic->tme_m68k_ireg_pc_last);
                   1059: 
                   1060:       /* finish with a format 2 stack frame: */
                   1061:       tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_2, vector);
                   1062:     }
                   1063:   }
                   1064: 
                   1065:   /* group 3 exceptions: */
                   1066:   if (exceptions & TME_M68K_EXCEPTION_ILL) {
                   1067:     if (TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 12, 4) == 0xa) {
                   1068:       vector = TME_M68K_VECTOR_LINE_A;
                   1069:     }
                   1070:     else if (TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 12, 4) == 0xf) {
                   1071:       vector = TME_M68K_VECTOR_LINE_F;
                   1072:     }
                   1073:     else {
                   1074:       vector = TME_M68K_VECTOR_ILL;
                   1075:     }
                   1076:     tme_m68k_exception_process_start(ic, 0);
                   1077:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, vector);
                   1078:   }
                   1079:   if (exceptions & TME_M68K_EXCEPTION_PRIV) {
                   1080:     tme_m68k_exception_process_start(ic, 0);
                   1081:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, TME_M68K_VECTOR_PRIV);
                   1082:   }
                   1083: 
                   1084:   /* group 4.1 exceptions: */
                   1085:   if (exceptions & TME_M68K_EXCEPTION_TRACE) {
                   1086:     tme_m68k_exception_process_start(ic, 0);
                   1087:     tme_m68k_push32(ic, ic->tme_m68k_ireg_pc_last);
                   1088:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_2, TME_M68K_VECTOR_TRACE);
                   1089:   }
                   1090:   
                   1091:   /* group 4.2 exceptions: */
                   1092:   if (TME_M68K_EXCEPTION_IS_INT(exceptions)) {
                   1093:     tme_m68k_exception_process_start(ic, TME_M68K_EXCEPTION_IS_INT(exceptions));
                   1094:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, TME_M68K_EXCEPTION_INT_VEC(exceptions));
                   1095: 
                   1096:     /* if the M-bit is set: */
                   1097:     if (ic->tme_m68k_ireg_sr & TME_M68K_FLAG_M) {
                   1098: 
                   1099:       /* make the throwaway four-word stack frame (format 1): */
                   1100:       fmt1.tme_m68k_fmt1_vector_offset = tme_htobe_u16((TME_M68K_FORMAT_1 << 12) | (TME_M68K_EXCEPTION_INT_VEC(exceptions) << 2));
                   1101:       fmt1.tme_m68k_fmt1_pc_lo = tme_htobe_u16((ic->tme_m68k_ireg_pc >>  0) & 0xffff);
                   1102:       fmt1.tme_m68k_fmt1_pc_hi = tme_htobe_u16((ic->tme_m68k_ireg_pc >> 16) & 0xffff);
                   1103:       fmt1.tme_m68k_fmt1_sr = tme_htobe_u16(ic->tme_m68k_ireg_sr);
                   1104: 
                   1105:       /* store the throwaway four-word stack frame on the interrupt stack: */
                   1106:       if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1107:        ic->_tme_m68k_ea_function_code = TME_M68K_FC_SD;
                   1108:        ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_isp - sizeof(fmt1);
                   1109:       }
                   1110:       tme_m68k_write_mem(ic, (tme_uint8_t *) &fmt1, sizeof(fmt1));
                   1111: 
                   1112:       /* move to the interrupt stack: */
                   1113:       ic->tme_m68k_ireg_isp -= sizeof(fmt1);
                   1114:       tme_m68k_change_sr(ic, ic->tme_m68k_ireg_sr & ~TME_M68K_FLAG_M);
                   1115:     }
1.1       root     1116:   }
                   1117:   
                   1118:   /* we have processed all exceptions - resume execution: */
                   1119:   ic->_tme_m68k_exceptions = 0;
                   1120:   ic->_tme_m68k_mode = TME_M68K_MODE_EXECUTION;
                   1121:   TME_M68K_SEQUENCE_START;
                   1122:   tme_m68k_redispatch(ic);
                   1123: }
                   1124: 
                   1125: /* this starts an m68k RTE: */
                   1126: tme_uint16_t
                   1127: tme_m68k_rte_start(struct tme_m68k *ic)
                   1128: {
                   1129: 
                   1130:   /* set up to read from the stack frame: */
1.1.1.3   root     1131:   if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1132:     ic->_tme_m68k_ea_function_code = TME_M68K_FC_SD;
                   1133:     ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_a7;
                   1134:   }
1.1       root     1135: 
                   1136:   /* read the stacked status register: */
                   1137:   tme_m68k_read_mem16(ic, TME_M68K_IREG_SHADOW_SR);
1.1.1.3   root     1138:   if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1139:     ic->_tme_m68k_ea_address += sizeof(ic->tme_m68k_ireg_shadow_sr);
                   1140:   }
1.1       root     1141: 
                   1142:   /* read the stacked PC: */
                   1143:   tme_m68k_read_mem32(ic, TME_M68K_IREG_PC_NEXT);
1.1.1.3   root     1144:   if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1145:     ic->_tme_m68k_ea_address += sizeof(ic->tme_m68k_ireg_pc_next);
                   1146:   }
1.1       root     1147: 
                   1148:   /* read the stacked format/offset word, unless this is a 68000: */
                   1149:   if (ic->tme_m68k_type != TME_M68K_M68000) {
                   1150:     tme_m68k_read_mem16(ic, TME_M68K_IREG_FORMAT_OFFSET);
1.1.1.3   root     1151:     if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1152:       ic->_tme_m68k_ea_address += sizeof(ic->tme_m68k_ireg_format_offset);
                   1153:     }
1.1       root     1154:   }
                   1155:   else {
                   1156:     ic->tme_m68k_ireg_format_offset = 0;
                   1157:   }
                   1158: 
                   1159:   /* return the frame format: */
                   1160:   return (ic->tme_m68k_ireg_format_offset >> 12);
                   1161: }
                   1162: 
                   1163: /* this finishes an m68k RTE: */
                   1164: void
                   1165: tme_m68k_rte_finish(struct tme_m68k *ic, tme_uint32_t format_extra)
                   1166: {
                   1167:   tme_uint32_t frame_size;
                   1168: 
                   1169:   /* calculate the total frame size.  the 68000 doesn't have a
                   1170:      format/status word: */
                   1171:   frame_size = (sizeof(ic->tme_m68k_ireg_shadow_sr)
                   1172:                + sizeof(ic->tme_m68k_ireg_pc_next)
                   1173:                + (ic->tme_m68k_type != TME_M68K_M68000
                   1174:                   ? sizeof(ic->tme_m68k_ireg_format_offset)
                   1175:                   : 0)
                   1176:                + format_extra);
                   1177:   assert((frame_size & 1) == 0);
                   1178: 
                   1179:   /* adjust the stack: */
                   1180:   ic->tme_m68k_ireg_a7 += frame_size;
                   1181:   
                   1182:   /* set the status register: */
                   1183:   tme_m68k_change_sr(ic, ic->tme_m68k_ireg_shadow_sr);
                   1184:                     
                   1185:   /* set the PC: */
                   1186:   ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
                   1187:   
                   1188:   /* redispatch: */
                   1189:   tme_m68k_redispatch(ic);
                   1190: }
                   1191: 
                   1192: /* this stores the group 0 sequence into a region of host memory.
                   1193:    this is used when preparing the state information to be stored
                   1194:    on the stack for a bus or address error: */
1.1.1.4   root     1195: unsigned int
1.1       root     1196: tme_m68k_sequence_empty(const struct tme_m68k *ic, tme_uint8_t *raw, unsigned int raw_avail)
                   1197: {
                   1198:   const struct _tme_m68k_sequence *sequence;
                   1199:   unsigned int raw_used;
                   1200:   
                   1201:   /* get the group 0 sequence: */
                   1202:   sequence = &ic->_tme_m68k_group0_sequence;
                   1203:   raw_used = 0;
                   1204: 
                   1205:   /* we use 8 bits for the mode (2 bits) and flags (6 bits): */
                   1206:   raw_used += sizeof(tme_uint8_t);
                   1207:   assert(raw_avail >= raw_used);
                   1208:   assert(sequence->_tme_m68k_sequence_mode < TME_BIT(2));
                   1209:   assert(sequence->_tme_m68k_sequence_mode_flags < TME_BIT(6));
                   1210:   *(raw++) = ((sequence->_tme_m68k_sequence_mode << 6)
                   1211:              | sequence->_tme_m68k_sequence_mode_flags);
                   1212:   
                   1213: 
                   1214:   /* we use 16 bits for the faulted memory transfer ordinal
                   1215:      (12 bits) and already-transferred byte count (4 bits): */
                   1216:   raw_used += sizeof(tme_uint16_t);
                   1217:   assert(raw_avail >= raw_used);
                   1218:   assert(sequence->_tme_m68k_sequence_transfer_faulted < TME_BIT(12));
                   1219:   assert(sequence->_tme_m68k_sequence_transfer_faulted_after < TME_BIT(4));
                   1220:   *(raw++) = sequence->_tme_m68k_sequence_transfer_faulted >> 4;
                   1221:   *(raw++) = ((sequence->_tme_m68k_sequence_transfer_faulted << 4)
                   1222:              | sequence->_tme_m68k_sequence_transfer_faulted_after);
                   1223: 
                   1224: #ifdef _TME_M68K_VERIFY
                   1225:   /* we use sizeof(_tme_m68k_sequence_uid) bytes for the sequence UID: */
                   1226:   raw_used += sizeof(sequence->_tme_m68k_sequence_uid);
                   1227:   assert(raw_avail >= raw_used);
                   1228:   memcpy(raw,
                   1229:         &sequence->_tme_m68k_sequence_uid,
                   1230:         sizeof(sequence->_tme_m68k_sequence_uid));
                   1231:   raw += sizeof(sequence->_tme_m68k_sequence_uid);
                   1232: #endif /* _TME_M68K_VERIFY */
                   1233: 
                   1234:   /* done: */
                   1235:   return (raw_used);
                   1236: }
                   1237: 
                   1238: /* this restores the group 0 sequence from a region of host memory.
                   1239:    this is used when reading the state information stored on the
                   1240:    stack for a bus or address error: */
1.1.1.4   root     1241: unsigned int
1.1       root     1242: tme_m68k_sequence_fill(struct tme_m68k *ic, const tme_uint8_t *raw, unsigned int raw_avail)
                   1243: {
                   1244:   struct _tme_m68k_sequence *sequence;
                   1245:   unsigned int raw_used;
                   1246:   
                   1247:   /* get the group 0 sequence: */
                   1248:   sequence = &ic->_tme_m68k_group0_sequence;
                   1249:   raw_used = 0;
                   1250: 
                   1251:   /* we used 8 bits for the mode (2 bits) and flags (6 bits): */
                   1252:   raw_used += sizeof(tme_uint8_t);
                   1253:   if (raw_avail < raw_used) {
1.1.1.4   root     1254:     return (0);
1.1       root     1255:   }
                   1256:   sequence->_tme_m68k_sequence_mode = *raw >> 6;
                   1257:   sequence->_tme_m68k_sequence_mode_flags = (*(raw++) & (TME_BIT(6) - 1));
                   1258: 
                   1259:   /* we used 16 bits for the faulted memory transfer ordinal
                   1260:      (12 bits) and already-transferred byte count (4 bits): */
                   1261:   raw_used += sizeof(tme_uint16_t);
                   1262:   if (raw_avail < raw_used) {
1.1.1.4   root     1263:     return (0);
1.1       root     1264:   }
                   1265:   sequence->_tme_m68k_sequence_transfer_faulted = 
                   1266:     (((tme_uint16_t) raw[0]) << 4)
                   1267:     | (raw[1] >> 4);
                   1268:   sequence->_tme_m68k_sequence_transfer_faulted_after = raw[1] & (TME_BIT(4) - 1);
                   1269:   raw += sizeof(tme_uint16_t);
                   1270: 
                   1271: #ifdef _TME_M68K_VERIFY
                   1272:   /* we used sizeof(_tme_m68k_sequence_uid) bytes for the sequence UID: */
                   1273:   raw_used += sizeof(sequence->_tme_m68k_sequence_uid);
                   1274:   if (raw_avail < raw_used) {
1.1.1.4   root     1275:     return (0);
1.1       root     1276:   }
                   1277:   memcpy(&sequence->_tme_m68k_sequence_uid,
                   1278:         raw,
                   1279:         sizeof(sequence->_tme_m68k_sequence_uid));
                   1280:   raw += sizeof(sequence->_tme_m68k_sequence_uid);
                   1281: #endif /* _TME_M68K_VERIFY */
                   1282: 
                   1283:   /* initialize this to one: */
                   1284:   sequence->_tme_m68k_sequence_transfer_next = 1;
                   1285: 
                   1286:   /* done: */
                   1287:   return (raw_used);
                   1288: }
                   1289: 
1.1.1.4   root     1290: /* this empties the instruction buffer into an exception frame: */
                   1291: unsigned int
                   1292: tme_m68k_insn_buffer_empty(const struct tme_m68k *ic, tme_uint8_t *raw, unsigned int raw_avail)
1.1       root     1293: {
1.1.1.4   root     1294:   unsigned int fetch_total;
                   1295:   
                   1296:   /* get the total number of bytes in the instruction buffer: */
                   1297:   fetch_total = ic->_tme_m68k_insn_fetch_slow_count_total;
1.1       root     1298: 
1.1.1.4   root     1299:   /* save the total number of bytes fetched into the instruction
                   1300:      buffer, the number of bytes in the instruction buffer fetched by
                   1301:      the fast executor, and then the instruction buffer itself: */
                   1302:   assert ((fetch_total % sizeof(tme_uint16_t)) == 0
                   1303:          && fetch_total <= (TME_M68K_INSN_WORDS_MAX * sizeof(tme_uint16_t)));
                   1304:   assert ((ic->_tme_m68k_insn_fetch_slow_count_fast % sizeof(tme_uint16_t)) == 0
                   1305:          && ic->_tme_m68k_insn_fetch_slow_count_fast <= fetch_total);
                   1306:   assert (raw_avail >= (sizeof(tme_uint8_t) + sizeof(tme_uint8_t) + fetch_total));
                   1307:   raw[0] = fetch_total;
                   1308:   raw[1] = ic->_tme_m68k_insn_fetch_slow_count_fast;
                   1309:   memcpy(raw + 2,
                   1310:         &ic->_tme_m68k_insn_fetch_buffer[0],
                   1311:         fetch_total);
                   1312:   
                   1313:   /* return the number of bytes we put in an exception frame: */
                   1314:   return (sizeof(tme_uint8_t) + sizeof(tme_uint8_t) + fetch_total);
                   1315: }
1.1       root     1316: 
1.1.1.4   root     1317: /* this fills the instruction buffer from an exception frame: */
                   1318: unsigned int
                   1319: tme_m68k_insn_buffer_fill(struct tme_m68k *ic, const tme_uint8_t *raw, unsigned int raw_avail)
                   1320: {
                   1321:   unsigned int fetch_total;
                   1322:   unsigned int fetch_fast;
1.1       root     1323: 
1.1.1.4   root     1324:   /* there must be at least two bytes in the exception frame: */
                   1325:   if (raw_avail >= (sizeof(tme_uint8_t) + sizeof(tme_uint8_t))) {
                   1326: 
                   1327:     /* restore the total number of bytes fetched into the instruction
                   1328:        buffer, and the number of bytes in the instruction buffer
                   1329:        fetched by the fast executor: */
                   1330:     fetch_total = raw[0];
                   1331:     fetch_fast = raw[1];
                   1332:     if ((fetch_total % sizeof(tme_uint16_t)) == 0
                   1333:        && fetch_total <= (TME_M68K_INSN_WORDS_MAX * sizeof(tme_uint16_t))
                   1334:        && (fetch_fast % sizeof(tme_uint16_t)) == 0
                   1335:        && fetch_fast <= fetch_total
                   1336:        && raw_avail >= (sizeof(tme_uint8_t) + sizeof(tme_uint8_t) + fetch_total)) {
                   1337: 
                   1338:       /* restore the total number of bytes fetched into the instruction
                   1339:         buffer, the number of bytes in the instruction buffer fetched by
                   1340:         the fast executor, and then the instruction buffer itself: */
                   1341:       ic->_tme_m68k_insn_fetch_slow_count_total = fetch_total;
                   1342:       ic->_tme_m68k_insn_fetch_slow_count_fast = fetch_fast;
                   1343:       memcpy(&ic->_tme_m68k_insn_fetch_buffer[0],
                   1344:             raw + 2,
                   1345:             fetch_total);
                   1346: 
                   1347:       /* return the number of bytes restored from the exception frame: */
                   1348:       return ((sizeof(tme_uint8_t) + sizeof(tme_uint8_t) + fetch_total));
1.1       root     1349:     }
                   1350:   }
                   1351: 
1.1.1.4   root     1352:   /* this exception frame is invalid: */
                   1353:   return (0);
                   1354: }
1.1       root     1355: 
1.1.1.4   root     1356: /* this unlocks data structures before a callout: */
                   1357: void
                   1358: tme_m68k_callout_unlock(struct tme_m68k *ic)
                   1359: {
                   1360:   struct tme_m68k_tlb *tlb;
                   1361: 
                   1362:   assert ((ic->_tme_m68k_mode == TME_M68K_MODE_EXECUTION)
                   1363:          || (ic->_tme_m68k_insn_fetch_fast_itlb == NULL));
                   1364: 
                   1365:   /* if we have a busy fast instruction TLB entry: */
                   1366:   tlb = ic->_tme_m68k_insn_fetch_fast_itlb;
                   1367:   if (tlb != NULL) {
                   1368: 
                   1369:     /* unbusy the fast instruction TLB entry: */
                   1370:     tme_m68k_tlb_unbusy(tlb);
                   1371:   }
                   1372: }
                   1373: 
                   1374: /* this relocks data structures after a callout: */
                   1375: void
                   1376: tme_m68k_callout_relock(struct tme_m68k *ic)
                   1377: {
                   1378:   struct tme_m68k_tlb *tlb;
1.1.1.5   root     1379:   tme_bus_context_t bus_context;
1.1.1.4   root     1380:   struct tme_m68k_tlb *tlb_now;
                   1381: 
                   1382:   assert ((ic->_tme_m68k_mode == TME_M68K_MODE_EXECUTION)
                   1383:          || (ic->_tme_m68k_insn_fetch_fast_itlb == NULL));
                   1384: 
                   1385:   /* if we have a busy fast instruction TLB entry: */
                   1386:   tlb = ic->_tme_m68k_insn_fetch_fast_itlb;
                   1387:   if (tlb != NULL) {
                   1388: 
                   1389:     /* rebusy the fast instruction TLB entry: */
                   1390:     tme_m68k_tlb_busy(tlb);
                   1391:       
1.1.1.5   root     1392:     /* get the bus context: */
                   1393:     bus_context = ic->_tme_m68k_bus_context;
                   1394: 
1.1.1.4   root     1395:     /* get what should be our instruction TLB entry now: */
1.1.1.5   root     1396:     tlb_now = &ic->_tme_m68k_itlb;
1.1.1.4   root     1397: 
1.1.1.5   root     1398:     /* if this instruction TLB entry has changed, is for the wrong
                   1399:        context, or is invalid: */
1.1.1.4   root     1400:     if (__tme_predict_false(tlb_now != tlb
1.1.1.5   root     1401:                            || tlb->tme_m68k_tlb_bus_context != bus_context
                   1402:                            || tme_m68k_tlb_is_invalid(tlb))) {
1.1.1.4   root     1403: 
                   1404:       /* poison ic->_tme_m68k_insn_fetch_fast_last so the fast
                   1405:         instruction executor fetch macros will fail: */
                   1406:       assert ((ic->_tme_m68k_insn_fetch_fast_next - 1) < ic->_tme_m68k_insn_fetch_fast_next);
                   1407:       ic->_tme_m68k_insn_fetch_fast_last = ic->_tme_m68k_insn_fetch_fast_next - 1;
                   1408:     }
                   1409:   }
1.1       root     1410: }
                   1411: 
                   1412: /* this is the group 0 fault hook for the fast executor: */
                   1413: void
                   1414: tme_m68k_group0_hook_fast(struct tme_m68k *ic)
                   1415: {
1.1.1.4   root     1416:   unsigned int fetch_fast;
1.1       root     1417: 
1.1.1.4   root     1418:   /* get the number of bytes in the instruction buffer.  they have all
                   1419:      been fetched by the fast executor: */
                   1420:   /* NB: it's possible for this to be zero: */
                   1421:   fetch_fast = (ic->_tme_m68k_insn_fetch_fast_next - ic->_tme_m68k_insn_fetch_fast_start);
                   1422:   assert ((fetch_fast % sizeof(tme_uint16_t)) == 0
                   1423:          && fetch_fast <= (TME_M68K_INSN_WORDS_MAX * sizeof(tme_uint16_t)));
                   1424:   ic->_tme_m68k_insn_fetch_slow_count_total = fetch_fast;
                   1425:   ic->_tme_m68k_insn_fetch_slow_count_fast = fetch_fast;
1.1       root     1426: }
                   1427: 
1.1.1.4   root     1428: /* this starts a read/modify/write cycle: */
                   1429: int
                   1430: tme_m68k_rmw_start(struct tme_m68k *ic,
                   1431:                   struct tme_m68k_rmw *rmw)
1.1       root     1432: {
1.1.1.5   root     1433:   tme_bus_context_t bus_context;
1.1.1.4   root     1434:   struct tme_m68k_tlb *tlbs_all[3];
                   1435:   int tlbs_busy[2];
1.1       root     1436:   struct tme_m68k_tlb *tlb;
1.1.1.4   root     1437:   struct tme_m68k_tlb *tlb_use;
                   1438:   unsigned int tlb_i;
                   1439:   unsigned int address_i;
                   1440:   unsigned int address_i_fill;
                   1441:   tme_uint32_t address;
                   1442:   unsigned int address_cycles[2];
                   1443:   unsigned int address_fills[2];
                   1444:   tme_uint32_t *buffer_reg;
                   1445:   int supported;
1.1       root     1446: 
1.1.1.4   root     1447:   /* if the user reran the cycle: */
1.1       root     1448:   if (TME_M68K_SEQUENCE_RESTARTING
                   1449:       && (ic->_tme_m68k_group0_buffer_read_softrr > 0
                   1450:          || ic->_tme_m68k_group0_buffer_write_softrr > 0)) {
1.1.1.4   root     1451: 
                   1452:     /* return failure: */
                   1453:     return (-1);
1.1       root     1454:   }
                   1455: 
                   1456:   /* we always rerun read/modify/write cycles in their entirety: */
                   1457:   ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted
                   1458:     = ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next - 1;
                   1459: 
1.1.1.4   root     1460:   /* we only support tas and cas, which have one address, and cas2,
                   1461:      which has two addresses: */
                   1462:   assert (rmw->tme_m68k_rmw_address_count == 1
                   1463:          || rmw->tme_m68k_rmw_address_count == 2);
                   1464: 
1.1.1.5   root     1465:   /* get the context that we will use to index TLB entries for this
                   1466:      instruction.  NB that this may be different from the context in
                   1467:      which the instruction eventually completes: */
                   1468:   bus_context = ic->_tme_m68k_bus_context;
1.1.1.4   root     1469: 
                   1470:   /* assume that we will only consider one TLB entry, for the first
                   1471:      address: */
1.1.1.5   root     1472:   tlbs_all[0] = TME_M68K_DTLB_ENTRY(ic,
                   1473:                                    bus_context,
                   1474:                                    ic->_tme_m68k_ea_function_code,
                   1475:                                    rmw->tme_m68k_rmw_addresses[0]);
1.1.1.4   root     1476:   tlbs_all[1] = NULL;
                   1477: 
                   1478:   /* if there are two addresses: */
                   1479:   if (rmw->tme_m68k_rmw_address_count == 2) {
                   1480: 
                   1481:     /* we will consider another TLB entry for the second address: */
1.1.1.5   root     1482:     tlbs_all[1] = TME_M68K_DTLB_ENTRY(ic,
                   1483:                                      bus_context,
                   1484:                                      ic->_tme_m68k_ea_function_code,
                   1485:                                      rmw->tme_m68k_rmw_addresses[1]);
1.1.1.4   root     1486: 
                   1487:     /* if the TLB entry for the second address collides with the TLB
                   1488:        entry for the first address: */
                   1489:     if (tlbs_all[1] == tlbs_all[0]) {
                   1490: 
                   1491:       /* we will instead consider an alternate TLB entry for the
                   1492:          second address: */
1.1.1.5   root     1493:       tlbs_all[1] = TME_M68K_DTLB_ENTRY(ic,
                   1494:                                        bus_context,
                   1495:                                        ic->_tme_m68k_ea_function_code,
                   1496:                                        (rmw->tme_m68k_rmw_addresses[1]
                   1497:                                         + TME_M68K_TLB_ADDRESS_BIAS(1)));
1.1.1.4   root     1498:       assert (tlbs_all[1] != tlbs_all[0]);
                   1499:     }
                   1500:   }
                   1501: 
                   1502:   /* make sure that the list of TLB entries to consider is terminated: */
                   1503:   tlbs_all[2] = NULL;
                   1504: 
                   1505:   /* none of the TLB entries to consider are busy: */
                   1506:   tlbs_busy[0] = FALSE;
                   1507:   tlbs_busy[1] = FALSE;
                   1508: 
                   1509:   /* the addresses aren't using any TLB entries yet: */
                   1510:   rmw->tme_m68k_rmw_tlbs[0] = NULL;
                   1511:   rmw->tme_m68k_rmw_tlbs[1] = NULL;
                   1512: 
                   1513:   /* we haven't done any slow reads for any addresses yet: */
                   1514:   rmw->tme_m68k_rmw_slow_reads[0] = FALSE;
                   1515:   rmw->tme_m68k_rmw_slow_reads[1] = FALSE;
                   1516: 
                   1517:   /* whenever we need to find a TLB entry to use for an address, we
                   1518:      always prefer one that allows both reading and writing, because
                   1519:      we hope that such a TLB entry allows both fast reading and fast
                   1520:      writing.
                   1521: 
                   1522:      if we can't find such a TLB entry initially, we try to fill a TLB
                   1523:      entry for writing (you can't fill a TLB entry for both reading
                   1524:      and writing), in the hopes that this gives us a TLB entry that
                   1525:      allows both fast reading and fast writing.  filling for writing
                   1526:      is important with some virtual memory hardware, and may actually
                   1527:      be required to enable writing.
                   1528: 
                   1529:      if this fill gives us a TLB entry that doesn't allow both fast
                   1530:      reading and fast writing, it actually might not allow reading at
                   1531:      all.  to check for this, we then try to fill a TLB entry for
                   1532:      reading.
                   1533: 
                   1534:      if we still don't have a TLB entry that allows both fast reading
                   1535:      and fast writing, we must at least have a TLB entry that allows
                   1536:      slow reading.  at this point we do a slow read to start a locked
                   1537:      read-modify-write cycle (unless this is a cas2, in which case we
                   1538:      do a normal slow read).
                   1539: 
                   1540:      we always want to return to the caller with a TLB entry that
                   1541:      allows writing, so after we do a slow read we do one more TLB
                   1542:      fill for writing.
                   1543: 
                   1544:      the first TLB fill we do for an address will be for writing, so
                   1545:      that is how we initialize an address' address_cycles mask: */
                   1546:   address_cycles[0] = TME_BUS_CYCLE_WRITE;
                   1547:   address_cycles[1] = TME_BUS_CYCLE_WRITE;
                   1548: 
                   1549:   /* we haven't filled TLBs for any addresses yet: */
                   1550:   address_fills[0] = 0;
                   1551:   address_fills[1] = 0;
                   1552: 
                   1553:   /* assume that we can support this instruction on the given memory: */
                   1554:   supported = TRUE;  
                   1555: 
                   1556:   /* loop forever: */
                   1557:   for (;;) {
                   1558: 
                   1559:     /* assume that no address needs a TLB fill: */
                   1560:     address_i_fill = rmw->tme_m68k_rmw_address_count;
                   1561: 
1.1.1.5   root     1562:     /* get the bus context for this iteration: */
                   1563:     bus_context = ic->_tme_m68k_bus_context;
                   1564: 
1.1.1.4   root     1565:     /* walk the addresses: */
                   1566:     address_i = 0;
                   1567:     do {
                   1568:       
                   1569:       /* get this address: */
                   1570:       address = rmw->tme_m68k_rmw_addresses[address_i];
                   1571: 
                   1572:       /* this address isn't using a TLB entry yet: */
                   1573:       tlb_use = NULL;
                   1574: 
                   1575:       /* walk the TLB entries we are considering: */
                   1576:       for (tlb_i = 0; 
                   1577:           (tlb = tlbs_all[tlb_i]) != NULL;
                   1578:           tlb_i++) {
                   1579: 
                   1580:        /* if this TLB entry isn't busy, busy it: */
                   1581:        if (!tlbs_busy[tlb_i]) {
1.1.1.5   root     1582:          tme_m68k_tlb_busy(tlb);
1.1.1.4   root     1583:          tlbs_busy[tlb_i] = TRUE;
                   1584:        }
                   1585: 
1.1.1.5   root     1586:        /* if this TLB entry is valid, applies to this context, function code
1.1.1.4   root     1587:           and address, and allows at least the desired cycle(s), and
                   1588:           either this address isn't already using a TLB entry, or the
                   1589:           TLB entry it's using doesn't cover the entire operand, or
                   1590:           this TLB entry allows more cycles or allows both fast
                   1591:           reading and fast writing: */
1.1.1.5   root     1592:        if (tme_m68k_tlb_is_valid(tlb)
                   1593:            && tlb->tme_m68k_tlb_bus_context == bus_context
1.1.1.4   root     1594:            && (tlb->tme_m68k_tlb_function_codes_mask
                   1595:                & TME_BIT(ic->_tme_m68k_ea_function_code)) != 0
1.1.1.5   root     1596:            && address >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
                   1597:            && address <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
1.1.1.4   root     1598:            && (tlb->tme_m68k_tlb_cycles_ok
                   1599:                & address_cycles[address_i]) != 0
                   1600:            && (tlb_use == NULL
1.1.1.5   root     1601:                || (((tme_bus_addr32_t) tlb_use->tme_m68k_tlb_linear_last) - address) < rmw->tme_m68k_rmw_size
1.1.1.4   root     1602:                || tlb->tme_m68k_tlb_cycles_ok > tlb_use->tme_m68k_tlb_cycles_ok
                   1603:                || (tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF
                   1604:                    && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF))) {
                   1605: 
                   1606:          /* update the TLB entry this address is using: */
                   1607:          tlb_use = tlb;
                   1608:        }
                   1609:       }
                   1610: 
                   1611:       /* set the TLB entry being used by this address: */
                   1612:       rmw->tme_m68k_rmw_tlbs[address_i] = tlb_use;
1.1       root     1613: 
1.1.1.4   root     1614:       /* if this address is not using any TLB entry: */
                   1615:       if (tlb_use == NULL) {
                   1616: 
                   1617:        /* we need to fill a TLB entry for this address: */
                   1618:        address_i_fill = address_i;
                   1619:       }
                   1620: 
                   1621:     } while (++address_i < rmw->tme_m68k_rmw_address_count);
                   1622: 
                   1623:     /* if we need to fill a TLB entry for an address: */
                   1624:     address_i = address_i_fill;
                   1625:     if (address_i < rmw->tme_m68k_rmw_address_count) {
                   1626: 
                   1627:       /* get this address: */
                   1628:       address = rmw->tme_m68k_rmw_addresses[address_i];
                   1629: 
                   1630:       /* get an unused TLB entry to fill: */
                   1631:       tlb_i = 0;
                   1632:       tlb = tlbs_all[0];
                   1633:       if (tlb == rmw->tme_m68k_rmw_tlbs[!address_i]) {
                   1634:        tlb_i = 1;
                   1635:        tlb = tlbs_all[1];
                   1636:       }
                   1637:       assert (tlb != NULL
                   1638:              && tlb != rmw->tme_m68k_rmw_tlbs[!address_i]);
                   1639: 
                   1640:       /* NB: cas2 can need two TLB entries.  we may find one good TLB
                   1641:         entry for one address, but need to call out to fill a TLB for
                   1642:         the second address, and unfortunately we have to unbusy the
                   1643:         good one while we're doing the fill.  while the good one is
                   1644:         unbusy, it can be invalidated, and we'll have to fill it
                   1645:         again, unbusying the good one we just filled, possibly
                   1646:         leading to a vicious cycle.
                   1647: 
                   1648:         it's also possible that the TLB entry we fill here could be
                   1649:         invalidated after it's been filled and before we've busied it
                   1650:         again.  this is also the case for the single-TLB operations:
                   1651:         normal memory reads and writes, and tas and cas, and to
                   1652:         handle that we simply loop around the fill.  since these
                   1653:         operations only use a single TLB entry, we assume that there
                   1654:         won't be a vicious cycle - that eventually a single filled
                   1655:         TLB entry will stay valid until we can busy it and use it.
                   1656: 
                   1657:         but we can't really guarantee this for two TLB entries.
                   1658:         there's not much we can do about this, except put a limit on
                   1659:         the number of times we will fill for each address.  this
                   1660:         limit is somewhat arbitrary: */
                   1661:       /* XXX FIXME - this should be a macro, or a per-m68k argument: */
                   1662:       if (rmw->tme_m68k_rmw_address_count == 2
                   1663:          && address_fills[address_i]++ >= 20) {
                   1664: 
                   1665:        /* we can't support this instruction on this memory: */
                   1666:        supported = FALSE;
                   1667:        break;
                   1668:       }
                   1669: 
                   1670:       /* if the other TLB entry is busy, unbusy it: */
                   1671:       if (tlbs_busy[!tlb_i]) {
1.1.1.5   root     1672:        tme_m68k_tlb_unbusy(tlbs_all[tlb_i]);
1.1.1.4   root     1673:        tlbs_busy[!tlb_i] = FALSE;
                   1674:       }
                   1675: 
                   1676:       /* fill this TLB entry: */
                   1677:       tme_m68k_tlb_fill(ic,
                   1678:                        tlb,
                   1679:                        ic->_tme_m68k_ea_function_code,
                   1680:                        address,
                   1681:                        address_cycles[address_i]);
                   1682: 
                   1683:       /* restart: */
                   1684:       continue;
                   1685:     }
                   1686: 
                   1687:     /* walk the addresses: */
                   1688:     address_i = 0;
                   1689:     do {
                   1690: 
                   1691:       /* get this address and its TLB entry: */
                   1692:       address = rmw->tme_m68k_rmw_addresses[address_i];
                   1693:       tlb = rmw->tme_m68k_rmw_tlbs[address_i];
                   1694: 
                   1695:       /* if this TLB entry doesn't cover the entire operand: */
1.1.1.5   root     1696:       if ((((tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last) - address) < rmw->tme_m68k_rmw_size) {
1.1.1.4   root     1697: 
                   1698:        /* we can't support this instruction on this memory, because
                   1699:           we can't split an atomic operation across TLB entries.  on
                   1700:           a real m68k, the CPU can do repeated bus cycles under one
                   1701:           bus lock: */
                   1702:        supported = FALSE;
                   1703:        break;
                   1704:       }
                   1705: 
                   1706:       /* if this TLB entry supports both fast reading and fast
                   1707:          writing: */
                   1708:       if (tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF
                   1709:          && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF) {
                   1710: 
                   1711:        /* if fast reading and fast writing aren't to the same memory: */
                   1712:        if (tlb->tme_m68k_tlb_emulator_off_read
                   1713:            != tlb->tme_m68k_tlb_emulator_off_write) {
                   1714:          
                   1715:          /* we can't support this instruction on this memory, because
                   1716:             we can't split an atomic operation across two memories.
                   1717:             on a real m68k, the CPU can do repeated bus cycles under
                   1718:             one bus lock: */
                   1719:          supported = FALSE;
                   1720:          break;
                   1721:        }
                   1722:       }
                   1723: 
                   1724:       /* otherwise, this TLB entry does not support both fast reading
                   1725:         and fast writing: */
                   1726: 
                   1727:       /* if we have already done a slow read for this address: */
                   1728:       else if (rmw->tme_m68k_rmw_slow_reads[address_i]) {
                   1729: 
                   1730:        /* this TLB entry must support writing: */
                   1731:        assert (tlb->tme_m68k_tlb_cycles_ok & TME_BUS_CYCLE_WRITE);
                   1732: 
                   1733:        /* nothing to do: */
                   1734:       }
                   1735: 
                   1736:       /* otherwise, we have not already done a slow read for this
                   1737:          address: */
                   1738: 
                   1739:       /* if this TLB entry doesn't support slow reading: */
                   1740:       else if ((tlb->tme_m68k_tlb_cycles_ok & TME_BUS_CYCLE_READ) == 0) {
                   1741: 
                   1742:        /* we must fill a TLB entry for reading: */
                   1743:        assert (address_cycles[address_i] == TME_BUS_CYCLE_WRITE);
                   1744:        address_cycles[address_i] = TME_BUS_CYCLE_READ;
                   1745: 
                   1746:        /* restart: */
                   1747:        break;
                   1748:       }
                   1749: 
                   1750:       /* otherwise, this TLB entry does support slow reading: */
                   1751:       else {
                   1752: 
                   1753:        /* if the other TLB entry is busy, unbusy it: */
                   1754:        tlb_i = (tlb == tlbs_all[1]);
                   1755:        if (tlbs_busy[!tlb_i]) {
1.1.1.5   root     1756:          tme_m68k_tlb_unbusy(tlbs_all[tlb_i]);
1.1.1.4   root     1757:          tlbs_busy[!tlb_i] = FALSE;
                   1758:        }
                   1759: 
                   1760:        /* this instruction can fault: */
                   1761:        TME_M68K_INSN_CANFAULT;
                   1762: 
                   1763:        /* do a slow read.  if this is the first address, we start a
                   1764:           slow read-modify-write cycle, otherwise we do a normal slow
                   1765:           read cycle: */
                   1766:        assert (rmw->tme_m68k_rmw_size <= sizeof(ic->tme_m68k_ireg_memx32));
                   1767:        tme_m68k_read(ic,
                   1768:                      tlb,
                   1769:                      &ic->_tme_m68k_ea_function_code,
                   1770:                      &rmw->tme_m68k_rmw_addresses[address_i],
                   1771:                      (((tme_uint8_t *) 
                   1772:                        (address_i == 0
                   1773:                         ? &ic->tme_m68k_ireg_memx32
                   1774:                         : &ic->tme_m68k_ireg_memy32))
                   1775:                       + (TME_ENDIAN_NATIVE == TME_ENDIAN_BIG
                   1776:                          ? (sizeof(ic->tme_m68k_ireg_memx32)
                   1777:                             - rmw->tme_m68k_rmw_size)
                   1778:                          : 0)),
                   1779:                      rmw->tme_m68k_rmw_size,
                   1780:                      (address_i == 0
                   1781:                       ? TME_M68K_BUS_CYCLE_RMW
                   1782:                       : TME_M68K_BUS_CYCLE_NORMAL));
                   1783: 
                   1784:        /* we have done a slow read for this address: */
                   1785:        rmw->tme_m68k_rmw_slow_reads[address_i] = TRUE;
                   1786: 
                   1787:        /* now we need a TLB entry for this address that supports writing: */
                   1788:        address_cycles[address_i] = TME_BUS_CYCLE_WRITE;
                   1789: 
                   1790:        /* restart: */
                   1791:        break;
                   1792:       }
                   1793: 
                   1794:     } while (++address_i < rmw->tme_m68k_rmw_address_count);
                   1795: 
                   1796:     /* if this instruction is not supported or we've handled all
                   1797:        addresses, stop now: */
                   1798:     if (!supported
                   1799:        || address_i >= rmw->tme_m68k_rmw_address_count) {
                   1800:       break;
                   1801:     }
                   1802:   }
                   1803: 
                   1804:   /* unbusy any TLB entries that aren't being used: */
                   1805:   if (tlbs_busy[0]
                   1806:       && (!supported
                   1807:          || (tlbs_all[0] != rmw->tme_m68k_rmw_tlbs[0]
                   1808:              && tlbs_all[0] != rmw->tme_m68k_rmw_tlbs[1]))) {
1.1.1.5   root     1809:     tme_m68k_tlb_unbusy(tlbs_all[0]);
1.1.1.4   root     1810:   }
                   1811:   if (tlbs_busy[1]
                   1812:       && (!supported
                   1813:          || (tlbs_all[1] != rmw->tme_m68k_rmw_tlbs[0]
                   1814:              && tlbs_all[1] != rmw->tme_m68k_rmw_tlbs[1]))) {
1.1.1.5   root     1815:     tme_m68k_tlb_unbusy(tlbs_all[1]);
1.1.1.4   root     1816:   }
                   1817: 
                   1818:   /* if this instruction is not supported on this memory: */
                   1819:   if (!supported) {
                   1820: 
                   1821:     /* cause an illegal instruction exception: */
                   1822:     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
                   1823:   }
                   1824: 
                   1825:   /* if this is the cas2 instruction: */
                   1826:   if (rmw->tme_m68k_rmw_address_count == 2) {
                   1827: 
                   1828:     /* cas2 is a difficult instruction to emulate, since it accesses
                   1829:        two different addresses during one atomic read-modify-write
                   1830:        cycle.
                   1831: 
                   1832:        most host CPUs can't do this, so when threads are not
                   1833:        cooperative, we're forced to suspend all other threads when
                   1834:        running a cas2 instruction: */
                   1835:     if (!TME_THREADS_COOPERATIVE) {
                   1836:       tme_thread_suspend_others();
                   1837:     }
                   1838: 
                   1839:     /* the cas2 functions also assume that we have read all operands
                   1840:        into the memory buffers, which means we have to fast-read any
                   1841:        addresses that we haven't already slow-read: */
                   1842:     address_i = 0;
                   1843:     do {
                   1844: 
                   1845:       /* skip this address if we really did slow read it: */
                   1846:       if (rmw->tme_m68k_rmw_slow_reads[address_i]) {
                   1847:        continue;
                   1848:       }
                   1849: 
                   1850:       /* get this address and its TLB entry: */
                   1851:       address = rmw->tme_m68k_rmw_addresses[address_i];
                   1852:       tlb = rmw->tme_m68k_rmw_tlbs[address_i];
                   1853: 
                   1854:       /* this TLB entry must support fast reading and fast writing: */
                   1855:       assert (tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF
                   1856:              && tlb->tme_m68k_tlb_emulator_off_write == tlb->tme_m68k_tlb_emulator_off_read);
                   1857: 
                   1858:       /* do the fast read.  all other threads are suspended here, so
                   1859:         we can do a memcpy instead of an atomic read: */
                   1860:       assert (rmw->tme_m68k_rmw_size <= sizeof(ic->tme_m68k_ireg_memx32));
                   1861:       buffer_reg
                   1862:        = (address_i == 0
                   1863:           ? &ic->tme_m68k_ireg_memx32
                   1864:           : &ic->tme_m68k_ireg_memy32);
                   1865:       memcpy((((tme_uint8_t *) buffer_reg)
                   1866:              + (sizeof(ic->tme_m68k_ireg_memx32)
                   1867:                 - rmw->tme_m68k_rmw_size)),
                   1868:             (((tme_uint8_t *)
                   1869:               tlb->tme_m68k_tlb_emulator_off_read)
                   1870:              + address),
                   1871:             rmw->tme_m68k_rmw_size);
                   1872: 
                   1873:       /* byteswap the value read: */
                   1874:       *buffer_reg = tme_betoh_u32(*buffer_reg);
                   1875:     
                   1876:     } while (++address_i < rmw->tme_m68k_rmw_address_count);
                   1877:   }
                   1878: 
                   1879:   /* return success: */
                   1880:   return (0);
                   1881: }
                   1882: 
                   1883: /* this finishes a read/modify/write cycle: */
1.1       root     1884: void
1.1.1.4   root     1885: tme_m68k_rmw_finish(struct tme_m68k *ic, 
                   1886:                    struct tme_m68k_rmw *rmw,
                   1887:                    int do_write)
1.1       root     1888: {
1.1.1.4   root     1889:   struct tme_m68k_tlb *tlbs_all[2];
                   1890:   int tlbs_busy[2];
                   1891:   struct tme_m68k_tlb *tlb;
                   1892:   unsigned int tlb_i;
                   1893:   unsigned int address_i;
                   1894:   tme_uint32_t address;
                   1895:   int supported;
                   1896:   tme_uint32_t *buffer_reg;
                   1897: 
                   1898:   /* recover the tlbs_all[] array and tlbs_busy[] information: */
                   1899:   tlbs_all[0] = rmw->tme_m68k_rmw_tlbs[0];
                   1900:   tlbs_busy[0] = TRUE;
                   1901:   if (rmw->tme_m68k_rmw_tlbs[1] != NULL
                   1902:       && rmw->tme_m68k_rmw_tlbs[1] != rmw->tme_m68k_rmw_tlbs[0]) {
                   1903:     tlbs_all[1] = rmw->tme_m68k_rmw_tlbs[1];
                   1904:     tlbs_busy[1] = TRUE;
                   1905:   }
                   1906:   else {
                   1907:     tlbs_all[1] = NULL;
                   1908:     tlbs_busy[1] = FALSE;
                   1909:   }
                   1910: 
                   1911:   /* assume that this instruction is supported: */
                   1912:   supported = TRUE;
                   1913: 
                   1914:   /* loop over the addresses: */
                   1915:   address_i = 0;
                   1916:   do {
                   1917: 
                   1918:     /* get this address and TLB entry: */
                   1919:     address = rmw->tme_m68k_rmw_addresses[address_i];
                   1920:     tlb = rmw->tme_m68k_rmw_tlbs[address_i];
                   1921: 
                   1922:     /* get the buffer for this address: */
                   1923:     buffer_reg
                   1924:       = (address_i == 0
                   1925:         ? &ic->tme_m68k_ireg_memx32
                   1926:         : &ic->tme_m68k_ireg_memy32);
                   1927: 
                   1928:     /* if we did a slow read for this operand: */
                   1929:     if (rmw->tme_m68k_rmw_slow_reads[address_i]) {
                   1930: 
                   1931:       /* if the other TLB entry is busy, unbusy it: */
                   1932:       tlb_i = (tlb == tlbs_all[1]);
                   1933:       if (tlbs_busy[!tlb_i]) {
1.1.1.5   root     1934:        tme_m68k_tlb_unbusy(tlbs_all[tlb_i]);
1.1.1.4   root     1935:        tlbs_busy[!tlb_i] = FALSE;
                   1936:       }
                   1937: 
                   1938:       /* do the slow write for this operand: */
                   1939:       assert (rmw->tme_m68k_rmw_size <= sizeof(ic->tme_m68k_ireg_memx32));
                   1940:       tme_m68k_write(ic,
                   1941:                     tlb,
                   1942:                     &ic->_tme_m68k_ea_function_code,
                   1943:                     &rmw->tme_m68k_rmw_addresses[address_i],
                   1944:                     (((tme_uint8_t *) buffer_reg)
                   1945:                      + (TME_ENDIAN_NATIVE == TME_ENDIAN_BIG
                   1946:                         ? (sizeof(ic->tme_m68k_ireg_memx32)
                   1947:                            - rmw->tme_m68k_rmw_size)
                   1948:                         : 0)),
                   1949:                     rmw->tme_m68k_rmw_size,
                   1950:                     (address_i == 0
                   1951:                      ? TME_M68K_BUS_CYCLE_RMW
                   1952:                      : TME_M68K_BUS_CYCLE_NORMAL));
                   1953: 
                   1954:       /* if this is the cas2 instruction: */
                   1955:       if (rmw->tme_m68k_rmw_address_count == 2) {
                   1956: 
                   1957:        /* if a cas2 slow write doesn't fault, it just did a slow
                   1958:           write to device memory, which is actually bad because we
                   1959:           can't do an atomic cas2 involving any device memory at all
                   1960:           (we can't do the dual reads and dual writes all atomically).
                   1961: 
                   1962:           we tried to do the slow write anyways hoping that the slow
                   1963:           write was really to write-protected memory that would
                   1964:           fault, and when we would restart this address would point
                   1965:           to fast-writable memory.
                   1966: 
                   1967:           unfortunately, we can't undo the slow write.  we do cause
                   1968:           an illegal instruction exception, to make this problem
                   1969:           visible: */
                   1970:        supported = FALSE;
                   1971:        break;
                   1972:       }
                   1973:     }
                   1974: 
                   1975:     /* otherwise, if this is the cas2 instruction, and we're writing: */
                   1976:     else if (rmw->tme_m68k_rmw_address_count == 2
                   1977:             && do_write) {
                   1978: 
                   1979:       /* this TLB entry must support fast reading and fast writing: */
                   1980:       assert (tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF
                   1981:              && tlb->tme_m68k_tlb_emulator_off_write == tlb->tme_m68k_tlb_emulator_off_read);
                   1982: 
                   1983:       /* byteswap the value to write: */
                   1984:       *buffer_reg = tme_htobe_u32(*buffer_reg);
                   1985: 
                   1986:       /* do the fast write.  all other threads are suspended here, so
                   1987:         we can do a memcpy instead of an atomic write: */
                   1988:       assert (rmw->tme_m68k_rmw_size <= sizeof(ic->tme_m68k_ireg_memx32));
                   1989:       memcpy((((tme_uint8_t *)
                   1990:               tlb->tme_m68k_tlb_emulator_off_read)
                   1991:              + address),
                   1992:             (((tme_uint8_t *) buffer_reg)
                   1993:              + (sizeof(ic->tme_m68k_ireg_memx32)
                   1994:                 - rmw->tme_m68k_rmw_size)),
                   1995:             rmw->tme_m68k_rmw_size);
                   1996:     }
                   1997: 
                   1998:   } while (++address_i < rmw->tme_m68k_rmw_address_count);
                   1999: 
                   2000:   /* unbusy all TLB entries: */
                   2001:   if (tlbs_busy[0]) {
1.1.1.5   root     2002:     tme_m68k_tlb_unbusy(tlbs_all[0]);
1.1.1.4   root     2003:   }
                   2004:   if (tlbs_busy[1]) {
1.1.1.5   root     2005:     tme_m68k_tlb_unbusy(tlbs_all[1]);
1.1.1.4   root     2006:   }
                   2007: 
                   2008:   /* cas2 is a difficult instruction to emulate, since it accesses two
                   2009:      different addresses during one atomic read-modify-write cycle.
                   2010:      most host CPUs can't do this, so when threads are not
                   2011:      cooperative, we're forced to suspend all other threads when
                   2012:      running a cas2 instruction: */
                   2013:   if (!TME_THREADS_COOPERATIVE
                   2014:       && rmw->tme_m68k_rmw_address_count > 1) {
                   2015:     tme_thread_resume_others();
                   2016:   }
                   2017: 
                   2018:   /* if this instruction is not supported on this memory: */
                   2019:   if (!supported) {
                   2020: 
                   2021:     /* cause an illegal instruction exception: */
                   2022:     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
                   2023:   }
1.1       root     2024: }
                   2025: 
                   2026: /* this handles a bitfield offset.  if the bitfield is in memory,
                   2027:    and it hasn't already been done, this adjusts the effective
                   2028:    address to point to the beginning of the bitfield.  this always
                   2029:    returns a nonnegative bitfield offset: */
                   2030: unsigned int
                   2031: tme_m68k_bitfield_offset(struct tme_m68k *ic, int adjust)
                   2032: {
                   2033:   tme_int16_t specop;
                   2034:   tme_int32_t bf_offset;
                   2035:   tme_int32_t bf_ea_offset;
                   2036:     
                   2037:   /* get the bitfield offset from a data register or as an immediate: */
                   2038:   specop = ic->_tme_m68k_insn_specop;
                   2039:   bf_offset = ((specop & TME_BIT(11))
                   2040:               ? ic->tme_m68k_ireg_int32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop, 6, 3))
                   2041:               : (tme_int32_t) TME_FIELD_EXTRACTU(specop, 6, 5));
                   2042: 
                   2043:   /* if this bitfield is in a register (EA mode field is zero): */
                   2044:   if (TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 3, 3) == 0) {
                   2045: 
                   2046:     /* adjust the bitfield offset to be nonnegative: */
                   2047:     bf_offset &= 31;
                   2048:   }
                   2049: 
                   2050:   /* otherwise, this bitfield is in memory: */
                   2051:   else {
                   2052: 
                   2053:     /* calculate the effective address offset and adjust the bitfield
                   2054:        offset to be nonnegative: */
1.1.1.3   root     2055:     bf_ea_offset = ((bf_offset < 0
                   2056:                     ? (bf_offset - 7)
                   2057:                     : bf_offset)
                   2058:                    / 8);
1.1       root     2059:     bf_offset &= 7;
                   2060: 
                   2061:     /* if this is our first call to this function for this instruction
                   2062:        and we're not restarting, adjust the effective address: */
                   2063:     if (adjust
                   2064:        && !TME_M68K_SEQUENCE_RESTARTING) {
                   2065:       ic->_tme_m68k_ea_address += bf_ea_offset;
                   2066:     }
                   2067:   }
                   2068: 
                   2069:   /* return the nonnegative bitfield offset: */
                   2070:   return ((unsigned int) bf_offset);
                   2071: }
                   2072: 
                   2073: /* this returns a bitfield width: */
                   2074: unsigned int
                   2075: tme_m68k_bitfield_width(struct tme_m68k *ic)
                   2076: {
                   2077:   unsigned int bf_width;
                   2078:   tme_int16_t specop;
                   2079: 
                   2080:   /* get the bitfield width from a register or as an immediate: */
                   2081:   specop = ic->_tme_m68k_insn_specop;
                   2082:   if (specop & TME_BIT(5)) {
                   2083:     bf_width = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop, 0, 3));
1.1.1.3   root     2084:     bf_width &= 31;
1.1       root     2085:   }
                   2086:   else {
                   2087:     bf_width = TME_FIELD_EXTRACTU(specop, 0, 5);
                   2088:   }
                   2089:   if (bf_width == 0) bf_width = 32;
                   2090:   return (bf_width);
                   2091: }
                   2092: 
                   2093: /* this reads a bitfield: */
                   2094: tme_uint32_t
                   2095: _tme_m68k_bitfield_read(struct tme_m68k *ic, int is_signed)
                   2096: {
                   2097:   unsigned int bf_offset, bf_width;
                   2098:   unsigned int shift;
                   2099:   tme_uint8_t *bf_bytes;
                   2100:   tme_uint32_t bf_value;
                   2101:   int ireg;
                   2102: 
                   2103:   /* get the bitfield offset and width: */
                   2104:   bf_offset = tme_m68k_bitfield_offset(ic, TRUE);
                   2105:   bf_width = tme_m68k_bitfield_width(ic);
                   2106: 
                   2107:   /* if this expression is > 32, in a register this means the bitfield
1.1.1.3   root     2108:      wraps, and in memory this means the bitfield covers 5 bytes: */
1.1       root     2109:   shift = (bf_offset + bf_width);
                   2110: 
                   2111:   /* if this bitfield is in a register (EA mode field is zero): */
                   2112:   if (TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 3, 3) == 0) {
                   2113:     ireg = (TME_M68K_IREG_D0
                   2114:            + TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 0, 3));
                   2115: 
                   2116:     /* get the raw 32-bit word containing the bitfield: */
                   2117:     bf_value = ic->tme_m68k_ireg_uint32(ireg);
                   2118: 
                   2119:     /* if this bitfield wraps the register, shift in the wrapped part
                   2120:        on the right: */
                   2121:     if (shift > 32) {
                   2122:       shift -= 32;
                   2123:       bf_value = (bf_value << shift) | (bf_value >> (32 - shift));
                   2124:       bf_offset -= shift;
                   2125:     }
                   2126:   }
                   2127: 
                   2128:   /* otherwise, this bitfield is in memory: */
                   2129:   else {
                   2130: 
1.1.1.3   root     2131:     /* this instruction can fault: */
                   2132:     ic->_tme_m68k_mode_flags |= TME_M68K_EXECUTION_INST_CANFAULT;
                   2133: 
1.1       root     2134:     /* read in the bytes covering the bitfield: */
                   2135:     bf_bytes = (tme_uint8_t *) &ic->tme_m68k_ireg_memx32;
1.1.1.3   root     2136:     tme_m68k_read_mem(ic, bf_bytes, (bf_offset + bf_width + 7) / 8);
1.1       root     2137: 
                   2138:     /* get the raw 32-bit word containing the bitfield: */
                   2139:     bf_value = tme_betoh_u32(ic->tme_m68k_ireg_memx32);
                   2140: 
1.1.1.3   root     2141:     /* if this bitfield covers 5 bytes, shift in the part from the fifth byte
1.1       root     2142:        (actually in memy32!) on the right: */
                   2143:     if (shift > 32) {
                   2144:       shift -= 32;
                   2145:       bf_value = (bf_value << shift) | (bf_bytes[4] >> (8 - shift));
                   2146:       bf_offset -= shift;
                   2147:     }
                   2148:   }
                   2149:   
                   2150:   /* shift the value: */
                   2151:   shift = (32 - (bf_offset + bf_width));
                   2152:   bf_value >>= shift;
                   2153: 
                   2154:   /* mask the value: */
1.1.1.3   root     2155:   bf_value &= (0xffffffffUL >> (32 - bf_width));
1.1       root     2156: 
                   2157:   /* if this is a signed value, sign-extend it: */
                   2158:   if (is_signed
                   2159:       && (bf_value & TME_BIT(bf_width - 1))) {
1.1.1.3   root     2160:     bf_value |= (0xffffffffUL << (bf_width - 1));
1.1       root     2161:   }
                   2162: 
                   2163:   /* all bitfield instructions that read the bitfield set the flags: */
                   2164:   if (!TME_M68K_SEQUENCE_RESTARTING) {
                   2165:     ic->tme_m68k_ireg_ccr = ((ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X)
                   2166:                             | ((bf_value & TME_BIT(bf_width - 1))
                   2167:                                ? TME_M68K_FLAG_N
                   2168:                                : 0)
                   2169:                             | (bf_value
                   2170:                                ? 0
                   2171:                                : TME_M68K_FLAG_Z));
                   2172:   }
                   2173: 
                   2174:   /* return the bitfield value: */
                   2175:   return (bf_value);
                   2176: }
                   2177: 
                   2178: /* this writes a bitfield to memory: */
                   2179: void
                   2180: tme_m68k_bitfield_write_unsigned(struct tme_m68k *ic, tme_uint32_t bf_value, int set_flags)
                   2181: {
                   2182:   unsigned int bf_offset, bf_width;
                   2183:   unsigned int shift;
                   2184:   tme_uint8_t *bf_bytes;
                   2185:   unsigned int count;
                   2186:   int ireg;
                   2187: 
                   2188:   /* for bitfields in memory, we want to know if the memory covering
                   2189:      the bitfield is already in our memory buffer, so we can avoid
                   2190:      reading that memory again.  all bitfield instructions set flags
                   2191:      based on a bitfield value; if set_flags is FALSE our caller
                   2192:      must have tested the old bitfield value, and so the bitfield
                   2193:      memory must be in our buffer, otherwise assume that this is our
                   2194:      first access to the bitfield memory: */
                   2195: #define first_memory set_flags
                   2196:   
                   2197:   /* get the bitfield offset and width: */
                   2198:   bf_offset = tme_m68k_bitfield_offset(ic, first_memory);
                   2199:   bf_width = tme_m68k_bitfield_width(ic);
                   2200: 
                   2201:   /* if this expression is > 32, in a register this means the bitfield
1.1.1.3   root     2202:      wraps, and in memory this means the bitfield covers 5 bytes: */
1.1       root     2203:   shift = (bf_offset + bf_width);
                   2204: 
1.1.1.3   root     2205:   /* mask the value: */
                   2206:   bf_value &= (0xffffffffUL >> (32 - bf_width));
                   2207: 
1.1       root     2208:   /* if we're supposed to, set the flags: */
                   2209:   if (set_flags
                   2210:       && !TME_M68K_SEQUENCE_RESTARTING) {
                   2211:     ic->tme_m68k_ireg_ccr = ((ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X)
                   2212:                             | ((bf_value & TME_BIT(bf_width - 1))
                   2213:                                ? TME_M68K_FLAG_N
                   2214:                                : 0)
                   2215:                             | (bf_value
                   2216:                                ? 0
                   2217:                                : TME_M68K_FLAG_Z));
                   2218:   }
                   2219: 
                   2220:   /* if this bitfield is in a register (EA mode field is zero): */
                   2221:   if (TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 3, 3) == 0) {
                   2222:     ireg = (TME_M68K_IREG_D0
                   2223:            + TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 0, 3));
                   2224:     
                   2225:     /* if this bitfield wraps the register, put the wrapped
                   2226:        part in the left: */
                   2227:     if (shift > 32) {
                   2228:       shift -= 32;
                   2229:       ic->tme_m68k_ireg_uint32(ireg) = ((ic->tme_m68k_ireg_uint32(ireg)
                   2230:                                         & (0xffffffffUL >> shift))
                   2231:                                        | (bf_value << (32 - shift)));
                   2232:       bf_value >>= shift;
                   2233:       bf_width -= shift;
                   2234:     }
                   2235:     
                   2236:     /* update the register: */
                   2237:     shift = (32 - (bf_offset + bf_width));
                   2238:     ic->tme_m68k_ireg_uint32(ireg) = ((ic->tme_m68k_ireg_uint32(ireg)
1.1.1.3   root     2239:                                       & ~((0xffffffffUL >> (32 - bf_width)) << shift))
1.1       root     2240:                                      | (bf_value << shift));
                   2241:   }
                   2242: 
                   2243:   /* otherwise, this bitfield is in memory: */
                   2244:   else {
                   2245: 
1.1.1.3   root     2246:     /* this instruction can fault: */
                   2247:     ic->_tme_m68k_mode_flags |= TME_M68K_EXECUTION_INST_CANFAULT;
                   2248: 
1.1       root     2249:     /* read in the bytes covering the bitfield if we haven't yet: */
                   2250:     bf_bytes = (tme_uint8_t *) &ic->tme_m68k_ireg_memx32;
1.1.1.3   root     2251:     count = (bf_offset + bf_width + 7) / 8;
1.1       root     2252:     if (first_memory) {
                   2253:       tme_m68k_read_mem(ic, bf_bytes, count);
                   2254:     }
                   2255: 
1.1.1.3   root     2256:     /* if this bitfield covers 5 bytes, put the part for the fifth
1.1       root     2257:        byte (actually in memy32!) in on the left: */
                   2258:     if (shift > 32) {
                   2259:       shift -= 32;
                   2260:       if (!TME_M68K_SEQUENCE_RESTARTING) {
                   2261:        bf_bytes[4] = ((bf_bytes[4]
                   2262:                        & (0xff >> shift))
                   2263:                       | ((bf_value & 0xff) << (8 - shift)));
                   2264:       }
                   2265:       bf_value >>= shift;
                   2266:       bf_width -= shift;
                   2267:     }
                   2268: 
                   2269:     /* update the memory buffer: */
                   2270:     if (!TME_M68K_SEQUENCE_RESTARTING) {
                   2271:       shift = (32 - (bf_offset + bf_width));
                   2272:       ic->tme_m68k_ireg_memx32 =
                   2273:        tme_htobe_u32((tme_betoh_u32(ic->tme_m68k_ireg_memx32)
1.1.1.3   root     2274:                       & ~((0xffffffffUL >> (32 - bf_width)) << shift))
1.1       root     2275:                      | (bf_value << shift));
                   2276:     }
                   2277: 
                   2278:     /* write out the bytes covering bitfield to memory: */
                   2279:     tme_m68k_write_mem(ic, bf_bytes, count);
                   2280:   }
                   2281: #undef first_memory
                   2282: }
                   2283: 
                   2284: /* our global verify hook function: */
1.1.1.2   root     2285: #undef tme_m68k_verify_hook
1.1       root     2286: void
                   2287: tme_m68k_verify_hook(void)
                   2288: {
                   2289: }
                   2290: 
1.1.1.6 ! root     2291: void
        !          2292: tme_m68k_kill_cpu(struct tme_m68k *ic)
        !          2293: {
        !          2294:   ic->_tme_m68k_mode = TME_M68K_MODE_DIE;
        !          2295: }
        !          2296: 
        !          2297: int _m68k_dead;
        !          2298: void m68k_die(void)
        !          2299: {
        !          2300:        _m68k_dead = 1;
        !          2301: }
        !          2302: 
1.1       root     2303: #if 1
                   2304: #include <stdio.h>
                   2305: 
                   2306: /* this dumps out the m68k state: */
                   2307: void
                   2308: tme_m68k_dump(struct tme_m68k *ic)
                   2309: {
                   2310:   int ireg;
                   2311:   int count;
                   2312: 
                   2313:   /* dump out the integer registers: */
                   2314:   count = 0;
                   2315:   for (ireg = TME_M68K_IREG_D0;
                   2316:        ireg <= TME_M68K_IREG_A7;
                   2317:        ireg++) {
                   2318:     fprintf(stderr,
                   2319:            "%%%c%d[%p] = 0x%08x",
                   2320:            (ireg < TME_M68K_IREG_A0
                   2321:             ? 'd'
                   2322:             : 'a'),
                   2323:            ireg - (ireg < TME_M68K_IREG_A0
                   2324:                    ? TME_M68K_IREG_D0
                   2325:                    : TME_M68K_IREG_A0),
                   2326:            &ic->tme_m68k_ireg_uint32(ireg),
                   2327:            ic->tme_m68k_ireg_uint32(ireg));
                   2328:     if (++count == 2) {
                   2329:       fprintf(stderr, "\n");
                   2330:       count = 0;
                   2331:     }
                   2332:     else {
                   2333:       fprintf(stderr, "  ");
                   2334:     }
                   2335:   }
                   2336: 
                   2337:   /* dump out the PC and next PC: */
                   2338:   fprintf(stderr, "%%pc = 0x%08x  %%pc_next = 0x%08x\n",
                   2339:          ic->tme_m68k_ireg_pc,
                   2340:          ic->tme_m68k_ireg_pc_next);
                   2341: 
                   2342:   /* dump out the status register: */
                   2343:   fprintf(stderr, "%%sr = 0x%04x", ic->tme_m68k_ireg_sr);
                   2344:   fprintf(stderr, "  flags:");
                   2345:   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X) {
                   2346:     fprintf(stderr, " X");
                   2347:   }
                   2348:   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_N) {
                   2349:     fprintf(stderr, " N");
                   2350:   }
                   2351:   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) {
                   2352:     fprintf(stderr, " Z");
                   2353:   }
                   2354:   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_V) {
                   2355:     fprintf(stderr, " V");
                   2356:   }
                   2357:   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_C) {
                   2358:     fprintf(stderr, " C");
                   2359:   }
                   2360:   fprintf(stderr, "\n");
                   2361: 
                   2362:   /* dump out the effective address and memory buffers: */
                   2363:   fprintf(stderr, "\n");
                   2364:   fprintf(stderr, "EA = %d:0x%08x\n",
                   2365:          ic->_tme_m68k_ea_function_code,
                   2366:          ic->_tme_m68k_ea_address);
                   2367:   fprintf(stderr, "%%memx[%p] = 0x%08x  %%memy[%p] = 0x%08x\n",
                   2368:          &ic->tme_m68k_ireg_memx32,
                   2369:          ic->tme_m68k_ireg_memx32,
                   2370:          &ic->tme_m68k_ireg_memy32,
                   2371:          ic->tme_m68k_ireg_memy32);
                   2372: 
                   2373:   /* dump out the control registers: */
                   2374:   fprintf(stderr, "\n");
                   2375:   fprintf(stderr, "%%usp = 0x%08x\n", ic->tme_m68k_ireg_usp);
                   2376:   fprintf(stderr, "%%isp = 0x%08x\n", ic->tme_m68k_ireg_isp);
                   2377:   fprintf(stderr, "%%msp = 0x%08x\n", ic->tme_m68k_ireg_msp);
                   2378:   fprintf(stderr, "%%sfc = 0x%08x\n", ic->tme_m68k_ireg_sfc);
                   2379:   fprintf(stderr, "%%dfc = 0x%08x\n", ic->tme_m68k_ireg_dfc);
                   2380:   fprintf(stderr, "%%vbr = 0x%08x\n", ic->tme_m68k_ireg_vbr);
                   2381:   
                   2382:   /* dump out instruction decoding information: */
                   2383:   fprintf(stderr, "\n");
1.1.1.3   root     2384:   fprintf(stderr, "opcode = 0x%04x  specop = 0x%04x\n",
1.1       root     2385:          ic->_tme_m68k_insn_opcode,
1.1.1.3   root     2386:          ic->_tme_m68k_insn_specop);
1.1       root     2387: }
1.1.1.4   root     2388: 
                   2389: void
                   2390: tme_m68k_dump_memory(struct tme_m68k *ic, tme_uint32_t address, tme_uint32_t resid)
                   2391: {
                   2392:   unsigned int saved_ea_function_code;
                   2393:   tme_uint32_t saved_ea_address;
                   2394:   tme_uint32_t address_display;
                   2395:   tme_uint8_t buffer[16];
                   2396:   tme_uint32_t count;
                   2397:   tme_uint32_t byte_i;
                   2398: 
                   2399:   /* save any EA function code and address: */
                   2400:   saved_ea_function_code = ic->_tme_m68k_ea_function_code;
                   2401:   saved_ea_address = ic->_tme_m68k_ea_address;
                   2402: 
                   2403:   /* we always display aligned rows: */
                   2404:   address_display = address & (((tme_uint32_t) 0) - sizeof(buffer));
                   2405: 
                   2406:   /* while we have memory to dump: */
                   2407:   for (; resid > 0; ) {
                   2408: 
                   2409:     /* read more data: */
                   2410:     byte_i = address % sizeof(buffer);
                   2411:     count = TME_MIN(resid, sizeof(buffer) - byte_i);
                   2412:     ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
                   2413:     ic->_tme_m68k_ea_address = address;
                   2414:     tme_m68k_read_mem(ic, &buffer[byte_i], count);
                   2415:     count += byte_i;
                   2416: 
                   2417:     /* display the row: */
                   2418:     fprintf(stderr, "0x%08x ", address_display);
                   2419:     for (byte_i = 0;
                   2420:         byte_i < count;
                   2421:         byte_i++, address_display++) {
                   2422:       if (address_display < address) {
                   2423:        fprintf(stderr, "   ");
                   2424:       }
                   2425:       else {
                   2426:        fprintf(stderr, " %02x",
                   2427:                buffer[byte_i]);
                   2428:        address++;
                   2429:        resid--;
                   2430:       }
                   2431:     }
                   2432:     fputc('\n', stderr);
                   2433:   }
                   2434: 
                   2435:   /* restore any EA function code and address: */
                   2436:   ic->_tme_m68k_ea_function_code = saved_ea_function_code;
                   2437:   ic->_tme_m68k_ea_address = saved_ea_address;
                   2438: }
1.1       root     2439: #endif /* 1 */

unix.superglobalmegacorp.com

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