Signed-off-by: Fredrik Noring <nor...@nocrew.org> --- tests/tcg/mips/mipsn32r5900/Makefile | 3 +- tests/tcg/mips/mipsn32r5900/lq.c | 111 +++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 tests/tcg/mips/mipsn32r5900/lq.c
diff --git a/tests/tcg/mips/mipsn32r5900/Makefile b/tests/tcg/mips/mipsn32r5900/Makefile index f4887678ae..cb3ef9d26a 100644 --- a/tests/tcg/mips/mipsn32r5900/Makefile +++ b/tests/tcg/mips/mipsn32r5900/Makefile @@ -8,7 +8,8 @@ SIM_FLAGS=-cpu R5900 CC = $(CROSS)gcc CFLAGS = -Wall -mabi=n32 -march=r5900 -static -TESTCASES = pcpyuld.tst +TESTCASES = lq.tst +TESTCASES += pcpyuld.tst all: $(TESTCASES) diff --git a/tests/tcg/mips/mipsn32r5900/lq.c b/tests/tcg/mips/mipsn32r5900/lq.c new file mode 100644 index 0000000000..5a16b12450 --- /dev/null +++ b/tests/tcg/mips/mipsn32r5900/lq.c @@ -0,0 +1,111 @@ +/* + * Test LQ. + */ + +#include <stdio.h> +#include <inttypes.h> +#include <assert.h> + +/* 128-bit multimedia register */ +struct mmr { uint64_t hi, lo; } __attribute__((aligned(16))); + +#define LQ(base, offset) \ + ({ \ + uint64_t hi, lo; \ + \ + __asm__ __volatile__ ( \ + " pcpyld %1, %1, %1\n" \ + " lq %1, %3(%2)\n" \ + " pcpyud %0, %1, %1\n" \ + : "=r" (hi), "=r" (lo) \ + : "r" (base), "i" (offset)); \ + \ + (struct mmr) { .hi = hi, .lo = lo }; \ + }) + +static uint64_t ld_reference(const void *base, int16_t offset) +{ + const uint8_t *p = base; + uint64_t r = 0; + int i; + + for (i = 0; i < 8; i++) { + r |= (uint64_t)p[offset + i] << (8 * i); + } + + return r; +} + +static struct mmr lq_reference(const void *base, int16_t offset) +{ + /* + * The least significant four bits of the effective address are + * masked to zero, effectively creating an aligned address. No + * address exceptions due to alignment are possible. + */ + const uint8_t *b = base; + const uint8_t *o = &b[offset]; + const void *a = (const void*)((unsigned long)o & ~0xFUL); + + return (struct mmr) { + .hi = ld_reference(a, 8), + .lo = ld_reference(a, 0) + }; +} + +static void assert_equal_mmr(struct mmr a, struct mmr b) +{ + assert(a.hi == b.hi); + assert(a.lo == b.lo); +} + +#define VERIFY_LQ(base, offset) \ + assert_equal_mmr(LQ(base, offset), lq_reference(base, offset)) + +int main() +{ + static const char data[] __attribute__((aligned(16)))= + "0123456789abcdef" + "ghijklmnopqrstuv" + "wxyzABCDEFGHIJKL" + "MNOPQRSTUVWXYZ.,"; + int i; + + for (i = 16; i < 48; i++) { + VERIFY_LQ(&data[i], -16); + VERIFY_LQ(&data[i], -15); + VERIFY_LQ(&data[i], -14); + VERIFY_LQ(&data[i], -13); + VERIFY_LQ(&data[i], -12); + VERIFY_LQ(&data[i], -11); + VERIFY_LQ(&data[i], -10); + VERIFY_LQ(&data[i], -9); + VERIFY_LQ(&data[i], -8); + VERIFY_LQ(&data[i], -7); + VERIFY_LQ(&data[i], -6); + VERIFY_LQ(&data[i], -5); + VERIFY_LQ(&data[i], -4); + VERIFY_LQ(&data[i], -3); + VERIFY_LQ(&data[i], -2); + VERIFY_LQ(&data[i], -1); + VERIFY_LQ(&data[i], 0); + VERIFY_LQ(&data[i], 1); + VERIFY_LQ(&data[i], 2); + VERIFY_LQ(&data[i], 3); + VERIFY_LQ(&data[i], 4); + VERIFY_LQ(&data[i], 5); + VERIFY_LQ(&data[i], 6); + VERIFY_LQ(&data[i], 7); + VERIFY_LQ(&data[i], 8); + VERIFY_LQ(&data[i], 9); + VERIFY_LQ(&data[i], 10); + VERIFY_LQ(&data[i], 11); + VERIFY_LQ(&data[i], 12); + VERIFY_LQ(&data[i], 13); + VERIFY_LQ(&data[i], 14); + VERIFY_LQ(&data[i], 15); + VERIFY_LQ(&data[i], 16); + } + + return 0; +} -- 2.19.2