* [PATCH 3/6] tests/tcg/mips: Add mips32 arithmatic instruction test cases
2022-10-24 15:23 [PATCH 0/6] MIPS decodetree conversion Jiaxun Yang
2022-10-24 15:23 ` [PATCH 1/6] target/mips: Introduce register access helper functions Jiaxun Yang
2022-10-24 15:23 ` [PATCH 2/6] target/mips: Convert legacy arithmatic instructions to decodetree Jiaxun Yang
@ 2022-10-24 15:23 ` Jiaxun Yang
2022-10-24 15:23 ` [PATCH 4/6] target/mips: Split Loongson extention translation into standalone file Jiaxun Yang
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Jiaxun Yang @ 2022-10-24 15:23 UTC (permalink / raw)
To: qemu-devel; +Cc: f4bug, richard.henderson, Jiaxun Yang
Those cases are delivered from MIPS internal architecture validation
tools.
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
tests/tcg/mips/include/test_utils_32.h | 75 +++++++++++
.../tcg/mips/user/isa/mips32/arithmatic/add.c | 99 ++++++++++++++
.../mips/user/isa/mips32/arithmatic/addi.c | 70 ++++++++++
.../mips/user/isa/mips32/arithmatic/addiu.c | 90 +++++++++++++
.../mips/user/isa/mips32/arithmatic/addu.c | 125 ++++++++++++++++++
.../tcg/mips/user/isa/mips32/arithmatic/div.c | 81 ++++++++++++
.../mips/user/isa/mips32/arithmatic/divu.c | 78 +++++++++++
.../mips/user/isa/mips32/arithmatic/madd.c | 79 +++++++++++
.../mips/user/isa/mips32/arithmatic/maddu.c | 78 +++++++++++
.../mips/user/isa/mips32/arithmatic/msub.c | 78 +++++++++++
.../mips/user/isa/mips32/arithmatic/msubu.c | 78 +++++++++++
.../tcg/mips/user/isa/mips32/arithmatic/mul.c | 78 +++++++++++
.../mips/user/isa/mips32/arithmatic/mult.c | 78 +++++++++++
.../mips/user/isa/mips32/arithmatic/multu.c | 78 +++++++++++
.../tcg/mips/user/isa/mips32/arithmatic/slt.c | 61 +++++++++
.../mips/user/isa/mips32/arithmatic/slti.c | 48 +++++++
.../mips/user/isa/mips32/arithmatic/sltiu.c | 48 +++++++
.../mips/user/isa/mips32/arithmatic/sltu.c | 61 +++++++++
.../tcg/mips/user/isa/mips32/arithmatic/sub.c | 104 +++++++++++++++
.../mips/user/isa/mips32/arithmatic/subu.c | 108 +++++++++++++++
20 files changed, 1595 insertions(+)
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/add.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/addi.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/addiu.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/addu.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/div.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/divu.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/madd.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/maddu.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/msub.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/msubu.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/mul.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/mult.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/multu.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/slt.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/slti.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/sltiu.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/sltu.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/sub.c
create mode 100644 tests/tcg/mips/user/isa/mips32/arithmatic/subu.c
diff --git a/tests/tcg/mips/include/test_utils_32.h b/tests/tcg/mips/include/test_utils_32.h
index c33990c0c5..00480e3283 100644
--- a/tests/tcg/mips/include/test_utils_32.h
+++ b/tests/tcg/mips/include/test_utils_32.h
@@ -29,6 +29,81 @@
#define PRINT_RESULTS 0
+#define DO_MIPS32_r(mnemonic, id, input1, input2, expect) \
+{ \
+ uint32_t output; \
+ uint32_t expect_val = expect; \
+ __asm__ volatile ( \
+ "li $t1, " #input1 "\n\t" \
+ "li $t2, " #input2 "\n\t" \
+ #mnemonic " $t0, $t1, $t2\n\t" \
+ "sw $t0, 0(%0)\n\t" \
+ : \
+ : "r" (&output) \
+ : "t0", "t1", "t2", "memory" \
+ ); \
+ check_single_insn_32(id, &pass_count, &fail_count, 1, &expect_val, &output); \
+}
+
+#define DO_MIPS32_i(mnemonic, id, imm, input1, expect) \
+{ \
+ uint32_t output; \
+ uint32_t expect_val = expect; \
+ __asm__ volatile ( \
+ "li $t1, " #input1 "\n\t" \
+ #mnemonic " $t0, $t1, " #imm "\n\t" \
+ "sw $t0, 0(%0)\n\t" \
+ : \
+ : "r" (&output) \
+ : "t0", "t1", "memory" \
+ ); \
+ check_single_insn_32(id, &pass_count, &fail_count, 1, &expect_val, &output); \
+}
+
+#define DO_MIPS32_r2_s(mnemonic, id, hi, lo, input1, input2, expect_hi, expect_lo) \
+{ \
+ uint32_t output[2]; \
+ uint32_t expect_val[2] = {expect_lo, expect_hi}; \
+ __asm__ volatile ( \
+ ".set noreorder \n\t" \
+ "li $t0, " #hi "\n\t" \
+ "mthi $t0 \n\t" \
+ "li $t0, " #lo "\n\t" \
+ "mtlo $t0 \n\t" \
+ "li $t0, " #input1 "\n\t" \
+ "li $t1, " #input2 "\n\t" \
+ #mnemonic " $t0, $t1 \n\t" \
+ "mfhi $t0 \n\t" \
+ "sw $t0, 4(%0)\n\t" \
+ "mflo $t0 \n\t" \
+ "sw $t0, 0(%0)\n\t" \
+ ".set reorder \n\t" \
+ : \
+ : "r" (&output) \
+ : "t0", "t1", "hi", "lo", "memory" \
+ ); \
+ check_single_insn_32(id, &pass_count, &fail_count, 2, expect_val, output); \
+}
+
+static inline void check_single_insn_32(int id, int *pass, int *fail, int cnt,
+ uint32_t *expect, uint32_t *actual)
+{
+ int i;
+
+ if (memcmp(expect, actual, 4 * cnt) == 0) {
+ (*pass)++;
+ printf("Case %d pass:\n", id);
+ for (i = 0; i < cnt; i++) {
+ printf(" [%d]: actual: 0x%08x, expect: 0x%08x\n", i, actual[i], expect[i]);
+ }
+ } else {
+ (*fail)++;
+ printf("Case %d fail:\n", id);
+ for (i = 0; i < cnt; i++) {
+ printf(" [%d]: actual: 0x%08x, expect: 0x%08x\n", i, actual[i], expect[i]);
+ }
+ }
+}
static inline int32_t check_results_32(const char *instruction_name,
const uint32_t test_count,
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/add.c b/tests/tcg/mips/user/isa/mips32/arithmatic/add.c
new file mode 100644
index 0000000000..2e1d380c90
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/add.c
@@ -0,0 +1,99 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_r(add, 0, 0x00000000, 0x00000000, 0x00000000);
+ DO_MIPS32_r(add, 1, 0x00000001, 0x00000001, 0x00000002);
+ DO_MIPS32_r(add, 2, 0x00000002, 0x00000003, 0x00000005);
+ DO_MIPS32_r(add, 3, 0x00000004, 0x00000007, 0x0000000B);
+ DO_MIPS32_r(add, 4, 0x00000008, 0x0000000F, 0x00000017);
+ DO_MIPS32_r(add, 5, 0x00000010, 0x0000001F, 0x0000002F);
+ DO_MIPS32_r(add, 6, 0x00000020, 0x0000003F, 0x0000005F);
+ DO_MIPS32_r(add, 7, 0x00000040, 0x0000007F, 0x000000BF);
+ DO_MIPS32_r(add, 8, 0x00000080, 0x000000FF, 0x0000017F);
+ DO_MIPS32_r(add, 9, 0x00000100, 0x000001FF, 0x000002FF);
+ DO_MIPS32_r(add, 10, 0x00000200, 0x000003FF, 0x000005FF);
+ DO_MIPS32_r(add, 11, 0x00000400, 0x000007FF, 0x00000BFF);
+ DO_MIPS32_r(add, 12, 0x00000800, 0x00000FFF, 0x000017FF);
+ DO_MIPS32_r(add, 13, 0x00001000, 0x00001FFF, 0x00002FFF);
+ DO_MIPS32_r(add, 14, 0x00002000, 0x00003FFF, 0x00005FFF);
+ DO_MIPS32_r(add, 15, 0x00004000, 0x00007FFF, 0x0000BFFF);
+ DO_MIPS32_r(add, 16, 0x00008000, 0x0000FFFF, 0x00017FFF);
+ DO_MIPS32_r(add, 17, 0x00010000, 0x0001FFFF, 0x0002FFFF);
+ DO_MIPS32_r(add, 18, 0x00020000, 0x0003FFFF, 0x0005FFFF);
+ DO_MIPS32_r(add, 19, 0x00040000, 0x0007FFFF, 0x000BFFFF);
+ DO_MIPS32_r(add, 20, 0x00080000, 0x000FFFFF, 0x0017FFFF);
+ DO_MIPS32_r(add, 21, 0x00100000, 0x001FFFFF, 0x002FFFFF);
+ DO_MIPS32_r(add, 22, 0x00200000, 0x003FFFFF, 0x005FFFFF);
+ DO_MIPS32_r(add, 23, 0x00400000, 0x007FFFFF, 0x00BFFFFF);
+ DO_MIPS32_r(add, 24, 0x00800000, 0x00FFFFFF, 0x017FFFFF);
+ DO_MIPS32_r(add, 25, 0x01000000, 0x01FFFFFF, 0x02FFFFFF);
+ DO_MIPS32_r(add, 26, 0x02000000, 0x03FFFFFF, 0x05FFFFFF);
+ DO_MIPS32_r(add, 27, 0x04000000, 0x07FFFFFF, 0x0BFFFFFF);
+ DO_MIPS32_r(add, 28, 0x08000000, 0x0FFFFFFF, 0x17FFFFFF);
+ DO_MIPS32_r(add, 29, 0x10000000, 0x1FFFFFFF, 0x2FFFFFFF);
+ DO_MIPS32_r(add, 30, 0x20000000, 0x3FFFFFFF, 0x5FFFFFFF);
+ DO_MIPS32_r(add, 31, 0x00000000, 0x00000001, 0x00000001);
+ DO_MIPS32_r(add, 32, 0x80000001, 0xFFFFFFFF, 0x80000000);
+ DO_MIPS32_r(add, 33, 0xC0000003, 0x7FFFFFFD, 0x40000000);
+ DO_MIPS32_r(add, 34, 0xE0000007, 0x3FFFFFF9, 0x20000000);
+ DO_MIPS32_r(add, 35, 0xF000000F, 0x1FFFFFF1, 0x10000000);
+ DO_MIPS32_r(add, 36, 0xF800001F, 0x0FFFFFE1, 0x08000000);
+ DO_MIPS32_r(add, 37, 0xFC00003F, 0x07FFFFC1, 0x04000000);
+ DO_MIPS32_r(add, 38, 0xFE00007F, 0x03FFFF81, 0x02000000);
+ DO_MIPS32_r(add, 39, 0xFF0000FF, 0x01FFFF01, 0x01000000);
+ DO_MIPS32_r(add, 40, 0xFF8001FF, 0x00FFFE01, 0x00800000);
+ DO_MIPS32_r(add, 41, 0xFFC003FF, 0x007FFC01, 0x00400000);
+ DO_MIPS32_r(add, 42, 0xFFE007FF, 0x003FF801, 0x00200000);
+ DO_MIPS32_r(add, 43, 0xFFF00FFF, 0x001FF001, 0x00100000);
+ DO_MIPS32_r(add, 44, 0xFFF81FFF, 0x000FE001, 0x00080000);
+ DO_MIPS32_r(add, 45, 0xFFFC3FFF, 0x0007C001, 0x00040000);
+ DO_MIPS32_r(add, 46, 0xFFFE7FFF, 0x00038001, 0x00020000);
+ DO_MIPS32_r(add, 47, 0xFFFFFFFF, 0x00010001, 0x00010000);
+ DO_MIPS32_r(add, 48, 0xFFFFFFFF, 0x00018001, 0x00018000);
+ DO_MIPS32_r(add, 49, 0xFFFE7FFF, 0x00024001, 0x0000C000);
+ DO_MIPS32_r(add, 50, 0xFFFC3FFF, 0x00042001, 0x00006000);
+ DO_MIPS32_r(add, 51, 0xFFF81FFF, 0x00081001, 0x00003000);
+ DO_MIPS32_r(add, 52, 0xFFF00FFF, 0x00100801, 0x00001800);
+ DO_MIPS32_r(add, 53, 0xFFE007FF, 0x00200401, 0x00000C00);
+ DO_MIPS32_r(add, 54, 0xFFC003FF, 0x00400201, 0x00000600);
+ DO_MIPS32_r(add, 55, 0xFF8001FF, 0x00800101, 0x00000300);
+ DO_MIPS32_r(add, 56, 0xFF0000FF, 0x01000081, 0x00000180);
+ DO_MIPS32_r(add, 57, 0xFE00007F, 0x02000041, 0x000000C0);
+ DO_MIPS32_r(add, 58, 0xFC00003F, 0x04000021, 0x00000060);
+ DO_MIPS32_r(add, 59, 0xF800001F, 0x08000011, 0x00000030);
+ DO_MIPS32_r(add, 60, 0xF000000F, 0x10000009, 0x00000018);
+ DO_MIPS32_r(add, 61, 0xE0000007, 0x20000005, 0x0000000C);
+ DO_MIPS32_r(add, 62, 0xC0000003, 0x40000003, 0x00000006);
+ DO_MIPS32_r(add, 63, 0x00000000, 0x55555555, 0x55555555);
+ DO_MIPS32_r(add, 64, 0x15555555, 0x55555555, 0x6AAAAAAA);
+ DO_MIPS32_r(add, 65, 0xAAAAAAAA, 0x55555555, 0xFFFFFFFF);
+ DO_MIPS32_r(add, 66, 0xFFFFFFFF, 0x55555555, 0x55555554);
+ DO_MIPS32_r(add, 67, 0xAAAAAAAA, 0x00000000, 0xAAAAAAAA);
+ DO_MIPS32_r(add, 68, 0xAAAAAAAA, 0x55555555, 0xFFFFFFFF);
+ DO_MIPS32_r(add, 69, 0xAAAAAAAA, 0x2AAAAAAA, 0xD5555554);
+ DO_MIPS32_r(add, 70, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAA9);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/addi.c b/tests/tcg/mips/user/isa/mips32/arithmatic/addi.c
new file mode 100644
index 0000000000..c032e4d9e5
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/addi.c
@@ -0,0 +1,70 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_i(addi, 0, 0x0000, 0x00000000, 0x00000000);
+ DO_MIPS32_i(addi, 1, 0x0001, 0x00000001, 0x00000002);
+ DO_MIPS32_i(addi, 2, 0x0003, 0x00000002, 0x00000005);
+ DO_MIPS32_i(addi, 3, 0x0007, 0x00000004, 0x0000000B);
+ DO_MIPS32_i(addi, 4, 0x000F, 0x00000008, 0x00000017);
+ DO_MIPS32_i(addi, 5, 0x001F, 0x00000010, 0x0000002F);
+ DO_MIPS32_i(addi, 6, 0x003F, 0x00000020, 0x0000005F);
+ DO_MIPS32_i(addi, 7, 0x007F, 0x00000040, 0x000000BF);
+ DO_MIPS32_i(addi, 8, 0x00FF, 0x00000080, 0x0000017F);
+ DO_MIPS32_i(addi, 9, 0x01FF, 0x00000100, 0x000002FF);
+ DO_MIPS32_i(addi, 10, 0x03FF, 0x00000200, 0x000005FF);
+ DO_MIPS32_i(addi, 11, 0x07FF, 0x00000400, 0x00000BFF);
+ DO_MIPS32_i(addi, 12, 0x0FFF, 0x00000800, 0x000017FF);
+ DO_MIPS32_i(addi, 13, 0x1FFF, 0x00001000, 0x00002FFF);
+ DO_MIPS32_i(addi, 14, 0x3FFF, 0x00002000, 0x00005FFF);
+ DO_MIPS32_i(addi, 15, 0x7FFF, 0x00004000, 0x0000BFFF);
+ DO_MIPS32_i(addi, 16, 0xFFFF, 0x00008000, 0x00007FFF);
+ DO_MIPS32_i(addi, 17, 0x0001, 0x00000000, 0x00000001);
+ DO_MIPS32_i(addi, 18, 0xFFFF, 0x80000001, 0x80000000);
+ DO_MIPS32_i(addi, 19, 0xFFFD, 0xC0000003, 0xC0000000);
+ DO_MIPS32_i(addi, 20, 0xFFF9, 0xE0000007, 0xE0000000);
+ DO_MIPS32_i(addi, 21, 0xFFF1, 0xF000000F, 0xF0000000);
+ DO_MIPS32_i(addi, 22, 0xFFE1, 0xF800001F, 0xF8000000);
+ DO_MIPS32_i(addi, 23, 0xFFC1, 0xFC00003F, 0xFC000000);
+ DO_MIPS32_i(addi, 24, 0xFF81, 0xFE00007F, 0xFE000000);
+ DO_MIPS32_i(addi, 25, 0xFF01, 0xFF0000FF, 0xFF000000);
+ DO_MIPS32_i(addi, 26, 0xFE01, 0xFF8001FF, 0xFF800000);
+ DO_MIPS32_i(addi, 27, 0xFC01, 0xFFC003FF, 0xFFC00000);
+ DO_MIPS32_i(addi, 28, 0xF801, 0xFFE007FF, 0xFFE00000);
+ DO_MIPS32_i(addi, 29, 0xF001, 0xFFF00FFF, 0xFFF00000);
+ DO_MIPS32_i(addi, 30, 0xE001, 0xFFF81FFF, 0xFFF80000);
+ DO_MIPS32_i(addi, 31, 0xC001, 0xFFFC3FFF, 0xFFFC0000);
+ DO_MIPS32_i(addi, 32, 0x8001, 0xFFFE7FFF, 0xFFFE0000);
+ DO_MIPS32_i(addi, 33, 0x0001, 0xFFFFFFFF, 0x00000000);
+ DO_MIPS32_i(addi, 34, 0x5555, 0x00000000, 0x00005555);
+ DO_MIPS32_i(addi, 35, 0x5555, 0x55555555, 0x5555AAAA);
+ DO_MIPS32_i(addi, 36, 0x5555, 0xAAAAAAAA, 0xAAAAFFFF);
+ DO_MIPS32_i(addi, 37, 0x5555, 0xFFFFFFFF, 0x00005554);
+ DO_MIPS32_i(addi, 38, 0x0000, 0xAAAAAAAA, 0xAAAAAAAA);
+ DO_MIPS32_i(addi, 39, 0x5555, 0xAAAAAAAA, 0xAAAAFFFF);
+ DO_MIPS32_i(addi, 40, 0xAAAA, 0xAAAAAAAA, 0xAAAA5554);
+ DO_MIPS32_i(addi, 41, 0xFFFF, 0xAAAAAAAA, 0xAAAAAAA9);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/addiu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/addiu.c
new file mode 100644
index 0000000000..cdc2ebc932
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/addiu.c
@@ -0,0 +1,90 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_i(addiu, 0, 0x0000, 0x00000000, 0x00000000);
+ DO_MIPS32_i(addiu, 1, 0x0001, 0x00000001, 0x00000002);
+ DO_MIPS32_i(addiu, 2, 0x0003, 0x00000002, 0x00000005);
+ DO_MIPS32_i(addiu, 3, 0x0007, 0x00000004, 0x0000000B);
+ DO_MIPS32_i(addiu, 4, 0x000F, 0x00000008, 0x00000017);
+ DO_MIPS32_i(addiu, 5, 0x001F, 0x00000010, 0x0000002F);
+ DO_MIPS32_i(addiu, 6, 0x003F, 0x00000020, 0x0000005F);
+ DO_MIPS32_i(addiu, 7, 0x007F, 0x00000040, 0x000000BF);
+ DO_MIPS32_i(addiu, 8, 0x00FF, 0x00000080, 0x0000017F);
+ DO_MIPS32_i(addiu, 9, 0x01FF, 0x00000100, 0x000002FF);
+ DO_MIPS32_i(addiu, 10, 0x03FF, 0x00000200, 0x000005FF);
+ DO_MIPS32_i(addiu, 11, 0x07FF, 0x00000400, 0x00000BFF);
+ DO_MIPS32_i(addiu, 12, 0x0FFF, 0x00000800, 0x000017FF);
+ DO_MIPS32_i(addiu, 13, 0x1FFF, 0x00001000, 0x00002FFF);
+ DO_MIPS32_i(addiu, 14, 0x3FFF, 0x00002000, 0x00005FFF);
+ DO_MIPS32_i(addiu, 15, 0x7FFF, 0x00004000, 0x0000BFFF);
+ DO_MIPS32_i(addiu, 16, -1, 0x00008000, 0x00007FFF);
+ DO_MIPS32_i(addiu, 17, 0x0001, 0x00000000, 0x00000001);
+ DO_MIPS32_i(addiu, 18, -1, 0x80000001, 0x80000000);
+ DO_MIPS32_i(addiu, 19, -3, 0xC0000003, 0xC0000000);
+ DO_MIPS32_i(addiu, 20, -7, 0xE0000007, 0xE0000000);
+ DO_MIPS32_i(addiu, 21, -15, 0xF000000F, 0xF0000000);
+ DO_MIPS32_i(addiu, 22, -31, 0xF800001F, 0xF8000000);
+ DO_MIPS32_i(addiu, 23, -63, 0xFC00003F, 0xFC000000);
+ DO_MIPS32_i(addiu, 24, -127, 0xFE00007F, 0xFE000000);
+ DO_MIPS32_i(addiu, 25, -255, 0xFF0000FF, 0xFF000000);
+ DO_MIPS32_i(addiu, 26, -511, 0xFF8001FF, 0xFF800000);
+ DO_MIPS32_i(addiu, 27, -1023, 0xFFC003FF, 0xFFC00000);
+ DO_MIPS32_i(addiu, 28, -2047, 0xFFE007FF, 0xFFE00000);
+ DO_MIPS32_i(addiu, 29, -4095, 0xFFF00FFF, 0xFFF00000);
+ DO_MIPS32_i(addiu, 30, -8191, 0xFFF81FFF, 0xFFF80000);
+ DO_MIPS32_i(addiu, 31, 0xC001, 0xFFFC3FFF, 0xFFFC0000);
+ DO_MIPS32_i(addiu, 32, 0x8001, 0xFFFE7FFF, 0xFFFE0000);
+ DO_MIPS32_i(addiu, 33, 0x0001, 0xFFFFFFFF, 0x00000000);
+ DO_MIPS32_i(addiu, 34, 0x5555, 0x00000000, 0x00005555);
+ DO_MIPS32_i(addiu, 35, 0x5555, 0x55555555, 0x5555AAAA);
+ DO_MIPS32_i(addiu, 36, 0x5555, 0xAAAAAAAA, 0xAAAAFFFF);
+ DO_MIPS32_i(addiu, 37, 0x5555, 0xFFFFFFFF, 0x00005554);
+ DO_MIPS32_i(addiu, 38, 0x0000, 0xAAAAAAAA, 0xAAAAAAAA);
+ DO_MIPS32_i(addiu, 39, 0x5555, 0xAAAAAAAA, 0xAAAAFFFF);
+ DO_MIPS32_i(addiu, 40, 0xAAAA, 0xAAAAAAAA, 0xAAAA5554);
+ DO_MIPS32_i(addiu, 41, -1, 0xAAAAAAAA, 0xAAAAAAA9);
+ DO_MIPS32_i(addiu, 42, 0x0001, 0x7FFFFFFF, 0x80000000);
+ DO_MIPS32_i(addiu, 43, 0x7FFF, 0x7FFFFFFF, 0x80007FFE);
+ DO_MIPS32_i(addiu, 44, -1, 0x80000000, 0x7FFFFFFF);
+ DO_MIPS32_i(addiu, 45, 0x8000, 0x80000000, 0x7FFF8000);
+ DO_MIPS32_i(addiu, 46, 0x555F, 0x7FFFAAAA, 0x80000009);
+ DO_MIPS32_i(addiu, 47, 0xAAAA, 0x7FFF5555, 0x7FFEFFFF);
+ DO_MIPS32_i(addiu, 48, 0x0002, 0x7FFFFFFF, 0x80000001);
+ DO_MIPS32_i(addiu, 49, 0x0004, 0x7FFFFFFF, 0x80000003);
+ DO_MIPS32_i(addiu, 50, 0x0008, 0x7FFFFFFF, 0x80000007);
+ DO_MIPS32_i(addiu, 51, 0x0010, 0x7FFFFFFF, 0x8000000F);
+ DO_MIPS32_i(addiu, 52, 0x0020, 0x7FFFFFFF, 0x8000001F);
+ DO_MIPS32_i(addiu, 53, 0x0040, 0x7FFFFFFF, 0x8000003F);
+ DO_MIPS32_i(addiu, 54, 0x0080, 0x7FFFFFFF, 0x8000007F);
+ DO_MIPS32_i(addiu, 55, 0x0100, 0x7FFFFFFF, 0x800000FF);
+ DO_MIPS32_i(addiu, 56, 0x0200, 0x7FFFFFFF, 0x800001FF);
+ DO_MIPS32_i(addiu, 57, 0x0400, 0x7FFFFFFF, 0x800003FF);
+ DO_MIPS32_i(addiu, 58, 0x0800, 0x7FFFFFFF, 0x800007FF);
+ DO_MIPS32_i(addiu, 59, 0x1000, 0x7FFFFFFF, 0x80000FFF);
+ DO_MIPS32_i(addiu, 60, 0x2000, 0x7FFFFFFF, 0x80001FFF);
+ DO_MIPS32_i(addiu, 61, 0x4000, 0x7FFFFFFF, 0x80003FFF);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/addu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/addu.c
new file mode 100644
index 0000000000..062999edd6
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/addu.c
@@ -0,0 +1,125 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_r(addu, 0, 0x00000000, 0x00000000, 0x00000000);
+ DO_MIPS32_r(addu, 1, 0x00000001, 0x00000001, 0x00000002);
+ DO_MIPS32_r(addu, 2, 0x00000002, 0x00000003, 0x00000005);
+ DO_MIPS32_r(addu, 3, 0x00000004, 0x00000007, 0x0000000B);
+ DO_MIPS32_r(addu, 4, 0x00000008, 0x0000000F, 0x00000017);
+ DO_MIPS32_r(addu, 5, 0x00000010, 0x0000001F, 0x0000002F);
+ DO_MIPS32_r(addu, 6, 0x00000020, 0x0000003F, 0x0000005F);
+ DO_MIPS32_r(addu, 7, 0x00000040, 0x0000007F, 0x000000BF);
+ DO_MIPS32_r(addu, 8, 0x00000080, 0x000000FF, 0x0000017F);
+ DO_MIPS32_r(addu, 9, 0x00000100, 0x000001FF, 0x000002FF);
+ DO_MIPS32_r(addu, 10, 0x00000200, 0x000003FF, 0x000005FF);
+ DO_MIPS32_r(addu, 11, 0x00000400, 0x000007FF, 0x00000BFF);
+ DO_MIPS32_r(addu, 12, 0x00000800, 0x00000FFF, 0x000017FF);
+ DO_MIPS32_r(addu, 13, 0x00001000, 0x00001FFF, 0x00002FFF);
+ DO_MIPS32_r(addu, 14, 0x00002000, 0x00003FFF, 0x00005FFF);
+ DO_MIPS32_r(addu, 15, 0x00004000, 0x00007FFF, 0x0000BFFF);
+ DO_MIPS32_r(addu, 16, 0x00008000, 0x0000FFFF, 0x00017FFF);
+ DO_MIPS32_r(addu, 17, 0x00010000, 0x0001FFFF, 0x0002FFFF);
+ DO_MIPS32_r(addu, 18, 0x00020000, 0x0003FFFF, 0x0005FFFF);
+ DO_MIPS32_r(addu, 19, 0x00040000, 0x0007FFFF, 0x000BFFFF);
+ DO_MIPS32_r(addu, 20, 0x00080000, 0x000FFFFF, 0x0017FFFF);
+ DO_MIPS32_r(addu, 21, 0x00100000, 0x001FFFFF, 0x002FFFFF);
+ DO_MIPS32_r(addu, 22, 0x00200000, 0x003FFFFF, 0x005FFFFF);
+ DO_MIPS32_r(addu, 23, 0x00400000, 0x007FFFFF, 0x00BFFFFF);
+ DO_MIPS32_r(addu, 24, 0x00800000, 0x00FFFFFF, 0x017FFFFF);
+ DO_MIPS32_r(addu, 25, 0x01000000, 0x01FFFFFF, 0x02FFFFFF);
+ DO_MIPS32_r(addu, 26, 0x02000000, 0x03FFFFFF, 0x05FFFFFF);
+ DO_MIPS32_r(addu, 27, 0x04000000, 0x07FFFFFF, 0x0BFFFFFF);
+ DO_MIPS32_r(addu, 28, 0x08000000, 0x0FFFFFFF, 0x17FFFFFF);
+ DO_MIPS32_r(addu, 29, 0x10000000, 0x1FFFFFFF, 0x2FFFFFFF);
+ DO_MIPS32_r(addu, 30, 0x20000000, 0x3FFFFFFF, 0x5FFFFFFF);
+ DO_MIPS32_r(addu, 31, 0x40000000, 0x7FFFFFFF, 0xBFFFFFFF);
+ DO_MIPS32_r(addu, 32, 0x80000000, 0xFFFFFFFF, 0x7FFFFFFF);
+ DO_MIPS32_r(addu, 33, 0x00000000, 0x00000001, 0x00000001);
+ DO_MIPS32_r(addu, 34, 0x80000001, 0xFFFFFFFF, 0x80000000);
+ DO_MIPS32_r(addu, 35, 0xC0000003, 0x7FFFFFFD, 0x40000000);
+ DO_MIPS32_r(addu, 36, 0xE0000007, 0x3FFFFFF9, 0x20000000);
+ DO_MIPS32_r(addu, 37, 0xF000000F, 0x1FFFFFF1, 0x10000000);
+ DO_MIPS32_r(addu, 38, 0xF800001F, 0x0FFFFFE1, 0x08000000);
+ DO_MIPS32_r(addu, 39, 0xFC00003F, 0x07FFFFC1, 0x04000000);
+ DO_MIPS32_r(addu, 40, 0xFE00007F, 0x03FFFF81, 0x02000000);
+ DO_MIPS32_r(addu, 41, 0xFF0000FF, 0x01FFFF01, 0x01000000);
+ DO_MIPS32_r(addu, 42, 0xFF8001FF, 0x00FFFE01, 0x00800000);
+ DO_MIPS32_r(addu, 43, 0xFFC003FF, 0x007FFC01, 0x00400000);
+ DO_MIPS32_r(addu, 44, 0xFFE007FF, 0x003FF801, 0x00200000);
+ DO_MIPS32_r(addu, 45, 0xFFF00FFF, 0x001FF001, 0x00100000);
+ DO_MIPS32_r(addu, 46, 0xFFF81FFF, 0x000FE001, 0x00080000);
+ DO_MIPS32_r(addu, 47, 0xFFFC3FFF, 0x0007C001, 0x00040000);
+ DO_MIPS32_r(addu, 48, 0xFFFE7FFF, 0x00038001, 0x00020000);
+ DO_MIPS32_r(addu, 49, 0xFFFFFFFF, 0x00010001, 0x00010000);
+ DO_MIPS32_r(addu, 50, 0xFFFFFFFF, 0x00018001, 0x00018000);
+ DO_MIPS32_r(addu, 51, 0xFFFE7FFF, 0x00024001, 0x0000C000);
+ DO_MIPS32_r(addu, 52, 0xFFFC3FFF, 0x00042001, 0x00006000);
+ DO_MIPS32_r(addu, 53, 0xFFF81FFF, 0x00081001, 0x00003000);
+ DO_MIPS32_r(addu, 54, 0xFFF00FFF, 0x00100801, 0x00001800);
+ DO_MIPS32_r(addu, 55, 0xFFE007FF, 0x00200401, 0x00000C00);
+ DO_MIPS32_r(addu, 56, 0xFFC003FF, 0x00400201, 0x00000600);
+ DO_MIPS32_r(addu, 57, 0xFF8001FF, 0x00800101, 0x00000300);
+ DO_MIPS32_r(addu, 58, 0xFF0000FF, 0x01000081, 0x00000180);
+ DO_MIPS32_r(addu, 59, 0xFE00007F, 0x02000041, 0x000000C0);
+ DO_MIPS32_r(addu, 60, 0xFC00003F, 0x04000021, 0x00000060);
+ DO_MIPS32_r(addu, 61, 0xF800001F, 0x08000011, 0x00000030);
+ DO_MIPS32_r(addu, 62, 0xF000000F, 0x10000009, 0x00000018);
+ DO_MIPS32_r(addu, 63, 0xE0000007, 0x20000005, 0x0000000C);
+ DO_MIPS32_r(addu, 64, 0xC0000003, 0x40000003, 0x00000006);
+ DO_MIPS32_r(addu, 65, 0x80000001, 0x80000001, 0x00000002);
+ DO_MIPS32_r(addu, 66, 0x00000000, 0x55555555, 0x55555555);
+ DO_MIPS32_r(addu, 67, 0x15555555, 0x55555555, 0x6AAAAAAA);
+ DO_MIPS32_r(addu, 68, 0xAAAAAAAA, 0x55555555, 0xFFFFFFFF);
+ DO_MIPS32_r(addu, 69, 0xFFFFFFFF, 0x55555555, 0x55555554);
+ DO_MIPS32_r(addu, 70, 0xAAAAAAAA, 0x00000000, 0xAAAAAAAA);
+ DO_MIPS32_r(addu, 71, 0xAAAAAAAA, 0x55555555, 0xFFFFFFFF);
+ DO_MIPS32_r(addu, 72, 0xAAAAAAAA, 0x2AAAAAAA, 0xD5555554);
+ DO_MIPS32_r(addu, 73, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAA9);
+ DO_MIPS32_r(addu, 74, 0x7FFFFFFF, 0x00000001, 0x80000000);
+ DO_MIPS32_r(addu, 75, 0x7FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFE);
+ DO_MIPS32_r(addu, 76, 0x80000000, 0xFFFFFFFF, 0x7FFFFFFF);
+ DO_MIPS32_r(addu, 77, 0x80000000, 0x80000000, 0x00000000);
+ DO_MIPS32_r(addu, 78, 0x7FFFFFFF, 0x00000001, 0x80000000);
+ DO_MIPS32_r(addu, 79, 0x7FFFFFFF, 0x00007FFF, 0x80007FFE);
+ DO_MIPS32_r(addu, 80, 0x80000000, 0x0000FFFF, 0x8000FFFF);
+ DO_MIPS32_r(addu, 81, 0x80000000, 0x00008000, 0x80008000);
+ DO_MIPS32_r(addu, 82, 0x7FFFAAAA, 0x0000555F, 0x80000009);
+ DO_MIPS32_r(addu, 83, 0x7FFF5555, 0x0000AAAA, 0x7FFFFFFF);
+ DO_MIPS32_r(addu, 84, 0x7FFFFFFF, 0x00000002, 0x80000001);
+ DO_MIPS32_r(addu, 85, 0x7FFFFFFF, 0x00000004, 0x80000003);
+ DO_MIPS32_r(addu, 86, 0x7FFFFFFF, 0x00000008, 0x80000007);
+ DO_MIPS32_r(addu, 87, 0x7FFFFFFF, 0x00000010, 0x8000000F);
+ DO_MIPS32_r(addu, 88, 0x7FFFFFFF, 0x00000020, 0x8000001F);
+ DO_MIPS32_r(addu, 89, 0x7FFFFFFF, 0x00000040, 0x8000003F);
+ DO_MIPS32_r(addu, 90, 0x7FFFFFFF, 0x00000080, 0x8000007F);
+ DO_MIPS32_r(addu, 91, 0x7FFFFFFF, 0x00000100, 0x800000FF);
+ DO_MIPS32_r(addu, 92, 0x7FFFFFFF, 0x00000200, 0x800001FF);
+ DO_MIPS32_r(addu, 93, 0x7FFFFFFF, 0x00000400, 0x800003FF);
+ DO_MIPS32_r(addu, 94, 0x7FFFFFFF, 0x00000800, 0x800007FF);
+ DO_MIPS32_r(addu, 95, 0x7FFFFFFF, 0x00001000, 0x80000FFF);
+ DO_MIPS32_r(addu, 96, 0x7FFFFFFF, 0x00002000, 0x80001FFF);
+ DO_MIPS32_r(addu, 97, 0x7FFFFFFF, 0x00004000, 0x80003FFF);
+ DO_MIPS32_r(addu, 98, 0x7FFFFFFF, 0x00001000, 0x80003FFF);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/div.c b/tests/tcg/mips/user/isa/mips32/arithmatic/div.c
new file mode 100644
index 0000000000..5eafca326e
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/div.c
@@ -0,0 +1,81 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_r2_s(div, 0, 0, 0, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(div, 1, 0, 0, 0x80000001, 0x00000001, 0x00000000, 0x80000001);
+ DO_MIPS32_r2_s(div, 2, 0, 0, 0x40000002, 0x00000003, 0x00000000, 0x15555556);
+ DO_MIPS32_r2_s(div, 3, 0, 0, 0x20000004, 0x00000007, 0x00000001, 0x04924925);
+ DO_MIPS32_r2_s(div, 4, 0, 0, 0x10000008, 0x0000000F, 0x00000009, 0x01111111);
+ DO_MIPS32_r2_s(div, 5, 0, 0, 0x88000010, 0x0000001F, 0xFFFFFFF3, 0xFC210843);
+ DO_MIPS32_r2_s(div, 6, 0, 0, 0x44000020, 0x0000003F, 0x00000025, 0x01145145);
+ DO_MIPS32_r2_s(div, 7, 0, 0, 0x22000040, 0x0000007F, 0x00000052, 0x00448912);
+ DO_MIPS32_r2_s(div, 8, 0, 0, 0x11000080, 0x000000FF, 0x00000091, 0x00111111);
+ DO_MIPS32_r2_s(div, 9, 0, 0, 0x80800100, 0x000001FF, 0xFFFFFF11, 0xFFC02011);
+ DO_MIPS32_r2_s(div, 10, 0, 0, 0x40400200, 0x000003FF, 0x00000205, 0x00101405);
+ DO_MIPS32_r2_s(div, 11, 0, 0, 0x20200400, 0x000007FF, 0x00000081, 0x00040481);
+ DO_MIPS32_r2_s(div, 12, 0, 0, 0x10100800, 0x00000FFF, 0x00000910, 0x00010110);
+ DO_MIPS32_r2_s(div, 13, 0, 0, 0x80081000, 0x00001FFF, 0xFFFFF021, 0xFFFC0021);
+ DO_MIPS32_r2_s(div, 14, 0, 0, 0x40042000, 0x00003FFF, 0x00002014, 0x00010014);
+ DO_MIPS32_r2_s(div, 15, 0, 0, 0x20024000, 0x00007FFF, 0x00000005, 0x00004005);
+ DO_MIPS32_r2_s(div, 16, 0, 0, 0x10018000, 0x0000FFFF, 0x00009001, 0x00001001);
+ DO_MIPS32_r2_s(div, 17, 0, 0, 0x80018000, 0x0001FFFF, 0xFFFF4001, 0xFFFFC001);
+ DO_MIPS32_r2_s(div, 18, 0, 0, 0x40024000, 0x0003FFFF, 0x00025000, 0x00001000);
+ DO_MIPS32_r2_s(div, 19, 0, 0, 0x20042000, 0x0007FFFF, 0x00042400, 0x00000400);
+ DO_MIPS32_r2_s(div, 20, 0, 0, 0x10081000, 0x000FFFFF, 0x00081100, 0x00000100);
+ DO_MIPS32_r2_s(div, 21, 0, 0, 0x80100800, 0x001FFFFF, 0xFFF00401, 0xFFFFFC01);
+ DO_MIPS32_r2_s(div, 22, 0, 0, 0x40200400, 0x003FFFFF, 0x00200500, 0x00000100);
+ DO_MIPS32_r2_s(div, 23, 0, 0, 0x20400200, 0x007FFFFF, 0x00400240, 0x00000040);
+ DO_MIPS32_r2_s(div, 24, 0, 0, 0x10800100, 0x00FFFFFF, 0x00800110, 0x00000010);
+ DO_MIPS32_r2_s(div, 25, 0, 0, 0x81000080, 0x01FFFFFF, 0xFF000041, 0xFFFFFFC1);
+ DO_MIPS32_r2_s(div, 26, 0, 0, 0x42000040, 0x03FFFFFF, 0x02000050, 0x00000010);
+ DO_MIPS32_r2_s(div, 27, 0, 0, 0x24000020, 0x07FFFFFF, 0x04000024, 0x00000004);
+ DO_MIPS32_r2_s(div, 28, 0, 0, 0x18000010, 0x0FFFFFFF, 0x08000011, 0x00000001);
+ DO_MIPS32_r2_s(div, 29, 0, 0, 0x90000008, 0x1FFFFFFF, 0xF0000005, 0xFFFFFFFD);
+ DO_MIPS32_r2_s(div, 30, 0, 0, 0x60000004, 0x3FFFFFFF, 0x20000005, 0x00000001);
+ DO_MIPS32_r2_s(div, 31, 0, 0, 0x60000002, 0x7FFFFFFF, 0x60000002, 0x00000000);
+ DO_MIPS32_r2_s(div, 32, 0, 0, 0x90000001, 0xFFFFFFFF, 0x00000000, 0x6FFFFFFF);
+ DO_MIPS32_r2_s(div, 33, 0, 0, 0x00000000, 0x55555555, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(div, 34, 0, 0, 0x55555555, 0x55555555, 0x00000000, 0x00000001);
+ DO_MIPS32_r2_s(div, 35, 0, 0, 0xAAAAAAAA, 0x55555555, 0xFFFFFFFF, 0xFFFFFFFF);
+ DO_MIPS32_r2_s(div, 36, 0, 0, 0xFFFFFFFF, 0x55555555, 0xFFFFFFFF, 0x00000000);
+ DO_MIPS32_r2_s(div, 37, 0, 0, 0xAAAAAAAA, 0x00000001, 0x00000000, 0xAAAAAAAA);
+ DO_MIPS32_r2_s(div, 38, 0, 0, 0xAAAAAAAA, 0x55555555, 0xFFFFFFFF, 0xFFFFFFFF);
+ DO_MIPS32_r2_s(div, 39, 0, 0, 0xAAAAAAAA, 0xAAAAAAAA, 0x00000000, 0x00000001);
+ DO_MIPS32_r2_s(div, 40, 0, 0, 0xAAAAAAAA, 0xFFFFFFFF, 0x00000000, 0x55555556);
+ DO_MIPS32_r2_s(div, 41, 0, 0, 0x7FFFFFFF, 0x7FFFFFFF, 0x00000000, 0x00000001);
+ DO_MIPS32_r2_s(div, 42, 0, 0, 0x7FFFFFFF, 0x80000000, 0x7FFFFFFF, 0x00000000);
+ DO_MIPS32_r2_s(div, 43, 0, 0, 0x7FFFFFFF, 0xFFFFFFFF, 0x00000000, 0x80000001);
+ DO_MIPS32_r2_s(div, 44, 0, 0, 0x80000000, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
+ DO_MIPS32_r2_s(div, 45, 0, 0, 0x80000000, 0x80000000, 0x00000000, 0x00000001);
+#if 0
+ /* Disabled until we find a way to disable assembler trap */
+ DO_MIPS32_r2_s(div, 46, 0, 0, 0x80000000, 0xFFFFFFFF, 0x00000000, 0x80000000);
+#endif
+ DO_MIPS32_r2_s(div, 47, 0, 0, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, 0x00000000);
+ DO_MIPS32_r2_s(div, 48, 0, 0, 0xFFFFFFFF, 0x80000000, 0xFFFFFFFF, 0x00000000);
+ DO_MIPS32_r2_s(div, 49, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000001);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/divu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/divu.c
new file mode 100644
index 0000000000..172e8af693
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/divu.c
@@ -0,0 +1,78 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_r2_s(divu, 0, 0, 0, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(divu, 1, 0, 0, 0x80000001, 0x00000001, 0x00000000, 0x80000001);
+ DO_MIPS32_r2_s(divu, 2, 0, 0, 0x40000002, 0x00000003, 0x00000000, 0x15555556);
+ DO_MIPS32_r2_s(divu, 3, 0, 0, 0x20000004, 0x00000007, 0x00000001, 0x04924925);
+ DO_MIPS32_r2_s(divu, 4, 0, 0, 0x10000008, 0x0000000F, 0x00000009, 0x01111111);
+ DO_MIPS32_r2_s(divu, 5, 0, 0, 0x88000010, 0x0000001F, 0x00000016, 0x046318C6);
+ DO_MIPS32_r2_s(divu, 6, 0, 0, 0x44000020, 0x0000003F, 0x00000025, 0x01145145);
+ DO_MIPS32_r2_s(divu, 7, 0, 0, 0x22000040, 0x0000007F, 0x00000052, 0x00448912);
+ DO_MIPS32_r2_s(divu, 8, 0, 0, 0x11000080, 0x000000FF, 0x00000091, 0x00111111);
+ DO_MIPS32_r2_s(divu, 9, 0, 0, 0x80800100, 0x000001FF, 0x00000130, 0x00406030);
+ DO_MIPS32_r2_s(divu, 10, 0, 0, 0x40400200, 0x000003FF, 0x00000205, 0x00101405);
+ DO_MIPS32_r2_s(divu, 11, 0, 0, 0x20200400, 0x000007FF, 0x00000081, 0x00040481);
+ DO_MIPS32_r2_s(divu, 12, 0, 0, 0x10100800, 0x00000FFF, 0x00000910, 0x00010110);
+ DO_MIPS32_r2_s(divu, 13, 0, 0, 0x80081000, 0x00001FFF, 0x00001060, 0x00040060);
+ DO_MIPS32_r2_s(divu, 14, 0, 0, 0x40042000, 0x00003FFF, 0x00002014, 0x00010014);
+ DO_MIPS32_r2_s(divu, 15, 0, 0, 0x20024000, 0x00007FFF, 0x00000005, 0x00004005);
+ DO_MIPS32_r2_s(divu, 16, 0, 0, 0x10018000, 0x0000FFFF, 0x00009001, 0x00001001);
+ DO_MIPS32_r2_s(divu, 17, 0, 0, 0x80018000, 0x0001FFFF, 0x0001C000, 0x00004000);
+ DO_MIPS32_r2_s(divu, 18, 0, 0, 0x40024000, 0x0003FFFF, 0x00025000, 0x00001000);
+ DO_MIPS32_r2_s(divu, 19, 0, 0, 0x20042000, 0x0007FFFF, 0x00042400, 0x00000400);
+ DO_MIPS32_r2_s(divu, 20, 0, 0, 0x10081000, 0x000FFFFF, 0x00081100, 0x00000100);
+ DO_MIPS32_r2_s(divu, 21, 0, 0, 0x80100800, 0x001FFFFF, 0x00100C00, 0x00000400);
+ DO_MIPS32_r2_s(divu, 22, 0, 0, 0x40200400, 0x003FFFFF, 0x00200500, 0x00000100);
+ DO_MIPS32_r2_s(divu, 23, 0, 0, 0x20400200, 0x007FFFFF, 0x00400240, 0x00000040);
+ DO_MIPS32_r2_s(divu, 24, 0, 0, 0x10800100, 0x00FFFFFF, 0x00800110, 0x00000010);
+ DO_MIPS32_r2_s(divu, 25, 0, 0, 0x81000080, 0x01FFFFFF, 0x010000C0, 0x00000040);
+ DO_MIPS32_r2_s(divu, 26, 0, 0, 0x42000040, 0x03FFFFFF, 0x02000050, 0x00000010);
+ DO_MIPS32_r2_s(divu, 27, 0, 0, 0x24000020, 0x07FFFFFF, 0x04000024, 0x00000004);
+ DO_MIPS32_r2_s(divu, 28, 0, 0, 0x18000010, 0x0FFFFFFF, 0x08000011, 0x00000001);
+ DO_MIPS32_r2_s(divu, 29, 0, 0, 0x90000008, 0x1FFFFFFF, 0x1000000C, 0x00000004);
+ DO_MIPS32_r2_s(divu, 30, 0, 0, 0x60000004, 0x3FFFFFFF, 0x20000005, 0x00000001);
+ DO_MIPS32_r2_s(divu, 31, 0, 0, 0x60000002, 0x7FFFFFFF, 0x60000002, 0x00000000);
+ DO_MIPS32_r2_s(divu, 32, 0, 0, 0x90000001, 0xFFFFFFFF, 0x90000001, 0x00000000);
+ DO_MIPS32_r2_s(divu, 33, 0, 0, 0x00000000, 0x55555555, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(divu, 34, 0, 0, 0x55555555, 0x55555555, 0x00000000, 0x00000001);
+ DO_MIPS32_r2_s(divu, 35, 0, 0, 0xAAAAAAAA, 0x55555555, 0x00000000, 0x00000002);
+ DO_MIPS32_r2_s(divu, 36, 0, 0, 0xFFFFFFFF, 0x55555555, 0x00000000, 0x00000003);
+ DO_MIPS32_r2_s(divu, 37, 0, 0, 0xAAAAAAAA, 0x00000001, 0x00000000, 0xAAAAAAAA);
+ DO_MIPS32_r2_s(divu, 38, 0, 0, 0xAAAAAAAA, 0x55555555, 0x00000000, 0x00000002);
+ DO_MIPS32_r2_s(divu, 39, 0, 0, 0xAAAAAAAA, 0xAAAAAAAA, 0x00000000, 0x00000001);
+ DO_MIPS32_r2_s(divu, 40, 0, 0, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAA, 0x00000000);
+ DO_MIPS32_r2_s(divu, 41, 0, 0, 0x7FFFFFFF, 0x7FFFFFFF, 0x00000000, 0x00000001);
+ DO_MIPS32_r2_s(divu, 42, 0, 0, 0x7FFFFFFF, 0x80000000, 0x7FFFFFFF, 0x00000000);
+ DO_MIPS32_r2_s(divu, 43, 0, 0, 0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0x00000000);
+ DO_MIPS32_r2_s(divu, 44, 0, 0, 0x80000000, 0x7FFFFFFF, 0x00000001, 0x00000001);
+ DO_MIPS32_r2_s(divu, 45, 0, 0, 0x80000000, 0x80000000, 0x00000000, 0x00000001);
+ DO_MIPS32_r2_s(divu, 46, 0, 0, 0x80000000, 0xFFFFFFFF, 0x80000000, 0x00000000);
+ DO_MIPS32_r2_s(divu, 47, 0, 0, 0xFFFFFFFF, 0x7FFFFFFF, 0x00000001, 0x00000002);
+ DO_MIPS32_r2_s(divu, 48, 0, 0, 0xFFFFFFFF, 0x80000000, 0x7FFFFFFF, 0x00000001);
+ DO_MIPS32_r2_s(divu, 49, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000001);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/madd.c b/tests/tcg/mips/user/isa/mips32/arithmatic/madd.c
new file mode 100644
index 0000000000..7f047f76d9
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/madd.c
@@ -0,0 +1,79 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_r2_s(divu, 0, 0, 0, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(madd, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(madd, 1, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000001);
+ DO_MIPS32_r2_s(madd, 2, 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000000, 0x00000007);
+ DO_MIPS32_r2_s(madd, 3, 0x00000000, 0x00000007, 0x00000004, 0x00000007, 0x00000000, 0x00000023);
+ DO_MIPS32_r2_s(madd, 4, 0x00000000, 0x00000023, 0x00000008, 0x0000000F, 0x00000000, 0x0000009b);
+ DO_MIPS32_r2_s(madd, 5, 0x00000000, 0x0000009b, 0x00000010, 0x0000001F, 0x00000000, 0x0000028b);
+ DO_MIPS32_r2_s(madd, 6, 0x00000000, 0x0000028b, 0x00000020, 0x0000003F, 0x00000000, 0x00000a6b);
+ DO_MIPS32_r2_s(madd, 7, 0x00000000, 0x00000a6b, 0x00000040, 0x0000007F, 0x00000000, 0x00002a2b);
+ DO_MIPS32_r2_s(madd, 8, 0x00000000, 0x00002a2b, 0x00000080, 0x000000FF, 0x00000000, 0x0000a9ab);
+ DO_MIPS32_r2_s(madd, 9, 0x00000000, 0x0000a9ab, 0x00000100, 0x000001FF, 0x00000000, 0x0002a8ab);
+ DO_MIPS32_r2_s(madd, 10, 0x00000000, 0x0002a8ab, 0x00000200, 0x000003FF, 0x00000000, 0x000aa6ab);
+ DO_MIPS32_r2_s(madd, 11, 0x00000000, 0x000aa6ab, 0x00000400, 0x000007FF, 0x00000000, 0x002aa2ab);
+ DO_MIPS32_r2_s(madd, 12, 0x00000000, 0x002aa2ab, 0x00000800, 0x00000FFF, 0x00000000, 0x00aa9aab);
+ DO_MIPS32_r2_s(madd, 13, 0x00000000, 0x00aa9aab, 0x00001000, 0x00001FFF, 0x00000000, 0x02aa8aab);
+ DO_MIPS32_r2_s(madd, 14, 0x00000000, 0x02aa8aab, 0x00002000, 0x00003FFF, 0x00000000, 0x0aaa6aab);
+ DO_MIPS32_r2_s(madd, 15, 0x00000000, 0x0aaa6aab, 0x00004000, 0x00007FFF, 0x00000000, 0x2aaa2aab);
+ DO_MIPS32_r2_s(madd, 16, 0x00000000, 0x2aaa2aab, 0x00008000, 0x0000FFFF, 0x00000000, 0xaaa9aaab);
+ DO_MIPS32_r2_s(madd, 17, 0x00000000, 0xaaa9aaab, 0x00010000, 0x0001FFFF, 0x00000002, 0xaaa8aaab);
+ DO_MIPS32_r2_s(madd, 18, 0x00000002, 0xaaa8aaab, 0x00020000, 0x0003FFFF, 0x0000000a, 0xAAA6AAAB);
+ DO_MIPS32_r2_s(madd, 19, 0x0000000a, 0xAAA6AAAB, 0x00040000, 0x0007FFFF, 0x0000002A, 0xAAA2AAAB);
+ DO_MIPS32_r2_s(madd, 20, 0x0000002A, 0xAAA2AAAB, 0x00080000, 0x000FFFFF, 0x000000AA, 0xAA9AAAAB);
+ DO_MIPS32_r2_s(madd, 21, 0x000000AA, 0xAA9AAAAB, 0x00100000, 0x001FFFFF, 0x000002AA, 0xAA8AAAAB);
+ DO_MIPS32_r2_s(madd, 22, 0x000002AA, 0xAA8AAAAB, 0x00200000, 0x003FFFFF, 0x00000AAA, 0xAA6AAAAB);
+ DO_MIPS32_r2_s(madd, 23, 0x00000AAA, 0xAA6AAAAB, 0x00400000, 0x007FFFFF, 0x00002AAA, 0xAA2AAAAB);
+ DO_MIPS32_r2_s(madd, 24, 0x00002AAA, 0xAA2AAAAB, 0x00800000, 0x00FFFFFF, 0x0000AAAA, 0xA9AAAAAB);
+ DO_MIPS32_r2_s(madd, 25, 0x0000AAAA, 0xA9AAAAAB, 0x01000000, 0x01FFFFFF, 0x0002AAAA, 0xA8AAAAAB);
+ DO_MIPS32_r2_s(madd, 26, 0x0002AAAA, 0xA8AAAAAB, 0x02000000, 0x03FFFFFF, 0x000AAAAA, 0xA6AAAAAB);
+ DO_MIPS32_r2_s(madd, 27, 0x000AAAAA, 0xA6AAAAAB, 0x04000000, 0x07FFFFFF, 0x002AAAAA, 0xA2AAAAAB);
+ DO_MIPS32_r2_s(madd, 28, 0x002AAAAA, 0xA2AAAAAB, 0x08000000, 0x0FFFFFFF, 0x00AAAAAA, 0x9AAAAAAB);
+ DO_MIPS32_r2_s(madd, 29, 0x00AAAAAA, 0x9AAAAAAB, 0x10000000, 0x1FFFFFFF, 0x02AAAAAA, 0x8AAAAAAB);
+ DO_MIPS32_r2_s(madd, 30, 0x02AAAAAA, 0x8AAAAAAB, 0x20000000, 0x3FFFFFFF, 0x0AAAAAAA, 0x6AAAAAAB);
+ DO_MIPS32_r2_s(madd, 31, 0x0AAAAAAA, 0x6AAAAAAB, 0x40000000, 0x7FFFFFFF, 0x2AAAAAAA, 0x2AAAAAAB);
+ DO_MIPS32_r2_s(madd, 32, 0x2AAAAAAA, 0x2AAAAAAB, 0x80000000, 0xFFFFFFFF, 0x2AAAAAAA, 0xAAAAAAAB);
+ DO_MIPS32_r2_s(madd, 33, 0x00000000, 0x00000000, 0x00000000, 0x55555555, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(madd, 34, 0x00000000, 0x00000000, 0x55555555, 0x55555555, 0x1C71C71C, 0x38E38E39);
+ DO_MIPS32_r2_s(madd, 35, 0x1C71C71C, 0x38E38E39, 0xAAAAAAAA, 0x55555555, 0xFFFFFFFF, 0xAAAAAAAB);
+ DO_MIPS32_r2_s(madd, 36, 0xFFFFFFFF, 0xAAAAAAAB, 0xFFFFFFFF, 0x55555555, 0xFFFFFFFF, 0x55555556);
+ DO_MIPS32_r2_s(madd, 37, 0xFFFFFFFF, 0x55555556, 0xAAAAAAAA, 0x00000000, 0xFFFFFFFF, 0x55555556);
+ DO_MIPS32_r2_s(madd, 38, 0xFFFFFFFF, 0x55555556, 0xAAAAAAAA, 0x55555555, 0xe38e38e2, 0xc71c71c8);
+ DO_MIPS32_r2_s(madd, 39, 0xe38e38e2, 0xc71c71c8, 0xAAAAAAAA, 0xAAAAAAAA, 0xffffffff, 0xaaaaaaac);
+ DO_MIPS32_r2_s(madd, 40, 0xffffffff, 0xaaaaaaac, 0xAAAAAAAA, 0xFFFFFFFF, 0x00000000, 0x00000002);
+ DO_MIPS32_r2_s(madd, 41, 0x00000000, 0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0x3FFFFFFF, 0x00000001);
+ DO_MIPS32_r2_s(madd, 42, 0x3FFFFFFF, 0x00000001, 0x7FFFFFFF, 0x80000000, 0xffffffff, 0x80000001);
+ DO_MIPS32_r2_s(madd, 43, 0xffffffff, 0x80000001, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000002);
+ DO_MIPS32_r2_s(madd, 44, 0xFFFFFFFF, 0x00000002, 0x80000000, 0x7FFFFFFF, 0xbfffffff, 0x80000002);
+ DO_MIPS32_r2_s(madd, 45, 0xbfffffff, 0x80000002, 0x80000000, 0x80000000, 0xffffffff, 0x80000002);
+ DO_MIPS32_r2_s(madd, 46, 0xffffffff, 0x80000002, 0x80000000, 0xFFFFFFFF, 0x00000000, 0x00000002);
+ DO_MIPS32_r2_s(madd, 47, 0x00000000, 0x00000002, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, 0x80000003);
+ DO_MIPS32_r2_s(madd, 48, 0xFFFFFFFF, 0x80000003, 0xFFFFFFFF, 0x80000000, 0x00000000, 0x00000003);
+ DO_MIPS32_r2_s(madd, 49, 0x00000000, 0x00000003, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000004);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/maddu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/maddu.c
new file mode 100644
index 0000000000..8073841b33
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/maddu.c
@@ -0,0 +1,78 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_r2_s(maddu, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(maddu, 1, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000001);
+ DO_MIPS32_r2_s(maddu, 2, 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000000, 0x00000007);
+ DO_MIPS32_r2_s(maddu, 3, 0x00000000, 0x00000007, 0x00000004, 0x00000007, 0x00000000, 0x00000023);
+ DO_MIPS32_r2_s(maddu, 4, 0x00000000, 0x00000023, 0x00000008, 0x0000000F, 0x00000000, 0x0000009b);
+ DO_MIPS32_r2_s(maddu, 5, 0x00000000, 0x0000009b, 0x00000010, 0x0000001F, 0x00000000, 0x0000028b);
+ DO_MIPS32_r2_s(maddu, 6, 0x00000000, 0x0000028b, 0x00000020, 0x0000003F, 0x00000000, 0x00000a6b);
+ DO_MIPS32_r2_s(maddu, 7, 0x00000000, 0x00000a6b, 0x00000040, 0x0000007F, 0x00000000, 0x00002a2b);
+ DO_MIPS32_r2_s(maddu, 8, 0x00000000, 0x00002a2b, 0x00000080, 0x000000FF, 0x00000000, 0x0000a9ab);
+ DO_MIPS32_r2_s(maddu, 9, 0x00000000, 0x0000a9ab, 0x00000100, 0x000001FF, 0x00000000, 0x0002a8ab);
+ DO_MIPS32_r2_s(maddu, 10, 0x00000000, 0x0002a8ab, 0x00000200, 0x000003FF, 0x00000000, 0x000aa6ab);
+ DO_MIPS32_r2_s(maddu, 11, 0x00000000, 0x000aa6ab, 0x00000400, 0x000007FF, 0x00000000, 0x002aa2ab);
+ DO_MIPS32_r2_s(maddu, 12, 0x00000000, 0x002aa2ab, 0x00000800, 0x00000FFF, 0x00000000, 0x00aa9aab);
+ DO_MIPS32_r2_s(maddu, 13, 0x00000000, 0x00aa9aab, 0x00001000, 0x00001FFF, 0x00000000, 0x02aa8aab);
+ DO_MIPS32_r2_s(maddu, 14, 0x00000000, 0x02aa8aab, 0x00002000, 0x00003FFF, 0x00000000, 0x0aaa6aab);
+ DO_MIPS32_r2_s(maddu, 15, 0x00000000, 0x0aaa6aab, 0x00004000, 0x00007FFF, 0x00000000, 0x2aaa2aab);
+ DO_MIPS32_r2_s(maddu, 16, 0x00000000, 0x2aaa2aab, 0x00008000, 0x0000FFFF, 0x00000000, 0xaaa9aaab);
+ DO_MIPS32_r2_s(maddu, 17, 0x00000000, 0xaaa9aaab, 0x00010000, 0x0001FFFF, 0x00000002, 0xaaa8aaab);
+ DO_MIPS32_r2_s(maddu, 18, 0x00000002, 0xaaa8aaab, 0x00020000, 0x0003FFFF, 0x0000000a, 0xAAA6AAAB);
+ DO_MIPS32_r2_s(maddu, 19, 0x0000000a, 0xAAA6AAAB, 0x00040000, 0x0007FFFF, 0x0000002A, 0xAAA2AAAB);
+ DO_MIPS32_r2_s(maddu, 20, 0x0000002A, 0xAAA2AAAB, 0x00080000, 0x000FFFFF, 0x000000AA, 0xAA9AAAAB);
+ DO_MIPS32_r2_s(maddu, 21, 0x000000AA, 0xAA9AAAAB, 0x00100000, 0x001FFFFF, 0x000002AA, 0xAA8AAAAB);
+ DO_MIPS32_r2_s(maddu, 22, 0x000002AA, 0xAA8AAAAB, 0x00200000, 0x003FFFFF, 0x00000AAA, 0xAA6AAAAB);
+ DO_MIPS32_r2_s(maddu, 23, 0x00000AAA, 0xAA6AAAAB, 0x00400000, 0x007FFFFF, 0x00002AAA, 0xAA2AAAAB);
+ DO_MIPS32_r2_s(maddu, 24, 0x00002AAA, 0xAA2AAAAB, 0x00800000, 0x00FFFFFF, 0x0000AAAA, 0xA9AAAAAB);
+ DO_MIPS32_r2_s(maddu, 25, 0x0000AAAA, 0xA9AAAAAB, 0x01000000, 0x01FFFFFF, 0x0002AAAA, 0xA8AAAAAB);
+ DO_MIPS32_r2_s(maddu, 26, 0x0002AAAA, 0xA8AAAAAB, 0x02000000, 0x03FFFFFF, 0x000AAAAA, 0xA6AAAAAB);
+ DO_MIPS32_r2_s(maddu, 27, 0x000AAAAA, 0xA6AAAAAB, 0x04000000, 0x07FFFFFF, 0x002AAAAA, 0xA2AAAAAB);
+ DO_MIPS32_r2_s(maddu, 28, 0x002AAAAA, 0xA2AAAAAB, 0x08000000, 0x0FFFFFFF, 0x00AAAAAA, 0x9AAAAAAB);
+ DO_MIPS32_r2_s(maddu, 29, 0x00AAAAAA, 0x9AAAAAAB, 0x10000000, 0x1FFFFFFF, 0x02AAAAAA, 0x8AAAAAAB);
+ DO_MIPS32_r2_s(maddu, 30, 0x02AAAAAA, 0x8AAAAAAB, 0x20000000, 0x3FFFFFFF, 0x0AAAAAAA, 0x6AAAAAAB);
+ DO_MIPS32_r2_s(maddu, 31, 0x0AAAAAAA, 0x6AAAAAAB, 0x40000000, 0x7FFFFFFF, 0x2AAAAAAA, 0x2AAAAAAB);
+ DO_MIPS32_r2_s(maddu, 32, 0x2AAAAAAA, 0x2AAAAAAB, 0x80000000, 0xFFFFFFFF, 0xAAAAAAA9, 0xAAAAAAAB);
+ DO_MIPS32_r2_s(maddu, 33, 0x00000000, 0x00000000, 0x00000000, 0x55555555, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(maddu, 34, 0x00000000, 0x00000000, 0x55555555, 0x55555555, 0x1C71C71C, 0x38E38E39);
+ DO_MIPS32_r2_s(maddu, 35, 0x1C71C71C, 0x38E38E39, 0xAAAAAAAA, 0x55555555, 0x55555554, 0xaaaaaaab);
+ DO_MIPS32_r2_s(maddu, 36, 0x55555554, 0xaaaaaaab, 0xFFFFFFFF, 0x55555555, 0xaaaaaaa9, 0x55555556);
+ DO_MIPS32_r2_s(maddu, 37, 0xaaaaaaa9, 0x55555556, 0xAAAAAAAA, 0x00000000, 0xaaaaaaa9, 0x55555556);
+ DO_MIPS32_r2_s(maddu, 38, 0xaaaaaaa9, 0x55555556, 0xAAAAAAAA, 0x55555555, 0xe38e38e1, 0xc71c71c8);
+ DO_MIPS32_r2_s(maddu, 39, 0xe38e38e1, 0xc71c71c8, 0xAAAAAAAA, 0xAAAAAAAA, 0x55555552, 0xaaaaaaac);
+ DO_MIPS32_r2_s(maddu, 40, 0x55555552, 0xaaaaaaac, 0xAAAAAAAA, 0xFFFFFFFF, 0xfffffffc, 0x00000002);
+ DO_MIPS32_r2_s(maddu, 41, 0x00000000, 0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0x3fffffff, 0x00000001);
+ DO_MIPS32_r2_s(maddu, 42, 0x3fffffff, 0x00000001, 0x7FFFFFFF, 0x80000000, 0x7ffffffe, 0x80000001);
+ DO_MIPS32_r2_s(maddu, 43, 0x7ffffffe, 0x80000001, 0x7FFFFFFF, 0xFFFFFFFF, 0xfffffffd, 0x00000002);
+ DO_MIPS32_r2_s(maddu, 44, 0xfffffffd, 0x00000002, 0x80000000, 0x7FFFFFFF, 0x3ffffffc, 0x80000002);
+ DO_MIPS32_r2_s(maddu, 45, 0x3ffffffc, 0x80000002, 0x80000000, 0x80000000, 0x7ffffffc, 0x80000002);
+ DO_MIPS32_r2_s(maddu, 46, 0x7ffffffc, 0x80000002, 0x80000000, 0xFFFFFFFF, 0xfffffffc, 0x00000002);
+ DO_MIPS32_r2_s(maddu, 47, 0xfffffffc, 0x00000002, 0xFFFFFFFF, 0x7FFFFFFF, 0x7ffffffa, 0x80000003);
+ DO_MIPS32_r2_s(maddu, 48, 0x7ffffffa, 0x80000003, 0xFFFFFFFF, 0x80000000, 0xfffffffa, 0x00000003);
+ DO_MIPS32_r2_s(maddu, 49, 0xfffffffa, 0x00000003, 0xFFFFFFFF, 0xFFFFFFFF, 0xfffffff8, 0x00000004);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/msub.c b/tests/tcg/mips/user/isa/mips32/arithmatic/msub.c
new file mode 100644
index 0000000000..36387cbdf8
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/msub.c
@@ -0,0 +1,78 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_r2_s(msub, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(msub, 1, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0xffffffff, 0xffffffff);
+ DO_MIPS32_r2_s(msub, 2, 0xffffffff, 0xffffffff, 0x00000002, 0x00000003, 0xffffffff, 0xfffffff9);
+ DO_MIPS32_r2_s(msub, 3, 0xffffffff, 0xfffffff9, 0x00000004, 0x00000007, 0xffffffff, 0xffffffdd);
+ DO_MIPS32_r2_s(msub, 4, 0xffffffff, 0xffffffdd, 0x00000008, 0x0000000F, 0xffffffff, 0xffffff65);
+ DO_MIPS32_r2_s(msub, 5, 0xffffffff, 0xffffff65, 0x00000010, 0x0000001F, 0xffffffff, 0xfffffd75);
+ DO_MIPS32_r2_s(msub, 6, 0xffffffff, 0xfffffd75, 0x00000020, 0x0000003F, 0xffffffff, 0xfffff595);
+ DO_MIPS32_r2_s(msub, 7, 0xffffffff, 0xfffff595, 0x00000040, 0x0000007F, 0xffffffff, 0xffffd5d5);
+ DO_MIPS32_r2_s(msub, 8, 0xffffffff, 0xffffd5d5, 0x00000080, 0x000000FF, 0xffffffff, 0xffff5655);
+ DO_MIPS32_r2_s(msub, 9, 0xffffffff, 0xffff5655, 0x00000100, 0x000001FF, 0xffffffff, 0xfffd5755);
+ DO_MIPS32_r2_s(msub, 10, 0xffffffff, 0xfffd5755, 0x00000200, 0x000003FF, 0xffffffff, 0xfff55955);
+ DO_MIPS32_r2_s(msub, 11, 0xffffffff, 0xfff55955, 0x00000400, 0x000007FF, 0xffffffff, 0xffd55d55);
+ DO_MIPS32_r2_s(msub, 12, 0xffffffff, 0xffd55d55, 0x00000800, 0x00000FFF, 0xffffffff, 0xff556555);
+ DO_MIPS32_r2_s(msub, 13, 0xffffffff, 0xff556555, 0x00001000, 0x00001FFF, 0xffffffff, 0xfd557555);
+ DO_MIPS32_r2_s(msub, 14, 0xffffffff, 0xfd557555, 0x00002000, 0x00003FFF, 0xffffffff, 0xf5559555);
+ DO_MIPS32_r2_s(msub, 15, 0xffffffff, 0xf5559555, 0x00004000, 0x00007FFF, 0xffffffff, 0xd555d555);
+ DO_MIPS32_r2_s(msub, 16, 0xffffffff, 0xd555d555, 0x00008000, 0x0000FFFF, 0xffffffff, 0x55565555);
+ DO_MIPS32_r2_s(msub, 17, 0xffffffff, 0x55565555, 0x00010000, 0x0001FFFF, 0xfffffffd, 0x55575555);
+ DO_MIPS32_r2_s(msub, 18, 0xfffffffd, 0x55575555, 0x00020000, 0x0003FFFF, 0xfffffff5, 0x55595555);
+ DO_MIPS32_r2_s(msub, 19, 0xfffffff5, 0x55595555, 0x00040000, 0x0007FFFF, 0xffffffd5, 0x555d5555);
+ DO_MIPS32_r2_s(msub, 20, 0xffffffd5, 0x555d5555, 0x00080000, 0x000FFFFF, 0xffffff55, 0x55655555);
+ DO_MIPS32_r2_s(msub, 21, 0xffffff55, 0x55655555, 0x00100000, 0x001FFFFF, 0xfffffd55, 0x55755555);
+ DO_MIPS32_r2_s(msub, 22, 0xfffffd55, 0x55755555, 0x00200000, 0x003FFFFF, 0xfffff555, 0x55955555);
+ DO_MIPS32_r2_s(msub, 23, 0xfffff555, 0x55955555, 0x00400000, 0x007FFFFF, 0xffffd555, 0x55d55555);
+ DO_MIPS32_r2_s(msub, 24, 0xffffd555, 0x55d55555, 0x00800000, 0x00FFFFFF, 0xffff5555, 0x56555555);
+ DO_MIPS32_r2_s(msub, 25, 0xffff5555, 0x56555555, 0x01000000, 0x01FFFFFF, 0xfffd5555, 0x57555555);
+ DO_MIPS32_r2_s(msub, 26, 0xfffd5555, 0x57555555, 0x02000000, 0x03FFFFFF, 0xfff55555, 0x59555555);
+ DO_MIPS32_r2_s(msub, 27, 0xfff55555, 0x59555555, 0x04000000, 0x07FFFFFF, 0xffd55555, 0x5d555555);
+ DO_MIPS32_r2_s(msub, 28, 0xffd55555, 0x5d555555, 0x08000000, 0x0FFFFFFF, 0xff555555, 0x65555555);
+ DO_MIPS32_r2_s(msub, 29, 0xff555555, 0x65555555, 0x10000000, 0x1FFFFFFF, 0xfd555555, 0x75555555);
+ DO_MIPS32_r2_s(msub, 30, 0xfd555555, 0x75555555, 0x20000000, 0x3FFFFFFF, 0xf5555555, 0x95555555);
+ DO_MIPS32_r2_s(msub, 31, 0xf5555555, 0x95555555, 0x40000000, 0x7FFFFFFF, 0xd5555555, 0xd5555555);
+ DO_MIPS32_r2_s(msub, 32, 0xd5555555, 0xd5555555, 0x80000000, 0xFFFFFFFF, 0xd5555555, 0x55555555);
+ DO_MIPS32_r2_s(msub, 33, 0x00000000, 0x00000000, 0x00000000, 0x55555555, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(msub, 34, 0x00000000, 0x00000000, 0x55555555, 0x55555555, 0xe38e38e3, 0xc71c71c7);
+ DO_MIPS32_r2_s(msub, 35, 0xe38e38e3, 0xc71c71c7, 0xAAAAAAAA, 0x55555555, 0x00000000, 0x55555555);
+ DO_MIPS32_r2_s(msub, 36, 0x00000000, 0x55555555, 0xFFFFFFFF, 0x55555555, 0x00000000, 0xaaaaaaaa);
+ DO_MIPS32_r2_s(msub, 37, 0x00000000, 0xaaaaaaaa, 0xAAAAAAAA, 0x00000000, 0x00000000, 0xaaaaaaaa);
+ DO_MIPS32_r2_s(msub, 38, 0x00000000, 0xaaaaaaaa, 0xAAAAAAAA, 0x55555555, 0x1c71c71d, 0x38e38e38);
+ DO_MIPS32_r2_s(msub, 39, 0x1c71c71d, 0x38e38e38, 0xAAAAAAAA, 0xAAAAAAAA, 0x00000000, 0x55555554);
+ DO_MIPS32_r2_s(msub, 40, 0x00000000, 0x55555554, 0xAAAAAAAA, 0xFFFFFFFF, 0xffffffff, 0xfffffffe);
+ DO_MIPS32_r2_s(msub, 41, 0x00000000, 0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0xc0000000, 0xffffffff);
+ DO_MIPS32_r2_s(msub, 42, 0xc0000000, 0xffffffff, 0x7FFFFFFF, 0x80000000, 0x00000000, 0x7fffffff);
+ DO_MIPS32_r2_s(msub, 43, 0x00000000, 0x7fffffff, 0x7FFFFFFF, 0xFFFFFFFF, 0x00000000, 0xfffffffe);
+ DO_MIPS32_r2_s(msub, 44, 0x00000000, 0xfffffffe, 0x80000000, 0x7FFFFFFF, 0x40000000, 0x7ffffffe);
+ DO_MIPS32_r2_s(msub, 45, 0x40000000, 0x7ffffffe, 0x80000000, 0x80000000, 0x00000000, 0x7ffffffe);
+ DO_MIPS32_r2_s(msub, 46, 0x00000000, 0x7ffffffe, 0x80000000, 0xFFFFFFFF, 0xffffffff, 0xfffffffe);
+ DO_MIPS32_r2_s(msub, 47, 0xffffffff, 0xfffffffe, 0xFFFFFFFF, 0x7FFFFFFF, 0x00000000, 0x7ffffffd);
+ DO_MIPS32_r2_s(msub, 48, 0x00000000, 0x7ffffffd, 0xFFFFFFFF, 0x80000000, 0xffffffff, 0xfffffffd);
+ DO_MIPS32_r2_s(msub, 49, 0xffffffff, 0xfffffffd, 0xFFFFFFFF, 0xFFFFFFFF, 0xffffffff, 0xfffffffc);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/msubu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/msubu.c
new file mode 100644
index 0000000000..d20065d0b2
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/msubu.c
@@ -0,0 +1,78 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_r2_s(msubu, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(msubu, 1, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0xffffffff, 0xffffffff);
+ DO_MIPS32_r2_s(msubu, 2, 0xffffffff, 0xffffffff, 0x00000002, 0x00000003, 0xffffffff, 0xfffffff9);
+ DO_MIPS32_r2_s(msubu, 3, 0xffffffff, 0xfffffff9, 0x00000004, 0x00000007, 0xffffffff, 0xffffffdd);
+ DO_MIPS32_r2_s(msubu, 4, 0xffffffff, 0xffffffdd, 0x00000008, 0x0000000F, 0xffffffff, 0xffffff65);
+ DO_MIPS32_r2_s(msubu, 5, 0xffffffff, 0xffffff65, 0x00000010, 0x0000001F, 0xffffffff, 0xfffffd75);
+ DO_MIPS32_r2_s(msubu, 6, 0xffffffff, 0xfffffd75, 0x00000020, 0x0000003F, 0xffffffff, 0xfffff595);
+ DO_MIPS32_r2_s(msubu, 7, 0xffffffff, 0xfffff595, 0x00000040, 0x0000007F, 0xffffffff, 0xffffd5d5);
+ DO_MIPS32_r2_s(msubu, 8, 0xffffffff, 0xffffd5d5, 0x00000080, 0x000000FF, 0xffffffff, 0xffff5655);
+ DO_MIPS32_r2_s(msubu, 9, 0xffffffff, 0xffff5655, 0x00000100, 0x000001FF, 0xffffffff, 0xfffd5755);
+ DO_MIPS32_r2_s(msubu, 10, 0xffffffff, 0xfffd5755, 0x00000200, 0x000003FF, 0xffffffff, 0xfff55955);
+ DO_MIPS32_r2_s(msubu, 11, 0xffffffff, 0xfff55955, 0x00000400, 0x000007FF, 0xffffffff, 0xffd55d55);
+ DO_MIPS32_r2_s(msubu, 12, 0xffffffff, 0xffd55d55, 0x00000800, 0x00000FFF, 0xffffffff, 0xff556555);
+ DO_MIPS32_r2_s(msubu, 13, 0xffffffff, 0xff556555, 0x00001000, 0x00001FFF, 0xffffffff, 0xfd557555);
+ DO_MIPS32_r2_s(msubu, 14, 0xffffffff, 0xfd557555, 0x00002000, 0x00003FFF, 0xffffffff, 0xf5559555);
+ DO_MIPS32_r2_s(msubu, 15, 0xffffffff, 0xf5559555, 0x00004000, 0x00007FFF, 0xffffffff, 0xd555d555);
+ DO_MIPS32_r2_s(msubu, 16, 0xffffffff, 0xd555d555, 0x00008000, 0x0000FFFF, 0xffffffff, 0x55565555);
+ DO_MIPS32_r2_s(msubu, 17, 0xffffffff, 0x55565555, 0x00010000, 0x0001FFFF, 0xfffffffd, 0x55575555);
+ DO_MIPS32_r2_s(msubu, 18, 0xfffffffd, 0x55575555, 0x00020000, 0x0003FFFF, 0xfffffff5, 0x55595555);
+ DO_MIPS32_r2_s(msubu, 19, 0xfffffff5, 0x55595555, 0x00040000, 0x0007FFFF, 0xffffffd5, 0x555d5555);
+ DO_MIPS32_r2_s(msubu, 20, 0xffffffd5, 0x555d5555, 0x00080000, 0x000FFFFF, 0xffffff55, 0x55655555);
+ DO_MIPS32_r2_s(msubu, 21, 0xffffff55, 0x55655555, 0x00100000, 0x001FFFFF, 0xfffffd55, 0x55755555);
+ DO_MIPS32_r2_s(msubu, 22, 0xfffffd55, 0x55755555, 0x00200000, 0x003FFFFF, 0xfffff555, 0x55955555);
+ DO_MIPS32_r2_s(msubu, 23, 0xfffff555, 0x55955555, 0x00400000, 0x007FFFFF, 0xffffd555, 0x55d55555);
+ DO_MIPS32_r2_s(msubu, 24, 0xffffd555, 0x55d55555, 0x00800000, 0x00FFFFFF, 0xffff5555, 0x56555555);
+ DO_MIPS32_r2_s(msubu, 25, 0xffff5555, 0x56555555, 0x01000000, 0x01FFFFFF, 0xfffd5555, 0x57555555);
+ DO_MIPS32_r2_s(msubu, 26, 0xfffd5555, 0x57555555, 0x02000000, 0x03FFFFFF, 0xfff55555, 0x59555555);
+ DO_MIPS32_r2_s(msubu, 27, 0xfff55555, 0x59555555, 0x04000000, 0x07FFFFFF, 0xffd55555, 0x5d555555);
+ DO_MIPS32_r2_s(msubu, 28, 0xffd55555, 0x5d555555, 0x08000000, 0x0FFFFFFF, 0xff555555, 0x65555555);
+ DO_MIPS32_r2_s(msubu, 29, 0xff555555, 0x65555555, 0x10000000, 0x1FFFFFFF, 0xfd555555, 0x75555555);
+ DO_MIPS32_r2_s(msubu, 30, 0xfd555555, 0x75555555, 0x20000000, 0x3FFFFFFF, 0xf5555555, 0x95555555);
+ DO_MIPS32_r2_s(msubu, 31, 0xf5555555, 0x95555555, 0x40000000, 0x7FFFFFFF, 0xd5555555, 0xd5555555);
+ DO_MIPS32_r2_s(msubu, 32, 0xd5555555, 0xd5555555, 0x80000000, 0xFFFFFFFF, 0x55555556, 0x55555555);
+ DO_MIPS32_r2_s(msubu, 33, 0x00000000, 0x00000000, 0x00000000, 0x55555555, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(msubu, 34, 0x00000000, 0x00000000, 0x55555555, 0x55555555, 0xe38e38e3, 0xc71c71c7);
+ DO_MIPS32_r2_s(msubu, 35, 0xe38e38e3, 0xc71c71c7, 0xAAAAAAAA, 0x55555555, 0xaaaaaaab, 0x55555555);
+ DO_MIPS32_r2_s(msubu, 36, 0xaaaaaaab, 0x55555555, 0xFFFFFFFF, 0x55555555, 0x55555556, 0xaaaaaaaa);
+ DO_MIPS32_r2_s(msubu, 37, 0x55555556, 0xaaaaaaaa, 0xAAAAAAAA, 0x00000000, 0x55555556, 0xaaaaaaaa);
+ DO_MIPS32_r2_s(msubu, 38, 0x55555556, 0xaaaaaaaa, 0xAAAAAAAA, 0x55555555, 0x1c71c71e, 0x38e38e38);
+ DO_MIPS32_r2_s(msubu, 39, 0x1c71c71e, 0x38e38e38, 0xAAAAAAAA, 0xAAAAAAAA, 0xaaaaaaad, 0x55555554);
+ DO_MIPS32_r2_s(msubu, 40, 0xaaaaaaad, 0x55555554, 0xAAAAAAAA, 0xFFFFFFFF, 0x00000003, 0xfffffffe);
+ DO_MIPS32_r2_s(msubu, 41, 0x00000000, 0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0xc0000000, 0xffffffff);
+ DO_MIPS32_r2_s(msubu, 42, 0xc0000000, 0xffffffff, 0x7FFFFFFF, 0x80000000, 0x80000001, 0x7fffffff);
+ DO_MIPS32_r2_s(msubu, 43, 0x80000001, 0x7fffffff, 0x7FFFFFFF, 0xFFFFFFFF, 0x00000002, 0xfffffffe);
+ DO_MIPS32_r2_s(msubu, 44, 0x00000002, 0xfffffffe, 0x80000000, 0x7FFFFFFF, 0xc0000003, 0x7ffffffe);
+ DO_MIPS32_r2_s(msubu, 45, 0xc0000003, 0x7ffffffe, 0x80000000, 0x80000000, 0x80000003, 0x7ffffffe);
+ DO_MIPS32_r2_s(msubu, 46, 0x80000003, 0x7ffffffe, 0x80000000, 0xFFFFFFFF, 0x00000003, 0xfffffffe);
+ DO_MIPS32_r2_s(msubu, 47, 0x00000003, 0xfffffffe, 0xFFFFFFFF, 0x7FFFFFFF, 0x80000005, 0x7ffffffd);
+ DO_MIPS32_r2_s(msubu, 48, 0x80000005, 0x7ffffffd, 0xFFFFFFFF, 0x80000000, 0x00000005, 0xfffffffd);
+ DO_MIPS32_r2_s(msubu, 49, 0x00000005, 0xfffffffd, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0xfffffffc);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/mul.c b/tests/tcg/mips/user/isa/mips32/arithmatic/mul.c
new file mode 100644
index 0000000000..ab74a14545
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/mul.c
@@ -0,0 +1,78 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_r(mul, 0, 0x00000000, 0x00000000, 0x00000000);
+ DO_MIPS32_r(mul, 1, 0x00000001, 0x00000001, 0x00000001);
+ DO_MIPS32_r(mul, 2, 0x00000002, 0x00000003, 0x00000006);
+ DO_MIPS32_r(mul, 3, 0x00000004, 0x00000007, 0x0000001C);
+ DO_MIPS32_r(mul, 4, 0x00000008, 0x0000000F, 0x00000078);
+ DO_MIPS32_r(mul, 5, 0x00000010, 0x0000001F, 0x000001F0);
+ DO_MIPS32_r(mul, 6, 0x00000020, 0x0000003F, 0x000007E0);
+ DO_MIPS32_r(mul, 7, 0x00000040, 0x0000007F, 0x00001FC0);
+ DO_MIPS32_r(mul, 8, 0x00000080, 0x000000FF, 0x00007F80);
+ DO_MIPS32_r(mul, 9, 0x00000100, 0x000001FF, 0x0001FF00);
+ DO_MIPS32_r(mul, 10, 0x00000200, 0x000003FF, 0x0007FE00);
+ DO_MIPS32_r(mul, 11, 0x00000400, 0x000007FF, 0x001FFC00);
+ DO_MIPS32_r(mul, 12, 0x00000800, 0x00000FFF, 0x007FF800);
+ DO_MIPS32_r(mul, 13, 0x00001000, 0x00001FFF, 0x01FFF000);
+ DO_MIPS32_r(mul, 14, 0x00002000, 0x00003FFF, 0x07FFE000);
+ DO_MIPS32_r(mul, 15, 0x00004000, 0x00007FFF, 0x1FFFC000);
+ DO_MIPS32_r(mul, 16, 0x00008000, 0x0000FFFF, 0x7FFF8000);
+ DO_MIPS32_r(mul, 17, 0x00010000, 0x0001FFFF, 0xFFFF0000);
+ DO_MIPS32_r(mul, 18, 0x00020000, 0x0003FFFF, 0xFFFE0000);
+ DO_MIPS32_r(mul, 19, 0x00040000, 0x0007FFFF, 0xFFFC0000);
+ DO_MIPS32_r(mul, 20, 0x00080000, 0x000FFFFF, 0xFFF80000);
+ DO_MIPS32_r(mul, 21, 0x00100000, 0x001FFFFF, 0xFFF00000);
+ DO_MIPS32_r(mul, 22, 0x00200000, 0x003FFFFF, 0xFFE00000);
+ DO_MIPS32_r(mul, 23, 0x00400000, 0x007FFFFF, 0xFFC00000);
+ DO_MIPS32_r(mul, 24, 0x00800000, 0x00FFFFFF, 0xFF800000);
+ DO_MIPS32_r(mul, 25, 0x01000000, 0x01FFFFFF, 0xFF000000);
+ DO_MIPS32_r(mul, 26, 0x02000000, 0x03FFFFFF, 0xFE000000);
+ DO_MIPS32_r(mul, 27, 0x04000000, 0x07FFFFFF, 0xFC000000);
+ DO_MIPS32_r(mul, 28, 0x08000000, 0x0FFFFFFF, 0xF8000000);
+ DO_MIPS32_r(mul, 29, 0x10000000, 0x1FFFFFFF, 0xF0000000);
+ DO_MIPS32_r(mul, 30, 0x20000000, 0x3FFFFFFF, 0xE0000000);
+ DO_MIPS32_r(mul, 31, 0x40000000, 0x7FFFFFFF, 0xC0000000);
+ DO_MIPS32_r(mul, 32, 0x80000000, 0xFFFFFFFF, 0x80000000);
+ DO_MIPS32_r(mul, 33, 0x00000000, 0x55555555, 0x00000000);
+ DO_MIPS32_r(mul, 34, 0x55555555, 0x55555555, 0x38E38E39);
+ DO_MIPS32_r(mul, 35, 0xAAAAAAAA, 0x55555555, 0x71C71C72);
+ DO_MIPS32_r(mul, 36, 0xFFFFFFFF, 0x55555555, 0xAAAAAAAB);
+ DO_MIPS32_r(mul, 37, 0xAAAAAAAA, 0x00000000, 0x00000000);
+ DO_MIPS32_r(mul, 38, 0xAAAAAAAA, 0x55555555, 0x71C71C72);
+ DO_MIPS32_r(mul, 39, 0xAAAAAAAA, 0xAAAAAAAA, 0xE38E38E4);
+ DO_MIPS32_r(mul, 40, 0xAAAAAAAA, 0xFFFFFFFF, 0x55555556);
+ DO_MIPS32_r(mul, 41, 0x7FFFFFFF, 0x7FFFFFFF, 0x00000001);
+ DO_MIPS32_r(mul, 42, 0x7FFFFFFF, 0x80000000, 0x80000000);
+ DO_MIPS32_r(mul, 43, 0x7FFFFFFF, 0xFFFFFFFF, 0x80000001);
+ DO_MIPS32_r(mul, 44, 0x80000000, 0x7FFFFFFF, 0x80000000);
+ DO_MIPS32_r(mul, 45, 0x80000000, 0x80000000, 0x00000000);
+ DO_MIPS32_r(mul, 46, 0x80000000, 0xFFFFFFFF, 0x80000000);
+ DO_MIPS32_r(mul, 47, 0xFFFFFFFF, 0x7FFFFFFF, 0x80000001);
+ DO_MIPS32_r(mul, 48, 0xFFFFFFFF, 0x80000000, 0x80000000);
+ DO_MIPS32_r(mul, 49, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/mult.c b/tests/tcg/mips/user/isa/mips32/arithmatic/mult.c
new file mode 100644
index 0000000000..8ac7b2c1b8
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/mult.c
@@ -0,0 +1,78 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_r2_s(mult, 0, 0, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(mult, 1, 0, 0, 0x00000001, 0x00000001, 0x00000000, 0x00000001);
+ DO_MIPS32_r2_s(mult, 2, 0, 0, 0x00000002, 0x00000003, 0x00000000, 0x00000006);
+ DO_MIPS32_r2_s(mult, 3, 0, 0, 0x00000004, 0x00000007, 0x00000000, 0x0000001C);
+ DO_MIPS32_r2_s(mult, 4, 0, 0, 0x00000008, 0x0000000F, 0x00000000, 0x00000078);
+ DO_MIPS32_r2_s(mult, 5, 0, 0, 0x00000010, 0x0000001F, 0x00000000, 0x000001F0);
+ DO_MIPS32_r2_s(mult, 6, 0, 0, 0x00000020, 0x0000003F, 0x00000000, 0x000007E0);
+ DO_MIPS32_r2_s(mult, 7, 0, 0, 0x00000040, 0x0000007F, 0x00000000, 0x00001FC0);
+ DO_MIPS32_r2_s(mult, 8, 0, 0, 0x00000080, 0x000000FF, 0x00000000, 0x00007F80);
+ DO_MIPS32_r2_s(mult, 9, 0, 0, 0x00000100, 0x000001FF, 0x00000000, 0x0001FF00);
+ DO_MIPS32_r2_s(mult, 10, 0, 0, 0x00000200, 0x000003FF, 0x00000000, 0x0007FE00);
+ DO_MIPS32_r2_s(mult, 11, 0, 0, 0x00000400, 0x000007FF, 0x00000000, 0x001FFC00);
+ DO_MIPS32_r2_s(mult, 12, 0, 0, 0x00000800, 0x00000FFF, 0x00000000, 0x007FF800);
+ DO_MIPS32_r2_s(mult, 13, 0, 0, 0x00001000, 0x00001FFF, 0x00000000, 0x01FFF000);
+ DO_MIPS32_r2_s(mult, 14, 0, 0, 0x00002000, 0x00003FFF, 0x00000000, 0x07FFE000);
+ DO_MIPS32_r2_s(mult, 15, 0, 0, 0x00004000, 0x00007FFF, 0x00000000, 0x1FFFC000);
+ DO_MIPS32_r2_s(mult, 16, 0, 0, 0x00008000, 0x0000FFFF, 0x00000000, 0x7FFF8000);
+ DO_MIPS32_r2_s(mult, 17, 0, 0, 0x00010000, 0x0001FFFF, 0x00000001, 0xFFFF0000);
+ DO_MIPS32_r2_s(mult, 18, 0, 0, 0x00020000, 0x0003FFFF, 0x00000007, 0xFFFE0000);
+ DO_MIPS32_r2_s(mult, 19, 0, 0, 0x00040000, 0x0007FFFF, 0x0000001F, 0xFFFC0000);
+ DO_MIPS32_r2_s(mult, 20, 0, 0, 0x00080000, 0x000FFFFF, 0x0000007F, 0xFFF80000);
+ DO_MIPS32_r2_s(mult, 21, 0, 0, 0x00100000, 0x001FFFFF, 0x000001FF, 0xFFF00000);
+ DO_MIPS32_r2_s(mult, 22, 0, 0, 0x00200000, 0x003FFFFF, 0x000007FF, 0xFFE00000);
+ DO_MIPS32_r2_s(mult, 23, 0, 0, 0x00400000, 0x007FFFFF, 0x00001FFF, 0xFFC00000);
+ DO_MIPS32_r2_s(mult, 24, 0, 0, 0x00800000, 0x00FFFFFF, 0x00007FFF, 0xFF800000);
+ DO_MIPS32_r2_s(mult, 25, 0, 0, 0x01000000, 0x01FFFFFF, 0x0001FFFF, 0xFF000000);
+ DO_MIPS32_r2_s(mult, 26, 0, 0, 0x02000000, 0x03FFFFFF, 0x0007FFFF, 0xFE000000);
+ DO_MIPS32_r2_s(mult, 27, 0, 0, 0x04000000, 0x07FFFFFF, 0x001FFFFF, 0xFC000000);
+ DO_MIPS32_r2_s(mult, 28, 0, 0, 0x08000000, 0x0FFFFFFF, 0x007FFFFF, 0xF8000000);
+ DO_MIPS32_r2_s(mult, 29, 0, 0, 0x10000000, 0x1FFFFFFF, 0x01FFFFFF, 0xF0000000);
+ DO_MIPS32_r2_s(mult, 30, 0, 0, 0x20000000, 0x3FFFFFFF, 0x07FFFFFF, 0xE0000000);
+ DO_MIPS32_r2_s(mult, 31, 0, 0, 0x40000000, 0x7FFFFFFF, 0x1FFFFFFF, 0xC0000000);
+ DO_MIPS32_r2_s(mult, 32, 0, 0, 0x80000000, 0xFFFFFFFF, 0x00000000, 0x80000000);
+ DO_MIPS32_r2_s(mult, 33, 0, 0, 0x00000000, 0x55555555, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(mult, 34, 0, 0, 0x55555555, 0x55555555, 0x1C71C71C, 0x38E38E39);
+ DO_MIPS32_r2_s(mult, 35, 0, 0, 0xAAAAAAAA, 0x55555555, 0xE38E38E3, 0x71C71C72);
+ DO_MIPS32_r2_s(mult, 36, 0, 0, 0xFFFFFFFF, 0x55555555, 0xFFFFFFFF, 0xAAAAAAAB);
+ DO_MIPS32_r2_s(mult, 37, 0, 0, 0xAAAAAAAA, 0x00000000, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(mult, 38, 0, 0, 0xAAAAAAAA, 0x55555555, 0xE38E38E3, 0x71C71C72);
+ DO_MIPS32_r2_s(mult, 39, 0, 0, 0xAAAAAAAA, 0xAAAAAAAA, 0x1C71C71C, 0xE38E38E4);
+ DO_MIPS32_r2_s(mult, 40, 0, 0, 0xAAAAAAAA, 0xFFFFFFFF, 0x00000000, 0x55555556);
+ DO_MIPS32_r2_s(mult, 41, 0, 0, 0x7FFFFFFF, 0x7FFFFFFF, 0x3FFFFFFF, 0x00000001);
+ DO_MIPS32_r2_s(mult, 42, 0, 0, 0x7FFFFFFF, 0x80000000, 0xC0000000, 0x80000000);
+ DO_MIPS32_r2_s(mult, 43, 0, 0, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x80000001);
+ DO_MIPS32_r2_s(mult, 44, 0, 0, 0x80000000, 0x7FFFFFFF, 0xC0000000, 0x80000000);
+ DO_MIPS32_r2_s(mult, 45, 0, 0, 0x80000000, 0x80000000, 0x40000000, 0x00000000);
+ DO_MIPS32_r2_s(mult, 46, 0, 0, 0x80000000, 0xFFFFFFFF, 0x00000000, 0x80000000);
+ DO_MIPS32_r2_s(mult, 47, 0, 0, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, 0x80000001);
+ DO_MIPS32_r2_s(mult, 48, 0, 0, 0xFFFFFFFF, 0x80000000, 0x00000000, 0x80000000);
+ DO_MIPS32_r2_s(mult, 49, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000001);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/multu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/multu.c
new file mode 100644
index 0000000000..eeafbd2d50
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/multu.c
@@ -0,0 +1,78 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_r2_s(multu, 0, 0, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(multu, 1, 0, 0, 0x00000001, 0x00000001, 0x00000000, 0x00000001);
+ DO_MIPS32_r2_s(multu, 2, 0, 0, 0x00000002, 0x00000003, 0x00000000, 0x00000006);
+ DO_MIPS32_r2_s(multu, 3, 0, 0, 0x00000004, 0x00000007, 0x00000000, 0x0000001C);
+ DO_MIPS32_r2_s(multu, 4, 0, 0, 0x00000008, 0x0000000F, 0x00000000, 0x00000078);
+ DO_MIPS32_r2_s(multu, 5, 0, 0, 0x00000010, 0x0000001F, 0x00000000, 0x000001F0);
+ DO_MIPS32_r2_s(multu, 6, 0, 0, 0x00000020, 0x0000003F, 0x00000000, 0x000007E0);
+ DO_MIPS32_r2_s(multu, 7, 0, 0, 0x00000040, 0x0000007F, 0x00000000, 0x00001FC0);
+ DO_MIPS32_r2_s(multu, 8, 0, 0, 0x00000080, 0x000000FF, 0x00000000, 0x00007F80);
+ DO_MIPS32_r2_s(multu, 9, 0, 0, 0x00000100, 0x000001FF, 0x00000000, 0x0001FF00);
+ DO_MIPS32_r2_s(multu, 10, 0, 0, 0x00000200, 0x000003FF, 0x00000000, 0x0007FE00);
+ DO_MIPS32_r2_s(multu, 11, 0, 0, 0x00000400, 0x000007FF, 0x00000000, 0x001FFC00);
+ DO_MIPS32_r2_s(multu, 12, 0, 0, 0x00000800, 0x00000FFF, 0x00000000, 0x007FF800);
+ DO_MIPS32_r2_s(multu, 13, 0, 0, 0x00001000, 0x00001FFF, 0x00000000, 0x01FFF000);
+ DO_MIPS32_r2_s(multu, 14, 0, 0, 0x00002000, 0x00003FFF, 0x00000000, 0x07FFE000);
+ DO_MIPS32_r2_s(multu, 15, 0, 0, 0x00004000, 0x00007FFF, 0x00000000, 0x1FFFC000);
+ DO_MIPS32_r2_s(multu, 16, 0, 0, 0x00008000, 0x0000FFFF, 0x00000000, 0x7FFF8000);
+ DO_MIPS32_r2_s(multu, 17, 0, 0, 0x00010000, 0x0001FFFF, 0x00000001, 0xFFFF0000);
+ DO_MIPS32_r2_s(multu, 18, 0, 0, 0x00020000, 0x0003FFFF, 0x00000007, 0xFFFE0000);
+ DO_MIPS32_r2_s(multu, 19, 0, 0, 0x00040000, 0x0007FFFF, 0x0000001F, 0xFFFC0000);
+ DO_MIPS32_r2_s(multu, 20, 0, 0, 0x00080000, 0x000FFFFF, 0x0000007F, 0xFFF80000);
+ DO_MIPS32_r2_s(multu, 21, 0, 0, 0x00100000, 0x001FFFFF, 0x000001FF, 0xFFF00000);
+ DO_MIPS32_r2_s(multu, 22, 0, 0, 0x00200000, 0x003FFFFF, 0x000007FF, 0xFFE00000);
+ DO_MIPS32_r2_s(multu, 23, 0, 0, 0x00400000, 0x007FFFFF, 0x00001FFF, 0xFFC00000);
+ DO_MIPS32_r2_s(multu, 24, 0, 0, 0x00800000, 0x00FFFFFF, 0x00007FFF, 0xFF800000);
+ DO_MIPS32_r2_s(multu, 25, 0, 0, 0x01000000, 0x01FFFFFF, 0x0001FFFF, 0xFF000000);
+ DO_MIPS32_r2_s(multu, 26, 0, 0, 0x02000000, 0x03FFFFFF, 0x0007FFFF, 0xFE000000);
+ DO_MIPS32_r2_s(multu, 27, 0, 0, 0x04000000, 0x07FFFFFF, 0x001FFFFF, 0xFC000000);
+ DO_MIPS32_r2_s(multu, 28, 0, 0, 0x08000000, 0x0FFFFFFF, 0x007FFFFF, 0xF8000000);
+ DO_MIPS32_r2_s(multu, 29, 0, 0, 0x10000000, 0x1FFFFFFF, 0x01FFFFFF, 0xF0000000);
+ DO_MIPS32_r2_s(multu, 30, 0, 0, 0x20000000, 0x3FFFFFFF, 0x07FFFFFF, 0xE0000000);
+ DO_MIPS32_r2_s(multu, 31, 0, 0, 0x40000000, 0x7FFFFFFF, 0x1FFFFFFF, 0xC0000000);
+ DO_MIPS32_r2_s(multu, 32, 0, 0, 0x80000000, 0xFFFFFFFF, 0x7FFFFFFF, 0x80000000);
+ DO_MIPS32_r2_s(multu, 33, 0, 0, 0x00000000, 0x55555555, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(multu, 34, 0, 0, 0x55555555, 0x55555555, 0x1C71C71C, 0x38E38E39);
+ DO_MIPS32_r2_s(multu, 35, 0, 0, 0xAAAAAAAA, 0x55555555, 0x38E38E38, 0x71C71C72);
+ DO_MIPS32_r2_s(multu, 36, 0, 0, 0xFFFFFFFF, 0x55555555, 0x55555554, 0xAAAAAAAB);
+ DO_MIPS32_r2_s(multu, 37, 0, 0, 0xAAAAAAAA, 0x00000000, 0x00000000, 0x00000000);
+ DO_MIPS32_r2_s(multu, 38, 0, 0, 0xAAAAAAAA, 0x55555555, 0x38E38E38, 0x71C71C72);
+ DO_MIPS32_r2_s(multu, 39, 0, 0, 0xAAAAAAAA, 0xAAAAAAAA, 0x71C71C70, 0xE38E38E4);
+ DO_MIPS32_r2_s(multu, 40, 0, 0, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAA9, 0x55555556);
+ DO_MIPS32_r2_s(multu, 41, 0, 0, 0x7FFFFFFF, 0x7FFFFFFF, 0x3FFFFFFF, 0x00000001);
+ DO_MIPS32_r2_s(multu, 42, 0, 0, 0x7FFFFFFF, 0x80000000, 0x3FFFFFFF, 0x80000000);
+ DO_MIPS32_r2_s(multu, 43, 0, 0, 0x7FFFFFFF, 0xFFFFFFFF, 0x7FFFFFFE, 0x80000001);
+ DO_MIPS32_r2_s(multu, 44, 0, 0, 0x80000000, 0x7FFFFFFF, 0x3FFFFFFF, 0x80000000);
+ DO_MIPS32_r2_s(multu, 45, 0, 0, 0x80000000, 0x80000000, 0x40000000, 0x00000000);
+ DO_MIPS32_r2_s(multu, 46, 0, 0, 0x80000000, 0xFFFFFFFF, 0x7FFFFFFF, 0x80000000);
+ DO_MIPS32_r2_s(multu, 47, 0, 0, 0xFFFFFFFF, 0x7FFFFFFF, 0x7FFFFFFE, 0x80000001);
+ DO_MIPS32_r2_s(multu, 48, 0, 0, 0xFFFFFFFF, 0x80000000, 0x7FFFFFFF, 0x80000000);
+ DO_MIPS32_r2_s(multu, 49, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/slt.c b/tests/tcg/mips/user/isa/mips32/arithmatic/slt.c
new file mode 100644
index 0000000000..74f22c365e
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/slt.c
@@ -0,0 +1,61 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_r(slt, 0, 0x00000000, 0x00000000, 0);
+ DO_MIPS32_r(slt, 1, 0x00000001, 0x00000001, 0);
+ DO_MIPS32_r(slt, 2, 0x00000002, 0x00000003, 1);
+ DO_MIPS32_r(slt, 3, 0x00000005, 0x00000007, 1);
+ DO_MIPS32_r(slt, 4, 0x0000000B, 0x0000000F, 1);
+ DO_MIPS32_r(slt, 5, 0x00000017, 0x0000001F, 1);
+ DO_MIPS32_r(slt, 6, 0x0000002F, 0x0000003F, 1);
+ DO_MIPS32_r(slt, 7, 0x0000005F, 0x0000007F, 1);
+ DO_MIPS32_r(slt, 8, 0x000000BF, 0x000000FF, 1);
+ DO_MIPS32_r(slt, 9, 0x0000017F, 0x000001FF, 1);
+ DO_MIPS32_r(slt, 10, 0x000002FF, 0x000003FF, 1);
+ DO_MIPS32_r(slt, 11, 0x000005FF, 0x000007FF, 1);
+ DO_MIPS32_r(slt, 12, 0x00000BFF, 0x00000FFF, 1);
+ DO_MIPS32_r(slt, 13, 0x000017FF, 0x00001FFF, 1);
+ DO_MIPS32_r(slt, 14, 0x00002FFF, 0x00003FFF, 1);
+ DO_MIPS32_r(slt, 15, 0x00005FFF, 0x00007FFF, 1);
+ DO_MIPS32_r(slt, 16, 0x0000BFFF, 0x0000FFFF, 1);
+ DO_MIPS32_r(slt, 17, 0x00017FFF, 0x0001FFFF, 1);
+ DO_MIPS32_r(slt, 18, 0x0002FFFF, 0x0003FFFF, 1);
+ DO_MIPS32_r(slt, 19, 0x0005FFFF, 0x0007FFFF, 1);
+ DO_MIPS32_r(slt, 20, 0x000BFFFF, 0x000FFFFF, 1);
+ DO_MIPS32_r(slt, 21, 0x0017FFFF, 0x001FFFFF, 1);
+ DO_MIPS32_r(slt, 22, 0x002FFFFF, 0x003FFFFF, 1);
+ DO_MIPS32_r(slt, 23, 0x005FFFFF, 0x007FFFFF, 1);
+ DO_MIPS32_r(slt, 24, 0x00BFFFFF, 0x00FFFFFF, 1);
+ DO_MIPS32_r(slt, 25, 0x017FFFFF, 0x01FFFFFF, 1);
+ DO_MIPS32_r(slt, 26, 0x02FFFFFF, 0x03FFFFFF, 1);
+ DO_MIPS32_r(slt, 27, 0x05FFFFFF, 0x07FFFFFF, 1);
+ DO_MIPS32_r(slt, 28, 0x0BFFFFFF, 0x0FFFFFFF, 1);
+ DO_MIPS32_r(slt, 29, 0x17FFFFFF, 0x1FFFFFFF, 1);
+ DO_MIPS32_r(slt, 30, 0x2FFFFFFF, 0x3FFFFFFF, 1);
+ DO_MIPS32_r(slt, 31, 0x5FFFFFFF, 0x7FFFFFFF, 1);
+ DO_MIPS32_r(slt, 32, 0xBFFFFFFF, 0xFFFFFFFF, 1);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/slti.c b/tests/tcg/mips/user/isa/mips32/arithmatic/slti.c
new file mode 100644
index 0000000000..823af3e4d4
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/slti.c
@@ -0,0 +1,48 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_i(slti, 0, 0x0000, 0x00000000, 0);
+ DO_MIPS32_i(slti, 1, 0x0001, 0x00000001, 0);
+ DO_MIPS32_i(slti, 2, 0x0003, 0x00000002, 1);
+ DO_MIPS32_i(slti, 3, 0x0007, 0x00000005, 1);
+ DO_MIPS32_i(slti, 4, 0x000F, 0x0000000B, 1);
+ DO_MIPS32_i(slti, 5, 0x001F, 0x00000017, 1);
+ DO_MIPS32_i(slti, 6, 0x003F, 0x0000002F, 1);
+ DO_MIPS32_i(slti, 7, 0x007F, 0x0000005F, 1);
+ DO_MIPS32_i(slti, 8, 0x00FF, 0x000000BF, 1);
+ DO_MIPS32_i(slti, 9, 0x01FF, 0x0000017F, 1);
+ DO_MIPS32_i(slti, 10, 0x03FF, 0x000002FF, 1);
+ DO_MIPS32_i(slti, 11, 0x07FF, 0x000005FF, 1);
+ DO_MIPS32_i(slti, 12, 0x0FFF, 0x00000BFF, 1);
+ DO_MIPS32_i(slti, 13, 0x1FFF, 0x000017FF, 1);
+ DO_MIPS32_i(slti, 14, 0x3FFF, 0x00002FFF, 1);
+ DO_MIPS32_i(slti, 15, 0x7FFF, 0x00005FFF, 1);
+ DO_MIPS32_i(slti, 16, 0xFFFF, 0x0000BFFF, 0);
+ DO_MIPS32_i(slti, 17, 0xFFFF, 0x7FFFFFFF, 0);
+ DO_MIPS32_i(slti, 18, 0x8000, 0x7FFFFFFF, 0);
+ DO_MIPS32_i(slti, 19, 0x5555, 0x00000000, 1);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/sltiu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/sltiu.c
new file mode 100644
index 0000000000..5644d4d1c1
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/sltiu.c
@@ -0,0 +1,48 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_i(sltiu, 0, 0x0000, 0x00000000, 0);
+ DO_MIPS32_i(sltiu, 1, 0x0001, 0x00000001, 0);
+ DO_MIPS32_i(sltiu, 2, 0x0003, 0x00000002, 1);
+ DO_MIPS32_i(sltiu, 3, 0x0007, 0x00000005, 1);
+ DO_MIPS32_i(sltiu, 4, 0x000F, 0x0000000B, 1);
+ DO_MIPS32_i(sltiu, 5, 0x001F, 0x00000017, 1);
+ DO_MIPS32_i(sltiu, 6, 0x003F, 0x0000002F, 1);
+ DO_MIPS32_i(sltiu, 7, 0x007F, 0x0000005F, 1);
+ DO_MIPS32_i(sltiu, 8, 0x00FF, 0x000000BF, 1);
+ DO_MIPS32_i(sltiu, 9, 0x01FF, 0x0000017F, 1);
+ DO_MIPS32_i(sltiu, 10, 0x03FF, 0x000002FF, 1);
+ DO_MIPS32_i(sltiu, 11, 0x07FF, 0x000005FF, 1);
+ DO_MIPS32_i(sltiu, 12, 0x0FFF, 0x00000BFF, 1);
+ DO_MIPS32_i(sltiu, 13, 0x1FFF, 0x000017FF, 1);
+ DO_MIPS32_i(sltiu, 14, 0x3FFF, 0x00002FFF, 1);
+ DO_MIPS32_i(sltiu, 15, 0x7FFF, 0x00005FFF, 1);
+ DO_MIPS32_i(sltiu, 16, 0xFFFF, 0x0000BFFF, 1);
+ DO_MIPS32_i(sltiu, 17, 0x5555, 0x00000000, 1);
+ DO_MIPS32_i(sltiu, 18, 0xFFFF, 0x7FFFFFFF, 1);
+ DO_MIPS32_i(sltiu, 19, 0x8000, 0x7FFFFFFF, 1);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/sltu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/sltu.c
new file mode 100644
index 0000000000..bba246626e
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/sltu.c
@@ -0,0 +1,61 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_r(sltu, 0, 0x00000000, 0x00000000, 0);
+ DO_MIPS32_r(sltu, 1, 0x00000001, 0x00000001, 0);
+ DO_MIPS32_r(sltu, 2, 0x00000002, 0x00000003, 1);
+ DO_MIPS32_r(sltu, 3, 0x00000005, 0x00000007, 1);
+ DO_MIPS32_r(sltu, 4, 0x0000000B, 0x0000000F, 1);
+ DO_MIPS32_r(sltu, 5, 0x00000017, 0x0000001F, 1);
+ DO_MIPS32_r(sltu, 6, 0x0000002F, 0x0000003F, 1);
+ DO_MIPS32_r(sltu, 7, 0x0000005F, 0x0000007F, 1);
+ DO_MIPS32_r(sltu, 8, 0x000000BF, 0x000000FF, 1);
+ DO_MIPS32_r(sltu, 9, 0x0000017F, 0x000001FF, 1);
+ DO_MIPS32_r(sltu, 10, 0x000002FF, 0x000003FF, 1);
+ DO_MIPS32_r(sltu, 11, 0x000005FF, 0x000007FF, 1);
+ DO_MIPS32_r(sltu, 12, 0x00000BFF, 0x00000FFF, 1);
+ DO_MIPS32_r(sltu, 13, 0x000017FF, 0x00001FFF, 1);
+ DO_MIPS32_r(sltu, 14, 0x00002FFF, 0x00003FFF, 1);
+ DO_MIPS32_r(sltu, 15, 0x00005FFF, 0x00007FFF, 1);
+ DO_MIPS32_r(sltu, 16, 0x0000BFFF, 0x0000FFFF, 1);
+ DO_MIPS32_r(sltu, 17, 0x00017FFF, 0x0001FFFF, 1);
+ DO_MIPS32_r(sltu, 18, 0x0002FFFF, 0x0003FFFF, 1);
+ DO_MIPS32_r(sltu, 19, 0x0005FFFF, 0x0007FFFF, 1);
+ DO_MIPS32_r(sltu, 20, 0x000BFFFF, 0x000FFFFF, 1);
+ DO_MIPS32_r(sltu, 21, 0x0017FFFF, 0x001FFFFF, 1);
+ DO_MIPS32_r(sltu, 22, 0x002FFFFF, 0x003FFFFF, 1);
+ DO_MIPS32_r(sltu, 23, 0x005FFFFF, 0x007FFFFF, 1);
+ DO_MIPS32_r(sltu, 24, 0x00BFFFFF, 0x00FFFFFF, 1);
+ DO_MIPS32_r(sltu, 25, 0x017FFFFF, 0x01FFFFFF, 1);
+ DO_MIPS32_r(sltu, 26, 0x02FFFFFF, 0x03FFFFFF, 1);
+ DO_MIPS32_r(sltu, 27, 0x05FFFFFF, 0x07FFFFFF, 1);
+ DO_MIPS32_r(sltu, 28, 0x0BFFFFFF, 0x0FFFFFFF, 1);
+ DO_MIPS32_r(sltu, 29, 0x17FFFFFF, 0x1FFFFFFF, 1);
+ DO_MIPS32_r(sltu, 30, 0x2FFFFFFF, 0x3FFFFFFF, 1);
+ DO_MIPS32_r(sltu, 31, 0x5FFFFFFF, 0x7FFFFFFF, 1);
+ DO_MIPS32_r(sltu, 32, 0xBFFFFFFF, 0xFFFFFFFF, 1);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/sub.c b/tests/tcg/mips/user/isa/mips32/arithmatic/sub.c
new file mode 100644
index 0000000000..86f747c2e7
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/sub.c
@@ -0,0 +1,104 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_r(sub, 0, 0x00000000, 0x00000000, 0x00000000);
+ DO_MIPS32_r(sub, 1, 0x00000001, 0x00000001, 0x00000000);
+ DO_MIPS32_r(sub, 2, 0x00000002, 0x00000003, 0xFFFFFFFF);
+ DO_MIPS32_r(sub, 3, 0x00000004, 0x00000006, 0xFFFFFFFE);
+ DO_MIPS32_r(sub, 4, 0x00000008, 0x0000000C, 0xFFFFFFFC);
+ DO_MIPS32_r(sub, 5, 0x00000010, 0x00000018, 0xFFFFFFF8);
+ DO_MIPS32_r(sub, 6, 0x00000020, 0x00000030, 0xFFFFFFF0);
+ DO_MIPS32_r(sub, 7, 0x00000040, 0x00000060, 0xFFFFFFE0);
+ DO_MIPS32_r(sub, 8, 0x00000080, 0x000000C0, 0xFFFFFFC0);
+ DO_MIPS32_r(sub, 9, 0x00000100, 0x00000180, 0xFFFFFF80);
+ DO_MIPS32_r(sub, 10, 0x00000200, 0x00000300, 0xFFFFFF00);
+ DO_MIPS32_r(sub, 11, 0x00000400, 0x00000600, 0xFFFFFE00);
+ DO_MIPS32_r(sub, 12, 0x00000800, 0x00000C00, 0xFFFFFC00);
+ DO_MIPS32_r(sub, 13, 0x00001000, 0x00001800, 0xFFFFF800);
+ DO_MIPS32_r(sub, 14, 0x00002000, 0x00003000, 0xFFFFF000);
+ DO_MIPS32_r(sub, 15, 0x00004000, 0x00006000, 0xFFFFE000);
+ DO_MIPS32_r(sub, 16, 0x00008000, 0x0000C000, 0xFFFFC000);
+ DO_MIPS32_r(sub, 17, 0x00010000, 0x00018000, 0xFFFF8000);
+ DO_MIPS32_r(sub, 18, 0x00020000, 0x00030000, 0xFFFF0000);
+ DO_MIPS32_r(sub, 19, 0x00040000, 0x00060000, 0xFFFE0000);
+ DO_MIPS32_r(sub, 20, 0x00080000, 0x000C0000, 0xFFFC0000);
+ DO_MIPS32_r(sub, 21, 0x00100000, 0x00180000, 0xFFF80000);
+ DO_MIPS32_r(sub, 22, 0x00200000, 0x00300000, 0xFFF00000);
+ DO_MIPS32_r(sub, 23, 0x00400000, 0x00600000, 0xFFE00000);
+ DO_MIPS32_r(sub, 24, 0x00800000, 0x00C00000, 0xFFC00000);
+ DO_MIPS32_r(sub, 25, 0x01000000, 0x01800000, 0xFF800000);
+ DO_MIPS32_r(sub, 26, 0x02000000, 0x03000000, 0xFF000000);
+ DO_MIPS32_r(sub, 27, 0x04000000, 0x06000000, 0xFE000000);
+ DO_MIPS32_r(sub, 28, 0x08000000, 0x0C000000, 0xFC000000);
+ DO_MIPS32_r(sub, 29, 0x10000000, 0x18000000, 0xF8000000);
+ DO_MIPS32_r(sub, 30, 0x20000000, 0x30000000, 0xF0000000);
+ DO_MIPS32_r(sub, 31, 0x40000000, 0x60000000, 0xE0000000);
+ DO_MIPS32_r(sub, 32, 0x80000000, 0xC0000000, 0xC0000000);
+ DO_MIPS32_r(sub, 33, 0x00000000, 0x80000000, 0x80000000);
+ DO_MIPS32_r(sub, 34, 0x80000001, 0x80000001, 0x00000000);
+ DO_MIPS32_r(sub, 35, 0xC0000003, 0x40000002, 0x80000001);
+ DO_MIPS32_r(sub, 36, 0xE0000007, 0x20000004, 0xC0000003);
+ DO_MIPS32_r(sub, 37, 0xF000000F, 0x10000008, 0xE0000007);
+ DO_MIPS32_r(sub, 38, 0xF800001F, 0x08000010, 0xF000000F);
+ DO_MIPS32_r(sub, 39, 0xFC00003F, 0x04000020, 0xF800001F);
+ DO_MIPS32_r(sub, 40, 0xFE00007F, 0x02000040, 0xFC00003F);
+ DO_MIPS32_r(sub, 41, 0xFF0000FF, 0x01000080, 0xFE00007F);
+ DO_MIPS32_r(sub, 42, 0xFF8001FF, 0x00800100, 0xFF0000FF);
+ DO_MIPS32_r(sub, 43, 0xFFC003FF, 0x00400200, 0xFF8001FF);
+ DO_MIPS32_r(sub, 44, 0xFFE007FF, 0x00200400, 0xFFC003FF);
+ DO_MIPS32_r(sub, 45, 0xFFF00FFF, 0x00100800, 0xFFE007FF);
+ DO_MIPS32_r(sub, 46, 0xFFF81FFF, 0x00081000, 0xFFF00FFF);
+ DO_MIPS32_r(sub, 47, 0xFFFC3FFF, 0x00042000, 0xFFF81FFF);
+ DO_MIPS32_r(sub, 48, 0xFFFE7FFF, 0x00024000, 0xFFFC3FFF);
+ DO_MIPS32_r(sub, 49, 0xFFFFFFFF, 0x00018000, 0xFFFE7FFF);
+ DO_MIPS32_r(sub, 50, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF);
+ DO_MIPS32_r(sub, 51, 0xFFFFFFFF, 0x00018000, 0xFFFE7FFF);
+ DO_MIPS32_r(sub, 52, 0xFFFE7FFF, 0x0003C000, 0xFFFABFFF);
+ DO_MIPS32_r(sub, 53, 0xFFFC3FFF, 0x0007E000, 0xFFF45FFF);
+ DO_MIPS32_r(sub, 54, 0xFFF81FFF, 0x000FF000, 0xFFE82FFF);
+ DO_MIPS32_r(sub, 55, 0xFFF00FFF, 0x001FF800, 0xFFD017FF);
+ DO_MIPS32_r(sub, 56, 0xFFE007FF, 0x003FFC00, 0xFFA00BFF);
+ DO_MIPS32_r(sub, 57, 0xFFC003FF, 0x007FFE00, 0xFF4005FF);
+ DO_MIPS32_r(sub, 58, 0xFF8001FF, 0x00FFFF00, 0xFE8002FF);
+ DO_MIPS32_r(sub, 59, 0xFF0000FF, 0x01FFFF80, 0xFD00017F);
+ DO_MIPS32_r(sub, 60, 0xFE00007F, 0x03FFFFC0, 0xFA0000BF);
+ DO_MIPS32_r(sub, 61, 0xFC00003F, 0x07FFFFE0, 0xF400005F);
+ DO_MIPS32_r(sub, 62, 0xF800001F, 0x0FFFFFF0, 0xE800002F);
+ DO_MIPS32_r(sub, 63, 0xF000000F, 0x1FFFFFF8, 0xD0000017);
+ DO_MIPS32_r(sub, 64, 0xE0000007, 0x3FFFFFFC, 0xA000000B);
+ DO_MIPS32_r(sub, 65, 0xC0000003, 0x7FFFFFFE, 0x40000005);
+ DO_MIPS32_r(sub, 66, 0x80000001, 0xFFFFFFFF, 0x80000002);
+ DO_MIPS32_r(sub, 67, 0x00000000, 0xFFFFFFFF, 0x00000001);
+ DO_MIPS32_r(sub, 68, 0x00000000, 0x55555555, 0xAAAAAAAB);
+ DO_MIPS32_r(sub, 69, 0x55555555, 0x55555555, 0x00000000);
+ DO_MIPS32_r(sub, 70, 0xAAAAAAAA, 0x15555555, 0x95555555);
+ DO_MIPS32_r(sub, 71, 0xFFFFFFFF, 0x55555555, 0xAAAAAAAA);
+ DO_MIPS32_r(sub, 72, 0xAAAAAAAA, 0x00000000, 0xAAAAAAAA);
+ DO_MIPS32_r(sub, 73, 0xAAAAAAAA, 0x15555555, 0x95555555);
+ DO_MIPS32_r(sub, 74, 0xAAAAAAAA, 0xAAAAAAAA, 0x00000000);
+ DO_MIPS32_r(sub, 75, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAB);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/tests/tcg/mips/user/isa/mips32/arithmatic/subu.c b/tests/tcg/mips/user/isa/mips32/arithmatic/subu.c
new file mode 100644
index 0000000000..fe1df6a71e
--- /dev/null
+++ b/tests/tcg/mips/user/isa/mips32/arithmatic/subu.c
@@ -0,0 +1,108 @@
+/*
+ * MIPS instruction test case
+ *
+ * Copyright (c) 2022 Jiaxun Yang
+ *
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ */
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "../../../../include/test_utils_32.h"
+
+int main(void)
+{
+ int ret = 0;
+ int pass_count = 0;
+ int fail_count = 0;
+
+ DO_MIPS32_r(subu, 0, 0x00000000, 0x00000000, 0x00000000);
+ DO_MIPS32_r(subu, 1, 0x00000001, 0x00000001, 0x00000000);
+ DO_MIPS32_r(subu, 2, 0x00000002, 0x00000003, 0xFFFFFFFF);
+ DO_MIPS32_r(subu, 3, 0x00000004, 0x00000006, 0xFFFFFFFE);
+ DO_MIPS32_r(subu, 4, 0x00000008, 0x0000000C, 0xFFFFFFFC);
+ DO_MIPS32_r(subu, 5, 0x00000010, 0x00000018, 0xFFFFFFF8);
+ DO_MIPS32_r(subu, 6, 0x00000020, 0x00000030, 0xFFFFFFF0);
+ DO_MIPS32_r(subu, 7, 0x00000040, 0x00000060, 0xFFFFFFE0);
+ DO_MIPS32_r(subu, 8, 0x00000080, 0x000000C0, 0xFFFFFFC0);
+ DO_MIPS32_r(subu, 9, 0x00000100, 0x00000180, 0xFFFFFF80);
+ DO_MIPS32_r(subu, 10, 0x00000200, 0x00000300, 0xFFFFFF00);
+ DO_MIPS32_r(subu, 11, 0x00000400, 0x00000600, 0xFFFFFE00);
+ DO_MIPS32_r(subu, 12, 0x00000800, 0x00000C00, 0xFFFFFC00);
+ DO_MIPS32_r(subu, 13, 0x00001000, 0x00001800, 0xFFFFF800);
+ DO_MIPS32_r(subu, 14, 0x00002000, 0x00003000, 0xFFFFF000);
+ DO_MIPS32_r(subu, 15, 0x00004000, 0x00006000, 0xFFFFE000);
+ DO_MIPS32_r(subu, 16, 0x00008000, 0x0000C000, 0xFFFFC000);
+ DO_MIPS32_r(subu, 17, 0x00010000, 0x00018000, 0xFFFF8000);
+ DO_MIPS32_r(subu, 18, 0x00020000, 0x00030000, 0xFFFF0000);
+ DO_MIPS32_r(subu, 19, 0x00040000, 0x00060000, 0xFFFE0000);
+ DO_MIPS32_r(subu, 20, 0x00080000, 0x000C0000, 0xFFFC0000);
+ DO_MIPS32_r(subu, 21, 0x00100000, 0x00180000, 0xFFF80000);
+ DO_MIPS32_r(subu, 22, 0x00200000, 0x00300000, 0xFFF00000);
+ DO_MIPS32_r(subu, 23, 0x00400000, 0x00600000, 0xFFE00000);
+ DO_MIPS32_r(subu, 24, 0x00800000, 0x00C00000, 0xFFC00000);
+ DO_MIPS32_r(subu, 25, 0x01000000, 0x01800000, 0xFF800000);
+ DO_MIPS32_r(subu, 26, 0x02000000, 0x03000000, 0xFF000000);
+ DO_MIPS32_r(subu, 27, 0x04000000, 0x06000000, 0xFE000000);
+ DO_MIPS32_r(subu, 28, 0x08000000, 0x0C000000, 0xFC000000);
+ DO_MIPS32_r(subu, 29, 0x10000000, 0x18000000, 0xF8000000);
+ DO_MIPS32_r(subu, 30, 0x20000000, 0x30000000, 0xF0000000);
+ DO_MIPS32_r(subu, 31, 0x40000000, 0x60000000, 0xE0000000);
+ DO_MIPS32_r(subu, 32, 0x80000000, 0xC0000000, 0xC0000000);
+ DO_MIPS32_r(subu, 33, 0x00000000, 0x80000000, 0x80000000);
+ DO_MIPS32_r(subu, 34, 0x80000001, 0x80000001, 0x00000000);
+ DO_MIPS32_r(subu, 35, 0xC0000003, 0x40000002, 0x80000001);
+ DO_MIPS32_r(subu, 36, 0xE0000007, 0x20000004, 0xC0000003);
+ DO_MIPS32_r(subu, 37, 0xF000000F, 0x10000008, 0xE0000007);
+ DO_MIPS32_r(subu, 38, 0xF800001F, 0x08000010, 0xF000000F);
+ DO_MIPS32_r(subu, 39, 0xFC00003F, 0x04000020, 0xF800001F);
+ DO_MIPS32_r(subu, 40, 0xFE00007F, 0x02000040, 0xFC00003F);
+ DO_MIPS32_r(subu, 41, 0xFF0000FF, 0x01000080, 0xFE00007F);
+ DO_MIPS32_r(subu, 42, 0xFF8001FF, 0x00800100, 0xFF0000FF);
+ DO_MIPS32_r(subu, 43, 0xFFC003FF, 0x00400200, 0xFF8001FF);
+ DO_MIPS32_r(subu, 44, 0xFFE007FF, 0x00200400, 0xFFC003FF);
+ DO_MIPS32_r(subu, 45, 0xFFF00FFF, 0x00100800, 0xFFE007FF);
+ DO_MIPS32_r(subu, 46, 0xFFF81FFF, 0x00081000, 0xFFF00FFF);
+ DO_MIPS32_r(subu, 47, 0xFFFC3FFF, 0x00042000, 0xFFF81FFF);
+ DO_MIPS32_r(subu, 48, 0xFFFE7FFF, 0x00024000, 0xFFFC3FFF);
+ DO_MIPS32_r(subu, 49, 0xFFFFFFFF, 0x00018000, 0xFFFE7FFF);
+ DO_MIPS32_r(subu, 50, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF);
+ DO_MIPS32_r(subu, 51, 0xFFFFFFFF, 0x00018000, 0xFFFE7FFF);
+ DO_MIPS32_r(subu, 52, 0xFFFE7FFF, 0x0003C000, 0xFFFABFFF);
+ DO_MIPS32_r(subu, 53, 0xFFFC3FFF, 0x0007E000, 0xFFF45FFF);
+ DO_MIPS32_r(subu, 54, 0xFFF81FFF, 0x000FF000, 0xFFE82FFF);
+ DO_MIPS32_r(subu, 55, 0xFFF00FFF, 0x001FF800, 0xFFD017FF);
+ DO_MIPS32_r(subu, 56, 0xFFE007FF, 0x003FFC00, 0xFFA00BFF);
+ DO_MIPS32_r(subu, 57, 0xFFC003FF, 0x007FFE00, 0xFF4005FF);
+ DO_MIPS32_r(subu, 58, 0xFF8001FF, 0x00FFFF00, 0xFE8002FF);
+ DO_MIPS32_r(subu, 59, 0xFF0000FF, 0x01FFFF80, 0xFD00017F);
+ DO_MIPS32_r(subu, 60, 0xFE00007F, 0x03FFFFC0, 0xFA0000BF);
+ DO_MIPS32_r(subu, 61, 0xFC00003F, 0x07FFFFE0, 0xF400005F);
+ DO_MIPS32_r(subu, 62, 0xF800001F, 0x0FFFFFF0, 0xE800002F);
+ DO_MIPS32_r(subu, 63, 0xF000000F, 0x1FFFFFF8, 0xD0000017);
+ DO_MIPS32_r(subu, 64, 0xE0000007, 0x3FFFFFFC, 0xA000000B);
+ DO_MIPS32_r(subu, 65, 0xC0000003, 0x7FFFFFFE, 0x40000005);
+ DO_MIPS32_r(subu, 66, 0x80000001, 0xFFFFFFFF, 0x80000002);
+ DO_MIPS32_r(subu, 67, 0x00000000, 0xFFFFFFFF, 0x00000001);
+ DO_MIPS32_r(subu, 68, 0x00000000, 0x55555555, 0xAAAAAAAB);
+ DO_MIPS32_r(subu, 69, 0x55555555, 0x55555555, 0x00000000);
+ DO_MIPS32_r(subu, 70, 0xAAAAAAAA, 0x55555555, 0x55555555);
+ DO_MIPS32_r(subu, 71, 0xFFFFFFFF, 0x55555555, 0xAAAAAAAA);
+ DO_MIPS32_r(subu, 72, 0xAAAAAAAA, 0x00000000, 0xAAAAAAAA);
+ DO_MIPS32_r(subu, 73, 0xAAAAAAAA, 0x55555555, 0x55555555);
+ DO_MIPS32_r(subu, 74, 0xAAAAAAAA, 0xAAAAAAAA, 0x00000000);
+ DO_MIPS32_r(subu, 75, 0xAAAAAAAA, 0xFFFFFFFF, 0xAAAAAAAB);
+ DO_MIPS32_r(subu, 76, 0x7FFFFFFF, 0xFFFFFFFF, 0x80000000);
+ DO_MIPS32_r(subu, 77, 0x7FFFFFFF, 0x80000000, 0xFFFFFFFF);
+ DO_MIPS32_r(subu, 78, 0x80000000, 0x00000001, 0x7FFFFFFF);
+ DO_MIPS32_r(subu, 79, 0x80000000, 0x7FFFFFFF, 0x00000001);
+
+ printf("%s: PASS: %d, FAIL: %d\n", __FILE__, pass_count, fail_count);
+
+ if (fail_count) {
+ ret = -1;
+ }
+
+ return ret;
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 4/6] target/mips: Split Loongson extention translation into standalone file
2022-10-24 15:23 [PATCH 0/6] MIPS decodetree conversion Jiaxun Yang
` (2 preceding siblings ...)
2022-10-24 15:23 ` [PATCH 3/6] tests/tcg/mips: Add mips32 arithmatic instruction test cases Jiaxun Yang
@ 2022-10-24 15:23 ` Jiaxun Yang
2022-10-24 15:23 ` [PATCH 5/6] target/mips: Move all tx79 instructions to decodetree Jiaxun Yang
2022-10-24 15:23 ` [PATCH 6/6] target/mips: Make MXU decoder standalone Jiaxun Yang
5 siblings, 0 replies; 8+ messages in thread
From: Jiaxun Yang @ 2022-10-24 15:23 UTC (permalink / raw)
To: qemu-devel; +Cc: f4bug, richard.henderson, Jiaxun Yang
So we can do decodetree translation for those exts alone.
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
target/mips/tcg/loongson_translate.c | 1290 +++++++++++++++++++++
target/mips/tcg/meson.build | 1 +
target/mips/tcg/translate.c | 1577 ++++----------------------
target/mips/tcg/translate.h | 6 +
4 files changed, 1493 insertions(+), 1381 deletions(-)
create mode 100644 target/mips/tcg/loongson_translate.c
diff --git a/target/mips/tcg/loongson_translate.c b/target/mips/tcg/loongson_translate.c
new file mode 100644
index 0000000000..efeb1d6e28
--- /dev/null
+++ b/target/mips/tcg/loongson_translate.c
@@ -0,0 +1,1290 @@
+/*
+ * Loongson EXT and MMI translation routines.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This code is licensed under the LGPL v2.1 or later.
+ */
+
+#include "qemu/osdep.h"
+#include "tcg/tcg-op.h"
+#include "tcg/tcg-op-gvec.h"
+#include "exec/helper-gen.h"
+#include "translate.h"
+
+enum {
+ OPC_CP2 = (0x12 << 26),
+ OPC_SPECIAL2 = (0x1C << 26),
+ OPC_SPECIAL3 = (0x1F << 26),
+ OPC_LWC2 = (0x32 << 26),
+ OPC_LDC2 = (0x36 << 26),
+ OPC_SWC2 = (0x3A << 26),
+ OPC_SDC2 = (0x3E << 26),
+};
+
+/* Special2 opcodes */
+#define MASK_2F_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
+
+enum {
+ OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
+ OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
+ OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
+ OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
+ OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
+ OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
+ OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
+ OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
+ OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
+ OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
+ OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
+ OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
+};
+
+/* Special3 opcodes */
+#define MASK_2E_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
+enum {
+ /* Loongson 2E */
+ OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
+ OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
+ OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
+ OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
+ OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
+ OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
+ OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
+ OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
+ OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
+ OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
+ OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
+ OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
+};
+
+/* Loongson EXT load/store quad word opcodes */
+#define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
+enum {
+ OPC_GSLQ = 0x0020 | OPC_LWC2,
+ OPC_GSLQC1 = 0x8020 | OPC_LWC2,
+ OPC_GSSHFL = OPC_LWC2,
+ OPC_GSSQ = 0x0020 | OPC_SWC2,
+ OPC_GSSQC1 = 0x8020 | OPC_SWC2,
+ OPC_GSSHFS = OPC_SWC2,
+};
+
+/* Loongson EXT shifted load/store opcodes */
+#define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
+enum {
+ OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
+ OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
+ OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
+ OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
+ OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
+ OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
+ OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
+ OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
+};
+
+/* Loongson EXT LDC2/SDC2 opcodes */
+#define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
+
+enum {
+ OPC_GSLBX = 0x0 | OPC_LDC2,
+ OPC_GSLHX = 0x1 | OPC_LDC2,
+ OPC_GSLWX = 0x2 | OPC_LDC2,
+ OPC_GSLDX = 0x3 | OPC_LDC2,
+ OPC_GSLWXC1 = 0x6 | OPC_LDC2,
+ OPC_GSLDXC1 = 0x7 | OPC_LDC2,
+ OPC_GSSBX = 0x0 | OPC_SDC2,
+ OPC_GSSHX = 0x1 | OPC_SDC2,
+ OPC_GSSWX = 0x2 | OPC_SDC2,
+ OPC_GSSDX = 0x3 | OPC_SDC2,
+ OPC_GSSWXC1 = 0x6 | OPC_SDC2,
+ OPC_GSSDXC1 = 0x7 | OPC_SDC2,
+};
+
+#define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
+
+enum {
+ OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
+ OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
+ OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
+ OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
+ OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
+ OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
+ OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
+ OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
+
+ OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
+ OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
+ OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
+ OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
+ OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
+ OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
+ OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
+ OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
+
+ OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
+ OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
+ OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
+ OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
+ OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
+ OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
+ OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
+ OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
+
+ OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
+ OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
+ OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
+ OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
+ OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
+ OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
+ OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
+ OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
+
+ OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
+ OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
+ OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
+ OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
+ OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
+ OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
+
+ OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
+ OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
+ OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
+ OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
+ OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
+ OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
+
+ OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
+ OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
+ OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
+ OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
+ OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
+ OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
+
+ OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
+ OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
+ OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
+ OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
+ OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
+ OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
+
+ OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
+ OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
+ OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
+ OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
+ OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
+ OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
+
+ OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
+ OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
+ OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
+ OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
+ OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
+ OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
+
+ OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
+ OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
+ OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
+ OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
+ OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
+ OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
+
+ OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
+ OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
+ OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
+ OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
+ OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
+ OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
+};
+
+/* Godson integer instructions */
+static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
+ int rd, int rs, int rt)
+{
+ TCGv t0, t1;
+
+ if (rd == 0) {
+ /* Treat as NOP. */
+ return;
+ }
+
+ switch (opc) {
+ case OPC_MULT_G_2E:
+ case OPC_MULT_G_2F:
+ case OPC_MULTU_G_2E:
+ case OPC_MULTU_G_2F:
+#if defined(TARGET_MIPS64)
+ case OPC_DMULT_G_2E:
+ case OPC_DMULT_G_2F:
+ case OPC_DMULTU_G_2E:
+ case OPC_DMULTU_G_2F:
+#endif
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
+ break;
+ default:
+ t0 = tcg_temp_local_new();
+ t1 = tcg_temp_local_new();
+ break;
+ }
+
+ gen_load_gpr(t0, rs);
+ gen_load_gpr(t1, rt);
+
+ switch (opc) {
+ case OPC_MULT_G_2E:
+ case OPC_MULT_G_2F:
+ tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ break;
+ case OPC_MULTU_G_2E:
+ case OPC_MULTU_G_2F:
+ tcg_gen_ext32u_tl(t0, t0);
+ tcg_gen_ext32u_tl(t1, t1);
+ tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ break;
+ case OPC_DIV_G_2E:
+ case OPC_DIV_G_2F:
+ {
+ TCGLabel *l1 = gen_new_label();
+ TCGLabel *l2 = gen_new_label();
+ TCGLabel *l3 = gen_new_label();
+ tcg_gen_ext32s_tl(t0, t0);
+ tcg_gen_ext32s_tl(t1, t1);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l3);
+ gen_set_label(l1);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
+ tcg_gen_mov_tl(cpu_gpr[rd], t0);
+ tcg_gen_br(l3);
+ gen_set_label(l2);
+ tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ gen_set_label(l3);
+ }
+ break;
+ case OPC_DIVU_G_2E:
+ case OPC_DIVU_G_2F:
+ {
+ TCGLabel *l1 = gen_new_label();
+ TCGLabel *l2 = gen_new_label();
+ tcg_gen_ext32u_tl(t0, t0);
+ tcg_gen_ext32u_tl(t1, t1);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l2);
+ gen_set_label(l1);
+ tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ gen_set_label(l2);
+ }
+ break;
+ case OPC_MOD_G_2E:
+ case OPC_MOD_G_2F:
+ {
+ TCGLabel *l1 = gen_new_label();
+ TCGLabel *l2 = gen_new_label();
+ TCGLabel *l3 = gen_new_label();
+ tcg_gen_ext32u_tl(t0, t0);
+ tcg_gen_ext32u_tl(t1, t1);
+ tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
+ gen_set_label(l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l3);
+ gen_set_label(l2);
+ tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ gen_set_label(l3);
+ }
+ break;
+ case OPC_MODU_G_2E:
+ case OPC_MODU_G_2F:
+ {
+ TCGLabel *l1 = gen_new_label();
+ TCGLabel *l2 = gen_new_label();
+ tcg_gen_ext32u_tl(t0, t0);
+ tcg_gen_ext32u_tl(t1, t1);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l2);
+ gen_set_label(l1);
+ tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
+ tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
+ gen_set_label(l2);
+ }
+ break;
+#if defined(TARGET_MIPS64)
+ case OPC_DMULT_G_2E:
+ case OPC_DMULT_G_2F:
+ tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
+ break;
+ case OPC_DMULTU_G_2E:
+ case OPC_DMULTU_G_2F:
+ tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
+ break;
+ case OPC_DDIV_G_2E:
+ case OPC_DDIV_G_2F:
+ {
+ TCGLabel *l1 = gen_new_label();
+ TCGLabel *l2 = gen_new_label();
+ TCGLabel *l3 = gen_new_label();
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l3);
+ gen_set_label(l1);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
+ tcg_gen_mov_tl(cpu_gpr[rd], t0);
+ tcg_gen_br(l3);
+ gen_set_label(l2);
+ tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
+ gen_set_label(l3);
+ }
+ break;
+ case OPC_DDIVU_G_2E:
+ case OPC_DDIVU_G_2F:
+ {
+ TCGLabel *l1 = gen_new_label();
+ TCGLabel *l2 = gen_new_label();
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l2);
+ gen_set_label(l1);
+ tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
+ gen_set_label(l2);
+ }
+ break;
+ case OPC_DMOD_G_2E:
+ case OPC_DMOD_G_2F:
+ {
+ TCGLabel *l1 = gen_new_label();
+ TCGLabel *l2 = gen_new_label();
+ TCGLabel *l3 = gen_new_label();
+ tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
+ gen_set_label(l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l3);
+ gen_set_label(l2);
+ tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
+ gen_set_label(l3);
+ }
+ break;
+ case OPC_DMODU_G_2E:
+ case OPC_DMODU_G_2F:
+ {
+ TCGLabel *l1 = gen_new_label();
+ TCGLabel *l2 = gen_new_label();
+ tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
+ tcg_gen_movi_tl(cpu_gpr[rd], 0);
+ tcg_gen_br(l2);
+ gen_set_label(l1);
+ tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
+ gen_set_label(l2);
+ }
+ break;
+#endif
+ }
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+}
+
+/* Loongson multimedia instructions */
+static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
+{
+ uint32_t opc, shift_max;
+ TCGv_i64 t0, t1;
+ TCGCond cond;
+
+ opc = MASK_LMMI(ctx->opcode);
+ switch (opc) {
+ case OPC_ADD_CP2:
+ case OPC_SUB_CP2:
+ case OPC_DADD_CP2:
+ case OPC_DSUB_CP2:
+ t0 = tcg_temp_local_new_i64();
+ t1 = tcg_temp_local_new_i64();
+ break;
+ default:
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+ break;
+ }
+
+ check_cp1_enabled(ctx);
+ gen_load_fpr64(ctx, t0, rs);
+ gen_load_fpr64(ctx, t1, rt);
+
+ switch (opc) {
+ case OPC_PADDSH:
+ gen_helper_paddsh(t0, t0, t1);
+ break;
+ case OPC_PADDUSH:
+ gen_helper_paddush(t0, t0, t1);
+ break;
+ case OPC_PADDH:
+ gen_helper_paddh(t0, t0, t1);
+ break;
+ case OPC_PADDW:
+ gen_helper_paddw(t0, t0, t1);
+ break;
+ case OPC_PADDSB:
+ gen_helper_paddsb(t0, t0, t1);
+ break;
+ case OPC_PADDUSB:
+ gen_helper_paddusb(t0, t0, t1);
+ break;
+ case OPC_PADDB:
+ gen_helper_paddb(t0, t0, t1);
+ break;
+
+ case OPC_PSUBSH:
+ gen_helper_psubsh(t0, t0, t1);
+ break;
+ case OPC_PSUBUSH:
+ gen_helper_psubush(t0, t0, t1);
+ break;
+ case OPC_PSUBH:
+ gen_helper_psubh(t0, t0, t1);
+ break;
+ case OPC_PSUBW:
+ gen_helper_psubw(t0, t0, t1);
+ break;
+ case OPC_PSUBSB:
+ gen_helper_psubsb(t0, t0, t1);
+ break;
+ case OPC_PSUBUSB:
+ gen_helper_psubusb(t0, t0, t1);
+ break;
+ case OPC_PSUBB:
+ gen_helper_psubb(t0, t0, t1);
+ break;
+
+ case OPC_PSHUFH:
+ gen_helper_pshufh(t0, t0, t1);
+ break;
+ case OPC_PACKSSWH:
+ gen_helper_packsswh(t0, t0, t1);
+ break;
+ case OPC_PACKSSHB:
+ gen_helper_packsshb(t0, t0, t1);
+ break;
+ case OPC_PACKUSHB:
+ gen_helper_packushb(t0, t0, t1);
+ break;
+
+ case OPC_PUNPCKLHW:
+ gen_helper_punpcklhw(t0, t0, t1);
+ break;
+ case OPC_PUNPCKHHW:
+ gen_helper_punpckhhw(t0, t0, t1);
+ break;
+ case OPC_PUNPCKLBH:
+ gen_helper_punpcklbh(t0, t0, t1);
+ break;
+ case OPC_PUNPCKHBH:
+ gen_helper_punpckhbh(t0, t0, t1);
+ break;
+ case OPC_PUNPCKLWD:
+ gen_helper_punpcklwd(t0, t0, t1);
+ break;
+ case OPC_PUNPCKHWD:
+ gen_helper_punpckhwd(t0, t0, t1);
+ break;
+
+ case OPC_PAVGH:
+ gen_helper_pavgh(t0, t0, t1);
+ break;
+ case OPC_PAVGB:
+ gen_helper_pavgb(t0, t0, t1);
+ break;
+ case OPC_PMAXSH:
+ gen_helper_pmaxsh(t0, t0, t1);
+ break;
+ case OPC_PMINSH:
+ gen_helper_pminsh(t0, t0, t1);
+ break;
+ case OPC_PMAXUB:
+ gen_helper_pmaxub(t0, t0, t1);
+ break;
+ case OPC_PMINUB:
+ gen_helper_pminub(t0, t0, t1);
+ break;
+
+ case OPC_PCMPEQW:
+ gen_helper_pcmpeqw(t0, t0, t1);
+ break;
+ case OPC_PCMPGTW:
+ gen_helper_pcmpgtw(t0, t0, t1);
+ break;
+ case OPC_PCMPEQH:
+ gen_helper_pcmpeqh(t0, t0, t1);
+ break;
+ case OPC_PCMPGTH:
+ gen_helper_pcmpgth(t0, t0, t1);
+ break;
+ case OPC_PCMPEQB:
+ gen_helper_pcmpeqb(t0, t0, t1);
+ break;
+ case OPC_PCMPGTB:
+ gen_helper_pcmpgtb(t0, t0, t1);
+ break;
+
+ case OPC_PSLLW:
+ gen_helper_psllw(t0, t0, t1);
+ break;
+ case OPC_PSLLH:
+ gen_helper_psllh(t0, t0, t1);
+ break;
+ case OPC_PSRLW:
+ gen_helper_psrlw(t0, t0, t1);
+ break;
+ case OPC_PSRLH:
+ gen_helper_psrlh(t0, t0, t1);
+ break;
+ case OPC_PSRAW:
+ gen_helper_psraw(t0, t0, t1);
+ break;
+ case OPC_PSRAH:
+ gen_helper_psrah(t0, t0, t1);
+ break;
+
+ case OPC_PMULLH:
+ gen_helper_pmullh(t0, t0, t1);
+ break;
+ case OPC_PMULHH:
+ gen_helper_pmulhh(t0, t0, t1);
+ break;
+ case OPC_PMULHUH:
+ gen_helper_pmulhuh(t0, t0, t1);
+ break;
+ case OPC_PMADDHW:
+ gen_helper_pmaddhw(t0, t0, t1);
+ break;
+
+ case OPC_PASUBUB:
+ gen_helper_pasubub(t0, t0, t1);
+ break;
+ case OPC_BIADD:
+ gen_helper_biadd(t0, t0);
+ break;
+ case OPC_PMOVMSKB:
+ gen_helper_pmovmskb(t0, t0);
+ break;
+
+ case OPC_PADDD:
+ tcg_gen_add_i64(t0, t0, t1);
+ break;
+ case OPC_PSUBD:
+ tcg_gen_sub_i64(t0, t0, t1);
+ break;
+ case OPC_XOR_CP2:
+ tcg_gen_xor_i64(t0, t0, t1);
+ break;
+ case OPC_NOR_CP2:
+ tcg_gen_nor_i64(t0, t0, t1);
+ break;
+ case OPC_AND_CP2:
+ tcg_gen_and_i64(t0, t0, t1);
+ break;
+ case OPC_OR_CP2:
+ tcg_gen_or_i64(t0, t0, t1);
+ break;
+
+ case OPC_PANDN:
+ tcg_gen_andc_i64(t0, t1, t0);
+ break;
+
+ case OPC_PINSRH_0:
+ tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
+ break;
+ case OPC_PINSRH_1:
+ tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
+ break;
+ case OPC_PINSRH_2:
+ tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
+ break;
+ case OPC_PINSRH_3:
+ tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
+ break;
+
+ case OPC_PEXTRH:
+ tcg_gen_andi_i64(t1, t1, 3);
+ tcg_gen_shli_i64(t1, t1, 4);
+ tcg_gen_shr_i64(t0, t0, t1);
+ tcg_gen_ext16u_i64(t0, t0);
+ break;
+
+ case OPC_ADDU_CP2:
+ tcg_gen_add_i64(t0, t0, t1);
+ tcg_gen_ext32s_i64(t0, t0);
+ break;
+ case OPC_SUBU_CP2:
+ tcg_gen_sub_i64(t0, t0, t1);
+ tcg_gen_ext32s_i64(t0, t0);
+ break;
+
+ case OPC_SLL_CP2:
+ shift_max = 32;
+ goto do_shift;
+ case OPC_SRL_CP2:
+ shift_max = 32;
+ goto do_shift;
+ case OPC_SRA_CP2:
+ shift_max = 32;
+ goto do_shift;
+ case OPC_DSLL_CP2:
+ shift_max = 64;
+ goto do_shift;
+ case OPC_DSRL_CP2:
+ shift_max = 64;
+ goto do_shift;
+ case OPC_DSRA_CP2:
+ shift_max = 64;
+ goto do_shift;
+ do_shift:
+ /* Make sure shift count isn't TCG undefined behaviour. */
+ tcg_gen_andi_i64(t1, t1, shift_max - 1);
+
+ switch (opc) {
+ case OPC_SLL_CP2:
+ case OPC_DSLL_CP2:
+ tcg_gen_shl_i64(t0, t0, t1);
+ break;
+ case OPC_SRA_CP2:
+ case OPC_DSRA_CP2:
+ /*
+ * Since SRA is UndefinedResult without sign-extended inputs,
+ * we can treat SRA and DSRA the same.
+ */
+ tcg_gen_sar_i64(t0, t0, t1);
+ break;
+ case OPC_SRL_CP2:
+ /* We want to shift in zeros for SRL; zero-extend first. */
+ tcg_gen_ext32u_i64(t0, t0);
+ /* FALLTHRU */
+ case OPC_DSRL_CP2:
+ tcg_gen_shr_i64(t0, t0, t1);
+ break;
+ }
+
+ if (shift_max == 32) {
+ tcg_gen_ext32s_i64(t0, t0);
+ }
+
+ /* Shifts larger than MAX produce zero. */
+ tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
+ tcg_gen_neg_i64(t1, t1);
+ tcg_gen_and_i64(t0, t0, t1);
+ break;
+
+ case OPC_ADD_CP2:
+ case OPC_DADD_CP2:
+ {
+ TCGv_i64 t2 = tcg_temp_new_i64();
+ TCGLabel *lab = gen_new_label();
+
+ tcg_gen_mov_i64(t2, t0);
+ tcg_gen_add_i64(t0, t1, t2);
+ if (opc == OPC_ADD_CP2) {
+ tcg_gen_ext32s_i64(t0, t0);
+ }
+ tcg_gen_xor_i64(t1, t1, t2);
+ tcg_gen_xor_i64(t2, t2, t0);
+ tcg_gen_andc_i64(t1, t2, t1);
+ tcg_temp_free_i64(t2);
+ tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
+ generate_exception(ctx, EXCP_OVERFLOW);
+ gen_set_label(lab);
+ break;
+ }
+
+ case OPC_SUB_CP2:
+ case OPC_DSUB_CP2:
+ {
+ TCGv_i64 t2 = tcg_temp_new_i64();
+ TCGLabel *lab = gen_new_label();
+
+ tcg_gen_mov_i64(t2, t0);
+ tcg_gen_sub_i64(t0, t1, t2);
+ if (opc == OPC_SUB_CP2) {
+ tcg_gen_ext32s_i64(t0, t0);
+ }
+ tcg_gen_xor_i64(t1, t1, t2);
+ tcg_gen_xor_i64(t2, t2, t0);
+ tcg_gen_and_i64(t1, t1, t2);
+ tcg_temp_free_i64(t2);
+ tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
+ generate_exception(ctx, EXCP_OVERFLOW);
+ gen_set_label(lab);
+ break;
+ }
+
+ case OPC_PMULUW:
+ tcg_gen_ext32u_i64(t0, t0);
+ tcg_gen_ext32u_i64(t1, t1);
+ tcg_gen_mul_i64(t0, t0, t1);
+ break;
+
+ case OPC_SEQU_CP2:
+ case OPC_SEQ_CP2:
+ cond = TCG_COND_EQ;
+ goto do_cc_cond;
+ break;
+ case OPC_SLTU_CP2:
+ cond = TCG_COND_LTU;
+ goto do_cc_cond;
+ break;
+ case OPC_SLT_CP2:
+ cond = TCG_COND_LT;
+ goto do_cc_cond;
+ break;
+ case OPC_SLEU_CP2:
+ cond = TCG_COND_LEU;
+ goto do_cc_cond;
+ break;
+ case OPC_SLE_CP2:
+ cond = TCG_COND_LE;
+ do_cc_cond:
+ {
+ int cc = (ctx->opcode >> 8) & 0x7;
+ TCGv_i64 t64 = tcg_temp_new_i64();
+ TCGv_i32 t32 = tcg_temp_new_i32();
+
+ tcg_gen_setcond_i64(cond, t64, t0, t1);
+ tcg_gen_extrl_i64_i32(t32, t64);
+ tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
+ get_fp_bit(cc), 1);
+
+ tcg_temp_free_i32(t32);
+ tcg_temp_free_i64(t64);
+ }
+ goto no_rd;
+ break;
+ default:
+ MIPS_INVAL("loongson_cp2");
+ gen_reserved_instruction(ctx);
+ return;
+ }
+
+ gen_store_fpr64(ctx, t0, rd);
+
+no_rd:
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+}
+
+static void gen_loongson_lswc2(DisasContext *ctx, int rt,
+ int rs, int rd)
+{
+ TCGv t0, t1, t2;
+ TCGv_i32 fp0;
+#if defined(TARGET_MIPS64)
+ int lsq_rt1 = ctx->opcode & 0x1f;
+ int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
+#endif
+ int shf_offset = sextract32(ctx->opcode, 6, 8);
+
+ t0 = tcg_temp_new();
+
+ switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
+#if defined(TARGET_MIPS64)
+ case OPC_GSLQ:
+ t1 = tcg_temp_new();
+ gen_base_offset_addr(ctx, t0, rs, lsq_offset);
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ ctx->default_tcg_memop_mask);
+ gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
+ ctx->default_tcg_memop_mask);
+ gen_store_gpr(t1, rt);
+ gen_store_gpr(t0, lsq_rt1);
+ tcg_temp_free(t1);
+ break;
+ case OPC_GSLQC1:
+ check_cp1_enabled(ctx);
+ t1 = tcg_temp_new();
+ gen_base_offset_addr(ctx, t0, rs, lsq_offset);
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ ctx->default_tcg_memop_mask);
+ gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
+ ctx->default_tcg_memop_mask);
+ gen_store_fpr64(ctx, t1, rt);
+ gen_store_fpr64(ctx, t0, lsq_rt1);
+ tcg_temp_free(t1);
+ break;
+ case OPC_GSSQ:
+ t1 = tcg_temp_new();
+ gen_base_offset_addr(ctx, t0, rs, lsq_offset);
+ gen_load_gpr(t1, rt);
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ ctx->default_tcg_memop_mask);
+ gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
+ gen_load_gpr(t1, lsq_rt1);
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ ctx->default_tcg_memop_mask);
+ tcg_temp_free(t1);
+ break;
+ case OPC_GSSQC1:
+ check_cp1_enabled(ctx);
+ t1 = tcg_temp_new();
+ gen_base_offset_addr(ctx, t0, rs, lsq_offset);
+ gen_load_fpr64(ctx, t1, rt);
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ ctx->default_tcg_memop_mask);
+ gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
+ gen_load_fpr64(ctx, t1, lsq_rt1);
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ ctx->default_tcg_memop_mask);
+ tcg_temp_free(t1);
+ break;
+#endif
+ case OPC_GSSHFL:
+ switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
+ case OPC_GSLWLC1:
+ check_cp1_enabled(ctx);
+ gen_base_offset_addr(ctx, t0, rs, shf_offset);
+ t1 = tcg_temp_new();
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+ tcg_gen_andi_tl(t1, t0, 3);
+ if (!cpu_is_bigendian(ctx)) {
+ tcg_gen_xori_tl(t1, t1, 3);
+ }
+ tcg_gen_shli_tl(t1, t1, 3);
+ tcg_gen_andi_tl(t0, t0, ~3);
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
+ tcg_gen_shl_tl(t0, t0, t1);
+ t2 = tcg_const_tl(-1);
+ tcg_gen_shl_tl(t2, t2, t1);
+ fp0 = tcg_temp_new_i32();
+ gen_load_fpr32(ctx, fp0, rt);
+ tcg_gen_ext_i32_tl(t1, fp0);
+ tcg_gen_andc_tl(t1, t1, t2);
+ tcg_temp_free(t2);
+ tcg_gen_or_tl(t0, t0, t1);
+ tcg_temp_free(t1);
+#if defined(TARGET_MIPS64)
+ tcg_gen_extrl_i64_i32(fp0, t0);
+#else
+ tcg_gen_ext32s_tl(fp0, t0);
+#endif
+ gen_store_fpr32(ctx, fp0, rt);
+ tcg_temp_free_i32(fp0);
+ break;
+ case OPC_GSLWRC1:
+ check_cp1_enabled(ctx);
+ gen_base_offset_addr(ctx, t0, rs, shf_offset);
+ t1 = tcg_temp_new();
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+ tcg_gen_andi_tl(t1, t0, 3);
+ if (cpu_is_bigendian(ctx)) {
+ tcg_gen_xori_tl(t1, t1, 3);
+ }
+ tcg_gen_shli_tl(t1, t1, 3);
+ tcg_gen_andi_tl(t0, t0, ~3);
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
+ tcg_gen_shr_tl(t0, t0, t1);
+ tcg_gen_xori_tl(t1, t1, 31);
+ t2 = tcg_const_tl(0xfffffffeull);
+ tcg_gen_shl_tl(t2, t2, t1);
+ fp0 = tcg_temp_new_i32();
+ gen_load_fpr32(ctx, fp0, rt);
+ tcg_gen_ext_i32_tl(t1, fp0);
+ tcg_gen_and_tl(t1, t1, t2);
+ tcg_temp_free(t2);
+ tcg_gen_or_tl(t0, t0, t1);
+ tcg_temp_free(t1);
+#if defined(TARGET_MIPS64)
+ tcg_gen_extrl_i64_i32(fp0, t0);
+#else
+ tcg_gen_ext32s_tl(fp0, t0);
+#endif
+ gen_store_fpr32(ctx, fp0, rt);
+ tcg_temp_free_i32(fp0);
+ break;
+#if defined(TARGET_MIPS64)
+ case OPC_GSLDLC1:
+ check_cp1_enabled(ctx);
+ gen_base_offset_addr(ctx, t0, rs, shf_offset);
+ t1 = tcg_temp_new();
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+ tcg_gen_andi_tl(t1, t0, 7);
+ if (!cpu_is_bigendian(ctx)) {
+ tcg_gen_xori_tl(t1, t1, 7);
+ }
+ tcg_gen_shli_tl(t1, t1, 3);
+ tcg_gen_andi_tl(t0, t0, ~7);
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ);
+ tcg_gen_shl_tl(t0, t0, t1);
+ t2 = tcg_const_tl(-1);
+ tcg_gen_shl_tl(t2, t2, t1);
+ gen_load_fpr64(ctx, t1, rt);
+ tcg_gen_andc_tl(t1, t1, t2);
+ tcg_temp_free(t2);
+ tcg_gen_or_tl(t0, t0, t1);
+ tcg_temp_free(t1);
+ gen_store_fpr64(ctx, t0, rt);
+ break;
+ case OPC_GSLDRC1:
+ check_cp1_enabled(ctx);
+ gen_base_offset_addr(ctx, t0, rs, shf_offset);
+ t1 = tcg_temp_new();
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+ tcg_gen_andi_tl(t1, t0, 7);
+ if (cpu_is_bigendian(ctx)) {
+ tcg_gen_xori_tl(t1, t1, 7);
+ }
+ tcg_gen_shli_tl(t1, t1, 3);
+ tcg_gen_andi_tl(t0, t0, ~7);
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ);
+ tcg_gen_shr_tl(t0, t0, t1);
+ tcg_gen_xori_tl(t1, t1, 63);
+ t2 = tcg_const_tl(0xfffffffffffffffeull);
+ tcg_gen_shl_tl(t2, t2, t1);
+ gen_load_fpr64(ctx, t1, rt);
+ tcg_gen_and_tl(t1, t1, t2);
+ tcg_temp_free(t2);
+ tcg_gen_or_tl(t0, t0, t1);
+ tcg_temp_free(t1);
+ gen_store_fpr64(ctx, t0, rt);
+ break;
+#endif
+ default:
+ MIPS_INVAL("loongson_gsshfl");
+ gen_reserved_instruction(ctx);
+ break;
+ }
+ break;
+ case OPC_GSSHFS:
+ switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
+ case OPC_GSSWLC1:
+ check_cp1_enabled(ctx);
+ t1 = tcg_temp_new();
+ gen_base_offset_addr(ctx, t0, rs, shf_offset);
+ fp0 = tcg_temp_new_i32();
+ gen_load_fpr32(ctx, fp0, rt);
+ tcg_gen_ext_i32_tl(t1, fp0);
+ gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
+ tcg_temp_free_i32(fp0);
+ tcg_temp_free(t1);
+ break;
+ case OPC_GSSWRC1:
+ check_cp1_enabled(ctx);
+ t1 = tcg_temp_new();
+ gen_base_offset_addr(ctx, t0, rs, shf_offset);
+ fp0 = tcg_temp_new_i32();
+ gen_load_fpr32(ctx, fp0, rt);
+ tcg_gen_ext_i32_tl(t1, fp0);
+ gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
+ tcg_temp_free_i32(fp0);
+ tcg_temp_free(t1);
+ break;
+#if defined(TARGET_MIPS64)
+ case OPC_GSSDLC1:
+ check_cp1_enabled(ctx);
+ t1 = tcg_temp_new();
+ gen_base_offset_addr(ctx, t0, rs, shf_offset);
+ gen_load_fpr64(ctx, t1, rt);
+ gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
+ tcg_temp_free(t1);
+ break;
+ case OPC_GSSDRC1:
+ check_cp1_enabled(ctx);
+ t1 = tcg_temp_new();
+ gen_base_offset_addr(ctx, t0, rs, shf_offset);
+ gen_load_fpr64(ctx, t1, rt);
+ gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
+ tcg_temp_free(t1);
+ break;
+#endif
+ default:
+ MIPS_INVAL("loongson_gsshfs");
+ gen_reserved_instruction(ctx);
+ break;
+ }
+ break;
+ default:
+ MIPS_INVAL("loongson_gslsq");
+ gen_reserved_instruction(ctx);
+ break;
+ }
+ tcg_temp_free(t0);
+}
+
+/* Loongson EXT LDC2/SDC2 */
+static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
+ int rs, int rd)
+{
+ int offset = sextract32(ctx->opcode, 3, 8);
+ uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
+ TCGv t0, t1;
+ TCGv_i32 fp0;
+
+ /* Pre-conditions */
+ switch (opc) {
+ case OPC_GSLBX:
+ case OPC_GSLHX:
+ case OPC_GSLWX:
+ case OPC_GSLDX:
+ /* prefetch, implement as NOP */
+ if (rt == 0) {
+ return;
+ }
+ break;
+ case OPC_GSSBX:
+ case OPC_GSSHX:
+ case OPC_GSSWX:
+ case OPC_GSSDX:
+ break;
+ case OPC_GSLWXC1:
+#if defined(TARGET_MIPS64)
+ case OPC_GSLDXC1:
+#endif
+ check_cp1_enabled(ctx);
+ /* prefetch, implement as NOP */
+ if (rt == 0) {
+ return;
+ }
+ break;
+ case OPC_GSSWXC1:
+#if defined(TARGET_MIPS64)
+ case OPC_GSSDXC1:
+#endif
+ check_cp1_enabled(ctx);
+ break;
+ default:
+ MIPS_INVAL("loongson_lsdc2");
+ gen_reserved_instruction(ctx);
+ return;
+ break;
+ }
+
+ t0 = tcg_temp_new();
+
+ gen_base_offset_addr(ctx, t0, rs, offset);
+ gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
+
+ switch (opc) {
+ case OPC_GSLBX:
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
+ gen_store_gpr(t0, rt);
+ break;
+ case OPC_GSLHX:
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
+ ctx->default_tcg_memop_mask);
+ gen_store_gpr(t0, rt);
+ break;
+ case OPC_GSLWX:
+ gen_base_offset_addr(ctx, t0, rs, offset);
+ if (rd) {
+ gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
+ }
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
+ ctx->default_tcg_memop_mask);
+ gen_store_gpr(t0, rt);
+ break;
+#if defined(TARGET_MIPS64)
+ case OPC_GSLDX:
+ gen_base_offset_addr(ctx, t0, rs, offset);
+ if (rd) {
+ gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
+ }
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
+ ctx->default_tcg_memop_mask);
+ gen_store_gpr(t0, rt);
+ break;
+#endif
+ case OPC_GSLWXC1:
+ gen_base_offset_addr(ctx, t0, rs, offset);
+ if (rd) {
+ gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
+ }
+ fp0 = tcg_temp_new_i32();
+ tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
+ ctx->default_tcg_memop_mask);
+ gen_store_fpr32(ctx, fp0, rt);
+ tcg_temp_free_i32(fp0);
+ break;
+#if defined(TARGET_MIPS64)
+ case OPC_GSLDXC1:
+ gen_base_offset_addr(ctx, t0, rs, offset);
+ if (rd) {
+ gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
+ }
+ tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
+ ctx->default_tcg_memop_mask);
+ gen_store_fpr64(ctx, t0, rt);
+ break;
+#endif
+ case OPC_GSSBX:
+ t1 = tcg_temp_new();
+ gen_load_gpr(t1, rt);
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
+ tcg_temp_free(t1);
+ break;
+ case OPC_GSSHX:
+ t1 = tcg_temp_new();
+ gen_load_gpr(t1, rt);
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
+ ctx->default_tcg_memop_mask);
+ tcg_temp_free(t1);
+ break;
+ case OPC_GSSWX:
+ t1 = tcg_temp_new();
+ gen_load_gpr(t1, rt);
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
+ ctx->default_tcg_memop_mask);
+ tcg_temp_free(t1);
+ break;
+#if defined(TARGET_MIPS64)
+ case OPC_GSSDX:
+ t1 = tcg_temp_new();
+ gen_load_gpr(t1, rt);
+ tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
+ ctx->default_tcg_memop_mask);
+ tcg_temp_free(t1);
+ break;
+#endif
+ case OPC_GSSWXC1:
+ fp0 = tcg_temp_new_i32();
+ gen_load_fpr32(ctx, fp0, rt);
+ tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
+ ctx->default_tcg_memop_mask);
+ tcg_temp_free_i32(fp0);
+ break;
+#if defined(TARGET_MIPS64)
+ case OPC_GSSDXC1:
+ t1 = tcg_temp_new();
+ gen_load_fpr64(ctx, t1, rt);
+ tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEUQ |
+ ctx->default_tcg_memop_mask);
+ tcg_temp_free(t1);
+ break;
+#endif
+ default:
+ break;
+ }
+
+ tcg_temp_free(t0);
+}
+
+bool decode_ext_loongson2e(DisasContext *ctx, uint32_t insn)
+{
+ int rs, rt, rd;
+ uint32_t op;
+
+ op = MASK_2E_SPECIAL3(insn);
+ rs = (insn >> 21) & 0x1f;
+ rt = (insn >> 16) & 0x1f;
+ rd = (insn >> 11) & 0x1f;
+
+ switch (op) {
+ case OPC_DIV_G_2E:
+ case OPC_DIVU_G_2E:
+ case OPC_MOD_G_2E:
+ case OPC_MODU_G_2E:
+ case OPC_MULT_G_2E:
+ case OPC_MULTU_G_2E:
+ gen_loongson_integer(ctx, op, rd, rs, rt);
+ return true;
+#if defined(TARGET_MIPS64)
+ case OPC_DDIV_G_2E:
+ case OPC_DDIVU_G_2E:
+ case OPC_DMULT_G_2E:
+ case OPC_DMULTU_G_2E:
+ case OPC_DMOD_G_2E:
+ case OPC_DMODU_G_2E:
+ gen_loongson_integer(ctx, op, rd, rs, rt);
+ return true;
+#endif
+ default:
+ return false;
+ }
+}
+
+bool decode_ext_loongson2f(DisasContext *ctx, uint32_t insn)
+{
+ int rs, rt, rd;
+ uint32_t op;
+
+ op = MASK_2F_SPECIAL2(insn);
+ rs = (insn >> 21) & 0x1f;
+ rt = (insn >> 16) & 0x1f;
+ rd = (insn >> 11) & 0x1f;
+
+ switch (op) {
+ case OPC_DIV_G_2F:
+ case OPC_DIVU_G_2F:
+ case OPC_MULT_G_2F:
+ case OPC_MULTU_G_2F:
+ case OPC_MOD_G_2F:
+ case OPC_MODU_G_2F:
+ gen_loongson_integer(ctx, op, rd, rs, rt);
+ return true;
+#if defined(TARGET_MIPS64)
+ case OPC_DMULT_G_2F:
+ case OPC_DMULTU_G_2F:
+ case OPC_DDIV_G_2F:
+ case OPC_DDIVU_G_2F:
+ case OPC_DMOD_G_2F:
+ case OPC_DMODU_G_2F:
+ gen_loongson_integer(ctx, op, rd, rs, rt);
+ return true;
+#endif
+ default:
+ return false;
+ }
+}
+
+bool decode_ase_lext(DisasContext *ctx, uint32_t insn)
+{
+ int rs, rt, rd;
+ uint32_t op;
+
+ op = MASK_OP_MAJOR(insn);
+ rs = (insn >> 21) & 0x1f;
+ rt = (insn >> 16) & 0x1f;
+ rd = (insn >> 11) & 0x1f;
+
+ switch (op) {
+ case OPC_SPECIAL2:
+ /* LEXT inherits Loongson2F integer extensions */
+ return decode_ext_loongson2f(ctx, insn);
+ case OPC_LWC2:
+ case OPC_SWC2:
+ gen_loongson_lswc2(ctx, rt, rs, rd);
+ return true;
+ case OPC_LDC2:
+ case OPC_SDC2:
+ gen_loongson_lsdc2(ctx, rt, rs, rd);
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool decode_ase_lmmi(DisasContext *ctx, uint32_t insn)
+{
+ int sa, rt, rd;
+ uint32_t op;
+
+ op = MASK_OP_MAJOR(insn);
+ rt = (insn >> 16) & 0x1f;
+ rd = (insn >> 11) & 0x1f;
+ sa = (insn >> 6) & 0x1f;
+
+ switch (op) {
+ case OPC_CP2:
+ gen_loongson_multimedia(ctx, sa, rd, rt);
+ return true;
+ default:
+ return false;
+ }
+}
diff --git a/target/mips/tcg/meson.build b/target/mips/tcg/meson.build
index 7a27fe93e0..a615cd81b6 100644
--- a/target/mips/tcg/meson.build
+++ b/target/mips/tcg/meson.build
@@ -14,6 +14,7 @@ mips_ss.add(files(
'fpu_helper.c',
'ldst_helper.c',
'lmmi_helper.c',
+ 'loongson_translate.c',
'msa_helper.c',
'msa_translate.c',
'op_helper.c',
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index bcb267e6bd..d398b2f44d 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -332,19 +332,6 @@ enum {
OPC_MUL = 0x02 | OPC_SPECIAL2,
OPC_MSUB = 0x04 | OPC_SPECIAL2,
OPC_MSUBU = 0x05 | OPC_SPECIAL2,
- /* Loongson 2F */
- OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
- OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
- OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
- OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
- OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
- OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
- OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
- OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
- OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
- OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
- OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
- OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
/* Misc */
OPC_CLZ = 0x20 | OPC_SPECIAL2,
OPC_CLO = 0x21 | OPC_SPECIAL2,
@@ -373,20 +360,6 @@ enum {
OPC_RDHWR = 0x3B | OPC_SPECIAL3,
OPC_GINV = 0x3D | OPC_SPECIAL3,
- /* Loongson 2E */
- OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
- OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
- OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
- OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
- OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
- OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
- OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
- OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
- OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
- OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
- OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
- OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
-
/* MIPS DSP Load */
OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
/* MIPS DSP Arithmetic */
@@ -394,8 +367,7 @@ enum {
OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
- /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
- /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
+ OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3,
OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
/* MIPS DSP GPR-Based Shift Sub-class */
@@ -443,48 +415,6 @@ enum {
R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
};
-/* Loongson EXT load/store quad word opcodes */
-#define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
-enum {
- OPC_GSLQ = 0x0020 | OPC_LWC2,
- OPC_GSLQC1 = 0x8020 | OPC_LWC2,
- OPC_GSSHFL = OPC_LWC2,
- OPC_GSSQ = 0x0020 | OPC_SWC2,
- OPC_GSSQC1 = 0x8020 | OPC_SWC2,
- OPC_GSSHFS = OPC_SWC2,
-};
-
-/* Loongson EXT shifted load/store opcodes */
-#define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
-enum {
- OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
- OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
- OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
- OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
- OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
- OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
- OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
- OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
-};
-
-/* Loongson EXT LDC2/SDC2 opcodes */
-#define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
-
-enum {
- OPC_GSLBX = 0x0 | OPC_LDC2,
- OPC_GSLHX = 0x1 | OPC_LDC2,
- OPC_GSLWX = 0x2 | OPC_LDC2,
- OPC_GSLDX = 0x3 | OPC_LDC2,
- OPC_GSLWXC1 = 0x6 | OPC_LDC2,
- OPC_GSLDXC1 = 0x7 | OPC_LDC2,
- OPC_GSSBX = 0x0 | OPC_SDC2,
- OPC_GSSHX = 0x1 | OPC_SDC2,
- OPC_GSSWX = 0x2 | OPC_SDC2,
- OPC_GSSDX = 0x3 | OPC_SDC2,
- OPC_GSSWXC1 = 0x6 | OPC_SDC2,
- OPC_GSSDXC1 = 0x7 | OPC_SDC2,
-};
-
/* BSHFL opcodes */
#define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
@@ -561,7 +491,6 @@ enum {
OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
};
-#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
#define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP Arithmetic Sub-class */
@@ -1002,103 +931,6 @@ enum {
OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
};
-#define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
-
-enum {
- OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
- OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
- OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
- OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
- OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
- OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
- OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
- OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
-
- OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
- OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
- OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
- OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
- OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
- OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
- OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
- OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
-
- OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
- OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
- OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
- OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
- OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
- OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
- OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
- OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
-
- OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
- OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
- OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
- OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
- OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
- OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
- OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
- OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
-
- OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
- OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
- OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
- OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
- OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
- OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
-
- OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
- OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
- OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
- OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
- OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
- OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
-
- OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
- OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
- OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
- OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
- OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
- OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
-
- OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
- OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
- OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
- OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
- OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
- OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
-
- OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
- OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
- OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
- OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
- OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
- OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
-
- OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
- OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
- OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
- OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
- OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
- OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
-
- OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
- OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
- OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
- OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
- OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
- OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
-
- OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
- OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
- OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
- OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
- OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
- OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
-};
-
-
#define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
enum {
@@ -3684,1163 +3516,184 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc,
gen_reserved_instruction(ctx);
goto out;
}
- out:
- tcg_temp_free(t0);
- tcg_temp_free(t1);
-}
-
-/*
- * These MULT[U] and MADD[U] instructions implemented in for example
- * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
- * architectures are special three-operand variants with the syntax
- *
- * MULT[U][1] rd, rs, rt
- *
- * such that
- *
- * (rd, LO, HI) <- rs * rt
- *
- * and
- *
- * MADD[U][1] rd, rs, rt
- *
- * such that
- *
- * (rd, LO, HI) <- (LO, HI) + rs * rt
- *
- * where the low-order 32-bits of the result is placed into both the
- * GPR rd and the special register LO. The high-order 32-bits of the
- * result is placed into the special register HI.
- *
- * If the GPR rd is omitted in assembly language, it is taken to be 0,
- * which is the zero register that always reads as 0.
- */
-static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
- int rd, int rs, int rt)
-{
- TCGv t0 = tcg_temp_new();
- TCGv t1 = tcg_temp_new();
- int acc = 0;
-
- gen_load_gpr(t0, rs);
- gen_load_gpr(t1, rt);
-
- switch (opc) {
- case MMI_OPC_MULT1:
- acc = 1;
- /* Fall through */
- case OPC_MULT:
- {
- TCGv_i32 t2 = tcg_temp_new_i32();
- TCGv_i32 t3 = tcg_temp_new_i32();
- tcg_gen_trunc_tl_i32(t2, t0);
- tcg_gen_trunc_tl_i32(t3, t1);
- tcg_gen_muls2_i32(t2, t3, t2, t3);
- if (rd) {
- tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
- }
- tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
- tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
- tcg_temp_free_i32(t2);
- tcg_temp_free_i32(t3);
- }
- break;
- case MMI_OPC_MULTU1:
- acc = 1;
- /* Fall through */
- case OPC_MULTU:
- {
- TCGv_i32 t2 = tcg_temp_new_i32();
- TCGv_i32 t3 = tcg_temp_new_i32();
- tcg_gen_trunc_tl_i32(t2, t0);
- tcg_gen_trunc_tl_i32(t3, t1);
- tcg_gen_mulu2_i32(t2, t3, t2, t3);
- if (rd) {
- tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
- }
- tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
- tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
- tcg_temp_free_i32(t2);
- tcg_temp_free_i32(t3);
- }
- break;
- case MMI_OPC_MADD1:
- acc = 1;
- /* Fall through */
- case MMI_OPC_MADD:
- {
- TCGv_i64 t2 = tcg_temp_new_i64();
- TCGv_i64 t3 = tcg_temp_new_i64();
-
- tcg_gen_ext_tl_i64(t2, t0);
- tcg_gen_ext_tl_i64(t3, t1);
- tcg_gen_mul_i64(t2, t2, t3);
- tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
- tcg_gen_add_i64(t2, t2, t3);
- tcg_temp_free_i64(t3);
- gen_move_low32(cpu_LO[acc], t2);
- gen_move_high32(cpu_HI[acc], t2);
- if (rd) {
- gen_move_low32(cpu_gpr[rd], t2);
- }
- tcg_temp_free_i64(t2);
- }
- break;
- case MMI_OPC_MADDU1:
- acc = 1;
- /* Fall through */
- case MMI_OPC_MADDU:
- {
- TCGv_i64 t2 = tcg_temp_new_i64();
- TCGv_i64 t3 = tcg_temp_new_i64();
-
- tcg_gen_ext32u_tl(t0, t0);
- tcg_gen_ext32u_tl(t1, t1);
- tcg_gen_extu_tl_i64(t2, t0);
- tcg_gen_extu_tl_i64(t3, t1);
- tcg_gen_mul_i64(t2, t2, t3);
- tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
- tcg_gen_add_i64(t2, t2, t3);
- tcg_temp_free_i64(t3);
- gen_move_low32(cpu_LO[acc], t2);
- gen_move_high32(cpu_HI[acc], t2);
- if (rd) {
- gen_move_low32(cpu_gpr[rd], t2);
- }
- tcg_temp_free_i64(t2);
- }
- break;
- default:
- MIPS_INVAL("mul/madd TXx9");
- gen_reserved_instruction(ctx);
- goto out;
- }
-
- out:
- tcg_temp_free(t0);
- tcg_temp_free(t1);
-}
-
-static void gen_cl(DisasContext *ctx, uint32_t opc,
- int rd, int rs)
-{
- TCGv t0;
-
- if (rd == 0) {
- /* Treat as NOP. */
- return;
- }
- t0 = cpu_gpr[rd];
- gen_load_gpr(t0, rs);
-
- switch (opc) {
- case OPC_CLO:
- case R6_OPC_CLO:
-#if defined(TARGET_MIPS64)
- case OPC_DCLO:
- case R6_OPC_DCLO:
-#endif
- tcg_gen_not_tl(t0, t0);
- break;
- }
-
- switch (opc) {
- case OPC_CLO:
- case R6_OPC_CLO:
- case OPC_CLZ:
- case R6_OPC_CLZ:
- tcg_gen_ext32u_tl(t0, t0);
- tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
- tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
- break;
-#if defined(TARGET_MIPS64)
- case OPC_DCLO:
- case R6_OPC_DCLO:
- case OPC_DCLZ:
- case R6_OPC_DCLZ:
- tcg_gen_clzi_i64(t0, t0, 64);
- break;
-#endif
- }
-}
-
-/* Godson integer instructions */
-static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
- int rd, int rs, int rt)
-{
- TCGv t0, t1;
-
- if (rd == 0) {
- /* Treat as NOP. */
- return;
- }
-
- switch (opc) {
- case OPC_MULT_G_2E:
- case OPC_MULT_G_2F:
- case OPC_MULTU_G_2E:
- case OPC_MULTU_G_2F:
-#if defined(TARGET_MIPS64)
- case OPC_DMULT_G_2E:
- case OPC_DMULT_G_2F:
- case OPC_DMULTU_G_2E:
- case OPC_DMULTU_G_2F:
-#endif
- t0 = tcg_temp_new();
- t1 = tcg_temp_new();
- break;
- default:
- t0 = tcg_temp_local_new();
- t1 = tcg_temp_local_new();
- break;
- }
-
- gen_load_gpr(t0, rs);
- gen_load_gpr(t1, rt);
-
- switch (opc) {
- case OPC_MULT_G_2E:
- case OPC_MULT_G_2F:
- tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
- tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
- break;
- case OPC_MULTU_G_2E:
- case OPC_MULTU_G_2F:
- tcg_gen_ext32u_tl(t0, t0);
- tcg_gen_ext32u_tl(t1, t1);
- tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
- tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
- break;
- case OPC_DIV_G_2E:
- case OPC_DIV_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- TCGLabel *l3 = gen_new_label();
- tcg_gen_ext32s_tl(t0, t0);
- tcg_gen_ext32s_tl(t1, t1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l3);
- gen_set_label(l1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
- tcg_gen_mov_tl(cpu_gpr[rd], t0);
- tcg_gen_br(l3);
- gen_set_label(l2);
- tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
- tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
- gen_set_label(l3);
- }
- break;
- case OPC_DIVU_G_2E:
- case OPC_DIVU_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- tcg_gen_ext32u_tl(t0, t0);
- tcg_gen_ext32u_tl(t1, t1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
- tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
- gen_set_label(l2);
- }
- break;
- case OPC_MOD_G_2E:
- case OPC_MOD_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- TCGLabel *l3 = gen_new_label();
- tcg_gen_ext32u_tl(t0, t0);
- tcg_gen_ext32u_tl(t1, t1);
- tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
- gen_set_label(l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l3);
- gen_set_label(l2);
- tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
- tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
- gen_set_label(l3);
- }
- break;
- case OPC_MODU_G_2E:
- case OPC_MODU_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- tcg_gen_ext32u_tl(t0, t0);
- tcg_gen_ext32u_tl(t1, t1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
- tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
- gen_set_label(l2);
- }
- break;
-#if defined(TARGET_MIPS64)
- case OPC_DMULT_G_2E:
- case OPC_DMULT_G_2F:
- tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
- break;
- case OPC_DMULTU_G_2E:
- case OPC_DMULTU_G_2F:
- tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
- break;
- case OPC_DDIV_G_2E:
- case OPC_DDIV_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- TCGLabel *l3 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l3);
- gen_set_label(l1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
- tcg_gen_mov_tl(cpu_gpr[rd], t0);
- tcg_gen_br(l3);
- gen_set_label(l2);
- tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
- gen_set_label(l3);
- }
- break;
- case OPC_DDIVU_G_2E:
- case OPC_DDIVU_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
- gen_set_label(l2);
- }
- break;
- case OPC_DMOD_G_2E:
- case OPC_DMOD_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- TCGLabel *l3 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
- tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
- gen_set_label(l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l3);
- gen_set_label(l2);
- tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
- gen_set_label(l3);
- }
- break;
- case OPC_DMODU_G_2E:
- case OPC_DMODU_G_2F:
- {
- TCGLabel *l1 = gen_new_label();
- TCGLabel *l2 = gen_new_label();
- tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- tcg_gen_br(l2);
- gen_set_label(l1);
- tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
- gen_set_label(l2);
- }
- break;
-#endif
- }
-
- tcg_temp_free(t0);
- tcg_temp_free(t1);
-}
-
-/* Loongson multimedia instructions */
-static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
-{
- uint32_t opc, shift_max;
- TCGv_i64 t0, t1;
- TCGCond cond;
-
- opc = MASK_LMMI(ctx->opcode);
- switch (opc) {
- case OPC_ADD_CP2:
- case OPC_SUB_CP2:
- case OPC_DADD_CP2:
- case OPC_DSUB_CP2:
- t0 = tcg_temp_local_new_i64();
- t1 = tcg_temp_local_new_i64();
- break;
- default:
- t0 = tcg_temp_new_i64();
- t1 = tcg_temp_new_i64();
- break;
- }
-
- check_cp1_enabled(ctx);
- gen_load_fpr64(ctx, t0, rs);
- gen_load_fpr64(ctx, t1, rt);
-
- switch (opc) {
- case OPC_PADDSH:
- gen_helper_paddsh(t0, t0, t1);
- break;
- case OPC_PADDUSH:
- gen_helper_paddush(t0, t0, t1);
- break;
- case OPC_PADDH:
- gen_helper_paddh(t0, t0, t1);
- break;
- case OPC_PADDW:
- gen_helper_paddw(t0, t0, t1);
- break;
- case OPC_PADDSB:
- gen_helper_paddsb(t0, t0, t1);
- break;
- case OPC_PADDUSB:
- gen_helper_paddusb(t0, t0, t1);
- break;
- case OPC_PADDB:
- gen_helper_paddb(t0, t0, t1);
- break;
-
- case OPC_PSUBSH:
- gen_helper_psubsh(t0, t0, t1);
- break;
- case OPC_PSUBUSH:
- gen_helper_psubush(t0, t0, t1);
- break;
- case OPC_PSUBH:
- gen_helper_psubh(t0, t0, t1);
- break;
- case OPC_PSUBW:
- gen_helper_psubw(t0, t0, t1);
- break;
- case OPC_PSUBSB:
- gen_helper_psubsb(t0, t0, t1);
- break;
- case OPC_PSUBUSB:
- gen_helper_psubusb(t0, t0, t1);
- break;
- case OPC_PSUBB:
- gen_helper_psubb(t0, t0, t1);
- break;
-
- case OPC_PSHUFH:
- gen_helper_pshufh(t0, t0, t1);
- break;
- case OPC_PACKSSWH:
- gen_helper_packsswh(t0, t0, t1);
- break;
- case OPC_PACKSSHB:
- gen_helper_packsshb(t0, t0, t1);
- break;
- case OPC_PACKUSHB:
- gen_helper_packushb(t0, t0, t1);
- break;
-
- case OPC_PUNPCKLHW:
- gen_helper_punpcklhw(t0, t0, t1);
- break;
- case OPC_PUNPCKHHW:
- gen_helper_punpckhhw(t0, t0, t1);
- break;
- case OPC_PUNPCKLBH:
- gen_helper_punpcklbh(t0, t0, t1);
- break;
- case OPC_PUNPCKHBH:
- gen_helper_punpckhbh(t0, t0, t1);
- break;
- case OPC_PUNPCKLWD:
- gen_helper_punpcklwd(t0, t0, t1);
- break;
- case OPC_PUNPCKHWD:
- gen_helper_punpckhwd(t0, t0, t1);
- break;
-
- case OPC_PAVGH:
- gen_helper_pavgh(t0, t0, t1);
- break;
- case OPC_PAVGB:
- gen_helper_pavgb(t0, t0, t1);
- break;
- case OPC_PMAXSH:
- gen_helper_pmaxsh(t0, t0, t1);
- break;
- case OPC_PMINSH:
- gen_helper_pminsh(t0, t0, t1);
- break;
- case OPC_PMAXUB:
- gen_helper_pmaxub(t0, t0, t1);
- break;
- case OPC_PMINUB:
- gen_helper_pminub(t0, t0, t1);
- break;
-
- case OPC_PCMPEQW:
- gen_helper_pcmpeqw(t0, t0, t1);
- break;
- case OPC_PCMPGTW:
- gen_helper_pcmpgtw(t0, t0, t1);
- break;
- case OPC_PCMPEQH:
- gen_helper_pcmpeqh(t0, t0, t1);
- break;
- case OPC_PCMPGTH:
- gen_helper_pcmpgth(t0, t0, t1);
- break;
- case OPC_PCMPEQB:
- gen_helper_pcmpeqb(t0, t0, t1);
- break;
- case OPC_PCMPGTB:
- gen_helper_pcmpgtb(t0, t0, t1);
- break;
-
- case OPC_PSLLW:
- gen_helper_psllw(t0, t0, t1);
- break;
- case OPC_PSLLH:
- gen_helper_psllh(t0, t0, t1);
- break;
- case OPC_PSRLW:
- gen_helper_psrlw(t0, t0, t1);
- break;
- case OPC_PSRLH:
- gen_helper_psrlh(t0, t0, t1);
- break;
- case OPC_PSRAW:
- gen_helper_psraw(t0, t0, t1);
- break;
- case OPC_PSRAH:
- gen_helper_psrah(t0, t0, t1);
- break;
-
- case OPC_PMULLH:
- gen_helper_pmullh(t0, t0, t1);
- break;
- case OPC_PMULHH:
- gen_helper_pmulhh(t0, t0, t1);
- break;
- case OPC_PMULHUH:
- gen_helper_pmulhuh(t0, t0, t1);
- break;
- case OPC_PMADDHW:
- gen_helper_pmaddhw(t0, t0, t1);
- break;
-
- case OPC_PASUBUB:
- gen_helper_pasubub(t0, t0, t1);
- break;
- case OPC_BIADD:
- gen_helper_biadd(t0, t0);
- break;
- case OPC_PMOVMSKB:
- gen_helper_pmovmskb(t0, t0);
- break;
-
- case OPC_PADDD:
- tcg_gen_add_i64(t0, t0, t1);
- break;
- case OPC_PSUBD:
- tcg_gen_sub_i64(t0, t0, t1);
- break;
- case OPC_XOR_CP2:
- tcg_gen_xor_i64(t0, t0, t1);
- break;
- case OPC_NOR_CP2:
- tcg_gen_nor_i64(t0, t0, t1);
- break;
- case OPC_AND_CP2:
- tcg_gen_and_i64(t0, t0, t1);
- break;
- case OPC_OR_CP2:
- tcg_gen_or_i64(t0, t0, t1);
- break;
-
- case OPC_PANDN:
- tcg_gen_andc_i64(t0, t1, t0);
- break;
-
- case OPC_PINSRH_0:
- tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
- break;
- case OPC_PINSRH_1:
- tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
- break;
- case OPC_PINSRH_2:
- tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
- break;
- case OPC_PINSRH_3:
- tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
- break;
-
- case OPC_PEXTRH:
- tcg_gen_andi_i64(t1, t1, 3);
- tcg_gen_shli_i64(t1, t1, 4);
- tcg_gen_shr_i64(t0, t0, t1);
- tcg_gen_ext16u_i64(t0, t0);
- break;
-
- case OPC_ADDU_CP2:
- tcg_gen_add_i64(t0, t0, t1);
- tcg_gen_ext32s_i64(t0, t0);
- break;
- case OPC_SUBU_CP2:
- tcg_gen_sub_i64(t0, t0, t1);
- tcg_gen_ext32s_i64(t0, t0);
- break;
-
- case OPC_SLL_CP2:
- shift_max = 32;
- goto do_shift;
- case OPC_SRL_CP2:
- shift_max = 32;
- goto do_shift;
- case OPC_SRA_CP2:
- shift_max = 32;
- goto do_shift;
- case OPC_DSLL_CP2:
- shift_max = 64;
- goto do_shift;
- case OPC_DSRL_CP2:
- shift_max = 64;
- goto do_shift;
- case OPC_DSRA_CP2:
- shift_max = 64;
- goto do_shift;
- do_shift:
- /* Make sure shift count isn't TCG undefined behaviour. */
- tcg_gen_andi_i64(t1, t1, shift_max - 1);
-
- switch (opc) {
- case OPC_SLL_CP2:
- case OPC_DSLL_CP2:
- tcg_gen_shl_i64(t0, t0, t1);
- break;
- case OPC_SRA_CP2:
- case OPC_DSRA_CP2:
- /*
- * Since SRA is UndefinedResult without sign-extended inputs,
- * we can treat SRA and DSRA the same.
- */
- tcg_gen_sar_i64(t0, t0, t1);
- break;
- case OPC_SRL_CP2:
- /* We want to shift in zeros for SRL; zero-extend first. */
- tcg_gen_ext32u_i64(t0, t0);
- /* FALLTHRU */
- case OPC_DSRL_CP2:
- tcg_gen_shr_i64(t0, t0, t1);
- break;
- }
-
- if (shift_max == 32) {
- tcg_gen_ext32s_i64(t0, t0);
- }
-
- /* Shifts larger than MAX produce zero. */
- tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
- tcg_gen_neg_i64(t1, t1);
- tcg_gen_and_i64(t0, t0, t1);
- break;
-
- case OPC_ADD_CP2:
- case OPC_DADD_CP2:
- {
- TCGv_i64 t2 = tcg_temp_new_i64();
- TCGLabel *lab = gen_new_label();
-
- tcg_gen_mov_i64(t2, t0);
- tcg_gen_add_i64(t0, t1, t2);
- if (opc == OPC_ADD_CP2) {
- tcg_gen_ext32s_i64(t0, t0);
- }
- tcg_gen_xor_i64(t1, t1, t2);
- tcg_gen_xor_i64(t2, t2, t0);
- tcg_gen_andc_i64(t1, t2, t1);
- tcg_temp_free_i64(t2);
- tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
- generate_exception(ctx, EXCP_OVERFLOW);
- gen_set_label(lab);
- break;
- }
-
- case OPC_SUB_CP2:
- case OPC_DSUB_CP2:
- {
- TCGv_i64 t2 = tcg_temp_new_i64();
- TCGLabel *lab = gen_new_label();
-
- tcg_gen_mov_i64(t2, t0);
- tcg_gen_sub_i64(t0, t1, t2);
- if (opc == OPC_SUB_CP2) {
- tcg_gen_ext32s_i64(t0, t0);
- }
- tcg_gen_xor_i64(t1, t1, t2);
- tcg_gen_xor_i64(t2, t2, t0);
- tcg_gen_and_i64(t1, t1, t2);
- tcg_temp_free_i64(t2);
- tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
- generate_exception(ctx, EXCP_OVERFLOW);
- gen_set_label(lab);
- break;
- }
-
- case OPC_PMULUW:
- tcg_gen_ext32u_i64(t0, t0);
- tcg_gen_ext32u_i64(t1, t1);
- tcg_gen_mul_i64(t0, t0, t1);
- break;
-
- case OPC_SEQU_CP2:
- case OPC_SEQ_CP2:
- cond = TCG_COND_EQ;
- goto do_cc_cond;
- break;
- case OPC_SLTU_CP2:
- cond = TCG_COND_LTU;
- goto do_cc_cond;
- break;
- case OPC_SLT_CP2:
- cond = TCG_COND_LT;
- goto do_cc_cond;
- break;
- case OPC_SLEU_CP2:
- cond = TCG_COND_LEU;
- goto do_cc_cond;
- break;
- case OPC_SLE_CP2:
- cond = TCG_COND_LE;
- do_cc_cond:
- {
- int cc = (ctx->opcode >> 8) & 0x7;
- TCGv_i64 t64 = tcg_temp_new_i64();
- TCGv_i32 t32 = tcg_temp_new_i32();
-
- tcg_gen_setcond_i64(cond, t64, t0, t1);
- tcg_gen_extrl_i64_i32(t32, t64);
- tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
- get_fp_bit(cc), 1);
-
- tcg_temp_free_i32(t32);
- tcg_temp_free_i64(t64);
- }
- goto no_rd;
- break;
- default:
- MIPS_INVAL("loongson_cp2");
- gen_reserved_instruction(ctx);
- return;
- }
-
- gen_store_fpr64(ctx, t0, rd);
-
-no_rd:
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
-}
-
-static void gen_loongson_lswc2(DisasContext *ctx, int rt,
- int rs, int rd)
-{
- TCGv t0, t1, t2;
- TCGv_i32 fp0;
-#if defined(TARGET_MIPS64)
- int lsq_rt1 = ctx->opcode & 0x1f;
- int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
-#endif
- int shf_offset = sextract32(ctx->opcode, 6, 8);
-
- t0 = tcg_temp_new();
-
- switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
-#if defined(TARGET_MIPS64)
- case OPC_GSLQ:
- t1 = tcg_temp_new();
- gen_base_offset_addr(ctx, t0, rs, lsq_offset);
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
- ctx->default_tcg_memop_mask);
- gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
- ctx->default_tcg_memop_mask);
- gen_store_gpr(t1, rt);
- gen_store_gpr(t0, lsq_rt1);
- tcg_temp_free(t1);
- break;
- case OPC_GSLQC1:
- check_cp1_enabled(ctx);
- t1 = tcg_temp_new();
- gen_base_offset_addr(ctx, t0, rs, lsq_offset);
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
- ctx->default_tcg_memop_mask);
- gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
- ctx->default_tcg_memop_mask);
- gen_store_fpr64(ctx, t1, rt);
- gen_store_fpr64(ctx, t0, lsq_rt1);
- tcg_temp_free(t1);
- break;
- case OPC_GSSQ:
- t1 = tcg_temp_new();
- gen_base_offset_addr(ctx, t0, rs, lsq_offset);
- gen_load_gpr(t1, rt);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
- ctx->default_tcg_memop_mask);
- gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
- gen_load_gpr(t1, lsq_rt1);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
- ctx->default_tcg_memop_mask);
- tcg_temp_free(t1);
- break;
- case OPC_GSSQC1:
- check_cp1_enabled(ctx);
- t1 = tcg_temp_new();
- gen_base_offset_addr(ctx, t0, rs, lsq_offset);
- gen_load_fpr64(ctx, t1, rt);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
- ctx->default_tcg_memop_mask);
- gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
- gen_load_fpr64(ctx, t1, lsq_rt1);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
- ctx->default_tcg_memop_mask);
- tcg_temp_free(t1);
- break;
-#endif
- case OPC_GSSHFL:
- switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
- case OPC_GSLWLC1:
- check_cp1_enabled(ctx);
- gen_base_offset_addr(ctx, t0, rs, shf_offset);
- t1 = tcg_temp_new();
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
- tcg_gen_andi_tl(t1, t0, 3);
- if (!cpu_is_bigendian(ctx)) {
- tcg_gen_xori_tl(t1, t1, 3);
- }
- tcg_gen_shli_tl(t1, t1, 3);
- tcg_gen_andi_tl(t0, t0, ~3);
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
- tcg_gen_shl_tl(t0, t0, t1);
- t2 = tcg_const_tl(-1);
- tcg_gen_shl_tl(t2, t2, t1);
- fp0 = tcg_temp_new_i32();
- gen_load_fpr32(ctx, fp0, rt);
- tcg_gen_ext_i32_tl(t1, fp0);
- tcg_gen_andc_tl(t1, t1, t2);
- tcg_temp_free(t2);
- tcg_gen_or_tl(t0, t0, t1);
- tcg_temp_free(t1);
-#if defined(TARGET_MIPS64)
- tcg_gen_extrl_i64_i32(fp0, t0);
-#else
- tcg_gen_ext32s_tl(fp0, t0);
-#endif
- gen_store_fpr32(ctx, fp0, rt);
- tcg_temp_free_i32(fp0);
- break;
- case OPC_GSLWRC1:
- check_cp1_enabled(ctx);
- gen_base_offset_addr(ctx, t0, rs, shf_offset);
- t1 = tcg_temp_new();
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
- tcg_gen_andi_tl(t1, t0, 3);
- if (cpu_is_bigendian(ctx)) {
- tcg_gen_xori_tl(t1, t1, 3);
- }
- tcg_gen_shli_tl(t1, t1, 3);
- tcg_gen_andi_tl(t0, t0, ~3);
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
- tcg_gen_shr_tl(t0, t0, t1);
- tcg_gen_xori_tl(t1, t1, 31);
- t2 = tcg_const_tl(0xfffffffeull);
- tcg_gen_shl_tl(t2, t2, t1);
- fp0 = tcg_temp_new_i32();
- gen_load_fpr32(ctx, fp0, rt);
- tcg_gen_ext_i32_tl(t1, fp0);
- tcg_gen_and_tl(t1, t1, t2);
- tcg_temp_free(t2);
- tcg_gen_or_tl(t0, t0, t1);
- tcg_temp_free(t1);
-#if defined(TARGET_MIPS64)
- tcg_gen_extrl_i64_i32(fp0, t0);
-#else
- tcg_gen_ext32s_tl(fp0, t0);
-#endif
- gen_store_fpr32(ctx, fp0, rt);
- tcg_temp_free_i32(fp0);
- break;
-#if defined(TARGET_MIPS64)
- case OPC_GSLDLC1:
- check_cp1_enabled(ctx);
- gen_base_offset_addr(ctx, t0, rs, shf_offset);
- t1 = tcg_temp_new();
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
- tcg_gen_andi_tl(t1, t0, 7);
- if (!cpu_is_bigendian(ctx)) {
- tcg_gen_xori_tl(t1, t1, 7);
- }
- tcg_gen_shli_tl(t1, t1, 3);
- tcg_gen_andi_tl(t0, t0, ~7);
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ);
- tcg_gen_shl_tl(t0, t0, t1);
- t2 = tcg_const_tl(-1);
- tcg_gen_shl_tl(t2, t2, t1);
- gen_load_fpr64(ctx, t1, rt);
- tcg_gen_andc_tl(t1, t1, t2);
- tcg_temp_free(t2);
- tcg_gen_or_tl(t0, t0, t1);
- tcg_temp_free(t1);
- gen_store_fpr64(ctx, t0, rt);
- break;
- case OPC_GSLDRC1:
- check_cp1_enabled(ctx);
- gen_base_offset_addr(ctx, t0, rs, shf_offset);
- t1 = tcg_temp_new();
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
- tcg_gen_andi_tl(t1, t0, 7);
- if (cpu_is_bigendian(ctx)) {
- tcg_gen_xori_tl(t1, t1, 7);
- }
- tcg_gen_shli_tl(t1, t1, 3);
- tcg_gen_andi_tl(t0, t0, ~7);
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ);
- tcg_gen_shr_tl(t0, t0, t1);
- tcg_gen_xori_tl(t1, t1, 63);
- t2 = tcg_const_tl(0xfffffffffffffffeull);
- tcg_gen_shl_tl(t2, t2, t1);
- gen_load_fpr64(ctx, t1, rt);
- tcg_gen_and_tl(t1, t1, t2);
- tcg_temp_free(t2);
- tcg_gen_or_tl(t0, t0, t1);
- tcg_temp_free(t1);
- gen_store_fpr64(ctx, t0, rt);
- break;
-#endif
- default:
- MIPS_INVAL("loongson_gsshfl");
- gen_reserved_instruction(ctx);
- break;
- }
- break;
- case OPC_GSSHFS:
- switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
- case OPC_GSSWLC1:
- check_cp1_enabled(ctx);
- t1 = tcg_temp_new();
- gen_base_offset_addr(ctx, t0, rs, shf_offset);
- fp0 = tcg_temp_new_i32();
- gen_load_fpr32(ctx, fp0, rt);
- tcg_gen_ext_i32_tl(t1, fp0);
- gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
- tcg_temp_free_i32(fp0);
- tcg_temp_free(t1);
- break;
- case OPC_GSSWRC1:
- check_cp1_enabled(ctx);
- t1 = tcg_temp_new();
- gen_base_offset_addr(ctx, t0, rs, shf_offset);
- fp0 = tcg_temp_new_i32();
- gen_load_fpr32(ctx, fp0, rt);
- tcg_gen_ext_i32_tl(t1, fp0);
- gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
- tcg_temp_free_i32(fp0);
- tcg_temp_free(t1);
- break;
-#if defined(TARGET_MIPS64)
- case OPC_GSSDLC1:
- check_cp1_enabled(ctx);
- t1 = tcg_temp_new();
- gen_base_offset_addr(ctx, t0, rs, shf_offset);
- gen_load_fpr64(ctx, t1, rt);
- gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
- tcg_temp_free(t1);
- break;
- case OPC_GSSDRC1:
- check_cp1_enabled(ctx);
- t1 = tcg_temp_new();
- gen_base_offset_addr(ctx, t0, rs, shf_offset);
- gen_load_fpr64(ctx, t1, rt);
- gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
- tcg_temp_free(t1);
- break;
-#endif
- default:
- MIPS_INVAL("loongson_gsshfs");
- gen_reserved_instruction(ctx);
- break;
- }
- break;
- default:
- MIPS_INVAL("loongson_gslsq");
- gen_reserved_instruction(ctx);
- break;
- }
+ out:
tcg_temp_free(t0);
+ tcg_temp_free(t1);
}
-/* Loongson EXT LDC2/SDC2 */
-static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
- int rs, int rd)
+/*
+ * These MULT[U] and MADD[U] instructions implemented in for example
+ * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
+ * architectures are special three-operand variants with the syntax
+ *
+ * MULT[U][1] rd, rs, rt
+ *
+ * such that
+ *
+ * (rd, LO, HI) <- rs * rt
+ *
+ * and
+ *
+ * MADD[U][1] rd, rs, rt
+ *
+ * such that
+ *
+ * (rd, LO, HI) <- (LO, HI) + rs * rt
+ *
+ * where the low-order 32-bits of the result is placed into both the
+ * GPR rd and the special register LO. The high-order 32-bits of the
+ * result is placed into the special register HI.
+ *
+ * If the GPR rd is omitted in assembly language, it is taken to be 0,
+ * which is the zero register that always reads as 0.
+ */
+static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
+ int rd, int rs, int rt)
{
- int offset = sextract32(ctx->opcode, 3, 8);
- uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
- TCGv t0, t1;
- TCGv_i32 fp0;
+ TCGv t0 = tcg_temp_new();
+ TCGv t1 = tcg_temp_new();
+ int acc = 0;
+
+ gen_load_gpr(t0, rs);
+ gen_load_gpr(t1, rt);
- /* Pre-conditions */
switch (opc) {
- case OPC_GSLBX:
- case OPC_GSLHX:
- case OPC_GSLWX:
- case OPC_GSLDX:
- /* prefetch, implement as NOP */
- if (rt == 0) {
- return;
+ case MMI_OPC_MULT1:
+ acc = 1;
+ /* Fall through */
+ case OPC_MULT:
+ {
+ TCGv_i32 t2 = tcg_temp_new_i32();
+ TCGv_i32 t3 = tcg_temp_new_i32();
+ tcg_gen_trunc_tl_i32(t2, t0);
+ tcg_gen_trunc_tl_i32(t3, t1);
+ tcg_gen_muls2_i32(t2, t3, t2, t3);
+ if (rd) {
+ tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
+ }
+ tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
+ tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
+ tcg_temp_free_i32(t2);
+ tcg_temp_free_i32(t3);
}
break;
- case OPC_GSSBX:
- case OPC_GSSHX:
- case OPC_GSSWX:
- case OPC_GSSDX:
+ case MMI_OPC_MULTU1:
+ acc = 1;
+ /* Fall through */
+ case OPC_MULTU:
+ {
+ TCGv_i32 t2 = tcg_temp_new_i32();
+ TCGv_i32 t3 = tcg_temp_new_i32();
+ tcg_gen_trunc_tl_i32(t2, t0);
+ tcg_gen_trunc_tl_i32(t3, t1);
+ tcg_gen_mulu2_i32(t2, t3, t2, t3);
+ if (rd) {
+ tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
+ }
+ tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
+ tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
+ tcg_temp_free_i32(t2);
+ tcg_temp_free_i32(t3);
+ }
break;
- case OPC_GSLWXC1:
-#if defined(TARGET_MIPS64)
- case OPC_GSLDXC1:
-#endif
- check_cp1_enabled(ctx);
- /* prefetch, implement as NOP */
- if (rt == 0) {
- return;
+ case MMI_OPC_MADD1:
+ acc = 1;
+ /* Fall through */
+ case MMI_OPC_MADD:
+ {
+ TCGv_i64 t2 = tcg_temp_new_i64();
+ TCGv_i64 t3 = tcg_temp_new_i64();
+
+ tcg_gen_ext_tl_i64(t2, t0);
+ tcg_gen_ext_tl_i64(t3, t1);
+ tcg_gen_mul_i64(t2, t2, t3);
+ tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
+ tcg_gen_add_i64(t2, t2, t3);
+ tcg_temp_free_i64(t3);
+ gen_move_low32(cpu_LO[acc], t2);
+ gen_move_high32(cpu_HI[acc], t2);
+ if (rd) {
+ gen_move_low32(cpu_gpr[rd], t2);
+ }
+ tcg_temp_free_i64(t2);
}
break;
- case OPC_GSSWXC1:
-#if defined(TARGET_MIPS64)
- case OPC_GSSDXC1:
-#endif
- check_cp1_enabled(ctx);
+ case MMI_OPC_MADDU1:
+ acc = 1;
+ /* Fall through */
+ case MMI_OPC_MADDU:
+ {
+ TCGv_i64 t2 = tcg_temp_new_i64();
+ TCGv_i64 t3 = tcg_temp_new_i64();
+
+ tcg_gen_ext32u_tl(t0, t0);
+ tcg_gen_ext32u_tl(t1, t1);
+ tcg_gen_extu_tl_i64(t2, t0);
+ tcg_gen_extu_tl_i64(t3, t1);
+ tcg_gen_mul_i64(t2, t2, t3);
+ tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
+ tcg_gen_add_i64(t2, t2, t3);
+ tcg_temp_free_i64(t3);
+ gen_move_low32(cpu_LO[acc], t2);
+ gen_move_high32(cpu_HI[acc], t2);
+ if (rd) {
+ gen_move_low32(cpu_gpr[rd], t2);
+ }
+ tcg_temp_free_i64(t2);
+ }
break;
default:
- MIPS_INVAL("loongson_lsdc2");
+ MIPS_INVAL("mul/madd TXx9");
gen_reserved_instruction(ctx);
- return;
- break;
+ goto out;
}
- t0 = tcg_temp_new();
+ out:
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+}
+
+static void gen_cl(DisasContext *ctx, uint32_t opc,
+ int rd, int rs)
+{
+ TCGv t0;
- gen_base_offset_addr(ctx, t0, rs, offset);
- gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
+ if (rd == 0) {
+ /* Treat as NOP. */
+ return;
+ }
+ t0 = cpu_gpr[rd];
+ gen_load_gpr(t0, rs);
switch (opc) {
- case OPC_GSLBX:
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
- gen_store_gpr(t0, rt);
- break;
- case OPC_GSLHX:
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
- ctx->default_tcg_memop_mask);
- gen_store_gpr(t0, rt);
- break;
- case OPC_GSLWX:
- gen_base_offset_addr(ctx, t0, rs, offset);
- if (rd) {
- gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
- }
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
- ctx->default_tcg_memop_mask);
- gen_store_gpr(t0, rt);
- break;
-#if defined(TARGET_MIPS64)
- case OPC_GSLDX:
- gen_base_offset_addr(ctx, t0, rs, offset);
- if (rd) {
- gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
- }
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
- ctx->default_tcg_memop_mask);
- gen_store_gpr(t0, rt);
- break;
-#endif
- case OPC_GSLWXC1:
- gen_base_offset_addr(ctx, t0, rs, offset);
- if (rd) {
- gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
- }
- fp0 = tcg_temp_new_i32();
- tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
- ctx->default_tcg_memop_mask);
- gen_store_fpr32(ctx, fp0, rt);
- tcg_temp_free_i32(fp0);
- break;
+ case OPC_CLO:
+ case R6_OPC_CLO:
#if defined(TARGET_MIPS64)
- case OPC_GSLDXC1:
- gen_base_offset_addr(ctx, t0, rs, offset);
- if (rd) {
- gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
- }
- tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ |
- ctx->default_tcg_memop_mask);
- gen_store_fpr64(ctx, t0, rt);
- break;
+ case OPC_DCLO:
+ case R6_OPC_DCLO:
#endif
- case OPC_GSSBX:
- t1 = tcg_temp_new();
- gen_load_gpr(t1, rt);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
- tcg_temp_free(t1);
- break;
- case OPC_GSSHX:
- t1 = tcg_temp_new();
- gen_load_gpr(t1, rt);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
- ctx->default_tcg_memop_mask);
- tcg_temp_free(t1);
- break;
- case OPC_GSSWX:
- t1 = tcg_temp_new();
- gen_load_gpr(t1, rt);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
- ctx->default_tcg_memop_mask);
- tcg_temp_free(t1);
- break;
-#if defined(TARGET_MIPS64)
- case OPC_GSSDX:
- t1 = tcg_temp_new();
- gen_load_gpr(t1, rt);
- tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ |
- ctx->default_tcg_memop_mask);
- tcg_temp_free(t1);
+ tcg_gen_not_tl(t0, t0);
break;
-#endif
- case OPC_GSSWXC1:
- fp0 = tcg_temp_new_i32();
- gen_load_fpr32(ctx, fp0, rt);
- tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
- ctx->default_tcg_memop_mask);
- tcg_temp_free_i32(fp0);
+ }
+
+ switch (opc) {
+ case OPC_CLO:
+ case R6_OPC_CLO:
+ case OPC_CLZ:
+ case R6_OPC_CLZ:
+ tcg_gen_ext32u_tl(t0, t0);
+ tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
+ tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
break;
#if defined(TARGET_MIPS64)
- case OPC_GSSDXC1:
- t1 = tcg_temp_new();
- gen_load_fpr64(ctx, t1, rt);
- tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEUQ |
- ctx->default_tcg_memop_mask);
- tcg_temp_free(t1);
+ case OPC_DCLO:
+ case R6_OPC_DCLO:
+ case OPC_DCLZ:
+ case R6_OPC_DCLZ:
+ tcg_gen_clzi_i64(t0, t0, 64);
break;
#endif
- default:
- break;
}
-
- tcg_temp_free(t0);
}
/* Traps */
@@ -12347,8 +11200,7 @@ static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
gen_load_gpr(v2_t, v2);
switch (op1) {
- /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
- case OPC_MULT_G_2E:
+ case OPC_ADDUH_QB_DSP:
check_dsp_r2(ctx);
switch (op2) {
case OPC_ADDUH_QB:
@@ -13042,11 +11894,7 @@ static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
gen_load_gpr(v2_t, v2);
switch (op1) {
- /*
- * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
- * the same mask and op1.
- */
- case OPC_MULT_G_2E:
+ case OPC_ADDUH_QB_DSP:
check_dsp_r2(ctx);
switch (op2) {
case OPC_MUL_PH:
@@ -14413,15 +13261,6 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
case OPC_MUL:
gen_arith(ctx, op1, rd, rs, rt);
break;
- case OPC_DIV_G_2F:
- case OPC_DIVU_G_2F:
- case OPC_MULT_G_2F:
- case OPC_MULTU_G_2F:
- case OPC_MOD_G_2F:
- case OPC_MODU_G_2F:
- check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
- gen_loongson_integer(ctx, op1, rd, rs, rt);
- break;
case OPC_CLO:
case OPC_CLZ:
check_insn(ctx, ISA_MIPS_R1);
@@ -14446,15 +13285,6 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
check_mips_64(ctx);
gen_cl(ctx, op1, rd, rs);
break;
- case OPC_DMULT_G_2F:
- case OPC_DMULTU_G_2F:
- case OPC_DDIV_G_2F:
- case OPC_DDIVU_G_2F:
- case OPC_DMOD_G_2F:
- case OPC_DMODU_G_2F:
- check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
- gen_loongson_integer(ctx, op1, rd, rs, rt);
- break;
#endif
default: /* Invalid */
MIPS_INVAL("special2_legacy");
@@ -14587,48 +13417,33 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
op1 = MASK_SPECIAL3(ctx->opcode);
switch (op1) {
- case OPC_DIV_G_2E:
- case OPC_DIVU_G_2E:
- case OPC_MOD_G_2E:
- case OPC_MODU_G_2E:
- case OPC_MULT_G_2E:
- case OPC_MULTU_G_2E:
- /*
- * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
- * the same mask and op1.
- */
- if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
- op2 = MASK_ADDUH_QB(ctx->opcode);
- switch (op2) {
- case OPC_ADDUH_QB:
- case OPC_ADDUH_R_QB:
- case OPC_ADDQH_PH:
- case OPC_ADDQH_R_PH:
- case OPC_ADDQH_W:
- case OPC_ADDQH_R_W:
- case OPC_SUBUH_QB:
- case OPC_SUBUH_R_QB:
- case OPC_SUBQH_PH:
- case OPC_SUBQH_R_PH:
- case OPC_SUBQH_W:
- case OPC_SUBQH_R_W:
- gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
- break;
- case OPC_MUL_PH:
- case OPC_MUL_S_PH:
- case OPC_MULQ_S_W:
- case OPC_MULQ_RS_W:
- gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
- break;
- default:
- MIPS_INVAL("MASK ADDUH.QB");
- gen_reserved_instruction(ctx);
- break;
- }
- } else if (ctx->insn_flags & INSN_LOONGSON2E) {
- gen_loongson_integer(ctx, op1, rd, rs, rt);
- } else {
+ case OPC_ADDUH_QB_DSP:
+ op2 = MASK_ADDUH_QB(ctx->opcode);
+ switch (op2) {
+ case OPC_ADDUH_QB:
+ case OPC_ADDUH_R_QB:
+ case OPC_ADDQH_PH:
+ case OPC_ADDQH_R_PH:
+ case OPC_ADDQH_W:
+ case OPC_ADDQH_R_W:
+ case OPC_SUBUH_QB:
+ case OPC_SUBUH_R_QB:
+ case OPC_SUBQH_PH:
+ case OPC_SUBQH_R_PH:
+ case OPC_SUBQH_W:
+ case OPC_SUBQH_R_W:
+ gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
+ break;
+ case OPC_MUL_PH:
+ case OPC_MUL_S_PH:
+ case OPC_MULQ_S_W:
+ case OPC_MULQ_RS_W:
+ gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
+ break;
+ default:
+ MIPS_INVAL("MASK ADDUH.QB");
gen_reserved_instruction(ctx);
+ break;
}
break;
case OPC_LX_DSP:
@@ -14858,15 +13673,6 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
}
break;
#if defined(TARGET_MIPS64)
- case OPC_DDIV_G_2E:
- case OPC_DDIVU_G_2E:
- case OPC_DMULT_G_2E:
- case OPC_DMULTU_G_2E:
- case OPC_DMOD_G_2E:
- case OPC_DMODU_G_2E:
- check_insn(ctx, INSN_LOONGSON2E);
- gen_loongson_integer(ctx, op1, rd, rs, rt);
- break;
case OPC_ABSQ_S_QH_DSP:
op2 = MASK_ABSQ_S_QH(ctx->opcode);
switch (op2) {
@@ -15867,8 +14673,6 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
/* OPC_BC, OPC_BALC */
gen_compute_compact_branch(ctx, op, 0, 0,
sextract32(ctx->opcode << 2, 0, 28));
- } else if (ctx->insn_flags & ASE_LEXT) {
- gen_loongson_lswc2(ctx, rt, rs, rd);
} else {
/* OPC_LWC2, OPC_SWC2 */
/* COP2: Not implemented. */
@@ -15886,8 +14690,6 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
/* OPC_JIC, OPC_JIALC */
gen_compute_compact_branch(ctx, op, 0, rt, imm);
}
- } else if (ctx->insn_flags & ASE_LEXT) {
- gen_loongson_lsdc2(ctx, rt, rs, rd);
} else {
/* OPC_LWC2, OPC_SWC2 */
/* COP2: Not implemented. */
@@ -15895,9 +14697,8 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
}
break;
case OPC_CP2:
- check_insn(ctx, ASE_LMMI);
- /* Note that these instructions use different fields. */
- gen_loongson_multimedia(ctx, sa, rd, rt);
+ MIPS_INVAL("cp2");
+ gen_reserved_instruction(ctx);
break;
case OPC_CP3:
@@ -16075,8 +14876,22 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
return;
}
#endif
+ if (cpu_supports_isa(env, INSN_LOONGSON2E) &&
+ decode_ext_loongson2e(ctx, ctx->opcode)) {
+ return;
+ }
+ if (cpu_supports_isa(env, INSN_LOONGSON2F) &&
+ decode_ext_loongson2f(ctx, ctx->opcode)) {
+ return;
+ }
/* ISA extensions */
+ if (cpu_supports_isa(env, ASE_LEXT) && decode_ase_lext(ctx, ctx->opcode)) {
+ return;
+ }
+ if (cpu_supports_isa(env, ASE_LMMI) && decode_ase_lmmi(ctx, ctx->opcode)) {
+ return;
+ }
if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
return;
}
diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h
index 980aa8682d..c5fd16e657 100644
--- a/target/mips/tcg/translate.h
+++ b/target/mips/tcg/translate.h
@@ -241,6 +241,12 @@ void msa_translate_init(void);
void mxu_translate_init(void);
bool decode_ase_mxu(DisasContext *ctx, uint32_t insn);
+/* loongson */
+bool decode_ext_loongson2e(DisasContext *ctx, uint32_t insn);
+bool decode_ext_loongson2f(DisasContext *ctx, uint32_t insn);
+bool decode_ase_lext(DisasContext *ctx, uint32_t insn);
+bool decode_ase_lmmi(DisasContext *ctx, uint32_t insn);
+
/* decodetree generated */
bool decode_isa_rel6(DisasContext *ctx, uint32_t insn);
bool decode_ase_msa(DisasContext *ctx, uint32_t insn);
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread