diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-10-24 16:31:40 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-10-24 16:31:40 +0100 |
commit | c96292036a17857d62b8b5d3c8752bac3d6b7193 (patch) | |
tree | b1b55929e04de9057831164792f64e40523432e1 /tests | |
parent | 18e195645aa36da3395d4b0934bcf4f5076e9e1e (diff) | |
parent | 373ecd3823f949fd550ec49685299e287af5753e (diff) | |
download | qemu-c96292036a17857d62b8b5d3c8752bac3d6b7193.zip qemu-c96292036a17857d62b8b5d3c8752bac3d6b7193.tar.gz qemu-c96292036a17857d62b8b5d3c8752bac3d6b7193.tar.bz2 |
Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-oct-2018-part-2-v2' into staging
MIPS queue for October 2018 - part 2 - v2
# gpg: Signature made Wed 24 Oct 2018 14:22:54 BST
# gpg: using RSA key D4972A8967F75A65
# gpg: Good signature from "Aleksandar Markovic <amarkovic@wavecomp.com>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 8526 FBF1 5DA3 811F 4A01 DD75 D497 2A89 67F7 5A65
* remotes/amarkovic/tags/mips-queue-oct-2018-part-2-v2: (33 commits)
target/mips: Fix decoding of ALIGN and DALIGN instructions
target/mips: Fix the title of translate.c
linux-user/mips: Recognize the R5900 CPU model
target/mips: Define the R5900 CPU
tests/tcg/mips: Add tests for R5900 DIVU1
tests/tcg/mips: Add tests for R5900 DIV1
tests/tcg/mips: Add tests for R5900 MTLO1 and MTHI1
tests/tcg/mips: Add tests for R5900 MFLO1 and MFHI1
tests/tcg/mips: Add tests for R5900 three-operand MULTU1
tests/tcg/mips: Add tests for R5900 three-operand MULT1
tests/tcg/mips: Add tests for R5900 three-operand MULTU
tests/tcg/mips: Add tests for R5900 three-operand MULT
target/mips: Make R5900 DMULT[U], DDIV[U], LL[D] and SC[D] user only
target/mips: Support R5900 MOVN, MOVZ and PREF instructions from MIPS IV
target/mips: Support R5900 DIV1 and DIVU1 instructions
target/mips: Support R5900 MFLO1, MTLO1, MFHI1 and MTHI1 instructions
target/mips: Support R5900 three-operand MULT1 and MULTU1 instructions
target/mips: Support R5900 three-operand MULT and MULTU instructions
target/mips: Add a placeholder for R5900 MMI3 instruction subclass
target/mips: Add a placeholder for R5900 MMI2 instruction subclass
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/tcg/mips/mipsr5900/Makefile | 30 | ||||
-rw-r--r-- | tests/tcg/mips/mipsr5900/div1.c | 73 | ||||
-rw-r--r-- | tests/tcg/mips/mipsr5900/divu1.c | 48 | ||||
-rw-r--r-- | tests/tcg/mips/mipsr5900/mflohi1.c | 35 | ||||
-rw-r--r-- | tests/tcg/mips/mipsr5900/mtlohi1.c | 40 | ||||
-rw-r--r-- | tests/tcg/mips/mipsr5900/mult.c | 76 | ||||
-rw-r--r-- | tests/tcg/mips/mipsr5900/multu.c | 68 |
7 files changed, 370 insertions, 0 deletions
diff --git a/tests/tcg/mips/mipsr5900/Makefile b/tests/tcg/mips/mipsr5900/Makefile new file mode 100644 index 0000000..a1c388b --- /dev/null +++ b/tests/tcg/mips/mipsr5900/Makefile @@ -0,0 +1,30 @@ +-include ../../config-host.mak + +CROSS=mipsr5900el-unknown-linux-gnu- + +SIM=qemu-mipsel +SIM_FLAGS=-cpu R5900 + +CC = $(CROSS)gcc +CFLAGS = -Wall -mabi=32 -march=r5900 -static + +TESTCASES = div1.tst +TESTCASES += divu1.tst +TESTCASES += mflohi1.tst +TESTCASES += mtlohi1.tst +TESTCASES += mult.tst +TESTCASES += multu.tst + +all: $(TESTCASES) + +%.tst: %.c + $(CC) $(CFLAGS) $< -o $@ + +check: $(TESTCASES) + @for case in $(TESTCASES); do \ + echo $(SIM) $(SIM_FLAGS) ./$$case;\ + $(SIM) $(SIM_FLAGS) ./$$case; \ + done + +clean: + $(RM) -rf $(TESTCASES) diff --git a/tests/tcg/mips/mipsr5900/div1.c b/tests/tcg/mips/mipsr5900/div1.c new file mode 100644 index 0000000..83dafa0 --- /dev/null +++ b/tests/tcg/mips/mipsr5900/div1.c @@ -0,0 +1,73 @@ +/* + * Test R5900-specific DIV1. + */ + +#include <stdio.h> +#include <inttypes.h> +#include <assert.h> + +struct quotient_remainder { int32_t quotient, remainder; }; + +static struct quotient_remainder div1(int32_t rs, int32_t rt) +{ + int32_t lo, hi; + + __asm__ __volatile__ ( + " div1 $0, %2, %3\n" + " mflo1 %0\n" + " mfhi1 %1\n" + : "=r" (lo), "=r" (hi) + : "r" (rs), "r" (rt)); + + assert(rs / rt == lo); + assert(rs % rt == hi); + + return (struct quotient_remainder) { .quotient = lo, .remainder = hi }; +} + +static void verify_div1(int32_t rs, int32_t rt, + int32_t expected_quotient, + int32_t expected_remainder) +{ + struct quotient_remainder qr = div1(rs, rt); + + assert(qr.quotient == expected_quotient); + assert(qr.remainder == expected_remainder); +} + +static void verify_div1_negations(int32_t rs, int32_t rt, + int32_t expected_quotient, + int32_t expected_remainder) +{ + verify_div1(rs, rt, expected_quotient, expected_remainder); + verify_div1(rs, -rt, -expected_quotient, expected_remainder); + verify_div1(-rs, rt, -expected_quotient, -expected_remainder); + verify_div1(-rs, -rt, expected_quotient, -expected_remainder); +} + +int main() +{ + verify_div1_negations(0, 1, 0, 0); + verify_div1_negations(1, 1, 1, 0); + verify_div1_negations(1, 2, 0, 1); + verify_div1_negations(17, 19, 0, 17); + verify_div1_negations(19, 17, 1, 2); + verify_div1_negations(77773, 101, 770, 3); + + verify_div1(-0x80000000, 1, -0x80000000, 0); + + /* + * Supplementary explanation from the Toshiba TX System RISC TX79 Core + * Architecture manual, A-38 and B-7, https://wiki.qemu.org/File:C790.pdf + * + * Normally, when 0x80000000 (-2147483648) the signed minimum value is + * divided by 0xFFFFFFFF (-1), the operation will result in an overflow. + * However, in this instruction an overflow exception doesn't occur and + * the result will be as follows: + * + * Quotient is 0x80000000 (-2147483648), and remainder is 0x00000000 (0). + */ + verify_div1(-0x80000000, -1, -0x80000000, 0); + + return 0; +} diff --git a/tests/tcg/mips/mipsr5900/divu1.c b/tests/tcg/mips/mipsr5900/divu1.c new file mode 100644 index 0000000..72aeed3 --- /dev/null +++ b/tests/tcg/mips/mipsr5900/divu1.c @@ -0,0 +1,48 @@ +/* + * Test R5900-specific DIVU1. + */ + +#include <stdio.h> +#include <inttypes.h> +#include <assert.h> + +struct quotient_remainder { uint32_t quotient, remainder; }; + +static struct quotient_remainder divu1(uint32_t rs, uint32_t rt) +{ + uint32_t lo, hi; + + __asm__ __volatile__ ( + " divu1 $0, %2, %3\n" + " mflo1 %0\n" + " mfhi1 %1\n" + : "=r" (lo), "=r" (hi) + : "r" (rs), "r" (rt)); + + assert(rs / rt == lo); + assert(rs % rt == hi); + + return (struct quotient_remainder) { .quotient = lo, .remainder = hi }; +} + +static void verify_divu1(uint32_t rs, uint32_t rt, + uint32_t expected_quotient, + uint32_t expected_remainder) +{ + struct quotient_remainder qr = divu1(rs, rt); + + assert(qr.quotient == expected_quotient); + assert(qr.remainder == expected_remainder); +} + +int main() +{ + verify_divu1(0, 1, 0, 0); + verify_divu1(1, 1, 1, 0); + verify_divu1(1, 2, 0, 1); + verify_divu1(17, 19, 0, 17); + verify_divu1(19, 17, 1, 2); + verify_divu1(77773, 101, 770, 3); + + return 0; +} diff --git a/tests/tcg/mips/mipsr5900/mflohi1.c b/tests/tcg/mips/mipsr5900/mflohi1.c new file mode 100644 index 0000000..eed3683 --- /dev/null +++ b/tests/tcg/mips/mipsr5900/mflohi1.c @@ -0,0 +1,35 @@ +/* + * Test R5900-specific MFLO1 and MFHI1. + */ + +#include <stdio.h> +#include <inttypes.h> +#include <assert.h> + +int main() +{ + int32_t rs = 12207031, rt = 305175781; + int32_t rs1 = 32452867, rt1 = 49979687; + int64_t lo, hi, lo1, hi1; + int64_t r, r1; + + /* Test both LO/HI and LO1/HI1 to verify separation. */ + __asm__ __volatile__ ( + " mult $0, %4, %5\n" + " mult1 $0, %6, %7\n" + " mflo %0\n" + " mfhi %1\n" + " mflo1 %2\n" + " mfhi1 %3\n" + : "=r" (lo), "=r" (hi), + "=r" (lo1), "=r" (hi1) + : "r" (rs), "r" (rt), + "r" (rs1), "r" (rt1)); + r = ((int64_t)hi << 32) | (uint32_t)lo; + r1 = ((int64_t)hi1 << 32) | (uint32_t)lo1; + + assert(r == 3725290219116211); + assert(r1 == 1621984134912629); + + return 0; +} diff --git a/tests/tcg/mips/mipsr5900/mtlohi1.c b/tests/tcg/mips/mipsr5900/mtlohi1.c new file mode 100644 index 0000000..7f3e728 --- /dev/null +++ b/tests/tcg/mips/mipsr5900/mtlohi1.c @@ -0,0 +1,40 @@ +/* + * Test R5900-specific MTLO1 and MTHI1. + */ + +#include <stdio.h> +#include <inttypes.h> +#include <assert.h> + +int main() +{ + int32_t tlo = 12207031, thi = 305175781; + int32_t tlo1 = 32452867, thi1 = 49979687; + int32_t flo, fhi, flo1, fhi1; + + /* Test both LO/HI and LO1/HI1 to verify separation. */ + __asm__ __volatile__ ( + " mtlo %4\n" + " mthi %5\n" + " mtlo1 %6\n" + " mthi1 %7\n" + " move %0, $0\n" + " move %1, $0\n" + " move %2, $0\n" + " move %3, $0\n" + " mflo %0\n" + " mfhi %1\n" + " mflo1 %2\n" + " mfhi1 %3\n" + : "=r" (flo), "=r" (fhi), + "=r" (flo1), "=r" (fhi1) + : "r" (tlo), "r" (thi), + "r" (tlo1), "r" (thi1)); + + assert(flo == 12207031); + assert(fhi == 305175781); + assert(flo1 == 32452867); + assert(fhi1 == 49979687); + + return 0; +} diff --git a/tests/tcg/mips/mipsr5900/mult.c b/tests/tcg/mips/mipsr5900/mult.c new file mode 100644 index 0000000..5710b39 --- /dev/null +++ b/tests/tcg/mips/mipsr5900/mult.c @@ -0,0 +1,76 @@ +/* + * Test R5900-specific three-operand MULT and MULT1. + */ + +#include <stdio.h> +#include <inttypes.h> +#include <assert.h> + +static int64_t mult(int32_t rs, int32_t rt) +{ + int32_t rd, lo, hi; + int64_t r; + + __asm__ __volatile__ ( + " mult %0, %3, %4\n" + " mflo %1\n" + " mfhi %2\n" + : "=r" (rd), "=r" (lo), "=r" (hi) + : "r" (rs), "r" (rt)); + r = ((int64_t)hi << 32) | (uint32_t)lo; + + assert((int64_t)rs * rt == r); + assert(rd == lo); + + return r; +} + +static int64_t mult1(int32_t rs, int32_t rt) +{ + int32_t rd, lo, hi; + int64_t r; + + __asm__ __volatile__ ( + " mult1 %0, %3, %4\n" + " mflo1 %1\n" + " mfhi1 %2\n" + : "=r" (rd), "=r" (lo), "=r" (hi) + : "r" (rs), "r" (rt)); + r = ((int64_t)hi << 32) | (uint32_t)lo; + + assert((int64_t)rs * rt == r); + assert(rd == lo); + + return r; +} + +static int64_t mult_variants(int32_t rs, int32_t rt) +{ + int64_t rd = mult(rs, rt); + int64_t rd1 = mult1(rs, rt); + + assert(rd == rd1); + + return rd; +} + +static void verify_mult_negations(int32_t rs, int32_t rt, int64_t expected) +{ + assert(mult_variants(rs, rt) == expected); + assert(mult_variants(-rs, rt) == -expected); + assert(mult_variants(rs, -rt) == -expected); + assert(mult_variants(-rs, -rt) == expected); +} + +int main() +{ + verify_mult_negations(17, 19, 323); + verify_mult_negations(77773, 99991, 7776600043); + verify_mult_negations(12207031, 305175781, 3725290219116211); + + assert(mult_variants(-0x80000000, 0x7FFFFFFF) == -0x3FFFFFFF80000000); + assert(mult_variants(-0x80000000, -0x7FFFFFFF) == 0x3FFFFFFF80000000); + assert(mult_variants(-0x80000000, -0x80000000) == 0x4000000000000000); + + return 0; +} diff --git a/tests/tcg/mips/mipsr5900/multu.c b/tests/tcg/mips/mipsr5900/multu.c new file mode 100644 index 0000000..f043904 --- /dev/null +++ b/tests/tcg/mips/mipsr5900/multu.c @@ -0,0 +1,68 @@ +/* + * Test R5900-specific three-operand MULTU and MULTU1. + */ + +#include <stdio.h> +#include <inttypes.h> +#include <assert.h> + +static uint64_t multu(uint32_t rs, uint32_t rt) +{ + uint32_t rd, lo, hi; + uint64_t r; + + __asm__ __volatile__ ( + " multu %0, %3, %4\n" + " mflo %1\n" + " mfhi %2\n" + : "=r" (rd), "=r" (lo), "=r" (hi) + : "r" (rs), "r" (rt)); + r = ((uint64_t)hi << 32) | (uint32_t)lo; + + assert((uint64_t)rs * rt == r); + assert(rd == lo); + + return r; +} + +static uint64_t multu1(uint32_t rs, uint32_t rt) +{ + uint32_t rd, lo, hi; + uint64_t r; + + __asm__ __volatile__ ( + " multu1 %0, %3, %4\n" + " mflo1 %1\n" + " mfhi1 %2\n" + : "=r" (rd), "=r" (lo), "=r" (hi) + : "r" (rs), "r" (rt)); + r = ((uint64_t)hi << 32) | (uint32_t)lo; + + assert((uint64_t)rs * rt == r); + assert(rd == lo); + + return r; +} + +static uint64_t multu_variants(uint32_t rs, uint32_t rt) +{ + uint64_t rd = multu(rs, rt); + uint64_t rd1 = multu1(rs, rt); + + assert(rd == rd1); + + return rd; +} + +int main() +{ + assert(multu_variants(17, 19) == 323); + assert(multu_variants(77773, 99991) == 7776600043); + assert(multu_variants(12207031, 305175781) == 3725290219116211); + + assert(multu_variants(0x80000000U, 0x7FFFFFFF) == 0x3FFFFFFF80000000); + assert(multu_variants(0x80000000U, 0x80000000U) == 0x4000000000000000); + assert(multu_variants(0xFFFFFFFFU, 0xFFFFFFFFU) == 0xFFFFFFFE00000001U); + + return 0; +} |