Test A[L]UIPC opcodes.

Signed-off-by: Philippe Mathieu-Daudé <[email protected]>
---
 tests/tcg/mipsel/test_mips32r6_pcrel.c | 95 ++++++++++++++++++++++++++
 tests/tcg/mipsel/meson.build           |  1 +
 2 files changed, 96 insertions(+)
 create mode 100644 tests/tcg/mipsel/test_mips32r6_pcrel.c

diff --git a/tests/tcg/mipsel/test_mips32r6_pcrel.c 
b/tests/tcg/mipsel/test_mips32r6_pcrel.c
new file mode 100644
index 000000000000..dd16357953ae
--- /dev/null
+++ b/tests/tcg/mipsel/test_mips32r6_pcrel.c
@@ -0,0 +1,95 @@
+/*
+ * MIPS32R6 tests: PC-relative AUIPC and ALUIPC instructions
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+/*
+ * Run INSN with the immediate IMM, and probe the address of INSN with a
+ * second AUIPC (which yields its own address, +4 being INSN's size).
+ */
+#define PCREL(insn, imm, res, addr)                                     \
+    __asm__ volatile (                                                  \
+        ".set push\n\t"                                                 \
+        ".set noreorder\n\t"                                            \
+        insn " %0, " #imm "\n\t"                                        \
+        "auipc %1, 0\n\t"                                               \
+        ".set pop\n\t"                                                  \
+        : "=r" (res), "=r" (addr))
+
+static int count;
+
+static int check(const char *name, uint32_t imm, uint32_t res, uint32_t probe,
+                 int aligned)
+{
+    /* The probe AUIPC is the instruction after the tested one. */
+    uint32_t addr = probe - 4;
+    uint32_t expected = addr + (imm << 16);
+    int ok;
+
+    if (aligned) {
+        expected &= ~0xffffu;
+    }
+    ok = res == expected;
+    if (!ok) {
+        printf("# %s imm=0x%04x at 0x%08x: got 0x%08x expected 0x%08x\n",
+               name, imm, addr, res, expected);
+    }
+    return !ok;
+}
+
+#define CHECK_AUIPC(imm)                                                \
+    do {                                                                \
+        uint32_t res, probe;                                            \
+        PCREL("auipc", imm, res, probe);                                \
+        ret |= check("AUIPC", imm, res, probe, 0);                      \
+    } while (0)
+
+#define CHECK_ALUIPC(imm)                                               \
+    do {                                                                \
+        uint32_t res, probe;                                            \
+        PCREL("aluipc", imm, res, probe);                               \
+        ret |= check("ALUIPC", imm, res, probe, 1);                     \
+    } while (0)
+
+static int test_auipc(void)
+{
+    int ret = 0;
+
+    CHECK_AUIPC(0);
+    CHECK_AUIPC(1);
+    CHECK_AUIPC(0x7fff);
+    CHECK_AUIPC(0x8000);
+    CHECK_AUIPC(0xffff);
+    return ret;
+}
+
+static int test_aluipc(void)
+{
+    int ret = 0;
+
+    CHECK_ALUIPC(0);
+    CHECK_ALUIPC(1);
+    CHECK_ALUIPC(0x7fff);
+    CHECK_ALUIPC(0x8000);
+    CHECK_ALUIPC(0xffff);
+    return ret;
+}
+
+int main(void)
+{
+    int ret = 0, r;
+
+    printf("TAP version 14\n1..2\n");
+    r = test_auipc();
+    printf("%s %d - MIPS32R6 AUIPC\n", r ? "not ok" : "ok", ++count);
+    ret |= r;
+    r = test_aluipc();
+    printf("%s %d - MIPS32R6 ALUIPC\n", r ? "not ok" : "ok", ++count);
+    ret |= r;
+
+    return ret ? 1 : 0;
+}
diff --git a/tests/tcg/mipsel/meson.build b/tests/tcg/mipsel/meson.build
index 9d7cfcf1c6a0..3425962d3715 100644
--- a/tests/tcg/mipsel/meson.build
+++ b/tests/tcg/mipsel/meson.build
@@ -91,6 +91,7 @@ tests_mips32r6 = [
   'test_mips32r6_bitops.c',
   'test_mips32r6_logic.c',
   'test_mips32r6_multiply.c',
+  'test_mips32r6_pcrel.c',
   'test_mips32r6_shift.c',
 ]
 
-- 
2.55.0


Reply via email to