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