Statistics
| Branch: | Revision:

root / target-arm / helper.c @ 906879a9

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