Annotation of tme/ic/m68k/m68020.c, revision 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.