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

1.1.1.3 ! root        1: /* $Id: m68k-misc.c,v 1.23 2005/03/23 12:42:56 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.3 ! root       39: _TME_RCSID("$Id: m68k-misc.c,v 1.23 2005/03/23 12:42:56 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: */
                    222:     rc = (*ic->_tme_m68k_bus_connection->tme_m68k_bus_connection.tme_bus_intack)
                    223:       (&ic->_tme_m68k_bus_connection->tme_m68k_bus_connection,
                    224:        ipl, &vector);
                    225:     if (rc == TME_EDEADLK) {
                    226:       abort();
                    227:     }
                    228: 
                    229:     /* if the interrupt acknowledge failed, this is a spurious interrupt: */
                    230:     if (rc == ENOENT) {
1.1.1.3 ! root      231:       vector = TME_M68K_VECTOR_SPURIOUS;
1.1       root      232:     }
                    233: 
                    234:     /* if no vector is given, use the autovector: */
                    235:     else if (vector == TME_BUS_INTERRUPT_VECTOR_UNDEF) {
1.1.1.3 ! root      236:       vector = TME_M68K_VECTOR_SPURIOUS + ipl;
1.1       root      237:     }
                    238: 
                    239:     /* dispatch the exceptions: */
1.1.1.3 ! root      240:     tme_m68k_exception(ic, internal_exceptions | TME_M68K_EXCEPTION_INT(ipl, vector));
1.1       root      241:   }
                    242: 
                    243:   /* if there are internal exceptions to process, do so: */
                    244:   if (internal_exceptions != 0) {
                    245:     tme_mutex_unlock(&ic->tme_m68k_external_mutex);
                    246:     tme_m68k_exception(ic, internal_exceptions);
                    247:   }
                    248: 
                    249:   /* there are no exceptions to process: */
                    250: }
                    251: 
                    252: /* the idle function, used when the processor is halted or stopped: */
                    253: static void
                    254: tme_m68k_idle(struct tme_m68k *ic)
                    255: {  
                    256:   /* lock the external mutex: */
                    257:   tme_mutex_lock(&ic->tme_m68k_external_mutex);
                    258: 
                    259:   /* loop forever: */
                    260:   for (;;) {
                    261: 
                    262:     /* check for any external signal: */
                    263:     tme_m68k_external_check(ic, 0);
                    264: 
                    265:     /* await an external condition: */
                    266:     tme_cond_wait_yield(&ic->tme_m68k_external_cond, &ic->tme_m68k_external_mutex);
                    267:   }
                    268: }
                    269: 
                    270: /* the m68k thread: */
                    271: static void
                    272: tme_m68k_thread(struct tme_m68k *ic)
                    273: {
                    274: 
                    275:   /* we use longjmp to redispatch: */
                    276:   do { } while (setjmp(ic->_tme_m68k_dispatcher));
                    277: 
                    278:   /* dispatch on the current mode: */
                    279:   switch (ic->_tme_m68k_mode) {
                    280: 
                    281:   case TME_M68K_MODE_EXECUTION:
                    282:     (*ic->_tme_m68k_mode_execute)(ic);
                    283:     /* NOTREACHED */
                    284: 
                    285:   case TME_M68K_MODE_EXCEPTION:
                    286:     (*ic->_tme_m68k_mode_exception)(ic);
                    287:     /* NOTREACHED */
                    288: 
                    289:   case TME_M68K_MODE_RTE:
                    290:     (*ic->_tme_m68k_mode_rte)(ic);
                    291:     /* NOTREACHED */
                    292: 
                    293:   case TME_M68K_MODE_STOP:
                    294:   case TME_M68K_MODE_HALT:
                    295:     tme_m68k_idle(ic);
                    296:     /* NOTREACHED */
                    297: 
                    298:   default:
                    299:     abort();
                    300:   }
                    301:   /* NOTREACHED */
                    302: }
                    303: 
                    304: /* the TLB filler for when we are on a generic bus: */
                    305: static int
                    306: _tme_m68k_generic_tlb_fill(struct tme_m68k_bus_connection *conn_m68k, 
                    307:                           struct tme_m68k_tlb *tlb,
                    308:                           unsigned int function_code, 
                    309:                           tme_uint32_t external_address, 
                    310:                           unsigned int cycles)
                    311: {
                    312:   struct tme_m68k *ic;
                    313: 
                    314:   /* recover our IC: */
                    315:   ic = conn_m68k->tme_m68k_bus_connection.tme_bus_connection.tme_connection_element->tme_element_private;
                    316: 
1.1.1.3 ! root      317:   /* this m68k implementation never fills TLB entries on the stack, so
        !           318:      a TLB entry reserves itself.  this also means that we don't have
        !           319:      to call tme_bus_tlb_back() after the fill: */
        !           320:   tme_bus_tlb_reserve(&tlb->tme_m68k_tlb_bus_tlb, &tlb->tme_m68k_tlb_bus_tlb);
        !           321: 
1.1       root      322:   /* call the generic bus TLB filler: */
                    323:   (ic->_tme_m68k_bus_generic->tme_bus_tlb_fill)
                    324:     (ic->_tme_m68k_bus_generic,
                    325:      &tlb->tme_m68k_tlb_bus_tlb,
                    326:      external_address,
                    327:      cycles);
                    328:   
                    329:   /* when we're on a generic bus a TLB entry is valid for all function codes: */
                    330:   tlb->tme_m68k_tlb_function_codes_mask = -1;
                    331: 
                    332:   return (TME_OK);
                    333: }
                    334: 
                    335: /* the connection scorer: */
                    336: static int
                    337: _tme_m68k_connection_score(struct tme_connection *conn, unsigned int *_score)
                    338: {
                    339:   struct tme_m68k_bus_connection *conn_m68k;
                    340:   struct tme_bus_connection *conn_bus;
                    341:   unsigned int score;
                    342: 
                    343:   /* assume that this connection is useless: */
                    344:   score = 0;
                    345: 
                    346:   /* dispatch on the connection type: */
                    347:   conn_m68k = (struct tme_m68k_bus_connection *) conn->tme_connection_other;
                    348:   conn_bus = (struct tme_bus_connection *) conn->tme_connection_other;
                    349:   switch (conn->tme_connection_type) {
                    350: 
                    351:     /* this must be a bus, and not another m68k chip: */
                    352:   case TME_CONNECTION_BUS_M68K:
                    353:     if (conn_bus->tme_bus_tlb_set_allocate != NULL
1.1.1.3 ! root      354:        && conn_m68k->tme_m68k_bus_tlb_fill != NULL
        !           355:        && conn_m68k->tme_m68k_bus_m6888x_enable == NULL) {
1.1       root      356:       score = 10;
                    357:     }
                    358:     break;
                    359: 
                    360:     /* this must be a bus, and not another chip: */
                    361:   case TME_CONNECTION_BUS_GENERIC:
                    362:     if (conn_bus->tme_bus_tlb_set_allocate != NULL
                    363:        && conn_bus->tme_bus_tlb_fill != NULL) {
                    364:       score = 1;
                    365:     }
                    366:     break;
                    367: 
                    368:   default: abort();
                    369:   }
                    370: 
                    371:   *_score = score;
                    372:   return (TME_OK);
                    373: }
                    374: 
                    375: /* this makes a new connection: */
                    376: static int
                    377: _tme_m68k_connection_make(struct tme_connection *conn, unsigned int state)
                    378: {
                    379:   struct tme_m68k *ic;
                    380:   struct tme_m68k_bus_connection *conn_m68k;
                    381:   struct tme_bus_connection *conn_bus;
                    382:   struct tme_connection *conn_other;
                    383: 
                    384:   /* since the CPU is halted, it won't be making any connection calls,
                    385:      so we only have to do work when the connection is fully made: */
                    386:   if (state == TME_CONNECTION_FULL) {
                    387: 
                    388:     /* recover our IC: */
                    389:     ic = conn->tme_connection_element->tme_element_private;
                    390:     
                    391:     /* dispatch on the connection type: */
                    392:     conn_other = conn->tme_connection_other;
                    393:     conn_m68k = (struct tme_m68k_bus_connection *) conn_other;
                    394:     conn_bus = (struct tme_bus_connection *) conn_other;
                    395:     switch (conn->tme_connection_type) {
                    396:       
                    397:     case TME_CONNECTION_BUS_M68K:
                    398:       ic->_tme_m68k_bus_connection = conn_m68k;
                    399:       break;
                    400:       
                    401:       /* we need an adaptation layer: */
                    402:     case TME_CONNECTION_BUS_GENERIC:
                    403:       conn_m68k = tme_new0(struct tme_m68k_bus_connection, 1);
                    404:       conn_m68k->tme_m68k_bus_connection.tme_bus_connection.tme_connection_element = conn->tme_connection_element;
                    405:       conn_m68k->tme_m68k_bus_tlb_fill = _tme_m68k_generic_tlb_fill;
                    406:       ic->_tme_m68k_bus_connection = conn_m68k;
                    407:       ic->_tme_m68k_bus_generic = conn_bus;
                    408:       break;
                    409:       
                    410:     default: abort();
                    411:     }
                    412: 
                    413:     /* allocate the TLB hash set: */
                    414:     (*ic->_tme_m68k_bus_connection->tme_m68k_bus_connection.tme_bus_tlb_set_allocate)
                    415:       (&ic->_tme_m68k_bus_connection->tme_m68k_bus_connection, 
                    416:        _TME_M68K_TLB_HASH_SIZE, 
                    417:        sizeof(struct tme_m68k_tlb),
                    418:        TME_ATOMIC_POINTER((struct tme_bus_tlb **) &ic->_tme_m68k_tlb_array));
                    419: 
                    420:     /* allocate the ITLB set: */
                    421:     (*ic->_tme_m68k_bus_connection->tme_m68k_bus_connection.tme_bus_tlb_set_allocate)
                    422:       (&ic->_tme_m68k_bus_connection->tme_m68k_bus_connection, 
                    423:        1, 
                    424:        sizeof(struct tme_m68k_tlb),
                    425:        TME_ATOMIC_POINTER((struct tme_bus_tlb **) &ic->_tme_m68k_itlb));
                    426:   }
                    427: 
                    428:   /* NB: the machine needs to issue a reset to bring the CPU out of halt. */
                    429:   return (TME_OK);
                    430: }
                    431: 
                    432: /* this breaks a connection: */
                    433: static int 
                    434: _tme_m68k_connection_break(struct tme_connection *conn, unsigned int state)
                    435: {
                    436:   abort();
1.1.1.3 ! root      437:   return (0);
1.1       root      438: }
                    439: 
                    440: /* this makes new connection sides: */
                    441: static int
                    442: _tme_m68k_connections_new(struct tme_element *element, const char * const *args, struct tme_connection **_conns, char **_output)
                    443: {
                    444:   struct tme_m68k_bus_connection *conn_m68k;
                    445:   struct tme_bus_connection *conn_bus;
                    446:   struct tme_connection *conn;
                    447: 
                    448:   /* if we already have a bus connection, we can take no more connections: */
                    449:   if (((struct tme_m68k *) element->tme_element_private)->_tme_m68k_bus_connection != NULL) {
                    450:     return (TME_OK);
                    451:   }
                    452: 
                    453:   /* create our side of an m68k bus connection: */
                    454:   conn_m68k = tme_new0(struct tme_m68k_bus_connection, 1);
                    455:   conn_bus = &conn_m68k->tme_m68k_bus_connection;
                    456:   conn = &conn_bus->tme_bus_connection;
                    457: 
                    458:   /* fill in the generic connection: */
                    459:   conn->tme_connection_next = *_conns;
                    460:   conn->tme_connection_type = TME_CONNECTION_BUS_M68K;
                    461:   conn->tme_connection_score = _tme_m68k_connection_score;
                    462:   conn->tme_connection_make = _tme_m68k_connection_make;
                    463:   conn->tme_connection_break = _tme_m68k_connection_break;
                    464: 
                    465:   /* fill in the generic bus connection: */
                    466:   conn_bus->tme_bus_signal = _tme_m68k_bus_signal;
                    467:   conn_bus->tme_bus_tlb_set_allocate = NULL;
                    468: 
                    469:   /* full in the m68k bus connection: */
                    470:   conn_m68k->tme_m68k_bus_interrupt = _tme_m68k_bus_interrupt;
                    471:   conn_m68k->tme_m68k_bus_tlb_fill = NULL;
1.1.1.3 ! root      472:   conn_m68k->tme_m68k_bus_m6888x_enable = _tme_m6888x_enable;
1.1       root      473: 
                    474:   /* add this connection to the set of possibilities: */
                    475:   *_conns = conn;
                    476: 
                    477:   /* create our side of a generic bus connection: */
                    478:   conn_bus = tme_new0(struct tme_bus_connection, 1);
                    479:   conn = &conn_bus->tme_bus_connection;
                    480: 
                    481:   /* fill in the generic connection: */
                    482:   conn->tme_connection_next = *_conns;
                    483:   conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC;
                    484:   conn->tme_connection_score = _tme_m68k_connection_score;
                    485:   conn->tme_connection_make = _tme_m68k_connection_make;
                    486:   conn->tme_connection_break = _tme_m68k_connection_break;
                    487: 
                    488:   /* fill in the generic bus connection: */
                    489:   conn_bus->tme_bus_signal = _tme_m68k_bus_signal;
                    490:   conn_bus->tme_bus_tlb_set_allocate = NULL;
                    491:   conn_bus->tme_bus_tlb_fill = NULL;
                    492: 
                    493:   /* add this connection to the set of possibilities: */
                    494:   *_conns = conn;
                    495: 
                    496:   /* done: */
                    497:   return (TME_OK);
                    498: }
                    499: 
                    500: /* the common m68k new function: */
                    501: int
                    502: tme_m68k_new(struct tme_m68k *ic, const char * const *args, const void *extra, char **_output)
                    503: {
                    504:   struct tme_element *element;
1.1.1.3 ! root      505:   int arg_i;
        !           506:   int usage;
1.1       root      507: 
1.1.1.3 ! root      508:   /* check our arguments: */
        !           509:   arg_i = 1;
        !           510:   usage = FALSE;
        !           511:   for (;;) {
        !           512:     
        !           513:     if (0) {
        !           514: 
        !           515:     }
        !           516: 
        !           517:     /* if we've run out of arguments: */
        !           518:     else if (args[arg_i + 0] == NULL) {
        !           519:       break;
        !           520:     }
        !           521: 
        !           522:     /* this is either a bad argument or an FPU argument: */
        !           523:     else {
        !           524: 
        !           525:       /* if this is not an FPU argument: */
        !           526:       if (!tme_m68k_fpu_new(ic, args, &arg_i, &usage, _output)) {
        !           527:        tme_output_append_error(_output,
        !           528:                                "%s %s, ",
        !           529:                                args[arg_i],
        !           530:                                _("unexpected"));
        !           531:        usage = TRUE;
        !           532:       }
        !           533:       
        !           534:       if (usage) {
        !           535:        break;
        !           536:       }
        !           537:     }
        !           538:   }
        !           539: 
        !           540:   if (usage) {
        !           541:     tme_output_append_error(_output, 
        !           542:                            "%s %s",
1.1       root      543:                            _("usage:"),
                    544:                            args[0]);
1.1.1.3 ! root      545:     tme_m68k_fpu_usage(_output);
1.1       root      546:     tme_free(ic);
                    547:     return (EINVAL);
                    548:   }
                    549: 
                    550:   /* initialize the verifier: */
                    551:   tme_m68k_verify_init();
                    552: 
                    553:   /* dispatch on the type: */
                    554:   switch (ic->tme_m68k_type) {
                    555:   case TME_M68K_M68000:
                    556:     ic->_tme_m68k_bus_16bit = TRUE;
                    557:     break;
                    558:   case TME_M68K_M68010:
                    559:     ic->_tme_m68k_bus_16bit = TRUE;
                    560:     break;
                    561:   case TME_M68K_M68020:
                    562:     ic->_tme_m68k_bus_16bit = FALSE;
                    563:     break;
                    564:   default:
                    565:     abort();
                    566:   }
                    567: 
                    568:   /* we have no bus connection yet: */
                    569:   ic->_tme_m68k_bus_connection = NULL;
                    570: 
                    571:   /* fill the element: */
                    572:   element = ic->tme_m68k_element;
                    573:   element->tme_element_private = ic;
                    574:   element->tme_element_connections_new = _tme_m68k_connections_new;
                    575: 
                    576:   /* calculate the instruction burst size: */
                    577:   /* XXX TBD: */
1.1.1.3 ! root      578:   ic->_tme_m68k_instruction_burst = 200;
1.1.1.2   root      579:   ic->_tme_m68k_instruction_burst_remaining
                    580:     = ic->_tme_m68k_instruction_burst;
1.1       root      581: 
1.1.1.3 ! root      582:   /* set the status register T bits mask: */
        !           583:   ic->_tme_m68k_sr_mask_t
        !           584:     = (TME_M68K_FLAG_T1
        !           585:        | ((ic->tme_m68k_type >= TME_M68K_M68020)
        !           586:          * TME_M68K_FLAG_T0));
        !           587: 
        !           588:   /* initialize the small immediates: */
        !           589:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_ZERO) = 0;
        !           590:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_ONE) = 1;
        !           591:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_TWO) = 2;
        !           592:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_THREE) = 3;
        !           593:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_FOUR) = 4;
        !           594:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_FIVE) = 5;
        !           595:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_SIX) = 6;
        !           596:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_SEVEN) = 7;
        !           597:   ic->tme_m68k_ireg_uint32(TME_M68K_IREG_EIGHT) = 8;
        !           598: 
