Statistics
| Branch: | Revision:

root / target-arm / helper.c @ 72f24d15

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