Statistics
| Branch: | Revision:

root / target-arm / helper.c @ 1146a817

History | View | Annotate | Download (85.1 kB)

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