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

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

unix.superglobalmegacorp.com

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