|
|
1.1.1.4 ! root 1: /* $Id: m68k-execute.c,v 1.23 2007/02/21 01:28:59 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: 1.1.1.4 ! root 36: _TME_RCSID("$Id: m68k-execute.c,v 1.23 2007/02/21 01:28:59 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; 1.1.1.4 ! root 49: const tme_shared tme_uint8_t *fetch_fast_next; 1.1 root 50: #define _TME_M68K_INSN_FETCH_SAVE \ 51: do { \ 1.1.1.4 ! root 52: ic->_tme_m68k_insn_fetch_fast_next = fetch_fast_next; \ 1.1 root 53: } while (/* CONSTCOND */ 0) 54: #define _TME_M68K_SEQUENCE_RESTARTING (FALSE) 55: #else /* !_TME_M68K_EXECUTE_FAST */ 56: unsigned int exceptions; 57: tme_uint32_t linear_pc; 58: #define _TME_M68K_INSN_FETCH_SAVE \ 59: do { \ 60: } while (/* CONSTCOND */ 0) 61: #define _TME_M68K_SEQUENCE_RESTARTING TME_M68K_SEQUENCE_RESTARTING 62: #endif /* !_TME_M68K_EXECUTE_FAST */ 63: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030) 64: unsigned int eai_function_code; 65: int ea_post_index; 66: unsigned int ea_i_is; 1.1.1.3 root 67: tme_uint32_t ea_od; 68: unsigned int src_specifier; 1.1 root 69: #else /* !TME_M68K_M68020 && !TME_M68K_M68030 */ 70: #define eai_function_code ea_function_code 71: #endif /* !TME_M68K_M68020 && !TME_M68K_M68030 */ 72: unsigned int function_code_program; 73: unsigned int function_code_data; 74: tme_uint16_t opw, extword; 75: void (*func) _TME_P((struct tme_m68k *, void *, void *)); 1.1.1.3 root 76: tme_uint32_t params; 77: int ea_size; 1.1 root 78: int ea_reg, ea_pre_index; 79: unsigned int ea_index_long, ea_index_scale; 80: tme_uint32_t ea_address; 81: unsigned int ea_function_code; 1.1.1.3 root 82: tme_int32_t ea_bd; 1.1 root 83: tme_uint32_t imm32; 84: tme_uint16_t transfer_next_before; 85: int rc; 86: 1.1.1.3 root 87: /* silence gcc -Wuninitialized: */ 88: ea_size = 0; 89: 1.1 root 90: /* get the function codes. if the privilege ever changes as a 91: result of any instruction, we must redispatch: */ 92: if (TME_M68K_PRIV(ic)) { 93: function_code_program = TME_M68K_FC_SP; 94: function_code_data = TME_M68K_FC_SD; 95: } 96: else { 97: function_code_program = TME_M68K_FC_UP; 98: function_code_data = TME_M68K_FC_UD; 99: } 100: 1.1.1.2 root 101: /* if we have used up our burst: */ 102: if (ic->_tme_m68k_instruction_burst_remaining == 0) { 103: 104: /* start a new burst: */ 105: ic->_tme_m68k_instruction_burst_remaining 106: = ic->_tme_m68k_instruction_burst; 107: 108: /* if this is a cooperative threading system, yield: */ 1.1.1.4 ! root 109: #if TME_THREADS_COOPERATIVE 1.1.1.2 root 110: tme_thread_yield(); 111: #endif /* TME_THREADS_COOPERATIVE */ 112: } 113: 1.1 root 114: #ifdef _TME_M68K_EXECUTE_FAST 115: 116: /* get our instruction TLB entry and reload it: */ 1.1.1.4 ! root 117: tlb = tme_memory_atomic_pointer_read(struct tme_m68k_tlb *, ic->_tme_m68k_itlb, &ic->_tme_m68k_tlbs_rwlock); ! 118: tme_m68k_tlb_busy(tlb); 1.1 root 119: if (!TME_M68K_TLB_OK_FAST_READ(tlb, function_code_program, ic->tme_m68k_ireg_pc, ic->tme_m68k_ireg_pc)) { 120: tme_m68k_tlb_fill(ic, tlb, 121: function_code_program, 122: ic->tme_m68k_ireg_pc, 123: TME_BUS_CYCLE_READ); 124: } 125: 126: /* if we have to go slow, run the slow executor: */ 127: if (TME_M68K_SEQUENCE_RESTARTING 128: || tme_m68k_go_slow(ic)) { 1.1.1.4 ! root 129: tme_m68k_tlb_unbusy(tlb); ! 130: _TME_M68K_EXECUTE_SLOW(ic); ! 131: return; 1.1 root 132: } 133: 134: /* set up to do fast reads from the instruction TLB entry: */ 1.1.1.4 ! root 135: ic->_tme_m68k_insn_fetch_fast_last = tlb->tme_m68k_tlb_emulator_off_read + tlb->tme_m68k_tlb_linear_last - (sizeof(tme_uint32_t) - 1); ! 136: ic->_tme_m68k_insn_fetch_fast_itlb = tlb; 1.1 root 137: ic->_tme_m68k_group0_hook = tme_m68k_group0_hook_fast; 138: #else /* !_TME_M68K_EXECUTE_FAST */ 139: 140: /* set up to do slow reads from the instruction TLB entry: */ 141: ic->_tme_m68k_group0_hook = NULL; 142: #endif /* !_TME_M68K_EXECUTE_FAST */ 143: 144: /* the execution loop: */ 145: for (;;) { 146: 147: /* reset for this instruction: */ 148: #ifdef _TME_M68K_EXECUTE_FAST 1.1.1.4 ! root 149: fetch_fast_next = tlb->tme_m68k_tlb_emulator_off_read + ic->tme_m68k_ireg_pc; ! 150: ic->_tme_m68k_insn_fetch_fast_start = fetch_fast_next; ! 151: assert (ic->_tme_m68k_insn_fetch_fast_itlb == tlb ! 152: && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF ! 153: && (tlb->tme_m68k_tlb_function_codes_mask & TME_BIT(function_code_program)) != 0 ! 154: && (fetch_fast_next > ic->_tme_m68k_insn_fetch_fast_last ! 155: || ((tme_bus_tlb_is_valid(&tlb->tme_m68k_tlb_bus_tlb) ! 156: || !TME_THREADS_COOPERATIVE) ! 157: && ic->tme_m68k_ireg_pc >= tlb->tme_m68k_tlb_linear_first ! 158: && (ic->tme_m68k_ireg_pc + sizeof(tme_uint16_t) - 1) <= tlb->tme_m68k_tlb_linear_last))); ! 159: tme_m68k_verify_begin(ic, fetch_fast_next); 1.1 root 160: #else /* !_TME_M68K_EXECUTE_FAST */ 161: linear_pc = ic->tme_m68k_ireg_pc; 1.1.1.4 ! root 162: ic->_tme_m68k_insn_fetch_slow_next = 0; ! 163: if (!_TME_M68K_SEQUENCE_RESTARTING) { ! 164: ic->_tme_m68k_insn_fetch_slow_count_fast = 0; ! 165: ic->_tme_m68k_insn_fetch_slow_count_total = 0; ! 166: } 1.1 root 167: exceptions = 0; 1.1.1.3 root 168: if (__tme_predict_false((ic->tme_m68k_ireg_sr & ic->_tme_m68k_sr_mask_t) == TME_M68K_FLAG_T1)) { 169: ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc; 170: exceptions |= TME_M68K_EXCEPTION_TRACE; 1.1 root 171: } 172: tme_m68k_verify_begin(ic, NULL); 173: #endif /* _TME_M68K_EXECUTE_FAST */ 174: #ifdef _TME_M68K_VERIFY 175: if (ic->tme_m68k_ireg_pc == 0x6000) { 176: tme_m68k_verify_hook(); 177: } 178: #endif 1.1.1.3 root 179: #ifdef _TME_M68K_STATS 180: ic->tme_m68k_stats.tme_m68k_stats_insns_total++; 181: #ifndef _TME_M68K_EXECUTE_FAST 182: ic->tme_m68k_stats.tme_m68k_stats_insns_slow++; 183: #endif /* !_TME_M68K_EXECUTE_FAST */ 184: #endif /* _TME_M68K_STATS */ 1.1.1.2 root 185: ic->_tme_m68k_instruction_burst_remaining--; 1.1 root 186: 187: /* fetch and decode the first word of this instruction: */ 1.1.1.4 ! root 188: _TME_M68K_EXECUTE_FETCH_U16_FIXED(opw, _tme_m68k_insn_opcode); 1.1 root 189: ic->_tme_m68k_insn_opcode = opw; 1.1.1.3 root 190: params = _TME_M68K_EXECUTE_OPMAP[opw]; 191: func = tme_m68k_opcode_insns[TME_M68K_OPCODE_INSN_WHICH(params)]; 192: 193: /* now that we no longer need the insn index part of the params, 194: replace it with the least significant bits of the opcode, which 195: contain any EA mode and reg fields: */ 196: TME_FIELD_MASK_DEPOSITU(params, 197: TME_M68K_OPCODE_INSN_MASK, 198: (opw & (TME_M68K_OPCODE_INSN_MASK / TME_M68K_OPCODE_INSN(1)))); 1.1 root 199: 1.1.1.3 root 200: /* if this is a special opcode: */ 201: if (__tme_predict_false((params & TME_M68K_OPCODE_SPECOP) != 0)) { 202: 1.1 root 203: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030) 1.1.1.3 root 204: 205: /* a general floating-point instruction: */ 206: if (__tme_predict_false((opw & 0xffc0) == 0xf200)) { 207: 208: /* if there is no FPU present, or if it isn't enabled: */ 209: if (__tme_predict_false(!ic->tme_m68k_fpu_enabled)) { 210: 211: /* mark this instruction as illegal and use an FPgen command 212: word of zero: */ 213: func = tme_m68k_illegal; 214: extword = 0; 1.1 root 215: } 1.1.1.3 root 216: 217: /* otherwise, there is an FPU present and it is enabled: */ 218: else { 219: 220: /* fetch the FPgen command word: */ 1.1.1.4 ! root 221: _TME_M68K_EXECUTE_FETCH_U16_FIXED(ic->_tme_m68k_insn_specop, _tme_m68k_insn_specop); 1.1.1.3 root 222: 223: /* temporarily store the FPgen command word in extword: */ 224: extword = ic->_tme_m68k_insn_specop; 225: } 226: 227: /* the goal here is not to decide whether or not an FPgen 228: instruction is legal, although some illegal instructions 229: are caught. the goal is to only decide if this FPgen 230: instruction uses the EA field. 231: 232: we need to know this here because only the executer can 233: calculate all memory EAs (i.e., absolute addresses, 234: indirect addresses, PC-relative addresses, etc.) and fetch 235: immediates. 236: 237: in general, all other decisions about whether or not an 238: instruction is legal (including whether or not certain EAs 239: are legal, like data register direct or address register 240: direct) or how to dispatch it is done somewhere else. 241: 242: all legal FPgen instructions that use the EA field are 243: handled by one of the following ifs. all illegal FPgen 244: instructions, and all FPgen instructions that do not use 245: the EA field are handled by the final unconditional else 246: clause that cancels memory EA calculation and immediate 247: fetching. 248: 249: for those FPgen instructions that do use the EA field, they 250: either leave the EA cycles unchanged, as TME_M68K_OPCODE_EA_READ, to 251: indicate that they read the EA, or they change it to 252: TME_M68K_OPCODE_EA_WRITE to indicate that they write the EA. 253: additionally, they either flag any immediate operand as 254: illegal, fetch it themselves, or specify its size for the 255: normal immediate fetching code to use: */ 256: 257: /* m68k-iset.txt must assume that any EA is not written: */ 258: assert (!TME_M68K_OPCODE_HAS_EA(params) 259: || ((params 260: & (TME_M68K_OPCODE_EA_READ 261: | TME_M68K_OPCODE_EA_WRITE)) 262: == TME_M68K_OPCODE_EA_READ)); 263: 264: /* m68k-iset.txt must assume that any immediate is 32 bits: */ 265: assert (!TME_M68K_OPCODE_HAS_IMM(params) 266: || (params & (TME_M68K_OPCODE_IMM_16 | TME_M68K_OPCODE_IMM_32)) == TME_M68K_OPCODE_IMM_32); 267: 268: /* if this is an FMOVE or FMOVEM of floating-point control 269: registers (command word pattern 10dr rr00 0000 0000): */ 270: if ((extword & 0xc3ff) == 0x8000) { 271: 272: /* override the function: */ 273: func = tme_m68k_fmovemctl; 274: 275: /* if this is a register-to-memory operation: */ 276: if (extword & TME_BIT(13)) { 277: 278: /* any EA must be writable: */ 279: params |= TME_M68K_OPCODE_EA_WRITE; 280: } 281: 282: /* otherwise, this is a memory-to-register operation: */ 283: else { 284: 285: /* if this instruction has an immediate, and this 286: instruction is moving multiple control registers, this 287: is an illegal instruction: */ 288: /* NB the trick we use to see if multiple bits are set in 289: the rrr field - we subtract one from the base of the 290: rrr field (0x0400), binary-AND the result with extword, 291: and mask off all bits except the rrr field. this 292: result will be nonzero iff the rrr field has multiple 293: bits set: */ 294: if (__tme_predict_false(TME_M68K_OPCODE_HAS_IMM(params) 295: && ((extword & (extword - 0x0400)) & 0x1c00))) { 296: func = tme_m68k_illegal; 297: } 298: } 1.1 root 299: } 1.1.1.3 root 300: 301: /* if this is an FMOVEM 302: (command word pattern 11dm m000 rrrr rrrr): */ 303: else if ((extword & 0xc700) == 0xc000) { 304: 305: /* override the function: */ 306: func = tme_m68k_fmovem; 307: 308: /* if this instruction has an immediate, this is an 309: illegal instruction: */ 310: if (__tme_predict_false(TME_M68K_OPCODE_HAS_IMM(params))) { 311: func = tme_m68k_illegal; 312: } 313: 314: /* if this is a register-to-memory operation: */ 315: if (extword & TME_BIT(13)) { 316: 317: /* any EA must be writable: */ 318: params |= TME_M68K_OPCODE_EA_WRITE; 319: } 1.1 root 320: } 1.1.1.3 root 321: 322: /* if this is a register-to-memory FMOVE instruction 323: (command word pattern 011d ddss skkk kkkk): */ 324: else if ((extword & 0xe000) == 0x6000) { 325: 326: /* override the function: */ 327: func = tme_m68k_fmove_rm; 328: 329: /* any EA must be writable: */ 330: params |= TME_M68K_OPCODE_EA_WRITE; 331: } 332: 333: /* if this is a memory-to-register true FPgen instruction 334: (command word pattern 010s ssdd dooo oooo): */ 335: else if ((extword & 0xe000) == 0x4000 336: && (_tme_m6888x_fpgen_opmode_bitmap[TME_FIELD_EXTRACTU(extword, 0, 7) / 8] 337: & (1 << (TME_FIELD_EXTRACTU(extword, 0, 7) % 8))) 338: && TME_FIELD_EXTRACTU(extword, 10, 3) != TME_M6888X_TYPE_INVALID) { 339: 340: /* if this instruction has an immediate: */ 341: if (TME_M68K_OPCODE_HAS_IMM(params)) { 342: 343: /* if the source specifier is for a size that the normal 344: immediate fetching code can handle, let it handle it, 345: otherwise we have to fetch the immediate ourselves: */ 346: 347: /* m68k-iset.txt must have specified the EA operand to be 348: operand one: */ 349: assert((void *) TME_M68K_OPCODE_OP1_WHICH(ic, params) 350: == (void *) &ic->tme_m68k_ireg_uint32(TME_M68K_IREG_IMM32 + 0)); 351: 352: /* dispatch on the source specifier: */ 353: src_specifier = TME_FIELD_EXTRACTU(extword, 10, 3); 354: switch (src_specifier) { 355: 356: /* we can let the normal immediate fetching code fetch 357: word integers, long-word integers, and 358: single-precision reals: */ 359: default: 360: assert (func == tme_m68k_illegal); 361: /* FALLTHROUGH */ 362: case TME_M6888X_TYPE_WORD: 363: /* we can simply flip TME_M68K_OPCODE_IMM_16 and 364: TME_M68K_OPCODE_IMM_32 to select a 16-bit immediate; 365: we know that only TME_M68K_OPCODE_IMM_32 is set, 366: thanks to the assert we did at the beginning of the 367: fpgen specop handling: */ 368: params ^= (TME_M68K_OPCODE_IMM_16 | TME_M68K_OPCODE_IMM_32); 369: /* FALLTHROUGH */ 370: case TME_M6888X_TYPE_LONG: 371: case TME_M6888X_TYPE_SINGLE: 372: break; 373: case TME_M6888X_TYPE_EXTENDED80: 374: case TME_M6888X_TYPE_PACKEDDEC: 375: case TME_M6888X_TYPE_DOUBLE: 376: _TME_M68K_EXECUTE_FETCH_U32(imm32); 377: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_IMM32 + 0) = imm32; 378: _TME_M68K_EXECUTE_FETCH_U32(imm32); 379: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_IMM32 + 1) = imm32; 380: if (src_specifier != TME_M6888X_TYPE_DOUBLE) { 381: _TME_M68K_EXECUTE_FETCH_U32(imm32); 382: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_IMM32 + 2) = imm32; 383: } 384: /* we only need to clear TME_M68K_OPCODE_IMM_32 here to 385: cancel the later immediate fetching; we know that 386: only TME_M68K_OPCODE_IMM_32 is set, thanks to the 387: assert we did at the beginning of the fpgen specop 388: handling: */ 389: params &= ~TME_M68K_OPCODE_IMM_32; 390: break; 391: case TME_M6888X_TYPE_BYTE: 392: _TME_M68K_EXECUTE_FETCH_U16(imm32); 393: ic->tme_m68k_ireg_uint32(TME_M68K_IREG_IMM32 + 0) = TME_EXT_S8_U32((tme_int8_t) imm32); 394: /* we only need to clear TME_M68K_OPCODE_IMM_32 here to 395: cancel the later immediate fetching; we know that 396: only TME_M68K_OPCODE_IMM_32 is set, thanks to the 397: assert we did at the beginning of the fpgen specop 398: handling: */ 399: params &= ~TME_M68K_OPCODE_IMM_32; 400: break; 401: } 402: } 1.1 root 403: } 1.1.1.3 root 404: 405: /* otherwise, this FPgen instruction does not need any memory 406: EA or immediate. we'll decide later if this instruction is 407: actually legal: */ 1.1 root 408: else { 1.1.1.3 root 409: /* cancel immediate fetching and all EA work: */ 410: params &= ~(TME_M68K_OPCODE_IMM_32 411: | TME_M68K_OPCODE_IMM_16 412: | TME_M68K_OPCODE_EA_SIZE_MASK 413: | TME_M68K_OPCODE_EA_READ 414: | TME_M68K_OPCODE_EA_WRITE); 415: } 416: 417: /* if this instruction has already been marked as illegal, or 418: this EA must be writable, and this is a PC-relative or 419: immediate EA, this instruction is illegal: */ 420: if (__tme_predict_false(func == tme_m68k_illegal 421: || (params & TME_M68K_OPCODE_EA_WRITE 422: && (TME_M68K_OPCODE_HAS_IMM(params) 423: || (TME_M68K_OPCODE_EA_MODE_WHICH(params) == 7 424: && (TME_M68K_OPCODE_EA_REG_WHICH(params) & 6) == 2))))) { 425: func = tme_m68k_illegal; 426: /* cancel immediate fetching and all EA work: */ 427: params &= ~(TME_M68K_OPCODE_IMM_32 428: | TME_M68K_OPCODE_IMM_16 429: | TME_M68K_OPCODE_EA_SIZE_MASK 430: | TME_M68K_OPCODE_EA_READ 431: | TME_M68K_OPCODE_EA_WRITE); 432: } 433: 434: /* otherwise, if this instruction has a memory EA: */ 435: else if (params & TME_M68K_OPCODE_EA_READ) { 436: 437: /* override any m68k-iset.txt guess about the operand 438: size, and cancel all memory cycles. the instruction 439: itself will do the actual operand reading and any address 440: register postincrement or predecrement: */ 441: params = 442: ((params 443: & ~(TME_M68K_OPCODE_EA_READ 444: | TME_M68K_OPCODE_EA_WRITE 445: | TME_M68K_OPCODE_EA_SIZE_MASK)) 446: | TME_M68K_OPCODE_EA_UNSIZED); 1.1 root 447: } 448: 1.1.1.3 root 449: /* otherwise, this instruction does not have a memory EA: */ 450: else { 1.1 root 451: 1.1.1.3 root 452: /* cancel all EA work: */ 453: params &= ~(TME_M68K_OPCODE_EA_SIZE_MASK 454: | TME_M68K_OPCODE_EA_READ 455: | TME_M68K_OPCODE_EA_WRITE); 456: } 457: } 458: else 459: #endif /* TME_M68K_M68020 || TME_M68K_M68030 */ 1.1 root 460: 1.1.1.3 root 461: /* if this is not a memory-to-memory move instruction: */ 462: if ((params & TME_M68K_OPCODE_EA_Y) == 0) { 1.1 root 463: 1.1.1.3 root 464: /* many instructions have a single special extension word: */ 1.1.1.4 ! root 465: _TME_M68K_EXECUTE_FETCH_U16_FIXED(ic->_tme_m68k_insn_specop, _tme_m68k_insn_specop); 1.1.1.3 root 466: } 1.1 root 467: } 1.1.1.3 root 468: 1.1 root 469: /* get any immediate operand: */ 1.1.1.3 root 470: if (__tme_predict_false(TME_M68K_OPCODE_HAS_IMM(params))) { 471: if (params & TME_M68K_OPCODE_IMM_16) { 1.1 root 472: _TME_M68K_EXECUTE_FETCH_S16(imm32); 473: } 1.1.1.3 root 474: else { 475: _TME_M68K_EXECUTE_FETCH_U32(imm32); 476: } 477: ic->tme_m68k_ireg_imm32 = imm32; 478: } 1.1 root 479: 480: /* loop over up to two effective addresses calculations. this 481: initializes for the normal, single effective address: */ 1.1.1.3 root 482: while (TME_M68K_OPCODE_HAS_EA(params)) { 483: 484: /* if this EA is described by the alternate EA mode and reg 485: fields, copy them into the EA mode and reg fields in 486: params: */ 487: if (__tme_predict_false((params 488: & (TME_M68K_OPCODE_EA_Y | TME_M68K_OPCODE_SPECOP)) 489: == TME_M68K_OPCODE_EA_Y)) { 490: 491: /* reload to write the other memory EA: */ 492: params 493: = ((params 494: & ~(TME_M68K_OPCODE_EA_MODE_MASK 495: | TME_M68K_OPCODE_EA_REG_MASK 496: | TME_M68K_OPCODE_EA_READ 497: | TME_M68K_OPCODE_EA_Y)) 498: | TME_M68K_OPCODE_EA_MODE(TME_FIELD_EXTRACTU(opw, 6, 3)) 499: | TME_M68K_OPCODE_EA_REG(TME_FIELD_EXTRACTU(opw, 9, 3)) 500: | TME_M68K_OPCODE_EA_WRITE); 501: } 502: 503: /* get the reg, size, and function code of this EA: */ 504: ea_reg = TME_M68K_IREG_A0 + TME_M68K_OPCODE_EA_REG_WHICH(params); 505: ea_size = TME_M68K_OPCODE_EA_SIZE_WHICH(params); 506: ea_function_code = function_code_data; 1.1 root 507: 508: /* this EA must have either no size, or be exactly one, two, or 509: four bytes: */ 510: assert(ea_size == TME_M68K_SIZE_UNSIZED 511: || ea_size == TME_M68K_SIZE_8 512: || ea_size == TME_M68K_SIZE_16 513: || ea_size == TME_M68K_SIZE_32); 514: 515: /* for the effective address predecrement and postincrement 516: modes, we require that these size macros correspond exactly 517: to the number of bytes, that the %a7 register number be 15, 518: and that the ea reg not be greater than %a7: */ 519: #if TME_M68K_SIZE_UNSIZED != 0 520: #error "TME_M68K_SIZE_UNSIZED must be 0" 521: #endif 522: #if TME_M68K_SIZE_8 != 1 523: #error "TME_M68K_SIZE_8 must be 1" 524: #endif 525: #if TME_M68K_SIZE_16 != 2 526: #error "TME_M68K_SIZE_16 must be 2" 527: #endif 528: #if TME_M68K_SIZE_32 != 4 529: #error "TME_M68K_SIZE_32 must be 4" 530: #endif 531: #if TME_M68K_IREG_A7 != 15 532: #error "TME_M68K_IREG_A7 must be 15" 533: #endif 534: assert(ea_reg <= TME_M68K_IREG_A7); 535: #define TME_M68K_AREG_INCREMENT(areg, size) \ 536: (((((areg) + 1) / (TME_M68K_IREG_A7 + 1)) & (size)) + (size)) 537: 538: /* initialize ea_address to silence -Wuninitialized: */ 539: ea_address = 0; 540: 541: /* set the EA inner function code: */ 542: eai_function_code = ea_function_code; 543: 544: /* dispatch on the mode: */ 1.1.1.3 root 545: switch (TME_M68K_OPCODE_EA_MODE_WHICH(params)) { 1.1 root 546: 547: /* address register indirect: */ 548: case 2: 549: ea_address = ic->tme_m68k_ireg_uint32(ea_reg); 550: break; 551: 552: /* address register indirect postincrement: */ 553: case 3: 554: /* if we are not restarting, set the effective address: */ 555: if (!_TME_M68K_SEQUENCE_RESTARTING) { 556: ea_address = ic->tme_m68k_ireg_uint32(ea_reg); 557: ic->tme_m68k_ireg_uint32(ea_reg) += TME_M68K_AREG_INCREMENT(ea_reg, ea_size); 558: } 559: break; 560: 561: /* address register indirect predecrement: */ 562: case 4: 563: /* if we are not restarting, set the effective address: */ 564: if (!_TME_M68K_SEQUENCE_RESTARTING) { 565: ic->tme_m68k_ireg_uint32(ea_reg) -= TME_M68K_AREG_INCREMENT(ea_reg, ea_size); 566: ea_address = ic->tme_m68k_ireg_uint32(ea_reg); 567: } 568: break; 569: 570: /* address register indirect with 16-bit displacement: */ 571: case 5: 572: _TME_M68K_EXECUTE_FETCH_S16(ea_bd); 573: ea_address = ic->tme_m68k_ireg_uint32(ea_reg) + ea_bd; 574: break; 575: 576: /* miscellaneous modes: */ 577: case 7: 578: 579: /* absolute short addressing: */ 580: if (ea_reg == TME_M68K_IREG_A0) { 581: _TME_M68K_EXECUTE_FETCH_S16(ea_address); 582: break; 583: } 584: 585: /* absolute long addressing: */ 586: if (ea_reg == TME_M68K_IREG_A1) { 587: _TME_M68K_EXECUTE_FETCH_S32(ea_address); 588: break; 589: } 590: 1.1.1.4 ! root 591: /* the remaining modes use the PC of the first extension word ! 592: as a base register: */ ! 593: #ifdef _TME_M68K_EXECUTE_FAST ! 594: ic->tme_m68k_ireg_pc_next = ic->tme_m68k_ireg_pc + (fetch_fast_next - ic->_tme_m68k_insn_fetch_fast_start); ! 595: #else /* !_TME_M68K_EXECUTE_FAST */ ! 596: ic->tme_m68k_ireg_pc_next = linear_pc; ! 597: #endif /* !_TME_M68K_EXECUTE_FAST */ ! 598: 1.1 root 599: /* program counter indirect with 16-bit displacement: */ 600: if (ea_reg == TME_M68K_IREG_A2) { 601: _TME_M68K_EXECUTE_FETCH_S16(ea_bd); 1.1.1.4 ! root 602: ea_address = ic->tme_m68k_ireg_pc_next + ea_bd; 1.1 root 603: ea_function_code = function_code_program; 604: break; 605: } 606: 1.1.1.4 ! root 607: /* everything else is just like mode 6 except with the PC of ! 608: the first extension word as the base register: */ 1.1 root 609: assert (ea_reg == TME_M68K_IREG_A3); 1.1.1.4 ! root 610: ea_reg = TME_M68K_IREG_PC_NEXT; 1.1 root 611: eai_function_code = function_code_program; 612: /* FALLTHROUGH */ 613: 614: /* various indexed modes: */ 615: case 6: 616: 617: /* fetch the extension word and take it apart. the 68000 and 618: 68010 ignore the scale field in the extension word and always 619: behave as if it is zero: */ 620: _TME_M68K_EXECUTE_FETCH_U16(extword); 621: ea_pre_index = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(extword, 12, 4); 622: ea_index_long = (extword & TME_BIT(11)); 623: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030) 624: ea_index_scale = TME_FIELD_EXTRACTU(extword, 9, 2); 625: #else /* !TME_M68K_M68020 && !TME_M68K_M68030 */ 626: ea_index_scale = 0; 627: #endif /* !TME_M68K_M68020 && !TME_M68K_M68030 */ 628: 629: /* if this is a full extension word: */ 1.1.1.3 root 630: if (__tme_predict_false(extword & TME_BIT(8))) { 1.1 root 631: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030) 632: 633: ea_i_is = TME_FIELD_EXTRACTU(extword, 0, 3); 634: 635: /* optionally suppress the base register: */ 636: if (extword & TME_BIT(7)) { 1.1.1.3 root 637: ea_reg = TME_M68K_IREG_ZERO; 1.1 root 638: } 639: 640: /* fetch any base displacement: */ 1.1.1.3 root 641: ea_bd = 0; 1.1 root 642: switch (TME_FIELD_EXTRACTU(extword, 4, 2)) { 643: case 0: abort(); 1.1.1.3 root 644: case 1: break; 1.1 root 645: case 2: _TME_M68K_EXECUTE_FETCH_S16(ea_bd); break; 646: case 3: _TME_M68K_EXECUTE_FETCH_S32(ea_bd); break; 647: } 648: 649: /* optionally suppress the index register. this is also 650: where we check for combined IS-I/IS fields greater than 651: or equal to 0xc, which are reserved: */ 652: if (extword & TME_BIT(6)) { 1.1.1.3 root 653: ea_pre_index = TME_M68K_IREG_ZERO; 1.1 root 654: if (ea_i_is >= 0x4) { 655: abort(); 656: } 657: } 658: 659: /* fetch any outer displacement: */ 1.1.1.3 root 660: ea_od = 0; 1.1 root 661: switch (ea_i_is & 3) { 1.1.1.3 root 662: case 0: case 1: break; 1.1 root 663: case 2: _TME_M68K_EXECUTE_FETCH_S16(ea_od); break; 664: case 3: _TME_M68K_EXECUTE_FETCH_S32(ea_od); break; 665: } 666: 667: /* dispatch on the I/IS fields: */ 1.1.1.3 root 668: ea_post_index = TME_M68K_IREG_ZERO; 1.1 root 669: switch (ea_i_is) { 670: 671: /* no memory indirect action: */ 672: case 0x0: 673: ea_post_index = TME_M68K_IREG_UNDEF; 674: break; 675: 676: /* indirect preindexed with null outer displacement: */ 677: /* indirect preindexed with word outer displacement: */ 678: /* indirect preindexed with long outer displacement: */ 679: case 0x1: case 0x2: case 0x3: 680: break; 681: 682: /* reserved: */ 683: case 0x4: default: abort(); 684: 685: /* indirect postindexed with null outer displacement: */ 686: /* indirect postindexed with word outer displacement: */ 687: /* indirect postindexed with long outer displacement: */ 688: case 0x5: case 0x6: case 0x7: 689: ea_post_index = ea_pre_index; 1.1.1.3 root 690: ea_pre_index = TME_M68K_IREG_ZERO; 1.1 root 691: break; 692: } 693: 694: /* preindex and base-displace the original address register 695: to arrive at the indirect EA: */ 696: ea_address = 697: (ic->tme_m68k_ireg_uint32(ea_reg) 698: + ((ea_index_long 699: ? ic->tme_m68k_ireg_int32(ea_pre_index) 700: : ((tme_int32_t) ic->tme_m68k_ireg_int16(ea_pre_index << 1))) 701: << ea_index_scale) 1.1.1.4 ! root 702: + ea_bd); 1.1 root 703: 704: /* if this is a memory indirect, read the indirect EA. 705: don't disturb the EA in the IC state if we're restarting, 706: for two reasons: 707: 708: first, the value in the IC state may belong to some later 709: part of the instruction handling, in which case we must 710: (continue to) preserve it, and 711: 712: second, if the EA in the IC state *is* from this part of 713: the instruction handling, it's correct, while our EA may 714: *not* be correct, since it was generated from IC state 715: that may have changed since the instruction originally 716: started (i.e., address register changes by the user or by 717: our own postincrement/predecrement, or function code 718: register changes by the user): */ 719: if (ea_post_index != TME_M68K_IREG_UNDEF) { 720: if (!_TME_M68K_SEQUENCE_RESTARTING) { 721: ic->_tme_m68k_ea_address = ea_address; 722: ic->_tme_m68k_ea_function_code = eai_function_code; 723: } 724: _TME_M68K_INSN_FETCH_SAVE; 725: tme_m68k_read_mem32(ic, TME_M68K_IREG_MEMY32); 726: ea_address = 727: (ic->tme_m68k_ireg_memy32 728: + ((ea_index_long 729: ? ic->tme_m68k_ireg_int32(ea_post_index) 730: : ((tme_int32_t) ic->tme_m68k_ireg_int16(ea_post_index << 1))) 731: << ea_index_scale) 732: + ea_od); 733: } 734: else { 735: ea_function_code = eai_function_code; 736: } 737: 738: #else /* !TME_M68K_M68020 && !TME_M68K_M68030 */ 739: /* XXX - illegal instruction */ 740: abort(); 741: #endif /* !TME_M68K_M68020 && !TME_M68K_M68030 */ 742: } 743: 744: /* otherwise, this is a brief extension word: */ 745: else { 746: ea_address = 747: (ic->tme_m68k_ireg_uint32(ea_reg) 748: + ((tme_int32_t) ((tme_int8_t) (extword & 0xff))) 749: + ((ea_index_long 750: ? ic->tme_m68k_ireg_int32(ea_pre_index) 751: : ((tme_int32_t) ic->tme_m68k_ireg_int16(ea_pre_index << 1))) 1.1.1.4 ! root 752: << ea_index_scale)); 1.1 root 753: ea_function_code = eai_function_code; 754: } 755: break; 756: 757: default: assert(FALSE); 758: } 759: 760: /* we have calculated the effective address. we don't store it 761: if we're restarting, because it may have been calculated 762: using user-visible registers (address registers and even 763: function code registers!) that the user may have changed (or, 764: in the case of pre/postdecrement EAs, that *we* may have 765: changed) between the bus fault and the instruction restart. 766: when we restart an instruction we *always* want to use the 767: same effective address as before: */ 768: if (!_TME_M68K_SEQUENCE_RESTARTING) { 769: ic->_tme_m68k_ea_address = ea_address; 770: ic->_tme_m68k_ea_function_code = eai_function_code; 771: } 772: 773: /* XXX XXX XXX - if we detect a store to program space, that's an illegal: */ 774: /* XXX but maybe not for moves? */ 1.1.1.3 root 775: if (__tme_predict_false(ea_function_code == function_code_program 776: && (params & TME_M68K_OPCODE_EA_WRITE) != 0)) { 1.1 root 777: abort(); 778: } 779: 780: /* if we're loading this operand: */ 1.1.1.3 root 781: if (params & TME_M68K_OPCODE_EA_READ) { 1.1 root 782: _TME_M68K_INSN_FETCH_SAVE; 783: (*_tme_m68k_read_memx[ea_size])(ic); 784: } 785: 786: /* stop unless this is a memory-to-memory move: */ 1.1.1.3 root 787: if (__tme_predict_true(!(params & TME_M68K_OPCODE_EA_Y))) 1.1 root 788: break; 789: 1.1.1.3 root 790: /* loop to reload for the other memory EA at the same size: */ 791: params &= ~TME_M68K_OPCODE_SPECOP; 1.1 root 792: } 793: 794: /* we've fetched all of the instruction words: */ 795: _TME_M68K_INSN_FETCH_SAVE; 796: 797: /* set the next PC: */ 798: #ifdef _TME_M68K_EXECUTE_FAST 1.1.1.4 ! root 799: ic->tme_m68k_ireg_pc_next = ic->tme_m68k_ireg_pc + (fetch_fast_next - ic->_tme_m68k_insn_fetch_fast_start); 1.1 root 800: #else /* !_TME_M68K_EXECUTE_FAST */ 801: ic->tme_m68k_ireg_pc_next = linear_pc; 802: #endif /* !_TME_M68K_EXECUTE_FAST */ 803: 804: /* if we're not restarting, or if this instruction function can 805: fault, call the instruction function: */ 806: if (!_TME_M68K_SEQUENCE_RESTARTING 807: || (ic->_tme_m68k_mode_flags & TME_M68K_EXECUTION_INST_CANFAULT)) { 808: transfer_next_before = ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next; 1.1.1.3 root 809: (*func)(ic, TME_M68K_OPCODE_OP0_WHICH(ic, params), TME_M68K_OPCODE_OP1_WHICH(ic, params)); 1.1 root 810: assert(!(ic->_tme_m68k_mode_flags & TME_M68K_EXECUTION_INST_CANFAULT) 811: != (ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next 812: != transfer_next_before)); 813: ic->_tme_m68k_mode_flags &= ~TME_M68K_EXECUTION_INST_CANFAULT; 814: } 815: 816: /* store up to one EA path: */ 1.1.1.3 root 817: if ((params & TME_M68K_OPCODE_EA_WRITE) != 0) { 1.1 root 818: (*_tme_m68k_write_memx[ea_size])(ic); 819: } 820: 821: /* an instruction has ended: */ 822: tme_m68k_verify_end(ic, func); 823: 824: /* update the PC: */ 825: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next; 826: TME_M68K_SEQUENCE_START; 827: 828: #ifdef _TME_M68K_EXECUTE_FAST 829: /* if we haven't finished the instruction burst yet, continue: */ 1.1.1.2 root 830: if (__tme_predict_true(ic->_tme_m68k_instruction_burst_remaining != 0)) { 1.1 root 831: continue; 832: } 833: #endif /* _TME_M68K_EXECUTE_FAST */ 834: 835: /* try to acquire the external mutex and check for external 836: resets, halts, or interrupts, and process them along 837: with any internal exceptions: */ 838: rc = tme_mutex_trylock(&ic->tme_m68k_external_mutex); 839: if (TME_THREADS_ERRNO(rc) == TME_OK) { 840: tme_m68k_external_check(ic, 841: #ifdef _TME_M68K_EXECUTE_FAST 842: 0 843: #else /* !_TME_M68K_EXECUTE_FAST */ 844: exceptions 845: #endif /* !_TME_M68K_EXECUTE_FAST */ 846: ); 847: 848: /* unlock the external mutex: */ 849: tme_mutex_unlock(&ic->tme_m68k_external_mutex); 850: } 851: 852: #ifndef _TME_M68K_EXECUTE_FAST 853: 854: /* otherwise, if we have internal exceptions, process them: */ 855: else if (exceptions) { 856: tme_m68k_exception(ic, exceptions); 857: } 858: 859: /* if we can go fast now, go fast: */ 860: if (!tme_m68k_go_slow(ic)) { 861: tme_m68k_redispatch(ic); 862: } 863: 1.1.1.2 root 864: /* otherwise, unless we've used up our burst, continue: */ 865: if (ic->_tme_m68k_instruction_burst_remaining != 0) { 866: continue; 867: } 868: 869: #endif /* !_TME_M68K_EXECUTE_FAST */ 870: 871: /* start a new burst: */ 872: ic->_tme_m68k_instruction_burst_remaining 873: = ic->_tme_m68k_instruction_burst; 1.1 root 874: 875: /* if this is a cooperative threading system, yield: */ 1.1.1.4 ! root 876: #if TME_THREADS_COOPERATIVE ! 877: #ifdef _TME_M68K_EXECUTE_FAST ! 878: /* unbusy and forget the fast instruction TLB entry: */ ! 879: assert (ic->_tme_m68k_insn_fetch_fast_itlb == tlb); ! 880: tme_m68k_tlb_unbusy(tlb); ! 881: ic->_tme_m68k_insn_fetch_fast_itlb = NULL; ! 882: #endif /* _TME_M68K_EXECUTE_FAST */ 1.1 root 883: tme_thread_yield(); 884: #endif /* TME_THREADS_COOPERATIVE */ 885: 1.1.1.4 ! root 886: #ifdef _TME_M68K_EXECUTE_FAST ! 887: /* if this instruction TLB entry has been invalidated, redispatch. ! 888: this can only happen in a multiprocessing (preemptive or true ! 889: multiprocessor) environment, and it means that during the ! 890: previous burst, another thread invalidated this instruction TLB ! 891: entry, but we didn't make any callouts at all (for TLB fills, ! 892: slow bus cycles, etc.) where we would have noticed this ! 893: earlier: */ ! 894: if (tme_bus_tlb_is_invalid(&tlb->tme_m68k_tlb_bus_tlb)) { ! 895: tme_m68k_redispatch(ic); ! 896: } ! 897: #endif /* _TME_M68K_EXECUTE_FAST */ ! 898: 1.1 root 899: } 900: /* NOTREACHED */ 901: 902: #ifdef _TME_M68K_EXECUTE_FAST 903: 904: /* if we get here, we "faulted" trying to fetch an instruction word 905: from host memory. it's possibly not a "real" fault, since this 906: instruction may simply cross a page boundary, but since the fast 907: executor can't restart instructions we have to treat this like a 908: group 0 fault: */ 909: _tme_m68k_fast_fetch_failed: 910: 911: /* mimic a group 0 exception: */ 912: _TME_M68K_INSN_FETCH_SAVE; 913: ic->_tme_m68k_group0_flags = TME_M68K_BUS_CYCLE_FETCH | TME_M68K_BUS_CYCLE_READ; 914: ic->_tme_m68k_group0_function_code = function_code_program; 1.1.1.4 ! root 915: ic->_tme_m68k_group0_address = ic->tme_m68k_ireg_pc + (fetch_fast_next - ic->_tme_m68k_insn_fetch_fast_start); 1.1 root 916: ic->_tme_m68k_group0_sequence = ic->_tme_m68k_sequence; 917: ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted_after = 0; 918: ic->_tme_m68k_group0_buffer_read_size = 0; 919: ic->_tme_m68k_group0_buffer_read_softrr = 0; 920: tme_m68k_group0_hook_fast(ic); 921: ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted = 922: ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_next; 923: 924: /* mimic the rte: */ 925: ic->_tme_m68k_sequence = ic->_tme_m68k_group0_sequence; 926: ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next = 1; 927: TME_M68K_SEQUENCE_RESTART; 928: 929: tme_m68k_redispatch(ic); 930: /* NOTREACHED */ 931: #endif /* _TME_M68K_EXECUTE_FAST */ 932: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.