Annotation of tme/ic/m68k/m68k-execute.c, revision 1.1.1.3

1.1.1.3 ! root        1: /* $Id: m68k-execute.c,v 1.20 2005/04/30 15:18:33 fredette Exp $ */
1.1       root        2: 
1.1.1.2   root        3: /* ic/m68k/m68k-execute.c - executes Motorola 68k instructions: */
1.1       root        4: 
1.1.1.2   root        5: /*
                      6:  * Copyright (c) 2002, 2003 Matt Fredette
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *      This product includes software developed by Matt Fredette.
                     20:  * 4. The name of the author may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     25:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     26:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     27:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     28:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     29:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     31:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     32:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     33:  * POSSIBILITY OF SUCH DAMAGE.
                     34:  */
                     35: 
1.1.1.3 ! root       36: _TME_RCSID("$Id: m68k-execute.c,v 1.20 2005/04/30 15:18:33 fredette Exp $");
1.1       root       37: 
                     38: /* includes: */
                     39: #include "m68k-auto.h"
                     40: 
                     41: /* the m68k instruction executor: */
                     42: static void
                     43: _TME_M68K_EXECUTE_NAME(struct tme_m68k *ic)
                     44: {
                     45: #undef _TME_M68K_SEQUENCE_RESTARTING
                     46: #undef _TME_M68K_INSN_FETCH_SAVE
                     47: #ifdef _TME_M68K_EXECUTE_FAST
                     48:   struct tme_m68k_tlb *tlb;
1.1.1.3 ! root       49:   const tme_uint8_t *emulator_load, *emulator_load_last;
        !            50:   const tme_uint8_t *emulator_load_start;
        !            51:   tme_uint16_t insn_fetch_sizes;
1.1       root       52: #define _TME_M68K_INSN_FETCH_SAVE \
                     53: do { \
                     54:   ic->_tme_m68k_insn_buffer_fetch_total = emulator_load - emulator_load_start; \
                     55:   ic->_tme_m68k_insn_buffer_fetch_sizes = insn_fetch_sizes; \
                     56: } while (/* CONSTCOND */ 0)
                     57: #define _TME_M68K_SEQUENCE_RESTARTING  (FALSE)
                     58: #else  /* !_TME_M68K_EXECUTE_FAST */
                     59:   unsigned int exceptions;
                     60:   tme_uint32_t linear_pc;
                     61: #define _TME_M68K_INSN_FETCH_SAVE \
                     62: do { \
                     63: } while (/* CONSTCOND */ 0)
                     64: #define _TME_M68K_SEQUENCE_RESTARTING  TME_M68K_SEQUENCE_RESTARTING
                     65: #endif /* !_TME_M68K_EXECUTE_FAST */
                     66: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030)
                     67:   unsigned int eai_function_code;
                     68:   int ea_post_index;
                     69:   unsigned int ea_i_is;
1.1.1.3 ! root       70:   tme_uint32_t ea_od;
        !            71:   unsigned int src_specifier;
1.1       root       72: #else  /* !TME_M68K_M68020 && !TME_M68K_M68030 */
                     73: #define eai_function_code ea_function_code
                     74: #endif  /* !TME_M68K_M68020 && !TME_M68K_M68030 */
                     75:   unsigned int function_code_program;
                     76:   unsigned int function_code_data;
                     77:   tme_uint16_t opw, extword;
                     78:   void (*func) _TME_P((struct tme_m68k *, void *, void *));
1.1.1.3 ! root       79:   tme_uint32_t params;
1.1       root       80:   unsigned int first_ea_extword_offset;
1.1.1.3 ! root       81:   int ea_size;
1.1       root       82:   int ea_reg, ea_pre_index;
                     83:   unsigned int ea_index_long, ea_index_scale;
                     84:   tme_uint32_t ea_address;
                     85:   unsigned int ea_function_code;
1.1.1.3 ! root       86:   tme_int32_t ea_bd;
1.1       root       87:   tme_uint32_t imm32;
                     88:   tme_uint16_t transfer_next_before;
                     89:   int rc;
                     90: 
1.1.1.3 ! root       91:   /* silence gcc -Wuninitialized: */
        !            92:   ea_size = 0;
        !            93: 
1.1       root       94:   /* get the function codes.  if the privilege ever changes as a
                     95:      result of any instruction, we must redispatch: */
                     96:   if (TME_M68K_PRIV(ic)) {
                     97:     function_code_program = TME_M68K_FC_SP;
                     98:     function_code_data = TME_M68K_FC_SD;
                     99:   }
                    100:   else {
                    101:     function_code_program = TME_M68K_FC_UP;
                    102:     function_code_data = TME_M68K_FC_UD;
                    103:   }
                    104: 
1.1.1.2   root      105:   /* if we have used up our burst: */
                    106:   if (ic->_tme_m68k_instruction_burst_remaining == 0) {
                    107: 
                    108:     /* start a new burst: */
                    109:     ic->_tme_m68k_instruction_burst_remaining
                    110:       = ic->_tme_m68k_instruction_burst;
                    111: 
                    112:     /* if this is a cooperative threading system, yield: */
                    113: #ifdef TME_THREADS_COOPERATIVE
                    114:     tme_thread_yield();
                    115: #endif /* TME_THREADS_COOPERATIVE */
                    116:   }
                    117: 
