i386: Add ABI test for __bf16 type

gcc/testsuite/ChangeLog:

	* gcc.target/x86_64/abi/bf16/abi-bf16.exp: New test.
	* gcc.target/x86_64/abi/bf16/args.h: Ditto.
	* gcc.target/x86_64/abi/bf16/asm-support.S: Ditto.
	* gcc.target/x86_64/abi/bf16/bf16-check.h: Ditto.
	* gcc.target/x86_64/abi/bf16/bf16-helper.h: Ditto.
	* gcc.target/x86_64/abi/bf16/defines.h: Ditto.
	* gcc.target/x86_64/abi/bf16/m256bf16/abi-bf16-ymm.exp: Ditto.
	* gcc.target/x86_64/abi/bf16/m256bf16/args.h: Ditto.
	* gcc.target/x86_64/abi/bf16/m256bf16/asm-support.S: Ditto.
	* gcc.target/x86_64/abi/bf16/m256bf16/bf16-ymm-check.h: Ditto.
	* gcc.target/x86_64/abi/bf16/m256bf16/test_m256_returning.c: Ditto.
	* gcc.target/x86_64/abi/bf16/m256bf16/test_passing_m256.c: Ditto.
	* gcc.target/x86_64/abi/bf16/m256bf16/test_passing_structs.c: Ditto.
	* gcc.target/x86_64/abi/bf16/m256bf16/test_passing_unions.c: Ditto.
	* gcc.target/x86_64/abi/bf16/m256bf16/test_varargs-m256.c: Ditto.
	* gcc.target/x86_64/abi/bf16/m512bf16/abi-bf16-zmm.exp: Ditto.
	* gcc.target/x86_64/abi/bf16/m512bf16/args.h: Ditto.
	* gcc.target/x86_64/abi/bf16/m512bf16/asm-support.S: Ditto.
	* gcc.target/x86_64/abi/bf16/m512bf16/bf16-zmm-check.h: Ditto.
	* gcc.target/x86_64/abi/bf16/m512bf16/test_m512_returning.c: Ditto.
	* gcc.target/x86_64/abi/bf16/m512bf16/test_passing_m512.c: Ditto.
	* gcc.target/x86_64/abi/bf16/m512bf16/test_passing_structs.c: Ditto.
	* gcc.target/x86_64/abi/bf16/m512bf16/test_passing_unions.c: Ditto.
	* gcc.target/x86_64/abi/bf16/m512bf16/test_varargs-m512.c: Ditto.
	* gcc.target/x86_64/abi/bf16/macros.h: Ditto.
	* gcc.target/x86_64/abi/bf16/test_3_element_struct_and_unions.c: Ditto.
	* gcc.target/x86_64/abi/bf16/test_basic_alignment.c: Ditto.
	* gcc.target/x86_64/abi/bf16/test_basic_array_size_and_align.c: Ditto.
	* gcc.target/x86_64/abi/bf16/test_basic_returning.c: Ditto.
	* gcc.target/x86_64/abi/bf16/test_basic_sizes.c: Ditto.
	* gcc.target/x86_64/abi/bf16/test_basic_struct_size_and_align.c: Ditto.
	* gcc.target/x86_64/abi/bf16/test_basic_union_size_and_align.c: Ditto.
	* gcc.target/x86_64/abi/bf16/test_m128_returning.c: Ditto.
	* gcc.target/x86_64/abi/bf16/test_passing_floats.c: Ditto.
	* gcc.target/x86_64/abi/bf16/test_passing_m128.c: Ditto.
	* gcc.target/x86_64/abi/bf16/test_passing_structs.c: Ditto.
	* gcc.target/x86_64/abi/bf16/test_passing_unions.c: Ditto.
	* gcc.target/x86_64/abi/bf16/test_struct_returning.c: Ditto.
	* gcc.target/x86_64/abi/bf16/test_varargs-m128.c: Ditto.
This commit is contained in:
Haochen Jiang 2022-06-23 14:16:43 +08:00
parent 30afe5e763
commit 86c0d98620
39 changed files with 3933 additions and 0 deletions

View File

@ -0,0 +1,46 @@
# Copyright (C) 2022 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
# The x86-64 ABI testsuite needs one additional assembler file for most
# testcases. For simplicity we will just link it into each test.
load_lib c-torture.exp
load_lib target-supports.exp
load_lib torture-options.exp
load_lib clearcap.exp
if { (![istarget x86_64-*-*] && ![istarget i?86-*-*])
|| ![is-effective-target lp64]
|| ![is-effective-target sse2] } then {
return
}
torture-init
clearcap-init
set-torture-options $C_TORTURE_OPTIONS
set additional_flags "-W -Wall -msse2"
foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] {
if {[runtest_file_p $runtests $src]} {
c-torture-execute [list $src \
$srcdir/$subdir/asm-support.S] \
$additional_flags
}
}
clearcap-finish
torture-finish

View File

