[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 18/30] target-arm: A64: Add FRECPX (reciprocal expone
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PULL 18/30] target-arm: A64: Add FRECPX (reciprocal exponent) |
Date: |
Mon, 17 Mar 2014 22:12:09 +0000 |
From: Alex Bennée <address@hidden>
These are fairly simple exponent only estimation functions using helpers.
Signed-off-by: Alex Bennée <address@hidden>
Signed-off-by: Peter Maydell <address@hidden>
Reviewed-by: Richard Henderson <address@hidden>
Message-id: address@hidden
---
target-arm/helper-a64.c | 59 ++++++++++++++++++++++++++++++++++++++
target-arm/helper-a64.h | 2 ++
target-arm/translate-a64.c | 70 +++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 130 insertions(+), 1 deletion(-)
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index c31c45e..cea2468 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -354,3 +354,62 @@ uint64_t HELPER(neon_addlp_u16)(uint64_t a)
tmp += (a >> 16) & 0x0000ffff0000ffffULL;
return tmp;
}
+
+/* Floating-point reciprocal exponent - see FPRecpX in ARM ARM */
+float32 HELPER(frecpx_f32)(float32 a, void *fpstp)
+{
+ float_status *fpst = fpstp;
+ uint32_t val32, sbit;
+ int32_t exp;
+
+ if (float32_is_any_nan(a)) {
+ float32 nan = a;
+ if (float32_is_signaling_nan(a)) {
+ float_raise(float_flag_invalid, fpst);
+ nan = float32_maybe_silence_nan(a);
+ }
+ if (fpst->default_nan_mode) {
+ nan = float32_default_nan;
+ }
+ return nan;
+ }
+
+ val32 = float32_val(a);
+ sbit = 0x80000000ULL & val32;
+ exp = extract32(val32, 23, 8);
+
+ if (exp == 0) {
+ return make_float32(sbit | (0xfe << 23));
+ } else {
+ return make_float32(sbit | (~exp & 0xff) << 23);
+ }
+}
+
+float64 HELPER(frecpx_f64)(float64 a, void *fpstp)
+{
+ float_status *fpst = fpstp;
+ uint64_t val64, sbit;
+ int64_t exp;
+
+ if (float64_is_any_nan(a)) {
+ float64 nan = a;
+ if (float64_is_signaling_nan(a)) {
+ float_raise(float_flag_invalid, fpst);
+ nan = float64_maybe_silence_nan(a);
+ }
+ if (fpst->default_nan_mode) {
+ nan = float64_default_nan;
+ }
+ return nan;
+ }
+
+ val64 = float64_val(a);
+ sbit = 0x8000000000000000ULL & val64;
+ exp = extract64(float64_val(a), 52, 11);
+
+ if (exp == 0) {
+ return make_float64(sbit | (0x7feULL << 52));
+ } else {
+ return make_float64(sbit | (~exp & 0x7ffULL) << 52);
+ }
+}
diff --git a/target-arm/helper-a64.h b/target-arm/helper-a64.h
index 88fc9fe..8cbc349 100644
--- a/target-arm/helper-a64.h
+++ b/target-arm/helper-a64.h
@@ -43,3 +43,5 @@ DEF_HELPER_FLAGS_1(neon_addlp_s8, TCG_CALL_NO_RWG_SE, i64,
i64)
DEF_HELPER_FLAGS_1(neon_addlp_u8, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_FLAGS_1(neon_addlp_s16, TCG_CALL_NO_RWG_SE, i64, i64)
DEF_HELPER_FLAGS_1(neon_addlp_u16, TCG_CALL_NO_RWG_SE, i64, i64)
+DEF_HELPER_FLAGS_2(frecpx_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
+DEF_HELPER_FLAGS_2(frecpx_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 2b1ca64..86e5d3e 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -6886,6 +6886,72 @@ static void handle_2misc_fcmp_zero(DisasContext *s, int
opcode,
tcg_temp_free_ptr(fpst);
}
+static void handle_2misc_reciprocal(DisasContext *s, int opcode,
+ bool is_scalar, bool is_u, bool is_q,
+ int size, int rn, int rd)
+{
+ bool is_double = (size == 3);
+ TCGv_ptr fpst = get_fpstatus_ptr();
+
+ if (is_double) {
+ TCGv_i64 tcg_op = tcg_temp_new_i64();
+ TCGv_i64 tcg_res = tcg_temp_new_i64();
+ int pass;
+
+ for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
+ read_vec_element(s, tcg_op, rn, pass, MO_64);
+ switch (opcode) {
+ case 0x3f: /* FRECPX */
+ gen_helper_frecpx_f64(tcg_res, tcg_op, fpst);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ write_vec_element(s, tcg_res, rd, pass, MO_64);
+ }
+ if (is_scalar) {
+ clear_vec_high(s, rd);
+ }
+
+ tcg_temp_free_i64(tcg_res);
+ tcg_temp_free_i64(tcg_op);
+ } else {
+ TCGv_i32 tcg_op = tcg_temp_new_i32();
+ TCGv_i32 tcg_res = tcg_temp_new_i32();
+ int pass, maxpasses;
+
+ if (is_scalar) {
+ maxpasses = 1;
+ } else {
+ maxpasses = is_q ? 4 : 2;
+ }
+
+ for (pass = 0; pass < maxpasses; pass++) {
+ read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
+
+ switch (opcode) {
+ case 0x3f: /* FRECPX */
+ gen_helper_frecpx_f32(tcg_res, tcg_op, fpst);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ if (is_scalar) {
+ write_fp_sreg(s, rd, tcg_res);
+ } else {
+ write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
+ }
+ }
+ tcg_temp_free_i32(tcg_res);
+ tcg_temp_free_i32(tcg_op);
+ if (!is_q && !is_scalar) {
+ clear_vec_high(s, rd);
+ }
+ }
+ tcg_temp_free_ptr(fpst);
+}
+
/* C3.6.12 AdvSIMD scalar two reg misc
* 31 30 29 28 24 23 22 21 17 16 12 11 10 9 5 4 0
* +-----+---+-----------+------+-----------+--------+-----+------+------+
@@ -6942,6 +7008,9 @@ static void disas_simd_scalar_two_reg_misc(DisasContext
*s, uint32_t insn)
handle_simd_intfp_conv(s, rd, rn, 1, is_signed, 0, size);
return;
}
+ case 0x3f: /* FRECPX */
+ handle_2misc_reciprocal(s, opcode, true, u, true, size, rn, rd);
+ return;
case 0x1a: /* FCVTNS */
case 0x1b: /* FCVTMS */
case 0x3a: /* FCVTPS */
@@ -6960,7 +7029,6 @@ static void disas_simd_scalar_two_reg_misc(DisasContext
*s, uint32_t insn)
rmode = FPROUNDING_TIEAWAY;
break;
case 0x3d: /* FRECPE */
- case 0x3f: /* FRECPX */
case 0x56: /* FCVTXN, FCVTXN2 */
case 0x7d: /* FRSQRTE */
unsupported_encoding(s, insn);
--
1.9.0
- [Qemu-devel] [PULL 17/30] target-arm: A64: List unsupported shift-imm opcodes, (continued)
- [Qemu-devel] [PULL 17/30] target-arm: A64: List unsupported shift-imm opcodes, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 27/30] target-arm: A64: Implement scalar saturating narrow ops, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 30/30] scripts/qemu-binfmt-conf.sh: Add AArch64 registration, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 11/30] target-arm: A64: Saturating and narrowing shift ops, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 20/30] target-arm: A64: Implement FRINT*, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 29/30] target-arm: A64: Add [UF]RSQRTE (reciprocal root estimate), Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 15/30] target-arm: A64: Implement FCVTN, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 08/30] target-arm: A64: Add last AdvSIMD Integer to FP ops, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 24/30] softfloat: export squash_input_denormal functions, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 01/30] vexpress: Set reset-cbar property for CPUs, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 18/30] target-arm: A64: Add FRECPX (reciprocal exponent),
Peter Maydell <=
- [Qemu-devel] [PULL 28/30] target-arm: A64: Implement FCVTXN, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 25/30] target-arm: A64: Implement AdvSIMD reciprocal estimate insns URECPE, FRECPE, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 26/30] target-arm: A64: Move handle_2misc_narrow function, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 04/30] virt: Set reset-cbar on CPUs, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 21/30] exec-all.h: Increase MAX_OP_PER_INSTR for ARM A64 decoder, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 02/30] realview-pbx-a9: Set reset-cbar property for CPUs, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 06/30] target-arm: A64: Implement PMULL instruction, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 05/30] target-arm: Add ARM_CP_IO notation to PMCR reginfo, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 19/30] target-arm: A64: Implement SRI, Peter Maydell, 2014/03/17
- [Qemu-devel] [PULL 22/30] target-arm: A64: Handle saturating left shifts SQSHL, SQSHLU, UQSHL, Peter Maydell, 2014/03/17