Statistics
| Branch: | Revision:

root / target-arm / helper.c @ 9ee6e8bb

History | View | Annotate | Download (50.3 kB)

1 b5ff1b31 bellard
#include <stdio.h>
2 b5ff1b31 bellard
#include <stdlib.h>
3 b5ff1b31 bellard
#include <string.h>
4 b5ff1b31 bellard
5 b5ff1b31 bellard
#include "cpu.h"
6 b5ff1b31 bellard
#include "exec-all.h"
7 9ee6e8bb pbrook
#include "gdbstub.h"
8 9ee6e8bb pbrook
9 9ee6e8bb pbrook
static uint32_t cortexa8_cp15_c0_c1[8] =
10 9ee6e8bb pbrook
{ 0x1031, 0x11, 0x400, 0, 0x31100003, 0x20000000, 0x01202000, 0x11 };
11 9ee6e8bb pbrook
12 9ee6e8bb pbrook
static uint32_t cortexa8_cp15_c0_c2[8] =
13 9ee6e8bb pbrook
{ 0x00101111, 0x12112111, 0x21232031, 0x11112131, 0x00111142, 0, 0, 0 };
14 9ee6e8bb pbrook
15 9ee6e8bb pbrook
static uint32_t mpcore_cp15_c0_c1[8] =
16 9ee6e8bb pbrook
{ 0x111, 0x1, 0, 0x2, 0x01100103, 0x10020302, 0x01222000, 0 };
17 9ee6e8bb pbrook
18 9ee6e8bb pbrook
static uint32_t mpcore_cp15_c0_c2[8] =
19 9ee6e8bb pbrook
{ 0x00100011, 0x12002111, 0x11221011, 0x01102131, 0x141, 0, 0, 0 };
20 9ee6e8bb pbrook
21 9ee6e8bb pbrook
static uint32_t arm1136_cp15_c0_c1[8] =
22 9ee6e8bb pbrook
{ 0x111, 0x1, 0x2, 0x3, 0x01130003, 0x10030302, 0x01222110, 0 };
23 9ee6e8bb pbrook
24 9ee6e8bb pbrook
static uint32_t arm1136_cp15_c0_c2[8] =
25 9ee6e8bb pbrook
{ 0x00140011, 0x12002111, 0x11231111, 0x01102131, 0x141, 0, 0, 0 };
26 b5ff1b31 bellard
27 aaed909a bellard
static uint32_t cpu_arm_find_by_name(const char *name);
28 aaed909a bellard
29 f3d6b95e pbrook
static inline void set_feature(CPUARMState *env, int feature)
30 f3d6b95e pbrook
{
31 f3d6b95e pbrook
    env->features |= 1u << feature;
32 f3d6b95e pbrook
}
33 f3d6b95e pbrook
34 f3d6b95e pbrook
static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
35 f3d6b95e pbrook
{
36 f3d6b95e pbrook
    env->cp15.c0_cpuid = id;
37 f3d6b95e pbrook
    switch (id) {
38 f3d6b95e pbrook
    case ARM_CPUID_ARM926:
39 f3d6b95e pbrook
        set_feature(env, ARM_FEATURE_VFP);
40 f3d6b95e pbrook
        env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
41 c1713132 balrog
        env->cp15.c0_cachetype = 0x1dd20d2;
42 610c3c8a balrog
        env->cp15.c1_sys = 0x00090078;
43 f3d6b95e pbrook
        break;
44 ce819861 pbrook
    case ARM_CPUID_ARM946:
45 ce819861 pbrook
        set_feature(env, ARM_FEATURE_MPU);
46 ce819861 pbrook
        env->cp15.c0_cachetype = 0x0f004006;
47 610c3c8a balrog
        env->cp15.c1_sys = 0x00000078;
48 ce819861 pbrook
        break;
49 f3d6b95e pbrook
    case ARM_CPUID_ARM1026:
50 f3d6b95e pbrook
        set_feature(env, ARM_FEATURE_VFP);
51 f3d6b95e pbrook
        set_feature(env, ARM_FEATURE_AUXCR);
52 f3d6b95e pbrook
        env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0;
53 c1713132 balrog
        env->cp15.c0_cachetype = 0x1dd20d2;
54 610c3c8a balrog
        env->cp15.c1_sys = 0x00090078;
55 c1713132 balrog
        break;
56 9ee6e8bb pbrook
    case ARM_CPUID_ARM1136:
57 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_V6);
58 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_VFP);
59 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_AUXCR);
60 9ee6e8bb pbrook
        env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b4;
61 9ee6e8bb pbrook
        env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111;
62 9ee6e8bb pbrook
        env->vfp.xregs[ARM_VFP_MVFR1] = 0x00000000;
63 9ee6e8bb pbrook
        memcpy(env->cp15.c0_c1, arm1136_cp15_c0_c1, 8 * sizeof(uint32_t));
64 9ee6e8bb pbrook
        memcpy(env->cp15.c0_c1, arm1136_cp15_c0_c2, 8 * sizeof(uint32_t));
65 9ee6e8bb pbrook
        env->cp15.c0_cachetype = 0x1dd20d2;
66 9ee6e8bb pbrook
        break;
67 9ee6e8bb pbrook
    case ARM_CPUID_ARM11MPCORE:
68 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_V6);
69 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_V6K);
70 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_VFP);
71 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_AUXCR);
72 9ee6e8bb pbrook
        env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b4;
73 9ee6e8bb pbrook
        env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111;
74 9ee6e8bb pbrook
        env->vfp.xregs[ARM_VFP_MVFR1] = 0x00000000;
75 9ee6e8bb pbrook
        memcpy(env->cp15.c0_c1, mpcore_cp15_c0_c1, 8 * sizeof(uint32_t));
76 9ee6e8bb pbrook
        memcpy(env->cp15.c0_c1, mpcore_cp15_c0_c2, 8 * sizeof(uint32_t));
77 9ee6e8bb pbrook
        env->cp15.c0_cachetype = 0x1dd20d2;
78 9ee6e8bb pbrook
        break;
79 9ee6e8bb pbrook
    case ARM_CPUID_CORTEXA8:
80 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_V6);
81 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_V6K);
82 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_V7);
83 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_AUXCR);
84 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_THUMB2);
85 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_VFP);
86 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_VFP3);
87 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_NEON);
88 9ee6e8bb pbrook
        env->vfp.xregs[ARM_VFP_FPSID] = 0x410330c0;
89 9ee6e8bb pbrook
        env->vfp.xregs[ARM_VFP_MVFR0] = 0x11110222;
90 9ee6e8bb pbrook
        env->vfp.xregs[ARM_VFP_MVFR1] = 0x00011100;
91 9ee6e8bb pbrook
        memcpy(env->cp15.c0_c1, cortexa8_cp15_c0_c1, 8 * sizeof(uint32_t));
92 9ee6e8bb pbrook
        memcpy(env->cp15.c0_c1, cortexa8_cp15_c0_c2, 8 * sizeof(uint32_t));
93 9ee6e8bb pbrook
        env->cp15.c0_cachetype = 0x1dd20d2;
94 9ee6e8bb pbrook
        break;
95 9ee6e8bb pbrook
    case ARM_CPUID_CORTEXM3:
96 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_V6);
97 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_THUMB2);
98 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_V7);
99 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_M);
100 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_DIV);
101 9ee6e8bb pbrook
        break;
102 9ee6e8bb pbrook
    case ARM_CPUID_ANY: /* For userspace emulation.  */
103 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_V6);
104 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_V6K);
105 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_V7);
106 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_THUMB2);
107 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_VFP);
108 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_VFP3);
109 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_NEON);
110 9ee6e8bb pbrook
        set_feature(env, ARM_FEATURE_DIV);
111 9ee6e8bb pbrook
        break;
112 c3d2689d balrog
    case ARM_CPUID_TI915T:
113 c3d2689d balrog
    case ARM_CPUID_TI925T:
114 c3d2689d balrog
        set_feature(env, ARM_FEATURE_OMAPCP);
115 c3d2689d balrog
        env->cp15.c0_cpuid = ARM_CPUID_TI925T; /* Depends on wiring.  */
116 c3d2689d balrog
        env->cp15.c0_cachetype = 0x5109149;
117 c3d2689d balrog
        env->cp15.c1_sys = 0x00000070;
118 c3d2689d balrog
        env->cp15.c15_i_max = 0x000;
119 c3d2689d balrog
        env->cp15.c15_i_min = 0xff0;
120 c3d2689d balrog
        break;
121 c1713132 balrog
    case ARM_CPUID_PXA250:
122 c1713132 balrog
    case ARM_CPUID_PXA255:
123 c1713132 balrog
    case ARM_CPUID_PXA260:
124 c1713132 balrog
    case ARM_CPUID_PXA261:
125 c1713132 balrog
    case ARM_CPUID_PXA262:
126 c1713132 balrog
        set_feature(env, ARM_FEATURE_XSCALE);
127 c1713132 balrog
        /* JTAG_ID is ((id << 28) | 0x09265013) */
128 c1713132 balrog
        env->cp15.c0_cachetype = 0xd172172;
129 610c3c8a balrog
        env->cp15.c1_sys = 0x00000078;
130 c1713132 balrog
        break;
131 c1713132 balrog
    case ARM_CPUID_PXA270_A0:
132 c1713132 balrog
    case ARM_CPUID_PXA270_A1:
133 c1713132 balrog
    case ARM_CPUID_PXA270_B0:
134 c1713132 balrog
    case ARM_CPUID_PXA270_B1:
135 c1713132 balrog
    case ARM_CPUID_PXA270_C0:
136 c1713132 balrog
    case ARM_CPUID_PXA270_C5:
137 c1713132 balrog
        set_feature(env, ARM_FEATURE_XSCALE);
138 c1713132 balrog
        /* JTAG_ID is ((id << 28) | 0x09265013) */
139 18c9b560 balrog
        set_feature(env, ARM_FEATURE_IWMMXT);
140 18c9b560 balrog
        env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q';
141 c1713132 balrog
        env->cp15.c0_cachetype = 0xd172172;
142 610c3c8a balrog
        env->cp15.c1_sys = 0x00000078;
143 f3d6b95e pbrook
        break;
144 f3d6b95e pbrook
    default:
145 f3d6b95e pbrook
        cpu_abort(env, "Bad CPU ID: %x\n", id);
146 f3d6b95e pbrook
        break;
147 f3d6b95e pbrook
    }
148 f3d6b95e pbrook
}
149 f3d6b95e pbrook
150 40f137e1 pbrook
void cpu_reset(CPUARMState *env)
151 40f137e1 pbrook
{
152 f3d6b95e pbrook
    uint32_t id;
153 f3d6b95e pbrook
    id = env->cp15.c0_cpuid;
154 f3d6b95e pbrook
    memset(env, 0, offsetof(CPUARMState, breakpoints));
155 f3d6b95e pbrook
    if (id)
156 f3d6b95e pbrook
        cpu_reset_model_id(env, id);
157 40f137e1 pbrook
#if defined (CONFIG_USER_ONLY)
158 40f137e1 pbrook
    env->uncached_cpsr = ARM_CPU_MODE_USR;
159 40f137e1 pbrook
    env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30;
160 40f137e1 pbrook
#else
161 40f137e1 pbrook
    /* SVC mode with interrupts disabled.  */
162 40f137e1 pbrook
    env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
163 9ee6e8bb pbrook
    /* On ARMv7-M the CPSR_I is the value of the PRIMASK register, and is
164 9ee6e8bb pbrook
       clear at reset.  */
165 9ee6e8bb pbrook
    if (IS_M(env))
166 9ee6e8bb pbrook
        env->uncached_cpsr &= ~CPSR_I;
167 40f137e1 pbrook
    env->vfp.xregs[ARM_VFP_FPEXC] = 0;
168 40f137e1 pbrook
#endif
169 40f137e1 pbrook
    env->regs[15] = 0;
170 f3d6b95e pbrook
    tlb_flush(env, 1);
171 40f137e1 pbrook
}
172 40f137e1 pbrook
173 aaed909a bellard
CPUARMState *cpu_arm_init(const char *cpu_model)
174 40f137e1 pbrook
{
175 40f137e1 pbrook
    CPUARMState *env;
176 aaed909a bellard
    uint32_t id;
177 40f137e1 pbrook
178 aaed909a bellard
    id = cpu_arm_find_by_name(cpu_model);
179 aaed909a bellard
    if (id == 0)
180 aaed909a bellard
        return NULL;
181 40f137e1 pbrook
    env = qemu_mallocz(sizeof(CPUARMState));
182 40f137e1 pbrook
    if (!env)
183 40f137e1 pbrook
        return NULL;
184 40f137e1 pbrook
    cpu_exec_init(env);
185 aaed909a bellard
    env->cp15.c0_cpuid = id;
186 40f137e1 pbrook
    cpu_reset(env);
187 40f137e1 pbrook
    return env;
188 40f137e1 pbrook
}
189 40f137e1 pbrook
190 3371d272 pbrook
struct arm_cpu_t {
191 3371d272 pbrook
    uint32_t id;
192 3371d272 pbrook
    const char *name;
193 3371d272 pbrook
};
194 3371d272 pbrook
195 3371d272 pbrook
static const struct arm_cpu_t arm_cpu_names[] = {
196 3371d272 pbrook
    { ARM_CPUID_ARM926, "arm926"},
197 ce819861 pbrook
    { ARM_CPUID_ARM946, "arm946"},
198 3371d272 pbrook
    { ARM_CPUID_ARM1026, "arm1026"},
199 9ee6e8bb pbrook
    { ARM_CPUID_ARM1136, "arm1136"},
200 9ee6e8bb pbrook
    { ARM_CPUID_ARM11MPCORE, "arm11mpcore"},
201 9ee6e8bb pbrook
    { ARM_CPUID_CORTEXM3, "cortex-m3"},
202 9ee6e8bb pbrook
    { ARM_CPUID_CORTEXA8, "cortex-a8"},
203 c3d2689d balrog
    { ARM_CPUID_TI925T, "ti925t" },
204 c1713132 balrog
    { ARM_CPUID_PXA250, "pxa250" },
205 c1713132 balrog
    { ARM_CPUID_PXA255, "pxa255" },
206 c1713132 balrog
    { ARM_CPUID_PXA260, "pxa260" },
207 c1713132 balrog
    { ARM_CPUID_PXA261, "pxa261" },
208 c1713132 balrog
    { ARM_CPUID_PXA262, "pxa262" },
209 c1713132 balrog
    { ARM_CPUID_PXA270, "pxa270" },
210 c1713132 balrog
    { ARM_CPUID_PXA270_A0, "pxa270-a0" },
211 c1713132 balrog
    { ARM_CPUID_PXA270_A1, "pxa270-a1" },
212 c1713132 balrog
    { ARM_CPUID_PXA270_B0, "pxa270-b0" },
213 c1713132 balrog
    { ARM_CPUID_PXA270_B1, "pxa270-b1" },
214 c1713132 balrog
    { ARM_CPUID_PXA270_C0, "pxa270-c0" },
215 c1713132 balrog
    { ARM_CPUID_PXA270_C5, "pxa270-c5" },
216 9ee6e8bb pbrook
    { ARM_CPUID_ANY, "any"},
217 3371d272 pbrook
    { 0, NULL}
218 3371d272 pbrook
};
219 3371d272 pbrook
220 c732abe2 j_mayer
void arm_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
221 5adb4839 pbrook
{
222 5adb4839 pbrook
    int i;
223 5adb4839 pbrook
224 c732abe2 j_mayer
    (*cpu_fprintf)(f, "Available CPUs:\n");
225 5adb4839 pbrook
    for (i = 0; arm_cpu_names[i].name; i++) {
226 c732abe2 j_mayer
        (*cpu_fprintf)(f, "  %s\n", arm_cpu_names[i].name);
227 5adb4839 pbrook
    }
228 5adb4839 pbrook
}
229 5adb4839 pbrook
230 aaed909a bellard
/* return 0 if not found */
231 aaed909a bellard
static uint32_t cpu_arm_find_by_name(const char *name)
232 40f137e1 pbrook
{
233 3371d272 pbrook
    int i;
234 3371d272 pbrook
    uint32_t id;
235 3371d272 pbrook
236 3371d272 pbrook
    id = 0;
237 3371d272 pbrook
    for (i = 0; arm_cpu_names[i].name; i++) {
238 3371d272 pbrook
        if (strcmp(name, arm_cpu_names[i].name) == 0) {
239 3371d272 pbrook
            id = arm_cpu_names[i].id;
240 3371d272 pbrook
            break;
241 3371d272 pbrook
        }
242 3371d272 pbrook
    }
243 aaed909a bellard
    return id;
244 40f137e1 pbrook
}
245 40f137e1 pbrook
246 40f137e1 pbrook
void cpu_arm_close(CPUARMState *env)
247 40f137e1 pbrook
{
248 40f137e1 pbrook
    free(env);
249 40f137e1 pbrook
}
250 40f137e1 pbrook
251 9ee6e8bb pbrook
/* Polynomial multiplication is like integer multiplcation except the
252 9ee6e8bb pbrook
   partial products are XORed, not added.  */
