|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.