@ -0,0 +1,164 @@
#ifndef INCLUDED_ARGS_H
#define INCLUDED_ARGS_H
#include <string.h>
/* This defines the calling sequences for integers and floats. */
#define I0 rdi
#define I1 rsi
#define I2 rdx
#define I3 rcx
#define I4 r8
#define I5 r9
#define F0 xmm0
#define F1 xmm1
#define F2 xmm2
#define F3 xmm3
#define F4 xmm4
#define F5 xmm5
#define F6 xmm6
#define F7 xmm7
typedef union {
__bf16 ___bf16[8];
float _float[4];
double _double[2];
long long _longlong[2];
int _int[4];
ulonglong _ulonglong[2];
#ifdef CHECK_M64_M128
__m64 _m64[2];
__m128 _m128[1];
__m128bf16 _m128bf16[1];
#endif
} XMM_T;
typedef union {
__bf16 ___bf16;
float _float;
double _double;
ldouble _ldouble;
ulonglong _ulonglong[2];
} X87_T;
extern void (*callthis)(void);
extern unsigned long long rax,rbx,rcx,rdx,rsi,rdi,rsp,rbp,r8,r9,r10,r11,r12,r13,r14,r15;
XMM_T xmm_regs[16];
X87_T x87_regs[8];
extern volatile unsigned long long volatile_var;
extern void snapshot (void);
extern void snapshot_ret (void);
#define WRAP_CALL(N) \
(callthis = (void (*)()) (N), (typeof (&N)) snapshot)
#define WRAP_RET(N) \
(callthis = (void (*)()) (N), (typeof (&N)) snapshot_ret)
/* Clear all integer registers. */
#define clear_int_hardware_registers \
asm __volatile__ ("xor %%rax, %%rax\n\t" \
"xor %%rbx, %%rbx\n\t" \
"xor %%rcx, %%rcx\n\t" \
"xor %%rdx, %%rdx\n\t" \
"xor %%rsi, %%rsi\n\t" \
"xor %%rdi, %%rdi\n\t" \
"xor %%r8, %%r8\n\t" \
"xor %%r9, %%r9\n\t" \
"xor %%r10, %%r10\n\t" \
"xor %%r11, %%r11\n\t" \
"xor %%r12, %%r12\n\t" \
"xor %%r13, %%r13\n\t" \
"xor %%r14, %%r14\n\t" \
"xor %%r15, %%r15\n\t" \
::: "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", \
"r9", "r10", "r11", "r12", "r13", "r14", "r15");
/* This is the list of registers available for passing arguments. Not all of
these are used or even really available. */
struct IntegerRegisters
{
unsigned long long rax, rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15;
};
struct FloatRegisters
{
double mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7;
ldouble st0, st1, st2, st3, st4, st5, st6, st7;
XMM_T xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9,
xmm10, xmm11, xmm12, xmm13, xmm14, xmm15;
};
/* Implemented in scalarargs.c */
extern struct IntegerRegisters iregs;
extern struct FloatRegisters fregs;
extern unsigned int num_iregs, num_fregs;
/* Clear register struct. */
#define clear_struct_registers \
rax = rbx = rcx = rdx = rdi = rsi = rbp = rsp \
= r8 = r9 = r10 = r11 = r12 = r13 = r14 = r15 = 0; \
memset (&iregs, 0, sizeof (iregs)); \
memset (&fregs, 0, sizeof (fregs)); \
memset (xmm_regs, 0, sizeof (xmm_regs)); \
memset (x87_regs, 0, sizeof (x87_regs));
/* Clear both hardware and register structs for integers. */
#define clear_int_registers \
clear_struct_registers \
clear_int_hardware_registers
/* Do the checking. */
#define check_f_arguments(T) do { \
assert (num_fregs <= 0 || check_bf16 (fregs.xmm0._ ## T [0], xmm_regs[0]._ ## T [0]) == 1); \
assert (num_fregs <= 1 || check_bf16 (fregs.xmm1._ ## T [0], xmm_regs[1]._ ## T [0]) == 1); \
assert (num_fregs <= 2 || check_bf16 (fregs.xmm2._ ## T [0], xmm_regs[2]._ ## T [0]) == 1); \
assert (num_fregs <= 3 || check_bf16 (fregs.xmm3._ ## T [0], xmm_regs[3]._ ## T [0]) == 1); \
assert (num_fregs <= 4 || check_bf16 (fregs.xmm4._ ## T [0], xmm_regs[4]._ ## T [0]) == 1); \
assert (num_fregs <= 5 || check_bf16 (fregs.xmm5._ ## T [0], xmm_regs[5]._ ## T [0]) == 1); \
assert (num_fregs <= 6 || check_bf16 (fregs.xmm6._ ## T [0], xmm_regs[6]._ ## T [0]) == 1); \
assert (num_fregs <= 7 || check_bf16 (fregs.xmm7._ ## T [0], xmm_regs[7]._ ## T [0]) == 1); \
} while (0)
#define check_bf16_arguments check_f_arguments(__bf16)
#define check_vector_arguments(T,O) do { \
assert (num_fregs <= 0 \
|| memcmp (((char *) &fregs.xmm0) + (O), \
&xmm_regs[0], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 1 \
|| memcmp (((char *) &fregs.xmm1) + (O), \
&xmm_regs[1], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 2 \
|| memcmp (((char *) &fregs.xmm2) + (O), \
&xmm_regs[2], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 3 \
|| memcmp (((char *) &fregs.xmm3) + (O), \
&xmm_regs[3], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 4 \
|| memcmp (((char *) &fregs.xmm4) + (O), \
&xmm_regs[4], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 5 \
|| memcmp (((char *) &fregs.xmm5) + (O), \
&xmm_regs[5], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 6 \
|| memcmp (((char *) &fregs.xmm6) + (O), \
&xmm_regs[6], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 7 \
|| memcmp (((char *) &fregs.xmm7) + (O), \
&xmm_regs[7], \
sizeof (__ ## T) - (O)) == 0); \
} while (0)
#define check_m128_arguments check_vector_arguments(m128, 0)
#define clear_float_registers \
clear_struct_registers
#define clear_x87_registers \
clear_struct_registers
#endif /* INCLUDED_ARGS_H */

View File

@ -0,0 +1,84 @@
.text
.p2align 4,,15
.globl snapshot
.type snapshot, @function
snapshot:
.LFB3:
movq %rax, rax(%rip)
movq %rbx, rbx(%rip)
movq %rcx, rcx(%rip)
movq %rdx, rdx(%rip)
movq %rdi, rdi(%rip)
movq %rsi, rsi(%rip)
movq %rbp, rbp(%rip)
movq %rsp, rsp(%rip)
movq %r8, r8(%rip)
movq %r9, r9(%rip)
movq %r10, r10(%rip)
movq %r11, r11(%rip)
movq %r12, r12(%rip)
movq %r13, r13(%rip)
movq %r14, r14(%rip)
movq %r15, r15(%rip)
vmovdqu %xmm0, xmm_regs+0(%rip)
vmovdqu %xmm1, xmm_regs+16(%rip)
vmovdqu %xmm2, xmm_regs+32(%rip)
vmovdqu %xmm3, xmm_regs+48(%rip)
vmovdqu %xmm4, xmm_regs+64(%rip)
vmovdqu %xmm5, xmm_regs+80(%rip)
vmovdqu %xmm6, xmm_regs+96(%rip)
vmovdqu %xmm7, xmm_regs+112(%rip)
vmovdqu %xmm8, xmm_regs+128(%rip)
vmovdqu %xmm9, xmm_regs+144(%rip)
vmovdqu %xmm10, xmm_regs+160(%rip)
vmovdqu %xmm11, xmm_regs+176(%rip)
vmovdqu %xmm12, xmm_regs+192(%rip)
vmovdqu %xmm13, xmm_regs+208(%rip)
vmovdqu %xmm14, xmm_regs+224(%rip)
vmovdqu %xmm15, xmm_regs+240(%rip)
jmp *callthis(%rip)
.LFE3:
.size snapshot, .-snapshot
.p2align 4,,15
.globl snapshot_ret
.type snapshot_ret, @function
snapshot_ret:
movq %rdi, rdi(%rip)
subq $8, %rsp
call *callthis(%rip)
addq $8, %rsp
movq %rax, rax(%rip)
movq %rdx, rdx(%rip)
vmovdqu %xmm0, xmm_regs+0(%rip)
vmovdqu %xmm1, xmm_regs+16(%rip)
fstpt x87_regs(%rip)
fstpt x87_regs+16(%rip)
fldt x87_regs+16(%rip)
fldt x87_regs(%rip)
ret
.size snapshot_ret, .-snapshot_ret
.comm callthis,8,8
.comm rax,8,8
.comm rbx,8,8
.comm rcx,8,8
.comm rdx,8,8
.comm rsi,8,8
.comm rdi,8,8
.comm rsp,8,8
.comm rbp,8,8
.comm r8,8,8
.comm r9,8,8
.comm r10,8,8
.comm r11,8,8
.comm r12,8,8
.comm r13,8,8
.comm r14,8,8
.comm r15,8,8
.comm xmm_regs,256,32
.comm x87_regs,128,32
.comm volatile_var,8,8
#ifdef __linux__
.section .note.GNU-stack,"",@progbits
#endif

View File

@ -0,0 +1,24 @@
#include <stdlib.h>
#include "bf16-helper.h"
static void do_test (void);
int
main ()
{
if (__builtin_cpu_supports ("sse2"))
{
do_test ();
#ifdef DEBUG
printf ("PASSED\n");
#endif
return 0;
}
#ifdef DEBUG
printf ("SKIPPED\n");
#endif
return 0;
}

View File

@ -0,0 +1,41 @@
typedef union
{
float f;
unsigned int u;
__bf16 b[2];
} unionf_b;
static __bf16 make_f32_bf16 (float f)
{
unionf_b tmp;
tmp.f = f;
return tmp.b[1];
}
static float make_bf16_f32 (__bf16 bf)
{
unionf_b tmp;
tmp.u = 0;
tmp.b[1] = bf;
return tmp.f;
}
static int check_bf16 (__bf16 bf1, __bf16 bf2)
{
unionf_b tmp1, tmp2;
tmp1.u = 0;
tmp2.u = 0;
tmp1.b[1] = bf1;
tmp2.b[1] = bf2;
return (tmp1.u == tmp2.u);
}
static int check_bf16_float (__bf16 bf, float f)
{
unionf_b tmp1, tmp2;
tmp1.u = 0;
tmp1.b[0] = bf;
tmp2.f = f;
tmp2.u >>= 16;
return (tmp1.u == tmp2.u);
}

View File

@ -0,0 +1,163 @@
#ifndef DEFINED_DEFINES_H
#define DEFINED_DEFINES_H
/* Get __m64 and __m128. */
#include <immintrin.h>
typedef unsigned long long ulonglong;
typedef long double ldouble;
/* These defines determines what part of the test should be run. When
GCC implements these parts, the defines should be uncommented to
enable testing. */
/* Scalar type __int128. */
/* #define CHECK_INT128 */
/* Scalar type long double. */
#define CHECK_LONG_DOUBLE
/* Scalar type __float128. */
/* #define CHECK_FLOAT128 */
/* Scalar types __m64 and __m128. */
#define CHECK_M64_M128
/* Structs with size >= 16. */
#define CHECK_LARGER_STRUCTS
/* Checks for passing floats and doubles. */
#define CHECK_FLOAT_DOUBLE_PASSING
/* Union passing with not-extremely-simple unions. */
#define CHECK_LARGER_UNION_PASSING
/* Variable args. */
#define CHECK_VARARGS
/* Check argument passing and returning for scalar types with sizeof = 16. */
/* TODO: Implement these tests. Don't activate them for now. */
#define CHECK_LARGE_SCALAR_PASSING
/* Defines for sizing and alignment. */
#define TYPE_SIZE_CHAR 1
#define TYPE_SIZE_SHORT 2
#define TYPE_SIZE_INT 4
#ifdef __ILP32__
# define TYPE_SIZE_LONG 4
#else
# define TYPE_SIZE_LONG 8
#endif
#define TYPE_SIZE_LONG_LONG 8
#define TYPE_SIZE_INT128 16
#define TYPE_SIZE_BF16 2
#define TYPE_SIZE_FLOAT 4
#define TYPE_SIZE_DOUBLE 8
#define TYPE_SIZE_LONG_DOUBLE 16
#define TYPE_SIZE_FLOAT128 16
#define TYPE_SIZE_M64 8
#define TYPE_SIZE_M128 16
#define TYPE_SIZE_ENUM 4
#ifdef __ILP32__
# define TYPE_SIZE_POINTER 4
#else
# define TYPE_SIZE_POINTER 8
#endif
#define TYPE_ALIGN_CHAR 1
#define TYPE_ALIGN_SHORT 2
#define TYPE_ALIGN_INT 4
#ifdef __ILP32__
# define TYPE_ALIGN_LONG 4
#else
# define TYPE_ALIGN_LONG 8
#endif
#define TYPE_ALIGN_LONG_LONG 8
#define TYPE_ALIGN_INT128 16
#define TYPE_ALIGN_BF16 2
#define TYPE_ALIGN_FLOAT 4
#define TYPE_ALIGN_DOUBLE 8
#define TYPE_ALIGN_LONG_DOUBLE 16
#define TYPE_ALIGN_FLOAT128 16
#define TYPE_ALIGN_M64 8
#define TYPE_ALIGN_M128 16
#define TYPE_ALIGN_ENUM 4
#ifdef __ILP32__
# define TYPE_ALIGN_POINTER 4
#else
# define TYPE_ALIGN_POINTER 8
#endif
/* These defines control the building of the list of types to check. There
is a string identifying the type (with a comma after), a size of the type
(also with a comma and an integer for adding to the total amount of types)
and an alignment of the type (which is currently not really needed since
the abi specifies that alignof == sizeof for all scalar types). */
#ifdef CHECK_INT128
#define CI128_STR "__int128",
#define CI128_SIZ TYPE_SIZE_INT128,
#define CI128_ALI TYPE_ALIGN_INT128,
#define CI128_RET "???",
#else
#define CI128_STR
#define CI128_SIZ
#define CI128_ALI
#define CI128_RET
#endif
#ifdef CHECK_LONG_DOUBLE
#define CLD_STR "long double",
#define CLD_SIZ TYPE_SIZE_LONG_DOUBLE,
#define CLD_ALI TYPE_ALIGN_LONG_DOUBLE,
#define CLD_RET "x87_regs[0]._ldouble",
#else
#define CLD_STR
#define CLD_SIZ
#define CLD_ALI
#define CLD_RET
#endif
#ifdef CHECK_FLOAT128
#define CF128_STR "__float128",
#define CF128_SIZ TYPE_SIZE_FLOAT128,
#define CF128_ALI TYPE_ALIGN_FLOAT128,
#define CF128_RET "???",
#else
#define CF128_STR
#define CF128_SIZ
#define CF128_ALI
#define CF128_RET
#endif
#ifdef CHECK_M64_M128
#define CMM_STR "__m64", "__m128",
#define CMM_SIZ TYPE_SIZE_M64, TYPE_SIZE_M128,
#define CMM_ALI TYPE_ALIGN_M64, TYPE_ALIGN_M128,
#define CMM_RET "???", "???",
#else
#define CMM_STR
#define CMM_SIZ
#define CMM_ALI
#define CMM_RET
#endif
/* Used in size and alignment tests. */
enum dummytype { enumtype };
extern void abort (void);
/* Assertion macro. */
#define assert(test) if (!(test)) abort()
#ifdef __GNUC__
#define ATTRIBUTE_UNUSED __attribute__((__unused__))
#else
#define ATTRIBUTE_UNUSED
#endif
#ifdef __GNUC__
#define PACKED __attribute__((__packed__))
#else
#warning Some tests will fail due to missing __packed__ support
#define PACKED
#endif
#endif /* DEFINED_DEFINES_H */

View File

@ -0,0 +1,46 @@
# Copyright (C) 2022 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
# The x86-64 ABI testsuite needs one additional assembler file for most
# testcases. For simplicity we will just link it into each test.
load_lib c-torture.exp
load_lib target-supports.exp
load_lib torture-options.exp
load_lib clearcap.exp
if { (![istarget x86_64-*-*] && ![istarget i?86-*-*])
|| ![is-effective-target lp64]
|| ![is-effective-target avx2] } then {
return
}
torture-init
clearcap-init
set-torture-options $C_TORTURE_OPTIONS
set additional_flags "-W -Wall -mavx2"
foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] {
if {[runtest_file_p $runtests $src]} {
c-torture-execute [list $src \
$srcdir/$subdir/asm-support.S] \
$additional_flags
}
}
clearcap-finish
torture-finish

View File

@ -0,0 +1,152 @@
#ifndef INCLUDED_ARGS_H
#define INCLUDED_ARGS_H
#include <immintrin.h>
#include <string.h>
/* Assertion macro. */
#define assert(test) if (!(test)) abort()
#ifdef __GNUC__
#define ATTRIBUTE_UNUSED __attribute__((__unused__))
#else
#define ATTRIBUTE_UNUSED
#endif
/* This defines the calling sequences for integers and floats. */
#define I0 rdi
#define I1 rsi
#define I2 rdx
#define I3 rcx
#define I4 r8
#define I5 r9
#define F0 ymm0
#define F1 ymm1
#define F2 ymm2
#define F3 ymm3
#define F4 ymm4
#define F5 ymm5
#define F6 ymm6
#define F7 ymm7
typedef union {
__bf16 ___bf16[16];
float _float[8];
double _double[4];
long long _longlong[4];
int _int[8];
unsigned long long _ulonglong[4];
__m64 _m64[4];
__m128 _m128[2];
__m256 _m256[1];
__m256bf16 _m256bf16[1];
} YMM_T;
typedef union {
float _float;
double _double;
long double _ldouble;
unsigned long long _ulonglong[2];
} X87_T;
extern void (*callthis)(void);
extern unsigned long long rax,rbx,rcx,rdx,rsi,rdi,rsp,rbp,r8,r9,r10,r11,r12,r13,r14,r15;
YMM_T ymm_regs[16];
X87_T x87_regs[8];
extern volatile unsigned long long volatile_var;
extern void snapshot (void);
extern void snapshot_ret (void);
#define WRAP_CALL(N) \
(callthis = (void (*)()) (N), (typeof (&N)) snapshot)
#define WRAP_RET(N) \
(callthis = (void (*)()) (N), (typeof (&N)) snapshot_ret)
/* Clear all integer registers. */
#define clear_int_hardware_registers \
asm __volatile__ ("xor %%rax, %%rax\n\t" \
"xor %%rbx, %%rbx\n\t" \
"xor %%rcx, %%rcx\n\t" \
"xor %%rdx, %%rdx\n\t" \
"xor %%rsi, %%rsi\n\t" \
"xor %%rdi, %%rdi\n\t" \
"xor %%r8, %%r8\n\t" \
"xor %%r9, %%r9\n\t" \
"xor %%r10, %%r10\n\t" \
"xor %%r11, %%r11\n\t" \
"xor %%r12, %%r12\n\t" \
"xor %%r13, %%r13\n\t" \
"xor %%r14, %%r14\n\t" \
"xor %%r15, %%r15\n\t" \
::: "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", \
"r9", "r10", "r11", "r12", "r13", "r14", "r15");
/* This is the list of registers available for passing arguments. Not all of
these are used or even really available. */
struct IntegerRegisters
{
unsigned long long rax, rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15;
};
struct FloatRegisters
{
double mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7;
long double st0, st1, st2, st3, st4, st5, st6, st7;
YMM_T ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7, ymm8, ymm9,
ymm10, ymm11, ymm12, ymm13, ymm14, ymm15;
};
/* Implemented in scalarargs.c */
extern struct IntegerRegisters iregs;
extern struct FloatRegisters fregs;
extern unsigned int num_iregs, num_fregs;
/* Clear register struct. */
#define clear_struct_registers \
rax = rbx = rcx = rdx = rdi = rsi = rbp = rsp \
= r8 = r9 = r10 = r11 = r12 = r13 = r14 = r15 = 0; \
memset (&iregs, 0, sizeof (iregs)); \
memset (&fregs, 0, sizeof (fregs)); \
memset (ymm_regs, 0, sizeof (ymm_regs)); \
memset (x87_regs, 0, sizeof (x87_regs));
/* Clear both hardware and register structs for integers. */
#define clear_int_registers \
clear_struct_registers \
clear_int_hardware_registers
#define check_vector_arguments(T,O) do { \
assert (num_fregs <= 0 \
|| memcmp (((char *) &fregs.ymm0) + (O), \
&ymm_regs[0], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 1 \
|| memcmp (((char *) &fregs.ymm1) + (O), \
&ymm_regs[1], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 2 \
|| memcmp (((char *) &fregs.ymm2) + (O), \
&ymm_regs[2], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 3 \
|| memcmp (((char *) &fregs.ymm3) + (O), \
&ymm_regs[3], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 4 \
|| memcmp (((char *) &fregs.ymm4) + (O), \
&ymm_regs[4], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 5 \
|| memcmp (((char *) &fregs.ymm5) + (O), \
&ymm_regs[5], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 6 \
|| memcmp (((char *) &fregs.ymm6) + (O), \
&ymm_regs[6], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 7 \
|| memcmp (((char *) &fregs.ymm7) + (O), \
&ymm_regs[7], \
sizeof (__ ## T) - (O)) == 0); \
} while (0)
#define check_m256_arguments check_vector_arguments(m256, 0)
#endif /* INCLUDED_ARGS_H */

View File

@ -0,0 +1,84 @@
.text
.p2align 4,,15
.globl snapshot
.type snapshot, @function
snapshot:
.LFB3:
movq %rax, rax(%rip)
movq %rbx, rbx(%rip)
movq %rcx, rcx(%rip)
movq %rdx, rdx(%rip)
movq %rdi, rdi(%rip)
movq %rsi, rsi(%rip)
movq %rbp, rbp(%rip)
movq %rsp, rsp(%rip)
movq %r8, r8(%rip)
movq %r9, r9(%rip)
movq %r10, r10(%rip)
movq %r11, r11(%rip)
movq %r12, r12(%rip)
movq %r13, r13(%rip)
movq %r14, r14(%rip)
movq %r15, r15(%rip)
vmovdqu %ymm0, ymm_regs+0(%rip)
vmovdqu %ymm1, ymm_regs+32(%rip)
vmovdqu %ymm2, ymm_regs+64(%rip)
vmovdqu %ymm3, ymm_regs+96(%rip)
vmovdqu %ymm4, ymm_regs+128(%rip)
vmovdqu %ymm5, ymm_regs+160(%rip)
vmovdqu %ymm6, ymm_regs+192(%rip)
vmovdqu %ymm7, ymm_regs+224(%rip)
vmovdqu %ymm8, ymm_regs+256(%rip)
vmovdqu %ymm9, ymm_regs+288(%rip)
vmovdqu %ymm10, ymm_regs+320(%rip)
vmovdqu %ymm11, ymm_regs+352(%rip)
vmovdqu %ymm12, ymm_regs+384(%rip)
vmovdqu %ymm13, ymm_regs+416(%rip)
vmovdqu %ymm14, ymm_regs+448(%rip)
vmovdqu %ymm15, ymm_regs+480(%rip)
jmp *callthis(%rip)
.LFE3:
.size snapshot, .-snapshot
.p2align 4,,15
.globl snapshot_ret
.type snapshot_ret, @function
snapshot_ret:
movq %rdi, rdi(%rip)
subq $8, %rsp
call *callthis(%rip)
addq $8, %rsp
movq %rax, rax(%rip)
movq %rdx, rdx(%rip)
vmovdqu %ymm0, ymm_regs+0(%rip)
vmovdqu %ymm1, ymm_regs+32(%rip)
fstpt x87_regs(%rip)
fstpt x87_regs+16(%rip)
fldt x87_regs+16(%rip)
fldt x87_regs(%rip)
ret
.size snapshot_ret, .-snapshot_ret
.comm callthis,8,8
.comm rax,8,8
.comm rbx,8,8
.comm rcx,8,8
.comm rdx,8,8
.comm rsi,8,8
.comm rdi,8,8
.comm rsp,8,8
.comm rbp,8,8
.comm r8,8,8
.comm r9,8,8
.comm r10,8,8
.comm r11,8,8
.comm r12,8,8
.comm r13,8,8
.comm r14,8,8
.comm r15,8,8
.comm ymm_regs,512,32
.comm x87_regs,128,32
.comm volatile_var,8,8
#ifdef __linux__
.section .note.GNU-stack,"",@progbits
#endif

View File

@ -0,0 +1,24 @@
#include <stdlib.h>
#include "../bf16-helper.h"
static void do_test (void);
int
main ()
{
if (__builtin_cpu_supports ("avx2"))
{
do_test ();
#ifdef DEBUG
printf ("PASSED\n");
#endif
return 0;
}
#ifdef DEBUG
printf ("SKIPPED\n");
#endif
return 0;
}

View File

@ -0,0 +1,38 @@
#include <stdio.h>
#include "bf16-ymm-check.h"
#include "args.h"
struct FloatRegisters fregs;
struct IntegerRegisters iregs;
unsigned int num_fregs, num_iregs;
volatile __bf16 bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16;
__m256bf16
fun_test_returning___m256bf16 (void)
{
volatile_var++;
return (__m256bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16};
}
__m256bf16 test_256bf16;
static void
do_test (void)
{
unsigned failed = 0;
YMM_T ymmt1, ymmt2;
clear_struct_registers;
test_256bf16 = (__m256bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16};
ymmt1._m256bf16[0] = test_256bf16;
ymmt2._m256bf16[0] = WRAP_RET (fun_test_returning___m256bf16) ();
if (memcmp (&ymmt1, &ymmt2, sizeof (ymmt2)) != 0)
printf ("fail m256bf16\n"), failed++;
if (failed)
abort ();
}

View File

@ -0,0 +1,235 @@
#include <stdio.h>
#include "bf16-ymm-check.h"
#include "args.h"
struct IntegerRegisters iregs;
struct FloatRegisters fregs;
unsigned int num_iregs, num_fregs;
/* This struct holds values for argument checking. */
struct
{
YMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15,
i16, i17, i18, i19, i20, i21, i22, i23;
} values;
char *pass;
int failed = 0;
#undef assert
#define assert(c) do { \
if (!(c)) {failed++; printf ("failed %s\n", pass); } \
} while (0)
#define compare(X1,X2,T) do { \
assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
} while (0)
fun_check_passing_m256bf16_8_values (__m256bf16 i0 ATTRIBUTE_UNUSED,
__m256bf16 i1 ATTRIBUTE_UNUSED,
__m256bf16 i2 ATTRIBUTE_UNUSED,
__m256bf16 i3 ATTRIBUTE_UNUSED,
__m256bf16 i4 ATTRIBUTE_UNUSED,
__m256bf16 i5 ATTRIBUTE_UNUSED,
__m256bf16 i6 ATTRIBUTE_UNUSED,
__m256bf16 i7 ATTRIBUTE_UNUSED)
{
/* Check argument values. */
compare (values.i0, i0, __m256bf16);
compare (values.i1, i1, __m256bf16);
compare (values.i2, i2, __m256bf16);
compare (values.i3, i3, __m256bf16);
compare (values.i4, i4, __m256bf16);
compare (values.i5, i5, __m256bf16);
compare (values.i6, i6, __m256bf16);
compare (values.i7, i7, __m256bf16);
}
void
fun_check_passing_m256bf16_8_regs (__m256bf16 i0 ATTRIBUTE_UNUSED,
__m256bf16 i1 ATTRIBUTE_UNUSED,
__m256bf16 i2 ATTRIBUTE_UNUSED,
__m256bf16 i3 ATTRIBUTE_UNUSED,
__m256bf16 i4 ATTRIBUTE_UNUSED,
__m256bf16 i5 ATTRIBUTE_UNUSED,
__m256bf16 i6 ATTRIBUTE_UNUSED,
__m256bf16 i7 ATTRIBUTE_UNUSED)
{
/* Check register contents. */
check_m256_arguments;
}
void
fun_check_passing_m256bf16_20_values (__m256bf16 i0 ATTRIBUTE_UNUSED,
__m256bf16 i1 ATTRIBUTE_UNUSED,
__m256bf16 i2 ATTRIBUTE_UNUSED,
__m256bf16 i3 ATTRIBUTE_UNUSED,
__m256bf16 i4 ATTRIBUTE_UNUSED,
__m256bf16 i5 ATTRIBUTE_UNUSED,
__m256bf16 i6 ATTRIBUTE_UNUSED,
__m256bf16 i7 ATTRIBUTE_UNUSED,
__m256bf16 i8 ATTRIBUTE_UNUSED,
__m256bf16 i9 ATTRIBUTE_UNUSED,
__m256bf16 i10 ATTRIBUTE_UNUSED,
__m256bf16 i11 ATTRIBUTE_UNUSED,
__m256bf16 i12 ATTRIBUTE_UNUSED,
__m256bf16 i13 ATTRIBUTE_UNUSED,
__m256bf16 i14 ATTRIBUTE_UNUSED,
__m256bf16 i15 ATTRIBUTE_UNUSED,
__m256bf16 i16 ATTRIBUTE_UNUSED,
__m256bf16 i17 ATTRIBUTE_UNUSED,
__m256bf16 i18 ATTRIBUTE_UNUSED,
__m256bf16 i19 ATTRIBUTE_UNUSED)
{
/* Check argument values. */
compare (values.i0, i0, __m256bf16);
compare (values.i1, i1, __m256bf16);
compare (values.i2, i2, __m256bf16);
compare (values.i3, i3, __m256bf16);
compare (values.i4, i4, __m256bf16);
compare (values.i5, i5, __m256bf16);
compare (values.i6, i6, __m256bf16);
compare (values.i7, i7, __m256bf16);
compare (values.i8, i8, __m256bf16);
compare (values.i9, i9, __m256bf16);
compare (values.i10, i10, __m256bf16);
compare (values.i11, i11, __m256bf16);
compare (values.i12, i12, __m256bf16);
compare (values.i13, i13, __m256bf16);
compare (values.i14, i14, __m256bf16);
compare (values.i15, i15, __m256bf16);
compare (values.i16, i16, __m256bf16);
compare (values.i17, i17, __m256bf16);
compare (values.i18, i18, __m256bf16);
compare (values.i19, i19, __m256bf16);
}
void
fun_check_passing_m256bf16_20_regs (__m256bf16 i0 ATTRIBUTE_UNUSED,
__m256bf16 i1 ATTRIBUTE_UNUSED,
__m256bf16 i2 ATTRIBUTE_UNUSED,
__m256bf16 i3 ATTRIBUTE_UNUSED,
__m256bf16 i4 ATTRIBUTE_UNUSED,
__m256bf16 i5 ATTRIBUTE_UNUSED,
__m256bf16 i6 ATTRIBUTE_UNUSED,
__m256bf16 i7 ATTRIBUTE_UNUSED,
__m256bf16 i8 ATTRIBUTE_UNUSED,
__m256bf16 i9 ATTRIBUTE_UNUSED,
__m256bf16 i10 ATTRIBUTE_UNUSED,
__m256bf16 i11 ATTRIBUTE_UNUSED,
__m256bf16 i12 ATTRIBUTE_UNUSED,
__m256bf16 i13 ATTRIBUTE_UNUSED,
__m256bf16 i14 ATTRIBUTE_UNUSED,
__m256bf16 i15 ATTRIBUTE_UNUSED,
__m256bf16 i16 ATTRIBUTE_UNUSED,
__m256bf16 i17 ATTRIBUTE_UNUSED,
__m256bf16 i18 ATTRIBUTE_UNUSED,
__m256bf16 i19 ATTRIBUTE_UNUSED)
{
/* Check register contents. */
check_m256_arguments;
}
#define def_check_passing8(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _func1, _func2, TYPE) \
values.i0.TYPE[0] = _i0; \
values.i1.TYPE[0] = _i1; \
values.i2.TYPE[0] = _i2; \
values.i3.TYPE[0] = _i3; \
values.i4.TYPE[0] = _i4; \
values.i5.TYPE[0] = _i5; \
values.i6.TYPE[0] = _i6; \
values.i7.TYPE[0] = _i7; \
WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7); \
clear_struct_registers; \
fregs.F0.TYPE[0] = _i0; \
fregs.F1.TYPE[0] = _i1; \
fregs.F2.TYPE[0] = _i2; \
fregs.F3.TYPE[0] = _i3; \
fregs.F4.TYPE[0] = _i4; \
fregs.F5.TYPE[0] = _i5; \
fregs.F6.TYPE[0] = _i6; \
fregs.F7.TYPE[0] = _i7; \
num_fregs = 8; \
WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7);
#define def_check_passing20(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
_i8, _i9, _i10, _i11, _i12, _i13, _i14, \
_i15, _i16, _i17, _i18, _i19, _func1, \
_func2, TYPE) \
values.i0.TYPE[0] = _i0; \
values.i1.TYPE[0] = _i1; \
values.i2.TYPE[0] = _i2; \
values.i3.TYPE[0] = _i3; \
values.i4.TYPE[0] = _i4; \
values.i5.TYPE[0] = _i5; \
values.i6.TYPE[0] = _i6; \
values.i7.TYPE[0] = _i7; \
values.i8.TYPE[0] = _i8; \
values.i9.TYPE[0] = _i9; \
values.i10.TYPE[0] = _i10; \
values.i11.TYPE[0] = _i11; \
values.i12.TYPE[0] = _i12; \
values.i13.TYPE[0] = _i13; \
values.i14.TYPE[0] = _i14; \
values.i15.TYPE[0] = _i15; \
values.i16.TYPE[0] = _i16; \
values.i17.TYPE[0] = _i17; \
values.i18.TYPE[0] = _i18; \
values.i19.TYPE[0] = _i19; \
WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
_i9, _i10, _i11, _i12, _i13, _i14, _i15, \
_i16, _i17, _i18, _i19); \
clear_struct_registers; \
fregs.F0.TYPE[0] = _i0; \
fregs.F1.TYPE[0] = _i1; \
fregs.F2.TYPE[0] = _i2; \
fregs.F3.TYPE[0] = _i3; \
fregs.F4.TYPE[0] = _i4; \
fregs.F5.TYPE[0] = _i5; \
fregs.F6.TYPE[0] = _i6; \
fregs.F7.TYPE[0] = _i7; \
num_fregs = 8; \
WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
_i9, _i10, _i11, _i12, _i13, _i14, _i15, \
_i16, _i17, _i18, _i19);
volatile __bf16 bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16;
void
test_m256bf16_on_stack ()
{
__m256bf16 x[8];
int i;
for (i = 0; i < 8; i++)
x[i] = (__m256bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16};
pass = "m256bf16-8";
def_check_passing8 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
fun_check_passing_m256bf16_8_values,
fun_check_passing_m256bf16_8_regs, _m256bf16);
}
void
test_too_many_m256bf16 ()
{
__m256bf16 x[20];
int i;
for (i = 0; i < 20; i++)
x[i] = (__m256bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16};
pass = "m256bf16-20";
def_check_passing20 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8],
x[9], x[10], x[11], x[12], x[13], x[14], x[15], x[16],
x[17], x[18], x[19], fun_check_passing_m256bf16_20_values,
fun_check_passing_m256bf16_20_regs, _m256bf16);
}
static void
do_test (void)
{
test_m256bf16_on_stack ();
test_too_many_m256bf16 ();
if (failed)
abort ();
}

View File

@ -0,0 +1,69 @@
#include "bf16-ymm-check.h"
#include "args.h"
struct FloatRegisters fregs;
struct IntegerRegisters iregs;
unsigned int num_fregs, num_iregs;
struct m256bf16_struct
{
__m256bf16 x;
};
struct m256bf16_2_struct
{
__m256bf16 x1, x2;
};
/* Check that the struct is passed as the individual members in fregs. */
void
check_struct_passing1bf16 (struct m256bf16_struct ms1 ATTRIBUTE_UNUSED,
struct m256bf16_struct ms2 ATTRIBUTE_UNUSED,
struct m256bf16_struct ms3 ATTRIBUTE_UNUSED,
struct m256bf16_struct ms4 ATTRIBUTE_UNUSED,
struct m256bf16_struct ms5 ATTRIBUTE_UNUSED,
struct m256bf16_struct ms6 ATTRIBUTE_UNUSED,
struct m256bf16_struct ms7 ATTRIBUTE_UNUSED,
struct m256bf16_struct ms8 ATTRIBUTE_UNUSED)
{
check_m256_arguments;
}
void
check_struct_passing2bf16 (struct m256bf16_2_struct ms ATTRIBUTE_UNUSED)
{
/* Check the passing on the stack by comparing the address of the
stack elements to the expected place on the stack. */
assert ((unsigned long)&ms.x1 == rsp+8);
assert ((unsigned long)&ms.x2 == rsp+40);
}
volatile __bf16 bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16;
static void
do_test (void)
{
struct m256bf16_struct m256bf16s [8];
struct m256bf16_2_struct m256bf16_2s = {
{ bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16},
{ bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16},
};
int i;
for (i = 0; i < 8; i++)
{
m256bf16s[i].x = (__m256bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16};
}
clear_struct_registers;
for (i = 0; i < 8; i++)
(&fregs.ymm0)[i]._m256bf16[0] = m256bf16s[i].x;
num_fregs = 8;
WRAP_CALL (check_struct_passing1bf16) (m256bf16s[0], m256bf16s[1], m256bf16s[2], m256bf16s[3],
m256bf16s[4], m256bf16s[5], m256bf16s[6], m256bf16s[7]);
WRAP_CALL (check_struct_passing2bf16) (m256bf16_2s);
}

View File

@ -0,0 +1,179 @@
#include "bf16-ymm-check.h"
#include "args.h"
struct FloatRegisters fregs;
struct IntegerRegisters iregs;
unsigned int num_fregs, num_iregs;
union un1b
{
__m256bf16 x;
float f;
};
union un1bb
{
__m256bf16 x;
__bf16 f;
};
union un2b
{
__m256bf16 x;
double d;
};
union un3b
{
__m256bf16 x;
__m128 v;
};
union un4b
{
__m256bf16 x;
long double ld;
};
union un5b
{
__m256bf16 x;
int i;
};
void
check_union_passing1b (union un1b u1 ATTRIBUTE_UNUSED,
union un1b u2 ATTRIBUTE_UNUSED,
union un1b u3 ATTRIBUTE_UNUSED,
union un1b u4 ATTRIBUTE_UNUSED,
union un1b u5 ATTRIBUTE_UNUSED,
union un1b u6 ATTRIBUTE_UNUSED,
union un1b u7 ATTRIBUTE_UNUSED,
union un1b u8 ATTRIBUTE_UNUSED)
{
check_m256_arguments;
}
void
check_union_passing1bb (union un1bb u1 ATTRIBUTE_UNUSED,
union un1bb u2 ATTRIBUTE_UNUSED,
union un1bb u3 ATTRIBUTE_UNUSED,
union un1bb u4 ATTRIBUTE_UNUSED,
union un1bb u5 ATTRIBUTE_UNUSED,
union un1bb u6 ATTRIBUTE_UNUSED,
union un1bb u7 ATTRIBUTE_UNUSED,
union un1bb u8 ATTRIBUTE_UNUSED)
{
check_m256_arguments;
}
void
check_union_passing2b (union un2b u1 ATTRIBUTE_UNUSED,
union un2b u2 ATTRIBUTE_UNUSED,
union un2b u3 ATTRIBUTE_UNUSED,
union un2b u4 ATTRIBUTE_UNUSED,
union un2b u5 ATTRIBUTE_UNUSED,
union un2b u6 ATTRIBUTE_UNUSED,
union un2b u7 ATTRIBUTE_UNUSED,
union un2b u8 ATTRIBUTE_UNUSED)
{
check_m256_arguments;
}
void
check_union_passing3b (union un3b u1 ATTRIBUTE_UNUSED,
union un3b u2 ATTRIBUTE_UNUSED,
union un3b u3 ATTRIBUTE_UNUSED,
union un3b u4 ATTRIBUTE_UNUSED,
union un3b u5 ATTRIBUTE_UNUSED,
union un3b u6 ATTRIBUTE_UNUSED,
union un3b u7 ATTRIBUTE_UNUSED,
union un3b u8 ATTRIBUTE_UNUSED)
{
check_m256_arguments;
}
void
check_union_passing4b (union un4b u ATTRIBUTE_UNUSED)
{
/* Check the passing on the stack by comparing the address of the
stack elements to the expected place on the stack. */
assert ((unsigned long)&u.x == rsp+8);
assert ((unsigned long)&u.ld == rsp+8);
}
void
check_union_passing5b (union un5b u ATTRIBUTE_UNUSED)
{
/* Check the passing on the stack by comparing the address of the
stack elements to the expected place on the stack. */
assert ((unsigned long)&u.x == rsp+8);
assert ((unsigned long)&u.i == rsp+8);
}
#define check_union_passing1b WRAP_CALL(check_union_passing1b)
#define check_union_passing1bb WRAP_CALL(check_union_passing1bb)
#define check_union_passing2b WRAP_CALL(check_union_passing2b)
#define check_union_passing3b WRAP_CALL(check_union_passing3b)
#define check_union_passing4b WRAP_CALL(check_union_passing4b)
#define check_union_passing5b WRAP_CALL(check_union_passing5b)
static void
do_test (void)
{
union un1b u1b[8];
union un1bb u1bb[8];
union un2b u2b[8];
union un3b u3b[8];
union un4b u4b;
union un5b u5b;
int i;
__bf16 bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16;
for (i = 0; i < 8; i++)
{
u1b[i].x = (__m256bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16 };
}
clear_struct_registers;
for (i = 0; i < 8; i++)
(&fregs.ymm0)[i]._m256bf16[0] = u1b[i].x;
num_fregs = 8;
check_union_passing1b (u1b[0], u1b[1], u1b[2], u1b[3],
u1b[4], u1b[5], u1b[6], u1b[7]);
clear_struct_registers;
for (i = 0; i < 8; i++)
{
u1bb[i].x = u1b[i].x;
(&fregs.ymm0)[i]._m256bf16[0] = u1bb[i].x;
}
num_fregs = 8;
check_union_passing1bb (u1bb[0], u1bb[1], u1bb[2], u1bb[3],
u1bb[4], u1bb[5], u1bb[6], u1bb[7]);
clear_struct_registers;
for (i = 0; i < 8; i++)
{
u2b[i].x = u1b[i].x;
(&fregs.ymm0)[i]._m256bf16[0] = u2b[i].x;
}
num_fregs = 8;
check_union_passing2b (u2b[0], u2b[1], u2b[2], u2b[3],
u2b[4], u2b[5], u2b[6], u2b[7]);
clear_struct_registers;
for (i = 0; i < 8; i++)
{
u3b[i].x = u1b[i].x;
(&fregs.ymm0)[i]._m256bf16[0] = u3b[i].x;
}
num_fregs = 8;
check_union_passing3b (u3b[0], u3b[1], u3b[2], u3b[3],
u3b[4], u3b[5], u3b[6], u3b[7]);
check_union_passing4b (u4b);
check_union_passing5b (u5b);
}

View File

@ -0,0 +1,107 @@
/* Test variable number of 256-bit vector arguments passed to functions. */
#include <stdio.h>
#include "bf16-ymm-check.h"
#include "args.h"
struct FloatRegisters fregs;
struct IntegerRegisters iregs;
/* This struct holds values for argument checking. */
struct
{
YMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
} values;
char *pass;
int failed = 0;
#undef assert
#define assert(c) do { \
if (!(c)) {failed++; printf ("failed %s\n", pass); } \
} while (0)
#define compare(X1,X2,T) do { \
assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
} while (0)
void
fun_check_passing_m256bf16_varargs (__m256bf16 i0, __m256bf16 i1, __m256bf16 i2,
__m256bf16 i3, ...)
{
/* Check argument values. */
void **fp = __builtin_frame_address (0);
void *ra = __builtin_return_address (0);
__m256bf16 *argp;
compare (values.i0, i0, __m256bf16);
compare (values.i1, i1, __m256bf16);
compare (values.i2, i2, __m256bf16);
compare (values.i3, i3, __m256bf16);
/* Get the pointer to the return address on stack. */
while (*fp != ra)
fp++;
/* Skip the return address stack slot. */
argp = (__m256bf16 *)(((char *) fp) + 8);
/* Check __m256bf16 arguments passed on stack. */
compare (values.i4, argp[0], __m256bf16);
compare (values.i5, argp[1], __m256bf16);
compare (values.i6, argp[2], __m256bf16);
compare (values.i7, argp[3], __m256bf16);
compare (values.i8, argp[4], __m256bf16);
compare (values.i9, argp[5], __m256bf16);
/* Check register contents. */
compare (fregs.ymm0, ymm_regs[0], __m256bf16);
compare (fregs.ymm1, ymm_regs[1], __m256bf16);
compare (fregs.ymm2, ymm_regs[2], __m256bf16);
compare (fregs.ymm3, ymm_regs[3], __m256bf16);
}
#define def_check_int_passing_varargs(_i0, _i1, _i2, _i3, _i4, _i5, \
_i6, _i7, _i8, _i9, \
_func, TYPE) \
values.i0.TYPE[0] = _i0; \
values.i1.TYPE[0] = _i1; \
values.i2.TYPE[0] = _i2; \
values.i3.TYPE[0] = _i3; \
values.i4.TYPE[0] = _i4; \
values.i5.TYPE[0] = _i5; \
values.i6.TYPE[0] = _i6; \
values.i7.TYPE[0] = _i7; \
values.i8.TYPE[0] = _i8; \
values.i9.TYPE[0] = _i9; \
clear_struct_registers; \
fregs.F0.TYPE[0] = _i0; \
fregs.F1.TYPE[0] = _i1; \
fregs.F2.TYPE[0] = _i2; \
fregs.F3.TYPE[0] = _i3; \
WRAP_CALL(_func) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9);
void
test_m256bf16_varargs (void)
{
__m256bf16 x[10];
int i;
__bf16 bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16;
for (i = 0; i < 10; i++)
x[i] = (__m256bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16 };
pass = "m256bf16-varargs";
def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5],
x[6], x[7], x[8], x[9],
fun_check_passing_m256bf16_varargs,
_m256bf16);
}
void
do_test (void)
{
test_m256bf16_varargs ();
if (failed)
abort ();
}

View File

@ -0,0 +1,46 @@
# Copyright (C) 2022 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
# The x86-64 ABI testsuite needs one additional assembler file for most
# testcases. For simplicity we will just link it into each test.
load_lib c-torture.exp
load_lib target-supports.exp
load_lib torture-options.exp
load_lib clearcap.exp
if { (![istarget x86_64-*-*] && ![istarget i?86-*-*])
|| ![is-effective-target lp64]
|| ![is-effective-target avx512f] } then {
return
}
torture-init
clearcap-init
set-torture-options $C_TORTURE_OPTIONS
set additional_flags "-W -Wall -mavx512f"
foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] {
if {[runtest_file_p $runtests $src]} {
c-torture-execute [list $src \
$srcdir/$subdir/asm-support.S] \
$additional_flags
}
}
clearcap-finish
torture-finish

View File

@ -0,0 +1,155 @@
#ifndef INCLUDED_ARGS_H
#define INCLUDED_ARGS_H
#include <immintrin.h>
#include <string.h>
/* Assertion macro. */
#define assert(test) if (!(test)) abort()
#ifdef __GNUC__
#define ATTRIBUTE_UNUSED __attribute__((__unused__))
#else
#define ATTRIBUTE_UNUSED
#endif
/* This defines the calling sequences for integers and floats. */
#define I0 rdi
#define I1 rsi
#define I2 rdx
#define I3 rcx
#define I4 r8
#define I5 r9
#define F0 zmm0
#define F1 zmm1
#define F2 zmm2
#define F3 zmm3
#define F4 zmm4
#define F5 zmm5
#define F6 zmm6
#define F7 zmm7
typedef union {
__bf16 ___bf16[32];
float _float[16];
double _double[8];
long long _longlong[8];
int _int[16];
unsigned long long _ulonglong[8];
__m64 _m64[8];
__m128 _m128[4];
__m256 _m256[2];
__m512 _m512[1];
__m512bf16 _m512bf16[1];
} ZMM_T;
typedef union {
float _float;
double _double;
long double _ldouble;
unsigned long long _ulonglong[2];
} X87_T;
extern void (*callthis)(void);
extern unsigned long long rax,rbx,rcx,rdx,rsi,rdi,rsp,rbp,r8,r9,r10,r11,r12,r13,r14,r15;
ZMM_T zmm_regs[32];
X87_T x87_regs[8];
extern volatile unsigned long long volatile_var;
extern void snapshot (void);
extern void snapshot_ret (void);
#define WRAP_CALL(N) \
(callthis = (void (*)()) (N), (typeof (&N)) snapshot)
#define WRAP_RET(N) \
(callthis = (void (*)()) (N), (typeof (&N)) snapshot_ret)
/* Clear all integer registers. */
#define clear_int_hardware_registers \
asm __volatile__ ("xor %%rax, %%rax\n\t" \
"xor %%rbx, %%rbx\n\t" \
"xor %%rcx, %%rcx\n\t" \
"xor %%rdx, %%rdx\n\t" \
"xor %%rsi, %%rsi\n\t" \
"xor %%rdi, %%rdi\n\t" \
"xor %%r8, %%r8\n\t" \
"xor %%r9, %%r9\n\t" \
"xor %%r10, %%r10\n\t" \
"xor %%r11, %%r11\n\t" \
"xor %%r12, %%r12\n\t" \
"xor %%r13, %%r13\n\t" \
"xor %%r14, %%r14\n\t" \
"xor %%r15, %%r15\n\t" \
::: "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", \
"r9", "r10", "r11", "r12", "r13", "r14", "r15");
/* This is the list of registers available for passing arguments. Not all of
these are used or even really available. */
struct IntegerRegisters
{
unsigned long long rax, rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15;
};
struct FloatRegisters
{
double mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7;
long double st0, st1, st2, st3, st4, st5, st6, st7;
ZMM_T zmm0, zmm1, zmm2, zmm3, zmm4, zmm5, zmm6, zmm7, zmm8, zmm9,
zmm10, zmm11, zmm12, zmm13, zmm14, zmm15, zmm16, zmm17, zmm18,
zmm19, zmm20, zmm21, zmm22, zmm23, zmm24, zmm25, zmm26, zmm27,
zmm28, zmm29, zmm30, zmm31;
};
/* Implemented in scalarargs.c */
extern struct IntegerRegisters iregs;
extern struct FloatRegisters fregs;
extern unsigned int num_iregs, num_fregs;
/* Clear register struct. */
#define clear_struct_registers \
rax = rbx = rcx = rdx = rdi = rsi = rbp = rsp \
= r8 = r9 = r10 = r11 = r12 = r13 = r14 = r15 = 0; \
memset (&iregs, 0, sizeof (iregs)); \
memset (&fregs, 0, sizeof (fregs)); \
memset (zmm_regs, 0, sizeof (zmm_regs)); \
memset (x87_regs, 0, sizeof (x87_regs));
/* Clear both hardware and register structs for integers. */
#define clear_int_registers \
clear_struct_registers \
clear_int_hardware_registers
#define check_vector_arguments(T,O) do { \
assert (num_fregs <= 0 \
|| memcmp (((char *) &fregs.zmm0) + (O), \
&zmm_regs[0], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 1 \
|| memcmp (((char *) &fregs.zmm1) + (O), \
&zmm_regs[1], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 2 \
|| memcmp (((char *) &fregs.zmm2) + (O), \
&zmm_regs[2], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 3 \
|| memcmp (((char *) &fregs.zmm3) + (O), \
&zmm_regs[3], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 4 \
|| memcmp (((char *) &fregs.zmm4) + (O), \
&zmm_regs[4], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 5 \
|| memcmp (((char *) &fregs.zmm5) + (O), \
&zmm_regs[5], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 6 \
|| memcmp (((char *) &fregs.zmm6) + (O), \
&zmm_regs[6], \
sizeof (__ ## T) - (O)) == 0); \
assert (num_fregs <= 7 \
|| memcmp (((char *) &fregs.zmm7) + (O), \
&zmm_regs[7], \
sizeof (__ ## T) - (O)) == 0); \
} while (0)
#define check_m512_arguments check_vector_arguments(m512, 0)
#endif /* INCLUDED_ARGS_H */

View File

@ -0,0 +1,100 @@
.text
.p2align 4,,15
.globl snapshot
.type snapshot, @function
snapshot:
.LFB3:
movq %rax, rax(%rip)
movq %rbx, rbx(%rip)
movq %rcx, rcx(%rip)
movq %rdx, rdx(%rip)
movq %rdi, rdi(%rip)
movq %rsi, rsi(%rip)
movq %rbp, rbp(%rip)
movq %rsp, rsp(%rip)
movq %r8, r8(%rip)
movq %r9, r9(%rip)
movq %r10, r10(%rip)
movq %r11, r11(%rip)
movq %r12, r12(%rip)
movq %r13, r13(%rip)
movq %r14, r14(%rip)
movq %r15, r15(%rip)
vmovdqu32 %zmm0, zmm_regs+0(%rip)
vmovdqu32 %zmm1, zmm_regs+64(%rip)
vmovdqu32 %zmm2, zmm_regs+128(%rip)
vmovdqu32 %zmm3, zmm_regs+192(%rip)
vmovdqu32 %zmm4, zmm_regs+256(%rip)
vmovdqu32 %zmm5, zmm_regs+320(%rip)
vmovdqu32 %zmm6, zmm_regs+384(%rip)
vmovdqu32 %zmm7, zmm_regs+448(%rip)
vmovdqu32 %zmm8, zmm_regs+512(%rip)
vmovdqu32 %zmm9, zmm_regs+576(%rip)
vmovdqu32 %zmm10, zmm_regs+640(%rip)
vmovdqu32 %zmm11, zmm_regs+704(%rip)
vmovdqu32 %zmm12, zmm_regs+768(%rip)
vmovdqu32 %zmm13, zmm_regs+832(%rip)
vmovdqu32 %zmm14, zmm_regs+896(%rip)
vmovdqu32 %zmm15, zmm_regs+960(%rip)
vmovdqu32 %zmm16, zmm_regs+1024(%rip)
vmovdqu32 %zmm17, zmm_regs+1088(%rip)
vmovdqu32 %zmm18, zmm_regs+1152(%rip)
vmovdqu32 %zmm19, zmm_regs+1216(%rip)
vmovdqu32 %zmm20, zmm_regs+1280(%rip)
vmovdqu32 %zmm21, zmm_regs+1344(%rip)
vmovdqu32 %zmm22, zmm_regs+1408(%rip)
vmovdqu32 %zmm23, zmm_regs+1472(%rip)
vmovdqu32 %zmm24, zmm_regs+1536(%rip)
vmovdqu32 %zmm25, zmm_regs+1600(%rip)
vmovdqu32 %zmm26, zmm_regs+1664(%rip)
vmovdqu32 %zmm27, zmm_regs+1728(%rip)
vmovdqu32 %zmm28, zmm_regs+1792(%rip)
vmovdqu32 %zmm29, zmm_regs+1856(%rip)
vmovdqu32 %zmm30, zmm_regs+1920(%rip)
vmovdqu32 %zmm31, zmm_regs+1984(%rip)
jmp *callthis(%rip)
.LFE3:
.size snapshot, .-snapshot
.p2align 4,,15
.globl snapshot_ret
.type snapshot_ret, @function
snapshot_ret:
movq %rdi, rdi(%rip)
subq $8, %rsp
call *callthis(%rip)
addq $8, %rsp
movq %rax, rax(%rip)
movq %rdx, rdx(%rip)
vmovdqu32 %zmm0, zmm_regs+0(%rip)
vmovdqu32 %zmm1, zmm_regs+64(%rip)
fstpt x87_regs(%rip)
fstpt x87_regs+16(%rip)
fldt x87_regs+16(%rip)
fldt x87_regs(%rip)
ret
.size snapshot_ret, .-snapshot_ret
.comm callthis,8,8
.comm rax,8,8
.comm rbx,8,8
.comm rcx,8,8
.comm rdx,8,8
.comm rsi,8,8
.comm rdi,8,8
.comm rsp,8,8
.comm rbp,8,8
.comm r8,8,8
.comm r9,8,8
.comm r10,8,8
.comm r11,8,8
.comm r12,8,8
.comm r13,8,8
.comm r14,8,8
.comm r15,8,8
.comm zmm_regs,2048,64
.comm x87_regs,128,32
.comm volatile_var,8,8
#ifdef __linux__
.section .note.GNU-stack,"",@progbits
#endif

View File

@ -0,0 +1,23 @@
#include <stdlib.h>
static void do_test (void);
int
main ()
{
if (__builtin_cpu_supports ("avx512f"))
{
do_test ();
#ifdef DEBUG
printf ("PASSED\n");
#endif
return 0;
}
#ifdef DEBUG
printf ("SKIPPED\n");
#endif
return 0;
}

View File

@ -0,0 +1,44 @@
#include <stdio.h>
#include "bf16-zmm-check.h"
#include "args.h"
struct FloatRegisters fregs;
struct IntegerRegisters iregs;
unsigned int num_fregs, num_iregs;
volatile __bf16 bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16,
bf17,bf18,bf19,bf20,bf21,bf22,bf23,bf24,
bf25,bf26,bf27,bf28,bf29,bf30,bf31,bf32;
__m512bf16
fun_test_returning___m512bf16 (void)
{
volatile_var++;
return (__m512bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16,
bf17,bf18,bf19,bf20,bf21,bf22,bf23,bf24,
bf25,bf26,bf27,bf28,bf29,bf30,bf31,bf32 };
}
__m512bf16 test_512bf16;
static void
do_test (void)
{
unsigned failed = 0;
ZMM_T zmmt1, zmmt2;
clear_struct_registers;
test_512bf16 = (__m512bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16,
bf17,bf18,bf19,bf20,bf21,bf22,bf23,bf24,
bf25,bf26,bf27,bf28,bf29,bf30,bf31,bf32 };
zmmt1._m512bf16[0] = test_512bf16;
zmmt2._m512bf16[0] = WRAP_RET (fun_test_returning___m512bf16)();
if (memcmp (&zmmt1, &zmmt2, sizeof (zmmt2)) != 0)
printf ("fail m512bf16\n"), failed++;
if (failed)
abort ();
}

View File

@ -0,0 +1,243 @@
#include <stdio.h>
#include "bf16-zmm-check.h"
#include "args.h"
struct FloatRegisters fregs;
struct IntegerRegisters iregs;
unsigned int num_fregs, num_iregs;
/* This struct holds values for argument checking. */
struct
{
ZMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15,
i16, i17, i18, i19, i20, i21, i22, i23;
} values;
char *pass;
int failed = 0;
#undef assert
#define assert(c) do { \
if (!(c)) {failed++; printf ("failed %s\n", pass); } \
} while (0)
#define compare(X1,X2,T) do { \
assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
} while (0)
fun_check_passing_m512bf16_8_values (__m512bf16 i0 ATTRIBUTE_UNUSED,
__m512bf16 i1 ATTRIBUTE_UNUSED,
__m512bf16 i2 ATTRIBUTE_UNUSED,
__m512bf16 i3 ATTRIBUTE_UNUSED,
__m512bf16 i4 ATTRIBUTE_UNUSED,
__m512bf16 i5 ATTRIBUTE_UNUSED,
__m512bf16 i6 ATTRIBUTE_UNUSED,
__m512bf16 i7 ATTRIBUTE_UNUSED)
{
/* Check argument values. */
compare (values.i0, i0, __m512bf16);
compare (values.i1, i1, __m512bf16);
compare (values.i2, i2, __m512bf16);
compare (values.i3, i3, __m512bf16);
compare (values.i4, i4, __m512bf16);
compare (values.i5, i5, __m512bf16);
compare (values.i6, i6, __m512bf16);
compare (values.i7, i7, __m512bf16);
}
void
fun_check_passing_m512bf16_8_regs (__m512bf16 i0 ATTRIBUTE_UNUSED,
__m512bf16 i1 ATTRIBUTE_UNUSED,
__m512bf16 i2 ATTRIBUTE_UNUSED,
__m512bf16 i3 ATTRIBUTE_UNUSED,
__m512bf16 i4 ATTRIBUTE_UNUSED,
__m512bf16 i5 ATTRIBUTE_UNUSED,
__m512bf16 i6 ATTRIBUTE_UNUSED,
__m512bf16 i7 ATTRIBUTE_UNUSED)
{
/* Check register contents. */
check_m512_arguments;
}
void
fun_check_passing_m512bf16_20_values (__m512bf16 i0 ATTRIBUTE_UNUSED,
__m512bf16 i1 ATTRIBUTE_UNUSED,
__m512bf16 i2 ATTRIBUTE_UNUSED,
__m512bf16 i3 ATTRIBUTE_UNUSED,
__m512bf16 i4 ATTRIBUTE_UNUSED,
__m512bf16 i5 ATTRIBUTE_UNUSED,
__m512bf16 i6 ATTRIBUTE_UNUSED,
__m512bf16 i7 ATTRIBUTE_UNUSED,
__m512bf16 i8 ATTRIBUTE_UNUSED,
__m512bf16 i9 ATTRIBUTE_UNUSED,
__m512bf16 i10 ATTRIBUTE_UNUSED,
__m512bf16 i11 ATTRIBUTE_UNUSED,
__m512bf16 i12 ATTRIBUTE_UNUSED,
__m512bf16 i13 ATTRIBUTE_UNUSED,
__m512bf16 i14 ATTRIBUTE_UNUSED,
__m512bf16 i15 ATTRIBUTE_UNUSED,
__m512bf16 i16 ATTRIBUTE_UNUSED,
__m512bf16 i17 ATTRIBUTE_UNUSED,
__m512bf16 i18 ATTRIBUTE_UNUSED,
__m512bf16 i19 ATTRIBUTE_UNUSED)
{
/* Check argument values. */
compare (values.i0, i0, __m512bf16);
compare (values.i1, i1, __m512bf16);
compare (values.i2, i2, __m512bf16);
compare (values.i3, i3, __m512bf16);
compare (values.i4, i4, __m512bf16);
compare (values.i5, i5, __m512bf16);
compare (values.i6, i6, __m512bf16);
compare (values.i7, i7, __m512bf16);
compare (values.i8, i8, __m512bf16);
compare (values.i9, i9, __m512bf16);
compare (values.i10, i10, __m512bf16);
compare (values.i11, i11, __m512bf16);
compare (values.i12, i12, __m512bf16);
compare (values.i13, i13, __m512bf16);
compare (values.i14, i14, __m512bf16);
compare (values.i15, i15, __m512bf16);
compare (values.i16, i16, __m512bf16);
compare (values.i17, i17, __m512bf16);
compare (values.i18, i18, __m512bf16);
compare (values.i19, i19, __m512bf16);
}
void
fun_check_passing_m512bf16_20_regs (__m512bf16 i0 ATTRIBUTE_UNUSED,
__m512bf16 i1 ATTRIBUTE_UNUSED,
__m512bf16 i2 ATTRIBUTE_UNUSED,
__m512bf16 i3 ATTRIBUTE_UNUSED,
__m512bf16 i4 ATTRIBUTE_UNUSED,
__m512bf16 i5 ATTRIBUTE_UNUSED,
__m512bf16 i6 ATTRIBUTE_UNUSED,
__m512bf16 i7 ATTRIBUTE_UNUSED,
__m512bf16 i8 ATTRIBUTE_UNUSED,
__m512bf16 i9 ATTRIBUTE_UNUSED,
__m512bf16 i10 ATTRIBUTE_UNUSED,
__m512bf16 i11 ATTRIBUTE_UNUSED,
__m512bf16 i12 ATTRIBUTE_UNUSED,
__m512bf16 i13 ATTRIBUTE_UNUSED,
__m512bf16 i14 ATTRIBUTE_UNUSED,
__m512bf16 i15 ATTRIBUTE_UNUSED,
__m512bf16 i16 ATTRIBUTE_UNUSED,
__m512bf16 i17 ATTRIBUTE_UNUSED,
__m512bf16 i18 ATTRIBUTE_UNUSED,
__m512bf16 i19 ATTRIBUTE_UNUSED)
{
/* Check register contents. */
check_m512_arguments;
}
#define def_check_passing8(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _func1, _func2, TYPE) \
values.i0.TYPE[0] = _i0; \
values.i1.TYPE[0] = _i1; \
values.i2.TYPE[0] = _i2; \
values.i3.TYPE[0] = _i3; \
values.i4.TYPE[0] = _i4; \
values.i5.TYPE[0] = _i5; \
values.i6.TYPE[0] = _i6; \
values.i7.TYPE[0] = _i7; \
WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7); \
\
clear_struct_registers; \
fregs.F0.TYPE[0] = _i0; \
fregs.F1.TYPE[0] = _i1; \
fregs.F2.TYPE[0] = _i2; \
fregs.F3.TYPE[0] = _i3; \
fregs.F4.TYPE[0] = _i4; \
fregs.F5.TYPE[0] = _i5; \
fregs.F6.TYPE[0] = _i6; \
fregs.F7.TYPE[0] = _i7; \
num_fregs = 8; \
WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7);
#define def_check_passing20(_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, \
_i10, _i11, _i12, _i13, _i14, _i15, _i16, _i17, \
_i18, _i19, _func1, _func2, TYPE) \
values.i0.TYPE[0] = _i0; \
values.i1.TYPE[0] = _i1; \
values.i2.TYPE[0] = _i2; \
values.i3.TYPE[0] = _i3; \
values.i4.TYPE[0] = _i4; \
values.i5.TYPE[0] = _i5; \
values.i6.TYPE[0] = _i6; \
values.i7.TYPE[0] = _i7; \
values.i8.TYPE[0] = _i8; \
values.i9.TYPE[0] = _i9; \
values.i10.TYPE[0] = _i10; \
values.i11.TYPE[0] = _i11; \
values.i12.TYPE[0] = _i12; \
values.i13.TYPE[0] = _i13; \
values.i14.TYPE[0] = _i14; \
values.i15.TYPE[0] = _i15; \
values.i16.TYPE[0] = _i16; \
values.i17.TYPE[0] = _i17; \
values.i18.TYPE[0] = _i18; \
values.i19.TYPE[0] = _i19; \
WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, \
_i10, _i11, _i12, _i13, _i14, _i15, _i16, _i17, \
_i18, _i19); \
\
clear_struct_registers; \
fregs.F0.TYPE[0] = _i0; \
fregs.F1.TYPE[0] = _i1; \
fregs.F2.TYPE[0] = _i2; \
fregs.F3.TYPE[0] = _i3; \
fregs.F4.TYPE[0] = _i4; \
fregs.F5.TYPE[0] = _i5; \
fregs.F6.TYPE[0] = _i6; \
fregs.F7.TYPE[0] = _i7; \
num_fregs = 8; \
WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9, \
_i10, _i11, _i12, _i13, _i14, _i15, _i16, _i17, \
_i18, _i19);
volatile __bf16 bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16,
bf17,bf18,bf19,bf20,bf21,bf22,bf23,bf24,
bf25,bf26,bf27,bf28,bf29,bf30,bf31,bf32;
void
test_m512bf16_on_stack ()
{
__m512bf16 x[8];
int i;
for (i = 0; i < 8; i++)
x[i] = (__m512bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16,
bf17,bf18,bf19,bf20,bf21,bf22,bf23,bf24,
bf25,bf26,bf27,bf28,bf29,bf30,bf31,bf32 };
pass = "m512bf16-8";
def_check_passing8 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
fun_check_passing_m512bf16_8_values,
fun_check_passing_m512bf16_8_regs, _m512bf16);
}
void
test_too_many_m512bf16 ()
{
__m512bf16 x[20];
int i;
for (i = 0; i < 20; i++)
x[i] = (__m512bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16,
bf17,bf18,bf19,bf20,bf21,bf22,bf23,bf24,
bf25,bf26,bf27,bf28,bf29,bf30,bf31,bf32 };
pass = "m512bf16-20";
def_check_passing20 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8],
x[9], x[10], x[11], x[12], x[13], x[14], x[15], x[16],
x[17], x[18], x[19], fun_check_passing_m512bf16_20_values,
fun_check_passing_m512bf16_20_regs, _m512bf16);
}
static void
do_test (void)
{
test_m512bf16_on_stack ();
test_too_many_m512bf16 ();
if (failed)
abort ();
}

View File

@ -0,0 +1,77 @@
#include "bf16-zmm-check.h"
#include "args.h"
struct FloatRegisters fregs;
struct IntegerRegisters iregs;
unsigned int num_fregs, num_iregs;
struct m512bf16_struct
{
__m512bf16 x;
};
struct m512bf16_2_struct
{
__m512bf16 x1, x2;
};
/* Check that the struct is passed as the individual members in fregs. */
void
check_struct_passing1bf16 (struct m512bf16_struct ms1 ATTRIBUTE_UNUSED,
struct m512bf16_struct ms2 ATTRIBUTE_UNUSED,
struct m512bf16_struct ms3 ATTRIBUTE_UNUSED,
struct m512bf16_struct ms4 ATTRIBUTE_UNUSED,
struct m512bf16_struct ms5 ATTRIBUTE_UNUSED,
struct m512bf16_struct ms6 ATTRIBUTE_UNUSED,
struct m512bf16_struct ms7 ATTRIBUTE_UNUSED,
struct m512bf16_struct ms8 ATTRIBUTE_UNUSED)
{
/* Check register contents. */
check_m512_arguments;
}
void
check_struct_passing2bf16 (struct m512bf16_2_struct ms ATTRIBUTE_UNUSED)
{
/* Check the passing on the stack by comparing the address of the
stack elements to the expected place on the stack. */
assert ((unsigned long)&ms.x1 == rsp+8);
assert ((unsigned long)&ms.x2 == rsp+72);
}
static void
do_test (void)
{
__bf16 bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16,
bf17,bf18,bf19,bf20,bf21,bf22,bf23,bf24,
bf25,bf26,bf27,bf28,bf29,bf30,bf31,bf32;
struct m512bf16_struct m512bf16s [8];
struct m512bf16_2_struct m512bf16_2s = {
{ bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16,
bf17,bf18,bf19,bf20,bf21,bf22,bf23,bf24,
bf25,bf26,bf27,bf28,bf29,bf30,bf31,bf32 },
{ bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16,
bf17,bf18,bf19,bf20,bf21,bf22,bf23,bf24,
bf25,bf26,bf27,bf28,bf29,bf30,bf31,bf32 }
};
int i;
for (i = 0; i < 8; i++)
{
m512bf16s[i].x = (__m512bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16,
bf17,bf18,bf19,bf20,bf21,bf22,bf23,bf24,
bf25,bf26,bf27,bf28,bf29,bf30,bf31,bf32 };
}
clear_struct_registers;
for (i = 0; i < 8; i++)
(&fregs.zmm0)[i]._m512bf16[0] = m512bf16s[i].x;
num_fregs = 8;
WRAP_CALL (check_struct_passing1bf16) (m512bf16s[0], m512bf16s[1], m512bf16s[2], m512bf16s[3],
m512bf16s[4], m512bf16s[5], m512bf16s[6], m512bf16s[7]);
WRAP_CALL (check_struct_passing2bf16) (m512bf16_2s);
}

View File

@ -0,0 +1,222 @@
#include "bf16-zmm-check.h"
#include "args.h"
struct FloatRegisters fregs;
struct IntegerRegisters iregs;
unsigned int num_fregs, num_iregs;
union un1b
{
__m512bf16 x;
float f;
};
union un1bb
{
__m512bf16 x;
__bf16 f;
};
union un2b
{
__m512bf16 x;
double d;
};
union un3b
{
__m512bf16 x;
__m128 v;
};
union un4b
{
__m512bf16 x;
long double ld;
};
union un5b
{
__m512bf16 x;
int i;
};
union un6b
{
__m512bf16 x;
__m256 v;
};
void
check_union_passing1b (union un1b u1 ATTRIBUTE_UNUSED,
union un1b u2 ATTRIBUTE_UNUSED,
union un1b u3 ATTRIBUTE_UNUSED,
union un1b u4 ATTRIBUTE_UNUSED,
union un1b u5 ATTRIBUTE_UNUSED,
union un1b u6 ATTRIBUTE_UNUSED,
union un1b u7 ATTRIBUTE_UNUSED,
union un1b u8 ATTRIBUTE_UNUSED)
{
/* Check register contents. */
check_m512_arguments;
}
void
check_union_passing1bb (union un1bb u1 ATTRIBUTE_UNUSED,
union un1bb u2 ATTRIBUTE_UNUSED,
union un1bb u3 ATTRIBUTE_UNUSED,
union un1bb u4 ATTRIBUTE_UNUSED,
union un1bb u5 ATTRIBUTE_UNUSED,
union un1bb u6 ATTRIBUTE_UNUSED,
union un1bb u7 ATTRIBUTE_UNUSED,
union un1bb u8 ATTRIBUTE_UNUSED)
{
/* Check register contents. */
check_m512_arguments;
}
void
check_union_passing2b (union un2b u1 ATTRIBUTE_UNUSED,
union un2b u2 ATTRIBUTE_UNUSED,
union un2b u3 ATTRIBUTE_UNUSED,
union un2b u4 ATTRIBUTE_UNUSED,
union un2b u5 ATTRIBUTE_UNUSED,
union un2b u6 ATTRIBUTE_UNUSED,
union un2b u7 ATTRIBUTE_UNUSED,
union un2b u8 ATTRIBUTE_UNUSED)
{
/* Check register contents. */
check_m512_arguments;
}
void
check_union_passing3b (union un3b u1 ATTRIBUTE_UNUSED,
union un3b u2 ATTRIBUTE_UNUSED,
union un3b u3 ATTRIBUTE_UNUSED,
union un3b u4 ATTRIBUTE_UNUSED,
union un3b u5 ATTRIBUTE_UNUSED,
union un3b u6 ATTRIBUTE_UNUSED,
union un3b u7 ATTRIBUTE_UNUSED,
union un3b u8 ATTRIBUTE_UNUSED)
{
/* Check register contents. */
check_m512_arguments;
}
void
check_union_passing4b (union un4b u ATTRIBUTE_UNUSED)
{
/* Check the passing on the stack by comparing the address of the
stack elements to the expected place on the stack. */
assert ((unsigned long)&u.x == rsp+8);
assert ((unsigned long)&u.ld == rsp+8);
}
void
check_union_passing5b (union un5b u ATTRIBUTE_UNUSED)
{
/* Check the passing on the stack by comparing the address of the
stack elements to the expected place on the stack. */
assert ((unsigned long)&u.x == rsp+8);
assert ((unsigned long)&u.i == rsp+8);
}
void
check_union_passing6b (union un6b u1 ATTRIBUTE_UNUSED,
union un6b u2 ATTRIBUTE_UNUSED,
union un6b u3 ATTRIBUTE_UNUSED,
union un6b u4 ATTRIBUTE_UNUSED,
union un6b u5 ATTRIBUTE_UNUSED,
union un6b u6 ATTRIBUTE_UNUSED,
union un6b u7 ATTRIBUTE_UNUSED,
union un6b u8 ATTRIBUTE_UNUSED)
{
/* Check register contents. */
check_m512_arguments;
}
#define check_union_passing1b WRAP_CALL(check_union_passing1b)
#define check_union_passing1bf WRAP_CALL(check_union_passing1bf)
#define check_union_passing1bb WRAP_CALL(check_union_passing1bb)
#define check_union_passing2b WRAP_CALL(check_union_passing2b)
#define check_union_passing3b WRAP_CALL(check_union_passing3b)
#define check_union_passing4b WRAP_CALL(check_union_passing4b)
#define check_union_passing5b WRAP_CALL(check_union_passing5b)
#define check_union_passing6b WRAP_CALL(check_union_passing6b)
static void
do_test (void)
{
__bf16 bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16,
bf17,bf18,bf19,bf20,bf21,bf22,bf23,bf24,
bf25,bf26,bf27,bf28,bf29,bf30,bf31,bf32;
union un1b u1b[8];
union un1bb u1bb[8];
union un2b u2b[8];
union un3b u3b[8];
union un4b u4b;
union un5b u5b;
union un6b u6b[8];
int i;
for (i = 0; i < 8; i++)
{
u1b[i].x = (__m512bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16,
bf17,bf18,bf19,bf20,bf21,bf22,bf23,bf24,
bf25,bf26,bf27,bf28,bf29,bf30,bf31,bf32 };
}
clear_struct_registers;
for (i = 0; i < 8; i++)
(&fregs.zmm0)[i]._m512bf16[0] = u1b[i].x;
num_fregs = 8;
check_union_passing1b (u1b[0], u1b[1], u1b[2], u1b[3],
u1b[4], u1b[5], u1b[6], u1b[7]);
clear_struct_registers;
for (i = 0; i < 8; i++)
{
u1bb[i].x = u1b[i].x;
(&fregs.zmm0)[i]._m512bf16[0] = u1bb[i].x;
}
num_fregs = 8;
check_union_passing1bb (u1bb[0], u1bb[1], u1bb[2], u1bb[3],
u1bb[4], u1bb[5], u1bb[6], u1bb[7]);
clear_struct_registers;
for (i = 0; i < 8; i++)
{
u2b[i].x = u1bb[i].x;
(&fregs.zmm0)[i]._m512bf16[0] = u2b[i].x;
}
num_fregs = 8;
check_union_passing2b (u2b[0], u2b[1], u2b[2], u2b[3],
u2b[4], u2b[5], u2b[6], u2b[7]);
clear_struct_registers;
for (i = 0; i < 8; i++)
{
u3b[i].x = u1b[i].x;
(&fregs.zmm0)[i]._m512bf16[0] = u3b[i].x;
}
num_fregs = 8;
check_union_passing3b (u3b[0], u3b[1], u3b[2], u3b[3],
u3b[4], u3b[5], u3b[6], u3b[7]);
check_union_passing4b (u4b);
check_union_passing5b (u5b);
clear_struct_registers;
for (i = 0; i < 8; i++)
{
u6b[i].x = u1b[i].x;
(&fregs.zmm0)[i]._m512bf16[0] = u6b[i].x;
}
num_fregs = 8;
check_union_passing6b (u6b[0], u6b[1], u6b[2], u6b[3],
u6b[4], u6b[5], u6b[6], u6b[7]);
}

View File

@ -0,0 +1,111 @@
/* Test variable number of 512-bit vector arguments passed to functions. */
#include <stdio.h>
#include "bf16-zmm-check.h"
#include "args.h"
struct FloatRegisters fregs;
struct IntegerRegisters iregs;
/* This struct holds values for argument checking. */
struct
{
ZMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
} values;
char *pass;
int failed = 0;
#undef assert
#define assert(c) do { \
if (!(c)) {failed++; printf ("failed %s\n", pass); } \
} while (0)
#define compare(X1,X2,T) do { \
assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
} while (0)
void
fun_check_passing_m512bf16_varargs (__m512bf16 i0, __m512bf16 i1, __m512bf16 i2,
__m512bf16 i3, ...)
{
/* Check argument values. */
void **fp = __builtin_frame_address (0);
void *ra = __builtin_return_address (0);
__m512bf16 *argp;
compare (values.i0, i0, __m512bf16);
compare (values.i1, i1, __m512bf16);
compare (values.i2, i2, __m512bf16);
compare (values.i3, i3, __m512bf16);
/* Get the pointer to the return address on stack. */
while (*fp != ra)
fp++;
/* Skip the return address stack slot. */
argp = (__m512bf16 *)(((char *) fp) + 8);
/* Check __m512bf16 arguments passed on stack. */
compare (values.i4, argp[0], __m512bf16);
compare (values.i5, argp[1], __m512bf16);
compare (values.i6, argp[2], __m512bf16);
compare (values.i7, argp[3], __m512bf16);
compare (values.i8, argp[4], __m512bf16);
compare (values.i9, argp[5], __m512bf16);
/* Check register contents. */
compare (fregs.zmm0, zmm_regs[0], __m512bf16);
compare (fregs.zmm1, zmm_regs[1], __m512bf16);
compare (fregs.zmm2, zmm_regs[2], __m512bf16);
compare (fregs.zmm3, zmm_regs[3], __m512bf16);
}
#define def_check_int_passing_varargs(_i0, _i1, _i2, _i3, _i4, _i5, \
_i6, _i7, _i8, _i9, \
_func, TYPE) \
values.i0.TYPE[0] = _i0; \
values.i1.TYPE[0] = _i1; \
values.i2.TYPE[0] = _i2; \
values.i3.TYPE[0] = _i3; \
values.i4.TYPE[0] = _i4; \
values.i5.TYPE[0] = _i5; \
values.i6.TYPE[0] = _i6; \
values.i7.TYPE[0] = _i7; \
values.i8.TYPE[0] = _i8; \
values.i9.TYPE[0] = _i9; \
clear_struct_registers; \
fregs.F0.TYPE[0] = _i0; \
fregs.F1.TYPE[0] = _i1; \
fregs.F2.TYPE[0] = _i2; \
fregs.F3.TYPE[0] = _i3; \
WRAP_CALL(_func) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9);
void
test_m512bf16_varargs (void)
{
__m512bf16 x[10];
__bf16 bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16,
bf17,bf18,bf19,bf20,bf21,bf22,bf23,bf24,
bf25,bf26,bf27,bf28,bf29,bf30,bf31,bf32;
int i;
for (i = 0; i < 10; i++)
x[i] = (__m512bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16,
bf17,bf18,bf19,bf20,bf21,bf22,bf23,bf24,
bf25,bf26,bf27,bf28,bf29,bf30,bf31,bf32 };
pass = "m512bf16-varargs";
def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5],
x[6], x[7], x[8], x[9],
fun_check_passing_m512bf16_varargs,
_m512bf16);
}
void
do_test (void)
{
test_m512bf16_varargs ();
if (failed)
abort ();
}

View File

@ -0,0 +1,53 @@
#ifndef MACROS_H
#define check_size(_t, _size) assert(sizeof(_t) == (_size))
#define check_align(_t, _align) assert(__alignof__(_t) == (_align))
#define check_align_lv(_t, _align) assert(__alignof__(_t) == (_align) \
&& (((unsigned long)&(_t)) & ((_align) - 1) ) == 0)
#define check_basic_struct_size_and_align(_type, _size, _align) { \
struct _str { _type dummy; } _t; \
check_size(_t, _size); \
check_align_lv(_t, _align); \
}
#define check_array_size_and_align(_type, _size, _align) { \
_type _a[1]; _type _b[2]; _type _c[16]; \
struct _str { _type _a[1]; } _s; \
check_align_lv(_a[0], _align); \
check_size(_a, _size); \
check_size(_b, (_size*2)); \
check_size(_c, (_size*16)); \
check_size(_s, _size); \
check_align_lv(_s._a[0], _align); \
}
#define check_basic_union_size_and_align(_type, _size, _align) { \
union _union { _type dummy; } _u; \
check_size(_u, _size); \
check_align_lv(_u, _align); \
}
#define run_signed_tests2(_function, _arg1, _arg2) \
_function(_arg1, _arg2); \
_function(signed _arg1, _arg2); \
_function(unsigned _arg1, _arg2);
#define run_signed_tests3(_function, _arg1, _arg2, _arg3) \
_function(_arg1, _arg2, _arg3); \
_function(signed _arg1, _arg2, _arg3); \
_function(unsigned _arg1, _arg2, _arg3);
/* Check size of a struct and a union of three types. */
#define check_struct_and_union3(type1, type2, type3, struct_size, align_size) \
{ \
struct _str { type1 t1; type2 t2; type3 t3; } _t; \
union _uni { type1 t1; type2 t2; type3 t3; } _u; \
check_size(_t, struct_size); \
check_size(_u, align_size); \
}
#endif // MACROS_H

View File

@ -0,0 +1,214 @@
/* This is an autogenerated file. Do not edit. */
#include "defines.h"
#include "macros.h"
/* Check structs and unions of all permutations of 3 basic types. */
int
main (void)
{
check_struct_and_union3(char, char, __bf16, 4, 2);
check_struct_and_union3(char, __bf16, char, 6, 2);
check_struct_and_union3(char, __bf16, __bf16, 6, 2);
check_struct_and_union3(char, __bf16, int, 8, 4);
#ifndef __ILP32__
check_struct_and_union3(char, __bf16, long, 16, 8);
#endif
check_struct_and_union3(char, __bf16, long long, 16, 8);
check_struct_and_union3(char, __bf16, float, 8, 4);
check_struct_and_union3(char, __bf16, double, 16, 8);
check_struct_and_union3(char, __bf16, long double, 32, 16);
check_struct_and_union3(char, int, __bf16, 12, 4);
#ifndef __ILP32__
check_struct_and_union3(char, long, __bf16, 24, 8);
#endif
check_struct_and_union3(char, long long, __bf16, 24, 8);
check_struct_and_union3(char, float, __bf16, 12, 4);
check_struct_and_union3(char, double, __bf16, 24, 8);
check_struct_and_union3(char, long double, __bf16, 48, 16);
check_struct_and_union3(__bf16, char, char, 4, 2);
check_struct_and_union3(__bf16, char, __bf16, 6, 2);
check_struct_and_union3(__bf16, char, int, 8, 4);
#ifndef __ILP32__
check_struct_and_union3(__bf16, char, long, 16, 8);
#endif
check_struct_and_union3(__bf16, char, long long, 16, 8);
check_struct_and_union3(__bf16, char, float, 8, 4);
check_struct_and_union3(__bf16, char, double, 16, 8);
check_struct_and_union3(__bf16, char, long double, 32, 16);
check_struct_and_union3(__bf16, __bf16, char, 6, 2);
check_struct_and_union3(__bf16, __bf16, __bf16, 6, 2);
check_struct_and_union3(__bf16, __bf16, int, 8, 4);
#ifndef __ILP32__
check_struct_and_union3(__bf16, __bf16, long, 16, 8);
#endif
check_struct_and_union3(__bf16, __bf16, long long, 16, 8);
check_struct_and_union3(__bf16, __bf16, float, 8, 4);
check_struct_and_union3(__bf16, __bf16, double, 16, 8);
check_struct_and_union3(__bf16, __bf16, long double, 32, 16);
check_struct_and_union3(__bf16, int, char, 12, 4);
check_struct_and_union3(__bf16, int, __bf16, 12, 4);
check_struct_and_union3(__bf16, int, int, 12, 4);
#ifndef __ILP32__
check_struct_and_union3(__bf16, int, long, 16, 8);
#endif
check_struct_and_union3(__bf16, int, long long, 16, 8);
check_struct_and_union3(__bf16, int, float, 12, 4);
check_struct_and_union3(__bf16, int, double, 16, 8);
check_struct_and_union3(__bf16, int, long double, 32, 16);
#ifndef __ILP32__
check_struct_and_union3(__bf16, long, char, 24, 8);
check_struct_and_union3(__bf16, long, __bf16, 24, 8);
check_struct_and_union3(__bf16, long, int, 24, 8);
check_struct_and_union3(__bf16, long, long, 24, 8);
check_struct_and_union3(__bf16, long, long long, 24, 8);
check_struct_and_union3(__bf16, long, float, 24, 8);
check_struct_and_union3(__bf16, long, double, 24, 8);
#endif
check_struct_and_union3(__bf16, long, long double, 32, 16);
check_struct_and_union3(__bf16, long long, char, 24, 8);
check_struct_and_union3(__bf16, long long, __bf16, 24, 8);
check_struct_and_union3(__bf16, long long, int, 24, 8);
check_struct_and_union3(__bf16, long long, long, 24, 8);
check_struct_and_union3(__bf16, long long, long long, 24, 8);
check_struct_and_union3(__bf16, long long, float, 24, 8);
check_struct_and_union3(__bf16, long long, double, 24, 8);
check_struct_and_union3(__bf16, long long, long double, 32, 16);
check_struct_and_union3(__bf16, float, char, 12, 4);
check_struct_and_union3(__bf16, float, __bf16, 12, 4);
check_struct_and_union3(__bf16, float, int, 12, 4);
#ifndef __ILP32__
check_struct_and_union3(__bf16, float, long, 16, 8);
#endif
check_struct_and_union3(__bf16, float, long long, 16, 8);
check_struct_and_union3(__bf16, float, float, 12, 4);
check_struct_and_union3(__bf16, float, double, 16, 8);
check_struct_and_union3(__bf16, float, long double, 32, 16);
check_struct_and_union3(__bf16, double, char, 24, 8);
check_struct_and_union3(__bf16, double, __bf16, 24, 8);
check_struct_and_union3(__bf16, double, int, 24, 8);
check_struct_and_union3(__bf16, double, long, 24, 8);
check_struct_and_union3(__bf16, double, long long, 24, 8);
check_struct_and_union3(__bf16, double, float, 24, 8);
check_struct_and_union3(__bf16, double, double, 24, 8);
check_struct_and_union3(__bf16, double, long double, 32, 16);
check_struct_and_union3(__bf16, long double, char, 48, 16);
check_struct_and_union3(__bf16, long double, __bf16, 48, 16);
check_struct_and_union3(__bf16, long double, int, 48, 16);
check_struct_and_union3(__bf16, long double, long, 48, 16);
check_struct_and_union3(__bf16, long double, long long, 48, 16);
check_struct_and_union3(__bf16, long double, float, 48, 16);
check_struct_and_union3(__bf16, long double, double, 48, 16);
check_struct_and_union3(__bf16, long double, long double, 48, 16);
check_struct_and_union3(int, char, __bf16, 8, 4);
check_struct_and_union3(int, __bf16, char, 8, 4);
check_struct_and_union3(int, __bf16, __bf16, 8, 4);
check_struct_and_union3(int, __bf16, int, 12, 4);
#ifndef __ILP32__
check_struct_and_union3(int, __bf16, long, 16, 8);
#endif
check_struct_and_union3(int, __bf16, long long, 16, 8);
check_struct_and_union3(int, __bf16, float, 12, 4);
check_struct_and_union3(int, __bf16, double, 16, 8);
check_struct_and_union3(int, __bf16, long double, 32, 16);
check_struct_and_union3(int, int, __bf16, 12, 4);
#ifndef __ILP32__
check_struct_and_union3(int, long, __bf16, 24, 8);
#endif
check_struct_and_union3(int, long long, __bf16, 24, 8);
check_struct_and_union3(int, float, __bf16, 12, 4);
check_struct_and_union3(int, double, __bf16, 24, 8);
check_struct_and_union3(int, long double, __bf16, 48, 16);
#ifndef __ILP32__
check_struct_and_union3(long, char, __bf16, 16, 8);
check_struct_and_union3(long, __bf16, char, 16, 8);
check_struct_and_union3(long, __bf16, __bf16, 16, 8);
check_struct_and_union3(long, __bf16, int, 16, 8);
check_struct_and_union3(long, __bf16, long, 24, 8);
check_struct_and_union3(long, __bf16, long long, 24, 8);
check_struct_and_union3(long, __bf16, float, 16, 8);
check_struct_and_union3(long, __bf16, double, 24, 8);
#endif
check_struct_and_union3(long, __bf16, long double, 32, 16);
#ifndef __ILP32__
check_struct_and_union3(long, int, __bf16, 16, 8);
check_struct_and_union3(long, long, __bf16, 24, 8);
check_struct_and_union3(long, long long, __bf16, 24, 8);
check_struct_and_union3(long, float, __bf16, 16, 8);
check_struct_and_union3(long, double, __bf16, 24, 8);
#endif
check_struct_and_union3(long, long double, __bf16, 48, 16);
check_struct_and_union3(long long, char, __bf16, 16, 8);
check_struct_and_union3(long long, __bf16, char, 16, 8);
check_struct_and_union3(long long, __bf16, __bf16, 16, 8);
check_struct_and_union3(long long, __bf16, int, 16, 8);
#ifndef __ILP32__
check_struct_and_union3(long long, __bf16, long, 24, 8);
#endif
check_struct_and_union3(long long, __bf16, long long, 24, 8);
check_struct_and_union3(long long, __bf16, float, 16, 8);
check_struct_and_union3(long long, __bf16, double, 24, 8);
check_struct_and_union3(long long, __bf16, long double, 32, 16);
check_struct_and_union3(long long, int, __bf16, 16, 8);
#ifndef __ILP32__
check_struct_and_union3(long long, long, __bf16, 24, 8);
#endif
check_struct_and_union3(long long, long long, __bf16, 24, 8);
check_struct_and_union3(long long, float, __bf16, 16, 8);
check_struct_and_union3(long long, double, __bf16, 24, 8);
check_struct_and_union3(long long, long double, __bf16, 48, 16);
check_struct_and_union3(float, char, __bf16, 8, 4);
check_struct_and_union3(float, __bf16, char, 8, 4);
check_struct_and_union3(float, __bf16, __bf16, 8, 4);
check_struct_and_union3(float, __bf16, int, 12, 4);
#ifndef __ILP32__
check_struct_and_union3(float, __bf16, long, 16, 8);
#endif
check_struct_and_union3(float, __bf16, long long, 16, 8);
check_struct_and_union3(float, __bf16, float, 12, 4);
check_struct_and_union3(float, __bf16, double, 16, 8);
check_struct_and_union3(float, __bf16, long double, 32, 16);
check_struct_and_union3(float, int, __bf16, 12, 4);
#ifndef __ILP32__
check_struct_and_union3(float, long, __bf16, 24, 8);
#endif
check_struct_and_union3(float, long long, __bf16, 24, 8);
check_struct_and_union3(float, float, __bf16, 12, 4);
check_struct_and_union3(float, double, __bf16, 24, 8);
check_struct_and_union3(float, long double, __bf16, 48, 16);
check_struct_and_union3(double, char, __bf16, 16, 8);
check_struct_and_union3(double, __bf16, char, 16, 8);
check_struct_and_union3(double, __bf16, __bf16, 16, 8);
check_struct_and_union3(double, __bf16, int, 16, 8);
#ifndef __ILP32__
check_struct_and_union3(double, __bf16, long, 24, 8);
#endif
check_struct_and_union3(double, __bf16, long long, 24, 8);
check_struct_and_union3(double, __bf16, float, 16, 8);
check_struct_and_union3(double, __bf16, double, 24, 8);
check_struct_and_union3(double, __bf16, long double, 32, 16);
check_struct_and_union3(double, int, __bf16, 16, 8);
#ifndef __ILP32__
check_struct_and_union3(double, long, __bf16, 24, 8);
#endif
check_struct_and_union3(double, long long, __bf16, 24, 8);
check_struct_and_union3(double, float, __bf16, 16, 8);
check_struct_and_union3(double, double, __bf16, 24, 8);
check_struct_and_union3(double, long double, __bf16, 48, 16);
check_struct_and_union3(long double, char, __bf16, 32, 16);
check_struct_and_union3(long double, __bf16, char, 32, 16);
check_struct_and_union3(long double, __bf16, __bf16, 32, 16);
check_struct_and_union3(long double, __bf16, int, 32, 16);
check_struct_and_union3(long double, __bf16, long, 32, 16);
check_struct_and_union3(long double, __bf16, long long, 32, 16);
check_struct_and_union3(long double, __bf16, float, 32, 16);
check_struct_and_union3(long double, __bf16, double, 32, 16);
check_struct_and_union3(long double, __bf16, long double, 48, 16);
check_struct_and_union3(long double, int, __bf16, 32, 16);
check_struct_and_union3(long double, long, __bf16, 32, 16);
check_struct_and_union3(long double, long long, __bf16, 32, 16);
check_struct_and_union3(long double, float, __bf16, 32, 16);
check_struct_and_union3(long double, double, __bf16, 32, 16);
check_struct_and_union3(long double, long double, __bf16, 48, 16);
return 0;
}

View File

@ -0,0 +1,14 @@
/* This checks alignment of basic types. */
#include "defines.h"
#include "macros.h"
int
main (void)
{
/* __bf16 point types. */
check_align(__bf16, TYPE_ALIGN_BF16);
return 0;
}

View File

@ -0,0 +1,13 @@
/* This checks . */
#include "defines.h"
#include "macros.h"
int
main (void)
{
check_array_size_and_align(__bf16, TYPE_SIZE_BF16, TYPE_ALIGN_BF16);
return 0;
}

View File

@ -0,0 +1,20 @@
#include "bf16-check.h"
#include "defines.h"
#include "macros.h"
#include "args.h"
__bf16
fun_test_returning_bf16 (void)
{
__bf16 b = make_f32_bf16 (72.0f);
volatile_var++;
return b;
}
static void
do_test (void)
{
__bf16 var = WRAP_RET (fun_test_returning_bf16) ();
assert (check_bf16_float (xmm_regs[0].___bf16[0], 72.0f) == 1);
assert (check_bf16_float (var, 72.0f) == 1);
}

View File

@ -0,0 +1,14 @@
/* This checks sizes of basic types. */
#include "defines.h"
#include "macros.h"
int
main (void)
{
/* Floating point types. */
check_size(__bf16, TYPE_SIZE_BF16);
return 0;
}

View File

@ -0,0 +1,14 @@
/* This checks size and alignment of structs with a single basic type
element. All basic types are checked. */
#include "bf16-check.h"
#include "defines.h"
#include "macros.h"
static void
do_test (void)
{
/* Floating point types. */
check_basic_struct_size_and_align(__bf16, TYPE_SIZE_BF16, TYPE_ALIGN_BF16);
}

View File

@ -0,0 +1,12 @@
/* Test of simple unions, size and alignment. */
#include "bf16-check.h"
#include "defines.h"
#include "macros.h"
static void
do_test (void)
{
/* Floating point types. */
check_basic_union_size_and_align(__bf16, TYPE_SIZE_BF16, TYPE_ALIGN_BF16);
}

View File

@ -0,0 +1,38 @@
#include <stdio.h>
#include "bf16-check.h"
#include "defines.h"
#include "macros.h"
#include "args.h"
struct FloatRegisters fregs;
struct IntegerRegisters iregs;
unsigned int num_fregs, num_iregs;
volatile __bf16 bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8;
__m128bf16
fun_test_returning___m128bf16 (void)
{
volatile_var++;
return (__m128bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8 };
}
__m128bf16 test_128bf16;
static void
do_test (void)
{
unsigned failed = 0;
XMM_T xmmt1, xmmt2;
clear_struct_registers;
test_128bf16 = (__m128bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8 };
xmmt1._m128bf16[0] = test_128bf16;
xmmt2._m128bf16[0] = WRAP_RET (fun_test_returning___m128bf16)();
if (xmmt1._longlong[0] != xmmt2._longlong[0]
|| xmmt1._longlong[0] != xmm_regs[0]._longlong[0])
printf ("fail m128bf16\n"), failed++;
if (failed)
abort ();
}

View File

@ -0,0 +1,312 @@
/* This is an autogenerated file. Do not edit. */
#include "bf16-check.h"
#include "defines.h"
#include "macros.h"
#include "args.h"
struct IntegerRegisters iregs;
struct FloatRegisters fregs;
unsigned int num_iregs, num_fregs;
/* This struct holds values for argument checking. */
struct
{
__bf16 f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14,
f15, f16, f17, f18, f19, f20, f21, f22, f23;
} values___bf16;
void
fun_check_bf16_passing_8_values (__bf16 f0 ATTRIBUTE_UNUSED,
__bf16 f1 ATTRIBUTE_UNUSED,
__bf16 f2 ATTRIBUTE_UNUSED,
__bf16 f3 ATTRIBUTE_UNUSED,
__bf16 f4 ATTRIBUTE_UNUSED,
__bf16 f5 ATTRIBUTE_UNUSED,
__bf16 f6 ATTRIBUTE_UNUSED,
__bf16 f7 ATTRIBUTE_UNUSED)
{
/* Check argument values. */
check_bf16 (values___bf16.f0, f0);
check_bf16 (values___bf16.f1, f1);
check_bf16 (values___bf16.f2, f2);
check_bf16 (values___bf16.f3, f3);
check_bf16 (values___bf16.f4, f4);
check_bf16 (values___bf16.f5, f5);
check_bf16 (values___bf16.f6, f6);
check_bf16 (values___bf16.f7, f7);
}
void
fun_check_bf16_passing_8_regs (__bf16 f0 ATTRIBUTE_UNUSED,
__bf16 f1 ATTRIBUTE_UNUSED,
__bf16 f2 ATTRIBUTE_UNUSED,
__bf16 f3 ATTRIBUTE_UNUSED,
__bf16 f4 ATTRIBUTE_UNUSED,
__bf16 f5 ATTRIBUTE_UNUSED,
__bf16 f6 ATTRIBUTE_UNUSED,
__bf16 f7 ATTRIBUTE_UNUSED)
{
/* Check register contents. */
check_bf16_arguments;
}
void
fun_check_bf16_passing_16_values (__bf16 f0 ATTRIBUTE_UNUSED,
__bf16 f1 ATTRIBUTE_UNUSED,
__bf16 f2 ATTRIBUTE_UNUSED,
__bf16 f3 ATTRIBUTE_UNUSED,
__bf16 f4 ATTRIBUTE_UNUSED,
__bf16 f5 ATTRIBUTE_UNUSED,
__bf16 f6 ATTRIBUTE_UNUSED,
__bf16 f7 ATTRIBUTE_UNUSED,
__bf16 f8 ATTRIBUTE_UNUSED,
__bf16 f9 ATTRIBUTE_UNUSED,
__bf16 f10 ATTRIBUTE_UNUSED,
__bf16 f11 ATTRIBUTE_UNUSED,
__bf16 f12 ATTRIBUTE_UNUSED,
__bf16 f13 ATTRIBUTE_UNUSED,
__bf16 f14 ATTRIBUTE_UNUSED,
__bf16 f15 ATTRIBUTE_UNUSED)
{
/* Check argument values. */
check_bf16 (values___bf16.f0, f0);
check_bf16 (values___bf16.f1, f1);
check_bf16 (values___bf16.f2, f2);
check_bf16 (values___bf16.f3, f3);
check_bf16 (values___bf16.f4, f4);
check_bf16 (values___bf16.f5, f5);
check_bf16 (values___bf16.f6, f6);
check_bf16 (values___bf16.f7, f7);
check_bf16 (values___bf16.f8, f8);
check_bf16 (values___bf16.f9, f9);
check_bf16 (values___bf16.f10, f10);
check_bf16 (values___bf16.f11, f11);
check_bf16 (values___bf16.f12, f12);
check_bf16 (values___bf16.f13, f13);
check_bf16 (values___bf16.f14, f14);
check_bf16 (values___bf16.f15, f15);
}
void
fun_check_bf16_passing_16_regs (__bf16 f0 ATTRIBUTE_UNUSED,
__bf16 f1 ATTRIBUTE_UNUSED,
__bf16 f2 ATTRIBUTE_UNUSED,
__bf16 f3 ATTRIBUTE_UNUSED,
__bf16 f4 ATTRIBUTE_UNUSED,
__bf16 f5 ATTRIBUTE_UNUSED,
__bf16 f6 ATTRIBUTE_UNUSED,
__bf16 f7 ATTRIBUTE_UNUSED,
__bf16 f8 ATTRIBUTE_UNUSED,
__bf16 f9 ATTRIBUTE_UNUSED,
__bf16 f10 ATTRIBUTE_UNUSED,
__bf16 f11 ATTRIBUTE_UNUSED,
__bf16 f12 ATTRIBUTE_UNUSED,
__bf16 f13 ATTRIBUTE_UNUSED,
__bf16 f14 ATTRIBUTE_UNUSED,
__bf16 f15 ATTRIBUTE_UNUSED)
{
/* Check register contents. */
check_bf16_arguments;
}
void
fun_check_bf16_passing_20_values (__bf16 f0 ATTRIBUTE_UNUSED,
__bf16 f1 ATTRIBUTE_UNUSED,
__bf16 f2 ATTRIBUTE_UNUSED,
__bf16 f3 ATTRIBUTE_UNUSED,
__bf16 f4 ATTRIBUTE_UNUSED,
__bf16 f5 ATTRIBUTE_UNUSED,
__bf16 f6 ATTRIBUTE_UNUSED,
__bf16 f7 ATTRIBUTE_UNUSED,
__bf16 f8 ATTRIBUTE_UNUSED,
__bf16 f9 ATTRIBUTE_UNUSED,
__bf16 f10 ATTRIBUTE_UNUSED,
__bf16 f11 ATTRIBUTE_UNUSED,
__bf16 f12 ATTRIBUTE_UNUSED,
__bf16 f13 ATTRIBUTE_UNUSED,
__bf16 f14 ATTRIBUTE_UNUSED,
__bf16 f15 ATTRIBUTE_UNUSED,
__bf16 f16 ATTRIBUTE_UNUSED,
__bf16 f17 ATTRIBUTE_UNUSED,
__bf16 f18 ATTRIBUTE_UNUSED,
__bf16 f19 ATTRIBUTE_UNUSED)
{
/* Check argument values. */
check_bf16 (values___bf16.f0, f0);
check_bf16 (values___bf16.f1, f1);
check_bf16 (values___bf16.f2, f2);
check_bf16 (values___bf16.f3, f3);
check_bf16 (values___bf16.f4, f4);
check_bf16 (values___bf16.f5, f5);
check_bf16 (values___bf16.f6, f6);
check_bf16 (values___bf16.f7, f7);
check_bf16 (values___bf16.f8, f8);
check_bf16 (values___bf16.f9, f9);
check_bf16 (values___bf16.f10, f10);
check_bf16 (values___bf16.f11, f11);
check_bf16 (values___bf16.f12, f12);
check_bf16 (values___bf16.f13, f13);
check_bf16 (values___bf16.f14, f14);
check_bf16 (values___bf16.f15, f15);
check_bf16 (values___bf16.f16, f16);
check_bf16 (values___bf16.f17, f17);
check_bf16 (values___bf16.f18, f18);
check_bf16 (values___bf16.f19, f19);
}
void
fun_check_bf16_passing_20_regs (__bf16 f0 ATTRIBUTE_UNUSED,
__bf16 f1 ATTRIBUTE_UNUSED,
__bf16 f2 ATTRIBUTE_UNUSED,
__bf16 f3 ATTRIBUTE_UNUSED,
__bf16 f4 ATTRIBUTE_UNUSED,
__bf16 f5 ATTRIBUTE_UNUSED,
__bf16 f6 ATTRIBUTE_UNUSED,
__bf16 f7 ATTRIBUTE_UNUSED,
__bf16 f8 ATTRIBUTE_UNUSED,
__bf16 f9 ATTRIBUTE_UNUSED,
__bf16 f10 ATTRIBUTE_UNUSED,
__bf16 f11 ATTRIBUTE_UNUSED,
__bf16 f12 ATTRIBUTE_UNUSED,
__bf16 f13 ATTRIBUTE_UNUSED,
__bf16 f14 ATTRIBUTE_UNUSED,
__bf16 f15 ATTRIBUTE_UNUSED,
__bf16 f16 ATTRIBUTE_UNUSED,
__bf16 f17 ATTRIBUTE_UNUSED,
__bf16 f18 ATTRIBUTE_UNUSED,
__bf16 f19 ATTRIBUTE_UNUSED)
{
/* Check register contents. */
check_bf16_arguments;
}
#define def_check_bf16_passing8(_f0, _f1, _f2, _f3, _f4, _f5, _f6,\
_f7, _func1, _func2, TYPE) \
values_ ## TYPE .f0 = _f0; \
values_ ## TYPE .f1 = _f1; \
values_ ## TYPE .f2 = _f2; \
values_ ## TYPE .f3 = _f3; \
values_ ## TYPE .f4 = _f4; \
values_ ## TYPE .f5 = _f5; \
values_ ## TYPE .f6 = _f6; \
values_ ## TYPE .f7 = _f7; \
WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7); \
clear_float_registers; \
fregs.F0._ ## TYPE [0] = _f0; \
fregs.F1._ ## TYPE [0] = _f1; \
fregs.F2._ ## TYPE [0] = _f2; \
fregs.F3._ ## TYPE [0] = _f3; \
fregs.F4._ ## TYPE [0] = _f4; \
fregs.F5._ ## TYPE [0] = _f5; \
fregs.F6._ ## TYPE [0] = _f6; \
fregs.F7._ ## TYPE [0] = _f7; \
num_fregs = 8; \
WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7);
#define def_check_bf16_passing16(_f0, _f1, _f2, _f3, _f4, _f5, _f6, \
_f7, _f8, _f9, _f10, _f11, _f12, _f13, \
_f14, _f15, _func1, _func2, TYPE) \
values_ ## TYPE .f0 = _f0; \
values_ ## TYPE .f1 = _f1; \
values_ ## TYPE .f2 = _f2; \
values_ ## TYPE .f3 = _f3; \
values_ ## TYPE .f4 = _f4; \
values_ ## TYPE .f5 = _f5; \
values_ ## TYPE .f6 = _f6; \
values_ ## TYPE .f7 = _f7; \
values_ ## TYPE .f8 = _f8; \
values_ ## TYPE .f9 = _f9; \
values_ ## TYPE .f10 = _f10; \
values_ ## TYPE .f11 = _f11; \
values_ ## TYPE .f12 = _f12; \
values_ ## TYPE .f13 = _f13; \
values_ ## TYPE .f14 = _f14; \
values_ ## TYPE .f15 = _f15; \
WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, \
_f10, _f11, _f12, _f13, _f14, _f15); \
clear_float_registers; \
fregs.F0._ ## TYPE [0] = _f0; \
fregs.F1._ ## TYPE [0] = _f1; \
fregs.F2._ ## TYPE [0] = _f2; \
fregs.F3._ ## TYPE [0] = _f3; \
fregs.F4._ ## TYPE [0] = _f4; \
fregs.F5._ ## TYPE [0] = _f5; \
fregs.F6._ ## TYPE [0] = _f6; \
fregs.F7._ ## TYPE [0] = _f7; \
num_fregs = 8; \
WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, \
_f10, _f11, _f12, _f13, _f14, _f15);
#define def_check_bf16_passing20(_f0, _f1, _f2, _f3, _f4, _f5, _f6, \
_f7, _f8, _f9, _f10, _f11, _f12, \
_f13, _f14, _f15, _f16, _f17, \
_f18, _f19, _func1, _func2, TYPE) \
values_ ## TYPE .f0 = _f0; \
values_ ## TYPE .f1 = _f1; \
values_ ## TYPE .f2 = _f2; \
values_ ## TYPE .f3 = _f3; \
values_ ## TYPE .f4 = _f4; \
values_ ## TYPE .f5 = _f5; \
values_ ## TYPE .f6 = _f6; \
values_ ## TYPE .f7 = _f7; \
values_ ## TYPE .f8 = _f8; \
values_ ## TYPE .f9 = _f9; \
values_ ## TYPE .f10 = _f10; \
values_ ## TYPE .f11 = _f11; \
values_ ## TYPE .f12 = _f12; \
values_ ## TYPE .f13 = _f13; \
values_ ## TYPE .f14 = _f14; \
values_ ## TYPE .f15 = _f15; \
values_ ## TYPE .f16 = _f16; \
values_ ## TYPE .f17 = _f17; \
values_ ## TYPE .f18 = _f18; \
values_ ## TYPE .f19 = _f19; \
WRAP_CALL(_func1) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, \
_f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, \
_f17, _f18, _f19); \
clear_float_registers; \
fregs.F0._ ## TYPE [0] = _f0; \
fregs.F1._ ## TYPE [0] = _f1; \
fregs.F2._ ## TYPE [0] = _f2; \
fregs.F3._ ## TYPE [0] = _f3; \
fregs.F4._ ## TYPE [0] = _f4; \
fregs.F5._ ## TYPE [0] = _f5; \
fregs.F6._ ## TYPE [0] = _f6; \
fregs.F7._ ## TYPE [0] = _f7; \
num_fregs = 8; \
WRAP_CALL(_func2) (_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, \
_f10, _f11, _f12, _f13, _f14, _f15, _f16, _f17, \
_f18, _f19);
volatile __bf16 bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8, bf9, bf10,
bf11,bf12,bf13,bf14,bf15,bf16,bf17,bf18,bf19,bf20;
void
test_bf16_on_stack ()
{
def_check_bf16_passing8 (bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
fun_check_bf16_passing_8_values,
fun_check_bf16_passing_8_regs, __bf16);
def_check_bf16_passing16 (bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16,
fun_check_bf16_passing_16_values,
fun_check_bf16_passing_16_regs, __bf16);
}
void
test_too_many_bf16 ()
{
def_check_bf16_passing20 (bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8, bf9, bf10,
bf11,bf12,bf13,bf14,bf15,bf16,bf17,bf18,bf19,bf20,
fun_check_bf16_passing_20_values,
fun_check_bf16_passing_20_regs, __bf16);
}
static void
do_test (void)
{
test_bf16_on_stack ();
test_too_many_bf16 ();
}