253 9ee6e8bb pbrook
uint32_t helper_neon_mul_p8(uint32_t op1, uint32_t op2)
254 9ee6e8bb pbrook
{
255 9ee6e8bb pbrook
    uint32_t mask;
256 9ee6e8bb pbrook
    uint32_t result;
257 9ee6e8bb pbrook
    result = 0;
258 9ee6e8bb pbrook
    while (op1) {
259 9ee6e8bb pbrook
        mask = 0;
260 9ee6e8bb pbrook
        if (op1 & 1)
261 9ee6e8bb pbrook
            mask |= 0xff;
262 9ee6e8bb pbrook
        if (op1 & (1 << 8))
263 9ee6e8bb pbrook
            mask |= (0xff << 8);
264 9ee6e8bb pbrook
        if (op1 & (1 << 16))
265 9ee6e8bb pbrook
            mask |= (0xff << 16);
266 9ee6e8bb pbrook
        if (op1 & (1 << 24))
267 9ee6e8bb pbrook
            mask |= (0xff << 24);
268 9ee6e8bb pbrook
        result ^= op2 & mask;
269 9ee6e8bb pbrook
        op1 = (op1 >> 1) & 0x7f7f7f7f;
270 9ee6e8bb pbrook
        op2 = (op2 << 1) & 0xfefefefe;
271 9ee6e8bb pbrook
    }
272 9ee6e8bb pbrook
    return result;
273 9ee6e8bb pbrook
}
274 9ee6e8bb pbrook
275 5fafdf24 ths
#if defined(CONFIG_USER_ONLY)
276 b5ff1b31 bellard
277 b5ff1b31 bellard
void do_interrupt (CPUState *env)
278 b5ff1b31 bellard
{
279 b5ff1b31 bellard
    env->exception_index = -1;
280 b5ff1b31 bellard
}
281 b5ff1b31 bellard
282 9ee6e8bb pbrook
/* Structure used to record exclusive memory locations.  */
283 9ee6e8bb pbrook
typedef struct mmon_state {
284 9ee6e8bb pbrook
    struct mmon_state *next;
285 9ee6e8bb pbrook
    CPUARMState *cpu_env;
286 9ee6e8bb pbrook
    uint32_t addr;
287 9ee6e8bb pbrook
} mmon_state;
288 9ee6e8bb pbrook
289 9ee6e8bb pbrook
/* Chain of current locks.  */
290 9ee6e8bb pbrook
static mmon_state* mmon_head = NULL;
291 9ee6e8bb pbrook
292 b5ff1b31 bellard
int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
293 6ebbf390 j_mayer
                              int mmu_idx, int is_softmmu)
294 b5ff1b31 bellard
{
295 b5ff1b31 bellard
    if (rw == 2) {
296 b5ff1b31 bellard
        env->exception_index = EXCP_PREFETCH_ABORT;
297 b5ff1b31 bellard
        env->cp15.c6_insn = address;
298 b5ff1b31 bellard
    } else {
299 b5ff1b31 bellard
        env->exception_index = EXCP_DATA_ABORT;
300 b5ff1b31 bellard
        env->cp15.c6_data = address;
301 b5ff1b31 bellard
    }
302 b5ff1b31 bellard
    return 1;
303 b5ff1b31 bellard
}
304 b5ff1b31 bellard
305 9ee6e8bb pbrook
static void allocate_mmon_state(CPUState *env)
306 9ee6e8bb pbrook
{
307 9ee6e8bb pbrook
    env->mmon_entry = malloc(sizeof (mmon_state));
308 9ee6e8bb pbrook
    if (!env->mmon_entry)
309 9ee6e8bb pbrook
        abort();
310 9ee6e8bb pbrook
    memset (env->mmon_entry, 0, sizeof (mmon_state));
311 9ee6e8bb pbrook
    env->mmon_entry->cpu_env = env;
312 9ee6e8bb pbrook
    mmon_head = env->mmon_entry;
313 9ee6e8bb pbrook
}
314 9ee6e8bb pbrook
315 9ee6e8bb pbrook
/* Flush any monitor locks for the specified address.  */
316 9ee6e8bb pbrook
static void flush_mmon(uint32_t addr)
317 9ee6e8bb pbrook
{
318 9ee6e8bb pbrook
    mmon_state *mon;
319 9ee6e8bb pbrook
320 9ee6e8bb pbrook
    for (mon = mmon_head; mon; mon = mon->next)
321 9ee6e8bb pbrook
      {
322 9ee6e8bb pbrook
        if (mon->addr != addr)
323 9ee6e8bb pbrook
          continue;
324 9ee6e8bb pbrook
325 9ee6e8bb pbrook
        mon->addr = 0;
326 9ee6e8bb pbrook
        break;
327 9ee6e8bb pbrook
      }
328 9ee6e8bb pbrook
}
329 9ee6e8bb pbrook
330 9ee6e8bb pbrook
/* Mark an address for exclusive access.  */
331 9ee6e8bb pbrook
void helper_mark_exclusive(CPUState *env, uint32_t addr)
332 9ee6e8bb pbrook
{
333 9ee6e8bb pbrook
    if (!env->mmon_entry)
334 9ee6e8bb pbrook
        allocate_mmon_state(env);
335 9ee6e8bb pbrook
    /* Clear any previous locks.  */
336 9ee6e8bb pbrook
    flush_mmon(addr);
337 9ee6e8bb pbrook
    env->mmon_entry->addr = addr;
338 9ee6e8bb pbrook
}
339 9ee6e8bb pbrook
340 9ee6e8bb pbrook
/* Test if an exclusive address is still exclusive.  Returns zero
341 9ee6e8bb pbrook
   if the address is still exclusive.   */
