1 | /* |
2 | * OpenRISC interrupt. |
3 | * |
4 | * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> |
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.1 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 "qemu/osdep.h" |
21 | #include "cpu.h" |
22 | #include "exec/exec-all.h" |
23 | #include "exec/gdbstub.h" |
24 | #include "qemu/host-utils.h" |
25 | #ifndef CONFIG_USER_ONLY |
26 | #include "hw/loader.h" |
27 | #endif |
28 | |
29 | void openrisc_cpu_do_interrupt(CPUState *cs) |
30 | { |
31 | #ifndef CONFIG_USER_ONLY |
32 | OpenRISCCPU *cpu = OPENRISC_CPU(cs); |
33 | CPUOpenRISCState *env = &cpu->env; |
34 | int exception = cs->exception_index; |
35 | |
36 | env->epcr = env->pc; |
37 | if (exception == EXCP_SYSCALL) { |
38 | env->epcr += 4; |
39 | } |
40 | /* When we have an illegal instruction the error effective address |
41 | shall be set to the illegal instruction address. */ |
42 | if (exception == EXCP_ILLEGAL) { |
43 | env->eear = env->pc; |
44 | } |
45 | |
46 | /* During exceptions esr is populared with the pre-exception sr. */ |
47 | env->esr = cpu_get_sr(env); |
48 | /* In parallel sr is updated to disable mmu, interrupts, timers and |
49 | set the delay slot exception flag. */ |
50 | env->sr &= ~SR_DME; |
51 | env->sr &= ~SR_IME; |
52 | env->sr |= SR_SM; |
53 | env->sr &= ~SR_IEE; |
54 | env->sr &= ~SR_TEE; |
55 | env->pmr &= ~PMR_DME; |
56 | env->pmr &= ~PMR_SME; |
57 | env->lock_addr = -1; |
58 | |
59 | /* Set/clear dsx to indicate if we are in a delay slot exception. */ |
60 | if (env->dflag) { |
61 | env->dflag = 0; |
62 | env->sr |= SR_DSX; |
63 | env->epcr -= 4; |
64 | } else { |
65 | env->sr &= ~SR_DSX; |
66 | } |
67 | |
68 | if (exception > 0 && exception < EXCP_NR) { |
69 | static const char * const int_name[EXCP_NR] = { |
70 | [EXCP_RESET] = "RESET" , |
71 | [EXCP_BUSERR] = "BUSERR (bus error)" , |
72 | [EXCP_DPF] = "DFP (data protection fault)" , |
73 | [EXCP_IPF] = "IPF (code protection fault)" , |
74 | [EXCP_TICK] = "TICK (timer interrupt)" , |
75 | [EXCP_ALIGN] = "ALIGN" , |
76 | [EXCP_ILLEGAL] = "ILLEGAL" , |
77 | [EXCP_INT] = "INT (device interrupt)" , |
78 | [EXCP_DTLBMISS] = "DTLBMISS (data tlb miss)" , |
79 | [EXCP_ITLBMISS] = "ITLBMISS (code tlb miss)" , |
80 | [EXCP_RANGE] = "RANGE" , |
81 | [EXCP_SYSCALL] = "SYSCALL" , |
82 | [EXCP_FPE] = "FPE" , |
83 | [EXCP_TRAP] = "TRAP" , |
84 | }; |
85 | |
86 | qemu_log_mask(CPU_LOG_INT, "INT: %s\n" , int_name[exception]); |
87 | |
88 | hwaddr vect_pc = exception << 8; |
89 | if (env->cpucfgr & CPUCFGR_EVBARP) { |
90 | vect_pc |= env->evbar; |
91 | } |
92 | if (env->sr & SR_EPH) { |
93 | vect_pc |= 0xf0000000; |
94 | } |
95 | env->pc = vect_pc; |
96 | } else { |
97 | cpu_abort(cs, "Unhandled exception 0x%x\n" , exception); |
98 | } |
99 | #endif |
100 | |
101 | cs->exception_index = -1; |
102 | } |
103 | |
104 | bool openrisc_cpu_exec_interrupt(CPUState *cs, int interrupt_request) |
105 | { |
106 | OpenRISCCPU *cpu = OPENRISC_CPU(cs); |
107 | CPUOpenRISCState *env = &cpu->env; |
108 | int idx = -1; |
109 | |
110 | if ((interrupt_request & CPU_INTERRUPT_HARD) && (env->sr & SR_IEE)) { |
111 | idx = EXCP_INT; |
112 | } |
113 | if ((interrupt_request & CPU_INTERRUPT_TIMER) && (env->sr & SR_TEE)) { |
114 | idx = EXCP_TICK; |
115 | } |
116 | if (idx >= 0) { |
117 | cs->exception_index = idx; |
118 | openrisc_cpu_do_interrupt(cs); |
119 | return true; |
120 | } |
121 | return false; |
122 | } |
123 | |