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

1.1.1.2 ! root        1: /* $Id: m68k-execute.c,v 1.14 2003/10/25 17:08:00 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: 
        !            36: _TME_RCSID("$Id: m68k-execute.c,v 1.14 2003/10/25 17:08:00 fredette Exp $");
1.1       root       37: 
                     38: /* includes: */
                     39: #include "m68k-auto.h"
                     40: 
                     41: /* the m68k instruction executor: */
                     42: static void
                     43: _TME_M68K_EXECUTE_NAME(struct tme_m68k *ic)
                     44: {
                     45: #undef _TME_M68K_SEQUENCE_RESTARTING
                     46: #undef _TME_M68K_INSN_FETCH_SAVE
                     47: #ifdef _TME_M68K_EXECUTE_FAST
                     48:   struct tme_m68k_tlb *tlb;
                     49:   tme_uint8_t *emulator_load, *emulator_load_last;
                     50:   tme_uint8_t *emulator_load_start;
                     51: #define _TME_M68K_INSN_FETCH_SAVE \
                     52: do { \
                     53:   ic->_tme_m68k_insn_buffer_fetch_total = emulator_load - emulator_load_start; \
                     54:   ic->_tme_m68k_insn_buffer_fetch_sizes = insn_fetch_sizes; \
                     55: } while (/* CONSTCOND */ 0)
                     56: #define _TME_M68K_SEQUENCE_RESTARTING  (FALSE)
                     57: #else  /* !_TME_M68K_EXECUTE_FAST */
                     58:   unsigned int exceptions;
                     59:   tme_uint32_t linear_pc;
                     60: #define _TME_M68K_INSN_FETCH_SAVE \
                     61: do { \
                     62:   ic->_tme_m68k_insn_buffer_fetch_total = linear_pc - ic->tme_m68k_ireg_pc; \
                     63:   ic->_tme_m68k_insn_buffer_fetch_sizes = insn_fetch_sizes; \
                     64: } while (/* CONSTCOND */ 0)
                     65: #define _TME_M68K_SEQUENCE_RESTARTING  TME_M68K_SEQUENCE_RESTARTING
                     66: #endif /* !_TME_M68K_EXECUTE_FAST */
                     67: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030)
                     68:   unsigned int eai_function_code;
                     69:   int ea_post_index;
                     70:   unsigned int ea_i_is;
                     71: #else  /* !TME_M68K_M68020 && !TME_M68K_M68030 */
                     72: #define eai_function_code ea_function_code
                     73: #endif  /* !TME_M68K_M68020 && !TME_M68K_M68030 */
                     74:   unsigned int function_code_program;
                     75:   unsigned int function_code_data;
                     76:   tme_uint16_t opw, extword;
                     77:   const struct _tme_m68k_decoder_root *root_entry;
                     78:   const struct _tme_m68k_decoder_submap *submap_entry;
                     79:   const struct _tme_m68k_opcode *opcode;
                     80:   void (*func) _TME_P((struct tme_m68k *, void *, void *));
                     81:   int specop_type;
                     82:   void *operand0, *operand1;
                     83:   tme_uint16_t insn_fetch_sizes;
                     84:   unsigned int first_ea_extword_offset;
                     85:   int ea_size, ea_cycles;
                     86:   unsigned int ea_mode;
                     87:   int ea_reg, ea_pre_index;
                     88:   unsigned int ea_index_long, ea_index_scale;
                     89:   tme_uint32_t ea_address;
                     90:   unsigned int ea_function_code;
                     91:   tme_int32_t disp, ea_bd;
                     92:   int imm_operand, imm_size;
                     93:   tme_uint32_t imm32;
                     94:   tme_uint16_t imm16;
                     95:   tme_uint8_t imm8;
                     96:   tme_uint16_t transfer_next_before;
                     97:   int rc;
                     98: 
                     99:   /* get the function codes.  if the privilege ever changes as a
                    100:      result of any instruction, we must redispatch: */
                    101:   if (TME_M68K_PRIV(ic)) {
                    102:     function_code_program = TME_M68K_FC_SP;
                    103:     function_code_data = TME_M68K_FC_SD;
                    104:   }
                    105:   else {
                    106:     function_code_program = TME_M68K_FC_UP;
                    107:     function_code_data = TME_M68K_FC_UD;
                    108:   }
                    109: 
1.1.1.2 ! root      110:   /* if we have used up our burst: */
        !           111:   if (ic->_tme_m68k_instruction_burst_remaining == 0) {
        !           112: 
        !           113:     /* start a new burst: */
        !           114:     ic->_tme_m68k_instruction_burst_remaining
        !           115:       = ic->_tme_m68k_instruction_burst;
        !           116: 
        !           117:     /* if this is a cooperative threading system, yield: */
        !           118: #ifdef TME_THREADS_COOPERATIVE
        !           119:     tme_thread_yield();
        !           120: #endif /* TME_THREADS_COOPERATIVE */
        !           121:   }
        !           122: 