1.1       root      118: #ifdef _TME_M68K_EXECUTE_FAST
                    119: 
                    120:   /* get our instruction TLB entry and reload it: */
                    121:   tlb = TME_ATOMIC_READ(struct tme_m68k_tlb *, ic->_tme_m68k_itlb);
                    122:   if (!TME_M68K_TLB_OK_FAST_READ(tlb, function_code_program, ic->tme_m68k_ireg_pc, ic->tme_m68k_ireg_pc)) {
                    123:     tme_m68k_tlb_fill(ic, tlb,
                    124:                      function_code_program,
                    125:                      ic->tme_m68k_ireg_pc,
                    126:                      TME_BUS_CYCLE_READ);
                    127:   }
                    128: 
                    129:   /* if we have to go slow, run the slow executor: */
                    130:   if (TME_M68K_SEQUENCE_RESTARTING
                    131:       || tme_m68k_go_slow(ic)) {
                    132:     return (_TME_M68K_EXECUTE_SLOW(ic));
                    133:   }
                    134: 
                    135:   /* set up to do fast reads from the instruction TLB entry: */
                    136:   emulator_load_last = tlb->tme_m68k_tlb_emulator_off_read + TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_m68k_tlb_linear_last);
                    137:   ic->_tme_m68k_group0_hook = tme_m68k_group0_hook_fast;
                    138: #else  /* !_TME_M68K_EXECUTE_FAST */
                    139: 
                    140:   /* set up to do slow reads from the instruction TLB entry: */
                    141:   ic->_tme_m68k_group0_hook = NULL;
                    142: #endif /* !_TME_M68K_EXECUTE_FAST */
                    143: 
                    144:   /* the execution loop: */
                    145:   for (;;) {
                    146: 
                    147:     /* reset for this instruction: */
                    148: #ifdef _TME_M68K_EXECUTE_FAST
                    149:     if (__tme_predict_false(TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_m68k_tlb_linear_last) == 0)) {
                    150:       tme_m68k_redispatch(ic);
                    151:     }
                    152:     emulator_load_start = emulator_load = tlb->tme_m68k_tlb_emulator_off_read + ic->tme_m68k_ireg_pc;
1.1.1.3 ! root      153:     insn_fetch_sizes = 0;
1.1       root      154:     assert(TME_M68K_TLB_OK_FAST_READ(tlb, function_code_program, ic->tme_m68k_ireg_pc, ic->tme_m68k_ireg_pc)
                    155:           || (emulator_load - 1) == emulator_load_last);
                    156:     tme_m68k_verify_begin(ic, emulator_load_start);
                    157: #else  /* !_TME_M68K_EXECUTE_FAST */
                    158:     linear_pc = ic->tme_m68k_ireg_pc;
                    159:     ic->_tme_m68k_insn_buffer_off = 0;
1.1.1.3 ! root      160:     ic->_tme_m68k_insn_buffer_fetch_total = 0;
        !           161:     ic->_tme_m68k_insn_buffer_fetch_sizes = 0;
1.1       root      162:     exceptions = 0;
1.1.1.3 ! root      163:     if (__tme_predict_false((ic->tme_m68k_ireg_sr & ic->_tme_m68k_sr_mask_t) == TME_M68K_FLAG_T1)) {
        !           164:       ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;
        !           165:       exceptions |= TME_M68K_EXCEPTION_TRACE;
1.1       root      166:     }
                    167:     tme_m68k_verify_begin(ic, NULL);
                    168: #endif /* _TME_M68K_EXECUTE_FAST */
                    169: #ifdef _TME_M68K_VERIFY
                    170:     if (ic->tme_m68k_ireg_pc == 0x6000) {
                    171:       tme_m68k_verify_hook();
                    172:     }
                    173: #endif
1.1.1.3 ! root      174: #ifdef _TME_M68K_STATS
        !           175:     ic->tme_m68k_stats.tme_m68k_stats_insns_total++;
        !           176: #ifndef _TME_M68K_EXECUTE_FAST
        !           177:     ic->tme_m68k_stats.tme_m68k_stats_insns_slow++;
        !           178: #endif /* !_TME_M68K_EXECUTE_FAST */
        !           179: #endif /* _TME_M68K_STATS */
1.1       root      180:     first_ea_extword_offset = sizeof(opw);
1.1.1.2   root      181:     ic->_tme_m68k_instruction_burst_remaining--;
1.1       root      182:     
                    183:     /* fetch and decode the first word of this instruction: */
                    184:     _TME_M68K_EXECUTE_FETCH_U16(opw);
                    185:     ic->_tme_m68k_insn_opcode = opw;
1.1.1.3 ! root      186:     params = _TME_M68K_EXECUTE_OPMAP[opw];
        !           187:     func = tme_m68k_opcode_insns[TME_M68K_OPCODE_INSN_WHICH(params)];
        !           188: 
        !           189:     /* now that we no longer need the insn index part of the params,
        !           190:        replace it with the least significant bits of the opcode, which
        !           191:        contain any EA mode and reg fields: */
        !           192:     TME_FIELD_MASK_DEPOSITU(params, 
        !           193:                            TME_M68K_OPCODE_INSN_MASK, 
        !           194:                            (opw & (TME_M68K_OPCODE_INSN_MASK / TME_M68K_OPCODE_INSN(1))));
