Home | History | Annotate | Download | only in arm
      1 
      2 /*
      3 gcc -g -o v8memory_a -march=armv8-a -mfpu=crypto-neon-fp-armv8 \
      4    none/tests/arm/v8memory.c -I. -Wall -marm
      5 
      6 gcc -g -o v8memory_t -march=armv8-a -mfpu=crypto-neon-fp-armv8 \
      7    none/tests/arm/v8memory.c -I. -Wall -mthumb
      8 */
      9 
     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. */
     14 
     15 #include <stdio.h>
     16 #include <malloc.h>  // memalign
     17 #include <string.h>  // memset
     18 #include "tests/malloc.h"
     19 #include <assert.h>
     20 
     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;
     28 
     29 typedef  unsigned char           Bool;
     30 #define False ((Bool)0)
     31 #define True  ((Bool)1)
     32 
     33 static inline UChar randUChar ( void )
     34 {
     35    static UInt seed = 90210; // Somewhere in Beverly Hills, allegedly.
     36    seed = 1103515245 * seed + 12345;
     37    return (seed >> 17) & 0xFF;
     38 }
     39 
     40 static UInt randUInt ( void )
     41 {
     42    Int i;
     43    UInt r = 0;
     44    for (i = 0; i < 4; i++) {
     45       r = (r << 8) | (UInt)(0xFF & randUChar());
     46    }
     47    return r;
     48 }
     49 
     50 static void show_block_xor ( UChar* block1, UChar* block2, Int n )
     51 {
     52    Int i;
     53    printf("  ");
     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]);
     58       if (diff == 0)
     59          printf(".. ");
     60       else
     61          printf("%02x ", diff);
     62    }
     63    printf("\n");
     64 }
     65 
     66 
     67 // INSN may mention the following regs as containing load/store data:
     68 //      r2 r3 r6 r9
     69 // INSN must mention the following reg as containing the EA: r10
     70 //
     71 // INSN can use r4 and r5 as scratch
     72 //
     73 // In: rand: memory area (128 bytes), r2, r3, r6, r9
     74 //       r10 pointing to middle of memory area
     75 //
     76 // Out: memory area, r2, r3, r6, r9, r10
     77 //
     78 // What is printed out: the XOR of the new and old versions of the
     79 // following:
     80 //    the memory area
     81 //    r2, r3 r6 r9 r10
     82 
     83 #define MEM_TEST(INSN) { \
     84   int i; \
     85   const int N = 128; \
     86   UChar* area1 = memalign16(N); \
     87   UChar* area2 = memalign16(N); \
     88   for (i = 0; i < N; i++) area1[i] = area2[i] = randUChar(); \
     89   UInt block1[5]; \
     90   UInt block2[5]; \
     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] ; " \
    100     INSN " ; " \
    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", \
    107         "memory", "cc" \
    108   ); \
    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]); \
    116   printf("\n"); \
    117   free(area1); free(area2); \
    118   }
    119 
    120 
    121 int main ( void )
    122 {
    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]")
    128 
    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]")
    134 
    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]")
    141 
    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]")
    149 
    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]")
    162 
    163    return 0;
    164 }
    165