342 9ee6e8bb pbrook
int helper_test_exclusive(CPUState *env, uint32_t addr)
343 9ee6e8bb pbrook
{
344 9ee6e8bb pbrook
    int res;
345 9ee6e8bb pbrook
346 9ee6e8bb pbrook
    if (!env->mmon_entry)
347 9ee6e8bb pbrook
        return 1;
348 9ee6e8bb pbrook
    if (env->mmon_entry->addr == addr)
349 9ee6e8bb pbrook
        res = 0;
350 9ee6e8bb pbrook
    else
351 9ee6e8bb pbrook
        res = 1;
352 9ee6e8bb pbrook
    flush_mmon(addr);
353 9ee6e8bb pbrook
    return res;
354 9ee6e8bb pbrook
}
355 9ee6e8bb pbrook
356 9ee6e8bb pbrook
void helper_clrex(CPUState *env)
357 9ee6e8bb pbrook
{
358 9ee6e8bb pbrook
    if (!(env->mmon_entry && env->mmon_entry->addr))
359 9ee6e8bb pbrook
        return;
360 9ee6e8bb pbrook
    flush_mmon(env->mmon_entry->addr);
361 9ee6e8bb pbrook
}
362 9ee6e8bb pbrook
363 9b3c35e0 j_mayer
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
364 b5ff1b31 bellard
{
365 b5ff1b31 bellard
    return addr;
366 b5ff1b31 bellard
}
367 b5ff1b31 bellard
368 b5ff1b31 bellard
/* These should probably raise undefined insn exceptions.  */
369 c1713132 balrog
void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val)
370 c1713132 balrog
{
371 c1713132 balrog
    int op1 = (insn >> 8) & 0xf;
372 c1713132 balrog
    cpu_abort(env, "cp%i insn %08x\n", op1, insn);
373 c1713132 balrog
    return;
374 c1713132 balrog
}
375 c1713132 balrog
376 c1713132 balrog
uint32_t helper_get_cp(CPUState *env, uint32_t insn)
377 c1713132 balrog
{
378 c1713132 balrog
    int op1 = (insn >> 8) & 0xf;
379 c1713132 balrog
    cpu_abort(env, "cp%i insn %08x\n", op1, insn);
380 c1713132 balrog
    return 0;
381 c1713132 balrog
}
382 c1713132 balrog
383 b5ff1b31 bellard
void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
384 b5ff1b31 bellard
{
385 b5ff1b31 bellard
    cpu_abort(env, "cp15 insn %08x\n", insn);
386 b5ff1b31 bellard
}
387 b5ff1b31 bellard
388 b5ff1b31 bellard
uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
389 b5ff1b31 bellard
{
390 b5ff1b31 bellard
    cpu_abort(env, "cp15 insn %08x\n", insn);
391 b5ff1b31 bellard
    return 0;
392 b5ff1b31 bellard
}
393 b5ff1b31 bellard
394 9ee6e8bb pbrook
/* These should probably raise undefined insn exceptions.  */
395 9ee6e8bb pbrook
void helper_v7m_msr(CPUState *env, int reg, uint32_t val)
396 9ee6e8bb pbrook
{
397 9ee6e8bb pbrook
    cpu_abort(env, "v7m_mrs %d\n", reg);
398 9ee6e8bb pbrook
}
399 9ee6e8bb pbrook
400 9ee6e8bb pbrook
uint32_t helper_v7m_mrs(CPUState *env, int reg)
401 9ee6e8bb pbrook
{
402 9ee6e8bb pbrook
    cpu_abort(env, "v7m_mrs %d\n", reg);
403 9ee6e8bb pbrook
    return 0;
404 9ee6e8bb pbrook
}
405 9ee6e8bb pbrook
406 b5ff1b31 bellard
void switch_mode(CPUState *env, int mode)
407 b5ff1b31 bellard
{
408 b5ff1b31 bellard
    if (mode != ARM_CPU_MODE_USR)
409 b5ff1b31 bellard
        cpu_abort(env, "Tried to switch out of user mode\n");
410 b5ff1b31 bellard
}
411 b5ff1b31 bellard
412 9ee6e8bb pbrook
void helper_set_r13_banked(CPUState *env, int mode, uint32_t val)
413 9ee6e8bb pbrook
{
414 9ee6e8bb pbrook
    cpu_abort(env, "banked r13 write\n");
415 9ee6e8bb pbrook
}
416 9ee6e8bb pbrook
417 9ee6e8bb pbrook
uint32_t helper_get_r13_banked(CPUState *env, int mode)
418 9ee6e8bb pbrook
{
419 9ee6e8bb pbrook
    cpu_abort(env, "banked r13 read\n");
420 9ee6e8bb pbrook
    return 0;
421 9ee6e8bb pbrook
}
422 9ee6e8bb pbrook
423 b5ff1b31 bellard
#else
424 b5ff1b31 bellard
425 8e71621f pbrook
extern int semihosting_enabled;
426 8e71621f pbrook
427 b5ff1b31 bellard
/* Map CPU modes onto saved register banks.  */
428 b5ff1b31 bellard
static inline int bank_number (int mode)
429 b5ff1b31 bellard
{
430 b5ff1b31 bellard
    switch (mode) {
431 b5ff1b31 bellard
    case ARM_CPU_MODE_USR:
432 b5ff1b31 bellard
    case ARM_CPU_MODE_SYS:
433 b5ff1b31 bellard
        return 0;
434 b5ff1b31 bellard
    case ARM_CPU_MODE_SVC:
435 b5ff1b31 bellard
        return 1;
436 b5ff1b31 bellard
    case ARM_CPU_MODE_ABT:
437 b5ff1b31 bellard
        return 2;
438 b5ff1b31 bellard
    case ARM_CPU_MODE_UND:
439 b5ff1b31 bellard
        return 3;
440 b5ff1b31 bellard
    case ARM_CPU_MODE_IRQ:
441 b5ff1b31 bellard
        return 4;
442 b5ff1b31 bellard
    case ARM_CPU_MODE_FIQ:
443 b5ff1b31 bellard
        return 5;
444 b5ff1b31 bellard
    }
445 b5ff1b31 bellard
    cpu_abort(cpu_single_env, "Bad mode %x\n", mode);
446 b5ff1b31 bellard
    return -1;
447 b5ff1b31 bellard
}
448 b5ff1b31 bellard
449 b5ff1b31 bellard
void switch_mode(CPUState *env, int mode)
450 b5ff1b31 bellard
{
451 b5ff1b31 bellard
    int old_mode;
452 b5ff1b31 bellard
    int i;
453 b5ff1b31 bellard
454 b5ff1b31 bellard
    old_mode = env->uncached_cpsr & CPSR_M;
455 b5ff1b31 bellard
    if (mode == old_mode)
456 b5ff1b31 bellard
        return;
457 b5ff1b31 bellard
458 b5ff1b31 bellard
    if (old_mode == ARM_CPU_MODE_FIQ) {
459 b5ff1b31 bellard
        memcpy (env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
460 8637c67f pbrook
        memcpy (env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
461 b5ff1b31 bellard
    } else if (mode == ARM_CPU_MODE_FIQ) {
462 b5ff1b31 bellard
        memcpy (env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
463 8637c67f pbrook
        memcpy (env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
464 b5ff1b31 bellard
    }
465 b5ff1b31 bellard
466 b5ff1b31 bellard
    i = bank_number(old_mode);
467 b5ff1b31 bellard
    env->banked_r13[i] = env->regs[13];
468 b5ff1b31 bellard
    env->banked_r14[i] = env->regs[14];
469 b5ff1b31 bellard
    env->banked_spsr[i] = env->spsr;
470 b5ff1b31 bellard
471 b5ff1b31 bellard
    i = bank_number(mode);
472 b5ff1b31 bellard
    env->regs[13] = env->banked_r13[i];
473 b5ff1b31 bellard
    env->regs[14] = env->banked_r14[i];
474 b5ff1b31 bellard
    env->spsr = env->banked_spsr[i];
475 b5ff1b31 bellard
}
476 b5ff1b31 bellard
477 9ee6e8bb pbrook
static void v7m_push(CPUARMState *env, uint32_t val)
478 9ee6e8bb pbrook
{
479 9ee6e8bb pbrook
    env->regs[13] -= 4;
480 9ee6e8bb pbrook
    stl_phys(env->regs[13], val);
481 9ee6e8bb pbrook
}
482 9ee6e8bb pbrook
483 9ee6e8bb pbrook
static uint32_t v7m_pop(CPUARMState *env)
484 9ee6e8bb pbrook
{
485 9ee6e8bb pbrook
    uint32_t val;
486 9ee6e8bb pbrook
    val = ldl_phys(env->regs[13]);
487 9ee6e8bb pbrook
    env->regs[13] += 4;
488 9ee6e8bb pbrook
    return val;
489 9ee6e8bb pbrook
}
490 9ee6e8bb pbrook
491 9ee6e8bb pbrook
/* Switch to V7M main or process stack pointer.  */
492 9ee6e8bb pbrook
static void switch_v7m_sp(CPUARMState *env, int process)
493 9ee6e8bb pbrook
{
494 9ee6e8bb pbrook
    uint32_t tmp;
495 9ee6e8bb pbrook
    if (env->v7m.current_sp != process) {
496 9ee6e8bb pbrook
        tmp = env->v7m.other_sp;
497 9ee6e8bb pbrook
        env->v7m.other_sp = env->regs[13];
498 9ee6e8bb pbrook
        env->regs[13] = tmp;
499 9ee6e8bb pbrook
        env->v7m.current_sp = process;
500 9ee6e8bb pbrook
    }
501 9ee6e8bb pbrook
}
502 9ee6e8bb pbrook
503 9ee6e8bb pbrook
static void do_v7m_exception_exit(CPUARMState *env)
504 9ee6e8bb pbrook
{
505 9ee6e8bb pbrook
    uint32_t type;
506 9ee6e8bb pbrook
    uint32_t xpsr;
507 9ee6e8bb pbrook
508 9ee6e8bb pbrook
    type = env->regs[15];
509 9ee6e8bb pbrook
    if (env->v7m.exception != 0)
510 9ee6e8bb pbrook
        armv7m_nvic_complete_irq(env->v7m.nvic, env->v7m.exception);
511 9ee6e8bb pbrook
512 9ee6e8bb pbrook
    /* Switch to the target stack.  */
513 9ee6e8bb pbrook
    switch_v7m_sp(env, (type & 4) != 0);
514 9ee6e8bb pbrook
    /* Pop registers.  */
515 9ee6e8bb pbrook
    env->regs[0] = v7m_pop(env);
516 9ee6e8bb pbrook
    env->regs[1] = v7m_pop(env);
517 9ee6e8bb pbrook
    env->regs[2] = v7m_pop(env);
518 9ee6e8bb pbrook
    env->regs[3] = v7m_pop(env);
519 9ee6e8bb pbrook
    env->regs[12] = v7m_pop(env);
520 9ee6e8bb pbrook
    env->regs[14] = v7m_pop(env);
521 9ee6e8bb pbrook
    env->regs[15] = v7m_pop(env);
522 9ee6e8bb pbrook
    xpsr = v7m_pop(env);
523 9ee6e8bb pbrook
    xpsr_write(env, xpsr, 0xfffffdff);
524 9ee6e8bb pbrook
    /* Undo stack alignment.  */
525 9ee6e8bb pbrook
    if (xpsr & 0x200)
526 9ee6e8bb pbrook
        env->regs[13] |= 4;
527 9ee6e8bb pbrook
    /* ??? The exception return type specifies Thread/Handler mode.  However
528 9ee6e8bb pbrook
       this is also implied by the xPSR value. Not sure what to do
529 9ee6e8bb pbrook
       if there is a mismatch.  */
530 9ee6e8bb pbrook
    /* ??? Likewise for mismatches between the CONTROL register and the stack
531 9ee6e8bb pbrook
       pointer.  */
532 9ee6e8bb pbrook
}
533 9ee6e8bb pbrook
534 9ee6e8bb pbrook
void do_interrupt_v7m(CPUARMState *env)
535 9ee6e8bb pbrook
{
536 9ee6e8bb pbrook
    uint32_t xpsr = xpsr_read(env);
537 9ee6e8bb pbrook
    uint32_t lr;
538 9ee6e8bb pbrook
    uint32_t addr;
539 9ee6e8bb pbrook
540 9ee6e8bb pbrook
    lr = 0xfffffff1;
541 9ee6e8bb pbrook
    if (env->v7m.current_sp)
542 9ee6e8bb pbrook
        lr |= 4;
543 9ee6e8bb pbrook
    if (env->v7m.exception == 0)
544 9ee6e8bb pbrook
        lr |= 8;
545 9ee6e8bb pbrook
546 9ee6e8bb pbrook
    /* For exceptions we just mark as pending on the NVIC, and let that
547 9ee6e8bb pbrook
       handle it.  */
548 9ee6e8bb pbrook
    /* TODO: Need to escalate if the current priority is higher than the
549 9ee6e8bb pbrook
       one we're raising.  */
550 9ee6e8bb pbrook
    switch (env->exception_index) {
551 9ee6e8bb pbrook
    case EXCP_UDEF:
552 9ee6e8bb pbrook
        armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_USAGE);
553 9ee6e8bb pbrook
        return;
554 9ee6e8bb pbrook
    case EXCP_SWI:
555 9ee6e8bb pbrook
        env->regs[15] += 2;
556 9ee6e8bb pbrook
        armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_SVC);
557 9ee6e8bb pbrook
        return;
558 9ee6e8bb pbrook
    case EXCP_PREFETCH_ABORT:
559 9ee6e8bb pbrook
    case EXCP_DATA_ABORT:
560 9ee6e8bb pbrook
        armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_MEM);
561 9ee6e8bb pbrook
        return;
562 9ee6e8bb pbrook
    case EXCP_BKPT:
563 9ee6e8bb pbrook
        armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_DEBUG);
564 9ee6e8bb pbrook
        return;
565 9ee6e8bb pbrook
    case EXCP_IRQ:
566 9ee6e8bb pbrook
        env->v7m.exception = armv7m_nvic_acknowledge_irq(env->v7m.nvic);
567 9ee6e8bb pbrook
        break;
568 9ee6e8bb pbrook
    case EXCP_EXCEPTION_EXIT:
569 9ee6e8bb pbrook
        do_v7m_exception_exit(env);
570 9ee6e8bb pbrook
        return;
571 9ee6e8bb pbrook
    default:
572 9ee6e8bb pbrook
        cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
573 9ee6e8bb pbrook
        return; /* Never happens.  Keep compiler happy.  */
574 9ee6e8bb pbrook
    }
575 9ee6e8bb pbrook
576 9ee6e8bb pbrook
    /* Align stack pointer.  */
577 9ee6e8bb pbrook
    /* ??? Should only do this if Configuration Control Register
578 9ee6e8bb pbrook
       STACKALIGN bit is set.  */
579 9ee6e8bb pbrook
    if (env->regs[13] & 4) {
580 9ee6e8bb pbrook
        env->regs[13] += 4;
581 9ee6e8bb pbrook
        xpsr |= 0x200;
582 9ee6e8bb pbrook
    }
583 9ee6e8bb pbrook
    /* Switch to the hander mode.  */
584 9ee6e8bb pbrook
    v7m_push(env, xpsr);
585 9ee6e8bb pbrook
    v7m_push(env, env->regs[15]);
586 9ee6e8bb pbrook
    v7m_push(env, env->regs[14]);
587 9ee6e8bb pbrook
    v7m_push(env, env->regs[12]);
588 9ee6e8bb pbrook
    v7m_push(env, env->regs[3]);
589 9ee6e8bb pbrook
    v7m_push(env, env->regs[2]);
590 9ee6e8bb pbrook
    v7m_push(env, env->regs[1]);
591 9ee6e8bb pbrook
    v7m_push(env, env->regs[0]);
592 9ee6e8bb pbrook
    switch_v7m_sp(env, 0);
593 9ee6e8bb pbrook
    env->uncached_cpsr &= ~CPSR_IT;
594 9ee6e8bb pbrook
    env->regs[14] = lr;
595 9ee6e8bb pbrook
    addr = ldl_phys(env->v7m.vecbase + env->v7m.exception * 4);
596 9ee6e8bb pbrook
    env->regs[15] = addr & 0xfffffffe;
597 9ee6e8bb pbrook
    env->thumb = addr & 1;
598 9ee6e8bb pbrook
}
599 9ee6e8bb pbrook
600 b5ff1b31 bellard
/* Handle a CPU exception.  */
601 b5ff1b31 bellard
void do_interrupt(CPUARMState *env)
602 b5ff1b31 bellard
{
603 b5ff1b31 bellard
    uint32_t addr;
604 b5ff1b31 bellard
    uint32_t mask;
605 b5ff1b31 bellard
    int new_mode;
606 b5ff1b31 bellard
    uint32_t offset;
607 b5ff1b31 bellard
608 9ee6e8bb pbrook
    if (IS_M(env)) {
609 9ee6e8bb pbrook
        do_interrupt_v7m(env);
610 9ee6e8bb pbrook
        return;
611 9ee6e8bb pbrook
    }
612 b5ff1b31 bellard
    /* TODO: Vectored interrupt controller.  */
613 b5ff1b31 bellard
    switch (env->exception_index) {
614 b5ff1b31 bellard
    case EXCP_UDEF:
615 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_UND;
616 b5ff1b31 bellard
        addr = 0x04;
617 b5ff1b31 bellard
        mask = CPSR_I;
618 b5ff1b31 bellard
        if (env->thumb)
619 b5ff1b31 bellard
            offset = 2;
620 b5ff1b31 bellard
        else
621 b5ff1b31 bellard
            offset = 4;
622 b5ff1b31 bellard
        break;
623 b5ff1b31 bellard
    case EXCP_SWI:
624 8e71621f pbrook
        if (semihosting_enabled) {
625 8e71621f pbrook
            /* Check for semihosting interrupt.  */
626 8e71621f pbrook
            if (env->thumb) {
627 8e71621f pbrook
                mask = lduw_code(env->regs[15] - 2) & 0xff;
628 8e71621f pbrook
            } else {
629 8e71621f pbrook
                mask = ldl_code(env->regs[15] - 4) & 0xffffff;
630 8e71621f pbrook
            }
631 8e71621f pbrook
            /* Only intercept calls from privileged modes, to provide some
632 8e71621f pbrook
               semblance of security.  */
633 8e71621f pbrook
            if (((mask == 0x123456 && !env->thumb)
634 8e71621f pbrook
                    || (mask == 0xab && env->thumb))
635 8e71621f pbrook
                  && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
636 8e71621f pbrook
                env->regs[0] = do_arm_semihosting(env);
637 8e71621f pbrook
                return;
638 8e71621f pbrook
            }
639 8e71621f pbrook
        }
640 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_SVC;
641 b5ff1b31 bellard
        addr = 0x08;
642 b5ff1b31 bellard
        mask = CPSR_I;
643 b5ff1b31 bellard
        /* The PC already points to the next instructon.  */
644 b5ff1b31 bellard
        offset = 0;
645 b5ff1b31 bellard
        break;
646 06c949e6 pbrook
    case EXCP_BKPT:
647 9ee6e8bb pbrook
        /* See if this is a semihosting syscall.  */
648 9ee6e8bb pbrook
        if (env->thumb) {
649 9ee6e8bb pbrook
            mask = lduw_code(env->regs[15]) & 0xff;
650 9ee6e8bb pbrook
            if (mask == 0xab
651 9ee6e8bb pbrook
                  && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
652 9ee6e8bb pbrook
                env->regs[15] += 2;
653 9ee6e8bb pbrook
                env->regs[0] = do_arm_semihosting(env);
654 9ee6e8bb pbrook
                return;
655 9ee6e8bb pbrook
            }
656 9ee6e8bb pbrook
        }
657 9ee6e8bb pbrook
        /* Fall through to prefetch abort.  */
658 9ee6e8bb pbrook
    case EXCP_PREFETCH_ABORT:
659 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_ABT;
660 b5ff1b31 bellard
        addr = 0x0c;
661 b5ff1b31 bellard
        mask = CPSR_A | CPSR_I;
662 b5ff1b31 bellard
        offset = 4;
663 b5ff1b31 bellard
        break;
664 b5ff1b31 bellard
    case EXCP_DATA_ABORT:
665 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_ABT;
666 b5ff1b31 bellard
        addr = 0x10;
667 b5ff1b31 bellard
        mask = CPSR_A | CPSR_I;
668 b5ff1b31 bellard
        offset = 8;
669 b5ff1b31 bellard
        break;
670 b5ff1b31 bellard
    case EXCP_IRQ:
671 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_IRQ;
672 b5ff1b31 bellard
        addr = 0x18;
673 b5ff1b31 bellard
        /* Disable IRQ and imprecise data aborts.  */
674 b5ff1b31 bellard
        mask = CPSR_A | CPSR_I;
675 b5ff1b31 bellard
        offset = 4;
676 b5ff1b31 bellard
        break;
677 b5ff1b31 bellard
    case EXCP_FIQ:
678 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_FIQ;
679 b5ff1b31 bellard
        addr = 0x1c;
680 b5ff1b31 bellard
        /* Disable FIQ, IRQ and imprecise data aborts.  */
681 b5ff1b31 bellard
        mask = CPSR_A | CPSR_I | CPSR_F;
682 b5ff1b31 bellard
        offset = 4;
683 b5ff1b31 bellard
        break;
684 b5ff1b31 bellard
    default:
685 b5ff1b31 bellard
        cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
686 b5ff1b31 bellard
        return; /* Never happens.  Keep compiler happy.  */
687 b5ff1b31 bellard
    }
688 b5ff1b31 bellard
    /* High vectors.  */
689 b5ff1b31 bellard
    if (env->cp15.c1_sys & (1 << 13)) {
690 b5ff1b31 bellard
        addr += 0xffff0000;
691 b5ff1b31 bellard
    }
692 b5ff1b31 bellard
    switch_mode (env, new_mode);
693 b5ff1b31 bellard
    env->spsr = cpsr_read(env);
694 9ee6e8bb pbrook
    /* Clear IT bits.  */
695 9ee6e8bb pbrook
    env->condexec_bits = 0;
696 6d7e6326 bellard
    /* Switch to the new mode, and switch to Arm mode.  */
697 b5ff1b31 bellard
    /* ??? Thumb interrupt handlers not implemented.  */
698 6d7e6326 bellard
    env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
699 b5ff1b31 bellard
    env->uncached_cpsr |= mask;
700 6d7e6326 bellard
    env->thumb = 0;
701 b5ff1b31 bellard
    env->regs[14] = env->regs[15] + offset;
702 b5ff1b31 bellard
    env->regs[15] = addr;
703 b5ff1b31 bellard
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
704 b5ff1b31 bellard
}
705 b5ff1b31 bellard
706 b5ff1b31 bellard
/* Check section/page access permissions.
707 b5ff1b31 bellard
   Returns the page protection flags, or zero if the access is not
708 b5ff1b31 bellard
   permitted.  */
