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