root / target-sparc / int64_helper.c @ 5b50e790
History | View | Annotate | Download (5.9 kB)
1 | ab3b491f | Blue Swirl | /*
|
---|---|---|---|
2 | ab3b491f | Blue Swirl | * Sparc64 interrupt helpers
|
3 | ab3b491f | Blue Swirl | *
|
4 | ab3b491f | Blue Swirl | * Copyright (c) 2003-2005 Fabrice Bellard
|
5 | ab3b491f | Blue Swirl | *
|
6 | ab3b491f | Blue Swirl | * This library is free software; you can redistribute it and/or
|
7 | ab3b491f | Blue Swirl | * modify it under the terms of the GNU Lesser General Public
|
8 | ab3b491f | Blue Swirl | * License as published by the Free Software Foundation; either
|
9 | ab3b491f | Blue Swirl | * version 2 of the License, or (at your option) any later version.
|
10 | ab3b491f | Blue Swirl | *
|
11 | ab3b491f | Blue Swirl | * This library is distributed in the hope that it will be useful,
|
12 | ab3b491f | Blue Swirl | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | ab3b491f | Blue Swirl | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | ab3b491f | Blue Swirl | * Lesser General Public License for more details.
|
15 | ab3b491f | Blue Swirl | *
|
16 | ab3b491f | Blue Swirl | * You should have received a copy of the GNU Lesser General Public
|
17 | ab3b491f | Blue Swirl | * License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
18 | ab3b491f | Blue Swirl | */
|
19 | ab3b491f | Blue Swirl | |
20 | ab3b491f | Blue Swirl | #include "cpu.h" |
21 | 79227036 | Blue Swirl | #include "helper.h" |
22 | 11e66bca | Blue Swirl | #include "trace.h" |
23 | ab3b491f | Blue Swirl | |
24 | b884fc5e | Richard Henderson | #define DEBUG_PCALL
|
25 | ab3b491f | Blue Swirl | |
26 | ab3b491f | Blue Swirl | #ifdef DEBUG_PCALL
|
27 | ab3b491f | Blue Swirl | static const char * const excp_names[0x80] = { |
28 | ab3b491f | Blue Swirl | [TT_TFAULT] = "Instruction Access Fault",
|
29 | ab3b491f | Blue Swirl | [TT_TMISS] = "Instruction Access MMU Miss",
|
30 | ab3b491f | Blue Swirl | [TT_CODE_ACCESS] = "Instruction Access Error",
|
31 | ab3b491f | Blue Swirl | [TT_ILL_INSN] = "Illegal Instruction",
|
32 | ab3b491f | Blue Swirl | [TT_PRIV_INSN] = "Privileged Instruction",
|
33 | ab3b491f | Blue Swirl | [TT_NFPU_INSN] = "FPU Disabled",
|
34 | ab3b491f | Blue Swirl | [TT_FP_EXCP] = "FPU Exception",
|
35 | ab3b491f | Blue Swirl | [TT_TOVF] = "Tag Overflow",
|
36 | ab3b491f | Blue Swirl | [TT_CLRWIN] = "Clean Windows",
|
37 | ab3b491f | Blue Swirl | [TT_DIV_ZERO] = "Division By Zero",
|
38 | ab3b491f | Blue Swirl | [TT_DFAULT] = "Data Access Fault",
|
39 | ab3b491f | Blue Swirl | [TT_DMISS] = "Data Access MMU Miss",
|
40 | ab3b491f | Blue Swirl | [TT_DATA_ACCESS] = "Data Access Error",
|
41 | ab3b491f | Blue Swirl | [TT_DPROT] = "Data Protection Error",
|
42 | ab3b491f | Blue Swirl | [TT_UNALIGNED] = "Unaligned Memory Access",
|
43 | ab3b491f | Blue Swirl | [TT_PRIV_ACT] = "Privileged Action",
|
44 | ab3b491f | Blue Swirl | [TT_EXTINT | 0x1] = "External Interrupt 1", |
45 | ab3b491f | Blue Swirl | [TT_EXTINT | 0x2] = "External Interrupt 2", |
46 | ab3b491f | Blue Swirl | [TT_EXTINT | 0x3] = "External Interrupt 3", |
47 | ab3b491f | Blue Swirl | [TT_EXTINT | 0x4] = "External Interrupt 4", |
48 | ab3b491f | Blue Swirl | [TT_EXTINT | 0x5] = "External Interrupt 5", |
49 | ab3b491f | Blue Swirl | [TT_EXTINT | 0x6] = "External Interrupt 6", |
50 | ab3b491f | Blue Swirl | [TT_EXTINT | 0x7] = "External Interrupt 7", |
51 | ab3b491f | Blue Swirl | [TT_EXTINT | 0x8] = "External Interrupt 8", |
52 | ab3b491f | Blue Swirl | [TT_EXTINT | 0x9] = "External Interrupt 9", |
53 | ab3b491f | Blue Swirl | [TT_EXTINT | 0xa] = "External Interrupt 10", |
54 | ab3b491f | Blue Swirl | [TT_EXTINT | 0xb] = "External Interrupt 11", |
55 | ab3b491f | Blue Swirl | [TT_EXTINT | 0xc] = "External Interrupt 12", |
56 | ab3b491f | Blue Swirl | [TT_EXTINT | 0xd] = "External Interrupt 13", |
57 | ab3b491f | Blue Swirl | [TT_EXTINT | 0xe] = "External Interrupt 14", |
58 | ab3b491f | Blue Swirl | [TT_EXTINT | 0xf] = "External Interrupt 15", |
59 | ab3b491f | Blue Swirl | }; |
60 | ab3b491f | Blue Swirl | #endif
|
61 | ab3b491f | Blue Swirl | |
62 | 97a8ea5a | Andreas Färber | void sparc_cpu_do_interrupt(CPUState *cs)
|
63 | ab3b491f | Blue Swirl | { |
64 | 97a8ea5a | Andreas Färber | SPARCCPU *cpu = SPARC_CPU(cs); |
65 | 97a8ea5a | Andreas Färber | CPUSPARCState *env = &cpu->env; |
66 | ab3b491f | Blue Swirl | int intno = env->exception_index;
|
67 | ab3b491f | Blue Swirl | trap_state *tsptr; |
68 | ab3b491f | Blue Swirl | |
69 | 20132b96 | Richard Henderson | /* Compute PSR before exposing state. */
|
70 | 20132b96 | Richard Henderson | if (env->cc_op != CC_OP_FLAGS) {
|
71 | 20132b96 | Richard Henderson | cpu_get_psr(env); |
72 | 20132b96 | Richard Henderson | } |
73 | 20132b96 | Richard Henderson | |
74 | ab3b491f | Blue Swirl | #ifdef DEBUG_PCALL
|
75 | ab3b491f | Blue Swirl | if (qemu_loglevel_mask(CPU_LOG_INT)) {
|
76 | ab3b491f | Blue Swirl | static int count; |
77 | ab3b491f | Blue Swirl | const char *name; |
78 | ab3b491f | Blue Swirl | |
79 | ab3b491f | Blue Swirl | if (intno < 0 || intno >= 0x180) { |
80 | ab3b491f | Blue Swirl | name = "Unknown";
|
81 | ab3b491f | Blue Swirl | } else if (intno >= 0x100) { |
82 | ab3b491f | Blue Swirl | name = "Trap Instruction";
|
83 | ab3b491f | Blue Swirl | } else if (intno >= 0xc0) { |
84 | ab3b491f | Blue Swirl | name = "Window Fill";
|
85 | ab3b491f | Blue Swirl | } else if (intno >= 0x80) { |
86 | ab3b491f | Blue Swirl | name = "Window Spill";
|
87 | ab3b491f | Blue Swirl | } else {
|
88 | ab3b491f | Blue Swirl | name = excp_names[intno]; |
89 | ab3b491f | Blue Swirl | if (!name) {
|
90 | ab3b491f | Blue Swirl | name = "Unknown";
|
91 | ab3b491f | Blue Swirl | } |
92 | ab3b491f | Blue Swirl | } |
93 | ab3b491f | Blue Swirl | |
94 | b884fc5e | Richard Henderson | qemu_log("%6d: %s (v=%04x)\n", count, name, intno);
|
95 | a0762859 | Andreas Färber | log_cpu_state(cs, 0);
|
96 | ab3b491f | Blue Swirl | #if 0
|
97 | ab3b491f | Blue Swirl | {
|
98 | ab3b491f | Blue Swirl | int i;
|
99 | ab3b491f | Blue Swirl | uint8_t *ptr;
|
100 | ab3b491f | Blue Swirl | |
101 | ab3b491f | Blue Swirl | qemu_log(" code=");
|
102 | ab3b491f | Blue Swirl | ptr = (uint8_t *)env->pc;
|
103 | ab3b491f | Blue Swirl | for (i = 0; i < 16; i++) {
|
104 | ab3b491f | Blue Swirl | qemu_log(" %02x", ldub(ptr + i));
|
105 | ab3b491f | Blue Swirl | }
|
106 | ab3b491f | Blue Swirl | qemu_log("\n");
|
107 | ab3b491f | Blue Swirl | }
|
108 | ab3b491f | Blue Swirl | #endif
|
109 | ab3b491f | Blue Swirl | count++; |
110 | ab3b491f | Blue Swirl | } |
111 | ab3b491f | Blue Swirl | #endif
|
112 | ab3b491f | Blue Swirl | #if !defined(CONFIG_USER_ONLY)
|
113 | ab3b491f | Blue Swirl | if (env->tl >= env->maxtl) {
|
114 | ab3b491f | Blue Swirl | cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
|
115 | ab3b491f | Blue Swirl | " Error state", env->exception_index, env->tl, env->maxtl);
|
116 | ab3b491f | Blue Swirl | return;
|
117 | ab3b491f | Blue Swirl | } |
118 | ab3b491f | Blue Swirl | #endif
|
119 | ab3b491f | Blue Swirl | if (env->tl < env->maxtl - 1) { |
120 | ab3b491f | Blue Swirl | env->tl++; |
121 | ab3b491f | Blue Swirl | } else {
|
122 | ab3b491f | Blue Swirl | env->pstate |= PS_RED; |
123 | ab3b491f | Blue Swirl | if (env->tl < env->maxtl) {
|
124 | ab3b491f | Blue Swirl | env->tl++; |
125 | ab3b491f | Blue Swirl | } |
126 | ab3b491f | Blue Swirl | } |
127 | ab3b491f | Blue Swirl | tsptr = cpu_tsptr(env); |
128 | ab3b491f | Blue Swirl | |
129 | ab3b491f | Blue Swirl | tsptr->tstate = (cpu_get_ccr(env) << 32) |
|
130 | ab3b491f | Blue Swirl | ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) | |
131 | ab3b491f | Blue Swirl | cpu_get_cwp64(env); |
132 | ab3b491f | Blue Swirl | tsptr->tpc = env->pc; |
133 | ab3b491f | Blue Swirl | tsptr->tnpc = env->npc; |
134 | ab3b491f | Blue Swirl | tsptr->tt = intno; |
135 | ab3b491f | Blue Swirl | |
136 | ab3b491f | Blue Swirl | switch (intno) {
|
137 | ab3b491f | Blue Swirl | case TT_IVEC:
|
138 | ab3b491f | Blue Swirl | cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_IG); |
139 | ab3b491f | Blue Swirl | break;
|
140 | ab3b491f | Blue Swirl | case TT_TFAULT:
|
141 | ab3b491f | Blue Swirl | case TT_DFAULT:
|
142 | ab3b491f | Blue Swirl | case TT_TMISS ... TT_TMISS + 3: |
143 | ab3b491f | Blue Swirl | case TT_DMISS ... TT_DMISS + 3: |
144 | ab3b491f | Blue Swirl | case TT_DPROT ... TT_DPROT + 3: |
145 | ab3b491f | Blue Swirl | cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_MG); |
146 | ab3b491f | Blue Swirl | break;
|
147 | ab3b491f | Blue Swirl | default:
|
148 | ab3b491f | Blue Swirl | cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_AG); |
149 | ab3b491f | Blue Swirl | break;
|
150 | ab3b491f | Blue Swirl | } |
151 | ab3b491f | Blue Swirl | |
152 | ab3b491f | Blue Swirl | if (intno == TT_CLRWIN) {
|
153 | ab3b491f | Blue Swirl | cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
|
154 | ab3b491f | Blue Swirl | } else if ((intno & 0x1c0) == TT_SPILL) { |
155 | ab3b491f | Blue Swirl | cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
|
156 | ab3b491f | Blue Swirl | } else if ((intno & 0x1c0) == TT_FILL) { |
157 | ab3b491f | Blue Swirl | cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
|
158 | ab3b491f | Blue Swirl | } |
159 | ab3b491f | Blue Swirl | env->tbr &= ~0x7fffULL;
|
160 | ab3b491f | Blue Swirl | env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5); |
161 | ab3b491f | Blue Swirl | env->pc = env->tbr; |
162 | ab3b491f | Blue Swirl | env->npc = env->pc + 4;
|
163 | ab3b491f | Blue Swirl | env->exception_index = -1;
|
164 | ab3b491f | Blue Swirl | } |
165 | 2336c1f1 | Blue Swirl | |
166 | c5f9864e | Andreas Färber | trap_state *cpu_tsptr(CPUSPARCState* env) |
167 | 2336c1f1 | Blue Swirl | { |
168 | 2336c1f1 | Blue Swirl | return &env->ts[env->tl & MAXTL_MASK];
|
169 | 2336c1f1 | Blue Swirl | } |
170 | 79227036 | Blue Swirl | |
171 | c5f9864e | Andreas Färber | static bool do_modify_softint(CPUSPARCState *env, uint32_t value) |
172 | 79227036 | Blue Swirl | { |
173 | 79227036 | Blue Swirl | if (env->softint != value) {
|
174 | 79227036 | Blue Swirl | env->softint = value; |
175 | 79227036 | Blue Swirl | #if !defined(CONFIG_USER_ONLY)
|
176 | 79227036 | Blue Swirl | if (cpu_interrupts_enabled(env)) {
|
177 | 79227036 | Blue Swirl | cpu_check_irqs(env); |
178 | 79227036 | Blue Swirl | } |
179 | 79227036 | Blue Swirl | #endif
|
180 | 11e66bca | Blue Swirl | return true; |
181 | 79227036 | Blue Swirl | } |
182 | 11e66bca | Blue Swirl | return false; |
183 | 79227036 | Blue Swirl | } |
184 | 79227036 | Blue Swirl | |
185 | c5f9864e | Andreas Färber | void helper_set_softint(CPUSPARCState *env, uint64_t value)
|
186 | 79227036 | Blue Swirl | { |
187 | 11e66bca | Blue Swirl | if (do_modify_softint(env, env->softint | (uint32_t)value)) {
|
188 | 11e66bca | Blue Swirl | trace_int_helper_set_softint(env->softint); |
189 | 11e66bca | Blue Swirl | } |
190 | 79227036 | Blue Swirl | } |
191 | 79227036 | Blue Swirl | |
192 | c5f9864e | Andreas Färber | void helper_clear_softint(CPUSPARCState *env, uint64_t value)
|
193 | 79227036 | Blue Swirl | { |
194 | 11e66bca | Blue Swirl | if (do_modify_softint(env, env->softint & (uint32_t)~value)) {
|
195 | 11e66bca | Blue Swirl | trace_int_helper_clear_softint(env->softint); |
196 | 11e66bca | Blue Swirl | } |
197 | 79227036 | Blue Swirl | } |
198 | 79227036 | Blue Swirl | |
199 | c5f9864e | Andreas Färber | void helper_write_softint(CPUSPARCState *env, uint64_t value)
|
200 | 79227036 | Blue Swirl | { |
201 | 11e66bca | Blue Swirl | if (do_modify_softint(env, (uint32_t)value)) {
|
202 | 11e66bca | Blue Swirl | trace_int_helper_write_softint(env->softint); |
203 | 11e66bca | Blue Swirl | } |
204 | 79227036 | Blue Swirl | } |