View File

@ -0,0 +1,238 @@
#include <stdio.h>
#include "bf16-check.h"
#include "defines.h"
#include "macros.h"
#include "args.h"
struct FloatRegisters fregs;
struct IntegerRegisters iregs;
unsigned int num_fregs, num_iregs;
/* This struct holds values for argument checking. */
struct
{
XMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15,
i16, i17, i18, i19, i20, i21, i22, i23;
} values;
char *pass;
int failed = 0;
#undef assert
#define assert(c) do { \
if (!(c)) {failed++; printf ("failed %s\n", pass); } \
} while (0)
#define compare(X1,X2,T) do { \
assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
} while (0)
void
fun_check_passing_m128bf16_8_values (__m128bf16 i0 ATTRIBUTE_UNUSED,
__m128bf16 i1 ATTRIBUTE_UNUSED,
__m128bf16 i2 ATTRIBUTE_UNUSED,
__m128bf16 i3 ATTRIBUTE_UNUSED,
__m128bf16 i4 ATTRIBUTE_UNUSED,
__m128bf16 i5 ATTRIBUTE_UNUSED,
__m128bf16 i6 ATTRIBUTE_UNUSED,
__m128bf16 i7 ATTRIBUTE_UNUSED)
{
/* Check argument values. */
compare (values.i0, i0, __m128bf16);
compare (values.i1, i1, __m128bf16);
compare (values.i2, i2, __m128bf16);
compare (values.i3, i3, __m128bf16);
compare (values.i4, i4, __m128bf16);
compare (values.i5, i5, __m128bf16);
compare (values.i6, i6, __m128bf16);
compare (values.i7, i7, __m128bf16);
}
void
fun_check_passing_m128bf16_8_regs (__m128bf16 i0 ATTRIBUTE_UNUSED,
__m128bf16 i1 ATTRIBUTE_UNUSED,
__m128bf16 i2 ATTRIBUTE_UNUSED,
__m128bf16 i3 ATTRIBUTE_UNUSED,
__m128bf16 i4 ATTRIBUTE_UNUSED,
__m128bf16 i5 ATTRIBUTE_UNUSED,
__m128bf16 i6 ATTRIBUTE_UNUSED,
__m128bf16 i7 ATTRIBUTE_UNUSED)
{
/* Check register contents. */
check_m128_arguments;
}
void
fun_check_passing_m128bf16_20_values (__m128bf16 i0 ATTRIBUTE_UNUSED,
__m128bf16 i1 ATTRIBUTE_UNUSED,
__m128bf16 i2 ATTRIBUTE_UNUSED,
__m128bf16 i3 ATTRIBUTE_UNUSED,
__m128bf16 i4 ATTRIBUTE_UNUSED,
__m128bf16 i5 ATTRIBUTE_UNUSED,
__m128bf16 i6 ATTRIBUTE_UNUSED,
__m128bf16 i7 ATTRIBUTE_UNUSED,
__m128bf16 i8 ATTRIBUTE_UNUSED,
__m128bf16 i9 ATTRIBUTE_UNUSED,
__m128bf16 i10 ATTRIBUTE_UNUSED,
__m128bf16 i11 ATTRIBUTE_UNUSED,
__m128bf16 i12 ATTRIBUTE_UNUSED,
__m128bf16 i13 ATTRIBUTE_UNUSED,
__m128bf16 i14 ATTRIBUTE_UNUSED,
__m128bf16 i15 ATTRIBUTE_UNUSED,
__m128bf16 i16 ATTRIBUTE_UNUSED,
__m128bf16 i17 ATTRIBUTE_UNUSED,
__m128bf16 i18 ATTRIBUTE_UNUSED,
__m128bf16 i19 ATTRIBUTE_UNUSED)
{
/* Check argument values. */
compare (values.i0, i0, __m128bf16);
compare (values.i1, i1, __m128bf16);
compare (values.i2, i2, __m128bf16);
compare (values.i3, i3, __m128bf16);
compare (values.i4, i4, __m128bf16);
compare (values.i5, i5, __m128bf16);
compare (values.i6, i6, __m128bf16);
compare (values.i7, i7, __m128bf16);
compare (values.i8, i8, __m128bf16);
compare (values.i9, i9, __m128bf16);
compare (values.i10, i10, __m128bf16);
compare (values.i11, i11, __m128bf16);
compare (values.i12, i12, __m128bf16);
compare (values.i13, i13, __m128bf16);
compare (values.i14, i14, __m128bf16);
compare (values.i15, i15, __m128bf16);
compare (values.i16, i16, __m128bf16);
compare (values.i17, i17, __m128bf16);
compare (values.i18, i18, __m128bf16);
compare (values.i19, i19, __m128bf16);
}
void
fun_check_passing_m128bf16_20_regs (__m128bf16 i0 ATTRIBUTE_UNUSED,
__m128bf16 i1 ATTRIBUTE_UNUSED,
__m128bf16 i2 ATTRIBUTE_UNUSED,
__m128bf16 i3 ATTRIBUTE_UNUSED,
__m128bf16 i4 ATTRIBUTE_UNUSED,
__m128bf16 i5 ATTRIBUTE_UNUSED,
__m128bf16 i6 ATTRIBUTE_UNUSED,
__m128bf16 i7 ATTRIBUTE_UNUSED,
__m128bf16 i8 ATTRIBUTE_UNUSED,
__m128bf16 i9 ATTRIBUTE_UNUSED,
__m128bf16 i10 ATTRIBUTE_UNUSED,
__m128bf16 i11 ATTRIBUTE_UNUSED,
__m128bf16 i12 ATTRIBUTE_UNUSED,
__m128bf16 i13 ATTRIBUTE_UNUSED,
__m128bf16 i14 ATTRIBUTE_UNUSED,
__m128bf16 i15 ATTRIBUTE_UNUSED,
__m128bf16 i16 ATTRIBUTE_UNUSED,
__m128bf16 i17 ATTRIBUTE_UNUSED,
__m128bf16 i18 ATTRIBUTE_UNUSED,
__m128bf16 i19 ATTRIBUTE_UNUSED)
{
/* Check register contents. */
check_m128_arguments;
}
#define def_check_int_passing8(_i0, _i1, _i2, _i3, \
_i4, _i5, _i6, _i7, \
_func1, _func2, TYPE) \
values.i0.TYPE[0] = _i0; \
values.i1.TYPE[0] = _i1; \
values.i2.TYPE[0] = _i2; \
values.i3.TYPE[0] = _i3; \
values.i4.TYPE[0] = _i4; \
values.i5.TYPE[0] = _i5; \
values.i6.TYPE[0] = _i6; \
values.i7.TYPE[0] = _i7; \
WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7); \
clear_float_registers; \
fregs.F0.TYPE[0] = _i0; \
fregs.F1.TYPE[0] = _i1; \
fregs.F2.TYPE[0] = _i2; \
fregs.F3.TYPE[0] = _i3; \
fregs.F4.TYPE[0] = _i4; \
fregs.F5.TYPE[0] = _i5; \
fregs.F6.TYPE[0] = _i6; \
fregs.F7.TYPE[0] = _i7; \
num_fregs = 8; \
WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7);
#define def_check_int_passing20(_i0, _i1, _i2, _i3, _i4, _i5, _i6, \
_i7, _i8, _i9, _i10, _i11, _i12, _i13, \
_i14, _i15, _i16, _i17, _i18, _i19, \
_func1, _func2, TYPE) \
values.i0.TYPE[0] = _i0; \
values.i1.TYPE[0] = _i1; \
values.i2.TYPE[0] = _i2; \
values.i3.TYPE[0] = _i3; \
values.i4.TYPE[0] = _i4; \
values.i5.TYPE[0] = _i5; \
values.i6.TYPE[0] = _i6; \
values.i7.TYPE[0] = _i7; \
values.i8.TYPE[0] = _i8; \
values.i9.TYPE[0] = _i9; \
values.i10.TYPE[0] = _i10; \
values.i11.TYPE[0] = _i11; \
values.i12.TYPE[0] = _i12; \
values.i13.TYPE[0] = _i13; \
values.i14.TYPE[0] = _i14; \
values.i15.TYPE[0] = _i15; \
values.i16.TYPE[0] = _i16; \
values.i17.TYPE[0] = _i17; \
values.i18.TYPE[0] = _i18; \
values.i19.TYPE[0] = _i19; \
WRAP_CALL(_func1) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
_i9, _i10, _i11, _i12, _i13, _i14, _i15, _i16, \
_i17, _i18, _i19); \
clear_float_registers; \
fregs.F0.TYPE[0] = _i0; \
fregs.F1.TYPE[0] = _i1; \
fregs.F2.TYPE[0] = _i2; \
fregs.F3.TYPE[0] = _i3; \
fregs.F4.TYPE[0] = _i4; \
fregs.F5.TYPE[0] = _i5; \
fregs.F6.TYPE[0] = _i6; \
fregs.F7.TYPE[0] = _i7; \
num_fregs = 8; \
WRAP_CALL(_func2) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
_i9, _i10, _i11, _i12, _i13, _i14, _i15, _i16, \
_i17, _i18, _i19);
volatile __bf16 bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8;
void
test_m128bf16_on_stack ()
{
__m128bf16 x[8];
int i;
for (i = 0; i < 8; i++)
x[i] = (__m128bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8 };
pass = "m128bf16-8";
def_check_int_passing8 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
fun_check_passing_m128bf16_8_values,
fun_check_passing_m128bf16_8_regs, _m128bf16);
}
void
test_too_many_m128bf16 ()
{
__m128bf16 x[20];
int i;
for (i = 0; i < 20; i++)
x[i] = (__m128bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8 };
pass = "m128bf16-20";
def_check_int_passing20 (x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
x[8], x[9], x[10], x[11], x[12], x[13], x[14],
x[15], x[16], x[17], x[18], x[19],
fun_check_passing_m128bf16_20_values,
fun_check_passing_m128bf16_20_regs, _m128bf16);
}
static void
do_test (void)
{
test_m128bf16_on_stack ();
test_too_many_m128bf16 ();
if (failed)
abort ();
}

