Statistics
| Branch: | Revision:

root / target-cris / helper.c @ 85097db6

History | View | Annotate | Download (6.7 kB)

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