102
101
cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF");
103
102
cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF");
105
cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0,
104
cpu_exclusive_addr = tcg_global_mem_new_i64(TCG_AREG0,
106
105
offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
107
cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0,
106
cpu_exclusive_val = tcg_global_mem_new_i64(TCG_AREG0,
108
107
offsetof(CPUARMState, exclusive_val), "exclusive_val");
109
cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0,
110
offsetof(CPUARMState, exclusive_high), "exclusive_high");
111
108
#ifdef CONFIG_USER_ONLY
112
cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0,
109
cpu_exclusive_test = tcg_global_mem_new_i64(TCG_AREG0,
113
110
offsetof(CPUARMState, exclusive_test), "exclusive_test");
114
111
cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
115
112
offsetof(CPUARMState, exclusive_info), "exclusive_info");
1113
1110
VFP_GEN_FTOI(tosiz)
1114
1111
#undef VFP_GEN_FTOI
1116
#define VFP_GEN_FIX(name) \
1113
#define VFP_GEN_FIX(name, round) \
1117
1114
static inline void gen_vfp_##name(int dp, int shift, int neon) \
1119
1116
TCGv_i32 tmp_shift = tcg_const_i32(shift); \
1120
1117
TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1122
gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \
1119
gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
1124
gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, statusptr); \
1122
gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
1126
1125
tcg_temp_free_i32(tmp_shift); \
1127
1126
tcg_temp_free_ptr(statusptr); \
1128
VFP_GEN_FIX(tosh, _round_to_zero)
1129
VFP_GEN_FIX(tosl, _round_to_zero)
1130
VFP_GEN_FIX(touh, _round_to_zero)
1131
VFP_GEN_FIX(toul, _round_to_zero)
1137
1136
#undef VFP_GEN_FIX
1139
1138
static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
2740
2739
tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2741
2740
tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2743
gen_helper_vfp_minnmd(dest, frn, frm, fpst);
2742
gen_helper_vfp_minnumd(dest, frn, frm, fpst);
2745
gen_helper_vfp_maxnmd(dest, frn, frm, fpst);
2744
gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
2747
2746
tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2748
2747
tcg_temp_free_i64(frn);
2758
2757
tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2759
2758
tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2761
gen_helper_vfp_minnms(dest, frn, frm, fpst);
2760
gen_helper_vfp_minnums(dest, frn, frm, fpst);
2763
gen_helper_vfp_maxnms(dest, frn, frm, fpst);
2762
gen_helper_vfp_maxnums(dest, frn, frm, fpst);
2765
2764
tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2766
2765
tcg_temp_free_i32(frn);
2774
static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
2777
TCGv_ptr fpst = get_fpstatus_ptr(0);
2780
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
2781
gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2786
tcg_op = tcg_temp_new_i64();
2787
tcg_res = tcg_temp_new_i64();
2788
tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
2789
gen_helper_rintd(tcg_res, tcg_op, fpst);
2790
tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
2791
tcg_temp_free_i64(tcg_op);
2792
tcg_temp_free_i64(tcg_res);
2796
tcg_op = tcg_temp_new_i32();
2797
tcg_res = tcg_temp_new_i32();
2798
tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
2799
gen_helper_rints(tcg_res, tcg_op, fpst);
2800
tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
2801
tcg_temp_free_i32(tcg_op);
2802
tcg_temp_free_i32(tcg_res);
2805
gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2806
tcg_temp_free_i32(tcg_rmode);
2808
tcg_temp_free_ptr(fpst);
2812
static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
2815
bool is_signed = extract32(insn, 7, 1);
2816
TCGv_ptr fpst = get_fpstatus_ptr(0);
2817
TCGv_i32 tcg_rmode, tcg_shift;
2819
tcg_shift = tcg_const_i32(0);
2821
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
2822
gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2825
TCGv_i64 tcg_double, tcg_res;
2827
/* Rd is encoded as a single precision register even when the source
2828
* is double precision.
2830
rd = ((rd << 1) & 0x1e) | ((rd >> 4) & 0x1);
2831
tcg_double = tcg_temp_new_i64();
2832
tcg_res = tcg_temp_new_i64();
2833
tcg_tmp = tcg_temp_new_i32();
2834
tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
2836
gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
2838
gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
2840
tcg_gen_trunc_i64_i32(tcg_tmp, tcg_res);
2841
tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
2842
tcg_temp_free_i32(tcg_tmp);
2843
tcg_temp_free_i64(tcg_res);
2844
tcg_temp_free_i64(tcg_double);
2846
TCGv_i32 tcg_single, tcg_res;
2847
tcg_single = tcg_temp_new_i32();
2848
tcg_res = tcg_temp_new_i32();
2849
tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
2851
gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
2853
gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
2855
tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
2856
tcg_temp_free_i32(tcg_res);
2857
tcg_temp_free_i32(tcg_single);
2860
gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2861
tcg_temp_free_i32(tcg_rmode);
2863
tcg_temp_free_i32(tcg_shift);
2865
tcg_temp_free_ptr(fpst);
2870
/* Table for converting the most common AArch32 encoding of
2871
* rounding mode to arm_fprounding order (which matches the
2872
* common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
2874
static const uint8_t fp_decode_rm[] = {
2775
2881
static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
2777
2883
uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
2794
2900
return handle_vsel(insn, rd, rn, rm, dp);
2795
2901
} else if ((insn & 0x0fb00e10) == 0x0e800a00) {
2796
2902
return handle_vminmaxnm(insn, rd, rn, rm, dp);
2903
} else if ((insn & 0x0fbc0ed0) == 0x0eb80a40) {
2904
/* VRINTA, VRINTN, VRINTP, VRINTM */
2905
int rounding = fp_decode_rm[extract32(insn, 16, 2)];
2906
return handle_vrint(insn, rd, rm, dp, rounding);
2907
} else if ((insn & 0x0fbc0e50) == 0x0ebc0a40) {
2908
/* VCVTA, VCVTN, VCVTP, VCVTM */
2909
int rounding = fp_decode_rm[extract32(insn, 16, 2)];
2910
return handle_vcvt(insn, rd, rm, dp, rounding);
3142
/* VCVTB, VCVTT: only present with the halfprec extension,
3143
* UNPREDICTABLE if bit 8 is set (we choose to UNDEF)
3259
/* VCVTB, VCVTT: only present with the halfprec extension
3260
* UNPREDICTABLE if bit 8 is set prior to ARMv8
3261
* (we choose to UNDEF)
3145
if (dp || !arm_feature(env, ARM_FEATURE_VFP_FP16)) {
3263
if ((dp && !arm_feature(env, ARM_FEATURE_V8)) ||
3264
!arm_feature(env, ARM_FEATURE_VFP_FP16)) {
3267
if (!extract32(rn, 1, 1)) {
3268
/* Half precision source. */
3269
gen_mov_F0_vreg(0, rm);
3148
3272
/* Otherwise fall through */
3150
3274
/* One source operand. */
3292
3416
case 3: /* sqrt */
3293
3417
gen_vfp_sqrt(dp);
3295
case 4: /* vcvtb.f32.f16 */
3419
case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */
3296
3420
tmp = gen_vfp_mrs();
3297
3421
tcg_gen_ext16u_i32(tmp, tmp);
3298
gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3423
gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3426
gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3299
3429
tcg_temp_free_i32(tmp);
3301
case 5: /* vcvtt.f32.f16 */
3431
case 5: /* vcvtt.f32.f16, vcvtt.f64.f16 */
3302
3432
tmp = gen_vfp_mrs();
3303
3433
tcg_gen_shri_i32(tmp, tmp, 16);
3304
gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3435
gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3438
gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3305
3441
tcg_temp_free_i32(tmp);
3307
case 6: /* vcvtb.f16.f32 */
3443
case 6: /* vcvtb.f16.f32, vcvtb.f16.f64 */
3308
3444
tmp = tcg_temp_new_i32();
3309
gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3446
gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3449
gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3310
3452
gen_mov_F0_vreg(0, rd);
3311
3453
tmp2 = gen_vfp_mrs();
3312
3454
tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3338
3486
gen_vfp_F1_ld0(dp);
3339
3487
gen_vfp_cmpe(dp);
3489
case 12: /* vrintr */
3491
TCGv_ptr fpst = get_fpstatus_ptr(0);
3493
gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3495
gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3497
tcg_temp_free_ptr(fpst);
3500
case 13: /* vrintz */
3502
TCGv_ptr fpst = get_fpstatus_ptr(0);
3504
tcg_rmode = tcg_const_i32(float_round_to_zero);
3505
gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3507
gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3509
gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3511
gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3512
tcg_temp_free_i32(tcg_rmode);
3513
tcg_temp_free_ptr(fpst);
3516
case 14: /* vrintx */
3518
TCGv_ptr fpst = get_fpstatus_ptr(0);
3520
gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);
3522
gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);
3524
tcg_temp_free_ptr(fpst);
3341
3527
case 15: /* single<->double conversion */
3343
3529
gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3413
3599
/* Write back the result. */
3414
if (op == 15 && (rn >= 8 && rn <= 11))
3415
; /* Comparison, do nothing. */
3416
else if (op == 15 && dp && ((rn & 0x1c) == 0x18))
3417
/* VCVT double to int: always integer result. */
3600
if (op == 15 && (rn >= 8 && rn <= 11)) {
3601
/* Comparison, do nothing. */
3602
} else if (op == 15 && dp && ((rn & 0x1c) == 0x18 ||
3603
(rn & 0x1e) == 0x6)) {
3604
/* VCVT double to int: always integer result.
3605
* VCVT double to half precision is always a single
3418
3608
gen_mov_vreg_F0(0, rd);
3419
else if (op == 15 && rn == 15)
3609
} else if (op == 15 && rn == 15) {
3420
3610
/* conversion */
3421
3611
gen_mov_vreg_F0(!dp, rd);
3423
3613
gen_mov_vreg_F0(dp, rd);
3425
3616
/* break out of the loop if we have finished */
3426
3617
if (veclen == 0)
4628
4819
#define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4629
4820
#define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4630
4821
#define NEON_2RM_VSHLL 38
4822
#define NEON_2RM_VRINTN 40
4823
#define NEON_2RM_VRINTX 41
4824
#define NEON_2RM_VRINTA 42
4825
#define NEON_2RM_VRINTZ 43
4631
4826
#define NEON_2RM_VCVT_F16_F32 44
4827
#define NEON_2RM_VRINTM 45
4632
4828
#define NEON_2RM_VCVT_F32_F16 46
4829
#define NEON_2RM_VRINTP 47
4830
#define NEON_2RM_VCVTAU 48
4831
#define NEON_2RM_VCVTAS 49
4832
#define NEON_2RM_VCVTNU 50
4833
#define NEON_2RM_VCVTNS 51
4834
#define NEON_2RM_VCVTPU 52
4835
#define NEON_2RM_VCVTPS 53
4836
#define NEON_2RM_VCVTMU 54
4837
#define NEON_2RM_VCVTMS 55
4633
4838
#define NEON_2RM_VRECPE 56
4634
4839
#define NEON_2RM_VRSQRTE 57
4635
4840
#define NEON_2RM_VRECPE_F 58
6376
6598
neon_store_reg(rm, pass, tmp2);
6600
case NEON_2RM_VRINTN:
6601
case NEON_2RM_VRINTA:
6602
case NEON_2RM_VRINTM:
6603
case NEON_2RM_VRINTP:
6604
case NEON_2RM_VRINTZ:
6607
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6610
if (op == NEON_2RM_VRINTZ) {
6611
rmode = FPROUNDING_ZERO;
6613
rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
6616
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6617
gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6619
gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
6620
gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6622
tcg_temp_free_ptr(fpstatus);
6623
tcg_temp_free_i32(tcg_rmode);
6626
case NEON_2RM_VRINTX:
6628
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6629
gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
6630
tcg_temp_free_ptr(fpstatus);
6633
case NEON_2RM_VCVTAU:
6634
case NEON_2RM_VCVTAS:
6635
case NEON_2RM_VCVTNU:
6636
case NEON_2RM_VCVTNS:
6637
case NEON_2RM_VCVTPU:
6638
case NEON_2RM_VCVTPS:
6639
case NEON_2RM_VCVTMU:
6640
case NEON_2RM_VCVTMS:
6642
bool is_signed = !extract32(insn, 7, 1);
6643
TCGv_ptr fpst = get_fpstatus_ptr(1);
6644
TCGv_i32 tcg_rmode, tcg_shift;
6645
int rmode = fp_decode_rm[extract32(insn, 8, 2)];
6647
tcg_shift = tcg_const_i32(0);
6648
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6649
gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6653
gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
6656
gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
6660
gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6662
tcg_temp_free_i32(tcg_rmode);
6663
tcg_temp_free_i32(tcg_shift);
6664
tcg_temp_free_ptr(fpst);
6378
6667
case NEON_2RM_VRECPE:
6379
6668
gen_helper_recpe_u32(tmp, tmp, cpu_env);
6748
tcg_gen_mov_i32(cpu_exclusive_val, tmp);
7038
TCGv_i32 tmp2 = tcg_temp_new_i32();
7039
TCGv_i32 tmp3 = tcg_temp_new_i32();
7041
tcg_gen_addi_i32(tmp2, addr, 4);
7042
gen_aa32_ld32u(tmp3, tmp2, IS_USER(s));
7043
tcg_temp_free_i32(tmp2);
7044
tcg_gen_concat_i32_i64(cpu_exclusive_val, tmp, tmp3);
7045
store_reg(s, rt2, tmp3);
7047
tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
6749
7050
store_reg(s, rt, tmp);
6751
TCGv_i32 tmp2 = tcg_temp_new_i32();
6752
tcg_gen_addi_i32(tmp2, addr, 4);
6753
tmp = tcg_temp_new_i32();
6754
gen_aa32_ld32u(tmp, tmp2, IS_USER(s));
6755
tcg_temp_free_i32(tmp2);
6756
tcg_gen_mov_i32(cpu_exclusive_high, tmp);
6757
store_reg(s, rt2, tmp);
6759
tcg_gen_mov_i32(cpu_exclusive_addr, addr);
7051
tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
6762
7054
static void gen_clrex(DisasContext *s)
6764
tcg_gen_movi_i32(cpu_exclusive_addr, -1);
7056
tcg_gen_movi_i64(cpu_exclusive_addr, -1);
6767
7059
#ifdef CONFIG_USER_ONLY
6768
7060
static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6769
7061
TCGv_i32 addr, int size)
6771
tcg_gen_mov_i32(cpu_exclusive_test, addr);
7063
tcg_gen_extu_i32_i64(cpu_exclusive_test, addr);
6772
7064
tcg_gen_movi_i32(cpu_exclusive_info,
6773
7065
size | (rd << 4) | (rt << 8) | (rt2 << 12));
6774
7066
gen_exception_insn(s, 4, EXCP_STREX);
6808
tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
6809
tcg_temp_free_i32(tmp);
7106
val64 = tcg_temp_new_i64();
6810
7107
if (size == 3) {
6811
7108
TCGv_i32 tmp2 = tcg_temp_new_i32();
7109
TCGv_i32 tmp3 = tcg_temp_new_i32();
6812
7110
tcg_gen_addi_i32(tmp2, addr, 4);
6813
tmp = tcg_temp_new_i32();
6814
gen_aa32_ld32u(tmp, tmp2, IS_USER(s));
7111
gen_aa32_ld32u(tmp3, tmp2, IS_USER(s));
6815
7112
tcg_temp_free_i32(tmp2);
6816
tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
6817
tcg_temp_free_i32(tmp);
7113
tcg_gen_concat_i32_i64(val64, tmp, tmp3);
7114
tcg_temp_free_i32(tmp3);
7116
tcg_gen_extu_i32_i64(val64, tmp);
7118
tcg_temp_free_i32(tmp);
7120
tcg_gen_brcond_i64(TCG_COND_NE, val64, cpu_exclusive_val, fail_label);
7121
tcg_temp_free_i64(val64);
6819
7123
tmp = load_reg(s, rt);
6820
7124
switch (size) {