root / tests / test-i386.c @ 1a9353d2
History | View | Annotate | Download (18.2 kB)
1 |
#include <stdlib.h> |
---|---|
2 |
#include <stdio.h> |
3 |
#include <inttypes.h> |
4 |
#include <math.h> |
5 |
|
6 |
#define xglue(x, y) x ## y |
7 |
#define glue(x, y) xglue(x, y)
|
8 |
#define stringify(s) tostring(s)
|
9 |
#define tostring(s) #s |
10 |
|
11 |
#define CC_C 0x0001 |
12 |
#define CC_P 0x0004 |
13 |
#define CC_A 0x0010 |
14 |
#define CC_Z 0x0040 |
15 |
#define CC_S 0x0080 |
16 |
#define CC_O 0x0800 |
17 |
|
18 |
#define __init_call __attribute__ ((unused,__section__ (".initcall.init"))) |
19 |
|
20 |
static void *call_start __init_call = NULL; |
21 |
|
22 |
#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
|
23 |
|
24 |
#define OP add
|
25 |
#include "test-i386.h" |
26 |
|
27 |
#define OP sub
|
28 |
#include "test-i386.h" |
29 |
|
30 |
#define OP xor
|
31 |
#include "test-i386.h" |
32 |
|
33 |
#define OP and
|
34 |
#include "test-i386.h" |
35 |
|
36 |
#define OP or
|
37 |
#include "test-i386.h" |
38 |
|
39 |
#define OP cmp
|
40 |
#include "test-i386.h" |
41 |
|
42 |
#define OP adc
|
43 |
#define OP_CC
|
44 |
#include "test-i386.h" |
45 |
|
46 |
#define OP sbb
|
47 |
#define OP_CC
|
48 |
#include "test-i386.h" |
49 |
|
50 |
#define OP inc
|
51 |
#define OP_CC
|
52 |
#define OP1
|
53 |
#include "test-i386.h" |
54 |
|
55 |
#define OP dec
|
56 |
#define OP_CC
|
57 |
#define OP1
|
58 |
#include "test-i386.h" |
59 |
|
60 |
#define OP neg
|
61 |
#define OP_CC
|
62 |
#define OP1
|
63 |
#include "test-i386.h" |
64 |
|
65 |
#define OP not
|
66 |
#define OP_CC
|
67 |
#define OP1
|
68 |
#include "test-i386.h" |
69 |
|
70 |
#undef CC_MASK
|
71 |
#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)
|
72 |
|
73 |
#define OP shl
|
74 |
#include "test-i386-shift.h" |
75 |
|
76 |
#define OP shr
|
77 |
#include "test-i386-shift.h" |
78 |
|
79 |
#define OP sar
|
80 |
#include "test-i386-shift.h" |
81 |
|
82 |
#define OP rol
|
83 |
#include "test-i386-shift.h" |
84 |
|
85 |
#define OP ror
|
86 |
#include "test-i386-shift.h" |
87 |
|
88 |
#define OP rcr
|
89 |
#define OP_CC
|
90 |
#include "test-i386-shift.h" |
91 |
|
92 |
#define OP rcl
|
93 |
#define OP_CC
|
94 |
#include "test-i386-shift.h" |
95 |
|
96 |
#define OP shld
|
97 |
#define OP_SHIFTD
|
98 |
#define OP_NOBYTE
|
99 |
#include "test-i386-shift.h" |
100 |
|
101 |
#define OP shrd
|
102 |
#define OP_SHIFTD
|
103 |
#define OP_NOBYTE
|
104 |
#include "test-i386-shift.h" |
105 |
|
106 |
/* XXX: should be more precise ? */
|
107 |
#undef CC_MASK
|
108 |
#define CC_MASK (CC_C)
|
109 |
|
110 |
#define OP bt
|
111 |
#define OP_NOBYTE
|
112 |
#include "test-i386-shift.h" |
113 |
|
114 |
#define OP bts
|
115 |
#define OP_NOBYTE
|
116 |
#include "test-i386-shift.h" |
117 |
|
118 |
#define OP btr
|
119 |
#define OP_NOBYTE
|
120 |
#include "test-i386-shift.h" |
121 |
|
122 |
#define OP btc
|
123 |
#define OP_NOBYTE
|
124 |
#include "test-i386-shift.h" |
125 |
|
126 |
/* lea test (modrm support) */
|
127 |
#define TEST_LEA(STR)\
|
128 |
{\ |
129 |
asm("leal " STR ", %0"\ |
130 |
: "=r" (res)\
|
131 |
: "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\ |
132 |
printf("lea %s = %08x\n", STR, res);\
|
133 |
} |
134 |
|
135 |
#define TEST_LEA16(STR)\
|
136 |
{\ |
137 |
asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\ |
138 |
: "=wq" (res)\
|
139 |
: "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\ |
140 |
printf("lea %s = %08x\n", STR, res);\
|
141 |
} |
142 |
|
143 |
|
144 |
void test_lea(void) |
145 |
{ |
146 |
int eax, ebx, ecx, edx, esi, edi, res;
|
147 |
eax = 0x0001;
|
148 |
ebx = 0x0002;
|
149 |
ecx = 0x0004;
|
150 |
edx = 0x0008;
|
151 |
esi = 0x0010;
|
152 |
edi = 0x0020;
|
153 |
|
154 |
TEST_LEA("0x4000");
|
155 |
|
156 |
TEST_LEA("(%%eax)");
|
157 |
TEST_LEA("(%%ebx)");
|
158 |
TEST_LEA("(%%ecx)");
|
159 |
TEST_LEA("(%%edx)");
|
160 |
TEST_LEA("(%%esi)");
|
161 |
TEST_LEA("(%%edi)");
|
162 |
|
163 |
TEST_LEA("0x40(%%eax)");
|
164 |
TEST_LEA("0x40(%%ebx)");
|
165 |
TEST_LEA("0x40(%%ecx)");
|
166 |
TEST_LEA("0x40(%%edx)");
|
167 |
TEST_LEA("0x40(%%esi)");
|
168 |
TEST_LEA("0x40(%%edi)");
|
169 |
|
170 |
TEST_LEA("0x4000(%%eax)");
|
171 |
TEST_LEA("0x4000(%%ebx)");
|
172 |
TEST_LEA("0x4000(%%ecx)");
|
173 |
TEST_LEA("0x4000(%%edx)");
|
174 |
TEST_LEA("0x4000(%%esi)");
|
175 |
TEST_LEA("0x4000(%%edi)");
|
176 |
|
177 |
TEST_LEA("(%%eax, %%ecx)");
|
178 |
TEST_LEA("(%%ebx, %%edx)");
|
179 |
TEST_LEA("(%%ecx, %%ecx)");
|
180 |
TEST_LEA("(%%edx, %%ecx)");
|
181 |
TEST_LEA("(%%esi, %%ecx)");
|
182 |
TEST_LEA("(%%edi, %%ecx)");
|
183 |
|
184 |
TEST_LEA("0x40(%%eax, %%ecx)");
|
185 |
TEST_LEA("0x4000(%%ebx, %%edx)");
|
186 |
|
187 |
TEST_LEA("(%%ecx, %%ecx, 2)");
|
188 |
TEST_LEA("(%%edx, %%ecx, 4)");
|
189 |
TEST_LEA("(%%esi, %%ecx, 8)");
|
190 |
|
191 |
TEST_LEA("(,%%eax, 2)");
|
192 |
TEST_LEA("(,%%ebx, 4)");
|
193 |
TEST_LEA("(,%%ecx, 8)");
|
194 |
|
195 |
TEST_LEA("0x40(,%%eax, 2)");
|
196 |
TEST_LEA("0x40(,%%ebx, 4)");
|
197 |
TEST_LEA("0x40(,%%ecx, 8)");
|
198 |
|
199 |
|
200 |
TEST_LEA("-10(%%ecx, %%ecx, 2)");
|
201 |
TEST_LEA("-10(%%edx, %%ecx, 4)");
|
202 |
TEST_LEA("-10(%%esi, %%ecx, 8)");
|
203 |
|
204 |
TEST_LEA("0x4000(%%ecx, %%ecx, 2)");
|
205 |
TEST_LEA("0x4000(%%edx, %%ecx, 4)");
|
206 |
TEST_LEA("0x4000(%%esi, %%ecx, 8)");
|
207 |
|
208 |
/* limited 16 bit addressing test */
|
209 |
TEST_LEA16("0x4000");
|
210 |
TEST_LEA16("(%%bx)");
|
211 |
TEST_LEA16("(%%si)");
|
212 |
TEST_LEA16("(%%di)");
|
213 |
TEST_LEA16("0x40(%%bx)");
|
214 |
TEST_LEA16("0x40(%%si)");
|
215 |
TEST_LEA16("0x40(%%di)");
|
216 |
TEST_LEA16("0x4000(%%bx)");
|
217 |
TEST_LEA16("0x4000(%%si)");
|
218 |
TEST_LEA16("(%%bx,%%si)");
|
219 |
TEST_LEA16("(%%bx,%%di)");
|
220 |
TEST_LEA16("0x40(%%bx,%%si)");
|
221 |
TEST_LEA16("0x40(%%bx,%%di)");
|
222 |
TEST_LEA16("0x4000(%%bx,%%si)");
|
223 |
TEST_LEA16("0x4000(%%bx,%%di)");
|
224 |
} |
225 |
|
226 |
#define TEST_JCC(JCC, v1, v2)\
|
227 |
{\ |
228 |
asm("movl $1, %0\n\t"\ |
229 |
"cmpl %2, %1\n\t"\
|
230 |
JCC " 1f\n\t"\
|
231 |
"movl $0, %0\n\t"\
|
232 |
"1:\n\t"\
|
233 |
: "=r" (res)\
|
234 |
: "r" (v1), "r" (v2));\ |
235 |
printf("%-10s %d\n", JCC, res);\
|
236 |
} |
237 |
|
238 |
/* various jump tests */
|
239 |
void test_jcc(void) |
240 |
{ |
241 |
int res;
|
242 |
|
243 |
TEST_JCC("jne", 1, 1); |
244 |
TEST_JCC("jne", 1, 0); |
245 |
|
246 |
TEST_JCC("je", 1, 1); |
247 |
TEST_JCC("je", 1, 0); |
248 |
|
249 |
TEST_JCC("jl", 1, 1); |
250 |
TEST_JCC("jl", 1, 0); |
251 |
TEST_JCC("jl", 1, -1); |
252 |
|
253 |
TEST_JCC("jle", 1, 1); |
254 |
TEST_JCC("jle", 1, 0); |
255 |
TEST_JCC("jle", 1, -1); |
256 |
|
257 |
TEST_JCC("jge", 1, 1); |
258 |
TEST_JCC("jge", 1, 0); |
259 |
TEST_JCC("jge", -1, 1); |
260 |
|
261 |
TEST_JCC("jg", 1, 1); |
262 |
TEST_JCC("jg", 1, 0); |
263 |
TEST_JCC("jg", 1, -1); |
264 |
|
265 |
TEST_JCC("jb", 1, 1); |
266 |
TEST_JCC("jb", 1, 0); |
267 |
TEST_JCC("jb", 1, -1); |
268 |
|
269 |
TEST_JCC("jbe", 1, 1); |
270 |
TEST_JCC("jbe", 1, 0); |
271 |
TEST_JCC("jbe", 1, -1); |
272 |
|
273 |
TEST_JCC("jae", 1, 1); |
274 |
TEST_JCC("jae", 1, 0); |
275 |
TEST_JCC("jae", 1, -1); |
276 |
|
277 |
TEST_JCC("ja", 1, 1); |
278 |
TEST_JCC("ja", 1, 0); |
279 |
TEST_JCC("ja", 1, -1); |
280 |
|
281 |
|
282 |
TEST_JCC("jp", 1, 1); |
283 |
TEST_JCC("jp", 1, 0); |
284 |
|
285 |
TEST_JCC("jnp", 1, 1); |
286 |
TEST_JCC("jnp", 1, 0); |
287 |
|
288 |
TEST_JCC("jo", 0x7fffffff, 0); |
289 |
TEST_JCC("jo", 0x7fffffff, -1); |
290 |
|
291 |
TEST_JCC("jno", 0x7fffffff, 0); |
292 |
TEST_JCC("jno", 0x7fffffff, -1); |
293 |
|
294 |
TEST_JCC("js", 0, 1); |
295 |
TEST_JCC("js", 0, -1); |
296 |
TEST_JCC("js", 0, 0); |
297 |
|
298 |
TEST_JCC("jns", 0, 1); |
299 |
TEST_JCC("jns", 0, -1); |
300 |
TEST_JCC("jns", 0, 0); |
301 |
} |
302 |
|
303 |
#undef CC_MASK
|
304 |
#define CC_MASK (CC_O | CC_C)
|
305 |
|
306 |
#define OP mul
|
307 |
#include "test-i386-muldiv.h" |
308 |
|
309 |
#define OP imul
|
310 |
#include "test-i386-muldiv.h" |
311 |
|
312 |
#undef CC_MASK
|
313 |
#define CC_MASK (0) |
314 |
|
315 |
#define OP div
|
316 |
#include "test-i386-muldiv.h" |
317 |
|
318 |
#define OP idiv
|
319 |
#include "test-i386-muldiv.h" |
320 |
|
321 |
void test_imulw2(int op0, int op1) |
322 |
{ |
323 |
int res, s1, s0, flags;
|
324 |
s0 = op0; |
325 |
s1 = op1; |
326 |
res = s0; |
327 |
flags = 0;
|
328 |
asm ("push %4\n\t" |
329 |
"popf\n\t"
|
330 |
"imulw %w2, %w0\n\t"
|
331 |
"pushf\n\t"
|
332 |
"popl %1\n\t"
|
333 |
: "=q" (res), "=g" (flags) |
334 |
: "q" (s1), "0" (res), "1" (flags)); |
335 |
printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
|
336 |
"imulw", s0, s1, res, flags & CC_MASK);
|
337 |
} |
338 |
|
339 |
void test_imull2(int op0, int op1) |
340 |
{ |
341 |
int res, s1, s0, flags;
|
342 |
s0 = op0; |
343 |
s1 = op1; |
344 |
res = s0; |
345 |
flags = 0;
|
346 |
asm ("push %4\n\t" |
347 |
"popf\n\t"
|
348 |
"imull %2, %0\n\t"
|
349 |
"pushf\n\t"
|
350 |
"popl %1\n\t"
|
351 |
: "=q" (res), "=g" (flags) |
352 |
: "q" (s1), "0" (res), "1" (flags)); |
353 |
printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
|
354 |
"imull", s0, s1, res, flags & CC_MASK);
|
355 |
} |
356 |
|
357 |
void test_mul(void) |
358 |
{ |
359 |
test_imulb(0x1234561d, 4); |
360 |
test_imulb(3, -4); |
361 |
test_imulb(0x80, 0x80); |
362 |
test_imulb(0x10, 0x10); |
363 |
|
364 |
test_imulw(0, 0x1234001d, 45); |
365 |
test_imulw(0, 23, -45); |
366 |
test_imulw(0, 0x8000, 0x8000); |
367 |
test_imulw(0, 0x100, 0x100); |
368 |
|
369 |
test_imull(0, 0x1234001d, 45); |
370 |
test_imull(0, 23, -45); |
371 |
test_imull(0, 0x80000000, 0x80000000); |
372 |
test_imull(0, 0x10000, 0x10000); |
373 |
|
374 |
test_mulb(0x1234561d, 4); |
375 |
test_mulb(3, -4); |
376 |
test_mulb(0x80, 0x80); |
377 |
test_mulb(0x10, 0x10); |
378 |
|
379 |
test_mulw(0, 0x1234001d, 45); |
380 |
test_mulw(0, 23, -45); |
381 |
test_mulw(0, 0x8000, 0x8000); |
382 |
test_mulw(0, 0x100, 0x100); |
383 |
|
384 |
test_mull(0, 0x1234001d, 45); |
385 |
test_mull(0, 23, -45); |
386 |
test_mull(0, 0x80000000, 0x80000000); |
387 |
test_mull(0, 0x10000, 0x10000); |
388 |
|
389 |
test_imulw2(0x1234001d, 45); |
390 |
test_imulw2(23, -45); |
391 |
test_imulw2(0x8000, 0x8000); |
392 |
test_imulw2(0x100, 0x100); |
393 |
|
394 |
test_imull2(0x1234001d, 45); |
395 |
test_imull2(23, -45); |
396 |
test_imull2(0x80000000, 0x80000000); |
397 |
test_imull2(0x10000, 0x10000); |
398 |
|
399 |
test_idivb(0x12341678, 0x127e); |
400 |
test_idivb(0x43210123, -5); |
401 |
test_idivb(0x12340004, -1); |
402 |
|
403 |
test_idivw(0, 0x12345678, 12347); |
404 |
test_idivw(0, -23223, -45); |
405 |
test_idivw(0, 0x12348000, -1); |
406 |
test_idivw(0x12343, 0x12345678, 0x81238567); |
407 |
|
408 |
test_idivl(0, 0x12345678, 12347); |
409 |
test_idivl(0, -233223, -45); |
410 |
test_idivl(0, 0x80000000, -1); |
411 |
test_idivl(0x12343, 0x12345678, 0x81234567); |
412 |
|
413 |
test_divb(0x12341678, 0x127e); |
414 |
test_divb(0x43210123, -5); |
415 |
test_divb(0x12340004, -1); |
416 |
|
417 |
test_divw(0, 0x12345678, 12347); |
418 |
test_divw(0, -23223, -45); |
419 |
test_divw(0, 0x12348000, -1); |
420 |
test_divw(0x12343, 0x12345678, 0x81238567); |
421 |
|
422 |
test_divl(0, 0x12345678, 12347); |
423 |
test_divl(0, -233223, -45); |
424 |
test_divl(0, 0x80000000, -1); |
425 |
test_divl(0x12343, 0x12345678, 0x81234567); |
426 |
} |
427 |
|
428 |
#define TEST_BSX(op, size, op0)\
|
429 |
{\ |
430 |
int res, val, resz;\
|
431 |
val = op0;\ |
432 |
asm("xorl %1, %1 ; " #op " %" size "2, %" size "0 ; setz %b1" \ |
433 |
: "=r" (res), "=q" (resz)\ |
434 |
: "g" (val));\
|
435 |
printf("%-10s A=%08x R=%08x %d\n", #op, val, resz ? 0 : res, resz);\ |
436 |
} |
437 |
|
438 |
void test_bsx(void) |
439 |
{ |
440 |
TEST_BSX(bsrw, "w", 0); |
441 |
TEST_BSX(bsrw, "w", 0x12340128); |
442 |
TEST_BSX(bsrl, "", 0); |
443 |
TEST_BSX(bsrl, "", 0x00340128); |
444 |
TEST_BSX(bsfw, "w", 0); |
445 |
TEST_BSX(bsfw, "w", 0x12340128); |
446 |
TEST_BSX(bsfl, "", 0); |
447 |
TEST_BSX(bsfl, "", 0x00340128); |
448 |
} |
449 |
|
450 |
/**********************************************/
|
451 |
|
452 |
void test_fops(double a, double b) |
453 |
{ |
454 |
printf("a=%f b=%f a+b=%f\n", a, b, a + b);
|
455 |
printf("a=%f b=%f a-b=%f\n", a, b, a - b);
|
456 |
printf("a=%f b=%f a*b=%f\n", a, b, a * b);
|
457 |
printf("a=%f b=%f a/b=%f\n", a, b, a / b);
|
458 |
printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b));
|
459 |
printf("a=%f sqrt(a)=%f\n", a, sqrt(a));
|
460 |
printf("a=%f sin(a)=%f\n", a, sin(a));
|
461 |
printf("a=%f cos(a)=%f\n", a, cos(a));
|
462 |
printf("a=%f tan(a)=%f\n", a, tan(a));
|
463 |
printf("a=%f log(a)=%f\n", a, log(a));
|
464 |
printf("a=%f exp(a)=%f\n", a, exp(a));
|
465 |
printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
|
466 |
/* just to test some op combining */
|
467 |
printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a)));
|
468 |
printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a)));
|
469 |
printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));
|
470 |
|
471 |
} |
472 |
|
473 |
void test_fcmp(double a, double b) |
474 |
{ |
475 |
printf("(%f<%f)=%d\n",
|
476 |
a, b, a < b); |
477 |
printf("(%f<=%f)=%d\n",
|
478 |
a, b, a <= b); |
479 |
printf("(%f==%f)=%d\n",
|
480 |
a, b, a == b); |
481 |
printf("(%f>%f)=%d\n",
|
482 |
a, b, a > b); |
483 |
printf("(%f<=%f)=%d\n",
|
484 |
a, b, a >= b); |
485 |
} |
486 |
|
487 |
void test_fcvt(double a) |
488 |
{ |
489 |
float fa;
|
490 |
long double la; |
491 |
|
492 |
fa = a; |
493 |
la = a; |
494 |
printf("(float)%f = %f\n", a, fa);
|
495 |
printf("(long double)%f = %Lf\n", a, la);
|
496 |
printf("a=%016Lx\n", *(long long *)&a); |
497 |
printf("la=%016Lx %04x\n", *(long long *)&la, |
498 |
*(unsigned short *)((char *)(&la) + 8)); |
499 |
printf("a=%f floor(a)=%f\n", a, floor(a));
|
500 |
printf("a=%f ceil(a)=%f\n", a, ceil(a));
|
501 |
printf("a=%f rint(a)=%f\n", a, rint(a));
|
502 |
} |
503 |
|
504 |
#define TEST(N) \
|
505 |
asm("fld" #N : "=t" (a)); \ |
506 |
printf("fld" #N "= %f\n", a); |
507 |
|
508 |
void test_fconst(void) |
509 |
{ |
510 |
double a;
|
511 |
TEST(1);
|
512 |
TEST(l2t); |
513 |
TEST(l2e); |
514 |
TEST(pi); |
515 |
TEST(lg2); |
516 |
TEST(ln2); |
517 |
TEST(z); |
518 |
} |
519 |
|
520 |
void test_fbcd(double a) |
521 |
{ |
522 |
unsigned short bcd[5]; |
523 |
double b;
|
524 |
|
525 |
asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st"); |
526 |
asm("fbld %1" : "=t" (b) : "m" (bcd[0])); |
527 |
printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n",
|
528 |
a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b); |
529 |
} |
530 |
|
531 |
void test_floats(void) |
532 |
{ |
533 |
test_fops(2, 3); |
534 |
test_fops(1.4, -5); |
535 |
test_fcmp(2, -1); |
536 |
test_fcmp(2, 2); |
537 |
test_fcmp(2, 3); |
538 |
test_fcvt(1.0/7.0); |
539 |
test_fcvt(-1.0/9.0); |
540 |
test_fcvt(1e30);
|
541 |
test_fconst(); |
542 |
test_fbcd(1234567890123456);
|
543 |
test_fbcd(-123451234567890);
|
544 |
} |
545 |
|
546 |
/**********************************************/
|
547 |
|
548 |
#define TEST_BCD(op, op0, cc_in, cc_mask)\
|
549 |
{\ |
550 |
int res, flags;\
|
551 |
res = op0;\ |
552 |
flags = cc_in;\ |
553 |
asm ("push %3\n\t"\ |
554 |
"popf\n\t"\
|
555 |
#op "\n\t"\ |
556 |
"pushf\n\t"\
|
557 |
"popl %1\n\t"\
|
558 |
: "=a" (res), "=g" (flags)\ |
559 |
: "0" (res), "1" (flags));\ |
560 |
printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\
|
561 |
#op, op0, res, cc_in, flags & cc_mask);\
|
562 |
} |
563 |
|
564 |
void test_bcd(void) |
565 |
{ |
566 |
TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
567 |
TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
568 |
TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
569 |
TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
570 |
TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
571 |
TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
572 |
TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
573 |
TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); |
574 |
TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); |
575 |
TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
576 |
TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
577 |
TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
578 |
TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
579 |
|
580 |
TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
581 |
TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
582 |
TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
583 |
TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
584 |
TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
585 |
TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
586 |
TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
587 |
TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); |
588 |
TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); |
589 |
TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
590 |
TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
591 |
TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
592 |
TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
|
593 |
|
594 |
TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A));
|
595 |
TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A));
|
596 |
TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A));
|
597 |
TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A));
|
598 |
TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A)); |
599 |
TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A)); |
600 |
TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A)); |
601 |
TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A)); |
602 |
|
603 |
TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A));
|
604 |
TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A));
|
605 |
TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A));
|
606 |
TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A));
|
607 |
TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A)); |
608 |
TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A)); |
609 |
TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A)); |
610 |
TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A)); |
611 |
|
612 |
TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
|
613 |
TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
|
614 |
} |
615 |
|
616 |
/**********************************************/
|
617 |
/* segmentation tests */
|
618 |
|
619 |
#include <asm/ldt.h> |
620 |
#include <linux/unistd.h> |
621 |
|
622 |
_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount) |
623 |
|
624 |
uint8_t seg_data1[4096];
|
625 |
uint8_t seg_data2[4096];
|
626 |
|
627 |
#define MK_SEL(n) (((n) << 3) | 4) |
628 |
|
629 |
/* NOTE: we use Linux modify_ldt syscall */
|
630 |
void test_segs(void) |
631 |
{ |
632 |
struct modify_ldt_ldt_s ldt;
|
633 |
long long ldt_table[3]; |
634 |
int i, res, res2;
|
635 |
char tmp;
|
636 |
|
637 |
ldt.entry_number = 1;
|
638 |
ldt.base_addr = (unsigned long)&seg_data1; |
639 |
ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12; |
640 |
ldt.seg_32bit = 1;
|
641 |
ldt.contents = MODIFY_LDT_CONTENTS_DATA; |
642 |
ldt.read_exec_only = 0;
|
643 |
ldt.limit_in_pages = 1;
|
644 |
ldt.seg_not_present = 0;
|
645 |
ldt.useable = 1;
|
646 |
modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ |
647 |
|
648 |
ldt.entry_number = 2;
|
649 |
ldt.base_addr = (unsigned long)&seg_data2; |
650 |
ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12; |
651 |
ldt.seg_32bit = 1;
|
652 |
ldt.contents = MODIFY_LDT_CONTENTS_DATA; |
653 |
ldt.read_exec_only = 0;
|
654 |
ldt.limit_in_pages = 1;
|
655 |
ldt.seg_not_present = 0;
|
656 |
ldt.useable = 1;
|
657 |
modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ |
658 |
|
659 |
modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */ |
660 |
for(i=0;i<3;i++) |
661 |
printf("%d: %016Lx\n", i, ldt_table[i]);
|
662 |
|
663 |
/* do some tests with fs or gs */
|
664 |
asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1))); |
665 |
asm volatile ("movl %0, %%gs" : : "r" (MK_SEL(2))); |
666 |
|
667 |
seg_data1[1] = 0xaa; |
668 |
seg_data2[1] = 0x55; |
669 |
|
670 |
asm volatile ("fs movzbl 0x1, %0" : "=r" (res)); |
671 |
printf("FS[1] = %02x\n", res);
|
672 |
|
673 |
asm volatile ("gs movzbl 0x1, %0" : "=r" (res)); |
674 |
printf("GS[1] = %02x\n", res);
|
675 |
|
676 |
/* tests with ds/ss (implicit segment case) */
|
677 |
tmp = 0xa5;
|
678 |
asm volatile ("pushl %%ebp\n\t" |
679 |
"pushl %%ds\n\t"
|
680 |
"movl %2, %%ds\n\t"
|
681 |
"movl %3, %%ebp\n\t"
|
682 |
"movzbl 0x1, %0\n\t"
|
683 |
"movzbl (%%ebp), %1\n\t"
|
684 |
"popl %%ds\n\t"
|
685 |
"popl %%ebp\n\t"
|
686 |
: "=r" (res), "=r" (res2) |
687 |
: "r" (MK_SEL(1)), "r" (&tmp)); |
688 |
printf("DS[1] = %02x\n", res);
|
689 |
printf("SS[tmp] = %02x\n", res2);
|
690 |
} |
691 |
|
692 |
#define TEST_XCHG(op, size, opconst)\
|
693 |
{\ |
694 |
int op0, op1;\
|
695 |
op0 = 0x12345678;\
|
696 |
op1 = 0xfbca7654;\
|
697 |
asm(#op " %" size "0, %" size "1" \ |
698 |
: "=q" (op0), opconst (op1) \
|
699 |
: "0" (op0), "1" (op1));\ |
700 |
printf("%-10s A=%08x B=%08x\n",\
|
701 |
#op, op0, op1);\
|
702 |
} |
703 |
|
704 |
void test_xchg(void) |
705 |
{ |
706 |
TEST_XCHG(xchgl, "", "=q"); |
707 |
TEST_XCHG(xchgw, "w", "=q"); |
708 |
TEST_XCHG(xchgb, "b", "=q"); |
709 |
|
710 |
TEST_XCHG(xchgl, "", "=m"); |
711 |
TEST_XCHG(xchgw, "w", "=m"); |
712 |
TEST_XCHG(xchgb, "b", "=m"); |
713 |
|
714 |
TEST_XCHG(xaddl, "", "=q"); |
715 |
TEST_XCHG(xaddw, "w", "=q"); |
716 |
TEST_XCHG(xaddb, "b", "=q"); |
717 |
|
718 |
TEST_XCHG(xaddl, "", "=m"); |
719 |
TEST_XCHG(xaddw, "w", "=m"); |
720 |
TEST_XCHG(xaddb, "b", "=m"); |
721 |
} |
722 |
|
723 |
static void *call_end __init_call = NULL; |
724 |
|
725 |
int main(int argc, char **argv) |
726 |
{ |
727 |
void **ptr;
|
728 |
void (*func)(void); |
729 |
|
730 |
ptr = &call_start + 1;
|
731 |
while (*ptr != NULL) { |
732 |
func = *ptr++; |
733 |
func(); |
734 |
} |
735 |
test_bsx(); |
736 |
test_mul(); |
737 |
test_jcc(); |
738 |
test_floats(); |
739 |
test_bcd(); |
740 |
test_xchg(); |
741 |
test_lea(); |
742 |
test_segs(); |
743 |
return 0; |
744 |
} |