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

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

unix.superglobalmegacorp.com

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