1e67db06eSJia Liu /* 2e67db06eSJia Liu * OpenRISC interrupt. 3e67db06eSJia Liu * 4e67db06eSJia Liu * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> 5e67db06eSJia Liu * 6e67db06eSJia Liu * This library is free software; you can redistribute it and/or 7e67db06eSJia Liu * modify it under the terms of the GNU Lesser General Public 8e67db06eSJia Liu * License as published by the Free Software Foundation; either 9e67db06eSJia Liu * version 2 of the License, or (at your option) any later version. 10e67db06eSJia Liu * 11e67db06eSJia Liu * This library is distributed in the hope that it will be useful, 12e67db06eSJia Liu * but WITHOUT ANY WARRANTY; without even the implied warranty of 13e67db06eSJia Liu * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14e67db06eSJia Liu * Lesser General Public License for more details. 15e67db06eSJia Liu * 16e67db06eSJia Liu * You should have received a copy of the GNU Lesser General Public 17e67db06eSJia Liu * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18e67db06eSJia Liu */ 19e67db06eSJia Liu 20e67db06eSJia Liu #include "cpu.h" 21e67db06eSJia Liu #include "qemu-common.h" 22022c62cbSPaolo Bonzini #include "exec/gdbstub.h" 231de7afc9SPaolo Bonzini #include "qemu/host-utils.h" 24e67db06eSJia Liu #ifndef CONFIG_USER_ONLY 25e67db06eSJia Liu #include "hw/loader.h" 26e67db06eSJia Liu #endif 27e67db06eSJia Liu 2897a8ea5aSAndreas Färber void openrisc_cpu_do_interrupt(CPUState *cs) 29e67db06eSJia Liu { 3097a8ea5aSAndreas Färber OpenRISCCPU *cpu = OPENRISC_CPU(cs); 3197a8ea5aSAndreas Färber CPUOpenRISCState *env = &cpu->env; 32b6a71ef7SJia Liu #ifndef CONFIG_USER_ONLY 33ae52bd96SSebastian Macke 34ae52bd96SSebastian Macke env->epcr = env->pc; 35ae52bd96SSebastian Macke if (env->flags & D_FLAG) { 36b6a71ef7SJia Liu env->flags &= ~D_FLAG; 37b6a71ef7SJia Liu env->sr |= SR_DSX; 38ae52bd96SSebastian Macke env->epcr -= 4; 39b6a71ef7SJia Liu } 40ae52bd96SSebastian Macke if (env->exception_index == EXCP_SYSCALL) { 41ae52bd96SSebastian Macke env->epcr += 4; 42b6a71ef7SJia Liu } 43b6a71ef7SJia Liu 44b6a71ef7SJia Liu /* For machine-state changed between user-mode and supervisor mode, 45b6a71ef7SJia Liu we need flush TLB when we enter&exit EXCP. */ 46b6a71ef7SJia Liu tlb_flush(env, 1); 47b6a71ef7SJia Liu 48b6a71ef7SJia Liu env->esr = env->sr; 49b6a71ef7SJia Liu env->sr &= ~SR_DME; 50b6a71ef7SJia Liu env->sr &= ~SR_IME; 51b6a71ef7SJia Liu env->sr |= SR_SM; 52b6a71ef7SJia Liu env->sr &= ~SR_IEE; 53b6a71ef7SJia Liu env->sr &= ~SR_TEE; 54b6a71ef7SJia Liu env->tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu; 55b6a71ef7SJia Liu env->tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu; 56b6a71ef7SJia Liu 57b6a71ef7SJia Liu if (env->exception_index > 0 && env->exception_index < EXCP_NR) { 58b6a71ef7SJia Liu env->pc = (env->exception_index << 8); 59b6a71ef7SJia Liu } else { 60b6a71ef7SJia Liu cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index); 61b6a71ef7SJia Liu } 62b6a71ef7SJia Liu #endif 63b6a71ef7SJia Liu 64b6a71ef7SJia Liu env->exception_index = -1; 65e67db06eSJia Liu } 66