Statistics
| Branch: | Revision:

root / target-arm / helper.c @ 8641136c

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