aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
authorH.J. Lu <hongjiu.lu@intel.com>2009-07-10 12:04:14 -0700
committerUlrich Drepper <drepper@redhat.com>2009-07-10 12:04:14 -0700
commitb0ecde3a63fd3e987137aa9eb76da3b556b14559 (patch)
tree9ec97c379f41fcb36164d03ee5b852e1b3f1e59f /elf
parent786b74f41a076ac67b5d4fe59ab26e55745095df (diff)
downloadglibc-b0ecde3a63fd3e987137aa9eb76da3b556b14559.zip
glibc-b0ecde3a63fd3e987137aa9eb76da3b556b14559.tar.gz
glibc-b0ecde3a63fd3e987137aa9eb76da3b556b14559.tar.bz2
Add AVX support to ld.so auditing for x86-64.
Diffstat (limited to 'elf')
-rw-r--r--elf/Makefile22
-rw-r--r--elf/tst-audit4.c35
-rw-r--r--elf/tst-audit5.c21
-rw-r--r--elf/tst-auditmod4a.c48
-rw-r--r--elf/tst-auditmod4b.c206
-rw-r--r--elf/tst-auditmod5a.c46
-rw-r--r--elf/tst-auditmod5b.c178
7 files changed, 554 insertions, 2 deletions
diff --git a/elf/Makefile b/elf/Makefile
index 3e656ae..e4b977e 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -89,8 +89,10 @@ distribute := rtld-Rules \
unload4mod1.c unload4mod2.c unload4mod3.c unload4mod4.c \
unload6mod1.c unload6mod2.c unload6mod3.c \
unload7mod1.c unload7mod2.c \
- tst-audit1.c tst-audit2.c tst-audit3.c \
+ tst-audit1.c tst-audit2.c tst-audit3.c tst-audit4.c \
tst-auditmod1.c tst-auditmod3a.c tst-auditmod3b.c \
+ tst-auditmod4a.c tst-auditmod4b.c \
+ tst-audit5.c tst-auditmod5a.c tst-auditmod5b.c \
order2mod1.c order2mod2.c order2mod3.c order2mod4.c \
tst-stackguard1.c tst-stackguard1-static.c \
tst-array5.c tst-array5-static.c tst-array5dep.c \
@@ -198,7 +200,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
test-srcs = tst-pathopt
tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog
ifeq (x86_64,$(config-machine))
-tests += tst-audit3
+tests += tst-audit3 tst-audit4 tst-audit5
endif
endif
ifeq (yesyes,$(have-fpie)$(build-shared))
@@ -238,6 +240,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3 \
tst-dlmopen1mod tst-auditmod1 \
tst-auditmod3a tst-auditmod3b \
+ tst-auditmod4a tst-auditmod4b \
+ tst-auditmod5a tst-auditmod5b \
unload3mod1 unload3mod2 unload3mod3 unload3mod4 \
unload4mod1 unload4mod2 unload4mod3 unload4mod4 \
unload6mod1 unload6mod2 unload6mod3 \
@@ -973,6 +977,14 @@ $(objpfx)tst-audit3: $(objpfx)tst-auditmod3a.so
$(objpfx)tst-audit3.out: $(objpfx)tst-auditmod3b.so
tst-audit3-ENV = LD_AUDIT=$(objpfx)tst-auditmod3b.so
+$(objpfx)tst-audit4: $(objpfx)tst-auditmod4a.so
+$(objpfx)tst-audit4.out: $(objpfx)tst-auditmod4b.so
+tst-audit4-ENV = LD_AUDIT=$(objpfx)tst-auditmod4b.so
+
+$(objpfx)tst-audit5: $(objpfx)tst-auditmod5a.so
+$(objpfx)tst-audit5.out: $(objpfx)tst-auditmod5b.so
+tst-audit5-ENV = LD_AUDIT=$(objpfx)tst-auditmod5b.so
+
$(objpfx)tst-global1: $(libdl)
$(objpfx)tst-global1.out: $(objpfx)testobj6.so $(objpfx)testobj2.so
@@ -1115,3 +1127,9 @@ $(objpfx)tst-unique1.out: $(objpfx)tst-unique1mod1.so \
$(objpfx)tst-unique2: $(libdl) $(objpfx)tst-unique2mod1.so
$(objpfx)tst-unique2.out: $(objpfx)tst-unique2mod2.so
+
+ifeq (yes,$(config-cflags-avx))
+CFLAGS-tst-audit4.c += -mavx
+CFLAGS-tst-auditmod4a.c += -mavx
+CFLAGS-tst-auditmod4b.c += -mavx
+endif
diff --git a/elf/tst-audit4.c b/elf/tst-audit4.c
new file mode 100644
index 0000000..b17d4a6
--- /dev/null
+++ b/elf/tst-audit4.c
@@ -0,0 +1,35 @@
+/* Test case for x86-64 preserved registers in dynamic linker. */
+
+#ifdef __AVX__
+#include <stdlib.h>
+#include <string.h>
+#include <cpuid.h>
+#include <immintrin.h>
+
+extern __m256i audit_test (__m256i, __m256i, __m256i, __m256i,
+ __m256i, __m256i, __m256i, __m256i);
+int
+main (void)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ /* Run AVX test only if AVX is supported. */
+ if (__get_cpuid (1, &eax, &ebx, &ecx, &edx)
+ && (ecx & bit_AVX))
+ {
+ __m256i ymm = _mm256_setzero_si256 ();
+ __m256i ret = audit_test (ymm, ymm, ymm, ymm, ymm, ymm, ymm, ymm);
+
+ ymm = _mm256_set1_epi32 (0x12349876);
+ if (memcmp (&ymm, &ret, sizeof (ret)))
+ abort ();
+ }
+ return 0;
+}
+#else
+int
+main (void)
+{
+ return 0;
+}
+#endif
diff --git a/elf/tst-audit5.c b/elf/tst-audit5.c
new file mode 100644
index 0000000..0094fee
--- /dev/null
+++ b/elf/tst-audit5.c
@@ -0,0 +1,21 @@
+/* Test case for x86-64 preserved registers in dynamic linker. */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <emmintrin.h>
+
+extern __m128i audit_test (__m128i, __m128i, __m128i, __m128i,
+ __m128i, __m128i, __m128i, __m128i);
+int
+main (void)
+{
+ __m128i xmm = _mm_setzero_si128 ();
+ __m128i ret = audit_test (xmm, xmm, xmm, xmm, xmm, xmm, xmm, xmm);
+
+ xmm = _mm_set1_epi32 (0x12349876);
+ if (memcmp (&xmm, &ret, sizeof (ret)))
+ abort ();
+
+ return 0;
+}
diff --git a/elf/tst-auditmod4a.c b/elf/tst-auditmod4a.c
new file mode 100644
index 0000000..c9c24c0
--- /dev/null
+++ b/elf/tst-auditmod4a.c
@@ -0,0 +1,48 @@
+/* Test case for x86-64 preserved registers in dynamic linker. */
+
+#ifdef __AVX__
+#include <stdlib.h>
+#include <string.h>
+#include <immintrin.h>
+
+__m256i
+audit_test (__m256i x0, __m256i x1, __m256i x2, __m256i x3,
+ __m256i x4, __m256i x5, __m256i x6, __m256i x7)
+{
+ __m256i ymm;
+
+ ymm = _mm256_set1_epi32 (1);
+ if (memcmp (&ymm, &x0, sizeof (ymm)))
+ abort ();
+
+ ymm = _mm256_set1_epi32 (2);
+ if (memcmp (&ymm, &x1, sizeof (ymm)))
+ abort ();
+
+ ymm = _mm256_set1_epi32 (3);
+ if (memcmp (&ymm, &x2, sizeof (ymm)))
+ abort ();
+
+ ymm = _mm256_set1_epi32 (4);
+ if (memcmp (&ymm, &x3, sizeof (ymm)))
+ abort ();
+
+ ymm = _mm256_set1_epi32 (5);
+ if (memcmp (&ymm, &x4, sizeof (ymm)))
+ abort ();
+
+ ymm = _mm256_set1_epi32 (6);
+ if (memcmp (&ymm, &x5, sizeof (ymm)))
+ abort ();
+
+ ymm = _mm256_set1_epi32 (7);
+ if (memcmp (&ymm, &x6, sizeof (ymm)))
+ abort ();
+
+ ymm = _mm256_set1_epi32 (8);
+ if (memcmp (&ymm, &x7, sizeof (ymm)))
+ abort ();
+
+ return _mm256_setzero_si256 ();
+}
+#endif
diff --git a/elf/tst-auditmod4b.c b/elf/tst-auditmod4b.c
new file mode 100644
index 0000000..a6d3c6a
--- /dev/null
+++ b/elf/tst-auditmod4b.c
@@ -0,0 +1,206 @@
+/* Verify that changing AVX registers in audit library won't affect
+ function parameter passing/return. */
+
+#include <dlfcn.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <bits/wordsize.h>
+#include <gnu/lib-names.h>
+
+unsigned int
+la_version (unsigned int v)
+{
+ setlinebuf (stdout);
+
+ printf ("version: %u\n", v);
+
+ char buf[20];
+ sprintf (buf, "%u", v);
+
+ return v;
+}
+
+void
+la_activity (uintptr_t *cookie, unsigned int flag)
+{
+ if (flag == LA_ACT_CONSISTENT)
+ printf ("activity: consistent\n");
+ else if (flag == LA_ACT_ADD)
+ printf ("activity: add\n");
+ else if (flag == LA_ACT_DELETE)
+ printf ("activity: delete\n");
+ else
+ printf ("activity: unknown activity %u\n", flag);
+}
+
+char *
+la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag)
+{
+ char buf[100];
+ const char *flagstr;
+ if (flag == LA_SER_ORIG)
+ flagstr = "LA_SET_ORIG";
+ else if (flag == LA_SER_LIBPATH)
+ flagstr = "LA_SER_LIBPATH";
+ else if (flag == LA_SER_RUNPATH)
+ flagstr = "LA_SER_RUNPATH";
+ else if (flag == LA_SER_CONFIG)
+ flagstr = "LA_SER_CONFIG";
+ else if (flag == LA_SER_DEFAULT)
+ flagstr = "LA_SER_DEFAULT";
+ else if (flag == LA_SER_SECURE)
+ flagstr = "LA_SER_SECURE";
+ else
+ {
+ sprintf (buf, "unknown flag %d", flag);
+ flagstr = buf;
+ }
+ printf ("objsearch: %s, %s\n", name, flagstr);
+
+ return (char *) name;
+}
+
+unsigned int
+la_objopen (struct link_map *l, Lmid_t lmid, uintptr_t *cookie)
+{
+ printf ("objopen: %ld, %s\n", lmid, l->l_name);
+
+ return 3;
+}
+
+void
+la_preinit (uintptr_t *cookie)
+{
+ printf ("preinit\n");
+}
+
+unsigned int
+la_objclose (uintptr_t *cookie)
+{
+ printf ("objclose\n");
+ return 0;
+}
+
+uintptr_t
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, unsigned int *flags, const char *symname)
+{
+ printf ("symbind64: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
+ symname, (long int) sym->st_value, ndx, *flags);
+
+ return sym->st_value;
+}
+
+#define pltenter la_x86_64_gnu_pltenter
+#define pltexit la_x86_64_gnu_pltexit
+#define La_regs La_x86_64_regs
+#define La_retval La_x86_64_retval
+#define int_retval lrv_rax
+
+#include <tst-audit.h>
+
+#ifdef __AVX__
+#include <immintrin.h>
+#include <cpuid.h>
+
+static int avx = -1;
+
+static int
+__attribute ((always_inline))
+check_avx (void)
+{
+ if (avx == -1)
+ {
+ unsigned int eax, ebx, ecx, edx;
+
+ if (__get_cpuid (1, &eax, &ebx, &ecx, &edx)
+ && (ecx & bit_AVX))
+ avx = 1;
+ else
+ avx = 0;
+ }
+ return avx;
+}
+#else
+#include <emmintrin.h>
+#endif
+
+ElfW(Addr)
+pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, La_regs *regs, unsigned int *flags,
+ const char *symname, long int *framesizep)
+{
+ printf ("pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
+ symname, (long int) sym->st_value, ndx, *flags);
+
+#ifdef __AVX__
+ if (check_avx () && strcmp (symname, "audit_test") == 0)
+ {
+ __m256i zero = _mm256_setzero_si256 ();
+ if (memcmp (&regs->lr_vector[0], &zero, sizeof (zero))
+ || memcmp (&regs->lr_vector[1], &zero, sizeof (zero))
+ || memcmp (&regs->lr_vector[2], &zero, sizeof (zero))
+ || memcmp (&regs->lr_vector[3], &zero, sizeof (zero))
+ || memcmp (&regs->lr_vector[4], &zero, sizeof (zero))
+ || memcmp (&regs->lr_vector[5], &zero, sizeof (zero))
+ || memcmp (&regs->lr_vector[6], &zero, sizeof (zero))
+ || memcmp (&regs->lr_vector[7], &zero, sizeof (zero)))
+ abort ();
+
+ for (int i = 0; i < 8; i++)
+ regs->lr_vector[i].ymm[0]
+ = (La_x86_64_ymm) _mm256_set1_epi32 (i + 1);
+
+ __m256i ymm = _mm256_set1_epi32 (-1);
+ asm volatile ("vmovdqa %0, %%ymm0" : : "x" (ymm) : "xmm0" );
+ asm volatile ("vmovdqa %0, %%ymm1" : : "x" (ymm) : "xmm1" );
+ asm volatile ("vmovdqa %0, %%ymm2" : : "x" (ymm) : "xmm2" );
+ asm volatile ("vmovdqa %0, %%ymm3" : : "x" (ymm) : "xmm3" );
+ asm volatile ("vmovdqa %0, %%ymm4" : : "x" (ymm) : "xmm4" );
+ asm volatile ("vmovdqa %0, %%ymm5" : : "x" (ymm) : "xmm5" );
+ asm volatile ("vmovdqa %0, %%ymm6" : : "x" (ymm) : "xmm6" );
+ asm volatile ("vmovdqa %0, %%ymm7" : : "x" (ymm) : "xmm7" );
+
+ *framesizep = 1024;
+ }
+#endif
+
+ return sym->st_value;
+}
+
+unsigned int
+pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, const La_regs *inregs, La_retval *outregs,
+ const char *symname)
+{
+ printf ("pltexit: symname=%s, st_value=%#lx, ndx=%u, retval=%tu\n",
+ symname, (long int) sym->st_value, ndx, outregs->int_retval);
+
+#ifdef __AVX__
+ if (check_avx () && strcmp (symname, "audit_test") == 0)
+ {
+ __m256i zero = _mm256_setzero_si256 ();
+ if (memcmp (&outregs->lrv_vector0, &zero, sizeof (zero)))
+ abort ();
+
+ for (int i = 0; i < 8; i++)
+ {
+ __m256i ymm = _mm256_set1_epi32 (i + 1);
+ if (memcmp (&inregs->lr_vector[i], &ymm, sizeof (ymm)) != 0)
+ abort ();
+ }
+
+ outregs->lrv_vector0.ymm[0]
+ = (La_x86_64_ymm) _mm256_set1_epi32 (0x12349876);
+
+ __m256i ymm = _mm256_set1_epi32 (-1);
+ asm volatile ("vmovdqa %0, %%ymm0" : : "x" (ymm) : "xmm0" );
+ asm volatile ("vmovdqa %0, %%ymm1" : : "x" (ymm) : "xmm1" );
+ }
+#endif
+
+ return 0;
+}
diff --git a/elf/tst-auditmod5a.c b/elf/tst-auditmod5a.c
new file mode 100644
index 0000000..8511a70
--- /dev/null
+++ b/elf/tst-auditmod5a.c
@@ -0,0 +1,46 @@
+/* Test case for x86-64 preserved registers in dynamic linker. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <emmintrin.h>
+
+__m128i
+audit_test (__m128i x0, __m128i x1, __m128i x2, __m128i x3,
+ __m128i x4, __m128i x5, __m128i x6, __m128i x7)
+{
+ __m128i xmm;
+
+ xmm = _mm_set1_epi32 (1);
+ if (memcmp (&xmm, &x0, sizeof (xmm)))
+ abort ();
+
+ xmm = _mm_set1_epi32 (2);
+ if (memcmp (&xmm, &x1, sizeof (xmm)))
+ abort ();
+
+ xmm = _mm_set1_epi32 (3);
+ if (memcmp (&xmm, &x2, sizeof (xmm)))
+ abort ();
+
+ xmm = _mm_set1_epi32 (4);
+ if (memcmp (&xmm, &x3, sizeof (xmm)))
+ abort ();
+
+ xmm = _mm_set1_epi32 (5);
+ if (memcmp (&xmm, &x4, sizeof (xmm)))
+ abort ();
+
+ xmm = _mm_set1_epi32 (6);
+ if (memcmp (&xmm, &x5, sizeof (xmm)))
+ abort ();
+
+ xmm = _mm_set1_epi32 (7);
+ if (memcmp (&xmm, &x6, sizeof (xmm)))
+ abort ();
+
+ xmm = _mm_set1_epi32 (8);
+ if (memcmp (&xmm, &x7, sizeof (xmm)))
+ abort ();
+
+ return _mm_setzero_si128 ();
+}
diff --git a/elf/tst-auditmod5b.c b/elf/tst-auditmod5b.c
new file mode 100644
index 0000000..7e1e941
--- /dev/null
+++ b/elf/tst-auditmod5b.c
@@ -0,0 +1,178 @@
+/* Verify that changing xmm registers in audit library won't affect
+ function parameter passing/return. */
+
+#include <dlfcn.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <bits/wordsize.h>
+#include <gnu/lib-names.h>
+#include <emmintrin.h>
+
+unsigned int
+la_version (unsigned int v)
+{
+ setlinebuf (stdout);
+
+ printf ("version: %u\n", v);
+
+ char buf[20];
+ sprintf (buf, "%u", v);
+
+ return v;
+}
+
+void
+la_activity (uintptr_t *cookie, unsigned int flag)
+{
+ if (flag == LA_ACT_CONSISTENT)
+ printf ("activity: consistent\n");
+ else if (flag == LA_ACT_ADD)
+ printf ("activity: add\n");
+ else if (flag == LA_ACT_DELETE)
+ printf ("activity: delete\n");
+ else
+ printf ("activity: unknown activity %u\n", flag);
+}
+
+char *
+la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag)
+{
+ char buf[100];
+ const char *flagstr;
+ if (flag == LA_SER_ORIG)
+ flagstr = "LA_SET_ORIG";
+ else if (flag == LA_SER_LIBPATH)
+ flagstr = "LA_SER_LIBPATH";
+ else if (flag == LA_SER_RUNPATH)
+ flagstr = "LA_SER_RUNPATH";
+ else if (flag == LA_SER_CONFIG)
+ flagstr = "LA_SER_CONFIG";
+ else if (flag == LA_SER_DEFAULT)
+ flagstr = "LA_SER_DEFAULT";
+ else if (flag == LA_SER_SECURE)
+ flagstr = "LA_SER_SECURE";
+ else
+ {
+ sprintf (buf, "unknown flag %d", flag);
+ flagstr = buf;
+ }
+ printf ("objsearch: %s, %s\n", name, flagstr);
+
+ return (char *) name;
+}
+
+unsigned int
+la_objopen (struct link_map *l, Lmid_t lmid, uintptr_t *cookie)
+{
+ printf ("objopen: %ld, %s\n", lmid, l->l_name);
+
+ return 3;
+}
+
+void
+la_preinit (uintptr_t *cookie)
+{
+ printf ("preinit\n");
+}
+
+unsigned int
+la_objclose (uintptr_t *cookie)
+{
+ printf ("objclose\n");
+ return 0;
+}
+
+uintptr_t
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, unsigned int *flags, const char *symname)
+{
+ printf ("symbind64: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
+ symname, (long int) sym->st_value, ndx, *flags);
+
+ return sym->st_value;
+}
+
+#define pltenter la_x86_64_gnu_pltenter
+#define pltexit la_x86_64_gnu_pltexit
+#define La_regs La_x86_64_regs
+#define La_retval La_x86_64_retval
+#define int_retval lrv_rax
+
+#include <tst-audit.h>
+
+ElfW(Addr)
+pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, La_regs *regs, unsigned int *flags,
+ const char *symname, long int *framesizep)
+{
+ printf ("pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
+ symname, (long int) sym->st_value, ndx, *flags);
+
+ __m128i minusone = _mm_set1_epi32 (-1);
+
+ if (strcmp (symname, "audit_test") == 0)
+ {
+ __m128i zero = _mm_setzero_si128 ();
+ if (memcmp (&regs->lr_xmm[0], &zero, sizeof (zero))
+ || memcmp (&regs->lr_xmm[1], &zero, sizeof (zero))
+ || memcmp (&regs->lr_xmm[2], &zero, sizeof (zero))
+ || memcmp (&regs->lr_xmm[3], &zero, sizeof (zero))
+ || memcmp (&regs->lr_xmm[4], &zero, sizeof (zero))
+ || memcmp (&regs->lr_xmm[5], &zero, sizeof (zero))
+ || memcmp (&regs->lr_xmm[6], &zero, sizeof (zero))
+ || memcmp (&regs->lr_xmm[7], &zero, sizeof (zero)))
+ abort ();
+
+ for (int i = 0; i < 8; i++)
+ regs->lr_xmm[i] = (La_x86_64_xmm) _mm_set1_epi32 (i + 1);
+
+ *framesizep = 1024;
+ }
+
+ asm volatile ("movdqa %0, %%xmm0" : : "x" (minusone) : "xmm0" );
+ asm volatile ("movdqa %0, %%xmm1" : : "x" (minusone) : "xmm1" );
+ asm volatile ("movdqa %0, %%xmm2" : : "x" (minusone) : "xmm2" );
+ asm volatile ("movdqa %0, %%xmm3" : : "x" (minusone) : "xmm3" );
+ asm volatile ("movdqa %0, %%xmm4" : : "x" (minusone) : "xmm4" );
+ asm volatile ("movdqa %0, %%xmm5" : : "x" (minusone) : "xmm5" );
+ asm volatile ("movdqa %0, %%xmm6" : : "x" (minusone) : "xmm6" );
+ asm volatile ("movdqa %0, %%xmm7" : : "x" (minusone) : "xmm7" );
+
+ return sym->st_value;
+}
+
+unsigned int
+pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, const La_regs *inregs, La_retval *outregs,
+ const char *symname)
+{
+ printf ("pltexit: symname=%s, st_value=%#lx, ndx=%u, retval=%tu\n",
+ symname, (long int) sym->st_value, ndx, outregs->int_retval);
+
+ __m128i xmm;
+
+ if (strcmp (symname, "audit_test") == 0)
+ {
+ __m128i zero = _mm_setzero_si128 ();
+ if (memcmp (&outregs->lrv_xmm0, &zero, sizeof (zero)))
+ abort ();
+
+ for (int i = 0; i < 8; i++)
+ {
+ xmm = _mm_set1_epi32 (i + 1);
+ if (memcmp (&inregs->lr_xmm[i], &xmm, sizeof (xmm)) != 0)
+ abort ();
+ }
+
+ outregs->lrv_xmm0 = (La_x86_64_xmm) _mm_set1_epi32 (0x12349876);
+ }
+
+ xmm = _mm_set1_epi32 (-1);
+ asm volatile ("movdqa %0, %%xmm0" : : "x" (xmm) : "xmm0" );
+ asm volatile ("movdqa %0, %%xmm1" : : "x" (xmm) : "xmm1" );
+
+ return 0;
+}