Statistics
| Branch: | Revision:

root / target-cris / helper.c @ a8170e5e

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