709 b5ff1b31 bellard
static inline int check_ap(CPUState *env, int ap, int domain, int access_type,
710 b5ff1b31 bellard
                           int is_user)
711 b5ff1b31 bellard
{
712 9ee6e8bb pbrook
  int prot_ro;
713 9ee6e8bb pbrook
714 b5ff1b31 bellard
  if (domain == 3)
715 b5ff1b31 bellard
    return PAGE_READ | PAGE_WRITE;
716 b5ff1b31 bellard
717 9ee6e8bb pbrook
  if (access_type == 1)
718 9ee6e8bb pbrook
      prot_ro = 0;
719 9ee6e8bb pbrook
  else
720 9ee6e8bb pbrook
      prot_ro = PAGE_READ;
721 9ee6e8bb pbrook
722 b5ff1b31 bellard
  switch (ap) {
723 b5ff1b31 bellard
  case 0:
724 78600320 pbrook
      if (access_type == 1)
725 b5ff1b31 bellard
          return 0;
726 b5ff1b31 bellard
      switch ((env->cp15.c1_sys >> 8) & 3) {
727 b5ff1b31 bellard
      case 1:
728 b5ff1b31 bellard
          return is_user ? 0 : PAGE_READ;
729 b5ff1b31 bellard
      case 2:
730 b5ff1b31 bellard
          return PAGE_READ;
731 b5ff1b31 bellard
      default:
732 b5ff1b31 bellard
          return 0;
733 b5ff1b31 bellard
      }
734 b5ff1b31 bellard
  case 1:
735 b5ff1b31 bellard
      return is_user ? 0 : PAGE_READ | PAGE_WRITE;
736 b5ff1b31 bellard
  case 2:
737 b5ff1b31 bellard
      if (is_user)
738 9ee6e8bb pbrook
          return prot_ro;
739 b5ff1b31 bellard
      else
740 b5ff1b31 bellard
          return PAGE_READ | PAGE_WRITE;
741 b5ff1b31 bellard
  case 3:
742 b5ff1b31 bellard
      return PAGE_READ | PAGE_WRITE;
743 9ee6e8bb pbrook
  case 4: case 7: /* Reserved.  */
744 9ee6e8bb pbrook
      return 0;
745 9ee6e8bb pbrook
  case 5:
746 9ee6e8bb pbrook
      return is_user ? 0 : prot_ro;
747 9ee6e8bb pbrook
  case 6:
748 9ee6e8bb pbrook
      return prot_ro;
749 b5ff1b31 bellard
  default:
750 b5ff1b31 bellard
      abort();
751 b5ff1b31 bellard
  }
752 b5ff1b31 bellard
}
753 b5ff1b31 bellard
754 9ee6e8bb pbrook
static int get_phys_addr_v5(CPUState *env, uint32_t address, int access_type,
755 9ee6e8bb pbrook
                            int is_user, uint32_t *phys_ptr, int *prot)
756 b5ff1b31 bellard
{
757 b5ff1b31 bellard
    int code;
758 b5ff1b31 bellard
    uint32_t table;
759 b5ff1b31 bellard
    uint32_t desc;
760 b5ff1b31 bellard
    int type;
761 b5ff1b31 bellard
    int ap;
762 b5ff1b31 bellard
    int domain;
763 b5ff1b31 bellard
    uint32_t phys_addr;
764 b5ff1b31 bellard
765 9ee6e8bb pbrook
    /* Pagetable walk.  */
766 9ee6e8bb pbrook
    /* Lookup l1 descriptor.  */
767 9ee6e8bb pbrook
    if (address & env->cp15.c2_mask)
768 9ee6e8bb pbrook
        table = env->cp15.c2_base1;
769 9ee6e8bb pbrook
    else
770 9ee6e8bb pbrook
        table = env->cp15.c2_base0;
771 9ee6e8bb pbrook
    table = (table & 0xffffc000) | ((address >> 18) & 0x3ffc);
772 9ee6e8bb pbrook
    desc = ldl_phys(table);
773 9ee6e8bb pbrook
    type = (desc & 3);
774 9ee6e8bb pbrook
    domain = (env->cp15.c3 >> ((desc >> 4) & 0x1e)) & 3;
775 9ee6e8bb pbrook
    if (type == 0) {
776 9ee6e8bb pbrook
        /* Secton translation fault.  */
777 9ee6e8bb pbrook
        code = 5;
778 9ee6e8bb pbrook
        goto do_fault;
779 9ee6e8bb pbrook
    }
780 9ee6e8bb pbrook
    if (domain == 0 || domain == 2) {
781 9ee6e8bb pbrook
        if (type == 2)
782 9ee6e8bb pbrook
            code = 9; /* Section domain fault.  */
783 9ee6e8bb pbrook
        else
784 9ee6e8bb pbrook
            code = 11; /* Page domain fault.  */
785 9ee6e8bb pbrook
        goto do_fault;
786 9ee6e8bb pbrook
    }
787 9ee6e8bb pbrook
    if (type == 2) {
788 9ee6e8bb pbrook
        /* 1Mb section.  */
789 9ee6e8bb pbrook
        phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
790 9ee6e8bb pbrook
        ap = (desc >> 10) & 3;
791 9ee6e8bb pbrook
        code = 13;
792 9ee6e8bb pbrook
    } else {
793 9ee6e8bb pbrook
        /* Lookup l2 entry.  */
794 9ee6e8bb pbrook
        if (type == 1) {
795 9ee6e8bb pbrook
            /* Coarse pagetable.  */
796 9ee6e8bb pbrook
            table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
797 9ee6e8bb pbrook
        } else {
798 9ee6e8bb pbrook
            /* Fine pagetable.  */
799 9ee6e8bb pbrook
            table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
800 9ee6e8bb pbrook
        }
801 9ee6e8bb pbrook
        desc = ldl_phys(table);
802 9ee6e8bb pbrook
        switch (desc & 3) {
803 9ee6e8bb pbrook
        case 0: /* Page translation fault.  */
804 9ee6e8bb pbrook
            code = 7;
805 9ee6e8bb pbrook
            goto do_fault;
806 9ee6e8bb pbrook
        case 1: /* 64k page.  */
807 9ee6e8bb pbrook
            phys_addr = (desc & 0xffff0000) | (address & 0xffff);
808 9ee6e8bb pbrook
            ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
809 ce819861 pbrook
            break;
810 9ee6e8bb pbrook
        case 2: /* 4k page.  */
811 9ee6e8bb pbrook
            phys_addr = (desc & 0xfffff000) | (address & 0xfff);
812 9ee6e8bb pbrook
            ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
813 ce819861 pbrook
            break;
814 9ee6e8bb pbrook
        case 3: /* 1k page.  */
815 9ee6e8bb pbrook
            if (type == 1) {
816 9ee6e8bb pbrook
                if (arm_feature(env, ARM_FEATURE_XSCALE)) {
817 9ee6e8bb pbrook
                    phys_addr = (desc & 0xfffff000) | (address & 0xfff);
818 9ee6e8bb pbrook
                } else {
819 9ee6e8bb pbrook
                    /* Page translation fault.  */
820 9ee6e8bb pbrook
                    code = 7;
821 9ee6e8bb pbrook
                    goto do_fault;
822 9ee6e8bb pbrook
                }
823 9ee6e8bb pbrook
            } else {
824 9ee6e8bb pbrook
                phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
825 9ee6e8bb pbrook
            }
826 9ee6e8bb pbrook
            ap = (desc >> 4) & 3;
827 ce819861 pbrook
            break;
828 ce819861 pbrook
        default:
829 9ee6e8bb pbrook
            /* Never happens, but compiler isn't smart enough to tell.  */
830 9ee6e8bb pbrook
            abort();
831 ce819861 pbrook
        }
832 9ee6e8bb pbrook
        code = 15;
833 9ee6e8bb pbrook
    }
834 9ee6e8bb pbrook
    *prot = check_ap(env, ap, domain, access_type, is_user);
835 9ee6e8bb pbrook
    if (!*prot) {
836 9ee6e8bb pbrook
        /* Access permission fault.  */
837 9ee6e8bb pbrook
        goto do_fault;
838 9ee6e8bb pbrook
    }
839 9ee6e8bb pbrook
    *phys_ptr = phys_addr;
840 9ee6e8bb pbrook
    return 0;
841 9ee6e8bb pbrook
do_fault:
842 9ee6e8bb pbrook
    return code | (domain << 4);
843 9ee6e8bb pbrook
}
844 9ee6e8bb pbrook
845 9ee6e8bb pbrook
static int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type,
846 9ee6e8bb pbrook
                            int is_user, uint32_t *phys_ptr, int *prot)
847 9ee6e8bb pbrook
{
848 9ee6e8bb pbrook
    int code;
849 9ee6e8bb pbrook
    uint32_t table;
850 9ee6e8bb pbrook
    uint32_t desc;
851 9ee6e8bb pbrook
    uint32_t xn;
852 9ee6e8bb pbrook
    int type;
853 9ee6e8bb pbrook
    int ap;
854 9ee6e8bb pbrook
    int domain;
855 9ee6e8bb pbrook
    uint32_t phys_addr;
856 9ee6e8bb pbrook
857 9ee6e8bb pbrook
    /* Pagetable walk.  */
858 9ee6e8bb pbrook
    /* Lookup l1 descriptor.  */
859 9ee6e8bb pbrook
    if (address & env->cp15.c2_mask)
860 9ee6e8bb pbrook
        table = env->cp15.c2_base1;
861 9ee6e8bb pbrook
    else
862 9ee6e8bb pbrook
        table = env->cp15.c2_base0;
863 9ee6e8bb pbrook
    table = (table & 0xffffc000) | ((address >> 18) & 0x3ffc);
864 9ee6e8bb pbrook
    desc = ldl_phys(table);
865 9ee6e8bb pbrook
    type = (desc & 3);
866 9ee6e8bb pbrook
    if (type == 0) {
867 9ee6e8bb pbrook
        /* Secton translation fault.  */
868 9ee6e8bb pbrook
        code = 5;
869 9ee6e8bb pbrook
        domain = 0;
870 9ee6e8bb pbrook
        goto do_fault;
871 9ee6e8bb pbrook
    } else if (type == 2 && (desc & (1 << 18))) {
872 9ee6e8bb pbrook
        /* Supersection.  */
873 9ee6e8bb pbrook
        domain = 0;
874 b5ff1b31 bellard
    } else {
875 9ee6e8bb pbrook
        /* Section or page.  */
876 9ee6e8bb pbrook
        domain = (desc >> 4) & 0x1e;
877 9ee6e8bb pbrook
    }
878 9ee6e8bb pbrook
    domain = (env->cp15.c3 >> domain) & 3;
879 9ee6e8bb pbrook
    if (domain == 0 || domain == 2) {
880 9ee6e8bb pbrook
        if (type == 2)
881 9ee6e8bb pbrook
            code = 9; /* Section domain fault.  */
882 9ee6e8bb pbrook
        else
883 9ee6e8bb pbrook
            code = 11; /* Page domain fault.  */
884 9ee6e8bb pbrook
        goto do_fault;
885 9ee6e8bb pbrook
    }
886 9ee6e8bb pbrook
    if (type == 2) {
887 9ee6e8bb pbrook
        if (desc & (1 << 18)) {
888 9ee6e8bb pbrook
            /* Supersection.  */
889 9ee6e8bb pbrook
            phys_addr = (desc & 0xff000000) | (address & 0x00ffffff);
890 b5ff1b31 bellard
        } else {
891 9ee6e8bb pbrook
            /* Section.  */
892 9ee6e8bb pbrook
            phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
893 b5ff1b31 bellard
        }
894 9ee6e8bb pbrook
        ap = ((desc >> 10) & 3) | ((desc >> 13) & 4);
895 9ee6e8bb pbrook
        xn = desc & (1 << 4);
896 9ee6e8bb pbrook
        code = 13;
897 9ee6e8bb pbrook
    } else {
898 9ee6e8bb pbrook
        /* Lookup l2 entry.  */
899 9ee6e8bb pbrook
        table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
900 9ee6e8bb pbrook
        desc = ldl_phys(table);
901 9ee6e8bb pbrook
        ap = ((desc >> 4) & 3) | ((desc >> 7) & 4);
902 9ee6e8bb pbrook
        switch (desc & 3) {
903 9ee6e8bb pbrook
        case 0: /* Page translation fault.  */
904 9ee6e8bb pbrook
            code = 7;
905 b5ff1b31 bellard
            goto do_fault;
906 9ee6e8bb pbrook
        case 1: /* 64k page.  */
907 9ee6e8bb pbrook
            phys_addr = (desc & 0xffff0000) | (address & 0xffff);
908 9ee6e8bb pbrook
            xn = desc & (1 << 15);
909 9ee6e8bb pbrook
            break;
910 9ee6e8bb pbrook
        case 2: case 3: /* 4k page.  */
911 9ee6e8bb pbrook
            phys_addr = (desc & 0xfffff000) | (address & 0xfff);
912 9ee6e8bb pbrook
            xn = desc & 1;
913 9ee6e8bb pbrook
            break;
914 9ee6e8bb pbrook
        default:
915 9ee6e8bb pbrook
            /* Never happens, but compiler isn't smart enough to tell.  */
916 9ee6e8bb pbrook
            abort();
917 b5ff1b31 bellard
        }
918 9ee6e8bb pbrook
        code = 15;
919 9ee6e8bb pbrook
    }
920 9ee6e8bb pbrook
    if (xn && access_type == 2)
921 9ee6e8bb pbrook
        goto do_fault;
922 9ee6e8bb pbrook
923 9ee6e8bb pbrook
    *prot = check_ap(env, ap, domain, access_type, is_user);
924 9ee6e8bb pbrook
    if (!*prot) {
925 9ee6e8bb pbrook
        /* Access permission fault.  */
926 9ee6e8bb pbrook
        goto do_fault;
927 b5ff1b31 bellard
    }
928 9ee6e8bb pbrook
    *phys_ptr = phys_addr;
929 b5ff1b31 bellard
    return 0;
930 b5ff1b31 bellard
do_fault:
931 b5ff1b31 bellard
    return code | (domain << 4);
932 b5ff1b31 bellard
}
933 b5ff1b31 bellard
934 9ee6e8bb pbrook
static int get_phys_addr_mpu(CPUState *env, uint32_t address, int access_type,
935 9ee6e8bb pbrook
                             int is_user, uint32_t *phys_ptr, int *prot)