1.1       root      123: #ifdef _TME_M68K_EXECUTE_FAST
                    124: 
                    125:   /* get our instruction TLB entry and reload it: */
                    126:   tlb = TME_ATOMIC_READ(struct tme_m68k_tlb *, ic->_tme_m68k_itlb);
                    127:   if (!TME_M68K_TLB_OK_FAST_READ(tlb, function_code_program, ic->tme_m68k_ireg_pc, ic->tme_m68k_ireg_pc)) {
                    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)) {
                    137:     return (_TME_M68K_EXECUTE_SLOW(ic));
                    138:   }
                    139: 
                    140:   /* set up to do fast reads from the instruction TLB entry: */
                    141:   emulator_load_last = tlb->tme_m68k_tlb_emulator_off_read + TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_m68k_tlb_linear_last);
                    142:   ic->_tme_m68k_group0_hook = tme_m68k_group0_hook_fast;
                    143: #else  /* !_TME_M68K_EXECUTE_FAST */
                    144: 
                    145:   /* set up to do slow reads from the instruction TLB entry: */
                    146:   ic->_tme_m68k_group0_hook = NULL;
                    147: #endif /* !_TME_M68K_EXECUTE_FAST */
                    148: 
                    149:   /* the execution loop: */
                    150:   for (;;) {
                    151: 
                    152:     /* reset for this instruction: */
                    153: #ifdef _TME_M68K_EXECUTE_FAST
                    154:     if (__tme_predict_false(TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_m68k_tlb_linear_last) == 0)) {
                    155:       tme_m68k_redispatch(ic);
                    156:     }
                    157:     emulator_load_start = emulator_load = tlb->tme_m68k_tlb_emulator_off_read + ic->tme_m68k_ireg_pc;
                    158:     assert(TME_M68K_TLB_OK_FAST_READ(tlb, function_code_program, ic->tme_m68k_ireg_pc, ic->tme_m68k_ireg_pc)
                    159:           || (emulator_load - 1) == emulator_load_last);
                    160:     tme_m68k_verify_begin(ic, emulator_load_start);
                    161: #else  /* !_TME_M68K_EXECUTE_FAST */
                    162:     linear_pc = ic->tme_m68k_ireg_pc;
                    163:     ic->_tme_m68k_insn_buffer_off = 0;
                    164:     exceptions = 0;
                    165:     if (__tme_predict_false(TME_M68K_FLAG_T(ic->tme_m68k_ireg_sr) != 0)) {
                    166:       exceptions |= TME_M68K_EXCEPTION_GROUP1_TRACE;
                    167:     }
                    168:     tme_m68k_verify_begin(ic, NULL);
                    169: #endif /* _TME_M68K_EXECUTE_FAST */
                    170: #ifdef _TME_M68K_VERIFY
                    171:     if (ic->tme_m68k_ireg_pc == 0x6000) {
                    172:       tme_m68k_verify_hook();
                    173:     }
                    174: #endif
                    175:     insn_fetch_sizes = 0;
                    176:     first_ea_extword_offset = sizeof(opw);
