Statistics
| Branch: | Revision:

root / target-arm / helper.c @ 016b2b28

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