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

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

unix.superglobalmegacorp.com

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