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