1.1       root      195:     
1.1.1.3 ! root      196:     /* if this is a special opcode: */
        !           197:     if (__tme_predict_false((params & TME_M68K_OPCODE_SPECOP) != 0)) {
        !           198: 
1.1       root      199: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030)
1.1.1.3 ! root      200: 
        !           201:       /* a general floating-point instruction: */
        !           202:       if (__tme_predict_false((opw & 0xffc0) == 0xf200)) {
        !           203: 
        !           204:        /* if there is no FPU present, or if it isn't enabled: */
        !           205:        if (__tme_predict_false(!ic->tme_m68k_fpu_enabled)) {
        !           206: 
        !           207:          /* mark this instruction as illegal and use an FPgen command
        !           208:             word of zero: */
        !           209:          func = tme_m68k_illegal;
        !           210:          extword = 0;
1.1       root      211:        }
1.1.1.3 ! root      212: 
        !           213:        /* otherwise, there is an FPU present and it is enabled: */
        !           214:        else {
        !           215: 
        !           216:          /* fetch the FPgen command word: */
        !           217:          _TME_M68K_EXECUTE_FETCH_U16(ic->_tme_m68k_insn_specop);
        !           218:          first_ea_extword_offset = 4;
        !           219: 
        !           220:          /* temporarily store the FPgen command word in extword: */
        !           221:          extword = ic->_tme_m68k_insn_specop;
        !           222:        }
        !           223: 
        !           224:        /* the goal here is not to decide whether or not an FPgen
        !           225:           instruction is legal, although some illegal instructions
        !           226:           are caught.  the goal is to only decide if this FPgen
        !           227:           instruction uses the EA field.
        !           228: 
        !           229:           we need to know this here because only the executer can
        !           230:           calculate all memory EAs (i.e., absolute addresses,
        !           231:           indirect addresses, PC-relative addresses, etc.) and fetch
        !           232:           immediates.
        !           233: 
        !           234:           in general, all other decisions about whether or not an
        !           235:           instruction is legal (including whether or not certain EAs
        !           236:           are legal, like data register direct or address register
        !           237:           direct) or how to dispatch it is done somewhere else.
        !           238: 
        !           239:           all legal FPgen instructions that use the EA field are
        !           240:           handled by one of the following ifs.  all illegal FPgen
        !           241:           instructions, and all FPgen instructions that do not use
        !           242:           the EA field are handled by the final unconditional else
        !           243:           clause that cancels memory EA calculation and immediate
        !           244:           fetching.
        !           245: 
        !           246:           for those FPgen instructions that do use the EA field, they
        !           247:           either leave the EA cycles unchanged, as TME_M68K_OPCODE_EA_READ, to
        !           248:           indicate that they read the EA, or they change it to
        !           249:           TME_M68K_OPCODE_EA_WRITE to indicate that they write the EA.
        !           250:           additionally, they either flag any immediate operand as
        !           251:           illegal, fetch it themselves, or specify its size for the
        !           252:           normal immediate fetching code to use: */
        !           253: 
        !           254:        /* m68k-iset.txt must assume that any EA is not written: */
        !           255:        assert (!TME_M68K_OPCODE_HAS_EA(params)
        !           256:                || ((params
        !           257:                     & (TME_M68K_OPCODE_EA_READ
        !           258:                        | TME_M68K_OPCODE_EA_WRITE))
        !           259:                    == TME_M68K_OPCODE_EA_READ));
        !           260: 
        !           261:        /* m68k-iset.txt must assume that any immediate is 32 bits: */
        !           262:        assert (!TME_M68K_OPCODE_HAS_IMM(params)
        !           263:                || (params & (TME_M68K_OPCODE_IMM_16 | TME_M68K_OPCODE_IMM_32)) == TME_M68K_OPCODE_IMM_32);
        !           264: 
        !           265:        /* if this is an FMOVE or FMOVEM of floating-point control
        !           266:           registers (command word pattern 10dr rr00 0000 0000): */
        !           267:        if ((extword & 0xc3ff) == 0x8000) {
        !           268: 
        !           269:          /* override the function: */
        !           270:          func = tme_m68k_fmovemctl;
        !           271: 
        !           272:          /* if this is a register-to-memory operation: */
        !           273:          if (extword & TME_BIT(13)) {
        !           274: 
        !           275:            /* any EA must be writable: */
        !           276:            params |= TME_M68K_OPCODE_EA_WRITE;
        !           277:          }
        !           278: 
        !           279:          /* otherwise, this is a memory-to-register operation: */
        !           280:          else {
        !           281: 
        !           282:            /* if this instruction has an immediate, and this
        !           283:               instruction is moving multiple control registers, this
        !           284:               is an illegal instruction: */
        !           285:            /* NB the trick we use to see if multiple bits are set in
        !           286:               the rrr field - we subtract one from the base of the
        !           287:               rrr field (0x0400), binary-AND the result with extword,
        !           288:               and mask off all bits except the rrr field.  this
        !           289:               result will be nonzero iff the rrr field has multiple
        !           290:               bits set: */
        !           291:            if (__tme_predict_false(TME_M68K_OPCODE_HAS_IMM(params)
        !           292:                                    && ((extword & (extword - 0x0400)) & 0x1c00))) {
        !           293:              func = tme_m68k_illegal;
        !           294:            }
        !           295:          }
1.1       root      296:        }
1.1.1.3 ! root      297: 
        !           298:        /* if this is an FMOVEM
        !           299:           (command word pattern 11dm m000 rrrr rrrr): */
        !           300:        else if ((extword & 0xc700) == 0xc000) {
        !           301: 
        !           302:          /* override the function: */
        !           303:          func = tme_m68k_fmovem;
        !           304: 
        !           305:          /* if this instruction has an immediate, this is an
        !           306:             illegal instruction: */
        !           307:          if (__tme_predict_false(TME_M68K_OPCODE_HAS_IMM(params))) {
        !           308:            func = tme_m68k_illegal;
        !           309:          }
        !           310: 
        !           311:          /* if this is a register-to-memory operation: */
        !           312:          if (extword & TME_BIT(13)) {
        !           313: 
        !           314:            /* any EA must be writable: */
        !           315:            params |= TME_M68K_OPCODE_EA_WRITE;
        !           316:          }
1.1       root      317:        }
1.1.1.3 ! root      318: 
        !           319:        /* if this is a register-to-memory FMOVE instruction
        !           320:           (command word pattern 011d ddss skkk kkkk): */
        !           321:        else if ((extword & 0xe000) == 0x6000) {
        !           322: 
        !           323:          /* override the function: */
        !           324:          func = tme_m68k_fmove_rm;
        !           325: 
        !           326:          /* any EA must be writable: */
        !           327:          params |= TME_M68K_OPCODE_EA_WRITE;
        !           328:        }
        !           329: 
        !           330:        /* if this is a memory-to-register true FPgen instruction
        !           331:           (command word pattern 010s ssdd dooo oooo): */
        !           332:        else if ((extword & 0xe000) == 0x4000
        !           333:                 && (_tme_m6888x_fpgen_opmode_bitmap[TME_FIELD_EXTRACTU(extword, 0, 7) / 8]
        !           334:                     & (1 << (TME_FIELD_EXTRACTU(extword, 0, 7) % 8)))
        !           335:                 && TME_FIELD_EXTRACTU(extword, 10, 3) != TME_M6888X_TYPE_INVALID) {
        !           336: 
        !           337:          /* if this instruction has an immediate: */
        !           338:          if (TME_M68K_OPCODE_HAS_IMM(params)) {
        !           339: 
        !           340:            /* if the source specifier is for a size that the normal
        !           341:               immediate fetching code can handle, let it handle it,
        !           342:               otherwise we have to fetch the immediate ourselves: */
        !           343: 
        !           344:            /* m68k-iset.txt must have specified the EA operand to be
        !           345:               operand one: */
        !           346:            assert((void *) TME_M68K_OPCODE_OP1_WHICH(ic, params)
        !           347:                   == (void *) &ic->tme_m68k_ireg_uint32(TME_M68K_IREG_IMM32 + 0));
        !           348: 
        !           349:            /* dispatch on the source specifier: */
        !           350:            src_specifier = TME_FIELD_EXTRACTU(extword, 10, 3);
        !           351:            switch (src_specifier) {
        !           352: 
        !           353:              /* we can let the normal immediate fetching code fetch
        !           354:                 word integers, long-word integers, and
        !           355:                 single-precision reals: */
        !           356:            default: 
        !           357:              assert (func == tme_m68k_illegal);
        !           358:              /* FALLTHROUGH */
        !           359:            case TME_M6888X_TYPE_WORD:
        !           360:              /* we can simply flip TME_M68K_OPCODE_IMM_16 and
        !           361:                 TME_M68K_OPCODE_IMM_32 to select a 16-bit immediate;
        !           362:                 we know that only TME_M68K_OPCODE_IMM_32 is set,
        !           363:                 thanks to the assert we did at the beginning of the
        !           364:                 fpgen specop handling: */
        !           365:              params ^= (TME_M68K_OPCODE_IMM_16 | TME_M68K_OPCODE_IMM_32);
        !           366:              /* FALLTHROUGH */
        !           367:            case TME_M6888X_TYPE_LONG:
        !           368:            case TME_M6888X_TYPE_SINGLE:
        !           369:              break;
        !           370:            case TME_M6888X_TYPE_EXTENDED80:
        !           371:            case TME_M6888X_TYPE_PACKEDDEC:
        !           372:            case TME_M6888X_TYPE_DOUBLE:
        !           373:              _TME_M68K_EXECUTE_FETCH_U32(imm32);
        !           374:              ic->tme_m68k_ireg_uint32(TME_M68K_IREG_IMM32 + 0) = imm32;
        !           375:              _TME_M68K_EXECUTE_FETCH_U32(imm32);
        !           376:              ic->tme_m68k_ireg_uint32(TME_M68K_IREG_IMM32 + 1) = imm32;
        !           377:              if (src_specifier != TME_M6888X_TYPE_DOUBLE) {
        !           378:                _TME_M68K_EXECUTE_FETCH_U32(imm32);
        !           379:                ic->tme_m68k_ireg_uint32(TME_M68K_IREG_IMM32 + 2) = imm32;
        !           380:              }
        !           381:              /* we only need to clear TME_M68K_OPCODE_IMM_32 here to
        !           382:                 cancel the later immediate fetching; we know that
        !           383:                 only TME_M68K_OPCODE_IMM_32 is set, thanks to the
        !           384:                 assert we did at the beginning of the fpgen specop
        !           385:                 handling: */
        !           386:              params &= ~TME_M68K_OPCODE_IMM_32;
        !           387:              break;
        !           388:            case TME_M6888X_TYPE_BYTE:        
        !           389:              _TME_M68K_EXECUTE_FETCH_U16(imm32);
        !           390:              ic->tme_m68k_ireg_uint32(TME_M68K_IREG_IMM32 + 0) = TME_EXT_S8_U32((tme_int8_t) imm32);
        !           391:              /* we only need to clear TME_M68K_OPCODE_IMM_32 here to
        !           392:                 cancel the later immediate fetching; we know that
        !           393:                 only TME_M68K_OPCODE_IMM_32 is set, thanks to the
        !           394:                 assert we did at the beginning of the fpgen specop
        !           395:                 handling: */
        !           396:              params &= ~TME_M68K_OPCODE_IMM_32;
        !           397:              break;
        !           398:            }
        !           399:          }
1.1       root      400:        }
1.1.1.3 ! root      401: 
        !           402:        /* otherwise, this FPgen instruction does not need any memory
        !           403:           EA or immediate.  we'll decide later if this instruction is
        !           404:           actually legal: */
1.1       root      405:        else {
1.1.1.3 ! root      406:          /* cancel immediate fetching and all EA work: */
        !           407:          params &= ~(TME_M68K_OPCODE_IMM_32
        !           408:                      | TME_M68K_OPCODE_IMM_16
        !           409:                      | TME_M68K_OPCODE_EA_SIZE_MASK
        !           410:                      | TME_M68K_OPCODE_EA_READ
        !           411:                      | TME_M68K_OPCODE_EA_WRITE);
        !           412:        }
        !           413: 
        !           414:        /* if this instruction has already been marked as illegal, or
        !           415:           this EA must be writable, and this is a PC-relative or
        !           416:           immediate EA, this instruction is illegal: */
        !           417:        if (__tme_predict_false(func == tme_m68k_illegal
        !           418:                                || (params & TME_M68K_OPCODE_EA_WRITE
        !           419:                                    && (TME_M68K_OPCODE_HAS_IMM(params)
        !           420:                                        || (TME_M68K_OPCODE_EA_MODE_WHICH(params) == 7
        !           421:                                            && (TME_M68K_OPCODE_EA_REG_WHICH(params) & 6) == 2))))) {
        !           422:          func = tme_m68k_illegal;
        !           423:          /* cancel immediate fetching and all EA work: */
        !           424:          params &= ~(TME_M68K_OPCODE_IMM_32
        !           425:                      | TME_M68K_OPCODE_IMM_16
        !           426:                      | TME_M68K_OPCODE_EA_SIZE_MASK
        !           427:                      | TME_M68K_OPCODE_EA_READ
        !           428:                      | TME_M68K_OPCODE_EA_WRITE);
        !           429:        }
        !           430: 
        !           431:        /* otherwise, if this instruction has a memory EA: */
        !           432:        else if (params & TME_M68K_OPCODE_EA_READ) {
        !           433: 
        !           434:          /* override any m68k-iset.txt guess about the operand
        !           435:             size, and cancel all memory cycles.  the instruction
        !           436:             itself will do the actual operand reading and any address
        !           437:             register postincrement or predecrement: */
        !           438:          params = 
        !           439:            ((params
        !           440:              & ~(TME_M68K_OPCODE_EA_READ
        !           441:                  | TME_M68K_OPCODE_EA_WRITE
        !           442:                  | TME_M68K_OPCODE_EA_SIZE_MASK))
        !           443:             | TME_M68K_OPCODE_EA_UNSIZED);
1.1       root      444:        }
                    445: 
1.1.1.3 ! root      446:        /* otherwise, this instruction does not have a memory EA: */
        !           447:        else {
1.1       root      448: 
1.1.1.3 ! root      449:          /* cancel all EA work: */
        !           450:          params &= ~(TME_M68K_OPCODE_EA_SIZE_MASK
        !           451:                      | TME_M68K_OPCODE_EA_READ
        !           452:                      | TME_M68K_OPCODE_EA_WRITE);
        !           453:        }
        !           454:       }
        !           455:       else
        !           456: #endif /* TME_M68K_M68020 || TME_M68K_M68030 */
