|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.