12d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//===-- asan_asm_test.cc --------------------------------------------------===//
22d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
32d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//                     The LLVM Compiler Infrastructure
42d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
52d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// This file is distributed under the University of Illinois Open Source
62d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// License. See LICENSE.TXT for details.
72d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
82d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//===----------------------------------------------------------------------===//
92d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// This file is a part of AddressSanitizer, an address sanity checker.
112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//===----------------------------------------------------------------------===//
132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "asan_test_utils.h"
142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if defined(__linux__)
162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if defined(__x86_64__) || (defined(__i386__) && defined(__SSE2__))
182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <emmintrin.h>
202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesnamespace {
222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestemplate<typename T> void asm_write(T *ptr, T val);
242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestemplate<typename T> T asm_read(T *ptr);
252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} // End of anonymous namespace
272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // defined(__x86_64__) || (defined(__i386__) && defined(__SSE2__))
292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if defined(__x86_64__)
312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesnamespace {
332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define DECLARE_ASM_WRITE(Type, Size, Mov, Reg)        \
352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestemplate<> void asm_write<Type>(Type *ptr, Type val) { \
362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __asm__(                                             \
372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    Mov " %[val], (%[ptr])  \n\t"                      \
382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    :                                                  \
392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    : [ptr] "r" (ptr), [val] Reg (val)                 \
405d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    : "memory"                                         \
412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  );                                                   \
422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define DECLARE_ASM_READ(Type, Size, Mov, Reg)     \
452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestemplate<> Type asm_read<Type>(Type *ptr) {        \
462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  Type res;                                        \
472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __asm__(                                         \
482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    Mov " (%[ptr]), %[res]  \n\t"                  \
492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    : [res] Reg (res)                              \
502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    : [ptr] "r" (ptr)                              \
515d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    : "memory"                                     \
522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  );                                               \
532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return res;                                      \
542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesDECLARE_ASM_WRITE(U8, "8", "movq", "r");
572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesDECLARE_ASM_READ(U8, "8", "movq", "=r");
582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} // End of anonymous namespace
602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // defined(__x86_64__)
622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if defined(__i386__) && defined(__SSE2__)
642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesnamespace {
662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define DECLARE_ASM_WRITE(Type, Size, Mov, Reg)        \
682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestemplate<> void asm_write<Type>(Type *ptr, Type val) { \
692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __asm__(                                             \
702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    Mov " %[val], (%[ptr])  \n\t"                      \
712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    :                                                  \
722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    : [ptr] "r" (ptr), [val] Reg (val)                 \
735d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    : "memory"                                         \
742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  );                                                   \
752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define DECLARE_ASM_READ(Type, Size, Mov, Reg)     \
782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestemplate<> Type asm_read<Type>(Type *ptr) {        \
792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  Type res;                                        \
802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __asm__(                                         \
812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    Mov " (%[ptr]), %[res]  \n\t"                  \
822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    : [res] Reg (res)                              \
832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    : [ptr] "r" (ptr)                              \
845d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines    : "memory"                                     \
852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  );                                               \
862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return res;                                      \
872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} // End of anonymous namespace
902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // defined(__i386__) && defined(__SSE2__)
922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if defined(__x86_64__) || (defined(__i386__) && defined(__SSE2__))
942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesnamespace {
962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesDECLARE_ASM_WRITE(U1, "1", "movb", "r");
982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesDECLARE_ASM_WRITE(U2, "2", "movw", "r");
992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesDECLARE_ASM_WRITE(U4, "4", "movl", "r");
1002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesDECLARE_ASM_WRITE(__m128i, "16", "movaps", "x");
1012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesDECLARE_ASM_READ(U1, "1", "movb", "=r");
1032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesDECLARE_ASM_READ(U2, "2", "movw", "=r");
1042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesDECLARE_ASM_READ(U4, "4", "movl", "=r");
1052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesDECLARE_ASM_READ(__m128i, "16", "movaps", "=x");
1062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestemplate<typename T> void TestAsmWrite(const char *DeathPattern) {
1082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  T *buf = new T;
1092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  EXPECT_DEATH(asm_write(&buf[1], static_cast<T>(0)), DeathPattern);
1102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  T var = 0x12;
1112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  asm_write(&var, static_cast<T>(0x21));
1122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ASSERT_EQ(static_cast<T>(0x21), var);
1132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  delete buf;
1142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestemplate<> void TestAsmWrite<__m128i>(const char *DeathPattern) {
1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  char *buf = new char[16];
1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  char *p = buf + 16;
1192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (((uintptr_t) p % 16) != 0)
1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    p = buf + 8;
1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  assert(((uintptr_t) p % 16) == 0);
1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __m128i val = _mm_set1_epi16(0x1234);
1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  EXPECT_DEATH(asm_write<__m128i>((__m128i*) p, val), DeathPattern);
1242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __m128i var = _mm_set1_epi16(0x4321);
1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  asm_write(&var, val);
1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ASSERT_EQ(0x1234, _mm_extract_epi16(var, 0));
1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  delete [] buf;
1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestemplate<typename T> void TestAsmRead(const char *DeathPattern) {
1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  T *buf = new T;
1322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  EXPECT_DEATH(asm_read(&buf[1]), DeathPattern);
1332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  T var = 0x12;
1342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ASSERT_EQ(static_cast<T>(0x12), asm_read(&var));
1352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  delete buf;
1362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestemplate<> void TestAsmRead<__m128i>(const char *DeathPattern) {
1392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  char *buf = new char[16];
1402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  char *p = buf + 16;
1412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (((uintptr_t) p % 16) != 0)
1422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    p = buf + 8;
1432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  assert(((uintptr_t) p % 16) == 0);
1442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  EXPECT_DEATH(asm_read<__m128i>((__m128i*) p), DeathPattern);
1452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __m128i val = _mm_set1_epi16(0x1234);
1462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ASSERT_EQ(0x1234, _mm_extract_epi16(asm_read(&val), 0));
1472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  delete [] buf;
1482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesU4 AsmLoad(U4 *a) {
1512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  U4 r;
1522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __asm__("movl (%[a]), %[r]  \n\t" : [r] "=r" (r) : [a] "r" (a) : "memory");
1532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return r;
1542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid AsmStore(U4 r, U4 *a) {
1572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __asm__("movl %[r], (%[a])  \n\t" : : [a] "r" (a), [r] "r" (r) : "memory");
1582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} // End of anonymous namespace
1612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesTEST(AddressSanitizer, asm_load_store) {
1632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  U4* buf = new U4[2];
1642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  EXPECT_DEATH(AsmLoad(&buf[3]), "READ of size 4");
1652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  EXPECT_DEATH(AsmStore(0x1234, &buf[3]), "WRITE of size 4");
1662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  delete [] buf;
1672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesTEST(AddressSanitizer, asm_rw) {
1702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  TestAsmWrite<U1>("WRITE of size 1");
1712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  TestAsmWrite<U2>("WRITE of size 2");
1722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  TestAsmWrite<U4>("WRITE of size 4");
1735d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#if defined(__x86_64__)
1742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  TestAsmWrite<U8>("WRITE of size 8");
1755d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#endif // defined(__x86_64__)
1762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  TestAsmWrite<__m128i>("WRITE of size 16");
1772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  TestAsmRead<U1>("READ of size 1");
1792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  TestAsmRead<U2>("READ of size 2");
1802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  TestAsmRead<U4>("READ of size 4");
1815d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#if defined(__x86_64__)
1822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  TestAsmRead<U8>("READ of size 8");
1835d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines#endif // defined(__x86_64__)
1842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  TestAsmRead<__m128i>("READ of size 16");
1852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesTEST(AddressSanitizer, asm_flags) {
1882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  long magic = 0x1234;
1892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  long r = 0x0;
1902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if defined(__x86_64__)
1922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __asm__("xorq %%rax, %%rax  \n\t"
1932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          "movq (%[p]), %%rax \n\t"
1942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          "sete %%al          \n\t"
1952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          "movzbq %%al, %[r]  \n\t"
1962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          : [r] "=r"(r)
1972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          : [p] "r"(&magic)
1982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          : "rax", "memory");
1992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
2002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  __asm__("xorl %%eax, %%eax  \n\t"
2012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          "movl (%[p]), %%eax \n\t"
2022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          "sete %%al          \n\t"
2032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          "movzbl %%al, %[r]  \n\t"
2042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          : [r] "=r"(r)
2052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          : [p] "r"(&magic)
2062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          : "eax", "memory");
2072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // defined(__x86_64__)
2082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ASSERT_EQ(0x1, r);
2102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
2112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // defined(__x86_64__) || (defined(__i386__) && defined(__SSE2__))
2132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif // defined(__linux__)
215