Skip to content

Commit

Permalink
target/arm: Implement vector shifted FCVT for fp16
Browse files Browse the repository at this point in the history
While we have some of the scalar paths for FCVT for fp16,
we failed to decode the fp16 version of these instructions.

Cc: qemu-stable@nongnu.org
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20180502221552.3873-3-richard.henderson@linaro.org
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
rth7680 authored and pm215 committed May 10, 2018
1 parent a6117fa commit d0ba8e7
Showing 1 changed file with 45 additions and 18 deletions.
63 changes: 45 additions & 18 deletions target/arm/translate-a64.c
Expand Up @@ -7448,19 +7448,28 @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
bool is_q, bool is_u,
int immh, int immb, int rn, int rd)
{
bool is_double = extract32(immh, 3, 1);
int immhb = immh << 3 | immb;
int fracbits = (is_double ? 128 : 64) - immhb;
int pass;
int pass, size, fracbits;
TCGv_ptr tcg_fpstatus;
TCGv_i32 tcg_rmode, tcg_shift;

if (!extract32(immh, 2, 2)) {
unallocated_encoding(s);
return;
}

if (!is_scalar && !is_q && is_double) {
if (immh & 0x8) {
size = MO_64;
if (!is_scalar && !is_q) {
unallocated_encoding(s);
return;
}
} else if (immh & 0x4) {
size = MO_32;
} else if (immh & 0x2) {
size = MO_16;
if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
unallocated_encoding(s);
return;
}
} else {
/* Should have split out AdvSIMD modified immediate earlier. */
assert(immh == 1);
unallocated_encoding(s);
return;
}
Expand All @@ -7472,11 +7481,12 @@ 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 = get_fpstatus_ptr(false);
tcg_fpstatus = get_fpstatus_ptr(size == MO_16);
gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
fracbits = (16 << size) - immhb;
tcg_shift = tcg_const_i32(fracbits);

if (is_double) {
if (size == MO_64) {
int maxpass = is_scalar ? 1 : 2;

for (pass = 0; pass < maxpass; pass++) {
Expand All @@ -7493,20 +7503,37 @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
}
clear_vec_high(s, is_q, rd);
} else {
int maxpass = is_scalar ? 1 : is_q ? 4 : 2;
for (pass = 0; pass < maxpass; pass++) {
TCGv_i32 tcg_op = tcg_temp_new_i32();
void (*fn)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
int maxpass = is_scalar ? 1 : ((8 << is_q) >> size);

read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
switch (size) {
case MO_16:
if (is_u) {
fn = gen_helper_vfp_toulh;
} else {
fn = gen_helper_vfp_toslh;
}
break;
case MO_32:
if (is_u) {
gen_helper_vfp_touls(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
fn = gen_helper_vfp_touls;
} else {
gen_helper_vfp_tosls(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
fn = gen_helper_vfp_tosls;
}
break;
default:
g_assert_not_reached();
}

for (pass = 0; pass < maxpass; pass++) {
TCGv_i32 tcg_op = tcg_temp_new_i32();

read_vec_element_i32(s, tcg_op, rn, pass, size);
fn(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
if (is_scalar) {
write_fp_sreg(s, rd, tcg_op);
} else {
write_vec_element_i32(s, tcg_op, rd, pass, MO_32);
write_vec_element_i32(s, tcg_op, rd, pass, size);
}
tcg_temp_free_i32(tcg_op);
}
Expand Down

0 comments on commit d0ba8e7

Please sign in to comment.