1.1       root      599:   /* force the processor to be halted: */
                    600:   ic->_tme_m68k_mode = TME_M68K_MODE_HALT;
                    601:   TME_M68K_SEQUENCE_START;
                    602: 
                    603:   /* start the m68k thread: */
                    604:   tme_thread_create((tme_thread_t) tme_m68k_thread, ic);
                    605: 
                    606:   return (TME_OK);
                    607: }  
                    608: 
                    609: /* the common m68k reset function: */
                    610: void
                    611: tme_m68k_do_reset(struct tme_m68k *ic)
                    612: {
                    613:   
                    614:   /* force the VBR to zero: */
                    615:   ic->tme_m68k_ireg_vbr = 0;
                    616: 
1.1.1.3 ! root      617:   /* clear the E and F bits in the CACR: */
        !           618:   ic->tme_m68k_ireg_cacr = 0;
        !           619: 
1.1       root      620:   /* force supervisor mode, interrupts disabled: */
                    621:   tme_m68k_change_sr(ic, TME_M68K_FLAG_S | (7 << 8));
                    622: 
                    623:   /* load the initial SSP and PC: */
1.1.1.3 ! root      624:   ic->_tme_m68k_ea_function_code = TME_M68K_FC_SP;
1.1       root      625:   ic->_tme_m68k_ea_address = 0;
                    626:   tme_m68k_read_mem32(ic, TME_M68K_IREG_A7);
                    627:   ic->_tme_m68k_ea_address += sizeof(ic->tme_m68k_ireg_a7);
                    628:   tme_m68k_read_mem32(ic, TME_M68K_IREG_PC);
                    629: 
                    630:   /* clear all exceptions: */
                    631:   ic->_tme_m68k_exceptions = 0;
                    632: 
1.1.1.3 ! root      633:   /* reset the FPU: */
        !           634:   tme_m68k_fpu_reset(ic);
        !           635: 
1.1       root      636:   /* start execution: */
                    637:   ic->_tme_m68k_mode = TME_M68K_MODE_EXECUTION;
                    638:   TME_M68K_SEQUENCE_START;
                    639:   tme_m68k_redispatch(ic);
                    640: }
                    641: 
                    642: /* this returns nonzero iff the slow instruction executor must be
                    643:    used: */
                    644: int
                    645: tme_m68k_go_slow(const struct tme_m68k *ic)
                    646: {
                    647:   struct tme_m68k_tlb *tlb;
                    648:   tme_uint32_t linear_pc;
                    649: 
                    650:   tlb = TME_ATOMIC_READ(struct tme_m68k_tlb *, ic->_tme_m68k_itlb);
                    651:   linear_pc = ic->tme_m68k_ireg_pc;
                    652:   return (
                    653:          
                    654:          /* the ITLB entry must support reads from emulator memory: */
                    655:          !TME_M68K_TLB_OK_FAST_READ(tlb, 
                    656:                                     TME_M68K_FUNCTION_CODE_PROGRAM(ic),
                    657:                                     linear_pc,
                    658:                                     linear_pc)
                    659: 
                    660:          /* the ITLB emulator memory must be 32-bit aligned for the
                    661:             benefit of the fast instruction word fetch macros, so
                    662:             that emulator address alignment goes with linear address
                    663:             alignment: */
                    664:          || (((unsigned long) tlb->tme_m68k_tlb_emulator_off_read)
                    665:              & (sizeof(tme_uint32_t) - 1))
                    666: 
                    667:          /* the linear PC must be 16-bit aligned: */
                    668:          || (linear_pc & 1)
                    669: 
                    670:          /* there must be no tracing: */
1.1.1.3 ! root      671:          || (ic->tme_m68k_ireg_sr & ic->_tme_m68k_sr_mask_t) != 0);
1.1       root      672: }
                    673: 
                    674: /* this redispatches: */
                    675: void
                    676: tme_m68k_redispatch(struct tme_m68k *ic)
                    677: {
1.1.1.3 ! root      678: #ifdef _TME_M68K_STATS
        !           679:   ic->tme_m68k_stats.tme_m68k_stats_redispatches++;
        !           680: #endif /* _TME_M68K_STATS */
1.1       root      681:   longjmp(ic->_tme_m68k_dispatcher, 1);
                    682: }
                    683: 
                    684: /* this fills a TLB entry: */
                    685: void
                    686: tme_m68k_tlb_fill(struct tme_m68k *ic, struct tme_m68k_tlb *tlb, 
                    687:                  unsigned int function_code, 
                    688:                  tme_uint32_t linear_address, 
                    689:                  unsigned int cycles)
                    690: {
                    691:   tme_uint32_t external_address;
                    692:   struct tme_bus_tlb tlb_internal;
                    693:   
1.1.1.3 ! root      694: #ifdef _TME_M68K_STATS
        !           695:   if (function_code == TME_M68K_FC_UP
        !           696:       || function_code == TME_M68K_FC_SP) {
        !           697:     ic->tme_m68k_stats.tme_m68k_stats_itlb_fill++;
        !           698:   }
        !           699:   else {
        !           700:     ic->tme_m68k_stats.tme_m68k_stats_dtlb_fill++;
        !           701:   }
        !           702: #endif /* _TME_M68K_STATS */
        !           703: 
1.1       root      704:   /* when emulating a CPU with a 16-bit bus, only 24 bits of address
                    705:      are external: */
                    706:   external_address = linear_address;
                    707:   if (ic->_tme_m68k_bus_16bit) {
                    708:     external_address &= 0x00ffffff;
                    709:   }
                    710: 
1.1.1.3 ! root      711:   /* this m68k implementation never fills TLB entries on the stack, so
        !           712:      a TLB entry reserves itself.  this also means that we don't have
        !           713:      to call tme_bus_tlb_back() after the fill: */
        !           714:   tme_bus_tlb_reserve(&tlb->tme_m68k_tlb_bus_tlb, &tlb->tme_m68k_tlb_bus_tlb);
        !           715: 
1.1       root      716:   /* fill the TLB entry: */
                    717:   (*ic->_tme_m68k_bus_connection->tme_m68k_bus_tlb_fill)
                    718:     (ic->_tme_m68k_bus_connection, tlb,
                    719:      function_code,
                    720:      external_address,
                    721:      cycles);
                    722: 
                    723:   /* if this code isn't 32-bit clean, we have to deal: */
                    724:   if (external_address != linear_address) {
                    725:     TME_ATOMIC_WRITE(tme_bus_addr_t, tlb_internal.tme_bus_tlb_addr_first,
                    726:                     TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_m68k_tlb_linear_first)
                    727:                     | (linear_address ^ external_address));
                    728:     TME_ATOMIC_WRITE(tme_bus_addr_t, tlb_internal.tme_bus_tlb_addr_last,
                    729:                     TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_m68k_tlb_linear_last)
                    730:                     | (linear_address ^ external_address));
                    731:     tlb_internal.tme_bus_tlb_cycles_ok = tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycles_ok;
                    732:     tme_bus_tlb_map(&tlb->tme_m68k_tlb_bus_tlb, external_address,
                    733:                    &tlb_internal, linear_address);
                    734:   }
                    735: }
                    736: 
                    737: /* this triggers exception processing: */
                    738: void
                    739: tme_m68k_exception(struct tme_m68k *ic, tme_uint32_t new_exceptions)
                    740: {
                    741:   assert(new_exceptions != 0);
                    742: 
                    743:   /* if the set of new exceptions includes a group zero exception: */
                    744:   if (new_exceptions & 
1.1.1.3 ! root      745:       (TME_M68K_EXCEPTION_RESET
        !           746:        | TME_M68K_EXCEPTION_AERR
        !           747:        | TME_M68K_EXCEPTION_BERR)) {
1.1       root      748:     
                    749:     /* there must be only one exception - you cannot trigger a group 0
                    750:        exception simultaneously with any other group 0, 1, or 2
                    751:        exception: */
                    752:     assert((new_exceptions & (new_exceptions - 1)) == 0);
                    753:     
                    754:     /* if this is a reset exception, it clears all other exceptions: */
1.1.1.3 ! root      755:     if (new_exceptions == TME_M68K_EXCEPTION_RESET) {
1.1       root      756:       ic->_tme_m68k_exceptions = 0;
                    757:     }
                    758: 
                    759:     /* otherwise, this is an address error or a bus error.  if we were
                    760:        already processing a group 0 exception, this is a
                    761:        double fault, and the processor enters the halted state: */
                    762:     else if (ic->_tme_m68k_exceptions &
1.1.1.3 ! root      763:             (TME_M68K_EXCEPTION_RESET
        !           764:              | TME_M68K_EXCEPTION_AERR
        !           765:              | TME_M68K_EXCEPTION_BERR)) {
        !           766:       tme_log(TME_M68K_LOG_HANDLE(ic), 0, TME_OK,
        !           767:              (TME_M68K_LOG_HANDLE(ic),
        !           768:               _("double fault, processor halted")));
1.1       root      769:       ic->_tme_m68k_mode = TME_M68K_MODE_HALT;
                    770:       TME_M68K_SEQUENCE_START;
                    771:       tme_m68k_redispatch(ic);
                    772:     }
                    773:   }
                    774: 
                    775:   /* otherwise, exception processing must not already be happening: */
                    776:   else {
                    777:     assert(ic->_tme_m68k_exceptions == 0);
                    778:   }
                    779: 
                    780:   /* begin exception processing: */
                    781:   ic->_tme_m68k_exceptions |= new_exceptions;
                    782:   ic->_tme_m68k_mode = TME_M68K_MODE_EXCEPTION;
                    783:   TME_M68K_SEQUENCE_START;
                    784:   tme_m68k_redispatch(ic);
                    785: }
                    786: 
                    787: /* this changes SR, and swaps %a7 as needed: */
                    788: void
                    789: tme_m68k_change_sr(struct tme_m68k *ic, tme_uint16_t sr)
                    790: {
1.1.1.3 ! root      791:   tme_uint16_t flags_mode;
        !           792: 
        !           793:   /* only recognize the M bit on a 68020 or better: */
        !           794:   flags_mode = (TME_M68K_FLAG_S
        !           795:                | ((ic->tme_m68k_type >= TME_M68K_M68020)
        !           796:                   * TME_M68K_FLAG_M));
1.1       root      797:   
                    798:   /* save %a7 in the proper stack pointer control register: */
1.1.1.3 ! root      799:   switch (ic->tme_m68k_ireg_sr & flags_mode) {
1.1       root      800:   case 0:
                    801:   case TME_M68K_FLAG_M:
                    802:     ic->tme_m68k_ireg_usp = ic->tme_m68k_ireg_a7;
                    803:     break;
                    804:   case TME_M68K_FLAG_S:
1.1.1.3 ! root      805:     ic->tme_m68k_ireg_isp = ic->tme_m68k_ireg_a7;
1.1       root      806:     break;
                    807:   case (TME_M68K_FLAG_S | TME_M68K_FLAG_M):
1.1.1.3 ! root      808:     ic->tme_m68k_ireg_msp = ic->tme_m68k_ireg_a7;
1.1       root      809:     break;
                    810:   }
                    811: 
                    812:   /* load %a7 from the proper stack pointer control register: */
                    813:   ic->tme_m68k_ireg_sr = sr;
1.1.1.3 ! root      814:   switch (ic->tme_m68k_ireg_sr & flags_mode) {
1.1       root      815:   case 0:
                    816:   case TME_M68K_FLAG_M:
                    817:     ic->tme_m68k_ireg_a7 = ic->tme_m68k_ireg_usp;
                    818:     break;
                    819:   case TME_M68K_FLAG_S:
1.1.1.3 ! root      820:     ic->tme_m68k_ireg_a7 = ic->tme_m68k_ireg_isp;
1.1       root      821:     break;
                    822:   case (TME_M68K_FLAG_S | TME_M68K_FLAG_M):
1.1.1.3 ! root      823:     ic->tme_m68k_ireg_a7 = ic->tme_m68k_ireg_msp;
1.1       root      824:     break;
                    825:   }
                    826: }
                    827: 
                    828: /* this starts processing an m68k exception: */
                    829: void
                    830: tme_m68k_exception_process_start(struct tme_m68k *ic, unsigned int ipl)
                    831: {
                    832:   tme_uint16_t sr;
                    833: 
                    834:   /* make an internal copy of the status register, then set S, clear
                    835:      T, and update I: */
                    836:   if (!TME_M68K_SEQUENCE_RESTARTING) {
                    837:     ic->tme_m68k_ireg_shadow_sr = ic->tme_m68k_ireg_sr;
1.1.1.3 ! root      838:     sr = (ic->tme_m68k_ireg_sr | TME_M68K_FLAG_S) & ~ic->_tme_m68k_sr_mask_t;
1.1       root      839:     if (ipl > TME_M68K_IPL_NONE) {
                    840:       assert(ipl == TME_M68K_IPL_NMI
                    841:             || ipl > TME_M68K_FLAG_IPM(sr));
                    842:       sr = (sr & ~(TME_M68K_IPL_MAX << 8)) | (ipl << 8);
                    843:     }
                    844:     tme_m68k_change_sr(ic, sr);
                    845:   }
                    846: }
                    847: 
                    848: /* this finishes processing an m68k exception: */
                    849: void
                    850: tme_m68k_exception_process_finish(struct tme_m68k *ic, tme_uint8_t format, tme_uint8_t vector)
                    851: {
                    852:   tme_uint16_t vector_offset;
                    853: 
                    854:   /* stack the frame format and vector offset, unless this is a 68000: */
                    855:   vector_offset = ((tme_uint16_t) vector) << 2;
                    856:   if (ic->tme_m68k_type != TME_M68K_M68000) {
                    857:     tme_m68k_push16(ic, (((tme_uint16_t) format) << 12) | vector_offset);
                    858:   }
                    859: 
                    860:   /* stack the program counter: */
                    861:   tme_m68k_push32(ic, ic->tme_m68k_ireg_pc);
                    862:   
                    863:   /* stack the internal copy of the status register: */
                    864:   tme_m68k_push16(ic, ic->tme_m68k_ireg_shadow_sr);
                    865: 
                    866:   /* do a bus cycle to read the vector into the program counter: */
                    867:   if (!TME_M68K_SEQUENCE_RESTARTING) {
1.1.1.3 ! root      868:     ic->_tme_m68k_ea_function_code = TME_M68K_FC_SD;
1.1       root      869:     ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_vbr + vector_offset;
                    870:   }
                    871:   tme_m68k_read_mem32(ic, TME_M68K_IREG_PC);
                    872: }
                    873: 
