aboutsummaryrefslogtreecommitdiff
path: root/target/arm/tcg/translate-a64.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/arm/tcg/translate-a64.c')
-rw-r--r--target/arm/tcg/translate-a64.c168
1 files changed, 73 insertions, 95 deletions
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 2c2ea45b47..dff391bfe2 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -6146,13 +6146,12 @@ static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
case 0xb: /* FRINTZ */
case 0xc: /* FRINTA */
{
- TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
- fpst = fpstatus_ptr(FPST_FPCR_F16);
+ TCGv_i32 tcg_rmode;
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
+ fpst = fpstatus_ptr(FPST_FPCR_F16);
+ tcg_rmode = gen_set_rmode(opcode & 7, fpst);
gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
-
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
+ gen_restore_rmode(tcg_rmode, fpst);
break;
}
case 0xe: /* FRINTX */
@@ -6202,7 +6201,7 @@ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
case 0xa: /* FRINTM */
case 0xb: /* FRINTZ */
case 0xc: /* FRINTA */
- rmode = arm_rmode_to_sf(opcode & 7);
+ rmode = opcode & 7;
gen_fpst = gen_helper_rints;
break;
case 0xe: /* FRINTX */
@@ -6212,14 +6211,14 @@ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
gen_fpst = gen_helper_rints;
break;
case 0x10: /* FRINT32Z */
- rmode = float_round_to_zero;
+ rmode = FPROUNDING_ZERO;
gen_fpst = gen_helper_frint32_s;
break;
case 0x11: /* FRINT32X */
gen_fpst = gen_helper_frint32_s;
break;
case 0x12: /* FRINT64Z */
- rmode = float_round_to_zero;
+ rmode = FPROUNDING_ZERO;
gen_fpst = gen_helper_frint64_s;
break;
case 0x13: /* FRINT64X */
@@ -6231,10 +6230,9 @@ static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
fpst = fpstatus_ptr(FPST_FPCR);
if (rmode >= 0) {
- TCGv_i32 tcg_rmode = tcg_const_i32(rmode);
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
+ TCGv_i32 tcg_rmode = gen_set_rmode(rmode, fpst);
gen_fpst(tcg_res, tcg_op, fpst);
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
+ gen_restore_rmode(tcg_rmode, fpst);
} else {
gen_fpst(tcg_res, tcg_op, fpst);
}
@@ -6275,7 +6273,7 @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
case 0xa: /* FRINTM */
case 0xb: /* FRINTZ */
case 0xc: /* FRINTA */
- rmode = arm_rmode_to_sf(opcode & 7);
+ rmode = opcode & 7;
gen_fpst = gen_helper_rintd;
break;
case 0xe: /* FRINTX */
@@ -6285,14 +6283,14 @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
gen_fpst = gen_helper_rintd;
break;
case 0x10: /* FRINT32Z */
- rmode = float_round_to_zero;
+ rmode = FPROUNDING_ZERO;
gen_fpst = gen_helper_frint32_d;
break;
case 0x11: /* FRINT32X */
gen_fpst = gen_helper_frint32_d;
break;
case 0x12: /* FRINT64Z */
- rmode = float_round_to_zero;
+ rmode = FPROUNDING_ZERO;
gen_fpst = gen_helper_frint64_d;
break;
case 0x13: /* FRINT64X */
@@ -6304,10 +6302,9 @@ static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
fpst = fpstatus_ptr(FPST_FPCR);
if (rmode >= 0) {
- TCGv_i32 tcg_rmode = tcg_const_i32(rmode);
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
+ TCGv_i32 tcg_rmode = gen_set_rmode(rmode, fpst);
gen_fpst(tcg_res, tcg_op, fpst);
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
+ gen_restore_rmode(tcg_rmode, fpst);
} else {
gen_fpst(tcg_res, tcg_op, fpst);
}
@@ -6944,9 +6941,7 @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
rmode = FPROUNDING_TIEAWAY;
}
- tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
-
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
+ tcg_rmode = gen_set_rmode(rmode, tcg_fpstatus);
switch (type) {
case 1: /* float64 */
@@ -7023,7 +7018,7 @@ static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
g_assert_not_reached();
}
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
+ gen_restore_rmode(tcg_rmode, tcg_fpstatus);
}
}
@@ -7447,10 +7442,10 @@ static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
bool part = extract32(insn, 14, 1);
bool is_q = extract32(insn, 30, 1);
int esize = 8 << size;
- int i, ofs;
+ int i;
int datasize = is_q ? 128 : 64;
int elements = datasize / esize;
- TCGv_i64 tcg_res, tcg_resl, tcg_resh;
+ TCGv_i64 tcg_res[2], tcg_ele;
if (opcode == 0 || (size == 3 && !is_q)) {
unallocated_encoding(s);
@@ -7461,37 +7456,39 @@ static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
return;
}
- tcg_resl = tcg_const_i64(0);
- tcg_resh = is_q ? tcg_const_i64(0) : NULL;
- tcg_res = tcg_temp_new_i64();
+ tcg_res[0] = tcg_temp_new_i64();
+ tcg_res[1] = is_q ? tcg_temp_new_i64() : NULL;
+ tcg_ele = tcg_temp_new_i64();
for (i = 0; i < elements; i++) {
+ int o, w;
+
switch (opcode) {
case 1: /* UZP1/2 */
{
int midpoint = elements / 2;
if (i < midpoint) {
- read_vec_element(s, tcg_res, rn, 2 * i + part, size);
+ read_vec_element(s, tcg_ele, rn, 2 * i + part, size);
} else {
- read_vec_element(s, tcg_res, rm,
+ read_vec_element(s, tcg_ele, rm,
2 * (i - midpoint) + part, size);
}
break;
}
case 2: /* TRN1/2 */
if (i & 1) {
- read_vec_element(s, tcg_res, rm, (i & ~1) + part, size);
+ read_vec_element(s, tcg_ele, rm, (i & ~1) + part, size);
} else {
- read_vec_element(s, tcg_res, rn, (i & ~1) + part, size);
+ read_vec_element(s, tcg_ele, rn, (i & ~1) + part, size);
}
break;
case 3: /* ZIP1/2 */
{
int base = part * elements / 2;
if (i & 1) {
- read_vec_element(s, tcg_res, rm, base + (i >> 1), size);
+ read_vec_element(s, tcg_ele, rm, base + (i >> 1), size);
} else {
- read_vec_element(s, tcg_res, rn, base + (i >> 1), size);
+ read_vec_element(s, tcg_ele, rn, base + (i >> 1), size);
}
break;
}
@@ -7499,19 +7496,18 @@ static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
g_assert_not_reached();
}
- ofs = i * esize;
- if (ofs < 64) {
- tcg_gen_shli_i64(tcg_res, tcg_res, ofs);
- tcg_gen_or_i64(tcg_resl, tcg_resl, tcg_res);
+ w = (i * esize) / 64;
+ o = (i * esize) % 64;
+ if (o == 0) {
+ tcg_gen_mov_i64(tcg_res[w], tcg_ele);
} else {
- tcg_gen_shli_i64(tcg_res, tcg_res, ofs - 64);
- tcg_gen_or_i64(tcg_resh, tcg_resh, tcg_res);
+ tcg_gen_shli_i64(tcg_ele, tcg_ele, o);
+ tcg_gen_or_i64(tcg_res[w], tcg_res[w], tcg_ele);
}
}
- write_vec_element(s, tcg_resl, rd, 0, MO_64);
- if (is_q) {
- write_vec_element(s, tcg_resh, rd, 1, MO_64);
+ for (i = 0; i <= is_q; ++i) {
+ write_vec_element(s, tcg_res[i], rd, i, MO_64);
}
clear_vec_high(s, is_q, rd);
}
@@ -8463,7 +8459,7 @@ static void handle_vec_simd_sqshrn(DisasContext *s, bool is_scalar, bool is_q,
tcg_rn = tcg_temp_new_i64();
tcg_rd = tcg_temp_new_i64();
tcg_rd_narrowed = tcg_temp_new_i32();
- tcg_final = tcg_const_i64(0);
+ tcg_final = tcg_temp_new_i64();
if (round) {
tcg_round = tcg_constant_i64(1ULL << (shift - 1));
@@ -8477,7 +8473,11 @@ static void handle_vec_simd_sqshrn(DisasContext *s, bool is_scalar, bool is_q,
false, is_u_shift, size+1, shift);
narrowfn(tcg_rd_narrowed, cpu_env, tcg_rd);
tcg_gen_extu_i32_i64(tcg_rd, tcg_rd_narrowed);
- tcg_gen_deposit_i64(tcg_final, tcg_final, tcg_rd, esize * i, esize);
+ if (i == 0) {
+ tcg_gen_mov_i64(tcg_final, tcg_rd);
+ } else {
+ tcg_gen_deposit_i64(tcg_final, tcg_final, tcg_rd, esize * i, esize);
+ }
}
if (!is_q) {
@@ -8771,9 +8771,8 @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
assert(!(is_scalar && is_q));
- tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO));
tcg_fpstatus = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
+ tcg_rmode = gen_set_rmode(FPROUNDING_ZERO, tcg_fpstatus);
fracbits = (16 << size) - immhb;
tcg_shift = tcg_constant_i32(fracbits);
@@ -8831,7 +8830,7 @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
}
}
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
+ gen_restore_rmode(tcg_rmode, tcg_fpstatus);
}
/* AdvSIMD scalar shift by immediate
@@ -10219,12 +10218,11 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
}
if (is_fcvt) {
- tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
tcg_fpstatus = fpstatus_ptr(FPST_FPCR);
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
+ tcg_rmode = gen_set_rmode(rmode, tcg_fpstatus);
} else {
- tcg_rmode = NULL;
tcg_fpstatus = NULL;
+ tcg_rmode = NULL;
}
if (size == 3) {
@@ -10276,7 +10274,7 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
}
if (is_fcvt) {
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
+ gen_restore_rmode(tcg_rmode, tcg_fpstatus);
}
}
@@ -12005,22 +12003,26 @@ static void handle_rev(DisasContext *s, int opcode, bool u,
int esize = 8 << size;
int elements = dsize / esize;
TCGv_i64 tcg_rn = tcg_temp_new_i64();
- TCGv_i64 tcg_rd = tcg_const_i64(0);
- TCGv_i64 tcg_rd_hi = tcg_const_i64(0);
+ TCGv_i64 tcg_rd[2];
+
+ for (i = 0; i < 2; i++) {
+ tcg_rd[i] = tcg_temp_new_i64();
+ tcg_gen_movi_i64(tcg_rd[i], 0);
+ }
for (i = 0; i < elements; i++) {
int e_rev = (i & 0xf) ^ revmask;
- int off = e_rev * esize;
+ int w = (e_rev * esize) / 64;
+ int o = (e_rev * esize) % 64;
+
read_vec_element(s, tcg_rn, rn, i, size);
- if (off >= 64) {
- tcg_gen_deposit_i64(tcg_rd_hi, tcg_rd_hi,
- tcg_rn, off - 64, esize);
- } else {
- tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_rn, off, esize);
- }
+ tcg_gen_deposit_i64(tcg_rd[w], tcg_rd[w], tcg_rn, o, esize);
+ }
+
+ for (i = 0; i < 2; i++) {
+ write_vec_element(s, tcg_rd[i], rd, i, MO_64);
}
- write_vec_element(s, tcg_rd, rd, 0, MO_64);
- write_vec_element(s, tcg_rd_hi, rd, 1, MO_64);
+ clear_vec_high(s, true, rd);
}
}
@@ -12133,7 +12135,6 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
int rn = extract32(insn, 5, 5);
int rd = extract32(insn, 0, 5);
bool need_fpstatus = false;
- bool need_rmode = false;
int rmode = -1;
TCGv_i32 tcg_rmode;
TCGv_ptr tcg_fpstatus;
@@ -12283,7 +12284,6 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
case 0x7a: /* FCVTPU */
case 0x7b: /* FCVTZU */
need_fpstatus = true;
- need_rmode = true;
rmode = extract32(opcode, 5, 1) | (extract32(opcode, 0, 1) << 1);
if (size == 3 && !is_q) {
unallocated_encoding(s);
@@ -12293,7 +12293,6 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
case 0x5c: /* FCVTAU */
case 0x1c: /* FCVTAS */
need_fpstatus = true;
- need_rmode = true;
rmode = FPROUNDING_TIEAWAY;
if (size == 3 && !is_q) {
unallocated_encoding(s);
@@ -12352,7 +12351,6 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
case 0x19: /* FRINTM */
case 0x38: /* FRINTP */
case 0x39: /* FRINTZ */
- need_rmode = true;
rmode = extract32(opcode, 5, 1) | (extract32(opcode, 0, 1) << 1);
/* fall through */
case 0x59: /* FRINTX */
@@ -12364,7 +12362,6 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
}
break;
case 0x58: /* FRINTA */
- need_rmode = true;
rmode = FPROUNDING_TIEAWAY;
need_fpstatus = true;
if (size == 3 && !is_q) {
@@ -12380,7 +12377,6 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
break;
case 0x1e: /* FRINT32Z */
case 0x1f: /* FRINT64Z */
- need_rmode = true;
rmode = FPROUNDING_ZERO;
/* fall through */
case 0x5e: /* FRINT32X */
@@ -12406,14 +12402,13 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
return;
}
- if (need_fpstatus || need_rmode) {
+ if (need_fpstatus || rmode >= 0) {
tcg_fpstatus = fpstatus_ptr(FPST_FPCR);
} else {
tcg_fpstatus = NULL;
}
- if (need_rmode) {
- tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
+ if (rmode >= 0) {
+ tcg_rmode = gen_set_rmode(rmode, tcg_fpstatus);
} else {
tcg_rmode = NULL;
}
@@ -12595,8 +12590,8 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
}
clear_vec_high(s, is_q, rd);
- if (need_rmode) {
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
+ if (tcg_rmode) {
+ gen_restore_rmode(tcg_rmode, tcg_fpstatus);
}
}
@@ -12625,9 +12620,8 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
int pass;
TCGv_i32 tcg_rmode = NULL;
TCGv_ptr tcg_fpstatus = NULL;
- bool need_rmode = false;
bool need_fpst = true;
- int rmode;
+ int rmode = -1;
if (!dc_isar_feature(aa64_fp16, s)) {
unallocated_encoding(s);
@@ -12676,27 +12670,22 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
case 0x3f: /* FRECPX */
break;
case 0x18: /* FRINTN */
- need_rmode = true;
only_in_vector = true;
rmode = FPROUNDING_TIEEVEN;
break;
case 0x19: /* FRINTM */
- need_rmode = true;
only_in_vector = true;
rmode = FPROUNDING_NEGINF;
break;
case 0x38: /* FRINTP */
- need_rmode = true;
only_in_vector = true;
rmode = FPROUNDING_POSINF;
break;
case 0x39: /* FRINTZ */
- need_rmode = true;
only_in_vector = true;
rmode = FPROUNDING_ZERO;
break;
case 0x58: /* FRINTA */
- need_rmode = true;
only_in_vector = true;
rmode = FPROUNDING_TIEAWAY;
break;
@@ -12706,43 +12695,33 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
/* current rounding mode */
break;
case 0x1a: /* FCVTNS */
- need_rmode = true;
rmode = FPROUNDING_TIEEVEN;
break;
case 0x1b: /* FCVTMS */
- need_rmode = true;
rmode = FPROUNDING_NEGINF;
break;
case 0x1c: /* FCVTAS */
- need_rmode = true;
rmode = FPROUNDING_TIEAWAY;
break;
case 0x3a: /* FCVTPS */
- need_rmode = true;
rmode = FPROUNDING_POSINF;
break;
case 0x3b: /* FCVTZS */
- need_rmode = true;
rmode = FPROUNDING_ZERO;
break;
case 0x5a: /* FCVTNU */
- need_rmode = true;
rmode = FPROUNDING_TIEEVEN;
break;
case 0x5b: /* FCVTMU */
- need_rmode = true;
rmode = FPROUNDING_NEGINF;
break;
case 0x5c: /* FCVTAU */
- need_rmode = true;
rmode = FPROUNDING_TIEAWAY;
break;
case 0x7a: /* FCVTPU */
- need_rmode = true;
rmode = FPROUNDING_POSINF;
break;
case 0x7b: /* FCVTZU */
- need_rmode = true;
rmode = FPROUNDING_ZERO;
break;
case 0x2f: /* FABS */
@@ -12775,13 +12754,12 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
return;
}
- if (need_rmode || need_fpst) {
+ if (rmode >= 0 || need_fpst) {
tcg_fpstatus = fpstatus_ptr(FPST_FPCR_F16);
}
- if (need_rmode) {
- tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
+ if (rmode >= 0) {
+ tcg_rmode = gen_set_rmode(rmode, tcg_fpstatus);
}
if (is_scalar) {
@@ -12881,7 +12859,7 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
}
if (tcg_rmode) {
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
+ gen_restore_rmode(tcg_rmode, tcg_fpstatus);
}
}