1.1       root      457: 
1.1.1.3 ! root      458:        /* if this is not a memory-to-memory move instruction: */
        !           459:        if ((params & TME_M68K_OPCODE_EA_Y) == 0) {
1.1       root      460: 
1.1.1.3 ! root      461:          /* many instructions have a single special extension word: */
        !           462:          _TME_M68K_EXECUTE_FETCH_U16(ic->_tme_m68k_insn_specop);
        !           463:          first_ea_extword_offset = 4;
        !           464:        }
1.1       root      465:     }
1.1.1.3 ! root      466: 
1.1       root      467:     /* get any immediate operand: */
1.1.1.3 ! root      468:     if (__tme_predict_false(TME_M68K_OPCODE_HAS_IMM(params))) {
        !           469:       if (params & TME_M68K_OPCODE_IMM_16) {
1.1       root      470:        _TME_M68K_EXECUTE_FETCH_S16(imm32);
                    471:       }
1.1.1.3 ! root      472:       else {
        !           473:        _TME_M68K_EXECUTE_FETCH_U32(imm32);
        !           474:       }
        !           475:       ic->tme_m68k_ireg_imm32 = imm32;
        !           476:     }  
1.1       root      477:     
                    478:     /* loop over up to two effective addresses calculations.  this
                    479:        initializes for the normal, single effective address: */
