Statistics
| Branch: | Revision:

root / target-arm / helper.c @ 85df3786

History | View | Annotate | Download (87.7 kB)

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