View File

@ -0,0 +1,67 @@
#include "bf16-check.h"
#include "defines.h"
#include "args.h"
struct FloatRegisters fregs;
struct IntegerRegisters iregs;
unsigned int num_fregs, num_iregs;
struct m128bf16_struct
{
__m128bf16 x;
};
struct m128bf16_2_struct
{
__m128bf16 x1, x2;
};
/* Check that the struct is passed as the individual members in fregs. */
void
check_struct_passing1bf16 (struct m128bf16_struct ms1 ATTRIBUTE_UNUSED,
struct m128bf16_struct ms2 ATTRIBUTE_UNUSED,
struct m128bf16_struct ms3 ATTRIBUTE_UNUSED,
struct m128bf16_struct ms4 ATTRIBUTE_UNUSED,
struct m128bf16_struct ms5 ATTRIBUTE_UNUSED,
struct m128bf16_struct ms6 ATTRIBUTE_UNUSED,
struct m128bf16_struct ms7 ATTRIBUTE_UNUSED,
struct m128bf16_struct ms8 ATTRIBUTE_UNUSED)
{
check_m128_arguments;
}
void
check_struct_passing2bf16 (struct m128bf16_2_struct ms ATTRIBUTE_UNUSED)
{
/* Check the passing on the stack by comparing the address of the
stack elements to the expected place on the stack. */
assert ((unsigned long)&ms.x1 == rsp+8);
assert ((unsigned long)&ms.x2 == rsp+24);
}
volatile __bf16 bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8,
bf9, bf10,bf11,bf12,bf13,bf14,bf15,bf16;
static void
do_test (void)
{
struct m128bf16_struct m128bf16s [8];
struct m128bf16_2_struct m128bf16_2s = {
{ bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8 },
{ bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8 },
};
int i;
for (i = 0; i < 8; i++)
{
m128bf16s[i].x = (__m128bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8 };
}
clear_struct_registers;
for (i = 0; i < 8; i++)
(&fregs.xmm0)[i]._m128bf16[0] = m128bf16s[i].x;
num_fregs = 8;
WRAP_CALL (check_struct_passing1bf16) (m128bf16s[0], m128bf16s[1], m128bf16s[2], m128bf16s[3],
m128bf16s[4], m128bf16s[5], m128bf16s[6], m128bf16s[7]);
WRAP_CALL (check_struct_passing2bf16) (m128bf16_2s);
}