1.1.1.3 ! root      480:     while (TME_M68K_OPCODE_HAS_EA(params)) {
        !           481: 
        !           482:       /* if this EA is described by the alternate EA mode and reg
        !           483:         fields, copy them into the EA mode and reg fields in
        !           484:         params: */
        !           485:       if (__tme_predict_false((params
        !           486:                               & (TME_M68K_OPCODE_EA_Y | TME_M68K_OPCODE_SPECOP))
        !           487:                              == TME_M68K_OPCODE_EA_Y)) {
        !           488:       
        !           489:        /* reload to write the other memory EA: */
        !           490:        params
        !           491:          = ((params
        !           492:              & ~(TME_M68K_OPCODE_EA_MODE_MASK
        !           493:                  | TME_M68K_OPCODE_EA_REG_MASK
        !           494:                  | TME_M68K_OPCODE_EA_READ
        !           495:                  | TME_M68K_OPCODE_EA_Y))
        !           496:             | TME_M68K_OPCODE_EA_MODE(TME_FIELD_EXTRACTU(opw, 6, 3))
        !           497:             | TME_M68K_OPCODE_EA_REG(TME_FIELD_EXTRACTU(opw, 9, 3))
        !           498:             | TME_M68K_OPCODE_EA_WRITE);
        !           499:       }
        !           500: 
        !           501:       /* get the reg, size, and function code of this EA: */
        !           502:       ea_reg = TME_M68K_IREG_A0 + TME_M68K_OPCODE_EA_REG_WHICH(params);
        !           503:       ea_size = TME_M68K_OPCODE_EA_SIZE_WHICH(params);
        !           504:       ea_function_code = function_code_data;
1.1       root      505:       
                    506:       /* this EA must have either no size, or be exactly one, two, or
                    507:         four bytes: */
                    508:       assert(ea_size == TME_M68K_SIZE_UNSIZED
                    509:             || ea_size == TME_M68K_SIZE_8
                    510:             || ea_size == TME_M68K_SIZE_16
                    511:             || ea_size == TME_M68K_SIZE_32);
                    512: 
                    513:       /* for the effective address predecrement and postincrement
                    514:         modes, we require that these size macros correspond exactly
                    515:         to the number of bytes, that the %a7 register number be 15,
                    516:         and that the ea reg not be greater than %a7: */
                    517: #if TME_M68K_SIZE_UNSIZED != 0
                    518: #error "TME_M68K_SIZE_UNSIZED must be 0"
                    519: #endif
                    520: #if TME_M68K_SIZE_8 != 1
                    521: #error "TME_M68K_SIZE_8 must be 1"
                    522: #endif
                    523: #if TME_M68K_SIZE_16 != 2
                    524: #error "TME_M68K_SIZE_16 must be 2"
                    525: #endif
                    526: #if TME_M68K_SIZE_32 != 4
                    527: #error "TME_M68K_SIZE_32 must be 4"
                    528: #endif
                    529: #if TME_M68K_IREG_A7 != 15
                    530: #error "TME_M68K_IREG_A7 must be 15"
                    531: #endif
                    532:       assert(ea_reg <= TME_M68K_IREG_A7);
                    533: #define TME_M68K_AREG_INCREMENT(areg, size) \
                    534:   (((((areg) + 1) / (TME_M68K_IREG_A7 + 1)) & (size)) + (size))
                    535: 
                    536:       /* initialize ea_address to silence -Wuninitialized: */
                    537:       ea_address = 0;
                    538: 
                    539:       /* set the EA inner function code: */
                    540:       eai_function_code = ea_function_code;
                    541: 
                    542:       /* dispatch on the mode: */
1.1.1.3 ! root      543:       switch (TME_M68K_OPCODE_EA_MODE_WHICH(params)) {
1.1       root      544:        
                    545:        /* address register indirect: */
                    546:       case 2:
                    547:        ea_address = ic->tme_m68k_ireg_uint32(ea_reg);
                    548:        break;
                    549:          
                    550:        /* address register indirect postincrement: */
                    551:       case 3:
                    552:        /* if we are not restarting, set the effective address: */
                    553:        if (!_TME_M68K_SEQUENCE_RESTARTING) {
                    554:          ea_address = ic->tme_m68k_ireg_uint32(ea_reg);
                    555:          ic->tme_m68k_ireg_uint32(ea_reg) += TME_M68K_AREG_INCREMENT(ea_reg, ea_size);
                    556:        }
                    557:        break;
                    558:          
                    559:        /* address register indirect predecrement: */
                    560:       case 4:
                    561:        /* if we are not restarting, set the effective address: */
                    562:        if (!_TME_M68K_SEQUENCE_RESTARTING) {
                    563:          ic->tme_m68k_ireg_uint32(ea_reg) -= TME_M68K_AREG_INCREMENT(ea_reg, ea_size);
                    564:          ea_address = ic->tme_m68k_ireg_uint32(ea_reg);
                    565:        }
                    566:        break;
                    567:          
                    568:        /* address register indirect with 16-bit displacement: */
                    569:       case 5:
                    570:        _TME_M68K_EXECUTE_FETCH_S16(ea_bd);
                    571:        ea_address = ic->tme_m68k_ireg_uint32(ea_reg) + ea_bd;
                    572:        break;
                    573:          
                    574:        /* miscellaneous modes: */
                    575:       case 7:
                    576:          
                    577:        /* absolute short addressing: */
                    578:        if (ea_reg == TME_M68K_IREG_A0) {
                    579:          _TME_M68K_EXECUTE_FETCH_S16(ea_address);
                    580:          break;
                    581:        }           
                    582:          
                    583:        /* absolute long addressing: */
                    584:        if (ea_reg == TME_M68K_IREG_A1) {
                    585:          _TME_M68K_EXECUTE_FETCH_S32(ea_address);
                    586:          break;
                    587:        }           
                    588:          
                    589:        /* program counter indirect with 16-bit displacement: */
                    590:        if (ea_reg == TME_M68K_IREG_A2) {
                    591:          _TME_M68K_EXECUTE_FETCH_S16(ea_bd);
                    592:          /* XXX simulates preincremented pc: */
                    593:          ea_address = ic->tme_m68k_ireg_pc + first_ea_extword_offset + ea_bd;
                    594:          ea_function_code = function_code_program;
                    595:          break;
                    596:        }
                    597:          
                    598:        /* everything else is just like mode 6 except with the PC as
                    599:           the base register: */
                    600:        assert (ea_reg == TME_M68K_IREG_A3);
                    601:        ea_reg = TME_M68K_IREG_PC;
                    602:        eai_function_code = function_code_program;
                    603:        /* FALLTHROUGH */
                    604:          
                    605:        /* various indexed modes: */
                    606:       case 6:
                    607:          
                    608:        /* fetch the extension word and take it apart.  the 68000 and
                    609:           68010 ignore the scale field in the extension word and always
                    610:           behave as if it is zero: */
                    611:        _TME_M68K_EXECUTE_FETCH_U16(extword);
                    612:        ea_pre_index = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(extword, 12, 4);
                    613:        ea_index_long = (extword & TME_BIT(11));
                    614: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030)
                    615:        ea_index_scale = TME_FIELD_EXTRACTU(extword, 9, 2);
                    616: #else  /* !TME_M68K_M68020 && !TME_M68K_M68030 */
                    617:        ea_index_scale = 0;
                    618: #endif /* !TME_M68K_M68020 && !TME_M68K_M68030 */
                    619:          
                    620:        /* if this is a full extension word: */
1.1.1.3 ! root      621:        if (__tme_predict_false(extword & TME_BIT(8))) {
1.1       root      622: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030)
                    623: 
                    624:          ea_i_is = TME_FIELD_EXTRACTU(extword, 0, 3);
                    625: 
                    626:          /* optionally suppress the base register: */
                    627:          if (extword & TME_BIT(7)) {
1.1.1.3 ! root      628:            ea_reg = TME_M68K_IREG_ZERO;
1.1       root      629:          }
                    630:            
                    631:          /* fetch any base displacement: */
1.1.1.3 ! root      632:          ea_bd = 0;
1.1       root      633:          switch (TME_FIELD_EXTRACTU(extword, 4, 2)) {
                    634:          case 0: abort();
1.1.1.3 ! root      635:          case 1: break;
1.1       root      636:          case 2: _TME_M68K_EXECUTE_FETCH_S16(ea_bd); break;
                    637:          case 3: _TME_M68K_EXECUTE_FETCH_S32(ea_bd); break;
                    638:          }
                    639:            
                    640:          /* optionally suppress the index register.  this is also
                    641:             where we check for combined IS-I/IS fields greater than
                    642:             or equal to 0xc, which are reserved: */
                    643:          if (extword & TME_BIT(6)) {
1.1.1.3 ! root      644:            ea_pre_index = TME_M68K_IREG_ZERO;
1.1       root      645:            if (ea_i_is >= 0x4) {
                    646:              abort();
                    647:            }
                    648:          }
                    649: 
                    650:          /* fetch any outer displacement: */
1.1.1.3 ! root      651:          ea_od = 0;
1.1       root      652:          switch (ea_i_is & 3) {
1.1.1.3 ! root      653:          case 0: case 1: break;
1.1       root      654:          case 2: _TME_M68K_EXECUTE_FETCH_S16(ea_od); break;
                    655:          case 3: _TME_M68K_EXECUTE_FETCH_S32(ea_od); break;
                    656:          }
                    657: 
                    658:          /* dispatch on the I/IS fields: */
1.1.1.3 ! root      659:          ea_post_index = TME_M68K_IREG_ZERO;
1.1       root      660:          switch (ea_i_is) {
                    661: 
                    662:            /* no memory indirect action: */
                    663:          case 0x0:
                    664:            ea_post_index = TME_M68K_IREG_UNDEF;
                    665:            break;
                    666:            
                    667:            /* indirect preindexed with null outer displacement: */
                    668:            /* indirect preindexed with word outer displacement: */
                    669:            /* indirect preindexed with long outer displacement: */
                    670:          case 0x1: case 0x2: case 0x3:
                    671:            break;
                    672: 
                    673:            /* reserved: */
                    674:          case 0x4: default: abort();
                    675: 
                    676:            /* indirect postindexed with null outer displacement: */
                    677:            /* indirect postindexed with word outer displacement: */
                    678:            /* indirect postindexed with long outer displacement: */
                    679:          case 0x5: case 0x6: case 0x7:
                    680:            ea_post_index = ea_pre_index;
1.1.1.3 ! root      681:            ea_pre_index = TME_M68K_IREG_ZERO;
1.1       root      682:            break;
                    683:          }
                    684: 
                    685:          /* preindex and base-displace the original address register
                    686:             to arrive at the indirect EA: */
                    687:          ea_address = 
                    688:            (ic->tme_m68k_ireg_uint32(ea_reg)
                    689:             + ((ea_index_long
                    690:                 ? ic->tme_m68k_ireg_int32(ea_pre_index)
                    691:                 : ((tme_int32_t) ic->tme_m68k_ireg_int16(ea_pre_index << 1)))
                    692:                << ea_index_scale)
                    693:             + ea_bd
                    694:             + (ea_reg == TME_M68K_IREG_PC
                    695:                /* XXX simulates preincremented pc: */
                    696:                ? first_ea_extword_offset
                    697:                : 0));
                    698:          
                    699:          /* if this is a memory indirect, read the indirect EA.
                    700:             don't disturb the EA in the IC state if we're restarting,
                    701:             for two reasons:
                    702: 
                    703:             first, the value in the IC state may belong to some later
                    704:             part of the instruction handling, in which case we must
                    705:             (continue to) preserve it, and
                    706:             
                    707:             second, if the EA in the IC state *is* from this part of
                    708:             the instruction handling, it's correct, while our EA may
                    709:             *not* be correct, since it was generated from IC state
                    710:             that may have changed since the instruction originally
                    711:             started (i.e., address register changes by the user or by
                    712:             our own postincrement/predecrement, or function code
                    713:             register changes by the user): */
                    714:          if (ea_post_index != TME_M68K_IREG_UNDEF) {
                    715:            if (!_TME_M68K_SEQUENCE_RESTARTING) {
                    716:              ic->_tme_m68k_ea_address = ea_address;
                    717:              ic->_tme_m68k_ea_function_code = eai_function_code;
                    718:            }
                    719:            _TME_M68K_INSN_FETCH_SAVE;
                    720:            tme_m68k_read_mem32(ic, TME_M68K_IREG_MEMY32);
                    721:            ea_address =
                    722:              (ic->tme_m68k_ireg_memy32
                    723:               + ((ea_index_long
                    724:                   ? ic->tme_m68k_ireg_int32(ea_post_index)
                    725:                   : ((tme_int32_t) ic->tme_m68k_ireg_int16(ea_post_index << 1)))
                    726:                  << ea_index_scale)
                    727:               + ea_od);
                    728:          }
                    729:          else {
                    730:            ea_function_code = eai_function_code;
                    731:          }
                    732:          
                    733: #else  /* !TME_M68K_M68020 && !TME_M68K_M68030 */
                    734:          /* XXX - illegal instruction */
                    735:          abort();
                    736: #endif /* !TME_M68K_M68020 && !TME_M68K_M68030 */
                    737:        }
                    738:        
                    739:        /* otherwise, this is a brief extension word: */
                    740:        else {
                    741:          ea_address = 
                    742:            (ic->tme_m68k_ireg_uint32(ea_reg)
                    743:             + ((tme_int32_t) ((tme_int8_t) (extword & 0xff)))
                    744:             + ((ea_index_long
                    745:                 ? ic->tme_m68k_ireg_int32(ea_pre_index)
                    746:                 : ((tme_int32_t) ic->tme_m68k_ireg_int16(ea_pre_index << 1)))
                    747:                << ea_index_scale)
                    748:             + (ea_reg == TME_M68K_IREG_PC
                    749:                /* XXX simulates preincremented pc: */
                    750:                ? first_ea_extword_offset
                    751:                : 0));
                    752:          ea_function_code = eai_function_code;
                    753:        }
                    754:        break;
                    755: 
                    756:       default: assert(FALSE);
                    757:       }
                    758: 
                    759:       /* we have calculated the effective address.  we don't store it
                    760:         if we're restarting, because it may have been calculated
                    761:         using user-visible registers (address registers and even
                    762:         function code registers!) that the user may have changed (or,
                    763:         in the case of pre/postdecrement EAs, that *we* may have
                    764:         changed) between the bus fault and the instruction restart.
                    765:         when we restart an instruction we *always* want to use the
                    766:         same effective address as before: */
                    767:       if (!_TME_M68K_SEQUENCE_RESTARTING) {
                    768:        ic->_tme_m68k_ea_address = ea_address;
                    769:        ic->_tme_m68k_ea_function_code = eai_function_code;
                    770:       }
                    771:       
                    772:       /* XXX XXX XXX - if we detect a store to program space, that's an illegal: */
                    773:       /* XXX but maybe not for moves? */
