Statistics
| Branch: | Revision:

root / target-arm / helper.c @ 4373f3ce

History | View | Annotate | Download (67.8 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 3670669c pbrook
int32_t HELPER(sdiv)(int32_t num, int32_t den)
351 3670669c pbrook
{
352 3670669c pbrook
    if (den == 0)
353 3670669c pbrook
      return 0;
354 3670669c pbrook
    return num / den;
355 3670669c pbrook
}
356 3670669c pbrook
357 3670669c pbrook
uint32_t HELPER(udiv)(uint32_t num, uint32_t den)
358 3670669c pbrook
{
359 3670669c pbrook
    if (den == 0)
360 3670669c pbrook
      return 0;
361 3670669c pbrook
    return num / den;
362 3670669c pbrook
}
363 3670669c pbrook
364 3670669c pbrook
uint32_t HELPER(rbit)(uint32_t x)
365 3670669c pbrook
{
366 3670669c pbrook
    x =  ((x & 0xff000000) >> 24)
367 3670669c pbrook
       | ((x & 0x00ff0000) >> 8)
368 3670669c pbrook
       | ((x & 0x0000ff00) << 8)
369 3670669c pbrook
       | ((x & 0x000000ff) << 24);
370 3670669c pbrook
    x =  ((x & 0xf0f0f0f0) >> 4)
371 3670669c pbrook
       | ((x & 0x0f0f0f0f) << 4);
372 3670669c pbrook
    x =  ((x & 0x88888888) >> 3)
373 3670669c pbrook
       | ((x & 0x44444444) >> 1)
374 3670669c pbrook
       | ((x & 0x22222222) << 1)
375 3670669c pbrook
       | ((x & 0x11111111) << 3);
376 3670669c pbrook
    return x;
377 3670669c pbrook
}
378 3670669c pbrook
379 5fafdf24 ths
#if defined(CONFIG_USER_ONLY)
380 b5ff1b31 bellard
381 b5ff1b31 bellard
void do_interrupt (CPUState *env)
382 b5ff1b31 bellard
{
383 b5ff1b31 bellard
    env->exception_index = -1;
384 b5ff1b31 bellard
}
385 b5ff1b31 bellard
386 9ee6e8bb pbrook
/* Structure used to record exclusive memory locations.  */
387 9ee6e8bb pbrook
typedef struct mmon_state {
388 9ee6e8bb pbrook
    struct mmon_state *next;
389 9ee6e8bb pbrook
    CPUARMState *cpu_env;
390 9ee6e8bb pbrook
    uint32_t addr;
391 9ee6e8bb pbrook
} mmon_state;
392 9ee6e8bb pbrook
393 9ee6e8bb pbrook
/* Chain of current locks.  */
394 9ee6e8bb pbrook
static mmon_state* mmon_head = NULL;
395 9ee6e8bb pbrook
396 b5ff1b31 bellard
int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
397 6ebbf390 j_mayer
                              int mmu_idx, int is_softmmu)
398 b5ff1b31 bellard
{
399 b5ff1b31 bellard
    if (rw == 2) {
400 b5ff1b31 bellard
        env->exception_index = EXCP_PREFETCH_ABORT;
401 b5ff1b31 bellard
        env->cp15.c6_insn = address;
402 b5ff1b31 bellard
    } else {
403 b5ff1b31 bellard
        env->exception_index = EXCP_DATA_ABORT;
404 b5ff1b31 bellard
        env->cp15.c6_data = address;
405 b5ff1b31 bellard
    }
406 b5ff1b31 bellard
    return 1;
407 b5ff1b31 bellard
}
408 b5ff1b31 bellard
409 9ee6e8bb pbrook
static void allocate_mmon_state(CPUState *env)
410 9ee6e8bb pbrook
{
411 9ee6e8bb pbrook
    env->mmon_entry = malloc(sizeof (mmon_state));
412 9ee6e8bb pbrook
    if (!env->mmon_entry)
413 9ee6e8bb pbrook
        abort();
414 9ee6e8bb pbrook
    memset (env->mmon_entry, 0, sizeof (mmon_state));
415 9ee6e8bb pbrook
    env->mmon_entry->cpu_env = env;
416 9ee6e8bb pbrook
    mmon_head = env->mmon_entry;
417 9ee6e8bb pbrook
}
418 9ee6e8bb pbrook
419 9ee6e8bb pbrook
/* Flush any monitor locks for the specified address.  */
420 9ee6e8bb pbrook
static void flush_mmon(uint32_t addr)
421 9ee6e8bb pbrook
{
422 9ee6e8bb pbrook
    mmon_state *mon;
423 9ee6e8bb pbrook
424 9ee6e8bb pbrook
    for (mon = mmon_head; mon; mon = mon->next)
425 9ee6e8bb pbrook
      {
426 9ee6e8bb pbrook
        if (mon->addr != addr)
427 9ee6e8bb pbrook
          continue;
428 9ee6e8bb pbrook
429 9ee6e8bb pbrook
        mon->addr = 0;
430 9ee6e8bb pbrook
        break;
431 9ee6e8bb pbrook
      }
432 9ee6e8bb pbrook
}
433 9ee6e8bb pbrook
434 9ee6e8bb pbrook
/* Mark an address for exclusive access.  */
435 9ee6e8bb pbrook
void helper_mark_exclusive(CPUState *env, uint32_t addr)
436 9ee6e8bb pbrook
{
437 9ee6e8bb pbrook
    if (!env->mmon_entry)
438 9ee6e8bb pbrook
        allocate_mmon_state(env);
439 9ee6e8bb pbrook
    /* Clear any previous locks.  */
440 9ee6e8bb pbrook
    flush_mmon(addr);
441 9ee6e8bb pbrook
    env->mmon_entry->addr = addr;
442 9ee6e8bb pbrook
}
443 9ee6e8bb pbrook
444 9ee6e8bb pbrook
/* Test if an exclusive address is still exclusive.  Returns zero
445 9ee6e8bb pbrook
   if the address is still exclusive.   */
446 9ee6e8bb pbrook
int helper_test_exclusive(CPUState *env, uint32_t addr)
447 9ee6e8bb pbrook
{
448 9ee6e8bb pbrook
    int res;
449 9ee6e8bb pbrook
450 9ee6e8bb pbrook
    if (!env->mmon_entry)
451 9ee6e8bb pbrook
        return 1;
452 9ee6e8bb pbrook
    if (env->mmon_entry->addr == addr)
453 9ee6e8bb pbrook
        res = 0;
454 9ee6e8bb pbrook
    else
455 9ee6e8bb pbrook
        res = 1;
456 9ee6e8bb pbrook
    flush_mmon(addr);
457 9ee6e8bb pbrook
    return res;
458 9ee6e8bb pbrook
}
459 9ee6e8bb pbrook
460 9ee6e8bb pbrook
void helper_clrex(CPUState *env)
461 9ee6e8bb pbrook
{
462 9ee6e8bb pbrook
    if (!(env->mmon_entry && env->mmon_entry->addr))
463 9ee6e8bb pbrook
        return;
464 9ee6e8bb pbrook
    flush_mmon(env->mmon_entry->addr);
465 9ee6e8bb pbrook
}
466 9ee6e8bb pbrook
467 9b3c35e0 j_mayer
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
468 b5ff1b31 bellard
{
469 b5ff1b31 bellard
    return addr;
470 b5ff1b31 bellard
}
471 b5ff1b31 bellard
472 b5ff1b31 bellard
/* These should probably raise undefined insn exceptions.  */
473 c1713132 balrog
void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val)
474 c1713132 balrog
{
475 c1713132 balrog
    int op1 = (insn >> 8) & 0xf;
476 c1713132 balrog
    cpu_abort(env, "cp%i insn %08x\n", op1, insn);
477 c1713132 balrog
    return;
478 c1713132 balrog
}
479 c1713132 balrog
480 c1713132 balrog
uint32_t helper_get_cp(CPUState *env, uint32_t insn)
481 c1713132 balrog
{
482 c1713132 balrog
    int op1 = (insn >> 8) & 0xf;
483 c1713132 balrog
    cpu_abort(env, "cp%i insn %08x\n", op1, insn);
484 c1713132 balrog
    return 0;
485 c1713132 balrog
}
486 c1713132 balrog
487 b5ff1b31 bellard
void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
488 b5ff1b31 bellard
{
489 b5ff1b31 bellard
    cpu_abort(env, "cp15 insn %08x\n", insn);
490 b5ff1b31 bellard
}
491 b5ff1b31 bellard
492 b5ff1b31 bellard
uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
493 b5ff1b31 bellard
{
494 b5ff1b31 bellard
    cpu_abort(env, "cp15 insn %08x\n", insn);
495 b5ff1b31 bellard
    return 0;
496 b5ff1b31 bellard
}
497 b5ff1b31 bellard
498 9ee6e8bb pbrook
/* These should probably raise undefined insn exceptions.  */
499 9ee6e8bb pbrook
void helper_v7m_msr(CPUState *env, int reg, uint32_t val)
500 9ee6e8bb pbrook
{
501 9ee6e8bb pbrook
    cpu_abort(env, "v7m_mrs %d\n", reg);
502 9ee6e8bb pbrook
}
503 9ee6e8bb pbrook
504 9ee6e8bb pbrook
uint32_t helper_v7m_mrs(CPUState *env, int reg)
505 9ee6e8bb pbrook
{
506 9ee6e8bb pbrook
    cpu_abort(env, "v7m_mrs %d\n", reg);
507 9ee6e8bb pbrook
    return 0;
508 9ee6e8bb pbrook
}
509 9ee6e8bb pbrook
510 b5ff1b31 bellard
void switch_mode(CPUState *env, int mode)
511 b5ff1b31 bellard
{
512 b5ff1b31 bellard
    if (mode != ARM_CPU_MODE_USR)
513 b5ff1b31 bellard
        cpu_abort(env, "Tried to switch out of user mode\n");
514 b5ff1b31 bellard
}
515 b5ff1b31 bellard
516 b0109805 pbrook
void HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val)
517 9ee6e8bb pbrook
{
518 9ee6e8bb pbrook
    cpu_abort(env, "banked r13 write\n");
519 9ee6e8bb pbrook
}
520 9ee6e8bb pbrook
521 b0109805 pbrook
uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
522 9ee6e8bb pbrook
{
523 9ee6e8bb pbrook
    cpu_abort(env, "banked r13 read\n");
524 9ee6e8bb pbrook
    return 0;
525 9ee6e8bb pbrook
}
526 9ee6e8bb pbrook
527 b5ff1b31 bellard
#else
528 b5ff1b31 bellard
529 8e71621f pbrook
extern int semihosting_enabled;
530 8e71621f pbrook
531 b5ff1b31 bellard
/* Map CPU modes onto saved register banks.  */
532 b5ff1b31 bellard
static inline int bank_number (int mode)
533 b5ff1b31 bellard
{
534 b5ff1b31 bellard
    switch (mode) {
535 b5ff1b31 bellard
    case ARM_CPU_MODE_USR:
536 b5ff1b31 bellard
    case ARM_CPU_MODE_SYS:
537 b5ff1b31 bellard
        return 0;
538 b5ff1b31 bellard
    case ARM_CPU_MODE_SVC:
539 b5ff1b31 bellard
        return 1;
540 b5ff1b31 bellard
    case ARM_CPU_MODE_ABT:
541 b5ff1b31 bellard
        return 2;
542 b5ff1b31 bellard
    case ARM_CPU_MODE_UND:
543 b5ff1b31 bellard
        return 3;
544 b5ff1b31 bellard
    case ARM_CPU_MODE_IRQ:
545 b5ff1b31 bellard
        return 4;
546 b5ff1b31 bellard
    case ARM_CPU_MODE_FIQ:
547 b5ff1b31 bellard
        return 5;
548 b5ff1b31 bellard
    }
549 b5ff1b31 bellard
    cpu_abort(cpu_single_env, "Bad mode %x\n", mode);
550 b5ff1b31 bellard
    return -1;
551 b5ff1b31 bellard
}
552 b5ff1b31 bellard
553 b5ff1b31 bellard
void switch_mode(CPUState *env, int mode)
554 b5ff1b31 bellard
{
555 b5ff1b31 bellard
    int old_mode;
556 b5ff1b31 bellard
    int i;
557 b5ff1b31 bellard
558 b5ff1b31 bellard
    old_mode = env->uncached_cpsr & CPSR_M;
559 b5ff1b31 bellard
    if (mode == old_mode)
560 b5ff1b31 bellard
        return;
561 b5ff1b31 bellard
562 b5ff1b31 bellard
    if (old_mode == ARM_CPU_MODE_FIQ) {
563 b5ff1b31 bellard
        memcpy (env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
564 8637c67f pbrook
        memcpy (env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
565 b5ff1b31 bellard
    } else if (mode == ARM_CPU_MODE_FIQ) {
566 b5ff1b31 bellard
        memcpy (env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
567 8637c67f pbrook
        memcpy (env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
568 b5ff1b31 bellard
    }
569 b5ff1b31 bellard
570 b5ff1b31 bellard
    i = bank_number(old_mode);
571 b5ff1b31 bellard
    env->banked_r13[i] = env->regs[13];
572 b5ff1b31 bellard
    env->banked_r14[i] = env->regs[14];
573 b5ff1b31 bellard
    env->banked_spsr[i] = env->spsr;
574 b5ff1b31 bellard
575 b5ff1b31 bellard
    i = bank_number(mode);
576 b5ff1b31 bellard
    env->regs[13] = env->banked_r13[i];
577 b5ff1b31 bellard
    env->regs[14] = env->banked_r14[i];
578 b5ff1b31 bellard
    env->spsr = env->banked_spsr[i];
579 b5ff1b31 bellard
}
580 b5ff1b31 bellard
581 9ee6e8bb pbrook
static void v7m_push(CPUARMState *env, uint32_t val)
582 9ee6e8bb pbrook
{
583 9ee6e8bb pbrook
    env->regs[13] -= 4;
584 9ee6e8bb pbrook
    stl_phys(env->regs[13], val);
585 9ee6e8bb pbrook
}
586 9ee6e8bb pbrook
587 9ee6e8bb pbrook
static uint32_t v7m_pop(CPUARMState *env)
588 9ee6e8bb pbrook
{
589 9ee6e8bb pbrook
    uint32_t val;
590 9ee6e8bb pbrook
    val = ldl_phys(env->regs[13]);
591 9ee6e8bb pbrook
    env->regs[13] += 4;
592 9ee6e8bb pbrook
    return val;
593 9ee6e8bb pbrook
}
594 9ee6e8bb pbrook
595 9ee6e8bb pbrook
/* Switch to V7M main or process stack pointer.  */
596 9ee6e8bb pbrook
static void switch_v7m_sp(CPUARMState *env, int process)
597 9ee6e8bb pbrook
{
598 9ee6e8bb pbrook
    uint32_t tmp;
599 9ee6e8bb pbrook
    if (env->v7m.current_sp != process) {
600 9ee6e8bb pbrook
        tmp = env->v7m.other_sp;
601 9ee6e8bb pbrook
        env->v7m.other_sp = env->regs[13];
602 9ee6e8bb pbrook
        env->regs[13] = tmp;
603 9ee6e8bb pbrook
        env->v7m.current_sp = process;
604 9ee6e8bb pbrook
    }
605 9ee6e8bb pbrook
}
606 9ee6e8bb pbrook
607 9ee6e8bb pbrook
static void do_v7m_exception_exit(CPUARMState *env)
608 9ee6e8bb pbrook
{
609 9ee6e8bb pbrook
    uint32_t type;
610 9ee6e8bb pbrook
    uint32_t xpsr;
611 9ee6e8bb pbrook
612 9ee6e8bb pbrook
    type = env->regs[15];
613 9ee6e8bb pbrook
    if (env->v7m.exception != 0)
614 9ee6e8bb pbrook
        armv7m_nvic_complete_irq(env->v7m.nvic, env->v7m.exception);
615 9ee6e8bb pbrook
616 9ee6e8bb pbrook
    /* Switch to the target stack.  */
617 9ee6e8bb pbrook
    switch_v7m_sp(env, (type & 4) != 0);
618 9ee6e8bb pbrook
    /* Pop registers.  */
619 9ee6e8bb pbrook
    env->regs[0] = v7m_pop(env);
620 9ee6e8bb pbrook
    env->regs[1] = v7m_pop(env);
621 9ee6e8bb pbrook
    env->regs[2] = v7m_pop(env);
622 9ee6e8bb pbrook
    env->regs[3] = v7m_pop(env);
623 9ee6e8bb pbrook
    env->regs[12] = v7m_pop(env);
624 9ee6e8bb pbrook
    env->regs[14] = v7m_pop(env);
625 9ee6e8bb pbrook
    env->regs[15] = v7m_pop(env);
626 9ee6e8bb pbrook
    xpsr = v7m_pop(env);
627 9ee6e8bb pbrook
    xpsr_write(env, xpsr, 0xfffffdff);
628 9ee6e8bb pbrook
    /* Undo stack alignment.  */
629 9ee6e8bb pbrook
    if (xpsr & 0x200)
630 9ee6e8bb pbrook
        env->regs[13] |= 4;
631 9ee6e8bb pbrook
    /* ??? The exception return type specifies Thread/Handler mode.  However
632 9ee6e8bb pbrook
       this is also implied by the xPSR value. Not sure what to do
633 9ee6e8bb pbrook
       if there is a mismatch.  */
634 9ee6e8bb pbrook
    /* ??? Likewise for mismatches between the CONTROL register and the stack
635 9ee6e8bb pbrook
       pointer.  */
636 9ee6e8bb pbrook
}
637 9ee6e8bb pbrook
638 9ee6e8bb pbrook
void do_interrupt_v7m(CPUARMState *env)
639 9ee6e8bb pbrook
{
640 9ee6e8bb pbrook
    uint32_t xpsr = xpsr_read(env);
641 9ee6e8bb pbrook
    uint32_t lr;
642 9ee6e8bb pbrook
    uint32_t addr;
643 9ee6e8bb pbrook
644 9ee6e8bb pbrook
    lr = 0xfffffff1;
645 9ee6e8bb pbrook
    if (env->v7m.current_sp)
646 9ee6e8bb pbrook
        lr |= 4;
647 9ee6e8bb pbrook
    if (env->v7m.exception == 0)
648 9ee6e8bb pbrook
        lr |= 8;
649 9ee6e8bb pbrook
650 9ee6e8bb pbrook
    /* For exceptions we just mark as pending on the NVIC, and let that
651 9ee6e8bb pbrook
       handle it.  */
652 9ee6e8bb pbrook
    /* TODO: Need to escalate if the current priority is higher than the
653 9ee6e8bb pbrook
       one we're raising.  */
654 9ee6e8bb pbrook
    switch (env->exception_index) {
655 9ee6e8bb pbrook
    case EXCP_UDEF:
656 9ee6e8bb pbrook
        armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_USAGE);
657 9ee6e8bb pbrook
        return;
658 9ee6e8bb pbrook
    case EXCP_SWI:
659 9ee6e8bb pbrook
        env->regs[15] += 2;
660 9ee6e8bb pbrook
        armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_SVC);
661 9ee6e8bb pbrook
        return;
662 9ee6e8bb pbrook
    case EXCP_PREFETCH_ABORT:
663 9ee6e8bb pbrook
    case EXCP_DATA_ABORT:
664 9ee6e8bb pbrook
        armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_MEM);
665 9ee6e8bb pbrook
        return;
666 9ee6e8bb pbrook
    case EXCP_BKPT:
667 2ad207d4 pbrook
        if (semihosting_enabled) {
668 2ad207d4 pbrook
            int nr;
669 2ad207d4 pbrook
            nr = lduw_code(env->regs[15]) & 0xff;
670 2ad207d4 pbrook
            if (nr == 0xab) {
671 2ad207d4 pbrook
                env->regs[15] += 2;
672 2ad207d4 pbrook
                env->regs[0] = do_arm_semihosting(env);
673 2ad207d4 pbrook
                return;
674 2ad207d4 pbrook
            }
675 2ad207d4 pbrook
        }
676 9ee6e8bb pbrook
        armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_DEBUG);
677 9ee6e8bb pbrook
        return;
678 9ee6e8bb pbrook
    case EXCP_IRQ:
679 9ee6e8bb pbrook
        env->v7m.exception = armv7m_nvic_acknowledge_irq(env->v7m.nvic);
680 9ee6e8bb pbrook
        break;
681 9ee6e8bb pbrook
    case EXCP_EXCEPTION_EXIT:
682 9ee6e8bb pbrook
        do_v7m_exception_exit(env);
683 9ee6e8bb pbrook
        return;
684 9ee6e8bb pbrook
    default:
685 9ee6e8bb pbrook
        cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
686 9ee6e8bb pbrook
        return; /* Never happens.  Keep compiler happy.  */
687 9ee6e8bb pbrook
    }
688 9ee6e8bb pbrook
689 9ee6e8bb pbrook
    /* Align stack pointer.  */
690 9ee6e8bb pbrook
    /* ??? Should only do this if Configuration Control Register
691 9ee6e8bb pbrook
       STACKALIGN bit is set.  */
692 9ee6e8bb pbrook
    if (env->regs[13] & 4) {
693 9ee6e8bb pbrook
        env->regs[13] += 4;
694 9ee6e8bb pbrook
        xpsr |= 0x200;
695 9ee6e8bb pbrook
    }
696 9ee6e8bb pbrook
    /* Switch to the hander mode.  */
697 9ee6e8bb pbrook
    v7m_push(env, xpsr);
698 9ee6e8bb pbrook
    v7m_push(env, env->regs[15]);
699 9ee6e8bb pbrook
    v7m_push(env, env->regs[14]);
700 9ee6e8bb pbrook
    v7m_push(env, env->regs[12]);
701 9ee6e8bb pbrook
    v7m_push(env, env->regs[3]);
702 9ee6e8bb pbrook
    v7m_push(env, env->regs[2]);
703 9ee6e8bb pbrook
    v7m_push(env, env->regs[1]);
704 9ee6e8bb pbrook
    v7m_push(env, env->regs[0]);
705 9ee6e8bb pbrook
    switch_v7m_sp(env, 0);
706 9ee6e8bb pbrook
    env->uncached_cpsr &= ~CPSR_IT;
707 9ee6e8bb pbrook
    env->regs[14] = lr;
708 9ee6e8bb pbrook
    addr = ldl_phys(env->v7m.vecbase + env->v7m.exception * 4);
709 9ee6e8bb pbrook
    env->regs[15] = addr & 0xfffffffe;
710 9ee6e8bb pbrook
    env->thumb = addr & 1;
711 9ee6e8bb pbrook
}
712 9ee6e8bb pbrook
713 b5ff1b31 bellard
/* Handle a CPU exception.  */
714 b5ff1b31 bellard
void do_interrupt(CPUARMState *env)
715 b5ff1b31 bellard
{
716 b5ff1b31 bellard
    uint32_t addr;
717 b5ff1b31 bellard
    uint32_t mask;
718 b5ff1b31 bellard
    int new_mode;
719 b5ff1b31 bellard
    uint32_t offset;
720 b5ff1b31 bellard
721 9ee6e8bb pbrook
    if (IS_M(env)) {
722 9ee6e8bb pbrook
        do_interrupt_v7m(env);
723 9ee6e8bb pbrook
        return;
724 9ee6e8bb pbrook
    }
725 b5ff1b31 bellard
    /* TODO: Vectored interrupt controller.  */
726 b5ff1b31 bellard
    switch (env->exception_index) {
727 b5ff1b31 bellard
    case EXCP_UDEF:
728 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_UND;
729 b5ff1b31 bellard
        addr = 0x04;
730 b5ff1b31 bellard
        mask = CPSR_I;
731 b5ff1b31 bellard
        if (env->thumb)
732 b5ff1b31 bellard
            offset = 2;
733 b5ff1b31 bellard
        else
734 b5ff1b31 bellard
            offset = 4;
735 b5ff1b31 bellard
        break;
736 b5ff1b31 bellard
    case EXCP_SWI:
737 8e71621f pbrook
        if (semihosting_enabled) {
738 8e71621f pbrook
            /* Check for semihosting interrupt.  */
739 8e71621f pbrook
            if (env->thumb) {
740 8e71621f pbrook
                mask = lduw_code(env->regs[15] - 2) & 0xff;
741 8e71621f pbrook
            } else {
742 8e71621f pbrook
                mask = ldl_code(env->regs[15] - 4) & 0xffffff;
743 8e71621f pbrook
            }
744 8e71621f pbrook
            /* Only intercept calls from privileged modes, to provide some
745 8e71621f pbrook
               semblance of security.  */
746 8e71621f pbrook
            if (((mask == 0x123456 && !env->thumb)
747 8e71621f pbrook
                    || (mask == 0xab && env->thumb))
748 8e71621f pbrook
                  && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
749 8e71621f pbrook
                env->regs[0] = do_arm_semihosting(env);
750 8e71621f pbrook
                return;
751 8e71621f pbrook
            }
752 8e71621f pbrook
        }
753 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_SVC;
754 b5ff1b31 bellard
        addr = 0x08;
755 b5ff1b31 bellard
        mask = CPSR_I;
756 b5ff1b31 bellard
        /* The PC already points to the next instructon.  */
757 b5ff1b31 bellard
        offset = 0;
758 b5ff1b31 bellard
        break;
759 06c949e6 pbrook
    case EXCP_BKPT:
760 9ee6e8bb pbrook
        /* See if this is a semihosting syscall.  */
761 2ad207d4 pbrook
        if (env->thumb && semihosting_enabled) {
762 9ee6e8bb pbrook
            mask = lduw_code(env->regs[15]) & 0xff;
763 9ee6e8bb pbrook
            if (mask == 0xab
764 9ee6e8bb pbrook
                  && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
765 9ee6e8bb pbrook
                env->regs[15] += 2;
766 9ee6e8bb pbrook
                env->regs[0] = do_arm_semihosting(env);
767 9ee6e8bb pbrook
                return;
768 9ee6e8bb pbrook
            }
769 9ee6e8bb pbrook
        }
770 9ee6e8bb pbrook
        /* Fall through to prefetch abort.  */
771 9ee6e8bb pbrook
    case EXCP_PREFETCH_ABORT:
772 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_ABT;
773 b5ff1b31 bellard
        addr = 0x0c;
774 b5ff1b31 bellard
        mask = CPSR_A | CPSR_I;
775 b5ff1b31 bellard
        offset = 4;
776 b5ff1b31 bellard
        break;
777 b5ff1b31 bellard
    case EXCP_DATA_ABORT:
778 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_ABT;
779 b5ff1b31 bellard
        addr = 0x10;
780 b5ff1b31 bellard
        mask = CPSR_A | CPSR_I;
781 b5ff1b31 bellard
        offset = 8;
782 b5ff1b31 bellard
        break;
783 b5ff1b31 bellard
    case EXCP_IRQ:
784 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_IRQ;
785 b5ff1b31 bellard
        addr = 0x18;
786 b5ff1b31 bellard
        /* Disable IRQ and imprecise data aborts.  */
787 b5ff1b31 bellard
        mask = CPSR_A | CPSR_I;
788 b5ff1b31 bellard
        offset = 4;
789 b5ff1b31 bellard
        break;
790 b5ff1b31 bellard
    case EXCP_FIQ:
791 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_FIQ;
792 b5ff1b31 bellard
        addr = 0x1c;
793 b5ff1b31 bellard
        /* Disable FIQ, IRQ and imprecise data aborts.  */
794 b5ff1b31 bellard
        mask = CPSR_A | CPSR_I | CPSR_F;
795 b5ff1b31 bellard
        offset = 4;
796 b5ff1b31 bellard
        break;
797 b5ff1b31 bellard
    default:
798 b5ff1b31 bellard
        cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
799 b5ff1b31 bellard
        return; /* Never happens.  Keep compiler happy.  */
800 b5ff1b31 bellard
    }
801 b5ff1b31 bellard
    /* High vectors.  */
802 b5ff1b31 bellard
    if (env->cp15.c1_sys & (1 << 13)) {
803 b5ff1b31 bellard
        addr += 0xffff0000;
804 b5ff1b31 bellard
    }
805 b5ff1b31 bellard
    switch_mode (env, new_mode);
806 b5ff1b31 bellard
    env->spsr = cpsr_read(env);
807 9ee6e8bb pbrook
    /* Clear IT bits.  */
808 9ee6e8bb pbrook
    env->condexec_bits = 0;
809 6d7e6326 bellard
    /* Switch to the new mode, and switch to Arm mode.  */
810 b5ff1b31 bellard
    /* ??? Thumb interrupt handlers not implemented.  */
811 6d7e6326 bellard
    env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
812 b5ff1b31 bellard
    env->uncached_cpsr |= mask;
813 6d7e6326 bellard
    env->thumb = 0;
814 b5ff1b31 bellard
    env->regs[14] = env->regs[15] + offset;
815 b5ff1b31 bellard
    env->regs[15] = addr;
816 b5ff1b31 bellard
    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
817 b5ff1b31 bellard
}
818 b5ff1b31 bellard
819 b5ff1b31 bellard
/* Check section/page access permissions.
820 b5ff1b31 bellard
   Returns the page protection flags, or zero if the access is not
821 b5ff1b31 bellard
   permitted.  */