936 9ee6e8bb pbrook
{
937 9ee6e8bb pbrook
    int n;
938 9ee6e8bb pbrook
    uint32_t mask;
939 9ee6e8bb pbrook
    uint32_t base;
940 9ee6e8bb pbrook
941 9ee6e8bb pbrook
    *phys_ptr = address;
942 9ee6e8bb pbrook
    for (n = 7; n >= 0; n--) {
943 9ee6e8bb pbrook
        base = env->cp15.c6_region[n];
944 9ee6e8bb pbrook
        if ((base & 1) == 0)
945 9ee6e8bb pbrook
            continue;
946 9ee6e8bb pbrook
        mask = 1 << ((base >> 1) & 0x1f);
947 9ee6e8bb pbrook
        /* Keep this shift separate from the above to avoid an
948 9ee6e8bb pbrook
           (undefined) << 32.  */
949 9ee6e8bb pbrook
        mask = (mask << 1) - 1;
950 9ee6e8bb pbrook
        if (((base ^ address) & ~mask) == 0)
951 9ee6e8bb pbrook
            break;
952 9ee6e8bb pbrook
    }
953 9ee6e8bb pbrook
    if (n < 0)
954 9ee6e8bb pbrook
        return 2;
955 9ee6e8bb pbrook
956 9ee6e8bb pbrook
    if (access_type == 2) {
957 9ee6e8bb pbrook
        mask = env->cp15.c5_insn;
958 9ee6e8bb pbrook
    } else {
959 9ee6e8bb pbrook
        mask = env->cp15.c5_data;
960 9ee6e8bb pbrook
    }
961 9ee6e8bb pbrook
    mask = (mask >> (n * 4)) & 0xf;
962 9ee6e8bb pbrook
    switch (mask) {
963 9ee6e8bb pbrook
    case 0:
964 9ee6e8bb pbrook
        return 1;
965 9ee6e8bb pbrook
    case 1:
966 9ee6e8bb pbrook
        if (is_user)
967 9ee6e8bb pbrook
          return 1;
968 9ee6e8bb pbrook
        *prot = PAGE_READ | PAGE_WRITE;
969 9ee6e8bb pbrook
        break;
970 9ee6e8bb pbrook
    case 2:
971 9ee6e8bb pbrook
        *prot = PAGE_READ;
972 9ee6e8bb pbrook
        if (!is_user)
973 9ee6e8bb pbrook
            *prot |= PAGE_WRITE;
974 9ee6e8bb pbrook
        break;
975 9ee6e8bb pbrook
    case 3:
976 9ee6e8bb pbrook
        *prot = PAGE_READ | PAGE_WRITE;
977 9ee6e8bb pbrook
        break;
978 9ee6e8bb pbrook
    case 5:
979 9ee6e8bb pbrook
        if (is_user)
980 9ee6e8bb pbrook
            return 1;
981 9ee6e8bb pbrook
        *prot = PAGE_READ;
982 9ee6e8bb pbrook
        break;
983 9ee6e8bb pbrook
    case 6:
984 9ee6e8bb pbrook
        *prot = PAGE_READ;
985 9ee6e8bb pbrook
        break;
986 9ee6e8bb pbrook
    default:
987 9ee6e8bb pbrook
        /* Bad permission.  */
988 9ee6e8bb pbrook
        return 1;
989 9ee6e8bb pbrook
    }
990 9ee6e8bb pbrook
    return 0;
991 9ee6e8bb pbrook
}
992 9ee6e8bb pbrook
993 9ee6e8bb pbrook
static inline int get_phys_addr(CPUState *env, uint32_t address,
994 9ee6e8bb pbrook
                                int access_type, int is_user,
995 9ee6e8bb pbrook
                                uint32_t *phys_ptr, int *prot)
996 9ee6e8bb pbrook
{
997 9ee6e8bb pbrook
    /* Fast Context Switch Extension.  */
998 9ee6e8bb pbrook
    if (address < 0x02000000)
999 9ee6e8bb pbrook
        address += env->cp15.c13_fcse;
1000 9ee6e8bb pbrook
1001 9ee6e8bb pbrook
    if ((env->cp15.c1_sys & 1) == 0) {
1002 9ee6e8bb pbrook
        /* MMU/MPU disabled.  */
1003 9ee6e8bb pbrook
        *phys_ptr = address;
1004 9ee6e8bb pbrook
        *prot = PAGE_READ | PAGE_WRITE;
1005 9ee6e8bb pbrook
        return 0;
1006 9ee6e8bb pbrook
    } else if (arm_feature(env, ARM_FEATURE_MPU)) {
1007 9ee6e8bb pbrook
        return get_phys_addr_mpu(env, address, access_type, is_user, phys_ptr,
1008 9ee6e8bb pbrook
                                 prot);
1009 9ee6e8bb pbrook
    } else if (env->cp15.c1_sys & (1 << 23)) {
1010 9ee6e8bb pbrook
        return get_phys_addr_v6(env, address, access_type, is_user, phys_ptr,
1011 9ee6e8bb pbrook
                                prot);
1012 9ee6e8bb pbrook
    } else {
1013 9ee6e8bb pbrook
        return get_phys_addr_v5(env, address, access_type, is_user, phys_ptr,
1014 9ee6e8bb pbrook
                                prot);
1015 9ee6e8bb pbrook
    }
1016 9ee6e8bb pbrook
}
1017 9ee6e8bb pbrook
1018 b5ff1b31 bellard
int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address,
1019 6ebbf390 j_mayer
                              int access_type, int mmu_idx, int is_softmmu)
1020 b5ff1b31 bellard
{
1021 b5ff1b31 bellard
    uint32_t phys_addr;
1022 b5ff1b31 bellard
    int prot;
1023 6ebbf390 j_mayer
    int ret, is_user;
1024 b5ff1b31 bellard
1025 6ebbf390 j_mayer
    is_user = mmu_idx == MMU_USER_IDX;
1026 b5ff1b31 bellard
    ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot);
1027 b5ff1b31 bellard
    if (ret == 0) {
1028 b5ff1b31 bellard
        /* Map a single [sub]page.  */
1029 b5ff1b31 bellard
        phys_addr &= ~(uint32_t)0x3ff;
1030 b5ff1b31 bellard
        address &= ~(uint32_t)0x3ff;
1031 6ebbf390 j_mayer
        return tlb_set_page (env, address, phys_addr, prot, mmu_idx,
1032 b5ff1b31 bellard
                             is_softmmu);
1033 b5ff1b31 bellard
    }
1034 b5ff1b31 bellard
1035 b5ff1b31 bellard
    if (access_type == 2) {
1036 b5ff1b31 bellard
        env->cp15.c5_insn = ret;
1037 b5ff1b31 bellard
        env->cp15.c6_insn = address;
1038 b5ff1b31 bellard
        env->exception_index = EXCP_PREFETCH_ABORT;
1039 b5ff1b31 bellard
    } else {
1040 b5ff1b31 bellard
        env->cp15.c5_data = ret;
1041 9ee6e8bb pbrook
        if (access_type == 1 && arm_feature(env, ARM_FEATURE_V6))
1042 9ee6e8bb pbrook
            env->cp15.c5_data |= (1 << 11);
1043 b5ff1b31 bellard
        env->cp15.c6_data = address;
1044 b5ff1b31 bellard
        env->exception_index = EXCP_DATA_ABORT;
1045 b5ff1b31 bellard
    }
1046 b5ff1b31 bellard
    return 1;
1047 b5ff1b31 bellard
}
1048 b5ff1b31 bellard
1049 9b3c35e0 j_mayer
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1050 b5ff1b31 bellard
{
1051 b5ff1b31 bellard
    uint32_t phys_addr;
1052 b5ff1b31 bellard
    int prot;
1053 b5ff1b31 bellard
    int ret;
1054 b5ff1b31 bellard
1055 b5ff1b31 bellard
    ret = get_phys_addr(env, addr, 0, 0, &phys_addr, &prot);
1056 b5ff1b31 bellard
1057 b5ff1b31 bellard
    if (ret != 0)
1058 b5ff1b31 bellard
        return -1;
1059 b5ff1b31 bellard
1060 b5ff1b31 bellard
    return phys_addr;
1061 b5ff1b31 bellard
}
1062 b5ff1b31 bellard
1063 9ee6e8bb pbrook
/* Not really implemented.  Need to figure out a sane way of doing this.
1064 9ee6e8bb pbrook
   Maybe add generic watchpoint support and use that.  */