1.1.1.3 ! root      774:       if (__tme_predict_false(ea_function_code == function_code_program
        !           775:                              && (params & TME_M68K_OPCODE_EA_WRITE) != 0)) {
1.1       root      776:        abort();
                    777:       }
                    778: 
                    779:       /* if we're loading this operand: */
1.1.1.3 ! root      780:       if (params & TME_M68K_OPCODE_EA_READ) {
1.1       root      781:        _TME_M68K_INSN_FETCH_SAVE;
                    782:        (*_tme_m68k_read_memx[ea_size])(ic);
                    783:       }
                    784: 
                    785:       /* stop unless this is a memory-to-memory move: */
1.1.1.3 ! root      786:       if (__tme_predict_true(!(params & TME_M68K_OPCODE_EA_Y)))
1.1       root      787:        break;
                    788: 
1.1.1.3 ! root      789:       /* loop to reload for the other memory EA at the same size: */
        !           790:       params &= ~TME_M68K_OPCODE_SPECOP;
1.1       root      791:     }
                    792: 
                    793:     /* we've fetched all of the instruction words: */
                    794:     _TME_M68K_INSN_FETCH_SAVE;
                    795: 
                    796:     /* set the next PC: */
                    797: #ifdef _TME_M68K_EXECUTE_FAST
                    798:     ic->tme_m68k_ireg_pc_next = ic->tme_m68k_ireg_pc + (emulator_load - emulator_load_start);
                    799: #else  /* !_TME_M68K_EXECUTE_FAST */
                    800:     ic->tme_m68k_ireg_pc_next = linear_pc;
                    801: #endif /* !_TME_M68K_EXECUTE_FAST */
                    802: 
                    803:     /* if we're not restarting, or if this instruction function can
                    804:        fault, call the instruction function: */
                    805:     if (!_TME_M68K_SEQUENCE_RESTARTING
                    806:        || (ic->_tme_m68k_mode_flags & TME_M68K_EXECUTION_INST_CANFAULT)) {
                    807:       transfer_next_before = ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next;
1.1.1.3 ! root      808:       (*func)(ic, TME_M68K_OPCODE_OP0_WHICH(ic, params), TME_M68K_OPCODE_OP1_WHICH(ic, params));
1.1       root      809:       assert(!(ic->_tme_m68k_mode_flags & TME_M68K_EXECUTION_INST_CANFAULT)
                    810:             != (ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next
                    811:                 != transfer_next_before));
                    812:       ic->_tme_m68k_mode_flags &= ~TME_M68K_EXECUTION_INST_CANFAULT;
                    813:     }
                    814: 
                    815:     /* store up to one EA path: */
