1ff62002b4cf8103675514bf848f3f38bf26ba7ecsewardj#include "tests/malloc.h"
2da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj#include <stdio.h>
3da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj#include <assert.h>
4da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj
5da04f3ec707985d9c6cc963c1bbe06ee6131308esewardjtypedef  unsigned long long int  ULong;
6da04f3ec707985d9c6cc963c1bbe06ee6131308esewardjtypedef  unsigned long int       UWord;
7da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj
8da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj__attribute__((noinline))
9da04f3ec707985d9c6cc963c1bbe06ee6131308esewardjstatic int my_ffsll ( ULong x )
10da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj{
11da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj   int i;
12da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj   for (i = 0; i < 64; i++) {
13da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj      if ((x & 1ULL) == 1ULL)
14da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj         break;
15da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj      x >>= 1;
16da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj   }
17da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj   return i+1;
18da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj}
19da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj
20da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj/* Find length of string, assuming it is aligned and shorter than 8
21da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj   characters.  Little-endian only. */
22da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj__attribute__((noinline))
23da04f3ec707985d9c6cc963c1bbe06ee6131308esewardjstatic int aligned_strlen(char *s)
24da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj{
25da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    /* This is for 64-bit platforms */
26da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    assert(sizeof(ULong) == 8);
27da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    /* ..and only works for aligned input */
28da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    assert(((unsigned long)s & 0x7) == 0);
29da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj
30da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    /* read 8 bytes */
31da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    ULong val = *(ULong*)s;
32da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    /* Subtract one from each byte */
33da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    ULong val2 = val - 0x0101010101010101ULL;
34da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    /* Find lowest byte whose high bit changed */
35da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    val2 ^= val;
36da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    val2 &= 0x8080808080808080ULL;
37da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj
38da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    return (my_ffsll(val2) / 8) - 1;
39da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj}
40da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj
41da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj__attribute__((noinline)) void foo ( int x )
42da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj{
43da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj   __asm__ __volatile__("":::"memory");
44da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj}
45da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj
46da04f3ec707985d9c6cc963c1bbe06ee6131308esewardjint
47da04f3ec707985d9c6cc963c1bbe06ee6131308esewardjmain(int argc, char *argv[])
48da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj{
49ff62002b4cf8103675514bf848f3f38bf26ba7ecsewardj    char *buf = memalign16(5);
50da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    buf[0] = 'a';
51da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    buf[1] = 'b';
52da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    buf[2] = 'c';
53da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    buf[3] = 'd';
54da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    buf[4] = '\0';
55da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj
56da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    /* --partial-loads-ok=no:  expect addr error (here) */
57da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    /* --partial-loads-ok=yes: expect no error */
58da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    if (aligned_strlen(buf) == 4)
59da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj        foo(44);
60da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj
61da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    /* --partial-loads-ok=no:  expect addr error (here) */
62da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    /* --partial-loads-ok=yes: expect value error (in my_ffsll) */
63da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    buf[4] = 'x';
64da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    if (aligned_strlen(buf) == 0)
65da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj        foo(37);
66da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj
67da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    free(buf);
68da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj
69da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    /* Also, we need to check that a completely out-of-range,
70da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj       word-sized load gives an addressing error regardless of the
71da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj       start of --partial-loads-ok=.  *And* that the resulting
72da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj       value is completely defined. */
73da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    UWord* words = malloc(3 * sizeof(UWord));
74da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    free(words);
75da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj
76da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    /* Should ALWAYS give an addr error. */
77da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    UWord  w     = words[1];
78da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj
79da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    /* Should NEVER give an error (you might expect a value one, but no.) */
80da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    if (w == 0x31415927) {
81da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj       fprintf(stderr,
82da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj               "Elvis is alive and well and living in Milton Keynes.\n");
83da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    }
84da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj
85da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj    return 0;
86da04f3ec707985d9c6cc963c1bbe06ee6131308esewardj}
87