Statistics
| Branch: | Revision:

root / target-arm / helper.c @ 1497c961

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