|
|
1.1 ! root 1: /* ! 2: * Sparc64 interrupt helpers ! 3: * ! 4: * Copyright (c) 2003-2005 Fabrice Bellard ! 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, see <http://www.gnu.org/licenses/>. ! 18: */ ! 19: ! 20: #include "cpu.h" ! 21: #include "helper.h" ! 22: #include "trace.h" ! 23: ! 24: //#define DEBUG_PCALL ! 25: ! 26: #ifdef DEBUG_PCALL ! 27: static const char * const excp_names[0x80] = { ! 28: [TT_TFAULT] = "Instruction Access Fault", ! 29: [TT_TMISS] = "Instruction Access MMU Miss", ! 30: [TT_CODE_ACCESS] = "Instruction Access Error", ! 31: [TT_ILL_INSN] = "Illegal Instruction", ! 32: [TT_PRIV_INSN] = "Privileged Instruction", ! 33: [TT_NFPU_INSN] = "FPU Disabled", ! 34: [TT_FP_EXCP] = "FPU Exception", ! 35: [TT_TOVF] = "Tag Overflow", ! 36: [TT_CLRWIN] = "Clean Windows", ! 37: [TT_DIV_ZERO] = "Division By Zero", ! 38: [TT_DFAULT] = "Data Access Fault", ! 39: [TT_DMISS] = "Data Access MMU Miss", ! 40: [TT_DATA_ACCESS] = "Data Access Error", ! 41: [TT_DPROT] = "Data Protection Error", ! 42: [TT_UNALIGNED] = "Unaligned Memory Access", ! 43: [TT_PRIV_ACT] = "Privileged Action", ! 44: [TT_EXTINT | 0x1] = "External Interrupt 1", ! 45: [TT_EXTINT | 0x2] = "External Interrupt 2", ! 46: [TT_EXTINT | 0x3] = "External Interrupt 3", ! 47: [TT_EXTINT | 0x4] = "External Interrupt 4", ! 48: [TT_EXTINT | 0x5] = "External Interrupt 5", ! 49: [TT_EXTINT | 0x6] = "External Interrupt 6", ! 50: [TT_EXTINT | 0x7] = "External Interrupt 7", ! 51: [TT_EXTINT | 0x8] = "External Interrupt 8", ! 52: [TT_EXTINT | 0x9] = "External Interrupt 9", ! 53: [TT_EXTINT | 0xa] = "External Interrupt 10", ! 54: [TT_EXTINT | 0xb] = "External Interrupt 11", ! 55: [TT_EXTINT | 0xc] = "External Interrupt 12", ! 56: [TT_EXTINT | 0xd] = "External Interrupt 13", ! 57: [TT_EXTINT | 0xe] = "External Interrupt 14", ! 58: [TT_EXTINT | 0xf] = "External Interrupt 15", ! 59: }; ! 60: #endif ! 61: ! 62: void do_interrupt(CPUState *env) ! 63: { ! 64: int intno = env->exception_index; ! 65: trap_state *tsptr; ! 66: ! 67: #ifdef DEBUG_PCALL ! 68: if (qemu_loglevel_mask(CPU_LOG_INT)) { ! 69: static int count; ! 70: const char *name; ! 71: ! 72: if (intno < 0 || intno >= 0x180) { ! 73: name = "Unknown"; ! 74: } else if (intno >= 0x100) { ! 75: name = "Trap Instruction"; ! 76: } else if (intno >= 0xc0) { ! 77: name = "Window Fill"; ! 78: } else if (intno >= 0x80) { ! 79: name = "Window Spill"; ! 80: } else { ! 81: name = excp_names[intno]; ! 82: if (!name) { ! 83: name = "Unknown"; ! 84: } ! 85: } ! 86: ! 87: qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64 ! 88: " SP=%016" PRIx64 "\n", ! 89: count, name, intno, ! 90: env->pc, ! 91: env->npc, env->regwptr[6]); ! 92: log_cpu_state(env, 0); ! 93: #if 0 ! 94: { ! 95: int i; ! 96: uint8_t *ptr; ! 97: ! 98: qemu_log(" code="); ! 99: ptr = (uint8_t *)env->pc; ! 100: for (i = 0; i < 16; i++) { ! 101: qemu_log(" %02x", ldub(ptr + i)); ! 102: } ! 103: qemu_log("\n"); ! 104: } ! 105: #endif ! 106: count++; ! 107: } ! 108: #endif ! 109: #if !defined(CONFIG_USER_ONLY) ! 110: if (env->tl >= env->maxtl) { ! 111: cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d)," ! 112: " Error state", env->exception_index, env->tl, env->maxtl); ! 113: return; ! 114: } ! 115: #endif ! 116: if (env->tl < env->maxtl - 1) { ! 117: env->tl++; ! 118: } else { ! 119: env->pstate |= PS_RED; ! 120: if (env->tl < env->maxtl) { ! 121: env->tl++; ! 122: } ! 123: } ! 124: tsptr = cpu_tsptr(env); ! 125: ! 126: tsptr->tstate = (cpu_get_ccr(env) << 32) | ! 127: ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) | ! 128: cpu_get_cwp64(env); ! 129: tsptr->tpc = env->pc; ! 130: tsptr->tnpc = env->npc; ! 131: tsptr->tt = intno; ! 132: ! 133: switch (intno) { ! 134: case TT_IVEC: ! 135: cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_IG); ! 136: break; ! 137: case TT_TFAULT: ! 138: case TT_DFAULT: ! 139: case TT_TMISS ... TT_TMISS + 3: ! 140: case TT_DMISS ... TT_DMISS + 3: ! 141: case TT_DPROT ... TT_DPROT + 3: ! 142: cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_MG); ! 143: break; ! 144: default: ! 145: cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_AG); ! 146: break; ! 147: } ! 148: ! 149: if (intno == TT_CLRWIN) { ! 150: cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1)); ! 151: } else if ((intno & 0x1c0) == TT_SPILL) { ! 152: cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2)); ! 153: } else if ((intno & 0x1c0) == TT_FILL) { ! 154: cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1)); ! 155: } ! 156: env->tbr &= ~0x7fffULL; ! 157: env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5); ! 158: env->pc = env->tbr; ! 159: env->npc = env->pc + 4; ! 160: env->exception_index = -1; ! 161: } ! 162: ! 163: trap_state *cpu_tsptr(CPUState* env) ! 164: { ! 165: return &env->ts[env->tl & MAXTL_MASK]; ! 166: } ! 167: ! 168: static bool do_modify_softint(CPUState *env, uint32_t value) ! 169: { ! 170: if (env->softint != value) { ! 171: env->softint = value; ! 172: #if !defined(CONFIG_USER_ONLY) ! 173: if (cpu_interrupts_enabled(env)) { ! 174: cpu_check_irqs(env); ! 175: } ! 176: #endif ! 177: return true; ! 178: } ! 179: return false; ! 180: } ! 181: ! 182: void helper_set_softint(CPUState *env, uint64_t value) ! 183: { ! 184: if (do_modify_softint(env, env->softint | (uint32_t)value)) { ! 185: trace_int_helper_set_softint(env->softint); ! 186: } ! 187: } ! 188: ! 189: void helper_clear_softint(CPUState *env, uint64_t value) ! 190: { ! 191: if (do_modify_softint(env, env->softint & (uint32_t)~value)) { ! 192: trace_int_helper_clear_softint(env->softint); ! 193: } ! 194: } ! 195: ! 196: void helper_write_softint(CPUState *env, uint64_t value) ! 197: { ! 198: if (do_modify_softint(env, (uint32_t)value)) { ! 199: trace_int_helper_write_softint(env->softint); ! 200: } ! 201: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.