|
|
1.1 ! root 1: /* $Id: m68020.c,v 1.6 2005/04/30 15:14:37 fredette Exp $ */ ! 2: ! 3: /* ic/m68k/m68020.c - implementation of Motorola 68020 emulation: */ ! 4: ! 5: /* ! 6: * Copyright (c) 2002, 2003, 2004 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: */ ! 35: ! 36: #include <tme/common.h> ! 37: _TME_RCSID("$Id: m68020.c,v 1.6 2005/04/30 15:14:37 fredette Exp $"); ! 38: ! 39: /* includes: */ ! 40: #include "m68k-impl.h" ! 41: ! 42: /* macros: */ ! 43: #define TME_M68K_SSWB_FC (0x8000) ! 44: #define TME_M68K_SSWB_FB (0x4000) ! 45: #define TME_M68K_SSWB_RC (0x2000) ! 46: #define TME_M68K_SSWB_RB (0x1000) ! 47: #define TME_M68K_SSWB_DF (0x0100) ! 48: #define TME_M68K_SSWB_RM (0x0080) ! 49: #define TME_M68K_SSWB_RW (0x0040) ! 50: #define TME_M68K_SSWB_SIZE_MASK (0x0030) ! 51: #define TME_M68K_SSWB_SIZE_4 (0x0000) ! 52: #define TME_M68K_SSWB_SIZE_1 (0x0010) ! 53: #define TME_M68K_SSWB_SIZE_2 (0x0020) ! 54: #define TME_M68K_SSWB_SIZE_3 (0x0030) ! 55: ! 56: /* structures: */ ! 57: ! 58: /* the format 0xB stack frame: */ ! 59: /* XXX we assume that this will pack: */ ! 60: struct tme_m68k_fmtB { ! 61: ! 62: /* an unused word: */ ! 63: tme_uint8_t tme_m68k_fmtB_state0[1 * sizeof(tme_uint16_t)]; ! 64: ! 65: /* the special status word: */ ! 66: tme_uint16_t tme_m68k_fmtB_ssw; ! 67: ! 68: /* the instruction pipe stage C: */ ! 69: tme_uint16_t tme_m68k_fmtB_ipipe_C; ! 70: ! 71: /* the instruction pipe stage B: */ ! 72: tme_uint16_t tme_m68k_fmtB_ipipe_B; ! 73: ! 74: /* the data cycle fault address: */ ! 75: tme_uint32_t tme_m68k_fmtB_addr; ! 76: ! 77: /* two unused words: */ ! 78: tme_uint8_t tme_m68k_fmtB_state1[2 * sizeof(tme_uint16_t)]; ! 79: ! 80: /* the data output buffer: */ ! 81: tme_uint8_t tme_m68k_fmtB_dob[4]; ! 82: ! 83: /* four unused words: */ ! 84: tme_uint8_t tme_m68k_fmtB_state2[4 * sizeof(tme_uint16_t)]; ! 85: ! 86: /* the stage B address: */ ! 87: tme_uint32_t tme_m68k_fmtB_addr_B; ! 88: ! 89: /* two unused words: */ ! 90: tme_uint8_t tme_m68k_fmtB_state3[2 * sizeof(tme_uint16_t)]; ! 91: ! 92: /* the data input buffer: */ ! 93: tme_uint8_t tme_m68k_fmtB_dib[4]; ! 94: ! 95: /* three unused words: */ ! 96: tme_uint8_t tme_m68k_fmtB_state4[3 * sizeof(tme_uint16_t)]; ! 97: ! 98: /* the version number and internal information: */ ! 99: tme_uint16_t tme_m68k_fmtB_version_info; ! 100: ! 101: /* eighteen unused words: */ ! 102: tme_uint8_t tme_m68k_fmtB_state5[18 * sizeof(tme_uint16_t)]; ! 103: }; ! 104: ! 105: /* both executors are for the 68020: */ ! 106: #define _TME_M68K_EXECUTE_CPU TME_M68K_M68020 ! 107: #define _TME_M68K_EXECUTE_OPMAP tme_m68k_opcodes_m68020 ! 108: ! 109: /* create the slow executor: */ ! 110: #define _TME_M68K_EXECUTE_NAME _tme_m68020_execute_slow ! 111: #undef _TME_M68K_EXECUTE_FAST ! 112: #undef _TME_M68K_EXECUTE_SLOW ! 113: #include "m68k-execute.c" ! 114: #undef _TME_M68K_EXECUTE_NAME ! 115: #undef _TME_M68K_EXECUTE_FAST ! 116: #undef _TME_M68K_EXECUTE_SLOW ! 117: ! 118: /* create the fast executor: */ ! 119: #define _TME_M68K_EXECUTE_NAME _tme_m68020_execute ! 120: #define _TME_M68K_EXECUTE_FAST ! 121: #define _TME_M68K_EXECUTE_SLOW _tme_m68020_execute_slow ! 122: #include "m68k-execute.c" ! 123: #undef _TME_M68K_EXECUTE_NAME ! 124: #undef _TME_M68K_EXECUTE_FAST ! 125: #undef _TME_M68K_EXECUTE_SLOW ! 126: ! 127: #undef _TME_M68K_EXECUTE_CPU ! 128: ! 129: /* m68020 exception processing: */ ! 130: static void ! 131: _tme_m68020_exception(struct tme_m68k *ic) ! 132: { ! 133: tme_uint32_t exceptions; ! 134: /* one 16-bit word for each 16-bit internal register word in the format 0xB frame: */ ! 135: tme_uint8_t raw_state[(1 + 2 + 4 + 2 + 3 + 18) * sizeof(tme_uint16_t)], *raw; ! 136: unsigned int raw_avail, raw_used; ! 137: struct tme_m68k_fmtB fmtB; ! 138: unsigned int flags; ! 139: tme_uint8_t function_code; ! 140: tme_uint16_t ssw; ! 141: ! 142: /* get the set of exceptions: */ ! 143: exceptions = ic->_tme_m68k_exceptions; ! 144: ! 145: /* a reset exception: */ ! 146: if (exceptions & TME_M68K_EXCEPTION_RESET) { ! 147: ! 148: /* do the common reset processing: */ ! 149: tme_m68k_do_reset(ic); ! 150: /* NOTREACHED */ ! 151: } ! 152: ! 153: /* an address or bus error: */ ! 154: else if (exceptions & (TME_M68K_EXCEPTION_AERR ! 155: | TME_M68K_EXCEPTION_BERR)) { ! 156: ! 157: /* start the exception processing: */ ! 158: tme_m68k_exception_process_start(ic, 0); ! 159: ! 160: /* start assembling the raw data: */ ! 161: raw = raw_state; ! 162: raw_avail = sizeof(raw_state); ! 163: #define RAW_PUT(v) \ ! 164: do { \ ! 165: assert(raw_avail >= sizeof(v)); \ ! 166: memcpy(raw, &v, sizeof(v)); \ ! 167: raw += sizeof(v); \ ! 168: raw_avail -= sizeof(v); \ ! 169: } while (/* CONSTCOND */ 0) ! 170: ! 171: /* put in the sequence: */ ! 172: raw_used = tme_m68k_sequence_empty(ic, raw, raw_avail); ! 173: raw += raw_used; ! 174: raw_avail -= raw_used; ! 175: ! 176: /* dispatch on the mode: */ ! 177: switch (ic->_tme_m68k_group0_sequence._tme_m68k_sequence_mode) { ! 178: ! 179: case TME_M68K_MODE_EXECUTION: ! 180: ! 181: /* put in the instruction buffer: */ ! 182: raw_used = tme_m68k_insn_buffer_empty(ic, raw, raw_avail); ! 183: raw += raw_used; ! 184: raw_avail -= raw_used; ! 185: ! 186: /* put in the EA address: */ ! 187: function_code = ic->_tme_m68k_ea_function_code; ! 188: RAW_PUT(function_code); ! 189: RAW_PUT(ic->_tme_m68k_ea_address); ! 190: ! 191: /* put in the memory X, Y, and Z buffers: */ ! 192: RAW_PUT(ic->tme_m68k_ireg_memx32); ! 193: RAW_PUT(ic->tme_m68k_ireg_memy32); ! 194: RAW_PUT(ic->tme_m68k_ireg_memz32); ! 195: ! 196: /* done: */ ! 197: break; ! 198: ! 199: case TME_M68K_MODE_EXCEPTION: ! 200: ! 201: /* put in the exceptions set: */ ! 202: RAW_PUT(ic->_tme_m68k_exceptions); ! 203: ! 204: /* put in the shadow status register: */ ! 205: RAW_PUT(ic->tme_m68k_ireg_shadow_sr); ! 206: ! 207: /* put in the last PC: */ ! 208: RAW_PUT(ic->tme_m68k_ireg_pc_last); ! 209: ! 210: /* done: */ ! 211: break; ! 212: ! 213: case TME_M68K_MODE_RTE: ! 214: ! 215: /* put in the shadow status register: */ ! 216: RAW_PUT(ic->tme_m68k_ireg_shadow_sr); ! 217: ! 218: /* put in the next program counter: */ ! 219: RAW_PUT(ic->tme_m68k_ireg_pc_next); ! 220: ! 221: /* put in the format/offset word: */ ! 222: RAW_PUT(ic->tme_m68k_ireg_format_offset); ! 223: ! 224: break; ! 225: ! 226: default: abort(); ! 227: } ! 228: ! 229: /* put in the internal state: */ ! 230: raw_avail = raw - raw_state; ! 231: raw = raw_state; ! 232: #undef RAW_PUT ! 233: #define RAW_PUT(f) \ ! 234: do { \ ! 235: raw_used = TME_MIN(sizeof(f), raw_avail); \ ! 236: memcpy(f, raw, raw_used); \ ! 237: raw += raw_used; \ ! 238: raw_avail -= raw_used; \ ! 239: } while (/* CONSTCOND */ 0) ! 240: ! 241: /* use all of the reserved regions: */ ! 242: RAW_PUT(fmtB.tme_m68k_fmtB_state0); ! 243: RAW_PUT(fmtB.tme_m68k_fmtB_state1); ! 244: RAW_PUT(fmtB.tme_m68k_fmtB_state2); ! 245: RAW_PUT(fmtB.tme_m68k_fmtB_state3); ! 246: RAW_PUT(fmtB.tme_m68k_fmtB_state4); ! 247: RAW_PUT(fmtB.tme_m68k_fmtB_state5); ! 248: #undef RAW_PUT ! 249: ! 250: /* put in the special status word and the data output buffer: */ ! 251: ssw = 0; ! 252: flags = ic->_tme_m68k_group0_flags; ! 253: ! 254: /* if this was an instruction fetch: */ ! 255: if (flags & TME_M68K_BUS_CYCLE_FETCH) { ! 256: ! 257: /* we always ask for a rerun of at least the stage C word, so we ! 258: associate the fault address with the stage C word. the ! 259: address of the stage C word is the address of the stage B ! 260: word minus sizeof(stage C word): */ ! 261: ssw |= TME_M68K_SSWB_RC; ! 262: fmtB.tme_m68k_fmtB_addr_B = tme_htobe_u32(ic->_tme_m68k_group0_address + sizeof(fmtB.tme_m68k_fmtB_ipipe_C)); ! 263: ! 264: /* if this is an address fault: */ ! 265: if (exceptions & TME_M68K_EXCEPTION_AERR) { ! 266: ! 267: /* nothing to do */ ! 268: } ! 269: ! 270: /* otherwise, this is a bus fault: */ ! 271: else { ! 272: ! 273: /* mark stage C as faulted: */ ! 274: ssw |= TME_M68K_SSWB_FC; ! 275: ! 276: /* if this is a 32-bit fetch: */ ! 277: if (ic->_tme_m68k_group0_buffer_read_size == sizeof(tme_uint32_t)) { ! 278: ! 279: /* a 32-bit fetch additionally faults "prefetching" the stage B word: */ ! 280: ssw |= (TME_M68K_SSWB_FB | TME_M68K_SSWB_RB); ! 281: } ! 282: } ! 283: } ! 284: ! 285: /* otherwise, this was not an instruction fetch: */ ! 286: else { ! 287: ! 288: /* this is a data fault: */ ! 289: ssw |= TME_M68K_SSWB_DF; ! 290: ! 291: /* put in the function code and address: */ ! 292: ssw |= ic->_tme_m68k_group0_function_code; ! 293: fmtB.tme_m68k_fmtB_addr = tme_htobe_u32(ic->_tme_m68k_group0_address); ! 294: ! 295: /* if this was part of a read/modify/write cycle: */ ! 296: if (flags & TME_M68K_BUS_CYCLE_RMW) { ! 297: ssw |= TME_M68K_SSWB_RM; ! 298: } ! 299: ! 300: /* if this was a read: */ ! 301: if (flags & TME_M68K_BUS_CYCLE_READ) { ! 302: ssw |= TME_M68K_SSWB_RW; ! 303: ! 304: /* put in the size indication: */ ! 305: switch (ic->_tme_m68k_group0_buffer_read_size) { ! 306: default: assert(FALSE); ! 307: case 1: ssw |= TME_M68K_SSWB_SIZE_1; break; ! 308: case 2: ssw |= TME_M68K_SSWB_SIZE_2; break; ! 309: case 3: ssw |= TME_M68K_SSWB_SIZE_3; break; ! 310: case 4: ssw |= TME_M68K_SSWB_SIZE_4; break; ! 311: } ! 312: ! 313: } ! 314: ! 315: /* otherwise, this is a write: */ ! 316: else { ! 317: ! 318: /* put in the size indication: */ ! 319: switch (ic->_tme_m68k_group0_buffer_write_size) { ! 320: default: assert(FALSE); ! 321: case 1: ssw |= TME_M68K_SSWB_SIZE_1; break; ! 322: case 2: ssw |= TME_M68K_SSWB_SIZE_2; break; ! 323: case 3: ssw |= TME_M68K_SSWB_SIZE_3; break; ! 324: case 4: ssw |= TME_M68K_SSWB_SIZE_4; break; ! 325: } ! 326: ! 327: /* put in the data output buffer: */ ! 328: memcpy(fmtB.tme_m68k_fmtB_dob ! 329: + sizeof(fmtB.tme_m68k_fmtB_dob) ! 330: - ic->_tme_m68k_group0_buffer_write_size, ! 331: ic->_tme_m68k_group0_buffer_write, ! 332: ic->_tme_m68k_group0_buffer_write_size); ! 333: } ! 334: } ! 335: ! 336: /* put in the SSW: */ ! 337: fmtB.tme_m68k_fmtB_ssw = tme_htobe_u16(ssw); ! 338: ! 339: /* push the format 0xB contents. we don't need to worry about ! 340: restarting here, because any fault is a double fault: */ ! 341: ic->tme_m68k_ireg_a7 -= sizeof(fmtB); ! 342: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_a7; ! 343: ic->_tme_m68k_ea_function_code = TME_M68K_FC_SD; /* XXX right? */ ! 344: tme_m68k_write_mem(ic, (tme_uint8_t *) &fmtB, sizeof(fmtB)); ! 345: ! 346: /* now finish the processing for this exception: */ ! 347: tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_B, ! 348: ((exceptions & TME_M68K_EXCEPTION_BERR) ! 349: ? TME_M68K_VECTOR_BERR ! 350: : TME_M68K_VECTOR_AERR)); ! 351: ic->_tme_m68k_exceptions = (exceptions &= ~ (TME_M68K_EXCEPTION_AERR ! 352: | TME_M68K_EXCEPTION_BERR)); ! 353: } ! 354: ! 355: /* do normal exception processing: */ ! 356: tme_m68020_exception_process(ic); ! 357: /* NOTREACHED */ ! 358: } ! 359: ! 360: /* m68020 RTE processing: */ ! 361: static void ! 362: _tme_m68020_rte(struct tme_m68k *ic) ! 363: { ! 364: tme_uint16_t format; ! 365: struct tme_m68k_fmtB fmtB; ! 366: tme_uint32_t fmtB_address; ! 367: /* one 16-bit word for each 16-bit internal register word in the format 0xB frame: */ ! 368: tme_uint8_t raw_state[(1 + 2 + 4 + 2 + 3 + 18) * sizeof(tme_uint16_t)], *raw; ! 369: unsigned int raw_avail, raw_used; ! 370: tme_uint8_t function_code; ! 371: tme_uint16_t ssw; ! 372: unsigned int flags; ! 373: const tme_uint8_t *ib; ! 374: unsigned int buffer_size; ! 375: ! 376: /* start the RTE: */ ! 377: format = tme_m68k_rte_start(ic); ! 378: ! 379: /* if this is a format 0 or format two stack frame, finish it now: */ ! 380: if (format == TME_M68K_FORMAT_0 ! 381: || format == TME_M68K_FORMAT_2) { ! 382: ic->_tme_m68k_mode = TME_M68K_MODE_EXECUTION; ! 383: TME_M68K_SEQUENCE_START; ! 384: tme_m68k_rte_finish(ic, (format == TME_M68K_FORMAT_2 ! 385: ? sizeof(ic->tme_m68k_ireg_pc_last) ! 386: : 0)); ! 387: /* NOTREACHED */ ! 388: } ! 389: ! 390: /* if this is a format one stack frame: */ ! 391: if (format == TME_M68K_FORMAT_1) { ! 392: ! 393: /* "For the throwaway four-word frame, the processor reads the SR ! 394: value from the frame, increments the active stack pointer by 8, ! 395: updates the SR with the value read from the stack, and then ! 396: begins RTE processing again" */ ! 397: ic->tme_m68k_ireg_a7 += 8; ! 398: tme_m68k_change_sr(ic, ic->tme_m68k_ireg_shadow_sr); ! 399: TME_M68K_SEQUENCE_START; ! 400: tme_m68k_redispatch(ic); ! 401: /* NOTREACHED */ ! 402: } ! 403: ! 404: /* whenever we detect a format error, begin exception processing ! 405: for a format error. we have to back the PC up by the size of the ! 406: RTE instruction so the PC points to it: */ ! 407: #define FORMAT_ERROR_IF(e) \ ! 408: do { \ ! 409: if (e) { \ ! 410: ic->tme_m68k_ireg_pc -= sizeof(tme_uint16_t); \ ! 411: tme_m68k_exception(ic, TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_FORMAT));\ ! 412: /* NOTREACHED */ \ ! 413: } \ ! 414: } while (/* CONSTCOND */ 0) ! 415: ! 416: /* this frame must be a format 0xB frame: */ ! 417: FORMAT_ERROR_IF(format != TME_M68K_FORMAT_B); ! 418: ! 419: /* do a read of the last word in the stack frame to determine ! 420: accessibility. we rely on tme_m68k_rte_start leaving ! 421: ic->_tme_m68k_ea_address pointing after the format/offset word: */ ! 422: fmtB_address = ic->_tme_m68k_ea_address; ! 423: ic->_tme_m68k_ea_address += sizeof(fmtB) - sizeof(tme_uint32_t); ! 424: tme_m68k_read_memx32(ic); ! 425: ! 426: /* read in the format 0xB information. if we get a bus error ! 427: during this operation it's a double fault: */ ! 428: assert(ic->_tme_m68k_exceptions == 0); ! 429: ic->_tme_m68k_exceptions = TME_M68K_EXCEPTION_BERR; ! 430: ic->_tme_m68k_ea_address = fmtB_address; ! 431: tme_m68k_read_mem(ic, (tme_uint8_t *) &fmtB, sizeof(fmtB)); ! 432: ic->_tme_m68k_exceptions = 0; ! 433: ! 434: /* reset the input and output buffers: */ ! 435: ic->_tme_m68k_group0_buffer_read_size = 0; ! 436: ic->_tme_m68k_group0_buffer_read_softrr = 0; ! 437: ic->_tme_m68k_group0_buffer_write_size = 0; ! 438: ic->_tme_m68k_group0_buffer_write_softrr = 0; ! 439: ! 440: /* get out the SSW: */ ! 441: ssw = tme_betoh_u16(fmtB.tme_m68k_fmtB_ssw); ! 442: ! 443: /* initialize the flags: */ ! 444: flags = 0; ! 445: ! 446: /* initialize the buffer size: */ ! 447: buffer_size = 0; ! 448: ! 449: /* initialize the input buffer: */ ! 450: ib = NULL; ! 451: ! 452: /* if this was an instruction fetch: */ ! 453: if (ssw & (TME_M68K_SSWB_FC | TME_M68K_SSWB_FB)) { ! 454: ! 455: /* we don't generate bus errors that only fault on stage B: */ ! 456: if ((ssw & (TME_M68K_SSWB_FC | TME_M68K_SSWB_FB)) == TME_M68K_SSWB_FB) { ! 457: abort(); ! 458: } ! 459: ! 460: /* if we faulted on both stages, we must be rerunning both or not ! 461: rerunning both. since we already know we either faulted only on ! 462: stage C, or we faulted on both, if we faulted on stage B check ! 463: that both RB and RC have the same value: */ ! 464: if ((ssw & TME_M68K_SSWB_FB) ! 465: && !(ssw & TME_M68K_SSWB_RC) != !(ssw & TME_M68K_SSWB_RB)) { ! 466: abort(); ! 467: } ! 468: ! 469: /* note that this was an instruction fetch: */ ! 470: flags |= TME_M68K_BUS_CYCLE_FETCH; ! 471: ! 472: /* get out the function code: */ ! 473: ic->_tme_m68k_group0_function_code ! 474: = ((ic->tme_m68k_ireg_shadow_sr & TME_M68K_FLAG_S) ! 475: ? TME_M68K_FC_SP ! 476: : TME_M68K_FC_UP); ! 477: ! 478: /* get out the fault address: */ ! 479: ic->_tme_m68k_group0_address = tme_betoh_u32(fmtB.tme_m68k_fmtB_addr_B) - sizeof(fmtB.tme_m68k_fmtB_ipipe_C); ! 480: ! 481: /* if the user reran this cycle: */ ! 482: if (!(ssw & TME_M68K_SSWB_RC)) { ! 483: ! 484: /* set the input buffer pointer: */ ! 485: /* NB that for 32-bit fetches, this relies on the fact that the ! 486: stage B word comes immediately after the stage C word in the ! 487: frame: */ ! 488: ib = (const tme_uint8_t *) &fmtB.tme_m68k_fmtB_ipipe_C; ! 489: } ! 490: ! 491: /* if this is a fault only on stage C: */ ! 492: if (!(ssw & TME_M68K_SSWB_FB)) { ! 493: ! 494: /* set the input buffer size: */ ! 495: buffer_size = sizeof(tme_uint16_t); ! 496: } ! 497: ! 498: /* otherwise, if this is a fault on stages C and B: */ ! 499: else { ! 500: ! 501: /* set the input buffer size: */ ! 502: buffer_size = sizeof(tme_uint32_t); ! 503: } ! 504: } ! 505: ! 506: /* otherwise, this was a data access: */ ! 507: else { ! 508: ! 509: /* get out the function code: */ ! 510: ic->_tme_m68k_group0_function_code = ssw & TME_M68K_FC_7; ! 511: ! 512: /* get out the fault address: */ ! 513: ic->_tme_m68k_group0_address = tme_betoh_u32(fmtB.tme_m68k_fmtB_addr); ! 514: ! 515: /* get out the size: */ ! 516: switch (ssw & TME_M68K_SSWB_SIZE_MASK) { ! 517: case TME_M68K_SSWB_SIZE_1: buffer_size = 1; break; ! 518: case TME_M68K_SSWB_SIZE_2: buffer_size = 2; break; ! 519: case TME_M68K_SSWB_SIZE_3: buffer_size = 3; break; ! 520: case TME_M68K_SSWB_SIZE_4: buffer_size = 4; break; ! 521: } ! 522: ! 523: /* if this was a read cycle: */ ! 524: if (ssw & TME_M68K_SSWB_RW) { ! 525: ! 526: /* mark that this was a read cycle: */ ! 527: flags |= TME_M68K_BUS_CYCLE_READ; ! 528: ! 529: /* if the user reran this cycle: */ ! 530: if (!(ssw & TME_M68K_SSWB_DF)) { ! 531: ! 532: /* set the input buffer pointer: */ ! 533: ib = &fmtB.tme_m68k_fmtB_dib[0]; ! 534: } ! 535: } ! 536: ! 537: /* otherwise, this was a write cycle: */ ! 538: else { ! 539: ! 540: /* if the user reran this cycle, note that, otherwise ! 541: copy in the data output buffer: */ ! 542: if (!(ssw & TME_M68K_SSWB_DF)) { ! 543: ic->_tme_m68k_group0_buffer_write_softrr = buffer_size; ! 544: } ! 545: else { ! 546: memcpy(ic->_tme_m68k_group0_buffer_write, ! 547: fmtB.tme_m68k_fmtB_dob + sizeof(fmtB.tme_m68k_fmtB_dob) - buffer_size, ! 548: buffer_size); ! 549: ic->_tme_m68k_group0_buffer_write_size = buffer_size; ! 550: } ! 551: } ! 552: } ! 553: ! 554: /* if the user reran this instruction fetch or data read cycle, read ! 555: in the appropriate input buffer: */ ! 556: if (ib != NULL) { ! 557: memcpy(ic->_tme_m68k_group0_buffer_read, ! 558: ib + sizeof(fmtB.tme_m68k_fmtB_dib) - buffer_size, ! 559: buffer_size); ! 560: ic->_tme_m68k_group0_buffer_read_softrr = buffer_size; ! 561: ic->_tme_m68k_group0_buffer_read_size = buffer_size; ! 562: } ! 563: ! 564: /* get out our internal state: */ ! 565: raw = raw_state; ! 566: raw_avail = sizeof(raw_state); ! 567: #define RAW_GET(f) \ ! 568: do { \ ! 569: raw_used = TME_MIN(sizeof(f), raw_avail); \ ! 570: memcpy(raw, f, raw_used); \ ! 571: raw += raw_used; \ ! 572: raw_avail -= raw_used; \ ! 573: } while (/* CONSTCOND */ 0) ! 574: ! 575: /* use all of the reserved regions: */ ! 576: RAW_GET(fmtB.tme_m68k_fmtB_state0); ! 577: RAW_GET(fmtB.tme_m68k_fmtB_state1); ! 578: RAW_GET(fmtB.tme_m68k_fmtB_state2); ! 579: RAW_GET(fmtB.tme_m68k_fmtB_state3); ! 580: RAW_GET(fmtB.tme_m68k_fmtB_state4); ! 581: RAW_GET(fmtB.tme_m68k_fmtB_state5); ! 582: #undef RAW_GET ! 583: ! 584: /* take apart the internal state: */ ! 585: raw = raw_state; ! 586: raw_avail = sizeof(raw_state) - raw_avail; ! 587: #define RAW_GET(v) \ ! 588: do { \ ! 589: FORMAT_ERROR_IF(raw_avail < sizeof(v)); \ ! 590: memcpy(&v, raw, sizeof(v)); \ ! 591: raw += sizeof(v); \ ! 592: raw_avail -= sizeof(v); \ ! 593: } while (/* CONSTCOND */ 0) ! 594: ! 595: /* get out the sequence: */ ! 596: raw_used = tme_m68k_sequence_fill(ic, raw, raw_avail); ! 597: FORMAT_ERROR_IF(raw_used < 0); ! 598: raw += raw_used; ! 599: raw_avail -= raw_used; ! 600: ! 601: /* dispatch on the mode: */ ! 602: switch (ic->_tme_m68k_group0_sequence._tme_m68k_sequence_mode) { ! 603: ! 604: case TME_M68K_MODE_EXECUTION: ! 605: ! 606: /* get out the instruction buffer: */ ! 607: raw_used = tme_m68k_insn_buffer_fill(ic, raw, raw_avail); ! 608: FORMAT_ERROR_IF(raw_used < 0); ! 609: raw += raw_used; ! 610: raw_avail -= raw_used; ! 611: ! 612: /* get out the EA address: */ ! 613: RAW_GET(function_code); ! 614: ic->_tme_m68k_ea_function_code = function_code; ! 615: RAW_GET(ic->_tme_m68k_ea_address); ! 616: ! 617: /* get out the memory X, Y, and Z buffers: */ ! 618: RAW_GET(ic->tme_m68k_ireg_memx32); ! 619: RAW_GET(ic->tme_m68k_ireg_memy32); ! 620: RAW_GET(ic->tme_m68k_ireg_memz32); ! 621: ! 622: /* done: */ ! 623: break; ! 624: ! 625: case TME_M68K_MODE_EXCEPTION: ! 626: ! 627: /* get out the exceptions set: */ ! 628: RAW_GET(ic->_tme_m68k_exceptions); ! 629: ! 630: /* get out the shadow status register: */ ! 631: RAW_GET(ic->tme_m68k_ireg_shadow_sr); ! 632: ! 633: /* get out the last PC: */ ! 634: RAW_GET(ic->tme_m68k_ireg_pc_last); ! 635: ! 636: /* done: */ ! 637: break; ! 638: ! 639: case TME_M68K_MODE_RTE: ! 640: ! 641: /* get out the shadow status register: */ ! 642: RAW_GET(ic->tme_m68k_ireg_shadow_sr); ! 643: ! 644: /* get out the next program counter: */ ! 645: RAW_GET(ic->tme_m68k_ireg_pc_next); ! 646: ! 647: /* get out the format/offset word: */ ! 648: RAW_GET(ic->tme_m68k_ireg_format_offset); ! 649: ! 650: break; ! 651: ! 652: default: FORMAT_ERROR_IF(TRUE); ! 653: } ! 654: ! 655: /* finish the RTE: */ ! 656: ic->_tme_m68k_sequence = ic->_tme_m68k_group0_sequence; ! 657: TME_M68K_SEQUENCE_RESTART; ! 658: tme_m68k_rte_finish(ic, sizeof(fmtB)); ! 659: /* NOTREACHED */ ! 660: } ! 661: ! 662: /* this creates and returns a new m68020: */ ! 663: TME_ELEMENT_X_NEW_DECL(tme_ic_,m68k,m68020) { ! 664: struct tme_m68k *ic; ! 665: ! 666: /* allocate the m68k structure: */ ! 667: ic = tme_new0(struct tme_m68k, 1); ! 668: ic->tme_m68k_element = element; ! 669: ! 670: /* fill in the m68020-specific parts of the structure: */ ! 671: ic->tme_m68k_type = TME_M68K_M68020; ! 672: ic->_tme_m68k_mode_execute = _tme_m68020_execute; ! 673: ic->_tme_m68k_mode_exception = _tme_m68020_exception; ! 674: ic->_tme_m68k_mode_rte = _tme_m68020_rte; ! 675: tme_m68k_opcodes_init_m68020(tme_m68k_opcodes_m68020); ! 676: ! 677: /* call the common m68k new function: */ ! 678: return (tme_m68k_new(ic, args, extra, _output)); ! 679: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.