Statistics
| Branch: | Revision:

root / target-arm / helper.c @ 6aae3df1

History | View | Annotate | Download (83.4 kB)

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