View File

@ -0,0 +1,160 @@
#include "bf16-check.h"
#include "defines.h"
#include "args.h"
struct FloatRegisters fregs;
struct IntegerRegisters iregs;
unsigned int num_fregs, num_iregs;
union un1b
{
__m128bf16 x;
float f;
};
union un1bb
{
__m128bf16 x;
__bf16 f;
};
union un2b
{
__m128bf16 x;
double d;
};
union un3b
{
__m128bf16 x;
__m128 v;
};
union un4b
{
__m128bf16 x;
long double ld;
};
void
check_union_passing1b (union un1b u1 ATTRIBUTE_UNUSED,
union un1b u2 ATTRIBUTE_UNUSED,
union un1b u3 ATTRIBUTE_UNUSED,
union un1b u4 ATTRIBUTE_UNUSED,
union un1b u5 ATTRIBUTE_UNUSED,
union un1b u6 ATTRIBUTE_UNUSED,
union un1b u7 ATTRIBUTE_UNUSED,
union un1b u8 ATTRIBUTE_UNUSED)
{
check_m128_arguments;
}
void
check_union_passing1bb (union un1bb u1 ATTRIBUTE_UNUSED,
union un1bb u2 ATTRIBUTE_UNUSED,
union un1bb u3 ATTRIBUTE_UNUSED,
union un1bb u4 ATTRIBUTE_UNUSED,
union un1bb u5 ATTRIBUTE_UNUSED,
union un1bb u6 ATTRIBUTE_UNUSED,
union un1bb u7 ATTRIBUTE_UNUSED,
union un1bb u8 ATTRIBUTE_UNUSED)
{
check_m128_arguments;
}
void
check_union_passing2b (union un2b u1 ATTRIBUTE_UNUSED,
union un2b u2 ATTRIBUTE_UNUSED,
union un2b u3 ATTRIBUTE_UNUSED,
union un2b u4 ATTRIBUTE_UNUSED,
union un2b u5 ATTRIBUTE_UNUSED,
union un2b u6 ATTRIBUTE_UNUSED,
union un2b u7 ATTRIBUTE_UNUSED,
union un2b u8 ATTRIBUTE_UNUSED)
{
check_m128_arguments;
}
void
check_union_passing3b (union un3b u1 ATTRIBUTE_UNUSED,
union un3b u2 ATTRIBUTE_UNUSED,
union un3b u3 ATTRIBUTE_UNUSED,
union un3b u4 ATTRIBUTE_UNUSED,
union un3b u5 ATTRIBUTE_UNUSED,
union un3b u6 ATTRIBUTE_UNUSED,
union un3b u7 ATTRIBUTE_UNUSED,
union un3b u8 ATTRIBUTE_UNUSED)
{
check_m128_arguments;
}
void
check_union_passing4b (union un4b u ATTRIBUTE_UNUSED)
{
/* Check the passing on the stack by comparing the address of the
stack elements to the expected place on the stack. */
assert ((unsigned long)&u.x == rsp+8);
assert ((unsigned long)&u.ld == rsp+8);
}
#define check_union_passing1b WRAP_CALL(check_union_passing1b)
#define check_union_passing1bb WRAP_CALL(check_union_passing1bb)
#define check_union_passing2b WRAP_CALL(check_union_passing2b)
#define check_union_passing3b WRAP_CALL(check_union_passing3b)
#define check_union_passing4b WRAP_CALL(check_union_passing4b)
static void
do_test (void)
{
union un1b u1b[8];
union un1bb u1bb[8];
union un2b u2b[8];
union un3b u3b[8];
union un4b u4b;
int i;
__bf16 bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8;
for (i = 0; i < 8; i++)
{
u1b[i].x = (__m128bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8 };
}
clear_struct_registers;
for (i = 0; i < 8; i++)
(&fregs.xmm0)[i]._m128bf16[0] = u1b[i].x;
num_fregs = 8;
check_union_passing1b (u1b[0], u1b[1], u1b[2], u1b[3],
u1b[4], u1b[5], u1b[6], u1b[7]);
clear_struct_registers;
for (i = 0; i < 8; i++)
{
u1bb[i].x = u1b[i].x;
(&fregs.xmm0)[i]._m128bf16[0] = u1bb[i].x;
}
num_fregs = 8;
check_union_passing1bb (u1bb[0], u1bb[1], u1bb[2], u1bb[3],
u1bb[4], u1bb[5], u1bb[6], u1bb[7]);
clear_struct_registers;
for (i = 0; i < 8; i++)
{
u2b[i].x = u1b[i].x;
(&fregs.xmm0)[i]._m128bf16[0] = u2b[i].x;
}
num_fregs = 8;
check_union_passing2b (u2b[0], u2b[1], u2b[2], u2b[3],
u2b[4], u2b[5], u2b[6], u2b[7]);
clear_struct_registers;
for (i = 0; i < 8; i++)
{
u3b[i].x = u1b[i].x;
(&fregs.xmm0)[i]._m128bf16[0] = u3b[i].x;
}
num_fregs = 8;
check_union_passing3b (u3b[0], u3b[1], u3b[2], u3b[3],
u3b[4], u3b[5], u3b[6], u3b[7]);
check_union_passing4b (u4b);
}