1.1.1.3 ! root      874: /* common m68000 and m68010 exception processing: */
1.1       root      875: void
1.1.1.3 ! root      876: tme_m68000_exception_process(struct tme_m68k *ic)
1.1       root      877: {
                    878:   tme_uint32_t exceptions;
1.1.1.3 ! root      879:   tme_uint8_t vector;
1.1       root      880: 
                    881:   /* get the set of exceptions.  we must have no group 0 exceptions: */
                    882:   exceptions = ic->_tme_m68k_exceptions;
1.1.1.3 ! root      883:   assert((exceptions & (TME_M68K_EXCEPTION_RESET
        !           884:                        | TME_M68K_EXCEPTION_AERR
        !           885:                        | TME_M68K_EXCEPTION_BERR)) == 0);
1.1       root      886: 
                    887:   /* these if statements are ordered to implement the priority
                    888:      relationship between the different exceptions as outlined in 
                    889:      the 68000 user's manual (pp 93 in my copy): */
                    890:   
1.1.1.3 ! root      891:   if (TME_M68K_EXCEPTION_IS_INST(exceptions)) {
1.1       root      892:     tme_m68k_exception_process_start(ic, 0);
1.1.1.3 ! root      893:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, TME_M68K_EXCEPTION_IS_INST(exceptions));
1.1       root      894:   }
                    895:   
