Statistics
| Branch: | Revision:

root / target-arm / helper.c @ 64e58fe5

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