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