Statistics
| Branch: | Revision:

root / target-arm / helper.c @ 4cc35614

History | View | Annotate | Download (157.8 kB)

1 b5ff1b31 bellard
#include "cpu.h"
2 022c62cb Paolo Bonzini
#include "exec/gdbstub.h"
3 7b59220e Lluís
#include "helper.h"
4 1de7afc9 Paolo Bonzini
#include "qemu/host-utils.h"
5 78027bb6 Cole Robinson
#include "sysemu/arch_init.h"
6 9c17d615 Paolo Bonzini
#include "sysemu/sysemu.h"
7 1de7afc9 Paolo Bonzini
#include "qemu/bitops.h"
8 0b03bdfc Peter Maydell
9 4a501606 Peter Maydell
#ifndef CONFIG_USER_ONLY
10 4a501606 Peter Maydell
static inline int get_phys_addr(CPUARMState *env, uint32_t address,
11 4a501606 Peter Maydell
                                int access_type, int is_user,
12 a8170e5e Avi Kivity
                                hwaddr *phys_ptr, int *prot,
13 4a501606 Peter Maydell
                                target_ulong *page_size);
14 4a501606 Peter Maydell
#endif
15 4a501606 Peter Maydell
16 0ecb72a5 Andreas Färber
static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
17 56aebc89 pbrook
{
18 56aebc89 pbrook
    int nregs;
19 56aebc89 pbrook
20 56aebc89 pbrook
    /* VFP data registers are always little-endian.  */
21 56aebc89 pbrook
    nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
22 56aebc89 pbrook
    if (reg < nregs) {
23 56aebc89 pbrook
        stfq_le_p(buf, env->vfp.regs[reg]);
24 56aebc89 pbrook
        return 8;
25 56aebc89 pbrook
    }
26 56aebc89 pbrook
    if (arm_feature(env, ARM_FEATURE_NEON)) {
27 56aebc89 pbrook
        /* Aliases for Q regs.  */
28 56aebc89 pbrook
        nregs += 16;
29 56aebc89 pbrook
        if (reg < nregs) {
30 56aebc89 pbrook
            stfq_le_p(buf, env->vfp.regs[(reg - 32) * 2]);
31 56aebc89 pbrook
            stfq_le_p(buf + 8, env->vfp.regs[(reg - 32) * 2 + 1]);
32 56aebc89 pbrook
            return 16;
33 56aebc89 pbrook
        }
34 56aebc89 pbrook
    }
35 56aebc89 pbrook
    switch (reg - nregs) {
36 56aebc89 pbrook
    case 0: stl_p(buf, env->vfp.xregs[ARM_VFP_FPSID]); return 4;
37 56aebc89 pbrook
    case 1: stl_p(buf, env->vfp.xregs[ARM_VFP_FPSCR]); return 4;
38 56aebc89 pbrook
    case 2: stl_p(buf, env->vfp.xregs[ARM_VFP_FPEXC]); return 4;
39 56aebc89 pbrook
    }
40 56aebc89 pbrook
    return 0;
41 56aebc89 pbrook
}
42 56aebc89 pbrook
43 0ecb72a5 Andreas Färber
static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
44 56aebc89 pbrook
{
45 56aebc89 pbrook
    int nregs;
46 56aebc89 pbrook
47 56aebc89 pbrook
    nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
48 56aebc89 pbrook
    if (reg < nregs) {
49 56aebc89 pbrook
        env->vfp.regs[reg] = ldfq_le_p(buf);
50 56aebc89 pbrook
        return 8;
51 56aebc89 pbrook
    }
52 56aebc89 pbrook
    if (arm_feature(env, ARM_FEATURE_NEON)) {
53 56aebc89 pbrook
        nregs += 16;
54 56aebc89 pbrook
        if (reg < nregs) {
55 56aebc89 pbrook
            env->vfp.regs[(reg - 32) * 2] = ldfq_le_p(buf);
56 56aebc89 pbrook
            env->vfp.regs[(reg - 32) * 2 + 1] = ldfq_le_p(buf + 8);
57 56aebc89 pbrook
            return 16;
58 56aebc89 pbrook
        }
59 56aebc89 pbrook
    }
60 56aebc89 pbrook
    switch (reg - nregs) {
61 56aebc89 pbrook
    case 0: env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf); return 4;
62 56aebc89 pbrook
    case 1: env->vfp.xregs[ARM_VFP_FPSCR] = ldl_p(buf); return 4;
63 71b3c3de Juha Riihimäki
    case 2: env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30); return 4;
64 56aebc89 pbrook
    }
65 56aebc89 pbrook
    return 0;
66 56aebc89 pbrook
}
67 56aebc89 pbrook
68 6a669427 Peter Maydell
static int aarch64_fpu_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
69 6a669427 Peter Maydell
{
70 6a669427 Peter Maydell
    switch (reg) {
71 6a669427 Peter Maydell
    case 0 ... 31:
72 6a669427 Peter Maydell
        /* 128 bit FP register */
73 6a669427 Peter Maydell
        stfq_le_p(buf, env->vfp.regs[reg * 2]);
74 6a669427 Peter Maydell
        stfq_le_p(buf + 8, env->vfp.regs[reg * 2 + 1]);
75 6a669427 Peter Maydell
        return 16;
76 6a669427 Peter Maydell
    case 32:
77 6a669427 Peter Maydell
        /* FPSR */
78 6a669427 Peter Maydell
        stl_p(buf, vfp_get_fpsr(env));
79 6a669427 Peter Maydell
        return 4;
80 6a669427 Peter Maydell
    case 33:
81 6a669427 Peter Maydell
        /* FPCR */
82 6a669427 Peter Maydell
        stl_p(buf, vfp_get_fpcr(env));
83 6a669427 Peter Maydell
        return 4;
84 6a669427 Peter Maydell
    default:
85 6a669427 Peter Maydell
        return 0;
86 6a669427 Peter Maydell
    }
87 6a669427 Peter Maydell
}
88 6a669427 Peter Maydell
89 6a669427 Peter Maydell
static int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
90 6a669427 Peter Maydell
{
91 6a669427 Peter Maydell
    switch (reg) {
92 6a669427 Peter Maydell
    case 0 ... 31:
93 6a669427 Peter Maydell
        /* 128 bit FP register */
94 6a669427 Peter Maydell
        env->vfp.regs[reg * 2] = ldfq_le_p(buf);
95 6a669427 Peter Maydell
        env->vfp.regs[reg * 2 + 1] = ldfq_le_p(buf + 8);
96 6a669427 Peter Maydell
        return 16;
97 6a669427 Peter Maydell
    case 32:
98 6a669427 Peter Maydell
        /* FPSR */
99 6a669427 Peter Maydell
        vfp_set_fpsr(env, ldl_p(buf));
100 6a669427 Peter Maydell
        return 4;
101 6a669427 Peter Maydell
    case 33:
102 6a669427 Peter Maydell
        /* FPCR */
103 6a669427 Peter Maydell
        vfp_set_fpcr(env, ldl_p(buf));
104 6a669427 Peter Maydell
        return 4;
105 6a669427 Peter Maydell
    default:
106 6a669427 Peter Maydell
        return 0;
107 6a669427 Peter Maydell
    }
108 6a669427 Peter Maydell
}
109 6a669427 Peter Maydell
110 c4241c7d Peter Maydell
static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri)
111 d4e6df63 Peter Maydell
{
112 67ed771d Peter Maydell
    if (cpreg_field_is_64bit(ri)) {
113 c4241c7d Peter Maydell
        return CPREG_FIELD64(env, ri);
114 22d9e1a9 Peter Maydell
    } else {
115 c4241c7d Peter Maydell
        return CPREG_FIELD32(env, ri);
116 22d9e1a9 Peter Maydell
    }
117 d4e6df63 Peter Maydell
}
118 d4e6df63 Peter Maydell
119 c4241c7d Peter Maydell
static void raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
120 c4241c7d Peter Maydell
                      uint64_t value)
121 d4e6df63 Peter Maydell
{
122 67ed771d Peter Maydell
    if (cpreg_field_is_64bit(ri)) {
123 22d9e1a9 Peter Maydell
        CPREG_FIELD64(env, ri) = value;
124 22d9e1a9 Peter Maydell
    } else {
125 22d9e1a9 Peter Maydell
        CPREG_FIELD32(env, ri) = value;
126 22d9e1a9 Peter Maydell
    }
127 d4e6df63 Peter Maydell
}
128 d4e6df63 Peter Maydell
129 59a1c327 Peter Maydell
static uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri)
130 721fae12 Peter Maydell
{
131 59a1c327 Peter Maydell
    /* Raw read of a coprocessor register (as needed for migration, etc). */
132 721fae12 Peter Maydell
    if (ri->type & ARM_CP_CONST) {
133 59a1c327 Peter Maydell
        return ri->resetvalue;
134 721fae12 Peter Maydell
    } else if (ri->raw_readfn) {
135 59a1c327 Peter Maydell
        return ri->raw_readfn(env, ri);
136 721fae12 Peter Maydell
    } else if (ri->readfn) {
137 59a1c327 Peter Maydell
        return ri->readfn(env, ri);
138 721fae12 Peter Maydell
    } else {
139 59a1c327 Peter Maydell
        return raw_read(env, ri);
140 721fae12 Peter Maydell
    }
141 721fae12 Peter Maydell
}
142 721fae12 Peter Maydell
143 59a1c327 Peter Maydell
static void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri,
144 7900e9f1 Peter Maydell
                             uint64_t v)
145 721fae12 Peter Maydell
{
146 721fae12 Peter Maydell
    /* Raw write of a coprocessor register (as needed for migration, etc).
147 721fae12 Peter Maydell
     * Note that constant registers are treated as write-ignored; the
148 721fae12 Peter Maydell
     * caller should check for success by whether a readback gives the
149 721fae12 Peter Maydell
     * value written.
150 721fae12 Peter Maydell
     */
151 721fae12 Peter Maydell
    if (ri->type & ARM_CP_CONST) {
152 59a1c327 Peter Maydell
        return;
153 721fae12 Peter Maydell
    } else if (ri->raw_writefn) {
154 c4241c7d Peter Maydell
        ri->raw_writefn(env, ri, v);
155 721fae12 Peter Maydell
    } else if (ri->writefn) {
156 c4241c7d Peter Maydell
        ri->writefn(env, ri, v);
157 721fae12 Peter Maydell
    } else {
158 afb2530f Peter Crosthwaite
        raw_write(env, ri, v);
159 721fae12 Peter Maydell
    }
160 721fae12 Peter Maydell
}
161 721fae12 Peter Maydell
162 721fae12 Peter Maydell
bool write_cpustate_to_list(ARMCPU *cpu)
163 721fae12 Peter Maydell
{
164 721fae12 Peter Maydell
    /* Write the coprocessor state from cpu->env to the (index,value) list. */
165 721fae12 Peter Maydell
    int i;
166 721fae12 Peter Maydell
    bool ok = true;
167 721fae12 Peter Maydell
168 721fae12 Peter Maydell
    for (i = 0; i < cpu->cpreg_array_len; i++) {
169 721fae12 Peter Maydell
        uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
170 721fae12 Peter Maydell
        const ARMCPRegInfo *ri;
171 59a1c327 Peter Maydell
172 60322b39 Peter Maydell
        ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
173 721fae12 Peter Maydell
        if (!ri) {
174 721fae12 Peter Maydell
            ok = false;
175 721fae12 Peter Maydell
            continue;
176 721fae12 Peter Maydell
        }
177 721fae12 Peter Maydell
        if (ri->type & ARM_CP_NO_MIGRATE) {
178 721fae12 Peter Maydell
            continue;
179 721fae12 Peter Maydell
        }
180 59a1c327 Peter Maydell
        cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
181 721fae12 Peter Maydell
    }
182 721fae12 Peter Maydell
    return ok;
183 721fae12 Peter Maydell
}
184 721fae12 Peter Maydell
185 721fae12 Peter Maydell
bool write_list_to_cpustate(ARMCPU *cpu)
186 721fae12 Peter Maydell
{
187 721fae12 Peter Maydell
    int i;
188 721fae12 Peter Maydell
    bool ok = true;
189 721fae12 Peter Maydell
190 721fae12 Peter Maydell
    for (i = 0; i < cpu->cpreg_array_len; i++) {
191 721fae12 Peter Maydell
        uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
192 721fae12 Peter Maydell
        uint64_t v = cpu->cpreg_values[i];
193 721fae12 Peter Maydell
        const ARMCPRegInfo *ri;
194 721fae12 Peter Maydell
195 60322b39 Peter Maydell
        ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
196 721fae12 Peter Maydell
        if (!ri) {
197 721fae12 Peter Maydell
            ok = false;
198 721fae12 Peter Maydell
            continue;
199 721fae12 Peter Maydell
        }
200 721fae12 Peter Maydell
        if (ri->type & ARM_CP_NO_MIGRATE) {
201 721fae12 Peter Maydell
            continue;
202 721fae12 Peter Maydell
        }
203 721fae12 Peter Maydell
        /* Write value and confirm it reads back as written
204 721fae12 Peter Maydell
         * (to catch read-only registers and partially read-only
205 721fae12 Peter Maydell
         * registers where the incoming migration value doesn't match)
206 721fae12 Peter Maydell
         */
207 59a1c327 Peter Maydell
        write_raw_cp_reg(&cpu->env, ri, v);
208 59a1c327 Peter Maydell
        if (read_raw_cp_reg(&cpu->env, ri) != v) {
209 721fae12 Peter Maydell
            ok = false;
210 721fae12 Peter Maydell
        }
211 721fae12 Peter Maydell
    }
212 721fae12 Peter Maydell
    return ok;
213 721fae12 Peter Maydell
}
214 721fae12 Peter Maydell
215 721fae12 Peter Maydell
static void add_cpreg_to_list(gpointer key, gpointer opaque)
216 721fae12 Peter Maydell
{
217 721fae12 Peter Maydell
    ARMCPU *cpu = opaque;
218 721fae12 Peter Maydell
    uint64_t regidx;
219 721fae12 Peter Maydell
    const ARMCPRegInfo *ri;
220 721fae12 Peter Maydell
221 721fae12 Peter Maydell
    regidx = *(uint32_t *)key;
222 60322b39 Peter Maydell
    ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
223 721fae12 Peter Maydell
224 721fae12 Peter Maydell
    if (!(ri->type & ARM_CP_NO_MIGRATE)) {
225 721fae12 Peter Maydell
        cpu->cpreg_indexes[cpu->cpreg_array_len] = cpreg_to_kvm_id(regidx);
226 721fae12 Peter Maydell
        /* The value array need not be initialized at this point */
227 721fae12 Peter Maydell
        cpu->cpreg_array_len++;
228 721fae12 Peter Maydell
    }
229 721fae12 Peter Maydell
}
230 721fae12 Peter Maydell
231 721fae12 Peter Maydell
static void count_cpreg(gpointer key, gpointer opaque)
232 721fae12 Peter Maydell
{
233 721fae12 Peter Maydell
    ARMCPU *cpu = opaque;
234 721fae12 Peter Maydell
    uint64_t regidx;
235 721fae12 Peter Maydell
    const ARMCPRegInfo *ri;
236 721fae12 Peter Maydell
237 721fae12 Peter Maydell
    regidx = *(uint32_t *)key;
238 60322b39 Peter Maydell
    ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
239 721fae12 Peter Maydell
240 721fae12 Peter Maydell
    if (!(ri->type & ARM_CP_NO_MIGRATE)) {
241 721fae12 Peter Maydell
        cpu->cpreg_array_len++;
242 721fae12 Peter Maydell
    }
243 721fae12 Peter Maydell
}
244 721fae12 Peter Maydell
245 721fae12 Peter Maydell
static gint cpreg_key_compare(gconstpointer a, gconstpointer b)
246 721fae12 Peter Maydell
{
247 cbf239b7 Alvise Rigo
    uint64_t aidx = cpreg_to_kvm_id(*(uint32_t *)a);
248 cbf239b7 Alvise Rigo
    uint64_t bidx = cpreg_to_kvm_id(*(uint32_t *)b);
249 721fae12 Peter Maydell
250 cbf239b7 Alvise Rigo
    if (aidx > bidx) {
251 cbf239b7 Alvise Rigo
        return 1;
252 cbf239b7 Alvise Rigo
    }
253 cbf239b7 Alvise Rigo
    if (aidx < bidx) {
254 cbf239b7 Alvise Rigo
        return -1;
255 cbf239b7 Alvise Rigo
    }
256 cbf239b7 Alvise Rigo
    return 0;
257 721fae12 Peter Maydell
}
258 721fae12 Peter Maydell
259 82a3a118 Peter Maydell
static void cpreg_make_keylist(gpointer key, gpointer value, gpointer udata)
260 82a3a118 Peter Maydell
{
261 82a3a118 Peter Maydell
    GList **plist = udata;
262 82a3a118 Peter Maydell
263 82a3a118 Peter Maydell
    *plist = g_list_prepend(*plist, key);
264 82a3a118 Peter Maydell
}
265 82a3a118 Peter Maydell
266 721fae12 Peter Maydell
void init_cpreg_list(ARMCPU *cpu)
267 721fae12 Peter Maydell
{
268 721fae12 Peter Maydell
    /* Initialise the cpreg_tuples[] array based on the cp_regs hash.
269 721fae12 Peter Maydell
     * Note that we require cpreg_tuples[] to be sorted by key ID.
270 721fae12 Peter Maydell
     */
271 82a3a118 Peter Maydell
    GList *keys = NULL;
272 721fae12 Peter Maydell
    int arraylen;
273 721fae12 Peter Maydell
274 82a3a118 Peter Maydell
    g_hash_table_foreach(cpu->cp_regs, cpreg_make_keylist, &keys);
275 82a3a118 Peter Maydell
276 721fae12 Peter Maydell
    keys = g_list_sort(keys, cpreg_key_compare);
277 721fae12 Peter Maydell
278 721fae12 Peter Maydell
    cpu->cpreg_array_len = 0;
279 721fae12 Peter Maydell
280 721fae12 Peter Maydell
    g_list_foreach(keys, count_cpreg, cpu);
281 721fae12 Peter Maydell
282 721fae12 Peter Maydell
    arraylen = cpu->cpreg_array_len;
283 721fae12 Peter Maydell
    cpu->cpreg_indexes = g_new(uint64_t, arraylen);
284 721fae12 Peter Maydell
    cpu->cpreg_values = g_new(uint64_t, arraylen);
285 721fae12 Peter Maydell
    cpu->cpreg_vmstate_indexes = g_new(uint64_t, arraylen);
286 721fae12 Peter Maydell
    cpu->cpreg_vmstate_values = g_new(uint64_t, arraylen);
287 721fae12 Peter Maydell
    cpu->cpreg_vmstate_array_len = cpu->cpreg_array_len;
288 721fae12 Peter Maydell
    cpu->cpreg_array_len = 0;
289 721fae12 Peter Maydell
290 721fae12 Peter Maydell
    g_list_foreach(keys, add_cpreg_to_list, cpu);
291 721fae12 Peter Maydell
292 721fae12 Peter Maydell
    assert(cpu->cpreg_array_len == arraylen);
293 721fae12 Peter Maydell
294 721fae12 Peter Maydell
    g_list_free(keys);
295 721fae12 Peter Maydell
}
296 721fae12 Peter Maydell
297 c4241c7d Peter Maydell
static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
298 c983fe6c Peter Maydell
{
299 c983fe6c Peter Maydell
    env->cp15.c3 = value;
300 c983fe6c Peter Maydell
    tlb_flush(env, 1); /* Flush TLB as domain not tracked in TLB */
301 c983fe6c Peter Maydell
}
302 c983fe6c Peter Maydell
303 c4241c7d Peter Maydell
static void fcse_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
304 08de207b Peter Maydell
{
305 08de207b Peter Maydell
    if (env->cp15.c13_fcse != value) {
306 08de207b Peter Maydell
        /* Unlike real hardware the qemu TLB uses virtual addresses,
307 08de207b Peter Maydell
         * not modified virtual addresses, so this causes a TLB flush.
308 08de207b Peter Maydell
         */
309 08de207b Peter Maydell
        tlb_flush(env, 1);
310 08de207b Peter Maydell
        env->cp15.c13_fcse = value;
311 08de207b Peter Maydell
    }
312 08de207b Peter Maydell
}
313 c4241c7d Peter Maydell
314 c4241c7d Peter Maydell
static void contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri,
315 c4241c7d Peter Maydell
                             uint64_t value)
316 08de207b Peter Maydell
{
317 08de207b Peter Maydell
    if (env->cp15.c13_context != value && !arm_feature(env, ARM_FEATURE_MPU)) {
318 08de207b Peter Maydell
        /* For VMSA (when not using the LPAE long descriptor page table
319 08de207b Peter Maydell
         * format) this register includes the ASID, so do a TLB flush.
320 08de207b Peter Maydell
         * For PMSA it is purely a process ID and no action is needed.
321 08de207b Peter Maydell
         */
322 08de207b Peter Maydell
        tlb_flush(env, 1);
323 08de207b Peter Maydell
    }
324 08de207b Peter Maydell
    env->cp15.c13_context = value;
325 08de207b Peter Maydell
}
326 08de207b Peter Maydell
327 c4241c7d Peter Maydell
static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri,
328 c4241c7d Peter Maydell
                          uint64_t value)
329 d929823f Peter Maydell
{
330 d929823f Peter Maydell
    /* Invalidate all (TLBIALL) */
331 d929823f Peter Maydell
    tlb_flush(env, 1);
332 d929823f Peter Maydell
}
333 d929823f Peter Maydell
334 c4241c7d Peter Maydell
static void tlbimva_write(CPUARMState *env, const ARMCPRegInfo *ri,
335 c4241c7d Peter Maydell
                          uint64_t value)
336 d929823f Peter Maydell
{
337 d929823f Peter Maydell
    /* Invalidate single TLB entry by MVA and ASID (TLBIMVA) */
338 d929823f Peter Maydell
    tlb_flush_page(env, value & TARGET_PAGE_MASK);
339 d929823f Peter Maydell
}
340 d929823f Peter Maydell
341 c4241c7d Peter Maydell
static void tlbiasid_write(CPUARMState *env, const ARMCPRegInfo *ri,
342 c4241c7d Peter Maydell
                           uint64_t value)
343 d929823f Peter Maydell
{
344 d929823f Peter Maydell
    /* Invalidate by ASID (TLBIASID) */
345 d929823f Peter Maydell
    tlb_flush(env, value == 0);
346 d929823f Peter Maydell
}
347 d929823f Peter Maydell
348 c4241c7d Peter Maydell
static void tlbimvaa_write(CPUARMState *env, const ARMCPRegInfo *ri,
349 c4241c7d Peter Maydell
                           uint64_t value)
350 d929823f Peter Maydell
{
351 d929823f Peter Maydell
    /* Invalidate single entry by MVA, all ASIDs (TLBIMVAA) */
352 d929823f Peter Maydell
    tlb_flush_page(env, value & TARGET_PAGE_MASK);
353 d929823f Peter Maydell
}
354 d929823f Peter Maydell
355 e9aa6c21 Peter Maydell
static const ARMCPRegInfo cp_reginfo[] = {
356 e9aa6c21 Peter Maydell
    /* DBGDIDR: just RAZ. In particular this means the "debug architecture
357 e9aa6c21 Peter Maydell
     * version" bits will read as a reserved value, which should cause
358 e9aa6c21 Peter Maydell
     * Linux to not try to use the debug hardware.
359 e9aa6c21 Peter Maydell
     */
360 e9aa6c21 Peter Maydell
    { .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0,
361 e9aa6c21 Peter Maydell
      .access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 0 },
362 c983fe6c Peter Maydell
    /* MMU Domain access control / MPU write buffer control */
363 c983fe6c Peter Maydell
    { .name = "DACR", .cp = 15,
364 c983fe6c Peter Maydell
      .crn = 3, .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY,
365 c983fe6c Peter Maydell
      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c3),
366 d4e6df63 Peter Maydell
      .resetvalue = 0, .writefn = dacr_write, .raw_writefn = raw_write, },
367 08de207b Peter Maydell
    { .name = "FCSEIDR", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 0,
368 08de207b Peter Maydell
      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c13_fcse),
369 d4e6df63 Peter Maydell
      .resetvalue = 0, .writefn = fcse_write, .raw_writefn = raw_write, },
370 08de207b Peter Maydell
    { .name = "CONTEXTIDR", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 1,
371 a4f0cec6 Sergey Fedorov
      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c13_context),
372 d4e6df63 Peter Maydell
      .resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, },
373 4fdd17dd Peter Maydell
    /* ??? This covers not just the impdef TLB lockdown registers but also
374 4fdd17dd Peter Maydell
     * some v7VMSA registers relating to TEX remap, so it is overly broad.
375 4fdd17dd Peter Maydell
     */
376 4fdd17dd Peter Maydell
    { .name = "TLB_LOCKDOWN", .cp = 15, .crn = 10, .crm = CP_ANY,
377 4fdd17dd Peter Maydell
      .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_NOP },
378 d929823f Peter Maydell
    /* MMU TLB control. Note that the wildcarding means we cover not just
379 d929823f Peter Maydell
     * the unified TLB ops but also the dside/iside/inner-shareable variants.
380 d929823f Peter Maydell
     */
381 d929823f Peter Maydell
    { .name = "TLBIALL", .cp = 15, .crn = 8, .crm = CP_ANY,
382 d4e6df63 Peter Maydell
      .opc1 = CP_ANY, .opc2 = 0, .access = PL1_W, .writefn = tlbiall_write,
383 d4e6df63 Peter Maydell
      .type = ARM_CP_NO_MIGRATE },
384 d929823f Peter Maydell
    { .name = "TLBIMVA", .cp = 15, .crn = 8, .crm = CP_ANY,
385 d4e6df63 Peter Maydell
      .opc1 = CP_ANY, .opc2 = 1, .access = PL1_W, .writefn = tlbimva_write,
386 d4e6df63 Peter Maydell
      .type = ARM_CP_NO_MIGRATE },
387 d929823f Peter Maydell
    { .name = "TLBIASID", .cp = 15, .crn = 8, .crm = CP_ANY,
388 d4e6df63 Peter Maydell
      .opc1 = CP_ANY, .opc2 = 2, .access = PL1_W, .writefn = tlbiasid_write,
389 d4e6df63 Peter Maydell
      .type = ARM_CP_NO_MIGRATE },
390 d929823f Peter Maydell
    { .name = "TLBIMVAA", .cp = 15, .crn = 8, .crm = CP_ANY,
391 d4e6df63 Peter Maydell
      .opc1 = CP_ANY, .opc2 = 3, .access = PL1_W, .writefn = tlbimvaa_write,
392 d4e6df63 Peter Maydell
      .type = ARM_CP_NO_MIGRATE },
393 c4804214 Peter Maydell
    /* Cache maintenance ops; some of this space may be overridden later. */
394 c4804214 Peter Maydell
    { .name = "CACHEMAINT", .cp = 15, .crn = 7, .crm = CP_ANY,
395 c4804214 Peter Maydell
      .opc1 = 0, .opc2 = CP_ANY, .access = PL1_W,
396 c4804214 Peter Maydell
      .type = ARM_CP_NOP | ARM_CP_OVERRIDE },
397 e9aa6c21 Peter Maydell
    REGINFO_SENTINEL
398 e9aa6c21 Peter Maydell
};
399 e9aa6c21 Peter Maydell
400 7d57f408 Peter Maydell
static const ARMCPRegInfo not_v6_cp_reginfo[] = {
401 7d57f408 Peter Maydell
    /* Not all pre-v6 cores implemented this WFI, so this is slightly
402 7d57f408 Peter Maydell
     * over-broad.
403 7d57f408 Peter Maydell
     */
404 7d57f408 Peter Maydell
    { .name = "WFI_v5", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = 2,
405 7d57f408 Peter Maydell
      .access = PL1_W, .type = ARM_CP_WFI },
406 7d57f408 Peter Maydell
    REGINFO_SENTINEL
407 7d57f408 Peter Maydell
};
408 7d57f408 Peter Maydell
409 7d57f408 Peter Maydell
static const ARMCPRegInfo not_v7_cp_reginfo[] = {
410 7d57f408 Peter Maydell
    /* Standard v6 WFI (also used in some pre-v6 cores); not in v7 (which
411 7d57f408 Peter Maydell
     * is UNPREDICTABLE; we choose to NOP as most implementations do).
412 7d57f408 Peter Maydell
     */
413 7d57f408 Peter Maydell
    { .name = "WFI_v6", .cp = 15, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 4,
414 7d57f408 Peter Maydell
      .access = PL1_W, .type = ARM_CP_WFI },
415 34f90529 Peter Maydell
    /* L1 cache lockdown. Not architectural in v6 and earlier but in practice
416 34f90529 Peter Maydell
     * implemented in 926, 946, 1026, 1136, 1176 and 11MPCore. StrongARM and
417 34f90529 Peter Maydell
     * OMAPCP will override this space.
418 34f90529 Peter Maydell
     */
419 34f90529 Peter Maydell
    { .name = "DLOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 0, .opc2 = 0,
420 34f90529 Peter Maydell
      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c9_data),
421 34f90529 Peter Maydell
      .resetvalue = 0 },
422 34f90529 Peter Maydell
    { .name = "ILOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 0, .opc2 = 1,
423 34f90529 Peter Maydell
      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c9_insn),
424 34f90529 Peter Maydell
      .resetvalue = 0 },
425 776d4e5c Peter Maydell
    /* v6 doesn't have the cache ID registers but Linux reads them anyway */
426 776d4e5c Peter Maydell
    { .name = "DUMMY", .cp = 15, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = CP_ANY,
427 d4e6df63 Peter Maydell
      .access = PL1_R, .type = ARM_CP_CONST | ARM_CP_NO_MIGRATE,
428 d4e6df63 Peter Maydell
      .resetvalue = 0 },
429 7d57f408 Peter Maydell
    REGINFO_SENTINEL
430 7d57f408 Peter Maydell
};
431 7d57f408 Peter Maydell
432 c4241c7d Peter Maydell
static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
433 c4241c7d Peter Maydell
                        uint64_t value)
434 2771db27 Peter Maydell
{
435 2771db27 Peter Maydell
    if (env->cp15.c1_coproc != value) {
436 2771db27 Peter Maydell
        env->cp15.c1_coproc = value;
437 2771db27 Peter Maydell
        /* ??? Is this safe when called from within a TB?  */
438 2771db27 Peter Maydell
        tb_flush(env);
439 2771db27 Peter Maydell
    }
440 2771db27 Peter Maydell
}
441 2771db27 Peter Maydell
442 7d57f408 Peter Maydell
static const ARMCPRegInfo v6_cp_reginfo[] = {
443 7d57f408 Peter Maydell
    /* prefetch by MVA in v6, NOP in v7 */
444 7d57f408 Peter Maydell
    { .name = "MVA_prefetch",
445 7d57f408 Peter Maydell
      .cp = 15, .crn = 7, .crm = 13, .opc1 = 0, .opc2 = 1,
446 7d57f408 Peter Maydell
      .access = PL1_W, .type = ARM_CP_NOP },
447 7d57f408 Peter Maydell
    { .name = "ISB", .cp = 15, .crn = 7, .crm = 5, .opc1 = 0, .opc2 = 4,
448 7d57f408 Peter Maydell
      .access = PL0_W, .type = ARM_CP_NOP },
449 091fd17c Peter Maydell
    { .name = "DSB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 4,
450 7d57f408 Peter Maydell
      .access = PL0_W, .type = ARM_CP_NOP },
451 091fd17c Peter Maydell
    { .name = "DMB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 5,
452 7d57f408 Peter Maydell
      .access = PL0_W, .type = ARM_CP_NOP },
453 06d76f31 Peter Maydell
    { .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 2,
454 06d76f31 Peter Maydell
      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c6_insn),
455 06d76f31 Peter Maydell
      .resetvalue = 0, },
456 06d76f31 Peter Maydell
    /* Watchpoint Fault Address Register : should actually only be present
457 06d76f31 Peter Maydell
     * for 1136, 1176, 11MPCore.
458 06d76f31 Peter Maydell
     */
459 06d76f31 Peter Maydell
    { .name = "WFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1,
460 06d76f31 Peter Maydell
      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0, },
461 2771db27 Peter Maydell
    { .name = "CPACR", .cp = 15, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 2,
462 2771db27 Peter Maydell
      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c1_coproc),
463 2771db27 Peter Maydell
      .resetvalue = 0, .writefn = cpacr_write },
464 7d57f408 Peter Maydell
    REGINFO_SENTINEL
465 7d57f408 Peter Maydell
};
466 7d57f408 Peter Maydell
467 fcd25206 Peter Maydell
static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri)
468 200ac0ef Peter Maydell
{
469 fcd25206 Peter Maydell
    /* Perfomance monitor registers user accessibility is controlled
470 fcd25206 Peter Maydell
     * by PMUSERENR.
471 200ac0ef Peter Maydell
     */
472 200ac0ef Peter Maydell
    if (arm_current_pl(env) == 0 && !env->cp15.c9_pmuserenr) {
473 fcd25206 Peter Maydell
        return CP_ACCESS_TRAP;
474 200ac0ef Peter Maydell
    }
475 fcd25206 Peter Maydell
    return CP_ACCESS_OK;
476 200ac0ef Peter Maydell
}
477 200ac0ef Peter Maydell
478 c4241c7d Peter Maydell
static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
479 c4241c7d Peter Maydell
                       uint64_t value)
480 200ac0ef Peter Maydell
{
481 200ac0ef Peter Maydell
    /* only the DP, X, D and E bits are writable */
482 200ac0ef Peter Maydell
    env->cp15.c9_pmcr &= ~0x39;
483 200ac0ef Peter Maydell
    env->cp15.c9_pmcr |= (value & 0x39);
484 200ac0ef Peter Maydell
}
485 200ac0ef Peter Maydell
486 c4241c7d Peter Maydell
static void pmcntenset_write(CPUARMState *env, const ARMCPRegInfo *ri,
487 200ac0ef Peter Maydell
                            uint64_t value)
488 200ac0ef Peter Maydell
{
489 200ac0ef Peter Maydell
    value &= (1 << 31);
490 200ac0ef Peter Maydell
    env->cp15.c9_pmcnten |= value;
491 200ac0ef Peter Maydell
}
492 200ac0ef Peter Maydell
493 c4241c7d Peter Maydell
static void pmcntenclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
494 c4241c7d Peter Maydell
                             uint64_t value)
495 200ac0ef Peter Maydell
{
496 200ac0ef Peter Maydell
    value &= (1 << 31);
497 200ac0ef Peter Maydell
    env->cp15.c9_pmcnten &= ~value;
498 200ac0ef Peter Maydell
}
499 200ac0ef Peter Maydell
500 c4241c7d Peter Maydell
static void pmovsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
501 c4241c7d Peter Maydell
                         uint64_t value)
502 200ac0ef Peter Maydell
{
503 200ac0ef Peter Maydell
    env->cp15.c9_pmovsr &= ~value;
504 200ac0ef Peter Maydell
}
505 200ac0ef Peter Maydell
506 c4241c7d Peter Maydell
static void pmxevtyper_write(CPUARMState *env, const ARMCPRegInfo *ri,
507 c4241c7d Peter Maydell
                             uint64_t value)
508 200ac0ef Peter Maydell
{
509 200ac0ef Peter Maydell
    env->cp15.c9_pmxevtyper = value & 0xff;
510 200ac0ef Peter Maydell
}
511 200ac0ef Peter Maydell
512 c4241c7d Peter Maydell
static void pmuserenr_write(CPUARMState *env, const ARMCPRegInfo *ri,
513 200ac0ef Peter Maydell
                            uint64_t value)
514 200ac0ef Peter Maydell
{
515 200ac0ef Peter Maydell
    env->cp15.c9_pmuserenr = value & 1;
516 200ac0ef Peter Maydell
}
517 200ac0ef Peter Maydell
518 c4241c7d Peter Maydell
static void pmintenset_write(CPUARMState *env, const ARMCPRegInfo *ri,
519 c4241c7d Peter Maydell
                             uint64_t value)
520 200ac0ef Peter Maydell
{
521 200ac0ef Peter Maydell
    /* We have no event counters so only the C bit can be changed */
522 200ac0ef Peter Maydell
    value &= (1 << 31);
523 200ac0ef Peter Maydell
    env->cp15.c9_pminten |= value;
524 200ac0ef Peter Maydell
}
525 200ac0ef Peter Maydell
526 c4241c7d Peter Maydell
static void pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
527 c4241c7d Peter Maydell
                             uint64_t value)
528 200ac0ef Peter Maydell
{
529 200ac0ef Peter Maydell
    value &= (1 << 31);
530 200ac0ef Peter Maydell
    env->cp15.c9_pminten &= ~value;
531 200ac0ef Peter Maydell
}
532 200ac0ef Peter Maydell
533 c4241c7d Peter Maydell
static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
534 c4241c7d Peter Maydell
                       uint64_t value)
535 8641136c Nathan Rossi
{
536 a505d7fe Peter Maydell
    /* Note that even though the AArch64 view of this register has bits
537 a505d7fe Peter Maydell
     * [10:0] all RES0 we can only mask the bottom 5, to comply with the
538 a505d7fe Peter Maydell
     * architectural requirements for bits which are RES0 only in some
539 a505d7fe Peter Maydell
     * contexts. (ARMv8 would permit us to do no masking at all, but ARMv7
540 a505d7fe Peter Maydell
     * requires the bottom five bits to be RAZ/WI because they're UNK/SBZP.)
541 a505d7fe Peter Maydell
     */
542 8641136c Nathan Rossi
    env->cp15.c12_vbar = value & ~0x1Ful;
543 8641136c Nathan Rossi
}
544 8641136c Nathan Rossi
545 c4241c7d Peter Maydell
static uint64_t ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
546 776d4e5c Peter Maydell
{
547 776d4e5c Peter Maydell
    ARMCPU *cpu = arm_env_get_cpu(env);
548 c4241c7d Peter Maydell
    return cpu->ccsidr[env->cp15.c0_cssel];
549 776d4e5c Peter Maydell
}
550 776d4e5c Peter Maydell
551 c4241c7d Peter Maydell
static void csselr_write(CPUARMState *env, const ARMCPRegInfo *ri,
552 c4241c7d Peter Maydell
                         uint64_t value)
553 776d4e5c Peter Maydell
{
554 776d4e5c Peter Maydell
    env->cp15.c0_cssel = value & 0xf;
555 776d4e5c Peter Maydell
}
556 776d4e5c Peter Maydell
557 e9aa6c21 Peter Maydell
static const ARMCPRegInfo v7_cp_reginfo[] = {
558 e9aa6c21 Peter Maydell
    /* DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped
559 e9aa6c21 Peter Maydell
     * debug components
560 e9aa6c21 Peter Maydell
     */
561 e9aa6c21 Peter Maydell
    { .name = "DBGDRAR", .cp = 14, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0,
562 e9aa6c21 Peter Maydell
      .access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 0 },
563 091fd17c Peter Maydell
    { .name = "DBGDSAR", .cp = 14, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
564 e9aa6c21 Peter Maydell
      .access = PL0_R, .type = ARM_CP_CONST, .resetvalue = 0 },
565 7d57f408 Peter Maydell
    /* the old v6 WFI, UNPREDICTABLE in v7 but we choose to NOP */
566 7d57f408 Peter Maydell
    { .name = "NOP", .cp = 15, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 4,
567 7d57f408 Peter Maydell
      .access = PL1_W, .type = ARM_CP_NOP },
568 200ac0ef Peter Maydell
    /* Performance monitors are implementation defined in v7,
569 200ac0ef Peter Maydell
     * but with an ARM recommended set of registers, which we
570 200ac0ef Peter Maydell
     * follow (although we don't actually implement any counters)
571 200ac0ef Peter Maydell
     *
572 200ac0ef Peter Maydell
     * Performance registers fall into three categories:
573 200ac0ef Peter Maydell
     *  (a) always UNDEF in PL0, RW in PL1 (PMINTENSET, PMINTENCLR)
574 200ac0ef Peter Maydell
     *  (b) RO in PL0 (ie UNDEF on write), RW in PL1 (PMUSERENR)
575 200ac0ef Peter Maydell
     *  (c) UNDEF in PL0 if PMUSERENR.EN==0, otherwise accessible (all others)
576 200ac0ef Peter Maydell
     * For the cases controlled by PMUSERENR we must set .access to PL0_RW
577 200ac0ef Peter Maydell
     * or PL0_RO as appropriate and then check PMUSERENR in the helper fn.
578 200ac0ef Peter Maydell
     */
579 200ac0ef Peter Maydell
    { .name = "PMCNTENSET", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 1,
580 200ac0ef Peter Maydell
      .access = PL0_RW, .resetvalue = 0,
581 200ac0ef Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcnten),
582 fcd25206 Peter Maydell
      .writefn = pmcntenset_write,
583 fcd25206 Peter Maydell
      .accessfn = pmreg_access,
584 fcd25206 Peter Maydell
      .raw_writefn = raw_write },
585 200ac0ef Peter Maydell
    { .name = "PMCNTENCLR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 2,
586 200ac0ef Peter Maydell
      .access = PL0_RW, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcnten),
587 fcd25206 Peter Maydell
      .accessfn = pmreg_access,
588 fcd25206 Peter Maydell
      .writefn = pmcntenclr_write,
589 d4e6df63 Peter Maydell
      .type = ARM_CP_NO_MIGRATE },
590 200ac0ef Peter Maydell
    { .name = "PMOVSR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 3,
591 200ac0ef Peter Maydell
      .access = PL0_RW, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
592 fcd25206 Peter Maydell
      .accessfn = pmreg_access,
593 fcd25206 Peter Maydell
      .writefn = pmovsr_write,
594 fcd25206 Peter Maydell
      .raw_writefn = raw_write },
595 fcd25206 Peter Maydell
    /* Unimplemented so WI. */
596 200ac0ef Peter Maydell
    { .name = "PMSWINC", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 4,
597 fcd25206 Peter Maydell
      .access = PL0_W, .accessfn = pmreg_access, .type = ARM_CP_NOP },
598 200ac0ef Peter Maydell
    /* Since we don't implement any events, writing to PMSELR is UNPREDICTABLE.
599 fcd25206 Peter Maydell
     * We choose to RAZ/WI.
600 200ac0ef Peter Maydell
     */
601 200ac0ef Peter Maydell
    { .name = "PMSELR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 5,
602 fcd25206 Peter Maydell
      .access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0,
603 fcd25206 Peter Maydell
      .accessfn = pmreg_access },
604 fcd25206 Peter Maydell
    /* Unimplemented, RAZ/WI. */
605 200ac0ef Peter Maydell
    { .name = "PMCCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 0,
606 fcd25206 Peter Maydell
      .access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0,
607 fcd25206 Peter Maydell
      .accessfn = pmreg_access },
608 200ac0ef Peter Maydell
    { .name = "PMXEVTYPER", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 1,
609 200ac0ef Peter Maydell
      .access = PL0_RW,
610 200ac0ef Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c9_pmxevtyper),
611 fcd25206 Peter Maydell
      .accessfn = pmreg_access, .writefn = pmxevtyper_write,
612 fcd25206 Peter Maydell
      .raw_writefn = raw_write },
613 fcd25206 Peter Maydell
    /* Unimplemented, RAZ/WI. */
614 200ac0ef Peter Maydell
    { .name = "PMXEVCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 2,
615 fcd25206 Peter Maydell
      .access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0,
616 fcd25206 Peter Maydell
      .accessfn = pmreg_access },
617 200ac0ef Peter Maydell
    { .name = "PMUSERENR", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 0,
618 200ac0ef Peter Maydell
      .access = PL0_R | PL1_RW,
619 200ac0ef Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c9_pmuserenr),
620 200ac0ef Peter Maydell
      .resetvalue = 0,
621 d4e6df63 Peter Maydell
      .writefn = pmuserenr_write, .raw_writefn = raw_write },
622 200ac0ef Peter Maydell
    { .name = "PMINTENSET", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 1,
623 200ac0ef Peter Maydell
      .access = PL1_RW,
624 200ac0ef Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
625 200ac0ef Peter Maydell
      .resetvalue = 0,
626 d4e6df63 Peter Maydell
      .writefn = pmintenset_write, .raw_writefn = raw_write },
627 200ac0ef Peter Maydell
    { .name = "PMINTENCLR", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 2,
628 d4e6df63 Peter Maydell
      .access = PL1_RW, .type = ARM_CP_NO_MIGRATE,
629 200ac0ef Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
630 d4e6df63 Peter Maydell
      .resetvalue = 0, .writefn = pmintenclr_write, },
631 a505d7fe Peter Maydell
    { .name = "VBAR", .state = ARM_CP_STATE_BOTH,
632 a505d7fe Peter Maydell
      .opc0 = 3, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0,
633 8641136c Nathan Rossi
      .access = PL1_RW, .writefn = vbar_write,
634 8641136c Nathan Rossi
      .fieldoffset = offsetof(CPUARMState, cp15.c12_vbar),
635 8641136c Nathan Rossi
      .resetvalue = 0 },
636 2771db27 Peter Maydell
    { .name = "SCR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
637 2771db27 Peter Maydell
      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c1_scr),
638 2771db27 Peter Maydell
      .resetvalue = 0, },
639 7da845b0 Peter Maydell
    { .name = "CCSIDR", .state = ARM_CP_STATE_BOTH,
640 7da845b0 Peter Maydell
      .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 0,
641 d4e6df63 Peter Maydell
      .access = PL1_R, .readfn = ccsidr_read, .type = ARM_CP_NO_MIGRATE },
642 7da845b0 Peter Maydell
    { .name = "CSSELR", .state = ARM_CP_STATE_BOTH,
643 7da845b0 Peter Maydell
      .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 2, .opc2 = 0,
644 776d4e5c Peter Maydell
      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c0_cssel),
645 776d4e5c Peter Maydell
      .writefn = csselr_write, .resetvalue = 0 },
646 776d4e5c Peter Maydell
    /* Auxiliary ID register: this actually has an IMPDEF value but for now
647 776d4e5c Peter Maydell
     * just RAZ for all cores:
648 776d4e5c Peter Maydell
     */
649 776d4e5c Peter Maydell
    { .name = "AIDR", .cp = 15, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 7,
650 776d4e5c Peter Maydell
      .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
651 b0fe2427 Peter Maydell
    /* MAIR can just read-as-written because we don't implement caches
652 b0fe2427 Peter Maydell
     * and so don't need to care about memory attributes.
653 b0fe2427 Peter Maydell
     */
654 b0fe2427 Peter Maydell
    { .name = "MAIR_EL1", .state = ARM_CP_STATE_AA64,
655 b0fe2427 Peter Maydell
      .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 0,
656 b0fe2427 Peter Maydell
      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el1),
657 b0fe2427 Peter Maydell
      .resetvalue = 0 },
658 b0fe2427 Peter Maydell
    /* For non-long-descriptor page tables these are PRRR and NMRR;
659 b0fe2427 Peter Maydell
     * regardless they still act as reads-as-written for QEMU.
660 b0fe2427 Peter Maydell
     * The override is necessary because of the overly-broad TLB_LOCKDOWN
661 b0fe2427 Peter Maydell
     * definition.
662 b0fe2427 Peter Maydell
     */
663 b0fe2427 Peter Maydell
    { .name = "MAIR0", .state = ARM_CP_STATE_AA32, .type = ARM_CP_OVERRIDE,
664 b0fe2427 Peter Maydell
      .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 0, .access = PL1_RW,
665 b0fe2427 Peter Maydell
      .fieldoffset = offsetoflow32(CPUARMState, cp15.mair_el1),
666 b0fe2427 Peter Maydell
      .resetfn = arm_cp_reset_ignore },
667 b0fe2427 Peter Maydell
    { .name = "MAIR1", .state = ARM_CP_STATE_AA32, .type = ARM_CP_OVERRIDE,
668 b0fe2427 Peter Maydell
      .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 1, .access = PL1_RW,
669 b0fe2427 Peter Maydell
      .fieldoffset = offsetofhigh32(CPUARMState, cp15.mair_el1),
670 b0fe2427 Peter Maydell
      .resetfn = arm_cp_reset_ignore },
671 e9aa6c21 Peter Maydell
    REGINFO_SENTINEL
672 e9aa6c21 Peter Maydell
};
673 e9aa6c21 Peter Maydell
674 c4241c7d Peter Maydell
static void teecr_write(CPUARMState *env, const ARMCPRegInfo *ri,
675 c4241c7d Peter Maydell
                        uint64_t value)
676 c326b979 Peter Maydell
{
677 c326b979 Peter Maydell
    value &= 1;
678 c326b979 Peter Maydell
    env->teecr = value;
679 c326b979 Peter Maydell
}
680 c326b979 Peter Maydell
681 c4241c7d Peter Maydell
static CPAccessResult teehbr_access(CPUARMState *env, const ARMCPRegInfo *ri)
682 c326b979 Peter Maydell
{
683 c326b979 Peter Maydell
    if (arm_current_pl(env) == 0 && (env->teecr & 1)) {
684 92611c00 Peter Maydell
        return CP_ACCESS_TRAP;
685 c326b979 Peter Maydell
    }
686 92611c00 Peter Maydell
    return CP_ACCESS_OK;
687 c326b979 Peter Maydell
}
688 c326b979 Peter Maydell
689 c326b979 Peter Maydell
static const ARMCPRegInfo t2ee_cp_reginfo[] = {
690 c326b979 Peter Maydell
    { .name = "TEECR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 6, .opc2 = 0,
691 c326b979 Peter Maydell
      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, teecr),
692 c326b979 Peter Maydell
      .resetvalue = 0,
693 c326b979 Peter Maydell
      .writefn = teecr_write },
694 c326b979 Peter Maydell
    { .name = "TEEHBR", .cp = 14, .crn = 1, .crm = 0, .opc1 = 6, .opc2 = 0,
695 c326b979 Peter Maydell
      .access = PL0_RW, .fieldoffset = offsetof(CPUARMState, teehbr),
696 92611c00 Peter Maydell
      .accessfn = teehbr_access, .resetvalue = 0 },
697 c326b979 Peter Maydell
    REGINFO_SENTINEL
698 c326b979 Peter Maydell
};
699 c326b979 Peter Maydell
700 4d31c596 Peter Maydell
static const ARMCPRegInfo v6k_cp_reginfo[] = {
701 e4fe830b Peter Maydell
    { .name = "TPIDR_EL0", .state = ARM_CP_STATE_AA64,
702 e4fe830b Peter Maydell
      .opc0 = 3, .opc1 = 3, .opc2 = 2, .crn = 13, .crm = 0,
703 e4fe830b Peter Maydell
      .access = PL0_RW,
704 e4fe830b Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el0), .resetvalue = 0 },
705 4d31c596 Peter Maydell
    { .name = "TPIDRURW", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 2,
706 4d31c596 Peter Maydell
      .access = PL0_RW,
707 e4fe830b Peter Maydell
      .fieldoffset = offsetoflow32(CPUARMState, cp15.tpidr_el0),
708 e4fe830b Peter Maydell
      .resetfn = arm_cp_reset_ignore },
709 e4fe830b Peter Maydell
    { .name = "TPIDRRO_EL0", .state = ARM_CP_STATE_AA64,
710 e4fe830b Peter Maydell
      .opc0 = 3, .opc1 = 3, .opc2 = 3, .crn = 13, .crm = 0,
711 e4fe830b Peter Maydell
      .access = PL0_R|PL1_W,
712 e4fe830b Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.tpidrro_el0), .resetvalue = 0 },
713 4d31c596 Peter Maydell
    { .name = "TPIDRURO", .cp = 15, .crn = 13, .crm = 0, .opc1 = 0, .opc2 = 3,
714 4d31c596 Peter Maydell
      .access = PL0_R|PL1_W,
715 e4fe830b Peter Maydell
      .fieldoffset = offsetoflow32(CPUARMState, cp15.tpidrro_el0),
716 e4fe830b Peter Maydell
      .resetfn = arm_cp_reset_ignore },
717 e4fe830b Peter Maydell
    { .name = "TPIDR_EL1", .state = ARM_CP_STATE_BOTH,
718 e4fe830b Peter Maydell
      .opc0 = 3, .opc1 = 0, .opc2 = 4, .crn = 13, .crm = 0,
719 4d31c596 Peter Maydell
      .access = PL1_RW,
720 e4fe830b Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el1), .resetvalue = 0 },
721 4d31c596 Peter Maydell
    REGINFO_SENTINEL
722 4d31c596 Peter Maydell
};
723 4d31c596 Peter Maydell
724 55d284af Peter Maydell
#ifndef CONFIG_USER_ONLY
725 55d284af Peter Maydell
726 00108f2d Peter Maydell
static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInfo *ri)
727 00108f2d Peter Maydell
{
728 00108f2d Peter Maydell
    /* CNTFRQ: not visible from PL0 if both PL0PCTEN and PL0VCTEN are zero */
729 00108f2d Peter Maydell
    if (arm_current_pl(env) == 0 && !extract32(env->cp15.c14_cntkctl, 0, 2)) {
730 00108f2d Peter Maydell
        return CP_ACCESS_TRAP;
731 00108f2d Peter Maydell
    }
732 00108f2d Peter Maydell
    return CP_ACCESS_OK;
733 00108f2d Peter Maydell
}
734 00108f2d Peter Maydell
735 00108f2d Peter Maydell
static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx)
736 00108f2d Peter Maydell
{
737 00108f2d Peter Maydell
    /* CNT[PV]CT: not visible from PL0 if ELO[PV]CTEN is zero */
738 00108f2d Peter Maydell
    if (arm_current_pl(env) == 0 &&
739 00108f2d Peter Maydell
        !extract32(env->cp15.c14_cntkctl, timeridx, 1)) {
740 00108f2d Peter Maydell
        return CP_ACCESS_TRAP;
741 00108f2d Peter Maydell
    }
742 00108f2d Peter Maydell
    return CP_ACCESS_OK;
743 00108f2d Peter Maydell
}
744 00108f2d Peter Maydell
745 00108f2d Peter Maydell
static CPAccessResult gt_timer_access(CPUARMState *env, int timeridx)
746 00108f2d Peter Maydell
{
747 00108f2d Peter Maydell
    /* CNT[PV]_CVAL, CNT[PV]_CTL, CNT[PV]_TVAL: not visible from PL0 if
748 00108f2d Peter Maydell
     * EL0[PV]TEN is zero.
749 00108f2d Peter Maydell
     */
750 00108f2d Peter Maydell
    if (arm_current_pl(env) == 0 &&
751 00108f2d Peter Maydell
        !extract32(env->cp15.c14_cntkctl, 9 - timeridx, 1)) {
752 00108f2d Peter Maydell
        return CP_ACCESS_TRAP;
753 00108f2d Peter Maydell
    }
754 00108f2d Peter Maydell
    return CP_ACCESS_OK;
755 00108f2d Peter Maydell
}
756 00108f2d Peter Maydell
757 00108f2d Peter Maydell
static CPAccessResult gt_pct_access(CPUARMState *env,
758 00108f2d Peter Maydell
                                         const ARMCPRegInfo *ri)
759 00108f2d Peter Maydell
{
760 00108f2d Peter Maydell
    return gt_counter_access(env, GTIMER_PHYS);
761 00108f2d Peter Maydell
}
762 00108f2d Peter Maydell
763 00108f2d Peter Maydell
static CPAccessResult gt_vct_access(CPUARMState *env,
764 00108f2d Peter Maydell
                                         const ARMCPRegInfo *ri)
765 00108f2d Peter Maydell
{
766 00108f2d Peter Maydell
    return gt_counter_access(env, GTIMER_VIRT);
767 00108f2d Peter Maydell
}
768 00108f2d Peter Maydell
769 00108f2d Peter Maydell
static CPAccessResult gt_ptimer_access(CPUARMState *env, const ARMCPRegInfo *ri)
770 00108f2d Peter Maydell
{
771 00108f2d Peter Maydell
    return gt_timer_access(env, GTIMER_PHYS);
772 00108f2d Peter Maydell
}
773 00108f2d Peter Maydell
774 00108f2d Peter Maydell
static CPAccessResult gt_vtimer_access(CPUARMState *env, const ARMCPRegInfo *ri)
775 00108f2d Peter Maydell
{
776 00108f2d Peter Maydell
    return gt_timer_access(env, GTIMER_VIRT);
777 00108f2d Peter Maydell
}
778 00108f2d Peter Maydell
779 55d284af Peter Maydell
static uint64_t gt_get_countervalue(CPUARMState *env)
780 55d284af Peter Maydell
{
781 bc72ad67 Alex Bligh
    return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE;
782 55d284af Peter Maydell
}
783 55d284af Peter Maydell
784 55d284af Peter Maydell
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
785 55d284af Peter Maydell
{
786 55d284af Peter Maydell
    ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
787 55d284af Peter Maydell
788 55d284af Peter Maydell
    if (gt->ctl & 1) {
789 55d284af Peter Maydell
        /* Timer enabled: calculate and set current ISTATUS, irq, and
790 55d284af Peter Maydell
         * reset timer to when ISTATUS next has to change
791 55d284af Peter Maydell
         */
792 55d284af Peter Maydell
        uint64_t count = gt_get_countervalue(&cpu->env);
793 55d284af Peter Maydell
        /* Note that this must be unsigned 64 bit arithmetic: */
794 55d284af Peter Maydell
        int istatus = count >= gt->cval;
795 55d284af Peter Maydell
        uint64_t nexttick;
796 55d284af Peter Maydell
797 55d284af Peter Maydell
        gt->ctl = deposit32(gt->ctl, 2, 1, istatus);
798 55d284af Peter Maydell
        qemu_set_irq(cpu->gt_timer_outputs[timeridx],
799 55d284af Peter Maydell
                     (istatus && !(gt->ctl & 2)));
800 55d284af Peter Maydell
        if (istatus) {
801 55d284af Peter Maydell
            /* Next transition is when count rolls back over to zero */
802 55d284af Peter Maydell
            nexttick = UINT64_MAX;
803 55d284af Peter Maydell
        } else {
804 55d284af Peter Maydell
            /* Next transition is when we hit cval */
805 55d284af Peter Maydell
            nexttick = gt->cval;
806 55d284af Peter Maydell
        }
807 55d284af Peter Maydell
        /* Note that the desired next expiry time might be beyond the
808 55d284af Peter Maydell
         * signed-64-bit range of a QEMUTimer -- in this case we just
809 55d284af Peter Maydell
         * set the timer for as far in the future as possible. When the
810 55d284af Peter Maydell
         * timer expires we will reset the timer for any remaining period.
811 55d284af Peter Maydell
         */
812 55d284af Peter Maydell
        if (nexttick > INT64_MAX / GTIMER_SCALE) {
813 55d284af Peter Maydell
            nexttick = INT64_MAX / GTIMER_SCALE;
814 55d284af Peter Maydell
        }
815 bc72ad67 Alex Bligh
        timer_mod(cpu->gt_timer[timeridx], nexttick);
816 55d284af Peter Maydell
    } else {
817 55d284af Peter Maydell
        /* Timer disabled: ISTATUS and timer output always clear */
818 55d284af Peter Maydell
        gt->ctl &= ~4;
819 55d284af Peter Maydell
        qemu_set_irq(cpu->gt_timer_outputs[timeridx], 0);
820 bc72ad67 Alex Bligh
        timer_del(cpu->gt_timer[timeridx]);
821 55d284af Peter Maydell
    }
822 55d284af Peter Maydell
}
823 55d284af Peter Maydell
824 55d284af Peter Maydell
static void gt_cnt_reset(CPUARMState *env, const ARMCPRegInfo *ri)
825 55d284af Peter Maydell
{
826 55d284af Peter Maydell
    ARMCPU *cpu = arm_env_get_cpu(env);
827 55d284af Peter Maydell
    int timeridx = ri->opc1 & 1;
828 55d284af Peter Maydell
829 bc72ad67 Alex Bligh
    timer_del(cpu->gt_timer[timeridx]);
830 55d284af Peter Maydell
}
831 55d284af Peter Maydell
832 c4241c7d Peter Maydell
static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
833 55d284af Peter Maydell
{
834 c4241c7d Peter Maydell
    return gt_get_countervalue(env);
835 55d284af Peter Maydell
}
836 55d284af Peter Maydell
837 c4241c7d Peter Maydell
static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
838 c4241c7d Peter Maydell
                          uint64_t value)
839 55d284af Peter Maydell
{
840 55d284af Peter Maydell
    int timeridx = ri->opc1 & 1;
841 55d284af Peter Maydell
842 55d284af Peter Maydell
    env->cp15.c14_timer[timeridx].cval = value;
843 55d284af Peter Maydell
    gt_recalc_timer(arm_env_get_cpu(env), timeridx);
844 55d284af Peter Maydell
}
845 c4241c7d Peter Maydell
846 c4241c7d Peter Maydell
static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
847 55d284af Peter Maydell
{
848 55d284af Peter Maydell
    int timeridx = ri->crm & 1;
849 55d284af Peter Maydell
850 c4241c7d Peter Maydell
    return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
851 c4241c7d Peter Maydell
                      gt_get_countervalue(env));
852 55d284af Peter Maydell
}
853 55d284af Peter Maydell
854 c4241c7d Peter Maydell
static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
855 c4241c7d Peter Maydell
                          uint64_t value)
856 55d284af Peter Maydell
{
857 55d284af Peter Maydell
    int timeridx = ri->crm & 1;
858 55d284af Peter Maydell
859 55d284af Peter Maydell
    env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) +
860 55d284af Peter Maydell
        + sextract64(value, 0, 32);
861 55d284af Peter Maydell
    gt_recalc_timer(arm_env_get_cpu(env), timeridx);
862 55d284af Peter Maydell
}
863 55d284af Peter Maydell
864 c4241c7d Peter Maydell
static void gt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
865 c4241c7d Peter Maydell
                         uint64_t value)
866 55d284af Peter Maydell
{
867 55d284af Peter Maydell
    ARMCPU *cpu = arm_env_get_cpu(env);
868 55d284af Peter Maydell
    int timeridx = ri->crm & 1;
869 55d284af Peter Maydell
    uint32_t oldval = env->cp15.c14_timer[timeridx].ctl;
870 55d284af Peter Maydell
871 55d284af Peter Maydell
    env->cp15.c14_timer[timeridx].ctl = value & 3;
872 55d284af Peter Maydell
    if ((oldval ^ value) & 1) {
873 55d284af Peter Maydell
        /* Enable toggled */
874 55d284af Peter Maydell
        gt_recalc_timer(cpu, timeridx);
875 55d284af Peter Maydell
    } else if ((oldval & value) & 2) {
876 55d284af Peter Maydell
        /* IMASK toggled: don't need to recalculate,
877 55d284af Peter Maydell
         * just set the interrupt line based on ISTATUS
878 55d284af Peter Maydell
         */
879 55d284af Peter Maydell
        qemu_set_irq(cpu->gt_timer_outputs[timeridx],
880 55d284af Peter Maydell
                     (oldval & 4) && (value & 2));
881 55d284af Peter Maydell
    }
882 55d284af Peter Maydell
}
883 55d284af Peter Maydell
884 55d284af Peter Maydell
void arm_gt_ptimer_cb(void *opaque)
885 55d284af Peter Maydell
{
886 55d284af Peter Maydell
    ARMCPU *cpu = opaque;
887 55d284af Peter Maydell
888 55d284af Peter Maydell
    gt_recalc_timer(cpu, GTIMER_PHYS);
889 55d284af Peter Maydell
}
890 55d284af Peter Maydell
891 55d284af Peter Maydell
void arm_gt_vtimer_cb(void *opaque)
892 55d284af Peter Maydell
{
893 55d284af Peter Maydell
    ARMCPU *cpu = opaque;
894 55d284af Peter Maydell
895 55d284af Peter Maydell
    gt_recalc_timer(cpu, GTIMER_VIRT);
896 55d284af Peter Maydell
}
897 55d284af Peter Maydell
898 55d284af Peter Maydell
static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
899 55d284af Peter Maydell
    /* Note that CNTFRQ is purely reads-as-written for the benefit
900 55d284af Peter Maydell
     * of software; writing it doesn't actually change the timer frequency.
901 55d284af Peter Maydell
     * Our reset value matches the fixed frequency we implement the timer at.
902 55d284af Peter Maydell
     */
903 55d284af Peter Maydell
    { .name = "CNTFRQ", .cp = 15, .crn = 14, .crm = 0, .opc1 = 0, .opc2 = 0,
904 a7adc4b7 Peter Maydell
      .type = ARM_CP_NO_MIGRATE,
905 a7adc4b7 Peter Maydell
      .access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access,
906 a7adc4b7 Peter Maydell
      .fieldoffset = offsetoflow32(CPUARMState, cp15.c14_cntfrq),
907 a7adc4b7 Peter Maydell
      .resetfn = arm_cp_reset_ignore,
908 a7adc4b7 Peter Maydell
    },
909 a7adc4b7 Peter Maydell
    { .name = "CNTFRQ_EL0", .state = ARM_CP_STATE_AA64,
910 a7adc4b7 Peter Maydell
      .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0,
911 a7adc4b7 Peter Maydell
      .access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access,
912 55d284af Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq),
913 55d284af Peter Maydell
      .resetvalue = (1000 * 1000 * 1000) / GTIMER_SCALE,
914 55d284af Peter Maydell
    },
915 55d284af Peter Maydell
    /* overall control: mostly access permissions */
916 a7adc4b7 Peter Maydell
    { .name = "CNTKCTL", .state = ARM_CP_STATE_BOTH,
917 a7adc4b7 Peter Maydell
      .opc0 = 3, .opc1 = 0, .crn = 14, .crm = 1, .opc2 = 0,
918 55d284af Peter Maydell
      .access = PL1_RW,
919 55d284af Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c14_cntkctl),
920 55d284af Peter Maydell
      .resetvalue = 0,
921 55d284af Peter Maydell
    },
922 55d284af Peter Maydell
    /* per-timer control */
923 55d284af Peter Maydell
    { .name = "CNTP_CTL", .cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 1,
924 a7adc4b7 Peter Maydell
      .type = ARM_CP_IO | ARM_CP_NO_MIGRATE, .access = PL1_RW | PL0_R,
925 a7adc4b7 Peter Maydell
      .accessfn = gt_ptimer_access,
926 a7adc4b7 Peter Maydell
      .fieldoffset = offsetoflow32(CPUARMState,
927 a7adc4b7 Peter Maydell
                                   cp15.c14_timer[GTIMER_PHYS].ctl),
928 a7adc4b7 Peter Maydell
      .resetfn = arm_cp_reset_ignore,
929 a7adc4b7 Peter Maydell
      .writefn = gt_ctl_write, .raw_writefn = raw_write,
930 a7adc4b7 Peter Maydell
    },
931 a7adc4b7 Peter Maydell
    { .name = "CNTP_CTL_EL0", .state = ARM_CP_STATE_AA64,
932 a7adc4b7 Peter Maydell
      .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 2, .opc2 = 1,
933 55d284af Peter Maydell
      .type = ARM_CP_IO, .access = PL1_RW | PL0_R,
934 a7adc4b7 Peter Maydell
      .accessfn = gt_ptimer_access,
935 55d284af Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
936 55d284af Peter Maydell
      .resetvalue = 0,
937 00108f2d Peter Maydell
      .writefn = gt_ctl_write, .raw_writefn = raw_write,
938 55d284af Peter Maydell
    },
939 55d284af Peter Maydell
    { .name = "CNTV_CTL", .cp = 15, .crn = 14, .crm = 3, .opc1 = 0, .opc2 = 1,
940 a7adc4b7 Peter Maydell
      .type = ARM_CP_IO | ARM_CP_NO_MIGRATE, .access = PL1_RW | PL0_R,
941 a7adc4b7 Peter Maydell
      .accessfn = gt_vtimer_access,
942 a7adc4b7 Peter Maydell
      .fieldoffset = offsetoflow32(CPUARMState,
943 a7adc4b7 Peter Maydell
                                   cp15.c14_timer[GTIMER_VIRT].ctl),
944 a7adc4b7 Peter Maydell
      .resetfn = arm_cp_reset_ignore,
945 a7adc4b7 Peter Maydell
      .writefn = gt_ctl_write, .raw_writefn = raw_write,
946 a7adc4b7 Peter Maydell
    },
947 a7adc4b7 Peter Maydell
    { .name = "CNTV_CTL_EL0", .state = ARM_CP_STATE_AA64,
948 a7adc4b7 Peter Maydell
      .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 1,
949 55d284af Peter Maydell
      .type = ARM_CP_IO, .access = PL1_RW | PL0_R,
950 a7adc4b7 Peter Maydell
      .accessfn = gt_vtimer_access,
951 55d284af Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
952 55d284af Peter Maydell
      .resetvalue = 0,
953 00108f2d Peter Maydell
      .writefn = gt_ctl_write, .raw_writefn = raw_write,
954 55d284af Peter Maydell
    },
955 55d284af Peter Maydell
    /* TimerValue views: a 32 bit downcounting view of the underlying state */
956 55d284af Peter Maydell
    { .name = "CNTP_TVAL", .cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 0,
957 55d284af Peter Maydell
      .type = ARM_CP_NO_MIGRATE | ARM_CP_IO, .access = PL1_RW | PL0_R,
958 00108f2d Peter Maydell
      .accessfn = gt_ptimer_access,
959 55d284af Peter Maydell
      .readfn = gt_tval_read, .writefn = gt_tval_write,
960 55d284af Peter Maydell
    },
961 a7adc4b7 Peter Maydell
    { .name = "CNTP_TVAL_EL0", .state = ARM_CP_STATE_AA64,
962 a7adc4b7 Peter Maydell
      .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 2, .opc2 = 0,
963 a7adc4b7 Peter Maydell
      .type = ARM_CP_NO_MIGRATE | ARM_CP_IO, .access = PL1_RW | PL0_R,
964 a7adc4b7 Peter Maydell
      .readfn = gt_tval_read, .writefn = gt_tval_write,
965 a7adc4b7 Peter Maydell
    },
966 55d284af Peter Maydell
    { .name = "CNTV_TVAL", .cp = 15, .crn = 14, .crm = 3, .opc1 = 0, .opc2 = 0,
967 55d284af Peter Maydell
      .type = ARM_CP_NO_MIGRATE | ARM_CP_IO, .access = PL1_RW | PL0_R,
968 00108f2d Peter Maydell
      .accessfn = gt_vtimer_access,
969 55d284af Peter Maydell
      .readfn = gt_tval_read, .writefn = gt_tval_write,
970 55d284af Peter Maydell
    },
971 a7adc4b7 Peter Maydell
    { .name = "CNTV_TVAL_EL0", .state = ARM_CP_STATE_AA64,
972 a7adc4b7 Peter Maydell
      .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 0,
973 a7adc4b7 Peter Maydell
      .type = ARM_CP_NO_MIGRATE | ARM_CP_IO, .access = PL1_RW | PL0_R,
974 a7adc4b7 Peter Maydell
      .readfn = gt_tval_read, .writefn = gt_tval_write,
975 a7adc4b7 Peter Maydell
    },
976 55d284af Peter Maydell
    /* The counter itself */
977 55d284af Peter Maydell
    { .name = "CNTPCT", .cp = 15, .crm = 14, .opc1 = 0,
978 55d284af Peter Maydell
      .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE | ARM_CP_IO,
979 00108f2d Peter Maydell
      .accessfn = gt_pct_access,
980 a7adc4b7 Peter Maydell
      .readfn = gt_cnt_read, .resetfn = arm_cp_reset_ignore,
981 a7adc4b7 Peter Maydell
    },
982 a7adc4b7 Peter Maydell
    { .name = "CNTPCT_EL0", .state = ARM_CP_STATE_AA64,
983 a7adc4b7 Peter Maydell
      .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 1,
984 a7adc4b7 Peter Maydell
      .access = PL0_R, .type = ARM_CP_NO_MIGRATE | ARM_CP_IO,
985 a7adc4b7 Peter Maydell
      .accessfn = gt_pct_access,
986 55d284af Peter Maydell
      .readfn = gt_cnt_read, .resetfn = gt_cnt_reset,
987 55d284af Peter Maydell
    },
988 55d284af Peter Maydell
    { .name = "CNTVCT", .cp = 15, .crm = 14, .opc1 = 1,
989 55d284af Peter Maydell
      .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE | ARM_CP_IO,
990 00108f2d Peter Maydell
      .accessfn = gt_vct_access,
991 a7adc4b7 Peter Maydell
      .readfn = gt_cnt_read, .resetfn = arm_cp_reset_ignore,
992 a7adc4b7 Peter Maydell
    },
993 a7adc4b7 Peter Maydell
    { .name = "CNTVCT_EL0", .state = ARM_CP_STATE_AA64,
994 a7adc4b7 Peter Maydell
      .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 2,
995 a7adc4b7 Peter Maydell
      .access = PL0_R, .type = ARM_CP_NO_MIGRATE | ARM_CP_IO,
996 a7adc4b7 Peter Maydell
      .accessfn = gt_vct_access,
997 55d284af Peter Maydell
      .readfn = gt_cnt_read, .resetfn = gt_cnt_reset,
998 55d284af Peter Maydell
    },
999 55d284af Peter Maydell
    /* Comparison value, indicating when the timer goes off */
1000 55d284af Peter Maydell
    { .name = "CNTP_CVAL", .cp = 15, .crm = 14, .opc1 = 2,
1001 55d284af Peter Maydell
      .access = PL1_RW | PL0_R,
1002 a7adc4b7 Peter Maydell
      .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_NO_MIGRATE,
1003 55d284af Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
1004 a7adc4b7 Peter Maydell
      .accessfn = gt_ptimer_access, .resetfn = arm_cp_reset_ignore,
1005 a7adc4b7 Peter Maydell
      .writefn = gt_cval_write, .raw_writefn = raw_write,
1006 a7adc4b7 Peter Maydell
    },
1007 a7adc4b7 Peter Maydell
    { .name = "CNTP_CVAL_EL0", .state = ARM_CP_STATE_AA64,
1008 a7adc4b7 Peter Maydell
      .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 2, .opc2 = 2,
1009 a7adc4b7 Peter Maydell
      .access = PL1_RW | PL0_R,
1010 a7adc4b7 Peter Maydell
      .type = ARM_CP_IO,
1011 a7adc4b7 Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
1012 a7adc4b7 Peter Maydell
      .resetvalue = 0, .accessfn = gt_vtimer_access,
1013 00108f2d Peter Maydell
      .writefn = gt_cval_write, .raw_writefn = raw_write,
1014 55d284af Peter Maydell
    },
1015 55d284af Peter Maydell
    { .name = "CNTV_CVAL", .cp = 15, .crm = 14, .opc1 = 3,
1016 55d284af Peter Maydell
      .access = PL1_RW | PL0_R,
1017 a7adc4b7 Peter Maydell
      .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_NO_MIGRATE,
1018 55d284af Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
1019 a7adc4b7 Peter Maydell
      .accessfn = gt_vtimer_access, .resetfn = arm_cp_reset_ignore,
1020 a7adc4b7 Peter Maydell
      .writefn = gt_cval_write, .raw_writefn = raw_write,
1021 a7adc4b7 Peter Maydell
    },
1022 a7adc4b7 Peter Maydell
    { .name = "CNTV_CVAL_EL0", .state = ARM_CP_STATE_AA64,
1023 a7adc4b7 Peter Maydell
      .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 2,
1024 a7adc4b7 Peter Maydell
      .access = PL1_RW | PL0_R,
1025 a7adc4b7 Peter Maydell
      .type = ARM_CP_IO,
1026 a7adc4b7 Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
1027 a7adc4b7 Peter Maydell
      .resetvalue = 0, .accessfn = gt_vtimer_access,
1028 00108f2d Peter Maydell
      .writefn = gt_cval_write, .raw_writefn = raw_write,
1029 55d284af Peter Maydell
    },
1030 55d284af Peter Maydell
    REGINFO_SENTINEL
1031 55d284af Peter Maydell
};
1032 55d284af Peter Maydell
1033 55d284af Peter Maydell
#else
1034 55d284af Peter Maydell
/* In user-mode none of the generic timer registers are accessible,
1035 bc72ad67 Alex Bligh
 * and their implementation depends on QEMU_CLOCK_VIRTUAL and qdev gpio outputs,
1036 55d284af Peter Maydell
 * so instead just don't register any of them.
1037 55d284af Peter Maydell
 */
1038 6cc7a3ae Peter Maydell
static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
1039 6cc7a3ae Peter Maydell
    REGINFO_SENTINEL
1040 6cc7a3ae Peter Maydell
};
1041 6cc7a3ae Peter Maydell
1042 55d284af Peter Maydell
#endif
1043 55d284af Peter Maydell
1044 c4241c7d Peter Maydell
static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
1045 4a501606 Peter Maydell
{
1046 891a2fe7 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_LPAE)) {
1047 891a2fe7 Peter Maydell
        env->cp15.c7_par = value;
1048 891a2fe7 Peter Maydell
    } else if (arm_feature(env, ARM_FEATURE_V7)) {
1049 4a501606 Peter Maydell
        env->cp15.c7_par = value & 0xfffff6ff;
1050 4a501606 Peter Maydell
    } else {
1051 4a501606 Peter Maydell
        env->cp15.c7_par = value & 0xfffff1ff;
1052 4a501606 Peter Maydell
    }
1053 4a501606 Peter Maydell
}
1054 4a501606 Peter Maydell
1055 4a501606 Peter Maydell
#ifndef CONFIG_USER_ONLY
1056 4a501606 Peter Maydell
/* get_phys_addr() isn't present for user-mode-only targets */
1057 702a9357 Peter Maydell
1058 702a9357 Peter Maydell
/* Return true if extended addresses are enabled, ie this is an
1059 702a9357 Peter Maydell
 * LPAE implementation and we are using the long-descriptor translation
1060 702a9357 Peter Maydell
 * table format because the TTBCR EAE bit is set.
1061 702a9357 Peter Maydell
 */
1062 702a9357 Peter Maydell
static inline bool extended_addresses_enabled(CPUARMState *env)
1063 702a9357 Peter Maydell
{
1064 702a9357 Peter Maydell
    return arm_feature(env, ARM_FEATURE_LPAE)
1065 78dbbbe4 Peter Maydell
        && (env->cp15.c2_control & (1U << 31));
1066 702a9357 Peter Maydell
}
1067 702a9357 Peter Maydell
1068 92611c00 Peter Maydell
static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri)
1069 92611c00 Peter Maydell
{
1070 92611c00 Peter Maydell
    if (ri->opc2 & 4) {
1071 92611c00 Peter Maydell
        /* Other states are only available with TrustZone; in
1072 92611c00 Peter Maydell
         * a non-TZ implementation these registers don't exist
1073 92611c00 Peter Maydell
         * at all, which is an Uncategorized trap. This underdecoding
1074 92611c00 Peter Maydell
         * is safe because the reginfo is NO_MIGRATE.
1075 92611c00 Peter Maydell
         */
1076 92611c00 Peter Maydell
        return CP_ACCESS_TRAP_UNCATEGORIZED;
1077 92611c00 Peter Maydell
    }
1078 92611c00 Peter Maydell
    return CP_ACCESS_OK;
1079 92611c00 Peter Maydell
}
1080 92611c00 Peter Maydell
1081 c4241c7d Peter Maydell
static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
1082 4a501606 Peter Maydell
{
1083 a8170e5e Avi Kivity
    hwaddr phys_addr;
1084 4a501606 Peter Maydell
    target_ulong page_size;
1085 4a501606 Peter Maydell
    int prot;
1086 4a501606 Peter Maydell
    int ret, is_user = ri->opc2 & 2;
1087 4a501606 Peter Maydell
    int access_type = ri->opc2 & 1;
1088 4a501606 Peter Maydell
1089 4a501606 Peter Maydell
    ret = get_phys_addr(env, value, access_type, is_user,
1090 4a501606 Peter Maydell
                        &phys_addr, &prot, &page_size);
1091 702a9357 Peter Maydell
    if (extended_addresses_enabled(env)) {
1092 702a9357 Peter Maydell
        /* ret is a DFSR/IFSR value for the long descriptor
1093 702a9357 Peter Maydell
         * translation table format, but with WnR always clear.
1094 702a9357 Peter Maydell
         * Convert it to a 64-bit PAR.
1095 702a9357 Peter Maydell
         */
1096 702a9357 Peter Maydell
        uint64_t par64 = (1 << 11); /* LPAE bit always set */
1097 702a9357 Peter Maydell
        if (ret == 0) {
1098 702a9357 Peter Maydell
            par64 |= phys_addr & ~0xfffULL;
1099 702a9357 Peter Maydell
            /* We don't set the ATTR or SH fields in the PAR. */
1100 4a501606 Peter Maydell
        } else {
1101 702a9357 Peter Maydell
            par64 |= 1; /* F */
1102 702a9357 Peter Maydell
            par64 |= (ret & 0x3f) << 1; /* FS */
1103 702a9357 Peter Maydell
            /* Note that S2WLK and FSTAGE are always zero, because we don't
1104 702a9357 Peter Maydell
             * implement virtualization and therefore there can't be a stage 2
1105 702a9357 Peter Maydell
             * fault.
1106 702a9357 Peter Maydell
             */
1107 4a501606 Peter Maydell
        }
1108 702a9357 Peter Maydell
        env->cp15.c7_par = par64;
1109 702a9357 Peter Maydell
        env->cp15.c7_par_hi = par64 >> 32;
1110 4a501606 Peter Maydell
    } else {
1111 702a9357 Peter Maydell
        /* ret is a DFSR/IFSR value for the short descriptor
1112 702a9357 Peter Maydell
         * translation table format (with WnR always clear).
1113 702a9357 Peter Maydell
         * Convert it to a 32-bit PAR.
1114 702a9357 Peter Maydell
         */
1115 702a9357 Peter Maydell
        if (ret == 0) {
1116 702a9357 Peter Maydell
            /* We do not set any attribute bits in the PAR */
1117 702a9357 Peter Maydell
            if (page_size == (1 << 24)
1118 702a9357 Peter Maydell
                && arm_feature(env, ARM_FEATURE_V7)) {
1119 702a9357 Peter Maydell
                env->cp15.c7_par = (phys_addr & 0xff000000) | 1 << 1;
1120 702a9357 Peter Maydell
            } else {
1121 702a9357 Peter Maydell
                env->cp15.c7_par = phys_addr & 0xfffff000;
1122 702a9357 Peter Maydell
            }
1123 702a9357 Peter Maydell
        } else {
1124 775fda92 Peter Maydell
            env->cp15.c7_par = ((ret & (1 << 10)) >> 5) |
1125 775fda92 Peter Maydell
                ((ret & (1 << 12)) >> 6) |
1126 702a9357 Peter Maydell
                ((ret & 0xf) << 1) | 1;
1127 702a9357 Peter Maydell
        }
1128 702a9357 Peter Maydell
        env->cp15.c7_par_hi = 0;
1129 4a501606 Peter Maydell
    }
1130 4a501606 Peter Maydell
}
1131 4a501606 Peter Maydell
#endif
1132 4a501606 Peter Maydell
1133 4a501606 Peter Maydell
static const ARMCPRegInfo vapa_cp_reginfo[] = {
1134 4a501606 Peter Maydell
    { .name = "PAR", .cp = 15, .crn = 7, .crm = 4, .opc1 = 0, .opc2 = 0,
1135 4a501606 Peter Maydell
      .access = PL1_RW, .resetvalue = 0,
1136 4a501606 Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c7_par),
1137 4a501606 Peter Maydell
      .writefn = par_write },
1138 4a501606 Peter Maydell
#ifndef CONFIG_USER_ONLY
1139 4a501606 Peter Maydell
    { .name = "ATS", .cp = 15, .crn = 7, .crm = 8, .opc1 = 0, .opc2 = CP_ANY,
1140 92611c00 Peter Maydell
      .access = PL1_W, .accessfn = ats_access,
1141 92611c00 Peter Maydell
      .writefn = ats_write, .type = ARM_CP_NO_MIGRATE },
1142 4a501606 Peter Maydell
#endif
1143 4a501606 Peter Maydell
    REGINFO_SENTINEL
1144 4a501606 Peter Maydell
};
1145 4a501606 Peter Maydell
1146 18032bec Peter Maydell
/* Return basic MPU access permission bits.  */
1147 18032bec Peter Maydell
static uint32_t simple_mpu_ap_bits(uint32_t val)
1148 18032bec Peter Maydell
{
1149 18032bec Peter Maydell
    uint32_t ret;
1150 18032bec Peter Maydell
    uint32_t mask;
1151 18032bec Peter Maydell
    int i;
1152 18032bec Peter Maydell
    ret = 0;
1153 18032bec Peter Maydell
    mask = 3;
1154 18032bec Peter Maydell
    for (i = 0; i < 16; i += 2) {
1155 18032bec Peter Maydell
        ret |= (val >> i) & mask;
1156 18032bec Peter Maydell
        mask <<= 2;
1157 18032bec Peter Maydell
    }
1158 18032bec Peter Maydell
    return ret;
1159 18032bec Peter Maydell
}
1160 18032bec Peter Maydell
1161 18032bec Peter Maydell
/* Pad basic MPU access permission bits to extended format.  */
1162 18032bec Peter Maydell
static uint32_t extended_mpu_ap_bits(uint32_t val)
1163 18032bec Peter Maydell
{
1164 18032bec Peter Maydell
    uint32_t ret;
1165 18032bec Peter Maydell
    uint32_t mask;
1166 18032bec Peter Maydell
    int i;
1167 18032bec Peter Maydell
    ret = 0;
1168 18032bec Peter Maydell
    mask = 3;
1169 18032bec Peter Maydell
    for (i = 0; i < 16; i += 2) {
1170 18032bec Peter Maydell
        ret |= (val & mask) << i;
1171 18032bec Peter Maydell
        mask <<= 2;
1172 18032bec Peter Maydell
    }
1173 18032bec Peter Maydell
    return ret;
1174 18032bec Peter Maydell
}
1175 18032bec Peter Maydell
1176 c4241c7d Peter Maydell
static void pmsav5_data_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
1177 c4241c7d Peter Maydell
                                 uint64_t value)
1178 18032bec Peter Maydell
{
1179 18032bec Peter Maydell
    env->cp15.c5_data = extended_mpu_ap_bits(value);
1180 18032bec Peter Maydell
}
1181 18032bec Peter Maydell
1182 c4241c7d Peter Maydell
static uint64_t pmsav5_data_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
1183 18032bec Peter Maydell
{
1184 c4241c7d Peter Maydell
    return simple_mpu_ap_bits(env->cp15.c5_data);
1185 18032bec Peter Maydell
}
1186 18032bec Peter Maydell
1187 c4241c7d Peter Maydell
static void pmsav5_insn_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
1188 c4241c7d Peter Maydell
                                 uint64_t value)
1189 18032bec Peter Maydell
{
1190 18032bec Peter Maydell
    env->cp15.c5_insn = extended_mpu_ap_bits(value);
1191 18032bec Peter Maydell
}
1192 18032bec Peter Maydell
1193 c4241c7d Peter Maydell
static uint64_t pmsav5_insn_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
1194 18032bec Peter Maydell
{
1195 c4241c7d Peter Maydell
    return simple_mpu_ap_bits(env->cp15.c5_insn);
1196 18032bec Peter Maydell
}
1197 18032bec Peter Maydell
1198 18032bec Peter Maydell
static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
1199 18032bec Peter Maydell
    { .name = "DATA_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0,
1200 d4e6df63 Peter Maydell
      .access = PL1_RW, .type = ARM_CP_NO_MIGRATE,
1201 18032bec Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c5_data), .resetvalue = 0,
1202 18032bec Peter Maydell
      .readfn = pmsav5_data_ap_read, .writefn = pmsav5_data_ap_write, },
1203 18032bec Peter Maydell
    { .name = "INSN_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1,
1204 d4e6df63 Peter Maydell
      .access = PL1_RW, .type = ARM_CP_NO_MIGRATE,
1205 18032bec Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c5_insn), .resetvalue = 0,
1206 18032bec Peter Maydell
      .readfn = pmsav5_insn_ap_read, .writefn = pmsav5_insn_ap_write, },
1207 18032bec Peter Maydell
    { .name = "DATA_EXT_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 2,
1208 18032bec Peter Maydell
      .access = PL1_RW,
1209 18032bec Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c5_data), .resetvalue = 0, },
1210 18032bec Peter Maydell
    { .name = "INSN_EXT_AP", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 3,
1211 18032bec Peter Maydell
      .access = PL1_RW,
1212 18032bec Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c5_insn), .resetvalue = 0, },
1213 ecce5c3c Peter Maydell
    { .name = "DCACHE_CFG", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
1214 ecce5c3c Peter Maydell
      .access = PL1_RW,
1215 ecce5c3c Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c2_data), .resetvalue = 0, },
1216 ecce5c3c Peter Maydell
    { .name = "ICACHE_CFG", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 1,
1217 ecce5c3c Peter Maydell
      .access = PL1_RW,
1218 ecce5c3c Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c2_insn), .resetvalue = 0, },
1219 06d76f31 Peter Maydell
    /* Protection region base and size registers */
1220 e508a92b Peter Maydell
    { .name = "946_PRBS0", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0,
1221 e508a92b Peter Maydell
      .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
1222 e508a92b Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c6_region[0]) },
1223 e508a92b Peter Maydell
    { .name = "946_PRBS1", .cp = 15, .crn = 6, .crm = 1, .opc1 = 0,
1224 e508a92b Peter Maydell
      .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
1225 e508a92b Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c6_region[1]) },
1226 e508a92b Peter Maydell
    { .name = "946_PRBS2", .cp = 15, .crn = 6, .crm = 2, .opc1 = 0,
1227 e508a92b Peter Maydell
      .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
1228 e508a92b Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c6_region[2]) },
1229 e508a92b Peter Maydell
    { .name = "946_PRBS3", .cp = 15, .crn = 6, .crm = 3, .opc1 = 0,
1230 e508a92b Peter Maydell
      .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
1231 e508a92b Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c6_region[3]) },
1232 e508a92b Peter Maydell
    { .name = "946_PRBS4", .cp = 15, .crn = 6, .crm = 4, .opc1 = 0,
1233 e508a92b Peter Maydell
      .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
1234 e508a92b Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c6_region[4]) },
1235 e508a92b Peter Maydell
    { .name = "946_PRBS5", .cp = 15, .crn = 6, .crm = 5, .opc1 = 0,
1236 e508a92b Peter Maydell
      .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
1237 e508a92b Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c6_region[5]) },
1238 e508a92b Peter Maydell
    { .name = "946_PRBS6", .cp = 15, .crn = 6, .crm = 6, .opc1 = 0,
1239 e508a92b Peter Maydell
      .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
1240 e508a92b Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c6_region[6]) },
1241 e508a92b Peter Maydell
    { .name = "946_PRBS7", .cp = 15, .crn = 6, .crm = 7, .opc1 = 0,
1242 e508a92b Peter Maydell
      .opc2 = CP_ANY, .access = PL1_RW, .resetvalue = 0,
1243 e508a92b Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c6_region[7]) },
1244 18032bec Peter Maydell
    REGINFO_SENTINEL
1245 18032bec Peter Maydell
};
1246 18032bec Peter Maydell
1247 c4241c7d Peter Maydell
static void vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
1248 c4241c7d Peter Maydell
                                 uint64_t value)
1249 ecce5c3c Peter Maydell
{
1250 2ebcebe2 Peter Maydell
    int maskshift = extract32(value, 0, 3);
1251 2ebcebe2 Peter Maydell
1252 74f1c6dd Sergey Fedorov
    if (arm_feature(env, ARM_FEATURE_LPAE) && (value & (1 << 31))) {
1253 e42c4db3 Peter Maydell
        value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
1254 e42c4db3 Peter Maydell
    } else {
1255 e42c4db3 Peter Maydell
        value &= 7;
1256 e42c4db3 Peter Maydell
    }
1257 e42c4db3 Peter Maydell
    /* Note that we always calculate c2_mask and c2_base_mask, but
1258 e42c4db3 Peter Maydell
     * they are only used for short-descriptor tables (ie if EAE is 0);
1259 e42c4db3 Peter Maydell
     * for long-descriptor tables the TTBCR fields are used differently
1260 e42c4db3 Peter Maydell
     * and the c2_mask and c2_base_mask values are meaningless.
1261 e42c4db3 Peter Maydell
     */
1262 ecce5c3c Peter Maydell
    env->cp15.c2_control = value;
1263 2ebcebe2 Peter Maydell
    env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> maskshift);
1264 2ebcebe2 Peter Maydell
    env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> maskshift);
1265 ecce5c3c Peter Maydell
}
1266 ecce5c3c Peter Maydell
1267 c4241c7d Peter Maydell
static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1268 c4241c7d Peter Maydell
                             uint64_t value)
1269 d4e6df63 Peter Maydell
{
1270 d4e6df63 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_LPAE)) {
1271 d4e6df63 Peter Maydell
        /* With LPAE the TTBCR could result in a change of ASID
1272 d4e6df63 Peter Maydell
         * via the TTBCR.A1 bit, so do a TLB flush.
1273 d4e6df63 Peter Maydell
         */
1274 d4e6df63 Peter Maydell
        tlb_flush(env, 1);
1275 d4e6df63 Peter Maydell
    }
1276 c4241c7d Peter Maydell
    vmsa_ttbcr_raw_write(env, ri, value);
1277 d4e6df63 Peter Maydell
}
1278 d4e6df63 Peter Maydell
1279 ecce5c3c Peter Maydell
static void vmsa_ttbcr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
1280 ecce5c3c Peter Maydell
{
1281 ecce5c3c Peter Maydell
    env->cp15.c2_base_mask = 0xffffc000u;
1282 ecce5c3c Peter Maydell
    env->cp15.c2_control = 0;
1283 ecce5c3c Peter Maydell
    env->cp15.c2_mask = 0;
1284 ecce5c3c Peter Maydell
}
1285 ecce5c3c Peter Maydell
1286 cb2e37df Peter Maydell
static void vmsa_tcr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
1287 cb2e37df Peter Maydell
                               uint64_t value)
1288 cb2e37df Peter Maydell
{
1289 cb2e37df Peter Maydell
    /* For AArch64 the A1 bit could result in a change of ASID, so TLB flush. */
1290 cb2e37df Peter Maydell
    tlb_flush(env, 1);
1291 cb2e37df Peter Maydell
    env->cp15.c2_control = value;
1292 cb2e37df Peter Maydell
}
1293 cb2e37df Peter Maydell
1294 327ed10f Peter Maydell
static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1295 327ed10f Peter Maydell
                            uint64_t value)
1296 327ed10f Peter Maydell
{
1297 327ed10f Peter Maydell
    /* 64 bit accesses to the TTBRs can change the ASID and so we
1298 327ed10f Peter Maydell
     * must flush the TLB.
1299 327ed10f Peter Maydell
     */
1300 327ed10f Peter Maydell
    if (cpreg_field_is_64bit(ri)) {
1301 327ed10f Peter Maydell
        tlb_flush(env, 1);
1302 327ed10f Peter Maydell
    }
1303 327ed10f Peter Maydell
    raw_write(env, ri, value);
1304 327ed10f Peter Maydell
}
1305 327ed10f Peter Maydell
1306 18032bec Peter Maydell
static const ARMCPRegInfo vmsa_cp_reginfo[] = {
1307 18032bec Peter Maydell
    { .name = "DFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0,
1308 18032bec Peter Maydell
      .access = PL1_RW,
1309 18032bec Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c5_data), .resetvalue = 0, },
1310 18032bec Peter Maydell
    { .name = "IFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1,
1311 18032bec Peter Maydell
      .access = PL1_RW,
1312 18032bec Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c5_insn), .resetvalue = 0, },
1313 327ed10f Peter Maydell
    { .name = "TTBR0_EL1", .state = ARM_CP_STATE_BOTH,
1314 327ed10f Peter Maydell
      .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
1315 327ed10f Peter Maydell
      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el1),
1316 327ed10f Peter Maydell
      .writefn = vmsa_ttbr_write, .resetvalue = 0 },
1317 327ed10f Peter Maydell
    { .name = "TTBR1_EL1", .state = ARM_CP_STATE_BOTH,
1318 327ed10f Peter Maydell
      .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 1,
1319 327ed10f Peter Maydell
      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.ttbr1_el1),
1320 327ed10f Peter Maydell
      .writefn = vmsa_ttbr_write, .resetvalue = 0 },
1321 cb2e37df Peter Maydell
    { .name = "TCR_EL1", .state = ARM_CP_STATE_AA64,
1322 cb2e37df Peter Maydell
      .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
1323 cb2e37df Peter Maydell
      .access = PL1_RW, .writefn = vmsa_tcr_el1_write,
1324 cb2e37df Peter Maydell
      .resetfn = vmsa_ttbcr_reset, .raw_writefn = raw_write,
1325 ecce5c3c Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c2_control) },
1326 cb2e37df Peter Maydell
    { .name = "TTBCR", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
1327 cb2e37df Peter Maydell
      .access = PL1_RW, .type = ARM_CP_NO_MIGRATE, .writefn = vmsa_ttbcr_write,
1328 cb2e37df Peter Maydell
      .resetfn = arm_cp_reset_ignore, .raw_writefn = vmsa_ttbcr_raw_write,
1329 cb2e37df Peter Maydell
      .fieldoffset = offsetoflow32(CPUARMState, cp15.c2_control) },
1330 06d76f31 Peter Maydell
    { .name = "DFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
1331 06d76f31 Peter Maydell
      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c6_data),
1332 06d76f31 Peter Maydell
      .resetvalue = 0, },
1333 18032bec Peter Maydell
    REGINFO_SENTINEL
1334 18032bec Peter Maydell
};
1335 18032bec Peter Maydell
1336 c4241c7d Peter Maydell
static void omap_ticonfig_write(CPUARMState *env, const ARMCPRegInfo *ri,
1337 c4241c7d Peter Maydell
                                uint64_t value)
1338 1047b9d7 Peter Maydell
{
1339 1047b9d7 Peter Maydell
    env->cp15.c15_ticonfig = value & 0xe7;
1340 1047b9d7 Peter Maydell
    /* The OS_TYPE bit in this register changes the reported CPUID! */
1341 1047b9d7 Peter Maydell
    env->cp15.c0_cpuid = (value & (1 << 5)) ?
1342 1047b9d7 Peter Maydell
        ARM_CPUID_TI915T : ARM_CPUID_TI925T;
1343 1047b9d7 Peter Maydell
}
1344 1047b9d7 Peter Maydell
1345 c4241c7d Peter Maydell
static void omap_threadid_write(CPUARMState *env, const ARMCPRegInfo *ri,
1346 c4241c7d Peter Maydell
                                uint64_t value)
1347 1047b9d7 Peter Maydell
{
1348 1047b9d7 Peter Maydell
    env->cp15.c15_threadid = value & 0xffff;
1349 1047b9d7 Peter Maydell
}
1350 1047b9d7 Peter Maydell
1351 c4241c7d Peter Maydell
static void omap_wfi_write(CPUARMState *env, const ARMCPRegInfo *ri,
1352 c4241c7d Peter Maydell
                           uint64_t value)
1353 1047b9d7 Peter Maydell
{
1354 1047b9d7 Peter Maydell
    /* Wait-for-interrupt (deprecated) */
1355 c3affe56 Andreas Färber
    cpu_interrupt(CPU(arm_env_get_cpu(env)), CPU_INTERRUPT_HALT);
1356 1047b9d7 Peter Maydell
}
1357 1047b9d7 Peter Maydell
1358 c4241c7d Peter Maydell
static void omap_cachemaint_write(CPUARMState *env, const ARMCPRegInfo *ri,
1359 c4241c7d Peter Maydell
                                  uint64_t value)
1360 c4804214 Peter Maydell
{
1361 c4804214 Peter Maydell
    /* On OMAP there are registers indicating the max/min index of dcache lines
1362 c4804214 Peter Maydell
     * containing a dirty line; cache flush operations have to reset these.
1363 c4804214 Peter Maydell
     */
1364 c4804214 Peter Maydell
    env->cp15.c15_i_max = 0x000;
1365 c4804214 Peter Maydell
    env->cp15.c15_i_min = 0xff0;
1366 c4804214 Peter Maydell
}
1367 c4804214 Peter Maydell
1368 18032bec Peter Maydell
static const ARMCPRegInfo omap_cp_reginfo[] = {
1369 18032bec Peter Maydell
    { .name = "DFSR", .cp = 15, .crn = 5, .crm = CP_ANY,
1370 18032bec Peter Maydell
      .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_OVERRIDE,
1371 18032bec Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c5_data), .resetvalue = 0, },
1372 1047b9d7 Peter Maydell
    { .name = "", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
1373 1047b9d7 Peter Maydell
      .access = PL1_RW, .type = ARM_CP_NOP },
1374 1047b9d7 Peter Maydell
    { .name = "TICONFIG", .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0,
1375 1047b9d7 Peter Maydell
      .access = PL1_RW,
1376 1047b9d7 Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c15_ticonfig), .resetvalue = 0,
1377 1047b9d7 Peter Maydell
      .writefn = omap_ticonfig_write },
1378 1047b9d7 Peter Maydell
    { .name = "IMAX", .cp = 15, .crn = 15, .crm = 2, .opc1 = 0, .opc2 = 0,
1379 1047b9d7 Peter Maydell
      .access = PL1_RW,
1380 1047b9d7 Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c15_i_max), .resetvalue = 0, },
1381 1047b9d7 Peter Maydell
    { .name = "IMIN", .cp = 15, .crn = 15, .crm = 3, .opc1 = 0, .opc2 = 0,
1382 1047b9d7 Peter Maydell
      .access = PL1_RW, .resetvalue = 0xff0,
1383 1047b9d7 Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c15_i_min) },
1384 1047b9d7 Peter Maydell
    { .name = "THREADID", .cp = 15, .crn = 15, .crm = 4, .opc1 = 0, .opc2 = 0,
1385 1047b9d7 Peter Maydell
      .access = PL1_RW,
1386 1047b9d7 Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c15_threadid), .resetvalue = 0,
1387 1047b9d7 Peter Maydell
      .writefn = omap_threadid_write },
1388 1047b9d7 Peter Maydell
    { .name = "TI925T_STATUS", .cp = 15, .crn = 15,
1389 1047b9d7 Peter Maydell
      .crm = 8, .opc1 = 0, .opc2 = 0, .access = PL1_RW,
1390 d4e6df63 Peter Maydell
      .type = ARM_CP_NO_MIGRATE,
1391 1047b9d7 Peter Maydell
      .readfn = arm_cp_read_zero, .writefn = omap_wfi_write, },
1392 1047b9d7 Peter Maydell
    /* TODO: Peripheral port remap register:
1393 1047b9d7 Peter Maydell
     * On OMAP2 mcr p15, 0, rn, c15, c2, 4 sets up the interrupt controller
1394 1047b9d7 Peter Maydell
     * base address at $rn & ~0xfff and map size of 0x200 << ($rn & 0xfff),
1395 1047b9d7 Peter Maydell
     * when MMU is off.
1396 1047b9d7 Peter Maydell
     */
1397 c4804214 Peter Maydell
    { .name = "OMAP_CACHEMAINT", .cp = 15, .crn = 7, .crm = CP_ANY,
1398 d4e6df63 Peter Maydell
      .opc1 = 0, .opc2 = CP_ANY, .access = PL1_W,
1399 d4e6df63 Peter Maydell
      .type = ARM_CP_OVERRIDE | ARM_CP_NO_MIGRATE,
1400 c4804214 Peter Maydell
      .writefn = omap_cachemaint_write },
1401 34f90529 Peter Maydell
    { .name = "C9", .cp = 15, .crn = 9,
1402 34f90529 Peter Maydell
      .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW,
1403 34f90529 Peter Maydell
      .type = ARM_CP_CONST | ARM_CP_OVERRIDE, .resetvalue = 0 },
1404 1047b9d7 Peter Maydell
    REGINFO_SENTINEL
1405 1047b9d7 Peter Maydell
};
1406 1047b9d7 Peter Maydell
1407 c4241c7d Peter Maydell
static void xscale_cpar_write(CPUARMState *env, const ARMCPRegInfo *ri,
1408 c4241c7d Peter Maydell
                              uint64_t value)
1409 1047b9d7 Peter Maydell
{
1410 1047b9d7 Peter Maydell
    value &= 0x3fff;
1411 1047b9d7 Peter Maydell
    if (env->cp15.c15_cpar != value) {
1412 1047b9d7 Peter Maydell
        /* Changes cp0 to cp13 behavior, so needs a TB flush.  */
1413 1047b9d7 Peter Maydell
        tb_flush(env);
1414 1047b9d7 Peter Maydell
        env->cp15.c15_cpar = value;
1415 1047b9d7 Peter Maydell
    }
1416 1047b9d7 Peter Maydell
}
1417 1047b9d7 Peter Maydell
1418 1047b9d7 Peter Maydell
static const ARMCPRegInfo xscale_cp_reginfo[] = {
1419 1047b9d7 Peter Maydell
    { .name = "XSCALE_CPAR",
1420 1047b9d7 Peter Maydell
      .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0, .access = PL1_RW,
1421 1047b9d7 Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c15_cpar), .resetvalue = 0,
1422 1047b9d7 Peter Maydell
      .writefn = xscale_cpar_write, },
1423 2771db27 Peter Maydell
    { .name = "XSCALE_AUXCR",
1424 2771db27 Peter Maydell
      .cp = 15, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 1, .access = PL1_RW,
1425 2771db27 Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.c1_xscaleauxcr),
1426 2771db27 Peter Maydell
      .resetvalue = 0, },
1427 1047b9d7 Peter Maydell
    REGINFO_SENTINEL
1428 1047b9d7 Peter Maydell
};
1429 1047b9d7 Peter Maydell
1430 1047b9d7 Peter Maydell
static const ARMCPRegInfo dummy_c15_cp_reginfo[] = {
1431 1047b9d7 Peter Maydell
    /* RAZ/WI the whole crn=15 space, when we don't have a more specific
1432 1047b9d7 Peter Maydell
     * implementation of this implementation-defined space.
1433 1047b9d7 Peter Maydell
     * Ideally this should eventually disappear in favour of actually
1434 1047b9d7 Peter Maydell
     * implementing the correct behaviour for all cores.
1435 1047b9d7 Peter Maydell
     */
1436 1047b9d7 Peter Maydell
    { .name = "C15_IMPDEF", .cp = 15, .crn = 15,
1437 1047b9d7 Peter Maydell
      .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY,
1438 3671cd87 Peter Crosthwaite
      .access = PL1_RW,
1439 3671cd87 Peter Crosthwaite
      .type = ARM_CP_CONST | ARM_CP_NO_MIGRATE | ARM_CP_OVERRIDE,
1440 d4e6df63 Peter Maydell
      .resetvalue = 0 },
1441 18032bec Peter Maydell
    REGINFO_SENTINEL
1442 18032bec Peter Maydell
};
1443 18032bec Peter Maydell
1444 c4804214 Peter Maydell
static const ARMCPRegInfo cache_dirty_status_cp_reginfo[] = {
1445 c4804214 Peter Maydell
    /* Cache status: RAZ because we have no cache so it's always clean */
1446 c4804214 Peter Maydell
    { .name = "CDSR", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 6,
1447 d4e6df63 Peter Maydell
      .access = PL1_R, .type = ARM_CP_CONST | ARM_CP_NO_MIGRATE,
1448 d4e6df63 Peter Maydell
      .resetvalue = 0 },
1449 c4804214 Peter Maydell
    REGINFO_SENTINEL
1450 c4804214 Peter Maydell
};
1451 c4804214 Peter Maydell
1452 c4804214 Peter Maydell
static const ARMCPRegInfo cache_block_ops_cp_reginfo[] = {
1453 c4804214 Peter Maydell
    /* We never have a a block transfer operation in progress */
1454 c4804214 Peter Maydell
    { .name = "BXSR", .cp = 15, .crn = 7, .crm = 12, .opc1 = 0, .opc2 = 4,
1455 d4e6df63 Peter Maydell
      .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_NO_MIGRATE,
1456 d4e6df63 Peter Maydell
      .resetvalue = 0 },
1457 30b05bba Peter Maydell
    /* The cache ops themselves: these all NOP for QEMU */
1458 30b05bba Peter Maydell
    { .name = "IICR", .cp = 15, .crm = 5, .opc1 = 0,
1459 30b05bba Peter Maydell
      .access = PL1_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
1460 30b05bba Peter Maydell
    { .name = "IDCR", .cp = 15, .crm = 6, .opc1 = 0,
1461 30b05bba Peter Maydell
      .access = PL1_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
1462 30b05bba Peter Maydell
    { .name = "CDCR", .cp = 15, .crm = 12, .opc1 = 0,
1463 30b05bba Peter Maydell
      .access = PL0_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
1464 30b05bba Peter Maydell
    { .name = "PIR", .cp = 15, .crm = 12, .opc1 = 1,
1465 30b05bba Peter Maydell
      .access = PL0_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
1466 30b05bba Peter Maydell
    { .name = "PDR", .cp = 15, .crm = 12, .opc1 = 2,
1467 30b05bba Peter Maydell
      .access = PL0_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
1468 30b05bba Peter Maydell
    { .name = "CIDCR", .cp = 15, .crm = 14, .opc1 = 0,
1469 30b05bba Peter Maydell
      .access = PL1_W, .type = ARM_CP_NOP|ARM_CP_64BIT },
1470 c4804214 Peter Maydell
    REGINFO_SENTINEL
1471 c4804214 Peter Maydell
};
1472 c4804214 Peter Maydell
1473 c4804214 Peter Maydell
static const ARMCPRegInfo cache_test_clean_cp_reginfo[] = {
1474 c4804214 Peter Maydell
    /* The cache test-and-clean instructions always return (1 << 30)
1475 c4804214 Peter Maydell
     * to indicate that there are no dirty cache lines.
1476 c4804214 Peter Maydell
     */
1477 c4804214 Peter Maydell
    { .name = "TC_DCACHE", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 3,
1478 d4e6df63 Peter Maydell
      .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_NO_MIGRATE,
1479 d4e6df63 Peter Maydell
      .resetvalue = (1 << 30) },
1480 c4804214 Peter Maydell
    { .name = "TCI_DCACHE", .cp = 15, .crn = 7, .crm = 14, .opc1 = 0, .opc2 = 3,
1481 d4e6df63 Peter Maydell
      .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_NO_MIGRATE,
1482 d4e6df63 Peter Maydell
      .resetvalue = (1 << 30) },
1483 c4804214 Peter Maydell
    REGINFO_SENTINEL
1484 c4804214 Peter Maydell
};
1485 c4804214 Peter Maydell
1486 34f90529 Peter Maydell
static const ARMCPRegInfo strongarm_cp_reginfo[] = {
1487 34f90529 Peter Maydell
    /* Ignore ReadBuffer accesses */
1488 34f90529 Peter Maydell
    { .name = "C9_READBUFFER", .cp = 15, .crn = 9,
1489 34f90529 Peter Maydell
      .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY,
1490 d4e6df63 Peter Maydell
      .access = PL1_RW, .resetvalue = 0,
1491 d4e6df63 Peter Maydell
      .type = ARM_CP_CONST | ARM_CP_OVERRIDE | ARM_CP_NO_MIGRATE },
1492 34f90529 Peter Maydell
    REGINFO_SENTINEL
1493 34f90529 Peter Maydell
};
1494 34f90529 Peter Maydell
1495 c4241c7d Peter Maydell
static uint64_t mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
1496 81bdde9d Peter Maydell
{
1497 55e5c285 Andreas Färber
    CPUState *cs = CPU(arm_env_get_cpu(env));
1498 55e5c285 Andreas Färber
    uint32_t mpidr = cs->cpu_index;
1499 4b7fff2f Peter Maydell
    /* We don't support setting cluster ID ([8..11]) (known as Aff1
1500 4b7fff2f Peter Maydell
     * in later ARM ARM versions), or any of the higher affinity level fields,
1501 81bdde9d Peter Maydell
     * so these bits always RAZ.
1502 81bdde9d Peter Maydell
     */
1503 81bdde9d Peter Maydell
    if (arm_feature(env, ARM_FEATURE_V7MP)) {
1504 78dbbbe4 Peter Maydell
        mpidr |= (1U << 31);
1505 81bdde9d Peter Maydell
        /* Cores which are uniprocessor (non-coherent)
1506 81bdde9d Peter Maydell
         * but still implement the MP extensions set
1507 81bdde9d Peter Maydell
         * bit 30. (For instance, A9UP.) However we do
1508 81bdde9d Peter Maydell
         * not currently model any of those cores.
1509 81bdde9d Peter Maydell
         */
1510 81bdde9d Peter Maydell
    }
1511 c4241c7d Peter Maydell
    return mpidr;
1512 81bdde9d Peter Maydell
}
1513 81bdde9d Peter Maydell
1514 81bdde9d Peter Maydell
static const ARMCPRegInfo mpidr_cp_reginfo[] = {
1515 4b7fff2f Peter Maydell
    { .name = "MPIDR", .state = ARM_CP_STATE_BOTH,
1516 4b7fff2f Peter Maydell
      .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 5,
1517 d4e6df63 Peter Maydell
      .access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_MIGRATE },
1518 81bdde9d Peter Maydell
    REGINFO_SENTINEL
1519 81bdde9d Peter Maydell
};
1520 81bdde9d Peter Maydell
1521 c4241c7d Peter Maydell
static uint64_t par64_read(CPUARMState *env, const ARMCPRegInfo *ri)
1522 891a2fe7 Peter Maydell
{
1523 c4241c7d Peter Maydell
    return ((uint64_t)env->cp15.c7_par_hi << 32) | env->cp15.c7_par;
1524 891a2fe7 Peter Maydell
}
1525 891a2fe7 Peter Maydell
1526 c4241c7d Peter Maydell
static void par64_write(CPUARMState *env, const ARMCPRegInfo *ri,
1527 c4241c7d Peter Maydell
                        uint64_t value)
1528 891a2fe7 Peter Maydell
{
1529 891a2fe7 Peter Maydell
    env->cp15.c7_par_hi = value >> 32;
1530 891a2fe7 Peter Maydell
    env->cp15.c7_par = value;
1531 891a2fe7 Peter Maydell
}
1532 891a2fe7 Peter Maydell
1533 891a2fe7 Peter Maydell
static void par64_reset(CPUARMState *env, const ARMCPRegInfo *ri)
1534 891a2fe7 Peter Maydell
{
1535 891a2fe7 Peter Maydell
    env->cp15.c7_par_hi = 0;
1536 891a2fe7 Peter Maydell
    env->cp15.c7_par = 0;
1537 891a2fe7 Peter Maydell
}
1538 891a2fe7 Peter Maydell
1539 7ac681cf Peter Maydell
static const ARMCPRegInfo lpae_cp_reginfo[] = {
1540 b90372ad Peter Maydell
    /* NOP AMAIR0/1: the override is because these clash with the rather
1541 7ac681cf Peter Maydell
     * broadly specified TLB_LOCKDOWN entry in the generic cp_reginfo.
1542 7ac681cf Peter Maydell
     */
1543 b0fe2427 Peter Maydell
    { .name = "AMAIR0", .state = ARM_CP_STATE_BOTH,
1544 b0fe2427 Peter Maydell
      .opc0 = 3, .crn = 10, .crm = 3, .opc1 = 0, .opc2 = 0,
1545 7ac681cf Peter Maydell
      .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_OVERRIDE,
1546 7ac681cf Peter Maydell
      .resetvalue = 0 },
1547 b0fe2427 Peter Maydell
    /* AMAIR1 is mapped to AMAIR_EL1[63:32] */
1548 7ac681cf Peter Maydell
    { .name = "AMAIR1", .cp = 15, .crn = 10, .crm = 3, .opc1 = 0, .opc2 = 1,
1549 7ac681cf Peter Maydell
      .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_OVERRIDE,
1550 7ac681cf Peter Maydell
      .resetvalue = 0 },
1551 f9fc619a Peter Maydell
    /* 64 bit access versions of the (dummy) debug registers */
1552 f9fc619a Peter Maydell
    { .name = "DBGDRAR", .cp = 14, .crm = 1, .opc1 = 0,
1553 f9fc619a Peter Maydell
      .access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
1554 f9fc619a Peter Maydell
    { .name = "DBGDSAR", .cp = 14, .crm = 2, .opc1 = 0,
1555 f9fc619a Peter Maydell
      .access = PL0_R, .type = ARM_CP_CONST|ARM_CP_64BIT, .resetvalue = 0 },
1556 891a2fe7 Peter Maydell
    { .name = "PAR", .cp = 15, .crm = 7, .opc1 = 0,
1557 891a2fe7 Peter Maydell
      .access = PL1_RW, .type = ARM_CP_64BIT,
1558 891a2fe7 Peter Maydell
      .readfn = par64_read, .writefn = par64_write, .resetfn = par64_reset },
1559 891a2fe7 Peter Maydell
    { .name = "TTBR0", .cp = 15, .crm = 2, .opc1 = 0,
1560 327ed10f Peter Maydell
      .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE,
1561 327ed10f Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el1),
1562 327ed10f Peter Maydell
      .writefn = vmsa_ttbr_write, .resetfn = arm_cp_reset_ignore },
1563 891a2fe7 Peter Maydell
    { .name = "TTBR1", .cp = 15, .crm = 2, .opc1 = 1,
1564 327ed10f Peter Maydell
      .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE,
1565 327ed10f Peter Maydell
      .fieldoffset = offsetof(CPUARMState, cp15.ttbr1_el1),
1566 327ed10f Peter Maydell
      .writefn = vmsa_ttbr_write, .resetfn = arm_cp_reset_ignore },
1567 7ac681cf Peter Maydell
    REGINFO_SENTINEL
1568 7ac681cf Peter Maydell
};
1569 7ac681cf Peter Maydell
1570 c4241c7d Peter Maydell
static uint64_t aa64_fpcr_read(CPUARMState *env, const ARMCPRegInfo *ri)
1571 b0d2b7d0 Peter Maydell
{
1572 c4241c7d Peter Maydell
    return vfp_get_fpcr(env);
1573 b0d2b7d0 Peter Maydell
}
1574 b0d2b7d0 Peter Maydell
1575 c4241c7d Peter Maydell
static void aa64_fpcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1576 c4241c7d Peter Maydell
                            uint64_t value)
1577 b0d2b7d0 Peter Maydell
{
1578 b0d2b7d0 Peter Maydell
    vfp_set_fpcr(env, value);
1579 b0d2b7d0 Peter Maydell
}
1580 b0d2b7d0 Peter Maydell
1581 c4241c7d Peter Maydell
static uint64_t aa64_fpsr_read(CPUARMState *env, const ARMCPRegInfo *ri)
1582 b0d2b7d0 Peter Maydell
{
1583 c4241c7d Peter Maydell
    return vfp_get_fpsr(env);
1584 b0d2b7d0 Peter Maydell
}
1585 b0d2b7d0 Peter Maydell
1586 c4241c7d Peter Maydell
static void aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1587 c4241c7d Peter Maydell
                            uint64_t value)
1588 b0d2b7d0 Peter Maydell
{
1589 b0d2b7d0 Peter Maydell
    vfp_set_fpsr(env, value);
1590 b0d2b7d0 Peter Maydell
}
1591 b0d2b7d0 Peter Maydell
1592 8af35c37 Peter Maydell
static CPAccessResult aa64_cacheop_access(CPUARMState *env,
1593 8af35c37 Peter Maydell
                                          const ARMCPRegInfo *ri)
1594 8af35c37 Peter Maydell
{
1595 8af35c37 Peter Maydell
    /* Cache invalidate/clean: NOP, but EL0 must UNDEF unless
1596 8af35c37 Peter Maydell
     * SCTLR_EL1.UCI is set.
1597 8af35c37 Peter Maydell
     */
1598 8af35c37 Peter Maydell
    if (arm_current_pl(env) == 0 && !(env->cp15.c1_sys & SCTLR_UCI)) {
1599 8af35c37 Peter Maydell
        return CP_ACCESS_TRAP;
1600 8af35c37 Peter Maydell
    }
1601 8af35c37 Peter Maydell
    return CP_ACCESS_OK;
1602 8af35c37 Peter Maydell
}
1603 8af35c37 Peter Maydell
1604 168aa23b Peter Maydell
static void tlbi_aa64_va_write(CPUARMState *env, const ARMCPRegInfo *ri,
1605 168aa23b Peter Maydell
                               uint64_t value)
1606 168aa23b Peter Maydell
{
1607 168aa23b Peter Maydell
    /* Invalidate by VA (AArch64 version) */
1608 168aa23b Peter Maydell
    uint64_t pageaddr = value << 12;
1609 168aa23b Peter Maydell
    tlb_flush_page(env, pageaddr);
1610 168aa23b Peter Maydell
}
1611 168aa23b Peter Maydell
1612 168aa23b Peter Maydell
static void tlbi_aa64_vaa_write(CPUARMState *env, const ARMCPRegInfo *ri,
1613 168aa23b Peter Maydell
                                uint64_t value)
1614 168aa23b Peter Maydell
{
1615 168aa23b Peter Maydell
    /* Invalidate by VA, all ASIDs (AArch64 version) */
1616 168aa23b Peter Maydell
    uint64_t pageaddr = value << 12;
1617 168aa23b Peter Maydell
    tlb_flush_page(env, pageaddr);
1618 168aa23b Peter Maydell
}
1619 168aa23b Peter Maydell
1620 168aa23b Peter Maydell
static void tlbi_aa64_asid_write(CPUARMState *env, const ARMCPRegInfo *ri,
1621 168aa23b Peter Maydell
                                 uint64_t value)
1622 168aa23b Peter Maydell
{
1623 168aa23b Peter Maydell
    /* Invalidate by ASID (AArch64 version) */
1624 168aa23b Peter Maydell
    int asid = extract64(value, 48, 16);
1625 168aa23b Peter Maydell
    tlb_flush(env, asid == 0);
1626 168aa23b Peter Maydell
}
1627 168aa23b Peter Maydell
1628 b0d2b7d0 Peter Maydell
static const ARMCPRegInfo v8_cp_reginfo[] = {
1629 b0d2b7d0 Peter Maydell
    /* Minimal set of EL0-visible registers. This will need to be expanded
1630 b0d2b7d0 Peter Maydell
     * significantly for system emulation of AArch64 CPUs.
1631 b0d2b7d0 Peter Maydell
     */
1632 b0d2b7d0 Peter Maydell
    { .name = "NZCV", .state = ARM_CP_STATE_AA64,
1633 b0d2b7d0 Peter Maydell
      .opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 2,
1634 b0d2b7d0 Peter Maydell
      .access = PL0_RW, .type = ARM_CP_NZCV },
1635 b0d2b7d0 Peter Maydell
    { .name = "FPCR", .state = ARM_CP_STATE_AA64,
1636 b0d2b7d0 Peter Maydell
      .opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 4,
1637 b0d2b7d0 Peter Maydell
      .access = PL0_RW, .readfn = aa64_fpcr_read, .writefn = aa64_fpcr_write },
1638 b0d2b7d0 Peter Maydell
    { .name = "FPSR", .state = ARM_CP_STATE_AA64,
1639 b0d2b7d0 Peter Maydell
      .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 4, .crm = 4,
1640 b0d2b7d0 Peter Maydell
      .access = PL0_RW, .readfn = aa64_fpsr_read, .writefn = aa64_fpsr_write },
1641 b0d2b7d0 Peter Maydell
    /* Prohibit use of DC ZVA. OPTME: implement DC ZVA and allow its use.
1642 b0d2b7d0 Peter Maydell
     * For system mode the DZP bit here will need to be computed, not constant.
1643 b0d2b7d0 Peter Maydell
     */
1644 b0d2b7d0 Peter Maydell
    { .name = "DCZID_EL0", .state = ARM_CP_STATE_AA64,
1645 b0d2b7d0 Peter Maydell
      .opc0 = 3, .opc1 = 3, .opc2 = 7, .crn = 0, .crm = 0,
1646 b0d2b7d0 Peter Maydell
      .access = PL0_R, .type = ARM_CP_CONST,
1647 b0d2b7d0 Peter Maydell
      .resetvalue = 0x10 },
1648 0eef9d98 Peter Maydell
    { .name = "CURRENTEL", .state = ARM_CP_STATE_AA64,
1649 0eef9d98 Peter Maydell
      .opc0 = 3, .opc1 = 0, .opc2 = 2, .crn = 4, .crm = 2,
1650 0eef9d98 Peter Maydell
      .access = PL1_R, .type = ARM_CP_CURRENTEL },
1651 8af35c37 Peter Maydell
    /* Cache ops: all NOPs since we don't emulate caches */
1652 8af35c37 Peter Maydell
    { .name = "IC_IALLUIS", .state = ARM_CP_STATE_AA64,
1653 8af35c37 Peter Maydell
      .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0,
1654 8af35c37 Peter Maydell
      .access = PL1_W, .type = ARM_CP_NOP },
1655 8af35c37 Peter Maydell
    { .name = "IC_IALLU", .state = ARM_CP_STATE_AA64,
1656 8af35c37 Peter Maydell
      .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 0,
1657 8af35c37 Peter Maydell
      .access = PL1_W, .type = ARM_CP_NOP },
1658 8af35c37 Peter Maydell
    { .name = "IC_IVAU", .state = ARM_CP_STATE_AA64,
1659 8af35c37 Peter Maydell
      .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 5, .opc2 = 1,
1660 8af35c37 Peter Maydell
      .access = PL0_W, .type = ARM_CP_NOP,
1661 8af35c37 Peter Maydell
      .accessfn = aa64_cacheop_access },
1662 8af35c37 Peter Maydell
    { .name = "DC_IVAC", .state = ARM_CP_STATE_AA64,
1663 8af35c37 Peter Maydell
      .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 1,
1664 8af35c37 Peter Maydell
      .access = PL1_W, .type = ARM_CP_NOP },
1665 8af35c37 Peter Maydell
    { .name = "DC_ISW", .state = ARM_CP_STATE_AA64,
1666 8af35c37 Peter Maydell
      .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 2,
1667 8af35c37 Peter Maydell
      .access = PL1_W, .type = ARM_CP_NOP },
1668 8af35c37 Peter Maydell
    { .name = "DC_CVAC", .state = ARM_CP_STATE_AA64,
1669 8af35c37 Peter Maydell
      .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 10, .opc2 = 1,
1670 8af35c37 Peter Maydell
      .access = PL0_W, .type = ARM_CP_NOP,
1671 8af35c37 Peter Maydell
      .accessfn = aa64_cacheop_access },
1672 8af35c37 Peter Maydell
    { .name = "DC_CSW", .state = ARM_CP_STATE_AA64,
1673 8af35c37 Peter Maydell
      .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 2,
1674 8af35c37 Peter Maydell
      .access = PL1_W, .type = ARM_CP_NOP },
1675 8af35c37 Peter Maydell
    { .name = "DC_CVAU", .state = ARM_CP_STATE_AA64,
1676 8af35c37 Peter Maydell
      .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 11, .opc2 = 1,
1677 8af35c37 Peter Maydell
      .access = PL0_W, .type = ARM_CP_NOP,
1678 8af35c37 Peter Maydell
      .accessfn = aa64_cacheop_access },
1679 8af35c37 Peter Maydell
    { .name = "DC_CIVAC", .state = ARM_CP_STATE_AA64,
1680 8af35c37 Peter Maydell
      .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 14, .opc2 = 1,
1681 8af35c37 Peter Maydell
      .access = PL0_W, .type = ARM_CP_NOP,
1682 8af35c37 Peter Maydell
      .accessfn = aa64_cacheop_access },
1683 8af35c37 Peter Maydell
    { .name = "DC_CISW", .state = ARM_CP_STATE_AA64,
1684 8af35c37 Peter Maydell
      .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2,
1685 8af35c37 Peter Maydell
      .access = PL1_W, .type = ARM_CP_NOP },
1686 168aa23b Peter Maydell
    /* TLBI operations */
1687 168aa23b Peter Maydell
    { .name = "TLBI_VMALLE1IS", .state = ARM_CP_STATE_AA64,
1688 168aa23b Peter Maydell
      .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 0,
1689 168aa23b Peter Maydell
      .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
1690 168aa23b Peter Maydell
      .writefn = tlbiall_write },
1691 168aa23b Peter Maydell
    { .name = "TLBI_VAE1IS", .state = ARM_CP_STATE_AA64,
1692 168aa23b Peter Maydell
      .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 1,
1693 168aa23b Peter Maydell
      .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
1694 168aa23b Peter Maydell
      .writefn = tlbi_aa64_va_write },
1695 168aa23b Peter Maydell
    { .name = "TLBI_ASIDE1IS", .state = ARM_CP_STATE_AA64,
1696 168aa23b Peter Maydell
      .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 2,
1697 168aa23b Peter Maydell
      .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
1698 168aa23b Peter Maydell
      .writefn = tlbi_aa64_asid_write },
1699 168aa23b Peter Maydell
    { .name = "TLBI_VAAE1IS", .state = ARM_CP_STATE_AA64,
1700 168aa23b Peter Maydell
      .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 3,
1701 168aa23b Peter Maydell
      .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
1702 168aa23b Peter Maydell
      .writefn = tlbi_aa64_vaa_write },
1703 168aa23b Peter Maydell
    { .name = "TLBI_VALE1IS", .state = ARM_CP_STATE_AA64,
1704 168aa23b Peter Maydell
      .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 5,
1705 168aa23b Peter Maydell
      .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
1706 168aa23b Peter Maydell
      .writefn = tlbi_aa64_va_write },
1707 168aa23b Peter Maydell
    { .name = "TLBI_VAALE1IS", .state = ARM_CP_STATE_AA64,
1708 168aa23b Peter Maydell
      .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 7,
1709 168aa23b Peter Maydell
      .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
1710 168aa23b Peter Maydell
      .writefn = tlbi_aa64_vaa_write },
1711 168aa23b Peter Maydell
    { .name = "TLBI_VMALLE1", .state = ARM_CP_STATE_AA64,
1712 168aa23b Peter Maydell
      .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 0,
1713 168aa23b Peter Maydell
      .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
1714 168aa23b Peter Maydell
      .writefn = tlbiall_write },
1715 168aa23b Peter Maydell
    { .name = "TLBI_VAE1", .state = ARM_CP_STATE_AA64,
1716 168aa23b Peter Maydell
      .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 1,
1717 168aa23b Peter Maydell
      .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
1718 168aa23b Peter Maydell
      .writefn = tlbi_aa64_va_write },
1719 168aa23b Peter Maydell
    { .name = "TLBI_ASIDE1", .state = ARM_CP_STATE_AA64,
1720 168aa23b Peter Maydell
      .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 2,
1721 168aa23b Peter Maydell
      .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
1722 168aa23b Peter Maydell
      .writefn = tlbi_aa64_asid_write },
1723 168aa23b Peter Maydell
    { .name = "TLBI_VAAE1", .state = ARM_CP_STATE_AA64,
1724 168aa23b Peter Maydell
      .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 3,
1725 168aa23b Peter Maydell
      .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
1726 168aa23b Peter Maydell
      .writefn = tlbi_aa64_vaa_write },
1727 168aa23b Peter Maydell
    { .name = "TLBI_VALE1", .state = ARM_CP_STATE_AA64,
1728 168aa23b Peter Maydell
      .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 5,
1729 168aa23b Peter Maydell
      .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
1730 168aa23b Peter Maydell
      .writefn = tlbi_aa64_va_write },
1731 168aa23b Peter Maydell
    { .name = "TLBI_VAALE1", .state = ARM_CP_STATE_AA64,
1732 168aa23b Peter Maydell
      .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 7,
1733 168aa23b Peter Maydell
      .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
1734 168aa23b Peter Maydell
      .writefn = tlbi_aa64_vaa_write },
1735 91e24069 Peter Maydell
    /* Dummy implementation of monitor debug system control register:
1736 91e24069 Peter Maydell
     * we don't support debug.
1737 91e24069 Peter Maydell
     */
1738 91e24069 Peter Maydell
    { .name = "MDSCR_EL1", .state = ARM_CP_STATE_AA64,
1739 91e24069 Peter Maydell
      .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2,
1740 91e24069 Peter Maydell
      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
1741 cd5c11b8 Peter Maydell
    /* We define a dummy WI OSLAR_EL1, because Linux writes to it. */
1742 cd5c11b8 Peter Maydell
    { .name = "OSLAR_EL1", .state = ARM_CP_STATE_AA64,
1743 cd5c11b8 Peter Maydell
      .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 4,
1744 cd5c11b8 Peter Maydell
      .access = PL1_W, .type = ARM_CP_NOP },
1745 b0d2b7d0 Peter Maydell
    REGINFO_SENTINEL
1746 b0d2b7d0 Peter Maydell
};
1747 b0d2b7d0 Peter Maydell
1748 c4241c7d Peter Maydell
static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
1749 c4241c7d Peter Maydell
                        uint64_t value)
1750 2771db27 Peter Maydell
{
1751 2771db27 Peter Maydell
    env->cp15.c1_sys = value;
1752 2771db27 Peter Maydell
    /* ??? Lots of these bits are not implemented.  */
1753 2771db27 Peter Maydell
    /* This may enable/disable the MMU, so do a TLB flush.  */
1754 2771db27 Peter Maydell
    tlb_flush(env, 1);
1755 2771db27 Peter Maydell
}
1756 2771db27 Peter Maydell
1757 7da845b0 Peter Maydell
static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri)
1758 7da845b0 Peter Maydell
{
1759 7da845b0 Peter Maydell
    /* Only accessible in EL0 if SCTLR.UCT is set (and only in AArch64,
1760 7da845b0 Peter Maydell
     * but the AArch32 CTR has its own reginfo struct)
1761 7da845b0 Peter Maydell
     */
1762 7da845b0 Peter Maydell
    if (arm_current_pl(env) == 0 && !(env->cp15.c1_sys & SCTLR_UCT)) {
1763 7da845b0 Peter Maydell
        return CP_ACCESS_TRAP;
1764 7da845b0 Peter Maydell
    }
1765 7da845b0 Peter Maydell
    return CP_ACCESS_OK;
1766 7da845b0 Peter Maydell
}
1767 7da845b0 Peter Maydell
1768 0b45451e Peter Maydell
static void define_aarch64_debug_regs(ARMCPU *cpu)
1769 0b45451e Peter Maydell
{
1770 0b45451e Peter Maydell
    /* Define breakpoint and watchpoint registers. These do nothing
1771 0b45451e Peter Maydell
     * but read as written, for now.
1772 0b45451e Peter Maydell
     */
1773 0b45451e Peter Maydell
    int i;
1774 0b45451e Peter Maydell
1775 0b45451e Peter Maydell
    for (i = 0; i < 16; i++) {
1776 0b45451e Peter Maydell
        ARMCPRegInfo dbgregs[] = {
1777 0b45451e Peter Maydell
            { .name = "DBGBVR", .state = ARM_CP_STATE_AA64,
1778 0b45451e Peter Maydell
              .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 4,
1779 0b45451e Peter Maydell
              .access = PL1_RW,
1780 0b45451e Peter Maydell
              .fieldoffset = offsetof(CPUARMState, cp15.dbgbvr[i]) },
1781 0b45451e Peter Maydell
            { .name = "DBGBCR", .state = ARM_CP_STATE_AA64,
1782 0b45451e Peter Maydell
              .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 5,
1783 0b45451e Peter Maydell
              .access = PL1_RW,
1784 0b45451e Peter Maydell
              .fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]) },
1785 0b45451e Peter Maydell
            { .name = "DBGWVR", .state = ARM_CP_STATE_AA64,
1786 0b45451e Peter Maydell
              .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 6,
1787 0b45451e Peter Maydell
              .access = PL1_RW,
1788 0b45451e Peter Maydell
              .fieldoffset = offsetof(CPUARMState, cp15.dbgwvr[i]) },
1789 0b45451e Peter Maydell
            { .name = "DBGWCR", .state = ARM_CP_STATE_AA64,
1790 0b45451e Peter Maydell
              .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 7,
1791 0b45451e Peter Maydell
              .access = PL1_RW,
1792 0b45451e Peter Maydell
              .fieldoffset = offsetof(CPUARMState, cp15.dbgwcr[i]) },
1793 0b45451e Peter Maydell
               REGINFO_SENTINEL
1794 0b45451e Peter Maydell
        };
1795 0b45451e Peter Maydell
        define_arm_cp_regs(cpu, dbgregs);
1796 0b45451e Peter Maydell
    }
1797 0b45451e Peter Maydell
}
1798 0b45451e Peter Maydell
1799 2ceb98c0 Peter Maydell
void register_cp_regs_for_features(ARMCPU *cpu)
1800 2ceb98c0 Peter Maydell
{
1801 2ceb98c0 Peter Maydell
    /* Register all the coprocessor registers based on feature bits */
1802 2ceb98c0 Peter Maydell
    CPUARMState *env = &cpu->env;
1803 2ceb98c0 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_M)) {
1804 2ceb98c0 Peter Maydell
        /* M profile has no coprocessor registers */
1805 2ceb98c0 Peter Maydell
        return;
1806 2ceb98c0 Peter Maydell
    }
1807 2ceb98c0 Peter Maydell
1808 e9aa6c21 Peter Maydell
    define_arm_cp_regs(cpu, cp_reginfo);
1809 7d57f408 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_V6)) {
1810 8515a092 Peter Maydell
        /* The ID registers all have impdef reset values */
1811 8515a092 Peter Maydell
        ARMCPRegInfo v6_idregs[] = {
1812 8515a092 Peter Maydell
            { .name = "ID_PFR0", .cp = 15, .crn = 0, .crm = 1,
1813 8515a092 Peter Maydell
              .opc1 = 0, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST,
1814 8515a092 Peter Maydell
              .resetvalue = cpu->id_pfr0 },
1815 8515a092 Peter Maydell
            { .name = "ID_PFR1", .cp = 15, .crn = 0, .crm = 1,
1816 8515a092 Peter Maydell
              .opc1 = 0, .opc2 = 1, .access = PL1_R, .type = ARM_CP_CONST,
1817 8515a092 Peter Maydell
              .resetvalue = cpu->id_pfr1 },
1818 8515a092 Peter Maydell
            { .name = "ID_DFR0", .cp = 15, .crn = 0, .crm = 1,
1819 8515a092 Peter Maydell
              .opc1 = 0, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST,
1820 8515a092 Peter Maydell
              .resetvalue = cpu->id_dfr0 },
1821 8515a092 Peter Maydell
            { .name = "ID_AFR0", .cp = 15, .crn = 0, .crm = 1,
1822 8515a092 Peter Maydell
              .opc1 = 0, .opc2 = 3, .access = PL1_R, .type = ARM_CP_CONST,
1823 8515a092 Peter Maydell
              .resetvalue = cpu->id_afr0 },
1824 8515a092 Peter Maydell
            { .name = "ID_MMFR0", .cp = 15, .crn = 0, .crm = 1,
1825 8515a092 Peter Maydell
              .opc1 = 0, .opc2 = 4, .access = PL1_R, .type = ARM_CP_CONST,
1826 8515a092 Peter Maydell
              .resetvalue = cpu->id_mmfr0 },
1827 8515a092 Peter Maydell
            { .name = "ID_MMFR1", .cp = 15, .crn = 0, .crm = 1,
1828 8515a092 Peter Maydell
              .opc1 = 0, .opc2 = 5, .access = PL1_R, .type = ARM_CP_CONST,
1829 8515a092 Peter Maydell
              .resetvalue = cpu->id_mmfr1 },
1830 8515a092 Peter Maydell
            { .name = "ID_MMFR2", .cp = 15, .crn = 0, .crm = 1,
1831 8515a092 Peter Maydell
              .opc1 = 0, .opc2 = 6, .access = PL1_R, .type = ARM_CP_CONST,
1832 8515a092 Peter Maydell
              .resetvalue = cpu->id_mmfr2 },
1833 8515a092 Peter Maydell
            { .name = "ID_MMFR3", .cp = 15, .crn = 0, .crm = 1,
1834 8515a092 Peter Maydell
              .opc1 = 0, .opc2 = 7, .access = PL1_R, .type = ARM_CP_CONST,
1835 8515a092 Peter Maydell
              .resetvalue = cpu->id_mmfr3 },
1836 8515a092 Peter Maydell
            { .name = "ID_ISAR0", .cp = 15, .crn = 0, .crm = 2,
1837 8515a092 Peter Maydell
              .opc1 = 0, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST,
1838 8515a092 Peter Maydell
              .resetvalue = cpu->id_isar0 },
1839 8515a092 Peter Maydell
            { .name = "ID_ISAR1", .cp = 15, .crn = 0, .crm = 2,
1840 8515a092 Peter Maydell
              .opc1 = 0, .opc2 = 1, .access = PL1_R, .type = ARM_CP_CONST,
1841 8515a092 Peter Maydell
              .resetvalue = cpu->id_isar1 },
1842 8515a092 Peter Maydell
            { .name = "ID_ISAR2", .cp = 15, .crn = 0, .crm = 2,
1843 8515a092 Peter Maydell
              .opc1 = 0, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST,
1844 8515a092 Peter Maydell
              .resetvalue = cpu->id_isar2 },
1845 8515a092 Peter Maydell
            { .name = "ID_ISAR3", .cp = 15, .crn = 0, .crm = 2,
1846 8515a092 Peter Maydell
              .opc1 = 0, .opc2 = 3, .access = PL1_R, .type = ARM_CP_CONST,
1847 8515a092 Peter Maydell
              .resetvalue = cpu->id_isar3 },
1848 8515a092 Peter Maydell
            { .name = "ID_ISAR4", .cp = 15, .crn = 0, .crm = 2,
1849 8515a092 Peter Maydell
              .opc1 = 0, .opc2 = 4, .access = PL1_R, .type = ARM_CP_CONST,
1850 8515a092 Peter Maydell
              .resetvalue = cpu->id_isar4 },
1851 8515a092 Peter Maydell
            { .name = "ID_ISAR5", .cp = 15, .crn = 0, .crm = 2,
1852 8515a092 Peter Maydell
              .opc1 = 0, .opc2 = 5, .access = PL1_R, .type = ARM_CP_CONST,
1853 8515a092 Peter Maydell
              .resetvalue = cpu->id_isar5 },
1854 8515a092 Peter Maydell
            /* 6..7 are as yet unallocated and must RAZ */
1855 8515a092 Peter Maydell
            { .name = "ID_ISAR6", .cp = 15, .crn = 0, .crm = 2,
1856 8515a092 Peter Maydell
              .opc1 = 0, .opc2 = 6, .access = PL1_R, .type = ARM_CP_CONST,
1857 8515a092 Peter Maydell
              .resetvalue = 0 },
1858 8515a092 Peter Maydell
            { .name = "ID_ISAR7", .cp = 15, .crn = 0, .crm = 2,
1859 8515a092 Peter Maydell
              .opc1 = 0, .opc2 = 7, .access = PL1_R, .type = ARM_CP_CONST,
1860 8515a092 Peter Maydell
              .resetvalue = 0 },
1861 8515a092 Peter Maydell
            REGINFO_SENTINEL
1862 8515a092 Peter Maydell
        };
1863 8515a092 Peter Maydell
        define_arm_cp_regs(cpu, v6_idregs);
1864 7d57f408 Peter Maydell
        define_arm_cp_regs(cpu, v6_cp_reginfo);
1865 7d57f408 Peter Maydell
    } else {
1866 7d57f408 Peter Maydell
        define_arm_cp_regs(cpu, not_v6_cp_reginfo);
1867 7d57f408 Peter Maydell
    }
1868 4d31c596 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_V6K)) {
1869 4d31c596 Peter Maydell
        define_arm_cp_regs(cpu, v6k_cp_reginfo);
1870 4d31c596 Peter Maydell
    }
1871 e9aa6c21 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_V7)) {
1872 200ac0ef Peter Maydell
        /* v7 performance monitor control register: same implementor
1873 200ac0ef Peter Maydell
         * field as main ID register, and we implement no event counters.
1874 200ac0ef Peter Maydell
         */
1875 200ac0ef Peter Maydell
        ARMCPRegInfo pmcr = {
1876 200ac0ef Peter Maydell
            .name = "PMCR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 0,
1877 200ac0ef Peter Maydell
            .access = PL0_RW, .resetvalue = cpu->midr & 0xff000000,
1878 200ac0ef Peter Maydell
            .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),
1879 fcd25206 Peter Maydell
            .accessfn = pmreg_access, .writefn = pmcr_write,
1880 fcd25206 Peter Maydell
            .raw_writefn = raw_write,
1881 200ac0ef Peter Maydell
        };
1882 776d4e5c Peter Maydell
        ARMCPRegInfo clidr = {
1883 7da845b0 Peter Maydell
            .name = "CLIDR", .state = ARM_CP_STATE_BOTH,
1884 7da845b0 Peter Maydell
            .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 1,
1885 776d4e5c Peter Maydell
            .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->clidr
1886 776d4e5c Peter Maydell
        };
1887 200ac0ef Peter Maydell
        define_one_arm_cp_reg(cpu, &pmcr);
1888 776d4e5c Peter Maydell
        define_one_arm_cp_reg(cpu, &clidr);
1889 e9aa6c21 Peter Maydell
        define_arm_cp_regs(cpu, v7_cp_reginfo);
1890 7d57f408 Peter Maydell
    } else {
1891 7d57f408 Peter Maydell
        define_arm_cp_regs(cpu, not_v7_cp_reginfo);
1892 e9aa6c21 Peter Maydell
    }
1893 b0d2b7d0 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_V8)) {
1894 e60cef86 Peter Maydell
        /* AArch64 ID registers, which all have impdef reset values */
1895 e60cef86 Peter Maydell
        ARMCPRegInfo v8_idregs[] = {
1896 e60cef86 Peter Maydell
            { .name = "ID_AA64PFR0_EL1", .state = ARM_CP_STATE_AA64,
1897 e60cef86 Peter Maydell
              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 0,
1898 e60cef86 Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST,
1899 e60cef86 Peter Maydell
              .resetvalue = cpu->id_aa64pfr0 },
1900 e60cef86 Peter Maydell
            { .name = "ID_AA64PFR1_EL1", .state = ARM_CP_STATE_AA64,
1901 e60cef86 Peter Maydell
              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 1,
1902 e60cef86 Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST,
1903 e60cef86 Peter Maydell
              .resetvalue = cpu->id_aa64pfr1},
1904 e60cef86 Peter Maydell
            { .name = "ID_AA64DFR0_EL1", .state = ARM_CP_STATE_AA64,
1905 e60cef86 Peter Maydell
              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0,
1906 e60cef86 Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST,
1907 e60cef86 Peter Maydell
              .resetvalue = cpu->id_aa64dfr0 },
1908 e60cef86 Peter Maydell
            { .name = "ID_AA64DFR1_EL1", .state = ARM_CP_STATE_AA64,
1909 e60cef86 Peter Maydell
              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 1,
1910 e60cef86 Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST,
1911 e60cef86 Peter Maydell
              .resetvalue = cpu->id_aa64dfr1 },
1912 e60cef86 Peter Maydell
            { .name = "ID_AA64AFR0_EL1", .state = ARM_CP_STATE_AA64,
1913 e60cef86 Peter Maydell
              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 4,
1914 e60cef86 Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST,
1915 e60cef86 Peter Maydell
              .resetvalue = cpu->id_aa64afr0 },
1916 e60cef86 Peter Maydell
            { .name = "ID_AA64AFR1_EL1", .state = ARM_CP_STATE_AA64,
1917 e60cef86 Peter Maydell
              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 5,
1918 e60cef86 Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST,
1919 e60cef86 Peter Maydell
              .resetvalue = cpu->id_aa64afr1 },
1920 e60cef86 Peter Maydell
            { .name = "ID_AA64ISAR0_EL1", .state = ARM_CP_STATE_AA64,
1921 e60cef86 Peter Maydell
              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 0,
1922 e60cef86 Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST,
1923 e60cef86 Peter Maydell
              .resetvalue = cpu->id_aa64isar0 },
1924 e60cef86 Peter Maydell
            { .name = "ID_AA64ISAR1_EL1", .state = ARM_CP_STATE_AA64,
1925 e60cef86 Peter Maydell
              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 1,
1926 e60cef86 Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST,
1927 e60cef86 Peter Maydell
              .resetvalue = cpu->id_aa64isar1 },
1928 e60cef86 Peter Maydell
            { .name = "ID_AA64MMFR0_EL1", .state = ARM_CP_STATE_AA64,
1929 e60cef86 Peter Maydell
              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
1930 e60cef86 Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST,
1931 e60cef86 Peter Maydell
              .resetvalue = cpu->id_aa64mmfr0 },
1932 e60cef86 Peter Maydell
            { .name = "ID_AA64MMFR1_EL1", .state = ARM_CP_STATE_AA64,
1933 e60cef86 Peter Maydell
              .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 1,
1934 e60cef86 Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST,
1935 e60cef86 Peter Maydell
              .resetvalue = cpu->id_aa64mmfr1 },
1936 e60cef86 Peter Maydell
            REGINFO_SENTINEL
1937 e60cef86 Peter Maydell
        };
1938 e60cef86 Peter Maydell
        define_arm_cp_regs(cpu, v8_idregs);
1939 b0d2b7d0 Peter Maydell
        define_arm_cp_regs(cpu, v8_cp_reginfo);
1940 0b45451e Peter Maydell
        define_aarch64_debug_regs(cpu);
1941 b0d2b7d0 Peter Maydell
    }
1942 18032bec Peter Maydell
    if (arm_feature(env, ARM_FEATURE_MPU)) {
1943 18032bec Peter Maydell
        /* These are the MPU registers prior to PMSAv6. Any new
1944 18032bec Peter Maydell
         * PMSA core later than the ARM946 will require that we
1945 18032bec Peter Maydell
         * implement the PMSAv6 or PMSAv7 registers, which are
1946 18032bec Peter Maydell
         * completely different.
1947 18032bec Peter Maydell
         */
1948 18032bec Peter Maydell
        assert(!arm_feature(env, ARM_FEATURE_V6));
1949 18032bec Peter Maydell
        define_arm_cp_regs(cpu, pmsav5_cp_reginfo);
1950 18032bec Peter Maydell
    } else {
1951 18032bec Peter Maydell
        define_arm_cp_regs(cpu, vmsa_cp_reginfo);
1952 18032bec Peter Maydell
    }
1953 c326b979 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
1954 c326b979 Peter Maydell
        define_arm_cp_regs(cpu, t2ee_cp_reginfo);
1955 c326b979 Peter Maydell
    }
1956 6cc7a3ae Peter Maydell
    if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
1957 6cc7a3ae Peter Maydell
        define_arm_cp_regs(cpu, generic_timer_cp_reginfo);
1958 6cc7a3ae Peter Maydell
    }
1959 4a501606 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_VAPA)) {
1960 4a501606 Peter Maydell
        define_arm_cp_regs(cpu, vapa_cp_reginfo);
1961 4a501606 Peter Maydell
    }
1962 c4804214 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_CACHE_TEST_CLEAN)) {
1963 c4804214 Peter Maydell
        define_arm_cp_regs(cpu, cache_test_clean_cp_reginfo);
1964 c4804214 Peter Maydell
    }
1965 c4804214 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_CACHE_DIRTY_REG)) {
1966 c4804214 Peter Maydell
        define_arm_cp_regs(cpu, cache_dirty_status_cp_reginfo);
1967 c4804214 Peter Maydell
    }
1968 c4804214 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_CACHE_BLOCK_OPS)) {
1969 c4804214 Peter Maydell
        define_arm_cp_regs(cpu, cache_block_ops_cp_reginfo);
1970 c4804214 Peter Maydell
    }
1971 18032bec Peter Maydell
    if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
1972 18032bec Peter Maydell
        define_arm_cp_regs(cpu, omap_cp_reginfo);
1973 18032bec Peter Maydell
    }
1974 34f90529 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_STRONGARM)) {
1975 34f90529 Peter Maydell
        define_arm_cp_regs(cpu, strongarm_cp_reginfo);
1976 34f90529 Peter Maydell
    }
1977 1047b9d7 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_XSCALE)) {
1978 1047b9d7 Peter Maydell
        define_arm_cp_regs(cpu, xscale_cp_reginfo);
1979 1047b9d7 Peter Maydell
    }
1980 1047b9d7 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_DUMMY_C15_REGS)) {
1981 1047b9d7 Peter Maydell
        define_arm_cp_regs(cpu, dummy_c15_cp_reginfo);
1982 1047b9d7 Peter Maydell
    }
1983 7ac681cf Peter Maydell
    if (arm_feature(env, ARM_FEATURE_LPAE)) {
1984 7ac681cf Peter Maydell
        define_arm_cp_regs(cpu, lpae_cp_reginfo);
1985 7ac681cf Peter Maydell
    }
1986 7884849c Peter Maydell
    /* Slightly awkwardly, the OMAP and StrongARM cores need all of
1987 7884849c Peter Maydell
     * cp15 crn=0 to be writes-ignored, whereas for other cores they should
1988 7884849c Peter Maydell
     * be read-only (ie write causes UNDEF exception).
1989 7884849c Peter Maydell
     */
1990 7884849c Peter Maydell
    {
1991 7884849c Peter Maydell
        ARMCPRegInfo id_cp_reginfo[] = {
1992 7884849c Peter Maydell
            /* Note that the MIDR isn't a simple constant register because
1993 7884849c Peter Maydell
             * of the TI925 behaviour where writes to another register can
1994 7884849c Peter Maydell
             * cause the MIDR value to change.
1995 97ce8d61 Peter Crosthwaite
             *
1996 97ce8d61 Peter Crosthwaite
             * Unimplemented registers in the c15 0 0 0 space default to
1997 97ce8d61 Peter Crosthwaite
             * MIDR. Define MIDR first as this entire space, then CTR, TCMTR
1998 97ce8d61 Peter Crosthwaite
             * and friends override accordingly.
1999 7884849c Peter Maydell
             */
2000 7884849c Peter Maydell
            { .name = "MIDR",
2001 97ce8d61 Peter Crosthwaite
              .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = CP_ANY,
2002 7884849c Peter Maydell
              .access = PL1_R, .resetvalue = cpu->midr,
2003 d4e6df63 Peter Maydell
              .writefn = arm_cp_write_ignore, .raw_writefn = raw_write,
2004 97ce8d61 Peter Crosthwaite
              .fieldoffset = offsetof(CPUARMState, cp15.c0_cpuid),
2005 97ce8d61 Peter Crosthwaite
              .type = ARM_CP_OVERRIDE },
2006 cd4da631 Peter Maydell
            { .name = "MIDR_EL1", .state = ARM_CP_STATE_AA64,
2007 cd4da631 Peter Maydell
              .opc0 = 3, .opc1 = 0, .opc2 = 0, .crn = 0, .crm = 0,
2008 cd4da631 Peter Maydell
              .access = PL1_R, .resetvalue = cpu->midr, .type = ARM_CP_CONST },
2009 7884849c Peter Maydell
            { .name = "CTR",
2010 7884849c Peter Maydell
              .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 1,
2011 7884849c Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->ctr },
2012 7da845b0 Peter Maydell
            { .name = "CTR_EL0", .state = ARM_CP_STATE_AA64,
2013 7da845b0 Peter Maydell
              .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 0, .crm = 0,
2014 7da845b0 Peter Maydell
              .access = PL0_R, .accessfn = ctr_el0_access,
2015 7da845b0 Peter Maydell
              .type = ARM_CP_CONST, .resetvalue = cpu->ctr },
2016 7884849c Peter Maydell
            { .name = "TCMTR",
2017 7884849c Peter Maydell
              .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 2,
2018 7884849c Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
2019 7884849c Peter Maydell
            { .name = "TLBTR",
2020 7884849c Peter Maydell
              .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 3,
2021 7884849c Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
2022 7884849c Peter Maydell
            /* crn = 0 op1 = 0 crm = 3..7 : currently unassigned; we RAZ. */
2023 7884849c Peter Maydell
            { .name = "DUMMY",
2024 7884849c Peter Maydell
              .cp = 15, .crn = 0, .crm = 3, .opc1 = 0, .opc2 = CP_ANY,
2025 7884849c Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
2026 7884849c Peter Maydell
            { .name = "DUMMY",
2027 7884849c Peter Maydell
              .cp = 15, .crn = 0, .crm = 4, .opc1 = 0, .opc2 = CP_ANY,
2028 7884849c Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
2029 7884849c Peter Maydell
            { .name = "DUMMY",
2030 7884849c Peter Maydell
              .cp = 15, .crn = 0, .crm = 5, .opc1 = 0, .opc2 = CP_ANY,
2031 7884849c Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
2032 7884849c Peter Maydell
            { .name = "DUMMY",
2033 7884849c Peter Maydell
              .cp = 15, .crn = 0, .crm = 6, .opc1 = 0, .opc2 = CP_ANY,
2034 7884849c Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
2035 7884849c Peter Maydell
            { .name = "DUMMY",
2036 7884849c Peter Maydell
              .cp = 15, .crn = 0, .crm = 7, .opc1 = 0, .opc2 = CP_ANY,
2037 7884849c Peter Maydell
              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
2038 7884849c Peter Maydell
            REGINFO_SENTINEL
2039 7884849c Peter Maydell
        };
2040 7884849c Peter Maydell
        ARMCPRegInfo crn0_wi_reginfo = {
2041 7884849c Peter Maydell
            .name = "CRN0_WI", .cp = 15, .crn = 0, .crm = CP_ANY,
2042 7884849c Peter Maydell
            .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_W,
2043 7884849c Peter Maydell
            .type = ARM_CP_NOP | ARM_CP_OVERRIDE
2044 7884849c Peter Maydell
        };
2045 7884849c Peter Maydell
        if (arm_feature(env, ARM_FEATURE_OMAPCP) ||
2046 7884849c Peter Maydell
            arm_feature(env, ARM_FEATURE_STRONGARM)) {
2047 7884849c Peter Maydell
            ARMCPRegInfo *r;
2048 7884849c Peter Maydell
            /* Register the blanket "writes ignored" value first to cover the
2049 a703eda1 Peter Crosthwaite
             * whole space. Then update the specific ID registers to allow write
2050 a703eda1 Peter Crosthwaite
             * access, so that they ignore writes rather than causing them to
2051 a703eda1 Peter Crosthwaite
             * UNDEF.
2052 7884849c Peter Maydell
             */
2053 7884849c Peter Maydell
            define_one_arm_cp_reg(cpu, &crn0_wi_reginfo);
2054 7884849c Peter Maydell
            for (r = id_cp_reginfo; r->type != ARM_CP_SENTINEL; r++) {
2055 7884849c Peter Maydell
                r->access = PL1_RW;
2056 7884849c Peter Maydell
            }
2057 7884849c Peter Maydell
        }
2058 a703eda1 Peter Crosthwaite
        define_arm_cp_regs(cpu, id_cp_reginfo);
2059 7884849c Peter Maydell
    }
2060 7884849c Peter Maydell
2061 97ce8d61 Peter Crosthwaite
    if (arm_feature(env, ARM_FEATURE_MPIDR)) {
2062 97ce8d61 Peter Crosthwaite
        define_arm_cp_regs(cpu, mpidr_cp_reginfo);
2063 97ce8d61 Peter Crosthwaite
    }
2064 97ce8d61 Peter Crosthwaite
2065 2771db27 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_AUXCR)) {
2066 2771db27 Peter Maydell
        ARMCPRegInfo auxcr = {
2067 2771db27 Peter Maydell
            .name = "AUXCR", .cp = 15, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 1,
2068 2771db27 Peter Maydell
            .access = PL1_RW, .type = ARM_CP_CONST,
2069 2771db27 Peter Maydell
            .resetvalue = cpu->reset_auxcr
2070 2771db27 Peter Maydell
        };
2071 2771db27 Peter Maydell
        define_one_arm_cp_reg(cpu, &auxcr);
2072 2771db27 Peter Maydell
    }
2073 2771db27 Peter Maydell
2074 d8ba780b Peter Crosthwaite
    if (arm_feature(env, ARM_FEATURE_CBAR)) {
2075 d8ba780b Peter Crosthwaite
        ARMCPRegInfo cbar = {
2076 d8ba780b Peter Crosthwaite
            .name = "CBAR", .cp = 15, .crn = 15, .crm = 0, .opc1 = 4, .opc2 = 0,
2077 d8ba780b Peter Crosthwaite
            .access = PL1_R|PL3_W, .resetvalue = cpu->reset_cbar,
2078 d8ba780b Peter Crosthwaite
            .fieldoffset = offsetof(CPUARMState, cp15.c15_config_base_address)
2079 d8ba780b Peter Crosthwaite
        };
2080 d8ba780b Peter Crosthwaite
        define_one_arm_cp_reg(cpu, &cbar);
2081 d8ba780b Peter Crosthwaite
    }
2082 d8ba780b Peter Crosthwaite
2083 2771db27 Peter Maydell
    /* Generic registers whose values depend on the implementation */
2084 2771db27 Peter Maydell
    {
2085 2771db27 Peter Maydell
        ARMCPRegInfo sctlr = {
2086 5ebafdf3 Peter Maydell
            .name = "SCTLR", .state = ARM_CP_STATE_BOTH,
2087 5ebafdf3 Peter Maydell
            .opc0 = 3, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0,
2088 2771db27 Peter Maydell
            .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c1_sys),
2089 d4e6df63 Peter Maydell
            .writefn = sctlr_write, .resetvalue = cpu->reset_sctlr,
2090 d4e6df63 Peter Maydell
            .raw_writefn = raw_write,
2091 2771db27 Peter Maydell
        };
2092 2771db27 Peter Maydell
        if (arm_feature(env, ARM_FEATURE_XSCALE)) {
2093 2771db27 Peter Maydell
            /* Normally we would always end the TB on an SCTLR write, but Linux
2094 2771db27 Peter Maydell
             * arch/arm/mach-pxa/sleep.S expects two instructions following
2095 2771db27 Peter Maydell
             * an MMU enable to execute from cache.  Imitate this behaviour.
2096 2771db27 Peter Maydell
             */
2097 2771db27 Peter Maydell
            sctlr.type |= ARM_CP_SUPPRESS_TB_END;
2098 2771db27 Peter Maydell
        }
2099 2771db27 Peter Maydell
        define_one_arm_cp_reg(cpu, &sctlr);
2100 2771db27 Peter Maydell
    }
2101 2ceb98c0 Peter Maydell
}
2102 2ceb98c0 Peter Maydell
2103 778c3a06 Andreas Färber
ARMCPU *cpu_arm_init(const char *cpu_model)
2104 40f137e1 pbrook
{
2105 dec9c2d4 Andreas Färber
    ARMCPU *cpu;
2106 5900d6b2 Andreas Färber
    ObjectClass *oc;
2107 40f137e1 pbrook
2108 5900d6b2 Andreas Färber
    oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model);
2109 5900d6b2 Andreas Färber
    if (!oc) {
2110 aaed909a bellard
        return NULL;
2111 777dc784 Peter Maydell
    }
2112 5900d6b2 Andreas Färber
    cpu = ARM_CPU(object_new(object_class_get_name(oc)));
2113 14969266 Andreas Färber
2114 14969266 Andreas Färber
    /* TODO this should be set centrally, once possible */
2115 14969266 Andreas Färber
    object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
2116 777dc784 Peter Maydell
2117 14969266 Andreas Färber
    return cpu;
2118 14969266 Andreas Färber
}
2119 14969266 Andreas Färber
2120 14969266 Andreas Färber
void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
2121 14969266 Andreas Färber
{
2122 22169d41 Andreas Färber
    CPUState *cs = CPU(cpu);
2123 14969266 Andreas Färber
    CPUARMState *env = &cpu->env;
2124 14969266 Andreas Färber
2125 6a669427 Peter Maydell
    if (arm_feature(env, ARM_FEATURE_AARCH64)) {
2126 6a669427 Peter Maydell
        gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg,
2127 6a669427 Peter Maydell
                                 aarch64_fpu_gdb_set_reg,
2128 6a669427 Peter Maydell
                                 34, "aarch64-fpu.xml", 0);
2129 6a669427 Peter Maydell
    } else if (arm_feature(env, ARM_FEATURE_NEON)) {
2130 22169d41 Andreas Färber
        gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
2131 56aebc89 pbrook
                                 51, "arm-neon.xml", 0);
2132 56aebc89 pbrook
    } else if (arm_feature(env, ARM_FEATURE_VFP3)) {
2133 22169d41 Andreas Färber
        gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
2134 56aebc89 pbrook
                                 35, "arm-vfp3.xml", 0);
2135 56aebc89 pbrook
    } else if (arm_feature(env, ARM_FEATURE_VFP)) {
2136 22169d41 Andreas Färber
        gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
2137 56aebc89 pbrook
                                 19, "arm-vfp.xml", 0);
2138 56aebc89 pbrook
    }
2139 40f137e1 pbrook
}
2140 40f137e1 pbrook
2141 777dc784 Peter Maydell
/* Sort alphabetically by type name, except for "any". */
2142 777dc784 Peter Maydell
static gint arm_cpu_list_compare(gconstpointer a, gconstpointer b)
2143 5adb4839 pbrook
{
2144 777dc784 Peter Maydell
    ObjectClass *class_a = (ObjectClass *)a;
2145 777dc784 Peter Maydell
    ObjectClass *class_b = (ObjectClass *)b;
2146 777dc784 Peter Maydell
    const char *name_a, *name_b;
2147 5adb4839 pbrook
2148 777dc784 Peter Maydell
    name_a = object_class_get_name(class_a);
2149 777dc784 Peter Maydell
    name_b = object_class_get_name(class_b);
2150 51492fd1 Andreas Färber
    if (strcmp(name_a, "any-" TYPE_ARM_CPU) == 0) {
2151 777dc784 Peter Maydell
        return 1;
2152 51492fd1 Andreas Färber
    } else if (strcmp(name_b, "any-" TYPE_ARM_CPU) == 0) {
2153 777dc784 Peter Maydell
        return -1;
2154 777dc784 Peter Maydell
    } else {
2155 777dc784 Peter Maydell
        return strcmp(name_a, name_b);
2156 5adb4839 pbrook
    }
2157 5adb4839 pbrook
}
2158 5adb4839 pbrook
2159 777dc784 Peter Maydell
static void arm_cpu_list_entry(gpointer data, gpointer user_data)
2160 40f137e1 pbrook
{
2161 777dc784 Peter Maydell
    ObjectClass *oc = data;
2162 92a31361 Andreas Färber
    CPUListState *s = user_data;
2163 51492fd1 Andreas Färber
    const char *typename;
2164 51492fd1 Andreas Färber
    char *name;
2165 3371d272 pbrook
2166 51492fd1 Andreas Färber
    typename = object_class_get_name(oc);
2167 51492fd1 Andreas Färber
    name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_ARM_CPU));
2168 777dc784 Peter Maydell
    (*s->cpu_fprintf)(s->file, "  %s\n",
2169 51492fd1 Andreas Färber
                      name);
2170 51492fd1 Andreas Färber
    g_free(name);
2171 777dc784 Peter Maydell
}
2172 777dc784 Peter Maydell
2173 777dc784 Peter Maydell
void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf)
2174 777dc784 Peter Maydell
{
2175 92a31361 Andreas Färber
    CPUListState s = {
2176 777dc784 Peter Maydell
        .file = f,
2177 777dc784 Peter Maydell
        .cpu_fprintf = cpu_fprintf,
2178 777dc784 Peter Maydell
    };
2179 777dc784 Peter Maydell
    GSList *list;
2180 777dc784 Peter Maydell
2181 777dc784 Peter Maydell
    list = object_class_get_list(TYPE_ARM_CPU, false);
2182 777dc784 Peter Maydell
    list = g_slist_sort(list, arm_cpu_list_compare);
2183 777dc784 Peter Maydell
    (*cpu_fprintf)(f, "Available CPUs:\n");
2184 777dc784 Peter Maydell
    g_slist_foreach(list, arm_cpu_list_entry, &s);
2185 777dc784 Peter Maydell
    g_slist_free(list);
2186 a96c0514 Peter Maydell
#ifdef CONFIG_KVM
2187 a96c0514 Peter Maydell
    /* The 'host' CPU type is dynamically registered only if KVM is
2188 a96c0514 Peter Maydell
     * enabled, so we have to special-case it here:
2189 a96c0514 Peter Maydell
     */
2190 a96c0514 Peter Maydell
    (*cpu_fprintf)(f, "  host (only available in KVM mode)\n");
2191 a96c0514 Peter Maydell
#endif
2192 40f137e1 pbrook
}
2193 40f137e1 pbrook
2194 78027bb6 Cole Robinson
static void arm_cpu_add_definition(gpointer data, gpointer user_data)
2195 78027bb6 Cole Robinson
{
2196 78027bb6 Cole Robinson
    ObjectClass *oc = data;
2197 78027bb6 Cole Robinson
    CpuDefinitionInfoList **cpu_list = user_data;
2198 78027bb6 Cole Robinson
    CpuDefinitionInfoList *entry;
2199 78027bb6 Cole Robinson
    CpuDefinitionInfo *info;
2200 78027bb6 Cole Robinson
    const char *typename;
2201 78027bb6 Cole Robinson
2202 78027bb6 Cole Robinson
    typename = object_class_get_name(oc);
2203 78027bb6 Cole Robinson
    info = g_malloc0(sizeof(*info));
2204 78027bb6 Cole Robinson
    info->name = g_strndup(typename,
2205 78027bb6 Cole Robinson
                           strlen(typename) - strlen("-" TYPE_ARM_CPU));
2206 78027bb6 Cole Robinson
2207 78027bb6 Cole Robinson
    entry = g_malloc0(sizeof(*entry));
2208 78027bb6 Cole Robinson
    entry->value = info;
2209 78027bb6 Cole Robinson
    entry->next = *cpu_list;
2210 78027bb6 Cole Robinson
    *cpu_list = entry;
2211 78027bb6 Cole Robinson
}
2212 78027bb6 Cole Robinson
2213 78027bb6 Cole Robinson
CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
2214 78027bb6 Cole Robinson
{
2215 78027bb6 Cole Robinson
    CpuDefinitionInfoList *cpu_list = NULL;
2216 78027bb6 Cole Robinson
    GSList *list;
2217 78027bb6 Cole Robinson
2218 78027bb6 Cole Robinson
    list = object_class_get_list(TYPE_ARM_CPU, false);
2219 78027bb6 Cole Robinson
    g_slist_foreach(list, arm_cpu_add_definition, &cpu_list);
2220 78027bb6 Cole Robinson
    g_slist_free(list);
2221 78027bb6 Cole Robinson
2222 78027bb6 Cole Robinson
    return cpu_list;
2223 78027bb6 Cole Robinson
}
2224 78027bb6 Cole Robinson
2225 6e6efd61 Peter Maydell
static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
2226 f5a0a5a5 Peter Maydell
                                   void *opaque, int state,
2227 f5a0a5a5 Peter Maydell
                                   int crm, int opc1, int opc2)
2228 6e6efd61 Peter Maydell
{
2229 6e6efd61 Peter Maydell
    /* Private utility function for define_one_arm_cp_reg_with_opaque():
2230 6e6efd61 Peter Maydell
     * add a single reginfo struct to the hash table.
2231 6e6efd61 Peter Maydell
     */
2232 6e6efd61 Peter Maydell
    uint32_t *key = g_new(uint32_t, 1);
2233 6e6efd61 Peter Maydell
    ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
2234 6e6efd61 Peter Maydell
    int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
2235 f5a0a5a5 Peter Maydell
    if (r->state == ARM_CP_STATE_BOTH && state == ARM_CP_STATE_AA32) {
2236 f5a0a5a5 Peter Maydell
        /* The AArch32 view of a shared register sees the lower 32 bits
2237 f5a0a5a5 Peter Maydell
         * of a 64 bit backing field. It is not migratable as the AArch64
2238 f5a0a5a5 Peter Maydell
         * view handles that. AArch64 also handles reset.
2239 f5a0a5a5 Peter Maydell
         * We assume it is a cp15 register.
2240 f5a0a5a5 Peter Maydell
         */
2241 f5a0a5a5 Peter Maydell
        r2->cp = 15;
2242 f5a0a5a5 Peter Maydell
        r2->type |= ARM_CP_NO_MIGRATE;
2243 f5a0a5a5 Peter Maydell
        r2->resetfn = arm_cp_reset_ignore;
2244 f5a0a5a5 Peter Maydell
#ifdef HOST_WORDS_BIGENDIAN
2245 f5a0a5a5 Peter Maydell
        if (r2->fieldoffset) {
2246 f5a0a5a5 Peter Maydell
            r2->fieldoffset += sizeof(uint32_t);
2247 f5a0a5a5 Peter Maydell
        }
2248 f5a0a5a5 Peter Maydell
#endif
2249 f5a0a5a5 Peter Maydell
    }
2250 f5a0a5a5 Peter Maydell
    if (state == ARM_CP_STATE_AA64) {
2251 f5a0a5a5 Peter Maydell
        /* To allow abbreviation of ARMCPRegInfo
2252 f5a0a5a5 Peter Maydell
         * definitions, we treat cp == 0 as equivalent to
2253 f5a0a5a5 Peter Maydell
         * the value for "standard guest-visible sysreg".
2254 f5a0a5a5 Peter Maydell
         */
2255 f5a0a5a5 Peter Maydell
        if (r->cp == 0) {
2256 f5a0a5a5 Peter Maydell
            r2->cp = CP_REG_ARM64_SYSREG_CP;
2257 f5a0a5a5 Peter Maydell
        }
2258 f5a0a5a5 Peter Maydell
        *key = ENCODE_AA64_CP_REG(r2->cp, r2->crn, crm,
2259 f5a0a5a5 Peter Maydell
                                  r2->opc0, opc1, opc2);
2260 f5a0a5a5 Peter Maydell
    } else {
2261 f5a0a5a5 Peter Maydell
        *key = ENCODE_CP_REG(r2->cp, is64, r2->crn, crm, opc1, opc2);
2262 f5a0a5a5 Peter Maydell
    }
2263 6e6efd61 Peter Maydell
    if (opaque) {
2264 6e6efd61 Peter Maydell
        r2->opaque = opaque;
2265 6e6efd61 Peter Maydell
    }
2266 67ed771d Peter Maydell
    /* reginfo passed to helpers is correct for the actual access,
2267 67ed771d Peter Maydell
     * and is never ARM_CP_STATE_BOTH:
2268 67ed771d Peter Maydell
     */
2269 67ed771d Peter Maydell
    r2->state = state;
2270 6e6efd61 Peter Maydell
    /* Make sure reginfo passed to helpers for wildcarded regs
2271 6e6efd61 Peter Maydell
     * has the correct crm/opc1/opc2 for this reg, not CP_ANY:
2272 6e6efd61 Peter Maydell
     */
2273 6e6efd61 Peter Maydell
    r2->crm = crm;
2274 6e6efd61 Peter Maydell
    r2->opc1 = opc1;
2275 6e6efd61 Peter Maydell
    r2->opc2 = opc2;
2276 6e6efd61 Peter Maydell
    /* By convention, for wildcarded registers only the first
2277 6e6efd61 Peter Maydell
     * entry is used for migration; the others are marked as
2278 6e6efd61 Peter Maydell
     * NO_MIGRATE so we don't try to transfer the register
2279 6e6efd61 Peter Maydell
     * multiple times. Special registers (ie NOP/WFI) are
2280 6e6efd61 Peter Maydell
     * never migratable.
2281 6e6efd61 Peter Maydell
     */
2282 6e6efd61 Peter Maydell
    if ((r->type & ARM_CP_SPECIAL) ||
2283 6e6efd61 Peter Maydell
        ((r->crm == CP_ANY) && crm != 0) ||
2284 6e6efd61 Peter Maydell
        ((r->opc1 == CP_ANY) && opc1 != 0) ||
2285 6e6efd61 Peter Maydell
        ((r->opc2 == CP_ANY) && opc2 != 0)) {
2286 6e6efd61 Peter Maydell
        r2->type |= ARM_CP_NO_MIGRATE;
2287 6e6efd61 Peter Maydell
    }
2288 6e6efd61 Peter Maydell
2289 6e6efd61 Peter Maydell
    /* Overriding of an existing definition must be explicitly
2290 6e6efd61 Peter Maydell
     * requested.
2291 6e6efd61 Peter Maydell
     */
2292 6e6efd61 Peter Maydell
    if (!(r->type & ARM_CP_OVERRIDE)) {
2293 6e6efd61 Peter Maydell
        ARMCPRegInfo *oldreg;
2294 6e6efd61 Peter Maydell
        oldreg = g_hash_table_lookup(cpu->cp_regs, key);
2295 6e6efd61 Peter Maydell
        if (oldreg && !(oldreg->type & ARM_CP_OVERRIDE)) {
2296 6e6efd61 Peter Maydell
            fprintf(stderr, "Register redefined: cp=%d %d bit "
2297 6e6efd61 Peter Maydell
                    "crn=%d crm=%d opc1=%d opc2=%d, "
2298 6e6efd61 Peter Maydell
                    "was %s, now %s\n", r2->cp, 32 + 32 * is64,
2299 6e6efd61 Peter Maydell
                    r2->crn, r2->crm, r2->opc1, r2->opc2,
2300 6e6efd61 Peter Maydell
                    oldreg->name, r2->name);
2301 6e6efd61 Peter Maydell
            g_assert_not_reached();
2302 6e6efd61 Peter Maydell
        }
2303 6e6efd61 Peter Maydell
    }
2304 6e6efd61 Peter Maydell
    g_hash_table_insert(cpu->cp_regs, key, r2);
2305 6e6efd61 Peter Maydell
}
2306 6e6efd61 Peter Maydell
2307 6e6efd61 Peter Maydell
2308 4b6a83fb Peter Maydell
void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
2309 4b6a83fb Peter Maydell
                                       const ARMCPRegInfo *r, void *opaque)
2310 4b6a83fb Peter Maydell
{
2311 4b6a83fb Peter Maydell
    /* Define implementations of coprocessor registers.
2312 4b6a83fb Peter Maydell
     * We store these in a hashtable because typically
2313 4b6a83fb Peter Maydell
     * there are less than 150 registers in a space which
2314 4b6a83fb Peter Maydell
     * is 16*16*16*8*8 = 262144 in size.
2315 4b6a83fb Peter Maydell
     * Wildcarding is supported for the crm, opc1 and opc2 fields.
2316 4b6a83fb Peter Maydell
     * If a register is defined twice then the second definition is
2317 4b6a83fb Peter Maydell
     * used, so this can be used to define some generic registers and
2318 4b6a83fb Peter Maydell
     * then override them with implementation specific variations.
2319 4b6a83fb Peter Maydell
     * At least one of the original and the second definition should
2320 4b6a83fb Peter Maydell
     * include ARM_CP_OVERRIDE in its type bits -- this is just a guard
2321 4b6a83fb Peter Maydell
     * against accidental use.
2322 f5a0a5a5 Peter Maydell
     *
2323 f5a0a5a5 Peter Maydell
     * The state field defines whether the register is to be
2324 f5a0a5a5 Peter Maydell
     * visible in the AArch32 or AArch64 execution state. If the
2325 f5a0a5a5 Peter Maydell
     * state is set to ARM_CP_STATE_BOTH then we synthesise a
2326 f5a0a5a5 Peter Maydell
     * reginfo structure for the AArch32 view, which sees the lower
2327 f5a0a5a5 Peter Maydell
     * 32 bits of the 64 bit register.
2328 f5a0a5a5 Peter Maydell
     *
2329 f5a0a5a5 Peter Maydell
     * Only registers visible in AArch64 may set r->opc0; opc0 cannot
2330 f5a0a5a5 Peter Maydell
     * be wildcarded. AArch64 registers are always considered to be 64
2331 f5a0a5a5 Peter Maydell
     * bits; the ARM_CP_64BIT* flag applies only to the AArch32 view of
2332 f5a0a5a5 Peter Maydell
     * the register, if any.
2333 4b6a83fb Peter Maydell
     */
2334 f5a0a5a5 Peter Maydell
    int crm, opc1, opc2, state;
2335 4b6a83fb Peter Maydell
    int crmmin = (r->crm == CP_ANY) ? 0 : r->crm;
2336 4b6a83fb Peter Maydell
    int crmmax = (r->crm == CP_ANY) ? 15 : r->crm;
2337 4b6a83fb Peter Maydell
    int opc1min = (r->opc1 == CP_ANY) ? 0 : r->opc1;
2338 4b6a83fb Peter Maydell
    int opc1max = (r->opc1 == CP_ANY) ? 7 : r->opc1;
2339 4b6a83fb Peter Maydell
    int opc2min = (r->opc2 == CP_ANY) ? 0 : r->opc2;
2340 4b6a83fb Peter Maydell
    int opc2max = (r->opc2 == CP_ANY) ? 7 : r->opc2;
2341 4b6a83fb Peter Maydell
    /* 64 bit registers have only CRm and Opc1 fields */
2342 4b6a83fb Peter Maydell
    assert(!((r->type & ARM_CP_64BIT) && (r->opc2 || r->crn)));
2343 f5a0a5a5 Peter Maydell
    /* op0 only exists in the AArch64 encodings */
2344 f5a0a5a5 Peter Maydell
    assert((r->state != ARM_CP_STATE_AA32) || (r->opc0 == 0));
2345 f5a0a5a5 Peter Maydell
    /* AArch64 regs are all 64 bit so ARM_CP_64BIT is meaningless */
2346 f5a0a5a5 Peter Maydell
    assert((r->state != ARM_CP_STATE_AA64) || !(r->type & ARM_CP_64BIT));
2347 f5a0a5a5 Peter Maydell
    /* The AArch64 pseudocode CheckSystemAccess() specifies that op1
2348 f5a0a5a5 Peter Maydell
     * encodes a minimum access level for the register. We roll this
2349 f5a0a5a5 Peter Maydell
     * runtime check into our general permission check code, so check
2350 f5a0a5a5 Peter Maydell
     * here that the reginfo's specified permissions are strict enough
2351 f5a0a5a5 Peter Maydell
     * to encompass the generic architectural permission check.
2352 f5a0a5a5 Peter Maydell
     */
2353 f5a0a5a5 Peter Maydell
    if (r->state != ARM_CP_STATE_AA32) {
2354 f5a0a5a5 Peter Maydell
        int mask = 0;
2355 f5a0a5a5 Peter Maydell
        switch (r->opc1) {
2356 f5a0a5a5 Peter Maydell
        case 0: case 1: case 2:
2357 f5a0a5a5 Peter Maydell
            /* min_EL EL1 */
2358 f5a0a5a5 Peter Maydell
            mask = PL1_RW;
2359 f5a0a5a5 Peter Maydell
            break;
2360 f5a0a5a5 Peter Maydell
        case 3:
2361 f5a0a5a5 Peter Maydell
            /* min_EL EL0 */
2362 f5a0a5a5 Peter Maydell
            mask = PL0_RW;
2363 f5a0a5a5 Peter Maydell
            break;
2364 f5a0a5a5 Peter Maydell
        case 4:
2365 f5a0a5a5 Peter Maydell
            /* min_EL EL2 */
2366 f5a0a5a5 Peter Maydell
            mask = PL2_RW;
2367 f5a0a5a5 Peter Maydell
            break;
2368 f5a0a5a5 Peter Maydell
        case 5:
2369 f5a0a5a5 Peter Maydell
            /* unallocated encoding, so not possible */
2370 f5a0a5a5 Peter Maydell
            assert(false);
2371 f5a0a5a5 Peter Maydell
            break;
2372 f5a0a5a5 Peter Maydell
        case 6:
2373 f5a0a5a5 Peter Maydell
            /* min_EL EL3 */
2374 f5a0a5a5 Peter Maydell
            mask = PL3_RW;
2375 f5a0a5a5 Peter Maydell
            break;
2376 f5a0a5a5 Peter Maydell
        case 7:
2377 f5a0a5a5 Peter Maydell
            /* min_EL EL1, secure mode only (we don't check the latter) */
2378 f5a0a5a5 Peter Maydell
            mask = PL1_RW;
2379 f5a0a5a5 Peter Maydell
            break;
2380 f5a0a5a5 Peter Maydell
        default:
2381 f5a0a5a5 Peter Maydell
            /* broken reginfo with out-of-range opc1 */
2382 f5a0a5a5 Peter Maydell
            assert(false);
2383 f5a0a5a5 Peter Maydell
            break;
2384 f5a0a5a5 Peter Maydell
        }
2385 f5a0a5a5 Peter Maydell
        /* assert our permissions are not too lax (stricter is fine) */
2386 f5a0a5a5 Peter Maydell
        assert((r->access & ~mask) == 0);
2387 f5a0a5a5 Peter Maydell
    }
2388 f5a0a5a5 Peter Maydell
2389 4b6a83fb Peter Maydell
    /* Check that the register definition has enough info to handle
2390 4b6a83fb Peter Maydell
     * reads and writes if they are permitted.
2391 4b6a83fb Peter Maydell
     */
2392 4b6a83fb Peter Maydell
    if (!(r->type & (ARM_CP_SPECIAL|ARM_CP_CONST))) {
2393 4b6a83fb Peter Maydell
        if (r->access & PL3_R) {
2394 4b6a83fb Peter Maydell
            assert(r->fieldoffset || r->readfn);
2395 4b6a83fb Peter Maydell
        }
2396 4b6a83fb Peter Maydell
        if (r->access & PL3_W) {
2397 4b6a83fb Peter Maydell
            assert(r->fieldoffset || r->writefn);
2398 4b6a83fb Peter Maydell
        }
2399 4b6a83fb Peter Maydell
    }
2400 4b6a83fb Peter Maydell
    /* Bad type field probably means missing sentinel at end of reg list */
2401 4b6a83fb Peter Maydell
    assert(cptype_valid(r->type));
2402 4b6a83fb Peter Maydell
    for (crm = crmmin; crm <= crmmax; crm++) {
2403 4b6a83fb Peter Maydell
        for (opc1 = opc1min; opc1 <= opc1max; opc1++) {
2404 4b6a83fb Peter Maydell
            for (opc2 = opc2min; opc2 <= opc2max; opc2++) {
2405 f5a0a5a5 Peter Maydell
                for (state = ARM_CP_STATE_AA32;
2406 f5a0a5a5 Peter Maydell
                     state <= ARM_CP_STATE_AA64; state++) {
2407 f5a0a5a5 Peter Maydell
                    if (r->state != state && r->state != ARM_CP_STATE_BOTH) {
2408 f5a0a5a5 Peter Maydell
                        continue;
2409 f5a0a5a5 Peter Maydell
                    }
2410 f5a0a5a5 Peter Maydell
                    add_cpreg_to_hashtable(cpu, r, opaque, state,
2411 f5a0a5a5 Peter Maydell
                                           crm, opc1, opc2);
2412 f5a0a5a5 Peter Maydell
                }
2413 4b6a83fb Peter Maydell
            }
2414 4b6a83fb Peter Maydell
        }
2415 4b6a83fb Peter Maydell
    }
2416 4b6a83fb Peter Maydell
}
2417 4b6a83fb Peter Maydell
2418 4b6a83fb Peter Maydell
void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
2419 4b6a83fb Peter Maydell
                                    const ARMCPRegInfo *regs, void *opaque)
2420 4b6a83fb Peter Maydell
{
2421 4b6a83fb Peter Maydell
    /* Define a whole list of registers */
2422 4b6a83fb Peter Maydell
    const ARMCPRegInfo *r;
2423 4b6a83fb Peter Maydell
    for (r = regs; r->type != ARM_CP_SENTINEL; r++) {
2424 4b6a83fb Peter Maydell
        define_one_arm_cp_reg_with_opaque(cpu, r, opaque);
2425 4b6a83fb Peter Maydell
    }
2426 4b6a83fb Peter Maydell
}
2427 4b6a83fb Peter Maydell
2428 60322b39 Peter Maydell
const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encoded_cp)
2429 4b6a83fb Peter Maydell
{
2430 60322b39 Peter Maydell
    return g_hash_table_lookup(cpregs, &encoded_cp);
2431 4b6a83fb Peter Maydell
}
2432 4b6a83fb Peter Maydell
2433 c4241c7d Peter Maydell
void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
2434 c4241c7d Peter Maydell
                         uint64_t value)
2435 4b6a83fb Peter Maydell
{
2436 4b6a83fb Peter Maydell
    /* Helper coprocessor write function for write-ignore registers */
2437 4b6a83fb Peter Maydell
}
2438 4b6a83fb Peter Maydell
2439 c4241c7d Peter Maydell
uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri)
2440 4b6a83fb Peter Maydell
{
2441 4b6a83fb Peter Maydell
    /* Helper coprocessor write function for read-as-zero registers */
2442 4b6a83fb Peter Maydell
    return 0;
2443 4b6a83fb Peter Maydell
}
2444 4b6a83fb Peter Maydell
2445 f5a0a5a5 Peter Maydell
void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque)
2446 f5a0a5a5 Peter Maydell
{
2447 f5a0a5a5 Peter Maydell
    /* Helper coprocessor reset function for do-nothing-on-reset registers */
2448 f5a0a5a5 Peter Maydell
}
2449 f5a0a5a5 Peter Maydell
2450 0ecb72a5 Andreas Färber
static int bad_mode_switch(CPUARMState *env, int mode)
2451 37064a8b Peter Maydell
{
2452 37064a8b Peter Maydell
    /* Return true if it is not valid for us to switch to
2453 37064a8b Peter Maydell
     * this CPU mode (ie all the UNPREDICTABLE cases in
2454 37064a8b Peter Maydell
     * the ARM ARM CPSRWriteByInstr pseudocode).
2455 37064a8b Peter Maydell
     */
2456 37064a8b Peter Maydell
    switch (mode) {
2457 37064a8b Peter Maydell
    case ARM_CPU_MODE_USR:
2458 37064a8b Peter Maydell
    case ARM_CPU_MODE_SYS:
2459 37064a8b Peter Maydell
    case ARM_CPU_MODE_SVC:
2460 37064a8b Peter Maydell
    case ARM_CPU_MODE_ABT:
2461 37064a8b Peter Maydell
    case ARM_CPU_MODE_UND:
2462 37064a8b Peter Maydell
    case ARM_CPU_MODE_IRQ:
2463 37064a8b Peter Maydell
    case ARM_CPU_MODE_FIQ:
2464 37064a8b Peter Maydell
        return 0;
2465 37064a8b Peter Maydell
    default:
2466 37064a8b Peter Maydell
        return 1;
2467 37064a8b Peter Maydell
    }
2468 37064a8b Peter Maydell
}
2469 37064a8b Peter Maydell
2470 2f4a40e5 balrog
uint32_t cpsr_read(CPUARMState *env)
2471 2f4a40e5 balrog
{
2472 2f4a40e5 balrog
    int ZF;
2473 6fbe23d5 pbrook
    ZF = (env->ZF == 0);
2474 6fbe23d5 pbrook
    return env->uncached_cpsr | (env->NF & 0x80000000) | (ZF << 30) |
2475 2f4a40e5 balrog
        (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
2476 2f4a40e5 balrog
        | (env->thumb << 5) | ((env->condexec_bits & 3) << 25)
2477 2f4a40e5 balrog
        | ((env->condexec_bits & 0xfc) << 8)
2478 4cc35614 Peter Maydell
        | (env->GE << 16) | env->daif;
2479 2f4a40e5 balrog
}
2480 2f4a40e5 balrog
2481 2f4a40e5 balrog
void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
2482 2f4a40e5 balrog
{
2483 2f4a40e5 balrog
    if (mask & CPSR_NZCV) {
2484 6fbe23d5 pbrook
        env->ZF = (~val) & CPSR_Z;
2485 6fbe23d5 pbrook
        env->NF = val;
2486 2f4a40e5 balrog
        env->CF = (val >> 29) & 1;
2487 2f4a40e5 balrog
        env->VF = (val << 3) & 0x80000000;
2488 2f4a40e5 balrog
    }
2489 2f4a40e5 balrog
    if (mask & CPSR_Q)
2490 2f4a40e5 balrog
        env->QF = ((val & CPSR_Q) != 0);
2491 2f4a40e5 balrog
    if (mask & CPSR_T)
2492 2f4a40e5 balrog
        env->thumb = ((val & CPSR_T) != 0);
2493 2f4a40e5 balrog
    if (mask & CPSR_IT_0_1) {
2494 2f4a40e5 balrog
        env->condexec_bits &= ~3;
2495 2f4a40e5 balrog
        env->condexec_bits |= (val >> 25) & 3;
2496 2f4a40e5 balrog
    }
2497 2f4a40e5 balrog
    if (mask & CPSR_IT_2_7) {
2498 2f4a40e5 balrog
        env->condexec_bits &= 3;
2499 2f4a40e5 balrog
        env->condexec_bits |= (val >> 8) & 0xfc;
2500 2f4a40e5 balrog
    }
2501 2f4a40e5 balrog
    if (mask & CPSR_GE) {
2502 2f4a40e5 balrog
        env->GE = (val >> 16) & 0xf;
2503 2f4a40e5 balrog
    }
2504 2f4a40e5 balrog
2505 4cc35614 Peter Maydell
    env->daif &= ~(CPSR_AIF & mask);
2506 4cc35614 Peter Maydell
    env->daif |= val & CPSR_AIF & mask;
2507 4cc35614 Peter Maydell
2508 2f4a40e5 balrog
    if ((env->uncached_cpsr ^ val) & mask & CPSR_M) {
2509 37064a8b Peter Maydell
        if (bad_mode_switch(env, val & CPSR_M)) {
2510 37064a8b Peter Maydell
            /* Attempt to switch to an invalid mode: this is UNPREDICTABLE.
2511 37064a8b Peter Maydell
             * We choose to ignore the attempt and leave the CPSR M field
2512 37064a8b Peter Maydell
             * untouched.
2513 37064a8b Peter Maydell
             */
2514 37064a8b Peter Maydell
            mask &= ~CPSR_M;
2515 37064a8b Peter Maydell
        } else {
2516 37064a8b Peter Maydell
            switch_mode(env, val & CPSR_M);
2517 37064a8b Peter Maydell
        }
2518 2f4a40e5 balrog
    }
2519 2f4a40e5 balrog
    mask &= ~CACHED_CPSR_BITS;
2520 2f4a40e5 balrog
    env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask);
2521 2f4a40e5 balrog
}
2522 2f4a40e5 balrog
2523 b26eefb6 pbrook
/* Sign/zero extend */
2524 b26eefb6 pbrook
uint32_t HELPER(sxtb16)(uint32_t x)
2525 b26eefb6 pbrook
{
2526 b26eefb6 pbrook
    uint32_t res;
2527 b26eefb6 pbrook
    res = (uint16_t)(int8_t)x;
2528 b26eefb6 pbrook
    res |= (uint32_t)(int8_t)(x >> 16) << 16;
2529 b26eefb6 pbrook
    return res;
2530 b26eefb6 pbrook
}
2531 b26eefb6 pbrook
2532 b26eefb6 pbrook
uint32_t HELPER(uxtb16)(uint32_t x)
2533 b26eefb6 pbrook
{
2534 b26eefb6 pbrook
    uint32_t res;
2535 b26eefb6 pbrook
    res = (uint16_t)(uint8_t)x;
2536 b26eefb6 pbrook
    res |= (uint32_t)(uint8_t)(x >> 16) << 16;
2537 b26eefb6 pbrook
    return res;
2538 b26eefb6 pbrook
}
2539 b26eefb6 pbrook
2540 f51bbbfe pbrook
uint32_t HELPER(clz)(uint32_t x)
2541 f51bbbfe pbrook
{
2542 7bbcb0af Aurelien Jarno
    return clz32(x);
2543 f51bbbfe pbrook
}
2544 f51bbbfe pbrook
2545 3670669c pbrook
int32_t HELPER(sdiv)(int32_t num, int32_t den)
2546 3670669c pbrook
{
2547 3670669c pbrook
    if (den == 0)
2548 3670669c pbrook
      return 0;
2549 686eeb93 Aurelien Jarno
    if (num == INT_MIN && den == -1)
2550 686eeb93 Aurelien Jarno
      return INT_MIN;
2551 3670669c pbrook
    return num / den;
2552 3670669c pbrook
}
2553 3670669c pbrook
2554 3670669c pbrook
uint32_t HELPER(udiv)(uint32_t num, uint32_t den)
2555 3670669c pbrook
{
2556 3670669c pbrook
    if (den == 0)
2557 3670669c pbrook
      return 0;
2558 3670669c pbrook
    return num / den;
2559 3670669c pbrook
}
2560 3670669c pbrook
2561 3670669c pbrook
uint32_t HELPER(rbit)(uint32_t x)
2562 3670669c pbrook
{
2563 3670669c pbrook
    x =  ((x & 0xff000000) >> 24)
2564 3670669c pbrook
       | ((x & 0x00ff0000) >> 8)
2565 3670669c pbrook
       | ((x & 0x0000ff00) << 8)
2566 3670669c pbrook
       | ((x & 0x000000ff) << 24);
2567 3670669c pbrook
    x =  ((x & 0xf0f0f0f0) >> 4)
2568 3670669c pbrook
       | ((x & 0x0f0f0f0f) << 4);
2569 3670669c pbrook
    x =  ((x & 0x88888888) >> 3)
2570 3670669c pbrook
       | ((x & 0x44444444) >> 1)
2571 3670669c pbrook
       | ((x & 0x22222222) << 1)
2572 3670669c pbrook
       | ((x & 0x11111111) << 3);
2573 3670669c pbrook
    return x;
2574 3670669c pbrook
}
2575 3670669c pbrook
2576 5fafdf24 ths
#if defined(CONFIG_USER_ONLY)
2577 b5ff1b31 bellard
2578 97a8ea5a Andreas Färber
void arm_cpu_do_interrupt(CPUState *cs)
2579 b5ff1b31 bellard
{
2580 97a8ea5a Andreas Färber
    ARMCPU *cpu = ARM_CPU(cs);
2581 97a8ea5a Andreas Färber
    CPUARMState *env = &cpu->env;
2582 97a8ea5a Andreas Färber
2583 b5ff1b31 bellard
    env->exception_index = -1;
2584 b5ff1b31 bellard
}
2585 b5ff1b31 bellard
2586 0ecb72a5 Andreas Färber
int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw,
2587 97b348e7 Blue Swirl
                              int mmu_idx)
2588 b5ff1b31 bellard
{
2589 b5ff1b31 bellard
    if (rw == 2) {
2590 b5ff1b31 bellard
        env->exception_index = EXCP_PREFETCH_ABORT;
2591 b5ff1b31 bellard
        env->cp15.c6_insn = address;
2592 b5ff1b31 bellard
    } else {
2593 b5ff1b31 bellard
        env->exception_index = EXCP_DATA_ABORT;
2594 b5ff1b31 bellard
        env->cp15.c6_data = address;
2595 b5ff1b31 bellard
    }
2596 b5ff1b31 bellard
    return 1;
2597 b5ff1b31 bellard
}
2598 b5ff1b31 bellard
2599 9ee6e8bb pbrook
/* These should probably raise undefined insn exceptions.  */
2600 0ecb72a5 Andreas Färber
void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
2601 9ee6e8bb pbrook
{
2602 9ee6e8bb pbrook
    cpu_abort(env, "v7m_mrs %d\n", reg);
2603 9ee6e8bb pbrook
}
2604 9ee6e8bb pbrook
2605 0ecb72a5 Andreas Färber
uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
2606 9ee6e8bb pbrook
{
2607 9ee6e8bb pbrook
    cpu_abort(env, "v7m_mrs %d\n", reg);
2608 9ee6e8bb pbrook
    return 0;
2609 9ee6e8bb pbrook
}
2610 9ee6e8bb pbrook
2611 0ecb72a5 Andreas Färber
void switch_mode(CPUARMState *env, int mode)
2612 b5ff1b31 bellard
{
2613 b5ff1b31 bellard
    if (mode != ARM_CPU_MODE_USR)
2614 b5ff1b31 bellard
        cpu_abort(env, "Tried to switch out of user mode\n");
2615 b5ff1b31 bellard
}
2616 b5ff1b31 bellard
2617 0ecb72a5 Andreas Färber
void HELPER(set_r13_banked)(CPUARMState *env, uint32_t mode, uint32_t val)
2618 9ee6e8bb pbrook
{
2619 9ee6e8bb pbrook
    cpu_abort(env, "banked r13 write\n");
2620 9ee6e8bb pbrook
}
2621 9ee6e8bb pbrook
2622 0ecb72a5 Andreas Färber
uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode)
2623 9ee6e8bb pbrook
{
2624 9ee6e8bb pbrook
    cpu_abort(env, "banked r13 read\n");
2625 9ee6e8bb pbrook
    return 0;
2626 9ee6e8bb pbrook
}
2627 9ee6e8bb pbrook
2628 b5ff1b31 bellard
#else
2629 b5ff1b31 bellard
2630 b5ff1b31 bellard
/* Map CPU modes onto saved register banks.  */
2631 494b00c7 Christoffer Dall
int bank_number(int mode)
2632 b5ff1b31 bellard
{
2633 b5ff1b31 bellard
    switch (mode) {
2634 b5ff1b31 bellard
    case ARM_CPU_MODE_USR:
2635 b5ff1b31 bellard
    case ARM_CPU_MODE_SYS:
2636 b5ff1b31 bellard
        return 0;
2637 b5ff1b31 bellard
    case ARM_CPU_MODE_SVC:
2638 b5ff1b31 bellard
        return 1;
2639 b5ff1b31 bellard
    case ARM_CPU_MODE_ABT:
2640 b5ff1b31 bellard
        return 2;
2641 b5ff1b31 bellard
    case ARM_CPU_MODE_UND:
2642 b5ff1b31 bellard
        return 3;
2643 b5ff1b31 bellard
    case ARM_CPU_MODE_IRQ:
2644 b5ff1b31 bellard
        return 4;
2645 b5ff1b31 bellard
    case ARM_CPU_MODE_FIQ:
2646 b5ff1b31 bellard
        return 5;
2647 b5ff1b31 bellard
    }
2648 f5206413 Peter Maydell
    hw_error("bank number requested for bad CPSR mode value 0x%x\n", mode);
2649 b5ff1b31 bellard
}
2650 b5ff1b31 bellard
2651 0ecb72a5 Andreas Färber
void switch_mode(CPUARMState *env, int mode)
2652 b5ff1b31 bellard
{
2653 b5ff1b31 bellard
    int old_mode;
2654 b5ff1b31 bellard
    int i;
2655 b5ff1b31 bellard
2656 b5ff1b31 bellard
    old_mode = env->uncached_cpsr & CPSR_M;
2657 b5ff1b31 bellard
    if (mode == old_mode)
2658 b5ff1b31 bellard
        return;
2659 b5ff1b31 bellard
2660 b5ff1b31 bellard
    if (old_mode == ARM_CPU_MODE_FIQ) {
2661 b5ff1b31 bellard
        memcpy (env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
2662 8637c67f pbrook
        memcpy (env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
2663 b5ff1b31 bellard
    } else if (mode == ARM_CPU_MODE_FIQ) {
2664 b5ff1b31 bellard
        memcpy (env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
2665 8637c67f pbrook
        memcpy (env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
2666 b5ff1b31 bellard
    }
2667 b5ff1b31 bellard
2668 f5206413 Peter Maydell
    i = bank_number(old_mode);
2669 b5ff1b31 bellard
    env->banked_r13[i] = env->regs[13];
2670 b5ff1b31 bellard
    env->banked_r14[i] = env->regs[14];
2671 b5ff1b31 bellard
    env->banked_spsr[i] = env->spsr;
2672 b5ff1b31 bellard
2673 f5206413 Peter Maydell
    i = bank_number(mode);
2674 b5ff1b31 bellard
    env->regs[13] = env->banked_r13[i];
2675 b5ff1b31 bellard
    env->regs[14] = env->banked_r14[i];
2676 b5ff1b31 bellard
    env->spsr = env->banked_spsr[i];
2677 b5ff1b31 bellard
}
2678 b5ff1b31 bellard
2679 9ee6e8bb pbrook
static void v7m_push(CPUARMState *env, uint32_t val)
2680 9ee6e8bb pbrook
{
2681 ab1da857 Edgar E. Iglesias
    CPUState *cs = ENV_GET_CPU(env);
2682 9ee6e8bb pbrook
    env->regs[13] -= 4;
2683 ab1da857 Edgar E. Iglesias
    stl_phys(cs->as, env->regs[13], val);
2684 9ee6e8bb pbrook
}
2685 9ee6e8bb pbrook
2686 9ee6e8bb pbrook
static uint32_t v7m_pop(CPUARMState *env)
2687 9ee6e8bb pbrook
{
2688 fdfba1a2 Edgar E. Iglesias
    CPUState *cs = ENV_GET_CPU(env);
2689 9ee6e8bb pbrook
    uint32_t val;
2690 fdfba1a2 Edgar E. Iglesias
    val = ldl_phys(cs->as, env->regs[13]);
2691 9ee6e8bb pbrook
    env->regs[13] += 4;
2692 9ee6e8bb pbrook
    return val;
2693 9ee6e8bb pbrook
}
2694 9ee6e8bb pbrook
2695 9ee6e8bb pbrook
/* Switch to V7M main or process stack pointer.  */
2696 9ee6e8bb pbrook
static void switch_v7m_sp(CPUARMState *env, int process)
2697 9ee6e8bb pbrook
{
2698 9ee6e8bb pbrook
    uint32_t tmp;
2699 9ee6e8bb pbrook
    if (env->v7m.current_sp != process) {
2700 9ee6e8bb pbrook
        tmp = env->v7m.other_sp;
2701 9ee6e8bb pbrook
        env->v7m.other_sp = env->regs[13];
2702 9ee6e8bb pbrook
        env->regs[13] = tmp;
2703 9ee6e8bb pbrook
        env->v7m.current_sp = process;
2704 9ee6e8bb pbrook
    }
2705 9ee6e8bb pbrook
}
2706 9ee6e8bb pbrook
2707 9ee6e8bb pbrook
static void do_v7m_exception_exit(CPUARMState *env)
2708 9ee6e8bb pbrook
{
2709 9ee6e8bb pbrook
    uint32_t type;
2710 9ee6e8bb pbrook
    uint32_t xpsr;
2711 9ee6e8bb pbrook
2712 9ee6e8bb pbrook
    type = env->regs[15];
2713 9ee6e8bb pbrook
    if (env->v7m.exception != 0)
2714 983fe826 Paul Brook
        armv7m_nvic_complete_irq(env->nvic, env->v7m.exception);
2715 9ee6e8bb pbrook
2716 9ee6e8bb pbrook
    /* Switch to the target stack.  */
2717 9ee6e8bb pbrook
    switch_v7m_sp(env, (type & 4) != 0);
2718 9ee6e8bb pbrook
    /* Pop registers.  */
2719 9ee6e8bb pbrook
    env->regs[0] = v7m_pop(env);
2720 9ee6e8bb pbrook
    env->regs[1] = v7m_pop(env);
2721 9ee6e8bb pbrook
    env->regs[2] = v7m_pop(env);
2722 9ee6e8bb pbrook
    env->regs[3] = v7m_pop(env);
2723 9ee6e8bb pbrook
    env->regs[12] = v7m_pop(env);
2724 9ee6e8bb pbrook
    env->regs[14] = v7m_pop(env);
2725 9ee6e8bb pbrook
    env->regs[15] = v7m_pop(env);
2726 9ee6e8bb pbrook
    xpsr = v7m_pop(env);
2727 9ee6e8bb pbrook
    xpsr_write(env, xpsr, 0xfffffdff);
2728 9ee6e8bb pbrook
    /* Undo stack alignment.  */
2729 9ee6e8bb pbrook
    if (xpsr & 0x200)
2730 9ee6e8bb pbrook
        env->regs[13] |= 4;
2731 9ee6e8bb pbrook
    /* ??? The exception return type specifies Thread/Handler mode.  However
2732 9ee6e8bb pbrook
       this is also implied by the xPSR value. Not sure what to do
2733 9ee6e8bb pbrook
       if there is a mismatch.  */
2734 9ee6e8bb pbrook
    /* ??? Likewise for mismatches between the CONTROL register and the stack
2735 9ee6e8bb pbrook
       pointer.  */
2736 9ee6e8bb pbrook
}
2737 9ee6e8bb pbrook
2738 3f1beaca Peter Maydell
/* Exception names for debug logging; note that not all of these
2739 3f1beaca Peter Maydell
 * precisely correspond to architectural exceptions.
2740 3f1beaca Peter Maydell
 */
2741 3f1beaca Peter Maydell
static const char * const excnames[] = {
2742 3f1beaca Peter Maydell
    [EXCP_UDEF] = "Undefined Instruction",
2743 3f1beaca Peter Maydell
    [EXCP_SWI] = "SVC",
2744 3f1beaca Peter Maydell
    [EXCP_PREFETCH_ABORT] = "Prefetch Abort",
2745 3f1beaca Peter Maydell
    [EXCP_DATA_ABORT] = "Data Abort",
2746 3f1beaca Peter Maydell
    [EXCP_IRQ] = "IRQ",
2747 3f1beaca Peter Maydell
    [EXCP_FIQ] = "FIQ",
2748 3f1beaca Peter Maydell
    [EXCP_BKPT] = "Breakpoint",
2749 3f1beaca Peter Maydell
    [EXCP_EXCEPTION_EXIT] = "QEMU v7M exception exit",
2750 3f1beaca Peter Maydell
    [EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage",
2751 3f1beaca Peter Maydell
    [EXCP_STREX] = "QEMU intercept of STREX",
2752 3f1beaca Peter Maydell
};
2753 3f1beaca Peter Maydell
2754 3f1beaca Peter Maydell
static inline void arm_log_exception(int idx)
2755 3f1beaca Peter Maydell
{
2756 3f1beaca Peter Maydell
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
2757 3f1beaca Peter Maydell
        const char *exc = NULL;
2758 3f1beaca Peter Maydell
2759 3f1beaca Peter Maydell
        if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
2760 3f1beaca Peter Maydell
            exc = excnames[idx];
2761 3f1beaca Peter Maydell
        }
2762 3f1beaca Peter Maydell
        if (!exc) {
2763 3f1beaca Peter Maydell
            exc = "unknown";
2764 3f1beaca Peter Maydell
        }
2765 3f1beaca Peter Maydell
        qemu_log_mask(CPU_LOG_INT, "Taking exception %d [%s]\n", idx, exc);
2766 3f1beaca Peter Maydell
    }
2767 3f1beaca Peter Maydell
}
2768 3f1beaca Peter Maydell
2769 e6f010cc Andreas Färber
void arm_v7m_cpu_do_interrupt(CPUState *cs)
2770 9ee6e8bb pbrook
{
2771 e6f010cc Andreas Färber
    ARMCPU *cpu = ARM_CPU(cs);
2772 e6f010cc Andreas Färber
    CPUARMState *env = &cpu->env;
2773 9ee6e8bb pbrook
    uint32_t xpsr = xpsr_read(env);
2774 9ee6e8bb pbrook
    uint32_t lr;
2775 9ee6e8bb pbrook
    uint32_t addr;
2776 9ee6e8bb pbrook
2777 3f1beaca Peter Maydell
    arm_log_exception(env->exception_index);
2778 3f1beaca Peter Maydell
2779 9ee6e8bb pbrook
    lr = 0xfffffff1;
2780 9ee6e8bb pbrook
    if (env->v7m.current_sp)
2781 9ee6e8bb pbrook
        lr |= 4;
2782 9ee6e8bb pbrook
    if (env->v7m.exception == 0)
2783 9ee6e8bb pbrook
        lr |= 8;
2784 9ee6e8bb pbrook
2785 9ee6e8bb pbrook
    /* For exceptions we just mark as pending on the NVIC, and let that
2786 9ee6e8bb pbrook
       handle it.  */
2787 9ee6e8bb pbrook
    /* TODO: Need to escalate if the current priority is higher than the
2788 9ee6e8bb pbrook
       one we're raising.  */
2789 9ee6e8bb pbrook
    switch (env->exception_index) {
2790 9ee6e8bb pbrook
    case EXCP_UDEF:
2791 983fe826 Paul Brook
        armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
2792 9ee6e8bb pbrook
        return;
2793 9ee6e8bb pbrook
    case EXCP_SWI:
2794 314e2296 Alex_Rozenman@mentor.com
        /* The PC already points to the next instruction.  */
2795 983fe826 Paul Brook
        armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC);
2796 9ee6e8bb pbrook
        return;
2797 9ee6e8bb pbrook
    case EXCP_PREFETCH_ABORT:
2798 9ee6e8bb pbrook
    case EXCP_DATA_ABORT:
2799 983fe826 Paul Brook
        armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
2800 9ee6e8bb pbrook
        return;
2801 9ee6e8bb pbrook
    case EXCP_BKPT:
2802 2ad207d4 pbrook
        if (semihosting_enabled) {
2803 2ad207d4 pbrook
            int nr;
2804 d31dd73e Blue Swirl
            nr = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
2805 2ad207d4 pbrook
            if (nr == 0xab) {
2806 2ad207d4 pbrook
                env->regs[15] += 2;
2807 2ad207d4 pbrook
                env->regs[0] = do_arm_semihosting(env);
2808 3f1beaca Peter Maydell
                qemu_log_mask(CPU_LOG_INT, "...handled as semihosting call\n");
2809 2ad207d4 pbrook
                return;
2810 2ad207d4 pbrook
            }
2811 2ad207d4 pbrook
        }
2812 983fe826 Paul Brook
        armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG);
2813 9ee6e8bb pbrook
        return;
2814 9ee6e8bb pbrook
    case EXCP_IRQ:
2815 983fe826 Paul Brook
        env->v7m.exception = armv7m_nvic_acknowledge_irq(env->nvic);
2816 9ee6e8bb pbrook
        break;
2817 9ee6e8bb pbrook
    case EXCP_EXCEPTION_EXIT:
2818 9ee6e8bb pbrook
        do_v7m_exception_exit(env);
2819 9ee6e8bb pbrook
        return;
2820 9ee6e8bb pbrook
    default:
2821 9ee6e8bb pbrook
        cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
2822 9ee6e8bb pbrook
        return; /* Never happens.  Keep compiler happy.  */
2823 9ee6e8bb pbrook
    }
2824 9ee6e8bb pbrook
2825 9ee6e8bb pbrook
    /* Align stack pointer.  */
2826 9ee6e8bb pbrook
    /* ??? Should only do this if Configuration Control Register
2827 9ee6e8bb pbrook
       STACKALIGN bit is set.  */
2828 9ee6e8bb pbrook
    if (env->regs[13] & 4) {
2829 ab19b0ec pbrook
        env->regs[13] -= 4;
2830 9ee6e8bb pbrook
        xpsr |= 0x200;
2831 9ee6e8bb pbrook
    }
2832 6c95676b balrog
    /* Switch to the handler mode.  */
2833 9ee6e8bb pbrook
    v7m_push(env, xpsr);
2834 9ee6e8bb pbrook
    v7m_push(env, env->regs[15]);
2835 9ee6e8bb pbrook
    v7m_push(env, env->regs[14]);
2836 9ee6e8bb pbrook
    v7m_push(env, env->regs[12]);
2837 9ee6e8bb pbrook
    v7m_push(env, env->regs[3]);
2838 9ee6e8bb pbrook
    v7m_push(env, env->regs[2]);
2839 9ee6e8bb pbrook
    v7m_push(env, env->regs[1]);
2840 9ee6e8bb pbrook
    v7m_push(env, env->regs[0]);
2841 9ee6e8bb pbrook
    switch_v7m_sp(env, 0);
2842 c98d174c Peter Maydell
    /* Clear IT bits */
2843 c98d174c Peter Maydell
    env->condexec_bits = 0;
2844 9ee6e8bb pbrook
    env->regs[14] = lr;
2845 fdfba1a2 Edgar E. Iglesias
    addr = ldl_phys(cs->as, env->v7m.vecbase + env->v7m.exception * 4);
2846 9ee6e8bb pbrook
    env->regs[15] = addr & 0xfffffffe;
2847 9ee6e8bb pbrook
    env->thumb = addr & 1;
2848 9ee6e8bb pbrook
}
2849 9ee6e8bb pbrook
2850 b5ff1b31 bellard
/* Handle a CPU exception.  */
2851 97a8ea5a Andreas Färber
void arm_cpu_do_interrupt(CPUState *cs)
2852 b5ff1b31 bellard
{
2853 97a8ea5a Andreas Färber
    ARMCPU *cpu = ARM_CPU(cs);
2854 97a8ea5a Andreas Färber
    CPUARMState *env = &cpu->env;
2855 b5ff1b31 bellard
    uint32_t addr;
2856 b5ff1b31 bellard
    uint32_t mask;
2857 b5ff1b31 bellard
    int new_mode;
2858 b5ff1b31 bellard
    uint32_t offset;
2859 b5ff1b31 bellard
2860 e6f010cc Andreas Färber
    assert(!IS_M(env));
2861 e6f010cc Andreas Färber
2862 3f1beaca Peter Maydell
    arm_log_exception(env->exception_index);
2863 3f1beaca Peter Maydell
2864 b5ff1b31 bellard
    /* TODO: Vectored interrupt controller.  */
2865 b5ff1b31 bellard
    switch (env->exception_index) {
2866 b5ff1b31 bellard
    case EXCP_UDEF:
2867 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_UND;
2868 b5ff1b31 bellard
        addr = 0x04;
2869 b5ff1b31 bellard
        mask = CPSR_I;
2870 b5ff1b31 bellard
        if (env->thumb)
2871 b5ff1b31 bellard
            offset = 2;
2872 b5ff1b31 bellard
        else
2873 b5ff1b31 bellard
            offset = 4;
2874 b5ff1b31 bellard
        break;
2875 b5ff1b31 bellard
    case EXCP_SWI:
2876 8e71621f pbrook
        if (semihosting_enabled) {
2877 8e71621f pbrook
            /* Check for semihosting interrupt.  */
2878 8e71621f pbrook
            if (env->thumb) {
2879 d31dd73e Blue Swirl
                mask = arm_lduw_code(env, env->regs[15] - 2, env->bswap_code)
2880 d31dd73e Blue Swirl
                    & 0xff;
2881 8e71621f pbrook
            } else {
2882 d31dd73e Blue Swirl
                mask = arm_ldl_code(env, env->regs[15] - 4, env->bswap_code)
2883 d8fd2954 Paul Brook
                    & 0xffffff;
2884 8e71621f pbrook
            }
2885 8e71621f pbrook
            /* Only intercept calls from privileged modes, to provide some
2886 8e71621f pbrook
               semblance of security.  */
2887 8e71621f pbrook
            if (((mask == 0x123456 && !env->thumb)
2888 8e71621f pbrook
                    || (mask == 0xab && env->thumb))
2889 8e71621f pbrook
                  && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
2890 8e71621f pbrook
                env->regs[0] = do_arm_semihosting(env);
2891 3f1beaca Peter Maydell
                qemu_log_mask(CPU_LOG_INT, "...handled as semihosting call\n");
2892 8e71621f pbrook
                return;
2893 8e71621f pbrook
            }
2894 8e71621f pbrook
        }
2895 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_SVC;
2896 b5ff1b31 bellard
        addr = 0x08;
2897 b5ff1b31 bellard
        mask = CPSR_I;
2898 601d70b9 balrog
        /* The PC already points to the next instruction.  */
2899 b5ff1b31 bellard
        offset = 0;
2900 b5ff1b31 bellard
        break;
2901 06c949e6 pbrook
    case EXCP_BKPT:
2902 9ee6e8bb pbrook
        /* See if this is a semihosting syscall.  */
2903 2ad207d4 pbrook
        if (env->thumb && semihosting_enabled) {
2904 d31dd73e Blue Swirl
            mask = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
2905 9ee6e8bb pbrook
            if (mask == 0xab
2906 9ee6e8bb pbrook
                  && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
2907 9ee6e8bb pbrook
                env->regs[15] += 2;
2908 9ee6e8bb pbrook
                env->regs[0] = do_arm_semihosting(env);
2909 3f1beaca Peter Maydell
                qemu_log_mask(CPU_LOG_INT, "...handled as semihosting call\n");
2910 9ee6e8bb pbrook
                return;
2911 9ee6e8bb pbrook
            }
2912 9ee6e8bb pbrook
        }
2913 81c05daf Alex Zuepke
        env->cp15.c5_insn = 2;
2914 9ee6e8bb pbrook
        /* Fall through to prefetch abort.  */
2915 9ee6e8bb pbrook
    case EXCP_PREFETCH_ABORT:
2916 3f1beaca Peter Maydell
        qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x IFAR 0x%x\n",
2917 3f1beaca Peter Maydell
                      env->cp15.c5_insn, env->cp15.c6_insn);
2918 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_ABT;
2919 b5ff1b31 bellard
        addr = 0x0c;
2920 b5ff1b31 bellard
        mask = CPSR_A | CPSR_I;
2921 b5ff1b31 bellard
        offset = 4;
2922 b5ff1b31 bellard
        break;
2923 b5ff1b31 bellard
    case EXCP_DATA_ABORT:
2924 3f1beaca Peter Maydell
        qemu_log_mask(CPU_LOG_INT, "...with DFSR 0x%x DFAR 0x%x\n",
2925 3f1beaca Peter Maydell
                      env->cp15.c5_data, env->cp15.c6_data);
2926 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_ABT;
2927 b5ff1b31 bellard
        addr = 0x10;
2928 b5ff1b31 bellard
        mask = CPSR_A | CPSR_I;
2929 b5ff1b31 bellard
        offset = 8;
2930 b5ff1b31 bellard
        break;
2931 b5ff1b31 bellard
    case EXCP_IRQ:
2932 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_IRQ;
2933 b5ff1b31 bellard
        addr = 0x18;
2934 b5ff1b31 bellard
        /* Disable IRQ and imprecise data aborts.  */
2935 b5ff1b31 bellard
        mask = CPSR_A | CPSR_I;
2936 b5ff1b31 bellard
        offset = 4;
2937 b5ff1b31 bellard
        break;
2938 b5ff1b31 bellard
    case EXCP_FIQ:
2939 b5ff1b31 bellard
        new_mode = ARM_CPU_MODE_FIQ;
2940 b5ff1b31 bellard
        addr = 0x1c;
2941 b5ff1b31 bellard
        /* Disable FIQ, IRQ and imprecise data aborts.  */
2942 b5ff1b31 bellard
        mask = CPSR_A | CPSR_I | CPSR_F;
2943 b5ff1b31 bellard
        offset = 4;
2944 b5ff1b31 bellard
        break;
2945 b5ff1b31 bellard
    default:
2946 b5ff1b31 bellard
        cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
2947 b5ff1b31 bellard
        return; /* Never happens.  Keep compiler happy.  */
2948 b5ff1b31 bellard
    }
2949 b5ff1b31 bellard
    /* High vectors.  */
2950 76e3e1bc Peter Maydell
    if (env->cp15.c1_sys & SCTLR_V) {
2951 8641136c Nathan Rossi
        /* when enabled, base address cannot be remapped.  */
2952 b5ff1b31 bellard
        addr += 0xffff0000;
2953 8641136c Nathan Rossi
    } else {
2954 8641136c Nathan Rossi
        /* ARM v7 architectures provide a vector base address register to remap
2955 8641136c Nathan Rossi
         * the interrupt vector table.
2956 8641136c Nathan Rossi
         * This register is only followed in non-monitor mode, and has a secure
2957 8641136c Nathan Rossi
         * and un-secure copy. Since the cpu is always in a un-secure operation
2958 8641136c Nathan Rossi
         * and is never in monitor mode this feature is always active.
2959 8641136c Nathan Rossi
         * Note: only bits 31:5 are valid.
2960 8641136c Nathan Rossi
         */
2961 8641136c Nathan Rossi
        addr += env->cp15.c12_vbar;
2962 b5ff1b31 bellard
    }
2963 b5ff1b31 bellard
    switch_mode (env, new_mode);
2964 b5ff1b31 bellard
    env->spsr = cpsr_read(env);
2965 9ee6e8bb pbrook
    /* Clear IT bits.  */
2966 9ee6e8bb pbrook
    env->condexec_bits = 0;
2967 30a8cac1 Rabin Vincent
    /* Switch to the new mode, and to the correct instruction set.  */
2968 6d7e6326 bellard
    env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
2969 4cc35614 Peter Maydell
    env->daif |= mask;
2970 be5e7a76 Dmitry Eremin-Solenikov
    /* this is a lie, as the was no c1_sys on V4T/V5, but who cares
2971 be5e7a76 Dmitry Eremin-Solenikov
     * and we should just guard the thumb mode on V4 */
2972 be5e7a76 Dmitry Eremin-Solenikov
    if (arm_feature(env, ARM_FEATURE_V4T)) {
2973 76e3e1bc Peter Maydell
        env->thumb = (env->cp15.c1_sys & SCTLR_TE) != 0;
2974 be5e7a76 Dmitry Eremin-Solenikov
    }
2975 b5ff1b31 bellard
    env->regs[14] = env->regs[15] + offset;
2976 b5ff1b31 bellard
    env->regs[15] = addr;
2977 259186a7 Andreas Färber
    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
2978 b5ff1b31 bellard
}
2979 b5ff1b31 bellard
2980 b5ff1b31 bellard
/* Check section/page access permissions.
2981 b5ff1b31 bellard
   Returns the page protection flags, or zero if the access is not
2982 b5ff1b31 bellard
   permitted.  */
2983 0ecb72a5 Andreas Färber
static inline int check_ap(CPUARMState *env, int ap, int domain_prot,
2984 dd4ebc2e Jean-Christophe DUBOIS
                           int access_type, int is_user)
2985 b5ff1b31 bellard
{
2986 9ee6e8bb pbrook
  int prot_ro;
2987 9ee6e8bb pbrook
2988 dd4ebc2e Jean-Christophe DUBOIS
  if (domain_prot == 3) {
2989 b5ff1b31 bellard
    return PAGE_READ | PAGE_WRITE;
2990 dd4ebc2e Jean-Christophe DUBOIS
  }
2991 b5ff1b31 bellard
2992 9ee6e8bb pbrook
  if (access_type == 1)
2993 9ee6e8bb pbrook
      prot_ro = 0;
2994 9ee6e8bb pbrook
  else
2995 9ee6e8bb pbrook
      prot_ro = PAGE_READ;
2996 9ee6e8bb pbrook
2997 b5ff1b31 bellard
  switch (ap) {
2998 b5ff1b31 bellard
  case 0:
2999 99f678a6 Peter Maydell
      if (arm_feature(env, ARM_FEATURE_V7)) {
3000 99f678a6 Peter Maydell
          return 0;
3001 99f678a6 Peter Maydell
      }
3002 78600320 pbrook
      if (access_type == 1)
3003 b5ff1b31 bellard
          return 0;
3004 76e3e1bc Peter Maydell
      switch (env->cp15.c1_sys & (SCTLR_S | SCTLR_R)) {
3005 76e3e1bc Peter Maydell
      case SCTLR_S:
3006 b5ff1b31 bellard
          return is_user ? 0 : PAGE_READ;
3007 76e3e1bc Peter Maydell
      case SCTLR_R:
3008 b5ff1b31 bellard
          return PAGE_READ;
3009 b5ff1b31 bellard
      default:
3010 b5ff1b31 bellard
          return 0;
3011 b5ff1b31 bellard
      }
3012 b5ff1b31 bellard
  case 1:
3013 b5ff1b31 bellard
      return is_user ? 0 : PAGE_READ | PAGE_WRITE;
3014 b5ff1b31 bellard
  case 2:
3015 b5ff1b31 bellard
      if (is_user)
3016 9ee6e8bb pbrook
          return prot_ro;
3017 b5ff1b31 bellard
      else
3018 b5ff1b31 bellard
          return PAGE_READ | PAGE_WRITE;
3019 b5ff1b31 bellard
  case 3:
3020 b5ff1b31 bellard
      return PAGE_READ | PAGE_WRITE;
3021 d4934d18 pbrook
  case 4: /* Reserved.  */
3022 9ee6e8bb pbrook
      return 0;
3023 9ee6e8bb pbrook
  case 5:
3024 9ee6e8bb pbrook
      return is_user ? 0 : prot_ro;
3025 9ee6e8bb pbrook
  case 6:
3026 9ee6e8bb pbrook
      return prot_ro;
3027 d4934d18 pbrook
  case 7:
3028 0ab06d83 Jamie Iles
      if (!arm_feature (env, ARM_FEATURE_V6K))
3029 d4934d18 pbrook
          return 0;
3030 d4934d18 pbrook
      return prot_ro;
3031 b5ff1b31 bellard
  default:
3032 b5ff1b31 bellard
      abort();
3033 b5ff1b31 bellard
  }
3034 b5ff1b31 bellard
}
3035 b5ff1b31 bellard
3036 0ecb72a5 Andreas Färber
static uint32_t get_level1_table_address(CPUARMState *env, uint32_t address)
3037 b2fa1797 pbrook
{
3038 b2fa1797 pbrook
    uint32_t table;
3039 b2fa1797 pbrook
3040 b2fa1797 pbrook
    if (address & env->cp15.c2_mask)
3041 327ed10f Peter Maydell
        table = env->cp15.ttbr1_el1 & 0xffffc000;
3042 b2fa1797 pbrook
    else
3043 327ed10f Peter Maydell
        table = env->cp15.ttbr0_el1 & env->cp15.c2_base_mask;
3044 b2fa1797 pbrook
3045 b2fa1797 pbrook
    table |= (address >> 18) & 0x3ffc;
3046 b2fa1797 pbrook
    return table;
3047 b2fa1797 pbrook
}
3048 b2fa1797 pbrook
3049 0ecb72a5 Andreas Färber
static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
3050 a8170e5e Avi Kivity
                            int is_user, hwaddr *phys_ptr,
3051 77a71dd1 Peter Maydell
                            int *prot, target_ulong *page_size)
3052 b5ff1b31 bellard
{
3053 fdfba1a2 Edgar E. Iglesias
    CPUState *cs = ENV_GET_CPU(env);
3054 b5ff1b31 bellard
    int code;
3055 b5ff1b31 bellard
    uint32_t table;
3056 b5ff1b31 bellard
    uint32_t desc;
3057 b5ff1b31 bellard
    int type;
3058 b5ff1b31 bellard
    int ap;
3059 b5ff1b31 bellard
    int domain;
3060 dd4ebc2e Jean-Christophe DUBOIS
    int domain_prot;
3061 a8170e5e Avi Kivity
    hwaddr phys_addr;
3062 b5ff1b31 bellard
3063 9ee6e8bb pbrook
    /* Pagetable walk.  */
3064 9ee6e8bb pbrook
    /* Lookup l1 descriptor.  */
3065 b2fa1797 pbrook
    table = get_level1_table_address(env, address);
3066 fdfba1a2 Edgar E. Iglesias
    desc = ldl_phys(cs->as, table);
3067 9ee6e8bb pbrook
    type = (desc & 3);
3068 dd4ebc2e Jean-Christophe DUBOIS
    domain = (desc >> 5) & 0x0f;
3069 dd4ebc2e Jean-Christophe DUBOIS
    domain_prot = (env->cp15.c3 >> (domain * 2)) & 3;
3070 9ee6e8bb pbrook
    if (type == 0) {
3071 601d70b9 balrog
        /* Section translation fault.  */
3072 9ee6e8bb pbrook
        code = 5;
3073 9ee6e8bb pbrook
        goto do_fault;
3074 9ee6e8bb pbrook
    }
3075 dd4ebc2e Jean-Christophe DUBOIS
    if (domain_prot == 0 || domain_prot == 2) {
3076 9ee6e8bb pbrook
        if (type == 2)
3077 9ee6e8bb pbrook
            code = 9; /* Section domain fault.  */
3078 9ee6e8bb pbrook
        else
3079 9ee6e8bb pbrook
            code = 11; /* Page domain fault.  */
3080 9ee6e8bb pbrook
        goto do_fault;
3081 9ee6e8bb pbrook
    }
3082 9ee6e8bb pbrook
    if (type == 2) {
3083 9ee6e8bb pbrook
        /* 1Mb section.  */
3084 9ee6e8bb pbrook
        phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
3085 9ee6e8bb pbrook
        ap = (desc >> 10) & 3;
3086 9ee6e8bb pbrook
        code = 13;
3087 d4c430a8 Paul Brook
        *page_size = 1024 * 1024;
3088 9ee6e8bb pbrook
    } else {
3089 9ee6e8bb pbrook
        /* Lookup l2 entry.  */
3090 9ee6e8bb pbrook
        if (type == 1) {
3091 9ee6e8bb pbrook
            /* Coarse pagetable.  */
3092 9ee6e8bb pbrook
            table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
3093 9ee6e8bb pbrook
        } else {
3094 9ee6e8bb pbrook
            /* Fine pagetable.  */
3095 9ee6e8bb pbrook
            table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
3096 9ee6e8bb pbrook
        }
3097 fdfba1a2 Edgar E. Iglesias
        desc = ldl_phys(cs->as, table);
3098 9ee6e8bb pbrook
        switch (desc & 3) {
3099 9ee6e8bb pbrook
        case 0: /* Page translation fault.  */
3100 9ee6e8bb pbrook
            code = 7;
3101 9ee6e8bb pbrook
            goto do_fault;
3102 9ee6e8bb pbrook
        case 1: /* 64k page.  */
3103 9ee6e8bb pbrook
            phys_addr = (desc & 0xffff0000) | (address & 0xffff);
3104 9ee6e8bb pbrook
            ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
3105 d4c430a8 Paul Brook
            *page_size = 0x10000;
3106 ce819861 pbrook
            break;
3107 9ee6e8bb pbrook
        case 2: /* 4k page.  */
3108 9ee6e8bb pbrook
            phys_addr = (desc & 0xfffff000) | (address & 0xfff);
3109 c10f7fc3 Peter Maydell
            ap = (desc >> (4 + ((address >> 9) & 6))) & 3;
3110 d4c430a8 Paul Brook
            *page_size = 0x1000;
3111 ce819861 pbrook
            break;
3112 9ee6e8bb pbrook
        case 3: /* 1k page.  */
3113 9ee6e8bb pbrook
            if (type == 1) {
3114 9ee6e8bb pbrook
                if (arm_feature(env, ARM_FEATURE_XSCALE)) {
3115 9ee6e8bb pbrook
                    phys_addr = (desc & 0xfffff000) | (address & 0xfff);
3116 9ee6e8bb pbrook
                } else {
3117 9ee6e8bb pbrook
                    /* Page translation fault.  */
3118 9ee6e8bb pbrook
                    code = 7;
3119 9ee6e8bb pbrook
                    goto do_fault;
3120 9ee6e8bb pbrook
                }
3121 9ee6e8bb pbrook
            } else {
3122 9ee6e8bb pbrook
                phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
3123 9ee6e8bb pbrook
            }
3124 9ee6e8bb pbrook
            ap = (desc >> 4) & 3;
3125 d4c430a8 Paul Brook
            *page_size = 0x400;
3126 ce819861 pbrook
            break;
3127 ce819861 pbrook
        default:
3128 9ee6e8bb pbrook
            /* Never happens, but compiler isn't smart enough to tell.  */
3129 9ee6e8bb pbrook
            abort();
3130 ce819861 pbrook
        }
3131 9ee6e8bb pbrook
        code = 15;
3132 9ee6e8bb pbrook
    }
3133 dd4ebc2e Jean-Christophe DUBOIS
    *prot = check_ap(env, ap, domain_prot, access_type, is_user);
3134 9ee6e8bb pbrook
    if (!*prot) {
3135 9ee6e8bb pbrook
        /* Access permission fault.  */
3136 9ee6e8bb pbrook
        goto do_fault;
3137 9ee6e8bb pbrook
    }
3138 3ad493fc Rabin Vincent
    *prot |= PAGE_EXEC;
3139 9ee6e8bb pbrook
    *phys_ptr = phys_addr;
3140 9ee6e8bb pbrook
    return 0;
3141 9ee6e8bb pbrook
do_fault:
3142 9ee6e8bb pbrook
    return code | (domain << 4);
3143 9ee6e8bb pbrook
}
3144 9ee6e8bb pbrook
3145 0ecb72a5 Andreas Färber
static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
3146 a8170e5e Avi Kivity
                            int is_user, hwaddr *phys_ptr,
3147 77a71dd1 Peter Maydell
                            int *prot, target_ulong *page_size)
3148 9ee6e8bb pbrook
{
3149 fdfba1a2 Edgar E. Iglesias
    CPUState *cs = ENV_GET_CPU(env);
3150 9ee6e8bb pbrook
    int code;
3151 9ee6e8bb pbrook
    uint32_t table;
3152 9ee6e8bb pbrook
    uint32_t desc;
3153 9ee6e8bb pbrook
    uint32_t xn;
3154 de9b05b8 Peter Maydell
    uint32_t pxn = 0;
3155 9ee6e8bb pbrook
    int type;
3156 9ee6e8bb pbrook
    int ap;
3157 de9b05b8 Peter Maydell
    int domain = 0;
3158 dd4ebc2e Jean-Christophe DUBOIS
    int domain_prot;
3159 a8170e5e Avi Kivity
    hwaddr phys_addr;
3160 9ee6e8bb pbrook
3161 9ee6e8bb pbrook
    /* Pagetable walk.  */
3162 9ee6e8bb pbrook
    /* Lookup l1 descriptor.  */
3163 b2fa1797 pbrook
    table = get_level1_table_address(env, address);
3164 fdfba1a2 Edgar E. Iglesias
    desc = ldl_phys(cs->as, table);
3165 9ee6e8bb pbrook
    type = (desc & 3);
3166 de9b05b8 Peter Maydell
    if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
3167 de9b05b8 Peter Maydell
        /* Section translation fault, or attempt to use the encoding
3168 de9b05b8 Peter Maydell
         * which is Reserved on implementations without PXN.
3169 de9b05b8 Peter Maydell
         */
3170 9ee6e8bb pbrook
        code = 5;
3171 9ee6e8bb pbrook
        goto do_fault;
3172 de9b05b8 Peter Maydell
    }
3173 de9b05b8 Peter Maydell
    if ((type == 1) || !(desc & (1 << 18))) {
3174 de9b05b8 Peter Maydell
        /* Page or Section.  */
3175 dd4ebc2e Jean-Christophe DUBOIS
        domain = (desc >> 5) & 0x0f;
3176 9ee6e8bb pbrook
    }
3177 dd4ebc2e Jean-Christophe DUBOIS
    domain_prot = (env->cp15.c3 >> (domain * 2)) & 3;
3178 dd4ebc2e Jean-Christophe DUBOIS
    if (domain_prot == 0 || domain_prot == 2) {
3179 de9b05b8 Peter Maydell
        if (type != 1) {
3180 9ee6e8bb pbrook
            code = 9; /* Section domain fault.  */
3181 de9b05b8 Peter Maydell
        } else {
3182 9ee6e8bb pbrook
            code = 11; /* Page domain fault.  */
3183 de9b05b8 Peter Maydell
        }
3184 9ee6e8bb pbrook
        goto do_fault;
3185 9ee6e8bb pbrook
    }
3186 de9b05b8 Peter Maydell
    if (type != 1) {
3187 9ee6e8bb pbrook
        if (desc & (1 << 18)) {
3188 9ee6e8bb pbrook
            /* Supersection.  */
3189 9ee6e8bb pbrook
            phys_addr = (desc & 0xff000000) | (address & 0x00ffffff);
3190 d4c430a8 Paul Brook
            *page_size = 0x1000000;
3191 b5ff1b31 bellard
        } else {
3192 9ee6e8bb pbrook
            /* Section.  */
3193 9ee6e8bb pbrook
            phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
3194 d4c430a8 Paul Brook
            *page_size = 0x100000;
3195 b5ff1b31 bellard
        }
3196 9ee6e8bb pbrook
        ap = ((desc >> 10) & 3) | ((desc >> 13) & 4);
3197 9ee6e8bb pbrook
        xn = desc & (1 << 4);
3198 de9b05b8 Peter Maydell
        pxn = desc & 1;
3199 9ee6e8bb pbrook
        code = 13;
3200 9ee6e8bb pbrook
    } else {
3201 de9b05b8 Peter Maydell
        if (arm_feature(env, ARM_FEATURE_PXN)) {
3202 de9b05b8 Peter Maydell
            pxn = (desc >> 2) & 1;
3203 de9b05b8 Peter Maydell
        }
3204 9ee6e8bb pbrook
        /* Lookup l2 entry.  */
3205 9ee6e8bb pbrook
        table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
3206 fdfba1a2 Edgar E. Iglesias
        desc = ldl_phys(cs->as, table);
3207 9ee6e8bb pbrook
        ap = ((desc >> 4) & 3) | ((desc >> 7) & 4);
3208 9ee6e8bb pbrook
        switch (desc & 3) {
3209 9ee6e8bb pbrook
        case 0: /* Page translation fault.  */
3210 9ee6e8bb pbrook
            code = 7;
3211 b5ff1b31 bellard
            goto do_fault;
3212 9ee6e8bb pbrook
        case 1: /* 64k page.  */
3213 9ee6e8bb pbrook
            phys_addr = (desc & 0xffff0000) | (address & 0xffff);
3214 9ee6e8bb pbrook
            xn = desc & (1 << 15);
3215 d4c430a8 Paul Brook
            *page_size = 0x10000;
3216 9ee6e8bb pbrook
            break;
3217 9ee6e8bb pbrook
        case 2: case 3: /* 4k page.  */
3218 9ee6e8bb pbrook
            phys_addr = (desc & 0xfffff000) | (address & 0xfff);
3219 9ee6e8bb pbrook
            xn = desc & 1;
3220 d4c430a8 Paul Brook
            *page_size = 0x1000;
3221 9ee6e8bb pbrook
            break;
3222 9ee6e8bb pbrook
        default:
3223 9ee6e8bb pbrook
            /* Never happens, but compiler isn't smart enough to tell.  */
3224 9ee6e8bb pbrook
            abort();
3225 b5ff1b31 bellard
        }
3226 9ee6e8bb pbrook
        code = 15;
3227 9ee6e8bb pbrook
    }
3228 dd4ebc2e Jean-Christophe DUBOIS
    if (domain_prot == 3) {
3229 c0034328 Juha Riihimäki
        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
3230 c0034328 Juha Riihimäki
    } else {
3231 de9b05b8 Peter Maydell
        if (pxn && !is_user) {
3232 de9b05b8 Peter Maydell
            xn = 1;
3233 de9b05b8 Peter Maydell
        }
3234 c0034328 Juha Riihimäki
        if (xn && access_type == 2)
3235 c0034328 Juha Riihimäki
            goto do_fault;
3236 9ee6e8bb pbrook
3237 c0034328 Juha Riihimäki
        /* The simplified model uses AP[0] as an access control bit.  */
3238 76e3e1bc Peter Maydell
        if ((env->cp15.c1_sys & SCTLR_AFE) && (ap & 1) == 0) {
3239 c0034328 Juha Riihimäki
            /* Access flag fault.  */
3240 c0034328 Juha Riihimäki
            code = (code == 15) ? 6 : 3;
3241 c0034328 Juha Riihimäki
            goto do_fault;
3242 c0034328 Juha Riihimäki
        }
3243 dd4ebc2e Jean-Christophe DUBOIS
        *prot = check_ap(env, ap, domain_prot, access_type, is_user);
3244 c0034328 Juha Riihimäki
        if (!*prot) {
3245 c0034328 Juha Riihimäki
            /* Access permission fault.  */
3246 c0034328 Juha Riihimäki
            goto do_fault;
3247 c0034328 Juha Riihimäki
        }
3248 c0034328 Juha Riihimäki
        if (!xn) {
3249 c0034328 Juha Riihimäki
            *prot |= PAGE_EXEC;
3250 c0034328 Juha Riihimäki
        }
3251 3ad493fc Rabin Vincent
    }
3252 9ee6e8bb pbrook
    *phys_ptr = phys_addr;
3253 b5ff1b31 bellard
    return 0;
3254 b5ff1b31 bellard
do_fault:
3255 b5ff1b31 bellard
    return code | (domain << 4);
3256 b5ff1b31 bellard
}
3257 b5ff1b31 bellard
3258 3dde962f Peter Maydell
/* Fault type for long-descriptor MMU fault reporting; this corresponds
3259 3dde962f Peter Maydell
 * to bits [5..2] in the STATUS field in long-format DFSR/IFSR.
3260 3dde962f Peter Maydell
 */
3261 3dde962f Peter Maydell
typedef enum {
3262 3dde962f Peter Maydell
    translation_fault = 1,
3263 3dde962f Peter Maydell
    access_fault = 2,
3264 3dde962f Peter Maydell
    permission_fault = 3,
3265 3dde962f Peter Maydell
} MMUFaultType;
3266 3dde962f Peter Maydell
3267 3dde962f Peter Maydell
static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
3268 3dde962f Peter Maydell
                              int access_type, int is_user,
3269 a8170e5e Avi Kivity
                              hwaddr *phys_ptr, int *prot,
3270 3dde962f Peter Maydell
                              target_ulong *page_size_ptr)
3271 3dde962f Peter Maydell
{
3272 2c17449b Edgar E. Iglesias
    CPUState *cs = ENV_GET_CPU(env);
3273 3dde962f Peter Maydell
    /* Read an LPAE long-descriptor translation table. */
3274 3dde962f Peter Maydell
    MMUFaultType fault_type = translation_fault;
3275 3dde962f Peter Maydell
    uint32_t level = 1;
3276 3dde962f Peter Maydell
    uint32_t epd;
3277 3dde962f Peter Maydell
    uint32_t tsz;
3278 3dde962f Peter Maydell
    uint64_t ttbr;
3279 3dde962f Peter Maydell
    int ttbr_select;
3280 3dde962f Peter Maydell
    int n;
3281 a8170e5e Avi Kivity
    hwaddr descaddr;
3282 3dde962f Peter Maydell
    uint32_t tableattrs;
3283 3dde962f Peter Maydell
    target_ulong page_size;
3284 3dde962f Peter Maydell
    uint32_t attrs;
3285 3dde962f Peter Maydell
3286 3dde962f Peter Maydell
    /* Determine whether this address is in the region controlled by
3287 3dde962f Peter Maydell
     * TTBR0 or TTBR1 (or if it is in neither region and should fault).
3288 3dde962f Peter Maydell
     * This is a Non-secure PL0/1 stage 1 translation, so controlled by
3289 3dde962f Peter Maydell
     * TTBCR/TTBR0/TTBR1 in accordance with ARM ARM DDI0406C table B-32:
3290 3dde962f Peter Maydell
     */
3291 3dde962f Peter Maydell
    uint32_t t0sz = extract32(env->cp15.c2_control, 0, 3);
3292 3dde962f Peter Maydell
    uint32_t t1sz = extract32(env->cp15.c2_control, 16, 3);
3293 3dde962f Peter Maydell
    if (t0sz && !extract32(address, 32 - t0sz, t0sz)) {
3294 3dde962f Peter Maydell
        /* there is a ttbr0 region and we are in it (high bits all zero) */
3295 3dde962f Peter Maydell
        ttbr_select = 0;
3296 3dde962f Peter Maydell
    } else if (t1sz && !extract32(~address, 32 - t1sz, t1sz)) {
3297 3dde962f Peter Maydell
        /* there is a ttbr1 region and we are in it (high bits all one) */
3298 3dde962f Peter Maydell
        ttbr_select = 1;
3299 3dde962f Peter Maydell
    } else if (!t0sz) {
3300 3dde962f Peter Maydell
        /* ttbr0 region is "everything not in the ttbr1 region" */
3301 3dde962f Peter Maydell
        ttbr_select = 0;
3302 3dde962f Peter Maydell
    } else if (!t1sz) {
3303 3dde962f Peter Maydell
        /* ttbr1 region is "everything not in the ttbr0 region" */
3304 3dde962f Peter Maydell
        ttbr_select = 1;
3305 3dde962f Peter Maydell
    } else {
3306 3dde962f Peter Maydell
        /* in the gap between the two regions, this is a Translation fault */
3307 3dde962f Peter Maydell
        fault_type = translation_fault;
3308 3dde962f Peter Maydell
        goto do_fault;
3309 3dde962f Peter Maydell
    }
3310 3dde962f Peter Maydell
3311 3dde962f Peter Maydell
    /* Note that QEMU ignores shareability and cacheability attributes,
3312 3dde962f Peter Maydell
     * so we don't need to do anything with the SH, ORGN, IRGN fields
3313 3dde962f Peter Maydell
     * in the TTBCR.  Similarly, TTBCR:A1 selects whether we get the
3314 3dde962f Peter Maydell
     * ASID from TTBR0 or TTBR1, but QEMU's TLB doesn't currently
3315 3dde962f Peter Maydell
     * implement any ASID-like capability so we can ignore it (instead
3316 3dde962f Peter Maydell
     * we will always flush the TLB any time the ASID is changed).
3317 3dde962f Peter Maydell
     */
3318 3dde962f Peter Maydell
    if (ttbr_select == 0) {
3319 327ed10f Peter Maydell
        ttbr = env->cp15.ttbr0_el1;
3320 3dde962f Peter Maydell
        epd = extract32(env->cp15.c2_control, 7, 1);
3321 3dde962f Peter Maydell
        tsz = t0sz;
3322 3dde962f Peter Maydell
    } else {
3323 327ed10f Peter Maydell
        ttbr = env->cp15.ttbr1_el1;
3324 3dde962f Peter Maydell
        epd = extract32(env->cp15.c2_control, 23, 1);
3325 3dde962f Peter Maydell
        tsz = t1sz;
3326 3dde962f Peter Maydell
    }
3327 3dde962f Peter Maydell
3328 3dde962f Peter Maydell
    if (epd) {
3329 3dde962f Peter Maydell
        /* Translation table walk disabled => Translation fault on TLB miss */
3330 3dde962f Peter Maydell
        goto do_fault;
3331 3dde962f Peter Maydell
    }
3332 3dde962f Peter Maydell
3333 3dde962f Peter Maydell
    /* If the region is small enough we will skip straight to a 2nd level
3334 3dde962f Peter Maydell
     * lookup. This affects the number of bits of the address used in
3335 3dde962f Peter Maydell
     * combination with the TTBR to find the first descriptor. ('n' here
3336 3dde962f Peter Maydell
     * matches the usage in the ARM ARM sB3.6.6, where bits [39..n] are
3337 3dde962f Peter Maydell
     * from the TTBR, [n-1..3] from the vaddr, and [2..0] always zero).
3338 3dde962f Peter Maydell
     */
3339 3dde962f Peter Maydell
    if (tsz > 1) {
3340 3dde962f Peter Maydell
        level = 2;
3341 3dde962f Peter Maydell
        n = 14 - tsz;
3342 3dde962f Peter Maydell
    } else {
3343 3dde962f Peter Maydell
        n = 5 - tsz;
3344 3dde962f Peter Maydell
    }
3345 3dde962f Peter Maydell
3346 3dde962f Peter Maydell
    /* Clear the vaddr bits which aren't part of the within-region address,
3347 3dde962f Peter Maydell
     * so that we don't have to special case things when calculating the
3348 3dde962f Peter Maydell
     * first descriptor address.
3349 3dde962f Peter Maydell
     */
3350 3dde962f Peter Maydell
    address &= (0xffffffffU >> tsz);
3351 3dde962f Peter Maydell
3352 3dde962f Peter Maydell
    /* Now we can extract the actual base address from the TTBR */
3353 3dde962f Peter Maydell
    descaddr = extract64(ttbr, 0, 40);
3354 3dde962f Peter Maydell
    descaddr &= ~((1ULL << n) - 1);
3355 3dde962f Peter Maydell
3356 3dde962f Peter Maydell
    tableattrs = 0;
3357 3dde962f Peter Maydell
    for (;;) {
3358 3dde962f Peter Maydell
        uint64_t descriptor;
3359 3dde962f Peter Maydell
3360 3dde962f Peter Maydell
        descaddr |= ((address >> (9 * (4 - level))) & 0xff8);
3361 2c17449b Edgar E. Iglesias
        descriptor = ldq_phys(cs->as, descaddr);
3362 3dde962f Peter Maydell
        if (!(descriptor & 1) ||
3363 3dde962f Peter Maydell
            (!(descriptor & 2) && (level == 3))) {
3364 3dde962f Peter Maydell
            /* Invalid, or the Reserved level 3 encoding */
3365 3dde962f Peter Maydell
            goto do_fault;
3366 3dde962f Peter Maydell
        }
3367 3dde962f Peter Maydell
        descaddr = descriptor & 0xfffffff000ULL;
3368 3dde962f Peter Maydell
3369 3dde962f Peter Maydell
        if ((descriptor & 2) && (level < 3)) {
3370 3dde962f Peter Maydell
            /* Table entry. The top five bits are attributes which  may
3371 3dde962f Peter Maydell
             * propagate down through lower levels of the table (and
3372 3dde962f Peter Maydell
             * which are all arranged so that 0 means "no effect", so
3373 3dde962f Peter Maydell
             * we can gather them up by ORing in the bits at each level).
3374 3dde962f Peter Maydell
             */
3375 3dde962f Peter Maydell
            tableattrs |= extract64(descriptor, 59, 5);
3376 3dde962f Peter Maydell
            level++;
3377 3dde962f Peter Maydell
            continue;
3378 3dde962f Peter Maydell
        }
3379 3dde962f Peter Maydell
        /* Block entry at level 1 or 2, or page entry at level 3.
3380 3dde962f Peter Maydell
         * These are basically the same thing, although the number
3381 3dde962f Peter Maydell
         * of bits we pull in from the vaddr varies.
3382 3dde962f Peter Maydell
         */
3383 3dde962f Peter Maydell
        page_size = (1 << (39 - (9 * level)));
3384 3dde962f Peter Maydell
        descaddr |= (address & (page_size - 1));
3385 3dde962f Peter Maydell
        /* Extract attributes from the descriptor and merge with table attrs */
3386 3dde962f Peter Maydell
        attrs = extract64(descriptor, 2, 10)
3387 3dde962f Peter Maydell
            | (extract64(descriptor, 52, 12) << 10);
3388 3dde962f Peter Maydell
        attrs |= extract32(tableattrs, 0, 2) << 11; /* XN, PXN */
3389 3dde962f Peter Maydell
        attrs |= extract32(tableattrs, 3, 1) << 5; /* APTable[1] => AP[2] */
3390 3dde962f Peter Maydell
        /* The sense of AP[1] vs APTable[0] is reversed, as APTable[0] == 1
3391 3dde962f Peter Maydell
         * means "force PL1 access only", which means forcing AP[1] to 0.
3392 3dde962f Peter Maydell
         */
3393 3dde962f Peter Maydell
        if (extract32(tableattrs, 2, 1)) {
3394 3dde962f Peter Maydell
            attrs &= ~(1 << 4);
3395 3dde962f Peter Maydell
        }
3396 3dde962f Peter Maydell
        /* Since we're always in the Non-secure state, NSTable is ignored. */
3397 3dde962f Peter Maydell
        break;
3398 3dde962f Peter Maydell
    }
3399 3dde962f Peter Maydell
    /* Here descaddr is the final physical address, and attributes
3400 3dde962f Peter Maydell
     * are all in attrs.
3401 3dde962f Peter Maydell
     */
3402 3dde962f Peter Maydell
    fault_type = access_fault;
3403 3dde962f Peter Maydell
    if ((attrs & (1 << 8)) == 0) {
3404 3dde962f Peter Maydell
        /* Access flag */
3405 3dde962f Peter Maydell
        goto do_fault;
3406 3dde962f Peter Maydell
    }
3407 3dde962f Peter Maydell
    fault_type = permission_fault;
3408 3dde962f Peter Maydell
    if (is_user && !(attrs & (1 << 4))) {
3409 3dde962f Peter Maydell
        /* Unprivileged access not enabled */
3410 3dde962f Peter Maydell
        goto do_fault;
3411 3dde962f Peter Maydell
    }
3412 3dde962f Peter Maydell
    *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
3413 3dde962f Peter Maydell
    if (attrs & (1 << 12) || (!is_user && (attrs & (1 << 11)))) {
3414 3dde962f Peter Maydell
        /* XN or PXN */
3415 3dde962f Peter Maydell
        if (access_type == 2) {
3416 3dde962f Peter Maydell
            goto do_fault;
3417 3dde962f Peter Maydell
        }
3418 3dde962f Peter Maydell
        *prot &= ~PAGE_EXEC;
3419 3dde962f Peter Maydell
    }
3420 3dde962f Peter Maydell
    if (attrs & (1 << 5)) {
3421 3dde962f Peter Maydell
        /* Write access forbidden */
3422 3dde962f Peter Maydell
        if (access_type == 1) {
3423 3dde962f Peter Maydell
            goto do_fault;
3424 3dde962f Peter Maydell
        }
3425 3dde962f Peter Maydell
        *prot &= ~PAGE_WRITE;
3426 3dde962f Peter Maydell
    }
3427 3dde962f Peter Maydell
3428 3dde962f Peter Maydell
    *phys_ptr = descaddr;
3429 3dde962f Peter Maydell
    *page_size_ptr = page_size;
3430 3dde962f Peter Maydell
    return 0;
3431 3dde962f Peter Maydell
3432 3dde962f Peter Maydell
do_fault:
3433 3dde962f Peter Maydell
    /* Long-descriptor format IFSR/DFSR value */
3434 3dde962f Peter Maydell
    return (1 << 9) | (fault_type << 2) | level;
3435 3dde962f Peter Maydell
}
3436 3dde962f Peter Maydell
3437 77a71dd1 Peter Maydell
static int get_phys_addr_mpu(CPUARMState *env, uint32_t address,
3438 77a71dd1 Peter Maydell
                             int access_type, int is_user,
3439 a8170e5e Avi Kivity
                             hwaddr *phys_ptr, int *prot)
3440 9ee6e8bb pbrook
{
3441 9ee6e8bb pbrook
    int n;
3442 9ee6e8bb pbrook
    uint32_t mask;
3443 9ee6e8bb pbrook
    uint32_t base;
3444 9ee6e8bb pbrook
3445 9ee6e8bb pbrook
    *phys_ptr = address;
3446 9ee6e8bb pbrook
    for (n = 7; n >= 0; n--) {
3447 9ee6e8bb pbrook
        base = env->cp15.c6_region[n];
3448 9ee6e8bb pbrook
        if ((base & 1) == 0)
3449 9ee6e8bb pbrook
            continue;
3450 9ee6e8bb pbrook
        mask = 1 << ((base >> 1) & 0x1f);
3451 9ee6e8bb pbrook
        /* Keep this shift separate from the above to avoid an
3452 9ee6e8bb pbrook
           (undefined) << 32.  */
3453 9ee6e8bb pbrook
        mask = (mask << 1) - 1;
3454 9ee6e8bb pbrook
        if (((base ^ address) & ~mask) == 0)
3455 9ee6e8bb pbrook
            break;
3456 9ee6e8bb pbrook
    }
3457 9ee6e8bb pbrook
    if (n < 0)
3458 9ee6e8bb pbrook
        return 2;
3459 9ee6e8bb pbrook
3460 9ee6e8bb pbrook
    if (access_type == 2) {
3461 9ee6e8bb pbrook
        mask = env->cp15.c5_insn;
3462 9ee6e8bb pbrook
    } else {
3463 9ee6e8bb pbrook
        mask = env->cp15.c5_data;
3464 9ee6e8bb pbrook
    }
3465 9ee6e8bb pbrook
    mask = (mask >> (n * 4)) & 0xf;
3466 9ee6e8bb pbrook
    switch (mask) {
3467 9ee6e8bb pbrook
    case 0:
3468 9ee6e8bb pbrook
        return 1;
3469 9ee6e8bb pbrook
    case 1:
3470 9ee6e8bb pbrook
        if (is_user)
3471 9ee6e8bb pbrook
          return 1;
3472 9ee6e8bb pbrook
        *prot = PAGE_READ | PAGE_WRITE;
3473 9ee6e8bb pbrook
        break;
3474 9ee6e8bb pbrook
    case 2:
3475 9ee6e8bb pbrook
        *prot = PAGE_READ;
3476 9ee6e8bb pbrook
        if (!is_user)
3477 9ee6e8bb pbrook
            *prot |= PAGE_WRITE;
3478 9ee6e8bb pbrook
        break;
3479 9ee6e8bb pbrook
    case 3:
3480 9ee6e8bb pbrook
        *prot = PAGE_READ | PAGE_WRITE;
3481 9ee6e8bb pbrook
        break;
3482 9ee6e8bb pbrook
    case 5:
3483 9ee6e8bb pbrook
        if (is_user)
3484 9ee6e8bb pbrook
            return 1;
3485 9ee6e8bb pbrook
        *prot = PAGE_READ;
3486 9ee6e8bb pbrook
        break;
3487 9ee6e8bb pbrook
    case 6:
3488 9ee6e8bb pbrook
        *prot = PAGE_READ;
3489 9ee6e8bb pbrook
        break;
3490 9ee6e8bb pbrook
    default:
3491 9ee6e8bb pbrook
        /* Bad permission.  */
3492 9ee6e8bb pbrook
        return 1;
3493 9ee6e8bb pbrook
    }
3494 3ad493fc Rabin Vincent
    *prot |= PAGE_EXEC;
3495 9ee6e8bb pbrook
    return 0;
3496 9ee6e8bb pbrook
}
3497 9ee6e8bb pbrook
3498 702a9357 Peter Maydell
/* get_phys_addr - get the physical address for this virtual address
3499 702a9357 Peter Maydell
 *
3500 702a9357 Peter Maydell
 * Find the physical address corresponding to the given virtual address,
3501 702a9357 Peter Maydell
 * by doing a translation table walk on MMU based systems or using the
3502 702a9357 Peter Maydell
 * MPU state on MPU based systems.
3503 702a9357 Peter Maydell
 *
3504 702a9357 Peter Maydell
 * Returns 0 if the translation was successful. Otherwise, phys_ptr,
3505 702a9357 Peter Maydell
 * prot and page_size are not filled in, and the return value provides
3506 702a9357 Peter Maydell
 * information on why the translation aborted, in the format of a
3507 702a9357 Peter Maydell
 * DFSR/IFSR fault register, with the following caveats:
3508 702a9357 Peter Maydell
 *  * we honour the short vs long DFSR format differences.
3509 702a9357 Peter Maydell
 *  * the WnR bit is never set (the caller must do this).
3510 702a9357 Peter Maydell
 *  * for MPU based systems we don't bother to return a full FSR format
3511 702a9357 Peter Maydell
 *    value.
3512 702a9357 Peter Maydell
 *
3513 702a9357 Peter Maydell
 * @env: CPUARMState
3514 702a9357 Peter Maydell
 * @address: virtual address to get physical address for
3515 702a9357 Peter Maydell
 * @access_type: 0 for read, 1 for write, 2 for execute
3516 702a9357 Peter Maydell
 * @is_user: 0 for privileged access, 1 for user
3517 702a9357 Peter Maydell
 * @phys_ptr: set to the physical address corresponding to the virtual address
3518 702a9357 Peter Maydell
 * @prot: set to the permissions for the page containing phys_ptr
3519 702a9357 Peter Maydell
 * @page_size: set to the size of the page containing phys_ptr
3520 702a9357 Peter Maydell
 */
3521 0ecb72a5 Andreas Färber
static inline int get_phys_addr(CPUARMState *env, uint32_t address,
3522 9ee6e8bb pbrook
                                int access_type, int is_user,
3523 a8170e5e Avi Kivity
                                hwaddr *phys_ptr, int *prot,
3524 d4c430a8 Paul Brook
                                target_ulong *page_size)
3525 9ee6e8bb pbrook
{
3526 9ee6e8bb pbrook
    /* Fast Context Switch Extension.  */
3527 9ee6e8bb pbrook
    if (address < 0x02000000)
3528 9ee6e8bb pbrook
        address += env->cp15.c13_fcse;
3529 9ee6e8bb pbrook
3530 76e3e1bc Peter Maydell
    if ((env->cp15.c1_sys & SCTLR_M) == 0) {
3531 9ee6e8bb pbrook
        /* MMU/MPU disabled.  */
3532 9ee6e8bb pbrook
        *phys_ptr = address;
3533 3ad493fc Rabin Vincent
        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
3534 d4c430a8 Paul Brook
        *page_size = TARGET_PAGE_SIZE;
3535 9ee6e8bb pbrook
        return 0;
3536 9ee6e8bb pbrook
    } else if (arm_feature(env, ARM_FEATURE_MPU)) {
3537 d4c430a8 Paul Brook
        *page_size = TARGET_PAGE_SIZE;
3538 9ee6e8bb pbrook
        return get_phys_addr_mpu(env, address, access_type, is_user, phys_ptr,
3539 9ee6e8bb pbrook
                                 prot);
3540 3dde962f Peter Maydell
    } else if (extended_addresses_enabled(env)) {
3541 3dde962f Peter Maydell
        return get_phys_addr_lpae(env, address, access_type, is_user, phys_ptr,
3542 3dde962f Peter Maydell
                                  prot, page_size);
3543 76e3e1bc Peter Maydell
    } else if (env->cp15.c1_sys & SCTLR_XP) {
3544 9ee6e8bb pbrook
        return get_phys_addr_v6(env, address, access_type, is_user, phys_ptr,
3545 d4c430a8 Paul Brook
                                prot, page_size);
3546 9ee6e8bb pbrook
    } else {
3547 9ee6e8bb pbrook
        return get_phys_addr_v5(env, address, access_type, is_user, phys_ptr,
3548 d4c430a8 Paul Brook
                                prot, page_size);
3549 9ee6e8bb pbrook
    }
3550 9ee6e8bb pbrook
}
3551 9ee6e8bb pbrook
3552 0ecb72a5 Andreas Färber
int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address,
3553 97b348e7 Blue Swirl
                              int access_type, int mmu_idx)
3554 b5ff1b31 bellard
{
3555 a8170e5e Avi Kivity
    hwaddr phys_addr;
3556 d4c430a8 Paul Brook
    target_ulong page_size;
3557 b5ff1b31 bellard
    int prot;
3558 6ebbf390 j_mayer
    int ret, is_user;
3559 b5ff1b31 bellard
3560 6ebbf390 j_mayer
    is_user = mmu_idx == MMU_USER_IDX;
3561 d4c430a8 Paul Brook
    ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot,
3562 d4c430a8 Paul Brook
                        &page_size);
3563 b5ff1b31 bellard
    if (ret == 0) {
3564 b5ff1b31 bellard
        /* Map a single [sub]page.  */
3565 a8170e5e Avi Kivity
        phys_addr &= ~(hwaddr)0x3ff;
3566 b5ff1b31 bellard
        address &= ~(uint32_t)0x3ff;
3567 3ad493fc Rabin Vincent
        tlb_set_page (env, address, phys_addr, prot, mmu_idx, page_size);
3568 d4c430a8 Paul Brook
        return 0;
3569 b5ff1b31 bellard
    }
3570 b5ff1b31 bellard
3571 b5ff1b31 bellard
    if (access_type == 2) {
3572 b5ff1b31 bellard
        env->cp15.c5_insn = ret;
3573 b5ff1b31 bellard
        env->cp15.c6_insn = address;
3574 b5ff1b31 bellard
        env->exception_index = EXCP_PREFETCH_ABORT;
3575 b5ff1b31 bellard
    } else {
3576 b5ff1b31 bellard
        env->cp15.c5_data = ret;
3577 9ee6e8bb pbrook
        if (access_type == 1 && arm_feature(env, ARM_FEATURE_V6))
3578 9ee6e8bb pbrook
            env->cp15.c5_data |= (1 << 11);
3579 b5ff1b31 bellard
        env->cp15.c6_data = address;
3580 b5ff1b31 bellard
        env->exception_index = EXCP_DATA_ABORT;
3581 b5ff1b31 bellard
    }
3582 b5ff1b31 bellard
    return 1;
3583 b5ff1b31 bellard
}
3584 b5ff1b31 bellard
3585 00b941e5 Andreas Färber
hwaddr arm_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
3586 b5ff1b31 bellard
{
3587 00b941e5 Andreas Färber
    ARMCPU *cpu = ARM_CPU(cs);
3588 a8170e5e Avi Kivity
    hwaddr phys_addr;
3589 d4c430a8 Paul Brook
    target_ulong page_size;
3590 b5ff1b31 bellard
    int prot;
3591 b5ff1b31 bellard
    int ret;
3592 b5ff1b31 bellard
3593 00b941e5 Andreas Färber
    ret = get_phys_addr(&cpu->env, addr, 0, 0, &phys_addr, &prot, &page_size);
3594 b5ff1b31 bellard
3595 00b941e5 Andreas Färber
    if (ret != 0) {
3596 b5ff1b31 bellard
        return -1;
3597 00b941e5 Andreas Färber
    }
3598 b5ff1b31 bellard
3599 b5ff1b31 bellard
    return phys_addr;
3600 b5ff1b31 bellard
}
3601 b5ff1b31 bellard
3602 0ecb72a5 Andreas Färber
void HELPER(set_r13_banked)(CPUARMState *env, uint32_t mode, uint32_t val)
3603 9ee6e8bb pbrook
{
3604 39ea3d4e Peter Maydell
    if ((env->uncached_cpsr & CPSR_M) == mode) {
3605 39ea3d4e Peter Maydell
        env->regs[13] = val;
3606 39ea3d4e Peter Maydell
    } else {
3607 f5206413 Peter Maydell
        env->banked_r13[bank_number(mode)] = val;
3608 39ea3d4e Peter Maydell
    }
3609 9ee6e8bb pbrook
}
3610 9ee6e8bb pbrook
3611 0ecb72a5 Andreas Färber
uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode)
3612 9ee6e8bb pbrook
{
3613 39ea3d4e Peter Maydell
    if ((env->uncached_cpsr & CPSR_M) == mode) {
3614 39ea3d4e Peter Maydell
        return env->regs[13];
3615 39ea3d4e Peter Maydell
    } else {
3616 f5206413 Peter Maydell
        return env->banked_r13[bank_number(mode)];
3617 39ea3d4e Peter Maydell
    }
3618 9ee6e8bb pbrook
}
3619 9ee6e8bb pbrook
3620 0ecb72a5 Andreas Färber
uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
3621 9ee6e8bb pbrook
{
3622 9ee6e8bb pbrook
    switch (reg) {
3623 9ee6e8bb pbrook
    case 0: /* APSR */
3624 9ee6e8bb pbrook
        return xpsr_read(env) & 0xf8000000;
3625 9ee6e8bb pbrook
    case 1: /* IAPSR */
3626 9ee6e8bb pbrook
        return xpsr_read(env) & 0xf80001ff;
3627 9ee6e8bb pbrook
    case 2: /* EAPSR */
3628 9ee6e8bb pbrook
        return xpsr_read(env) & 0xff00fc00;
3629 9ee6e8bb pbrook
    case 3: /* xPSR */
3630 9ee6e8bb pbrook
        return xpsr_read(env) & 0xff00fdff;
3631 9ee6e8bb pbrook
    case 5: /* IPSR */
3632 9ee6e8bb pbrook
        return xpsr_read(env) & 0x000001ff;
3633 9ee6e8bb pbrook
    case 6: /* EPSR */
3634 9ee6e8bb pbrook
        return xpsr_read(env) & 0x0700fc00;
3635 9ee6e8bb pbrook
    case 7: /* IEPSR */
3636 9ee6e8bb pbrook
        return xpsr_read(env) & 0x0700edff;
3637 9ee6e8bb pbrook
    case 8: /* MSP */
3638 9ee6e8bb pbrook
        return env->v7m.current_sp ? env->v7m.other_sp : env->regs[13];
3639 9ee6e8bb pbrook
    case 9: /* PSP */
3640 9ee6e8bb pbrook
        return env->v7m.current_sp ? env->regs[13] : env->v7m.other_sp;
3641 9ee6e8bb pbrook
    case 16: /* PRIMASK */
3642 4cc35614 Peter Maydell
        return (env->daif & PSTATE_I) != 0;
3643 82845826 Sebastian Huber
    case 17: /* BASEPRI */
3644 82845826 Sebastian Huber
    case 18: /* BASEPRI_MAX */
3645 9ee6e8bb pbrook
        return env->v7m.basepri;
3646 82845826 Sebastian Huber
    case 19: /* FAULTMASK */
3647 4cc35614 Peter Maydell
        return (env->daif & PSTATE_F) != 0;
3648 9ee6e8bb pbrook
    case 20: /* CONTROL */
3649 9ee6e8bb pbrook
        return env->v7m.control;
3650 9ee6e8bb pbrook
    default:
3651 9ee6e8bb pbrook
        /* ??? For debugging only.  */
3652 9ee6e8bb pbrook
        cpu_abort(env, "Unimplemented system register read (%d)\n", reg);
3653 9ee6e8bb pbrook
        return 0;
3654 9ee6e8bb pbrook
    }
3655 9ee6e8bb pbrook
}
3656 9ee6e8bb pbrook
3657 0ecb72a5 Andreas Färber
void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
3658 9ee6e8bb pbrook
{
3659 9ee6e8bb pbrook
    switch (reg) {
3660 9ee6e8bb pbrook
    case 0: /* APSR */
3661 9ee6e8bb pbrook
        xpsr_write(env, val, 0xf8000000);
3662 9ee6e8bb pbrook
        break;
3663 9ee6e8bb pbrook
    case 1: /* IAPSR */
3664 9ee6e8bb pbrook
        xpsr_write(env, val, 0xf8000000);
3665 9ee6e8bb pbrook
        break;
3666 9ee6e8bb pbrook
    case 2: /* EAPSR */
3667 9ee6e8bb pbrook
        xpsr_write(env, val, 0xfe00fc00);
3668 9ee6e8bb pbrook
        break;
3669 9ee6e8bb pbrook
    case 3: /* xPSR */
3670 9ee6e8bb pbrook
        xpsr_write(env, val, 0xfe00fc00);
3671 9ee6e8bb pbrook
        break;
3672 9ee6e8bb pbrook
    case 5: /* IPSR */
3673 9ee6e8bb pbrook
        /* IPSR bits are readonly.  */
3674 9ee6e8bb pbrook
        break;
3675 9ee6e8bb pbrook
    case 6: /* EPSR */
3676 9ee6e8bb pbrook
        xpsr_write(env, val, 0x0600fc00);
3677 9ee6e8bb pbrook
        break;
3678 9ee6e8bb pbrook
    case 7: /* IEPSR */
3679 9ee6e8bb pbrook
        xpsr_write(env, val, 0x0600fc00);
3680 9ee6e8bb pbrook
        break;
3681 9ee6e8bb pbrook
    case 8: /* MSP */
3682 9ee6e8bb pbrook
        if (env->v7m.current_sp)
3683 9ee6e8bb pbrook
            env->v7m.other_sp = val;
3684 9ee6e8bb pbrook
        else
3685 9ee6e8bb pbrook
            env->regs[13] = val;
3686 9ee6e8bb pbrook
        break;
3687 9ee6e8bb pbrook
    case 9: /* PSP */
3688 9ee6e8bb pbrook
        if (env->v7m.current_sp)
3689 9ee6e8bb pbrook
            env->regs[13] = val;
3690 9ee6e8bb pbrook
        else
3691 9ee6e8bb pbrook
            env->v7m.other_sp = val;
3692 9ee6e8bb pbrook
        break;
3693 9ee6e8bb pbrook
    case 16: /* PRIMASK */
3694 4cc35614 Peter Maydell
        if (val & 1) {
3695 4cc35614 Peter Maydell
            env->daif |= PSTATE_I;
3696 4cc35614 Peter Maydell
        } else {
3697 4cc35614 Peter Maydell
            env->daif &= ~PSTATE_I;
3698 4cc35614 Peter Maydell
        }
3699 9ee6e8bb pbrook
        break;
3700 82845826 Sebastian Huber
    case 17: /* BASEPRI */
3701 9ee6e8bb pbrook
        env->v7m.basepri = val & 0xff;
3702 9ee6e8bb pbrook
        break;
3703 82845826 Sebastian Huber
    case 18: /* BASEPRI_MAX */
3704 9ee6e8bb pbrook
        val &= 0xff;
3705 9ee6e8bb pbrook
        if (val != 0 && (val < env->v7m.basepri || env->v7m.basepri == 0))
3706 9ee6e8bb pbrook
            env->v7m.basepri = val;
3707 9ee6e8bb pbrook
        break;
3708 82845826 Sebastian Huber
    case 19: /* FAULTMASK */
3709 4cc35614 Peter Maydell
        if (val & 1) {
3710 4cc35614 Peter Maydell
            env->daif |= PSTATE_F;
3711 4cc35614 Peter Maydell
        } else {
3712 4cc35614 Peter Maydell
            env->daif &= ~PSTATE_F;
3713 4cc35614 Peter Maydell
        }
3714 82845826 Sebastian Huber
        break;
3715 9ee6e8bb pbrook
    case 20: /* CONTROL */
3716 9ee6e8bb pbrook
        env->v7m.control = val & 3;
3717 9ee6e8bb pbrook
        switch_v7m_sp(env, (val & 2) != 0);
3718 9ee6e8bb pbrook
        break;
3719 9ee6e8bb pbrook
    default:
3720 9ee6e8bb pbrook
        /* ??? For debugging only.  */
3721 9ee6e8bb pbrook
        cpu_abort(env, "Unimplemented system register write (%d)\n", reg);
3722 9ee6e8bb pbrook
        return;
3723 9ee6e8bb pbrook
    }
3724 9ee6e8bb pbrook
}
3725 9ee6e8bb pbrook
3726 b5ff1b31 bellard
#endif
3727 6ddbc6e4 pbrook
3728 6ddbc6e4 pbrook
/* Note that signed overflow is undefined in C.  The following routines are
3729 6ddbc6e4 pbrook
   careful to use unsigned types where modulo arithmetic is required.
3730 6ddbc6e4 pbrook
   Failure to do so _will_ break on newer gcc.  */
3731 6ddbc6e4 pbrook
3732 6ddbc6e4 pbrook
/* Signed saturating arithmetic.  */
3733 6ddbc6e4 pbrook
3734 1654b2d6 aurel32
/* Perform 16-bit signed saturating addition.  */
3735 6ddbc6e4 pbrook
static inline uint16_t add16_sat(uint16_t a, uint16_t b)
3736 6ddbc6e4 pbrook
{
3737 6ddbc6e4 pbrook
    uint16_t res;
3738 6ddbc6e4 pbrook
3739 6ddbc6e4 pbrook
    res = a + b;
3740 6ddbc6e4 pbrook
    if (((res ^ a) & 0x8000) && !((a ^ b) & 0x8000)) {
3741 6ddbc6e4 pbrook
        if (a & 0x8000)
3742 6ddbc6e4 pbrook
            res = 0x8000;
3743 6ddbc6e4 pbrook
        else
3744 6ddbc6e4 pbrook
            res = 0x7fff;
3745 6ddbc6e4 pbrook
    }
3746 6ddbc6e4 pbrook
    return res;
3747 6ddbc6e4 pbrook
}
3748 6ddbc6e4 pbrook
3749 1654b2d6 aurel32
/* Perform 8-bit signed saturating addition.  */
3750 6ddbc6e4 pbrook
static inline uint8_t add8_sat(uint8_t a, uint8_t b)
3751 6ddbc6e4 pbrook
{
3752 6ddbc6e4 pbrook
    uint8_t res;
3753 6ddbc6e4 pbrook
3754 6ddbc6e4 pbrook
    res = a + b;
3755 6ddbc6e4 pbrook
    if (((res ^ a) & 0x80) && !((a ^ b) & 0x80)) {
3756 6ddbc6e4 pbrook
        if (a & 0x80)
3757 6ddbc6e4 pbrook
            res = 0x80;
3758 6ddbc6e4 pbrook
        else
3759 6ddbc6e4 pbrook
            res = 0x7f;
3760 6ddbc6e4 pbrook
    }
3761 6ddbc6e4 pbrook
    return res;
3762 6ddbc6e4 pbrook
}
3763 6ddbc6e4 pbrook
3764 1654b2d6 aurel32
/* Perform 16-bit signed saturating subtraction.  */
3765 6ddbc6e4 pbrook
static inline uint16_t sub16_sat(uint16_t a, uint16_t b)
3766 6ddbc6e4 pbrook
{
3767 6ddbc6e4 pbrook
    uint16_t res;
3768 6ddbc6e4 pbrook
3769 6ddbc6e4 pbrook
    res = a - b;
3770 6ddbc6e4 pbrook
    if (((res ^ a) & 0x8000) && ((a ^ b) & 0x8000)) {
3771 6ddbc6e4 pbrook
        if (a & 0x8000)
3772 6ddbc6e4 pbrook
            res = 0x8000;
3773 6ddbc6e4 pbrook
        else
3774 6ddbc6e4 pbrook
            res = 0x7fff;
3775 6ddbc6e4 pbrook
    }
3776 6ddbc6e4 pbrook
    return res;
3777 6ddbc6e4 pbrook
}
3778 6ddbc6e4 pbrook
3779 1654b2d6 aurel32
/* Perform 8-bit signed saturating subtraction.  */
3780 6ddbc6e4 pbrook
static inline uint8_t sub8_sat(uint8_t a, uint8_t b)
3781 6ddbc6e4 pbrook
{
3782 6ddbc6e4 pbrook
    uint8_t res;
3783 6ddbc6e4 pbrook
3784 6ddbc6e4 pbrook
    res = a - b;
3785 6ddbc6e4 pbrook
    if (((res ^ a) & 0x80) && ((a ^ b) & 0x80)) {
3786 6ddbc6e4 pbrook
        if (a & 0x80)
3787 6ddbc6e4 pbrook
            res = 0x80;
3788 6ddbc6e4 pbrook
        else
3789 6ddbc6e4 pbrook
            res = 0x7f;
3790 6ddbc6e4 pbrook
    }
3791 6ddbc6e4 pbrook
    return res;
3792 6ddbc6e4 pbrook
}
3793 6ddbc6e4 pbrook
3794 6ddbc6e4 pbrook
#define ADD16(a, b, n) RESULT(add16_sat(a, b), n, 16);
3795 6ddbc6e4 pbrook
#define SUB16(a, b, n) RESULT(sub16_sat(a, b), n, 16);
3796 6ddbc6e4 pbrook
#define ADD8(a, b, n)  RESULT(add8_sat(a, b), n, 8);
3797 6ddbc6e4 pbrook
#define SUB8(a, b, n)  RESULT(sub8_sat(a, b), n, 8);
3798 6ddbc6e4 pbrook
#define PFX q
3799 6ddbc6e4 pbrook
3800 6ddbc6e4 pbrook
#include "op_addsub.h"
3801 6ddbc6e4 pbrook
3802 6ddbc6e4 pbrook
/* Unsigned saturating arithmetic.  */
3803 460a09c1 pbrook
static inline uint16_t add16_usat(uint16_t a, uint16_t b)
3804 6ddbc6e4 pbrook
{
3805 6ddbc6e4 pbrook
    uint16_t res;
3806 6ddbc6e4 pbrook
    res = a + b;
3807 6ddbc6e4 pbrook
    if (res < a)
3808 6ddbc6e4 pbrook
        res = 0xffff;
3809 6ddbc6e4 pbrook
    return res;
3810 6ddbc6e4 pbrook
}
3811 6ddbc6e4 pbrook
3812 460a09c1 pbrook
static inline uint16_t sub16_usat(uint16_t a, uint16_t b)
3813 6ddbc6e4 pbrook
{
3814 4c4fd3f8 Chih-Min Chao
    if (a > b)
3815 6ddbc6e4 pbrook
        return a - b;
3816 6ddbc6e4 pbrook
    else
3817 6ddbc6e4 pbrook
        return 0;
3818 6ddbc6e4 pbrook
}
3819 6ddbc6e4 pbrook
3820 6ddbc6e4 pbrook
static inline uint8_t add8_usat(uint8_t a, uint8_t b)
3821 6ddbc6e4 pbrook
{
3822 6ddbc6e4 pbrook
    uint8_t res;
3823 6ddbc6e4 pbrook
    res = a + b;
3824 6ddbc6e4 pbrook
    if (res < a)
3825 6ddbc6e4 pbrook
        res = 0xff;
3826 6ddbc6e4 pbrook
    return res;
3827 6ddbc6e4 pbrook
}
3828 6ddbc6e4 pbrook
3829 6ddbc6e4 pbrook
static inline uint8_t sub8_usat(uint8_t a, uint8_t b)
3830 6ddbc6e4 pbrook
{
3831 4c4fd3f8 Chih-Min Chao
    if (a > b)
3832 6ddbc6e4 pbrook
        return a - b;
3833 6ddbc6e4 pbrook
    else
3834 6ddbc6e4 pbrook
        return 0;
3835 6ddbc6e4 pbrook
}
3836 6ddbc6e4 pbrook
3837 6ddbc6e4 pbrook
#define ADD16(a, b, n) RESULT(add16_usat(a, b), n, 16);
3838 6ddbc6e4 pbrook
#define SUB16(a, b, n) RESULT(sub16_usat(a, b), n, 16);
3839 6ddbc6e4 pbrook
#define ADD8(a, b, n)  RESULT(add8_usat(a, b), n, 8);
3840 6ddbc6e4 pbrook
#define SUB8(a, b, n)  RESULT(sub8_usat(a, b), n, 8);
3841 6ddbc6e4 pbrook
#define PFX uq
3842 6ddbc6e4 pbrook
3843 6ddbc6e4 pbrook
#include "op_addsub.h"
3844 6ddbc6e4 pbrook
3845 6ddbc6e4 pbrook
/* Signed modulo arithmetic.  */
3846 6ddbc6e4 pbrook
#define SARITH16(a, b, n, op) do { \
3847 6ddbc6e4 pbrook
    int32_t sum; \
3848 db6e2e65 Peter Maydell
    sum = (int32_t)(int16_t)(a) op (int32_t)(int16_t)(b); \
3849 6ddbc6e4 pbrook
    RESULT(sum, n, 16); \
3850 6ddbc6e4 pbrook
    if (sum >= 0) \
3851 6ddbc6e4 pbrook
        ge |= 3 << (n * 2); \
3852 6ddbc6e4 pbrook
    } while(0)
3853 6ddbc6e4 pbrook
3854 6ddbc6e4 pbrook
#define SARITH8(a, b, n, op) do { \
3855 6ddbc6e4 pbrook
    int32_t sum; \
3856 db6e2e65 Peter Maydell
    sum = (int32_t)(int8_t)(a) op (int32_t)(int8_t)(b); \
3857 6ddbc6e4 pbrook
    RESULT(sum, n, 8); \
3858 6ddbc6e4 pbrook
    if (sum >= 0) \
3859 6ddbc6e4 pbrook
        ge |= 1 << n; \
3860 6ddbc6e4 pbrook
    } while(0)
3861 6ddbc6e4 pbrook
3862 6ddbc6e4 pbrook
3863 6ddbc6e4 pbrook
#define ADD16(a, b, n) SARITH16(a, b, n, +)
3864 6ddbc6e4 pbrook
#define SUB16(a, b, n) SARITH16(a, b, n, -)
3865 6ddbc6e4 pbrook
#define ADD8(a, b, n)  SARITH8(a, b, n, +)
3866 6ddbc6e4 pbrook
#define SUB8(a, b, n)  SARITH8(a, b, n, -)
3867 6ddbc6e4 pbrook
#define PFX s
3868 6ddbc6e4 pbrook
#define ARITH_GE
3869 6ddbc6e4 pbrook
3870 6ddbc6e4 pbrook
#include "op_addsub.h"
3871 6ddbc6e4 pbrook
3872 6ddbc6e4 pbrook
/* Unsigned modulo arithmetic.  */
3873 6ddbc6e4 pbrook
#define ADD16(a, b, n) do { \
3874 6ddbc6e4 pbrook
    uint32_t sum; \
3875 6ddbc6e4 pbrook
    sum = (uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b); \
3876 6ddbc6e4 pbrook
    RESULT(sum, n, 16); \
3877 a87aa10b balrog
    if ((sum >> 16) == 1) \
3878 6ddbc6e4 pbrook
        ge |= 3 << (n * 2); \
3879 6ddbc6e4 pbrook
    } while(0)
3880 6ddbc6e4 pbrook
3881 6ddbc6e4 pbrook
#define ADD8(a, b, n) do { \
3882 6ddbc6e4 pbrook
    uint32_t sum; \
3883 6ddbc6e4 pbrook
    sum = (uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b); \
3884 6ddbc6e4 pbrook
    RESULT(sum, n, 8); \
3885 a87aa10b balrog
    if ((sum >> 8) == 1) \
3886 a87aa10b balrog
        ge |= 1 << n; \
3887 6ddbc6e4 pbrook
    } while(0)
3888 6ddbc6e4 pbrook
3889 6ddbc6e4 pbrook
#define SUB16(a, b, n) do { \
3890 6ddbc6e4 pbrook
    uint32_t sum; \
3891 6ddbc6e4 pbrook
    sum = (uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b); \
3892 6ddbc6e4 pbrook
    RESULT(sum, n, 16); \
3893 6ddbc6e4 pbrook
    if ((sum >> 16) == 0) \
3894 6ddbc6e4 pbrook
        ge |= 3 << (n * 2); \
3895 6ddbc6e4 pbrook
    } while(0)
3896 6ddbc6e4 pbrook
3897 6ddbc6e4 pbrook
#define SUB8(a, b, n) do { \
3898 6ddbc6e4 pbrook
    uint32_t sum; \
3899 6ddbc6e4 pbrook
    sum = (uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b); \
3900 6ddbc6e4 pbrook
    RESULT(sum, n, 8); \
3901 6ddbc6e4 pbrook
    if ((sum >> 8) == 0) \
3902 a87aa10b balrog
        ge |= 1 << n; \
3903 6ddbc6e4 pbrook
    } while(0)
3904 6ddbc6e4 pbrook
3905 6ddbc6e4 pbrook
#define PFX u
3906 6ddbc6e4 pbrook
#define ARITH_GE
3907 6ddbc6e4 pbrook
3908 6ddbc6e4 pbrook
#include "op_addsub.h"
3909 6ddbc6e4 pbrook
3910 6ddbc6e4 pbrook
/* Halved signed arithmetic.  */
3911 6ddbc6e4 pbrook
#define ADD16(a, b, n) \
3912 6ddbc6e4 pbrook
  RESULT(((int32_t)(int16_t)(a) + (int32_t)(int16_t)(b)) >> 1, n, 16)
3913 6ddbc6e4 pbrook
#define SUB16(a, b, n) \
3914 6ddbc6e4 pbrook
  RESULT(((int32_t)(int16_t)(a) - (int32_t)(int16_t)(b)) >> 1, n, 16)
3915 6ddbc6e4 pbrook
#define ADD8(a, b, n) \
3916 6ddbc6e4 pbrook
  RESULT(((int32_t)(int8_t)(a) + (int32_t)(int8_t)(b)) >> 1, n, 8)
3917 6ddbc6e4 pbrook
#define SUB8(a, b, n) \
3918 6ddbc6e4 pbrook
  RESULT(((int32_t)(int8_t)(a) - (int32_t)(int8_t)(b)) >> 1, n, 8)
3919 6ddbc6e4 pbrook
#define PFX sh
3920 6ddbc6e4 pbrook
3921 6ddbc6e4 pbrook
#include "op_addsub.h"
3922 6ddbc6e4 pbrook
3923 6ddbc6e4 pbrook
/* Halved unsigned arithmetic.  */
3924 6ddbc6e4 pbrook
#define ADD16(a, b, n) \
3925 6ddbc6e4 pbrook
  RESULT(((uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b)) >> 1, n, 16)
3926 6ddbc6e4 pbrook
#define SUB16(a, b, n) \
3927 6ddbc6e4 pbrook
  RESULT(((uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b)) >> 1, n, 16)
3928 6ddbc6e4 pbrook
#define ADD8(a, b, n) \
3929 6ddbc6e4 pbrook
  RESULT(((uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b)) >> 1, n, 8)
3930 6ddbc6e4 pbrook
#define SUB8(a, b, n) \
3931 6ddbc6e4 pbrook
  RESULT(((uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b)) >> 1, n, 8)
3932 6ddbc6e4 pbrook
#define PFX uh
3933 6ddbc6e4 pbrook
3934 6ddbc6e4 pbrook
#include "op_addsub.h"
3935 6ddbc6e4 pbrook
3936 6ddbc6e4 pbrook
static inline uint8_t do_usad(uint8_t a, uint8_t b)
3937 6ddbc6e4 pbrook
{
3938 6ddbc6e4 pbrook
    if (a > b)
3939 6ddbc6e4 pbrook
        return a - b;
3940 6ddbc6e4 pbrook
    else
3941 6ddbc6e4 pbrook
        return b - a;
3942 6ddbc6e4 pbrook
}
3943 6ddbc6e4 pbrook
3944 6ddbc6e4 pbrook
/* Unsigned sum of absolute byte differences.  */
3945 6ddbc6e4 pbrook
uint32_t HELPER(usad8)(uint32_t a, uint32_t b)
3946 6ddbc6e4 pbrook
{
3947 6ddbc6e4 pbrook
    uint32_t sum;
3948 6ddbc6e4 pbrook
    sum = do_usad(a, b);
3949 6ddbc6e4 pbrook
    sum += do_usad(a >> 8, b >> 8);
3950 6ddbc6e4 pbrook
    sum += do_usad(a >> 16, b >>16);
3951 6ddbc6e4 pbrook
    sum += do_usad(a >> 24, b >> 24);
3952 6ddbc6e4 pbrook
    return sum;
3953 6ddbc6e4 pbrook
}
3954 6ddbc6e4 pbrook
3955 6ddbc6e4 pbrook
/* For ARMv6 SEL instruction.  */
3956 6ddbc6e4 pbrook
uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b)
3957 6ddbc6e4 pbrook
{
3958 6ddbc6e4 pbrook
    uint32_t mask;
3959 6ddbc6e4 pbrook
3960 6ddbc6e4 pbrook
    mask = 0;
3961 6ddbc6e4 pbrook
    if (flags & 1)
3962 6ddbc6e4 pbrook
        mask |= 0xff;
3963 6ddbc6e4 pbrook
    if (flags & 2)
3964 6ddbc6e4 pbrook
        mask |= 0xff00;
3965 6ddbc6e4 pbrook
    if (flags & 4)
3966 6ddbc6e4 pbrook
        mask |= 0xff0000;
3967 6ddbc6e4 pbrook
    if (flags & 8)
3968 6ddbc6e4 pbrook
        mask |= 0xff000000;
3969 6ddbc6e4 pbrook
    return (a & mask) | (b & ~mask);
3970 6ddbc6e4 pbrook
}
3971 6ddbc6e4 pbrook
3972 b90372ad Peter Maydell
/* VFP support.  We follow the convention used for VFP instructions:
3973 b90372ad Peter Maydell
   Single precision routines have a "s" suffix, double precision a
3974 4373f3ce pbrook
   "d" suffix.  */
3975 4373f3ce pbrook
3976 4373f3ce pbrook
/* Convert host exception flags to vfp form.  */
3977 4373f3ce pbrook
static inline int vfp_exceptbits_from_host(int host_bits)
3978 4373f3ce pbrook
{
3979 4373f3ce pbrook
    int target_bits = 0;
3980 4373f3ce pbrook
3981 4373f3ce pbrook
    if (host_bits & float_flag_invalid)
3982 4373f3ce pbrook
        target_bits |= 1;
3983 4373f3ce pbrook
    if (host_bits & float_flag_divbyzero)
3984 4373f3ce pbrook
        target_bits |= 2;
3985 4373f3ce pbrook
    if (host_bits & float_flag_overflow)
3986 4373f3ce pbrook
        target_bits |= 4;
3987 36802b6b Peter Maydell
    if (host_bits & (float_flag_underflow | float_flag_output_denormal))
3988 4373f3ce pbrook
        target_bits |= 8;
3989 4373f3ce pbrook
    if (host_bits & float_flag_inexact)
3990 4373f3ce pbrook
        target_bits |= 0x10;
3991 cecd8504 Peter Maydell
    if (host_bits & float_flag_input_denormal)
3992 cecd8504 Peter Maydell
        target_bits |= 0x80;
3993 4373f3ce pbrook
    return target_bits;
3994 4373f3ce pbrook
}
3995 4373f3ce pbrook
3996 0ecb72a5 Andreas Färber
uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env)
3997 4373f3ce pbrook
{
3998 4373f3ce pbrook
    int i;
3999 4373f3ce pbrook
    uint32_t fpscr;
4000 4373f3ce pbrook
4001 4373f3ce pbrook
    fpscr = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff)
4002 4373f3ce pbrook
            | (env->vfp.vec_len << 16)
4003 4373f3ce pbrook
            | (env->vfp.vec_stride << 20);
4004 4373f3ce pbrook
    i = get_float_exception_flags(&env->vfp.fp_status);
4005 3a492f3a Peter Maydell
    i |= get_float_exception_flags(&env->vfp.standard_fp_status);
4006 4373f3ce pbrook
    fpscr |= vfp_exceptbits_from_host(i);
4007 4373f3ce pbrook
    return fpscr;
4008 4373f3ce pbrook
}
4009 4373f3ce pbrook
4010 0ecb72a5 Andreas Färber
uint32_t vfp_get_fpscr(CPUARMState *env)
4011 01653295 Peter Maydell
{
4012 01653295 Peter Maydell
    return HELPER(vfp_get_fpscr)(env);
4013 01653295 Peter Maydell
}
4014 01653295 Peter Maydell
4015 4373f3ce pbrook
/* Convert vfp exception flags to target form.  */
4016 4373f3ce pbrook
static inline int vfp_exceptbits_to_host(int target_bits)
4017 4373f3ce pbrook
{
4018 4373f3ce pbrook
    int host_bits = 0;
4019 4373f3ce pbrook
4020 4373f3ce pbrook
    if (target_bits & 1)
4021 4373f3ce pbrook
        host_bits |= float_flag_invalid;
4022 4373f3ce pbrook
    if (target_bits & 2)
4023 4373f3ce pbrook
        host_bits |= float_flag_divbyzero;
4024 4373f3ce pbrook
    if (target_bits & 4)
4025 4373f3ce pbrook
        host_bits |= float_flag_overflow;
4026 4373f3ce pbrook
    if (target_bits & 8)
4027 4373f3ce pbrook
        host_bits |= float_flag_underflow;
4028 4373f3ce pbrook
    if (target_bits & 0x10)
4029 4373f3ce pbrook
        host_bits |= float_flag_inexact;
4030 cecd8504 Peter Maydell
    if (target_bits & 0x80)
4031 cecd8504 Peter Maydell
        host_bits |= float_flag_input_denormal;
4032 4373f3ce pbrook
    return host_bits;
4033 4373f3ce pbrook
}
4034 4373f3ce pbrook
4035 0ecb72a5 Andreas Färber
void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
4036 4373f3ce pbrook
{
4037 4373f3ce pbrook
    int i;
4038 4373f3ce pbrook
    uint32_t changed;
4039 4373f3ce pbrook
4040 4373f3ce pbrook
    changed = env->vfp.xregs[ARM_VFP_FPSCR];
4041 4373f3ce pbrook
    env->vfp.xregs[ARM_VFP_FPSCR] = (val & 0xffc8ffff);
4042 4373f3ce pbrook
    env->vfp.vec_len = (val >> 16) & 7;
4043 4373f3ce pbrook
    env->vfp.vec_stride = (val >> 20) & 3;
4044 4373f3ce pbrook
4045 4373f3ce pbrook
    changed ^= val;
4046 4373f3ce pbrook
    if (changed & (3 << 22)) {
4047 4373f3ce pbrook
        i = (val >> 22) & 3;
4048 4373f3ce pbrook
        switch (i) {
4049 4d3da0f3 Alexander Graf
        case FPROUNDING_TIEEVEN:
4050 4373f3ce pbrook
            i = float_round_nearest_even;
4051 4373f3ce pbrook
            break;
4052 4d3da0f3 Alexander Graf
        case FPROUNDING_POSINF:
4053 4373f3ce pbrook
            i = float_round_up;
4054 4373f3ce pbrook
            break;
4055 4d3da0f3 Alexander Graf
        case FPROUNDING_NEGINF:
4056 4373f3ce pbrook
            i = float_round_down;
4057 4373f3ce pbrook
            break;
4058 4d3da0f3 Alexander Graf
        case FPROUNDING_ZERO:
4059 4373f3ce pbrook
            i = float_round_to_zero;
4060 4373f3ce pbrook
            break;
4061 4373f3ce pbrook
        }
4062 4373f3ce pbrook
        set_float_rounding_mode(i, &env->vfp.fp_status);
4063 4373f3ce pbrook
    }
4064 cecd8504 Peter Maydell
    if (changed & (1 << 24)) {
4065 fe76d976 pbrook
        set_flush_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status);
4066 cecd8504 Peter Maydell
        set_flush_inputs_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status);
4067 cecd8504 Peter Maydell
    }
4068 5c7908ed pbrook
    if (changed & (1 << 25))
4069 5c7908ed pbrook
        set_default_nan_mode((val & (1 << 25)) != 0, &env->vfp.fp_status);
4070 4373f3ce pbrook
4071 b12c390b Peter Maydell
    i = vfp_exceptbits_to_host(val);
4072 4373f3ce pbrook
    set_float_exception_flags(i, &env->vfp.fp_status);
4073 3a492f3a Peter Maydell
    set_float_exception_flags(0, &env->vfp.standard_fp_status);
4074 4373f3ce pbrook
}
4075 4373f3ce pbrook
4076 0ecb72a5 Andreas Färber
void vfp_set_fpscr(CPUARMState *env, uint32_t val)
4077 01653295 Peter Maydell
{
4078 01653295 Peter Maydell
    HELPER(vfp_set_fpscr)(env, val);
4079 01653295 Peter Maydell
}
4080 01653295 Peter Maydell
4081 4373f3ce pbrook
#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
4082 4373f3ce pbrook
4083 4373f3ce pbrook
#define VFP_BINOP(name) \
4084 ae1857ec Peter Maydell
float32 VFP_HELPER(name, s)(float32 a, float32 b, void *fpstp) \
4085 4373f3ce pbrook
{ \
4086 ae1857ec Peter Maydell
    float_status *fpst = fpstp; \
4087 ae1857ec Peter Maydell
    return float32_ ## name(a, b, fpst); \
4088 4373f3ce pbrook
} \
4089 ae1857ec Peter Maydell
float64 VFP_HELPER(name, d)(float64 a, float64 b, void *fpstp) \
4090 4373f3ce pbrook
{ \
4091 ae1857ec Peter Maydell
    float_status *fpst = fpstp; \
4092 ae1857ec Peter Maydell
    return float64_ ## name(a, b, fpst); \
4093 4373f3ce pbrook
}
4094 4373f3ce pbrook
VFP_BINOP(add)
4095 4373f3ce pbrook
VFP_BINOP(sub)
4096 4373f3ce pbrook
VFP_BINOP(mul)
4097 4373f3ce pbrook
VFP_BINOP(div)
4098 f71a2ae5 Peter Maydell
VFP_BINOP(min)
4099 f71a2ae5 Peter Maydell
VFP_BINOP(max)
4100 f71a2ae5 Peter Maydell
VFP_BINOP(minnum)
4101 f71a2ae5 Peter Maydell
VFP_BINOP(maxnum)
4102 4373f3ce pbrook
#undef VFP_BINOP
4103 4373f3ce pbrook
4104 4373f3ce pbrook
float32 VFP_HELPER(neg, s)(float32 a)
4105 4373f3ce pbrook
{
4106 4373f3ce pbrook
    return float32_chs(a);
4107 4373f3ce pbrook
}
4108 4373f3ce pbrook
4109 4373f3ce pbrook
float64 VFP_HELPER(neg, d)(float64 a)
4110 4373f3ce pbrook
{
4111 66230e0d balrog
    return float64_chs(a);
4112 4373f3ce pbrook
}
4113 4373f3ce pbrook
4114 4373f3ce pbrook
float32 VFP_HELPER(abs, s)(float32 a)
4115 4373f3ce pbrook
{
4116 4373f3ce pbrook
    return float32_abs(a);
4117 4373f3ce pbrook
}
4118 4373f3ce pbrook
4119 4373f3ce pbrook
float64 VFP_HELPER(abs, d)(float64 a)
4120 4373f3ce pbrook
{
4121 66230e0d balrog
    return float64_abs(a);
4122 4373f3ce pbrook
}
4123 4373f3ce pbrook
4124 0ecb72a5 Andreas Färber
float32 VFP_HELPER(sqrt, s)(float32 a, CPUARMState *env)
4125 4373f3ce pbrook
{
4126 4373f3ce pbrook
    return float32_sqrt(a, &env->vfp.fp_status);
4127 4373f3ce pbrook
}
4128 4373f3ce pbrook
4129 0ecb72a5 Andreas Färber
float64 VFP_HELPER(sqrt, d)(float64 a, CPUARMState *env)
4130 4373f3ce pbrook
{
4131 4373f3ce pbrook
    return float64_sqrt(a, &env->vfp.fp_status);
4132 4373f3ce pbrook
}
4133 4373f3ce pbrook
4134 4373f3ce pbrook
/* XXX: check quiet/signaling case */
4135 4373f3ce pbrook
#define DO_VFP_cmp(p, type) \
4136 0ecb72a5 Andreas Färber
void VFP_HELPER(cmp, p)(type a, type b, CPUARMState *env)  \
4137 4373f3ce pbrook
{ \
4138 4373f3ce pbrook
    uint32_t flags; \
4139 4373f3ce pbrook
    switch(type ## _compare_quiet(a, b, &env->vfp.fp_status)) { \
4140 4373f3ce pbrook
    case 0: flags = 0x6; break; \
4141 4373f3ce pbrook
    case -1: flags = 0x8; break; \
4142 4373f3ce pbrook
    case 1: flags = 0x2; break; \
4143 4373f3ce pbrook
    default: case 2: flags = 0x3; break; \
4144 4373f3ce pbrook
    } \
4145 4373f3ce pbrook
    env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \
4146 4373f3ce pbrook
        | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
4147 4373f3ce pbrook
} \
4148 0ecb72a5 Andreas Färber
void VFP_HELPER(cmpe, p)(type a, type b, CPUARMState *env) \
4149 4373f3ce pbrook
{ \
4150 4373f3ce pbrook
    uint32_t flags; \
4151 4373f3ce pbrook
    switch(type ## _compare(a, b, &env->vfp.fp_status)) { \
4152 4373f3ce pbrook
    case 0: flags = 0x6; break; \
4153 4373f3ce pbrook
    case -1: flags = 0x8; break; \
4154 4373f3ce pbrook
    case 1: flags = 0x2; break; \
4155 4373f3ce pbrook
    default: case 2: flags = 0x3; break; \
4156 4373f3ce pbrook
    } \
4157 4373f3ce pbrook
    env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \
4158 4373f3ce pbrook
        | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
4159 4373f3ce pbrook
}
4160 4373f3ce pbrook
DO_VFP_cmp(s, float32)
4161 4373f3ce pbrook
DO_VFP_cmp(d, float64)
4162 4373f3ce pbrook
#undef DO_VFP_cmp
4163 4373f3ce pbrook
4164 5500b06c Peter Maydell
/* Integer to float and float to integer conversions */
4165 4373f3ce pbrook
4166 5500b06c Peter Maydell
#define CONV_ITOF(name, fsz, sign) \
4167 5500b06c Peter Maydell
    float##fsz HELPER(name)(uint32_t x, void *fpstp) \
4168 5500b06c Peter Maydell
{ \
4169 5500b06c Peter Maydell
    float_status *fpst = fpstp; \
4170 85836979 Peter Maydell
    return sign##int32_to_##float##fsz((sign##int32_t)x, fpst); \
4171 4373f3ce pbrook
}
4172 4373f3ce pbrook
4173 5500b06c Peter Maydell
#define CONV_FTOI(name, fsz, sign, round) \
4174 5500b06c Peter Maydell
uint32_t HELPER(name)(float##fsz x, void *fpstp) \
4175 5500b06c Peter Maydell
{ \
4176 5500b06c Peter Maydell
    float_status *fpst = fpstp; \
4177 5500b06c Peter Maydell
    if (float##fsz##_is_any_nan(x)) { \
4178 5500b06c Peter Maydell
        float_raise(float_flag_invalid, fpst); \
4179 5500b06c Peter Maydell
        return 0; \
4180 5500b06c Peter Maydell
    } \
4181 5500b06c Peter Maydell
    return float##fsz##_to_##sign##int32##round(x, fpst); \
4182 4373f3ce pbrook
}
4183 4373f3ce pbrook
4184 5500b06c Peter Maydell
#define FLOAT_CONVS(name, p, fsz, sign) \
4185 5500b06c Peter Maydell
CONV_ITOF(vfp_##name##to##p, fsz, sign) \
4186 5500b06c Peter Maydell
CONV_FTOI(vfp_to##name##p, fsz, sign, ) \
4187 5500b06c Peter Maydell
CONV_FTOI(vfp_to##name##z##p, fsz, sign, _round_to_zero)
4188 4373f3ce pbrook
4189 5500b06c Peter Maydell
FLOAT_CONVS(si, s, 32, )
4190 5500b06c Peter Maydell
FLOAT_CONVS(si, d, 64, )
4191 5500b06c Peter Maydell
FLOAT_CONVS(ui, s, 32, u)
4192 5500b06c Peter Maydell
FLOAT_CONVS(ui, d, 64, u)
4193 4373f3ce pbrook
4194 5500b06c Peter Maydell
#undef CONV_ITOF
4195 5500b06c Peter Maydell
#undef CONV_FTOI
4196 5500b06c Peter Maydell
#undef FLOAT_CONVS
4197 4373f3ce pbrook
4198 4373f3ce pbrook
/* floating point conversion */
4199 0ecb72a5 Andreas Färber
float64 VFP_HELPER(fcvtd, s)(float32 x, CPUARMState *env)
4200 4373f3ce pbrook
{
4201 2d627737 Peter Maydell
    float64 r = float32_to_float64(x, &env->vfp.fp_status);
4202 2d627737 Peter Maydell
    /* ARM requires that S<->D conversion of any kind of NaN generates
4203 2d627737 Peter Maydell
     * a quiet NaN by forcing the most significant frac bit to 1.
4204 2d627737 Peter Maydell
     */
4205 2d627737 Peter Maydell
    return float64_maybe_silence_nan(r);
4206 4373f3ce pbrook
}
4207 4373f3ce pbrook
4208 0ecb72a5 Andreas Färber
float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
4209 4373f3ce pbrook
{
4210 2d627737 Peter Maydell
    float32 r =  float64_to_float32(x, &env->vfp.fp_status);
4211 2d627737 Peter Maydell
    /* ARM requires that S<->D conversion of any kind of NaN generates
4212 2d627737 Peter Maydell
     * a quiet NaN by forcing the most significant frac bit to 1.
4213 2d627737 Peter Maydell
     */
4214 2d627737 Peter Maydell
    return float32_maybe_silence_nan(r);
4215 4373f3ce pbrook
}
4216 4373f3ce pbrook
4217 4373f3ce pbrook
/* VFP3 fixed point conversion.  */
4218 16d5b3ca Will Newton
#define VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype) \
4219 8ed697e8 Will Newton
float##fsz HELPER(vfp_##name##to##p)(uint##isz##_t  x, uint32_t shift, \
4220 8ed697e8 Will Newton
                                     void *fpstp) \
4221 4373f3ce pbrook
{ \
4222 5500b06c Peter Maydell
    float_status *fpst = fpstp; \
4223 622465e1 Peter Maydell
    float##fsz tmp; \
4224 8ed697e8 Will Newton
    tmp = itype##_to_##float##fsz(x, fpst); \
4225 5500b06c Peter Maydell
    return float##fsz##_scalbn(tmp, -(int)shift, fpst); \
4226 16d5b3ca Will Newton
}
4227 16d5b3ca Will Newton
4228 abe66f70 Peter Maydell
/* Notice that we want only input-denormal exception flags from the
4229 abe66f70 Peter Maydell
 * scalbn operation: the other possible flags (overflow+inexact if
4230 abe66f70 Peter Maydell
 * we overflow to infinity, output-denormal) aren't correct for the
4231 abe66f70 Peter Maydell
 * complete scale-and-convert operation.
4232 abe66f70 Peter Maydell
 */
4233 16d5b3ca Will Newton
#define VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, round) \
4234 16d5b3ca Will Newton
uint##isz##_t HELPER(vfp_to##name##p##round)(float##fsz x, \
4235 16d5b3ca Will Newton
                                             uint32_t shift, \
4236 16d5b3ca Will Newton
                                             void *fpstp) \
4237 4373f3ce pbrook
{ \
4238 5500b06c Peter Maydell
    float_status *fpst = fpstp; \
4239 abe66f70 Peter Maydell
    int old_exc_flags = get_float_exception_flags(fpst); \
4240 622465e1 Peter Maydell
    float##fsz tmp; \
4241 622465e1 Peter Maydell
    if (float##fsz##_is_any_nan(x)) { \
4242 5500b06c Peter Maydell
        float_raise(float_flag_invalid, fpst); \
4243 622465e1 Peter Maydell
        return 0; \
4244 09d9487f Peter Maydell
    } \
4245 5500b06c Peter Maydell
    tmp = float##fsz##_scalbn(x, shift, fpst); \
4246 abe66f70 Peter Maydell
    old_exc_flags |= get_float_exception_flags(fpst) \
4247 abe66f70 Peter Maydell
        & float_flag_input_denormal; \
4248 abe66f70 Peter Maydell
    set_float_exception_flags(old_exc_flags, fpst); \
4249 16d5b3ca Will Newton
    return float##fsz##_to_##itype##round(tmp, fpst); \
4250 622465e1 Peter Maydell
}
4251 622465e1 Peter Maydell
4252 16d5b3ca Will Newton
#define VFP_CONV_FIX(name, p, fsz, isz, itype)                   \
4253 16d5b3ca Will Newton
VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype)                     \
4254 3c6a074a Will Newton
VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, _round_to_zero) \
4255 3c6a074a Will Newton
VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, )
4256 3c6a074a Will Newton
4257 3c6a074a Will Newton
#define VFP_CONV_FIX_A64(name, p, fsz, isz, itype)               \
4258 3c6a074a Will Newton
VFP_CONV_FIX_FLOAT(name, p, fsz, isz, itype)                     \
4259 3c6a074a Will Newton
VFP_CONV_FLOAT_FIX_ROUND(name, p, fsz, isz, itype, )
4260 16d5b3ca Will Newton
4261 8ed697e8 Will Newton
VFP_CONV_FIX(sh, d, 64, 64, int16)
4262 8ed697e8 Will Newton
VFP_CONV_FIX(sl, d, 64, 64, int32)
4263 3c6a074a Will Newton
VFP_CONV_FIX_A64(sq, d, 64, 64, int64)
4264 8ed697e8 Will Newton
VFP_CONV_FIX(uh, d, 64, 64, uint16)
4265 8ed697e8 Will Newton
VFP_CONV_FIX(ul, d, 64, 64, uint32)
4266 3c6a074a Will Newton
VFP_CONV_FIX_A64(uq, d, 64, 64, uint64)
4267 8ed697e8 Will Newton
VFP_CONV_FIX(sh, s, 32, 32, int16)
4268 8ed697e8 Will Newton
VFP_CONV_FIX(sl, s, 32, 32, int32)
4269 3c6a074a Will Newton
VFP_CONV_FIX_A64(sq, s, 32, 64, int64)
4270 8ed697e8 Will Newton
VFP_CONV_FIX(uh, s, 32, 32, uint16)
4271 8ed697e8 Will Newton
VFP_CONV_FIX(ul, s, 32, 32, uint32)
4272 3c6a074a Will Newton
VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
4273 4373f3ce pbrook
#undef VFP_CONV_FIX
4274 16d5b3ca Will Newton
#undef VFP_CONV_FIX_FLOAT
4275 16d5b3ca Will Newton
#undef VFP_CONV_FLOAT_FIX_ROUND
4276 4373f3ce pbrook
4277 52a1f6a3 Alexander Graf
/* Set the current fp rounding mode and return the old one.
4278 52a1f6a3 Alexander Graf
 * The argument is a softfloat float_round_ value.
4279 52a1f6a3 Alexander Graf
 */
4280 52a1f6a3 Alexander Graf
uint32_t HELPER(set_rmode)(uint32_t rmode, CPUARMState *env)
4281 52a1f6a3 Alexander Graf
{
4282 52a1f6a3 Alexander Graf
    float_status *fp_status = &env->vfp.fp_status;
4283 52a1f6a3 Alexander Graf
4284 52a1f6a3 Alexander Graf
    uint32_t prev_rmode = get_float_rounding_mode(fp_status);
4285 52a1f6a3 Alexander Graf
    set_float_rounding_mode(rmode, fp_status);
4286 52a1f6a3 Alexander Graf
4287 52a1f6a3 Alexander Graf
    return prev_rmode;
4288 52a1f6a3 Alexander Graf
}
4289 52a1f6a3 Alexander Graf
4290 43630e58 Will Newton
/* Set the current fp rounding mode in the standard fp status and return
4291 43630e58 Will Newton
 * the old one. This is for NEON instructions that need to change the
4292 43630e58 Will Newton
 * rounding mode but wish to use the standard FPSCR values for everything
4293 43630e58 Will Newton
 * else. Always set the rounding mode back to the correct value after
4294 43630e58 Will Newton
 * modifying it.
4295 43630e58 Will Newton
 * The argument is a softfloat float_round_ value.
4296 43630e58 Will Newton
 */
4297 43630e58 Will Newton
uint32_t HELPER(set_neon_rmode)(uint32_t rmode, CPUARMState *env)
4298 43630e58 Will Newton
{
4299 43630e58 Will Newton
    float_status *fp_status = &env->vfp.standard_fp_status;
4300 43630e58 Will Newton
4301 43630e58 Will Newton
    uint32_t prev_rmode = get_float_rounding_mode(fp_status);
4302 43630e58 Will Newton
    set_float_rounding_mode(rmode, fp_status);
4303 43630e58 Will Newton
4304 43630e58 Will Newton
    return prev_rmode;
4305 43630e58 Will Newton
}
4306 43630e58 Will Newton
4307 60011498 Paul Brook
/* Half precision conversions.  */
4308 0ecb72a5 Andreas Färber
static float32 do_fcvt_f16_to_f32(uint32_t a, CPUARMState *env, float_status *s)
4309 60011498 Paul Brook
{
4310 60011498 Paul Brook
    int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
4311 fb91678d Peter Maydell
    float32 r = float16_to_float32(make_float16(a), ieee, s);
4312 fb91678d Peter Maydell
    if (ieee) {
4313 fb91678d Peter Maydell
        return float32_maybe_silence_nan(r);
4314 fb91678d Peter Maydell
    }
4315 fb91678d Peter Maydell
    return r;
4316 60011498 Paul Brook
}
4317 60011498 Paul Brook
4318 0ecb72a5 Andreas Färber
static uint32_t do_fcvt_f32_to_f16(float32 a, CPUARMState *env, float_status *s)
4319 60011498 Paul Brook
{
4320 60011498 Paul Brook
    int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
4321 fb91678d Peter Maydell
    float16 r = float32_to_float16(a, ieee, s);
4322 fb91678d Peter Maydell
    if (ieee) {
4323 fb91678d Peter Maydell
        r = float16_maybe_silence_nan(r);
4324 fb91678d Peter Maydell
    }
4325 fb91678d Peter Maydell
    return float16_val(r);
4326 60011498 Paul Brook
}
4327 60011498 Paul Brook
4328 0ecb72a5 Andreas Färber
float32 HELPER(neon_fcvt_f16_to_f32)(uint32_t a, CPUARMState *env)
4329 2d981da7 Peter Maydell
{
4330 2d981da7 Peter Maydell
    return do_fcvt_f16_to_f32(a, env, &env->vfp.standard_fp_status);
4331 2d981da7 Peter Maydell
}
4332 2d981da7 Peter Maydell
4333 0ecb72a5 Andreas Färber
uint32_t HELPER(neon_fcvt_f32_to_f16)(float32 a, CPUARMState *env)
4334 2d981da7 Peter Maydell
{
4335 2d981da7 Peter Maydell
    return do_fcvt_f32_to_f16(a, env, &env->vfp.standard_fp_status);
4336 2d981da7 Peter Maydell
}
4337 2d981da7 Peter Maydell
4338 0ecb72a5 Andreas Färber
float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUARMState *env)
4339 2d981da7 Peter Maydell
{
4340 2d981da7 Peter Maydell
    return do_fcvt_f16_to_f32(a, env, &env->vfp.fp_status);
4341 2d981da7 Peter Maydell
}
4342 2d981da7 Peter Maydell
4343 0ecb72a5 Andreas Färber
uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUARMState *env)
4344 2d981da7 Peter Maydell
{
4345 2d981da7 Peter Maydell
    return do_fcvt_f32_to_f16(a, env, &env->vfp.fp_status);
4346 2d981da7 Peter Maydell
}
4347 2d981da7 Peter Maydell
4348 8900aad2 Peter Maydell
float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, CPUARMState *env)
4349 8900aad2 Peter Maydell
{
4350 8900aad2 Peter Maydell
    int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
4351 8900aad2 Peter Maydell
    float64 r = float16_to_float64(make_float16(a), ieee, &env->vfp.fp_status);
4352 8900aad2 Peter Maydell
    if (ieee) {
4353 8900aad2 Peter Maydell
        return float64_maybe_silence_nan(r);
4354 8900aad2 Peter Maydell
    }
4355 8900aad2 Peter Maydell
    return r;
4356 8900aad2 Peter Maydell
}
4357 8900aad2 Peter Maydell
4358 8900aad2 Peter Maydell
uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, CPUARMState *env)
4359 8900aad2 Peter Maydell
{
4360 8900aad2 Peter Maydell
    int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
4361 8900aad2 Peter Maydell
    float16 r = float64_to_float16(a, ieee, &env->vfp.fp_status);
4362 8900aad2 Peter Maydell
    if (ieee) {
4363 8900aad2 Peter Maydell
        r = float16_maybe_silence_nan(r);
4364 8900aad2 Peter Maydell
    }
4365 8900aad2 Peter Maydell
    return float16_val(r);
4366 8900aad2 Peter Maydell
}
4367 8900aad2 Peter Maydell
4368 dda3ec49 Peter Maydell
#define float32_two make_float32(0x40000000)
4369 6aae3df1 Peter Maydell
#define float32_three make_float32(0x40400000)
4370 6aae3df1 Peter Maydell
#define float32_one_point_five make_float32(0x3fc00000)
4371 dda3ec49 Peter Maydell
4372 0ecb72a5 Andreas Färber
float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
4373 4373f3ce pbrook
{
4374 dda3ec49 Peter Maydell
    float_status *s = &env->vfp.standard_fp_status;
4375 dda3ec49 Peter Maydell
    if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
4376 dda3ec49 Peter Maydell
        (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
4377 43fe9bdb Peter Maydell
        if (!(float32_is_zero(a) || float32_is_zero(b))) {
4378 43fe9bdb Peter Maydell
            float_raise(float_flag_input_denormal, s);
4379 43fe9bdb Peter Maydell
        }
4380 dda3ec49 Peter Maydell
        return float32_two;
4381 dda3ec49 Peter Maydell
    }
4382 dda3ec49 Peter Maydell
    return float32_sub(float32_two, float32_mul(a, b, s), s);
4383 4373f3ce pbrook
}
4384 4373f3ce pbrook
4385 0ecb72a5 Andreas Färber
float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
4386 4373f3ce pbrook
{
4387 71826966 Peter Maydell
    float_status *s = &env->vfp.standard_fp_status;
4388 9ea62f57 Peter Maydell
    float32 product;
4389 9ea62f57 Peter Maydell
    if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
4390 9ea62f57 Peter Maydell
        (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
4391 43fe9bdb Peter Maydell
        if (!(float32_is_zero(a) || float32_is_zero(b))) {
4392 43fe9bdb Peter Maydell
            float_raise(float_flag_input_denormal, s);
4393 43fe9bdb Peter Maydell
        }
4394 6aae3df1 Peter Maydell
        return float32_one_point_five;
4395 9ea62f57 Peter Maydell
    }
4396 6aae3df1 Peter Maydell
    product = float32_mul(a, b, s);
4397 6aae3df1 Peter Maydell
    return float32_div(float32_sub(float32_three, product, s), float32_two, s);
4398 4373f3ce pbrook
}
4399 4373f3ce pbrook
4400 8f8e3aa4 pbrook
/* NEON helpers.  */
4401 8f8e3aa4 pbrook
4402 56bf4fe2 Christophe Lyon
/* Constants 256 and 512 are used in some helpers; we avoid relying on
4403 56bf4fe2 Christophe Lyon
 * int->float conversions at run-time.  */
4404 56bf4fe2 Christophe Lyon
#define float64_256 make_float64(0x4070000000000000LL)
4405 56bf4fe2 Christophe Lyon
#define float64_512 make_float64(0x4080000000000000LL)
4406 56bf4fe2 Christophe Lyon
4407 fe0e4872 Christophe Lyon
/* The algorithm that must be used to calculate the estimate
4408 fe0e4872 Christophe Lyon
 * is specified by the ARM ARM.
4409 fe0e4872 Christophe Lyon
 */
4410 0ecb72a5 Andreas Färber
static float64 recip_estimate(float64 a, CPUARMState *env)
4411 fe0e4872 Christophe Lyon
{
4412 1146a817 Peter Maydell
    /* These calculations mustn't set any fp exception flags,
4413 1146a817 Peter Maydell
     * so we use a local copy of the fp_status.
4414 1146a817 Peter Maydell
     */
4415 1146a817 Peter Maydell
    float_status dummy_status = env->vfp.standard_fp_status;
4416 1146a817 Peter Maydell
    float_status *s = &dummy_status;
4417 fe0e4872 Christophe Lyon
    /* q = (int)(a * 512.0) */
4418 fe0e4872 Christophe Lyon
    float64 q = float64_mul(float64_512, a, s);
4419 fe0e4872 Christophe Lyon
    int64_t q_int = float64_to_int64_round_to_zero(q, s);
4420 fe0e4872 Christophe Lyon
4421 fe0e4872 Christophe Lyon
    /* r = 1.0 / (((double)q + 0.5) / 512.0) */
4422 fe0e4872 Christophe Lyon
    q = int64_to_float64(q_int, s);
4423 fe0e4872 Christophe Lyon
    q = float64_add(q, float64_half, s);
4424 fe0e4872 Christophe Lyon
    q = float64_div(q, float64_512, s);
4425 fe0e4872 Christophe Lyon
    q = float64_div(float64_one, q, s);
4426 fe0e4872 Christophe Lyon
4427 fe0e4872 Christophe Lyon
    /* s = (int)(256.0 * r + 0.5) */
4428 fe0e4872 Christophe Lyon
    q = float64_mul(q, float64_256, s);
4429 fe0e4872 Christophe Lyon
    q = float64_add(q, float64_half, s);
4430 fe0e4872 Christophe Lyon
    q_int = float64_to_int64_round_to_zero(q, s);
4431 fe0e4872 Christophe Lyon
4432 fe0e4872 Christophe Lyon
    /* return (double)s / 256.0 */
4433 fe0e4872 Christophe Lyon
    return float64_div(int64_to_float64(q_int, s), float64_256, s);
4434 fe0e4872 Christophe Lyon
}
4435 fe0e4872 Christophe Lyon
4436 0ecb72a5 Andreas Färber
float32 HELPER(recpe_f32)(float32 a, CPUARMState *env)
4437 4373f3ce pbrook
{
4438 fe0e4872 Christophe Lyon
    float_status *s = &env->vfp.standard_fp_status;
4439 fe0e4872 Christophe Lyon
    float64 f64;
4440 fe0e4872 Christophe Lyon
    uint32_t val32 = float32_val(a);
4441 fe0e4872 Christophe Lyon
4442 fe0e4872 Christophe Lyon
    int result_exp;
4443 fe0e4872 Christophe Lyon
    int a_exp = (val32  & 0x7f800000) >> 23;
4444 fe0e4872 Christophe Lyon
    int sign = val32 & 0x80000000;
4445 fe0e4872 Christophe Lyon
4446 fe0e4872 Christophe Lyon
    if (float32_is_any_nan(a)) {
4447 fe0e4872 Christophe Lyon
        if (float32_is_signaling_nan(a)) {
4448 fe0e4872 Christophe Lyon
            float_raise(float_flag_invalid, s);
4449 fe0e4872 Christophe Lyon
        }
4450 fe0e4872 Christophe Lyon
        return float32_default_nan;
4451 fe0e4872 Christophe Lyon
    } else if (float32_is_infinity(a)) {
4452 fe0e4872 Christophe Lyon
        return float32_set_sign(float32_zero, float32_is_neg(a));
4453 fe0e4872 Christophe Lyon
    } else if (float32_is_zero_or_denormal(a)) {
4454 43fe9bdb Peter Maydell
        if (!float32_is_zero(a)) {
4455 43fe9bdb Peter Maydell
            float_raise(float_flag_input_denormal, s);
4456 43fe9bdb Peter Maydell
        }
4457 fe0e4872 Christophe Lyon
        float_raise(float_flag_divbyzero, s);
4458 fe0e4872 Christophe Lyon
        return float32_set_sign(float32_infinity, float32_is_neg(a));
4459 fe0e4872 Christophe Lyon
    } else if (a_exp >= 253) {
4460 fe0e4872 Christophe Lyon
        float_raise(float_flag_underflow, s);
4461 fe0e4872 Christophe Lyon
        return float32_set_sign(float32_zero, float32_is_neg(a));
4462 fe0e4872 Christophe Lyon
    }
4463 fe0e4872 Christophe Lyon
4464 fe0e4872 Christophe Lyon
    f64 = make_float64((0x3feULL << 52)
4465 fe0e4872 Christophe Lyon
                       | ((int64_t)(val32 & 0x7fffff) << 29));
4466 fe0e4872 Christophe Lyon
4467 fe0e4872 Christophe Lyon
    result_exp = 253 - a_exp;
4468 fe0e4872 Christophe Lyon
4469 fe0e4872 Christophe Lyon
    f64 = recip_estimate(f64, env);
4470 fe0e4872 Christophe Lyon
4471 fe0e4872 Christophe Lyon
    val32 = sign
4472 fe0e4872 Christophe Lyon
        | ((result_exp & 0xff) << 23)
4473 fe0e4872 Christophe Lyon
        | ((float64_val(f64) >> 29) & 0x7fffff);
4474 fe0e4872 Christophe Lyon
    return make_float32(val32);
4475 4373f3ce pbrook
}
4476 4373f3ce pbrook
4477 e07be5d2 Christophe Lyon
/* The algorithm that must be used to calculate the estimate
4478 e07be5d2 Christophe Lyon
 * is specified by the ARM ARM.
4479 e07be5d2 Christophe Lyon
 */
4480 0ecb72a5 Andreas Färber
static float64 recip_sqrt_estimate(float64 a, CPUARMState *env)
4481 e07be5d2 Christophe Lyon
{
4482 1146a817 Peter Maydell
    /* These calculations mustn't set any fp exception flags,
4483 1146a817 Peter Maydell
     * so we use a local copy of the fp_status.
4484 1146a817 Peter Maydell
     */
4485 1146a817 Peter Maydell
    float_status dummy_status = env->vfp.standard_fp_status;
4486 1146a817 Peter Maydell
    float_status *s = &dummy_status;
4487 e07be5d2 Christophe Lyon
    float64 q;
4488 e07be5d2 Christophe Lyon
    int64_t q_int;
4489 e07be5d2 Christophe Lyon
4490 e07be5d2 Christophe Lyon
    if (float64_lt(a, float64_half, s)) {
4491 e07be5d2 Christophe Lyon
        /* range 0.25 <= a < 0.5 */
4492 e07be5d2 Christophe Lyon
4493 e07be5d2 Christophe Lyon
        /* a in units of 1/512 rounded down */
4494 e07be5d2 Christophe Lyon
        /* q0 = (int)(a * 512.0);  */
4495 e07be5d2 Christophe Lyon
        q = float64_mul(float64_512, a, s);
4496 e07be5d2 Christophe Lyon
        q_int = float64_to_int64_round_to_zero(q, s);
4497 e07be5d2 Christophe Lyon
4498 e07be5d2 Christophe Lyon
        /* reciprocal root r */
4499 e07be5d2 Christophe Lyon
        /* r = 1.0 / sqrt(((double)q0 + 0.5) / 512.0);  */
4500 e07be5d2 Christophe Lyon
        q = int64_to_float64(q_int, s);
4501 e07be5d2 Christophe Lyon
        q = float64_add(q, float64_half, s);
4502 e07be5d2 Christophe Lyon
        q = float64_div(q, float64_512, s);
4503 e07be5d2 Christophe Lyon
        q = float64_sqrt(q, s);
4504 e07be5d2 Christophe Lyon
        q = float64_div(float64_one, q, s);
4505 e07be5d2 Christophe Lyon
    } else {
4506 e07be5d2 Christophe Lyon
        /* range 0.5 <= a < 1.0 */
4507 e07be5d2 Christophe Lyon
4508 e07be5d2 Christophe Lyon
        /* a in units of 1/256 rounded down */
4509 e07be5d2 Christophe Lyon
        /* q1 = (int)(a * 256.0); */
4510 e07be5d2 Christophe Lyon
        q = float64_mul(float64_256, a, s);
4511 e07be5d2 Christophe Lyon
        int64_t q_int = float64_to_int64_round_to_zero(q, s);
4512 e07be5d2 Christophe Lyon
4513 e07be5d2 Christophe Lyon
        /* reciprocal root r */
4514 e07be5d2 Christophe Lyon
        /* r = 1.0 /sqrt(((double)q1 + 0.5) / 256); */
4515 e07be5d2 Christophe Lyon
        q = int64_to_float64(q_int, s);
4516 e07be5d2 Christophe Lyon
        q = float64_add(q, float64_half, s);
4517 e07be5d2 Christophe Lyon
        q = float64_div(q, float64_256, s);
4518 e07be5d2 Christophe Lyon
        q = float64_sqrt(q, s);
4519 e07be5d2 Christophe Lyon
        q = float64_div(float64_one, q, s);
4520 e07be5d2 Christophe Lyon
    }
4521 e07be5d2 Christophe Lyon
    /* r in units of 1/256 rounded to nearest */
4522 e07be5d2 Christophe Lyon
    /* s = (int)(256.0 * r + 0.5); */
4523 e07be5d2 Christophe Lyon
4524 e07be5d2 Christophe Lyon
    q = float64_mul(q, float64_256,s );
4525 e07be5d2 Christophe Lyon
    q = float64_add(q, float64_half, s);
4526 e07be5d2 Christophe Lyon
    q_int = float64_to_int64_round_to_zero(q, s);
4527 e07be5d2 Christophe Lyon
4528 e07be5d2 Christophe Lyon
    /* return (double)s / 256.0;*/
4529 e07be5d2 Christophe Lyon
    return float64_div(int64_to_float64(q_int, s), float64_256, s);
4530 e07be5d2 Christophe Lyon
}
4531 e07be5d2 Christophe Lyon
4532 0ecb72a5 Andreas Färber
float32 HELPER(rsqrte_f32)(float32 a, CPUARMState *env)
4533 4373f3ce pbrook
{
4534 e07be5d2 Christophe Lyon
    float_status *s = &env->vfp.standard_fp_status;
4535 e07be5d2 Christophe Lyon
    int result_exp;
4536 e07be5d2 Christophe Lyon
    float64 f64;
4537 e07be5d2 Christophe Lyon
    uint32_t val;
4538 e07be5d2 Christophe Lyon
    uint64_t val64;
4539 e07be5d2 Christophe Lyon
4540 e07be5d2 Christophe Lyon
    val = float32_val(a);
4541 e07be5d2 Christophe Lyon
4542 e07be5d2 Christophe Lyon
    if (float32_is_any_nan(a)) {
4543 e07be5d2 Christophe Lyon
        if (float32_is_signaling_nan(a)) {
4544 e07be5d2 Christophe Lyon
            float_raise(float_flag_invalid, s);
4545 e07be5d2 Christophe Lyon
        }
4546 e07be5d2 Christophe Lyon
        return float32_default_nan;
4547 e07be5d2 Christophe Lyon
    } else if (float32_is_zero_or_denormal(a)) {
4548 43fe9bdb Peter Maydell
        if (!float32_is_zero(a)) {
4549 43fe9bdb Peter Maydell
            float_raise(float_flag_input_denormal, s);
4550 43fe9bdb Peter Maydell
        }
4551 e07be5d2 Christophe Lyon
        float_raise(float_flag_divbyzero, s);
4552 e07be5d2 Christophe Lyon
        return float32_set_sign(float32_infinity, float32_is_neg(a));
4553 e07be5d2 Christophe Lyon
    } else if (float32_is_neg(a)) {
4554 e07be5d2 Christophe Lyon
        float_raise(float_flag_invalid, s);
4555 e07be5d2 Christophe Lyon
        return float32_default_nan;
4556 e07be5d2 Christophe Lyon
    } else if (float32_is_infinity(a)) {
4557 e07be5d2 Christophe Lyon
        return float32_zero;
4558 e07be5d2 Christophe Lyon
    }
4559 e07be5d2 Christophe Lyon
4560 e07be5d2 Christophe Lyon
    /* Normalize to a double-precision value between 0.25 and 1.0,
4561 e07be5d2 Christophe Lyon
     * preserving the parity of the exponent.  */
4562 e07be5d2 Christophe Lyon
    if ((val & 0x800000) == 0) {
4563 e07be5d2 Christophe Lyon
        f64 = make_float64(((uint64_t)(val & 0x80000000) << 32)
4564 e07be5d2 Christophe Lyon
                           | (0x3feULL << 52)
4565 e07be5d2 Christophe Lyon
                           | ((uint64_t)(val & 0x7fffff) << 29));
4566 e07be5d2 Christophe Lyon
    } else {
4567 e07be5d2 Christophe Lyon
        f64 = make_float64(((uint64_t)(val & 0x80000000) << 32)
4568 e07be5d2 Christophe Lyon
                           | (0x3fdULL << 52)
4569 e07be5d2 Christophe Lyon
                           | ((uint64_t)(val & 0x7fffff) << 29));
4570 e07be5d2 Christophe Lyon
    }
4571 e07be5d2 Christophe Lyon
4572 e07be5d2 Christophe Lyon
    result_exp = (380 - ((val & 0x7f800000) >> 23)) / 2;
4573 e07be5d2 Christophe Lyon
4574 e07be5d2 Christophe Lyon
    f64 = recip_sqrt_estimate(f64, env);
4575 e07be5d2 Christophe Lyon
4576 e07be5d2 Christophe Lyon
    val64 = float64_val(f64);
4577 e07be5d2 Christophe Lyon
4578 26cc6abf Christophe LYON
    val = ((result_exp & 0xff) << 23)
4579 e07be5d2 Christophe Lyon
        | ((val64 >> 29)  & 0x7fffff);
4580 e07be5d2 Christophe Lyon
    return make_float32(val);
4581 4373f3ce pbrook
}
4582 4373f3ce pbrook
4583 0ecb72a5 Andreas Färber
uint32_t HELPER(recpe_u32)(uint32_t a, CPUARMState *env)
4584 4373f3ce pbrook
{
4585 fe0e4872 Christophe Lyon
    float64 f64;
4586 fe0e4872 Christophe Lyon
4587 fe0e4872 Christophe Lyon
    if ((a & 0x80000000) == 0) {
4588 fe0e4872 Christophe Lyon
        return 0xffffffff;
4589 fe0e4872 Christophe Lyon
    }
4590 fe0e4872 Christophe Lyon
4591 fe0e4872 Christophe Lyon
    f64 = make_float64((0x3feULL << 52)
4592 fe0e4872 Christophe Lyon
                       | ((int64_t)(a & 0x7fffffff) << 21));
4593 fe0e4872 Christophe Lyon
4594 fe0e4872 Christophe Lyon
    f64 = recip_estimate (f64, env);
4595 fe0e4872 Christophe Lyon
4596 fe0e4872 Christophe Lyon
    return 0x80000000 | ((float64_val(f64) >> 21) & 0x7fffffff);
4597 4373f3ce pbrook
}
4598 4373f3ce pbrook
4599 0ecb72a5 Andreas Färber
uint32_t HELPER(rsqrte_u32)(uint32_t a, CPUARMState *env)
4600 4373f3ce pbrook
{
4601 e07be5d2 Christophe Lyon
    float64 f64;
4602 e07be5d2 Christophe Lyon
4603 e07be5d2 Christophe Lyon
    if ((a & 0xc0000000) == 0) {
4604 e07be5d2 Christophe Lyon
        return 0xffffffff;
4605 e07be5d2 Christophe Lyon
    }
4606 e07be5d2 Christophe Lyon
4607 e07be5d2 Christophe Lyon
    if (a & 0x80000000) {
4608 e07be5d2 Christophe Lyon
        f64 = make_float64((0x3feULL << 52)
4609 e07be5d2 Christophe Lyon
                           | ((uint64_t)(a & 0x7fffffff) << 21));
4610 e07be5d2 Christophe Lyon
    } else { /* bits 31-30 == '01' */
4611 e07be5d2 Christophe Lyon
        f64 = make_float64((0x3fdULL << 52)
4612 e07be5d2 Christophe Lyon
                           | ((uint64_t)(a & 0x3fffffff) << 22));
4613 e07be5d2 Christophe Lyon
    }
4614 e07be5d2 Christophe Lyon
4615 e07be5d2 Christophe Lyon
    f64 = recip_sqrt_estimate(f64, env);
4616 e07be5d2 Christophe Lyon
4617 e07be5d2 Christophe Lyon
    return 0x80000000 | ((float64_val(f64) >> 21) & 0x7fffffff);
4618 4373f3ce pbrook
}
4619 fe1479c3 pbrook
4620 da97f52c Peter Maydell
/* VFPv4 fused multiply-accumulate */
4621 da97f52c Peter Maydell
float32 VFP_HELPER(muladd, s)(float32 a, float32 b, float32 c, void *fpstp)
4622 da97f52c Peter Maydell
{
4623 da97f52c Peter Maydell
    float_status *fpst = fpstp;
4624 da97f52c Peter Maydell
    return float32_muladd(a, b, c, 0, fpst);
4625 da97f52c Peter Maydell
}
4626 da97f52c Peter Maydell
4627 da97f52c Peter Maydell
float64 VFP_HELPER(muladd, d)(float64 a, float64 b, float64 c, void *fpstp)
4628 da97f52c Peter Maydell
{
4629 da97f52c Peter Maydell
    float_status *fpst = fpstp;
4630 da97f52c Peter Maydell
    return float64_muladd(a, b, c, 0, fpst);
4631 da97f52c Peter Maydell
}
4632 d9b0848d Peter Maydell
4633 d9b0848d Peter Maydell
/* ARMv8 round to integral */
4634 d9b0848d Peter Maydell
float32 HELPER(rints_exact)(float32 x, void *fp_status)
4635 d9b0848d Peter Maydell
{
4636 d9b0848d Peter Maydell
    return float32_round_to_int(x, fp_status);
4637 d9b0848d Peter Maydell
}
4638 d9b0848d Peter Maydell
4639 d9b0848d Peter Maydell
float64 HELPER(rintd_exact)(float64 x, void *fp_status)
4640 d9b0848d Peter Maydell
{
4641 d9b0848d Peter Maydell
    return float64_round_to_int(x, fp_status);
4642 d9b0848d Peter Maydell
}
4643 d9b0848d Peter Maydell
4644 d9b0848d Peter Maydell
float32 HELPER(rints)(float32 x, void *fp_status)
4645 d9b0848d Peter Maydell
{
4646 d9b0848d Peter Maydell
    int old_flags = get_float_exception_flags(fp_status), new_flags;
4647 d9b0848d Peter Maydell
    float32 ret;
4648 d9b0848d Peter Maydell
4649 d9b0848d Peter Maydell
    ret = float32_round_to_int(x, fp_status);
4650 d9b0848d Peter Maydell
4651 d9b0848d Peter Maydell
    /* Suppress any inexact exceptions the conversion produced */
4652 d9b0848d Peter Maydell
    if (!(old_flags & float_flag_inexact)) {
4653 d9b0848d Peter Maydell
        new_flags = get_float_exception_flags(fp_status);
4654 d9b0848d Peter Maydell
        set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
4655 d9b0848d Peter Maydell
    }
4656 d9b0848d Peter Maydell
4657 d9b0848d Peter Maydell
    return ret;
4658 d9b0848d Peter Maydell
}
4659 d9b0848d Peter Maydell
4660 d9b0848d Peter Maydell
float64 HELPER(rintd)(float64 x, void *fp_status)
4661 d9b0848d Peter Maydell
{
4662 d9b0848d Peter Maydell
    int old_flags = get_float_exception_flags(fp_status), new_flags;
4663 d9b0848d Peter Maydell
    float64 ret;
4664 d9b0848d Peter Maydell
4665 d9b0848d Peter Maydell
    ret = float64_round_to_int(x, fp_status);
4666 d9b0848d Peter Maydell
4667 d9b0848d Peter Maydell
    new_flags = get_float_exception_flags(fp_status);
4668 d9b0848d Peter Maydell
4669 d9b0848d Peter Maydell
    /* Suppress any inexact exceptions the conversion produced */
4670 d9b0848d Peter Maydell
    if (!(old_flags & float_flag_inexact)) {
4671 d9b0848d Peter Maydell
        new_flags = get_float_exception_flags(fp_status);
4672 d9b0848d Peter Maydell
        set_float_exception_flags(new_flags & ~float_flag_inexact, fp_status);
4673 d9b0848d Peter Maydell
    }
4674 d9b0848d Peter Maydell
4675 d9b0848d Peter Maydell
    return ret;
4676 d9b0848d Peter Maydell
}
4677 9972da66 Will Newton
4678 9972da66 Will Newton
/* Convert ARM rounding mode to softfloat */
4679 9972da66 Will Newton
int arm_rmode_to_sf(int rmode)
4680 9972da66 Will Newton
{
4681 9972da66 Will Newton
    switch (rmode) {
4682 9972da66 Will Newton
    case FPROUNDING_TIEAWAY:
4683 9972da66 Will Newton
        rmode = float_round_ties_away;
4684 9972da66 Will Newton
        break;
4685 9972da66 Will Newton
    case FPROUNDING_ODD:
4686 9972da66 Will Newton
        /* FIXME: add support for TIEAWAY and ODD */
4687 9972da66 Will Newton
        qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
4688 9972da66 Will Newton
                      rmode);
4689 9972da66 Will Newton
    case FPROUNDING_TIEEVEN:
4690 9972da66 Will Newton
    default:
4691 9972da66 Will Newton
        rmode = float_round_nearest_even;
4692 9972da66 Will Newton
        break;
4693 9972da66 Will Newton
    case FPROUNDING_POSINF:
4694 9972da66 Will Newton
        rmode = float_round_up;
4695 9972da66 Will Newton
        break;
4696 9972da66 Will Newton
    case FPROUNDING_NEGINF:
4697 9972da66 Will Newton
        rmode = float_round_down;
4698 9972da66 Will Newton
        break;
4699 9972da66 Will Newton
    case FPROUNDING_ZERO:
4700 9972da66 Will Newton
        rmode = float_round_to_zero;
4701 9972da66 Will Newton
        break;
4702 9972da66 Will Newton
    }
4703 9972da66 Will Newton
    return rmode;
4704 9972da66 Will Newton
}