1065 9ee6e8bb pbrook
1066 9ee6e8bb pbrook
void helper_mark_exclusive(CPUState *env, uint32_t addr)
1067 9ee6e8bb pbrook
{
1068 9ee6e8bb pbrook
    env->mmon_addr = addr;
1069 9ee6e8bb pbrook
}
1070 9ee6e8bb pbrook
1071 9ee6e8bb pbrook
int helper_test_exclusive(CPUState *env, uint32_t addr)
1072 9ee6e8bb pbrook
{
1073 9ee6e8bb pbrook
    return (env->mmon_addr != addr);
1074 9ee6e8bb pbrook
}
1075 9ee6e8bb pbrook
1076 9ee6e8bb pbrook
void helper_clrex(CPUState *env)
1077 9ee6e8bb pbrook
{
1078 9ee6e8bb pbrook
    env->mmon_addr = -1;
1079 9ee6e8bb pbrook
}
1080 9ee6e8bb pbrook
1081 c1713132 balrog
void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val)
1082 c1713132 balrog
{
1083 c1713132 balrog
    int cp_num = (insn >> 8) & 0xf;
1084 c1713132 balrog
    int cp_info = (insn >> 5) & 7;
1085 c1713132 balrog
    int src = (insn >> 16) & 0xf;
1086 c1713132 balrog
    int operand = insn & 0xf;
1087 c1713132 balrog
1088 c1713132 balrog
    if (env->cp[cp_num].cp_write)
1089 c1713132 balrog
        env->cp[cp_num].cp_write(env->cp[cp_num].opaque,
1090 c1713132 balrog
                                 cp_info, src, operand, val);
1091 c1713132 balrog
}
1092 c1713132 balrog
1093 c1713132 balrog
uint32_t helper_get_cp(CPUState *env, uint32_t insn)
1094 c1713132 balrog
{
1095 c1713132 balrog
    int cp_num = (insn >> 8) & 0xf;
1096 c1713132 balrog
    int cp_info = (insn >> 5) & 7;
1097 c1713132 balrog
    int dest = (insn >> 16) & 0xf;
1098 c1713132 balrog
    int operand = insn & 0xf;
1099 c1713132 balrog
1100 c1713132 balrog
    if (env->cp[cp_num].cp_read)
1101 c1713132 balrog
        return env->cp[cp_num].cp_read(env->cp[cp_num].opaque,
1102 c1713132 balrog
                                       cp_info, dest, operand);
1103 c1713132 balrog
    return 0;
1104 c1713132 balrog
}
1105 c1713132 balrog
1106 ce819861 pbrook
/* Return basic MPU access permission bits.  */
1107 ce819861 pbrook
static uint32_t simple_mpu_ap_bits(uint32_t val)
1108 ce819861 pbrook
{
1109 ce819861 pbrook
    uint32_t ret;
1110 ce819861 pbrook
    uint32_t mask;
1111 ce819861 pbrook
    int i;
1112 ce819861 pbrook
    ret = 0;
1113 ce819861 pbrook
    mask = 3;
1114 ce819861 pbrook
    for (i = 0; i < 16; i += 2) {
1115 ce819861 pbrook
        ret |= (val >> i) & mask;
1116 ce819861 pbrook
        mask <<= 2;
1117 ce819861 pbrook
    }
1118 ce819861 pbrook
    return ret;
1119 ce819861 pbrook
}
1120 ce819861 pbrook
1121 ce819861 pbrook
/* Pad basic MPU access permission bits to extended format.  */
1122 ce819861 pbrook
static uint32_t extended_mpu_ap_bits(uint32_t val)
1123 ce819861 pbrook
{
1124 ce819861 pbrook
    uint32_t ret;
1125 ce819861 pbrook
    uint32_t mask;
1126 ce819861 pbrook
    int i;
1127 ce819861 pbrook
    ret = 0;
1128 ce819861 pbrook
    mask = 3;
1129 ce819861 pbrook
    for (i = 0; i < 16; i += 2) {
1130 ce819861 pbrook
        ret |= (val & mask) << i;
1131 ce819861 pbrook
        mask <<= 2;
1132 ce819861 pbrook
    }
1133 ce819861 pbrook
    return ret;
1134 ce819861 pbrook
}
1135 ce819861 pbrook
1136 b5ff1b31 bellard
void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
1137 b5ff1b31 bellard
{
1138 9ee6e8bb pbrook
    int op1;
1139 9ee6e8bb pbrook
    int op2;
1140 9ee6e8bb pbrook
    int crm;
1141 b5ff1b31 bellard
1142 9ee6e8bb pbrook
    op1 = (insn >> 21) & 7;
1143 b5ff1b31 bellard
    op2 = (insn >> 5) & 7;
1144 ce819861 pbrook
    crm = insn & 0xf;
1145 b5ff1b31 bellard
    switch ((insn >> 16) & 0xf) {
1146 9ee6e8bb pbrook
    case 0:
1147 9ee6e8bb pbrook
        if (((insn >> 21) & 7) == 2) {
1148 9ee6e8bb pbrook
            /* ??? Select cache level.  Ignore.  */
1149 9ee6e8bb pbrook
            return;
1150 9ee6e8bb pbrook
        }
1151 9ee6e8bb pbrook
        /* ID codes.  */
1152 610c3c8a balrog
        if (arm_feature(env, ARM_FEATURE_XSCALE))
1153 610c3c8a balrog
            break;
1154 c3d2689d balrog
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
1155 c3d2689d balrog
            break;
1156 b5ff1b31 bellard
        goto bad_reg;
1157 b5ff1b31 bellard
    case 1: /* System configuration.  */
1158 c3d2689d balrog
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
1159 c3d2689d balrog
            op2 = 0;
1160 b5ff1b31 bellard
        switch (op2) {
1161 b5ff1b31 bellard
        case 0:
1162 ce819861 pbrook
            if (!arm_feature(env, ARM_FEATURE_XSCALE) || crm == 0)
1163 c1713132 balrog
                env->cp15.c1_sys = val;
1164 b5ff1b31 bellard
            /* ??? Lots of these bits are not implemented.  */
1165 b5ff1b31 bellard
            /* This may enable/disable the MMU, so do a TLB flush.  */
1166 b5ff1b31 bellard
            tlb_flush(env, 1);
1167 b5ff1b31 bellard
            break;
1168 9ee6e8bb pbrook
        case 1: /* Auxiliary cotrol register.  */
1169 610c3c8a balrog
            if (arm_feature(env, ARM_FEATURE_XSCALE)) {
1170 610c3c8a balrog
                env->cp15.c1_xscaleauxcr = val;
1171 c1713132 balrog
                break;
1172 610c3c8a balrog
            }
1173 9ee6e8bb pbrook
            /* Not implemented.  */
1174 9ee6e8bb pbrook
            break;
1175 b5ff1b31 bellard
        case 2:
1176 610c3c8a balrog
            if (arm_feature(env, ARM_FEATURE_XSCALE))
1177 610c3c8a balrog
                goto bad_reg;
1178 b5ff1b31 bellard
            env->cp15.c1_coproc = val;
1179 b5ff1b31 bellard
            /* ??? Is this safe when called from within a TB?  */
1180 b5ff1b31 bellard
            tb_flush(env);
1181 c1713132 balrog
            break;
1182 b5ff1b31 bellard
        default:
1183 b5ff1b31 bellard
            goto bad_reg;
1184 b5ff1b31 bellard
        }
1185 b5ff1b31 bellard
        break;
1186 ce819861 pbrook
    case 2: /* MMU Page table control / MPU cache control.  */
1187 ce819861 pbrook
        if (arm_feature(env, ARM_FEATURE_MPU)) {
1188 ce819861 pbrook
            switch (op2) {
1189 ce819861 pbrook
            case 0:
1190 ce819861 pbrook
                env->cp15.c2_data = val;
1191 ce819861 pbrook
                break;
1192 ce819861 pbrook
            case 1:
1193 ce819861 pbrook
                env->cp15.c2_insn = val;
1194 ce819861 pbrook
                break;
1195 ce819861 pbrook
            default:
1196 ce819861 pbrook
                goto bad_reg;
1197 ce819861 pbrook
            }
1198 ce819861 pbrook
        } else {
1199 9ee6e8bb pbrook
            switch (op2) {
1200 9ee6e8bb pbrook
            case 0:
1201 9ee6e8bb pbrook
                env->cp15.c2_base0 = val;
1202 9ee6e8bb pbrook
                break;
1203 9ee6e8bb pbrook
            case 1:
1204 9ee6e8bb pbrook
                env->cp15.c2_base1 = val;
1205 9ee6e8bb pbrook
                break;
1206 9ee6e8bb pbrook
            case 2:
1207 9ee6e8bb pbrook
                env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> val);
1208 9ee6e8bb pbrook
                break;
1209 9ee6e8bb pbrook
            default:
1210 9ee6e8bb pbrook
                goto bad_reg;
1211 9ee6e8bb pbrook
            }
1212 ce819861 pbrook
        }
1213 b5ff1b31 bellard
        break;
1214 ce819861 pbrook
    case 3: /* MMU Domain access control / MPU write buffer control.  */
1215 b5ff1b31 bellard
        env->cp15.c3 = val;
1216 405ee3ad balrog
        tlb_flush(env, 1); /* Flush TLB as domain not tracked in TLB */
1217 b5ff1b31 bellard
        break;
1218 b5ff1b31 bellard
    case 4: /* Reserved.  */
1219 b5ff1b31 bellard
        goto bad_reg;
1220 ce819861 pbrook
    case 5: /* MMU Fault status / MPU access permission.  */
1221 c3d2689d balrog
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
1222 c3d2689d balrog
            op2 = 0;
1223 b5ff1b31 bellard
        switch (op2) {
1224 b5ff1b31 bellard
        case 0:
1225 ce819861 pbrook
            if (arm_feature(env, ARM_FEATURE_MPU))
1226 ce819861 pbrook
                val = extended_mpu_ap_bits(val);
1227 b5ff1b31 bellard
            env->cp15.c5_data = val;
1228 b5ff1b31 bellard
            break;
1229 b5ff1b31 bellard
        case 1:
1230 ce819861 pbrook
            if (arm_feature(env, ARM_FEATURE_MPU))
1231 ce819861 pbrook
                val = extended_mpu_ap_bits(val);
1232 b5ff1b31 bellard
            env->cp15.c5_insn = val;
1233 b5ff1b31 bellard
            break;
1234 ce819861 pbrook
        case 2:
1235 ce819861 pbrook
            if (!arm_feature(env, ARM_FEATURE_MPU))
1236 ce819861 pbrook
                goto bad_reg;
1237 ce819861 pbrook
            env->cp15.c5_data = val;
1238 b5ff1b31 bellard
            break;
1239 ce819861 pbrook
        case 3:
1240 ce819861 pbrook
            if (!arm_feature(env, ARM_FEATURE_MPU))
1241 ce819861 pbrook
                goto bad_reg;
1242 ce819861 pbrook
            env->cp15.c5_insn = val;
1243 b5ff1b31 bellard
            break;
1244 b5ff1b31 bellard
        default:
1245 b5ff1b31 bellard
            goto bad_reg;
1246 b5ff1b31 bellard
        }
1247 b5ff1b31 bellard
        break;
1248 ce819861 pbrook
    case 6: /* MMU Fault address / MPU base/size.  */
1249 ce819861 pbrook
        if (arm_feature(env, ARM_FEATURE_MPU)) {
1250 ce819861 pbrook
            if (crm >= 8)
1251 ce819861 pbrook
                goto bad_reg;
1252 ce819861 pbrook
            env->cp15.c6_region[crm] = val;
1253 ce819861 pbrook
        } else {
1254 c3d2689d balrog
            if (arm_feature(env, ARM_FEATURE_OMAPCP))
1255 c3d2689d balrog
                op2 = 0;
1256 ce819861 pbrook
            switch (op2) {
1257 ce819861 pbrook
            case 0:
1258 ce819861 pbrook
                env->cp15.c6_data = val;
1259 ce819861 pbrook
                break;
1260 9ee6e8bb pbrook
            case 1: /* ??? This is WFAR on armv6 */
1261 9ee6e8bb pbrook
            case 2:
1262 ce819861 pbrook
                env->cp15.c6_insn = val;
1263 ce819861 pbrook
                break;
1264 ce819861 pbrook
            default:
1265 ce819861 pbrook
                goto bad_reg;
1266 ce819861 pbrook
            }
1267 ce819861 pbrook
        }
1268 ce819861 pbrook
        break;
1269 b5ff1b31 bellard
    case 7: /* Cache control.  */
1270 c3d2689d balrog
        env->cp15.c15_i_max = 0x000;
1271 c3d2689d balrog
        env->cp15.c15_i_min = 0xff0;
1272 b5ff1b31 bellard
        /* No cache, so nothing to do.  */
1273 9ee6e8bb pbrook
        /* ??? MPCore has VA to PA translation functions.  */
1274 b5ff1b31 bellard
        break;
1275 b5ff1b31 bellard
    case 8: /* MMU TLB control.  */
1276 b5ff1b31 bellard
        switch (op2) {
1277 b5ff1b31 bellard
        case 0: /* Invalidate all.  */
1278 b5ff1b31 bellard
            tlb_flush(env, 0);
1279 b5ff1b31 bellard
            break;
1280 b5ff1b31 bellard
        case 1: /* Invalidate single TLB entry.  */
1281 b5ff1b31 bellard
#if 0
1282 b5ff1b31 bellard
            /* ??? This is wrong for large pages and sections.  */
1283 b5ff1b31 bellard
            /* As an ugly hack to make linux work we always flush a 4K
1284 b5ff1b31 bellard
               pages.  */
1285 b5ff1b31 bellard
            val &= 0xfffff000;
1286 b5ff1b31 bellard
            tlb_flush_page(env, val);
1287 b5ff1b31 bellard
            tlb_flush_page(env, val + 0x400);
1288 b5ff1b31 bellard
            tlb_flush_page(env, val + 0x800);
1289 b5ff1b31 bellard
            tlb_flush_page(env, val + 0xc00);
1290 b5ff1b31 bellard
#else
1291 b5ff1b31 bellard
            tlb_flush(env, 1);
1292 b5ff1b31 bellard
#endif
1293 b5ff1b31 bellard
            break;
1294 9ee6e8bb pbrook
        case 2: /* Invalidate on ASID.  */
1295 9ee6e8bb pbrook
            tlb_flush(env, val == 0);
1296 9ee6e8bb pbrook
            break;
1297 9ee6e8bb pbrook
        case 3: /* Invalidate single entry on MVA.  */
1298 9ee6e8bb pbrook
            /* ??? This is like case 1, but ignores ASID.  */
1299 9ee6e8bb pbrook
            tlb_flush(env, 1);
1300 9ee6e8bb pbrook
            break;
1301 b5ff1b31 bellard
        default:
1302 b5ff1b31 bellard
            goto bad_reg;
1303 b5ff1b31 bellard
        }
1304 b5ff1b31 bellard
        break;
1305 ce819861 pbrook
    case 9:
1306 c3d2689d balrog
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
1307 c3d2689d balrog
            break;
1308 ce819861 pbrook
        switch (crm) {
1309 ce819861 pbrook
        case 0: /* Cache lockdown.  */
1310 9ee6e8bb pbrook
            switch (op1) {
1311 9ee6e8bb pbrook
            case 0: /* L1 cache.  */
1312 9ee6e8bb pbrook
                switch (op2) {
1313 9ee6e8bb pbrook
                case 0:
1314 9ee6e8bb pbrook
                    env->cp15.c9_data = val;
1315 9ee6e8bb pbrook
                    break;
1316 9ee6e8bb pbrook
                case 1:
1317 9ee6e8bb pbrook
                    env->cp15.c9_insn = val;
1318 9ee6e8bb pbrook
                    break;
1319 9ee6e8bb pbrook
                default:
1320 9ee6e8bb pbrook
                    goto bad_reg;
1321 9ee6e8bb pbrook
                }
1322 9ee6e8bb pbrook
                break;
1323 9ee6e8bb pbrook
            case 1: /* L2 cache.  */
1324 9ee6e8bb pbrook
                /* Ignore writes to L2 lockdown/auxiliary registers.  */
1325 9ee6e8bb pbrook
                break;
1326 9ee6e8bb pbrook
            default:
1327 9ee6e8bb pbrook
                goto bad_reg;
1328 9ee6e8bb pbrook
            }
1329 9ee6e8bb pbrook
            break;
1330 ce819861 pbrook
        case 1: /* TCM memory region registers.  */
1331 ce819861 pbrook
            /* Not implemented.  */
1332 ce819861 pbrook
            goto bad_reg;
1333 b5ff1b31 bellard
        default:
1334 b5ff1b31 bellard
            goto bad_reg;
1335 b5ff1b31 bellard
        }
1336 b5ff1b31 bellard
        break;
1337 b5ff1b31 bellard
    case 10: /* MMU TLB lockdown.  */
1338 b5ff1b31 bellard
        /* ??? TLB lockdown not implemented.  */
1339 b5ff1b31 bellard
        break;
1340 b5ff1b31 bellard
    case 12: /* Reserved.  */
1341 b5ff1b31 bellard
        goto bad_reg;
1342 b5ff1b31 bellard
    case 13: /* Process ID.  */
1343 b5ff1b31 bellard
        switch (op2) {
1344 b5ff1b31 bellard
        case 0:
1345 d07edbfa pbrook
            /* Unlike real hardware the qemu TLB uses virtual addresses,
1346 d07edbfa pbrook
               not modified virtual addresses, so this causes a TLB flush.
1347 d07edbfa pbrook
             */
1348 d07edbfa pbrook
            if (env->cp15.c13_fcse != val)
1349 d07edbfa pbrook
              tlb_flush(env, 1);
1350 d07edbfa pbrook
            env->cp15.c13_fcse = val;
1351 b5ff1b31 bellard
            break;
1352 b5ff1b31 bellard
        case 1:
1353 d07edbfa pbrook
            /* This changes the ASID, so do a TLB flush.  */
1354 ce819861 pbrook
            if (env->cp15.c13_context != val
1355 ce819861 pbrook
                && !arm_feature(env, ARM_FEATURE_MPU))
1356 d07edbfa pbrook
              tlb_flush(env, 0);
1357 d07edbfa pbrook
            env->cp15.c13_context = val;
1358 b5ff1b31 bellard
            break;
1359 9ee6e8bb pbrook
        case 2:
1360 9ee6e8bb pbrook
            env->cp15.c13_tls1 = val;
1361 9ee6e8bb pbrook
            break;
1362 9ee6e8bb pbrook
        case 3:
1363 9ee6e8bb pbrook
            env->cp15.c13_tls2 = val;
1364 9ee6e8bb pbrook
            break;
1365 9ee6e8bb pbrook
        case 4:
1366 9ee6e8bb pbrook
            env->cp15.c13_tls3 = val;
1367 9ee6e8bb pbrook
            break;
1368 b5ff1b31 bellard
        default:
1369 b5ff1b31 bellard
            goto bad_reg;
1370 b5ff1b31 bellard
        }
1371 b5ff1b31 bellard
        break;
1372 b5ff1b31 bellard
    case 14: /* Reserved.  */
1373 b5ff1b31 bellard
        goto bad_reg;
1374 b5ff1b31 bellard
    case 15: /* Implementation specific.  */
1375 c1713132 balrog
        if (arm_feature(env, ARM_FEATURE_XSCALE)) {
1376 ce819861 pbrook
            if (op2 == 0 && crm == 1) {
1377 2e23213f balrog
                if (env->cp15.c15_cpar != (val & 0x3fff)) {
1378 2e23213f balrog
                    /* Changes cp0 to cp13 behavior, so needs a TB flush.  */
1379 2e23213f balrog
                    tb_flush(env);
1380 2e23213f balrog
                    env->cp15.c15_cpar = val & 0x3fff;
1381 2e23213f balrog
                }
1382 c1713132 balrog
                break;
1383 c1713132 balrog
            }
1384 c1713132 balrog
            goto bad_reg;
1385 c1713132 balrog
        }
1386 c3d2689d balrog
        if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
1387 c3d2689d balrog
            switch (crm) {
1388 c3d2689d balrog
            case 0:
1389 c3d2689d balrog
                break;
1390 c3d2689d balrog
            case 1: /* Set TI925T configuration.  */
1391 c3d2689d balrog
                env->cp15.c15_ticonfig = val & 0xe7;
1392 c3d2689d balrog
                env->cp15.c0_cpuid = (val & (1 << 5)) ? /* OS_TYPE bit */
1393 c3d2689d balrog
                        ARM_CPUID_TI915T : ARM_CPUID_TI925T;
1394 c3d2689d balrog
                break;
1395 c3d2689d balrog
            case 2: /* Set I_max.  */
1396 c3d2689d balrog
                env->cp15.c15_i_max = val;
1397 c3d2689d balrog
                break;
1398 c3d2689d balrog
            case 3: /* Set I_min.  */
1399 c3d2689d balrog
                env->cp15.c15_i_min = val;
1400 c3d2689d balrog
                break;
1401 c3d2689d balrog
            case 4: /* Set thread-ID.  */
1402 c3d2689d balrog
                env->cp15.c15_threadid = val & 0xffff;
1403 c3d2689d balrog
                break;
1404 c3d2689d balrog
            case 8: /* Wait-for-interrupt (deprecated).  */
1405 c3d2689d balrog
                cpu_interrupt(env, CPU_INTERRUPT_HALT);
1406 c3d2689d balrog
                break;
1407 c3d2689d balrog
            default:
1408 c3d2689d balrog
                goto bad_reg;
1409 c3d2689d balrog
            }
1410 c3d2689d balrog
        }
