18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdio.h>
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h>
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <string.h>
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "cpu.h"
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "exec-all.h"
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "gdbstub.h"
85285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#include "helper.h"
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu-common.h"
105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#include "host-utils.h"
115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#if !defined(CONFIG_USER_ONLY)
125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner//#include "hw/loader.h"
13ab42ada6ecfb81d6e231d5997b5892efd0fde5adJack Veenstra#ifdef CONFIG_TRACE
14406a59bd0a2e7a38cd840a5c08602e3a36bd2df8David 'Digit' Turner#include "android-trace.h"
15ab42ada6ecfb81d6e231d5997b5892efd0fde5adJack Veenstra#endif
165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#endif
175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
185285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic uint32_t cortexa9_cp15_c0_c1[8] =
195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 0x1031, 0x11, 0x000, 0, 0x00100103, 0x20000000, 0x01230000, 0x00002111 };
205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
215285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic uint32_t cortexa9_cp15_c0_c2[8] =
225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 0x00101111, 0x13112111, 0x21232041, 0x11112131, 0x00111142, 0, 0, 0 };
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t cortexa8_cp15_c0_c1[8] =
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 0x1031, 0x11, 0x400, 0, 0x31100003, 0x20000000, 0x01202000, 0x11 };
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t cortexa8_cp15_c0_c2[8] =
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 0x00101111, 0x12112111, 0x21232031, 0x11112131, 0x00111142, 0, 0, 0 };
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
305285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic uint32_t cortexa8r2_cp15_c0_c2[8] =
315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 0x00101111, 0x12112111, 0x21232031, 0x11112131, 0x00011142, 0, 0, 0 };
325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t mpcore_cp15_c0_c1[8] =
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 0x111, 0x1, 0, 0x2, 0x01100103, 0x10020302, 0x01222000, 0 };
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t mpcore_cp15_c0_c2[8] =
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 0x00100011, 0x12002111, 0x11221011, 0x01102131, 0x141, 0, 0, 0 };
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t arm1136_cp15_c0_c1[8] =
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 0x111, 0x1, 0x2, 0x3, 0x01130003, 0x10030302, 0x01222110, 0 };
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t arm1136_cp15_c0_c2[8] =
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 0x00140011, 0x12002111, 0x11231111, 0x01102131, 0x141, 0, 0, 0 };
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t cpu_arm_find_by_name(const char *name);
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void set_feature(CPUARMState *env, int feature)
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->features |= 1u << feature;
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void cpu_reset_model_id(CPUARMState *env, uint32_t id)
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cp15.c0_cpuid = id;
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (id) {
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_ARM926:
575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V4T);
585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V5);
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_VFP);
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c0_cachetype = 0x1dd20d2;
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c1_sys = 0x00090078;
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_ARM946:
655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V4T);
665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V5);
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_MPU);
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c0_cachetype = 0x0f004006;
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c1_sys = 0x00000078;
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_ARM1026:
725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V4T);
735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V5);
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_VFP);
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_AUXCR);
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0;
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c0_cachetype = 0x1dd20d2;
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c1_sys = 0x00090078;
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_ARM1136_R2:
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_ARM1136:
825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V4T);
835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V5);
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_V6);
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_VFP);
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_AUXCR);
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b4;
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111;
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->vfp.xregs[ARM_VFP_MVFR1] = 0x00000000;
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(env->cp15.c0_c1, arm1136_cp15_c0_c1, 8 * sizeof(uint32_t));
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(env->cp15.c0_c2, arm1136_cp15_c0_c2, 8 * sizeof(uint32_t));
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c0_cachetype = 0x1dd20d2;
935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->cp15.c1_sys = 0x00050078;
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_ARM11MPCORE:
965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V4T);
975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V5);
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_V6);
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_V6K);
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_VFP);
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_AUXCR);
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b4;
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111;
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->vfp.xregs[ARM_VFP_MVFR1] = 0x00000000;
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(env->cp15.c0_c1, mpcore_cp15_c0_c1, 8 * sizeof(uint32_t));
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(env->cp15.c0_c2, mpcore_cp15_c0_c2, 8 * sizeof(uint32_t));
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c0_cachetype = 0x1dd20d2;
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_CORTEXA8:
1105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V4T);
1115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V5);
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_V6);
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_V6K);
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_V7);
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_AUXCR);
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_THUMB2);
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_VFP);
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_VFP3);
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_NEON);
1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        set_feature(env, ARM_FEATURE_THUMB2EE);
1215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_TRUSTZONE);
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->vfp.xregs[ARM_VFP_FPSID] = 0x410330c0;
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->vfp.xregs[ARM_VFP_MVFR0] = 0x11110222;
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->vfp.xregs[ARM_VFP_MVFR1] = 0x00011100;
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(env->cp15.c0_c1, cortexa8_cp15_c0_c1, 8 * sizeof(uint32_t));
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(env->cp15.c0_c2, cortexa8_cp15_c0_c2, 8 * sizeof(uint32_t));
1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        env->cp15.c0_cachetype = 0x82048004;
1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        env->cp15.c0_clid = (1 << 27) | (2 << 24) | 3;
1295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        env->cp15.c0_ccsid[0] = 0xe007e01a; /* 16k L1 dcache. */
1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        env->cp15.c0_ccsid[1] = 0x2007e01a; /* 16k L1 icache. */
1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        env->cp15.c0_ccsid[2] = 0xf0000000; /* No L2 icache. */
1325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->cp15.c1_sys = 0x00c50078;
1335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
1345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case ARM_CPUID_CORTEXA8_R2:
1355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V4T);
1365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V5);
1375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V6);
1385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V6K);
1395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V7);
1405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_AUXCR);
1415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_THUMB2);
1425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_VFP);
1435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_VFP3);
1445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_NEON);
1455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_THUMB2EE);
1465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_TRUSTZONE);
1475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->vfp.xregs[ARM_VFP_FPSID] = 0x410330c2;
1485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->vfp.xregs[ARM_VFP_MVFR0] = 0x11110222;
1495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->vfp.xregs[ARM_VFP_MVFR1] = 0x00011111;
1505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        memcpy(env->cp15.c0_c1, cortexa8_cp15_c0_c1, 8 * sizeof(uint32_t));
1515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        memcpy(env->cp15.c0_c2, cortexa8r2_cp15_c0_c2, 8 * sizeof(uint32_t));
1525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->cp15.c0_cachetype = 0x82048004;
1535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->cp15.c0_clid = (1 << 27) | (2 << 24) | (4 << 3) | 3;
1545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->cp15.c0_ccsid[0] = 0xe007e01a; /* 16k L1 dcache. */
1555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->cp15.c0_ccsid[1] = 0x2007e01a; /* 16k L1 icache. */
1565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->cp15.c0_ccsid[2] = 0xf03fe03a; /* 256k L2 cache. */
1575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->cp15.c1_sys = 0x00c50078;
1585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
1595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case ARM_CPUID_CORTEXA9:
1605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V4T);
1615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V5);
1625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V6);
1635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V6K);
1645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V7);
1655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_AUXCR);
1665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_THUMB2);
1675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_VFP);
1685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_VFP3);
1695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_VFP_FP16);
1705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_NEON);
1715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_THUMB2EE);
1725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* Note that A9 supports the MP extensions even for
1735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         * A9UP and single-core A9MP (which are both different
1745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         * and valid configurations; we don't model A9UP).
1755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         */
1765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V7MP);
1775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_TRUSTZONE);
1785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->vfp.xregs[ARM_VFP_FPSID] = 0x41034000; /* Guess */
1795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->vfp.xregs[ARM_VFP_MVFR0] = 0x11110222;
1805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->vfp.xregs[ARM_VFP_MVFR1] = 0x01111111;
1815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        memcpy(env->cp15.c0_c1, cortexa9_cp15_c0_c1, 8 * sizeof(uint32_t));
1825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        memcpy(env->cp15.c0_c2, cortexa9_cp15_c0_c2, 8 * sizeof(uint32_t));
1835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->cp15.c0_cachetype = 0x80038003;
1845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->cp15.c0_clid = (1 << 27) | (1 << 24) | 3;
1855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->cp15.c0_ccsid[0] = 0xe00fe015; /* 16k L1 dcache. */
1865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->cp15.c0_ccsid[1] = 0x200fe015; /* 16k L1 icache. */
1875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->cp15.c1_sys = 0x00c50078;
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_CORTEXM3:
1905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V4T);
1915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V5);
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_V6);
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_THUMB2);
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_V7);
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_M);
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_DIV);
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_ANY: /* For userspace emulation.  */
1995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V4T);
2005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V5);
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_V6);
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_V6K);
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_V7);
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_THUMB2);
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_VFP);
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_VFP3);
2075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_VFP_FP16);
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_NEON);
2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        set_feature(env, ARM_FEATURE_THUMB2EE);
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_DIV);
2115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V7MP);
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_TI915T:
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_TI925T:
2155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V4T);
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_OMAPCP);
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c0_cpuid = ARM_CPUID_TI925T; /* Depends on wiring.  */
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c0_cachetype = 0x5109149;
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c1_sys = 0x00000070;
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c15_i_max = 0x000;
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c15_i_min = 0xff0;
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_PXA250:
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_PXA255:
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_PXA260:
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_PXA261:
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_PXA262:
2285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V4T);
2295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V5);
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_XSCALE);
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* JTAG_ID is ((id << 28) | 0x09265013) */
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c0_cachetype = 0xd172172;
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c1_sys = 0x00000078;
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_PXA270_A0:
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_PXA270_A1:
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_PXA270_B0:
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_PXA270_B1:
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_PXA270_C0:
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPUID_PXA270_C5:
2415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V4T);
2425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_V5);
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_XSCALE);
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* JTAG_ID is ((id << 28) | 0x09265013) */
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_feature(env, ARM_FEATURE_IWMMXT);
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q';
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c0_cachetype = 0xd172172;
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c1_sys = 0x00000078;
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case ARM_CPUID_SA1100:
2515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case ARM_CPUID_SA1110:
2525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_feature(env, ARM_FEATURE_STRONGARM);
2535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->cp15.c1_sys = 0x00000070;
2545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_abort(env, "Bad CPU ID: %x\n", id);
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_reset(CPUARMState *env)
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t id;
2645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
2665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
2675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        log_cpu_state(env, 0);
2685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
2695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    id = env->cp15.c0_cpuid;
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memset(env, 0, offsetof(CPUARMState, breakpoints));
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (id)
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_reset_model_id(env, id);
2745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* DBGDIDR : we implement nothing, and just mirror the main ID
2755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * register's Variant and Revision fields.
2765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     */
2775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    env->cp14_dbgdidr = (id >> 16 & 0xf0) | 0xf;
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined (CONFIG_USER_ONLY)
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->uncached_cpsr = ARM_CPU_MODE_USR;
2805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* For user mode we must enable access to coprocessors */
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30;
2825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
2835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->cp15.c15_cpar = 3;
2845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
2855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->cp15.c15_cpar = 1;
2865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* SVC mode with interrupts disabled.  */
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* On ARMv7-M the CPSR_I is the value of the PRIMASK register, and is
2915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner       clear at reset.  Initial SP and PC are loaded from ROM.  */
2925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (IS_M(env)) {
2935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        uint32_t pc;
2945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        uint8_t *rom;
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->uncached_cpsr &= ~CPSR_I;
2965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#ifndef CONFIG_ANDROID  /* No hw/loader.h and no ROM support for now on Android */
2975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        rom = rom_ptr(0);
2985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (rom) {
2995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* We should really use ldl_phys here, in case the guest
3005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner               modified flash and reset itself.  However images
3015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner               loaded via -kenrel have not been copied yet, so load the
3025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner               values directly from there.  */
3035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            env->regs[13] = ldl_p(rom);
3045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            pc = ldl_p(rom + 4);
3055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            env->thumb = pc & 1;
3065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            env->regs[15] = pc & ~1;
3075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
3085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#endif
3095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->vfp.xregs[ARM_VFP_FPEXC] = 0;
3115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    env->cp15.c2_base_mask = 0xffffc000u;
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    set_flush_to_zero(1, &env->vfp.standard_fp_status);
3145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status);
3155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    set_default_nan_mode(1, &env->vfp.standard_fp_status);
3165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    set_float_detect_tininess(float_tininess_before_rounding,
3175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                              &env->vfp.fp_status);
3185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    set_float_detect_tininess(float_tininess_before_rounding,
3195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                              &env->vfp.standard_fp_status);
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tlb_flush(env, 1);
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int vfp_gdb_get_reg(CPUState *env, uint8_t *buf, int reg)
3245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
3255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int nregs;
3265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* VFP data registers are always little-endian.  */
3285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (reg < nregs) {
3305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        stfq_le_p(buf, env->vfp.regs[reg]);
3315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 8;
3325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
3335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (arm_feature(env, ARM_FEATURE_NEON)) {
3345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Aliases for Q regs.  */
3355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        nregs += 16;
3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (reg < nregs) {
3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            stfq_le_p(buf, env->vfp.regs[(reg - 32) * 2]);
3385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            stfq_le_p(buf + 8, env->vfp.regs[(reg - 32) * 2 + 1]);
3395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 16;
3405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
3415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
3425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch (reg - nregs) {
3435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 0: stl_p(buf, env->vfp.xregs[ARM_VFP_FPSID]); return 4;
3445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 1: stl_p(buf, env->vfp.xregs[ARM_VFP_FPSCR]); return 4;
3455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 2: stl_p(buf, env->vfp.xregs[ARM_VFP_FPEXC]); return 4;
3465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
3475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
3485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int vfp_gdb_set_reg(CPUState *env, uint8_t *buf, int reg)
3515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
3525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int nregs;
3535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
3555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (reg < nregs) {
3565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        env->vfp.regs[reg] = ldfq_le_p(buf);
3575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 8;
3585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
3595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (arm_feature(env, ARM_FEATURE_NEON)) {
3605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        nregs += 16;
3615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (reg < nregs) {
3625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            env->vfp.regs[(reg - 32) * 2] = ldfq_le_p(buf);
3635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            env->vfp.regs[(reg - 32) * 2 + 1] = ldfq_le_p(buf + 8);
3645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 16;
3655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
3665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
3675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch (reg - nregs) {
3685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 0: env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf); return 4;
3695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 1: env->vfp.xregs[ARM_VFP_FPSCR] = ldl_p(buf); return 4;
3705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 2: env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30); return 4;
3715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
3725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
3735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectCPUARMState *cpu_arm_init(const char *cpu_model)
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CPUARMState *env;
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t id;
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static int inited = 0;
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    id = cpu_arm_find_by_name(cpu_model);
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (id == 0)
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = qemu_mallocz(sizeof(CPUARMState));
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_exec_init(env);
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!inited) {
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        inited = 1;
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        arm_translate_init();
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cpu_model_str = cpu_model;
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cp15.c0_cpuid = id;
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_reset(env);
3945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (arm_feature(env, ARM_FEATURE_NEON)) {
3955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg,
3965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                 51, "arm-neon.xml", 0);
3975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (arm_feature(env, ARM_FEATURE_VFP3)) {
3985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg,
3995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                 35, "arm-vfp3.xml", 0);
4005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (arm_feature(env, ARM_FEATURE_VFP)) {
4015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg,
4025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                 19, "arm-vfp.xml", 0);
4035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
4045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_init_vcpu(env);
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return env;
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct arm_cpu_t {
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t id;
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *name;
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const struct arm_cpu_t arm_cpu_names[] = {
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_ARM926, "arm926"},
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_ARM946, "arm946"},
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_ARM1026, "arm1026"},
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_ARM1136, "arm1136"},
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_ARM1136_R2, "arm1136-r2"},
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_ARM11MPCORE, "arm11mpcore"},
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_CORTEXM3, "cortex-m3"},
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_CORTEXA8, "cortex-a8"},
4225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    { ARM_CPUID_CORTEXA8_R2, "cortex-a8-r2"},
4235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    { ARM_CPUID_CORTEXA9, "cortex-a9"},
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_TI925T, "ti925t" },
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_PXA250, "pxa250" },
4265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    { ARM_CPUID_SA1100,    "sa1100" },
4275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    { ARM_CPUID_SA1110,    "sa1110" },
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_PXA255, "pxa255" },
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_PXA260, "pxa260" },
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_PXA261, "pxa261" },
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_PXA262, "pxa262" },
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_PXA270, "pxa270" },
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_PXA270_A0, "pxa270-a0" },
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_PXA270_A1, "pxa270-a1" },
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_PXA270_B0, "pxa270-b0" },
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_PXA270_B1, "pxa270-b1" },
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_PXA270_C0, "pxa270-c0" },
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_PXA270_C5, "pxa270-c5" },
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { ARM_CPUID_ANY, "any"},
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { 0, NULL}
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4435285864985be9077e58e42235af6582dee72e841David 'Digit' Turnervoid arm_cpu_list(FILE *f, fprintf_function cpu_fprintf)
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    (*cpu_fprintf)(f, "Available CPUs:\n");
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (i = 0; arm_cpu_names[i].name; i++) {
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        (*cpu_fprintf)(f, "  %s\n", arm_cpu_names[i].name);
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* return 0 if not found */
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t cpu_arm_find_by_name(const char *name)
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t id;
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    id = 0;
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (i = 0; arm_cpu_names[i].name; i++) {
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcmp(name, arm_cpu_names[i].name) == 0) {
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            id = arm_cpu_names[i].id;
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return id;
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_arm_close(CPUARMState *env)
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    free(env);
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t cpsr_read(CPUARMState *env)
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ZF;
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ZF = (env->ZF == 0);
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return env->uncached_cpsr | (env->NF & 0x80000000) | (ZF << 30) |
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        | (env->thumb << 5) | ((env->condexec_bits & 3) << 25)
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        | ((env->condexec_bits & 0xfc) << 8)
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        | (env->GE << 16);
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (mask & CPSR_NZCV) {
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->ZF = (~val) & CPSR_Z;
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->NF = val;
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->CF = (val >> 29) & 1;
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->VF = (val << 3) & 0x80000000;
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (mask & CPSR_Q)
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->QF = ((val & CPSR_Q) != 0);
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (mask & CPSR_T)
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->thumb = ((val & CPSR_T) != 0);
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (mask & CPSR_IT_0_1) {
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->condexec_bits &= ~3;
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->condexec_bits |= (val >> 25) & 3;
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (mask & CPSR_IT_2_7) {
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->condexec_bits &= 3;
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->condexec_bits |= (val >> 8) & 0xfc;
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (mask & CPSR_GE) {
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->GE = (val >> 16) & 0xf;
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((env->uncached_cpsr ^ val) & mask & CPSR_M) {
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch_mode(env, val & CPSR_M);
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask &= ~CACHED_CPSR_BITS;
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask);
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Sign/zero extend */
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(sxtb16)(uint32_t x)
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t res;
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    res = (uint16_t)(int8_t)x;
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    res |= (uint32_t)(int8_t)(x >> 16) << 16;
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return res;
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(uxtb16)(uint32_t x)
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t res;
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    res = (uint16_t)(uint8_t)x;
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    res |= (uint32_t)(uint8_t)(x >> 16) << 16;
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return res;
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(clz)(uint32_t x)
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return clz32(x);
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint32_t HELPER(sdiv)(int32_t num, int32_t den)
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (den == 0)
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return 0;
5425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (num == INT_MIN && den == -1)
5435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner      return INT_MIN;
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return num / den;
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(udiv)(uint32_t num, uint32_t den)
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (den == 0)
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return 0;
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return num / den;
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(rbit)(uint32_t x)
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    x =  ((x & 0xff000000) >> 24)
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       | ((x & 0x00ff0000) >> 8)
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       | ((x & 0x0000ff00) << 8)
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       | ((x & 0x000000ff) << 24);
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    x =  ((x & 0xf0f0f0f0) >> 4)
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       | ((x & 0x0f0f0f0f) << 4);
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    x =  ((x & 0x88888888) >> 3)
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       | ((x & 0x44444444) >> 1)
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       | ((x & 0x22222222) << 1)
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       | ((x & 0x11111111) << 3);
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return x;
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(abs)(uint32_t x)
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ((int32_t)x < 0) ? -x : x;
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(CONFIG_USER_ONLY)
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid do_interrupt (CPUState *env)
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->exception_index = -1;
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              int mmu_idx, int is_softmmu)
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (rw == 2) {
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->exception_index = EXCP_PREFETCH_ABORT;
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c6_insn = address;
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->exception_index = EXCP_DATA_ABORT;
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c6_data = address;
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 1;
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* These should probably raise undefined insn exceptions.  */
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_abort(env, "cp15 insn %08x\n", insn);
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_abort(env, "cp15 insn %08x\n", insn);
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* These should probably raise undefined insn exceptions.  */
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid HELPER(v7m_msr)(CPUState *env, uint32_t reg, uint32_t val)
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_abort(env, "v7m_mrs %d\n", reg);
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(v7m_mrs)(CPUState *env, uint32_t reg)
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_abort(env, "v7m_mrs %d\n", reg);
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid switch_mode(CPUState *env, int mode)
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (mode != ARM_CPU_MODE_USR)
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_abort(env, "Tried to switch out of user mode\n");
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val)
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_abort(env, "banked r13 write\n");
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_abort(env, "banked r13 read\n");
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectextern int semihosting_enabled;
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Map CPU modes onto saved register banks.  */
6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline int bank_number (int mode)
6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (mode) {
6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPU_MODE_USR:
6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPU_MODE_SYS:
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPU_MODE_SVC:
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPU_MODE_ABT:
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 2;
6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPU_MODE_UND:
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 3;
6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPU_MODE_IRQ:
6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 4;
6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case ARM_CPU_MODE_FIQ:
6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 5;
6565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case ARM_CPU_MODE_SMC:
6575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return 6;
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_abort(cpu_single_env, "Bad mode %x\n", mode);
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid switch_mode(CPUState *env, int mode)
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int old_mode;
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    old_mode = env->uncached_cpsr & CPSR_M;
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (mode == old_mode)
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (old_mode == ARM_CPU_MODE_FIQ) {
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy (env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy (env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (mode == ARM_CPU_MODE_FIQ) {
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy (env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy (env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    i = bank_number(old_mode);
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->banked_r13[i] = env->regs[13];
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->banked_r14[i] = env->regs[14];
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->banked_spsr[i] = env->spsr;
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    i = bank_number(mode);
6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->regs[13] = env->banked_r13[i];
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->regs[14] = env->banked_r14[i];
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->spsr = env->banked_spsr[i];
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void v7m_push(CPUARMState *env, uint32_t val)
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->regs[13] -= 4;
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stl_phys(env->regs[13], val);
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t v7m_pop(CPUARMState *env)
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t val;
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    val = ldl_phys(env->regs[13]);
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->regs[13] += 4;
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return val;
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Switch to V7M main or process stack pointer.  */
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void switch_v7m_sp(CPUARMState *env, int process)
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t tmp;
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (env->v7m.current_sp != process) {
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = env->v7m.other_sp;
7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->v7m.other_sp = env->regs[13];
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->regs[13] = tmp;
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->v7m.current_sp = process;
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void do_v7m_exception_exit(CPUARMState *env)
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t type;
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t xpsr;
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    type = env->regs[15];
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (env->v7m.exception != 0)
7245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        armv7m_nvic_complete_irq(env->nvic, env->v7m.exception);
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Switch to the target stack.  */
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch_v7m_sp(env, (type & 4) != 0);
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Pop registers.  */
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->regs[0] = v7m_pop(env);
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->regs[1] = v7m_pop(env);
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->regs[2] = v7m_pop(env);
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->regs[3] = v7m_pop(env);
7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->regs[12] = v7m_pop(env);
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->regs[14] = v7m_pop(env);
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->regs[15] = v7m_pop(env);
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    xpsr = v7m_pop(env);
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    xpsr_write(env, xpsr, 0xfffffdff);
7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Undo stack alignment.  */
7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (xpsr & 0x200)
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->regs[13] |= 4;
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* ??? The exception return type specifies Thread/Handler mode.  However
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       this is also implied by the xPSR value. Not sure what to do
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       if there is a mismatch.  */
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* ??? Likewise for mismatches between the CONTROL register and the stack
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       pointer.  */
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void do_interrupt_v7m(CPUARMState *env)
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t xpsr = xpsr_read(env);
7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t lr;
7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t addr;
7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    lr = 0xfffffff1;
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (env->v7m.current_sp)
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        lr |= 4;
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (env->v7m.exception == 0)
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        lr |= 8;
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* For exceptions we just mark as pending on the NVIC, and let that
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       handle it.  */
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* TODO: Need to escalate if the current priority is higher than the
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       one we're raising.  */
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (env->exception_index) {
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case EXCP_UDEF:
7665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE);
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case EXCP_SWI:
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->regs[15] += 2;
7705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC);
7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case EXCP_PREFETCH_ABORT:
7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case EXCP_DATA_ABORT:
7745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case EXCP_BKPT:
7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (semihosting_enabled) {
7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int nr;
7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nr = lduw_code(env->regs[15]) & 0xff;
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (nr == 0xab) {
7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                env->regs[15] += 2;
7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                env->regs[0] = do_arm_semihosting(env);
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG);
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case EXCP_IRQ:
7895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->v7m.exception = armv7m_nvic_acknowledge_irq(env->nvic);
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case EXCP_EXCEPTION_EXIT:
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        do_v7m_exception_exit(env);
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return; /* Never happens.  Keep compiler happy.  */
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Align stack pointer.  */
8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* ??? Should only do this if Configuration Control Register
8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       STACKALIGN bit is set.  */
8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (env->regs[13] & 4) {
8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->regs[13] -= 4;
8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        xpsr |= 0x200;
8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Switch to the handler mode.  */
8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    v7m_push(env, xpsr);
8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    v7m_push(env, env->regs[15]);
8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    v7m_push(env, env->regs[14]);
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    v7m_push(env, env->regs[12]);
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    v7m_push(env, env->regs[3]);
8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    v7m_push(env, env->regs[2]);
8138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    v7m_push(env, env->regs[1]);
8148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    v7m_push(env, env->regs[0]);
8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch_v7m_sp(env, 0);
8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->uncached_cpsr &= ~CPSR_IT;
8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->regs[14] = lr;
8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    addr = ldl_phys(env->v7m.vecbase + env->v7m.exception * 4);
8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->regs[15] = addr & 0xfffffffe;
8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->thumb = addr & 1;
8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Handle a CPU exception.  */
8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid do_interrupt(CPUARMState *env)
8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t addr;
8278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t mask;
8288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int new_mode;
8298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t offset;
8308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
831ab42ada6ecfb81d6e231d5997b5892efd0fde5adJack Veenstra#ifdef CONFIG_TRACE
832ab42ada6ecfb81d6e231d5997b5892efd0fde5adJack Veenstra    if (tracing) {
833ab42ada6ecfb81d6e231d5997b5892efd0fde5adJack Veenstra        trace_exception(env->regs[15]);
834ab42ada6ecfb81d6e231d5997b5892efd0fde5adJack Veenstra    }
835ab42ada6ecfb81d6e231d5997b5892efd0fde5adJack Veenstra#endif
836ab42ada6ecfb81d6e231d5997b5892efd0fde5adJack Veenstra
8378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (IS_M(env)) {
8388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        do_interrupt_v7m(env);
8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* TODO: Vectored interrupt controller.  */
8428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (env->exception_index) {
8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case EXCP_UDEF:
8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        new_mode = ARM_CPU_MODE_UND;
8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = 0x04;
8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask = CPSR_I;
8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (env->thumb)
8488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            offset = 2;
8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
8508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            offset = 4;
8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case EXCP_SWI:
8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (semihosting_enabled) {
8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Check for semihosting interrupt.  */
8558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (env->thumb) {
8568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                mask = lduw_code(env->regs[15] - 2) & 0xff;
8578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
8588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                mask = ldl_code(env->regs[15] - 4) & 0xffffff;
8598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
8608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Only intercept calls from privileged modes, to provide some
8618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               semblance of security.  */
8628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (((mask == 0x123456 && !env->thumb)
8638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    || (mask == 0xab && env->thumb))
8648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
8658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                env->regs[0] = do_arm_semihosting(env);
8668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
8678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
8688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        new_mode = ARM_CPU_MODE_SVC;
8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = 0x08;
8718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask = CPSR_I;
8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* The PC already points to the next instruction.  */
8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        offset = 0;
8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
8758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case EXCP_BKPT:
8768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* See if this is a semihosting syscall.  */
8778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (env->thumb && semihosting_enabled) {
8788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            mask = lduw_code(env->regs[15]) & 0xff;
8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (mask == 0xab
8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                env->regs[15] += 2;
8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                env->regs[0] = do_arm_semihosting(env);
8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
8848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Fall through to prefetch abort.  */
8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case EXCP_PREFETCH_ABORT:
8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        new_mode = ARM_CPU_MODE_ABT;
8898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = 0x0c;
8908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask = CPSR_A | CPSR_I;
8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        offset = 4;
8928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case EXCP_DATA_ABORT:
8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        new_mode = ARM_CPU_MODE_ABT;
8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = 0x10;
8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask = CPSR_A | CPSR_I;
8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        offset = 8;
8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case EXCP_IRQ:
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        new_mode = ARM_CPU_MODE_IRQ;
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = 0x18;
9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Disable IRQ and imprecise data aborts.  */
9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask = CPSR_A | CPSR_I;
9048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        offset = 4;
9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case EXCP_FIQ:
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        new_mode = ARM_CPU_MODE_FIQ;
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = 0x1c;
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Disable FIQ, IRQ and imprecise data aborts.  */
9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask = CPSR_A | CPSR_I | CPSR_F;
9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        offset = 4;
9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
9135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case EXCP_SMC:
9145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (semihosting_enabled) {
9155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            cpu_abort(env, "SMC handling under semihosting not implemented\n");
9165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return;
9175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
9185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_SMC) {
9195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            env->cp15.c1_secfg &= ~1;
9205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
9215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        offset = env->thumb ? 2 : 0;
9225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        new_mode = ARM_CPU_MODE_SMC;
9235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        addr = 0x08;
9245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        mask = CPSR_A | CPSR_I | CPSR_F;
9255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return; /* Never happens.  Keep compiler happy.  */
9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (arm_feature(env, ARM_FEATURE_TRUSTZONE)) {
9315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (new_mode == ARM_CPU_MODE_SMC ||
9325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_SMC) {
9335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            addr += env->cp15.c12_mvbar;
9345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else {
9355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (env->cp15.c1_sys & (1 << 13)) {
9365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                addr += 0xffff0000;
9375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
9385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                addr += env->cp15.c12_vbar;
9395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
9405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
9415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
9428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* High vectors.  */
9438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (env->cp15.c1_sys & (1 << 13)) {
9448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr += 0xffff0000;
9455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch_mode (env, new_mode);
9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->spsr = cpsr_read(env);
9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Clear IT bits.  */
9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->condexec_bits = 0;
9515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Switch to the new mode, and to the correct instruction set.  */
9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->uncached_cpsr |= mask;
9545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* this is a lie, as the was no c1_sys on V4T/V5, but who cares
9555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * and we should just guard the thumb mode on V4 */
9565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (arm_feature(env, ARM_FEATURE_V4T)) {
9575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->thumb = (env->cp15.c1_sys & (1 << 30)) != 0;
9585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->regs[14] = env->regs[15] + offset;
9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->regs[15] = addr;
9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Check section/page access permissions.
9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   Returns the page protection flags, or zero if the access is not
9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   permitted.  */
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline int check_ap(CPUState *env, int ap, int domain, int access_type,
9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           int is_user)
9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  int prot_ro;
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  if (domain == 3)
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return PAGE_READ | PAGE_WRITE;
9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  if (access_type == 1)
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      prot_ro = 0;
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  else
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      prot_ro = PAGE_READ;
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  switch (ap) {
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  case 0:
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (access_type == 1)
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          return 0;
9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      switch ((env->cp15.c1_sys >> 8) & 3) {
9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 1:
9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          return is_user ? 0 : PAGE_READ;
9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 2:
9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          return PAGE_READ;
9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      default:
9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          return 0;
9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  case 1:
9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return is_user ? 0 : PAGE_READ | PAGE_WRITE;
9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  case 2:
9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (is_user)
9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          return prot_ro;
9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      else
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          return PAGE_READ | PAGE_WRITE;
9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  case 3:
10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return PAGE_READ | PAGE_WRITE;
10015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner  case 4: /* Reserved.  */
10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return 0;
10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  case 5:
10048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return is_user ? 0 : prot_ro;
10058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  case 6:
10068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return prot_ro;
10075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner  case 7:
10085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      if (!arm_feature (env, ARM_FEATURE_V7))
10095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner          return 0;
10105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      return prot_ro;
10118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  default:
10128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      abort();
10138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  }
10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic uint32_t get_level1_table_address(CPUState *env, uint32_t address)
10175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint32_t table;
10195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (address & env->cp15.c2_mask)
10215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        table = env->cp15.c2_base1 & 0xffffc000;
10225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else
10235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        table = env->cp15.c2_base0 & env->cp15.c2_base_mask;
10245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    table |= (address >> 18) & 0x3ffc;
10265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return table;
10275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int get_phys_addr_v5(CPUState *env, uint32_t address, int access_type,
10305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner			    int is_user, uint32_t *phys_ptr, int *prot,
10315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            target_ulong *page_size)
10328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int code;
10348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t table;
10358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t desc;
10368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int type;
10378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ap;
10388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int domain;
10398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t phys_addr;
10408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Pagetable walk.  */
10428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Lookup l1 descriptor.  */
10435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    table = get_level1_table_address(env, address);
10448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    desc = ldl_phys(table);
10458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    type = (desc & 3);
10468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    domain = (env->cp15.c3 >> ((desc >> 4) & 0x1e)) & 3;
10478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (type == 0) {
10488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Section translation fault.  */
10498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        code = 5;
10508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto do_fault;
10518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (domain == 0 || domain == 2) {
10538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (type == 2)
10548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            code = 9; /* Section domain fault.  */
10558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            code = 11; /* Page domain fault.  */
10578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto do_fault;
10588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (type == 2) {
10608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* 1Mb section.  */
10618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
10628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ap = (desc >> 10) & 3;
10638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        code = 13;
10645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        *page_size = 1024 * 1024;
10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Lookup l2 entry.  */
10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (type == 1) {
10688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    /* Coarse pagetable.  */
10698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
10708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else {
10718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    /* Fine pagetable.  */
10728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
10738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        desc = ldl_phys(table);
10758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (desc & 3) {
10768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0: /* Page translation fault.  */
10778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            code = 7;
10788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto do_fault;
10798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: /* 64k page.  */
10808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            phys_addr = (desc & 0xffff0000) | (address & 0xffff);
10818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
10825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            *page_size = 0x10000;
10838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
10848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: /* 4k page.  */
10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            phys_addr = (desc & 0xfffff000) | (address & 0xfff);
10868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
10875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            *page_size = 0x1000;
10888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
10898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3: /* 1k page.  */
10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    if (type == 1) {
10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (arm_feature(env, ARM_FEATURE_XSCALE)) {
10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    phys_addr = (desc & 0xfffff000) | (address & 0xfff);
10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		} else {
10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    /* Page translation fault.  */
10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    code = 7;
10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    goto do_fault;
10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
10988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    } else {
10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
11008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    }
11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ap = (desc >> 4) & 3;
11025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            *page_size = 0x400;
11038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Never happens, but compiler isn't smart enough to tell.  */
11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            abort();
11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        code = 15;
11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *prot = check_ap(env, ap, domain, access_type, is_user);
11118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!*prot) {
11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Access permission fault.  */
11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto do_fault;
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    *prot |= PAGE_EXEC;
11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *phys_ptr = phys_addr;
11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_fault:
11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return code | (domain << 4);
11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type,
11235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner			    int is_user, uint32_t *phys_ptr, int *prot,
11245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            target_ulong *page_size)
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int code;
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t table;
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t desc;
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t xn;
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int type;
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ap;
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int domain;
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t phys_addr;
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Pagetable walk.  */
11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Lookup l1 descriptor.  */
11375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    table = get_level1_table_address(env, address);
11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    desc = ldl_phys(table);
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    type = (desc & 3);
11405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (type == 0 || type == 3) {
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Section translation fault.  */
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        code = 5;
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        domain = 0;
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto do_fault;
11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (type == 2 && (desc & (1 << 18))) {
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Supersection.  */
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        domain = 0;
11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Section or page.  */
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        domain = (desc >> 4) & 0x1e;
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    domain = (env->cp15.c3 >> domain) & 3;
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (domain == 0 || domain == 2) {
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (type == 2)
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            code = 9; /* Section domain fault.  */
11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            code = 11; /* Page domain fault.  */
11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto do_fault;
11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (type == 2) {
11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (desc & (1 << 18)) {
11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Supersection.  */
11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            phys_addr = (desc & 0xff000000) | (address & 0x00ffffff);
11645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            *page_size = 0x1000000;
11658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
11668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Section.  */
11678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
11685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            *page_size = 0x100000;
11698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ap = ((desc >> 10) & 3) | ((desc >> 13) & 4);
11718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        xn = desc & (1 << 4);
11728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        code = 13;
11738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
11748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Lookup l2 entry.  */
11758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
11768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        desc = ldl_phys(table);
11778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ap = ((desc >> 4) & 3) | ((desc >> 7) & 4);
11788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (desc & 3) {
11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0: /* Page translation fault.  */
11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            code = 7;
11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto do_fault;
11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: /* 64k page.  */
11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            phys_addr = (desc & 0xffff0000) | (address & 0xffff);
11848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            xn = desc & (1 << 15);
11855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            *page_size = 0x10000;
11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: case 3: /* 4k page.  */
11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            phys_addr = (desc & 0xfffff000) | (address & 0xfff);
11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            xn = desc & 1;
11905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            *page_size = 0x1000;
11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Never happens, but compiler isn't smart enough to tell.  */
11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            abort();
11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        code = 15;
11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (domain == 3) {
11995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
12005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (xn && access_type == 2)
12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto do_fault;
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* The simplified model uses AP[0] as an access control bit.  */
12055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if ((env->cp15.c1_sys & (1 << 29)) && (ap & 1) == 0) {
12065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Access flag fault.  */
12075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        code = (code == 15) ? 6 : 3;
12085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto do_fault;
12095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *prot = check_ap(env, ap, domain, access_type, is_user);
12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!*prot) {
12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Access permission fault.  */
12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto do_fault;
12145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
12155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (!xn) {
12165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            *prot |= PAGE_EXEC;
12175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *phys_ptr = phys_addr;
12208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_fault:
12228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return code | (domain << 4);
12238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int get_phys_addr_mpu(CPUState *env, uint32_t address, int access_type,
12268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			     int is_user, uint32_t *phys_ptr, int *prot)
12278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int n;
12298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t mask;
12308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t base;
12318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *phys_ptr = address;
12338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (n = 7; n >= 0; n--) {
12348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	base = env->cp15.c6_region[n];
12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if ((base & 1) == 0)
12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    continue;
12378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	mask = 1 << ((base >> 1) & 0x1f);
12388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Keep this shift separate from the above to avoid an
12398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   (undefined) << 32.  */
12408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	mask = (mask << 1) - 1;
12418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (((base ^ address) & ~mask) == 0)
12428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    break;
12438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (n < 0)
12458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return 2;
12468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (access_type == 2) {
12488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	mask = env->cp15.c5_insn;
12498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
12508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	mask = env->cp15.c5_data;
12518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask = (mask >> (n * 4)) & 0xf;
12538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (mask) {
12548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0:
12558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return 1;
12568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1:
12578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (is_user)
12588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  return 1;
12598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	*prot = PAGE_READ | PAGE_WRITE;
12608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	break;
12618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2:
12628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	*prot = PAGE_READ;
12638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (!is_user)
12648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    *prot |= PAGE_WRITE;
12658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	break;
12668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3:
12678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	*prot = PAGE_READ | PAGE_WRITE;
12688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	break;
12698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5:
12708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (is_user)
12718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    return 1;
12728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	*prot = PAGE_READ;
12738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	break;
12748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 6:
12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	*prot = PAGE_READ;
12768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	break;
12778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
12788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Bad permission.  */
12798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return 1;
12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    *prot |= PAGE_EXEC;
12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
12838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#ifdef CONFIG_GLES2
12865285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerint get_phys_addr(CPUState *env, uint32_t address,
12875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                  int access_type, int is_user,
12885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                  uint32_t *phys_ptr, int *prot,
12895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                  target_ulong *page_size);
12905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#else
12915285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic
12925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#endif
12935285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerint get_phys_addr(CPUState *env, uint32_t address,
12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                int access_type, int is_user,
12955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                uint32_t *phys_ptr, int *prot,
12965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                target_ulong *page_size)
12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Fast Context Switch Extension.  */
12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (address < 0x02000000)
13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        address += env->cp15.c13_fcse;
13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((env->cp15.c1_sys & 1) == 0) {
13038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* MMU/MPU disabled.  */
13048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *phys_ptr = address;
13055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
13065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        *page_size = TARGET_PAGE_SIZE;
13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
13088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (arm_feature(env, ARM_FEATURE_MPU)) {
13095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        *page_size = TARGET_PAGE_SIZE;
13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return get_phys_addr_mpu(env, address, access_type, is_user, phys_ptr,
13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				 prot);
13128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (env->cp15.c1_sys & (1 << 23)) {
13138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return get_phys_addr_v6(env, address, access_type, is_user, phys_ptr,
13145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                prot, page_size);
13158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
13168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return get_phys_addr_v5(env, address, access_type, is_user, phys_ptr,
13175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                prot, page_size);
13188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address,
13228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              int access_type, int mmu_idx, int is_softmmu)
13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    uint32_t phys_addr;
13255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    target_ulong page_size;
13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int prot;
13278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret, is_user;
13288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    is_user = mmu_idx == MMU_USER_IDX;
13305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot,
13315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        &page_size);
13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret == 0) {
13338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Map a single [sub]page.  */
13348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        phys_addr &= ~(uint32_t)0x3ff;
13358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        address &= ~(uint32_t)0x3ff;
13365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tlb_set_page (env, address, phys_addr, prot, mmu_idx, page_size);
13375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return 0;
13388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (access_type == 2) {
13418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c5_insn = ret;
13428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c6_insn = address;
13438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->exception_index = EXCP_PREFETCH_ABORT;
13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
13458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c5_data = ret;
13468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (access_type == 1 && arm_feature(env, ARM_FEATURE_V6))
13478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->cp15.c5_data |= (1 << 11);
13488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c6_data = address;
13498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->exception_index = EXCP_DATA_ABORT;
13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 1;
13528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttarget_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
13558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    uint32_t phys_addr;
13575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    target_ulong page_size;
13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int prot;
13598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
13608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    ret = get_phys_addr(env, addr, 0, 0, &phys_addr, &prot, &page_size);
13628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret != 0)
13648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return phys_addr;
13678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return basic MPU access permission bits.  */
13708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t simple_mpu_ap_bits(uint32_t val)
13718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t ret;
13738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t mask;
13748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = 0;
13768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask = 3;
13778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (i = 0; i < 16; i += 2) {
13788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret |= (val >> i) & mask;
13798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask <<= 2;
13808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
13828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Pad basic MPU access permission bits to extended format.  */
13858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t extended_mpu_ap_bits(uint32_t val)
13868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t ret;
13888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t mask;
13898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
13908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = 0;
13918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask = 3;
13928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (i = 0; i < 16; i += 2) {
13938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret |= (val & mask) << i;
13948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask <<= 2;
13958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
13978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
14008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int op1;
14028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int op2;
14038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int crm;
14048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    op1 = (insn >> 21) & 7;
14068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    op2 = (insn >> 5) & 7;
14078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    crm = insn & 0xf;
14088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch ((insn >> 16) & 0xf) {
14098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0:
14108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* ID codes.  */
14118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arm_feature(env, ARM_FEATURE_XSCALE))
14128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
14138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arm_feature(env, ARM_FEATURE_OMAPCP))
14148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
14155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (arm_feature(env, ARM_FEATURE_V7)
14165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                && op1 == 2 && crm == 0 && op2 == 0) {
14175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            env->cp15.c0_cssel = val & 0xf;
14185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
14195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
14208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto bad_reg;
14218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: /* System configuration.  */
14225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (crm) {
14235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 0:
14248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arm_feature(env, ARM_FEATURE_OMAPCP))
14258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op2 = 0;
14268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op2) {
14278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
14285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (!arm_feature(env, ARM_FEATURE_XSCALE))
14298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                env->cp15.c1_sys = val;
14308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* ??? Lots of these bits are not implemented.  */
14318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* This may enable/disable the MMU, so do a TLB flush.  */
14328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tlb_flush(env, 1);
14338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
14345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: /* Auxiliary control register.  */
14358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (arm_feature(env, ARM_FEATURE_XSCALE)) {
14368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                env->cp15.c1_xscaleauxcr = val;
14378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
14388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
14398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Not implemented.  */
14408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
14418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
14428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (arm_feature(env, ARM_FEATURE_XSCALE))
14438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
14445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (env->cp15.c1_coproc != val) {
14455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                env->cp15.c1_coproc = val;
14465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* ??? Is this safe when called from within a TB?  */
14475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tb_flush(env);
14485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
14495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
14505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            default:
14515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto bad_reg;
14525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
14535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
14545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 1:
14555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (!arm_feature(env, ARM_FEATURE_TRUSTZONE)
14565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                || (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)
14575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto bad_reg;
14585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            switch (op2) {
14595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 0: /* Secure configuration register. */
14605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (env->cp15.c1_secfg & 1)
14615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto bad_reg;
14625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                env->cp15.c1_secfg = val;
14635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
14645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: /* Secure debug enable register. */
14655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (env->cp15.c1_secfg & 1)
14665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto bad_reg;
14675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                env->cp15.c1_sedbg = val;
14685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
14695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2: /* Nonsecure access control register. */
14705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (env->cp15.c1_secfg & 1)
14715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto bad_reg;
14725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                env->cp15.c1_nseac = val;
14735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
14745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            default:
14755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto bad_reg;
14765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
14798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto bad_reg;
14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
14818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
14828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: /* MMU Page table control / MPU cache control.  */
14838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arm_feature(env, ARM_FEATURE_MPU)) {
14848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (op2) {
14858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0:
14868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                env->cp15.c2_data = val;
14878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
14888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1:
14898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                env->cp15.c2_insn = val;
14908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
14918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default:
14928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
14938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
14948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
14958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    switch (op2) {
14968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    case 0:
14978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		env->cp15.c2_base0 = val;
14988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		break;
14998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    case 1:
15008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		env->cp15.c2_base1 = val;
15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		break;
15028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    case 2:
15035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                val &= 7;
15045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                env->cp15.c2_control = val;
15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> val);
15065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> val);
15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		break;
15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    default:
15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		goto bad_reg;
15108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    }
15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: /* MMU Domain access control / MPU write buffer control.  */
15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c3 = val;
15158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tlb_flush(env, 1); /* Flush TLB as domain not tracked in TLB */
15168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4: /* Reserved.  */
15188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto bad_reg;
15198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5: /* MMU Fault status / MPU access permission.  */
15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arm_feature(env, ARM_FEATURE_OMAPCP))
15218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op2 = 0;
15228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op2) {
15238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
15248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (arm_feature(env, ARM_FEATURE_MPU))
15258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                val = extended_mpu_ap_bits(val);
15268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->cp15.c5_data = val;
15278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
15298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (arm_feature(env, ARM_FEATURE_MPU))
15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                val = extended_mpu_ap_bits(val);
15318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->cp15.c5_insn = val;
15328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
15348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!arm_feature(env, ARM_FEATURE_MPU))
15358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
15368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->cp15.c5_data = val;
15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
15398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!arm_feature(env, ARM_FEATURE_MPU))
15408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
15418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->cp15.c5_insn = val;
15428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
15448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto bad_reg;
15458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 6: /* MMU Fault address / MPU base/size.  */
15488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arm_feature(env, ARM_FEATURE_MPU)) {
15498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (crm >= 8)
15508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
15518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->cp15.c6_region[crm] = val;
15528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
15538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (arm_feature(env, ARM_FEATURE_OMAPCP))
15548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                op2 = 0;
15558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (op2) {
15568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0:
15578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                env->cp15.c6_data = val;
15588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
15598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: /* ??? This is WFAR on armv6 */
15608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2:
15618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                env->cp15.c6_insn = val;
15628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
15638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default:
15648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
15658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
15668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 7: /* Cache control.  */
15698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c15_i_max = 0x000;
15708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->cp15.c15_i_min = 0xff0;
15715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (op1 != 0) {
15725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            goto bad_reg;
15735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
15745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* No cache, so nothing to do except VA->PA translations. */
15755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (arm_feature(env, ARM_FEATURE_V6K)) {
15765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            switch (crm) {
15775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 4:
15785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (arm_feature(env, ARM_FEATURE_V7)) {
15795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    env->cp15.c7_par = val & 0xfffff6ff;
15805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                } else {
15815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    env->cp15.c7_par = val & 0xfffff1ff;
15825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
15835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
15845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 8: {
15855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                uint32_t phys_addr;
15865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                target_ulong page_size;
15875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                int prot;
15885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                int ret, is_user = op2 & 2;
15895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                int access_type = op2 & 1;
15905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
15915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (op2 & 4) {
15925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* Other states are only available with TrustZone */
15935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto bad_reg;
15945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
15955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                ret = get_phys_addr(env, val, access_type, is_user,
15965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    &phys_addr, &prot, &page_size);
15975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (ret == 0) {
15985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* We do not set any attribute bits in the PAR */
15995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (page_size == (1 << 24)
16005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        && arm_feature(env, ARM_FEATURE_V7)) {
16015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        env->cp15.c7_par = (phys_addr & 0xff000000) | 1 << 1;
16025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    } else {
16035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        env->cp15.c7_par = phys_addr & 0xfffff000;
16045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
16055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                } else {
16065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    env->cp15.c7_par = ((ret & (10 << 1)) >> 5) |
16075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                       ((ret & (12 << 1)) >> 6) |
16085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                       ((ret & 0xf) << 1) | 1;
16095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
16105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
16115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
16125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
16135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
16148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
16158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 8: /* MMU TLB control.  */
16168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op2) {
16178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0: /* Invalidate all.  */
16188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tlb_flush(env, 0);
16198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: /* Invalidate single TLB entry.  */
16215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tlb_flush_page(env, val & TARGET_PAGE_MASK);
16228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: /* Invalidate on ASID.  */
16248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tlb_flush(env, val == 0);
16258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3: /* Invalidate single entry on MVA.  */
16278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* ??? This is like case 1, but ignores ASID.  */
16288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tlb_flush(env, 1);
16298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
16318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto bad_reg;
16328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
16348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 9:
16358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arm_feature(env, ARM_FEATURE_OMAPCP))
16368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (arm_feature(env, ARM_FEATURE_STRONGARM))
16385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break; /* Ignore ReadBuffer access */
16398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (crm) {
16408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0: /* Cache lockdown.  */
16418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    switch (op1) {
16428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    case 0: /* L1 cache.  */
16438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		switch (op2) {
16448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		case 0:
16458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    env->cp15.c9_data = val;
16468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    break;
16478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		case 1:
16488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    env->cp15.c9_insn = val;
16498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    break;
16508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		default:
16518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    goto bad_reg;
16528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
16538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		break;
16548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    case 1: /* L2 cache.  */
16555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                switch (op2) {
16565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0: /* L2 cache lockdown */
16575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: /* L2 cache auxiliary control */
16585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* ignore */
16595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    break;
16605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                default:
16615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto bad_reg;
16625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
16638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		break;
16648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    default:
16658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		goto bad_reg;
16668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    }
16678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    break;
16688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: /* TCM memory region registers.  */
16695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 2:
16708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Not implemented.  */
16718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto bad_reg;
16725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 12: /* performance monitor control */
16735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (arm_feature(env, ARM_FEATURE_V7)) {
16745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                switch (op2) {
16755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0: /* performance monitor control */
16765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    env->cp15.c9_pmcr_data = val;
16775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    break;
16785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: /* count enable set */
16795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: /* count enable clear */
16805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 3: /* overflow flag status */
16815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 4: /* software increment */
16825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 5: /* performance counter selection */
16835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* not implemented */
16845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto bad_reg;
16855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                default:
16865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto bad_reg;
16875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
16885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
16895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto bad_reg;
16905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
16915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
16925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 13: /* performance counters */
16935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (arm_feature(env, ARM_FEATURE_V7)) {
16945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                switch (op2) {
16955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0: /* cycle count */
16965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: /* event selection */
16975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: /* performance monitor count */
16985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* not implemented */
16995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto bad_reg;
17005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                default:
17015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto bad_reg;
17025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
17035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
17045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto bad_reg;
17055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
17065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
17075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 14: /* performance monitor control */
17085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (arm_feature(env, ARM_FEATURE_V7)) {
17095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                switch (op2) {
17105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0: /* user enable */
17115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR) {
17125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        goto bad_reg;
17135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
17145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    env->cp15.c9_useren = val & 1;
17155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    break;
17165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: /* interrupt enable set */
17175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR) {
17185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        goto bad_reg;
17195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
17205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    env->cp15.c9_inten |= val & 0xf;
17215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    break;
17225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: /* interrupt enable clear */
17235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR) {
17245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        goto bad_reg;
17255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
17265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    env->cp15.c9_inten &= ~(val & 0xf);
17275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    break;
17285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                default:
17295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto bad_reg;
17305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
17315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
17325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto bad_reg;
17335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
17345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
17358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
17368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto bad_reg;
17378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
17398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 10: /* MMU TLB lockdown.  */
17408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* ??? TLB lockdown not implemented.  */
17418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
17428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 12: /* Reserved.  */
17435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (!op1 && !crm) {
17445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            switch (op2) {
17455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 0:
17465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (!arm_feature(env, ARM_FEATURE_TRUSTZONE)) {
17475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto bad_reg;
17485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
17495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                env->cp15.c12_vbar = val & ~0x1f;
17505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
17515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1:
17525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (!arm_feature(env, ARM_FEATURE_TRUSTZONE)) {
17535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto bad_reg;
17545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
17555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (!(env->cp15.c1_secfg & 1)) {
17565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    env->cp15.c12_mvbar = val & ~0x1f;
17575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
17585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
17595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            default:
17605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto bad_reg;
17615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
17625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
17635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
17648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto bad_reg;
17658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 13: /* Process ID.  */
17668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op2) {
17678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
17688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Unlike real hardware the qemu TLB uses virtual addresses,
17698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               not modified virtual addresses, so this causes a TLB flush.
17708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             */
17718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (env->cp15.c13_fcse != val)
17728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              tlb_flush(env, 1);
17738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->cp15.c13_fcse = val;
17748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
17768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* This changes the ASID, so do a TLB flush.  */
17778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (env->cp15.c13_context != val
17788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                && !arm_feature(env, ARM_FEATURE_MPU))
17798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              tlb_flush(env, 0);
17808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->cp15.c13_context = val;
17818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
17838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto bad_reg;
17848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
17868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 14: /* Reserved.  */
17878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto bad_reg;
17888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 15: /* Implementation specific.  */
17898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arm_feature(env, ARM_FEATURE_XSCALE)) {
17908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op2 == 0 && crm == 1) {
17918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (env->cp15.c15_cpar != (val & 0x3fff)) {
17928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Changes cp0 to cp13 behavior, so needs a TB flush.  */
17938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tb_flush(env);
17948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    env->cp15.c15_cpar = val & 0x3fff;
17958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
17968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
17978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
17988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto bad_reg;
17998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
18008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
18018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (crm) {
18028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0:
18038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
18048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: /* Set TI925T configuration.  */
18058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                env->cp15.c15_ticonfig = val & 0xe7;
18068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                env->cp15.c0_cpuid = (val & (1 << 5)) ? /* OS_TYPE bit */
18078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        ARM_CPUID_TI915T : ARM_CPUID_TI925T;
18088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
18098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: /* Set I_max.  */
18108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                env->cp15.c15_i_max = val;
18118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
18128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3: /* Set I_min.  */
18138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                env->cp15.c15_i_min = val;
18148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
18158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 4: /* Set thread-ID.  */
18168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                env->cp15.c15_threadid = val & 0xffff;
18178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
18188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 8: /* Wait-for-interrupt (deprecated).  */
18198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                cpu_interrupt(env, CPU_INTERRUPT_HALT);
18208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
18218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default:
18228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
18238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
18248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
18258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
18268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return;
18288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectbad_reg:
18298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* ??? For debugging only.  Should raise illegal instruction exception.  */
18308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_abort(env, "Unimplemented cp15 register write (c%d, c%d, {%d, %d})\n",
18318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              (insn >> 16) & 0xf, crm, op1, op2);
18328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
18358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int op1;
18378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int op2;
18388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int crm;
18398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    op1 = (insn >> 21) & 7;
18418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    op2 = (insn >> 5) & 7;
18428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    crm = insn & 0xf;
18438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch ((insn >> 16) & 0xf) {
18448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: /* ID codes.  */
18458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op1) {
18468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
18478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (crm) {
18488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0:
18498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (op2) {
18508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0: /* Device ID.  */
18518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return env->cp15.c0_cpuid;
18528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 1: /* Cache Type.  */
18538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    return env->cp15.c0_cachetype;
18548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 2: /* TCM status.  */
18558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 0;
18568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 3: /* TLB type register.  */
18578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 0; /* No lockable TLB entries.  */
18585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 5: /* MPIDR */
18595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* The MPIDR was standardised in v7; prior to
18605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     * this it was implemented only in the 11MPCore.
18615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     * For all other pre-v7 cores it does not exist.
18625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     */
18635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (arm_feature(env, ARM_FEATURE_V7) ||
18645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        ARM_CPUID(env) == ARM_CPUID_ARM11MPCORE) {
18655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        int mpidr = env->cpu_index;
18665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        /* We don't support setting cluster ID ([8..11])
18675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                         * so these bits always RAZ.
18685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                         */
18695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (arm_feature(env, ARM_FEATURE_V7MP)) {
18705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            mpidr |= (1 << 31);
18715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            /* Cores which are uniprocessor (non-coherent)
18725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                             * but still implement the MP extensions set
18735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                             * bit 30. (For instance, A9UP.) However we do
18745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                             * not currently model any of those cores.
18755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                             */
18765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
18775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        return mpidr;
18785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
18795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* otherwise fall through to the unimplemented-reg case */
18808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default:
18818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto bad_reg;
18828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
18838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1:
18848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (!arm_feature(env, ARM_FEATURE_V6))
18858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto bad_reg;
18868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return env->cp15.c0_c1[op2];
18878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2:
18888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (!arm_feature(env, ARM_FEATURE_V6))
18898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto bad_reg;
18908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return env->cp15.c0_c2[op2];
18918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3: case 4: case 5: case 6: case 7:
18928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 0;
18938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default:
18948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
18958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
18965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
18978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
18988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* These registers aren't documented on arm11 cores.  However
18998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               Linux looks at them anyway.  */
19008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!arm_feature(env, ARM_FEATURE_V6))
19018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
19028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (crm != 0)
19038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
19045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (!arm_feature(env, ARM_FEATURE_V7))
19055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return 0;
19065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            switch (op2) {
19085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case 0:
19095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return env->cp15.c0_ccsid[env->cp15.c0_cssel];
19105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case 1:
19115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return env->cp15.c0_clid;
19125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case 7:
19135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return 0;
19145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
19155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto bad_reg;
19165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case 2:
19175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (op2 != 0 || crm != 0)
19188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
19195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return env->cp15.c0_cssel;
19208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
19218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto bad_reg;
19228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
19248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: /* System configuration.  */
19255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (crm) {
19265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 0:
19278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arm_feature(env, ARM_FEATURE_OMAPCP))
19288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op2 = 0;
19298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op2) {
19308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0: /* Control register.  */
19318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return env->cp15.c1_sys;
19328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: /* Auxiliary control register.  */
19338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (arm_feature(env, ARM_FEATURE_XSCALE))
19348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return env->cp15.c1_xscaleauxcr;
19358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!arm_feature(env, ARM_FEATURE_AUXCR))
19368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
19378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (ARM_CPUID(env)) {
19388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case ARM_CPUID_ARM1026:
19398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 1;
19408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case ARM_CPUID_ARM1136:
19418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case ARM_CPUID_ARM1136_R2:
19428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 7;
19438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case ARM_CPUID_ARM11MPCORE:
19448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 1;
19458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case ARM_CPUID_CORTEXA8:
19465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case ARM_CPUID_CORTEXA8_R2:
19475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return 2;
19485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case ARM_CPUID_CORTEXA9:
19495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 0;
19508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default:
19518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
19528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
19535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
19548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: /* Coprocessor access register.  */
19558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (arm_feature(env, ARM_FEATURE_XSCALE))
19568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
19578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return env->cp15.c1_coproc;
19588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
19598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto bad_reg;
19608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
19625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 1:
19635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (!arm_feature(env, ARM_FEATURE_TRUSTZONE)
19645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                || (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)
19655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto bad_reg;
19665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            switch (op2) {
19675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 0: /* Secure configuration register. */
19685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (env->cp15.c1_secfg & 1)
19695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto bad_reg;
19705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return env->cp15.c1_secfg;
19715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: /* Secure debug enable register. */
19725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (env->cp15.c1_secfg & 1)
19735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto bad_reg;
19745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return env->cp15.c1_sedbg;
19755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2: /* Nonsecure access control register. */
19765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return env->cp15.c1_nseac;
19775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            default:
19785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto bad_reg;
19795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
19805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
19815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
19825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            goto bad_reg;
19835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
19845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
19858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: /* MMU Page table control / MPU cache control.  */
19868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arm_feature(env, ARM_FEATURE_MPU)) {
19878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (op2) {
19888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0:
19898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return env->cp15.c2_data;
19908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
19918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1:
19928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return env->cp15.c2_insn;
19938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
19948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default:
19958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
19968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
19978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
19988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    switch (op2) {
19998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    case 0:
20008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return env->cp15.c2_base0;
20018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    case 1:
20028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return env->cp15.c2_base1;
20038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    case 2:
20045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return env->cp15.c2_control;
20058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    default:
20068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		goto bad_reg;
20078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    }
20088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
20098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: /* MMU Domain access control / MPU write buffer control.  */
20108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return env->cp15.c3;
20118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4: /* Reserved.  */
20128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto bad_reg;
20138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5: /* MMU Fault status / MPU access permission.  */
20148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arm_feature(env, ARM_FEATURE_OMAPCP))
20158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op2 = 0;
20168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op2) {
20178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
20188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (arm_feature(env, ARM_FEATURE_MPU))
20198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return simple_mpu_ap_bits(env->cp15.c5_data);
20208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return env->cp15.c5_data;
20218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
20228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (arm_feature(env, ARM_FEATURE_MPU))
20238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return simple_mpu_ap_bits(env->cp15.c5_data);
20248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return env->cp15.c5_insn;
20258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
20268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!arm_feature(env, ARM_FEATURE_MPU))
20278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
20288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return env->cp15.c5_data;
20298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
20308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!arm_feature(env, ARM_FEATURE_MPU))
20318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
20328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return env->cp15.c5_insn;
20338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
20348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto bad_reg;
20358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
20368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 6: /* MMU Fault address.  */
20378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arm_feature(env, ARM_FEATURE_MPU)) {
20388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (crm >= 8)
20398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
20408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return env->cp15.c6_region[crm];
20418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
20428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (arm_feature(env, ARM_FEATURE_OMAPCP))
20438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                op2 = 0;
20448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    switch (op2) {
20458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    case 0:
20468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return env->cp15.c6_data;
20478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    case 1:
20488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (arm_feature(env, ARM_FEATURE_V6)) {
20498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    /* Watchpoint Fault Adrress.  */
20508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    return 0; /* Not implemented.  */
20515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
20528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    /* Instruction Fault Adrress.  */
20538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    /* Arm9 doesn't have an IFAR, but implementing it anyway
20548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		       shouldn't do any harm.  */
20558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    return env->cp15.c6_insn;
20568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    case 2:
20578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (arm_feature(env, ARM_FEATURE_V6)) {
20588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    /* Instruction Fault Adrress.  */
20598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    return env->cp15.c6_insn;
20608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
20615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto bad_reg;
20628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    default:
20638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		goto bad_reg;
20648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    }
20658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
20668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 7: /* Cache control.  */
20675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (crm == 4 && op1 == 0 && op2 == 0) {
20685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return env->cp15.c7_par;
20695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
20705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn >> 12) & 0xf) == 0xf) /* clear ZF only if destination is r15 */
20718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->ZF = 0;
20728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
20738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 8: /* MMU TLB control.  */
20748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto bad_reg;
20758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 9: /* Cache lockdown.  */
20768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op1) {
20775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 0:
20788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    if (arm_feature(env, ARM_FEATURE_OMAPCP))
20798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return 0;
20805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            switch (crm) {
20815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 0: /* L1 cache */
20828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (op2) {
20838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0:
20848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return env->cp15.c9_data;
20858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1:
20868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return env->cp15.c9_insn;
20878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default:
20888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
20898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
20905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
20915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 12:
20925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                switch (op2) {
20935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0:
20945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return env->cp15.c9_pmcr_data;
20955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                default:
20965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto bad_reg;
20975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
20985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
20995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 14: /* performance monitor control */
21005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (arm_feature(env, ARM_FEATURE_V7)) {
21015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    switch (op2) {
21025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 0: /* user enable */
21035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        return env->cp15.c9_useren;
21045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 1: /* interrupt enable set */
21055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 2: /* interrupt enable clear */
21065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR) {
21075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            goto bad_reg;
21085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
21095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        return env->cp15.c9_inten;
21105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    default:
21115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        goto bad_reg;
21125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
21135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                } else {
21145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto bad_reg;
21155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
21165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
21175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            default:
21185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto bad_reg;
21195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
21205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
21218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: /* L2 cache */
21228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (crm != 0)
21238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto bad_reg;
21248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* L2 Lockdown and Auxiliary control.  */
21258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
21268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
21278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto bad_reg;
21288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
21298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 10: /* MMU TLB lockdown.  */
21308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* ??? TLB lockdown not implemented.  */
21318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
21328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 11: /* TCM DMA control.  */
21338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 12: /* Reserved.  */
21345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (!op1 && !crm) {
21355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            switch (op2) {
21365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 0: /* secure or nonsecure vector base address */
21375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (arm_feature(env, ARM_FEATURE_TRUSTZONE)) {
21385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return env->cp15.c12_vbar;
21395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
21405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
21415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: /* monitor vector base address */
21425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (arm_feature(env, ARM_FEATURE_TRUSTZONE)) {
21435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return env->cp15.c12_mvbar;
21445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
21455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
21465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            default:
21475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
21485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
21495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
21508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto bad_reg;
21518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 13: /* Process ID.  */
21528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op2) {
21538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
21548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return env->cp15.c13_fcse;
21558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
21568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return env->cp15.c13_context;
21578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
21588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto bad_reg;
21598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
21608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 14: /* Reserved.  */
21618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto bad_reg;
21628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 15: /* Implementation specific.  */
21638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arm_feature(env, ARM_FEATURE_XSCALE)) {
21648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op2 == 0 && crm == 1)
21658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return env->cp15.c15_cpar;
21668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto bad_reg;
21688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
21698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
21708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (crm) {
21718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0:
21728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 0;
21738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: /* Read TI925T configuration.  */
21748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return env->cp15.c15_ticonfig;
21758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: /* Read I_max.  */
21768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return env->cp15.c15_i_max;
21778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3: /* Read I_min.  */
21788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return env->cp15.c15_i_min;
21798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 4: /* Read thread-ID.  */
21808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return env->cp15.c15_threadid;
21818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 8: /* TI925T_status */
21828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 0;
21838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
21848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* TODO: Peripheral port remap register:
21858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             * On OMAP2 mcr p15, 0, rn, c15, c2, 4 sets up the interrupt
21868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             * controller base address at $rn & ~0xfff and map size of
21878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             * 0x200 << ($rn & 0xfff), when MMU is off.  */
21888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto bad_reg;
21898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
21908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
21918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
21928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectbad_reg:
21938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* ??? For debugging only.  Should raise illegal instruction exception.  */
21948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_abort(env, "Unimplemented cp15 register read (c%d, c%d, {%d, %d})\n",
21958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              (insn >> 16) & 0xf, crm, op1, op2);
21968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
21978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
21988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val)
22008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
22015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if ((env->uncached_cpsr & CPSR_M) == mode) {
22025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->regs[13] = val;
22035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
22048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->banked_r13[bank_number(mode)] = val;
22058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
22065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
22078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
22098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
22105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if ((env->uncached_cpsr & CPSR_M) == mode) {
22115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return env->regs[13];
22125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
22138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return env->banked_r13[bank_number(mode)];
22145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
22158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
22168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(v7m_mrs)(CPUState *env, uint32_t reg)
22188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
22198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (reg) {
22208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: /* APSR */
22218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return xpsr_read(env) & 0xf8000000;
22228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: /* IAPSR */
22238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return xpsr_read(env) & 0xf80001ff;
22248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: /* EAPSR */
22258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return xpsr_read(env) & 0xff00fc00;
22268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: /* xPSR */
22278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return xpsr_read(env) & 0xff00fdff;
22288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5: /* IPSR */
22298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return xpsr_read(env) & 0x000001ff;
22308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 6: /* EPSR */
22318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return xpsr_read(env) & 0x0700fc00;
22328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 7: /* IEPSR */
22338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return xpsr_read(env) & 0x0700edff;
22348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 8: /* MSP */
22358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return env->v7m.current_sp ? env->v7m.other_sp : env->regs[13];
22368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 9: /* PSP */
22378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return env->v7m.current_sp ? env->regs[13] : env->v7m.other_sp;
22388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 16: /* PRIMASK */
22398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return (env->uncached_cpsr & CPSR_I) != 0;
22408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 17: /* FAULTMASK */
22418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return (env->uncached_cpsr & CPSR_F) != 0;
22428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 18: /* BASEPRI */
22438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 19: /* BASEPRI_MAX */
22448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return env->v7m.basepri;
22458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 20: /* CONTROL */
22468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return env->v7m.control;
22478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
22488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* ??? For debugging only.  */
22498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_abort(env, "Unimplemented system register read (%d)\n", reg);
22508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
22518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
22528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
22538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid HELPER(v7m_msr)(CPUState *env, uint32_t reg, uint32_t val)
22558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
22568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (reg) {
22578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: /* APSR */
22588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        xpsr_write(env, val, 0xf8000000);
22598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
22608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: /* IAPSR */
22618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        xpsr_write(env, val, 0xf8000000);
22628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
22638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: /* EAPSR */
22648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        xpsr_write(env, val, 0xfe00fc00);
22658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
22668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: /* xPSR */
22678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        xpsr_write(env, val, 0xfe00fc00);
22688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
22698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5: /* IPSR */
22708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* IPSR bits are readonly.  */
22718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
22728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 6: /* EPSR */
22738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        xpsr_write(env, val, 0x0600fc00);
22748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
22758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 7: /* IEPSR */
22768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        xpsr_write(env, val, 0x0600fc00);
22778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
22788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 8: /* MSP */
22798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (env->v7m.current_sp)
22808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->v7m.other_sp = val;
22818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
22828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->regs[13] = val;
22838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
22848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 9: /* PSP */
22858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (env->v7m.current_sp)
22868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->regs[13] = val;
22878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
22888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->v7m.other_sp = val;
22898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
22908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 16: /* PRIMASK */
22918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (val & 1)
22928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->uncached_cpsr |= CPSR_I;
22938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
22948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->uncached_cpsr &= ~CPSR_I;
22958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
22968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 17: /* FAULTMASK */
22978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (val & 1)
22988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->uncached_cpsr |= CPSR_F;
22998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
23008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->uncached_cpsr &= ~CPSR_F;
23018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
23028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 18: /* BASEPRI */
23038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->v7m.basepri = val & 0xff;
23048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
23058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 19: /* BASEPRI_MAX */
23068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val &= 0xff;
23078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (val != 0 && (val < env->v7m.basepri || env->v7m.basepri == 0))
23088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->v7m.basepri = val;
23098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
23108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 20: /* CONTROL */
23118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->v7m.control = val & 3;
23128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch_v7m_sp(env, (val & 2) != 0);
23138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
23148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
23158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* ??? For debugging only.  */
23168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_abort(env, "Unimplemented system register write (%d)\n", reg);
23178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
23188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
23198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
23228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ARMReadCPFunc *cp_read, ARMWriteCPFunc *cp_write,
23238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                void *opaque)
23248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cpnum < 0 || cpnum > 14) {
23268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_abort(env, "Bad coprocessor number: %i\n", cpnum);
23278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
23288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
23298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cp[cpnum].cp_read = cp_read;
23318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cp[cpnum].cp_write = cp_write;
23328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->cp[cpnum].opaque = opaque;
23338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
23368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Note that signed overflow is undefined in C.  The following routines are
23388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   careful to use unsigned types where modulo arithmetic is required.
23398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   Failure to do so _will_ break on newer gcc.  */
23408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Signed saturating arithmetic.  */
23428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Perform 16-bit signed saturating addition.  */
23448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline uint16_t add16_sat(uint16_t a, uint16_t b)
23458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint16_t res;
23478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    res = a + b;
23498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (((res ^ a) & 0x8000) && !((a ^ b) & 0x8000)) {
23508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (a & 0x8000)
23518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            res = 0x8000;
23528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
23538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            res = 0x7fff;
23548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
23558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return res;
23568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Perform 8-bit signed saturating addition.  */
23598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline uint8_t add8_sat(uint8_t a, uint8_t b)
23608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t res;
23628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    res = a + b;
23648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (((res ^ a) & 0x80) && !((a ^ b) & 0x80)) {
23658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (a & 0x80)
23668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            res = 0x80;
23678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
23688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            res = 0x7f;
23698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
23708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return res;
23718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Perform 16-bit signed saturating subtraction.  */
23748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline uint16_t sub16_sat(uint16_t a, uint16_t b)
23758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint16_t res;
23778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    res = a - b;
23798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (((res ^ a) & 0x8000) && ((a ^ b) & 0x8000)) {
23808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (a & 0x8000)
23818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            res = 0x8000;
23828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
23838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            res = 0x7fff;
23848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
23858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return res;
23868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Perform 8-bit signed saturating subtraction.  */
23898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline uint8_t sub8_sat(uint8_t a, uint8_t b)
23908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t res;
23928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    res = a - b;
23948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (((res ^ a) & 0x80) && ((a ^ b) & 0x80)) {
23958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (a & 0x80)
23968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            res = 0x80;
23978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
23988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            res = 0x7f;
23998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return res;
24018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ADD16(a, b, n) RESULT(add16_sat(a, b), n, 16);
24048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SUB16(a, b, n) RESULT(sub16_sat(a, b), n, 16);
24058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ADD8(a, b, n)  RESULT(add8_sat(a, b), n, 8);
24068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SUB8(a, b, n)  RESULT(sub8_sat(a, b), n, 8);
24078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PFX q
24088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "op_addsub.h"
24108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Unsigned saturating arithmetic.  */
24128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline uint16_t add16_usat(uint16_t a, uint16_t b)
24138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint16_t res;
24158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    res = a + b;
24168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (res < a)
24178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        res = 0xffff;
24188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return res;
24198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline uint16_t sub16_usat(uint16_t a, uint16_t b)
24228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (a > b)
24248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return a - b;
24258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
24268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
24278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline uint8_t add8_usat(uint8_t a, uint8_t b)
24308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t res;
24328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    res = a + b;
24338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (res < a)
24348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        res = 0xff;
24358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return res;
24368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline uint8_t sub8_usat(uint8_t a, uint8_t b)
24398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (a > b)
24418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return a - b;
24428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
24438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
24448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ADD16(a, b, n) RESULT(add16_usat(a, b), n, 16);
24478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SUB16(a, b, n) RESULT(sub16_usat(a, b), n, 16);
24488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ADD8(a, b, n)  RESULT(add8_usat(a, b), n, 8);
24498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SUB8(a, b, n)  RESULT(sub8_usat(a, b), n, 8);
24508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PFX uq
24518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "op_addsub.h"
24538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Signed modulo arithmetic.  */
24558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SARITH16(a, b, n, op) do { \
24568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int32_t sum; \
24575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    sum = (int32_t)(int16_t)(a) op (int32_t)(int16_t)(b); \
24588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    RESULT(sum, n, 16); \
24598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sum >= 0) \
24608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ge |= 3 << (n * 2); \
24618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while(0)
24628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SARITH8(a, b, n, op) do { \
24648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int32_t sum; \
24655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    sum = (int32_t)(int8_t)(a) op (int32_t)(int8_t)(b); \
24668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    RESULT(sum, n, 8); \
24678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sum >= 0) \
24688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ge |= 1 << n; \
24698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while(0)
24708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ADD16(a, b, n) SARITH16(a, b, n, +)
24738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SUB16(a, b, n) SARITH16(a, b, n, -)
24748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ADD8(a, b, n)  SARITH8(a, b, n, +)
24758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SUB8(a, b, n)  SARITH8(a, b, n, -)
24768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PFX s
24778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ARITH_GE
24788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "op_addsub.h"
24808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Unsigned modulo arithmetic.  */
24828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ADD16(a, b, n) do { \
24838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t sum; \
24848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sum = (uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b); \
24858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    RESULT(sum, n, 16); \
24868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((sum >> 16) == 1) \
24878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ge |= 3 << (n * 2); \
24888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while(0)
24898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ADD8(a, b, n) do { \
24918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t sum; \
24928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sum = (uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b); \
24938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    RESULT(sum, n, 8); \
24948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((sum >> 8) == 1) \
24958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ge |= 1 << n; \
24968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while(0)
24978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SUB16(a, b, n) do { \
24998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t sum; \
25008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sum = (uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b); \
25018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    RESULT(sum, n, 16); \
25028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((sum >> 16) == 0) \
25038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ge |= 3 << (n * 2); \
25048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while(0)
25058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SUB8(a, b, n) do { \
25078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t sum; \
25088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sum = (uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b); \
25098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    RESULT(sum, n, 8); \
25108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((sum >> 8) == 0) \
25118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ge |= 1 << n; \
25128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while(0)
25138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PFX u
25158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ARITH_GE
25168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "op_addsub.h"
25188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Halved signed arithmetic.  */
25208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ADD16(a, b, n) \
25218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  RESULT(((int32_t)(int16_t)(a) + (int32_t)(int16_t)(b)) >> 1, n, 16)
25228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SUB16(a, b, n) \
25238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  RESULT(((int32_t)(int16_t)(a) - (int32_t)(int16_t)(b)) >> 1, n, 16)
25248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ADD8(a, b, n) \
25258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  RESULT(((int32_t)(int8_t)(a) + (int32_t)(int8_t)(b)) >> 1, n, 8)
25268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SUB8(a, b, n) \
25278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  RESULT(((int32_t)(int8_t)(a) - (int32_t)(int8_t)(b)) >> 1, n, 8)
25288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PFX sh
25298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "op_addsub.h"
25318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Halved unsigned arithmetic.  */
25338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ADD16(a, b, n) \
25348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  RESULT(((uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b)) >> 1, n, 16)
25358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SUB16(a, b, n) \
25368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  RESULT(((uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b)) >> 1, n, 16)
25378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ADD8(a, b, n) \
25388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  RESULT(((uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b)) >> 1, n, 8)
25398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SUB8(a, b, n) \
25408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  RESULT(((uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b)) >> 1, n, 8)
25418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PFX uh
25428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "op_addsub.h"
25448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline uint8_t do_usad(uint8_t a, uint8_t b)
25468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (a > b)
25488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return a - b;
25498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
25508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return b - a;
25518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Unsigned sum of absolute byte differences.  */
25548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(usad8)(uint32_t a, uint32_t b)
25558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t sum;
25578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sum = do_usad(a, b);
25588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sum += do_usad(a >> 8, b >> 8);
25598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sum += do_usad(a >> 16, b >>16);
25608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sum += do_usad(a >> 24, b >> 24);
25618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return sum;
25628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* For ARMv6 SEL instruction.  */
25658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b)
25668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t mask;
25688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask = 0;
25708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & 1)
25718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask |= 0xff;
25728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & 2)
25738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask |= 0xff00;
25748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & 4)
25758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask |= 0xff0000;
25768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & 8)
25778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask |= 0xff000000;
25788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (a & mask) | (b & ~mask);
25798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(logicq_cc)(uint64_t val)
25828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (val >> 32) | (val != 0);
25848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* VFP support.  We follow the convention used for VFP instrunctions:
25878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   Single precition routines have a "s" suffix, double precision a
25888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   "d" suffix.  */
25898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Convert host exception flags to vfp form.  */
25918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline int vfp_exceptbits_from_host(int host_bits)
25928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int target_bits = 0;
25948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (host_bits & float_flag_invalid)
25968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        target_bits |= 1;
25978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (host_bits & float_flag_divbyzero)
25988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        target_bits |= 2;
25998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (host_bits & float_flag_overflow)
26008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        target_bits |= 4;
26015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (host_bits & (float_flag_underflow | float_flag_output_denormal))
26028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        target_bits |= 8;
26038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (host_bits & float_flag_inexact)
26048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        target_bits |= 0x10;
26055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (host_bits & float_flag_input_denormal)
26065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        target_bits |= 0x80;
26078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return target_bits;
26088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(vfp_get_fpscr)(CPUState *env)
26118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
26138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t fpscr;
26148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fpscr = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff)
26168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            | (env->vfp.vec_len << 16)
26178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            | (env->vfp.vec_stride << 20);
26188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    i = get_float_exception_flags(&env->vfp.fp_status);
26195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    i |= get_float_exception_flags(&env->vfp.standard_fp_status);
26208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fpscr |= vfp_exceptbits_from_host(i);
26218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return fpscr;
26228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26245285864985be9077e58e42235af6582dee72e841David 'Digit' Turneruint32_t vfp_get_fpscr(CPUState *env)
26255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
26265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return HELPER(vfp_get_fpscr)(env);
26275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
26285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
26298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Convert vfp exception flags to target form.  */
26308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline int vfp_exceptbits_to_host(int target_bits)
26318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int host_bits = 0;
26338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (target_bits & 1)
26358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        host_bits |= float_flag_invalid;
26368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (target_bits & 2)
26378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        host_bits |= float_flag_divbyzero;
26388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (target_bits & 4)
26398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        host_bits |= float_flag_overflow;
26408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (target_bits & 8)
26418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        host_bits |= float_flag_underflow;
26428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (target_bits & 0x10)
26438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        host_bits |= float_flag_inexact;
26445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (target_bits & 0x80)
26455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        host_bits |= float_flag_input_denormal;
26468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return host_bits;
26478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val)
26508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
26528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t changed;
26538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    changed = env->vfp.xregs[ARM_VFP_FPSCR];
26558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->vfp.xregs[ARM_VFP_FPSCR] = (val & 0xffc8ffff);
26568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->vfp.vec_len = (val >> 16) & 7;
26578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->vfp.vec_stride = (val >> 20) & 3;
26588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    changed ^= val;
26608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (changed & (3 << 22)) {
26618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        i = (val >> 22) & 3;
26628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (i) {
26638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
26648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            i = float_round_nearest_even;
26658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
26668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
26678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            i = float_round_up;
26688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
26698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
26708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            i = float_round_down;
26718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
26728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
26738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            i = float_round_to_zero;
26748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
26758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
26768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_float_rounding_mode(i, &env->vfp.fp_status);
26778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
26785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (changed & (1 << 24)) {
26795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        set_flush_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status);
26805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        set_flush_inputs_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status);
26815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
26825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (changed & (1 << 25))
26835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        set_default_nan_mode((val & (1 << 25)) != 0, &env->vfp.fp_status);
26848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    i = vfp_exceptbits_to_host(val);
26868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    set_float_exception_flags(i, &env->vfp.fp_status);
26875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    set_float_exception_flags(0, &env->vfp.standard_fp_status);
26885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
26895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
26905285864985be9077e58e42235af6582dee72e841David 'Digit' Turnervoid vfp_set_fpscr(CPUState *env, uint32_t val)
26915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
26925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    HELPER(vfp_set_fpscr)(env, val);
26938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
26968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_BINOP(name) \
26988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectfloat32 VFP_HELPER(name, s)(float32 a, float32 b, CPUState *env) \
26998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \
27008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return float32_ ## name (a, b, &env->vfp.fp_status); \
27018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} \
27028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectfloat64 VFP_HELPER(name, d)(float64 a, float64 b, CPUState *env) \
27038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \
27048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return float64_ ## name (a, b, &env->vfp.fp_status); \
27058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
27068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_BINOP(add)
27078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_BINOP(sub)
27088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_BINOP(mul)
27098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_BINOP(div)
27108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef VFP_BINOP
27118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectfloat32 VFP_HELPER(neg, s)(float32 a)
27138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
27148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return float32_chs(a);
27158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
27168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectfloat64 VFP_HELPER(neg, d)(float64 a)
27188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
27198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return float64_chs(a);
27208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
27218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectfloat32 VFP_HELPER(abs, s)(float32 a)
27238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
27248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return float32_abs(a);
27258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
27268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectfloat64 VFP_HELPER(abs, d)(float64 a)
27288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
27298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return float64_abs(a);
27308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
27318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectfloat32 VFP_HELPER(sqrt, s)(float32 a, CPUState *env)
27338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
27348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return float32_sqrt(a, &env->vfp.fp_status);
27358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
27368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectfloat64 VFP_HELPER(sqrt, d)(float64 a, CPUState *env)
27388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
27398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return float64_sqrt(a, &env->vfp.fp_status);
27408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
27418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* XXX: check quiet/signaling case */
27438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DO_VFP_cmp(p, type) \
27448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid VFP_HELPER(cmp, p)(type a, type b, CPUState *env)  \
27458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \
27468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t flags; \
27478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch(type ## _compare_quiet(a, b, &env->vfp.fp_status)) { \
27488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: flags = 0x6; break; \
27498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case -1: flags = 0x8; break; \
27508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: flags = 0x2; break; \
27518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: case 2: flags = 0x3; break; \
27528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } \
27538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \
27548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
27558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} \
27568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid VFP_HELPER(cmpe, p)(type a, type b, CPUState *env) \
27578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \
27588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t flags; \
27598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch(type ## _compare(a, b, &env->vfp.fp_status)) { \
27608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: flags = 0x6; break; \
27618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case -1: flags = 0x8; break; \
27628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: flags = 0x2; break; \
27638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: case 2: flags = 0x3; break; \
27648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } \
27658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \
27668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
27678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
27688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectDO_VFP_cmp(s, float32)
27698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectDO_VFP_cmp(d, float64)
27708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef DO_VFP_cmp
27718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Integer to float and float to integer conversions */
27738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define CONV_ITOF(name, fsz, sign) \
27755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float##fsz HELPER(name)(uint32_t x, void *fpstp) \
27765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ \
27775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float_status *fpst = fpstp; \
27785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return sign##int32_to_##float##fsz(x, fpst); \
27798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
27808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define CONV_FTOI(name, fsz, sign, round) \
27825285864985be9077e58e42235af6582dee72e841David 'Digit' Turneruint32_t HELPER(name)(float##fsz x, void *fpstp) \
27835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ \
27845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float_status *fpst = fpstp; \
27855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (float##fsz##_is_any_nan(x)) { \
27865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        float_raise(float_flag_invalid, fpst); \
27875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return 0; \
27885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } \
27895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return float##fsz##_to_##sign##int32##round(x, fpst); \
27908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
27918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define FLOAT_CONVS(name, p, fsz, sign) \
27935285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerCONV_ITOF(vfp_##name##to##p, fsz, sign) \
27945285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerCONV_FTOI(vfp_to##name##p, fsz, sign, ) \
27955285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerCONV_FTOI(vfp_to##name##z##p, fsz, sign, _round_to_zero)
27968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27975285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerFLOAT_CONVS(si, s, 32, )
27985285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerFLOAT_CONVS(si, d, 64, )
27995285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerFLOAT_CONVS(ui, s, 32, u)
28005285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerFLOAT_CONVS(ui, d, 64, u)
28018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef CONV_ITOF
28035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef CONV_FTOI
28045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef FLOAT_CONVS
28058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* floating point conversion */
28075285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerfloat64 VFP_HELPER(fcvtd, s)(float32 x, CPUState *env)
28088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
28095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float64 r = float32_to_float64(x, &env->vfp.fp_status);
28105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* ARM requires that S<->D conversion of any kind of NaN generates
28115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * a quiet NaN by forcing the most significant frac bit to 1.
28125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     */
28135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return float64_maybe_silence_nan(r);
28148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
28158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28165285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerfloat32 VFP_HELPER(fcvts, d)(float64 x, CPUState *env)
28178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
28185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float32 r =  float64_to_float32(x, &env->vfp.fp_status);
28195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* ARM requires that S<->D conversion of any kind of NaN generates
28205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * a quiet NaN by forcing the most significant frac bit to 1.
28215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     */
28225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return float32_maybe_silence_nan(r);
28238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
28248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* VFP3 fixed point conversion.  */
28265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define VFP_CONV_FIX(name, p, fsz, itype, sign) \
28275285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerfloat##fsz HELPER(vfp_##name##to##p)(uint##fsz##_t  x, uint32_t shift, \
28285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    void *fpstp) \
28295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ \
28305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float_status *fpst = fpstp; \
28315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float##fsz tmp; \
28325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = sign##int32_to_##float##fsz((itype##_t)x, fpst); \
28335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return float##fsz##_scalbn(tmp, -(int)shift, fpst); \
28345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} \
28355285864985be9077e58e42235af6582dee72e841David 'Digit' Turneruint##fsz##_t HELPER(vfp_to##name##p)(float##fsz x, uint32_t shift, \
28365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                       void *fpstp) \
28375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ \
28385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float_status *fpst = fpstp; \
28395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float##fsz tmp; \
28405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (float##fsz##_is_any_nan(x)) { \
28415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        float_raise(float_flag_invalid, fpst); \
28425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return 0; \
28435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } \
28445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = float##fsz##_scalbn(x, shift, fpst); \
28455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return float##fsz##_to_##itype##_round_to_zero(tmp, fpst); \
28465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
28475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
28485285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_CONV_FIX(sh, d, 64, int16, )
28495285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_CONV_FIX(sl, d, 64, int32, )
28505285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_CONV_FIX(uh, d, 64, uint16, u)
28515285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_CONV_FIX(ul, d, 64, uint32, u)
28525285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_CONV_FIX(sh, s, 32, int16, )
28535285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_CONV_FIX(sl, s, 32, int32, )
28545285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_CONV_FIX(uh, s, 32, uint16, u)
28555285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_CONV_FIX(ul, s, 32, uint32, u)
28565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef VFP_CONV_FIX
28578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Half precision conversions.  */
28595285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic float32 do_fcvt_f16_to_f32(uint32_t a, CPUState *env, float_status *s)
28608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
28615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
28625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float32 r = float16_to_float32(make_float16(a), ieee, s);
28635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (ieee) {
28645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return float32_maybe_silence_nan(r);
28655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
28665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return r;
28678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
28688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28695285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic uint32_t do_fcvt_f32_to_f16(float32 a, CPUState *env, float_status *s)
28708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
28715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
28725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float16 r = float32_to_float16(a, ieee, s);
28735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (ieee) {
28745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        r = float16_maybe_silence_nan(r);
28755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
28765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return float16_val(r);
28778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
28788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28795285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerfloat32 HELPER(neon_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
28808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
28815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return do_fcvt_f16_to_f32(a, env, &env->vfp.standard_fp_status);
28828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
28838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28845285864985be9077e58e42235af6582dee72e841David 'Digit' Turneruint32_t HELPER(neon_fcvt_f32_to_f16)(float32 a, CPUState *env)
28858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
28865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return do_fcvt_f32_to_f16(a, env, &env->vfp.standard_fp_status);
28878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
28888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28895285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerfloat32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
28908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
28915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return do_fcvt_f16_to_f32(a, env, &env->vfp.fp_status);
28928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
28938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28945285864985be9077e58e42235af6582dee72e841David 'Digit' Turneruint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUState *env)
28958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
28965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return do_fcvt_f32_to_f16(a, env, &env->vfp.fp_status);
28978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
28988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define float32_two make_float32(0x40000000)
29005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define float32_three make_float32(0x40400000)
29015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define float32_one_point_five make_float32(0x3fc00000)
29028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29035285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerfloat32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
29048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
29055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float_status *s = &env->vfp.standard_fp_status;
29065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
29075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
29085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (!(float32_is_zero(a) || float32_is_zero(b))) {
29095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            float_raise(float_flag_input_denormal, s);
29105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
29115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return float32_two;
29125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
29135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return float32_sub(float32_two, float32_mul(a, b, s), s);
29148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
29158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29165285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerfloat32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUState *env)
29178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
29185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float_status *s = &env->vfp.standard_fp_status;
29195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float32 product;
29205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
29215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
29225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (!(float32_is_zero(a) || float32_is_zero(b))) {
29235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            float_raise(float_flag_input_denormal, s);
29245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
29255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return float32_one_point_five;
29265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
29275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    product = float32_mul(a, b, s);
29285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return float32_div(float32_sub(float32_three, product, s), float32_two, s);
29298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
29308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* NEON helpers.  */
29325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
29335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Constants 256 and 512 are used in some helpers; we avoid relying on
29345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * int->float conversions at run-time.  */
29355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define float64_256 make_float64(0x4070000000000000LL)
29365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define float64_512 make_float64(0x4080000000000000LL)
29375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
29385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* The algorithm that must be used to calculate the estimate
29395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * is specified by the ARM ARM.
29405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */
29415285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic float64 recip_estimate(float64 a, CPUState *env)
29428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
29435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* These calculations mustn't set any fp exception flags,
29445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * so we use a local copy of the fp_status.
29455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     */
29465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float_status dummy_status = env->vfp.standard_fp_status;
29475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float_status *s = &dummy_status;
29485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* q = (int)(a * 512.0) */
29495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float64 q = float64_mul(float64_512, a, s);
29505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int64_t q_int = float64_to_int64_round_to_zero(q, s);
29515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
29525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* r = 1.0 / (((double)q + 0.5) / 512.0) */
29535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    q = int64_to_float64(q_int, s);
29545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    q = float64_add(q, float64_half, s);
29555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    q = float64_div(q, float64_512, s);
29565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    q = float64_div(float64_one, q, s);
29575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
29585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* s = (int)(256.0 * r + 0.5) */
29595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    q = float64_mul(q, float64_256, s);
29605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    q = float64_add(q, float64_half, s);
29615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    q_int = float64_to_int64_round_to_zero(q, s);
29625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
29635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* return (double)s / 256.0 */
29645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return float64_div(int64_to_float64(q_int, s), float64_256, s);
29658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
29668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29675285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerfloat32 HELPER(recpe_f32)(float32 a, CPUState *env)
29688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
29695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float_status *s = &env->vfp.standard_fp_status;
29705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float64 f64;
29715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    uint32_t val32 = float32_val(a);
29728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int result_exp;
29745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int a_exp = (val32  & 0x7f800000) >> 23;
29755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int sign = val32 & 0x80000000;
29768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (float32_is_any_nan(a)) {
29785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (float32_is_signaling_nan(a)) {
29795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            float_raise(float_flag_invalid, s);
29805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
29815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return float32_default_nan;
29825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else if (float32_is_infinity(a)) {
29835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return float32_set_sign(float32_zero, float32_is_neg(a));
29845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else if (float32_is_zero_or_denormal(a)) {
29855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (!float32_is_zero(a)) {
29865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            float_raise(float_flag_input_denormal, s);
29875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
29885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        float_raise(float_flag_divbyzero, s);
29895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return float32_set_sign(float32_infinity, float32_is_neg(a));
29905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else if (a_exp >= 253) {
29915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        float_raise(float_flag_underflow, s);
29925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return float32_set_sign(float32_zero, float32_is_neg(a));
29935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
29945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
29955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    f64 = make_float64((0x3feULL << 52)
29965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                       | ((int64_t)(val32 & 0x7fffff) << 29));
29975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
29985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    result_exp = 253 - a_exp;
29995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
30005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    f64 = recip_estimate(f64, env);
30015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
30025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    val32 = sign
30035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        | ((result_exp & 0xff) << 23)
30045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        | ((float64_val(f64) >> 29) & 0x7fffff);
30055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return make_float32(val32);
30068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
30078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
30085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* The algorithm that must be used to calculate the estimate
30095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * is specified by the ARM ARM.
30105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */
30115285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic float64 recip_sqrt_estimate(float64 a, CPUState *env)
30128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
30135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* These calculations mustn't set any fp exception flags,
30145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * so we use a local copy of the fp_status.
30155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     */
30165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float_status dummy_status = env->vfp.standard_fp_status;
30175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float_status *s = &dummy_status;
30185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float64 q;
30195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int64_t q_int;
30208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
30215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (float64_lt(a, float64_half, s)) {
30225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* range 0.25 <= a < 0.5 */
30238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
30245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* a in units of 1/512 rounded down */
30255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* q0 = (int)(a * 512.0);  */
30265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        q = float64_mul(float64_512, a, s);
30275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        q_int = float64_to_int64_round_to_zero(q, s);
30285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
30295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* reciprocal root r */
30305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* r = 1.0 / sqrt(((double)q0 + 0.5) / 512.0);  */
30315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        q = int64_to_float64(q_int, s);
30325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        q = float64_add(q, float64_half, s);
30335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        q = float64_div(q, float64_512, s);
30345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        q = float64_sqrt(q, s);
30355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        q = float64_div(float64_one, q, s);
30365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
30375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* range 0.5 <= a < 1.0 */
30385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
30395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* a in units of 1/256 rounded down */
30405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* q1 = (int)(a * 256.0); */
30415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        q = float64_mul(float64_256, a, s);
30425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        int64_t q_int = float64_to_int64_round_to_zero(q, s);
30435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
30445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* reciprocal root r */
30455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* r = 1.0 /sqrt(((double)q1 + 0.5) / 256); */
30465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        q = int64_to_float64(q_int, s);
30475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        q = float64_add(q, float64_half, s);
30485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        q = float64_div(q, float64_256, s);
30495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        q = float64_sqrt(q, s);
30505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        q = float64_div(float64_one, q, s);
30515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
30525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* r in units of 1/256 rounded to nearest */
30535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* s = (int)(256.0 * r + 0.5); */
30545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
30555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    q = float64_mul(q, float64_256,s );
30565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    q = float64_add(q, float64_half, s);
30575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    q_int = float64_to_int64_round_to_zero(q, s);
30585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
30595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* return (double)s / 256.0;*/
30605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return float64_div(int64_to_float64(q_int, s), float64_256, s);
30618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
30628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
30638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectfloat32 HELPER(rsqrte_f32)(float32 a, CPUState *env)
30648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
30655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float_status *s = &env->vfp.standard_fp_status;
30665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int result_exp;
30675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float64 f64;
30685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    uint32_t val;
30695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    uint64_t val64;
30705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
30715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    val = float32_val(a);
30725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
30735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (float32_is_any_nan(a)) {
30745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (float32_is_signaling_nan(a)) {
30755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            float_raise(float_flag_invalid, s);
30765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
30775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return float32_default_nan;
30785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else if (float32_is_zero_or_denormal(a)) {
30795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (!float32_is_zero(a)) {
30805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            float_raise(float_flag_input_denormal, s);
30815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
30825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        float_raise(float_flag_divbyzero, s);
30835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return float32_set_sign(float32_infinity, float32_is_neg(a));
30845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else if (float32_is_neg(a)) {
30855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        float_raise(float_flag_invalid, s);
30865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return float32_default_nan;
30875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else if (float32_is_infinity(a)) {
30885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return float32_zero;
30895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
30905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
30915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Normalize to a double-precision value between 0.25 and 1.0,
30925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * preserving the parity of the exponent.  */
30935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if ((val & 0x800000) == 0) {
30945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        f64 = make_float64(((uint64_t)(val & 0x80000000) << 32)
30955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                           | (0x3feULL << 52)
30965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                           | ((uint64_t)(val & 0x7fffff) << 29));
30975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
30985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        f64 = make_float64(((uint64_t)(val & 0x80000000) << 32)
30995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                           | (0x3fdULL << 52)
31005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                           | ((uint64_t)(val & 0x7fffff) << 29));
31015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
31025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
31035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    result_exp = (380 - ((val & 0x7f800000) >> 23)) / 2;
31045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
31055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    f64 = recip_sqrt_estimate(f64, env);
31065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
31075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    val64 = float64_val(f64);
31085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
31095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    val = ((val64 >> 63)  & 0x80000000)
31105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        | ((result_exp & 0xff) << 23)
31115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        | ((val64 >> 29)  & 0x7fffff);
31125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return make_float32(val);
31138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
31148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
31158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(recpe_u32)(uint32_t a, CPUState *env)
31168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
31175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float64 f64;
31185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
31195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if ((a & 0x80000000) == 0) {
31205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return 0xffffffff;
31215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
31225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
31235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    f64 = make_float64((0x3feULL << 52)
31245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                       | ((int64_t)(a & 0x7fffffff) << 21));
31255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
31265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    f64 = recip_estimate (f64, env);
31275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
31285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return 0x80000000 | ((float64_val(f64) >> 21) & 0x7fffffff);
31298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
31308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
31318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(rsqrte_u32)(uint32_t a, CPUState *env)
31328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
31335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    float64 f64;
31345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
31355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if ((a & 0xc0000000) == 0) {
31365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return 0xffffffff;
31375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
31385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
31395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (a & 0x80000000) {
31405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        f64 = make_float64((0x3feULL << 52)
31415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                           | ((uint64_t)(a & 0x7fffffff) << 21));
31425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else { /* bits 31-30 == '01' */
31435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        f64 = make_float64((0x3fdULL << 52)
31445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                           | ((uint64_t)(a & 0x3fffffff) << 22));
31455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
31465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
31475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    f64 = recip_sqrt_estimate(f64, env);
31485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
31495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return 0x80000000 | ((float64_val(f64) >> 21) & 0x7fffffff);
31508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
31518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
31525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid HELPER(set_teecr)(CPUState *env, uint32_t val)
31535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
31545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    val &= 1;
31555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (env->teecr != val) {
31565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        env->teecr = val;
31575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tb_flush(env);
31585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
31595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3160