1.1.1.3 ! root      896:   if (exceptions & TME_M68K_EXCEPTION_TRACE) {
1.1       root      897:     tme_m68k_exception_process_start(ic, 0);
1.1.1.3 ! root      898:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, TME_M68K_VECTOR_TRACE);
        !           899:   }
        !           900:   
        !           901:   if (TME_M68K_EXCEPTION_IS_INT(exceptions)) {
        !           902:     tme_m68k_exception_process_start(ic, TME_M68K_EXCEPTION_IS_INT(exceptions));
        !           903:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, TME_M68K_EXCEPTION_INT_VEC(exceptions));
1.1       root      904:   }
                    905:   
1.1.1.3 ! root      906:   if (exceptions & TME_M68K_EXCEPTION_ILL) {
        !           907:     if (TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 12, 4) == 0xa) {
        !           908:       vector = TME_M68K_VECTOR_LINE_A;
        !           909:     }
        !           910:     else if (TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 12, 4) == 0xf) {
        !           911:       vector = TME_M68K_VECTOR_LINE_F;
        !           912:     }
        !           913:     else {
        !           914:       vector = TME_M68K_VECTOR_ILL;
        !           915:     }
        !           916:     tme_m68k_exception_process_start(ic, 0);
        !           917:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, vector);
1.1       root      918:   }
                    919:   
1.1.1.3 ! root      920:   if (exceptions & TME_M68K_EXCEPTION_PRIV) {
1.1       root      921:     tme_m68k_exception_process_start(ic, 0);
1.1.1.3 ! root      922:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, TME_M68K_VECTOR_TRACE);
1.1       root      923:   }
                    924:   
1.1.1.3 ! root      925:   /* we have processed all exceptions - resume execution: */
        !           926:   ic->_tme_m68k_exceptions = 0;
        !           927:   ic->_tme_m68k_mode = TME_M68K_MODE_EXECUTION;
        !           928:   TME_M68K_SEQUENCE_START;
        !           929:   tme_m68k_redispatch(ic);
        !           930: }
        !           931: 
        !           932: /* common m68020 and later exception processing: */
        !           933: void
        !           934: tme_m68020_exception_process(struct tme_m68k *ic)
        !           935: {
        !           936:   tme_uint32_t exceptions;
        !           937:   tme_uint8_t vector;
        !           938:   struct {
        !           939:     tme_uint16_t tme_m68k_fmt1_sr;
        !           940:     tme_uint16_t tme_m68k_fmt1_pc_hi;
        !           941:     tme_uint16_t tme_m68k_fmt1_pc_lo;    
        !           942:     tme_uint16_t tme_m68k_fmt1_vector_offset;
        !           943:   } fmt1;
        !           944: 
        !           945:   /* get the set of exceptions.  we must have no group 0 or 1
        !           946:      exceptions: */
        !           947:   exceptions = ic->_tme_m68k_exceptions;
        !           948:   assert((exceptions & (TME_M68K_EXCEPTION_RESET
        !           949:                        | TME_M68K_EXCEPTION_AERR
        !           950:                        | TME_M68K_EXCEPTION_BERR)) == 0);
        !           951: 
        !           952:   /* these if statements are ordered to implement the priority
        !           953:      relationship between the different exceptions as outlined in 
        !           954:      the 68020 user's manual (pp 144 in my copy): */
        !           955:   
        !           956:   /* group 2 exceptions: */
        !           957:   if (TME_M68K_EXCEPTION_IS_INST(exceptions)) {
1.1       root      958:     tme_m68k_exception_process_start(ic, 0);
1.1.1.3 ! root      959: 
        !           960:     /* get the vector number: */
        !           961:     vector = TME_M68K_EXCEPTION_IS_INST(exceptions);
        !           962: 
        !           963:     /* of the group 2 exceptions, only the Format Error and TRAP #N
        !           964:        exceptions generate a format 0 stack frame.  the RTE mode code
        !           965:        and the TRAP instruction code are expected to have left
        !           966:        ic->tme_m68k_ireg_pc as the PC they want stacked: */
        !           967:     if (vector == TME_M68K_VECTOR_FORMAT
        !           968:        || (TME_M68K_VECTOR_TRAP_0 <= vector
        !           969:            && vector < (TME_M68K_VECTOR_TRAP_0 + 16))) {
        !           970:       tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, vector);
        !           971:     }
        !           972: 
        !           973:     /* all other group 2 exceptions generate a format 2 stack frame.
        !           974:        all code that can signal this exception is expected to have
        !           975:        left ic->tme_m68k_ireg_pc *and* ic->tme_m68k_ireg_pc_last as
        !           976:        the PCs they want stacked: */
        !           977:     else {
        !           978:       
        !           979:       /* stack the program counter of the instruction that caused the exception: */
        !           980:       tme_m68k_push32(ic, ic->tme_m68k_ireg_pc_last);
        !           981: 
        !           982:       /* finish with a format 2 stack frame: */
        !           983:       tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_2, vector);
        !           984:     }
        !           985:   }
        !           986: 
        !           987:   /* group 3 exceptions: */
        !           988:   if (exceptions & TME_M68K_EXCEPTION_ILL) {
        !           989:     if (TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 12, 4) == 0xa) {
        !           990:       vector = TME_M68K_VECTOR_LINE_A;
        !           991:     }
        !           992:     else if (TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 12, 4) == 0xf) {
        !           993:       vector = TME_M68K_VECTOR_LINE_F;
        !           994:     }
        !           995:     else {
        !           996:       vector = TME_M68K_VECTOR_ILL;
        !           997:     }
        !           998:     tme_m68k_exception_process_start(ic, 0);
        !           999:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, vector);
        !          1000:   }
        !          1001:   if (exceptions & TME_M68K_EXCEPTION_PRIV) {
        !          1002:     tme_m68k_exception_process_start(ic, 0);
        !          1003:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, TME_M68K_VECTOR_PRIV);
        !          1004:   }
        !          1005: 
        !          1006:   /* group 4.1 exceptions: */
        !          1007:   if (exceptions & TME_M68K_EXCEPTION_TRACE) {
        !          1008:     tme_m68k_exception_process_start(ic, 0);
        !          1009:     tme_m68k_push32(ic, ic->tme_m68k_ireg_pc_last);
        !          1010:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_2, TME_M68K_VECTOR_TRACE);
        !          1011:   }
        !          1012:   
        !          1013:   /* group 4.2 exceptions: */
        !          1014:   if (TME_M68K_EXCEPTION_IS_INT(exceptions)) {
        !          1015:     tme_m68k_exception_process_start(ic, TME_M68K_EXCEPTION_IS_INT(exceptions));
        !          1016:     tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_0, TME_M68K_EXCEPTION_INT_VEC(exceptions));
        !          1017: 
        !          1018:     /* if the M-bit is set: */
        !          1019:     if (ic->tme_m68k_ireg_sr & TME_M68K_FLAG_M) {
        !          1020: 
        !          1021:       /* make the throwaway four-word stack frame (format 1): */
        !          1022:       fmt1.tme_m68k_fmt1_vector_offset = tme_htobe_u16((TME_M68K_FORMAT_1 << 12) | (TME_M68K_EXCEPTION_INT_VEC(exceptions) << 2));
        !          1023:       fmt1.tme_m68k_fmt1_pc_lo = tme_htobe_u16((ic->tme_m68k_ireg_pc >>  0) & 0xffff);
        !          1024:       fmt1.tme_m68k_fmt1_pc_hi = tme_htobe_u16((ic->tme_m68k_ireg_pc >> 16) & 0xffff);
        !          1025:       fmt1.tme_m68k_fmt1_sr = tme_htobe_u16(ic->tme_m68k_ireg_sr);
        !          1026: 
        !          1027:       /* store the throwaway four-word stack frame on the interrupt stack: */
        !          1028:       if (!TME_M68K_SEQUENCE_RESTARTING) {
        !          1029:        ic->_tme_m68k_ea_function_code = TME_M68K_FC_SD;
        !          1030:        ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_isp - sizeof(fmt1);
        !          1031:       }
        !          1032:       tme_m68k_write_mem(ic, (tme_uint8_t *) &fmt1, sizeof(fmt1));
        !          1033: 
        !          1034:       /* move to the interrupt stack: */
        !          1035:       ic->tme_m68k_ireg_isp -= sizeof(fmt1);
        !          1036:       tme_m68k_change_sr(ic, ic->tme_m68k_ireg_sr & ~TME_M68K_FLAG_M);
        !          1037:     }