1.1.1.2 ! root      177:     ic->_tme_m68k_instruction_burst_remaining--;
1.1       root      178:     
                    179:     /* fetch and decode the first word of this instruction: */
                    180:     _TME_M68K_EXECUTE_FETCH_U16(opw);
                    181:     ic->_tme_m68k_insn_opcode = opw;
                    182:     root_entry = ic->_tme_m68k_decoder_root
                    183:       + TME_FIELD_EXTRACTU(opw, 6, 10);
                    184:     submap_entry = root_entry->_tme_m68k_decoder_root_submap
                    185:       + TME_FIELD_EXTRACTU(opw, 0, 6);
                    186:     opcode = root_entry->_tme_m68k_decoder_root_opcode_map
                    187:       + submap_entry->_tme_m68k_decoder_submap_opcode_map_index;
                    188:     
                    189:     /* set func: */
                    190:     func = opcode->_tme_m68k_opcode_func;
                    191:     
                    192:     /* set operand 0: */
                    193:     operand0 = submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_operand0;
                    194:     if (operand0 == NULL)
                    195:       operand0 = root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_operand0;
                    196:     
                    197:     /* set operand 1: */
                    198:     operand1 = submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_operand1;
                    199:     if (operand1 == NULL)
                    200:       operand1 = root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_operand1;
                    201:     
                    202:     /* set ea_size: */
                    203:     ea_size = submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_eax_size;
                    204:     if (ea_size == TME_M68K_SIZE_SUBMAP_X)
                    205:       ea_size = root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_eax_size;
                    206:     
                    207:     /* set imm_operand: */
                    208:     imm_operand = submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_imm_operand;
                    209:     imm_size = submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_imm_size;
                    210:     if (imm_operand == TME_M68K_OPNUM_SUBMAP_X) {
                    211:       imm_operand = root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_imm_operand;
                    212:       imm_size = root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_imm_size;
                    213:     }
                    214:     
                    215:     /* set ea_mode, ea_reg, ea_cycles and ea_function_code -
                    216:        instructions or the EA itself may override these: */
                    217:     ea_mode = TME_FIELD_EXTRACTU(opw, 3, 3);
                    218:     ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(opw, 0, 3);
                    219:     ea_cycles = opcode->_tme_m68k_opcode_eax_cycles;
                    220:     ea_function_code = function_code_data;
                    221:     assert(ea_size == TME_M68K_SIZE_UNDEF
                    222:           || ea_size == TME_M68K_SIZE_UNSIZED
                    223:           || ea_cycles != TME_BUS_CYCLE_UNDEF);
                    224:       
                    225:     /* dispatch on the special operand specifier type: */
                    226:     specop_type = opcode->_tme_m68k_opcode_specop_type;
                    227:     if (__tme_predict_false(specop_type != TME_M68K_SPECOP_UNDEF)) {
                    228:       switch (specop_type) {
                    229:        
                    230:        /* a Bcc may have an extended displacement, and we need to
                    231:           translate BF to BSR: */
                    232:       case TME_M68K_SPECOP_BCC:
                    233:        disp = TME_EXT_S8_S32((tme_int8_t) opw);
                    234:        if (disp == 0) {
                    235:          _TME_M68K_EXECUTE_FETCH_S16(disp);
                    236:        }
                    237: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030)
                    238:        else if (disp == -255) {
                    239:          _TME_M68K_EXECUTE_FETCH_S32(disp);
                    240:        }
                    241: #endif /* TME_M68K_M68020 || TME_M68K_M68030 */
                    242:        imm32 = (tme_uint32_t) disp;
                    243:        operand0 = &imm32;
                    244:        if (TME_FIELD_EXTRACTU(opw, 8, 4) == TME_M68K_C_F) {
                    245:          func = tme_m68k_bsr;
                    246:        }
                    247:        break;
                    248:        
                    249: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030)
                    250:        /* these are similar: */
                    251:       case TME_M68K_SPECOP_DIVUL:
                    252:       case TME_M68K_SPECOP_MULUL:
                    253:        _TME_M68K_EXECUTE_FETCH_U16(specop);
                    254:        first_ea_extword_offset = 4;
                    255:        if (specop & TME_BIT(11)) {
                    256:          /* this is really a signed operation, override
                    257:             m68k-opmap-make.sh's guess that it is unsigned: */
                    258:          func = ((opcode->_tme_m68k_opcode_specop_type == TME_M68K_SPECOP_DIVUL)
                    259:                  ? tme_m68k_divsl
                    260:                  : tme_m68k_mulsl);
                    261:        }
                    262:        break;
                    263: #endif /* TME_M68K_M68020 || TME_M68K_M68030 */
                    264:        
                    265: #if (_TME_M68K_EXECUTE_CPU != TME_M68K_M68000)
                    266:        /* moves: */
                    267:       case TME_M68K_SPECOP_MOVES:
                    268: 
                    269:        /* fetch the remainder of the instruction and decide what EA
                    270:           function code and cycles we need: */
                    271:        _TME_M68K_EXECUTE_FETCH_U16(ic->_tme_m68k_insn_specop);
                    272:        first_ea_extword_offset = 4;
                    273:        if (ic->_tme_m68k_insn_specop & TME_BIT(11)) {
                    274:          ea_cycles = TME_BUS_CYCLE_WRITE;
                    275:          ea_function_code = ic->tme_m68k_ireg_dfc;
                    276:        }
                    277:        else {
                    278:          ea_cycles = TME_BUS_CYCLE_READ;
                    279:          ea_function_code = ic->tme_m68k_ireg_sfc;
                    280:        }
                    281: 
                    282:        /* if we're not privileged, don't fetch any EA, and run the
                    283:           priv function instead: */
                    284:        if (!TME_M68K_PRIV(ic)) {
                    285:          func = tme_m68k_priv;
                    286:          ea_size = TME_M68K_SIZE_UNDEF;
                    287:        }
                    288:        break;
                    289: #endif /* !TME_M68K_M68000 */
                    290: 
                    291:        /* many instructions have a single special extension word: */
                    292:       case TME_M68K_SPECOP_SPECOP16:
                    293:        _TME_M68K_EXECUTE_FETCH_U16(ic->_tme_m68k_insn_specop);
                    294:        first_ea_extword_offset = 4;
                    295:        break;
                    296: 
                    297:        /* all of these always have two specop words: */
                    298:       case TME_M68K_SPECOP_CAS2:
                    299:        _TME_M68K_EXECUTE_FETCH_U16(ic->_tme_m68k_insn_specop);
                    300:        _TME_M68K_EXECUTE_FETCH_U16(ic->_tme_m68k_insn_specop2);
                    301:        first_ea_extword_offset = 6;
                    302:        break;
                    303:        
                    304:        /* a memory-to-memory move instruction has additional ea mode
                    305:           and reg fields, but we don't need to do anything for that
                    306:           yet: */
                    307:       case TME_M68K_SPECOP_MOVEMEMTOMEM:
                    308:        break;
                    309: 
                    310:        /* a nonmemory-to-memory move instruction has additional ea
                    311:           mode and reg fields, and we use them now: */
                    312:       case TME_M68K_SPECOP_MOVENONMEMTOMEM:
                    313:        ea_mode = TME_FIELD_EXTRACTU(opw, 6, 3);
                    314:        ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(opw, 9, 3);
                    315:        assert(ea_cycles == TME_BUS_CYCLE_WRITE);
                    316:        break;
                    317:        
                    318:        /* the illegal specop makes sure not to fetch any EAs or
                    319:            immediates: */
                    320:       case TME_M68K_SPECOP_ILLEGAL:
                    321:        ea_size = TME_M68K_SIZE_UNDEF;
                    322:        imm_operand = TME_M68K_OPNUM_UNDEF;
                    323:        break;
                    324:        
                    325:       default: abort();
                    326:       }
                    327:     }
                    328:     
                    329:     /* get any immediate operand: */
                    330:     if (__tme_predict_false(imm_operand != TME_M68K_OPNUM_UNDEF)) {
                    331:       switch (imm_size) {
                    332:       case TME_M68K_SIZE_16:
                    333:        _TME_M68K_EXECUTE_FETCH_U16(imm16);
                    334:        if (imm_operand == 0) operand0 = &imm16; else operand1 = &imm16;
                    335:        break;
                    336:       case TME_M68K_SIZE_32:
                    337:        _TME_M68K_EXECUTE_FETCH_U32(imm32);
                    338:        if (imm_operand == 0) operand0 = &imm32; else operand1 = &imm32;
                    339:        break;
                    340:       case TME_M68K_SIZE_16S32:
                    341:        _TME_M68K_EXECUTE_FETCH_S16(imm32);
                    342:        if (imm_operand == 0) operand0 = &imm32; else operand1 = &imm32;
                    343:        break;
                    344:       case TME_M68K_SIZE_16U8:
                    345:        _TME_M68K_EXECUTE_FETCH_U16(imm8);
                    346:        if (imm_operand == 0) operand0 = &imm8; else operand1 = &imm8;
                    347:        break;
                    348:       default: assert(FALSE);
                    349:       }
                    350:     }
                    351:     
                    352:     /* loop over up to two effective addresses calculations.  this
                    353:        initializes for the normal, single effective address: */
                    354:     while (ea_size != TME_M68K_SIZE_UNDEF) {
                    355:       
                    356:       /* this EA must have either no size, or be exactly one, two, or
                    357:         four bytes: */
                    358:       assert(ea_size == TME_M68K_SIZE_UNSIZED
                    359:             || ea_size == TME_M68K_SIZE_8
                    360:             || ea_size == TME_M68K_SIZE_16
                    361:             || ea_size == TME_M68K_SIZE_32);
                    362: 
                    363:       /* for the effective address predecrement and postincrement
                    364:         modes, we require that these size macros correspond exactly
                    365:         to the number of bytes, that the %a7 register number be 15,
                    366:         and that the ea reg not be greater than %a7: */
                    367: #if TME_M68K_SIZE_UNSIZED != 0
                    368: #error "TME_M68K_SIZE_UNSIZED must be 0"
                    369: #endif
                    370: #if TME_M68K_SIZE_8 != 1
                    371: #error "TME_M68K_SIZE_8 must be 1"
                    372: #endif
                    373: #if TME_M68K_SIZE_16 != 2
                    374: #error "TME_M68K_SIZE_16 must be 2"
                    375: #endif
                    376: #if TME_M68K_SIZE_32 != 4
                    377: #error "TME_M68K_SIZE_32 must be 4"
                    378: #endif
                    379: #if TME_M68K_IREG_A7 != 15
                    380: #error "TME_M68K_IREG_A7 must be 15"
                    381: #endif
                    382:       assert(ea_reg <= TME_M68K_IREG_A7);
                    383: #define TME_M68K_AREG_INCREMENT(areg, size) \
                    384:   (((((areg) + 1) / (TME_M68K_IREG_A7 + 1)) & (size)) + (size))
                    385: 
                    386:       /* initialize ea_address to silence -Wuninitialized: */
                    387:       ea_address = 0;
                    388: 
                    389:       /* set the EA inner function code: */
                    390:       eai_function_code = ea_function_code;
                    391: 
                    392:       /* dispatch on the mode: */
                    393:       switch (ea_mode) {
                    394:        
                    395:        /* address register indirect: */
                    396:       case 2:
                    397:        ea_address = ic->tme_m68k_ireg_uint32(ea_reg);
                    398:        break;
                    399:          
                    400:        /* address register indirect postincrement: */
                    401:       case 3:
                    402:        /* if we are not restarting, set the effective address: */
                    403:        if (!_TME_M68K_SEQUENCE_RESTARTING) {
                    404:          ea_address = ic->tme_m68k_ireg_uint32(ea_reg);
                    405:          ic->tme_m68k_ireg_uint32(ea_reg) += TME_M68K_AREG_INCREMENT(ea_reg, ea_size);
                    406:        }
                    407:        break;
                    408:          
                    409:        /* address register indirect predecrement: */
                    410:       case 4:
                    411:        /* if we are not restarting, set the effective address: */
                    412:        if (!_TME_M68K_SEQUENCE_RESTARTING) {
                    413:          ic->tme_m68k_ireg_uint32(ea_reg) -= TME_M68K_AREG_INCREMENT(ea_reg, ea_size);
                    414:          ea_address = ic->tme_m68k_ireg_uint32(ea_reg);
                    415:        }
                    416:        break;
                    417:          
                    418:        /* address register indirect with 16-bit displacement: */
                    419:       case 5:
                    420:        _TME_M68K_EXECUTE_FETCH_S16(ea_bd);
                    421:        ea_address = ic->tme_m68k_ireg_uint32(ea_reg) + ea_bd;
                    422:        break;
                    423:          
                    424:        /* miscellaneous modes: */
                    425:       case 7:
                    426:          
                    427:        /* absolute short addressing: */
                    428:        if (ea_reg == TME_M68K_IREG_A0) {
                    429:          _TME_M68K_EXECUTE_FETCH_S16(ea_address);
                    430:          break;
                    431:        }           
                    432:          
                    433:        /* absolute long addressing: */
                    434:        if (ea_reg == TME_M68K_IREG_A1) {
                    435:          _TME_M68K_EXECUTE_FETCH_S32(ea_address);
                    436:          break;
                    437:        }           
                    438:          
                    439:        /* program counter indirect with 16-bit displacement: */
                    440:        if (ea_reg == TME_M68K_IREG_A2) {
                    441:          _TME_M68K_EXECUTE_FETCH_S16(ea_bd);
                    442:          /* XXX simulates preincremented pc: */
                    443:          ea_address = ic->tme_m68k_ireg_pc + first_ea_extword_offset + ea_bd;
                    444:          ea_function_code = function_code_program;
                    445:          break;
                    446:        }
                    447:          
                    448:        /* everything else is just like mode 6 except with the PC as
                    449:           the base register: */
                    450:        assert (ea_reg == TME_M68K_IREG_A3);
                    451:        ea_reg = TME_M68K_IREG_PC;
                    452:        eai_function_code = function_code_program;
                    453:        /* FALLTHROUGH */
                    454:          
                    455:        /* various indexed modes: */
                    456:       case 6:
                    457:          
                    458:        /* fetch the extension word and take it apart.  the 68000 and
                    459:           68010 ignore the scale field in the extension word and always
                    460:           behave as if it is zero: */
                    461:        _TME_M68K_EXECUTE_FETCH_U16(extword);
                    462:        ea_pre_index = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(extword, 12, 4);
                    463:        ea_index_long = (extword & TME_BIT(11));
                    464: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030)
                    465:        ea_index_scale = TME_FIELD_EXTRACTU(extword, 9, 2);
                    466: #else  /* !TME_M68K_M68020 && !TME_M68K_M68030 */
                    467:        ea_index_scale = 0;
                    468: #endif /* !TME_M68K_M68020 && !TME_M68K_M68030 */
                    469:          
                    470:        /* if this is a full extension word: */
                    471:        if (extword & TME_BIT(8)) {
                    472: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030)
                    473: 
                    474:          ea_i_is = TME_FIELD_EXTRACTU(extword, 0, 3);
                    475: 
                    476:          /* optionally suppress the base register: */
                    477:          if (extword & TME_BIT(7)) {
                    478:            ea_reg = TME_M68K_IREG_ZERO32;
                    479:          }
                    480:            
                    481:          /* fetch any base displacement: */
                    482:          switch (TME_FIELD_EXTRACTU(extword, 4, 2)) {
                    483:          case 0: abort();
                    484:          case 1: ea_bd = 0; break;
                    485:          case 2: _TME_M68K_EXECUTE_FETCH_S16(ea_bd); break;
                    486:          case 3: _TME_M68K_EXECUTE_FETCH_S32(ea_bd); break;
                    487:          }
                    488:            
                    489:          /* optionally suppress the index register.  this is also
                    490:             where we check for combined IS-I/IS fields greater than
                    491:             or equal to 0xc, which are reserved: */
                    492:          if (extword & TME_BIT(6)) {
                    493:            ea_pre_index = TME_M68K_IREG_ZERO32;
                    494:            if (ea_i_is >= 0x4) {
                    495:              abort();
                    496:            }
                    497:          }
                    498: 
                    499:          /* fetch any outer displacement: */
                    500:          switch (ea_i_is & 3) {
                    501:          case 0: case 1: ea_od = 0; break;
                    502:          case 2: _TME_M68K_EXECUTE_FETCH_S16(ea_od); break;
                    503:          case 3: _TME_M68K_EXECUTE_FETCH_S32(ea_od); break;
                    504:          }
                    505: 
                    506:          /* dispatch on the I/IS fields: */
                    507:          ea_post_index = TME_M68K_IREG_ZERO32;
                    508:          switch (ea_i_is) {
                    509: 
                    510:            /* no memory indirect action: */
                    511:          case 0x0:
                    512:            ea_post_index = TME_M68K_IREG_UNDEF;
                    513:            break;
                    514:            
                    515:            /* indirect preindexed with null outer displacement: */
                    516:            /* indirect preindexed with word outer displacement: */
                    517:            /* indirect preindexed with long outer displacement: */
                    518:          case 0x1: case 0x2: case 0x3:
                    519:            break;
                    520: 
                    521:            /* reserved: */
                    522:          case 0x4: default: abort();
                    523: 
                    524:            /* indirect postindexed with null outer displacement: */
                    525:            /* indirect postindexed with word outer displacement: */
                    526:            /* indirect postindexed with long outer displacement: */
                    527:          case 0x5: case 0x6: case 0x7:
                    528:            ea_post_index = ea_pre_index;
                    529:            ea_pre_index = TME_M68K_IREG_ZERO32;
                    530:            break;
                    531:          }
                    532: 
                    533:          /* preindex and base-displace the original address register
                    534:             to arrive at the indirect EA: */
                    535:          ea_address = 
                    536:            (ic->tme_m68k_ireg_uint32(ea_reg)
                    537:             + ((ea_index_long
                    538:                 ? ic->tme_m68k_ireg_int32(ea_pre_index)
                    539:                 : ((tme_int32_t) ic->tme_m68k_ireg_int16(ea_pre_index << 1)))
                    540:                << ea_index_scale)
                    541:             + ea_bd
                    542:             + (ea_reg == TME_M68K_IREG_PC
                    543:                /* XXX simulates preincremented pc: */
                    544:                ? first_ea_extword_offset
                    545:                : 0));
                    546:          
                    547:          /* if this is a memory indirect, read the indirect EA.
                    548:             don't disturb the EA in the IC state if we're restarting,
                    549:             for two reasons:
                    550: 
                    551:             first, the value in the IC state may belong to some later
                    552:             part of the instruction handling, in which case we must
                    553:             (continue to) preserve it, and
                    554:             
                    555:             second, if the EA in the IC state *is* from this part of
                    556:             the instruction handling, it's correct, while our EA may
                    557:             *not* be correct, since it was generated from IC state
                    558:             that may have changed since the instruction originally
                    559:             started (i.e., address register changes by the user or by
                    560:             our own postincrement/predecrement, or function code
                    561:             register changes by the user): */
                    562:          if (ea_post_index != TME_M68K_IREG_UNDEF) {
                    563:            if (!_TME_M68K_SEQUENCE_RESTARTING) {
                    564:              ic->_tme_m68k_ea_address = ea_address;
                    565:              ic->_tme_m68k_ea_function_code = eai_function_code;
                    566:            }
                    567:            _TME_M68K_INSN_FETCH_SAVE;
                    568:            tme_m68k_read_mem32(ic, TME_M68K_IREG_MEMY32);
                    569:            ea_address =
                    570:              (ic->tme_m68k_ireg_memy32
                    571:               + ((ea_index_long
                    572:                   ? ic->tme_m68k_ireg_int32(ea_post_index)
                    573:                   : ((tme_int32_t) ic->tme_m68k_ireg_int16(ea_post_index << 1)))
                    574:                  << ea_index_scale)
                    575:               + ea_od);
                    576:          }
                    577:          else {
                    578:            ea_function_code = eai_function_code;
                    579:          }
                    580:          
                    581: #else  /* !TME_M68K_M68020 && !TME_M68K_M68030 */
                    582:          /* XXX - illegal instruction */
                    583:          abort();
                    584: #endif /* !TME_M68K_M68020 && !TME_M68K_M68030 */
                    585:        }
                    586:        
                    587:        /* otherwise, this is a brief extension word: */
                    588:        else {
                    589:          ea_address = 
                    590:            (ic->tme_m68k_ireg_uint32(ea_reg)
                    591:             + ((tme_int32_t) ((tme_int8_t) (extword & 0xff)))
                    592:             + ((ea_index_long
                    593:                 ? ic->tme_m68k_ireg_int32(ea_pre_index)
                    594:                 : ((tme_int32_t) ic->tme_m68k_ireg_int16(ea_pre_index << 1)))
                    595:                << ea_index_scale)
                    596:             + (ea_reg == TME_M68K_IREG_PC
                    597:                /* XXX simulates preincremented pc: */
                    598:                ? first_ea_extword_offset
                    599:                : 0));
                    600:          ea_function_code = eai_function_code;
                    601:        }
                    602:        break;
                    603: 
                    604:       default: assert(FALSE);
                    605:       }
                    606: 
                    607:       /* we have calculated the effective address.  we don't store it
                    608:         if we're restarting, because it may have been calculated
                    609:         using user-visible registers (address registers and even
                    610:         function code registers!) that the user may have changed (or,
                    611:         in the case of pre/postdecrement EAs, that *we* may have
                    612:         changed) between the bus fault and the instruction restart.
                    613:         when we restart an instruction we *always* want to use the
                    614:         same effective address as before: */
                    615:       if (!_TME_M68K_SEQUENCE_RESTARTING) {
                    616:        ic->_tme_m68k_ea_address = ea_address;
                    617:        ic->_tme_m68k_ea_function_code = eai_function_code;
                    618:       }
                    619:       
                    620:       /* XXX XXX XXX - if we detect a store to program space, that's an illegal: */
                    621:       /* XXX but maybe not for moves? */
                    622:       if (ea_function_code == function_code_program
                    623:          && (ea_cycles & TME_BUS_CYCLE_WRITE)) {
                    624:        abort();
                    625:       }
                    626: 
                    627:       /* if we're loading this operand: */
                    628:       if (ea_cycles & TME_BUS_CYCLE_READ) {
                    629:        _TME_M68K_INSN_FETCH_SAVE;
                    630:        (*_tme_m68k_read_memx[ea_size])(ic);
                    631:       }
                    632: 
                    633:       /* stop unless this is a memory-to-memory move: */
                    634:       if (specop_type != TME_M68K_SPECOP_MOVEMEMTOMEM)
                    635:        break;
                    636: 
                    637:       /* reload for the other memory EA at the same size: */
                    638:       ea_mode = TME_FIELD_EXTRACTU(opw, 6, 3);
                    639:       ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(opw, 9, 3);
                    640:       ea_cycles = TME_BUS_CYCLE_WRITE;
                    641:       ea_function_code = function_code_data;
                    642:       specop_type = TME_M68K_SPECOP_UNDEF;
                    643:     }
                    644: 
                    645:     /* we've fetched all of the instruction words: */
                    646:     _TME_M68K_INSN_FETCH_SAVE;
                    647: 
                    648:     /* set the next PC: */
                    649: #ifdef _TME_M68K_EXECUTE_FAST
                    650:     ic->tme_m68k_ireg_pc_next = ic->tme_m68k_ireg_pc + (emulator_load - emulator_load_start);
                    651: #else  /* !_TME_M68K_EXECUTE_FAST */
                    652:     ic->tme_m68k_ireg_pc_next = linear_pc;
                    653: #endif /* !_TME_M68K_EXECUTE_FAST */
                    654: 
                    655:     /* if we're not restarting, or if this instruction function can
                    656:        fault, call the instruction function: */
                    657:     if (!_TME_M68K_SEQUENCE_RESTARTING
                    658:        || (ic->_tme_m68k_mode_flags & TME_M68K_EXECUTION_INST_CANFAULT)) {
                    659:       transfer_next_before = ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next;
                    660:       (*func)(ic, operand0, operand1);
                    661:       assert(!(ic->_tme_m68k_mode_flags & TME_M68K_EXECUTION_INST_CANFAULT)
                    662:             != (ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next
                    663:                 != transfer_next_before));
                    664:       ic->_tme_m68k_mode_flags &= ~TME_M68K_EXECUTION_INST_CANFAULT;
                    665:     }
                    666: 
                    667:     /* store up to one EA path: */
                    668:     if (ea_size != TME_M68K_SIZE_UNDEF
                    669:        && (ea_cycles & TME_BUS_CYCLE_WRITE)) {
                    670:       (*_tme_m68k_write_memx[ea_size])(ic);
                    671:     }
                    672: 
                    673:     /* an instruction has ended: */
                    674:     tme_m68k_verify_end(ic, func);
                    675: 
                    676:     /* update the PC: */
                    677:     ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
                    678:     TME_M68K_SEQUENCE_START;
                    679: 
                    680: #ifdef _TME_M68K_EXECUTE_FAST
                    681:     /* if we haven't finished the instruction burst yet, continue: */
