Annotation of tme/ic/m68k/m68020.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

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