Add edge case tests for the sfrecipa instruction

Signed-off-by: Brian Cain <[email protected]>
---
 tests/tcg/hexagon/fpstuff.c | 81 +++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/tests/tcg/hexagon/fpstuff.c b/tests/tcg/hexagon/fpstuff.c
index 7561f31cdc3..f82262ab4ac 100644
--- a/tests/tcg/hexagon/fpstuff.c
+++ b/tests/tcg/hexagon/fpstuff.c
@@ -345,6 +345,86 @@ static void check_sfrecipa(void)
     check32(pred, 0x80);
 }
 
+/*
+ * Helper to run sfrecipa and capture result + USR.
+ */
+static void do_sfrecipa(uint32_t Rs, uint32_t Rt,
+                        uint32_t *Rd, uint32_t *usr_out)
+{
+    uint32_t rd, usr;
+
+    asm volatile(CLEAR_FPSTATUS
+        "%[rd],p0 = sfrecipa(%[Rs], %[Rt])\n\t"
+        "%[usr] = usr\n\t"
+        : [rd] "=r"(rd), [usr] "=r"(usr)
+        : [Rs] "r"(Rs), [Rt] "r"(Rt)
+        : "p0", "r2", "usr");
+    *Rd = rd;
+    *usr_out = usr;
+}
+
+/*
+ * Additional sfrecipa edge cases:
+ *   - inf/inf, 0/0 -> NaN + invalid
+ *   - normal/inf, 0/normal, inf/normal
+ *   - denominator with extreme biased exponents
+ */
+static void check_sfrecipa_edges(void)
+{
+    uint32_t rd, usr;
+
+    /* inf / inf -> invalid */
+    do_sfrecipa(SF_INF, SF_INF, &rd, &usr);
+    check_fpstatus(usr, USR_FPINVF);
+
+    /* -inf / +inf -> invalid */
+    do_sfrecipa(0xff800000, SF_INF, &rd, &usr);
+    check_fpstatus(usr, USR_FPINVF);
+
+    /* 0 / 0 -> invalid */
+    do_sfrecipa(SF_zero, SF_zero, &rd, &usr);
+    check_fpstatus(usr, USR_FPINVF);
+
+    /* -0 / +0 -> invalid */
+    do_sfrecipa(SF_zero_neg, SF_zero, &rd, &usr);
+    check_fpstatus(usr, USR_FPINVF);
+
+    /* normal / inf -> fixup (Rd = 1.0) */
+    do_sfrecipa(SF_one, SF_INF, &rd, &usr);
+    check32(rd, SF_one);
+
+    do_sfrecipa(SF_two, SF_INF, &rd, &usr);
+    check32(rd, SF_one);
+
+    /* 0 / normal -> fixup (Rd = 1.0) */
+    do_sfrecipa(SF_zero, SF_one, &rd, &usr);
+    check32(rd, SF_one);
+
+    do_sfrecipa(SF_zero_neg, SF_two, &rd, &usr);
+    check32(rd, SF_one);
+
+    /* inf / normal -> fixup (Rd = 1.0) */
+    do_sfrecipa(SF_INF, SF_one, &rd, &usr);
+    check32(rd, SF_one);
+
+    do_sfrecipa(0xff800000, SF_two, &rd, &usr);
+    check32(rd, SF_one);
+
+    /*
+     * Denominator with biased exponent <= 1.
+     * Rs: biased exp 26, Rt: biased exp 1.
+     */
+    do_sfrecipa(26U << 23, 1U << 23, &rd, &usr);
+    check32_ne(rd, 0);
+
+    /*
+     * Denominator with biased exponent > 252.
+     * Both: biased exp 253.
+     */
+    do_sfrecipa(253U << 23, 253U << 23, &rd, &usr);
+    check32_ne(rd, 0);
+}
+
 static void check_canonical_NaN(void)
 {
     uint32_t sf_result;
@@ -887,6 +967,7 @@ int main()
     check_sfminmax();
     check_dfminmax();
     check_sfrecipa();
+    check_sfrecipa_edges();
     check_canonical_NaN();
     check_invsqrta();
     check_sffixupn();
-- 
2.34.1

Reply via email to