arm/translate-a64: add FP16 FCMxx (zero) to simd_two_reg_misc_fp16

I re-use the existing handle_2misc_fcmp_zero handler and tweak it
slightly to deal with the half-precision case.

Backports commit 7d4dd1a73a023f75c893623710e43743501b318e from qemu
This commit is contained in:
Alex Bennée 2018-03-08 18:32:16 -05:00 committed by Lioncash
parent 39a68548d1
commit 8ac9e3cff2
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -7954,14 +7954,14 @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
int size, int rn, int rd) int size, int rn, int rd)
{ {
TCGContext *tcg_ctx = s->uc->tcg_ctx; TCGContext *tcg_ctx = s->uc->tcg_ctx;
bool is_double = (size == 3); bool is_double = (size == MO_64);
TCGv_ptr fpst; TCGv_ptr fpst;
if (!fp_access_check(s)) { if (!fp_access_check(s)) {
return; return;
} }
fpst = get_fpstatus_ptr(tcg_ctx, false); fpst = get_fpstatus_ptr(tcg_ctx, size == MO_16);
if (is_double) { if (is_double) {
TCGv_i64 tcg_op = tcg_temp_new_i64(tcg_ctx); TCGv_i64 tcg_op = tcg_temp_new_i64(tcg_ctx);
@ -8014,34 +8014,57 @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
bool swap = false; bool swap = false;
int pass, maxpasses; int pass, maxpasses;
switch (opcode) { if (size == MO_16) {
case 0x2e: /* FCMLT (zero) */ switch (opcode) {
swap = true; case 0x2e: /* FCMLT (zero) */
/* fall through */ swap = true;
case 0x2c: /* FCMGT (zero) */ /* fall through */
genfn = gen_helper_neon_cgt_f32; case 0x2c: /* FCMGT (zero) */
break; genfn = gen_helper_advsimd_cgt_f16;
case 0x2d: /* FCMEQ (zero) */ break;
genfn = gen_helper_neon_ceq_f32; case 0x2d: /* FCMEQ (zero) */
break; genfn = gen_helper_advsimd_ceq_f16;
case 0x6d: /* FCMLE (zero) */ break;
swap = true; case 0x6d: /* FCMLE (zero) */
/* fall through */ swap = true;
case 0x6c: /* FCMGE (zero) */ /* fall through */
genfn = gen_helper_neon_cge_f32; case 0x6c: /* FCMGE (zero) */
break; genfn = gen_helper_advsimd_cge_f16;
default: break;
g_assert_not_reached(); default:
g_assert_not_reached();
}
} else {
switch (opcode) {
case 0x2e: /* FCMLT (zero) */
swap = true;
/* fall through */
case 0x2c: /* FCMGT (zero) */
genfn = gen_helper_neon_cgt_f32;
break;
case 0x2d: /* FCMEQ (zero) */
genfn = gen_helper_neon_ceq_f32;
break;
case 0x6d: /* FCMLE (zero) */
swap = true;
/* fall through */
case 0x6c: /* FCMGE (zero) */
genfn = gen_helper_neon_cge_f32;
break;
default:
g_assert_not_reached();
}
} }
if (is_scalar) { if (is_scalar) {
maxpasses = 1; maxpasses = 1;
} else { } else {
maxpasses = is_q ? 4 : 2; int vector_size = 8 << is_q;
maxpasses = vector_size >> size;
} }
for (pass = 0; pass < maxpasses; pass++) { for (pass = 0; pass < maxpasses; pass++) {
read_vec_element_i32(s, tcg_op, rn, pass, MO_32); read_vec_element_i32(s, tcg_op, rn, pass, size);
if (swap) { if (swap) {
genfn(tcg_ctx, tcg_res, tcg_zero, tcg_op, fpst); genfn(tcg_ctx, tcg_res, tcg_zero, tcg_op, fpst);
} else { } else {
@ -8050,7 +8073,7 @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
if (is_scalar) { if (is_scalar) {
write_fp_sreg(s, rd, tcg_res); write_fp_sreg(s, rd, tcg_res);
} else { } else {
write_vec_element_i32(s, tcg_res, rd, pass, MO_32); write_vec_element_i32(s, tcg_res, rd, pass, size);
} }
} }
tcg_temp_free_i32(tcg_ctx, tcg_res); tcg_temp_free_i32(tcg_ctx, tcg_res);
@ -11366,7 +11389,18 @@ static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
fpop = deposit32(opcode, 5, 1, a); fpop = deposit32(opcode, 5, 1, a);
fpop = deposit32(fpop, 6, 1, u); fpop = deposit32(fpop, 6, 1, u);
rd = extract32(insn, 0, 5);
rn = extract32(insn, 5, 5);
switch (fpop) { switch (fpop) {
break;
case 0x2c: /* FCMGT (zero) */
case 0x2d: /* FCMEQ (zero) */
case 0x2e: /* FCMLT (zero) */
case 0x6c: /* FCMGE (zero) */
case 0x6d: /* FCMLE (zero) */
handle_2misc_fcmp_zero(s, fpop, is_scalar, 0, is_q, MO_16, rn, rd);
return;
case 0x18: /* FRINTN */ case 0x18: /* FRINTN */
need_rmode = true; need_rmode = true;
only_in_vector = true; only_in_vector = true;