1.1       root     1038:   }
                   1039:   
                   1040:   /* we have processed all exceptions - resume execution: */
                   1041:   ic->_tme_m68k_exceptions = 0;
                   1042:   ic->_tme_m68k_mode = TME_M68K_MODE_EXECUTION;
                   1043:   TME_M68K_SEQUENCE_START;
                   1044:   tme_m68k_redispatch(ic);
                   1045: }
                   1046: 
                   1047: /* this starts an m68k RTE: */
                   1048: tme_uint16_t
                   1049: tme_m68k_rte_start(struct tme_m68k *ic)
                   1050: {
                   1051: 
                   1052:   /* set up to read from the stack frame: */
1.1.1.3 ! root     1053:   if (!TME_M68K_SEQUENCE_RESTARTING) {
        !          1054:     ic->_tme_m68k_ea_function_code = TME_M68K_FC_SD;
        !          1055:     ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_a7;
        !          1056:   }
1.1       root     1057: 
                   1058:   /* read the stacked status register: */
                   1059:   tme_m68k_read_mem16(ic, TME_M68K_IREG_SHADOW_SR);
1.1.1.3 ! root     1060:   if (!TME_M68K_SEQUENCE_RESTARTING) {
        !          1061:     ic->_tme_m68k_ea_address += sizeof(ic->tme_m68k_ireg_shadow_sr);
        !          1062:   }
1.1       root     1063: 
                   1064:   /* read the stacked PC: */
                   1065:   tme_m68k_read_mem32(ic, TME_M68K_IREG_PC_NEXT);
1.1.1.3 ! root     1066:   if (!TME_M68K_SEQUENCE_RESTARTING) {
        !          1067:     ic->_tme_m68k_ea_address += sizeof(ic->tme_m68k_ireg_pc_next);
        !          1068:   }
1.1       root     1069: 
                   1070:   /* read the stacked format/offset word, unless this is a 68000: */
                   1071:   if (ic->tme_m68k_type != TME_M68K_M68000) {
                   1072:     tme_m68k_read_mem16(ic, TME_M68K_IREG_FORMAT_OFFSET);
1.1.1.3 ! root     1073:     if (!TME_M68K_SEQUENCE_RESTARTING) {
        !          1074:       ic->_tme_m68k_ea_address += sizeof(ic->tme_m68k_ireg_format_offset);
        !          1075:     }
1.1       root     1076:   }
                   1077:   else {
                   1078:     ic->tme_m68k_ireg_format_offset = 0;
                   1079:   }
                   1080: 
                   1081:   /* return the frame format: */
                   1082:   return (ic->tme_m68k_ireg_format_offset >> 12);
                   1083: }
                   1084: 
                   1085: /* this finishes an m68k RTE: */
                   1086: void
                   1087: tme_m68k_rte_finish(struct tme_m68k *ic, tme_uint32_t format_extra)
                   1088: {
                   1089:   tme_uint32_t frame_size;
                   1090: 
                   1091:   /* calculate the total frame size.  the 68000 doesn't have a
                   1092:      format/status word: */
                   1093:   frame_size = (sizeof(ic->tme_m68k_ireg_shadow_sr)
                   1094:                + sizeof(ic->tme_m68k_ireg_pc_next)
                   1095:                + (ic->tme_m68k_type != TME_M68K_M68000
                   1096:                   ? sizeof(ic->tme_m68k_ireg_format_offset)
                   1097:                   : 0)
                   1098:                + format_extra);
                   1099:   assert((frame_size & 1) == 0);
                   1100: 
                   1101:   /* adjust the stack: */
                   1102:   ic->tme_m68k_ireg_a7 += frame_size;
                   1103:   
                   1104:   /* set the status register: */
                   1105:   tme_m68k_change_sr(ic, ic->tme_m68k_ireg_shadow_sr);
                   1106:                     
                   1107:   /* set the PC: */
                   1108:   ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
                   1109:   
                   1110:   /* redispatch: */
                   1111:   tme_m68k_redispatch(ic);
                   1112: }
                   1113: 
                   1114: /* this stores the group 0 sequence into a region of host memory.
                   1115:    this is used when preparing the state information to be stored
                   1116:    on the stack for a bus or address error: */
                   1117: int
                   1118: tme_m68k_sequence_empty(const struct tme_m68k *ic, tme_uint8_t *raw, unsigned int raw_avail)
                   1119: {
                   1120:   const struct _tme_m68k_sequence *sequence;
                   1121:   unsigned int raw_used;
                   1122:   
                   1123:   /* get the group 0 sequence: */
                   1124:   sequence = &ic->_tme_m68k_group0_sequence;
                   1125:   raw_used = 0;
                   1126: 
                   1127:   /* we use 8 bits for the mode (2 bits) and flags (6 bits): */
                   1128:   raw_used += sizeof(tme_uint8_t);
                   1129:   assert(raw_avail >= raw_used);
                   1130:   assert(sequence->_tme_m68k_sequence_mode < TME_BIT(2));
                   1131:   assert(sequence->_tme_m68k_sequence_mode_flags < TME_BIT(6));
                   1132:   *(raw++) = ((sequence->_tme_m68k_sequence_mode << 6)
                   1133:              | sequence->_tme_m68k_sequence_mode_flags);
                   1134:   
                   1135: 
                   1136:   /* we use 16 bits for the faulted memory transfer ordinal
                   1137:      (12 bits) and already-transferred byte count (4 bits): */
                   1138:   raw_used += sizeof(tme_uint16_t);
                   1139:   assert(raw_avail >= raw_used);
                   1140:   assert(sequence->_tme_m68k_sequence_transfer_faulted < TME_BIT(12));
                   1141:   assert(sequence->_tme_m68k_sequence_transfer_faulted_after < TME_BIT(4));
                   1142:   *(raw++) = sequence->_tme_m68k_sequence_transfer_faulted >> 4;
                   1143:   *(raw++) = ((sequence->_tme_m68k_sequence_transfer_faulted << 4)
                   1144:              | sequence->_tme_m68k_sequence_transfer_faulted_after);
                   1145: 
                   1146: #ifdef _TME_M68K_VERIFY
                   1147:   /* we use sizeof(_tme_m68k_sequence_uid) bytes for the sequence UID: */
                   1148:   raw_used += sizeof(sequence->_tme_m68k_sequence_uid);
                   1149:   assert(raw_avail >= raw_used);
                   1150:   memcpy(raw,
                   1151:         &sequence->_tme_m68k_sequence_uid,
                   1152:         sizeof(sequence->_tme_m68k_sequence_uid));
                   1153:   raw += sizeof(sequence->_tme_m68k_sequence_uid);
                   1154: #endif /* _TME_M68K_VERIFY */
                   1155: 
                   1156:   /* done: */
                   1157:   return (raw_used);
                   1158: }
                   1159: 
                   1160: /* this restores the group 0 sequence from a region of host memory.
                   1161:    this is used when reading the state information stored on the
                   1162:    stack for a bus or address error: */
                   1163: int
                   1164: tme_m68k_sequence_fill(struct tme_m68k *ic, const tme_uint8_t *raw, unsigned int raw_avail)
                   1165: {
                   1166:   struct _tme_m68k_sequence *sequence;
                   1167:   unsigned int raw_used;
                   1168:   
                   1169:   /* get the group 0 sequence: */
                   1170:   sequence = &ic->_tme_m68k_group0_sequence;
                   1171:   raw_used = 0;
                   1172: 
                   1173:   /* we used 8 bits for the mode (2 bits) and flags (6 bits): */
                   1174:   raw_used += sizeof(tme_uint8_t);
                   1175:   if (raw_avail < raw_used) {
                   1176:     return (-1);
                   1177:   }
                   1178:   sequence->_tme_m68k_sequence_mode = *raw >> 6;
                   1179:   sequence->_tme_m68k_sequence_mode_flags = (*(raw++) & (TME_BIT(6) - 1));
                   1180: 
                   1181:   /* we used 16 bits for the faulted memory transfer ordinal
                   1182:      (12 bits) and already-transferred byte count (4 bits): */
                   1183:   raw_used += sizeof(tme_uint16_t);
                   1184:   if (raw_avail < raw_used) {
                   1185:     return (-1);
                   1186:   }
                   1187:   sequence->_tme_m68k_sequence_transfer_faulted = 
                   1188:     (((tme_uint16_t) raw[0]) << 4)
                   1189:     | (raw[1] >> 4);
                   1190:   sequence->_tme_m68k_sequence_transfer_faulted_after = raw[1] & (TME_BIT(4) - 1);
                   1191:   raw += sizeof(tme_uint16_t);
                   1192: 
                   1193: #ifdef _TME_M68K_VERIFY
                   1194:   /* we used sizeof(_tme_m68k_sequence_uid) bytes for the sequence UID: */
                   1195:   raw_used += sizeof(sequence->_tme_m68k_sequence_uid);
                   1196:   if (raw_avail < raw_used) {
                   1197:     return (-1);
                   1198:   }
                   1199:   memcpy(&sequence->_tme_m68k_sequence_uid,
                   1200:         raw,
                   1201:         sizeof(sequence->_tme_m68k_sequence_uid));
                   1202:   raw += sizeof(sequence->_tme_m68k_sequence_uid);
                   1203: #endif /* _TME_M68K_VERIFY */
                   1204: 
                   1205:   /* initialize this to one: */
                   1206:   sequence->_tme_m68k_sequence_transfer_next = 1;
                   1207: 
                   1208:   /* done: */
                   1209:   return (raw_used);
                   1210: }
                   1211: 
                   1212: /* this transfers the instruction buffer to or from a region of host
                   1213:    memory.  unlike the raw region in host memory, where the 16- and
                   1214:    32-bit parts of the instruction are contiguous and therefore
                   1215:    potentially misaligned, in the instruction buffer these instruction
                   1216:    parts are all properly aligned.  given the instruction buffer, a
                   1217:    contiguous host memory buffer, a count of instruction bytes and the
                   1218:    sizes of the instruction fetches, this transfers from one buffer to
                   1219:    the other.
                   1220: 
                   1221:    this is used to fill the instruction buffer when we're restoring
                   1222:    our state from an exception stack or when we fault anywhere inside
                   1223:    the fast executor, and it's used to empty the instruction buffer
                   1224:    into an exception stack when we fault: */
                   1225: int
                   1226: tme_m68k_insn_buffer_xfer(struct tme_m68k *ic, tme_uint8_t *raw, unsigned int raw_avail, int what)
                   1227: {
                   1228:   int fill, sanity_assert;
                   1229:   tme_uint16_t fetch_total;
                   1230:   tme_uint16_t fetch_sizes;
                   1231:   unsigned int fetch_sizes_bits;
                   1232:   unsigned int insn_buffer_off, fetch_off, fetch_size, resid;
                   1233: #define _FETCH_SIZES_BITS (8 * sizeof(ic->_tme_m68k_insn_buffer_fetch_sizes))
                   1234: #define _FETCH_SIZE_BIT (1 << (_FETCH_SIZES_BITS - 1))
                   1235: #define _FETCH_SANITY(e) \
                   1236: do { \
                   1237:   if (sanity_assert) \
                   1238:     assert(e); \
                   1239:   else if (!(e)) \
                   1240:     return (-1); \
                   1241: } while (/* CONSTCOND */ 0)
                   1242:   
                   1243:   /* if what is zero, we faulted somewhere inside the fast executor
                   1244:      and we need to fill the instruction buffer from raw host memory: */
                   1245:   if (what == 0) {
                   1246:     fill = TRUE;
                   1247:     sanity_assert = TRUE;
                   1248: 
                   1249:     /* the fetch total and sizes are in the state: */
                   1250:     fetch_total = ic->_tme_m68k_insn_buffer_fetch_total;
                   1251:     fetch_sizes = ic->_tme_m68k_insn_buffer_fetch_sizes;
                   1252:     raw_avail = fetch_total;
                   1253:   }
                   1254: 
                   1255:   /* else, if what is one, we're emptying the instruction buffer into
                   1256:      an exception frame: */
                   1257:   else if (what == 1) {
                   1258:     fill = FALSE;
                   1259:     sanity_assert = TRUE;
                   1260: 
                   1261:     /* the fetch total and sizes are in the state: */
                   1262:     fetch_total = ic->_tme_m68k_insn_buffer_fetch_total;
                   1263:     fetch_sizes = ic->_tme_m68k_insn_buffer_fetch_sizes;
                   1264: 
                   1265:     /* the first word we place into the exception frame is
                   1266:        (fetch_sizes << 4) | (fetch_total >> 1): */
                   1267:     _FETCH_SANITY(raw_avail >= sizeof(tme_uint16_t));
                   1268:     raw[1] = (fetch_sizes << 4) | (fetch_total >> 1);
                   1269:     raw[0] = (fetch_sizes >> 4);
                   1270:     raw += sizeof(tme_uint16_t);
                   1271:     raw_avail -= sizeof(tme_uint16_t);
                   1272:   }
                   1273: 
                   1274:   /* otherwise, we're filling the instruction buffer from an exception
                   1275:      frame: */
                   1276:   else {
                   1277:     fill = TRUE;
                   1278:     sanity_assert = FALSE;
                   1279: 
                   1280:     /* this function previously emptied the instruction buffer into
                   1281:        this exception frame, and the first big-endian word placed
                   1282:        there is (fetch_sizes << 4) | (fetch_total >> 1): */
                   1283:     _FETCH_SANITY(raw_avail >= sizeof(tme_uint16_t));
                   1284:     fetch_total = (raw[1] & 0x0f) << 1;
                   1285:     fetch_sizes = (raw[0] << 4) | (raw[1] >> 4);
                   1286:     raw += sizeof(tme_uint16_t);
                   1287:     raw_avail -= sizeof(tme_uint16_t);
                   1288:   }
                   1289: 
                   1290:   /* fetch_total must be even, because we only fetch some multiple of
                   1291:      16-bit words: */
                   1292:   _FETCH_SANITY((fetch_total & (sizeof(tme_uint16_t) - 1)) == 0);
                   1293: 
                   1294:   /* fetch_sizes is a bitmask, with a one bit representing a 32-bit
                   1295:      fetch and a zero bit representing a 16-bit fetch, and the least
                   1296:      significant bit is the *last* fetch performed.  count the number
                   1297:      of significant bits in fetch_sizes and confirm that it makes
                   1298:      sense with fetch_total: */
                   1299:   fetch_sizes_bits = 0;
                   1300:   for (fetch_off = 0; fetch_off < fetch_total; ) {
                   1301:     _FETCH_SANITY(fetch_sizes_bits < _FETCH_SIZES_BITS);
                   1302:     fetch_off += ((fetch_sizes & (1 << fetch_sizes_bits))
                   1303:                  /* a 32-bit fetch: */
                   1304:                  ? sizeof(tme_uint32_t)
                   1305:                  /* a 16-bit fetch: */
                   1306:                  : sizeof(tme_uint16_t));
                   1307:     fetch_sizes_bits++;
                   1308:   }
                   1309:   _FETCH_SANITY(fetch_off == fetch_total);
                   1310: 
                   1311:   /* we must have enough raw space available: */
                   1312:   _FETCH_SANITY(raw_avail >= fetch_total);
                   1313: 
                   1314:   /* shift fetch_sizes up so the bit for the first transfer
                   1315:      is the most significant bit: */
                   1316:   fetch_sizes <<= (_FETCH_SIZES_BITS - fetch_sizes_bits);
                   1317: 
                   1318:   /* now fill or empty the instruction buffer: */
                   1319:   insn_buffer_off = 0;
                   1320:   for (fetch_off = 0; fetch_off < fetch_total; ) {
                   1321: 
                   1322:     /* get the size of this fetch: */
                   1323:     fetch_size = ((fetch_sizes & _FETCH_SIZE_BIT)
                   1324:                  /* a 32-bit fetch: */
                   1325:                  ? sizeof(tme_uint32_t)
                   1326:                  /* a 16-bit fetch: */
                   1327:                  : sizeof(tme_uint16_t));
                   1328:     fetch_sizes <<= 1;
                   1329: 
                   1330:     /* do one transfer.  the insn buffer is kept in host byte
                   1331:        order, like the internal registers are: */
                   1332:     insn_buffer_off = TME_ALIGN(insn_buffer_off, fetch_size);
                   1333:     if (fill) {
                   1334:       for (resid = fetch_size; resid-- > 0; ) {
                   1335:        ic->_tme_m68k_insn_buffer[(insn_buffer_off
                   1336:                                   + (resid
                   1337: #ifndef WORDS_BIGENDIAN
                   1338:                                      ^ (fetch_size - 1)
                   1339: #endif /* !WORDS_BIGENDIAN */
                   1340:                                      ))] 
                   1341:          = raw[fetch_off + resid];
                   1342:       }
                   1343:     }
                   1344:     else {
                   1345:       for (resid = fetch_size; resid-- > 0; ) {
                   1346:        raw[fetch_off + resid] = 
                   1347:          ic->_tme_m68k_insn_buffer[(insn_buffer_off
                   1348:                                     + (resid
                   1349: #ifndef WORDS_BIGENDIAN
                   1350:                                        ^ (fetch_size - 1)
                   1351: #endif /* !WORDS_BIGENDIAN */
                   1352:                                        ))];
                   1353:       }
                   1354:     }
                   1355:     insn_buffer_off += fetch_size;
                   1356:     fetch_off += fetch_size;
                   1357: 
                   1358:     /* if we faulted somewhere in the fast executor, we need to
                   1359:        account for the instruction fetches in the group0 sequence: */
                   1360:     if (what == 0) {
                   1361:       ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_next++;
                   1362:     }
                   1363:   }
                   1364: 
                   1365:   /* NB: for total consistency we might want to store the fetch total
                   1366:      and sizes into the state when we're filling the instruction
                   1367:      buffer from an execution frame.  however this isn't really needed
                   1368:      because the fetch pattern from the restarting slow executor
                   1369:      should be exactly the same and it doesn't care anyways. 
                   1370:      if the user bashes the exception frame all bets are off. */
                   1371: 
                   1372:   /* return the number of bytes we put in an exception frame: */
                   1373:   return (sizeof(tme_uint16_t) + fetch_total);
                   1374: }
                   1375: 
                   1376: /* this is the group 0 fault hook for the fast executor: */
                   1377: void
                   1378: tme_m68k_group0_hook_fast(struct tme_m68k *ic)
                   1379: {
                   1380:   struct tme_m68k_tlb *tlb;
                   1381:   tme_uint8_t *raw;
                   1382: 
                   1383:   /* fill the instruction buffer and increase the transfer count
                   1384:      as if the slow executor had been doing the fetching: */
1.1.1.3 ! root     1385:   /* NB that this breaks const: */
1.1       root     1386:   tlb = TME_ATOMIC_READ(struct tme_m68k_tlb *, ic->_tme_m68k_itlb);
1.1.1.3 ! root     1387:   raw = (tme_uint8_t *) (tlb->tme_m68k_tlb_emulator_off_read + ic->tme_m68k_ireg_pc);
1.1       root     1388:   tme_m68k_insn_buffer_xfer(ic, raw, 0, 0);
                   1389: }
                   1390: 
                   1391: /* this starts a read/modify/write cycle.  this works in conjunction
                   1392:    with the tme_m68k_readSIZE() and tme_m68k_writeSIZE() functions to
                   1393:    aggregate many bus transactions into a larger transaction: */
                   1394: struct tme_m68k_tlb *
                   1395: tme_m68k_rmw_start(struct tme_m68k *ic)
                   1396: {
                   1397:   struct tme_m68k_tlb *tlb;
                   1398: 
                   1399:   /* if the user reran the cycle, do nothing: */
                   1400:   if (TME_M68K_SEQUENCE_RESTARTING
                   1401:       && (ic->_tme_m68k_group0_buffer_read_softrr > 0
                   1402:          || ic->_tme_m68k_group0_buffer_write_softrr > 0)) {
                   1403:     return (NULL);
                   1404:   }
                   1405: 
                   1406:   /* we always rerun read/modify/write cycles in their entirety: */
                   1407:   ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted
                   1408:     = ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next - 1;
                   1409: 
                   1410:   /* get an applicable TLB entry: */
                   1411:   tlb = TME_M68K_TLB_ENTRY(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address);
                   1412: 
                   1413:   /* we *must* guarantee that a read/modify/write cycle be atomic.
                   1414:      unfortunately, the only way we can really do that is to acquire a
                   1415:      single lock, now, that somehow protects all of the things we want
                   1416:      to do, and hold that lock for the duration.
                   1417: 
                   1418:      the only way we can do this is to require that read/modify/write
                   1419:      cycles always involve TLB entries that allow fast reads and
                   1420:      writes.  this gives us a single rwlock that we can lock for
                   1421:      writing now and hold until we're done: */
                   1422: 
                   1423:   /* we invalidate the TLB entry so we can set the TLB rwlock to NULL,
                   1424:      which is seen by the first tme_m68k_readSIZE (or
                   1425:      tme_m68k_writeSIZE, in the bizarre case that that's called first)
                   1426:      as a signal that, after it reloads the TLB entry, it has to lock
                   1427:      the rwlock: */
                   1428:   tme_bus_tlb_invalidate(&tlb->tme_m68k_tlb_bus_tlb);
                   1429:   tlb->tme_m68k_tlb_bus_rwlock = NULL;
                   1430: 
                   1431:   return (tlb);
                   1432: }
                   1433: 
                   1434: /* this finishes a read/modify/write cycle.  this works in conjunction
                   1435:    with the tme_m68k_readSIZE() and tme_m68k_writeSIZE() functions to
                   1436:    aggregate many bus transactions into a larger transaction: */
                   1437: void
                   1438: tme_m68k_rmw_finish(struct tme_m68k *ic, struct tme_m68k_tlb *tlb)
                   1439: {
                   1440:   
                   1441:   /* if we didn't acquire the rwlock, something is wrong: */
                   1442:   assert(tlb->tme_m68k_tlb_bus_rwlock != NULL);
                   1443:   
                   1444:   /* unlock the lock: */
                   1445:   tme_rwlock_unlock(tlb->tme_m68k_tlb_bus_rwlock);
                   1446: }
                   1447: 
                   1448: /* this handles a bitfield offset.  if the bitfield is in memory,
                   1449:    and it hasn't already been done, this adjusts the effective
                   1450:    address to point to the beginning of the bitfield.  this always
                   1451:    returns a nonnegative bitfield offset: */
                   1452: unsigned int
                   1453: tme_m68k_bitfield_offset(struct tme_m68k *ic, int adjust)
                   1454: {
                   1455:   tme_int16_t specop;
                   1456:   tme_int32_t bf_offset;
                   1457:   tme_int32_t bf_ea_offset;
                   1458:     
                   1459:   /* get the bitfield offset from a data register or as an immediate: */
                   1460:   specop = ic->_tme_m68k_insn_specop;
                   1461:   bf_offset = ((specop & TME_BIT(11))
                   1462:               ? ic->tme_m68k_ireg_int32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop, 6, 3))
                   1463:               : (tme_int32_t) TME_FIELD_EXTRACTU(specop, 6, 5));
                   1464: 
                   1465:   /* if this bitfield is in a register (EA mode field is zero): */
                   1466:   if (TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 3, 3) == 0) {
                   1467: 
                   1468:     /* adjust the bitfield offset to be nonnegative: */
                   1469:     bf_offset &= 31;
                   1470:   }
                   1471: 
                   1472:   /* otherwise, this bitfield is in memory: */
                   1473:   else {
                   1474: 
                   1475:     /* calculate the effective address offset and adjust the bitfield
                   1476:        offset to be nonnegative: */
1.1.1.3 ! root     1477:     bf_ea_offset = ((bf_offset < 0
        !          1478:                     ? (bf_offset - 7)
        !          1479:                     : bf_offset)
        !          1480:                    / 8);
1.1       root     1481:     bf_offset &= 7;
                   1482: 
                   1483:     /* if this is our first call to this function for this instruction
                   1484:        and we're not restarting, adjust the effective address: */
                   1485:     if (adjust
                   1486:        && !TME_M68K_SEQUENCE_RESTARTING) {
                   1487:       ic->_tme_m68k_ea_address += bf_ea_offset;
                   1488:     }
                   1489:   }
                   1490: 
                   1491:   /* return the nonnegative bitfield offset: */
                   1492:   return ((unsigned int) bf_offset);
                   1493: }
                   1494: 
                   1495: /* this returns a bitfield width: */
                   1496: unsigned int
                   1497: tme_m68k_bitfield_width(struct tme_m68k *ic)
                   1498: {
                   1499:   unsigned int bf_width;
                   1500:   tme_int16_t specop;
                   1501: 
                   1502:   /* get the bitfield width from a register or as an immediate: */
                   1503:   specop = ic->_tme_m68k_insn_specop;
                   1504:   if (specop & TME_BIT(5)) {
                   1505:     bf_width = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop, 0, 3));