1.1.1.2 ! root      682:     if (__tme_predict_true(ic->_tme_m68k_instruction_burst_remaining != 0)) {
1.1       root      683:       continue;
                    684:     }
                    685: #endif /* _TME_M68K_EXECUTE_FAST */
                    686: 
                    687:     /* try to acquire the external mutex and check for external
                    688:        resets, halts, or interrupts, and process them along
                    689:        with any internal exceptions: */
                    690:     rc = tme_mutex_trylock(&ic->tme_m68k_external_mutex);
                    691:     if (TME_THREADS_ERRNO(rc) == TME_OK) {
                    692:       tme_m68k_external_check(ic, 
                    693: #ifdef _TME_M68K_EXECUTE_FAST
                    694:                              0
                    695: #else  /* !_TME_M68K_EXECUTE_FAST */
                    696:                              exceptions
                    697: #endif /* !_TME_M68K_EXECUTE_FAST */
                    698:                              );
                    699: 
                    700:       /* unlock the external mutex: */
                    701:       tme_mutex_unlock(&ic->tme_m68k_external_mutex);
                    702:     }
                    703: 
                    704: #ifndef _TME_M68K_EXECUTE_FAST
                    705: 
                    706:     /* otherwise, if we have internal exceptions, process them: */
                    707:     else if (exceptions) {
                    708:       tme_m68k_exception(ic, exceptions);
                    709:     }
                    710: 
                    711:     /* if we can go fast now, go fast: */
                    712:     if (!tme_m68k_go_slow(ic)) {
                    713:       tme_m68k_redispatch(ic);
                    714:     }
                    715: 
