Statistics
| Branch: | Revision:

root / tests / test-i386.c @ e3b32540

History | View | Annotate | Download (32.7 kB)

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 v1;
1067
int tab[2];
1068

    
1069
void sig_handler(int sig, siginfo_t *info, void *puc)
1070
{
1071
    struct ucontext *uc = puc;
1072

    
1073
    printf("si_signo=%d si_errno=%d si_code=%d",
1074
           info->si_signo, info->si_errno, info->si_code);
1075
    printf(" si_addr=0x%08lx",
1076
           (unsigned long)info->si_addr);
1077
    printf("\n");
1078

    
1079
    printf("trapno=0x%02x err=0x%08x",
1080
           uc->uc_mcontext.gregs[REG_TRAPNO],
1081
           uc->uc_mcontext.gregs[REG_ERR]);
1082
    printf(" EIP=0x%08x", uc->uc_mcontext.gregs[REG_EIP]);
1083
    printf("\n");
1084
    longjmp(jmp_env, 1);
1085
}
1086

    
1087
void test_exceptions(void)
1088
{
1089
    struct modify_ldt_ldt_s ldt;
1090
    struct sigaction act;
1091
    volatile int val;
1092
    
1093
    act.sa_sigaction = sig_handler;
1094
    sigemptyset(&act.sa_mask);
1095
    act.sa_flags = SA_SIGINFO;
1096
    sigaction(SIGFPE, &act, NULL);
1097
    sigaction(SIGILL, &act, NULL);
1098
    sigaction(SIGSEGV, &act, NULL);
1099
    sigaction(SIGBUS, &act, NULL);
1100
    sigaction(SIGTRAP, &act, NULL);
1101

    
1102
    /* test division by zero reporting */
1103
    printf("DIVZ exception:\n");
1104
    if (setjmp(jmp_env) == 0) {
1105
        /* now divide by zero */
1106
        v1 = 0;
1107
        v1 = 2 / v1;
1108
    }
1109

    
1110
    printf("BOUND exception:\n");
1111
    if (setjmp(jmp_env) == 0) {
1112
        /* bound exception */
1113
        tab[0] = 1;
1114
        tab[1] = 10;
1115
        asm volatile ("bound %0, %1" : : "r" (11), "m" (tab));
1116
    }
1117

    
1118
    printf("segment exceptions:\n");
1119
    if (setjmp(jmp_env) == 0) {
1120
        /* load an invalid segment */
1121
        asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 1));
1122
    }
1123
    if (setjmp(jmp_env) == 0) {
1124
        /* null data segment is valid */
1125
        asm volatile ("movl %0, %%fs" : : "r" (3));
1126
        /* null stack segment */
1127
        asm volatile ("movl %0, %%ss" : : "r" (3));
1128
    }
1129

    
1130
    ldt.entry_number = 1;
1131
    ldt.base_addr = (unsigned long)&seg_data1;
1132
    ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
1133
    ldt.seg_32bit = 1;
1134
    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
1135
    ldt.read_exec_only = 0;
1136
    ldt.limit_in_pages = 1;
1137
    ldt.seg_not_present = 1;
1138
    ldt.useable = 1;
1139
    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
1140

    
1141
    if (setjmp(jmp_env) == 0) {
1142
        /* segment not present */
1143
        asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
1144
    }
1145

    
1146
    /* test SEGV reporting */
1147
    printf("PF exception:\n");
1148
    if (setjmp(jmp_env) == 0) {
1149
        val = 1;
1150
        /* now store in an invalid address */
1151
        *(char *)0x1234 = 1;
1152
    }
1153

    
1154
    /* test SEGV reporting */
1155
    printf("PF exception:\n");
1156
    if (setjmp(jmp_env) == 0) {
1157
        val = 1;
1158
        /* read from an invalid address */
1159
        v1 = *(char *)0x1234;
1160
    }
1161
    
1162
    /* test illegal instruction reporting */
1163
    printf("UD2 exception:\n");
