From: Julian Seward Date: Sun, 28 Aug 2016 16:17:12 +0000 (+0000) Subject: Add test cases for ARMv8 insns: LDA, LDAB, LDAH, STL, STLB, STLH. X-Git-Tag: svn/VALGRIND_3_12_0~82 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3e4a4540b1ea7229194c04cf1071aecdda652097;p=thirdparty%2Fvalgrind.git Add test cases for ARMv8 insns: LDA, LDAB, LDAH, STL, STLB, STLH. Not connected to the build system yet. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15941 --- diff --git a/none/tests/arm/v8memory.c b/none/tests/arm/v8memory.c new file mode 100644 index 0000000000..93e7050419 --- /dev/null +++ b/none/tests/arm/v8memory.c @@ -0,0 +1,155 @@ + +/* +gcc -g -o v8memory_a -march=armv8-a -mfpu=crypto-neon-fp-armv8 \ + none/tests/arm/v8memory.c -I. -Wall -marm + +gcc -g -o v8memory_t -march=armv8-a -mfpu=crypto-neon-fp-armv8 \ + none/tests/arm/v8memory.c -I. -Wall -mthumb +*/ + +#include +#include // memalign +#include // memset +#include "tests/malloc.h" +#include + +typedef unsigned char UChar; +typedef unsigned short int UShort; +typedef unsigned int UInt; +typedef signed int Int; +typedef unsigned char UChar; +typedef signed long long int Long; +typedef unsigned long long int ULong; + +typedef unsigned char Bool; +#define False ((Bool)0) +#define True ((Bool)1) + +static inline UChar randUChar ( void ) +{ + static UInt seed = 90210; // Somewhere in Beverly Hills, allegedly. + seed = 1103515245 * seed + 12345; + return (seed >> 17) & 0xFF; +} + +static UInt randUInt ( void ) +{ + Int i; + UInt r = 0; + for (i = 0; i < 4; i++) { + r = (r << 8) | (UInt)(0xFF & randUChar()); + } + return r; +} + +static void show_block_xor ( UChar* block1, UChar* block2, Int n ) +{ + Int i; + printf(" "); + for (i = 0; i < n; i++) { + if (i > 0 && 0 == (i & 15)) printf("\n "); + if (0 == (i & 15)) printf("[%3d] ", i); + UInt diff = 0xFF & (UInt)(block1[i] - block2[i]); + if (diff == 0) + printf(".. "); + else + printf("%02x ", diff); + } + printf("\n"); +} + + +// INSN may mention the following regs as containing load/store data: +// r2 r3 r6 r9 +// INSN must mention the following reg as containing the EA: r10 +// +// INSN can use r4 and r5 as scratch +// +// In: rand: memory area (128 bytes), r2, r3, r6, r9 +// r10 pointing to middle of memory area +// +// Out: memory area, r2, r3, r6, r9, r10 +// +// What is printed out: the XOR of the new and old versions of the +// following: +// the memory area +// r2, r3 r6 r9 r10 + +#define MEM_TEST(INSN) { \ + int i; \ + const int N = 128; \ + UChar* area1 = memalign16(N); \ + UChar* area2 = memalign16(N); \ + for (i = 0; i < N; i++) area1[i] = area2[i] = randUChar(); \ + UInt block1[5]; \ + UInt block2[5]; \ + /* 0:r2 1:r3 2:r6 3:r9 4:r10 */ \ + for (i = 0; i < 5; i++) block1[i] = block2[i] = randUInt(); \ + block1[4] = block2[4] = (UInt)(&area1[N/2]); \ + __asm__ __volatile__( \ + "ldr r2, [%0, #0] ; " \ + "ldr r3, [%0, #4] ; " \ + "ldr r6, [%0, #8] ; " \ + "ldr r9, [%0, #12] ; " \ + "ldr r10, [%0, #16] ; " \ + INSN " ; " \ + "str r2, [%0, #0] ; " \ + "str r3, [%0, #4] ; " \ + "str r6, [%0, #8] ; " \ + "str r9, [%0, #12] ; " \ + "str r10, [%0, #16] ; " \ + : : "r"(&block1[0]) : "r2", "r3", "r4", "r5", "r6", "r9", "r10", \ + "memory", "cc" \ + ); \ + printf("%s with r10 = middle_of_block\n", INSN); \ + show_block_xor(&area1[0], &area2[0], N); \ + printf(" %08x r2 (xor, data intreg #1)\n", block1[0] ^ block2[0]); \ + printf(" %08x r3 (xor, data intreg #2)\n", block1[1] ^ block2[1]); \ + printf(" %08x r6 (xor, data intreg #3)\n", block1[2] ^ block2[2]); \ + printf(" %08x r9 (xor, data intreg #4)\n", block1[3] ^ block2[3]); \ + printf(" %08x r10 (xor, addr intreg #1)\n", block1[4] ^ block2[4]); \ + printf("\n"); \ + free(area1); free(area2); \ + } + + +int main ( void ) +{ + //////////////////////////////////////////////////////////////// + printf("LDA{,B,H} (reg)\n\n"); + MEM_TEST("lda r6, [r10]") + MEM_TEST("ldab r9, [r10]") + MEM_TEST("ldah r3, [r10]") + + //////////////////////////////////////////////////////////////// + printf("STL{,B,H} (reg)\n\n"); + MEM_TEST("stl r6, [r10]") + MEM_TEST("stlb r9, [r10]") + MEM_TEST("stlh r3, [r10]") +#if 0 + //////////////////////////////////////////////////////////////// + printf("LDAEX{,B,H,D} (reg)\n\n"); + MEM_TEST("ldaex r6, [r10]") + MEM_TEST("ldaexb r9, [r10]") + MEM_TEST("ldaexh r3, [r10]") + MEM_TEST("ldaexd r2, r3, [r10]") + + //////////////////////////////////////////////////////////////// + printf("STLEX{,B,H,D} (reg) -- expected to fail\n\n"); + MEM_TEST("clrex; stlex r9, r6, [r10]") + MEM_TEST("clrex; stlexb r9, r6, [r10]") + MEM_TEST("clrex; stlexh r9, r3, [r10]") + MEM_TEST("clrex; stlexd r9, r2, r3, [r10]") + + //////////////////////////////////////////////////////////////// + printf("STLEX{,B,H,D} (reg) -- expected to succeed\n\n"); + MEM_TEST("ldrex r2, [r10] ; stlex r9, r6, [r10]") + MEM_TEST("ldrexb r2, [r10] ; stlexb r9, r6, [r10]") + MEM_TEST("ldrexh r2, [r10] ; stlexh r9, r3, [r10]") + MEM_TEST("mov r4, r2 ; mov r5, r3 ; " // preserve r2/r3 around the ldrexd + "ldrexd r2, r3, [r10] ; " + "mov r2, r4 ; mov r3, r5 ; " + "stlexd r9, r2, r3, [r10]") +#endif + return 0; +}