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

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

unix.superglobalmegacorp.com

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