1411 b5ff1b31 bellard
        break;
1412 b5ff1b31 bellard
    }
1413 b5ff1b31 bellard
    return;
1414 b5ff1b31 bellard
bad_reg:
1415 b5ff1b31 bellard
    /* ??? For debugging only.  Should raise illegal instruction exception.  */
1416 9ee6e8bb pbrook
    cpu_abort(env, "Unimplemented cp15 register write (c%d, c%d, {%d, %d})\n",
1417 9ee6e8bb pbrook
              (insn >> 16) & 0xf, crm, op1, op2);
1418 b5ff1b31 bellard
}
1419 b5ff1b31 bellard
1420 b5ff1b31 bellard
uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
1421 b5ff1b31 bellard
{
1422 9ee6e8bb pbrook
    int op1;
1423 9ee6e8bb pbrook
    int op2;
1424 9ee6e8bb pbrook
    int crm;
1425 b5ff1b31 bellard
1426 9ee6e8bb pbrook
    op1 = (insn >> 21) & 7;
1427 b5ff1b31 bellard
    op2 = (insn >> 5) & 7;
1428 c3d2689d balrog
    crm = insn & 0xf;
1429 b5ff1b31 bellard
    switch ((insn >> 16) & 0xf) {
1430 b5ff1b31 bellard
    case 0: /* ID codes.  */
1431 9ee6e8bb pbrook
        switch (op1) {
1432 9ee6e8bb pbrook
        case 0:
1433 9ee6e8bb pbrook
            switch (crm) {
1434 9ee6e8bb pbrook
            case 0:
1435 9ee6e8bb pbrook
                switch (op2) {
1436 9ee6e8bb pbrook
                case 0: /* Device ID.  */
1437 9ee6e8bb pbrook
                    return env->cp15.c0_cpuid;
1438 9ee6e8bb pbrook
                case 1: /* Cache Type.  */
1439 9ee6e8bb pbrook
                    return env->cp15.c0_cachetype;
1440 9ee6e8bb pbrook
                case 2: /* TCM status.  */
1441 9ee6e8bb pbrook
                    return 0;
1442 9ee6e8bb pbrook
                case 3: /* TLB type register.  */
1443 9ee6e8bb pbrook
                    return 0; /* No lockable TLB entries.  */
1444 9ee6e8bb pbrook
                case 5: /* CPU ID */
1445 9ee6e8bb pbrook
                    return env->cpu_index;
1446 9ee6e8bb pbrook
                default:
1447 9ee6e8bb pbrook
                    goto bad_reg;
1448 9ee6e8bb pbrook
                }
1449 9ee6e8bb pbrook
            case 1:
1450 9ee6e8bb pbrook
                if (!arm_feature(env, ARM_FEATURE_V6))
1451 9ee6e8bb pbrook
                    goto bad_reg;
1452 9ee6e8bb pbrook
                return env->cp15.c0_c1[op2];
1453 9ee6e8bb pbrook
            case 2:
1454 9ee6e8bb pbrook
                if (!arm_feature(env, ARM_FEATURE_V6))
1455 9ee6e8bb pbrook
                    goto bad_reg;
1456 9ee6e8bb pbrook
                return env->cp15.c0_c2[op2];
1457 9ee6e8bb pbrook
            case 3: case 4: case 5: case 6: case 7:
1458 9ee6e8bb pbrook
                return 0;
1459 9ee6e8bb pbrook
            default:
1460 9ee6e8bb pbrook
                goto bad_reg;
1461 9ee6e8bb pbrook
            }
1462 9ee6e8bb pbrook
        case 1:
1463 9ee6e8bb pbrook
            /* These registers aren't documented on arm11 cores.  However
1464 9ee6e8bb pbrook
               Linux looks at them anyway.  */
1465 9ee6e8bb pbrook
            if (!arm_feature(env, ARM_FEATURE_V6))
1466 9ee6e8bb pbrook
                goto bad_reg;
1467 9ee6e8bb pbrook
            if (crm != 0)
1468 9ee6e8bb pbrook
                goto bad_reg;
1469 610c3c8a balrog
            if (arm_feature(env, ARM_FEATURE_XSCALE))
1470 610c3c8a balrog
                goto bad_reg;
1471 b5ff1b31 bellard
            return 0;
1472 9ee6e8bb pbrook
        default:
1473 9ee6e8bb pbrook
            goto bad_reg;
1474 b5ff1b31 bellard
        }
1475 b5ff1b31 bellard
    case 1: /* System configuration.  */
1476 c3d2689d balrog
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
1477 c3d2689d balrog
            op2 = 0;
1478 b5ff1b31 bellard
        switch (op2) {
1479 b5ff1b31 bellard
        case 0: /* Control register.  */
1480 b5ff1b31 bellard
            return env->cp15.c1_sys;
1481 b5ff1b31 bellard
        case 1: /* Auxiliary control register.  */
1482 c1713132 balrog
            if (arm_feature(env, ARM_FEATURE_XSCALE))
1483 610c3c8a balrog
                return env->cp15.c1_xscaleauxcr;
1484 9ee6e8bb pbrook
            if (!arm_feature(env, ARM_FEATURE_AUXCR))
1485 9ee6e8bb pbrook
                goto bad_reg;
1486 9ee6e8bb pbrook
            switch (ARM_CPUID(env)) {
1487 9ee6e8bb pbrook
            case ARM_CPUID_ARM1026:
1488 9ee6e8bb pbrook
                return 1;
1489 9ee6e8bb pbrook
            case ARM_CPUID_ARM1136:
1490 9ee6e8bb pbrook
                return 7;
1491 9ee6e8bb pbrook
            case ARM_CPUID_ARM11MPCORE:
1492 9ee6e8bb pbrook
                return 1;
1493 9ee6e8bb pbrook
            case ARM_CPUID_CORTEXA8:
1494 9ee6e8bb pbrook
                return 0;
1495 9ee6e8bb pbrook
            default:
1496 9ee6e8bb pbrook
                goto bad_reg;
1497 9ee6e8bb pbrook
            }
1498 b5ff1b31 bellard
        case 2: /* Coprocessor access register.  */
1499 610c3c8a balrog
            if (arm_feature(env, ARM_FEATURE_XSCALE))
1500 610c3c8a balrog
                goto bad_reg;
1501 b5ff1b31 bellard
            return env->cp15.c1_coproc;
1502 b5ff1b31 bellard
        default:
1503 b5ff1b31 bellard
            goto bad_reg;
1504 b5ff1b31 bellard
        }
1505 ce819861 pbrook
    case 2: /* MMU Page table control / MPU cache control.  */
1506 ce819861 pbrook
        if (arm_feature(env, ARM_FEATURE_MPU)) {
1507 ce819861 pbrook
            switch (op2) {
1508 ce819861 pbrook
            case 0:
1509 ce819861 pbrook
                return env->cp15.c2_data;
1510 ce819861 pbrook
                break;
1511 ce819861 pbrook
            case 1:
1512 ce819861 pbrook
                return env->cp15.c2_insn;
1513 ce819861 pbrook
                break;
1514 ce819861 pbrook
            default:
1515 ce819861 pbrook
                goto bad_reg;
1516 ce819861 pbrook
            }
1517 ce819861 pbrook
        } else {
1518 9ee6e8bb pbrook
            switch (op2) {
1519 9ee6e8bb pbrook
            case 0:
1520 9ee6e8bb pbrook
                return env->cp15.c2_base0;
1521 9ee6e8bb pbrook
            case 1:
1522 9ee6e8bb pbrook
                return env->cp15.c2_base1;
1523 9ee6e8bb pbrook
            case 2:
1524 9ee6e8bb pbrook
                {
1525 9ee6e8bb pbrook
                    int n;
1526 9ee6e8bb pbrook
                    uint32_t mask;
1527 9ee6e8bb pbrook
                    n = 0;
1528 9ee6e8bb pbrook
                    mask = env->cp15.c2_mask;
1529 9ee6e8bb pbrook
                    while (mask) {
1530 9ee6e8bb pbrook
                        n++;
1531 9ee6e8bb pbrook
                        mask <<= 1;
1532 9ee6e8bb pbrook
                    }
1533 9ee6e8bb pbrook
                    return n;
1534 9ee6e8bb pbrook
                }
1535 9ee6e8bb pbrook
            default:
1536 9ee6e8bb pbrook
                goto bad_reg;
1537 9ee6e8bb pbrook
            }
1538 9ee6e8bb pbrook
        }
1539 ce819861 pbrook
    case 3: /* MMU Domain access control / MPU write buffer control.  */
1540 b5ff1b31 bellard
        return env->cp15.c3;
1541 b5ff1b31 bellard
    case 4: /* Reserved.  */
1542 b5ff1b31 bellard
        goto bad_reg;
1543 ce819861 pbrook
    case 5: /* MMU Fault status / MPU access permission.  */
1544 c3d2689d balrog
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
1545 c3d2689d balrog
            op2 = 0;
1546 b5ff1b31 bellard
        switch (op2) {
1547 b5ff1b31 bellard
        case 0:
1548 ce819861 pbrook
            if (arm_feature(env, ARM_FEATURE_MPU))
1549 ce819861 pbrook
                return simple_mpu_ap_bits(env->cp15.c5_data);
1550 b5ff1b31 bellard
            return env->cp15.c5_data;
1551 b5ff1b31 bellard
        case 1:
1552 ce819861 pbrook
            if (arm_feature(env, ARM_FEATURE_MPU))
1553 ce819861 pbrook
                return simple_mpu_ap_bits(env->cp15.c5_data);
1554 ce819861 pbrook
            return env->cp15.c5_insn;
1555 ce819861 pbrook
        case 2:
1556 ce819861 pbrook
            if (!arm_feature(env, ARM_FEATURE_MPU))
1557 ce819861 pbrook
                goto bad_reg;
1558 ce819861 pbrook
            return env->cp15.c5_data;
1559 ce819861 pbrook
        case 3:
1560 ce819861 pbrook
            if (!arm_feature(env, ARM_FEATURE_MPU))
1561 ce819861 pbrook
                goto bad_reg;
1562 b5ff1b31 bellard
            return env->cp15.c5_insn;
1563 b5ff1b31 bellard
        default:
1564 b5ff1b31 bellard
            goto bad_reg;
1565 b5ff1b31 bellard
        }
1566 9ee6e8bb pbrook
    case 6: /* MMU Fault address.  */
1567 ce819861 pbrook
        if (arm_feature(env, ARM_FEATURE_MPU)) {
1568 9ee6e8bb pbrook
            if (crm >= 8)
1569 ce819861 pbrook
                goto bad_reg;
1570 9ee6e8bb pbrook
            return env->cp15.c6_region[crm];
1571 ce819861 pbrook
        } else {
1572 c3d2689d balrog
            if (arm_feature(env, ARM_FEATURE_OMAPCP))
1573 c3d2689d balrog
                op2 = 0;
1574 9ee6e8bb pbrook
            switch (op2) {
1575 9ee6e8bb pbrook
            case 0:
1576 9ee6e8bb pbrook
                return env->cp15.c6_data;
1577 9ee6e8bb pbrook
            case 1:
1578 9ee6e8bb pbrook
                if (arm_feature(env, ARM_FEATURE_V6)) {
1579 9ee6e8bb pbrook
                    /* Watchpoint Fault Adrress.  */
1580 9ee6e8bb pbrook
                    return 0; /* Not implemented.  */
1581 9ee6e8bb pbrook
                } else {
1582 9ee6e8bb pbrook
                    /* Instruction Fault Adrress.  */
1583 9ee6e8bb pbrook
                    /* Arm9 doesn't have an IFAR, but implementing it anyway
1584 9ee6e8bb pbrook
                       shouldn't do any harm.  */
1585 9ee6e8bb pbrook
                    return env->cp15.c6_insn;
1586 9ee6e8bb pbrook
                }
1587 9ee6e8bb pbrook
            case 2:
1588 9ee6e8bb pbrook
                if (arm_feature(env, ARM_FEATURE_V6)) {
1589 9ee6e8bb pbrook
                    /* Instruction Fault Adrress.  */
1590 9ee6e8bb pbrook
                    return env->cp15.c6_insn;
1591 9ee6e8bb pbrook
                } else {
1592 9ee6e8bb pbrook
                    goto bad_reg;
1593 9ee6e8bb pbrook
                }
1594 9ee6e8bb pbrook
            default:
1595 9ee6e8bb pbrook
                goto bad_reg;
1596 9ee6e8bb pbrook
            }
1597 b5ff1b31 bellard
        }
1598 b5ff1b31 bellard
    case 7: /* Cache control.  */
1599 b5ff1b31 bellard
        /* ??? This is for test, clean and invaidate operations that set the
1600 c1713132 balrog
           Z flag.  We can't represent N = Z = 1, so it also clears
1601 b5ff1b31 bellard
           the N flag.  Oh well.  */
1602 b5ff1b31 bellard
        env->NZF = 0;
1603 b5ff1b31 bellard
        return 0;
1604 b5ff1b31 bellard
    case 8: /* MMU TLB control.  */
1605 b5ff1b31 bellard
        goto bad_reg;
1606 b5ff1b31 bellard
    case 9: /* Cache lockdown.  */
1607 9ee6e8bb pbrook
        switch (op1) {
1608 9ee6e8bb pbrook
        case 0: /* L1 cache.  */
1609 9ee6e8bb pbrook
            if (arm_feature(env, ARM_FEATURE_OMAPCP))
1610 9ee6e8bb pbrook
                return 0;
1611 9ee6e8bb pbrook
            switch (op2) {
1612 9ee6e8bb pbrook
            case 0:
1613 9ee6e8bb pbrook
                return env->cp15.c9_data;
1614 9ee6e8bb pbrook
            case 1:
1615 9ee6e8bb pbrook
                return env->cp15.c9_insn;
1616 9ee6e8bb pbrook
            default:
1617 9ee6e8bb pbrook
                goto bad_reg;
1618 9ee6e8bb pbrook
            }
1619 9ee6e8bb pbrook
        case 1: /* L2 cache */
1620 9ee6e8bb pbrook
            if (crm != 0)
1621 9ee6e8bb pbrook
                goto bad_reg;
1622 9ee6e8bb pbrook
            /* L2 Lockdown and Auxiliary control.  */
1623 c3d2689d balrog
            return 0;
1624 b5ff1b31 bellard
        default:
1625 b5ff1b31 bellard
            goto bad_reg;
1626 b5ff1b31 bellard
        }
1627 b5ff1b31 bellard
    case 10: /* MMU TLB lockdown.  */
1628 b5ff1b31 bellard
        /* ??? TLB lockdown not implemented.  */
1629 b5ff1b31 bellard
        return 0;
1630 b5ff1b31 bellard
    case 11: /* TCM DMA control.  */
1631 b5ff1b31 bellard
    case 12: /* Reserved.  */
1632 b5ff1b31 bellard
        goto bad_reg;
1633 b5ff1b31 bellard
    case 13: /* Process ID.  */
1634 b5ff1b31 bellard
        switch (op2) {
1635 b5ff1b31 bellard
        case 0:
1636 b5ff1b31 bellard
            return env->cp15.c13_fcse;
1637 b5ff1b31 bellard
        case 1:
1638 b5ff1b31 bellard
            return env->cp15.c13_context;
1639 9ee6e8bb pbrook
        case 2:
1640 9ee6e8bb pbrook
            return env->cp15.c13_tls1;
1641 9ee6e8bb pbrook
        case 3:
1642 9ee6e8bb pbrook
            return env->cp15.c13_tls2;
1643 9ee6e8bb pbrook
        case 4:
1644 9ee6e8bb pbrook
            return env->cp15.c13_tls3;
1645 b5ff1b31 bellard
        default:
1646 b5ff1b31 bellard
            goto bad_reg;
1647 b5ff1b31 bellard
        }
1648 b5ff1b31 bellard
    case 14: /* Reserved.  */
1649 b5ff1b31 bellard
        goto bad_reg;
1650 b5ff1b31 bellard
    case 15: /* Implementation specific.  */
1651 c1713132 balrog
        if (arm_feature(env, ARM_FEATURE_XSCALE)) {
1652 c3d2689d balrog
            if (op2 == 0 && crm == 1)
1653 c1713132 balrog
                return env->cp15.c15_cpar;
1654 c1713132 balrog
1655 c1713132 balrog
            goto bad_reg;
1656 c1713132 balrog
        }
1657 c3d2689d balrog
        if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
1658 c3d2689d balrog
            switch (crm) {
1659 c3d2689d balrog
            case 0:
1660 c3d2689d balrog
                return 0;
1661 c3d2689d balrog
            case 1: /* Read TI925T configuration.  */
1662 c3d2689d balrog
                return env->cp15.c15_ticonfig;
1663 c3d2689d balrog
            case 2: /* Read I_max.  */
1664 c3d2689d balrog
                return env->cp15.c15_i_max;
1665 c3d2689d balrog
            case 3: /* Read I_min.  */
1666 c3d2689d balrog
                return env->cp15.c15_i_min;
1667 c3d2689d balrog
            case 4: /* Read thread-ID.  */
1668 c3d2689d balrog
                return env->cp15.c15_threadid;
1669 c3d2689d balrog
            case 8: /* TI925T_status */
1670 c3d2689d balrog
                return 0;
1671 c3d2689d balrog
            }
1672 c3d2689d balrog
            goto bad_reg;
1673 c3d2689d balrog
        }
1674 b5ff1b31 bellard
        return 0;
1675 b5ff1b31 bellard
    }
