/* A program to test that SSE/SSE2 insns do not read memory they
should not. Covers insns of the form OP %xmm, %xmm and OP memory,
%xmm only. */
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "tests/malloc.h"
#include <string.h>
typedef unsigned char V128[16];
typedef unsigned int UInt;
typedef signed int Int;
typedef unsigned char UChar;
typedef
struct {
V128 arg1;
V128 arg2;
V128 res;
}
RRArgs;
typedef
struct {
V128 arg1;
V128 res;
}
RMArgs;
static UChar randUChar ( void )
{
static UInt seed = 80021;
seed = 1103515245 * seed + 12345;
return (seed >> 17) & 0xFF;
}
static void randomise ( UChar* p, Int n )
{
Int i;
for (i = 0; i < n; i++)
p[i] = randUChar();
}
static void randV128 ( V128* v )
{
Int i;
for (i = 0; i < 16; i++)
(*v)[i] = randUChar();
}
static void randRRArgs ( RRArgs* rra )
{
randV128(&rra->arg1);
randV128(&rra->arg2);
randV128(&rra->res);
}
static void randRMArgs ( RMArgs* rra )
{
randV128(&rra->arg1);
randV128(&rra->res);
}
static void showV128 ( V128* v )
{
Int i;
for (i = 0; i < 16; i++)
printf("%02x", (Int)(*v)[i]);
}
static void showMaskedV128 ( V128* v, V128* mask )
{
Int i;
for (i = 0; i < 16; i++)
printf("%02x", (Int)( ((*v)[i]) & ((*mask)[i]) ));
}
static void showRR ( char* op, RRArgs* rra, V128* rmask )
{
printf("r %10s ", op);
showV128(&rra->arg1);
printf(" ");
showV128(&rra->arg2);
printf(" ");
showMaskedV128(&rra->res, rmask);
printf("\n");
}
static void showRM ( char* op, RMArgs* rra, UChar* mem, Int nMem, V128* rmask )
{
Int i;
assert(nMem == 4 || nMem == 8 || nMem == 16 || nMem==0);
printf("m %10s ", op);
for (i = 0; i < nMem; i++)
printf("%02x", (Int)mem[i]);
printf(" ");
showV128(&rra->arg1);
printf(" ");
showMaskedV128(&rra->res, rmask );
printf("\n");
}
#define Wrapper_RegReg(OP) \
void r_r_##OP ( RRArgs* p ) \
{ \
__asm__ __volatile__("\n" \
"\tmovups 0(%0), %%xmm6\n" \
"\tmovups 16(%0), %%xmm7\n" \
"\t" #OP " %%xmm6, %%xmm7\n" \
"\tmovups %%xmm7, 32(%0)\n" \
: \
: "r" (p) \
: "memory", "xmm6", "xmm7", "cc" \
); \
}
#define Wrapper_RegMem(OP) \
void r_m_##OP ( RMArgs* p, void* mem ) \
{ \
__asm__ __volatile__("\n" \
"\tmovups 0(%0), %%xmm7\n" \
"\t" #OP " 0(%1), %%xmm7\n" \
"\tmovups %%xmm7, 16(%0)\n" \
: \
: "r" (p), "r" (mem) \
: "memory", "xmm7", "cc" \
); \
}
#define TEST_INSN(res_mask,mem_size,insn) \
\
Wrapper_RegReg(insn) \
Wrapper_RegMem(insn) \
\
void do_##insn ( void ) \
{ \
Int i; \
UChar* buf; \
RRArgs rargs __attribute__((aligned(16))); \
RMArgs margs __attribute__((aligned(16))); \
for (i = 0; i < 5; i++) { \
randRRArgs(&rargs); \
r_r_##insn(&rargs); \
showRR(#insn, &rargs, res_mask); \
} \
for (i = 0; i < 5; i++) { \
randRMArgs(&margs); \
buf = memalign16(mem_size); \
randomise(buf,mem_size); \
r_m_##insn(&margs,buf); \
showRM(#insn, &margs, buf, mem_size, res_mask);\
free(buf); \
} \
}
/* Note: these are little endian. Hence first byte is the least
significant byte of lane zero. */
/* Mask for insns where all result bits are non-approximated. */
static V128 AllMask = { 0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF };
/* Mark for insns which produce approximated vector short results. */
static V128 ApproxPS = { 0x00,0x00,0x80,0xFF, 0x00,0x00,0x80,0xFF,
0x00,0x00,0x80,0xFF, 0x00,0x00,0x80,0xFF };
/* Mark for insns which produce approximated scalar short results. */
static V128 ApproxSS = { 0x00,0x00,0x80,0xFF, 0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF };
#define PD 16
#define SD 8
#define PS 16
#define SS 4
/* ------------------------ SSE1 ------------------------ */
TEST_INSN( &AllMask, PS,addps)
TEST_INSN( &AllMask, SS,addss)
TEST_INSN( &AllMask, PS,andnps)
TEST_INSN( &AllMask, PS,andps)
TEST_INSN( &AllMask, PS,cmpeqps)
TEST_INSN( &AllMask, SS,cmpeqss)
TEST_INSN( &AllMask, PS,cmpleps)
TEST_INSN( &AllMask, SS,cmpless)
TEST_INSN( &AllMask, PS,cmpltps)
TEST_INSN( &AllMask, SS,cmpltss)
TEST_INSN( &AllMask, PS,cmpneqps)
TEST_INSN( &AllMask, SS,cmpneqss)
TEST_INSN( &AllMask, PS,cmpnleps)
TEST_INSN( &AllMask, SS,cmpnless)
TEST_INSN( &AllMask, PS,cmpnltps)
TEST_INSN( &AllMask, SS,cmpnltss)
TEST_INSN( &AllMask, PS,cmpordps)
TEST_INSN( &AllMask, SS,cmpordss)
TEST_INSN( &AllMask, PS,cmpunordps)
TEST_INSN( &AllMask, SS,cmpunordss)
TEST_INSN( &AllMask, SS,comiss)
//TEST_INSN( &AllMask, 0,cvtpi2ps)
//TEST_INSN( &AllMask, 0,cvtps2pi)
//TEST_INSN( &AllMask, 0,cvtsi2ss)
//TEST_INSN( &AllMask, 0,cvtss2si)
//TEST_INSN( &AllMask, 0,cvttps2pi)
//TEST_INSN( &AllMask, 0,cvttss2si)
TEST_INSN( &AllMask, PS,divps)
TEST_INSN( &AllMask, SS,divss)
TEST_INSN( &AllMask, PS,maxps)
TEST_INSN( &AllMask, SS,maxss)
TEST_INSN( &AllMask, PS,minps)
TEST_INSN( &AllMask, SS,minss)
TEST_INSN( &AllMask, 16,movaps)
//TEST_INSN( &AllMask, 0,movhlps)
//TEST_INSN( &AllMask, 0,movhps)
//TEST_INSN( &AllMask, 0,movlhps)
//TEST_INSN( &AllMask, 0,movlps)
//TEST_INSN( &AllMask, 0,movmskps)
//TEST_INSN( &AllMask, 0,movntps)
//TEST_INSN( &AllMask, 0,movntq)
TEST_INSN( &AllMask, 4,movss)
TEST_INSN( &AllMask, 16,movups)
TEST_INSN( &AllMask, PS,mulps)
TEST_INSN( &AllMask, SS,mulss)
TEST_INSN( &AllMask, PS,orps)
//TEST_INSN( &AllMask, 0,pavgb) -- dup with sse2?
//TEST_INSN( &AllMask, 0,pavgw) -- dup with sse2?
//TEST_INSN( &AllMask, 0,pextrw)
//TEST_INSN( &AllMask, 0,pinsrw)
//TEST_INSN( &AllMask, 0,pmaxsw) -- dup with sse2?
//TEST_INSN( &AllMask, 0,pmaxub) -- dup with sse2?
//TEST_INSN( &AllMask, 0,pminsw) -- dup with sse2?
//TEST_INSN( &AllMask, 0,pminub) -- dup with sse2?
//TEST_INSN( &AllMask, 0,pmovmskb)
//TEST_INSN( &AllMask, 0,pmulhuw) -- dup with sse2?
TEST_INSN( &AllMask, 16,psadbw) // -- XXXXXXXXXXXXXXXX sse2 (xmm variant) not implemented!
//TEST_INSN( &AllMask, 0,pshufw)
TEST_INSN(&ApproxPS, PS,rcpps)
TEST_INSN(&ApproxSS, SS,rcpss)
TEST_INSN(&ApproxPS, PS,rsqrtps)
TEST_INSN(&ApproxSS, SS,rsqrtss)
//TEST_INSN( &AllMask, PS,shufps)
TEST_INSN( &AllMask, PS,sqrtps)
TEST_INSN( &AllMask, SS,sqrtss)
TEST_INSN( &AllMask, PS,subps)
TEST_INSN( &AllMask, SS,subss)
TEST_INSN( &AllMask, SS,ucomiss)
TEST_INSN( &AllMask, PS,unpckhps)
TEST_INSN( &AllMask, PS,unpcklps)
TEST_INSN( &AllMask, PS,xorps)
/* ------------------------ SSE2 ------------------------ */
TEST_INSN( &AllMask, PD,addpd)
TEST_INSN( &AllMask, SD,addsd)
TEST_INSN( &AllMask, PD,andnpd)
TEST_INSN( &AllMask, PD,andpd)
TEST_INSN( &AllMask, PD,cmpeqpd)
TEST_INSN( &AllMask, SD,cmpeqsd)
TEST_INSN( &AllMask, PD,cmplepd)
TEST_INSN( &AllMask, SD,cmplesd)
TEST_INSN( &AllMask, PD,cmpltpd)
TEST_INSN( &AllMask, SD,cmpltsd)
TEST_INSN( &AllMask, PD,cmpneqpd)
TEST_INSN( &AllMask, SD,cmpneqsd)
TEST_INSN( &AllMask, PD,cmpnlepd)
TEST_INSN( &AllMask, SD,cmpnlesd)
TEST_INSN( &AllMask, PD,cmpnltpd)
TEST_INSN( &AllMask, SD,cmpnltsd)
TEST_INSN( &AllMask, PD,cmpordpd)
TEST_INSN( &AllMask, SD,cmpordsd)
TEST_INSN( &AllMask, PD,cmpunordpd)
TEST_INSN( &AllMask, SD,cmpunordsd)
TEST_INSN( &AllMask, SD,comisd)
TEST_INSN( &AllMask, 8,cvtdq2pd)
TEST_INSN( &AllMask, 16,cvtdq2ps)
TEST_INSN( &AllMask, 16,cvtpd2dq)
//TEST_INSN( &AllMask, 0,cvtpd2pi)
TEST_INSN( &AllMask, 16,cvtpd2ps) /* reads 16 */
//TEST_INSN( &AllMask, 0,cvtpi2pd)
TEST_INSN( &AllMask, 16,cvtps2dq) /* reads 16 */
TEST_INSN( &AllMask, 8,cvtps2pd) /* reads 8 */
//TEST_INSN( &AllMask, 0,cvtsd2si)
TEST_INSN( &AllMask, SD,cvtsd2ss) /* reads SD */
//TEST_INSN( &AllMask, 0,cvtsi2sd)
TEST_INSN( &AllMask, SS,cvtss2sd) /* reads SS */
TEST_INSN( &AllMask, 16,cvttpd2dq)
//TEST_INSN( &AllMask, 0,cvttpd2pi)
TEST_INSN( &AllMask, 16,cvttps2dq)
//TEST_INSN( &AllMask, 0,cvttsd2si)
TEST_INSN( &AllMask, PD,divpd)
TEST_INSN( &AllMask, SD,divsd)
TEST_INSN( &AllMask, PD,maxpd)
TEST_INSN( &AllMask, SD,maxsd)
TEST_INSN( &AllMask, PD,minpd)
TEST_INSN( &AllMask, SD,minsd)
TEST_INSN( &AllMask, PD,movapd)
//TEST_INSN( &AllMask, 8,movd)
//TEST_INSN( &AllMask, 0,movdq2q)
TEST_INSN( &AllMask, 16,movdqa)
TEST_INSN( &AllMask, 16,movdqu)
//TEST_INSN( &AllMask, 16,movhpd)
//TEST_INSN( &AllMask, 16,movlpd)
//TEST_INSN( &AllMask, 0,movmskpd)
//TEST_INSN( &AllMask, 0,movntdq)
//TEST_INSN( &AllMask, 0,movnti)
//TEST_INSN( &AllMask, 0,movntpd)
TEST_INSN( &AllMask, 8,movq)
//TEST_INSN( &AllMask, 0,movq2dq)
TEST_INSN( &AllMask, 8,movsd)
TEST_INSN( &AllMask, 16,movupd)
TEST_INSN( &AllMask, PD,mulpd)
TEST_INSN( &AllMask, SD,mulsd)
TEST_INSN( &AllMask, PD,orpd)
TEST_INSN( &AllMask, 16,packssdw)
TEST_INSN( &AllMask, 16,packsswb)
TEST_INSN( &AllMask, 16,packuswb)
TEST_INSN( &AllMask, 16,paddb)
TEST_INSN( &AllMask, 16,paddd)
TEST_INSN( &AllMask, 16,paddq)
TEST_INSN( &AllMask, 16,paddsb)
TEST_INSN( &AllMask, 16,paddsw)
TEST_INSN( &AllMask, 16,paddusb)
TEST_INSN( &AllMask, 16,paddusw)
TEST_INSN( &AllMask, 16,paddw)
TEST_INSN( &AllMask, 16,pand)
TEST_INSN( &AllMask, 16,pandn)
TEST_INSN( &AllMask, 16,pavgb)
TEST_INSN( &AllMask, 16,pavgw)
TEST_INSN( &AllMask, 16,pcmpeqb)
TEST_INSN( &AllMask, 16,pcmpeqd)
TEST_INSN( &AllMask, 16,pcmpeqw)
TEST_INSN( &AllMask, 16,pcmpgtb)
TEST_INSN( &AllMask, 16,pcmpgtd)
TEST_INSN( &AllMask, 16,pcmpgtw)
//TEST_INSN( &AllMask, 16,pextrw)
//TEST_INSN( &AllMask, 16,pinsrw)
TEST_INSN( &AllMask, 16,pmaxsw)
TEST_INSN( &AllMask, 16,pmaxub)
TEST_INSN( &AllMask, 16,pminsw)
TEST_INSN( &AllMask, 16,pminub)
//TEST_INSN( &AllMask, 0,pmovmskb)
TEST_INSN( &AllMask, 16,pmulhuw)
TEST_INSN( &AllMask, 16,pmulhw)
TEST_INSN( &AllMask, 16,pmullw)
TEST_INSN( &AllMask, 16,pmuludq)
TEST_INSN( &AllMask, 16,por)
//TEST_INSN( &AllMask, 16,pshufd)
//TEST_INSN( &AllMask, 16,pshufhw)
//TEST_INSN( &AllMask, 16,pshuflw)
TEST_INSN( &AllMask, 16,pslld)
//TEST_INSN( &AllMask, 16,pslldq)
TEST_INSN( &AllMask, 16,psllq)
TEST_INSN( &AllMask, 16,psllw)
TEST_INSN( &AllMask, 16,psrad)
TEST_INSN( &AllMask, 16,psraw)
TEST_INSN( &AllMask, 16,psrld)
//TEST_INSN( &AllMask, 16,psrldq)
TEST_INSN( &AllMask, 16,psrlq)
TEST_INSN( &AllMask, 16,psrlw)
TEST_INSN( &AllMask, 16,psubb)
TEST_INSN( &AllMask, 16,psubd)
TEST_INSN( &AllMask, 16,psubq)
TEST_INSN( &AllMask, 16,psubsb)
TEST_INSN( &AllMask, 16,psubsw)
TEST_INSN( &AllMask, 16,psubusb)
TEST_INSN( &AllMask, 16,psubusw)
TEST_INSN( &AllMask, 16,psubw)
TEST_INSN( &AllMask, 16,punpckhbw)
TEST_INSN( &AllMask, 16,punpckhdq)
TEST_INSN( &AllMask, 16,punpckhqdq)
TEST_INSN( &AllMask, 16,punpckhwd)
TEST_INSN( &AllMask, 16,punpcklbw)
TEST_INSN( &AllMask, 16,punpckldq)
TEST_INSN( &AllMask, 16,punpcklqdq)
TEST_INSN( &AllMask, 16,punpcklwd)
TEST_INSN( &AllMask, 16,pxor)
//TEST_INSN( &AllMask, PD,shufpd)
TEST_INSN( &AllMask, PD,sqrtpd)
TEST_INSN( &AllMask, SD,sqrtsd)
TEST_INSN( &AllMask, PD,subpd)
TEST_INSN( &AllMask, SD,subsd)
TEST_INSN( &AllMask, SD,ucomisd)
TEST_INSN( &AllMask, PD,unpckhpd)
TEST_INSN( &AllMask, PD,unpcklpd)
TEST_INSN( &AllMask, PD,xorpd)
int main ( int argc, char** argv )
{
Int sse1 = 0, sse2 = 0;
if (argc == 2 && 0==strcmp(argv[1], "sse1")) {
sse1 = 1;
}
else
if (argc == 2 && 0==strcmp(argv[1], "sse2")) {
sse2 = 1;
}
else
if (argc == 2 && 0==strcmp(argv[1], "all")) {
sse1 = sse2 = 1;
}
else {
fprintf(stderr, "usage: sse_memory [sse1|sse2|all]\n");
return 0;
}
/* ------------------------ SSE1 ------------------------ */
if (sse1) {
do_addps();
do_addss();
do_andnps();
do_andps();
do_cmpeqps();
do_cmpeqss();
do_cmpleps();
do_cmpless();
do_cmpltps();
do_cmpltss();
do_cmpneqps();
do_cmpneqss();
do_cmpnleps();
do_cmpnless();
do_cmpnltps();
do_cmpnltss();
do_cmpordps();
do_cmpordss();
do_cmpunordps();
do_cmpunordss();
do_comiss();
//TEST_INSN( &AllMask, 0,cvtpi2ps)
//TEST_INSN( &AllMask, 0,cvtps2pi)
//TEST_INSN( &AllMask, 0,cvtsi2ss)
//TEST_INSN( &AllMask, 0,cvtss2si)
//TEST_INSN( &AllMask, 0,cvttps2pi)
//TEST_INSN( &AllMask, 0,cvttss2si)
do_divps();
do_divss();
do_maxps();
do_maxss();
do_minps();
do_minss();
do_movaps();
//TEST_INSN( &AllMask, 0,movhlps)
//TEST_INSN( &AllMask, 0,movhps)
//TEST_INSN( &AllMask, 0,movlhps)
//TEST_INSN( &AllMask, 0,movlps)
//TEST_INSN( &AllMask, 0,movmskps)
//TEST_INSN( &AllMask, 0,movntps)
//TEST_INSN( &AllMask, 0,movntq)
do_movss();
do_movups();
do_mulps();
do_mulss();
do_orps();
//TEST_INSN( &AllMask, 0,pavgb) -- dup with sse2?
//TEST_INSN( &AllMask, 0,pavgw) -- dup with sse2?
//TEST_INSN( &AllMask, 0,pextrw)
//TEST_INSN( &AllMask, 0,pinsrw)
//TEST_INSN( &AllMask, 0,pmaxsw) -- dup with sse2?
//TEST_INSN( &AllMask, 0,pmaxub) -- dup with sse2?
//TEST_INSN( &AllMask, 0,pminsw) -- dup with sse2?
//TEST_INSN( &AllMask, 0,pminub) -- dup with sse2?
//TEST_INSN( &AllMask, 0,pmovmskb)
//TEST_INSN( &AllMask, 0,pmulhuw) -- dup with sse2?
//do_psadbw(); -- XXXXXXXXXXXXXXXX sse2 (xmm variant) not implemented!
//TEST_INSN( &AllMask, 0,pshufw)
do_rcpps();
do_rcpss();
do_rsqrtps();
do_rsqrtss();
//TEST_INSN( &AllMask, PS,shufps)
do_sqrtps();
do_sqrtss();
do_subps();
do_subss();
do_ucomiss();
do_unpckhps();
do_unpcklps();
do_xorps();
}
/* ------------------------ SSE2 ------------------------ */
if (sse2) {
do_addpd();
do_addsd();
do_andnpd();
do_andpd();
do_cmpeqpd();
do_cmpeqsd();
do_cmplepd();
do_cmplesd();
do_cmpltpd();
do_cmpltsd();
do_cmpneqpd();
do_cmpneqsd();
do_cmpnlepd();
do_cmpnlesd();
do_cmpnltpd();
do_cmpnltsd();
do_cmpordpd();
do_cmpordsd();
do_cmpunordpd();
do_cmpunordsd();
do_comisd();
do_cvtdq2pd();
do_cvtdq2ps();
do_cvtpd2dq();
//TEST_INSN( &AllMask, 0,cvtpd2pi)
do_cvtpd2ps();
//TEST_INSN( &AllMask, 0,cvtpi2pd)
do_cvtps2dq();
do_cvtps2pd();
//TEST_INSN( &AllMask, 0,cvtsd2si)
do_cvtsd2ss();
//TEST_INSN( &AllMask, 0,cvtsi2sd)
do_cvtss2sd();
do_cvttpd2dq();
//TEST_INSN( &AllMask, 0,cvttpd2pi)
do_cvttps2dq();
//TEST_INSN( &AllMask, 0,cvttsd2si)
do_divpd();
do_divsd();
do_maxpd();
do_maxsd();
do_minpd();
do_minsd();
do_movapd();
//TEST_INSN( &AllMask, 8,movd)
//TEST_INSN( &AllMask, 0,movdq2q)
do_movdqa();
do_movdqu();
//TEST_INSN( &AllMask, 16,movhpd)
//TEST_INSN( &AllMask, 16,movlpd)
//TEST_INSN( &AllMask, 0,movmskpd)
//TEST_INSN( &AllMask, 0,movntdq)
//TEST_INSN( &AllMask, 0,movnti)
//TEST_INSN( &AllMask, 0,movntpd)
do_movq();
//TEST_INSN( &AllMask, 0,movq2dq)
do_movsd();
do_movupd();
do_mulpd();
do_mulsd();
do_orpd();
do_packssdw();
do_packsswb();
do_packuswb();
do_paddb();
do_paddd();
do_paddq();
do_paddsb();
do_paddsw();
do_paddusb();
do_paddusw();
do_paddw();
do_pand();
do_pandn();
do_pavgb();
do_pavgw();
do_pcmpeqb();
do_pcmpeqd();
do_pcmpeqw();
do_pcmpgtb();
do_pcmpgtd();
do_pcmpgtw();
//TEST_INSN( &AllMask, 16,pextrw)
//TEST_INSN( &AllMask, 16,pinsrw)
do_pmaxsw();
do_pmaxub();
do_pminsw();
do_pminub();
//TEST_INSN( &AllMask, 0,pmovmskb)
do_pmulhuw();
do_pmulhw();
do_pmullw();
do_pmuludq();
do_por();
//TEST_INSN( &AllMask, 16,pshufd)
//TEST_INSN( &AllMask, 16,pshufhw)
//TEST_INSN( &AllMask, 16,pshuflw)
do_pslld();
//TEST_INSN( &AllMask, 16,pslldq)
do_psllq();
do_psllw();
do_psrad();
do_psraw();
do_psrld();
//TEST_INSN( &AllMask, 16,psrldq)
do_psrlq();
do_psrlw();
do_psubb();
do_psubd();
do_psubq();
do_psubsb();
do_psubsw();
do_psubusb();
do_psubusw();
do_psubw();
do_punpckhbw();
do_punpckhdq();
do_punpckhqdq();
do_punpckhwd();
do_punpcklbw();
do_punpckldq();
do_punpcklqdq();
do_punpcklwd();
do_pxor();
//TEST_INSN( &AllMask, PD,shufpd)
do_sqrtpd();
do_sqrtsd();
do_subpd();
do_subsd();
do_ucomisd();
do_unpckhpd();
do_unpcklpd();
do_xorpd();
}
return 0;
}