View File

@ -0,0 +1,176 @@
/* This tests returning of structures. */
#include <stdio.h>
#include "bf16-check.h"
#include "defines.h"
#include "macros.h"
#include "args.h"
struct IntegerRegisters iregs;
struct FloatRegisters fregs;
unsigned int num_iregs, num_fregs;
int current_test;
int num_failed = 0;
#undef assert
#define assert(test) do { if (!(test)) {fprintf (stderr, "failed in test %d\n", current_test); num_failed++; } } while (0)
#define xmm0b xmm_regs[0].___bf16
#define xmm1b xmm_regs[1].___bf16
#define xmm0f xmm_regs[0]._float
#define xmm0d xmm_regs[0]._double
#define xmm1f xmm_regs[1]._float
#define xmm1d xmm_regs[1]._double
typedef enum {
SSE_B = 0,
SSE_D,
MEM,
INT_SSE,
SSE_INT,
SSE_F_H,
SSE_F_H8
} Type;
/* Structures which should be returned in SSE. */
#define D(I,MEMBERS,C,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = C; \
struct S_ ## I f_ ## I (void) { struct S_ ## I s; memset (&s, 0, sizeof(s)); B; return s; }
D(120,__bf16 f,SSE_B, s.f=make_f32_bf16(42.0f))
D(121,__bf16 f;__bf16 f2,SSE_B, s.f=make_f32_bf16(42.0f))
D(122,__bf16 f;float d,SSE_B, s.f=make_f32_bf16(42.0f))
D(123,__bf16 f;double d,SSE_B, s.f=make_f32_bf16(42.0f))
D(124,double d; __bf16 f,SSE_D, s.d=42)
D(125,__bf16 f[2],SSE_B, s.f[0]=make_f32_bf16(42.0f))
D(126,__bf16 f[3],SSE_B, s.f[0]=make_f32_bf16(42.0f))
D(127,__bf16 f[4],SSE_B, s.f[0]=make_f32_bf16(42.0f))
D(128,__bf16 f[2]; double d,SSE_B, s.f[0]=make_f32_bf16(42.0f))
D(129,double d;__bf16 f[2],SSE_D, s.d=42)
#undef D
#define D(I,MEMBERS) struct S_ ## I { MEMBERS ; }; Type class_ ## I = INT_SSE; \
struct S_ ## I f_ ## I (void) { struct S_ ## I s = { 42, make_f32_bf16(43.0f) }; return s; }
D(310,char m1; __bf16 m2)
D(311,short m1; __bf16 m2)
D(312,int m1; __bf16 m2)
D(313,long long m1; __bf16 m2)
#undef D
void check_300 (void)
{
XMM_T x;
x._ulonglong[0] = rax;
switch (current_test) {
case 310: assert ((rax & 0xff) == 42
&& check_bf16_float (x.___bf16[1], 43.0f) == 1); break;
case 311: assert ((rax & 0xffff) == 42
&& check_bf16_float (x.___bf16[1], 43.0f) == 1); break;
case 312: assert ((rax & 0xffffffff) == 42
&& check_bf16_float (x.___bf16[2], 43.0f) == 1); break;
case 313: assert (rax == 42
&& check_bf16_float (xmm0b[0], 43.0f) == 1); break;
default: assert (0); break;
}
}
/* Structures which should be returned in SSE (low) and INT (high). */
#define D(I,MEMBERS,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = SSE_INT; \
struct S_ ## I f_ ## I (void) { struct S_ ## I s; memset (&s, 0, sizeof(s)); B; return s; }
D(402,__bf16 f[4];char c, s.f[0]=make_f32_bf16(42.0f); s.c=43)
#undef D
void check_400 (void)
{
switch (current_test) {
case 402: assert (check_bf16_float (xmm0b[0], 42.0f) == 1 && (rax & 0xff) == 43); break;
default: assert (0); break;
}
}
/* Structures which should be returned in MEM. */
void *struct_addr;
#define D(I,MEMBERS) struct S_ ## I { MEMBERS ; }; Type class_ ## I = MEM; \
struct S_ ## I f_ ## I (void) { union {unsigned char c; struct S_ ## I s;} u; memset (&u.s, 0, sizeof(u.s)); u.c = 42; return u.s; }
/* Unnaturally aligned members. */
D(540,__bf16 m1[10])
D(541,char m1[1];__bf16 f[8])
#undef D
/* Special tests. */
#define D(I,MEMBERS,C,B) struct S_ ## I { MEMBERS ; }; Type class_ ## I = C; \
struct S_ ## I f_ ## I (void) { struct S_ ## I s; B; return s; }
D(601,__bf16 f[4], SSE_F_H, s.f[0] = s.f[1] = s.f[2] = s.f[3] = make_f32_bf16 (42.0f))
D(602,__bf16 f[8], SSE_F_H8,
s.f[0] = s.f[1] = s.f[2] = s.f[3] = s.f[4] = s.f[5] = s.f[6] = s.f[7] = make_f32_bf16 (42.0f))
#undef D
void clear_all (void)
{
clear_int_registers;
}
void check_all (Type class, unsigned long size)
{
switch (class) {
case SSE_B: assert (check_bf16_float (xmm0b[0], 42.0f) == 1); break;
case SSE_D: assert (xmm0d[0] == 42); break;
case SSE_F_H: assert (check_bf16_float (xmm0b[0], 42) == 1
&& check_bf16_float (xmm0b[1], 42) == 1
&& check_bf16_float (xmm0b[2], 42) == 1
&& check_bf16_float (xmm0b[3], 42) == 1); break;
case SSE_F_H8: assert (check_bf16_float (xmm0b[0], 42) == 1
&& check_bf16_float (xmm0b[1], 42) == 1
&& check_bf16_float (xmm0b[2], 42) == 1
&& check_bf16_float (xmm0b[3], 42) == 1
&& check_bf16_float (xmm1b[0], 42) == 1
&& check_bf16_float (xmm1b[1], 42) == 1
&& check_bf16_float (xmm1b[2], 42) == 1
&& check_bf16_float (xmm1b[3], 42) == 1); break;
case INT_SSE: check_300(); break;
case SSE_INT: check_400(); break;
/* Ideally we would like to check that rax == struct_addr.
Unfortunately the address of the target struct escapes (for setting
struct_addr), so the return struct is a temporary one whose address
is given to the f_* functions, otherwise a conforming program
could notice the struct changing already before the function returns.
This temporary struct could be anywhere. For GCC it will be on
stack, but no one is forbidding that it could be a static variable
if there's no threading or proper locking. Nobody in his right mind
will not use the stack for that. */
case MEM: assert (*(unsigned char*)struct_addr == 42 && rdi == rax); break;
}
}
#define D(I) { struct S_ ## I s; current_test = I; struct_addr = (void*)&s; \
clear_all(); \
s = WRAP_RET(f_ ## I) (); \
check_all(class_ ## I, sizeof(s)); \
}
static void
do_test (void)
{
D(120) D(121) D(122) D(123) D(124) D(125) D(126) D(127) D(128) D(129)
D(310) D(311) D(312) D(313)
D(402)
D(540) D(541)
D(601) D(602)
if (num_failed)
abort ();
}
#undef D

View File

@ -0,0 +1,111 @@
/* Test variable number of 128-bit vector arguments passed to functions. */
#include <stdio.h>
#include "bf16-check.h"
#include "defines.h"
#include "macros.h"
#include "args.h"
struct FloatRegisters fregs;
struct IntegerRegisters iregs;
/* This struct holds values for argument checking. */
struct
{
XMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
} values;
char *pass;
int failed = 0;
#undef assert
#define assert(c) do { \
if (!(c)) {failed++; printf ("failed %s\n", pass); } \
} while (0)
#define compare(X1,X2,T) do { \
assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
} while (0)
void
fun_check_passing_m128bf16_varargs (__m128bf16 i0, __m128bf16 i1, __m128bf16 i2,
__m128bf16 i3, ...)
{
/* Check argument values. */
void **fp = __builtin_frame_address (0);
void *ra = __builtin_return_address (0);
__m128bf16 *argp;
compare (values.i0, i0, __m128bf16);
compare (values.i1, i1, __m128bf16);
compare (values.i2, i2, __m128bf16);
compare (values.i3, i3, __m128bf16);
/* Get the pointer to the return address on stack. */
while (*fp != ra)
fp++;
/* Skip the return address stack slot. */
argp = (__m128bf16 *) (((char *) fp) + 8);
/* Check __m128bf16 arguments passed on stack. */
compare (values.i8, argp[0], __m128bf16);
compare (values.i9, argp[1], __m128bf16);
/* Check register contents. */
compare (fregs.xmm0, xmm_regs[0], __m128bf16);
compare (fregs.xmm1, xmm_regs[1], __m128bf16);
compare (fregs.xmm2, xmm_regs[2], __m128bf16);
compare (fregs.xmm3, xmm_regs[3], __m128bf16);
compare (fregs.xmm4, xmm_regs[4], __m128bf16);
compare (fregs.xmm5, xmm_regs[5], __m128bf16);
compare (fregs.xmm6, xmm_regs[6], __m128bf16);
compare (fregs.xmm7, xmm_regs[7], __m128bf16);
}
#define def_check_int_passing_varargs(_i0, _i1, _i2, _i3, _i4, _i5, \
_i6, _i7, _i8, _i9, \
_func, TYPE) \
values.i0.TYPE[0] = _i0; \
values.i1.TYPE[0] = _i1; \
values.i2.TYPE[0] = _i2; \
values.i3.TYPE[0] = _i3; \
values.i4.TYPE[0] = _i4; \
values.i5.TYPE[0] = _i5; \
values.i6.TYPE[0] = _i6; \
values.i7.TYPE[0] = _i7; \
values.i8.TYPE[0] = _i8; \
values.i9.TYPE[0] = _i9; \
clear_float_registers; \
fregs.F0.TYPE[0] = _i0; \
fregs.F1.TYPE[0] = _i1; \
fregs.F2.TYPE[0] = _i2; \
fregs.F3.TYPE[0] = _i3; \
fregs.F4.TYPE[0] = _i4; \
fregs.F5.TYPE[0] = _i5; \
fregs.F6.TYPE[0] = _i6; \
fregs.F7.TYPE[0] = _i7; \
WRAP_CALL(_func) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9);
void
test_m128bf16_varargs (void)
{
__m128bf16 x[10];
__bf16 bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8;
int i;
for (i = 0; i < 10; i++)
x[i] = (__m128bf16) { bf1, bf2, bf3, bf4, bf5, bf6, bf7, bf8 };
pass = "m128bf16-varargs";
def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5],
x[6], x[7], x[8], x[9],
fun_check_passing_m128bf16_varargs,
_m128bf16);
}
static void
do_test (void)
{
test_m128bf16_varargs ();
if (failed)
abort ();
}