Statistics
| Branch: | Revision:

root / target-arm / helper.c @ f8ed7070

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