]>
Commit | Line | Data |
---|---|---|
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 | } |