]> git.proxmox.com Git - qemu.git/blob - tests/test-i386.c
self modifying code also tests translation block chaining invalidation
[qemu.git] / tests / test-i386.c
1 #define _GNU_SOURCE
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <inttypes.h>
5 #include <math.h>
6 #include <signal.h>
7 #include <setjmp.h>
8 #include <sys/ucontext.h>
9 #include <sys/mman.h>
10 #include <asm/vm86.h>
11
12 #define TEST_CMOV 0
13
14 #define xglue(x, y) x ## y
15 #define glue(x, y) xglue(x, y)
16 #define stringify(s) tostring(s)
17 #define tostring(s) #s
18
19 #define CC_C 0x0001
20 #define CC_P 0x0004
21 #define CC_A 0x0010
22 #define CC_Z 0x0040
23 #define CC_S 0x0080
24 #define CC_O 0x0800
25
26 #define __init_call __attribute__ ((unused,__section__ (".initcall.init")))
27
28 static void *call_start __init_call = NULL;
29
30 #define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
31
32 #define OP add
33 #include "test-i386.h"
34
35 #define OP sub
36 #include "test-i386.h"
37
38 #define OP xor
39 #include "test-i386.h"
40
41 #define OP and
42 #include "test-i386.h"
43
44 #define OP or
45 #include "test-i386.h"
46
47 #define OP cmp
48 #include "test-i386.h"
49
50 #define OP adc
51 #define OP_CC
52 #include "test-i386.h"
53
54 #define OP sbb
55 #define OP_CC
56 #include "test-i386.h"
57
58 #define OP inc
59 #define OP_CC
60 #define OP1
61 #include "test-i386.h"
62
63 #define OP dec
64 #define OP_CC
65 #define OP1
66 #include "test-i386.h"
67
68 #define OP neg
69 #define OP_CC
70 #define OP1
71 #include "test-i386.h"
72
73 #define OP not
74 #define OP_CC
75 #define OP1
76 #include "test-i386.h"
77
78 #undef CC_MASK
79 #define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)
80
81 #define OP shl
82 #include "test-i386-shift.h"
83
84 #define OP shr
85 #include "test-i386-shift.h"
86
87 #define OP sar
88 #include "test-i386-shift.h"
89
90 #define OP rol
91 #include "test-i386-shift.h"
92
93 #define OP ror
94 #include "test-i386-shift.h"
95
96 #define OP rcr
97 #define OP_CC
98 #include "test-i386-shift.h"
99
100 #define OP rcl
101 #define OP_CC
102 #include "test-i386-shift.h"
103
104 #define OP shld
105 #define OP_SHIFTD
106 #define OP_NOBYTE
107 #include "test-i386-shift.h"
108
109 #define OP shrd
110 #define OP_SHIFTD
111 #define OP_NOBYTE
112 #include "test-i386-shift.h"
113
114 /* XXX: should be more precise ? */
115 #undef CC_MASK
116 #define CC_MASK (CC_C)
117
118 #define OP bt
119 #define OP_NOBYTE
120 #include "test-i386-shift.h"
121
122 #define OP bts
123 #define OP_NOBYTE
124 #include "test-i386-shift.h"
125
126 #define OP btr
127 #define OP_NOBYTE
128 #include "test-i386-shift.h"
129
130 #define OP btc
131 #define OP_NOBYTE
132 #include "test-i386-shift.h"
133
134 /* lea test (modrm support) */
135 #define TEST_LEA(STR)\
136 {\
137 asm("leal " STR ", %0"\
138 : "=r" (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 #define TEST_LEA16(STR)\
144 {\
145 asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\
146 : "=wq" (res)\
147 : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
148 printf("lea %s = %08x\n", STR, res);\
149 }
150
151
152 void test_lea(void)
153 {
154 int eax, ebx, ecx, edx, esi, edi, res;
155 eax = 0x0001;
156 ebx = 0x0002;
157 ecx = 0x0004;
158 edx = 0x0008;
159 esi = 0x0010;
160 edi = 0x0020;
161
162 TEST_LEA("0x4000");
163
164 TEST_LEA("(%%eax)");
165 TEST_LEA("(%%ebx)");
166 TEST_LEA("(%%ecx)");
167 TEST_LEA("(%%edx)");
168 TEST_LEA("(%%esi)");
169 TEST_LEA("(%%edi)");
170
171 TEST_LEA("0x40(%%eax)");
172 TEST_LEA("0x40(%%ebx)");
173 TEST_LEA("0x40(%%ecx)");
174 TEST_LEA("0x40(%%edx)");
175 TEST_LEA("0x40(%%esi)");
176 TEST_LEA("0x40(%%edi)");
177
178 TEST_LEA("0x4000(%%eax)");
179 TEST_LEA("0x4000(%%ebx)");
180 TEST_LEA("0x4000(%%ecx)");
181 TEST_LEA("0x4000(%%edx)");
182 TEST_LEA("0x4000(%%esi)");
183 TEST_LEA("0x4000(%%edi)");
184
185 TEST_LEA("(%%eax, %%ecx)");
186 TEST_LEA("(%%ebx, %%edx)");
187 TEST_LEA("(%%ecx, %%ecx)");
188 TEST_LEA("(%%edx, %%ecx)");
189 TEST_LEA("(%%esi, %%ecx)");
190 TEST_LEA("(%%edi, %%ecx)");
191
192 TEST_LEA("0x40(%%eax, %%ecx)");
193 TEST_LEA("0x4000(%%ebx, %%edx)");
194
195 TEST_LEA("(%%ecx, %%ecx, 2)");
196 TEST_LEA("(%%edx, %%ecx, 4)");
197 TEST_LEA("(%%esi, %%ecx, 8)");
198
199 TEST_LEA("(,%%eax, 2)");
200 TEST_LEA("(,%%ebx, 4)");
201 TEST_LEA("(,%%ecx, 8)");
202
203 TEST_LEA("0x40(,%%eax, 2)");
204 TEST_LEA("0x40(,%%ebx, 4)");
205 TEST_LEA("0x40(,%%ecx, 8)");
206
207
208 TEST_LEA("-10(%%ecx, %%ecx, 2)");
209 TEST_LEA("-10(%%edx, %%ecx, 4)");
210 TEST_LEA("-10(%%esi, %%ecx, 8)");
211
212 TEST_LEA("0x4000(%%ecx, %%ecx, 2)");
213 TEST_LEA("0x4000(%%edx, %%ecx, 4)");
214 TEST_LEA("0x4000(%%esi, %%ecx, 8)");
215
216 /* limited 16 bit addressing test */
217 TEST_LEA16("0x4000");
218 TEST_LEA16("(%%bx)");
219 TEST_LEA16("(%%si)");
220 TEST_LEA16("(%%di)");
221 TEST_LEA16("0x40(%%bx)");
222 TEST_LEA16("0x40(%%si)");
223 TEST_LEA16("0x40(%%di)");
224 TEST_LEA16("0x4000(%%bx)");
225 TEST_LEA16("0x4000(%%si)");
226 TEST_LEA16("(%%bx,%%si)");
227 TEST_LEA16("(%%bx,%%di)");
228 TEST_LEA16("0x40(%%bx,%%si)");
229 TEST_LEA16("0x40(%%bx,%%di)");
230 TEST_LEA16("0x4000(%%bx,%%si)");
231 TEST_LEA16("0x4000(%%bx,%%di)");
232 }
233
234 #define TEST_JCC(JCC, v1, v2)\
235 {\
236 int res;\
237 asm("movl $1, %0\n\t"\
238 "cmpl %2, %1\n\t"\
239 "j" JCC " 1f\n\t"\
240 "movl $0, %0\n\t"\
241 "1:\n\t"\
242 : "=r" (res)\
243 : "r" (v1), "r" (v2));\
244 printf("%-10s %d\n", "j" JCC, res);\
245 \
246 asm("movl $0, %0\n\t"\
247 "cmpl %2, %1\n\t"\
248 "set" JCC " %b0\n\t"\
249 : "=r" (res)\
250 : "r" (v1), "r" (v2));\
251 printf("%-10s %d\n", "set" JCC, res);\
252 if (TEST_CMOV) {\
253 asm("movl $0x12345678, %0\n\t"\
254 "cmpl %2, %1\n\t"\
255 "cmov" JCC "l %3, %0\n\t"\
256 : "=r" (res)\
257 : "r" (v1), "r" (v2), "m" (1));\
258 printf("%-10s R=0x%08x\n", "cmov" JCC "l", res);\
259 asm("movl $0x12345678, %0\n\t"\
260 "cmpl %2, %1\n\t"\
261 "cmov" JCC "w %w3, %w0\n\t"\
262 : "=r" (res)\
263 : "r" (v1), "r" (v2), "r" (1));\
264 printf("%-10s R=0x%08x\n", "cmov" JCC "w", res);\
265 } \
266 }
267
268 /* various jump tests */
269 void test_jcc(void)
270 {
271 TEST_JCC("ne", 1, 1);
272 TEST_JCC("ne", 1, 0);
273
274 TEST_JCC("e", 1, 1);
275 TEST_JCC("e", 1, 0);
276
277 TEST_JCC("l", 1, 1);
278 TEST_JCC("l", 1, 0);
279 TEST_JCC("l", 1, -1);
280
281 TEST_JCC("le", 1, 1);
282 TEST_JCC("le", 1, 0);
283 TEST_JCC("le", 1, -1);
284
285 TEST_JCC("ge", 1, 1);
286 TEST_JCC("ge", 1, 0);
287 TEST_JCC("ge", -1, 1);
288
289 TEST_JCC("g", 1, 1);
290 TEST_JCC("g", 1, 0);
291 TEST_JCC("g", 1, -1);
292
293 TEST_JCC("b", 1, 1);
294 TEST_JCC("b", 1, 0);
295 TEST_JCC("b", 1, -1);
296
297 TEST_JCC("be", 1, 1);
298 TEST_JCC("be", 1, 0);
299 TEST_JCC("be", 1, -1);
300
301 TEST_JCC("ae", 1, 1);
302 TEST_JCC("ae", 1, 0);
303 TEST_JCC("ae", 1, -1);
304
305 TEST_JCC("a", 1, 1);
306 TEST_JCC("a", 1, 0);
307 TEST_JCC("a", 1, -1);
308
309
310 TEST_JCC("p", 1, 1);
311 TEST_JCC("p", 1, 0);
312
313 TEST_JCC("np", 1, 1);
314 TEST_JCC("np", 1, 0);
315
316 TEST_JCC("o", 0x7fffffff, 0);
317 TEST_JCC("o", 0x7fffffff, -1);
318
319 TEST_JCC("no", 0x7fffffff, 0);
320 TEST_JCC("no", 0x7fffffff, -1);
321
322 TEST_JCC("s", 0, 1);
323 TEST_JCC("s", 0, -1);
324 TEST_JCC("s", 0, 0);
325
326 TEST_JCC("ns", 0, 1);
327 TEST_JCC("ns", 0, -1);
328 TEST_JCC("ns", 0, 0);
329 }
330
331 #undef CC_MASK
332 #define CC_MASK (CC_O | CC_C)
333
334 #define OP mul
335 #include "test-i386-muldiv.h"
336
337 #define OP imul
338 #include "test-i386-muldiv.h"
339
340 #undef CC_MASK
341 #define CC_MASK (0)
342
343 #define OP div
344 #include "test-i386-muldiv.h"
345
346 #define OP idiv
347 #include "test-i386-muldiv.h"
348
349 void test_imulw2(int op0, int op1)
350 {
351 int res, s1, s0, flags;
352 s0 = op0;
353 s1 = op1;
354 res = s0;
355 flags = 0;
356 asm ("push %4\n\t"
357 "popf\n\t"
358 "imulw %w2, %w0\n\t"
359 "pushf\n\t"
360 "popl %1\n\t"
361 : "=q" (res), "=g" (flags)
362 : "q" (s1), "0" (res), "1" (flags));
363 printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
364 "imulw", s0, s1, res, flags & CC_MASK);
365 }
366
367 void test_imull2(int op0, int op1)
368 {
369 int res, s1, s0, flags;
370 s0 = op0;
371 s1 = op1;
372 res = s0;
373 flags = 0;
374 asm ("push %4\n\t"
375 "popf\n\t"
376 "imull %2, %0\n\t"
377 "pushf\n\t"
378 "popl %1\n\t"
379 : "=q" (res), "=g" (flags)
380 : "q" (s1), "0" (res), "1" (flags));
381 printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
382 "imull", s0, s1, res, flags & CC_MASK);
383 }
384
385 void test_mul(void)
386 {
387 test_imulb(0x1234561d, 4);
388 test_imulb(3, -4);
389 test_imulb(0x80, 0x80);
390 test_imulb(0x10, 0x10);
391
392 test_imulw(0, 0x1234001d, 45);
393 test_imulw(0, 23, -45);
394 test_imulw(0, 0x8000, 0x8000);
395 test_imulw(0, 0x100, 0x100);
396
397 test_imull(0, 0x1234001d, 45);
398 test_imull(0, 23, -45);
399 test_imull(0, 0x80000000, 0x80000000);
400 test_imull(0, 0x10000, 0x10000);
401
402 test_mulb(0x1234561d, 4);
403 test_mulb(3, -4);
404 test_mulb(0x80, 0x80);
405 test_mulb(0x10, 0x10);
406
407 test_mulw(0, 0x1234001d, 45);
408 test_mulw(0, 23, -45);
409 test_mulw(0, 0x8000, 0x8000);
410 test_mulw(0, 0x100, 0x100);
411
412 test_mull(0, 0x1234001d, 45);
413 test_mull(0, 23, -45);
414 test_mull(0, 0x80000000, 0x80000000);
415 test_mull(0, 0x10000, 0x10000);
416
417 test_imulw2(0x1234001d, 45);
418 test_imulw2(23, -45);
419 test_imulw2(0x8000, 0x8000);
420 test_imulw2(0x100, 0x100);
421
422 test_imull2(0x1234001d, 45);
423 test_imull2(23, -45);
424 test_imull2(0x80000000, 0x80000000);
425 test_imull2(0x10000, 0x10000);
426
427 test_idivb(0x12341678, 0x127e);
428 test_idivb(0x43210123, -5);
429 test_idivb(0x12340004, -1);
430
431 test_idivw(0, 0x12345678, 12347);
432 test_idivw(0, -23223, -45);
433 test_idivw(0, 0x12348000, -1);
434 test_idivw(0x12343, 0x12345678, 0x81238567);
435
436 test_idivl(0, 0x12345678, 12347);
437 test_idivl(0, -233223, -45);
438 test_idivl(0, 0x80000000, -1);
439 test_idivl(0x12343, 0x12345678, 0x81234567);
440
441 test_divb(0x12341678, 0x127e);
442 test_divb(0x43210123, -5);
443 test_divb(0x12340004, -1);
444
445 test_divw(0, 0x12345678, 12347);
446 test_divw(0, -23223, -45);
447 test_divw(0, 0x12348000, -1);
448 test_divw(0x12343, 0x12345678, 0x81238567);
449
450 test_divl(0, 0x12345678, 12347);
451 test_divl(0, -233223, -45);
452 test_divl(0, 0x80000000, -1);
453 test_divl(0x12343, 0x12345678, 0x81234567);
454 }
455
456 #define TEST_BSX(op, size, op0)\
457 {\
458 int res, val, resz;\
459 val = op0;\
460 asm("xorl %1, %1 ; " #op " %" size "2, %" size "0 ; setz %b1" \
461 : "=r" (res), "=q" (resz)\
462 : "g" (val));\
463 printf("%-10s A=%08x R=%08x %d\n", #op, val, resz ? 0 : res, resz);\
464 }
465
466 void test_bsx(void)
467 {
468 TEST_BSX(bsrw, "w", 0);
469 TEST_BSX(bsrw, "w", 0x12340128);
470 TEST_BSX(bsrl, "", 0);
471 TEST_BSX(bsrl, "", 0x00340128);
472 TEST_BSX(bsfw, "w", 0);
473 TEST_BSX(bsfw, "w", 0x12340128);
474 TEST_BSX(bsfl, "", 0);
475 TEST_BSX(bsfl, "", 0x00340128);
476 }
477
478 /**********************************************/
479
480 void test_fops(double a, double b)
481 {
482 printf("a=%f b=%f a+b=%f\n", a, b, a + b);
483 printf("a=%f b=%f a-b=%f\n", a, b, a - b);
484 printf("a=%f b=%f a*b=%f\n", a, b, a * b);
485 printf("a=%f b=%f a/b=%f\n", a, b, a / b);
486 printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b));
487 printf("a=%f sqrt(a)=%f\n", a, sqrt(a));
488 printf("a=%f sin(a)=%f\n", a, sin(a));
489 printf("a=%f cos(a)=%f\n", a, cos(a));
490 printf("a=%f tan(a)=%f\n", a, tan(a));
491 printf("a=%f log(a)=%f\n", a, log(a));
492 printf("a=%f exp(a)=%f\n", a, exp(a));
493 printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
494 /* just to test some op combining */
495 printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a)));
496 printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a)));
497 printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));
498
499 }
500
501 void test_fcmp(double a, double b)
502 {
503 printf("(%f<%f)=%d\n",
504 a, b, a < b);
505 printf("(%f<=%f)=%d\n",
506 a, b, a <= b);
507 printf("(%f==%f)=%d\n",
508 a, b, a == b);
509 printf("(%f>%f)=%d\n",
510 a, b, a > b);
511 printf("(%f<=%f)=%d\n",
512 a, b, a >= b);
513 }
514
515 void test_fcvt(double a)
516 {
517 float fa;
518 long double la;
519
520 fa = a;
521 la = a;
522 printf("(float)%f = %f\n", a, fa);
523 printf("(long double)%f = %Lf\n", a, la);
524 printf("a=%016Lx\n", *(long long *)&a);
525 printf("la=%016Lx %04x\n", *(long long *)&la,
526 *(unsigned short *)((char *)(&la) + 8));
527 printf("a=%f floor(a)=%f\n", a, floor(a));
528 printf("a=%f ceil(a)=%f\n", a, ceil(a));
529 printf("a=%f rint(a)=%f\n", a, rint(a));
530 }
531
532 #define TEST(N) \
533 asm("fld" #N : "=t" (a)); \
534 printf("fld" #N "= %f\n", a);
535
536 void test_fconst(void)
537 {
538 double a;
539 TEST(1);
540 TEST(l2t);
541 TEST(l2e);
542 TEST(pi);
543 TEST(lg2);
544 TEST(ln2);
545 TEST(z);
546 }
547
548 void test_fbcd(double a)
549 {
550 unsigned short bcd[5];
551 double b;
552
553 asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st");
554 asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
555 printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n",
556 a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);
557 }
558
559 void test_floats(void)
560 {
561 test_fops(2, 3);
562 test_fops(1.4, -5);
563 test_fcmp(2, -1);
564 test_fcmp(2, 2);
565 test_fcmp(2, 3);
566 test_fcvt(1.0/7.0);
567 test_fcvt(-1.0/9.0);
568 test_fcvt(1e30);
569 test_fconst();
570 test_fbcd(1234567890123456);
571 test_fbcd(-123451234567890);
572 }
573
574 /**********************************************/
575
576 #define TEST_BCD(op, op0, cc_in, cc_mask)\
577 {\
578 int res, flags;\
579 res = op0;\
580 flags = cc_in;\
581 asm ("push %3\n\t"\
582 "popf\n\t"\
583 #op "\n\t"\
584 "pushf\n\t"\
585 "popl %1\n\t"\
586 : "=a" (res), "=g" (flags)\
587 : "0" (res), "1" (flags));\
588 printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\
589 #op, op0, res, cc_in, flags & cc_mask);\
590 }
591
592 void test_bcd(void)
593 {
594 TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
595 TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
596 TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
597 TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
598 TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
599 TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
600 TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
601 TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
602 TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
603 TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
604 TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
605 TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
606 TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
607
608 TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
609 TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
610 TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
611 TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
612 TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
613 TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
614 TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
615 TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
616 TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
617 TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
618 TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
619 TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
620 TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
621
622 TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A));
623 TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A));
624 TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A));
625 TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A));
626 TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A));
627 TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A));
628 TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A));
629 TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A));
630
631 TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A));
632 TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A));
633 TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A));
634 TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A));
635 TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A));
636 TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A));
637 TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A));
638 TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A));
639
640 TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
641 TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
642 }
643
644 #define TEST_XCHG(op, size, opconst)\
645 {\
646 int op0, op1;\
647 op0 = 0x12345678;\
648 op1 = 0xfbca7654;\
649 asm(#op " %" size "0, %" size "1" \
650 : "=q" (op0), opconst (op1) \
651 : "0" (op0), "1" (op1));\
652 printf("%-10s A=%08x B=%08x\n",\
653 #op, op0, op1);\
654 }
655
656 #define TEST_CMPXCHG(op, size, opconst, eax)\
657 {\
658 int op0, op1;\
659 op0 = 0x12345678;\
660 op1 = 0xfbca7654;\
661 asm(#op " %" size "0, %" size "1" \
662 : "=q" (op0), opconst (op1) \
663 : "0" (op0), "1" (op1), "a" (eax));\
664 printf("%-10s EAX=%08x A=%08x C=%08x\n",\
665 #op, eax, op0, op1);\
666 }
667
668 void test_xchg(void)
669 {
670 TEST_XCHG(xchgl, "", "=q");
671 TEST_XCHG(xchgw, "w", "=q");
672 TEST_XCHG(xchgb, "b", "=q");
673
674 TEST_XCHG(xchgl, "", "=m");
675 TEST_XCHG(xchgw, "w", "=m");
676 TEST_XCHG(xchgb, "b", "=m");
677
678 TEST_XCHG(xaddl, "", "=q");
679 TEST_XCHG(xaddw, "w", "=q");
680 TEST_XCHG(xaddb, "b", "=q");
681
682 TEST_XCHG(xaddl, "", "=m");
683 TEST_XCHG(xaddw, "w", "=m");
684 TEST_XCHG(xaddb, "b", "=m");
685
686 TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfbca7654);
687 TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfbca7654);
688 TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfbca7654);
689
690 TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfffefdfc);
691 TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfffefdfc);
692 TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfffefdfc);
693
694 TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfbca7654);
695 TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfbca7654);
696 TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfbca7654);
697
698 TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfffefdfc);
699 TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfffefdfc);
700 TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfffefdfc);
701 }
702
703 /**********************************************/
704 /* segmentation tests */
705
706 #include <asm/ldt.h>
707 #include <linux/unistd.h>
708
709 _syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
710
711 uint8_t seg_data1[4096];
712 uint8_t seg_data2[4096];
713
714 #define MK_SEL(n) (((n) << 3) | 7)
715
716 #define TEST_LR(op, size, seg, mask)\
717 {\
718 int res, res2;\
719 res = 0x12345678;\
720 asm (op " %" size "2, %" size "0\n" \
721 "movl $0, %1\n"\
722 "jnz 1f\n"\
723 "movl $1, %1\n"\
724 "1:\n"\
725 : "=r" (res), "=r" (res2) : "m" (seg), "0" (res));\
726 printf(op ": Z=%d %08x\n", res2, res & ~(mask));\
727 }
728
729 /* NOTE: we use Linux modify_ldt syscall */
730 void test_segs(void)
731 {
732 struct modify_ldt_ldt_s ldt;
733 long long ldt_table[3];
734 int res, res2;
735 char tmp;
736 struct {
737 uint32_t offset;
738 uint16_t seg;
739 } __attribute__((packed)) segoff;
740
741 ldt.entry_number = 1;
742 ldt.base_addr = (unsigned long)&seg_data1;
743 ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
744 ldt.seg_32bit = 1;
745 ldt.contents = MODIFY_LDT_CONTENTS_DATA;
746 ldt.read_exec_only = 0;
747 ldt.limit_in_pages = 1;
748 ldt.seg_not_present = 0;
749 ldt.useable = 1;
750 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
751
752 ldt.entry_number = 2;
753 ldt.base_addr = (unsigned long)&seg_data2;
754 ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12;
755 ldt.seg_32bit = 1;
756 ldt.contents = MODIFY_LDT_CONTENTS_DATA;
757 ldt.read_exec_only = 0;
758 ldt.limit_in_pages = 1;
759 ldt.seg_not_present = 0;
760 ldt.useable = 1;
761 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
762
763 modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */
764 #if 0
765 {
766 int i;
767 for(i=0;i<3;i++)
768 printf("%d: %016Lx\n", i, ldt_table[i]);
769 }
770 #endif
771 /* do some tests with fs or gs */
772 asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
773 asm volatile ("movl %0, %%gs" : : "r" (MK_SEL(2)));
774
775 seg_data1[1] = 0xaa;
776 seg_data2[1] = 0x55;
777
778 asm volatile ("fs movzbl 0x1, %0" : "=r" (res));
779 printf("FS[1] = %02x\n", res);
780
781 asm volatile ("gs movzbl 0x1, %0" : "=r" (res));
782 printf("GS[1] = %02x\n", res);
783
784 /* tests with ds/ss (implicit segment case) */
785 tmp = 0xa5;
786 asm volatile ("pushl %%ebp\n\t"
787 "pushl %%ds\n\t"
788 "movl %2, %%ds\n\t"
789 "movl %3, %%ebp\n\t"
790 "movzbl 0x1, %0\n\t"
791 "movzbl (%%ebp), %1\n\t"
792 "popl %%ds\n\t"
793 "popl %%ebp\n\t"
794 : "=r" (res), "=r" (res2)
795 : "r" (MK_SEL(1)), "r" (&tmp));
796 printf("DS[1] = %02x\n", res);
797 printf("SS[tmp] = %02x\n", res2);
798
799 segoff.seg = MK_SEL(2);
800 segoff.offset = 0xabcdef12;
801 asm volatile("lfs %2, %0\n\t"
802 "movl %%fs, %1\n\t"
803 : "=r" (res), "=g" (res2)
804 : "m" (segoff));
805 printf("FS:reg = %04x:%08x\n", res2, res);
806
807 TEST_LR("larw", "w", MK_SEL(2), 0x0100);
808 TEST_LR("larl", "", MK_SEL(2), 0x0100);
809 TEST_LR("lslw", "w", MK_SEL(2), 0);
810 TEST_LR("lsll", "", MK_SEL(2), 0);
811
812 TEST_LR("larw", "w", 0xfff8, 0);
813 TEST_LR("larl", "", 0xfff8, 0);
814 TEST_LR("lslw", "w", 0xfff8, 0);
815 TEST_LR("lsll", "", 0xfff8, 0);
816 }
817
818 /* 16 bit code test */
819 extern char code16_start, code16_end;
820 extern char code16_func1;
821 extern char code16_func2;
822 extern char code16_func3;
823
824 void test_code16(void)
825 {
826 struct modify_ldt_ldt_s ldt;
827 int res, res2;
828
829 /* build a code segment */
830 ldt.entry_number = 1;
831 ldt.base_addr = (unsigned long)&code16_start;
832 ldt.limit = &code16_end - &code16_start;
833 ldt.seg_32bit = 0;
834 ldt.contents = MODIFY_LDT_CONTENTS_CODE;
835 ldt.read_exec_only = 0;
836 ldt.limit_in_pages = 0;
837 ldt.seg_not_present = 0;
838 ldt.useable = 1;
839 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
840
841 /* call the first function */
842 asm volatile ("lcall %1, %2"
843 : "=a" (res)
844 : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc");
845 printf("func1() = 0x%08x\n", res);
846 asm volatile ("lcall %2, %3"
847 : "=a" (res), "=c" (res2)
848 : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc");
849 printf("func2() = 0x%08x spdec=%d\n", res, res2);
850 asm volatile ("lcall %1, %2"
851 : "=a" (res)
852 : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc");
853 printf("func3() = 0x%08x\n", res);
854 }
855
856 void test_misc(void)
857 {
858 char table[256];
859 int res, i;
860
861 for(i=0;i<256;i++) table[i] = 256 - i;
862 res = 0x12345678;
863 asm ("xlat" : "=a" (res) : "b" (table), "0" (res));
864 printf("xlat: EAX=%08x\n", res);
865 }
866
867 uint8_t str_buffer[4096];
868
869 #define TEST_STRING1(OP, size, DF, REP)\
870 {\
871 int esi, edi, eax, ecx, eflags;\
872 \
873 esi = (long)(str_buffer + sizeof(str_buffer) / 2);\
874 edi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\
875 eax = 0x12345678;\
876 ecx = 17;\
877 \
878 asm volatile ("pushl $0\n\t"\
879 "popf\n\t"\
880 DF "\n\t"\
881 REP #OP size "\n\t"\
882 "cld\n\t"\
883 "pushf\n\t"\
884 "popl %4\n\t"\
885 : "=S" (esi), "=D" (edi), "=a" (eax), "=c" (ecx), "=g" (eflags)\
886 : "0" (esi), "1" (edi), "2" (eax), "3" (ecx));\
887 printf("%-10s ESI=%08x EDI=%08x EAX=%08x ECX=%08x EFL=%04x\n",\
888 REP #OP size, esi, edi, eax, ecx,\
889 eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\
890 }
891
892 #define TEST_STRING(OP, REP)\
893 TEST_STRING1(OP, "b", "", REP);\
894 TEST_STRING1(OP, "w", "", REP);\
895 TEST_STRING1(OP, "l", "", REP);\
896 TEST_STRING1(OP, "b", "std", REP);\
897 TEST_STRING1(OP, "w", "std", REP);\
898 TEST_STRING1(OP, "l", "std", REP)
899
900 void test_string(void)
901 {
902 int i;
903 for(i = 0;i < sizeof(str_buffer); i++)
904 str_buffer[i] = i + 0x56;
905 TEST_STRING(stos, "");
906 TEST_STRING(stos, "rep ");
907 TEST_STRING(lods, ""); /* to verify stos */
908 TEST_STRING(lods, "rep ");
909 TEST_STRING(movs, "");
910 TEST_STRING(movs, "rep ");
911 TEST_STRING(lods, ""); /* to verify stos */
912
913 /* XXX: better tests */
914 TEST_STRING(scas, "");
915 TEST_STRING(scas, "repz ");
916 TEST_STRING(scas, "repnz ");
917 TEST_STRING(cmps, "");
918 TEST_STRING(cmps, "repz ");
919 TEST_STRING(cmps, "repnz ");
920 }
921
922 /* VM86 test */
923
924 static inline void set_bit(uint8_t *a, unsigned int bit)
925 {
926 a[bit / 8] |= (1 << (bit % 8));
927 }
928
929 static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
930 {
931 return (uint8_t *)((seg << 4) + (reg & 0xffff));
932 }
933
934 static inline void pushw(struct vm86_regs *r, int val)
935 {
936 r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
937 *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
938 }
939
940 #undef __syscall_return
941 #define __syscall_return(type, res) \
942 do { \
943 return (type) (res); \
944 } while (0)
945
946 _syscall2(int, vm86, int, func, struct vm86plus_struct *, v86)
947
948 extern char vm86_code_start;
949 extern char vm86_code_end;
950
951 #define VM86_CODE_CS 0x100
952 #define VM86_CODE_IP 0x100
953
954 void test_vm86(void)
955 {
956 struct vm86plus_struct ctx;
957 struct vm86_regs *r;
958 uint8_t *vm86_mem;
959 int seg, ret;
960
961 vm86_mem = mmap((void *)0x00000000, 0x110000,
962 PROT_WRITE | PROT_READ | PROT_EXEC,
963 MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
964 if (vm86_mem == MAP_FAILED) {
965 printf("ERROR: could not map vm86 memory");
966 return;
967 }
968 memset(&ctx, 0, sizeof(ctx));
969
970 /* init basic registers */
971 r = &ctx.regs;
972 r->eip = VM86_CODE_IP;
973 r->esp = 0xfffe;
974 seg = VM86_CODE_CS;
975 r->cs = seg;
976 r->ss = seg;
977 r->ds = seg;
978 r->es = seg;
979 r->fs = seg;
980 r->gs = seg;
981 r->eflags = VIF_MASK;
982
983 /* move code to proper address. We use the same layout as a .com
984 dos program. */
985 memcpy(vm86_mem + (VM86_CODE_CS << 4) + VM86_CODE_IP,
986 &vm86_code_start, &vm86_code_end - &vm86_code_start);
987
988 /* mark int 0x21 as being emulated */
989 set_bit((uint8_t *)&ctx.int_revectored, 0x21);
990
991 for(;;) {
992 ret = vm86(VM86_ENTER, &ctx);
993 switch(VM86_TYPE(ret)) {
994 case VM86_INTx:
995 {
996 int int_num, ah;
997
998 int_num = VM86_ARG(ret);
999 if (int_num != 0x21)
1000 goto unknown_int;
1001 ah = (r->eax >> 8) & 0xff;
1002 switch(ah) {
1003 case 0x00: /* exit */
1004 goto the_end;
1005 case 0x02: /* write char */
1006 {
1007 uint8_t c = r->edx;
1008 putchar(c);
1009 }
1010 break;
1011 case 0x09: /* write string */
1012 {
1013 uint8_t c, *ptr;
1014 ptr = seg_to_linear(r->ds, r->edx);
1015 for(;;) {
1016 c = *ptr++;
1017 if (c == '$')
1018 break;
1019 putchar(c);
1020 }
1021 r->eax = (r->eax & ~0xff) | '$';
1022 }
1023 break;
1024 case 0xff: /* extension: write hex number in edx */
1025 printf("%08x\n", (int)r->edx);
1026 break;
1027 default:
1028 unknown_int:
1029 printf("unsupported int 0x%02x\n", int_num);
1030 goto the_end;
1031 }
1032 }
1033 break;
1034 case VM86_SIGNAL:
1035 /* a signal came, we just ignore that */
1036 break;
1037 case VM86_STI:
1038 break;
1039 default:
1040 printf("ERROR: unhandled vm86 return code (0x%x)\n", ret);
1041 goto the_end;
1042 }
1043 }
1044 the_end:
1045 printf("VM86 end\n");
1046 munmap(vm86_mem, 0x110000);
1047 }
1048
1049 /* exception tests */
1050 #ifndef REG_EAX
1051 #define REG_EAX EAX
1052 #define REG_EBX EBX
1053 #define REG_ECX ECX
1054 #define REG_EDX EDX
1055 #define REG_ESI ESI
1056 #define REG_EDI EDI
1057 #define REG_EBP EBP
1058 #define REG_ESP ESP
1059 #define REG_EIP EIP
1060 #define REG_EFL EFL
1061 #define REG_TRAPNO TRAPNO
1062 #define REG_ERR ERR
1063 #endif
1064
1065 jmp_buf jmp_env;
1066 int dump_eip;
1067 int dump_si_addr;
1068 int v1;
1069 int tab[2];
1070
1071 void sig_handler(int sig, siginfo_t *info, void *puc)
1072 {
1073 struct ucontext *uc = puc;
1074
1075 printf("si_signo=%d si_errno=%d si_code=%d",
1076 info->si_signo, info->si_errno, info->si_code);
1077 if (dump_si_addr) {
1078 printf(" si_addr=0x%08lx",
1079 (unsigned long)info->si_addr);
1080 }
1081 printf("\n");
1082
1083 printf("trapno=0x%02x err=0x%08x",
1084 uc->uc_mcontext.gregs[REG_TRAPNO],
1085 uc->uc_mcontext.gregs[REG_ERR]);
1086 if (dump_eip)
1087 printf(" EIP=0x%08x", uc->uc_mcontext.gregs[REG_EIP]);
1088 printf("\n");
1089 longjmp(jmp_env, 1);
1090 }
1091
1092 void test_exceptions(void)
1093 {
1094 struct sigaction act;
1095 volatile int val;
1096
1097 act.sa_sigaction = sig_handler;
1098 sigemptyset(&act.sa_mask);
1099 act.sa_flags = SA_SIGINFO;
1100 sigaction(SIGFPE, &act, NULL);
1101 sigaction(SIGILL, &act, NULL);
1102 sigaction(SIGSEGV, &act, NULL);
1103 sigaction(SIGTRAP, &act, NULL);
1104
1105 /* test division by zero reporting */
1106 dump_eip = 0;
1107 dump_si_addr = 0;
1108 printf("DIVZ exception (currently imprecise):\n");
1109 if (setjmp(jmp_env) == 0) {
1110 /* now divide by zero */
1111 v1 = 0;
1112 v1 = 2 / v1;
1113 }
1114
1115 dump_si_addr = 1;
1116 printf("BOUND exception (currently imprecise):\n");
1117 if (setjmp(jmp_env) == 0) {
1118 /* bound exception */
1119 tab[0] = 1;
1120 tab[1] = 10;
1121 asm volatile ("bound %0, %1" : : "r" (11), "m" (tab));
1122 }
1123
1124 /* test SEGV reporting */
1125 printf("PF exception (currently imprecise):\n");
1126 if (setjmp(jmp_env) == 0) {
1127 /* now store in an invalid address */
1128 *(char *)0x1234 = 1;
1129 }
1130
1131 /* test SEGV reporting */
1132 printf("PF exception (currently imprecise):\n");
1133 if (setjmp(jmp_env) == 0) {
1134 /* read from an invalid address */
1135 v1 = *(char *)0x1234;
1136 }
1137
1138 printf("segment GPF exception (currently imprecise):\n");
1139 if (setjmp(jmp_env) == 0) {
1140 /* load an invalid segment */
1141 asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 0));
1142 }
1143
1144 dump_eip = 1;
1145 /* test illegal instruction reporting */
1146 printf("UD2 exception:\n");
1147 if (setjmp(jmp_env) == 0) {
1148 /* now execute an invalid instruction */
1149 asm volatile("ud2");
1150 }
1151
1152 printf("INT exception:\n");
1153 if (setjmp(jmp_env) == 0) {
1154 asm volatile ("int $0xfd");
1155 }
1156
1157 printf("INT3 exception:\n");
1158 if (setjmp(jmp_env) == 0) {
1159 asm volatile ("int3");
1160 }
1161
1162 printf("CLI exception:\n");
1163 if (setjmp(jmp_env) == 0) {
1164 asm volatile ("cli");
1165 }
1166
1167 printf("STI exception:\n");
1168 if (setjmp(jmp_env) == 0) {
1169 asm volatile ("cli");
1170 }
1171
1172 printf("INTO exception:\n");
1173 if (setjmp(jmp_env) == 0) {
1174 /* overflow exception */
1175 asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff));
1176 }
1177
1178 printf("OUTB exception:\n");
1179 if (setjmp(jmp_env) == 0) {
1180 asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0));
1181 }
1182
1183 printf("INB exception:\n");
1184 if (setjmp(jmp_env) == 0) {
1185 asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321));
1186 }
1187
1188 printf("REP OUTSB exception:\n");
1189 if (setjmp(jmp_env) == 0) {
1190 asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1));
1191 }
1192
1193 printf("REP INSB exception:\n");
1194 if (setjmp(jmp_env) == 0) {
1195 asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1));
1196 }
1197
1198 printf("HLT exception:\n");
1199 if (setjmp(jmp_env) == 0) {
1200 asm volatile ("hlt");
1201 }
1202
1203 printf("single step exception:\n");
1204 val = 0;
1205 if (setjmp(jmp_env) == 0) {
1206 asm volatile ("pushf\n"
1207 "orl $0x00100, (%%esp)\n"
1208 "popf\n"
1209 "movl $0xabcd, %0\n"
1210 "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory");
1211 }
1212 printf("val=0x%x\n", val);
1213 }
1214
1215 /* self modifying code test */
1216 uint8_t code[] = {
1217 0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */
1218 0xc3, /* ret */
1219 };
1220
1221 typedef int FuncType(void);
1222
1223 void test_self_modifying_code(void)
1224 {
1225 int i;
1226
1227 printf("self modifying code:\n");
1228 printf("func1 = 0x%x\n", ((FuncType *)code)());
1229 for(i = 2; i <= 4; i++) {
1230 code[1] = i;
1231 printf("func%d = 0x%x\n", i, ((FuncType *)code)());
1232 }
1233 }
1234
1235 static void *call_end __init_call = NULL;
1236
1237 int main(int argc, char **argv)
1238 {
1239 void **ptr;
1240 void (*func)(void);
1241
1242 ptr = &call_start + 1;
1243 while (*ptr != NULL) {
1244 func = *ptr++;
1245 func();
1246 }
1247 test_bsx();
1248 test_mul();
1249 test_jcc();
1250 test_floats();
1251 test_bcd();
1252 test_xchg();
1253 test_string();
1254 test_misc();
1255 test_lea();
1256 test_segs();
1257 test_code16();
1258 test_vm86();
1259 test_exceptions();
1260 test_self_modifying_code();
1261 return 0;
1262 }