Statistics
| Branch: | Revision:

root / target-arm / helper.c @ cbf239b7

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