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