3 gcc -g -o v8memory_a -march=armv8-a -mfpu=crypto-neon-fp-armv8 \
4 none/tests/arm/v8memory.c -I. -Wall -marm
6 gcc -g -o v8memory_t -march=armv8-a -mfpu=crypto-neon-fp-armv8 \
7 none/tests/arm/v8memory.c -I. -Wall -mthumb
10 /* These tests unfortunately are unable to check the relative
11 placement (or, even, presence) of the required memory fences
12 relative to the store/load required. They only verify the
13 data-movement component. */
16 #include <malloc.h> // memalign
17 #include <string.h> // memset
18 #include "tests/malloc.h"
21 typedef unsigned char UChar
;
22 typedef unsigned short int UShort
;
23 typedef unsigned int UInt
;
24 typedef signed int Int
;
25 typedef unsigned char UChar
;
26 typedef signed long long int Long
;
27 typedef unsigned long long int ULong
;
29 typedef unsigned char Bool
;
30 #define False ((Bool)0)
31 #define True ((Bool)1)
33 static inline UChar
randUChar ( void )
35 static UInt seed
= 90210; // Somewhere in Beverly Hills, allegedly.
36 seed
= 1103515245 * seed
+ 12345;
37 return (seed
>> 17) & 0xFF;
40 static UInt
randUInt ( void )
44 for (i
= 0; i
< 4; i
++) {
45 r
= (r
<< 8) | (UInt
)(0xFF & randUChar());
50 static void show_block_xor ( UChar
* block1
, UChar
* block2
, Int n
)
54 for (i
= 0; i
< n
; i
++) {
55 if (i
> 0 && 0 == (i
& 15)) printf("\n ");
56 if (0 == (i
& 15)) printf("[%3d] ", i
);
57 UInt diff
= 0xFF & (UInt
)(block1
[i
] - block2
[i
]);
61 printf("%02x ", diff
);
67 // INSN may mention the following regs as containing load/store data:
69 // INSN must mention the following reg as containing the EA: r10
71 // INSN can use r4 and r5 as scratch
73 // In: rand: memory area (128 bytes), r2, r3, r6, r9
74 // r10 pointing to middle of memory area
76 // Out: memory area, r2, r3, r6, r9, r10
78 // What is printed out: the XOR of the new and old versions of the
83 #define MEM_TEST(INSN) { \
86 UChar* area1 = memalign16(N); \
87 UChar* area2 = memalign16(N); \
88 for (i = 0; i < N; i++) area1[i] = area2[i] = randUChar(); \
91 /* 0:r2 1:r3 2:r6 3:r9 4:r10 */ \
92 for (i = 0; i < 5; i++) block1[i] = block2[i] = randUInt(); \
93 block1[4] = block2[4] = (UInt)(&area1[N/2]); \
94 __asm__ __volatile__( \
95 "ldr r2, [%0, #0] ; " \
96 "ldr r3, [%0, #4] ; " \
97 "ldr r6, [%0, #8] ; " \
98 "ldr r9, [%0, #12] ; " \
99 "ldr r10, [%0, #16] ; " \
101 "str r2, [%0, #0] ; " \
102 "str r3, [%0, #4] ; " \
103 "str r6, [%0, #8] ; " \
104 "str r9, [%0, #12] ; " \
105 "str r10, [%0, #16] ; " \
106 : : "r"(&block1[0]) : "r2", "r3", "r4", "r5", "r6", "r9", "r10", \
109 printf("%s with r10 = middle_of_block\n", INSN); \
110 show_block_xor(&area1[0], &area2[0], N); \
111 printf(" %08x r2 (xor, data intreg #1)\n", block1[0] ^ block2[0]); \
112 printf(" %08x r3 (xor, data intreg #2)\n", block1[1] ^ block2[1]); \
113 printf(" %08x r6 (xor, data intreg #3)\n", block1[2] ^ block2[2]); \
114 printf(" %08x r9 (xor, data intreg #4)\n", block1[3] ^ block2[3]); \
115 printf(" %08x r10 (xor, addr intreg #1)\n", block1[4] ^ block2[4]); \
117 free(area1); free(area2); \
123 ////////////////////////////////////////////////////////////////
124 printf("LDA{,B,H} (reg)\n\n");
125 MEM_TEST("lda r6, [r10]")
126 MEM_TEST("ldab r9, [r10]")
127 MEM_TEST("ldah r3, [r10]")
129 ////////////////////////////////////////////////////////////////
130 printf("STL{,B,H} (reg)\n\n");
131 MEM_TEST("stl r6, [r10]")
132 MEM_TEST("stlb r9, [r10]")
133 MEM_TEST("stlh r3, [r10]")
135 ////////////////////////////////////////////////////////////////
136 printf("LDAEX{,B,H,D} (reg)\n\n");
137 MEM_TEST("ldaex r6, [r10]")
138 MEM_TEST("ldaexb r9, [r10]")
139 MEM_TEST("ldaexh r3, [r10]")
140 MEM_TEST("ldaexd r2, r3, [r10]")
142 ////////////////////////////////////////////////////////////////
143 // These verify that stlex* do notice a cleared (missing) reservation.
144 printf("STLEX{,B,H,D} (reg) -- expected to fail\n\n");
145 MEM_TEST("clrex; stlex r9, r6, [r10]")
146 MEM_TEST("clrex; stlexb r9, r6, [r10]")
147 MEM_TEST("clrex; stlexh r9, r3, [r10]")
148 MEM_TEST("clrex; stlexd r9, r2, r3, [r10]")
150 ////////////////////////////////////////////////////////////////
151 // These verify that stlex* do notice a successful reservation.
152 // By using ldaex* to create the reservation in the first place,
153 // they also verify that ldaex* actually create a reservation.
154 printf("STLEX{,B,H,D} (reg) -- expected to succeed\n\n");
155 MEM_TEST("ldaex r2, [r10] ; stlex r9, r6, [r10]")
156 MEM_TEST("ldaexb r2, [r10] ; stlexb r9, r6, [r10]")
157 MEM_TEST("ldaexh r2, [r10] ; stlexh r9, r3, [r10]")
158 MEM_TEST("mov r4, r2 ; mov r5, r3 ; " // preserve r2/r3 around the ldrexd
159 "ldaexd r2, r3, [r10] ; "
160 "mov r2, r4 ; mov r3, r5 ; "
161 "stlexd r9, r2, r3, [r10]")