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
10static void
11shift_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
23static void
24do_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
31static unsigned int
32calc_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
66static void
67reverse_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
87static void
88shift_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
98static void
99xor_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
108static DST_T
109compute_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
143static void
144sse4_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