1.1.1.2 ! root      716:     /* otherwise, unless we've used up our burst, continue: */
        !           717:     if (ic->_tme_m68k_instruction_burst_remaining != 0) {
        !           718:       continue;
        !           719:     }
        !           720: 
        !           721: #endif /* !_TME_M68K_EXECUTE_FAST */
        !           722: 
        !           723:     /* start a new burst: */
        !           724:     ic->_tme_m68k_instruction_burst_remaining
        !           725:       = ic->_tme_m68k_instruction_burst;
1.1       root      726: 
                    727:     /* if this is a cooperative threading system, yield: */
                    728: #ifdef TME_THREADS_COOPERATIVE
                    729:     tme_thread_yield();
                    730: #endif /* TME_THREADS_COOPERATIVE */
                    731: 
                    732:   }
                    733:   /* NOTREACHED */
                    734: 
                    735: #ifdef _TME_M68K_EXECUTE_FAST
                    736: 
                    737:   /* if we get here, we "faulted" trying to fetch an instruction word
                    738:      from host memory.  it's possibly not a "real" fault, since this
                    739:      instruction may simply cross a page boundary, but since the fast
                    740:      executor can't restart instructions we have to treat this like a
                    741:      group 0 fault: */
                    742:  _tme_m68k_fast_fetch_failed:
                    743: 
                    744:   /* mimic a group 0 exception: */
                    745:   _TME_M68K_INSN_FETCH_SAVE;
                    746:   ic->_tme_m68k_group0_flags = TME_M68K_BUS_CYCLE_FETCH | TME_M68K_BUS_CYCLE_READ;
                    747:   ic->_tme_m68k_group0_function_code = function_code_program;
                    748:   ic->_tme_m68k_group0_address = ic->tme_m68k_ireg_pc + (emulator_load - emulator_load_start);
                    749:   ic->_tme_m68k_group0_sequence = ic->_tme_m68k_sequence;
                    750:   ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted_after = 0;
                    751:   ic->_tme_m68k_group0_buffer_read_size = 0;
                    752:   ic->_tme_m68k_group0_buffer_read_softrr = 0;
                    753:   tme_m68k_group0_hook_fast(ic);
                    754:   ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted =
                    755:     ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_next;
                    756: 
                    757:   /* mimic the rte: */
                    758:   ic->_tme_m68k_sequence = ic->_tme_m68k_group0_sequence;
                    759:   ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next = 1;
                    760:   TME_M68K_SEQUENCE_RESTART;
                    761: 
                    762:   tme_m68k_redispatch(ic);
                    763:   /* NOTREACHED */
                    764: #endif /* _TME_M68K_EXECUTE_FAST */
                    765: }

unix.superglobalmegacorp.com

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