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);