1 #include "sse4_2-check.h"
2 
3 #include <nmmintrin.h>
4 #include <string.h>
5 
6 #define POLYNOMIAL 0x11EDC6F41LL
7 
8 #define MAX_BUF 16
9 
10 static void
shift_mem_by1(unsigned char * buf,int len)11 shift_mem_by1 (unsigned char* buf, int len)
12 {
13   int i;
14 
15   for (i = len - 1; i >= 0; i--)
16     {
17       buf[i] = buf[i] << 1;
18       if (i > 0 && (buf[i-1] & 0x80))
19 	buf[i] |= 1;
20    }
21 }
22 
23 static void
do_div(unsigned char * buf,unsigned char * div)24 do_div (unsigned char* buf, unsigned char* div)
25 {
26   int i;
27   for (i = 0; i < 5; i++)
28     buf[i] ^= div[i];
29 }
30 
31 static unsigned int
calc_rem(unsigned char * buf,int len)32 calc_rem (unsigned char* buf, int len)
33 {
34   union
35     {
36       unsigned long long ll;
37       unsigned char c[8];
38     } divisor;
39   union
40     {
41       unsigned int i;
42       unsigned char c[4];
43     } ret;
44   unsigned char *div_buf;
45   unsigned char divident[MAX_BUF];
46   int disp = len / 8;
47   int i;
48 
49   divisor.ll = POLYNOMIAL << 7LL;
50 
51   memcpy (divident, buf, disp);
52 
53   div_buf = divident + disp - 5;
54 
55   for (i = 0; i < len - 32; i++)
56     {
57       if ((div_buf[4] & 0x80))
58 	do_div (div_buf, divisor.c);
59       shift_mem_by1 (divident, disp);
60    }
61 
62   memcpy (ret.c, div_buf + 1, sizeof (ret));
63   return ret.i;
64 }
65 
66 static void
reverse_bits(unsigned char * src,int len)67 reverse_bits (unsigned char *src, int len)
68 {
69   unsigned char buf[MAX_BUF];
70   unsigned char *tmp = buf + len - 1;
71   unsigned char ch;
72   int i, j;
73 
74   for (i = 0; i < len; i++)
75     {
76       ch = 0;
77       for (j = 0; j < 8; j++)
78 	if ((src[i] & (1 << j)))
79 	  ch |= 1 << (7 - j);
80       *tmp-- = ch;
81     }
82 
83   for (i = 0; i < len; i++)
84     src[i] = buf[i];
85 }
86 
87 static void
shift_mem(unsigned char * src,unsigned char * dst,int len,int shft)88 shift_mem ( unsigned char *src, unsigned char *dst, int len, int shft)
89 {
90   int disp = shft / 8;
91   int i;
92 
93   memset (dst, 0, len + disp);
94   for (i = 0; i < len; i++)
95     dst[i + disp] = src[i];
96 }
97 
98 static void
xor_mem(unsigned char * src,unsigned char * dst,int len)99 xor_mem (unsigned char *src, unsigned char *dst, int len)
100 {
101   int disp = len / 8;
102   int i;
103 
104   for (i = 0; i < disp; i++)
105     dst[i] ^= src[i];
106 }
107 
108 static DST_T
compute_crc32(DST_T crc,SRC_T inp)109 compute_crc32 (DST_T crc, SRC_T inp)
110 {
111   unsigned char crcbuf[sizeof (DST_T)];
112   unsigned char inbuf[sizeof (SRC_T)];
113   unsigned char tmp1[MAX_BUF], tmp2[MAX_BUF];
114   int crc_sh, xor_sz;
115   union
116     {
117       unsigned int i;
118       unsigned char c[4];
119     } ret;
120 
121   crc_sh = sizeof (SRC_T) * 8;
122   xor_sz = 32 + crc_sh;
123   memcpy (crcbuf, &crc, sizeof (DST_T));
124   memcpy (inbuf, &inp, sizeof (SRC_T));
125 
126   reverse_bits (crcbuf, 4);
127   reverse_bits (inbuf, sizeof (SRC_T));
128 
129   shift_mem (inbuf, tmp1, sizeof (SRC_T), 32);
130   shift_mem (crcbuf, tmp2, 4, crc_sh);
131 
132   xor_mem (tmp1, tmp2, xor_sz);
133 
134   ret.i = calc_rem (tmp2, xor_sz);
135 
136   reverse_bits (ret.c, 4);
137 
138   return (DST_T)ret.i;
139 }
140 
141 #define NUM 1024
142 
143 static void
sse4_2_test(void)144 sse4_2_test (void)
145 {
146   DST_T dst[NUM];
147   SRC_T src[NUM];
148   int i;
149 
150  for (i = 0; i < NUM; i++)
151    {
152      dst[i] = rand ();
153      if (sizeof (DST_T) > 4)
154        dst[i] |= (DST_T)rand () << (DST_T)(sizeof (DST_T) * 4);
155      src[i] = rand ();
156      if (sizeof (SRC_T) > 4)
157        src[i] |= (SRC_T)rand () << (SRC_T)(sizeof (DST_T) * 4);
158    }
159 
160   for (i = 0; i < NUM; i++)
161     if (CRC32 (dst[i], src[i]) != compute_crc32 (dst[i], src[i]))
162       abort ();
163 }
164