|
|
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"
! 8:
! 9: static uint32_t cortexa8_cp15_c0_c1[8] =
! 10: { 0x1031, 0x11, 0x400, 0, 0x31100003, 0x20000000, 0x01202000, 0x11 };
! 11:
! 12: static uint32_t cortexa8_cp15_c0_c2[8] =
! 13: { 0x00101111, 0x12112111, 0x21232031, 0x11112131, 0x00111142, 0, 0, 0 };
! 14:
! 15: static uint32_t mpcore_cp15_c0_c1[8] =
! 16: { 0x111, 0x1, 0, 0x2, 0x01100103, 0x10020302, 0x01222000, 0 };
! 17:
! 18: static uint32_t mpcore_cp15_c0_c2[8] =
! 19: { 0x00100011, 0x12002111, 0x11221011, 0x01102131, 0x141, 0, 0, 0 };
! 20:
! 21: static uint32_t arm1136_cp15_c0_c1[8] =
! 22: { 0x111, 0x1, 0x2, 0x3, 0x01130003, 0x10030302, 0x01222110, 0 };
! 23:
! 24: static uint32_t arm1136_cp15_c0_c2[8] =
! 25: { 0x00140011, 0x12002111, 0x11231111, 0x01102131, 0x141, 0, 0, 0 };
! 26:
! 27: static uint32_t cpu_arm_find_by_name(const char *name);
! 28:
! 29: static inline void set_feature(CPUARMState *env, int feature)
! 30: {
! 31: env->features |= 1u << feature;
! 32: }
! 33:
! 34: static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
! 35: {
! 36: env->cp15.c0_cpuid = id;
! 37: switch (id) {
! 38: case ARM_CPUID_ARM926:
! 39: set_feature(env, ARM_FEATURE_VFP);
! 40: env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
! 41: env->cp15.c0_cachetype = 0x1dd20d2;
! 42: env->cp15.c1_sys = 0x00090078;
! 43: break;
! 44: case ARM_CPUID_ARM946:
! 45: set_feature(env, ARM_FEATURE_MPU);
! 46: env->cp15.c0_cachetype = 0x0f004006;
! 47: env->cp15.c1_sys = 0x00000078;
! 48: break;
! 49: case ARM_CPUID_ARM1026:
! 50: set_feature(env, ARM_FEATURE_VFP);
! 51: set_feature(env, ARM_FEATURE_AUXCR);
! 52: env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0;
! 53: env->cp15.c0_cachetype = 0x1dd20d2;
! 54: env->cp15.c1_sys = 0x00090078;
! 55: break;
! 56: case ARM_CPUID_ARM1136:
! 57: set_feature(env, ARM_FEATURE_V6);
! 58: set_feature(env, ARM_FEATURE_VFP);
! 59: set_feature(env, ARM_FEATURE_AUXCR);
! 60: env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b4;
! 61: env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111;
! 62: env->vfp.xregs[ARM_VFP_MVFR1] = 0x00000000;
! 63: memcpy(env->cp15.c0_c1, arm1136_cp15_c0_c1, 8 * sizeof(uint32_t));
! 64: memcpy(env->cp15.c0_c1, arm1136_cp15_c0_c2, 8 * sizeof(uint32_t));
! 65: env->cp15.c0_cachetype = 0x1dd20d2;
! 66: break;
! 67: case ARM_CPUID_ARM11MPCORE:
! 68: set_feature(env, ARM_FEATURE_V6);
! 69: set_feature(env, ARM_FEATURE_V6K);
! 70: set_feature(env, ARM_FEATURE_VFP);
! 71: set_feature(env, ARM_FEATURE_AUXCR);
! 72: env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b4;
! 73: env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111;
! 74: env->vfp.xregs[ARM_VFP_MVFR1] = 0x00000000;
! 75: memcpy(env->cp15.c0_c1, mpcore_cp15_c0_c1, 8 * sizeof(uint32_t));
! 76: memcpy(env->cp15.c0_c1, mpcore_cp15_c0_c2, 8 * sizeof(uint32_t));
! 77: env->cp15.c0_cachetype = 0x1dd20d2;
! 78: break;
! 79: case ARM_CPUID_CORTEXA8:
! 80: set_feature(env, ARM_FEATURE_V6);
! 81: set_feature(env, ARM_FEATURE_V6K);
! 82: set_feature(env, ARM_FEATURE_V7);
! 83: set_feature(env, ARM_FEATURE_AUXCR);
! 84: set_feature(env, ARM_FEATURE_THUMB2);
! 85: set_feature(env, ARM_FEATURE_VFP);
! 86: set_feature(env, ARM_FEATURE_VFP3);
! 87: set_feature(env, ARM_FEATURE_NEON);
! 88: env->vfp.xregs[ARM_VFP_FPSID] = 0x410330c0;
! 89: env->vfp.xregs[ARM_VFP_MVFR0] = 0x11110222;
! 90: env->vfp.xregs[ARM_VFP_MVFR1] = 0x00011100;
! 91: memcpy(env->cp15.c0_c1, cortexa8_cp15_c0_c1, 8 * sizeof(uint32_t));
! 92: memcpy(env->cp15.c0_c1, cortexa8_cp15_c0_c2, 8 * sizeof(uint32_t));
! 93: env->cp15.c0_cachetype = 0x1dd20d2;
! 94: break;
! 95: case ARM_CPUID_CORTEXM3:
! 96: set_feature(env, ARM_FEATURE_V6);
! 97: set_feature(env, ARM_FEATURE_THUMB2);
! 98: set_feature(env, ARM_FEATURE_V7);
! 99: set_feature(env, ARM_FEATURE_M);
! 100: set_feature(env, ARM_FEATURE_DIV);
! 101: break;
! 102: case ARM_CPUID_ANY: /* For userspace emulation. */
! 103: set_feature(env, ARM_FEATURE_V6);
! 104: set_feature(env, ARM_FEATURE_V6K);
! 105: set_feature(env, ARM_FEATURE_V7);
! 106: set_feature(env, ARM_FEATURE_THUMB2);
! 107: set_feature(env, ARM_FEATURE_VFP);
! 108: set_feature(env, ARM_FEATURE_VFP3);
! 109: set_feature(env, ARM_FEATURE_NEON);
! 110: set_feature(env, ARM_FEATURE_DIV);
! 111: break;
! 112: case ARM_CPUID_TI915T:
! 113: case ARM_CPUID_TI925T:
! 114: set_feature(env, ARM_FEATURE_OMAPCP);
! 115: env->cp15.c0_cpuid = ARM_CPUID_TI925T; /* Depends on wiring. */
! 116: env->cp15.c0_cachetype = 0x5109149;
! 117: env->cp15.c1_sys = 0x00000070;
! 118: env->cp15.c15_i_max = 0x000;
! 119: env->cp15.c15_i_min = 0xff0;
! 120: break;
! 121: case ARM_CPUID_PXA250:
! 122: case ARM_CPUID_PXA255:
! 123: case ARM_CPUID_PXA260:
! 124: case ARM_CPUID_PXA261:
! 125: case ARM_CPUID_PXA262:
! 126: set_feature(env, ARM_FEATURE_XSCALE);
! 127: /* JTAG_ID is ((id << 28) | 0x09265013) */
! 128: env->cp15.c0_cachetype = 0xd172172;
! 129: env->cp15.c1_sys = 0x00000078;
! 130: break;
! 131: case ARM_CPUID_PXA270_A0:
! 132: case ARM_CPUID_PXA270_A1:
! 133: case ARM_CPUID_PXA270_B0:
! 134: case ARM_CPUID_PXA270_B1:
! 135: case ARM_CPUID_PXA270_C0:
! 136: case ARM_CPUID_PXA270_C5:
! 137: set_feature(env, ARM_FEATURE_XSCALE);
! 138: /* JTAG_ID is ((id << 28) | 0x09265013) */
! 139: set_feature(env, ARM_FEATURE_IWMMXT);
! 140: env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q';
! 141: env->cp15.c0_cachetype = 0xd172172;
! 142: env->cp15.c1_sys = 0x00000078;
! 143: break;
! 144: default:
! 145: cpu_abort(env, "Bad CPU ID: %x\n", id);
! 146: break;
! 147: }
! 148: }
1.1 root 149:
1.1.1.2 root 150: void cpu_reset(CPUARMState *env)
151: {
1.1.1.5 ! root 152: uint32_t id;
! 153: id = env->cp15.c0_cpuid;
! 154: memset(env, 0, offsetof(CPUARMState, breakpoints));
! 155: if (id)
! 156: cpu_reset_model_id(env, id);
1.1.1.2 root 157: #if defined (CONFIG_USER_ONLY)
158: env->uncached_cpsr = ARM_CPU_MODE_USR;
159: env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30;
160: #else
161: /* SVC mode with interrupts disabled. */
162: env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
1.1.1.5 ! root 163: /* On ARMv7-M the CPSR_I is the value of the PRIMASK register, and is
! 164: clear at reset. */
! 165: if (IS_M(env))
! 166: env->uncached_cpsr &= ~CPSR_I;
1.1.1.2 root 167: env->vfp.xregs[ARM_VFP_FPEXC] = 0;
168: #endif
169: env->regs[15] = 0;
1.1.1.5 ! root 170: tlb_flush(env, 1);
1.1.1.2 root 171: }
172:
1.1.1.5 ! root 173: CPUARMState *cpu_arm_init(const char *cpu_model)
1.1.1.2 root 174: {
175: CPUARMState *env;
1.1.1.5 ! root 176: uint32_t id;
1.1.1.2 root 177:
1.1.1.5 ! root 178: id = cpu_arm_find_by_name(cpu_model);
! 179: if (id == 0)
! 180: return NULL;
1.1.1.2 root 181: env = qemu_mallocz(sizeof(CPUARMState));
182: if (!env)
183: return NULL;
184: cpu_exec_init(env);
1.1.1.5 ! root 185: env->cpu_model_str = cpu_model;
! 186: env->cp15.c0_cpuid = id;
1.1.1.2 root 187: cpu_reset(env);
188: return env;
189: }
190:
1.1.1.5 ! root 191: struct arm_cpu_t {
! 192: uint32_t id;
! 193: const char *name;
! 194: };
! 195:
! 196: static const struct arm_cpu_t arm_cpu_names[] = {
! 197: { ARM_CPUID_ARM926, "arm926"},
! 198: { ARM_CPUID_ARM946, "arm946"},
! 199: { ARM_CPUID_ARM1026, "arm1026"},
! 200: { ARM_CPUID_ARM1136, "arm1136"},
! 201: { ARM_CPUID_ARM11MPCORE, "arm11mpcore"},
! 202: { ARM_CPUID_CORTEXM3, "cortex-m3"},
! 203: { ARM_CPUID_CORTEXA8, "cortex-a8"},
! 204: { ARM_CPUID_TI925T, "ti925t" },
! 205: { ARM_CPUID_PXA250, "pxa250" },
! 206: { ARM_CPUID_PXA255, "pxa255" },
! 207: { ARM_CPUID_PXA260, "pxa260" },
! 208: { ARM_CPUID_PXA261, "pxa261" },
! 209: { ARM_CPUID_PXA262, "pxa262" },
! 210: { ARM_CPUID_PXA270, "pxa270" },
! 211: { ARM_CPUID_PXA270_A0, "pxa270-a0" },
! 212: { ARM_CPUID_PXA270_A1, "pxa270-a1" },
! 213: { ARM_CPUID_PXA270_B0, "pxa270-b0" },
! 214: { ARM_CPUID_PXA270_B1, "pxa270-b1" },
! 215: { ARM_CPUID_PXA270_C0, "pxa270-c0" },
! 216: { ARM_CPUID_PXA270_C5, "pxa270-c5" },
! 217: { ARM_CPUID_ANY, "any"},
! 218: { 0, NULL}
! 219: };
! 220:
! 221: void arm_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1.1.1.2 root 222: {
1.1.1.5 ! root 223: int i;
! 224:
! 225: (*cpu_fprintf)(f, "Available CPUs:\n");
! 226: for (i = 0; arm_cpu_names[i].name; i++) {
! 227: (*cpu_fprintf)(f, " %s\n", arm_cpu_names[i].name);
! 228: }
1.1.1.2 root 229: }
230:
1.1.1.5 ! root 231: /* return 0 if not found */
! 232: static uint32_t cpu_arm_find_by_name(const char *name)
1.1.1.2 root 233: {
1.1.1.5 ! root 234: int i;
! 235: uint32_t id;
! 236:
! 237: id = 0;
! 238: for (i = 0; arm_cpu_names[i].name; i++) {
! 239: if (strcmp(name, arm_cpu_names[i].name) == 0) {
! 240: id = arm_cpu_names[i].id;
! 241: break;
! 242: }
1.1.1.2 root 243: }
1.1.1.5 ! root 244: return id;
1.1.1.2 root 245: }
246:
247: void cpu_arm_close(CPUARMState *env)
248: {
249: free(env);
250: }
251:
1.1.1.5 ! root 252: /* Polynomial multiplication is like integer multiplcation except the
! 253: partial products are XORed, not added. */
! 254: uint32_t helper_neon_mul_p8(uint32_t op1, uint32_t op2)
! 255: {
! 256: uint32_t mask;
! 257: uint32_t result;
! 258: result = 0;
! 259: while (op1) {
! 260: mask = 0;
! 261: if (op1 & 1)
! 262: mask |= 0xff;
! 263: if (op1 & (1 << 8))
! 264: mask |= (0xff << 8);
! 265: if (op1 & (1 << 16))
! 266: mask |= (0xff << 16);
! 267: if (op1 & (1 << 24))
! 268: mask |= (0xff << 24);
! 269: result ^= op2 & mask;
! 270: op1 = (op1 >> 1) & 0x7f7f7f7f;
! 271: op2 = (op2 << 1) & 0xfefefefe;
! 272: }
! 273: return result;
! 274: }
! 275:
! 276: uint32_t cpsr_read(CPUARMState *env)
! 277: {
! 278: int ZF;
! 279: ZF = (env->NZF == 0);
! 280: return env->uncached_cpsr | (env->NZF & 0x80000000) | (ZF << 30) |
! 281: (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
! 282: | (env->thumb << 5) | ((env->condexec_bits & 3) << 25)
! 283: | ((env->condexec_bits & 0xfc) << 8)
! 284: | (env->GE << 16);
! 285: }
! 286:
! 287: void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
! 288: {
! 289: /* NOTE: N = 1 and Z = 1 cannot be stored currently */
! 290: if (mask & CPSR_NZCV) {
! 291: env->NZF = (val & 0xc0000000) ^ 0x40000000;
! 292: env->CF = (val >> 29) & 1;
! 293: env->VF = (val << 3) & 0x80000000;
! 294: }
! 295: if (mask & CPSR_Q)
! 296: env->QF = ((val & CPSR_Q) != 0);
! 297: if (mask & CPSR_T)
! 298: env->thumb = ((val & CPSR_T) != 0);
! 299: if (mask & CPSR_IT_0_1) {
! 300: env->condexec_bits &= ~3;
! 301: env->condexec_bits |= (val >> 25) & 3;
! 302: }
! 303: if (mask & CPSR_IT_2_7) {
! 304: env->condexec_bits &= 3;
! 305: env->condexec_bits |= (val >> 8) & 0xfc;
! 306: }
! 307: if (mask & CPSR_GE) {
! 308: env->GE = (val >> 16) & 0xf;
! 309: }
! 310:
! 311: if ((env->uncached_cpsr ^ val) & mask & CPSR_M) {
! 312: switch_mode(env, val & CPSR_M);
! 313: }
! 314: mask &= ~CACHED_CPSR_BITS;
! 315: env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask);
! 316: }
! 317:
! 318: #if defined(CONFIG_USER_ONLY)
1.1 root 319:
320: void do_interrupt (CPUState *env)
321: {
322: env->exception_index = -1;
323: }
324:
1.1.1.5 ! root 325: /* Structure used to record exclusive memory locations. */
! 326: typedef struct mmon_state {
! 327: struct mmon_state *next;
! 328: CPUARMState *cpu_env;
! 329: uint32_t addr;
! 330: } mmon_state;
! 331:
! 332: /* Chain of current locks. */
! 333: static mmon_state* mmon_head = NULL;
! 334:
1.1 root 335: int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1.1.1.5 ! root 336: int mmu_idx, int is_softmmu)
1.1 root 337: {
338: if (rw == 2) {
339: env->exception_index = EXCP_PREFETCH_ABORT;
340: env->cp15.c6_insn = address;
341: } else {
342: env->exception_index = EXCP_DATA_ABORT;
343: env->cp15.c6_data = address;
344: }
345: return 1;
346: }
347:
1.1.1.5 ! root 348: static void allocate_mmon_state(CPUState *env)
! 349: {
! 350: env->mmon_entry = malloc(sizeof (mmon_state));
! 351: if (!env->mmon_entry)
! 352: abort();
! 353: memset (env->mmon_entry, 0, sizeof (mmon_state));
! 354: env->mmon_entry->cpu_env = env;
! 355: mmon_head = env->mmon_entry;
! 356: }
! 357:
! 358: /* Flush any monitor locks for the specified address. */
! 359: static void flush_mmon(uint32_t addr)
! 360: {
! 361: mmon_state *mon;
! 362:
! 363: for (mon = mmon_head; mon; mon = mon->next)
! 364: {
! 365: if (mon->addr != addr)
! 366: continue;
! 367:
! 368: mon->addr = 0;
! 369: break;
! 370: }
! 371: }
! 372:
! 373: /* Mark an address for exclusive access. */
! 374: void helper_mark_exclusive(CPUState *env, uint32_t addr)
! 375: {
! 376: if (!env->mmon_entry)
! 377: allocate_mmon_state(env);
! 378: /* Clear any previous locks. */
! 379: flush_mmon(addr);
! 380: env->mmon_entry->addr = addr;
! 381: }
! 382:
! 383: /* Test if an exclusive address is still exclusive. Returns zero
! 384: if the address is still exclusive. */
! 385: int helper_test_exclusive(CPUState *env, uint32_t addr)
! 386: {
! 387: int res;
! 388:
! 389: if (!env->mmon_entry)
! 390: return 1;
! 391: if (env->mmon_entry->addr == addr)
! 392: res = 0;
! 393: else
! 394: res = 1;
! 395: flush_mmon(addr);
! 396: return res;
! 397: }
! 398:
! 399: void helper_clrex(CPUState *env)
! 400: {
! 401: if (!(env->mmon_entry && env->mmon_entry->addr))
! 402: return;
! 403: flush_mmon(env->mmon_entry->addr);
! 404: }
! 405:
! 406: target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1.1 root 407: {
408: return addr;
409: }
410:
411: /* These should probably raise undefined insn exceptions. */
1.1.1.5 ! root 412: void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val)
! 413: {
! 414: int op1 = (insn >> 8) & 0xf;
! 415: cpu_abort(env, "cp%i insn %08x\n", op1, insn);
! 416: return;
! 417: }
! 418:
! 419: uint32_t helper_get_cp(CPUState *env, uint32_t insn)
! 420: {
! 421: int op1 = (insn >> 8) & 0xf;
! 422: cpu_abort(env, "cp%i insn %08x\n", op1, insn);
! 423: return 0;
! 424: }
! 425:
1.1 root 426: void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
427: {
428: cpu_abort(env, "cp15 insn %08x\n", insn);
429: }
430:
431: uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
432: {
433: cpu_abort(env, "cp15 insn %08x\n", insn);
434: return 0;
435: }
436:
1.1.1.5 ! root 437: /* These should probably raise undefined insn exceptions. */
! 438: void helper_v7m_msr(CPUState *env, int reg, uint32_t val)
! 439: {
! 440: cpu_abort(env, "v7m_mrs %d\n", reg);
! 441: }
! 442:
! 443: uint32_t helper_v7m_mrs(CPUState *env, int reg)
! 444: {
! 445: cpu_abort(env, "v7m_mrs %d\n", reg);
! 446: return 0;
! 447: }
! 448:
1.1 root 449: void switch_mode(CPUState *env, int mode)
450: {
451: if (mode != ARM_CPU_MODE_USR)
452: cpu_abort(env, "Tried to switch out of user mode\n");
453: }
454:
1.1.1.5 ! root 455: void helper_set_r13_banked(CPUState *env, int mode, uint32_t val)
! 456: {
! 457: cpu_abort(env, "banked r13 write\n");
! 458: }
! 459:
! 460: uint32_t helper_get_r13_banked(CPUState *env, int mode)
! 461: {
! 462: cpu_abort(env, "banked r13 read\n");
! 463: return 0;
! 464: }
! 465:
1.1 root 466: #else
467:
1.1.1.4 root 468: extern int semihosting_enabled;
469:
1.1 root 470: /* Map CPU modes onto saved register banks. */
471: static inline int bank_number (int mode)
472: {
473: switch (mode) {
474: case ARM_CPU_MODE_USR:
475: case ARM_CPU_MODE_SYS:
476: return 0;
477: case ARM_CPU_MODE_SVC:
478: return 1;
479: case ARM_CPU_MODE_ABT:
480: return 2;
481: case ARM_CPU_MODE_UND:
482: return 3;
483: case ARM_CPU_MODE_IRQ:
484: return 4;
485: case ARM_CPU_MODE_FIQ:
486: return 5;
487: }
488: cpu_abort(cpu_single_env, "Bad mode %x\n", mode);
489: return -1;
490: }
491:
492: void switch_mode(CPUState *env, int mode)
493: {
494: int old_mode;
495: int i;
496:
497: old_mode = env->uncached_cpsr & CPSR_M;
498: if (mode == old_mode)
499: return;
500:
501: if (old_mode == ARM_CPU_MODE_FIQ) {
502: memcpy (env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
1.1.1.2 root 503: memcpy (env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
1.1 root 504: } else if (mode == ARM_CPU_MODE_FIQ) {
505: memcpy (env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
1.1.1.2 root 506: memcpy (env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
1.1 root 507: }
508:
509: i = bank_number(old_mode);
510: env->banked_r13[i] = env->regs[13];
511: env->banked_r14[i] = env->regs[14];
512: env->banked_spsr[i] = env->spsr;
513:
514: i = bank_number(mode);
515: env->regs[13] = env->banked_r13[i];
516: env->regs[14] = env->banked_r14[i];
517: env->spsr = env->banked_spsr[i];
518: }
519:
1.1.1.5 ! root 520: static void v7m_push(CPUARMState *env, uint32_t val)
! 521: {
! 522: env->regs[13] -= 4;
! 523: stl_phys(env->regs[13], val);
! 524: }
! 525:
! 526: static uint32_t v7m_pop(CPUARMState *env)
! 527: {
! 528: uint32_t val;
! 529: val = ldl_phys(env->regs[13]);
! 530: env->regs[13] += 4;
! 531: return val;
! 532: }
! 533:
! 534: /* Switch to V7M main or process stack pointer. */
! 535: static void switch_v7m_sp(CPUARMState *env, int process)
! 536: {
! 537: uint32_t tmp;
! 538: if (env->v7m.current_sp != process) {
! 539: tmp = env->v7m.other_sp;
! 540: env->v7m.other_sp = env->regs[13];
! 541: env->regs[13] = tmp;
! 542: env->v7m.current_sp = process;
! 543: }
! 544: }
! 545:
! 546: static void do_v7m_exception_exit(CPUARMState *env)
! 547: {
! 548: uint32_t type;
! 549: uint32_t xpsr;
! 550:
! 551: type = env->regs[15];
! 552: if (env->v7m.exception != 0)
! 553: armv7m_nvic_complete_irq(env->v7m.nvic, env->v7m.exception);
! 554:
! 555: /* Switch to the target stack. */
! 556: switch_v7m_sp(env, (type & 4) != 0);
! 557: /* Pop registers. */
! 558: env->regs[0] = v7m_pop(env);
! 559: env->regs[1] = v7m_pop(env);
! 560: env->regs[2] = v7m_pop(env);
! 561: env->regs[3] = v7m_pop(env);
! 562: env->regs[12] = v7m_pop(env);
! 563: env->regs[14] = v7m_pop(env);
! 564: env->regs[15] = v7m_pop(env);
! 565: xpsr = v7m_pop(env);
! 566: xpsr_write(env, xpsr, 0xfffffdff);
! 567: /* Undo stack alignment. */
! 568: if (xpsr & 0x200)
! 569: env->regs[13] |= 4;
! 570: /* ??? The exception return type specifies Thread/Handler mode. However
! 571: this is also implied by the xPSR value. Not sure what to do
! 572: if there is a mismatch. */
! 573: /* ??? Likewise for mismatches between the CONTROL register and the stack
! 574: pointer. */
! 575: }
! 576:
! 577: void do_interrupt_v7m(CPUARMState *env)
! 578: {
! 579: uint32_t xpsr = xpsr_read(env);
! 580: uint32_t lr;
! 581: uint32_t addr;
! 582:
! 583: lr = 0xfffffff1;
! 584: if (env->v7m.current_sp)
! 585: lr |= 4;
! 586: if (env->v7m.exception == 0)
! 587: lr |= 8;
! 588:
! 589: /* For exceptions we just mark as pending on the NVIC, and let that
! 590: handle it. */
! 591: /* TODO: Need to escalate if the current priority is higher than the
! 592: one we're raising. */
! 593: switch (env->exception_index) {
! 594: case EXCP_UDEF:
! 595: armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_USAGE);
! 596: return;
! 597: case EXCP_SWI:
! 598: env->regs[15] += 2;
! 599: armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_SVC);
! 600: return;
! 601: case EXCP_PREFETCH_ABORT:
! 602: case EXCP_DATA_ABORT:
! 603: armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_MEM);
! 604: return;
! 605: case EXCP_BKPT:
! 606: if (semihosting_enabled) {
! 607: int nr;
! 608: nr = lduw_code(env->regs[15]) & 0xff;
! 609: if (nr == 0xab) {
! 610: env->regs[15] += 2;
! 611: env->regs[0] = do_arm_semihosting(env);
! 612: return;
! 613: }
! 614: }
! 615: armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_DEBUG);
! 616: return;
! 617: case EXCP_IRQ:
! 618: env->v7m.exception = armv7m_nvic_acknowledge_irq(env->v7m.nvic);
! 619: break;
! 620: case EXCP_EXCEPTION_EXIT:
! 621: do_v7m_exception_exit(env);
! 622: return;
! 623: default:
! 624: cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
! 625: return; /* Never happens. Keep compiler happy. */
! 626: }
! 627:
! 628: /* Align stack pointer. */
! 629: /* ??? Should only do this if Configuration Control Register
! 630: STACKALIGN bit is set. */
! 631: if (env->regs[13] & 4) {
! 632: env->regs[13] += 4;
! 633: xpsr |= 0x200;
! 634: }
! 635: /* Switch to the hander mode. */
! 636: v7m_push(env, xpsr);
! 637: v7m_push(env, env->regs[15]);
! 638: v7m_push(env, env->regs[14]);
! 639: v7m_push(env, env->regs[12]);
! 640: v7m_push(env, env->regs[3]);
! 641: v7m_push(env, env->regs[2]);
! 642: v7m_push(env, env->regs[1]);
! 643: v7m_push(env, env->regs[0]);
! 644: switch_v7m_sp(env, 0);
! 645: env->uncached_cpsr &= ~CPSR_IT;
! 646: env->regs[14] = lr;
! 647: addr = ldl_phys(env->v7m.vecbase + env->v7m.exception * 4);
! 648: env->regs[15] = addr & 0xfffffffe;
! 649: env->thumb = addr & 1;
! 650: }
! 651:
1.1 root 652: /* Handle a CPU exception. */
653: void do_interrupt(CPUARMState *env)
654: {
655: uint32_t addr;
656: uint32_t mask;
657: int new_mode;
658: uint32_t offset;
659:
1.1.1.5 ! root 660: if (IS_M(env)) {
! 661: do_interrupt_v7m(env);
! 662: return;
! 663: }
1.1 root 664: /* TODO: Vectored interrupt controller. */
665: switch (env->exception_index) {
666: case EXCP_UDEF:
667: new_mode = ARM_CPU_MODE_UND;
668: addr = 0x04;
669: mask = CPSR_I;
670: if (env->thumb)
671: offset = 2;
672: else
673: offset = 4;
674: break;
675: case EXCP_SWI:
1.1.1.4 root 676: if (semihosting_enabled) {
677: /* Check for semihosting interrupt. */
678: if (env->thumb) {
679: mask = lduw_code(env->regs[15] - 2) & 0xff;
680: } else {
681: mask = ldl_code(env->regs[15] - 4) & 0xffffff;
682: }
683: /* Only intercept calls from privileged modes, to provide some
684: semblance of security. */
685: if (((mask == 0x123456 && !env->thumb)
686: || (mask == 0xab && env->thumb))
687: && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
688: env->regs[0] = do_arm_semihosting(env);
689: return;
690: }
691: }
1.1 root 692: new_mode = ARM_CPU_MODE_SVC;
693: addr = 0x08;
694: mask = CPSR_I;
695: /* The PC already points to the next instructon. */
696: offset = 0;
697: break;
1.1.1.2 root 698: case EXCP_BKPT:
1.1.1.5 ! root 699: /* See if this is a semihosting syscall. */
! 700: if (env->thumb && semihosting_enabled) {
! 701: mask = lduw_code(env->regs[15]) & 0xff;
! 702: if (mask == 0xab
! 703: && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
! 704: env->regs[15] += 2;
! 705: env->regs[0] = do_arm_semihosting(env);
! 706: return;
! 707: }
! 708: }
! 709: /* Fall through to prefetch abort. */
! 710: case EXCP_PREFETCH_ABORT:
1.1 root 711: new_mode = ARM_CPU_MODE_ABT;
712: addr = 0x0c;
713: mask = CPSR_A | CPSR_I;
714: offset = 4;
715: break;
716: case EXCP_DATA_ABORT:
717: new_mode = ARM_CPU_MODE_ABT;
718: addr = 0x10;
719: mask = CPSR_A | CPSR_I;
720: offset = 8;
721: break;
722: case EXCP_IRQ:
723: new_mode = ARM_CPU_MODE_IRQ;
724: addr = 0x18;
725: /* Disable IRQ and imprecise data aborts. */
726: mask = CPSR_A | CPSR_I;
727: offset = 4;
728: break;
729: case EXCP_FIQ:
730: new_mode = ARM_CPU_MODE_FIQ;
731: addr = 0x1c;
732: /* Disable FIQ, IRQ and imprecise data aborts. */
733: mask = CPSR_A | CPSR_I | CPSR_F;
734: offset = 4;
735: break;
736: default:
737: cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
738: return; /* Never happens. Keep compiler happy. */
739: }
740: /* High vectors. */
741: if (env->cp15.c1_sys & (1 << 13)) {
742: addr += 0xffff0000;
743: }
744: switch_mode (env, new_mode);
745: env->spsr = cpsr_read(env);
1.1.1.5 ! root 746: /* Clear IT bits. */
! 747: env->condexec_bits = 0;
1.1 root 748: /* Switch to the new mode, and switch to Arm mode. */
749: /* ??? Thumb interrupt handlers not implemented. */
750: env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
751: env->uncached_cpsr |= mask;
752: env->thumb = 0;
753: env->regs[14] = env->regs[15] + offset;
754: env->regs[15] = addr;
755: env->interrupt_request |= CPU_INTERRUPT_EXITTB;
756: }
757:
758: /* Check section/page access permissions.
759: Returns the page protection flags, or zero if the access is not
760: permitted. */
761: static inline int check_ap(CPUState *env, int ap, int domain, int access_type,
762: int is_user)
763: {
1.1.1.5 ! root 764: int prot_ro;
! 765:
1.1 root 766: if (domain == 3)
767: return PAGE_READ | PAGE_WRITE;
768:
1.1.1.5 ! root 769: if (access_type == 1)
! 770: prot_ro = 0;
! 771: else
! 772: prot_ro = PAGE_READ;
! 773:
1.1 root 774: switch (ap) {
775: case 0:
1.1.1.4 root 776: if (access_type == 1)
1.1 root 777: return 0;
778: switch ((env->cp15.c1_sys >> 8) & 3) {
779: case 1:
780: return is_user ? 0 : PAGE_READ;
781: case 2:
782: return PAGE_READ;
783: default:
784: return 0;
785: }
786: case 1:
787: return is_user ? 0 : PAGE_READ | PAGE_WRITE;
788: case 2:
789: if (is_user)
1.1.1.5 ! root 790: return prot_ro;
1.1 root 791: else
792: return PAGE_READ | PAGE_WRITE;
793: case 3:
794: return PAGE_READ | PAGE_WRITE;
1.1.1.5 ! root 795: case 4: case 7: /* Reserved. */
! 796: return 0;
! 797: case 5:
! 798: return is_user ? 0 : prot_ro;
! 799: case 6:
! 800: return prot_ro;
1.1 root 801: default:
802: abort();
803: }
804: }
805:
1.1.1.5 ! root 806: static int get_phys_addr_v5(CPUState *env, uint32_t address, int access_type,
! 807: int is_user, uint32_t *phys_ptr, int *prot)
1.1 root 808: {
809: int code;
810: uint32_t table;
811: uint32_t desc;
812: int type;
813: int ap;
814: int domain;
815: uint32_t phys_addr;
816:
1.1.1.5 ! root 817: /* Pagetable walk. */
! 818: /* Lookup l1 descriptor. */
! 819: if (address & env->cp15.c2_mask)
! 820: table = env->cp15.c2_base1;
! 821: else
! 822: table = env->cp15.c2_base0;
! 823: table = (table & 0xffffc000) | ((address >> 18) & 0x3ffc);
! 824: desc = ldl_phys(table);
! 825: type = (desc & 3);
! 826: domain = (env->cp15.c3 >> ((desc >> 4) & 0x1e)) & 3;
! 827: if (type == 0) {
! 828: /* Secton translation fault. */
! 829: code = 5;
! 830: goto do_fault;
! 831: }
! 832: if (domain == 0 || domain == 2) {
! 833: if (type == 2)
! 834: code = 9; /* Section domain fault. */
! 835: else
! 836: code = 11; /* Page domain fault. */
! 837: goto do_fault;
! 838: }
! 839: if (type == 2) {
! 840: /* 1Mb section. */
! 841: phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
! 842: ap = (desc >> 10) & 3;
! 843: code = 13;
1.1 root 844: } else {
1.1.1.5 ! root 845: /* Lookup l2 entry. */
! 846: if (type == 1) {
! 847: /* Coarse pagetable. */
! 848: table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
! 849: } else {
! 850: /* Fine pagetable. */
! 851: table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
! 852: }
1.1 root 853: desc = ldl_phys(table);
1.1.1.5 ! root 854: switch (desc & 3) {
! 855: case 0: /* Page translation fault. */
! 856: code = 7;
1.1 root 857: goto do_fault;
1.1.1.5 ! root 858: case 1: /* 64k page. */
! 859: phys_addr = (desc & 0xffff0000) | (address & 0xffff);
! 860: ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
! 861: break;
! 862: case 2: /* 4k page. */
! 863: phys_addr = (desc & 0xfffff000) | (address & 0xfff);
! 864: ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
! 865: break;
! 866: case 3: /* 1k page. */
! 867: if (type == 1) {
! 868: if (arm_feature(env, ARM_FEATURE_XSCALE)) {
! 869: phys_addr = (desc & 0xfffff000) | (address & 0xfff);
! 870: } else {
! 871: /* Page translation fault. */
! 872: code = 7;
! 873: goto do_fault;
! 874: }
! 875: } else {
! 876: phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
! 877: }
! 878: ap = (desc >> 4) & 3;
! 879: break;
! 880: default:
! 881: /* Never happens, but compiler isn't smart enough to tell. */
! 882: abort();
1.1 root 883: }
1.1.1.5 ! root 884: code = 15;
! 885: }
! 886: *prot = check_ap(env, ap, domain, access_type, is_user);
! 887: if (!*prot) {
! 888: /* Access permission fault. */
! 889: goto do_fault;
! 890: }
! 891: *phys_ptr = phys_addr;
! 892: return 0;
! 893: do_fault:
! 894: return code | (domain << 4);
! 895: }
! 896:
! 897: static int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type,
! 898: int is_user, uint32_t *phys_ptr, int *prot)
! 899: {
! 900: int code;
! 901: uint32_t table;
! 902: uint32_t desc;
! 903: uint32_t xn;
! 904: int type;
! 905: int ap;
! 906: int domain;
! 907: uint32_t phys_addr;
! 908:
! 909: /* Pagetable walk. */
! 910: /* Lookup l1 descriptor. */
! 911: if (address & env->cp15.c2_mask)
! 912: table = env->cp15.c2_base1;
! 913: else
! 914: table = env->cp15.c2_base0;
! 915: table = (table & 0xffffc000) | ((address >> 18) & 0x3ffc);
! 916: desc = ldl_phys(table);
! 917: type = (desc & 3);
! 918: if (type == 0) {
! 919: /* Secton translation fault. */
! 920: code = 5;
! 921: domain = 0;
! 922: goto do_fault;
! 923: } else if (type == 2 && (desc & (1 << 18))) {
! 924: /* Supersection. */
! 925: domain = 0;
! 926: } else {
! 927: /* Section or page. */
! 928: domain = (desc >> 4) & 0x1e;
! 929: }
! 930: domain = (env->cp15.c3 >> domain) & 3;
! 931: if (domain == 0 || domain == 2) {
! 932: if (type == 2)
! 933: code = 9; /* Section domain fault. */
! 934: else
! 935: code = 11; /* Page domain fault. */
! 936: goto do_fault;
! 937: }
! 938: if (type == 2) {
! 939: if (desc & (1 << 18)) {
! 940: /* Supersection. */
! 941: phys_addr = (desc & 0xff000000) | (address & 0x00ffffff);
1.1 root 942: } else {
1.1.1.5 ! root 943: /* Section. */
! 944: phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
1.1 root 945: }
1.1.1.5 ! root 946: ap = ((desc >> 10) & 3) | ((desc >> 13) & 4);
! 947: xn = desc & (1 << 4);
! 948: code = 13;
! 949: } else {
! 950: /* Lookup l2 entry. */
! 951: table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
! 952: desc = ldl_phys(table);
! 953: ap = ((desc >> 4) & 3) | ((desc >> 7) & 4);
! 954: switch (desc & 3) {
! 955: case 0: /* Page translation fault. */
! 956: code = 7;
1.1 root 957: goto do_fault;
1.1.1.5 ! root 958: case 1: /* 64k page. */
! 959: phys_addr = (desc & 0xffff0000) | (address & 0xffff);
! 960: xn = desc & (1 << 15);
! 961: break;
! 962: case 2: case 3: /* 4k page. */
! 963: phys_addr = (desc & 0xfffff000) | (address & 0xfff);
! 964: xn = desc & 1;
! 965: break;
! 966: default:
! 967: /* Never happens, but compiler isn't smart enough to tell. */
! 968: abort();
1.1 root 969: }
1.1.1.5 ! root 970: code = 15;
! 971: }
! 972: if (xn && access_type == 2)
! 973: goto do_fault;
! 974:
! 975: *prot = check_ap(env, ap, domain, access_type, is_user);
! 976: if (!*prot) {
! 977: /* Access permission fault. */
! 978: goto do_fault;
1.1 root 979: }
1.1.1.5 ! root 980: *phys_ptr = phys_addr;
1.1 root 981: return 0;
982: do_fault:
983: return code | (domain << 4);
984: }
985:
1.1.1.5 ! root 986: static int get_phys_addr_mpu(CPUState *env, uint32_t address, int access_type,
! 987: int is_user, uint32_t *phys_ptr, int *prot)
! 988: {
! 989: int n;
! 990: uint32_t mask;
! 991: uint32_t base;
! 992:
! 993: *phys_ptr = address;
! 994: for (n = 7; n >= 0; n--) {
! 995: base = env->cp15.c6_region[n];
! 996: if ((base & 1) == 0)
! 997: continue;
! 998: mask = 1 << ((base >> 1) & 0x1f);
! 999: /* Keep this shift separate from the above to avoid an
! 1000: (undefined) << 32. */
! 1001: mask = (mask << 1) - 1;
! 1002: if (((base ^ address) & ~mask) == 0)
! 1003: break;
! 1004: }
! 1005: if (n < 0)
! 1006: return 2;
! 1007:
! 1008: if (access_type == 2) {
! 1009: mask = env->cp15.c5_insn;
! 1010: } else {
! 1011: mask = env->cp15.c5_data;
! 1012: }
! 1013: mask = (mask >> (n * 4)) & 0xf;
! 1014: switch (mask) {
! 1015: case 0:
! 1016: return 1;
! 1017: case 1:
! 1018: if (is_user)
! 1019: return 1;
! 1020: *prot = PAGE_READ | PAGE_WRITE;
! 1021: break;
! 1022: case 2:
! 1023: *prot = PAGE_READ;
! 1024: if (!is_user)
! 1025: *prot |= PAGE_WRITE;
! 1026: break;
! 1027: case 3:
! 1028: *prot = PAGE_READ | PAGE_WRITE;
! 1029: break;
! 1030: case 5:
! 1031: if (is_user)
! 1032: return 1;
! 1033: *prot = PAGE_READ;
! 1034: break;
! 1035: case 6:
! 1036: *prot = PAGE_READ;
! 1037: break;
! 1038: default:
! 1039: /* Bad permission. */
! 1040: return 1;
! 1041: }
! 1042: return 0;
! 1043: }
! 1044:
! 1045: static inline int get_phys_addr(CPUState *env, uint32_t address,
! 1046: int access_type, int is_user,
! 1047: uint32_t *phys_ptr, int *prot)
! 1048: {
! 1049: /* Fast Context Switch Extension. */
! 1050: if (address < 0x02000000)
! 1051: address += env->cp15.c13_fcse;
! 1052:
! 1053: if ((env->cp15.c1_sys & 1) == 0) {
! 1054: /* MMU/MPU disabled. */
! 1055: *phys_ptr = address;
! 1056: *prot = PAGE_READ | PAGE_WRITE;
! 1057: return 0;
! 1058: } else if (arm_feature(env, ARM_FEATURE_MPU)) {
! 1059: return get_phys_addr_mpu(env, address, access_type, is_user, phys_ptr,
! 1060: prot);
! 1061: } else if (env->cp15.c1_sys & (1 << 23)) {
! 1062: return get_phys_addr_v6(env, address, access_type, is_user, phys_ptr,
! 1063: prot);
! 1064: } else {
! 1065: return get_phys_addr_v5(env, address, access_type, is_user, phys_ptr,
! 1066: prot);
! 1067: }
! 1068: }
! 1069:
1.1 root 1070: int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address,
1.1.1.5 ! root 1071: int access_type, int mmu_idx, int is_softmmu)
1.1 root 1072: {
1073: uint32_t phys_addr;
1074: int prot;
1.1.1.5 ! root 1075: int ret, is_user;
1.1 root 1076:
1.1.1.5 ! root 1077: is_user = mmu_idx == MMU_USER_IDX;
1.1 root 1078: ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot);
1079: if (ret == 0) {
1080: /* Map a single [sub]page. */
1081: phys_addr &= ~(uint32_t)0x3ff;
1082: address &= ~(uint32_t)0x3ff;
1.1.1.5 ! root 1083: return tlb_set_page (env, address, phys_addr, prot, mmu_idx,
1.1 root 1084: is_softmmu);
1085: }
1086:
1087: if (access_type == 2) {
1088: env->cp15.c5_insn = ret;
1089: env->cp15.c6_insn = address;
1090: env->exception_index = EXCP_PREFETCH_ABORT;
1091: } else {
1092: env->cp15.c5_data = ret;
1.1.1.5 ! root 1093: if (access_type == 1 && arm_feature(env, ARM_FEATURE_V6))
! 1094: env->cp15.c5_data |= (1 << 11);
1.1 root 1095: env->cp15.c6_data = address;
1096: env->exception_index = EXCP_DATA_ABORT;
1097: }
1098: return 1;
1099: }
1100:
1.1.1.5 ! root 1101: target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1.1 root 1102: {
1103: uint32_t phys_addr;
1104: int prot;
1105: int ret;
1106:
1107: ret = get_phys_addr(env, addr, 0, 0, &phys_addr, &prot);
1108:
1109: if (ret != 0)
1110: return -1;
1111:
1112: return phys_addr;
1113: }
1114:
1.1.1.5 ! root 1115: /* Not really implemented. Need to figure out a sane way of doing this.
! 1116: Maybe add generic watchpoint support and use that. */
! 1117:
! 1118: void helper_mark_exclusive(CPUState *env, uint32_t addr)
! 1119: {
! 1120: env->mmon_addr = addr;
! 1121: }
! 1122:
! 1123: int helper_test_exclusive(CPUState *env, uint32_t addr)
! 1124: {
! 1125: return (env->mmon_addr != addr);
! 1126: }
! 1127:
! 1128: void helper_clrex(CPUState *env)
! 1129: {
! 1130: env->mmon_addr = -1;
! 1131: }
! 1132:
! 1133: void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val)
! 1134: {
! 1135: int cp_num = (insn >> 8) & 0xf;
! 1136: int cp_info = (insn >> 5) & 7;
! 1137: int src = (insn >> 16) & 0xf;
! 1138: int operand = insn & 0xf;
! 1139:
! 1140: if (env->cp[cp_num].cp_write)
! 1141: env->cp[cp_num].cp_write(env->cp[cp_num].opaque,
! 1142: cp_info, src, operand, val);
! 1143: }
! 1144:
! 1145: uint32_t helper_get_cp(CPUState *env, uint32_t insn)
! 1146: {
! 1147: int cp_num = (insn >> 8) & 0xf;
! 1148: int cp_info = (insn >> 5) & 7;
! 1149: int dest = (insn >> 16) & 0xf;
! 1150: int operand = insn & 0xf;
! 1151:
! 1152: if (env->cp[cp_num].cp_read)
! 1153: return env->cp[cp_num].cp_read(env->cp[cp_num].opaque,
! 1154: cp_info, dest, operand);
! 1155: return 0;
! 1156: }
! 1157:
! 1158: /* Return basic MPU access permission bits. */
! 1159: static uint32_t simple_mpu_ap_bits(uint32_t val)
! 1160: {
! 1161: uint32_t ret;
! 1162: uint32_t mask;
! 1163: int i;
! 1164: ret = 0;
! 1165: mask = 3;
! 1166: for (i = 0; i < 16; i += 2) {
! 1167: ret |= (val >> i) & mask;
! 1168: mask <<= 2;
! 1169: }
! 1170: return ret;
! 1171: }
! 1172:
! 1173: /* Pad basic MPU access permission bits to extended format. */
! 1174: static uint32_t extended_mpu_ap_bits(uint32_t val)
! 1175: {
! 1176: uint32_t ret;
! 1177: uint32_t mask;
! 1178: int i;
! 1179: ret = 0;
! 1180: mask = 3;
! 1181: for (i = 0; i < 16; i += 2) {
! 1182: ret |= (val & mask) << i;
! 1183: mask <<= 2;
! 1184: }
! 1185: return ret;
! 1186: }
! 1187:
1.1 root 1188: void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
1189: {
1.1.1.5 ! root 1190: int op1;
! 1191: int op2;
! 1192: int crm;
1.1 root 1193:
1.1.1.5 ! root 1194: op1 = (insn >> 21) & 7;
1.1 root 1195: op2 = (insn >> 5) & 7;
1.1.1.5 ! root 1196: crm = insn & 0xf;
1.1 root 1197: switch ((insn >> 16) & 0xf) {
1.1.1.5 ! root 1198: case 0:
! 1199: if (((insn >> 21) & 7) == 2) {
! 1200: /* ??? Select cache level. Ignore. */
! 1201: return;
! 1202: }
! 1203: /* ID codes. */
! 1204: if (arm_feature(env, ARM_FEATURE_XSCALE))
! 1205: break;
! 1206: if (arm_feature(env, ARM_FEATURE_OMAPCP))
! 1207: break;
1.1 root 1208: goto bad_reg;
1209: case 1: /* System configuration. */
1.1.1.5 ! root 1210: if (arm_feature(env, ARM_FEATURE_OMAPCP))
! 1211: op2 = 0;
1.1 root 1212: switch (op2) {
1213: case 0:
1.1.1.5 ! root 1214: if (!arm_feature(env, ARM_FEATURE_XSCALE) || crm == 0)
! 1215: env->cp15.c1_sys = val;
1.1 root 1216: /* ??? Lots of these bits are not implemented. */
1217: /* This may enable/disable the MMU, so do a TLB flush. */
1218: tlb_flush(env, 1);
1219: break;
1.1.1.5 ! root 1220: case 1: /* Auxiliary cotrol register. */
! 1221: if (arm_feature(env, ARM_FEATURE_XSCALE)) {
! 1222: env->cp15.c1_xscaleauxcr = val;
! 1223: break;
! 1224: }
! 1225: /* Not implemented. */
! 1226: break;
1.1 root 1227: case 2:
1.1.1.5 ! root 1228: if (arm_feature(env, ARM_FEATURE_XSCALE))
! 1229: goto bad_reg;
1.1 root 1230: env->cp15.c1_coproc = val;
1231: /* ??? Is this safe when called from within a TB? */
1232: tb_flush(env);
1.1.1.5 ! root 1233: break;
1.1 root 1234: default:
1235: goto bad_reg;
1236: }
1237: break;
1.1.1.5 ! root 1238: case 2: /* MMU Page table control / MPU cache control. */
! 1239: if (arm_feature(env, ARM_FEATURE_MPU)) {
! 1240: switch (op2) {
! 1241: case 0:
! 1242: env->cp15.c2_data = val;
! 1243: break;
! 1244: case 1:
! 1245: env->cp15.c2_insn = val;
! 1246: break;
! 1247: default:
! 1248: goto bad_reg;
! 1249: }
! 1250: } else {
! 1251: switch (op2) {
! 1252: case 0:
! 1253: env->cp15.c2_base0 = val;
! 1254: break;
! 1255: case 1:
! 1256: env->cp15.c2_base1 = val;
! 1257: break;
! 1258: case 2:
! 1259: env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> val);
! 1260: break;
! 1261: default:
! 1262: goto bad_reg;
! 1263: }
! 1264: }
1.1 root 1265: break;
1.1.1.5 ! root 1266: case 3: /* MMU Domain access control / MPU write buffer control. */
1.1 root 1267: env->cp15.c3 = val;
1.1.1.5 ! root 1268: tlb_flush(env, 1); /* Flush TLB as domain not tracked in TLB */
1.1 root 1269: break;
1270: case 4: /* Reserved. */
1271: goto bad_reg;
1.1.1.5 ! root 1272: case 5: /* MMU Fault status / MPU access permission. */
! 1273: if (arm_feature(env, ARM_FEATURE_OMAPCP))
! 1274: op2 = 0;
1.1 root 1275: switch (op2) {
1276: case 0:
1.1.1.5 ! root 1277: if (arm_feature(env, ARM_FEATURE_MPU))
! 1278: val = extended_mpu_ap_bits(val);
1.1 root 1279: env->cp15.c5_data = val;
1280: break;
1281: case 1:
1.1.1.5 ! root 1282: if (arm_feature(env, ARM_FEATURE_MPU))
! 1283: val = extended_mpu_ap_bits(val);
1.1 root 1284: env->cp15.c5_insn = val;
1285: break;
1.1.1.5 ! root 1286: case 2:
! 1287: if (!arm_feature(env, ARM_FEATURE_MPU))
! 1288: goto bad_reg;
! 1289: env->cp15.c5_data = val;
1.1 root 1290: break;
1.1.1.5 ! root 1291: case 3:
! 1292: if (!arm_feature(env, ARM_FEATURE_MPU))
! 1293: goto bad_reg;
! 1294: env->cp15.c5_insn = val;
1.1 root 1295: break;
1296: default:
1297: goto bad_reg;
1298: }
1299: break;
1.1.1.5 ! root 1300: case 6: /* MMU Fault address / MPU base/size. */
! 1301: if (arm_feature(env, ARM_FEATURE_MPU)) {
! 1302: if (crm >= 8)
! 1303: goto bad_reg;
! 1304: env->cp15.c6_region[crm] = val;
! 1305: } else {
! 1306: if (arm_feature(env, ARM_FEATURE_OMAPCP))
! 1307: op2 = 0;
! 1308: switch (op2) {
! 1309: case 0:
! 1310: env->cp15.c6_data = val;
! 1311: break;
! 1312: case 1: /* ??? This is WFAR on armv6 */
! 1313: case 2:
! 1314: env->cp15.c6_insn = val;
! 1315: break;
! 1316: default:
! 1317: goto bad_reg;
! 1318: }
! 1319: }
! 1320: break;
1.1 root 1321: case 7: /* Cache control. */
1.1.1.5 ! root 1322: env->cp15.c15_i_max = 0x000;
! 1323: env->cp15.c15_i_min = 0xff0;
1.1 root 1324: /* No cache, so nothing to do. */
1.1.1.5 ! root 1325: /* ??? MPCore has VA to PA translation functions. */
1.1 root 1326: break;
1327: case 8: /* MMU TLB control. */
1328: switch (op2) {
1329: case 0: /* Invalidate all. */
1330: tlb_flush(env, 0);
1331: break;
1332: case 1: /* Invalidate single TLB entry. */
1333: #if 0
1334: /* ??? This is wrong for large pages and sections. */
1335: /* As an ugly hack to make linux work we always flush a 4K
1336: pages. */
1337: val &= 0xfffff000;
1338: tlb_flush_page(env, val);
1339: tlb_flush_page(env, val + 0x400);
1340: tlb_flush_page(env, val + 0x800);
1341: tlb_flush_page(env, val + 0xc00);
1342: #else
1343: tlb_flush(env, 1);
1344: #endif
1345: break;
1.1.1.5 ! root 1346: case 2: /* Invalidate on ASID. */
! 1347: tlb_flush(env, val == 0);
! 1348: break;
! 1349: case 3: /* Invalidate single entry on MVA. */
! 1350: /* ??? This is like case 1, but ignores ASID. */
! 1351: tlb_flush(env, 1);
! 1352: break;
1.1 root 1353: default:
1354: goto bad_reg;
1355: }
1356: break;
1.1.1.5 ! root 1357: case 9:
! 1358: if (arm_feature(env, ARM_FEATURE_OMAPCP))
1.1 root 1359: break;
1.1.1.5 ! root 1360: switch (crm) {
! 1361: case 0: /* Cache lockdown. */
! 1362: switch (op1) {
! 1363: case 0: /* L1 cache. */
! 1364: switch (op2) {
! 1365: case 0:
! 1366: env->cp15.c9_data = val;
! 1367: break;
! 1368: case 1:
! 1369: env->cp15.c9_insn = val;
! 1370: break;
! 1371: default:
! 1372: goto bad_reg;
! 1373: }
! 1374: break;
! 1375: case 1: /* L2 cache. */
! 1376: /* Ignore writes to L2 lockdown/auxiliary registers. */
! 1377: break;
! 1378: default:
! 1379: goto bad_reg;
! 1380: }
! 1381: break;
! 1382: case 1: /* TCM memory region registers. */
! 1383: /* Not implemented. */
! 1384: goto bad_reg;
1.1 root 1385: default:
1386: goto bad_reg;
1387: }
1388: break;
1389: case 10: /* MMU TLB lockdown. */
1390: /* ??? TLB lockdown not implemented. */
1391: break;
1392: case 12: /* Reserved. */
1393: goto bad_reg;
1394: case 13: /* Process ID. */
1395: switch (op2) {
1396: case 0:
1.1.1.3 root 1397: /* Unlike real hardware the qemu TLB uses virtual addresses,
1398: not modified virtual addresses, so this causes a TLB flush.
1399: */
1400: if (env->cp15.c13_fcse != val)
1401: tlb_flush(env, 1);
1402: env->cp15.c13_fcse = val;
1.1 root 1403: break;
1404: case 1:
1.1.1.3 root 1405: /* This changes the ASID, so do a TLB flush. */
1.1.1.5 ! root 1406: if (env->cp15.c13_context != val
! 1407: && !arm_feature(env, ARM_FEATURE_MPU))
1.1.1.3 root 1408: tlb_flush(env, 0);
1409: env->cp15.c13_context = val;
1.1 root 1410: break;
1.1.1.5 ! root 1411: case 2:
! 1412: env->cp15.c13_tls1 = val;
! 1413: break;
! 1414: case 3:
! 1415: env->cp15.c13_tls2 = val;
! 1416: break;
! 1417: case 4:
! 1418: env->cp15.c13_tls3 = val;
! 1419: break;
1.1 root 1420: default:
1421: goto bad_reg;
1422: }
1423: break;
1424: case 14: /* Reserved. */
1425: goto bad_reg;
1426: case 15: /* Implementation specific. */
1.1.1.5 ! root 1427: if (arm_feature(env, ARM_FEATURE_XSCALE)) {
! 1428: if (op2 == 0 && crm == 1) {
! 1429: if (env->cp15.c15_cpar != (val & 0x3fff)) {
! 1430: /* Changes cp0 to cp13 behavior, so needs a TB flush. */
! 1431: tb_flush(env);
! 1432: env->cp15.c15_cpar = val & 0x3fff;
! 1433: }
! 1434: break;
! 1435: }
! 1436: goto bad_reg;
! 1437: }
! 1438: if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
! 1439: switch (crm) {
! 1440: case 0:
! 1441: break;
! 1442: case 1: /* Set TI925T configuration. */
! 1443: env->cp15.c15_ticonfig = val & 0xe7;
! 1444: env->cp15.c0_cpuid = (val & (1 << 5)) ? /* OS_TYPE bit */
! 1445: ARM_CPUID_TI915T : ARM_CPUID_TI925T;
! 1446: break;
! 1447: case 2: /* Set I_max. */
! 1448: env->cp15.c15_i_max = val;
! 1449: break;
! 1450: case 3: /* Set I_min. */
! 1451: env->cp15.c15_i_min = val;
! 1452: break;
! 1453: case 4: /* Set thread-ID. */
! 1454: env->cp15.c15_threadid = val & 0xffff;
! 1455: break;
! 1456: case 8: /* Wait-for-interrupt (deprecated). */
! 1457: cpu_interrupt(env, CPU_INTERRUPT_HALT);
! 1458: break;
! 1459: default:
! 1460: goto bad_reg;
! 1461: }
! 1462: }
1.1 root 1463: break;
1464: }
1465: return;
1466: bad_reg:
1467: /* ??? For debugging only. Should raise illegal instruction exception. */
1.1.1.5 ! root 1468: cpu_abort(env, "Unimplemented cp15 register write (c%d, c%d, {%d, %d})\n",
! 1469: (insn >> 16) & 0xf, crm, op1, op2);
1.1 root 1470: }
1471:
1472: uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
1473: {
1.1.1.5 ! root 1474: int op1;
! 1475: int op2;
! 1476: int crm;
1.1 root 1477:
1.1.1.5 ! root 1478: op1 = (insn >> 21) & 7;
1.1 root 1479: op2 = (insn >> 5) & 7;
1.1.1.5 ! root 1480: crm = insn & 0xf;
1.1 root 1481: switch ((insn >> 16) & 0xf) {
1482: case 0: /* ID codes. */
1.1.1.5 ! root 1483: switch (op1) {
! 1484: case 0:
! 1485: switch (crm) {
! 1486: case 0:
! 1487: switch (op2) {
! 1488: case 0: /* Device ID. */
! 1489: return env->cp15.c0_cpuid;
! 1490: case 1: /* Cache Type. */
! 1491: return env->cp15.c0_cachetype;
! 1492: case 2: /* TCM status. */
! 1493: return 0;
! 1494: case 3: /* TLB type register. */
! 1495: return 0; /* No lockable TLB entries. */
! 1496: case 5: /* CPU ID */
! 1497: return env->cpu_index;
! 1498: default:
! 1499: goto bad_reg;
! 1500: }
! 1501: case 1:
! 1502: if (!arm_feature(env, ARM_FEATURE_V6))
! 1503: goto bad_reg;
! 1504: return env->cp15.c0_c1[op2];
! 1505: case 2:
! 1506: if (!arm_feature(env, ARM_FEATURE_V6))
! 1507: goto bad_reg;
! 1508: return env->cp15.c0_c2[op2];
! 1509: case 3: case 4: case 5: case 6: case 7:
! 1510: return 0;
! 1511: default:
! 1512: goto bad_reg;
! 1513: }
! 1514: case 1:
! 1515: /* These registers aren't documented on arm11 cores. However
! 1516: Linux looks at them anyway. */
! 1517: if (!arm_feature(env, ARM_FEATURE_V6))
! 1518: goto bad_reg;
! 1519: if (crm != 0)
! 1520: goto bad_reg;
! 1521: if (arm_feature(env, ARM_FEATURE_XSCALE))
! 1522: goto bad_reg;
1.1 root 1523: return 0;
1.1.1.5 ! root 1524: default:
! 1525: goto bad_reg;
1.1 root 1526: }
1527: case 1: /* System configuration. */
1.1.1.5 ! root 1528: if (arm_feature(env, ARM_FEATURE_OMAPCP))
! 1529: op2 = 0;
1.1 root 1530: switch (op2) {
1531: case 0: /* Control register. */
1532: return env->cp15.c1_sys;
1533: case 1: /* Auxiliary control register. */
1.1.1.5 ! root 1534: if (arm_feature(env, ARM_FEATURE_XSCALE))
! 1535: return env->cp15.c1_xscaleauxcr;
! 1536: if (!arm_feature(env, ARM_FEATURE_AUXCR))
! 1537: goto bad_reg;
! 1538: switch (ARM_CPUID(env)) {
! 1539: case ARM_CPUID_ARM1026:
1.1.1.2 root 1540: return 1;
1.1.1.5 ! root 1541: case ARM_CPUID_ARM1136:
! 1542: return 7;
! 1543: case ARM_CPUID_ARM11MPCORE:
! 1544: return 1;
! 1545: case ARM_CPUID_CORTEXA8:
! 1546: return 0;
! 1547: default:
! 1548: goto bad_reg;
! 1549: }
1.1 root 1550: case 2: /* Coprocessor access register. */
1.1.1.5 ! root 1551: if (arm_feature(env, ARM_FEATURE_XSCALE))
! 1552: goto bad_reg;
1.1 root 1553: return env->cp15.c1_coproc;
1554: default:
1555: goto bad_reg;
1556: }
1.1.1.5 ! root 1557: case 2: /* MMU Page table control / MPU cache control. */
! 1558: if (arm_feature(env, ARM_FEATURE_MPU)) {
! 1559: switch (op2) {
! 1560: case 0:
! 1561: return env->cp15.c2_data;
! 1562: break;
! 1563: case 1:
! 1564: return env->cp15.c2_insn;
! 1565: break;
! 1566: default:
! 1567: goto bad_reg;
! 1568: }
! 1569: } else {
! 1570: switch (op2) {
! 1571: case 0:
! 1572: return env->cp15.c2_base0;
! 1573: case 1:
! 1574: return env->cp15.c2_base1;
! 1575: case 2:
! 1576: {
! 1577: int n;
! 1578: uint32_t mask;
! 1579: n = 0;
! 1580: mask = env->cp15.c2_mask;
! 1581: while (mask) {
! 1582: n++;
! 1583: mask <<= 1;
! 1584: }
! 1585: return n;
! 1586: }
! 1587: default:
! 1588: goto bad_reg;
! 1589: }
! 1590: }
! 1591: case 3: /* MMU Domain access control / MPU write buffer control. */
1.1 root 1592: return env->cp15.c3;
1593: case 4: /* Reserved. */
1594: goto bad_reg;
1.1.1.5 ! root 1595: case 5: /* MMU Fault status / MPU access permission. */
! 1596: if (arm_feature(env, ARM_FEATURE_OMAPCP))
! 1597: op2 = 0;
1.1 root 1598: switch (op2) {
1599: case 0:
1.1.1.5 ! root 1600: if (arm_feature(env, ARM_FEATURE_MPU))
! 1601: return simple_mpu_ap_bits(env->cp15.c5_data);
1.1 root 1602: return env->cp15.c5_data;
1603: case 1:
1.1.1.5 ! root 1604: if (arm_feature(env, ARM_FEATURE_MPU))
! 1605: return simple_mpu_ap_bits(env->cp15.c5_data);
! 1606: return env->cp15.c5_insn;
! 1607: case 2:
! 1608: if (!arm_feature(env, ARM_FEATURE_MPU))
! 1609: goto bad_reg;
! 1610: return env->cp15.c5_data;
! 1611: case 3:
! 1612: if (!arm_feature(env, ARM_FEATURE_MPU))
! 1613: goto bad_reg;
1.1 root 1614: return env->cp15.c5_insn;
1615: default:
1616: goto bad_reg;
1617: }
1618: case 6: /* MMU Fault address. */
1.1.1.5 ! root 1619: if (arm_feature(env, ARM_FEATURE_MPU)) {
! 1620: if (crm >= 8)
! 1621: goto bad_reg;
! 1622: return env->cp15.c6_region[crm];
! 1623: } else {
! 1624: if (arm_feature(env, ARM_FEATURE_OMAPCP))
! 1625: op2 = 0;
! 1626: switch (op2) {
! 1627: case 0:
! 1628: return env->cp15.c6_data;
! 1629: case 1:
! 1630: if (arm_feature(env, ARM_FEATURE_V6)) {
! 1631: /* Watchpoint Fault Adrress. */
! 1632: return 0; /* Not implemented. */
! 1633: } else {
! 1634: /* Instruction Fault Adrress. */
! 1635: /* Arm9 doesn't have an IFAR, but implementing it anyway
! 1636: shouldn't do any harm. */
! 1637: return env->cp15.c6_insn;
! 1638: }
! 1639: case 2:
! 1640: if (arm_feature(env, ARM_FEATURE_V6)) {
! 1641: /* Instruction Fault Adrress. */
! 1642: return env->cp15.c6_insn;
! 1643: } else {
! 1644: goto bad_reg;
! 1645: }
! 1646: default:
! 1647: goto bad_reg;
! 1648: }
1.1 root 1649: }
1650: case 7: /* Cache control. */
1651: /* ??? This is for test, clean and invaidate operations that set the
1.1.1.5 ! root 1652: Z flag. We can't represent N = Z = 1, so it also clears
1.1 root 1653: the N flag. Oh well. */
1654: env->NZF = 0;
1655: return 0;
1656: case 8: /* MMU TLB control. */
1657: goto bad_reg;
1658: case 9: /* Cache lockdown. */
1.1.1.5 ! root 1659: switch (op1) {
! 1660: case 0: /* L1 cache. */
! 1661: if (arm_feature(env, ARM_FEATURE_OMAPCP))
! 1662: return 0;
! 1663: switch (op2) {
! 1664: case 0:
! 1665: return env->cp15.c9_data;
! 1666: case 1:
! 1667: return env->cp15.c9_insn;
! 1668: default:
! 1669: goto bad_reg;
! 1670: }
! 1671: case 1: /* L2 cache */
! 1672: if (crm != 0)
! 1673: goto bad_reg;
! 1674: /* L2 Lockdown and Auxiliary control. */
! 1675: return 0;
1.1 root 1676: default:
1677: goto bad_reg;
1678: }
1679: case 10: /* MMU TLB lockdown. */
1680: /* ??? TLB lockdown not implemented. */
1681: return 0;
1682: case 11: /* TCM DMA control. */
1683: case 12: /* Reserved. */
1684: goto bad_reg;
1685: case 13: /* Process ID. */
1686: switch (op2) {
1687: case 0:
1688: return env->cp15.c13_fcse;
1689: case 1:
1690: return env->cp15.c13_context;
1.1.1.5 ! root 1691: case 2:
! 1692: return env->cp15.c13_tls1;
! 1693: case 3:
! 1694: return env->cp15.c13_tls2;
! 1695: case 4:
! 1696: return env->cp15.c13_tls3;
1.1 root 1697: default:
1698: goto bad_reg;
1699: }
1700: case 14: /* Reserved. */
1701: goto bad_reg;
1702: case 15: /* Implementation specific. */
1.1.1.5 ! root 1703: if (arm_feature(env, ARM_FEATURE_XSCALE)) {
! 1704: if (op2 == 0 && crm == 1)
! 1705: return env->cp15.c15_cpar;
! 1706:
! 1707: goto bad_reg;
! 1708: }
! 1709: if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
! 1710: switch (crm) {
! 1711: case 0:
! 1712: return 0;
! 1713: case 1: /* Read TI925T configuration. */
! 1714: return env->cp15.c15_ticonfig;
! 1715: case 2: /* Read I_max. */
! 1716: return env->cp15.c15_i_max;
! 1717: case 3: /* Read I_min. */
! 1718: return env->cp15.c15_i_min;
! 1719: case 4: /* Read thread-ID. */
! 1720: return env->cp15.c15_threadid;
! 1721: case 8: /* TI925T_status */
! 1722: return 0;
! 1723: }
! 1724: goto bad_reg;
! 1725: }
1.1 root 1726: return 0;
1727: }
1728: bad_reg:
1729: /* ??? For debugging only. Should raise illegal instruction exception. */
1.1.1.5 ! root 1730: cpu_abort(env, "Unimplemented cp15 register read (c%d, c%d, {%d, %d})\n",
! 1731: (insn >> 16) & 0xf, crm, op1, op2);
1.1 root 1732: return 0;
1733: }
1734:
1.1.1.5 ! root 1735: void helper_set_r13_banked(CPUState *env, int mode, uint32_t val)
! 1736: {
! 1737: env->banked_r13[bank_number(mode)] = val;
! 1738: }
! 1739:
! 1740: uint32_t helper_get_r13_banked(CPUState *env, int mode)
! 1741: {
! 1742: return env->banked_r13[bank_number(mode)];
! 1743: }
! 1744:
! 1745: uint32_t helper_v7m_mrs(CPUState *env, int reg)
! 1746: {
! 1747: switch (reg) {
! 1748: case 0: /* APSR */
! 1749: return xpsr_read(env) & 0xf8000000;
! 1750: case 1: /* IAPSR */
! 1751: return xpsr_read(env) & 0xf80001ff;
! 1752: case 2: /* EAPSR */
! 1753: return xpsr_read(env) & 0xff00fc00;
! 1754: case 3: /* xPSR */
! 1755: return xpsr_read(env) & 0xff00fdff;
! 1756: case 5: /* IPSR */
! 1757: return xpsr_read(env) & 0x000001ff;
! 1758: case 6: /* EPSR */
! 1759: return xpsr_read(env) & 0x0700fc00;
! 1760: case 7: /* IEPSR */
! 1761: return xpsr_read(env) & 0x0700edff;
! 1762: case 8: /* MSP */
! 1763: return env->v7m.current_sp ? env->v7m.other_sp : env->regs[13];
! 1764: case 9: /* PSP */
! 1765: return env->v7m.current_sp ? env->regs[13] : env->v7m.other_sp;
! 1766: case 16: /* PRIMASK */
! 1767: return (env->uncached_cpsr & CPSR_I) != 0;
! 1768: case 17: /* FAULTMASK */
! 1769: return (env->uncached_cpsr & CPSR_F) != 0;
! 1770: case 18: /* BASEPRI */
! 1771: case 19: /* BASEPRI_MAX */
! 1772: return env->v7m.basepri;
! 1773: case 20: /* CONTROL */
! 1774: return env->v7m.control;
! 1775: default:
! 1776: /* ??? For debugging only. */
! 1777: cpu_abort(env, "Unimplemented system register read (%d)\n", reg);
! 1778: return 0;
! 1779: }
! 1780: }
! 1781:
! 1782: void helper_v7m_msr(CPUState *env, int reg, uint32_t val)
! 1783: {
! 1784: switch (reg) {
! 1785: case 0: /* APSR */
! 1786: xpsr_write(env, val, 0xf8000000);
! 1787: break;
! 1788: case 1: /* IAPSR */
! 1789: xpsr_write(env, val, 0xf8000000);
! 1790: break;
! 1791: case 2: /* EAPSR */
! 1792: xpsr_write(env, val, 0xfe00fc00);
! 1793: break;
! 1794: case 3: /* xPSR */
! 1795: xpsr_write(env, val, 0xfe00fc00);
! 1796: break;
! 1797: case 5: /* IPSR */
! 1798: /* IPSR bits are readonly. */
! 1799: break;
! 1800: case 6: /* EPSR */
! 1801: xpsr_write(env, val, 0x0600fc00);
! 1802: break;
! 1803: case 7: /* IEPSR */
! 1804: xpsr_write(env, val, 0x0600fc00);
! 1805: break;
! 1806: case 8: /* MSP */
! 1807: if (env->v7m.current_sp)
! 1808: env->v7m.other_sp = val;
! 1809: else
! 1810: env->regs[13] = val;
! 1811: break;
! 1812: case 9: /* PSP */
! 1813: if (env->v7m.current_sp)
! 1814: env->regs[13] = val;
! 1815: else
! 1816: env->v7m.other_sp = val;
! 1817: break;
! 1818: case 16: /* PRIMASK */
! 1819: if (val & 1)
! 1820: env->uncached_cpsr |= CPSR_I;
! 1821: else
! 1822: env->uncached_cpsr &= ~CPSR_I;
! 1823: break;
! 1824: case 17: /* FAULTMASK */
! 1825: if (val & 1)
! 1826: env->uncached_cpsr |= CPSR_F;
! 1827: else
! 1828: env->uncached_cpsr &= ~CPSR_F;
! 1829: break;
! 1830: case 18: /* BASEPRI */
! 1831: env->v7m.basepri = val & 0xff;
! 1832: break;
! 1833: case 19: /* BASEPRI_MAX */
! 1834: val &= 0xff;
! 1835: if (val != 0 && (val < env->v7m.basepri || env->v7m.basepri == 0))
! 1836: env->v7m.basepri = val;
! 1837: break;
! 1838: case 20: /* CONTROL */
! 1839: env->v7m.control = val & 3;
! 1840: switch_v7m_sp(env, (val & 2) != 0);
! 1841: break;
! 1842: default:
! 1843: /* ??? For debugging only. */
! 1844: cpu_abort(env, "Unimplemented system register write (%d)\n", reg);
! 1845: return;
! 1846: }
! 1847: }
! 1848:
! 1849: void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
! 1850: ARMReadCPFunc *cp_read, ARMWriteCPFunc *cp_write,
! 1851: void *opaque)
! 1852: {
! 1853: if (cpnum < 0 || cpnum > 14) {
! 1854: cpu_abort(env, "Bad coprocessor number: %i\n", cpnum);
! 1855: return;
! 1856: }
! 1857:
! 1858: env->cp[cpnum].cp_read = cp_read;
! 1859: env->cp[cpnum].cp_write = cp_write;
! 1860: env->cp[cpnum].opaque = opaque;
! 1861: }
! 1862:
1.1 root 1863: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.