822 b5ff1b31 bellard
static inline int check_ap(CPUState *env, int ap, int domain, int access_type,
823 b5ff1b31 bellard
                           int is_user)
824 b5ff1b31 bellard
{
825 9ee6e8bb pbrook
  int prot_ro;
826 9ee6e8bb pbrook
827 b5ff1b31 bellard
  if (domain == 3)
828 b5ff1b31 bellard
    return PAGE_READ | PAGE_WRITE;
829 b5ff1b31 bellard
830 9ee6e8bb pbrook
  if (access_type == 1)
831 9ee6e8bb pbrook
      prot_ro = 0;
832 9ee6e8bb pbrook
  else
833 9ee6e8bb pbrook
      prot_ro = PAGE_READ;
834 9ee6e8bb pbrook
835 b5ff1b31 bellard
  switch (ap) {
836 b5ff1b31 bellard
  case 0:
837 78600320 pbrook
      if (access_type == 1)
838 b5ff1b31 bellard
          return 0;
839 b5ff1b31 bellard
      switch ((env->cp15.c1_sys >> 8) & 3) {
840 b5ff1b31 bellard
      case 1:
841 b5ff1b31 bellard
          return is_user ? 0 : PAGE_READ;
842 b5ff1b31 bellard
      case 2:
843 b5ff1b31 bellard
          return PAGE_READ;
844 b5ff1b31 bellard
      default:
845 b5ff1b31 bellard
          return 0;
846 b5ff1b31 bellard
      }
847 b5ff1b31 bellard
  case 1:
848 b5ff1b31 bellard
      return is_user ? 0 : PAGE_READ | PAGE_WRITE;
849 b5ff1b31 bellard
  case 2:
850 b5ff1b31 bellard
      if (is_user)
851 9ee6e8bb pbrook
          return prot_ro;
852 b5ff1b31 bellard
      else
853 b5ff1b31 bellard
          return PAGE_READ | PAGE_WRITE;
854 b5ff1b31 bellard
  case 3:
855 b5ff1b31 bellard
      return PAGE_READ | PAGE_WRITE;
856 9ee6e8bb pbrook
  case 4: case 7: /* Reserved.  */
857 9ee6e8bb pbrook
      return 0;
858 9ee6e8bb pbrook
  case 5:
859 9ee6e8bb pbrook
      return is_user ? 0 : prot_ro;
860 9ee6e8bb pbrook
  case 6:
861 9ee6e8bb pbrook
      return prot_ro;
862 b5ff1b31 bellard
  default:
863 b5ff1b31 bellard
      abort();
864 b5ff1b31 bellard
  }
865 b5ff1b31 bellard
}
866 b5ff1b31 bellard
867 9ee6e8bb pbrook
static int get_phys_addr_v5(CPUState *env, uint32_t address, int access_type,
868 9ee6e8bb pbrook
                            int is_user, uint32_t *phys_ptr, int *prot)
869 b5ff1b31 bellard
{
870 b5ff1b31 bellard
    int code;
871 b5ff1b31 bellard
    uint32_t table;
872 b5ff1b31 bellard
    uint32_t desc;
873 b5ff1b31 bellard
    int type;
874 b5ff1b31 bellard
    int ap;
875 b5ff1b31 bellard
    int domain;
876 b5ff1b31 bellard
    uint32_t phys_addr;
877 b5ff1b31 bellard
878 9ee6e8bb pbrook
    /* Pagetable walk.  */
879 9ee6e8bb pbrook
    /* Lookup l1 descriptor.  */
880 9ee6e8bb pbrook
    if (address & env->cp15.c2_mask)
881 9ee6e8bb pbrook
        table = env->cp15.c2_base1;
882 9ee6e8bb pbrook
    else
883 9ee6e8bb pbrook
        table = env->cp15.c2_base0;
884 9ee6e8bb pbrook
    table = (table & 0xffffc000) | ((address >> 18) & 0x3ffc);
885 9ee6e8bb pbrook
    desc = ldl_phys(table);
886 9ee6e8bb pbrook
    type = (desc & 3);
887 9ee6e8bb pbrook
    domain = (env->cp15.c3 >> ((desc >> 4) & 0x1e)) & 3;
888 9ee6e8bb pbrook
    if (type == 0) {
889 9ee6e8bb pbrook
        /* Secton translation fault.  */
890 9ee6e8bb pbrook
        code = 5;
891 9ee6e8bb pbrook
        goto do_fault;
892 9ee6e8bb pbrook
    }
893 9ee6e8bb pbrook
    if (domain == 0 || domain == 2) {
894 9ee6e8bb pbrook
        if (type == 2)
895 9ee6e8bb pbrook
            code = 9; /* Section domain fault.  */
896 9ee6e8bb pbrook
        else
897 9ee6e8bb pbrook
            code = 11; /* Page domain fault.  */
898 9ee6e8bb pbrook
        goto do_fault;
899 9ee6e8bb pbrook
    }
900 9ee6e8bb pbrook
    if (type == 2) {
901 9ee6e8bb pbrook
        /* 1Mb section.  */
902 9ee6e8bb pbrook
        phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
903 9ee6e8bb pbrook
        ap = (desc >> 10) & 3;
904 9ee6e8bb pbrook
        code = 13;
905 9ee6e8bb pbrook
    } else {
906 9ee6e8bb pbrook
        /* Lookup l2 entry.  */
907 9ee6e8bb pbrook
        if (type == 1) {
908 9ee6e8bb pbrook
            /* Coarse pagetable.  */
909 9ee6e8bb pbrook
            table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
910 9ee6e8bb pbrook
        } else {
911 9ee6e8bb pbrook
            /* Fine pagetable.  */
912 9ee6e8bb pbrook
            table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
913 9ee6e8bb pbrook
        }
914 9ee6e8bb pbrook
        desc = ldl_phys(table);
915 9ee6e8bb pbrook
        switch (desc & 3) {
916 9ee6e8bb pbrook
        case 0: /* Page translation fault.  */
917 9ee6e8bb pbrook
            code = 7;
918 9ee6e8bb pbrook
            goto do_fault;
919 9ee6e8bb pbrook
        case 1: /* 64k page.  */
920 9ee6e8bb pbrook
            phys_addr = (desc & 0xffff0000) | (address & 0xffff);
921 9ee6e8bb pbrook
            ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
922 ce819861 pbrook
            break;
923 9ee6e8bb pbrook
        case 2: /* 4k page.  */
924 9ee6e8bb pbrook
            phys_addr = (desc & 0xfffff000) | (address & 0xfff);
925 9ee6e8bb pbrook
            ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
926 ce819861 pbrook
            break;
927 9ee6e8bb pbrook
        case 3: /* 1k page.  */
928 9ee6e8bb pbrook
            if (type == 1) {
929 9ee6e8bb pbrook
                if (arm_feature(env, ARM_FEATURE_XSCALE)) {
930 9ee6e8bb pbrook
                    phys_addr = (desc & 0xfffff000) | (address & 0xfff);
931 9ee6e8bb pbrook
                } else {
932 9ee6e8bb pbrook
                    /* Page translation fault.  */
933 9ee6e8bb pbrook
                    code = 7;
934 9ee6e8bb pbrook
                    goto do_fault;
935 9ee6e8bb pbrook
                }
936 9ee6e8bb pbrook
            } else {
937 9ee6e8bb pbrook
                phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
938 9ee6e8bb pbrook
            }
939 9ee6e8bb pbrook
            ap = (desc >> 4) & 3;
940 ce819861 pbrook
            break;
941 ce819861 pbrook
        default:
942 9ee6e8bb pbrook
            /* Never happens, but compiler isn't smart enough to tell.  */
943 9ee6e8bb pbrook
            abort();
944 ce819861 pbrook
        }
945 9ee6e8bb pbrook
        code = 15;
946 9ee6e8bb pbrook
    }
947 9ee6e8bb pbrook
    *prot = check_ap(env, ap, domain, access_type, is_user);
948 9ee6e8bb pbrook
    if (!*prot) {
949 9ee6e8bb pbrook
        /* Access permission fault.  */
950 9ee6e8bb pbrook
        goto do_fault;
951 9ee6e8bb pbrook
    }
952 9ee6e8bb pbrook
    *phys_ptr = phys_addr;
953 9ee6e8bb pbrook
    return 0;
954 9ee6e8bb pbrook
do_fault:
955 9ee6e8bb pbrook
    return code | (domain << 4);
956 9ee6e8bb pbrook
}
957 9ee6e8bb pbrook
958 9ee6e8bb pbrook
static int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type,
959 9ee6e8bb pbrook
                            int is_user, uint32_t *phys_ptr, int *prot)