1.1.1.3 ! root     1506:     bf_width &= 31;
1.1       root     1507:   }
                   1508:   else {
                   1509:     bf_width = TME_FIELD_EXTRACTU(specop, 0, 5);
                   1510:   }
                   1511:   if (bf_width == 0) bf_width = 32;
                   1512:   return (bf_width);
                   1513: }
                   1514: 
                   1515: /* this reads a bitfield: */
                   1516: tme_uint32_t
                   1517: _tme_m68k_bitfield_read(struct tme_m68k *ic, int is_signed)
                   1518: {
                   1519:   unsigned int bf_offset, bf_width;
                   1520:   unsigned int shift;
                   1521:   tme_uint8_t *bf_bytes;
                   1522:   tme_uint32_t bf_value;
                   1523:   int ireg;
                   1524: 
                   1525:   /* get the bitfield offset and width: */
                   1526:   bf_offset = tme_m68k_bitfield_offset(ic, TRUE);
                   1527:   bf_width = tme_m68k_bitfield_width(ic);
                   1528: 
                   1529:   /* if this expression is > 32, in a register this means the bitfield
1.1.1.3 ! root     1530:      wraps, and in memory this means the bitfield covers 5 bytes: */
1.1       root     1531:   shift = (bf_offset + bf_width);
                   1532: 
                   1533:   /* if this bitfield is in a register (EA mode field is zero): */
                   1534:   if (TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 3, 3) == 0) {
                   1535:     ireg = (TME_M68K_IREG_D0
                   1536:            + TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 0, 3));
                   1537: 
                   1538:     /* get the raw 32-bit word containing the bitfield: */
                   1539:     bf_value = ic->tme_m68k_ireg_uint32(ireg);
                   1540: 
                   1541:     /* if this bitfield wraps the register, shift in the wrapped part
                   1542:        on the right: */
                   1543:     if (shift > 32) {
                   1544:       shift -= 32;
                   1545:       bf_value = (bf_value << shift) | (bf_value >> (32 - shift));
                   1546:       bf_offset -= shift;
                   1547:     }
                   1548:   }
                   1549: 
                   1550:   /* otherwise, this bitfield is in memory: */
                   1551:   else {
                   1552: 
1.1.1.3 ! root     1553:     /* this instruction can fault: */
        !          1554:     ic->_tme_m68k_mode_flags |= TME_M68K_EXECUTION_INST_CANFAULT;
        !          1555: 
1.1       root     1556:     /* read in the bytes covering the bitfield: */
                   1557:     bf_bytes = (tme_uint8_t *) &ic->tme_m68k_ireg_memx32;
1.1.1.3 ! root     1558:     tme_m68k_read_mem(ic, bf_bytes, (bf_offset + bf_width + 7) / 8);
1.1       root     1559: 
                   1560:     /* get the raw 32-bit word containing the bitfield: */
                   1561:     bf_value = tme_betoh_u32(ic->tme_m68k_ireg_memx32);
                   1562: 
1.1.1.3 ! root     1563:     /* if this bitfield covers 5 bytes, shift in the part from the fifth byte
1.1       root     1564:        (actually in memy32!) on the right: */
                   1565:     if (shift > 32) {
                   1566:       shift -= 32;
                   1567:       bf_value = (bf_value << shift) | (bf_bytes[4] >> (8 - shift));
                   1568:       bf_offset -= shift;
                   1569:     }
                   1570:   }
                   1571:   
                   1572:   /* shift the value: */
                   1573:   shift = (32 - (bf_offset + bf_width));
                   1574:   bf_value >>= shift;
                   1575: 
                   1576:   /* mask the value: */
