diff options
Diffstat (limited to 'target-arm/translate.c')
| -rw-r--r-- | target-arm/translate.c | 112 |
1 files changed, 64 insertions, 48 deletions
diff --git a/target-arm/translate.c b/target-arm/translate.c index 1403ecf216..8d240e160d 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -61,11 +61,10 @@ TCGv_ptr cpu_env; static TCGv_i64 cpu_V0, cpu_V1, cpu_M0; static TCGv_i32 cpu_R[16]; static TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF; -static TCGv_i32 cpu_exclusive_addr; -static TCGv_i32 cpu_exclusive_val; -static TCGv_i32 cpu_exclusive_high; +static TCGv_i64 cpu_exclusive_addr; +static TCGv_i64 cpu_exclusive_val; #ifdef CONFIG_USER_ONLY -static TCGv_i32 cpu_exclusive_test; +static TCGv_i64 cpu_exclusive_test; static TCGv_i32 cpu_exclusive_info; #endif @@ -96,14 +95,12 @@ void arm_translate_init(void) cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF"); cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF"); - cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0, + cpu_exclusive_addr = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUARMState, exclusive_addr), "exclusive_addr"); - cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0, + cpu_exclusive_val = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUARMState, exclusive_val), "exclusive_val"); - cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0, - offsetof(CPUARMState, exclusive_high), "exclusive_high"); #ifdef CONFIG_USER_ONLY - cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0, + cpu_exclusive_test = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUARMState, exclusive_test), "exclusive_test"); cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, exclusive_info), "exclusive_info"); @@ -1101,27 +1098,29 @@ VFP_GEN_FTOI(tosi) VFP_GEN_FTOI(tosiz) #undef VFP_GEN_FTOI -#define VFP_GEN_FIX(name) \ +#define VFP_GEN_FIX(name, round) \ static inline void gen_vfp_##name(int dp, int shift, int neon) \ { \ TCGv_i32 tmp_shift = tcg_const_i32(shift); \ TCGv_ptr statusptr = get_fpstatus_ptr(neon); \ if (dp) { \ - gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \ + gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \ + statusptr); \ } else { \ - gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, statusptr); \ + gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \ + statusptr); \ } \ tcg_temp_free_i32(tmp_shift); \ tcg_temp_free_ptr(statusptr); \ } -VFP_GEN_FIX(tosh) -VFP_GEN_FIX(tosl) -VFP_GEN_FIX(touh) -VFP_GEN_FIX(toul) -VFP_GEN_FIX(shto) -VFP_GEN_FIX(slto) -VFP_GEN_FIX(uhto) -VFP_GEN_FIX(ulto) +VFP_GEN_FIX(tosh, _round_to_zero) +VFP_GEN_FIX(tosl, _round_to_zero) +VFP_GEN_FIX(touh, _round_to_zero) +VFP_GEN_FIX(toul, _round_to_zero) +VFP_GEN_FIX(shto, ) +VFP_GEN_FIX(slto, ) +VFP_GEN_FIX(uhto, ) +VFP_GEN_FIX(ulto, ) #undef VFP_GEN_FIX static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr) @@ -2728,9 +2727,9 @@ static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn, tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn)); tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm)); if (vmin) { - gen_helper_vfp_minnmd(dest, frn, frm, fpst); + gen_helper_vfp_minnumd(dest, frn, frm, fpst); } else { - gen_helper_vfp_maxnmd(dest, frn, frm, fpst); + gen_helper_vfp_maxnumd(dest, frn, frm, fpst); } tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd)); tcg_temp_free_i64(frn); @@ -2746,9 +2745,9 @@ static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn, tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn)); tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm)); if (vmin) { - gen_helper_vfp_minnms(dest, frn, frm, fpst); + gen_helper_vfp_minnums(dest, frn, frm, fpst); } else { - gen_helper_vfp_maxnms(dest, frn, frm, fpst); + gen_helper_vfp_maxnums(dest, frn, frm, fpst); } tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd)); tcg_temp_free_i32(frn); @@ -5124,9 +5123,9 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins { TCGv_ptr fpstatus = get_fpstatus_ptr(1); if (size == 0) { - gen_helper_neon_max_f32(tmp, tmp, tmp2, fpstatus); + gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus); } else { - gen_helper_neon_min_f32(tmp, tmp, tmp2, fpstatus); + gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus); } tcg_temp_free_ptr(fpstatus); break; @@ -5136,9 +5135,9 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins /* VMAXNM/VMINNM */ TCGv_ptr fpstatus = get_fpstatus_ptr(1); if (size == 0) { - gen_helper_vfp_maxnms(tmp, tmp, tmp2, fpstatus); + gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus); } else { - gen_helper_vfp_minnms(tmp, tmp, tmp2, fpstatus); + gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus); } tcg_temp_free_ptr(fpstatus); } else { @@ -6498,7 +6497,6 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn) { int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2; const ARMCPRegInfo *ri; - ARMCPU *cpu = arm_env_get_cpu(env); cpnum = (insn >> 8) & 0xf; if (arm_feature(env, ARM_FEATURE_XSCALE) @@ -6541,11 +6539,11 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn) isread = (insn >> 20) & 1; rt = (insn >> 12) & 0xf; - ri = get_arm_cp_reginfo(cpu, + ri = get_arm_cp_reginfo(s->cp_regs, ENCODE_CP_REG(cpnum, is64, crn, crm, opc1, opc2)); if (ri) { /* Check access permissions */ - if (!cp_access_ok(env, ri, isread)) { + if (!cp_access_ok(s->current_pl, ri, isread)) { return 1; } @@ -6759,30 +6757,34 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2, default: abort(); } - tcg_gen_mov_i32(cpu_exclusive_val, tmp); - store_reg(s, rt, tmp); + if (size == 3) { TCGv_i32 tmp2 = tcg_temp_new_i32(); + TCGv_i32 tmp3 = tcg_temp_new_i32(); + tcg_gen_addi_i32(tmp2, addr, 4); - tmp = tcg_temp_new_i32(); - gen_aa32_ld32u(tmp, tmp2, IS_USER(s)); + gen_aa32_ld32u(tmp3, tmp2, IS_USER(s)); tcg_temp_free_i32(tmp2); - tcg_gen_mov_i32(cpu_exclusive_high, tmp); - store_reg(s, rt2, tmp); + tcg_gen_concat_i32_i64(cpu_exclusive_val, tmp, tmp3); + store_reg(s, rt2, tmp3); + } else { + tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp); } - tcg_gen_mov_i32(cpu_exclusive_addr, addr); + + store_reg(s, rt, tmp); + tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr); } static void gen_clrex(DisasContext *s) { - tcg_gen_movi_i32(cpu_exclusive_addr, -1); + tcg_gen_movi_i64(cpu_exclusive_addr, -1); } #ifdef CONFIG_USER_ONLY static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, TCGv_i32 addr, int size) { - tcg_gen_mov_i32(cpu_exclusive_test, addr); + tcg_gen_extu_i32_i64(cpu_exclusive_test, addr); tcg_gen_movi_i32(cpu_exclusive_info, size | (rd << 4) | (rt << 8) | (rt2 << 12)); gen_exception_insn(s, 4, EXCP_STREX); @@ -6792,6 +6794,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, TCGv_i32 addr, int size) { TCGv_i32 tmp; + TCGv_i64 val64, extaddr; int done_label; int fail_label; @@ -6803,7 +6806,11 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, } */ fail_label = gen_new_label(); done_label = gen_new_label(); - tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label); + extaddr = tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(extaddr, addr); + tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label); + tcg_temp_free_i64(extaddr); + tmp = tcg_temp_new_i32(); switch (size) { case 0: @@ -6819,17 +6826,24 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, default: abort(); } - tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label); - tcg_temp_free_i32(tmp); + + val64 = tcg_temp_new_i64(); if (size == 3) { TCGv_i32 tmp2 = tcg_temp_new_i32(); + TCGv_i32 tmp3 = tcg_temp_new_i32(); tcg_gen_addi_i32(tmp2, addr, 4); - tmp = tcg_temp_new_i32(); - gen_aa32_ld32u(tmp, tmp2, IS_USER(s)); + gen_aa32_ld32u(tmp3, tmp2, IS_USER(s)); tcg_temp_free_i32(tmp2); - tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label); - tcg_temp_free_i32(tmp); + tcg_gen_concat_i32_i64(val64, tmp, tmp3); + tcg_temp_free_i32(tmp3); + } else { + tcg_gen_extu_i32_i64(val64, tmp); } + tcg_temp_free_i32(tmp); + + tcg_gen_brcond_i64(TCG_COND_NE, val64, cpu_exclusive_val, fail_label); + tcg_temp_free_i64(val64); + tmp = load_reg(s, rt); switch (size) { case 0: @@ -6857,7 +6871,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, gen_set_label(fail_label); tcg_gen_movi_i32(cpu_R[rd], 1); gen_set_label(done_label); - tcg_gen_movi_i32(cpu_exclusive_addr, -1); + tcg_gen_movi_i64(cpu_exclusive_addr, -1); } #endif @@ -10269,6 +10283,8 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags); dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags); dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags); + dc->cp_regs = cpu->cp_regs; + dc->current_pl = arm_current_pl(env); cpu_F0s = tcg_temp_new_i32(); cpu_F1s = tcg_temp_new_i32(); |