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

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

unix.superglobalmegacorp.com

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