Annotation of tme/ic/m68k/m68k-execute.c, revision 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.