1164
    if (setjmp(jmp_env) == 0) {
1165
        /* now execute an invalid instruction */
1166
        asm volatile("ud2");
1167
    }
1168
    
1169
    printf("INT exception:\n");
1170
    if (setjmp(jmp_env) == 0) {
1171
        asm volatile ("int $0xfd");
1172
    }
1173
    if (setjmp(jmp_env) == 0) {
1174
        asm volatile ("int $0x01");
1175
    }
1176
    if (setjmp(jmp_env) == 0) {
1177
        asm volatile (".byte 0xcd, 0x03");
1178
    }
1179
    if (setjmp(jmp_env) == 0) {
1180
        asm volatile ("int $0x04");
1181
    }
1182
    if (setjmp(jmp_env) == 0) {
1183
        asm volatile ("int $0x05");
1184
    }
1185

    
1186
    printf("INT3 exception:\n");
1187
    if (setjmp(jmp_env) == 0) {
1188
        asm volatile ("int3");
1189
    }
1190

    
1191
    printf("CLI exception:\n");
1192
    if (setjmp(jmp_env) == 0) {
1193
        asm volatile ("cli");
1194
    }
1195

    
1196
    printf("STI exception:\n");
1197
    if (setjmp(jmp_env) == 0) {
1198
        asm volatile ("cli");
1199
    }
1200

    
1201
    printf("INTO exception:\n");
1202
    if (setjmp(jmp_env) == 0) {
1203
        /* overflow exception */
1204
        asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff));
1205
    }
1206

    
1207
    printf("OUTB exception:\n");
1208
    if (setjmp(jmp_env) == 0) {
1209
        asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0));
1210
    }
1211

    
1212
    printf("INB exception:\n");
1213
    if (setjmp(jmp_env) == 0) {
1214
        asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321));
1215
    }
1216

    
1217
    printf("REP OUTSB exception:\n");
1218
    if (setjmp(jmp_env) == 0) {
1219
        asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1));
1220
    }
1221

    
1222
    printf("REP INSB exception:\n");
1223
    if (setjmp(jmp_env) == 0) {
1224
        asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1));
1225
    }
1226

    
1227
    printf("HLT exception:\n");
1228
    if (setjmp(jmp_env) == 0) {
1229
        asm volatile ("hlt");
1230
    }
1231

    
1232
    printf("single step exception:\n");
1233
    val = 0;
1234
    if (setjmp(jmp_env) == 0) {
1235
        asm volatile ("pushf\n"
1236
                      "orl $0x00100, (%%esp)\n"
1237
                      "popf\n"
1238
                      "movl $0xabcd, %0\n" 
1239
                      "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory");
1240
    }
1241
    printf("val=0x%x\n", val);
1242
}
1243

    
1244
/* self modifying code test */
1245
uint8_t code[] = {
1246
    0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */
1247
    0xc3, /* ret */
1248
};
1249

    
1250
typedef int FuncType(void);
1251

    
1252
void test_self_modifying_code(void)
1253
{
1254
    int i;
1255

    
1256
    printf("self modifying code:\n");
1257
    printf("func1 = 0x%x\n", ((FuncType *)code)());
1258
    for(i = 2; i <= 4; i++) {
1259
        code[1] = i;
1260
        printf("func%d = 0x%x\n", i, ((FuncType *)code)());
1261
    }
1262
}
1263
    
1264
static void *call_end __init_call = NULL;
1265

    
1266
int main(int argc, char **argv)
1267
{
1268
    void **ptr;
1269
    void (*func)(void);
1270

    
1271
    ptr = &call_start + 1;
1272
    while (*ptr != NULL) {
1273
        func = *ptr++;
1274
        func();
1275
    }
1276
    test_bsx();
1277
    test_mul();
1278
    test_jcc();
1279
    test_floats();
1280
    test_bcd();
1281
    test_xchg();
1282
    test_string();
1283
    test_misc();
1284
    test_lea();
1285
    test_segs();
1286
    test_code16();
1287
    test_vm86();
1288
    test_exceptions();
1289
    test_self_modifying_code();
1290
    return 0;
1291
}