]> git.proxmox.com Git - qemu.git/blob - target-cris/helper.c
target-cris/helper.c: Update Coding Style
[qemu.git] / target-cris / helper.c
1 /*
2 * CRIS helper routines.
3 *
4 * Copyright (c) 2007 AXIS Communications AB
5 * Written by Edgar E. Iglesias.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "cpu.h"
22 #include "mmu.h"
23 #include "qemu/host-utils.h"
24
25
26 //#define CRIS_HELPER_DEBUG
27
28
29 #ifdef CRIS_HELPER_DEBUG
30 #define D(x) x
31 #define D_LOG(...) qemu_log(__VA_ARGS__)
32 #else
33 #define D(x)
34 #define D_LOG(...) do { } while (0)
35 #endif
36
37 #if defined(CONFIG_USER_ONLY)
38
39 void do_interrupt(CPUCRISState *env)
40 {
41 env->exception_index = -1;
42 env->pregs[PR_ERP] = env->pc;
43 }
44
45 int cpu_cris_handle_mmu_fault(CPUCRISState * env, target_ulong address, int rw,
46 int mmu_idx)
47 {
48 env->exception_index = 0xaa;
49 env->pregs[PR_EDA] = address;
50 cpu_dump_state(env, stderr, fprintf, 0);
51 return 1;
52 }
53
54 #else /* !CONFIG_USER_ONLY */
55
56
57 static void cris_shift_ccs(CPUCRISState *env)
58 {
59 uint32_t ccs;
60 /* Apply the ccs shift. */
61 ccs = env->pregs[PR_CCS];
62 ccs = ((ccs & 0xc0000000) | ((ccs << 12) >> 2)) & ~0x3ff;
63 env->pregs[PR_CCS] = ccs;
64 }
65
66 int cpu_cris_handle_mmu_fault(CPUCRISState *env, target_ulong address, int rw,
67 int mmu_idx)
68 {
69 struct cris_mmu_result res;
70 int prot, miss;
71 int r = -1;
72 target_ulong phy;
73
74 D(printf("%s addr=%x pc=%x rw=%x\n", __func__, address, env->pc, rw));
75 miss = cris_mmu_translate(&res, env, address & TARGET_PAGE_MASK,
76 rw, mmu_idx, 0);
77 if (miss) {
78 if (env->exception_index == EXCP_BUSFAULT) {
79 cpu_abort(env,
80 "CRIS: Illegal recursive bus fault."
81 "addr=%x rw=%d\n",
82 address, rw);
83 }
84
85 env->pregs[PR_EDA] = address;
86 env->exception_index = EXCP_BUSFAULT;
87 env->fault_vector = res.bf_vec;
88 r = 1;
89 } else {
90 /*
91 * Mask off the cache selection bit. The ETRAX busses do not
92 * see the top bit.
93 */
94 phy = res.phy & ~0x80000000;
95 prot = res.prot;
96 tlb_set_page(env, address & TARGET_PAGE_MASK, phy,
97 prot, mmu_idx, TARGET_PAGE_SIZE);
98 r = 0;
99 }
100 if (r > 0) {
101 D_LOG("%s returns %d irqreq=%x addr=%x phy=%x vec=%x pc=%x\n",
102 __func__, r, env->interrupt_request, address, res.phy,
103 res.bf_vec, env->pc);
104 }
105 return r;
106 }
107
108 static void do_interruptv10(CPUCRISState *env)
109 {
110 int ex_vec = -1;
111
112 D_LOG("exception index=%d interrupt_req=%d\n",
113 env->exception_index,
114 env->interrupt_request);
115
116 assert(!(env->pregs[PR_CCS] & PFIX_FLAG));
117 switch (env->exception_index) {
118 case EXCP_BREAK:
119 /* These exceptions are genereated by the core itself.
120 ERP should point to the insn following the brk. */
121 ex_vec = env->trap_vector;
122 env->pregs[PRV10_BRP] = env->pc;
123 break;
124
125 case EXCP_NMI:
126 /* NMI is hardwired to vector zero. */
127 ex_vec = 0;
128 env->pregs[PR_CCS] &= ~M_FLAG_V10;
129 env->pregs[PRV10_BRP] = env->pc;
130 break;
131
132 case EXCP_BUSFAULT:
133 cpu_abort(env, "Unhandled busfault");
134 break;
135
136 default:
137 /* The interrupt controller gives us the vector. */
138 ex_vec = env->interrupt_vector;
139 /* Normal interrupts are taken between
140 TB's. env->pc is valid here. */
141 env->pregs[PR_ERP] = env->pc;
142 break;
143 }
144
145 if (env->pregs[PR_CCS] & U_FLAG) {
146 /* Swap stack pointers. */
147 env->pregs[PR_USP] = env->regs[R_SP];
148 env->regs[R_SP] = env->ksp;
149 }
150
151 /* Now that we are in kernel mode, load the handlers address. */
152 env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
153 env->locked_irq = 1;
154 env->pregs[PR_CCS] |= F_FLAG_V10; /* set F. */
155
156 qemu_log_mask(CPU_LOG_INT, "%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
157 __func__, env->pc, ex_vec,
158 env->pregs[PR_CCS],
159 env->pregs[PR_PID],
160 env->pregs[PR_ERP]);
161 }
162
163 void do_interrupt(CPUCRISState *env)
164 {
165 int ex_vec = -1;
166
167 if (env->pregs[PR_VR] < 32) {
168 return do_interruptv10(env);
169 }
170
171 D_LOG("exception index=%d interrupt_req=%d\n",
172 env->exception_index,
173 env->interrupt_request);
174
175 switch (env->exception_index) {
176 case EXCP_BREAK:
177 /* These exceptions are genereated by the core itself.
178 ERP should point to the insn following the brk. */
179 ex_vec = env->trap_vector;
180 env->pregs[PR_ERP] = env->pc;
181 break;
182
183 case EXCP_NMI:
184 /* NMI is hardwired to vector zero. */
185 ex_vec = 0;
186 env->pregs[PR_CCS] &= ~M_FLAG_V32;
187 env->pregs[PR_NRP] = env->pc;
188 break;
189
190 case EXCP_BUSFAULT:
191 ex_vec = env->fault_vector;
192 env->pregs[PR_ERP] = env->pc;
193 break;
194
195 default:
196 /* The interrupt controller gives us the vector. */
197 ex_vec = env->interrupt_vector;
198 /* Normal interrupts are taken between
199 TB's. env->pc is valid here. */
200 env->pregs[PR_ERP] = env->pc;
201 break;
202 }
203
204 /* Fill in the IDX field. */
205 env->pregs[PR_EXS] = (ex_vec & 0xff) << 8;
206
207 if (env->dslot) {
208 D_LOG("excp isr=%x PC=%x ds=%d SP=%x"
209 " ERP=%x pid=%x ccs=%x cc=%d %x\n",
210 ex_vec, env->pc, env->dslot,
211 env->regs[R_SP],
212 env->pregs[PR_ERP], env->pregs[PR_PID],
213 env->pregs[PR_CCS],
214 env->cc_op, env->cc_mask);
215 /* We loose the btarget, btaken state here so rexec the
216 branch. */
217 env->pregs[PR_ERP] -= env->dslot;
218 /* Exception starts with dslot cleared. */
219 env->dslot = 0;
220 }
221
222 if (env->pregs[PR_CCS] & U_FLAG) {
223 /* Swap stack pointers. */
224 env->pregs[PR_USP] = env->regs[R_SP];
225 env->regs[R_SP] = env->ksp;
226 }
227
228 /* Apply the CRIS CCS shift. Clears U if set. */
229 cris_shift_ccs(env);
230
231 /* Now that we are in kernel mode, load the handlers address.
232 This load may not fault, real hw leaves that behaviour as
233 undefined. */
234 env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
235
236 /* Clear the excption_index to avoid spurios hw_aborts for recursive
237 bus faults. */
238 env->exception_index = -1;
239
240 D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
241 __func__, env->pc, ex_vec,
242 env->pregs[PR_CCS],
243 env->pregs[PR_PID],
244 env->pregs[PR_ERP]);
245 }
246
247 hwaddr cpu_get_phys_page_debug(CPUCRISState * env, target_ulong addr)
248 {
249 uint32_t phy = addr;
250 struct cris_mmu_result res;
251 int miss;
252
253 miss = cris_mmu_translate(&res, env, addr, 0, 0, 1);
254 /* If D TLB misses, try I TLB. */
255 if (miss) {
256 miss = cris_mmu_translate(&res, env, addr, 2, 0, 1);
257 }
258
259 if (!miss) {
260 phy = res.phy;
261 }
262 D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy));
263 return phy;
264 }
265 #endif