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