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