1.1.1.3 ! root     1577:   bf_value &= (0xffffffffUL >> (32 - bf_width));
1.1       root     1578: 
                   1579:   /* if this is a signed value, sign-extend it: */
                   1580:   if (is_signed
                   1581:       && (bf_value & TME_BIT(bf_width - 1))) {
1.1.1.3 ! root     1582:     bf_value |= (0xffffffffUL << (bf_width - 1));
1.1       root     1583:   }
                   1584: 
                   1585:   /* all bitfield instructions that read the bitfield set the flags: */
                   1586:   if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1587:     ic->tme_m68k_ireg_ccr = ((ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X)
                   1588:                             | ((bf_value & TME_BIT(bf_width - 1))
                   1589:                                ? TME_M68K_FLAG_N
                   1590:                                : 0)
                   1591:                             | (bf_value
                   1592:                                ? 0
                   1593:                                : TME_M68K_FLAG_Z));
                   1594:   }
                   1595: 
                   1596:   /* return the bitfield value: */
                   1597:   return (bf_value);
                   1598: }
                   1599: 
                   1600: /* this writes a bitfield to memory: */
                   1601: void
                   1602: tme_m68k_bitfield_write_unsigned(struct tme_m68k *ic, tme_uint32_t bf_value, int set_flags)
                   1603: {
                   1604:   unsigned int bf_offset, bf_width;
                   1605:   unsigned int shift;
                   1606:   tme_uint8_t *bf_bytes;
                   1607:   unsigned int count;
                   1608:   int ireg;
                   1609: 
                   1610:   /* for bitfields in memory, we want to know if the memory covering
                   1611:      the bitfield is already in our memory buffer, so we can avoid
                   1612:      reading that memory again.  all bitfield instructions set flags
                   1613:      based on a bitfield value; if set_flags is FALSE our caller
                   1614:      must have tested the old bitfield value, and so the bitfield
                   1615:      memory must be in our buffer, otherwise assume that this is our
                   1616:      first access to the bitfield memory: */
                   1617: #define first_memory set_flags
                   1618:   
                   1619:   /* get the bitfield offset and width: */
                   1620:   bf_offset = tme_m68k_bitfield_offset(ic, first_memory);
                   1621:   bf_width = tme_m68k_bitfield_width(ic);
                   1622: 
                   1623:   /* if this expression is > 32, in a register this means the bitfield
1.1.1.3 ! root     1624:      wraps, and in memory this means the bitfield covers 5 bytes: */
1.1       root     1625:   shift = (bf_offset + bf_width);
                   1626: 
1.1.1.3 ! root     1627:   /* mask the value: */
        !          1628:   bf_value &= (0xffffffffUL >> (32 - bf_width));
        !          1629: 
1.1       root     1630:   /* if we're supposed to, set the flags: */
                   1631:   if (set_flags
                   1632:       && !TME_M68K_SEQUENCE_RESTARTING) {
                   1633:     ic->tme_m68k_ireg_ccr = ((ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X)
                   1634:                             | ((bf_value & TME_BIT(bf_width - 1))
                   1635:                                ? TME_M68K_FLAG_N
                   1636:                                : 0)
                   1637:                             | (bf_value
                   1638:                                ? 0
                   1639:                                : TME_M68K_FLAG_Z));
                   1640:   }
                   1641: 
                   1642:   /* if this bitfield is in a register (EA mode field is zero): */
                   1643:   if (TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 3, 3) == 0) {
                   1644:     ireg = (TME_M68K_IREG_D0
                   1645:            + TME_FIELD_EXTRACTU(ic->_tme_m68k_insn_opcode, 0, 3));
                   1646:     
                   1647:     /* if this bitfield wraps the register, put the wrapped
                   1648:        part in the left: */
                   1649:     if (shift > 32) {
                   1650:       shift -= 32;
                   1651:       ic->tme_m68k_ireg_uint32(ireg) = ((ic->tme_m68k_ireg_uint32(ireg)
                   1652:                                         & (0xffffffffUL >> shift))
                   1653:                                        | (bf_value << (32 - shift)));
                   1654:       bf_value >>= shift;
                   1655:       bf_width -= shift;
                   1656:     }
                   1657:     
                   1658:     /* update the register: */
                   1659:     shift = (32 - (bf_offset + bf_width));
                   1660:     ic->tme_m68k_ireg_uint32(ireg) = ((ic->tme_m68k_ireg_uint32(ireg)
1.1.1.3 ! root     1661:                                       & ~((0xffffffffUL >> (32 - bf_width)) << shift))
1.1       root     1662:                                      | (bf_value << shift));
                   1663:   }
                   1664: 
                   1665:   /* otherwise, this bitfield is in memory: */
                   1666:   else {
                   1667: 
1.1.1.3 ! root     1668:     /* this instruction can fault: */
        !          1669:     ic->_tme_m68k_mode_flags |= TME_M68K_EXECUTION_INST_CANFAULT;
        !          1670: 
1.1       root     1671:     /* read in the bytes covering the bitfield if we haven't yet: */
                   1672:     bf_bytes = (tme_uint8_t *) &ic->tme_m68k_ireg_memx32;
1.1.1.3 ! root     1673:     count = (bf_offset + bf_width + 7) / 8;
1.1       root     1674:     if (first_memory) {
                   1675:       tme_m68k_read_mem(ic, bf_bytes, count);
                   1676:     }
                   1677: 
1.1.1.3 ! root     1678:     /* if this bitfield covers 5 bytes, put the part for the fifth
1.1       root     1679:        byte (actually in memy32!) in on the left: */
                   1680:     if (shift > 32) {
                   1681:       shift -= 32;
                   1682:       if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1683:        bf_bytes[4] = ((bf_bytes[4]
                   1684:                        & (0xff >> shift))
                   1685:                       | ((bf_value & 0xff) << (8 - shift)));
                   1686:       }
                   1687:       bf_value >>= shift;
                   1688:       bf_width -= shift;
                   1689:     }
                   1690: 
                   1691:     /* update the memory buffer: */
                   1692:     if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1693:       shift = (32 - (bf_offset + bf_width));
                   1694:       ic->tme_m68k_ireg_memx32 =
                   1695:        tme_htobe_u32((tme_betoh_u32(ic->tme_m68k_ireg_memx32)
1.1.1.3 ! root     1696:                       & ~((0xffffffffUL >> (32 - bf_width)) << shift))
1.1       root     1697:                      | (bf_value << shift));
                   1698:     }
                   1699: 
                   1700:     /* write out the bytes covering bitfield to memory: */
                   1701:     tme_m68k_write_mem(ic, bf_bytes, count);
                   1702:   }
                   1703: #undef first_memory
                   1704: }
                   1705: 
                   1706: /* our global verify hook function: */
