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

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

unix.superglobalmegacorp.com

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