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