1.1.1.2   root     1707: #undef tme_m68k_verify_hook
1.1       root     1708: void
                   1709: tme_m68k_verify_hook(void)
                   1710: {
                   1711: }
                   1712: 
                   1713: #if 1
                   1714: #include <stdio.h>
                   1715: 
                   1716: /* this dumps out the m68k state: */
                   1717: void
                   1718: tme_m68k_dump(struct tme_m68k *ic)
                   1719: {
                   1720:   int ireg;
                   1721:   int count;
                   1722: 
                   1723:   /* dump out the integer registers: */
                   1724:   count = 0;
                   1725:   for (ireg = TME_M68K_IREG_D0;
                   1726:        ireg <= TME_M68K_IREG_A7;
                   1727:        ireg++) {
                   1728:     fprintf(stderr,
                   1729:            "%%%c%d[%p] = 0x%08x",
                   1730:            (ireg < TME_M68K_IREG_A0
                   1731:             ? 'd'
                   1732:             : 'a'),
                   1733:            ireg - (ireg < TME_M68K_IREG_A0
                   1734:                    ? TME_M68K_IREG_D0
                   1735:                    : TME_M68K_IREG_A0),
                   1736:            &ic->tme_m68k_ireg_uint32(ireg),
                   1737:            ic->tme_m68k_ireg_uint32(ireg));
                   1738:     if (++count == 2) {
                   1739:       fprintf(stderr, "\n");
                   1740:       count = 0;
                   1741:     }
                   1742:     else {
                   1743:       fprintf(stderr, "  ");
                   1744:     }
                   1745:   }
                   1746: 
                   1747:   /* dump out the PC and next PC: */
                   1748:   fprintf(stderr, "%%pc = 0x%08x  %%pc_next = 0x%08x\n",
                   1749:          ic->tme_m68k_ireg_pc,
                   1750:          ic->tme_m68k_ireg_pc_next);
                   1751: 
                   1752:   /* dump out the status register: */
                   1753:   fprintf(stderr, "%%sr = 0x%04x", ic->tme_m68k_ireg_sr);
                   1754:   fprintf(stderr, "  flags:");
                   1755:   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X) {
                   1756:     fprintf(stderr, " X");
                   1757:   }
                   1758:   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_N) {
                   1759:     fprintf(stderr, " N");
                   1760:   }
                   1761:   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) {
                   1762:     fprintf(stderr, " Z");
                   1763:   }
                   1764:   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_V) {
                   1765:     fprintf(stderr, " V");
                   1766:   }
                   1767:   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_C) {
                   1768:     fprintf(stderr, " C");
                   1769:   }
                   1770:   fprintf(stderr, "\n");
                   1771: 
                   1772:   /* dump out the effective address and memory buffers: */
                   1773:   fprintf(stderr, "\n");
                   1774:   fprintf(stderr, "EA = %d:0x%08x\n",
                   1775:          ic->_tme_m68k_ea_function_code,
                   1776:          ic->_tme_m68k_ea_address);
                   1777:   fprintf(stderr, "%%memx[%p] = 0x%08x  %%memy[%p] = 0x%08x\n",
                   1778:          &ic->tme_m68k_ireg_memx32,
                   1779:          ic->tme_m68k_ireg_memx32,
                   1780:          &ic->tme_m68k_ireg_memy32,
                   1781:          ic->tme_m68k_ireg_memy32);
                   1782: 
                   1783:   /* dump out the control registers: */
                   1784:   fprintf(stderr, "\n");
                   1785:   fprintf(stderr, "%%usp = 0x%08x\n", ic->tme_m68k_ireg_usp);
                   1786:   fprintf(stderr, "%%isp = 0x%08x\n", ic->tme_m68k_ireg_isp);
                   1787:   fprintf(stderr, "%%msp = 0x%08x\n", ic->tme_m68k_ireg_msp);
                   1788:   fprintf(stderr, "%%sfc = 0x%08x\n", ic->tme_m68k_ireg_sfc);
                   1789:   fprintf(stderr, "%%dfc = 0x%08x\n", ic->tme_m68k_ireg_dfc);
                   1790:   fprintf(stderr, "%%vbr = 0x%08x\n", ic->tme_m68k_ireg_vbr);
                   1791:   
                   1792:   /* dump out instruction decoding information: */
                   1793:   fprintf(stderr, "\n");
1.1.1.3 ! root     1794:   fprintf(stderr, "opcode = 0x%04x  specop = 0x%04x\n",
1.1       root     1795:          ic->_tme_m68k_insn_opcode,
1.1.1.3 ! root     1796:          ic->_tme_m68k_insn_specop);
1.1       root     1797: }
                   1798: #endif /* 1 */

unix.superglobalmegacorp.com

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