mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-02-02 02:11:09 +00:00
target/arm: Implement vector shifted FCVT for fp16
While we have some of the scalar paths for FCVT for fp16, we failed to decode the fp16 version of these instructions. Backports commit d0ba8e74acd299b092786ffc30b306638d395a9e from qemu
This commit is contained in:
parent
ad6c191d96
commit
e403957a5e
|
@ -7571,19 +7571,28 @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
|
|||
int immh, int immb, int rn, int rd)
|
||||
{
|
||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||
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;
|
||||
}
|
||||
|
@ -7595,11 +7604,12 @@ static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
|
|||
assert(!(is_scalar && is_q));
|
||||
|
||||
tcg_rmode = tcg_const_i32(tcg_ctx, arm_rmode_to_sf(FPROUNDING_ZERO));
|
||||
tcg_fpstatus = get_fpstatus_ptr(tcg_ctx, false);
|
||||
tcg_fpstatus = get_fpstatus_ptr(tcg_ctx, size == MO_16);
|
||||
gen_helper_set_rmode(tcg_ctx, tcg_rmode, tcg_rmode, tcg_fpstatus);
|
||||
fracbits = (16 << size) - immhb;
|
||||
tcg_shift = tcg_const_i32(tcg_ctx, fracbits);
|
||||
|
||||
if (is_double) {
|
||||
if (size == MO_64) {
|
||||
int maxpass = is_scalar ? 1 : 2;
|
||||
|
||||
for (pass = 0; pass < maxpass; pass++) {
|
||||
|
@ -7616,20 +7626,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;
|
||||
void (*fn)(TCGContext *, TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
|
||||
int maxpass = is_scalar ? 1 : ((8 << is_q) >> size);
|
||||
|
||||
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) {
|
||||
fn = gen_helper_vfp_touls;
|
||||
} else {
|
||||
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(tcg_ctx);
|
||||
|
||||
read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
|
||||
if (is_u) {
|
||||
gen_helper_vfp_touls(tcg_ctx, tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
|
||||
} else {
|
||||
gen_helper_vfp_tosls(tcg_ctx, tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
|
||||
}
|
||||
read_vec_element_i32(s, tcg_op, rn, pass, size);
|
||||
fn(tcg_ctx, 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_ctx, tcg_op);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue