diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2024-05-02 09:55:26 -0700 |
---|---|---|
committer | Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> | 2024-05-05 21:02:48 +0100 |
commit | be8998e046c2a7e434494b75cf468ffd9d536025 (patch) | |
tree | cec760857c6d3fbb1a05f4cf3ef7f65242ebc1e5 /target/sparc/translate.c | |
parent | a859602c746baf4892cc8ca1ce003e92411d1716 (diff) | |
download | qemu-be8998e046c2a7e434494b75cf468ffd9d536025.zip qemu-be8998e046c2a7e434494b75cf468ffd9d536025.tar.gz qemu-be8998e046c2a7e434494b75cf468ffd9d536025.tar.bz2 |
target/sparc: Fix FMULD8*X16
Not only do these instructions have f32 inputs, they also do not
perform rounding. Since these are relatively simple, implement
them properly inline.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20240502165528.244004-6-richard.henderson@linaro.org>
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Diffstat (limited to 'target/sparc/translate.c')
-rw-r--r-- | target/sparc/translate.c | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/target/sparc/translate.c b/target/sparc/translate.c index a8ada69..8a2894b 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -74,8 +74,6 @@ # define gen_helper_fmul8sux16 ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fmul8ulx16 ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fmul8x16 ({ qemu_build_not_reached(); NULL; }) -# define gen_helper_fmuld8sux16 ({ qemu_build_not_reached(); NULL; }) -# define gen_helper_fmuld8ulx16 ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fpmerge ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fqtox ({ qemu_build_not_reached(); NULL; }) # define gen_helper_fstox ({ qemu_build_not_reached(); NULL; }) @@ -730,6 +728,48 @@ static void gen_op_fmul8x16au(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) gen_helper_fmul8x16a(dst, src1, src2); } +static void gen_op_fmuld8ulx16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + + tcg_gen_ext8u_i32(t0, src1); + tcg_gen_ext16s_i32(t1, src2); + tcg_gen_mul_i32(t0, t0, t1); + + tcg_gen_extract_i32(t1, src1, 16, 8); + tcg_gen_sextract_i32(t2, src2, 16, 16); + tcg_gen_mul_i32(t1, t1, t2); + + tcg_gen_concat_i32_i64(dst, t0, t1); +} + +static void gen_op_fmuld8sux16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + + /* + * The insn description talks about extracting the upper 8 bits + * of the signed 16-bit input rs1, performing the multiply, then + * shifting left by 8 bits. Instead, zap the lower 8 bits of + * the rs1 input, which avoids the need for two shifts. + */ + tcg_gen_ext16s_i32(t0, src1); + tcg_gen_andi_i32(t0, t0, ~0xff); + tcg_gen_ext16s_i32(t1, src2); + tcg_gen_mul_i32(t0, t0, t1); + + tcg_gen_sextract_i32(t1, src1, 16, 16); + tcg_gen_andi_i32(t1, t1, ~0xff); + tcg_gen_sextract_i32(t2, src2, 16, 16); + tcg_gen_mul_i32(t1, t1, t2); + + tcg_gen_concat_i32_i64(dst, t0, t1); +} + static void finishing_insn(DisasContext *dc) { /* @@ -4614,6 +4654,8 @@ static bool do_dff(DisasContext *dc, arg_r_r_r *a, TRANS(FMUL8x16AU, VIS1, do_dff, a, gen_op_fmul8x16au) TRANS(FMUL8x16AL, VIS1, do_dff, a, gen_op_fmul8x16al) +TRANS(FMULD8SUx16, VIS1, do_dff, a, gen_op_fmuld8sux16) +TRANS(FMULD8ULx16, VIS1, do_dff, a, gen_op_fmuld8ulx16) static bool do_dfd(DisasContext *dc, arg_r_r_r *a, void (*func)(TCGv_i64, TCGv_i32, TCGv_i64)) @@ -4654,8 +4696,6 @@ static bool do_ddd(DisasContext *dc, arg_r_r_r *a, TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16) TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16) -TRANS(FMULD8SUx16, VIS1, do_ddd, a, gen_helper_fmuld8sux16) -TRANS(FMULD8ULx16, VIS1, do_ddd, a, gen_helper_fmuld8ulx16) TRANS(FPMERGE, VIS1, do_ddd, a, gen_helper_fpmerge) TRANS(FPADD16, VIS1, do_ddd, a, tcg_gen_vec_add16_i64) |