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