1676 b5ff1b31 bellard
bad_reg:
1677 b5ff1b31 bellard
    /* ??? For debugging only.  Should raise illegal instruction exception.  */
1678 9ee6e8bb pbrook
    cpu_abort(env, "Unimplemented cp15 register read (c%d, c%d, {%d, %d})\n",
1679 9ee6e8bb pbrook
              (insn >> 16) & 0xf, crm, op1, op2);
1680 b5ff1b31 bellard
    return 0;
1681 b5ff1b31 bellard
}
1682 b5ff1b31 bellard
1683 9ee6e8bb pbrook
void helper_set_r13_banked(CPUState *env, int mode, uint32_t val)
1684 9ee6e8bb pbrook
{
1685 9ee6e8bb pbrook
    env->banked_r13[bank_number(mode)] = val;
1686 9ee6e8bb pbrook
}
1687 9ee6e8bb pbrook
1688 9ee6e8bb pbrook
uint32_t helper_get_r13_banked(CPUState *env, int mode)
1689 9ee6e8bb pbrook
{
1690 9ee6e8bb pbrook
    return env->banked_r13[bank_number(mode)];
1691 9ee6e8bb pbrook
}
1692 9ee6e8bb pbrook
1693 9ee6e8bb pbrook
uint32_t helper_v7m_mrs(CPUState *env, int reg)
1694 9ee6e8bb pbrook
{
1695 9ee6e8bb pbrook
    switch (reg) {
1696 9ee6e8bb pbrook
    case 0: /* APSR */
1697 9ee6e8bb pbrook
        return xpsr_read(env) & 0xf8000000;
1698 9ee6e8bb pbrook
    case 1: /* IAPSR */
1699 9ee6e8bb pbrook
        return xpsr_read(env) & 0xf80001ff;
1700 9ee6e8bb pbrook
    case 2: /* EAPSR */
1701 9ee6e8bb pbrook
        return xpsr_read(env) & 0xff00fc00;
1702 9ee6e8bb pbrook
    case 3: /* xPSR */
1703 9ee6e8bb pbrook
        return xpsr_read(env) & 0xff00fdff;
1704 9ee6e8bb pbrook
    case 5: /* IPSR */
1705 9ee6e8bb pbrook
        return xpsr_read(env) & 0x000001ff;
1706 9ee6e8bb pbrook
    case 6: /* EPSR */
1707 9ee6e8bb pbrook
        return xpsr_read(env) & 0x0700fc00;
1708 9ee6e8bb pbrook
    case 7: /* IEPSR */
1709 9ee6e8bb pbrook
        return xpsr_read(env) & 0x0700edff;
1710 9ee6e8bb pbrook
    case 8: /* MSP */
1711 9ee6e8bb pbrook
        return env->v7m.current_sp ? env->v7m.other_sp : env->regs[13];
1712 9ee6e8bb pbrook
    case 9: /* PSP */
1713 9ee6e8bb pbrook
        return env->v7m.current_sp ? env->regs[13] : env->v7m.other_sp;
1714 9ee6e8bb pbrook
    case 16: /* PRIMASK */
1715 9ee6e8bb pbrook
        return (env->uncached_cpsr & CPSR_I) != 0;
1716 9ee6e8bb pbrook
    case 17: /* FAULTMASK */
1717 9ee6e8bb pbrook
        return (env->uncached_cpsr & CPSR_F) != 0;
1718 9ee6e8bb pbrook
    case 18: /* BASEPRI */
1719 9ee6e8bb pbrook
    case 19: /* BASEPRI_MAX */
1720 9ee6e8bb pbrook
        return env->v7m.basepri;
1721 9ee6e8bb pbrook
    case 20: /* CONTROL */
1722 9ee6e8bb pbrook
        return env->v7m.control;
1723 9ee6e8bb pbrook
    default:
1724 9ee6e8bb pbrook
        /* ??? For debugging only.  */
1725 9ee6e8bb pbrook
        cpu_abort(env, "Unimplemented system register read (%d)\n", reg);
1726 9ee6e8bb pbrook
        return 0;
1727 9ee6e8bb pbrook
    }
1728 9ee6e8bb pbrook
}
1729 9ee6e8bb pbrook
1730 9ee6e8bb pbrook
void helper_v7m_msr(CPUState *env, int reg, uint32_t val)
1731 9ee6e8bb pbrook
{
1732 9ee6e8bb pbrook
    switch (reg) {
1733 9ee6e8bb pbrook
    case 0: /* APSR */
1734 9ee6e8bb pbrook
        xpsr_write(env, val, 0xf8000000);
1735 9ee6e8bb pbrook
        break;
1736 9ee6e8bb pbrook
    case 1: /* IAPSR */
1737 9ee6e8bb pbrook
        xpsr_write(env, val, 0xf8000000);
1738 9ee6e8bb pbrook
        break;
1739 9ee6e8bb pbrook
    case 2: /* EAPSR */
1740 9ee6e8bb pbrook
        xpsr_write(env, val, 0xfe00fc00);
1741 9ee6e8bb pbrook
        break;
1742 9ee6e8bb pbrook
    case 3: /* xPSR */
1743 9ee6e8bb pbrook
        xpsr_write(env, val, 0xfe00fc00);
1744 9ee6e8bb pbrook
        break;
1745 9ee6e8bb pbrook
    case 5: /* IPSR */
1746 9ee6e8bb pbrook
        /* IPSR bits are readonly.  */
1747 9ee6e8bb pbrook
        break;
1748 9ee6e8bb pbrook
    case 6: /* EPSR */
1749 9ee6e8bb pbrook
        xpsr_write(env, val, 0x0600fc00);
1750 9ee6e8bb pbrook
        break;
1751 9ee6e8bb pbrook
    case 7: /* IEPSR */
1752 9ee6e8bb pbrook
        xpsr_write(env, val, 0x0600fc00);
1753 9ee6e8bb pbrook
        break;
1754 9ee6e8bb pbrook
    case 8: /* MSP */
1755 9ee6e8bb pbrook
        if (env->v7m.current_sp)
1756 9ee6e8bb pbrook
            env->v7m.other_sp = val;
1757 9ee6e8bb pbrook
        else
1758 9ee6e8bb pbrook
            env->regs[13] = val;
1759 9ee6e8bb pbrook
        break;
1760 9ee6e8bb pbrook
    case 9: /* PSP */
1761 9ee6e8bb pbrook
        if (env->v7m.current_sp)
1762 9ee6e8bb pbrook
            env->regs[13] = val;
1763 9ee6e8bb pbrook
        else
1764 9ee6e8bb pbrook
            env->v7m.other_sp = val;
1765 9ee6e8bb pbrook
        break;
1766 9ee6e8bb pbrook
    case 16: /* PRIMASK */
1767 9ee6e8bb pbrook
        if (val & 1)
1768 9ee6e8bb pbrook
            env->uncached_cpsr |= CPSR_I;
1769 9ee6e8bb pbrook
        else
1770 9ee6e8bb pbrook
            env->uncached_cpsr &= ~CPSR_I;
1771 9ee6e8bb pbrook
        break;
1772 9ee6e8bb pbrook
    case 17: /* FAULTMASK */
1773 9ee6e8bb pbrook
        if (val & 1)
1774 9ee6e8bb pbrook
            env->uncached_cpsr |= CPSR_F;
1775 9ee6e8bb pbrook
        else
1776 9ee6e8bb pbrook
            env->uncached_cpsr &= ~CPSR_F;
1777 9ee6e8bb pbrook
        break;
1778 9ee6e8bb pbrook
    case 18: /* BASEPRI */
1779 9ee6e8bb pbrook
        env->v7m.basepri = val & 0xff;
1780 9ee6e8bb pbrook
        break;
1781 9ee6e8bb pbrook
    case 19: /* BASEPRI_MAX */
1782 9ee6e8bb pbrook
        val &= 0xff;
1783 9ee6e8bb pbrook
        if (val != 0 && (val < env->v7m.basepri || env->v7m.basepri == 0))
1784 9ee6e8bb pbrook
            env->v7m.basepri = val;
1785 9ee6e8bb pbrook
        break;
1786 9ee6e8bb pbrook
    case 20: /* CONTROL */
1787 9ee6e8bb pbrook
        env->v7m.control = val & 3;
1788 9ee6e8bb pbrook
        switch_v7m_sp(env, (val & 2) != 0);
1789 9ee6e8bb pbrook
        break;
1790 9ee6e8bb pbrook
    default:
1791 9ee6e8bb pbrook
        /* ??? For debugging only.  */
1792 9ee6e8bb pbrook
        cpu_abort(env, "Unimplemented system register write (%d)\n", reg);
1793 9ee6e8bb pbrook
        return;
1794 9ee6e8bb pbrook
    }
1795 9ee6e8bb pbrook
}
1796 9ee6e8bb pbrook
1797 c1713132 balrog
void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
1798 c1713132 balrog
                ARMReadCPFunc *cp_read, ARMWriteCPFunc *cp_write,
1799 c1713132 balrog
                void *opaque)
1800 c1713132 balrog
{
1801 c1713132 balrog
    if (cpnum < 0 || cpnum > 14) {
1802 c1713132 balrog
        cpu_abort(env, "Bad coprocessor number: %i\n", cpnum);
1803 c1713132 balrog
        return;
1804 c1713132 balrog
    }
1805 c1713132 balrog
1806 c1713132 balrog
    env->cp[cpnum].cp_read = cp_read;
1807 c1713132 balrog
    env->cp[cpnum].cp_write = cp_write;
1808 c1713132 balrog
    env->cp[cpnum].opaque = opaque;
1809 c1713132 balrog
}
1810 c1713132 balrog
1811 b5ff1b31 bellard
#endif