960 9ee6e8bb pbrook
{
961 9ee6e8bb pbrook
    int code;
962 9ee6e8bb pbrook
    uint32_t table;
963 9ee6e8bb pbrook
    uint32_t desc;
964 9ee6e8bb pbrook
    uint32_t xn;
965 9ee6e8bb pbrook
    int type;
966 9ee6e8bb pbrook
    int ap;
967 9ee6e8bb pbrook
    int domain;
968 9ee6e8bb pbrook
    uint32_t phys_addr;
969 9ee6e8bb pbrook
970 9ee6e8bb pbrook
    /* Pagetable walk.  */
971 9ee6e8bb pbrook
    /* Lookup l1 descriptor.  */
972 9ee6e8bb pbrook
    if (address & env->cp15.c2_mask)
973 9ee6e8bb pbrook
        table = env->cp15.c2_base1;
974 9ee6e8bb pbrook
    else
975 9ee6e8bb pbrook
        table = env->cp15.c2_base0;
976 9ee6e8bb pbrook
    table = (table & 0xffffc000) | ((address >> 18) & 0x3ffc);
977 9ee6e8bb pbrook
    desc = ldl_phys(table);
978 9ee6e8bb pbrook
    type = (desc & 3);
979 9ee6e8bb pbrook
    if (type == 0) {
980 9ee6e8bb pbrook
        /* Secton translation fault.  */
981 9ee6e8bb pbrook
        code = 5;
982 9ee6e8bb pbrook
        domain = 0;
983 9ee6e8bb pbrook
        goto do_fault;
984 9ee6e8bb pbrook
    } else if (type == 2 && (desc & (1 << 18))) {
985 9ee6e8bb pbrook
        /* Supersection.  */
986 9ee6e8bb pbrook
        domain = 0;
987 b5ff1b31 bellard
    } else {
988 9ee6e8bb pbrook
        /* Section or page.  */
989 9ee6e8bb pbrook
        domain = (desc >> 4) & 0x1e;
990 9ee6e8bb pbrook
    }
991 9ee6e8bb pbrook
    domain = (env->cp15.c3 >> domain) & 3;
992 9ee6e8bb pbrook
    if (domain == 0 || domain == 2) {
993 9ee6e8bb pbrook
        if (type == 2)
994 9ee6e8bb pbrook
            code = 9; /* Section domain fault.  */
995 9ee6e8bb pbrook
        else
996 9ee6e8bb pbrook
            code = 11; /* Page domain fault.  */
997 9ee6e8bb pbrook
        goto do_fault;
998 9ee6e8bb pbrook
    }
999 9ee6e8bb pbrook
    if (type == 2) {
1000 9ee6e8bb pbrook
        if (desc & (1 << 18)) {
1001 9ee6e8bb pbrook
            /* Supersection.  */
1002 9ee6e8bb pbrook
            phys_addr = (desc & 0xff000000) | (address & 0x00ffffff);
1003 b5ff1b31 bellard
        } else {
1004 9ee6e8bb pbrook
            /* Section.  */
1005 9ee6e8bb pbrook
            phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
1006 b5ff1b31 bellard
        }
1007 9ee6e8bb pbrook
        ap = ((desc >> 10) & 3) | ((desc >> 13) & 4);
1008 9ee6e8bb pbrook
        xn = desc & (1 << 4);
1009 9ee6e8bb pbrook
        code = 13;
1010 9ee6e8bb pbrook
    } else {
1011 9ee6e8bb pbrook
        /* Lookup l2 entry.  */
1012 9ee6e8bb pbrook
        table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
1013 9ee6e8bb pbrook
        desc = ldl_phys(table);
1014 9ee6e8bb pbrook
        ap = ((desc >> 4) & 3) | ((desc >> 7) & 4);
1015 9ee6e8bb pbrook
        switch (desc & 3) {
1016 9ee6e8bb pbrook
        case 0: /* Page translation fault.  */
1017 9ee6e8bb pbrook
            code = 7;
1018 b5ff1b31 bellard
            goto do_fault;
1019 9ee6e8bb pbrook
        case 1: /* 64k page.  */
1020 9ee6e8bb pbrook
            phys_addr = (desc & 0xffff0000) | (address & 0xffff);
1021 9ee6e8bb pbrook
            xn = desc & (1 << 15);
1022 9ee6e8bb pbrook
            break;
1023 9ee6e8bb pbrook
        case 2: case 3: /* 4k page.  */
1024 9ee6e8bb pbrook
            phys_addr = (desc & 0xfffff000) | (address & 0xfff);
1025 9ee6e8bb pbrook
            xn = desc & 1;
1026 9ee6e8bb pbrook
            break;
1027 9ee6e8bb pbrook
        default:
1028 9ee6e8bb pbrook
            /* Never happens, but compiler isn't smart enough to tell.  */
1029 9ee6e8bb pbrook
            abort();
1030 b5ff1b31 bellard
        }
1031 9ee6e8bb pbrook
        code = 15;
1032 9ee6e8bb pbrook
    }
1033 9ee6e8bb pbrook
    if (xn && access_type == 2)
1034 9ee6e8bb pbrook
        goto do_fault;
1035 9ee6e8bb pbrook
1036 9ee6e8bb pbrook
    *prot = check_ap(env, ap, domain, access_type, is_user);
1037 9ee6e8bb pbrook
    if (!*prot) {
1038 9ee6e8bb pbrook
        /* Access permission fault.  */
1039 9ee6e8bb pbrook
        goto do_fault;
1040 b5ff1b31 bellard
    }
1041 9ee6e8bb pbrook
    *phys_ptr = phys_addr;
1042 b5ff1b31 bellard
    return 0;
1043 b5ff1b31 bellard
do_fault:
1044 b5ff1b31 bellard
    return code | (domain << 4);
1045 b5ff1b31 bellard
}
1046 b5ff1b31 bellard
1047 9ee6e8bb pbrook
static int get_phys_addr_mpu(CPUState *env, uint32_t address, int access_type,
1048 9ee6e8bb pbrook
                             int is_user, uint32_t *phys_ptr, int *prot)
1049 9ee6e8bb pbrook
{
1050 9ee6e8bb pbrook
    int n;
1051 9ee6e8bb pbrook
    uint32_t mask;
1052 9ee6e8bb pbrook
    uint32_t base;
1053 9ee6e8bb pbrook
1054 9ee6e8bb pbrook
    *phys_ptr = address;
1055 9ee6e8bb pbrook
    for (n = 7; n >= 0; n--) {
1056 9ee6e8bb pbrook
        base = env->cp15.c6_region[n];
1057 9ee6e8bb pbrook
        if ((base & 1) == 0)
1058 9ee6e8bb pbrook
            continue;
1059 9ee6e8bb pbrook
        mask = 1 << ((base >> 1) & 0x1f);
1060 9ee6e8bb pbrook
        /* Keep this shift separate from the above to avoid an
1061 9ee6e8bb pbrook
           (undefined) << 32.  */
1062 9ee6e8bb pbrook
        mask = (mask << 1) - 1;
1063 9ee6e8bb pbrook
        if (((base ^ address) & ~mask) == 0)
1064 9ee6e8bb pbrook
            break;
1065 9ee6e8bb pbrook
    }
1066 9ee6e8bb pbrook
    if (n < 0)
1067 9ee6e8bb pbrook
        return 2;
1068 9ee6e8bb pbrook
1069 9ee6e8bb pbrook
    if (access_type == 2) {
1070 9ee6e8bb pbrook
        mask = env->cp15.c5_insn;
1071 9ee6e8bb pbrook
    } else {
1072 9ee6e8bb pbrook
        mask = env->cp15.c5_data;
1073 9ee6e8bb pbrook
    }
1074 9ee6e8bb pbrook
    mask = (mask >> (n * 4)) & 0xf;
1075 9ee6e8bb pbrook
    switch (mask) {
1076 9ee6e8bb pbrook
    case 0:
1077 9ee6e8bb pbrook
        return 1;
1078 9ee6e8bb pbrook
    case 1:
1079 9ee6e8bb pbrook
        if (is_user)
1080 9ee6e8bb pbrook
          return 1;
1081 9ee6e8bb pbrook
        *prot = PAGE_READ | PAGE_WRITE;
1082 9ee6e8bb pbrook
        break;
1083 9ee6e8bb pbrook
    case 2:
1084 9ee6e8bb pbrook
        *prot = PAGE_READ;
1085 9ee6e8bb pbrook
        if (!is_user)
1086 9ee6e8bb pbrook
            *prot |= PAGE_WRITE;
1087 9ee6e8bb pbrook
        break;
1088 9ee6e8bb pbrook
    case 3:
1089 9ee6e8bb pbrook
        *prot = PAGE_READ | PAGE_WRITE;
1090 9ee6e8bb pbrook
        break;
1091 9ee6e8bb pbrook
    case 5:
1092 9ee6e8bb pbrook
        if (is_user)
1093 9ee6e8bb pbrook
            return 1;
1094 9ee6e8bb pbrook
        *prot = PAGE_READ;
1095 9ee6e8bb pbrook
        break;
1096 9ee6e8bb pbrook
    case 6:
1097 9ee6e8bb pbrook
        *prot = PAGE_READ;
1098 9ee6e8bb pbrook
        break;
1099 9ee6e8bb pbrook
    default:
1100 9ee6e8bb pbrook
        /* Bad permission.  */
1101 9ee6e8bb pbrook
        return 1;
1102 9ee6e8bb pbrook
    }
1103 9ee6e8bb pbrook
    return 0;
1104 9ee6e8bb pbrook
}
1105 9ee6e8bb pbrook
1106 9ee6e8bb pbrook
static inline int get_phys_addr(CPUState *env, uint32_t address,
1107 9ee6e8bb pbrook
                                int access_type, int is_user,
1108 9ee6e8bb pbrook
                                uint32_t *phys_ptr, int *prot)
1109 9ee6e8bb pbrook
{
1110 9ee6e8bb pbrook
    /* Fast Context Switch Extension.  */
1111 9ee6e8bb pbrook
    if (address < 0x02000000)
1112 9ee6e8bb pbrook
        address += env->cp15.c13_fcse;
1113 9ee6e8bb pbrook
1114 9ee6e8bb pbrook
    if ((env->cp15.c1_sys & 1) == 0) {
1115 9ee6e8bb pbrook
        /* MMU/MPU disabled.  */
1116 9ee6e8bb pbrook
        *phys_ptr = address;
1117 9ee6e8bb pbrook
        *prot = PAGE_READ | PAGE_WRITE;
1118 9ee6e8bb pbrook
        return 0;
1119 9ee6e8bb pbrook
    } else if (arm_feature(env, ARM_FEATURE_MPU)) {
1120 9ee6e8bb pbrook
        return get_phys_addr_mpu(env, address, access_type, is_user, phys_ptr,
1121 9ee6e8bb pbrook
                                 prot);
1122 9ee6e8bb pbrook
    } else if (env->cp15.c1_sys & (1 << 23)) {
1123 9ee6e8bb pbrook
        return get_phys_addr_v6(env, address, access_type, is_user, phys_ptr,
1124 9ee6e8bb pbrook
                                prot);
1125 9ee6e8bb pbrook
    } else {
1126 9ee6e8bb pbrook
        return get_phys_addr_v5(env, address, access_type, is_user, phys_ptr,
1127 9ee6e8bb pbrook
                                prot);
1128 9ee6e8bb pbrook
    }
1129 9ee6e8bb pbrook
}
1130 9ee6e8bb pbrook
1131 b5ff1b31 bellard
int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address,
1132 6ebbf390 j_mayer
                              int access_type, int mmu_idx, int is_softmmu)
1133 b5ff1b31 bellard
{
1134 b5ff1b31 bellard
    uint32_t phys_addr;
1135 b5ff1b31 bellard
    int prot;
1136 6ebbf390 j_mayer
    int ret, is_user;
1137 b5ff1b31 bellard
1138 6ebbf390 j_mayer
    is_user = mmu_idx == MMU_USER_IDX;
1139 b5ff1b31 bellard
    ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot);
1140 b5ff1b31 bellard
    if (ret == 0) {
1141 b5ff1b31 bellard
        /* Map a single [sub]page.  */
1142 b5ff1b31 bellard
        phys_addr &= ~(uint32_t)0x3ff;
1143 b5ff1b31 bellard
        address &= ~(uint32_t)0x3ff;
1144 6ebbf390 j_mayer
        return tlb_set_page (env, address, phys_addr, prot, mmu_idx,
1145 b5ff1b31 bellard
                             is_softmmu);
1146 b5ff1b31 bellard
    }
1147 b5ff1b31 bellard
1148 b5ff1b31 bellard
    if (access_type == 2) {
1149 b5ff1b31 bellard
        env->cp15.c5_insn = ret;
1150 b5ff1b31 bellard
        env->cp15.c6_insn = address;
1151 b5ff1b31 bellard
        env->exception_index = EXCP_PREFETCH_ABORT;
1152 b5ff1b31 bellard
    } else {
1153 b5ff1b31 bellard
        env->cp15.c5_data = ret;
1154 9ee6e8bb pbrook
        if (access_type == 1 && arm_feature(env, ARM_FEATURE_V6))
1155 9ee6e8bb pbrook
            env->cp15.c5_data |= (1 << 11);
1156 b5ff1b31 bellard
        env->cp15.c6_data = address;
1157 b5ff1b31 bellard
        env->exception_index = EXCP_DATA_ABORT;
1158 b5ff1b31 bellard
    }
1159 b5ff1b31 bellard
    return 1;
1160 b5ff1b31 bellard
}
1161 b5ff1b31 bellard
1162 9b3c35e0 j_mayer
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1163 b5ff1b31 bellard
{
1164 b5ff1b31 bellard
    uint32_t phys_addr;
1165 b5ff1b31 bellard
    int prot;
1166 b5ff1b31 bellard
    int ret;
1167 b5ff1b31 bellard
1168 b5ff1b31 bellard
    ret = get_phys_addr(env, addr, 0, 0, &phys_addr, &prot);
1169 b5ff1b31 bellard
1170 b5ff1b31 bellard
    if (ret != 0)
1171 b5ff1b31 bellard
        return -1;
1172 b5ff1b31 bellard
1173 b5ff1b31 bellard
    return phys_addr;
1174 b5ff1b31 bellard
}
1175 b5ff1b31 bellard
1176 9ee6e8bb pbrook
/* Not really implemented.  Need to figure out a sane way of doing this.
1177 9ee6e8bb pbrook
   Maybe add generic watchpoint support and use that.  */
