target/arm: Convert FCMP, FCMPE, FCCMP, FCCMPE to decodetree
Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20241211163036.2297116-23-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
43218f2346
commit
cc0db9dea0
@ -1325,6 +1325,14 @@ FMINV_s 0110 1110 10 11000 01111 10 ..... ..... @rr_q1e2
|
||||
|
||||
FMOVI_s 0001 1110 .. 1 imm:8 100 00000 rd:5 esz=%esz_hsd
|
||||
|
||||
# Floating-point Compare
|
||||
|
||||
FCMP 00011110 .. 1 rm:5 001000 rn:5 e:1 z:1 000 esz=%esz_hsd
|
||||
|
||||
# Floating-point Conditional Compare
|
||||
|
||||
FCCMP 00011110 .. 1 rm:5 cond:4 01 rn:5 e:1 nzcv:4 esz=%esz_hsd
|
||||
|
||||
# Advanced SIMD Modified Immediate / Shift by Immediate
|
||||
|
||||
%abcdefgh 16:3 5:5
|
||||
|
@ -6888,6 +6888,106 @@ static bool trans_FMOVI_s(DisasContext *s, arg_FMOVI_s *a)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Floating point compare, conditional compare
|
||||
*/
|
||||
|
||||
static void handle_fp_compare(DisasContext *s, int size,
|
||||
unsigned int rn, unsigned int rm,
|
||||
bool cmp_with_zero, bool signal_all_nans)
|
||||
{
|
||||
TCGv_i64 tcg_flags = tcg_temp_new_i64();
|
||||
TCGv_ptr fpst = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
|
||||
|
||||
if (size == MO_64) {
|
||||
TCGv_i64 tcg_vn, tcg_vm;
|
||||
|
||||
tcg_vn = read_fp_dreg(s, rn);
|
||||
if (cmp_with_zero) {
|
||||
tcg_vm = tcg_constant_i64(0);
|
||||
} else {
|
||||
tcg_vm = read_fp_dreg(s, rm);
|
||||
}
|
||||
if (signal_all_nans) {
|
||||
gen_helper_vfp_cmped_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
|
||||
} else {
|
||||
gen_helper_vfp_cmpd_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
|
||||
}
|
||||
} else {
|
||||
TCGv_i32 tcg_vn = tcg_temp_new_i32();
|
||||
TCGv_i32 tcg_vm = tcg_temp_new_i32();
|
||||
|
||||
read_vec_element_i32(s, tcg_vn, rn, 0, size);
|
||||
if (cmp_with_zero) {
|
||||
tcg_gen_movi_i32(tcg_vm, 0);
|
||||
} else {
|
||||
read_vec_element_i32(s, tcg_vm, rm, 0, size);
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case MO_32:
|
||||
if (signal_all_nans) {
|
||||
gen_helper_vfp_cmpes_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
|
||||
} else {
|
||||
gen_helper_vfp_cmps_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
|
||||
}
|
||||
break;
|
||||
case MO_16:
|
||||
if (signal_all_nans) {
|
||||
gen_helper_vfp_cmpeh_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
|
||||
} else {
|
||||
gen_helper_vfp_cmph_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
gen_set_nzcv(tcg_flags);
|
||||
}
|
||||
|
||||
/* FCMP, FCMPE */
|
||||
static bool trans_FCMP(DisasContext *s, arg_FCMP *a)
|
||||
{
|
||||
int check = fp_access_check_scalar_hsd(s, a->esz);
|
||||
|
||||
if (check <= 0) {
|
||||
return check == 0;
|
||||
}
|
||||
|
||||
handle_fp_compare(s, a->esz, a->rn, a->rm, a->z, a->e);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* FCCMP, FCCMPE */
|
||||
static bool trans_FCCMP(DisasContext *s, arg_FCCMP *a)
|
||||
{
|
||||
TCGLabel *label_continue = NULL;
|
||||
int check = fp_access_check_scalar_hsd(s, a->esz);
|
||||
|
||||
if (check <= 0) {
|
||||
return check == 0;
|
||||
}
|
||||
|
||||
if (a->cond < 0x0e) { /* not always */
|
||||
TCGLabel *label_match = gen_new_label();
|
||||
label_continue = gen_new_label();
|
||||
arm_gen_test_cc(a->cond, label_match);
|
||||
/* nomatch: */
|
||||
gen_set_nzcv(tcg_constant_i64(a->nzcv << 28));
|
||||
tcg_gen_br(label_continue);
|
||||
gen_set_label(label_match);
|
||||
}
|
||||
|
||||
handle_fp_compare(s, a->esz, a->rn, a->rm, false, a->e);
|
||||
|
||||
if (label_continue) {
|
||||
gen_set_label(label_continue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Advanced SIMD Modified Immediate
|
||||
*/
|
||||
@ -8183,174 +8283,6 @@ static bool trans_CSEL(DisasContext *s, arg_CSEL *a)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void handle_fp_compare(DisasContext *s, int size,
|
||||
unsigned int rn, unsigned int rm,
|
||||
bool cmp_with_zero, bool signal_all_nans)
|
||||
{
|
||||
TCGv_i64 tcg_flags = tcg_temp_new_i64();
|
||||
TCGv_ptr fpst = fpstatus_ptr(size == MO_16 ? FPST_FPCR_F16 : FPST_FPCR);
|
||||
|
||||
if (size == MO_64) {
|
||||
TCGv_i64 tcg_vn, tcg_vm;
|
||||
|
||||
tcg_vn = read_fp_dreg(s, rn);
|
||||
if (cmp_with_zero) {
|
||||
tcg_vm = tcg_constant_i64(0);
|
||||
} else {
|
||||
tcg_vm = read_fp_dreg(s, rm);
|
||||
}
|
||||
if (signal_all_nans) {
|
||||
gen_helper_vfp_cmped_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
|
||||
} else {
|
||||
gen_helper_vfp_cmpd_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
|
||||
}
|
||||
} else {
|
||||
TCGv_i32 tcg_vn = tcg_temp_new_i32();
|
||||
TCGv_i32 tcg_vm = tcg_temp_new_i32();
|
||||
|
||||
read_vec_element_i32(s, tcg_vn, rn, 0, size);
|
||||
if (cmp_with_zero) {
|
||||
tcg_gen_movi_i32(tcg_vm, 0);
|
||||
} else {
|
||||
read_vec_element_i32(s, tcg_vm, rm, 0, size);
|
||||
}
|
||||
|
||||
switch (size) {
|
||||
case MO_32:
|
||||
if (signal_all_nans) {
|
||||
gen_helper_vfp_cmpes_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
|
||||
} else {
|
||||
gen_helper_vfp_cmps_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
|
||||
}
|
||||
break;
|
||||
case MO_16:
|
||||
if (signal_all_nans) {
|
||||
gen_helper_vfp_cmpeh_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
|
||||
} else {
|
||||
gen_helper_vfp_cmph_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
gen_set_nzcv(tcg_flags);
|
||||
}
|
||||
|
||||
/* Floating point compare
|
||||
* 31 30 29 28 24 23 22 21 20 16 15 14 13 10 9 5 4 0
|
||||
* +---+---+---+-----------+------+---+------+-----+---------+------+-------+
|
||||
* | M | 0 | S | 1 1 1 1 0 | type | 1 | Rm | op | 1 0 0 0 | Rn | op2 |
|
||||
* +---+---+---+-----------+------+---+------+-----+---------+------+-------+
|
||||
*/
|
||||
static void disas_fp_compare(DisasContext *s, uint32_t insn)
|
||||
{
|
||||
unsigned int mos, type, rm, op, rn, opc, op2r;
|
||||
int size;
|
||||
|
||||
mos = extract32(insn, 29, 3);
|
||||
type = extract32(insn, 22, 2);
|
||||
rm = extract32(insn, 16, 5);
|
||||
op = extract32(insn, 14, 2);
|
||||
rn = extract32(insn, 5, 5);
|
||||
opc = extract32(insn, 3, 2);
|
||||
op2r = extract32(insn, 0, 3);
|
||||
|
||||
if (mos || op || op2r) {
|
||||
unallocated_encoding(s);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 0:
|
||||
size = MO_32;
|
||||
break;
|
||||
case 1:
|
||||
size = MO_64;
|
||||
break;
|
||||
case 3:
|
||||
size = MO_16;
|
||||
if (dc_isar_feature(aa64_fp16, s)) {
|
||||
break;
|
||||
}
|
||||
/* fallthru */
|
||||
default:
|
||||
unallocated_encoding(s);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fp_access_check(s)) {
|
||||
return;
|
||||
}
|
||||
|
||||
handle_fp_compare(s, size, rn, rm, opc & 1, opc & 2);
|
||||
}
|
||||
|
||||
/* Floating point conditional compare
|
||||
* 31 30 29 28 24 23 22 21 20 16 15 12 11 10 9 5 4 3 0
|
||||
* +---+---+---+-----------+------+---+------+------+-----+------+----+------+
|
||||
* | M | 0 | S | 1 1 1 1 0 | type | 1 | Rm | cond | 0 1 | Rn | op | nzcv |
|
||||
* +---+---+---+-----------+------+---+------+------+-----+------+----+------+
|
||||
*/
|
||||
static void disas_fp_ccomp(DisasContext *s, uint32_t insn)
|
||||
{
|
||||
unsigned int mos, type, rm, cond, rn, op, nzcv;
|
||||
TCGLabel *label_continue = NULL;
|
||||
int size;
|
||||
|
||||
mos = extract32(insn, 29, 3);
|
||||
type = extract32(insn, 22, 2);
|
||||
rm = extract32(insn, 16, 5);
|
||||
cond = extract32(insn, 12, 4);
|
||||
rn = extract32(insn, 5, 5);
|
||||
op = extract32(insn, 4, 1);
|
||||
nzcv = extract32(insn, 0, 4);
|
||||
|
||||
if (mos) {
|
||||
unallocated_encoding(s);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 0:
|
||||
size = MO_32;
|
||||
break;
|
||||
case 1:
|
||||
size = MO_64;
|
||||
break;
|
||||
case 3:
|
||||
size = MO_16;
|
||||
if (dc_isar_feature(aa64_fp16, s)) {
|
||||
break;
|
||||
}
|
||||
/* fallthru */
|
||||
default:
|
||||
unallocated_encoding(s);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fp_access_check(s)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cond < 0x0e) { /* not always */
|
||||
TCGLabel *label_match = gen_new_label();
|
||||
label_continue = gen_new_label();
|
||||
arm_gen_test_cc(cond, label_match);
|
||||
/* nomatch: */
|
||||
gen_set_nzcv(tcg_constant_i64(nzcv << 28));
|
||||
tcg_gen_br(label_continue);
|
||||
gen_set_label(label_match);
|
||||
}
|
||||
|
||||
handle_fp_compare(s, size, rn, rm, false, op);
|
||||
|
||||
if (cond < 0x0e) {
|
||||
gen_set_label(label_continue);
|
||||
}
|
||||
}
|
||||
|
||||
/* Floating-point data-processing (1 source) - half precision */
|
||||
static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
|
||||
{
|
||||
@ -9107,16 +9039,9 @@ static void disas_data_proc_fp(DisasContext *s, uint32_t insn)
|
||||
disas_fp_fixed_conv(s, insn);
|
||||
} else {
|
||||
switch (extract32(insn, 10, 2)) {
|
||||
case 1:
|
||||
/* Floating point conditional compare */
|
||||
disas_fp_ccomp(s, insn);
|
||||
break;
|
||||
case 2:
|
||||
/* Floating point data-processing (2 source) */
|
||||
unallocated_encoding(s); /* in decodetree */
|
||||
break;
|
||||
case 3:
|
||||
/* Floating point conditional select */
|
||||
case 1: /* Floating point conditional compare */
|
||||
case 2: /* Floating point data-processing (2 source) */
|
||||
case 3: /* Floating point conditional select */
|
||||
unallocated_encoding(s); /* in decodetree */
|
||||
break;
|
||||
case 0:
|
||||
@ -9127,7 +9052,7 @@ static void disas_data_proc_fp(DisasContext *s, uint32_t insn)
|
||||
break;
|
||||
case 1: /* [15:12] == xx10 */
|
||||
/* Floating point compare */
|
||||
disas_fp_compare(s, insn);
|
||||
unallocated_encoding(s); /* in decodetree */
|
||||
break;
|
||||
case 2: /* [15:12] == x100 */
|
||||
/* Floating point data-processing (1 source) */
|
||||
|
Loading…
x
Reference in New Issue
Block a user