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

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

unix.superglobalmegacorp.com

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