1178 9ee6e8bb pbrook
1179 9ee6e8bb pbrook
void helper_mark_exclusive(CPUState *env, uint32_t addr)
1180 9ee6e8bb pbrook
{
1181 9ee6e8bb pbrook
    env->mmon_addr = addr;
1182 9ee6e8bb pbrook
}
1183 9ee6e8bb pbrook
1184 9ee6e8bb pbrook
int helper_test_exclusive(CPUState *env, uint32_t addr)
1185 9ee6e8bb pbrook
{
1186 9ee6e8bb pbrook
    return (env->mmon_addr != addr);
1187 9ee6e8bb pbrook
}
1188 9ee6e8bb pbrook
1189 9ee6e8bb pbrook
void helper_clrex(CPUState *env)
1190 9ee6e8bb pbrook
{
1191 9ee6e8bb pbrook
    env->mmon_addr = -1;
1192 9ee6e8bb pbrook
}
1193 9ee6e8bb pbrook
1194 c1713132 balrog
void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val)
1195 c1713132 balrog
{
1196 c1713132 balrog
    int cp_num = (insn >> 8) & 0xf;
1197 c1713132 balrog
    int cp_info = (insn >> 5) & 7;
1198 c1713132 balrog
    int src = (insn >> 16) & 0xf;
1199 c1713132 balrog
    int operand = insn & 0xf;
1200 c1713132 balrog
1201 c1713132 balrog
    if (env->cp[cp_num].cp_write)
1202 c1713132 balrog
        env->cp[cp_num].cp_write(env->cp[cp_num].opaque,
1203 c1713132 balrog
                                 cp_info, src, operand, val);
1204 c1713132 balrog
}
1205 c1713132 balrog
1206 c1713132 balrog
uint32_t helper_get_cp(CPUState *env, uint32_t insn)
1207 c1713132 balrog
{
1208 c1713132 balrog
    int cp_num = (insn >> 8) & 0xf;
1209 c1713132 balrog
    int cp_info = (insn >> 5) & 7;
1210 c1713132 balrog
    int dest = (insn >> 16) & 0xf;
1211 c1713132 balrog
    int operand = insn & 0xf;
1212 c1713132 balrog
1213 c1713132 balrog
    if (env->cp[cp_num].cp_read)
1214 c1713132 balrog
        return env->cp[cp_num].cp_read(env->cp[cp_num].opaque,
1215 c1713132 balrog
                                       cp_info, dest, operand);
1216 c1713132 balrog
    return 0;
1217 c1713132 balrog
}
1218 c1713132 balrog
1219 ce819861 pbrook
/* Return basic MPU access permission bits.  */
1220 ce819861 pbrook
static uint32_t simple_mpu_ap_bits(uint32_t val)
1221 ce819861 pbrook
{
1222 ce819861 pbrook
    uint32_t ret;
1223 ce819861 pbrook
    uint32_t mask;
1224 ce819861 pbrook
    int i;
1225 ce819861 pbrook
    ret = 0;
1226 ce819861 pbrook
    mask = 3;
1227 ce819861 pbrook
    for (i = 0; i < 16; i += 2) {
1228 ce819861 pbrook
        ret |= (val >> i) & mask;
1229 ce819861 pbrook
        mask <<= 2;
1230 ce819861 pbrook
    }
1231 ce819861 pbrook
    return ret;
1232 ce819861 pbrook
}
1233 ce819861 pbrook
1234 ce819861 pbrook
/* Pad basic MPU access permission bits to extended format.  */
1235 ce819861 pbrook
static uint32_t extended_mpu_ap_bits(uint32_t val)
1236 ce819861 pbrook
{
1237 ce819861 pbrook
    uint32_t ret;
1238 ce819861 pbrook
    uint32_t mask;
1239 ce819861 pbrook
    int i;
1240 ce819861 pbrook
    ret = 0;
1241 ce819861 pbrook
    mask = 3;
1242 ce819861 pbrook
    for (i = 0; i < 16; i += 2) {
1243 ce819861 pbrook
        ret |= (val & mask) << i;
1244 ce819861 pbrook
        mask <<= 2;
1245 ce819861 pbrook
    }
1246 ce819861 pbrook
    return ret;
1247 ce819861 pbrook
}
1248 ce819861 pbrook
1249 b5ff1b31 bellard
void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
1250 b5ff1b31 bellard
{
1251 9ee6e8bb pbrook
    int op1;
1252 9ee6e8bb pbrook
    int op2;
1253 9ee6e8bb pbrook
    int crm;
1254 b5ff1b31 bellard
1255 9ee6e8bb pbrook
    op1 = (insn >> 21) & 7;
1256 b5ff1b31 bellard
    op2 = (insn >> 5) & 7;
1257 ce819861 pbrook
    crm = insn & 0xf;
1258 b5ff1b31 bellard
    switch ((insn >> 16) & 0xf) {
1259 9ee6e8bb pbrook
    case 0:
1260 9ee6e8bb pbrook
        if (((insn >> 21) & 7) == 2) {
1261 9ee6e8bb pbrook
            /* ??? Select cache level.  Ignore.  */
1262 9ee6e8bb pbrook
            return;
1263 9ee6e8bb pbrook
        }
1264 9ee6e8bb pbrook
        /* ID codes.  */
1265 610c3c8a balrog
        if (arm_feature(env, ARM_FEATURE_XSCALE))
1266 610c3c8a balrog
            break;
1267 c3d2689d balrog
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
1268 c3d2689d balrog
            break;
1269 b5ff1b31 bellard
        goto bad_reg;
1270 b5ff1b31 bellard
    case 1: /* System configuration.  */
1271 c3d2689d balrog
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
1272 c3d2689d balrog
            op2 = 0;
1273 b5ff1b31 bellard
        switch (op2) {
1274 b5ff1b31 bellard
        case 0:
1275 ce819861 pbrook
            if (!arm_feature(env, ARM_FEATURE_XSCALE) || crm == 0)
1276 c1713132 balrog
                env->cp15.c1_sys = val;
1277 b5ff1b31 bellard
            /* ??? Lots of these bits are not implemented.  */
1278 b5ff1b31 bellard
            /* This may enable/disable the MMU, so do a TLB flush.  */
1279 b5ff1b31 bellard
            tlb_flush(env, 1);
1280 b5ff1b31 bellard
            break;
1281 9ee6e8bb pbrook
        case 1: /* Auxiliary cotrol register.  */
1282 610c3c8a balrog
            if (arm_feature(env, ARM_FEATURE_XSCALE)) {
1283 610c3c8a balrog
                env->cp15.c1_xscaleauxcr = val;
1284 c1713132 balrog
                break;
1285 610c3c8a balrog
            }
1286 9ee6e8bb pbrook
            /* Not implemented.  */
1287 9ee6e8bb pbrook
            break;
1288 b5ff1b31 bellard
        case 2:
1289 610c3c8a balrog
            if (arm_feature(env, ARM_FEATURE_XSCALE))
1290 610c3c8a balrog
                goto bad_reg;
1291 b5ff1b31 bellard
            env->cp15.c1_coproc = val;
1292 b5ff1b31 bellard
            /* ??? Is this safe when called from within a TB?  */
1293 b5ff1b31 bellard
            tb_flush(env);
1294 c1713132 balrog
            break;
1295 b5ff1b31 bellard
        default:
1296 b5ff1b31 bellard
            goto bad_reg;
1297 b5ff1b31 bellard
        }
1298 b5ff1b31 bellard
        break;
1299 ce819861 pbrook
    case 2: /* MMU Page table control / MPU cache control.  */
1300 ce819861 pbrook
        if (arm_feature(env, ARM_FEATURE_MPU)) {
1301 ce819861 pbrook
            switch (op2) {
1302 ce819861 pbrook
            case 0:
1303 ce819861 pbrook
                env->cp15.c2_data = val;
1304 ce819861 pbrook
                break;
1305 ce819861 pbrook
            case 1:
1306 ce819861 pbrook
                env->cp15.c2_insn = val;
1307 ce819861 pbrook
                break;
1308 ce819861 pbrook
            default:
1309 ce819861 pbrook
                goto bad_reg;
1310 ce819861 pbrook
            }
1311 ce819861 pbrook
        } else {
1312 9ee6e8bb pbrook
            switch (op2) {
1313 9ee6e8bb pbrook
            case 0:
1314 9ee6e8bb pbrook
                env->cp15.c2_base0 = val;
1315 9ee6e8bb pbrook
                break;
1316 9ee6e8bb pbrook
            case 1:
1317 9ee6e8bb pbrook
                env->cp15.c2_base1 = val;
1318 9ee6e8bb pbrook
                break;
1319 9ee6e8bb pbrook
            case 2:
1320 9ee6e8bb pbrook
                env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> val);
1321 9ee6e8bb pbrook
                break;
1322 9ee6e8bb pbrook
            default:
1323 9ee6e8bb pbrook
                goto bad_reg;
1324 9ee6e8bb pbrook
            }
1325 ce819861 pbrook
        }
1326 b5ff1b31 bellard
        break;
1327 ce819861 pbrook
    case 3: /* MMU Domain access control / MPU write buffer control.  */
1328 b5ff1b31 bellard
        env->cp15.c3 = val;
1329 405ee3ad balrog
        tlb_flush(env, 1); /* Flush TLB as domain not tracked in TLB */
1330 b5ff1b31 bellard
        break;
1331 b5ff1b31 bellard
    case 4: /* Reserved.  */
1332 b5ff1b31 bellard
        goto bad_reg;
1333 ce819861 pbrook
    case 5: /* MMU Fault status / MPU access permission.  */
1334 c3d2689d balrog
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
1335 c3d2689d balrog
            op2 = 0;
1336 b5ff1b31 bellard
        switch (op2) {
1337 b5ff1b31 bellard
        case 0:
1338 ce819861 pbrook
            if (arm_feature(env, ARM_FEATURE_MPU))
1339 ce819861 pbrook
                val = extended_mpu_ap_bits(val);
1340 b5ff1b31 bellard
            env->cp15.c5_data = val;
1341 b5ff1b31 bellard
            break;
1342 b5ff1b31 bellard
        case 1:
1343 ce819861 pbrook
            if (arm_feature(env, ARM_FEATURE_MPU))
1344 ce819861 pbrook
                val = extended_mpu_ap_bits(val);
1345 b5ff1b31 bellard
            env->cp15.c5_insn = val;
1346 b5ff1b31 bellard
            break;
1347 ce819861 pbrook
        case 2:
1348 ce819861 pbrook
            if (!arm_feature(env, ARM_FEATURE_MPU))
1349 ce819861 pbrook
                goto bad_reg;
1350 ce819861 pbrook
            env->cp15.c5_data = val;
1351 b5ff1b31 bellard
            break;
1352 ce819861 pbrook
        case 3:
1353 ce819861 pbrook
            if (!arm_feature(env, ARM_FEATURE_MPU))
1354 ce819861 pbrook
                goto bad_reg;
1355 ce819861 pbrook
            env->cp15.c5_insn = val;
1356 b5ff1b31 bellard
            break;
1357 b5ff1b31 bellard
        default:
1358 b5ff1b31 bellard
            goto bad_reg;
1359 b5ff1b31 bellard
        }
1360 b5ff1b31 bellard
        break;
1361 ce819861 pbrook
    case 6: /* MMU Fault address / MPU base/size.  */
1362 ce819861 pbrook
        if (arm_feature(env, ARM_FEATURE_MPU)) {
1363 ce819861 pbrook
            if (crm >= 8)
1364 ce819861 pbrook
                goto bad_reg;
1365 ce819861 pbrook
            env->cp15.c6_region[crm] = val;
1366 ce819861 pbrook
        } else {
1367 c3d2689d balrog
            if (arm_feature(env, ARM_FEATURE_OMAPCP))
1368 c3d2689d balrog
                op2 = 0;
1369 ce819861 pbrook
            switch (op2) {
1370 ce819861 pbrook
            case 0:
1371 ce819861 pbrook
                env->cp15.c6_data = val;
1372 ce819861 pbrook
                break;
1373 9ee6e8bb pbrook
            case 1: /* ??? This is WFAR on armv6 */
1374 9ee6e8bb pbrook
            case 2:
1375 ce819861 pbrook
                env->cp15.c6_insn = val;
1376 ce819861 pbrook
                break;
1377 ce819861 pbrook
            default:
1378 ce819861 pbrook
                goto bad_reg;
1379 ce819861 pbrook
            }
1380 ce819861 pbrook
        }
1381 ce819861 pbrook
        break;
1382 b5ff1b31 bellard
    case 7: /* Cache control.  */
1383 c3d2689d balrog
        env->cp15.c15_i_max = 0x000;
1384 c3d2689d balrog
        env->cp15.c15_i_min = 0xff0;
1385 b5ff1b31 bellard
        /* No cache, so nothing to do.  */
1386 9ee6e8bb pbrook
        /* ??? MPCore has VA to PA translation functions.  */
1387 b5ff1b31 bellard
        break;
1388 b5ff1b31 bellard
    case 8: /* MMU TLB control.  */
1389 b5ff1b31 bellard
        switch (op2) {
1390 b5ff1b31 bellard
        case 0: /* Invalidate all.  */
1391 b5ff1b31 bellard
            tlb_flush(env, 0);
1392 b5ff1b31 bellard
            break;
1393 b5ff1b31 bellard
        case 1: /* Invalidate single TLB entry.  */
1394 b5ff1b31 bellard
#if 0
1395 b5ff1b31 bellard
            /* ??? This is wrong for large pages and sections.  */
1396 b5ff1b31 bellard
            /* As an ugly hack to make linux work we always flush a 4K
1397 b5ff1b31 bellard
               pages.  */
1398 b5ff1b31 bellard
            val &= 0xfffff000;
1399 b5ff1b31 bellard
            tlb_flush_page(env, val);
1400 b5ff1b31 bellard
            tlb_flush_page(env, val + 0x400);
1401 b5ff1b31 bellard
            tlb_flush_page(env, val + 0x800);
1402 b5ff1b31 bellard
            tlb_flush_page(env, val + 0xc00);
1403 b5ff1b31 bellard
#else
1404 b5ff1b31 bellard
            tlb_flush(env, 1);
1405 b5ff1b31 bellard
#endif
1406 b5ff1b31 bellard
            break;
1407 9ee6e8bb pbrook
        case 2: /* Invalidate on ASID.  */
1408 9ee6e8bb pbrook
            tlb_flush(env, val == 0);
1409 9ee6e8bb pbrook
            break;
1410 9ee6e8bb pbrook
        case 3: /* Invalidate single entry on MVA.  */
1411 9ee6e8bb pbrook
            /* ??? This is like case 1, but ignores ASID.  */
1412 9ee6e8bb pbrook
            tlb_flush(env, 1);
1413 9ee6e8bb pbrook
            break;
1414 b5ff1b31 bellard
        default:
1415 b5ff1b31 bellard
            goto bad_reg;
1416 b5ff1b31 bellard
        }
1417 b5ff1b31 bellard
        break;
1418 ce819861 pbrook
    case 9:
1419 c3d2689d balrog
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
1420 c3d2689d balrog
            break;
1421 ce819861 pbrook
        switch (crm) {
1422 ce819861 pbrook
        case 0: /* Cache lockdown.  */
1423 9ee6e8bb pbrook
            switch (op1) {
1424 9ee6e8bb pbrook
            case 0: /* L1 cache.  */
1425 9ee6e8bb pbrook
                switch (op2) {
1426 9ee6e8bb pbrook
                case 0:
1427 9ee6e8bb pbrook
                    env->cp15.c9_data = val;
1428 9ee6e8bb pbrook
                    break;
1429 9ee6e8bb pbrook
                case 1:
1430 9ee6e8bb pbrook
                    env->cp15.c9_insn = val;
1431 9ee6e8bb pbrook
                    break;
1432 9ee6e8bb pbrook
                default:
1433 9ee6e8bb pbrook
                    goto bad_reg;
1434 9ee6e8bb pbrook
                }
1435 9ee6e8bb pbrook
                break;
1436 9ee6e8bb pbrook
            case 1: /* L2 cache.  */
1437 9ee6e8bb pbrook
                /* Ignore writes to L2 lockdown/auxiliary registers.  */
1438 9ee6e8bb pbrook
                break;
1439 9ee6e8bb pbrook
            default:
1440 9ee6e8bb pbrook
                goto bad_reg;
1441 9ee6e8bb pbrook
            }
1442 9ee6e8bb pbrook
            break;
1443 ce819861 pbrook
        case 1: /* TCM memory region registers.  */
1444 ce819861 pbrook
            /* Not implemented.  */
1445 ce819861 pbrook
            goto bad_reg;
1446 b5ff1b31 bellard
        default:
1447 b5ff1b31 bellard
            goto bad_reg;
1448 b5ff1b31 bellard
        }
1449 b5ff1b31 bellard
        break;
1450 b5ff1b31 bellard
    case 10: /* MMU TLB lockdown.  */
1451 b5ff1b31 bellard
        /* ??? TLB lockdown not implemented.  */
1452 b5ff1b31 bellard
        break;
1453 b5ff1b31 bellard
    case 12: /* Reserved.  */
1454 b5ff1b31 bellard
        goto bad_reg;
1455 b5ff1b31 bellard
    case 13: /* Process ID.  */
1456 b5ff1b31 bellard
        switch (op2) {
1457 b5ff1b31 bellard
        case 0:
1458 d07edbfa pbrook
            /* Unlike real hardware the qemu TLB uses virtual addresses,
1459 d07edbfa pbrook
               not modified virtual addresses, so this causes a TLB flush.
1460 d07edbfa pbrook
             */
1461 d07edbfa pbrook
            if (env->cp15.c13_fcse != val)
1462 d07edbfa pbrook
              tlb_flush(env, 1);
1463 d07edbfa pbrook
            env->cp15.c13_fcse = val;
1464 b5ff1b31 bellard
            break;
1465 b5ff1b31 bellard
        case 1:
1466 d07edbfa pbrook
            /* This changes the ASID, so do a TLB flush.  */
1467 ce819861 pbrook
            if (env->cp15.c13_context != val
1468 ce819861 pbrook
                && !arm_feature(env, ARM_FEATURE_MPU))
1469 d07edbfa pbrook
              tlb_flush(env, 0);
1470 d07edbfa pbrook
            env->cp15.c13_context = val;
1471 b5ff1b31 bellard
            break;
1472 9ee6e8bb pbrook
        case 2:
1473 9ee6e8bb pbrook
            env->cp15.c13_tls1 = val;
1474 9ee6e8bb pbrook
            break;
1475 9ee6e8bb pbrook
        case 3:
1476 9ee6e8bb pbrook
            env->cp15.c13_tls2 = val;
1477 9ee6e8bb pbrook
            break;
1478 9ee6e8bb pbrook
        case 4:
1479 9ee6e8bb pbrook
            env->cp15.c13_tls3 = val;
1480 9ee6e8bb pbrook
            break;
1481 b5ff1b31 bellard
        default:
1482 b5ff1b31 bellard
            goto bad_reg;
1483 b5ff1b31 bellard
        }
1484 b5ff1b31 bellard
        break;
1485 b5ff1b31 bellard
    case 14: /* Reserved.  */
1486 b5ff1b31 bellard
        goto bad_reg;
1487 b5ff1b31 bellard
    case 15: /* Implementation specific.  */
1488 c1713132 balrog
        if (arm_feature(env, ARM_FEATURE_XSCALE)) {
1489 ce819861 pbrook
            if (op2 == 0 && crm == 1) {
1490 2e23213f balrog
                if (env->cp15.c15_cpar != (val & 0x3fff)) {
1491 2e23213f balrog
                    /* Changes cp0 to cp13 behavior, so needs a TB flush.  */
1492 2e23213f balrog
                    tb_flush(env);
1493 2e23213f balrog
                    env->cp15.c15_cpar = val & 0x3fff;
1494 2e23213f balrog
                }
1495 c1713132 balrog
                break;
1496 c1713132 balrog
            }
1497 c1713132 balrog
            goto bad_reg;
1498 c1713132 balrog
        }
1499 c3d2689d balrog
        if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
1500 c3d2689d balrog
            switch (crm) {
1501 c3d2689d balrog
            case 0:
1502 c3d2689d balrog
                break;
1503 c3d2689d balrog
            case 1: /* Set TI925T configuration.  */
1504 c3d2689d balrog
                env->cp15.c15_ticonfig = val & 0xe7;
1505 c3d2689d balrog
                env->cp15.c0_cpuid = (val & (1 << 5)) ? /* OS_TYPE bit */
1506 c3d2689d balrog
                        ARM_CPUID_TI915T : ARM_CPUID_TI925T;
1507 c3d2689d balrog
                break;
1508 c3d2689d balrog
            case 2: /* Set I_max.  */
1509 c3d2689d balrog
                env->cp15.c15_i_max = val;
1510 c3d2689d balrog
                break;
1511 c3d2689d balrog
            case 3: /* Set I_min.  */
1512 c3d2689d balrog
                env->cp15.c15_i_min = val;
1513 c3d2689d balrog
                break;
1514 c3d2689d balrog
            case 4: /* Set thread-ID.  */
1515 c3d2689d balrog
                env->cp15.c15_threadid = val & 0xffff;
1516 c3d2689d balrog
                break;
1517 c3d2689d balrog
            case 8: /* Wait-for-interrupt (deprecated).  */
1518 c3d2689d balrog
                cpu_interrupt(env, CPU_INTERRUPT_HALT);
1519 c3d2689d balrog
                break;
1520 c3d2689d balrog
            default:
1521 c3d2689d balrog
                goto bad_reg;
1522 c3d2689d balrog
            }
1523 c3d2689d balrog
        }