1.1.1.3 ! root      816:     if ((params & TME_M68K_OPCODE_EA_WRITE) != 0) {
1.1       root      817:       (*_tme_m68k_write_memx[ea_size])(ic);
                    818:     }
                    819: 
                    820:     /* an instruction has ended: */
                    821:     tme_m68k_verify_end(ic, func);
                    822: 
                    823:     /* update the PC: */
                    824:     ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
                    825:     TME_M68K_SEQUENCE_START;
                    826: 
                    827: #ifdef _TME_M68K_EXECUTE_FAST
                    828:     /* if we haven't finished the instruction burst yet, continue: */
1.1.1.2   root      829:     if (__tme_predict_true(ic->_tme_m68k_instruction_burst_remaining != 0)) {
1.1       root      830:       continue;
                    831:     }
                    832: #endif /* _TME_M68K_EXECUTE_FAST */
                    833: 
                    834:     /* try to acquire the external mutex and check for external
                    835:        resets, halts, or interrupts, and process them along
                    836:        with any internal exceptions: */
                    837:     rc = tme_mutex_trylock(&ic->tme_m68k_external_mutex);
                    838:     if (TME_THREADS_ERRNO(rc) == TME_OK) {
                    839:       tme_m68k_external_check(ic, 
                    840: #ifdef _TME_M68K_EXECUTE_FAST
                    841:                              0
                    842: #else  /* !_TME_M68K_EXECUTE_FAST */
                    843:                              exceptions
                    844: #endif /* !_TME_M68K_EXECUTE_FAST */
                    845:                              );
                    846: 
                    847:       /* unlock the external mutex: */
                    848:       tme_mutex_unlock(&ic->tme_m68k_external_mutex);
                    849:     }
                    850: 
                    851: #ifndef _TME_M68K_EXECUTE_FAST
                    852: 
                    853:     /* otherwise, if we have internal exceptions, process them: */
                    854:     else if (exceptions) {
                    855:       tme_m68k_exception(ic, exceptions);
                    856:     }
                    857: 
                    858:     /* if we can go fast now, go fast: */
                    859:     if (!tme_m68k_go_slow(ic)) {
                    860:       tme_m68k_redispatch(ic);
                    861:     }
                    862: 
