diff options
Diffstat (limited to 'target-arm/translate.c')
-rw-r--r-- | target-arm/translate.c | 95 |
1 files changed, 87 insertions, 8 deletions
diff --git a/target-arm/translate.c b/target-arm/translate.c index 0650bc3a2..2b5e5c8dd 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -3001,6 +3001,10 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) case 21: case 22: case 23: + case 28: + case 29: + case 30: + case 31: /* Source and destination the same. */ gen_mov_F0_vreg(dp, rd); break; @@ -3120,22 +3124,22 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) case 20: /* fshto */ if (!arm_feature(env, ARM_FEATURE_VFP3)) return 1; - gen_vfp_shto(dp, rm); + gen_vfp_shto(dp, 16 - rm); break; case 21: /* fslto */ if (!arm_feature(env, ARM_FEATURE_VFP3)) return 1; - gen_vfp_slto(dp, rm); + gen_vfp_slto(dp, 32 - rm); break; case 22: /* fuhto */ if (!arm_feature(env, ARM_FEATURE_VFP3)) return 1; - gen_vfp_uhto(dp, rm); + gen_vfp_uhto(dp, 16 - rm); break; case 23: /* fulto */ if (!arm_feature(env, ARM_FEATURE_VFP3)) return 1; - gen_vfp_ulto(dp, rm); + gen_vfp_ulto(dp, 32 - rm); break; case 24: /* ftoui */ gen_vfp_toui(dp); @@ -3152,22 +3156,22 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) case 28: /* ftosh */ if (!arm_feature(env, ARM_FEATURE_VFP3)) return 1; - gen_vfp_tosh(dp, rm); + gen_vfp_tosh(dp, 16 - rm); break; case 29: /* ftosl */ if (!arm_feature(env, ARM_FEATURE_VFP3)) return 1; - gen_vfp_tosl(dp, rm); + gen_vfp_tosl(dp, 32 - rm); break; case 30: /* ftouh */ if (!arm_feature(env, ARM_FEATURE_VFP3)) return 1; - gen_vfp_touh(dp, rm); + gen_vfp_touh(dp, 16 - rm); break; case 31: /* ftoul */ if (!arm_feature(env, ARM_FEATURE_VFP3)) return 1; - gen_vfp_toul(dp, rm); + gen_vfp_toul(dp, 32 - rm); break; default: /* undefined */ printf ("rn:%d\n", rn); @@ -5532,6 +5536,71 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) return 0; } +static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn) +{ + int crn = (insn >> 16) & 0xf; + int crm = insn & 0xf; + int op1 = (insn >> 21) & 7; + int op2 = (insn >> 5) & 7; + int rt = (insn >> 12) & 0xf; + TCGv tmp; + + if (arm_feature(env, ARM_FEATURE_THUMB2EE)) { + if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) { + /* TEECR */ + if (IS_USER(s)) + return 1; + tmp = load_cpu_field(teecr); + store_reg(s, rt, tmp); + return 0; + } + if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) { + /* TEEHBR */ + if (IS_USER(s) && (env->teecr & 1)) + return 1; + tmp = load_cpu_field(teehbr); + store_reg(s, rt, tmp); + return 0; + } + } + fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n", + op1, crn, crm, op2); + return 1; +} + +static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn) +{ + int crn = (insn >> 16) & 0xf; + int crm = insn & 0xf; + int op1 = (insn >> 21) & 7; + int op2 = (insn >> 5) & 7; + int rt = (insn >> 12) & 0xf; + TCGv tmp; + + if (arm_feature(env, ARM_FEATURE_THUMB2EE)) { + if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) { + /* TEECR */ + if (IS_USER(s)) + return 1; + tmp = load_reg(s, rt); + gen_helper_set_teecr(cpu_env, tmp); + dead_tmp(tmp); + return 0; + } + if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) { + /* TEEHBR */ + if (IS_USER(s) && (env->teecr & 1)) + return 1; + tmp = load_reg(s, rt); + store_cpu_field(tmp, teehbr); + return 0; + } + } + fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n", + op1, crn, crm, op2); + return 1; +} + static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn) { int cpnum; @@ -5553,9 +5622,19 @@ static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn) case 10: case 11: return disas_vfp_insn (env, s, insn); + case 14: + /* Coprocessors 7-15 are architecturally reserved by ARM. + Unfortunately Intel decided to ignore this. */ + if (arm_feature(env, ARM_FEATURE_XSCALE)) + goto board; + if (insn & (1 << 20)) + return disas_cp14_read(env, s, insn); + else + return disas_cp14_write(env, s, insn); case 15: return disas_cp15_insn (env, s, insn); default: + board: /* Unknown coprocessor. See if the board has hooked it. */ return disas_cp_insn (env, s, insn); } |