1524 b5ff1b31 bellard
        break;
1525 b5ff1b31 bellard
    }
1526 b5ff1b31 bellard
    return;
1527 b5ff1b31 bellard
bad_reg:
1528 b5ff1b31 bellard
    /* ??? For debugging only.  Should raise illegal instruction exception.  */
1529 9ee6e8bb pbrook
    cpu_abort(env, "Unimplemented cp15 register write (c%d, c%d, {%d, %d})\n",
1530 9ee6e8bb pbrook
              (insn >> 16) & 0xf, crm, op1, op2);
1531 b5ff1b31 bellard
}
1532 b5ff1b31 bellard
1533 b5ff1b31 bellard
uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
1534 b5ff1b31 bellard
{
1535 9ee6e8bb pbrook
    int op1;
1536 9ee6e8bb pbrook
    int op2;
1537 9ee6e8bb pbrook
    int crm;
1538 b5ff1b31 bellard
1539 9ee6e8bb pbrook
    op1 = (insn >> 21) & 7;
1540 b5ff1b31 bellard
    op2 = (insn >> 5) & 7;
1541 c3d2689d balrog
    crm = insn & 0xf;
1542 b5ff1b31 bellard
    switch ((insn >> 16) & 0xf) {
1543 b5ff1b31 bellard
    case 0: /* ID codes.  */
1544 9ee6e8bb pbrook
        switch (op1) {
1545 9ee6e8bb pbrook
        case 0:
1546 9ee6e8bb pbrook
            switch (crm) {
1547 9ee6e8bb pbrook
            case 0:
1548 9ee6e8bb pbrook
                switch (op2) {
1549 9ee6e8bb pbrook
                case 0: /* Device ID.  */
1550 9ee6e8bb pbrook
                    return env->cp15.c0_cpuid;
1551 9ee6e8bb pbrook
                case 1: /* Cache Type.  */
1552 9ee6e8bb pbrook
                    return env->cp15.c0_cachetype;
1553 9ee6e8bb pbrook
                case 2: /* TCM status.  */
1554 9ee6e8bb pbrook
                    return 0;
1555 9ee6e8bb pbrook
                case 3: /* TLB type register.  */
1556 9ee6e8bb pbrook
                    return 0; /* No lockable TLB entries.  */
1557 9ee6e8bb pbrook
                case 5: /* CPU ID */
1558 9ee6e8bb pbrook
                    return env->cpu_index;
1559 9ee6e8bb pbrook
                default:
1560 9ee6e8bb pbrook
                    goto bad_reg;
1561 9ee6e8bb pbrook
                }
1562 9ee6e8bb pbrook
            case 1:
1563 9ee6e8bb pbrook
                if (!arm_feature(env, ARM_FEATURE_V6))
1564 9ee6e8bb pbrook
                    goto bad_reg;
1565 9ee6e8bb pbrook
                return env->cp15.c0_c1[op2];
1566 9ee6e8bb pbrook
            case 2:
1567 9ee6e8bb pbrook
                if (!arm_feature(env, ARM_FEATURE_V6))
1568 9ee6e8bb pbrook
                    goto bad_reg;
1569 9ee6e8bb pbrook
                return env->cp15.c0_c2[op2];
1570 9ee6e8bb pbrook
            case 3: case 4: case 5: case 6: case 7:
1571 9ee6e8bb pbrook
                return 0;
1572 9ee6e8bb pbrook
            default:
1573 9ee6e8bb pbrook
                goto bad_reg;
1574 9ee6e8bb pbrook
            }
1575 9ee6e8bb pbrook
        case 1:
1576 9ee6e8bb pbrook
            /* These registers aren't documented on arm11 cores.  However
1577 9ee6e8bb pbrook
               Linux looks at them anyway.  */
1578 9ee6e8bb pbrook
            if (!arm_feature(env, ARM_FEATURE_V6))
1579 9ee6e8bb pbrook
                goto bad_reg;
1580 9ee6e8bb pbrook
            if (crm != 0)
1581 9ee6e8bb pbrook
                goto bad_reg;
1582 610c3c8a balrog
            if (arm_feature(env, ARM_FEATURE_XSCALE))
1583 610c3c8a balrog
                goto bad_reg;
1584 b5ff1b31 bellard
            return 0;
1585 9ee6e8bb pbrook
        default:
1586 9ee6e8bb pbrook
            goto bad_reg;
1587 b5ff1b31 bellard
        }
1588 b5ff1b31 bellard
    case 1: /* System configuration.  */
1589 c3d2689d balrog
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
1590 c3d2689d balrog
            op2 = 0;
1591 b5ff1b31 bellard
        switch (op2) {
1592 b5ff1b31 bellard
        case 0: /* Control register.  */
1593 b5ff1b31 bellard
            return env->cp15.c1_sys;
1594 b5ff1b31 bellard
        case 1: /* Auxiliary control register.  */
1595 c1713132 balrog
            if (arm_feature(env, ARM_FEATURE_XSCALE))
1596 610c3c8a balrog
                return env->cp15.c1_xscaleauxcr;
1597 9ee6e8bb pbrook
            if (!arm_feature(env, ARM_FEATURE_AUXCR))
1598 9ee6e8bb pbrook
                goto bad_reg;
1599 9ee6e8bb pbrook
            switch (ARM_CPUID(env)) {
1600 9ee6e8bb pbrook
            case ARM_CPUID_ARM1026:
1601 9ee6e8bb pbrook
                return 1;
1602 9ee6e8bb pbrook
            case ARM_CPUID_ARM1136:
1603 9ee6e8bb pbrook
                return 7;
1604 9ee6e8bb pbrook
            case ARM_CPUID_ARM11MPCORE:
1605 9ee6e8bb pbrook
                return 1;
1606 9ee6e8bb pbrook
            case ARM_CPUID_CORTEXA8:
1607 9ee6e8bb pbrook
                return 0;
1608 9ee6e8bb pbrook
            default:
1609 9ee6e8bb pbrook
                goto bad_reg;
1610 9ee6e8bb pbrook
            }
1611 b5ff1b31 bellard
        case 2: /* Coprocessor access register.  */
1612 610c3c8a balrog
            if (arm_feature(env, ARM_FEATURE_XSCALE))
1613 610c3c8a balrog
                goto bad_reg;
1614 b5ff1b31 bellard
            return env->cp15.c1_coproc;
1615 b5ff1b31 bellard
        default:
1616 b5ff1b31 bellard
            goto bad_reg;
1617 b5ff1b31 bellard
        }
1618 ce819861 pbrook
    case 2: /* MMU Page table control / MPU cache control.  */
1619 ce819861 pbrook
        if (arm_feature(env, ARM_FEATURE_MPU)) {
1620 ce819861 pbrook
            switch (op2) {
1621 ce819861 pbrook
            case 0:
1622 ce819861 pbrook
                return env->cp15.c2_data;
1623 ce819861 pbrook
                break;
1624 ce819861 pbrook
            case 1:
1625 ce819861 pbrook
                return env->cp15.c2_insn;
1626 ce819861 pbrook
                break;
1627 ce819861 pbrook
            default:
1628 ce819861 pbrook
                goto bad_reg;
1629 ce819861 pbrook
            }
1630 ce819861 pbrook
        } else {
1631 9ee6e8bb pbrook
            switch (op2) {
1632 9ee6e8bb pbrook
            case 0:
1633 9ee6e8bb pbrook
                return env->cp15.c2_base0;
1634 9ee6e8bb pbrook
            case 1:
1635 9ee6e8bb pbrook
                return env->cp15.c2_base1;
1636 9ee6e8bb pbrook
            case 2:
1637 9ee6e8bb pbrook
                {
1638 9ee6e8bb pbrook
                    int n;
1639 9ee6e8bb pbrook
                    uint32_t mask;
1640 9ee6e8bb pbrook
                    n = 0;
1641 9ee6e8bb pbrook
                    mask = env->cp15.c2_mask;
1642 9ee6e8bb pbrook
                    while (mask) {
1643 9ee6e8bb pbrook
                        n++;
1644 9ee6e8bb pbrook
                        mask <<= 1;
1645 9ee6e8bb pbrook
                    }
1646 9ee6e8bb pbrook
                    return n;
1647 9ee6e8bb pbrook
                }
1648 9ee6e8bb pbrook
            default:
1649 9ee6e8bb pbrook
                goto bad_reg;
1650 9ee6e8bb pbrook
            }
1651 9ee6e8bb pbrook
        }
1652 ce819861 pbrook
    case 3: /* MMU Domain access control / MPU write buffer control.  */
1653 b5ff1b31 bellard
        return env->cp15.c3;
1654 b5ff1b31 bellard
    case 4: /* Reserved.  */
1655 b5ff1b31 bellard
        goto bad_reg;
1656 ce819861 pbrook
    case 5: /* MMU Fault status / MPU access permission.  */
1657 c3d2689d balrog
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
1658 c3d2689d balrog
            op2 = 0;
1659 b5ff1b31 bellard
        switch (op2) {
1660 b5ff1b31 bellard
        case 0:
1661 ce819861 pbrook
            if (arm_feature(env, ARM_FEATURE_MPU))
1662 ce819861 pbrook
                return simple_mpu_ap_bits(env->cp15.c5_data);
1663 b5ff1b31 bellard
            return env->cp15.c5_data;
1664 b5ff1b31 bellard
        case 1:
1665 ce819861 pbrook
            if (arm_feature(env, ARM_FEATURE_MPU))
1666 ce819861 pbrook
                return simple_mpu_ap_bits(env->cp15.c5_data);
1667 ce819861 pbrook
            return env->cp15.c5_insn;
1668 ce819861 pbrook
        case 2:
1669 ce819861 pbrook
            if (!arm_feature(env, ARM_FEATURE_MPU))
1670 ce819861 pbrook
                goto bad_reg;
1671 ce819861 pbrook
            return env->cp15.c5_data;
1672 ce819861 pbrook
        case 3:
1673 ce819861 pbrook
            if (!arm_feature(env, ARM_FEATURE_MPU))
1674 ce819861 pbrook
                goto bad_reg;
1675 b5ff1b31 bellard
            return env->cp15.c5_insn;
1676 b5ff1b31 bellard
        default:
1677 b5ff1b31 bellard
            goto bad_reg;
1678 b5ff1b31 bellard
        }
1679 9ee6e8bb pbrook
    case 6: /* MMU Fault address.  */
1680 ce819861 pbrook
        if (arm_feature(env, ARM_FEATURE_MPU)) {
1681 9ee6e8bb pbrook
            if (crm >= 8)
1682 ce819861 pbrook
                goto bad_reg;
1683 9ee6e8bb pbrook
            return env->cp15.c6_region[crm];
1684 ce819861 pbrook
        } else {
1685 c3d2689d balrog
            if (arm_feature(env, ARM_FEATURE_OMAPCP))
1686 c3d2689d balrog
                op2 = 0;
1687 9ee6e8bb pbrook
            switch (op2) {
1688 9ee6e8bb pbrook
            case 0:
1689 9ee6e8bb pbrook
                return env->cp15.c6_data;
1690 9ee6e8bb pbrook
            case 1:
1691 9ee6e8bb pbrook
                if (arm_feature(env, ARM_FEATURE_V6)) {
1692 9ee6e8bb pbrook
                    /* Watchpoint Fault Adrress.  */
1693 9ee6e8bb pbrook
                    return 0; /* Not implemented.  */
1694 9ee6e8bb pbrook
                } else {
1695 9ee6e8bb pbrook
                    /* Instruction Fault Adrress.  */
1696 9ee6e8bb pbrook
                    /* Arm9 doesn't have an IFAR, but implementing it anyway
1697 9ee6e8bb pbrook
                       shouldn't do any harm.  */
1698 9ee6e8bb pbrook
                    return env->cp15.c6_insn;
1699 9ee6e8bb pbrook
                }
1700 9ee6e8bb pbrook
            case 2:
1701 9ee6e8bb pbrook
                if (arm_feature(env, ARM_FEATURE_V6)) {
1702 9ee6e8bb pbrook
                    /* Instruction Fault Adrress.  */
1703 9ee6e8bb pbrook
                    return env->cp15.c6_insn;
1704 9ee6e8bb pbrook
                } else {
1705 9ee6e8bb pbrook
                    goto bad_reg;
1706 9ee6e8bb pbrook
                }
1707 9ee6e8bb pbrook
            default:
1708 9ee6e8bb pbrook
                goto bad_reg;
1709 9ee6e8bb pbrook
            }
1710 b5ff1b31 bellard
        }
1711 b5ff1b31 bellard
    case 7: /* Cache control.  */
1712 b5ff1b31 bellard
        /* ??? This is for test, clean and invaidate operations that set the
1713 c1713132 balrog
           Z flag.  We can't represent N = Z = 1, so it also clears
1714 b5ff1b31 bellard
           the N flag.  Oh well.  */
1715 b5ff1b31 bellard
        env->NZF = 0;
1716 b5ff1b31 bellard
        return 0;
1717 b5ff1b31 bellard
    case 8: /* MMU TLB control.  */
1718 b5ff1b31 bellard
        goto bad_reg;
1719 b5ff1b31 bellard
    case 9: /* Cache lockdown.  */
1720 9ee6e8bb pbrook
        switch (op1) {
1721 9ee6e8bb pbrook
        case 0: /* L1 cache.  */
1722 9ee6e8bb pbrook
            if (arm_feature(env, ARM_FEATURE_OMAPCP))
1723 9ee6e8bb pbrook
                return 0;
1724 9ee6e8bb pbrook
            switch (op2) {
1725 9ee6e8bb pbrook
            case 0:
1726 9ee6e8bb pbrook
                return env->cp15.c9_data;
1727 9ee6e8bb pbrook
            case 1:
1728 9ee6e8bb pbrook
                return env->cp15.c9_insn;
1729 9ee6e8bb pbrook
            default:
1730 9ee6e8bb pbrook
                goto bad_reg;
1731 9ee6e8bb pbrook
            }
1732 9ee6e8bb pbrook
        case 1: /* L2 cache */
1733 9ee6e8bb pbrook
            if (crm != 0)
1734 9ee6e8bb pbrook
                goto bad_reg;
1735 9ee6e8bb pbrook
            /* L2 Lockdown and Auxiliary control.  */
1736 c3d2689d balrog
            return 0;
1737 b5ff1b31 bellard
        default:
1738 b5ff1b31 bellard
            goto bad_reg;
1739 b5ff1b31 bellard
        }
1740 b5ff1b31 bellard
    case 10: /* MMU TLB lockdown.  */
1741 b5ff1b31 bellard
        /* ??? TLB lockdown not implemented.  */
1742 b5ff1b31 bellard
        return 0;
1743 b5ff1b31 bellard
    case 11: /* TCM DMA control.  */
1744 b5ff1b31 bellard
    case 12: /* Reserved.  */
1745 b5ff1b31 bellard
        goto bad_reg;
1746 b5ff1b31 bellard
    case 13: /* Process ID.  */
1747 b5ff1b31 bellard
        switch (op2) {
1748 b5ff1b31 bellard
        case 0:
1749 b5ff1b31 bellard
            return env->cp15.c13_fcse;
1750 b5ff1b31 bellard
        case 1:
1751 b5ff1b31 bellard
            return env->cp15.c13_context;
1752 9ee6e8bb pbrook
        case 2:
1753 9ee6e8bb pbrook
            return env->cp15.c13_tls1;
1754 9ee6e8bb pbrook
        case 3:
1755 9ee6e8bb pbrook
            return env->cp15.c13_tls2;
1756 9ee6e8bb pbrook
        case 4:
1757 9ee6e8bb pbrook
            return env->cp15.c13_tls3;
1758 b5ff1b31 bellard
        default:
1759 b5ff1b31 bellard
            goto bad_reg;
1760 b5ff1b31 bellard
        }
1761 b5ff1b31 bellard
    case 14: /* Reserved.  */
1762 b5ff1b31 bellard
        goto bad_reg;
1763 b5ff1b31 bellard
    case 15: /* Implementation specific.  */
1764 c1713132 balrog
        if (arm_feature(env, ARM_FEATURE_XSCALE)) {
1765 c3d2689d balrog
            if (op2 == 0 && crm == 1)
1766 c1713132 balrog
                return env->cp15.c15_cpar;
1767 c1713132 balrog
1768 c1713132 balrog
            goto bad_reg;
1769 c1713132 balrog
        }
1770 c3d2689d balrog
        if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
1771 c3d2689d balrog
            switch (crm) {
1772 c3d2689d balrog
            case 0:
1773 c3d2689d balrog
                return 0;
1774 c3d2689d balrog
            case 1: /* Read TI925T configuration.  */
1775 c3d2689d balrog
                return env->cp15.c15_ticonfig;
1776 c3d2689d balrog
            case 2: /* Read I_max.  */
1777 c3d2689d balrog
                return env->cp15.c15_i_max;
1778 c3d2689d balrog
            case 3: /* Read I_min.  */
1779 c3d2689d balrog
                return env->cp15.c15_i_min;
1780 c3d2689d balrog
            case 4: /* Read thread-ID.  */
1781 c3d2689d balrog
                return env->cp15.c15_threadid;
1782 c3d2689d balrog
            case 8: /* TI925T_status */
1783 c3d2689d balrog
                return 0;
1784 c3d2689d balrog
            }
1785 c3d2689d balrog
            goto bad_reg;
1786 c3d2689d balrog
        }
1787 b5ff1b31 bellard
        return 0;
1788 b5ff1b31 bellard
    }
