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