Statistics
| Branch: | Revision:

root / target-arm / helper.c @ 4f78c9ad

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