1789 b5ff1b31 bellard
bad_reg:
1790 b5ff1b31 bellard
    /* ??? For debugging only.  Should raise illegal instruction exception.  */
1791 9ee6e8bb pbrook
    cpu_abort(env, "Unimplemented cp15 register read (c%d, c%d, {%d, %d})\n",
1792 9ee6e8bb pbrook
              (insn >> 16) & 0xf, crm, op1, op2);
1793 b5ff1b31 bellard
    return 0;
1794 b5ff1b31 bellard
}
1795 b5ff1b31 bellard
1796 b0109805 pbrook
void HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val)
1797 9ee6e8bb pbrook
{
1798 9ee6e8bb pbrook
    env->banked_r13[bank_number(mode)] = val;
1799 9ee6e8bb pbrook
}
1800 9ee6e8bb pbrook
1801 b0109805 pbrook
uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
1802 9ee6e8bb pbrook
{
1803 9ee6e8bb pbrook
    return env->banked_r13[bank_number(mode)];
1804 9ee6e8bb pbrook
}
1805 9ee6e8bb pbrook
1806 9ee6e8bb pbrook
uint32_t helper_v7m_mrs(CPUState *env, int reg)
1807 9ee6e8bb pbrook
{
1808 9ee6e8bb pbrook
    switch (reg) {
1809 9ee6e8bb pbrook
    case 0: /* APSR */
1810 9ee6e8bb pbrook
        return xpsr_read(env) & 0xf8000000;
1811 9ee6e8bb pbrook
    case 1: /* IAPSR */
1812 9ee6e8bb pbrook
        return xpsr_read(env) & 0xf80001ff;
1813 9ee6e8bb pbrook
    case 2: /* EAPSR */
1814 9ee6e8bb pbrook
        return xpsr_read(env) & 0xff00fc00;
1815 9ee6e8bb pbrook
    case 3: /* xPSR */
1816 9ee6e8bb pbrook
        return xpsr_read(env) & 0xff00fdff;
1817 9ee6e8bb pbrook
    case 5: /* IPSR */
1818 9ee6e8bb pbrook
        return xpsr_read(env) & 0x000001ff;
1819 9ee6e8bb pbrook
    case 6: /* EPSR */
1820 9ee6e8bb pbrook
        return xpsr_read(env) & 0x0700fc00;
1821 9ee6e8bb pbrook
    case 7: /* IEPSR */
1822 9ee6e8bb pbrook
        return xpsr_read(env) & 0x0700edff;
1823 9ee6e8bb pbrook
    case 8: /* MSP */
1824 9ee6e8bb pbrook
        return env->v7m.current_sp ? env->v7m.other_sp : env->regs[13];
1825 9ee6e8bb pbrook
    case 9: /* PSP */
1826 9ee6e8bb pbrook
        return env->v7m.current_sp ? env->regs[13] : env->v7m.other_sp;
1827 9ee6e8bb pbrook
    case 16: /* PRIMASK */
1828 9ee6e8bb pbrook
        return (env->uncached_cpsr & CPSR_I) != 0;
1829 9ee6e8bb pbrook
    case 17: /* FAULTMASK */
1830 9ee6e8bb pbrook
        return (env->uncached_cpsr & CPSR_F) != 0;
1831 9ee6e8bb pbrook
    case 18: /* BASEPRI */
1832 9ee6e8bb pbrook
    case 19: /* BASEPRI_MAX */
1833 9ee6e8bb pbrook
        return env->v7m.basepri;
1834 9ee6e8bb pbrook
    case 20: /* CONTROL */
1835 9ee6e8bb pbrook
        return env->v7m.control;
1836 9ee6e8bb pbrook
    default:
1837 9ee6e8bb pbrook
        /* ??? For debugging only.  */
1838 9ee6e8bb pbrook
        cpu_abort(env, "Unimplemented system register read (%d)\n", reg);
1839 9ee6e8bb pbrook
        return 0;
1840 9ee6e8bb pbrook
    }
1841 9ee6e8bb pbrook
}
1842 9ee6e8bb pbrook
1843 9ee6e8bb pbrook
void helper_v7m_msr(CPUState *env, int reg, uint32_t val)
1844 9ee6e8bb pbrook
{
1845 9ee6e8bb pbrook
    switch (reg) {
1846 9ee6e8bb pbrook
    case 0: /* APSR */
1847 9ee6e8bb pbrook
        xpsr_write(env, val, 0xf8000000);
1848 9ee6e8bb pbrook
        break;
1849 9ee6e8bb pbrook
    case 1: /* IAPSR */
1850 9ee6e8bb pbrook
        xpsr_write(env, val, 0xf8000000);
1851 9ee6e8bb pbrook
        break;
1852 9ee6e8bb pbrook
    case 2: /* EAPSR */
1853 9ee6e8bb pbrook
        xpsr_write(env, val, 0xfe00fc00);
1854 9ee6e8bb pbrook
        break;
1855 9ee6e8bb pbrook
    case 3: /* xPSR */
1856 9ee6e8bb pbrook
        xpsr_write(env, val, 0xfe00fc00);
1857 9ee6e8bb pbrook
        break;
1858 9ee6e8bb pbrook
    case 5: /* IPSR */
1859 9ee6e8bb pbrook
        /* IPSR bits are readonly.  */
1860 9ee6e8bb pbrook
        break;
1861 9ee6e8bb pbrook
    case 6: /* EPSR */
1862 9ee6e8bb pbrook
        xpsr_write(env, val, 0x0600fc00);
1863 9ee6e8bb pbrook
        break;
1864 9ee6e8bb pbrook
    case 7: /* IEPSR */
1865 9ee6e8bb pbrook
        xpsr_write(env, val, 0x0600fc00);
1866 9ee6e8bb pbrook
        break;
1867 9ee6e8bb pbrook
    case 8: /* MSP */
1868 9ee6e8bb pbrook
        if (env->v7m.current_sp)
1869 9ee6e8bb pbrook
            env->v7m.other_sp = val;
1870 9ee6e8bb pbrook
        else
1871 9ee6e8bb pbrook
            env->regs[13] = val;
1872 9ee6e8bb pbrook
        break;
1873 9ee6e8bb pbrook
    case 9: /* PSP */
1874 9ee6e8bb pbrook
        if (env->v7m.current_sp)
1875 9ee6e8bb pbrook
            env->regs[13] = val;
1876 9ee6e8bb pbrook
        else
1877 9ee6e8bb pbrook
            env->v7m.other_sp = val;
1878 9ee6e8bb pbrook
        break;
1879 9ee6e8bb pbrook
    case 16: /* PRIMASK */
1880 9ee6e8bb pbrook
        if (val & 1)
1881 9ee6e8bb pbrook
            env->uncached_cpsr |= CPSR_I;
1882 9ee6e8bb pbrook
        else
1883 9ee6e8bb pbrook
            env->uncached_cpsr &= ~CPSR_I;
1884 9ee6e8bb pbrook
        break;
1885 9ee6e8bb pbrook
    case 17: /* FAULTMASK */
1886 9ee6e8bb pbrook
        if (val & 1)
1887 9ee6e8bb pbrook
            env->uncached_cpsr |= CPSR_F;
1888 9ee6e8bb pbrook
        else
1889 9ee6e8bb pbrook
            env->uncached_cpsr &= ~CPSR_F;
1890 9ee6e8bb pbrook
        break;
1891 9ee6e8bb pbrook
    case 18: /* BASEPRI */
1892 9ee6e8bb pbrook
        env->v7m.basepri = val & 0xff;
1893 9ee6e8bb pbrook
        break;
1894 9ee6e8bb pbrook
    case 19: /* BASEPRI_MAX */
1895 9ee6e8bb pbrook
        val &= 0xff;
1896 9ee6e8bb pbrook
        if (val != 0 && (val < env->v7m.basepri || env->v7m.basepri == 0))
1897 9ee6e8bb pbrook
            env->v7m.basepri = val;
1898 9ee6e8bb pbrook
        break;
1899 9ee6e8bb pbrook
    case 20: /* CONTROL */
1900 9ee6e8bb pbrook
        env->v7m.control = val & 3;
1901 9ee6e8bb pbrook
        switch_v7m_sp(env, (val & 2) != 0);
1902 9ee6e8bb pbrook
        break;
1903 9ee6e8bb pbrook
    default:
1904 9ee6e8bb pbrook
        /* ??? For debugging only.  */
1905 9ee6e8bb pbrook
        cpu_abort(env, "Unimplemented system register write (%d)\n", reg);
1906 9ee6e8bb pbrook
        return;
1907 9ee6e8bb pbrook
    }
1908 9ee6e8bb pbrook
}
1909 9ee6e8bb pbrook
1910 c1713132 balrog
void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
1911 c1713132 balrog
                ARMReadCPFunc *cp_read, ARMWriteCPFunc *cp_write,
1912 c1713132 balrog
                void *opaque)
1913 c1713132 balrog
{
1914 c1713132 balrog
    if (cpnum < 0 || cpnum > 14) {
1915 c1713132 balrog
        cpu_abort(env, "Bad coprocessor number: %i\n", cpnum);
1916 c1713132 balrog
        return;
1917 c1713132 balrog
    }
1918 c1713132 balrog
1919 c1713132 balrog
    env->cp[cpnum].cp_read = cp_read;
1920 c1713132 balrog
    env->cp[cpnum].cp_write = cp_write;
1921 c1713132 balrog
    env->cp[cpnum].opaque = opaque;
1922 c1713132 balrog
}
1923 c1713132 balrog
1924 b5ff1b31 bellard
#endif
1925 6ddbc6e4 pbrook
1926 6ddbc6e4 pbrook
/* Note that signed overflow is undefined in C.  The following routines are
1927 6ddbc6e4 pbrook
   careful to use unsigned types where modulo arithmetic is required.
1928 6ddbc6e4 pbrook
   Failure to do so _will_ break on newer gcc.  */
1929 6ddbc6e4 pbrook
1930 6ddbc6e4 pbrook
/* Signed saturating arithmetic.  */
1931 6ddbc6e4 pbrook
1932 6ddbc6e4 pbrook
/* Perform 16-bit signed satruating addition.  */
1933 6ddbc6e4 pbrook
static inline uint16_t add16_sat(uint16_t a, uint16_t b)
1934 6ddbc6e4 pbrook
{
1935 6ddbc6e4 pbrook
    uint16_t res;
1936 6ddbc6e4 pbrook
1937 6ddbc6e4 pbrook
    res = a + b;
1938 6ddbc6e4 pbrook
    if (((res ^ a) & 0x8000) && !((a ^ b) & 0x8000)) {
1939 6ddbc6e4 pbrook
        if (a & 0x8000)
1940 6ddbc6e4 pbrook
            res = 0x8000;
1941 6ddbc6e4 pbrook
        else
1942 6ddbc6e4 pbrook
            res = 0x7fff;
1943 6ddbc6e4 pbrook
    }
1944 6ddbc6e4 pbrook
    return res;
1945 6ddbc6e4 pbrook
}
1946 6ddbc6e4 pbrook
1947 6ddbc6e4 pbrook
/* Perform 8-bit signed satruating addition.  */
1948 6ddbc6e4 pbrook
static inline uint8_t add8_sat(uint8_t a, uint8_t b)
1949 6ddbc6e4 pbrook
{
1950 6ddbc6e4 pbrook
    uint8_t res;
1951 6ddbc6e4 pbrook
1952 6ddbc6e4 pbrook
    res = a + b;
1953 6ddbc6e4 pbrook
    if (((res ^ a) & 0x80) && !((a ^ b) & 0x80)) {
1954 6ddbc6e4 pbrook
        if (a & 0x80)
1955 6ddbc6e4 pbrook
            res = 0x80;
1956 6ddbc6e4 pbrook
        else
1957 6ddbc6e4 pbrook
            res = 0x7f;
1958 6ddbc6e4 pbrook
    }
1959 6ddbc6e4 pbrook
    return res;
1960 6ddbc6e4 pbrook
}
1961 6ddbc6e4 pbrook
1962 6ddbc6e4 pbrook
/* Perform 16-bit signed satruating subtraction.  */
1963 6ddbc6e4 pbrook
static inline uint16_t sub16_sat(uint16_t a, uint16_t b)
1964 6ddbc6e4 pbrook
{
1965 6ddbc6e4 pbrook
    uint16_t res;
1966 6ddbc6e4 pbrook
1967 6ddbc6e4 pbrook
    res = a - b;
1968 6ddbc6e4 pbrook
    if (((res ^ a) & 0x8000) && ((a ^ b) & 0x8000)) {
1969 6ddbc6e4 pbrook
        if (a & 0x8000)
1970 6ddbc6e4 pbrook
            res = 0x8000;
1971 6ddbc6e4 pbrook
        else
1972 6ddbc6e4 pbrook
            res = 0x7fff;
1973 6ddbc6e4 pbrook
    }
1974 6ddbc6e4 pbrook
    return res;
1975 6ddbc6e4 pbrook
}
1976 6ddbc6e4 pbrook
1977 6ddbc6e4 pbrook
/* Perform 8-bit signed satruating subtraction.  */
1978 6ddbc6e4 pbrook
static inline uint8_t sub8_sat(uint8_t a, uint8_t b)
1979 6ddbc6e4 pbrook
{
1980 6ddbc6e4 pbrook
    uint8_t res;
1981 6ddbc6e4 pbrook
1982 6ddbc6e4 pbrook
    res = a - b;
1983 6ddbc6e4 pbrook
    if (((res ^ a) & 0x80) && ((a ^ b) & 0x80)) {
1984 6ddbc6e4 pbrook
        if (a & 0x80)
1985 6ddbc6e4 pbrook
            res = 0x80;
1986 6ddbc6e4 pbrook
        else
1987 6ddbc6e4 pbrook
            res = 0x7f;
1988 6ddbc6e4 pbrook
    }
1989 6ddbc6e4 pbrook
    return res;
1990 6ddbc6e4 pbrook
}
1991 6ddbc6e4 pbrook
1992 6ddbc6e4 pbrook
#define ADD16(a, b, n) RESULT(add16_sat(a, b), n, 16);
1993 6ddbc6e4 pbrook
#define SUB16(a, b, n) RESULT(sub16_sat(a, b), n, 16);
1994 6ddbc6e4 pbrook
#define ADD8(a, b, n)  RESULT(add8_sat(a, b), n, 8);
1995 6ddbc6e4 pbrook
#define SUB8(a, b, n)  RESULT(sub8_sat(a, b), n, 8);
1996 6ddbc6e4 pbrook
#define PFX q
1997 6ddbc6e4 pbrook
1998 6ddbc6e4 pbrook
#include "op_addsub.h"
1999 6ddbc6e4 pbrook
2000 6ddbc6e4 pbrook
/* Unsigned saturating arithmetic.  */
2001 6ddbc6e4 pbrook
static inline uint16_t add16_usat(uint16_t a, uint8_t b)
2002 6ddbc6e4 pbrook
{
2003 6ddbc6e4 pbrook
    uint16_t res;
2004 6ddbc6e4 pbrook
    res = a + b;
2005 6ddbc6e4 pbrook
    if (res < a)
2006 6ddbc6e4 pbrook
        res = 0xffff;
2007 6ddbc6e4 pbrook
    return res;
2008 6ddbc6e4 pbrook
}
2009 6ddbc6e4 pbrook
2010 6ddbc6e4 pbrook
static inline uint16_t sub16_usat(uint16_t a, uint8_t b)
2011 6ddbc6e4 pbrook
{
2012 6ddbc6e4 pbrook
    if (a < b)
2013 6ddbc6e4 pbrook
        return a - b;
2014 6ddbc6e4 pbrook
    else
2015 6ddbc6e4 pbrook
        return 0;
2016 6ddbc6e4 pbrook
}
2017 6ddbc6e4 pbrook
2018 6ddbc6e4 pbrook
static inline uint8_t add8_usat(uint8_t a, uint8_t b)
2019 6ddbc6e4 pbrook
{
2020 6ddbc6e4 pbrook
    uint8_t res;
2021 6ddbc6e4 pbrook
    res = a + b;
2022 6ddbc6e4 pbrook
    if (res < a)
2023 6ddbc6e4 pbrook
        res = 0xff;
2024 6ddbc6e4 pbrook
    return res;
2025 6ddbc6e4 pbrook
}
2026 6ddbc6e4 pbrook
2027 6ddbc6e4 pbrook
static inline uint8_t sub8_usat(uint8_t a, uint8_t b)
2028 6ddbc6e4 pbrook
{
2029 6ddbc6e4 pbrook
    if (a < b)
2030 6ddbc6e4 pbrook
        return a - b;
2031 6ddbc6e4 pbrook
    else
2032 6ddbc6e4 pbrook
        return 0;
2033 6ddbc6e4 pbrook
}
2034 6ddbc6e4 pbrook
2035 6ddbc6e4 pbrook
#define ADD16(a, b, n) RESULT(add16_usat(a, b), n, 16);
2036 6ddbc6e4 pbrook
#define SUB16(a, b, n) RESULT(sub16_usat(a, b), n, 16);
2037 6ddbc6e4 pbrook
#define ADD8(a, b, n)  RESULT(add8_usat(a, b), n, 8);
2038 6ddbc6e4 pbrook
#define SUB8(a, b, n)  RESULT(sub8_usat(a, b), n, 8);
2039 6ddbc6e4 pbrook
#define PFX uq
2040 6ddbc6e4 pbrook
2041 6ddbc6e4 pbrook
#include "op_addsub.h"
2042 6ddbc6e4 pbrook
2043 6ddbc6e4 pbrook
/* Signed modulo arithmetic.  */
2044 6ddbc6e4 pbrook
#define SARITH16(a, b, n, op) do { \
2045 6ddbc6e4 pbrook
    int32_t sum; \
