4 #define CFLAG 0x00000001
5 #define ZFLAG 0x00000002
6 #define SFLAG 0x00000004
7 #define OFLAG 0x00000008
8 #define AFLAG 0x00000010
9 #define PFLAG 0x00000020
11 #define PCMPSTR_EQ(X, Y, RES) \
13 int __size = (sizeof (*X) ^ 3) * 8; \
15 for (__i = 0; __i < __size; __i++) \
16 for (__j = 0; __j < __size; __j++) \
17 RES[__j][__i] = (X[__i] == Y[__j]); \
20 #define PCMPSTR_RNG(X, Y, RES) \
22 int __size = (sizeof (*X) ^ 3) * 8; \
24 for (__j = 0; __j < __size; __j++) \
25 for (__i = 0; __i < __size - 1; __i += 2) \
27 RES[__j][__i] = (Y[__j] >= X[__i]); \
28 RES[__j][__i+1] = (Y[__j] <= X[__i + 1]); \
33 override_invalid (unsigned char res[16][16], int la, int lb,
34 const int mode, int dim)
38 for (j = 0; j < dim; j++)
39 for (i = 0; i < dim; i++)
40 if (i < la && j >= lb)
43 switch ((mode & 0x0C))
45 case _SIDD_CMP_EQUAL_ANY:
46 case _SIDD_CMP_RANGES:
49 case _SIDD_CMP_EQUAL_EACH:
50 res[j][i] = (j >= lb) ? 1: 0;
52 case _SIDD_CMP_EQUAL_ORDERED:
59 calc_matrix (__m128i a, int la, __m128i b, int lb, const int mode,
60 unsigned char res[16][16])
77 if ((mode & 0x0C) == _SIDD_CMP_RANGES)
79 PCMPSTR_RNG (d.uc, s.uc, res);
83 PCMPSTR_EQ (d.uc, s.uc, res);
87 if ((mode & 0x0C) == _SIDD_CMP_RANGES)
89 PCMPSTR_RNG (d.us, s.us, res);
93 PCMPSTR_EQ (d.us, s.us, res);
97 if ((mode & 0x0C) == _SIDD_CMP_RANGES)
99 PCMPSTR_RNG (d.sc, s.sc, res);
103 PCMPSTR_EQ (d.sc, s.sc, res);
106 case _SIDD_SWORD_OPS:
107 if ((mode & 0x0C) == _SIDD_CMP_RANGES)
109 PCMPSTR_RNG (d.ss, s.ss, res);
113 PCMPSTR_EQ (d.ss, s.ss, res);
118 override_invalid (res, la, lb, mode, (mode & 1) == 0 ? 16 : 8);
122 calc_res (__m128i a, int la, __m128i b, int lb, const int mode)
124 unsigned char mtx[16][16];
125 int i, j, k, dim, res = 0;
127 memset (mtx, 0, sizeof (mtx));
129 dim = (mode & 1) == 0 ? 16 : 8;
143 calc_matrix (a, la, b, lb, mode, mtx);
145 switch ((mode & 0x0C))
147 case _SIDD_CMP_EQUAL_ANY:
148 for (i = 0; i < dim; i++)
149 for (j = 0; j < dim; j++)
154 case _SIDD_CMP_RANGES:
155 for (i = 0; i < dim; i += 2)
156 for(j = 0; j < dim; j++)
157 if (mtx[j][i] && mtx[j][i+1])
161 case _SIDD_CMP_EQUAL_EACH:
162 for(i = 0; i < dim; i++)
167 case _SIDD_CMP_EQUAL_ORDERED:
168 for(i = 0; i < dim; i++)
170 unsigned char val = 1;
172 for (j = 0, k = i; j < dim - i && k < dim; j++, k++)
183 switch ((mode & 0x30))
185 case _SIDD_POSITIVE_POLARITY:
186 case _SIDD_MASKED_POSITIVE_POLARITY:
189 case _SIDD_NEGATIVE_POLARITY:
193 case _SIDD_MASKED_NEGATIVE_POLARITY:
194 for (i = 0; i < lb; i++)
202 return res & ((dim == 8) ? 0xFF : 0xFFFF);
206 cmp_flags (__m128i a, int la, __m128i b, int lb,
207 int mode, int res2, int is_implicit)
211 int is_bytes_mode = (mode & 1) == 0;
215 unsigned char uc[16];
216 unsigned short us[8];
222 /* CF: reset if (RES2 == 0), set otherwise. */
228 /* ZF: set if any byte/word of src xmm operand is null, reset
230 SF: set if any byte/word of dst xmm operand is null, reset
235 for (i = 0; i < 16; i++)
245 for (i = 0; i < 8; i++)
256 /* ZF: set if abs value of EDX/RDX < 16 (8), reset otherwise.
257 SF: set if abs value of EAX/RAX < 16 (8), reset otherwise. */
258 int max_ind = is_bytes_mode ? 16 : 8;
271 /* OF: equal to RES2[0]. */
281 cmp_indexed (__m128i a, int la, __m128i b, int lb,
282 const int mode, int *res2)
285 int dim = (mode & 1) == 0 ? 16 : 8;
288 r2 = calc_res (a, la, b, lb, mode);
293 for (i = dim - 1; i >= 0; i--)
302 for (i = 0; i < dim; i++)
315 cmp_masked (__m128i a, int la, __m128i b, int lb,
316 const int mode, int *res2)
325 int dim = (mode & 1) == 0 ? 16 : 8;
333 r2.i = calc_res (a, la, b, lb, mode);
335 memset (&ret, 0, sizeof (ret));
339 for (i = 0; i < dim; i++)
341 ret.s [i] = (r2.i & (1 << i)) ? -1 : 0;
343 ret.c [i] = (r2.i & (1 << i)) ? -1 : 0;
359 calc_str_len (__m128i a, const int mode)
368 int dim = (mode & 1) == 0 ? 16 : 8;
374 for (i = 0; i < dim; i++)
380 for (i = 0; i < dim; i++)
389 cmp_ei (__m128i *a, int la, __m128i *b, int lb,
390 const int mode, int *flags)
393 int index = cmp_indexed (*a, la, *b, lb, mode, &res2);
396 *flags = cmp_flags (*a, la, *b, lb, mode, res2, 0);
402 cmp_ii (__m128i *a, __m128i *b, const int mode, int *flags)
408 la = calc_str_len (*a, mode);
409 lb = calc_str_len (*b, mode);
411 index = cmp_indexed (*a, la, *b, lb, mode, &res2);
414 *flags = cmp_flags (*a, la, *b, lb, mode, res2, 1);
419 static inline __m128i
420 cmp_em (__m128i *a, int la, __m128i *b, int lb,
421 const int mode, int *flags )
424 __m128i mask = cmp_masked (*a, la, *b, lb, mode, &res2);
427 *flags = cmp_flags (*a, la, *b, lb, mode, res2, 0);
432 static inline __m128i
433 cmp_im (__m128i *a, __m128i *b, const int mode, int *flags)
439 la = calc_str_len (*a, mode);
440 lb = calc_str_len (*b, mode);
442 mask = cmp_masked (*a, la, *b, lb, mode, &res2);
444 *flags = cmp_flags (*a, la, *b, lb, mode, res2, 1);