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

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

unix.superglobalmegacorp.com

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