2046 6ddbc6e4 pbrook
    sum = (int16_t)((uint16_t)(a) op (uint16_t)(b)); \
2047 6ddbc6e4 pbrook
    RESULT(sum, n, 16); \
2048 6ddbc6e4 pbrook
    if (sum >= 0) \
2049 6ddbc6e4 pbrook
        ge |= 3 << (n * 2); \
2050 6ddbc6e4 pbrook
    } while(0)
2051 6ddbc6e4 pbrook
2052 6ddbc6e4 pbrook
#define SARITH8(a, b, n, op) do { \
2053 6ddbc6e4 pbrook
    int32_t sum; \
2054 6ddbc6e4 pbrook
    sum = (int8_t)((uint8_t)(a) op (uint8_t)(b)); \
2055 6ddbc6e4 pbrook
    RESULT(sum, n, 8); \
2056 6ddbc6e4 pbrook
    if (sum >= 0) \
2057 6ddbc6e4 pbrook
        ge |= 1 << n; \
2058 6ddbc6e4 pbrook
    } while(0)
2059 6ddbc6e4 pbrook
2060 6ddbc6e4 pbrook
2061 6ddbc6e4 pbrook
#define ADD16(a, b, n) SARITH16(a, b, n, +)
2062 6ddbc6e4 pbrook
#define SUB16(a, b, n) SARITH16(a, b, n, -)
2063 6ddbc6e4 pbrook
#define ADD8(a, b, n)  SARITH8(a, b, n, +)
2064 6ddbc6e4 pbrook
#define SUB8(a, b, n)  SARITH8(a, b, n, -)
2065 6ddbc6e4 pbrook
#define PFX s
2066 6ddbc6e4 pbrook
#define ARITH_GE
2067 6ddbc6e4 pbrook
2068 6ddbc6e4 pbrook
#include "op_addsub.h"
2069 6ddbc6e4 pbrook
2070 6ddbc6e4 pbrook
/* Unsigned modulo arithmetic.  */
2071 6ddbc6e4 pbrook
#define ADD16(a, b, n) do { \
2072 6ddbc6e4 pbrook
    uint32_t sum; \
2073 6ddbc6e4 pbrook
    sum = (uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b); \
2074 6ddbc6e4 pbrook
    RESULT(sum, n, 16); \
2075 6ddbc6e4 pbrook
    if ((sum >> 16) == 0) \
2076 6ddbc6e4 pbrook
        ge |= 3 << (n * 2); \
2077 6ddbc6e4 pbrook
    } while(0)
2078 6ddbc6e4 pbrook
2079 6ddbc6e4 pbrook
#define ADD8(a, b, n) do { \
2080 6ddbc6e4 pbrook
    uint32_t sum; \
2081 6ddbc6e4 pbrook
    sum = (uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b); \
2082 6ddbc6e4 pbrook
    RESULT(sum, n, 8); \
2083 6ddbc6e4 pbrook
    if ((sum >> 8) == 0) \
2084 6ddbc6e4 pbrook
        ge |= 3 << (n * 2); \
2085 6ddbc6e4 pbrook
    } while(0)
2086 6ddbc6e4 pbrook
2087 6ddbc6e4 pbrook
#define SUB16(a, b, n) do { \
2088 6ddbc6e4 pbrook
    uint32_t sum; \
2089 6ddbc6e4 pbrook
    sum = (uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b); \
2090 6ddbc6e4 pbrook
    RESULT(sum, n, 16); \
2091 6ddbc6e4 pbrook
    if ((sum >> 16) == 0) \
2092 6ddbc6e4 pbrook
        ge |= 3 << (n * 2); \
2093 6ddbc6e4 pbrook
    } while(0)
2094 6ddbc6e4 pbrook
2095 6ddbc6e4 pbrook
#define SUB8(a, b, n) do { \
2096 6ddbc6e4 pbrook
    uint32_t sum; \
2097 6ddbc6e4 pbrook
    sum = (uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b); \
2098 6ddbc6e4 pbrook
    RESULT(sum, n, 8); \
2099 6ddbc6e4 pbrook
    if ((sum >> 8) == 0) \
2100 6ddbc6e4 pbrook
        ge |= 3 << (n * 2); \
2101 6ddbc6e4 pbrook
    } while(0)
2102 6ddbc6e4 pbrook
2103 6ddbc6e4 pbrook
#define PFX u
2104 6ddbc6e4 pbrook
#define ARITH_GE
2105 6ddbc6e4 pbrook
2106 6ddbc6e4 pbrook
#include "op_addsub.h"
2107 6ddbc6e4 pbrook
2108 6ddbc6e4 pbrook
/* Halved signed arithmetic.  */
2109 6ddbc6e4 pbrook
#define ADD16(a, b, n) \
2110 6ddbc6e4 pbrook
  RESULT(((int32_t)(int16_t)(a) + (int32_t)(int16_t)(b)) >> 1, n, 16)
2111 6ddbc6e4 pbrook
#define SUB16(a, b, n) \
2112 6ddbc6e4 pbrook
  RESULT(((int32_t)(int16_t)(a) - (int32_t)(int16_t)(b)) >> 1, n, 16)
2113 6ddbc6e4 pbrook
#define ADD8(a, b, n) \
2114 6ddbc6e4 pbrook
  RESULT(((int32_t)(int8_t)(a) + (int32_t)(int8_t)(b)) >> 1, n, 8)
2115 6ddbc6e4 pbrook
#define SUB8(a, b, n) \
2116 6ddbc6e4 pbrook
  RESULT(((int32_t)(int8_t)(a) - (int32_t)(int8_t)(b)) >> 1, n, 8)
2117 6ddbc6e4 pbrook
#define PFX sh
2118 6ddbc6e4 pbrook
2119 6ddbc6e4 pbrook
#include "op_addsub.h"
2120 6ddbc6e4 pbrook
2121 6ddbc6e4 pbrook
/* Halved unsigned arithmetic.  */
2122 6ddbc6e4 pbrook
#define ADD16(a, b, n) \
2123 6ddbc6e4 pbrook
  RESULT(((uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b)) >> 1, n, 16)
2124 6ddbc6e4 pbrook
#define SUB16(a, b, n) \
2125 6ddbc6e4 pbrook
  RESULT(((uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b)) >> 1, n, 16)
2126 6ddbc6e4 pbrook
#define ADD8(a, b, n) \
2127 6ddbc6e4 pbrook
  RESULT(((uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b)) >> 1, n, 8)
2128 6ddbc6e4 pbrook
#define SUB8(a, b, n) \
2129 6ddbc6e4 pbrook
  RESULT(((uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b)) >> 1, n, 8)
2130 6ddbc6e4 pbrook
#define PFX uh
2131 6ddbc6e4 pbrook
2132 6ddbc6e4 pbrook
#include "op_addsub.h"
2133 6ddbc6e4 pbrook
2134 6ddbc6e4 pbrook
static inline uint8_t do_usad(uint8_t a, uint8_t b)
2135 6ddbc6e4 pbrook
{
2136 6ddbc6e4 pbrook
    if (a > b)
2137 6ddbc6e4 pbrook
        return a - b;
2138 6ddbc6e4 pbrook
    else
2139 6ddbc6e4 pbrook
        return b - a;
2140 6ddbc6e4 pbrook
}
2141 6ddbc6e4 pbrook
2142 6ddbc6e4 pbrook
/* Unsigned sum of absolute byte differences.  */
2143 6ddbc6e4 pbrook
uint32_t HELPER(usad8)(uint32_t a, uint32_t b)
2144 6ddbc6e4 pbrook
{
2145 6ddbc6e4 pbrook
    uint32_t sum;
2146 6ddbc6e4 pbrook
    sum = do_usad(a, b);
2147 6ddbc6e4 pbrook
    sum += do_usad(a >> 8, b >> 8);
2148 6ddbc6e4 pbrook
    sum += do_usad(a >> 16, b >>16);
2149 6ddbc6e4 pbrook
    sum += do_usad(a >> 24, b >> 24);
2150 6ddbc6e4 pbrook
    return sum;
2151 6ddbc6e4 pbrook
}
2152 6ddbc6e4 pbrook
2153 6ddbc6e4 pbrook
/* For ARMv6 SEL instruction.  */
2154 6ddbc6e4 pbrook
uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b)
2155 6ddbc6e4 pbrook
{
2156 6ddbc6e4 pbrook
    uint32_t mask;
2157 6ddbc6e4 pbrook
2158 6ddbc6e4 pbrook
    mask = 0;
2159 6ddbc6e4 pbrook
    if (flags & 1)
2160 6ddbc6e4 pbrook
        mask |= 0xff;
2161 6ddbc6e4 pbrook
    if (flags & 2)
2162 6ddbc6e4 pbrook
        mask |= 0xff00;
2163 6ddbc6e4 pbrook
    if (flags & 4)
2164 6ddbc6e4 pbrook
        mask |= 0xff0000;
2165 6ddbc6e4 pbrook
    if (flags & 8)
2166 6ddbc6e4 pbrook
        mask |= 0xff000000;
2167 6ddbc6e4 pbrook
    return (a & mask) | (b & ~mask);
2168 6ddbc6e4 pbrook
}
2169 6ddbc6e4 pbrook
2170 4373f3ce pbrook
2171 4373f3ce pbrook
/* VFP support.  We follow the convention used for VFP instrunctions:
2172 4373f3ce pbrook
   Single precition routines have a "s" suffix, double precision a
2173 4373f3ce pbrook
   "d" suffix.  */
2174 4373f3ce pbrook
2175 4373f3ce pbrook
/* Convert host exception flags to vfp form.  */
2176 4373f3ce pbrook
static inline int vfp_exceptbits_from_host(int host_bits)
2177 4373f3ce pbrook
{
2178 4373f3ce pbrook
    int target_bits = 0;
2179 4373f3ce pbrook
2180 4373f3ce pbrook
    if (host_bits & float_flag_invalid)
2181 4373f3ce pbrook
        target_bits |= 1;
2182 4373f3ce pbrook
    if (host_bits & float_flag_divbyzero)
2183 4373f3ce pbrook
        target_bits |= 2;
2184 4373f3ce pbrook
    if (host_bits & float_flag_overflow)
2185 4373f3ce pbrook
        target_bits |= 4;
2186 4373f3ce pbrook
    if (host_bits & float_flag_underflow)
2187 4373f3ce pbrook
        target_bits |= 8;
2188 4373f3ce pbrook
    if (host_bits & float_flag_inexact)
2189 4373f3ce pbrook
        target_bits |= 0x10;
2190 4373f3ce pbrook
    return target_bits;
2191 4373f3ce pbrook
}
2192 4373f3ce pbrook
2193 4373f3ce pbrook
uint32_t HELPER(vfp_get_fpscr)(CPUState *env)
2194 4373f3ce pbrook
{
2195 4373f3ce pbrook
    int i;
2196 4373f3ce pbrook
    uint32_t fpscr;
2197 4373f3ce pbrook
2198 4373f3ce pbrook
    fpscr = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff)
2199 4373f3ce pbrook
            | (env->vfp.vec_len << 16)
2200 4373f3ce pbrook
            | (env->vfp.vec_stride << 20);
2201 4373f3ce pbrook
    i = get_float_exception_flags(&env->vfp.fp_status);
2202 4373f3ce pbrook
    fpscr |= vfp_exceptbits_from_host(i);
2203 4373f3ce pbrook
    return fpscr;
