|
|
1.1 ! root 1: /* ! 2: * M68K helper routines ! 3: * ! 4: * Copyright (c) 2007 CodeSourcery ! 5: * ! 6: * This library is free software; you can redistribute it and/or ! 7: * modify it under the terms of the GNU Lesser General Public ! 8: * License as published by the Free Software Foundation; either ! 9: * version 2 of the License, or (at your option) any later version. ! 10: * ! 11: * This library is distributed in the hope that it will be useful, ! 12: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 14: * Lesser General Public License for more details. ! 15: * ! 16: * You should have received a copy of the GNU Lesser General Public ! 17: * License along with this library; if not, write to the Free Software ! 18: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! 19: */ ! 20: #include "exec.h" ! 21: ! 22: #if defined(CONFIG_USER_ONLY) ! 23: ! 24: void do_interrupt(int is_hw) ! 25: { ! 26: env->exception_index = -1; ! 27: } ! 28: ! 29: #else ! 30: ! 31: extern int semihosting_enabled; ! 32: ! 33: #define MMUSUFFIX _mmu ! 34: #ifdef __s390__ ! 35: # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL)) ! 36: #else ! 37: # define GETPC() (__builtin_return_address(0)) ! 38: #endif ! 39: ! 40: #define SHIFT 0 ! 41: #include "softmmu_template.h" ! 42: ! 43: #define SHIFT 1 ! 44: #include "softmmu_template.h" ! 45: ! 46: #define SHIFT 2 ! 47: #include "softmmu_template.h" ! 48: ! 49: #define SHIFT 3 ! 50: #include "softmmu_template.h" ! 51: ! 52: /* Try to fill the TLB and return an exception if error. If retaddr is ! 53: NULL, it means that the function was called in C code (i.e. not ! 54: from generated code or from helper.c) */ ! 55: /* XXX: fix it to restore all registers */ ! 56: void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) ! 57: { ! 58: TranslationBlock *tb; ! 59: CPUState *saved_env; ! 60: unsigned long pc; ! 61: int ret; ! 62: ! 63: /* XXX: hack to restore env in all cases, even if not called from ! 64: generated code */ ! 65: saved_env = env; ! 66: env = cpu_single_env; ! 67: ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); ! 68: if (__builtin_expect(ret, 0)) { ! 69: if (retaddr) { ! 70: /* now we have a real cpu fault */ ! 71: pc = (unsigned long)retaddr; ! 72: tb = tb_find_pc(pc); ! 73: if (tb) { ! 74: /* the PC is inside the translated code. It means that we have ! 75: a virtual CPU fault */ ! 76: cpu_restore_state(tb, env, pc, NULL); ! 77: } ! 78: } ! 79: cpu_loop_exit(); ! 80: } ! 81: env = saved_env; ! 82: } ! 83: ! 84: static void do_rte(void) ! 85: { ! 86: uint32_t sp; ! 87: uint32_t fmt; ! 88: ! 89: sp = env->aregs[7]; ! 90: fmt = ldl_kernel(sp); ! 91: env->pc = ldl_kernel(sp + 4); ! 92: sp |= (fmt >> 28) & 3; ! 93: env->sr = fmt & 0xffff; ! 94: m68k_switch_sp(env); ! 95: env->aregs[7] = sp + 8; ! 96: } ! 97: ! 98: void do_interrupt(int is_hw) ! 99: { ! 100: uint32_t sp; ! 101: uint32_t fmt; ! 102: uint32_t retaddr; ! 103: uint32_t vector; ! 104: ! 105: fmt = 0; ! 106: retaddr = env->pc; ! 107: ! 108: if (!is_hw) { ! 109: switch (env->exception_index) { ! 110: case EXCP_RTE: ! 111: /* Return from an exception. */ ! 112: do_rte(); ! 113: return; ! 114: case EXCP_HALT_INSN: ! 115: if (semihosting_enabled ! 116: && (env->sr & SR_S) != 0 ! 117: && (env->pc & 3) == 0 ! 118: && lduw_code(env->pc - 4) == 0x4e71 ! 119: && ldl_code(env->pc) == 0x4e7bf000) { ! 120: env->pc += 4; ! 121: do_m68k_semihosting(env, env->dregs[0]); ! 122: return; ! 123: } ! 124: env->halted = 1; ! 125: env->exception_index = EXCP_HLT; ! 126: cpu_loop_exit(); ! 127: return; ! 128: } ! 129: if (env->exception_index >= EXCP_TRAP0 ! 130: && env->exception_index <= EXCP_TRAP15) { ! 131: /* Move the PC after the trap instruction. */ ! 132: retaddr += 2; ! 133: } ! 134: } ! 135: ! 136: vector = env->exception_index << 2; ! 137: ! 138: sp = env->aregs[7]; ! 139: ! 140: fmt |= 0x40000000; ! 141: fmt |= (sp & 3) << 28; ! 142: fmt |= vector << 16; ! 143: fmt |= env->sr; ! 144: ! 145: env->sr |= SR_S; ! 146: if (is_hw) { ! 147: env->sr = (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT); ! 148: env->sr &= ~SR_M; ! 149: } ! 150: m68k_switch_sp(env); ! 151: ! 152: /* ??? This could cause MMU faults. */ ! 153: sp &= ~3; ! 154: sp -= 4; ! 155: stl_kernel(sp, retaddr); ! 156: sp -= 4; ! 157: stl_kernel(sp, fmt); ! 158: env->aregs[7] = sp; ! 159: /* Jump to vector. */ ! 160: env->pc = ldl_kernel(env->vbr + vector); ! 161: } ! 162: ! 163: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.