Statistics
| Branch: | Revision:

root / target-arm / helper.c @ 9ea62f57

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