2204 4373f3ce pbrook
}
2205 4373f3ce pbrook
2206 4373f3ce pbrook
/* Convert vfp exception flags to target form.  */
2207 4373f3ce pbrook
static inline int vfp_exceptbits_to_host(int target_bits)
2208 4373f3ce pbrook
{
2209 4373f3ce pbrook
    int host_bits = 0;
2210 4373f3ce pbrook
2211 4373f3ce pbrook
    if (target_bits & 1)
2212 4373f3ce pbrook
        host_bits |= float_flag_invalid;
2213 4373f3ce pbrook
    if (target_bits & 2)
2214 4373f3ce pbrook
        host_bits |= float_flag_divbyzero;
2215 4373f3ce pbrook
    if (target_bits & 4)
2216 4373f3ce pbrook
        host_bits |= float_flag_overflow;
2217 4373f3ce pbrook
    if (target_bits & 8)
2218 4373f3ce pbrook
        host_bits |= float_flag_underflow;
2219 4373f3ce pbrook
    if (target_bits & 0x10)
2220 4373f3ce pbrook
        host_bits |= float_flag_inexact;
2221 4373f3ce pbrook
    return host_bits;
2222 4373f3ce pbrook
}
2223 4373f3ce pbrook
2224 4373f3ce pbrook
void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val)
2225 4373f3ce pbrook
{
2226 4373f3ce pbrook
    int i;
2227 4373f3ce pbrook
    uint32_t changed;
2228 4373f3ce pbrook
2229 4373f3ce pbrook
    changed = env->vfp.xregs[ARM_VFP_FPSCR];
2230 4373f3ce pbrook
    env->vfp.xregs[ARM_VFP_FPSCR] = (val & 0xffc8ffff);
2231 4373f3ce pbrook
    env->vfp.vec_len = (val >> 16) & 7;
2232 4373f3ce pbrook
    env->vfp.vec_stride = (val >> 20) & 3;
2233 4373f3ce pbrook
2234 4373f3ce pbrook
    changed ^= val;
2235 4373f3ce pbrook
    if (changed & (3 << 22)) {
2236 4373f3ce pbrook
        i = (val >> 22) & 3;
2237 4373f3ce pbrook
        switch (i) {
2238 4373f3ce pbrook
        case 0:
2239 4373f3ce pbrook
            i = float_round_nearest_even;
2240 4373f3ce pbrook
            break;
2241 4373f3ce pbrook
        case 1:
2242 4373f3ce pbrook
            i = float_round_up;
2243 4373f3ce pbrook
            break;
2244 4373f3ce pbrook
        case 2:
2245 4373f3ce pbrook
            i = float_round_down;
2246 4373f3ce pbrook
            break;
2247 4373f3ce pbrook
        case 3:
2248 4373f3ce pbrook
            i = float_round_to_zero;
2249 4373f3ce pbrook
            break;
2250 4373f3ce pbrook
        }
2251 4373f3ce pbrook
        set_float_rounding_mode(i, &env->vfp.fp_status);
2252 4373f3ce pbrook
    }
2253 4373f3ce pbrook
2254 4373f3ce pbrook
    i = vfp_exceptbits_to_host((val >> 8) & 0x1f);
2255 4373f3ce pbrook
    set_float_exception_flags(i, &env->vfp.fp_status);
2256 4373f3ce pbrook
    /* XXX: FZ and DN are not implemented.  */
2257 4373f3ce pbrook
}
2258 4373f3ce pbrook
2259 4373f3ce pbrook
#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
2260 4373f3ce pbrook
2261 4373f3ce pbrook
#define VFP_BINOP(name) \
2262 4373f3ce pbrook
float32 VFP_HELPER(name, s)(float32 a, float32 b, CPUState *env) \
2263 4373f3ce pbrook
{ \
2264 4373f3ce pbrook
    return float32_ ## name (a, b, &env->vfp.fp_status); \
2265 4373f3ce pbrook
} \
2266 4373f3ce pbrook
float64 VFP_HELPER(name, d)(float64 a, float64 b, CPUState *env) \
2267 4373f3ce pbrook
{ \
2268 4373f3ce pbrook
    return float64_ ## name (a, b, &env->vfp.fp_status); \
2269 4373f3ce pbrook
}
2270 4373f3ce pbrook
VFP_BINOP(add)
2271 4373f3ce pbrook
VFP_BINOP(sub)
2272 4373f3ce pbrook
VFP_BINOP(mul)
2273 4373f3ce pbrook
VFP_BINOP(div)
2274 4373f3ce pbrook
#undef VFP_BINOP
2275 4373f3ce pbrook
2276 4373f3ce pbrook
float32 VFP_HELPER(neg, s)(float32 a)
2277 4373f3ce pbrook
{
2278 4373f3ce pbrook
    return float32_chs(a);
2279 4373f3ce pbrook
}
2280 4373f3ce pbrook
2281 4373f3ce pbrook
float64 VFP_HELPER(neg, d)(float64 a)
2282 4373f3ce pbrook
{
2283 4373f3ce pbrook
    return float32_chs(a);
2284 4373f3ce pbrook
}
2285 4373f3ce pbrook
2286 4373f3ce pbrook
float32 VFP_HELPER(abs, s)(float32 a)
2287 4373f3ce pbrook
{
2288 4373f3ce pbrook
    return float32_abs(a);
2289 4373f3ce pbrook
}
2290 4373f3ce pbrook
2291 4373f3ce pbrook
float64 VFP_HELPER(abs, d)(float64 a)
2292 4373f3ce pbrook
{
2293 4373f3ce pbrook
    return float32_abs(a);
2294 4373f3ce pbrook
}
2295 4373f3ce pbrook
2296 4373f3ce pbrook
float32 VFP_HELPER(sqrt, s)(float32 a, CPUState *env)
2297 4373f3ce pbrook
{
2298 4373f3ce pbrook
    return float32_sqrt(a, &env->vfp.fp_status);
2299 4373f3ce pbrook
}
2300 4373f3ce pbrook
2301 4373f3ce pbrook
float64 VFP_HELPER(sqrt, d)(float64 a, CPUState *env)
2302 4373f3ce pbrook
{
2303 4373f3ce pbrook
    return float64_sqrt(a, &env->vfp.fp_status);
2304 4373f3ce pbrook
}
2305 4373f3ce pbrook
2306 4373f3ce pbrook
/* XXX: check quiet/signaling case */
2307 4373f3ce pbrook
#define DO_VFP_cmp(p, type) \
2308 4373f3ce pbrook
void VFP_HELPER(cmp, p)(type a, type b, CPUState *env)  \
2309 4373f3ce pbrook
{ \
2310 4373f3ce pbrook
    uint32_t flags; \
2311 4373f3ce pbrook
    switch(type ## _compare_quiet(a, b, &env->vfp.fp_status)) { \
2312 4373f3ce pbrook
    case 0: flags = 0x6; break; \
2313 4373f3ce pbrook
    case -1: flags = 0x8; break; \
2314 4373f3ce pbrook
    case 1: flags = 0x2; break; \
2315 4373f3ce pbrook
    default: case 2: flags = 0x3; break; \
2316 4373f3ce pbrook
    } \
2317 4373f3ce pbrook
    env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \
2318 4373f3ce pbrook
        | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
2319 4373f3ce pbrook
} \
2320 4373f3ce pbrook
void VFP_HELPER(cmpe, p)(type a, type b, CPUState *env) \
2321 4373f3ce pbrook
{ \
2322 4373f3ce pbrook
    uint32_t flags; \
2323 4373f3ce pbrook
    switch(type ## _compare(a, b, &env->vfp.fp_status)) { \
2324 4373f3ce pbrook
    case 0: flags = 0x6; break; \
2325 4373f3ce pbrook
    case -1: flags = 0x8; break; \
2326 4373f3ce pbrook
    case 1: flags = 0x2; break; \
2327 4373f3ce pbrook
    default: case 2: flags = 0x3; break; \
2328 4373f3ce pbrook
    } \
2329 4373f3ce pbrook
    env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \
2330 4373f3ce pbrook
        | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
2331 4373f3ce pbrook
}
2332 4373f3ce pbrook
DO_VFP_cmp(s, float32)
2333 4373f3ce pbrook
DO_VFP_cmp(d, float64)
2334 4373f3ce pbrook
#undef DO_VFP_cmp
2335 4373f3ce pbrook
2336 4373f3ce pbrook
/* Helper routines to perform bitwise copies between float and int.  */
2337 4373f3ce pbrook
static inline float32 vfp_itos(uint32_t i)
2338 4373f3ce pbrook
{
2339 4373f3ce pbrook
    union {
2340 4373f3ce pbrook
        uint32_t i;
2341 4373f3ce pbrook
        float32 s;
2342 4373f3ce pbrook
    } v;
2343 4373f3ce pbrook
2344 4373f3ce pbrook
    v.i = i;
2345 4373f3ce pbrook
    return v.s;
2346 4373f3ce pbrook
}
2347 4373f3ce pbrook
2348 4373f3ce pbrook
static inline uint32_t vfp_stoi(float32 s)
2349 4373f3ce pbrook
{
2350 4373f3ce pbrook
    union {
2351 4373f3ce pbrook
        uint32_t i;
2352 4373f3ce pbrook
        float32 s;
2353 4373f3ce pbrook
    } v;
2354 4373f3ce pbrook
2355 4373f3ce pbrook
    v.s = s;
2356 4373f3ce pbrook
    return v.i;
2357 4373f3ce pbrook
}
2358 4373f3ce pbrook
2359 4373f3ce pbrook
static inline float64 vfp_itod(uint64_t i)
2360 4373f3ce pbrook
{
2361 4373f3ce pbrook
    union {
2362 4373f3ce pbrook
        uint64_t i;
2363 4373f3ce pbrook
        float64 d;
2364 4373f3ce pbrook
    } v;
2365 4373f3ce pbrook
2366 4373f3ce pbrook
    v.i = i;
2367 4373f3ce pbrook
    return v.d;
2368 4373f3ce pbrook
}
2369 4373f3ce pbrook
2370 4373f3ce pbrook
static inline uint64_t vfp_dtoi(float64 d)
2371 4373f3ce pbrook
{
2372 4373f3ce pbrook
    union {
2373 4373f3ce pbrook
        uint64_t i;
2374 4373f3ce pbrook
        float64 d;
2375 4373f3ce pbrook
    } v;
2376 4373f3ce pbrook
2377 4373f3ce pbrook
    v.d = d;
2378 4373f3ce pbrook
    return v.i;
2379 4373f3ce pbrook
}
2380 4373f3ce pbrook
2381 4373f3ce pbrook
/* Integer to float conversion.  */
2382 4373f3ce pbrook
float32 VFP_HELPER(uito, s)(float32 x, CPUState *env)
2383 4373f3ce pbrook
{
2384 4373f3ce pbrook
    return uint32_to_float32(vfp_stoi(x), &env->vfp.fp_status);
2385 4373f3ce pbrook
}
2386 4373f3ce pbrook
2387 4373f3ce pbrook
float64 VFP_HELPER(uito, d)(float32 x, CPUState *env)
2388 4373f3ce pbrook
{
2389 4373f3ce pbrook
    return uint32_to_float64(vfp_stoi(x), &env->vfp.fp_status);
2390 4373f3ce pbrook
}
2391 4373f3ce pbrook
2392 4373f3ce pbrook
float32 VFP_HELPER(sito, s)(float32 x, CPUState *env)
2393 4373f3ce pbrook
{
2394 4373f3ce pbrook
    return int32_to_float32(vfp_stoi(x), &env->vfp.fp_status);
2395 4373f3ce pbrook
}
2396 4373f3ce pbrook
2397 4373f3ce pbrook
float64 VFP_HELPER(sito, d)(float32 x, CPUState *env)
2398 4373f3ce pbrook
{
2399 4373f3ce pbrook
    return int32_to_float64(vfp_stoi(x), &env->vfp.fp_status);
2400 4373f3ce pbrook
}
2401 4373f3ce pbrook
2402 4373f3ce pbrook
/* Float to integer conversion.  */
2403 4373f3ce pbrook
float32 VFP_HELPER(toui, s)(float32 x, CPUState *env)
2404 4373f3ce pbrook
{
2405 4373f3ce pbrook
    return vfp_itos(float32_to_uint32(x, &env->vfp.fp_status));
2406 4373f3ce pbrook
}
2407 4373f3ce pbrook
2408 4373f3ce pbrook
float32 VFP_HELPER(toui, d)(float64 x, CPUState *env)
2409 4373f3ce pbrook
{
2410 4373f3ce pbrook
    return vfp_itos(float64_to_uint32(x, &env->vfp.fp_status));
2411 4373f3ce pbrook
}
2412 4373f3ce pbrook
2413 4373f3ce pbrook
float32 VFP_HELPER(tosi, s)(float32 x, CPUState *env)
2414 4373f3ce pbrook
{
2415 4373f3ce pbrook
    return vfp_itos(float32_to_int32(x, &env->vfp.fp_status));
2416 4373f3ce pbrook
}
2417 4373f3ce pbrook
2418 4373f3ce pbrook
float32 VFP_HELPER(tosi, d)(float64 x, CPUState *env)
2419 4373f3ce pbrook
{
2420 4373f3ce pbrook
    return vfp_itos(float64_to_int32(x, &env->vfp.fp_status));
2421 4373f3ce pbrook
}
2422 4373f3ce pbrook
2423 4373f3ce pbrook
float32 VFP_HELPER(touiz, s)(float32 x, CPUState *env)
2424 4373f3ce pbrook
{
2425 4373f3ce pbrook
    return vfp_itos(float32_to_uint32_round_to_zero(x, &env->vfp.fp_status));
2426 4373f3ce pbrook
}
2427 4373f3ce pbrook
2428 4373f3ce pbrook
float32 VFP_HELPER(touiz, d)(float64 x, CPUState *env)
2429 4373f3ce pbrook
{
2430 4373f3ce pbrook
    return vfp_itos(float64_to_uint32_round_to_zero(x, &env->vfp.fp_status));
2431 4373f3ce pbrook
}
2432 4373f3ce pbrook
2433 4373f3ce pbrook
float32 VFP_HELPER(tosiz, s)(float32 x, CPUState *env)
2434 4373f3ce pbrook
{
2435 4373f3ce pbrook
    return vfp_itos(float32_to_int32_round_to_zero(x, &env->vfp.fp_status));
2436 4373f3ce pbrook
}
2437 4373f3ce pbrook
2438 4373f3ce pbrook
float32 VFP_HELPER(tosiz, d)(float64 x, CPUState *env)
2439 4373f3ce pbrook
{
2440 4373f3ce pbrook
    return vfp_itos(float64_to_int32_round_to_zero(x, &env->vfp.fp_status));
2441 4373f3ce pbrook
}
2442 4373f3ce pbrook
2443 4373f3ce pbrook
/* floating point conversion */
2444 4373f3ce pbrook
float64 VFP_HELPER(fcvtd, s)(float32 x, CPUState *env)
2445 4373f3ce pbrook
{
2446 4373f3ce pbrook
    return float32_to_float64(x, &env->vfp.fp_status);
2447 4373f3ce pbrook
}
2448 4373f3ce pbrook
2449 4373f3ce pbrook
float32 VFP_HELPER(fcvts, d)(float64 x, CPUState *env)
2450 4373f3ce pbrook
{
2451 4373f3ce pbrook
    return float64_to_float32(x, &env->vfp.fp_status);
2452 4373f3ce pbrook
}
2453 4373f3ce pbrook
2454 4373f3ce pbrook
/* VFP3 fixed point conversion.  */
2455 4373f3ce pbrook
#define VFP_CONV_FIX(name, p, ftype, itype, sign) \
2456 4373f3ce pbrook
ftype VFP_HELPER(name##to, p)(ftype x, uint32_t shift, CPUState *env) \
2457 4373f3ce pbrook
{ \
2458 4373f3ce pbrook
    ftype tmp; \
2459 4373f3ce pbrook
    tmp = sign##int32_to_##ftype ((itype)vfp_##p##toi(x), \
2460 4373f3ce pbrook
                                  &env->vfp.fp_status); \
2461 4373f3ce pbrook
    return ftype##_scalbn(tmp, shift, &env->vfp.fp_status); \
2462 4373f3ce pbrook
} \
2463 4373f3ce pbrook
ftype VFP_HELPER(to##name, p)(ftype x, uint32_t shift, CPUState *env) \
2464 4373f3ce pbrook
{ \
2465 4373f3ce pbrook
    ftype tmp; \
2466 4373f3ce pbrook
    tmp = ftype##_scalbn(x, shift, &env->vfp.fp_status); \
2467 4373f3ce pbrook
    return vfp_ito##p((itype)ftype##_to_##sign##int32_round_to_zero(tmp, \
2468 4373f3ce pbrook
        &env->vfp.fp_status)); \
2469 4373f3ce pbrook
}
2470 4373f3ce pbrook
2471 4373f3ce pbrook
VFP_CONV_FIX(sh, d, float64, int16, )
2472 4373f3ce pbrook
VFP_CONV_FIX(sl, d, float64, int32, )
2473 4373f3ce pbrook
VFP_CONV_FIX(uh, d, float64, uint16, u)
2474 4373f3ce pbrook
VFP_CONV_FIX(ul, d, float64, uint32, u)
2475 4373f3ce pbrook
VFP_CONV_FIX(sh, s, float32, int16, )
2476 4373f3ce pbrook
VFP_CONV_FIX(sl, s, float32, int32, )
2477 4373f3ce pbrook
VFP_CONV_FIX(uh, s, float32, uint16, u)
2478 4373f3ce pbrook
VFP_CONV_FIX(ul, s, float32, uint32, u)
2479 4373f3ce pbrook
#undef VFP_CONV_FIX
2480 4373f3ce pbrook
2481 4373f3ce pbrook
float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
2482 4373f3ce pbrook
{
2483 4373f3ce pbrook
    float_status *s = &env->vfp.fp_status;
2484 4373f3ce pbrook
    float32 two = int32_to_float32(2, s);
2485 4373f3ce pbrook
    return float32_sub(two, float32_mul(a, b, s), s);
2486 4373f3ce pbrook
}
2487 4373f3ce pbrook
2488 4373f3ce pbrook
float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUState *env)
2489 4373f3ce pbrook
{
2490 4373f3ce pbrook
    float_status *s = &env->vfp.fp_status;
2491 4373f3ce pbrook
    float32 three = int32_to_float32(3, s);
2492 4373f3ce pbrook
    return float32_sub(three, float32_mul(a, b, s), s);
2493 4373f3ce pbrook
}
2494 4373f3ce pbrook
2495 4373f3ce pbrook
/* TODO: The architecture specifies the value that the estimate functions
2496 4373f3ce pbrook
   should return.  We return the exact reciprocal/root instead.  */
2497 4373f3ce pbrook
float32 HELPER(recpe_f32)(float32 a, CPUState *env)
2498 4373f3ce pbrook
{
2499 4373f3ce pbrook
    float_status *s = &env->vfp.fp_status;
2500 4373f3ce pbrook
    float32 one = int32_to_float32(1, s);
2501 4373f3ce pbrook
    return float32_div(one, a, s);
2502 4373f3ce pbrook
}
2503 4373f3ce pbrook
2504 4373f3ce pbrook
float32 HELPER(rsqrte_f32)(float32 a, CPUState *env)
2505 4373f3ce pbrook
{
2506 4373f3ce pbrook
    float_status *s = &env->vfp.fp_status;
2507 4373f3ce pbrook
    float32 one = int32_to_float32(1, s);
2508 4373f3ce pbrook
    return float32_div(one, float32_sqrt(a, s), s);
2509 4373f3ce pbrook
}
2510 4373f3ce pbrook
2511 4373f3ce pbrook
uint32_t HELPER(recpe_u32)(uint32_t a, CPUState *env)
2512 4373f3ce pbrook
{
2513 4373f3ce pbrook
    float_status *s = &env->vfp.fp_status;
2514 4373f3ce pbrook
    float32 tmp;
2515 4373f3ce pbrook
    tmp = int32_to_float32(a, s);
2516 4373f3ce pbrook
    tmp = float32_scalbn(tmp, -32, s);
2517 4373f3ce pbrook
    tmp = helper_recpe_f32(tmp, env);
2518 4373f3ce pbrook
    tmp = float32_scalbn(tmp, 31, s);
2519 4373f3ce pbrook
    return float32_to_int32(tmp, s);
2520 4373f3ce pbrook
}
2521 4373f3ce pbrook
2522 4373f3ce pbrook
uint32_t HELPER(rsqrte_u32)(uint32_t a, CPUState *env)
2523 4373f3ce pbrook
{
2524 4373f3ce pbrook
    float_status *s = &env->vfp.fp_status;
2525 4373f3ce pbrook
    float32 tmp;
2526 4373f3ce pbrook
    tmp = int32_to_float32(a, s);
2527 4373f3ce pbrook
    tmp = float32_scalbn(tmp, -32, s);
2528 4373f3ce pbrook
    tmp = helper_rsqrte_f32(tmp, env);
2529 4373f3ce pbrook
    tmp = float32_scalbn(tmp, 31, s);
2530 4373f3ce pbrook
    return float32_to_int32(tmp, s);
2531 4373f3ce pbrook
}