Statistics
| Branch: | Revision:

root / target-cris / helper.c @ 1de7afc9

History | View | Annotate | Download (6.7 kB)

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
        {
79
                if (env->exception_index == EXCP_BUSFAULT)
80
                        cpu_abort(env,
81
                                  "CRIS: Illegal recursive bus fault."
82
                                 "addr=%x rw=%d\n",
83
                                 address, rw);
84

    
85
                env->pregs[PR_EDA] = address;
86
                env->exception_index = EXCP_BUSFAULT;
87
                env->fault_vector = res.bf_vec;
88
                r = 1;
89
        }
90
        else
91
        {
92
                /*
93
                 * Mask off the cache selection bit. The ETRAX busses do not
94
                 * see the top bit.
95
                 */
96
                phy = res.phy & ~0x80000000;
97
                prot = res.prot;
98
                tlb_set_page(env, address & TARGET_PAGE_MASK, phy,
99
                             prot, mmu_idx, TARGET_PAGE_SIZE);
100
                r = 0;
101
        }
102
        if (r > 0)
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);
106
        return r;
107
}
108

    
109
static void do_interruptv10(CPUCRISState *env)
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;
124
                        env->pregs[PRV10_BRP] = env->pc;
125
                        break;
126

    
127
                case EXCP_NMI:
128
                        /* NMI is hardwired to vector zero.  */
129
                        ex_vec = 0;
130
                        env->pregs[PR_CCS] &= ~M_FLAG_V10;
131
                        env->pregs[PRV10_BRP] = env->pc;
132
                        break;
133

    
134
                case EXCP_BUSFAULT:
135
                        cpu_abort(env, "Unhandled busfault");
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.  */
154
        env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
155
        env->locked_irq = 1;
156
        env->pregs[PR_CCS] |= F_FLAG_V10; /* set F.  */
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

    
165
void do_interrupt(CPUCRISState *env)
166
{
167
        int ex_vec = -1;
168

    
169
        if (env->pregs[PR_VR] < 32)
170
                return do_interruptv10(env);
171

    
172
        D_LOG( "exception index=%d interrupt_req=%d\n",
173
                   env->exception_index,
174
                   env->interrupt_request);
175

    
176
        switch (env->exception_index)
177
        {
178
                case EXCP_BREAK:
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;
182
                        env->pregs[PR_ERP] = env->pc;
183
                        break;
184

    
185
                case EXCP_NMI:
186
                        /* NMI is hardwired to vector zero.  */
187
                        ex_vec = 0;
188
                        env->pregs[PR_CCS] &= ~M_FLAG_V32;
189
                        env->pregs[PR_NRP] = env->pc;
190
                        break;
191

    
192
                case EXCP_BUSFAULT:
193
                        ex_vec = env->fault_vector;
194
                        env->pregs[PR_ERP] = env->pc;
195
                        break;
196

    
197
                default:
198
                        /* The interrupt controller gives us the vector.  */
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

    
206
        /* Fill in the IDX field.  */
207
        env->pregs[PR_EXS] = (ex_vec & 0xff) << 8;
208

    
209
        if (env->dslot) {
210
                D_LOG("excp isr=%x PC=%x ds=%d SP=%x"
211
                          " ERP=%x pid=%x ccs=%x cc=%d %x\n",
212
                          ex_vec, env->pc, env->dslot,
213
                          env->regs[R_SP],
214
                          env->pregs[PR_ERP], env->pregs[PR_PID],
215
                          env->pregs[PR_CCS],
216
                          env->cc_op, env->cc_mask);
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;
222
        }
223
        
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.  */
231
        cris_shift_ccs(env);
232

    
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.  */
236
        env->pc = cpu_ldl_code(env, env->pregs[PR_EBP] + ex_vec * 4);
237

    
238
        /* Clear the excption_index to avoid spurios hw_aborts for recursive
239
           bus faults.  */
240
        env->exception_index = -1;
241

    
242
        D_LOG("%s isr=%x vec=%x ccs=%x pid=%d erp=%x\n",
243
                   __func__, env->pc, ex_vec,
244
                   env->pregs[PR_CCS],
245
                   env->pregs[PR_PID], 
246
                   env->pregs[PR_ERP]);
247
}
248

    
249
hwaddr cpu_get_phys_page_debug(CPUCRISState * env, target_ulong addr)
250
{
251
        uint32_t phy = addr;
252
        struct cris_mmu_result res;
253
        int miss;
254

    
255
        miss = cris_mmu_translate(&res, env, addr, 0, 0, 1);
256
        /* If D TLB misses, try I TLB.  */
257
        if (miss) {
258
                miss = cris_mmu_translate(&res, env, addr, 2, 0, 1);
259
        }
260

    
261
        if (!miss)
262
                phy = res.phy;
263
        D(fprintf(stderr, "%s %x -> %x\n", __func__, addr, phy));
264
        return phy;
265
}
266
#endif