1.1.1.2   root      863:     /* otherwise, unless we've used up our burst, continue: */
                    864:     if (ic->_tme_m68k_instruction_burst_remaining != 0) {
                    865:       continue;
                    866:     }
                    867: 
                    868: #endif /* !_TME_M68K_EXECUTE_FAST */
                    869: 
                    870:     /* start a new burst: */
                    871:     ic->_tme_m68k_instruction_burst_remaining
                    872:       = ic->_tme_m68k_instruction_burst;
1.1       root      873: 
                    874:     /* if this is a cooperative threading system, yield: */
                    875: #ifdef TME_THREADS_COOPERATIVE
                    876:     tme_thread_yield();
                    877: #endif /* TME_THREADS_COOPERATIVE */
                    878: 
                    879:   }
                    880:   /* NOTREACHED */
                    881: 
                    882: #ifdef _TME_M68K_EXECUTE_FAST
                    883: 
                    884:   /* if we get here, we "faulted" trying to fetch an instruction word
                    885:      from host memory.  it's possibly not a "real" fault, since this
                    886:      instruction may simply cross a page boundary, but since the fast
                    887:      executor can't restart instructions we have to treat this like a
                    888:      group 0 fault: */
                    889:  _tme_m68k_fast_fetch_failed:
                    890: 
                    891:   /* mimic a group 0 exception: */
                    892:   _TME_M68K_INSN_FETCH_SAVE;
                    893:   ic->_tme_m68k_group0_flags = TME_M68K_BUS_CYCLE_FETCH | TME_M68K_BUS_CYCLE_READ;
                    894:   ic->_tme_m68k_group0_function_code = function_code_program;
                    895:   ic->_tme_m68k_group0_address = ic->tme_m68k_ireg_pc + (emulator_load - emulator_load_start);
                    896:   ic->_tme_m68k_group0_sequence = ic->_tme_m68k_sequence;
                    897:   ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted_after = 0;
                    898:   ic->_tme_m68k_group0_buffer_read_size = 0;
                    899:   ic->_tme_m68k_group0_buffer_read_softrr = 0;
                    900:   tme_m68k_group0_hook_fast(ic);
                    901:   ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted =
                    902:     ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_next;
                    903: 
                    904:   /* mimic the rte: */
                    905:   ic->_tme_m68k_sequence = ic->_tme_m68k_group0_sequence;
                    906:   ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next = 1;
                    907:   TME_M68K_SEQUENCE_RESTART;
                    908: 
                    909:   tme_m68k_redispatch(ic);
                    910:   /* NOTREACHED */
                    911: #endif /* _TME_M68K_EXECUTE_FAST */
                    912: }

unix.superglobalmegacorp.com

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