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