mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-11 06:45:33 +00:00
arm/translate-a64: add FP16 FMULX/MLS/FMLA to simd_indexed
The helpers use the new re-factored muladd support in SoftFloat for the float16 work. Backports commit 5d265064cf30daaacce5a4ce9945fc573015fb5f from qemu
This commit is contained in:
parent
c6fda07628
commit
38815b2901
|
@ -11355,6 +11355,7 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
|
||||||
int rd = extract32(insn, 0, 5);
|
int rd = extract32(insn, 0, 5);
|
||||||
bool is_long = false;
|
bool is_long = false;
|
||||||
bool is_fp = false;
|
bool is_fp = false;
|
||||||
|
bool is_fp16 = false;
|
||||||
int index;
|
int index;
|
||||||
TCGv_ptr fpst;
|
TCGv_ptr fpst;
|
||||||
|
|
||||||
|
@ -11401,7 +11402,7 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
|
||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case 0x9: /* FMUL, FMULX */
|
case 0x9: /* FMUL, FMULX */
|
||||||
if (!extract32(size, 1, 1)) {
|
if (size == 1) {
|
||||||
unallocated_encoding(s);
|
unallocated_encoding(s);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -11413,18 +11414,34 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_fp) {
|
if (is_fp) {
|
||||||
/* low bit of size indicates single/double */
|
/* convert insn encoded size to TCGMemOp size */
|
||||||
size = extract32(size, 0, 1) ? 3 : 2;
|
switch (size) {
|
||||||
if (size == 2) {
|
case 2: /* single precision */
|
||||||
|
size = MO_32;
|
||||||
index = h << 1 | l;
|
index = h << 1 | l;
|
||||||
} else {
|
rm |= (m << 4);
|
||||||
|
break;
|
||||||
|
case 3: /* double precision */
|
||||||
|
size = MO_64;
|
||||||
if (l || !is_q) {
|
if (l || !is_q) {
|
||||||
unallocated_encoding(s);
|
unallocated_encoding(s);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
index = h;
|
index = h;
|
||||||
|
rm |= (m << 4);
|
||||||
|
break;
|
||||||
|
case 0: /* half precision */
|
||||||
|
size = MO_16;
|
||||||
|
index = h << 2 | l << 1 | m;
|
||||||
|
is_fp16 = true;
|
||||||
|
if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* fallthru */
|
||||||
|
default: /* unallocated */
|
||||||
|
unallocated_encoding(s);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
rm |= (m << 4);
|
|
||||||
} else {
|
} else {
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -11445,7 +11462,7 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_fp) {
|
if (is_fp) {
|
||||||
fpst = get_fpstatus_ptr(tcg_ctx, false);
|
fpst = get_fpstatus_ptr(tcg_ctx, is_fp16);
|
||||||
} else {
|
} else {
|
||||||
fpst = NULL;
|
fpst = NULL;
|
||||||
}
|
}
|
||||||
|
@ -11547,18 +11564,51 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x5: /* FMLS */
|
case 0x5: /* FMLS */
|
||||||
/* As usual for ARM, separate negation for fused multiply-add */
|
|
||||||
gen_helper_vfp_negs(tcg_ctx, tcg_op, tcg_op);
|
|
||||||
/* fall through */
|
|
||||||
case 0x1: /* FMLA */
|
case 0x1: /* FMLA */
|
||||||
read_vec_element_i32(s, tcg_res, rd, pass, MO_32);
|
read_vec_element_i32(s, tcg_res, rd, pass,
|
||||||
gen_helper_vfp_muladds(tcg_ctx, tcg_res, tcg_op, tcg_idx, tcg_res, fpst);
|
is_scalar ? size : MO_32);
|
||||||
|
switch (size) {
|
||||||
|
case 1:
|
||||||
|
if (opcode == 0x5) {
|
||||||
|
/* As usual for ARM, separate negation for fused
|
||||||
|
* multiply-add */
|
||||||
|
tcg_gen_xori_i32(tcg_ctx, tcg_op, tcg_op, 0x80008000);
|
||||||
|
}
|
||||||
|
gen_helper_advsimd_muladdh(tcg_ctx, tcg_res, tcg_op, tcg_idx,
|
||||||
|
tcg_res, fpst);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (opcode == 0x5) {
|
||||||
|
/* As usual for ARM, separate negation for
|
||||||
|
* fused multiply-add */
|
||||||
|
tcg_gen_xori_i32(tcg_ctx, tcg_op, tcg_op, 0x80000000);
|
||||||
|
}
|
||||||
|
gen_helper_vfp_muladds(tcg_ctx, tcg_res, tcg_op, tcg_idx,
|
||||||
|
tcg_res, fpst);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0x9: /* FMUL, FMULX */
|
case 0x9: /* FMUL, FMULX */
|
||||||
if (u) {
|
switch (size) {
|
||||||
gen_helper_vfp_mulxs(tcg_ctx, tcg_res, tcg_op, tcg_idx, fpst);
|
case 1:
|
||||||
} else {
|
if (u) {
|
||||||
gen_helper_vfp_muls(tcg_ctx, tcg_res, tcg_op, tcg_idx, fpst);
|
gen_helper_advsimd_mulxh(tcg_ctx, tcg_res, tcg_op, tcg_idx,
|
||||||
|
fpst);
|
||||||
|
} else {
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (u) {
|
||||||
|
gen_helper_vfp_mulxs(tcg_ctx, tcg_res, tcg_op, tcg_idx, fpst);
|
||||||
|
} else {
|
||||||
|
gen_helper_vfp_muls(tcg_ctx, tcg_res, tcg_op, tcg_idx, fpst);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xc: /* SQDMULH */
|
case 0xc: /* SQDMULH */
|
||||||
|
|
Loading…
Reference in a new issue