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