Statistics
| Branch: | Revision:

root / target-cris / helper.c @ 0d84be5b

History | View | Annotate | Download (6.4 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 be9f2ded Edgar E. Iglesias
                                  rw, mmu_idx);
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 d4c430a8 Paul Brook
                             prot | PAGE_EXEC, 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 218951ef Edgar E. Iglesias
        /* Now that we are in kernel mode, load the handlers address.  */
239 218951ef Edgar E. Iglesias
        env->pc = ldl_code(env->pregs[PR_EBP] + ex_vec * 4);
240 218951ef Edgar E. Iglesias
241 7a977356 Edgar E. Iglesias
        D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
242 7a977356 Edgar E. Iglesias
                   __func__, env->pc, ex_vec,
243 b41f7df0 edgar_igl
                   env->pregs[PR_CCS],
244 b41f7df0 edgar_igl
                   env->pregs[PR_PID], 
245 d12d51d5 aliguori
                   env->pregs[PR_ERP]);
246 81fdc5f8 ths
}
247 81fdc5f8 ths
248 c227f099 Anthony Liguori
target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
249 81fdc5f8 ths
{
250 81fdc5f8 ths
        uint32_t phy = addr;
251 2fa73ec8 Edgar E. Iglesias
        struct cris_mmu_result res;
252 81fdc5f8 ths
        int miss;
253 81fdc5f8 ths
        miss = cris_mmu_translate(&res, env, addr, 0, 0);
254 81fdc5f8 ths
        if (!miss)
255 81fdc5f8 ths
                phy = res.phy;
256 e62b5b13 edgar_igl
        D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy));
257 81fdc5f8 ths
        return phy;
258 81fdc5f8 ths
}
259 81fdc5f8 ths
#endif