Annotation of qemu/target-arm/helper.c, revision 1.1.1.7

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.