Statistics
| Branch: | Revision:

root / tests / test-i386.c @ a412ac57

History | View | Annotate | Download (36 kB)

1
#define _GNU_SOURCE
2
#include <stdlib.h>
3
#include <stdio.h>
4
#include <string.h>
5
#include <inttypes.h>
6
#include <math.h>
7
#include <signal.h>
8
#include <setjmp.h>
9
#include <errno.h>
10
#include <sys/ucontext.h>
11
#include <sys/mman.h>
12
#include <asm/vm86.h>
13

    
14
#define TEST_CMOV  0
15
#define TEST_FCOMI 0
16

    
17
#define xglue(x, y) x ## y
18
#define glue(x, y) xglue(x, y)
19
#define stringify(s)        tostring(s)
20
#define tostring(s)        #s
21

    
22
#define CC_C           0x0001
23
#define CC_P         0x0004
24
#define CC_A        0x0010
25
#define CC_Z        0x0040
26
#define CC_S    0x0080
27
#define CC_O    0x0800
28

    
29
#define __init_call        __attribute__ ((unused,__section__ (".initcall.init")))
30

    
31
static void *call_start __init_call = NULL;
32

    
33
#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
34

    
35
#define OP add
36
#include "test-i386.h"
37

    
38
#define OP sub
39
#include "test-i386.h"
40

    
41
#define OP xor
42
#include "test-i386.h"
43

    
44
#define OP and
45
#include "test-i386.h"
46

    
47
#define OP or
48
#include "test-i386.h"
49

    
50
#define OP cmp
51
#include "test-i386.h"
52

    
53
#define OP adc
54
#define OP_CC
55
#include "test-i386.h"
56

    
57
#define OP sbb
58
#define OP_CC
59
#include "test-i386.h"
60

    
61
#define OP inc
62
#define OP_CC
63
#define OP1
64
#include "test-i386.h"
65

    
66
#define OP dec
67
#define OP_CC
68
#define OP1
69
#include "test-i386.h"
70

    
71
#define OP neg
72
#define OP_CC
73
#define OP1
74
#include "test-i386.h"
75

    
76
#define OP not
77
#define OP_CC
78
#define OP1
79
#include "test-i386.h"
80

    
81
#undef CC_MASK
82
#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)
83

    
84
#define OP shl
85
#include "test-i386-shift.h"
86

    
87
#define OP shr
88
#include "test-i386-shift.h"
89

    
90
#define OP sar
91
#include "test-i386-shift.h"
92

    
93
#define OP rol
94
#include "test-i386-shift.h"
95

    
96
#define OP ror
97
#include "test-i386-shift.h"
98

    
99
#define OP rcr
100
#define OP_CC
101
#include "test-i386-shift.h"
102

    
103
#define OP rcl
104
#define OP_CC
105
#include "test-i386-shift.h"
106

    
107
#define OP shld
108
#define OP_SHIFTD
109
#define OP_NOBYTE
110
#include "test-i386-shift.h"
111

    
112
#define OP shrd
113
#define OP_SHIFTD
114
#define OP_NOBYTE
115
#include "test-i386-shift.h"
116

    
117
/* XXX: should be more precise ? */
118
#undef CC_MASK
119
#define CC_MASK (CC_C)
120

    
121
#define OP bt
122
#define OP_NOBYTE
123
#include "test-i386-shift.h"
124

    
125
#define OP bts
126
#define OP_NOBYTE
127
#include "test-i386-shift.h"
128

    
129
#define OP btr
130
#define OP_NOBYTE
131
#include "test-i386-shift.h"
132

    
133
#define OP btc
134
#define OP_NOBYTE
135
#include "test-i386-shift.h"
136

    
137
/* lea test (modrm support) */
138
#define TEST_LEA(STR)\
139
{\
140
    asm("leal " STR ", %0"\
141
        : "=r" (res)\
142
        : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
143
    printf("lea %s = %08x\n", STR, res);\
144
}
145

    
146
#define TEST_LEA16(STR)\
147
{\
148
    asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\
149
        : "=wq" (res)\
150
        : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
151
    printf("lea %s = %08x\n", STR, res);\
152
}
153

    
154

    
155
void test_lea(void)
156
{
157
    int eax, ebx, ecx, edx, esi, edi, res;
158
    eax = 0x0001;
159
    ebx = 0x0002;
160
    ecx = 0x0004;
161
    edx = 0x0008;
162
    esi = 0x0010;
163
    edi = 0x0020;
164

    
165
    TEST_LEA("0x4000");
166

    
167
    TEST_LEA("(%%eax)");
168
    TEST_LEA("(%%ebx)");
169
    TEST_LEA("(%%ecx)");
170
    TEST_LEA("(%%edx)");
171
    TEST_LEA("(%%esi)");
172
    TEST_LEA("(%%edi)");
173

    
174
    TEST_LEA("0x40(%%eax)");
175
    TEST_LEA("0x40(%%ebx)");
176
    TEST_LEA("0x40(%%ecx)");
177
    TEST_LEA("0x40(%%edx)");
178
    TEST_LEA("0x40(%%esi)");
179
    TEST_LEA("0x40(%%edi)");
180

    
181
    TEST_LEA("0x4000(%%eax)");
182
    TEST_LEA("0x4000(%%ebx)");
183
    TEST_LEA("0x4000(%%ecx)");
184
    TEST_LEA("0x4000(%%edx)");
185
    TEST_LEA("0x4000(%%esi)");
186
    TEST_LEA("0x4000(%%edi)");
187

    
188
    TEST_LEA("(%%eax, %%ecx)");
189
    TEST_LEA("(%%ebx, %%edx)");
190
    TEST_LEA("(%%ecx, %%ecx)");
191
    TEST_LEA("(%%edx, %%ecx)");
192
    TEST_LEA("(%%esi, %%ecx)");
193
    TEST_LEA("(%%edi, %%ecx)");
194

    
195
    TEST_LEA("0x40(%%eax, %%ecx)");
196
    TEST_LEA("0x4000(%%ebx, %%edx)");
197

    
198
    TEST_LEA("(%%ecx, %%ecx, 2)");
199
    TEST_LEA("(%%edx, %%ecx, 4)");
200
    TEST_LEA("(%%esi, %%ecx, 8)");
201

    
202
    TEST_LEA("(,%%eax, 2)");
203
    TEST_LEA("(,%%ebx, 4)");
204
    TEST_LEA("(,%%ecx, 8)");
205

    
206
    TEST_LEA("0x40(,%%eax, 2)");
207
    TEST_LEA("0x40(,%%ebx, 4)");
208
    TEST_LEA("0x40(,%%ecx, 8)");
209

    
210

    
211
    TEST_LEA("-10(%%ecx, %%ecx, 2)");
212
    TEST_LEA("-10(%%edx, %%ecx, 4)");
213
    TEST_LEA("-10(%%esi, %%ecx, 8)");
214

    
215
    TEST_LEA("0x4000(%%ecx, %%ecx, 2)");
216
    TEST_LEA("0x4000(%%edx, %%ecx, 4)");
217
    TEST_LEA("0x4000(%%esi, %%ecx, 8)");
218

    
219
    /* limited 16 bit addressing test */
220
    TEST_LEA16("0x4000");
221
    TEST_LEA16("(%%bx)");
222
    TEST_LEA16("(%%si)");
223
    TEST_LEA16("(%%di)");
224
    TEST_LEA16("0x40(%%bx)");
225
    TEST_LEA16("0x40(%%si)");
226
    TEST_LEA16("0x40(%%di)");
227
    TEST_LEA16("0x4000(%%bx)");
228
    TEST_LEA16("0x4000(%%si)");
229
    TEST_LEA16("(%%bx,%%si)");
230
    TEST_LEA16("(%%bx,%%di)");
231
    TEST_LEA16("0x40(%%bx,%%si)");
232
    TEST_LEA16("0x40(%%bx,%%di)");
233
    TEST_LEA16("0x4000(%%bx,%%si)");
234
    TEST_LEA16("0x4000(%%bx,%%di)");
235
}
236

    
237
#define TEST_JCC(JCC, v1, v2)\
238
{\
239
    int res;\
240
    asm("movl $1, %0\n\t"\
241
        "cmpl %2, %1\n\t"\
242
        "j" JCC " 1f\n\t"\
243
        "movl $0, %0\n\t"\
244
        "1:\n\t"\
245
        : "=r" (res)\
246
        : "r" (v1), "r" (v2));\
247
    printf("%-10s %d\n", "j" JCC, res);\
248
\
249
    asm("movl $0, %0\n\t"\
250
        "cmpl %2, %1\n\t"\
251
        "set" JCC " %b0\n\t"\
252
        : "=r" (res)\
253
        : "r" (v1), "r" (v2));\
254
    printf("%-10s %d\n", "set" JCC, res);\
255
 if (TEST_CMOV) {\
256
    asm("movl $0x12345678, %0\n\t"\
257
        "cmpl %2, %1\n\t"\
258
        "cmov" JCC "l %3, %0\n\t"\
259
        : "=r" (res)\
260
        : "r" (v1), "r" (v2), "m" (1));\
261
        printf("%-10s R=0x%08x\n", "cmov" JCC "l", res);\
262
    asm("movl $0x12345678, %0\n\t"\
263
        "cmpl %2, %1\n\t"\
264
        "cmov" JCC "w %w3, %w0\n\t"\
265
        : "=r" (res)\
266
        : "r" (v1), "r" (v2), "r" (1));\
267
        printf("%-10s R=0x%08x\n", "cmov" JCC "w", res);\
268
 } \
269
}
270

    
271
/* various jump tests */
272
void test_jcc(void)
273
{
274
    TEST_JCC("ne", 1, 1);
275
    TEST_JCC("ne", 1, 0);
276

    
277
    TEST_JCC("e", 1, 1);
278
    TEST_JCC("e", 1, 0);
279

    
280
    TEST_JCC("l", 1, 1);
281
    TEST_JCC("l", 1, 0);
282
    TEST_JCC("l", 1, -1);
283

    
284
    TEST_JCC("le", 1, 1);
285
    TEST_JCC("le", 1, 0);
286
    TEST_JCC("le", 1, -1);
287

    
288
    TEST_JCC("ge", 1, 1);
289
    TEST_JCC("ge", 1, 0);
290
    TEST_JCC("ge", -1, 1);
291

    
292
    TEST_JCC("g", 1, 1);
293
    TEST_JCC("g", 1, 0);
294
    TEST_JCC("g", 1, -1);
295

    
296
    TEST_JCC("b", 1, 1);
297
    TEST_JCC("b", 1, 0);
298
    TEST_JCC("b", 1, -1);
299

    
300
    TEST_JCC("be", 1, 1);
301
    TEST_JCC("be", 1, 0);
302
    TEST_JCC("be", 1, -1);
303

    
304
    TEST_JCC("ae", 1, 1);
305
    TEST_JCC("ae", 1, 0);
306
    TEST_JCC("ae", 1, -1);
307

    
308
    TEST_JCC("a", 1, 1);
309
    TEST_JCC("a", 1, 0);
310
    TEST_JCC("a", 1, -1);
311

    
312

    
313
    TEST_JCC("p", 1, 1);
314
    TEST_JCC("p", 1, 0);
315

    
316
    TEST_JCC("np", 1, 1);
317
    TEST_JCC("np", 1, 0);
318

    
319
    TEST_JCC("o", 0x7fffffff, 0);
320
    TEST_JCC("o", 0x7fffffff, -1);
321

    
322
    TEST_JCC("no", 0x7fffffff, 0);
323
    TEST_JCC("no", 0x7fffffff, -1);
324

    
325
    TEST_JCC("s", 0, 1);
326
    TEST_JCC("s", 0, -1);
327
    TEST_JCC("s", 0, 0);
328

    
329
    TEST_JCC("ns", 0, 1);
330
    TEST_JCC("ns", 0, -1);
331
    TEST_JCC("ns", 0, 0);
332
}
333

    
334
#undef CC_MASK
335
#define CC_MASK (CC_O | CC_C)
336

    
337
#define OP mul
338
#include "test-i386-muldiv.h"
339

    
340
#define OP imul
341
#include "test-i386-muldiv.h"
342

    
343
#undef CC_MASK
344
#define CC_MASK (0)
345

    
346
#define OP div
347
#include "test-i386-muldiv.h"
348

    
349
#define OP idiv
350
#include "test-i386-muldiv.h"
351

    
352
void test_imulw2(int op0, int op1) 
353
{
354
    int res, s1, s0, flags;
355
    s0 = op0;
356
    s1 = op1;
357
    res = s0;
358
    flags = 0;
359
    asm ("push %4\n\t"
360
         "popf\n\t"
361
         "imulw %w2, %w0\n\t" 
362
         "pushf\n\t"
363
         "popl %1\n\t"
364
         : "=q" (res), "=g" (flags)
365
         : "q" (s1), "0" (res), "1" (flags));
366
    printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
367
           "imulw", s0, s1, res, flags & CC_MASK);
368
}
369

    
370
void test_imull2(int op0, int op1) 
371
{
372
    int res, s1, s0, flags;
373
    s0 = op0;
374
    s1 = op1;
375
    res = s0;
376
    flags = 0;
377
    asm ("push %4\n\t"
378
         "popf\n\t"
379
         "imull %2, %0\n\t" 
380
         "pushf\n\t"
381
         "popl %1\n\t"
382
         : "=q" (res), "=g" (flags)
383
         : "q" (s1), "0" (res), "1" (flags));
384
    printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
385
           "imull", s0, s1, res, flags & CC_MASK);
386
}
387

    
388
void test_mul(void)
389
{
390
    test_imulb(0x1234561d, 4);
391
    test_imulb(3, -4);
392
    test_imulb(0x80, 0x80);
393
    test_imulb(0x10, 0x10);
394

    
395
    test_imulw(0, 0x1234001d, 45);
396
    test_imulw(0, 23, -45);
397
    test_imulw(0, 0x8000, 0x8000);
398
    test_imulw(0, 0x100, 0x100);
399

    
400
    test_imull(0, 0x1234001d, 45);
401
    test_imull(0, 23, -45);
402
    test_imull(0, 0x80000000, 0x80000000);
403
    test_imull(0, 0x10000, 0x10000);
404

    
405
    test_mulb(0x1234561d, 4);
406
    test_mulb(3, -4);
407
    test_mulb(0x80, 0x80);
408
    test_mulb(0x10, 0x10);
409

    
410
    test_mulw(0, 0x1234001d, 45);
411
    test_mulw(0, 23, -45);
412
    test_mulw(0, 0x8000, 0x8000);
413
    test_mulw(0, 0x100, 0x100);
414

    
415
    test_mull(0, 0x1234001d, 45);
416
    test_mull(0, 23, -45);
417
    test_mull(0, 0x80000000, 0x80000000);
418
    test_mull(0, 0x10000, 0x10000);
419

    
420
    test_imulw2(0x1234001d, 45);
421
    test_imulw2(23, -45);
422
    test_imulw2(0x8000, 0x8000);
423
    test_imulw2(0x100, 0x100);
424

    
425
    test_imull2(0x1234001d, 45);
426
    test_imull2(23, -45);
427
    test_imull2(0x80000000, 0x80000000);
428
    test_imull2(0x10000, 0x10000);
429

    
430
    test_idivb(0x12341678, 0x127e);
431
    test_idivb(0x43210123, -5);
432
    test_idivb(0x12340004, -1);
433

    
434
    test_idivw(0, 0x12345678, 12347);
435
    test_idivw(0, -23223, -45);
436
    test_idivw(0, 0x12348000, -1);
437
    test_idivw(0x12343, 0x12345678, 0x81238567);
438

    
439
    test_idivl(0, 0x12345678, 12347);
440
    test_idivl(0, -233223, -45);
441
    test_idivl(0, 0x80000000, -1);
442
    test_idivl(0x12343, 0x12345678, 0x81234567);
443

    
444
    test_divb(0x12341678, 0x127e);
445
    test_divb(0x43210123, -5);
446
    test_divb(0x12340004, -1);
447

    
448
    test_divw(0, 0x12345678, 12347);
449
    test_divw(0, -23223, -45);
450
    test_divw(0, 0x12348000, -1);
451
    test_divw(0x12343, 0x12345678, 0x81238567);
452

    
453
    test_divl(0, 0x12345678, 12347);
454
    test_divl(0, -233223, -45);
455
    test_divl(0, 0x80000000, -1);
456
    test_divl(0x12343, 0x12345678, 0x81234567);
457
}
458

    
459
#define TEST_BSX(op, size, op0)\
460
{\
461
    int res, val, resz;\
462
    val = op0;\
463
    asm("xorl %1, %1 ; " #op " %" size "2, %" size "0 ; setz %b1" \
464
        : "=r" (res), "=q" (resz)\
465
        : "g" (val));\
466
    printf("%-10s A=%08x R=%08x %d\n", #op, val, resz ? 0 : res, resz);\
467
}
468

    
469
void test_bsx(void)
470
{
471
    TEST_BSX(bsrw, "w", 0);
472
    TEST_BSX(bsrw, "w", 0x12340128);
473
    TEST_BSX(bsrl, "", 0);
474
    TEST_BSX(bsrl, "", 0x00340128);
475
    TEST_BSX(bsfw, "w", 0);
476
    TEST_BSX(bsfw, "w", 0x12340128);
477
    TEST_BSX(bsfl, "", 0);
478
    TEST_BSX(bsfl, "", 0x00340128);
479
}
480

    
481
/**********************************************/
482

    
483
void test_fops(double a, double b)
484
{
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 a*b=%f\n", a, b, a * b);
488
    printf("a=%f b=%f a/b=%f\n", a, b, a / b);
489
    printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b));
490
    printf("a=%f sqrt(a)=%f\n", a, sqrt(a));
491
    printf("a=%f sin(a)=%f\n", a, sin(a));
492
    printf("a=%f cos(a)=%f\n", a, cos(a));
493
    printf("a=%f tan(a)=%f\n", a, tan(a));
494
    printf("a=%f log(a)=%f\n", a, log(a));
495
    printf("a=%f exp(a)=%f\n", a, exp(a));
496
    printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
497
    /* just to test some op combining */
498
    printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a)));
499
    printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a)));
500
    printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));
501

    
502
}
503

    
504
void test_fcmp(double a, double b)
505
{
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);
514
    printf("(%f<=%f)=%d\n",
515
           a, b, a >= b);
516
    if (TEST_FCOMI) {
517
        unsigned int eflags;
518
        /* test f(u)comi instruction */
519
        asm("fcomi %2, %1\n"
520
            "pushf\n"
521
            "pop %0\n"
522
            : "=r" (eflags)
523
            : "t" (a), "u" (b));
524
        printf("fcomi(%f %f)=%08x\n", a, b, eflags & (CC_Z | CC_P | CC_C));
525
    }
526
}
527

    
528
void test_fcvt(double a)
529
{
530
    float fa;
531
    long double la;
532
    int16_t fpuc;
533
    int i;
534
    int64_t lla;
535
    int ia;
536
    int16_t wa;
537
    double ra;
538

    
539
    fa = a;
540
    la = a;
541
    printf("(float)%f = %f\n", a, fa);
542
    printf("(long double)%f = %Lf\n", a, la);
543
    printf("a=%016Lx\n", *(long long *)&a);
544
    printf("la=%016Lx %04x\n", *(long long *)&la, 
545
           *(unsigned short *)((char *)(&la) + 8));
546

    
547
    /* test all roundings */
548
    asm volatile ("fstcw %0" : "=m" (fpuc));
549
    for(i=0;i<4;i++) {
550
        asm volatile ("fldcw %0" : : "m" ((fpuc & ~0x0c00) | (i << 10)));
551
        asm volatile ("fist %0" : "=m" (wa) : "t" (a));
552
        asm volatile ("fistl %0" : "=m" (ia) : "t" (a));
553
        asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st");
554
        asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a));
555
        asm volatile ("fldcw %0" : : "m" (fpuc));
556
        printf("(short)a = %d\n", wa);
557
        printf("(int)a = %d\n", ia);
558
        printf("(int64_t)a = %Ld\n", lla);
559
        printf("rint(a) = %f\n", ra);
560
    }
561
}
562

    
563
#define TEST(N) \
564
    asm("fld" #N : "=t" (a)); \
565
    printf("fld" #N "= %f\n", a);
566

    
567
void test_fconst(void)
568
{
569
    double a;
570
    TEST(1);
571
    TEST(l2t);
572
    TEST(l2e);
573
    TEST(pi);
574
    TEST(lg2);
575
    TEST(ln2);
576
    TEST(z);
577
}
578

    
579
void test_fbcd(double a)
580
{
581
    unsigned short bcd[5];
582
    double b;
583

    
584
    asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st");
585
    asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
586
    printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n", 
587
           a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);
588
}
589

    
590
#define TEST_ENV(env, prefix)\
591
{\
592
    memset((env), 0xaa, sizeof(*(env)));\
593
    asm("fld1\n"\
594
        prefix "fnstenv %1\n"\
595
        prefix "fldenv %1\n"\
596
        : "=t" (res) : "m" (*(env)));\
597
    printf("res=%f\n", res);\
598
    printf("fpuc=%04x fpus=%04x fptag=%04x\n",\
599
           (env)->fpuc,\
600
           (env)->fpus & 0xff00,\
601
           (env)->fptag);\
602
    memset((env), 0xaa, sizeof(*(env)));\
603
    asm("fld1\n"\
604
        prefix "fnsave %1\n"\
605
        prefix "frstor %1\n"\
606
        : "=t" (res) : "m" (*(env)));\
607
    printf("res=%f\n", res);\
608
    printf("fpuc=%04x fpus=%04x fptag=%04x\n",\
609
           (env)->fpuc,\
610
           (env)->fpus & 0xff00,\
611
           (env)->fptag);\
612
    printf("ST(0) = %Lf\n",\
613
           (env)->fpregs[0]);\
614
}
615

    
616
void test_fenv(void)
617
{
618
    struct __attribute__((packed)) {
619
        uint16_t fpuc;
620
        uint16_t dummy1;
621
        uint16_t fpus;
622
        uint16_t dummy2;
623
        uint16_t fptag;
624
        uint16_t dummy3;
625
        uint32_t ignored[4];
626
        long double fpregs[8];
627
    } float_env32;
628
    struct __attribute__((packed)) {
629
        uint16_t fpuc;
630
        uint16_t fpus;
631
        uint16_t fptag;
632
        uint16_t ignored[4];
633
        long double fpregs[8];
634
    } float_env16;
635
    double res;
636

    
637
    TEST_ENV(&float_env16, "data16 ");
638
    TEST_ENV(&float_env32, "");
639
}
640

    
641
void test_floats(void)
642
{
643
    test_fops(2, 3);
644
    test_fops(1.4, -5);
645
    test_fcmp(2, -1);
646
    test_fcmp(2, 2);
647
    test_fcmp(2, 3);
648
    test_fcvt(0.5);
649
    test_fcvt(-0.5);
650
    test_fcvt(1.0/7.0);
651
    test_fcvt(-1.0/9.0);
652
    test_fcvt(32768);
653
    test_fcvt(-1e20);
654
    test_fconst();
655
    test_fbcd(1234567890123456);
656
    test_fbcd(-123451234567890);
657
    test_fenv();
658
}
659

    
660
/**********************************************/
661

    
662
#define TEST_BCD(op, op0, cc_in, cc_mask)\
663
{\
664
    int res, flags;\
665
    res = op0;\
666
    flags = cc_in;\
667
    asm ("push %3\n\t"\
668
         "popf\n\t"\
669
         #op "\n\t"\
670
         "pushf\n\t"\
671
         "popl %1\n\t"\
672
        : "=a" (res), "=g" (flags)\
673
        : "0" (res), "1" (flags));\
674
    printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\
675
           #op, op0, res, cc_in, flags & cc_mask);\
676
}
677

    
678
void test_bcd(void)
679
{
680
    TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
681
    TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
682
    TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
683
    TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
684
    TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
685
    TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
686
    TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
687
    TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
688
    TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
689
    TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
690
    TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
691
    TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
692
    TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
693

    
694
    TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
695
    TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
696
    TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
697
    TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
698
    TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
699
    TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
700
    TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
701
    TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
702
    TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
703
    TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
704
    TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
705
    TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
706
    TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
707

    
708
    TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A));
709
    TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A));
710
    TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A));
711
    TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A));
712
    TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A));
713
    TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A));
714
    TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A));
715
    TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A));
716
    
717
    TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A));
718
    TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A));
719
    TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A));
720
    TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A));
721
    TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A));
722
    TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A));
723
    TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A));
724
    TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A));
725

    
726
    TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
727
    TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
728
}
729

    
730
#define TEST_XCHG(op, size, opconst)\
731
{\
732
    int op0, op1;\
733
    op0 = 0x12345678;\
734
    op1 = 0xfbca7654;\
735
    asm(#op " %" size "0, %" size "1" \
736
        : "=q" (op0), opconst (op1) \
737
        : "0" (op0), "1" (op1));\
738
    printf("%-10s A=%08x B=%08x\n",\
739
           #op, op0, op1);\
740
}
741

    
742
#define TEST_CMPXCHG(op, size, opconst, eax)\
743
{\
744
    int op0, op1;\
745
    op0 = 0x12345678;\
746
    op1 = 0xfbca7654;\
747
    asm(#op " %" size "0, %" size "1" \
748
        : "=q" (op0), opconst (op1) \
749
        : "0" (op0), "1" (op1), "a" (eax));\
750
    printf("%-10s EAX=%08x A=%08x C=%08x\n",\
751
           #op, eax, op0, op1);\
752
}
753

    
754
void test_xchg(void)
755
{
756
    TEST_XCHG(xchgl, "", "=q");
757
    TEST_XCHG(xchgw, "w", "=q");
758
    TEST_XCHG(xchgb, "b", "=q");
759

    
760
    TEST_XCHG(xchgl, "", "=m");
761
    TEST_XCHG(xchgw, "w", "=m");
762
    TEST_XCHG(xchgb, "b", "=m");
763

    
764
    TEST_XCHG(xaddl, "", "=q");
765
    TEST_XCHG(xaddw, "w", "=q");
766
    TEST_XCHG(xaddb, "b", "=q");
767

    
768
    TEST_XCHG(xaddl, "", "=m");
769
    TEST_XCHG(xaddw, "w", "=m");
770
    TEST_XCHG(xaddb, "b", "=m");
771

    
772
    TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfbca7654);
773
    TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfbca7654);
774
    TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfbca7654);
775

    
776
    TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfffefdfc);
777
    TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfffefdfc);
778
    TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfffefdfc);
779

    
780
    TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfbca7654);
781
    TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfbca7654);
782
    TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfbca7654);
783

    
784
    TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfffefdfc);
785
    TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfffefdfc);
786
    TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfffefdfc);
787
}
788

    
789
/**********************************************/
790
/* segmentation tests */
791

    
792
#include <asm/ldt.h>
793
#include <linux/unistd.h>
794

    
795
_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
796

    
797
uint8_t seg_data1[4096];
798
uint8_t seg_data2[4096];
799

    
800
#define MK_SEL(n) (((n) << 3) | 7)
801

    
802
#define TEST_LR(op, size, seg, mask)\
803
{\
804
    int res, res2;\
805
    res = 0x12345678;\
806
    asm (op " %" size "2, %" size "0\n" \
807
         "movl $0, %1\n"\
808
         "jnz 1f\n"\
809
         "movl $1, %1\n"\
810
         "1:\n"\
811
         : "=r" (res), "=r" (res2) : "m" (seg), "0" (res));\
812
    printf(op ": Z=%d %08x\n", res2, res & ~(mask));\
813
}
814

    
815
/* NOTE: we use Linux modify_ldt syscall */
816
void test_segs(void)
817
{
818
    struct modify_ldt_ldt_s ldt;
819
    long long ldt_table[3];
820
    int res, res2;
821
    char tmp;
822
    struct {
823
        uint32_t offset;
824
        uint16_t seg;
825
    } __attribute__((packed)) segoff;
826

    
827
    ldt.entry_number = 1;
828
    ldt.base_addr = (unsigned long)&seg_data1;
829
    ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
830
    ldt.seg_32bit = 1;
831
    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
832
    ldt.read_exec_only = 0;
833
    ldt.limit_in_pages = 1;
834
    ldt.seg_not_present = 0;
835
    ldt.useable = 1;
836
    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
837

    
838
    ldt.entry_number = 2;
839
    ldt.base_addr = (unsigned long)&seg_data2;
840
    ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12;
841
    ldt.seg_32bit = 1;
842
    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
843
    ldt.read_exec_only = 0;
844
    ldt.limit_in_pages = 1;
845
    ldt.seg_not_present = 0;
846
    ldt.useable = 1;
847
    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
848

    
849
    modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */
850
#if 0
851
    {
852
        int i;
853
        for(i=0;i<3;i++)
854
            printf("%d: %016Lx\n", i, ldt_table[i]);
855
    }
856
#endif
857
    /* do some tests with fs or gs */
858
    asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
859

    
860
    seg_data1[1] = 0xaa;
861
    seg_data2[1] = 0x55;
862

    
863
    asm volatile ("fs movzbl 0x1, %0" : "=r" (res));
864
    printf("FS[1] = %02x\n", res);
865

    
866
    asm volatile ("pushl %%gs\n"
867
                  "movl %1, %%gs\n"
868
                  "gs movzbl 0x1, %0\n"
869
                  "popl %%gs\n"
870
                  : "=r" (res)
871
                  : "r" (MK_SEL(2)));
872
    printf("GS[1] = %02x\n", res);
873

    
874
    /* tests with ds/ss (implicit segment case) */
875
    tmp = 0xa5;
876
    asm volatile ("pushl %%ebp\n\t"
877
                  "pushl %%ds\n\t"
878
                  "movl %2, %%ds\n\t"
879
                  "movl %3, %%ebp\n\t"
880
                  "movzbl 0x1, %0\n\t"
881
                  "movzbl (%%ebp), %1\n\t"
882
                  "popl %%ds\n\t"
883
                  "popl %%ebp\n\t"
884
                  : "=r" (res), "=r" (res2)
885
                  : "r" (MK_SEL(1)), "r" (&tmp));
886
    printf("DS[1] = %02x\n", res);
887
    printf("SS[tmp] = %02x\n", res2);
888

    
889
    segoff.seg = MK_SEL(2);
890
    segoff.offset = 0xabcdef12;
891
    asm volatile("lfs %2, %0\n\t" 
892
                 "movl %%fs, %1\n\t"
893
                 : "=r" (res), "=g" (res2) 
894
                 : "m" (segoff));
895
    printf("FS:reg = %04x:%08x\n", res2, res);
896

    
897
    TEST_LR("larw", "w", MK_SEL(2), 0x0100);
898
    TEST_LR("larl", "", MK_SEL(2), 0x0100);
899
    TEST_LR("lslw", "w", MK_SEL(2), 0);
900
    TEST_LR("lsll", "", MK_SEL(2), 0);
901

    
902
    TEST_LR("larw", "w", 0xfff8, 0);
903
    TEST_LR("larl", "", 0xfff8, 0);
904
    TEST_LR("lslw", "w", 0xfff8, 0);
905
    TEST_LR("lsll", "", 0xfff8, 0);
906
}
907

    
908
/* 16 bit code test */
909
extern char code16_start, code16_end;
910
extern char code16_func1;
911
extern char code16_func2;
912
extern char code16_func3;
913

    
914
void test_code16(void)
915
{
916
    struct modify_ldt_ldt_s ldt;
917
    int res, res2;
918

    
919
    /* build a code segment */
920
    ldt.entry_number = 1;
921
    ldt.base_addr = (unsigned long)&code16_start;
922
    ldt.limit = &code16_end - &code16_start;
923
    ldt.seg_32bit = 0;
924
    ldt.contents = MODIFY_LDT_CONTENTS_CODE;
925
    ldt.read_exec_only = 0;
926
    ldt.limit_in_pages = 0;
927
    ldt.seg_not_present = 0;
928
    ldt.useable = 1;
929
    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
930

    
931
    /* call the first function */
932
    asm volatile ("lcall %1, %2" 
933
                  : "=a" (res)
934
                  : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc");
935
    printf("func1() = 0x%08x\n", res);
936
    asm volatile ("lcall %2, %3" 
937
                  : "=a" (res), "=c" (res2)
938
                  : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc");
939
    printf("func2() = 0x%08x spdec=%d\n", res, res2);
940
    asm volatile ("lcall %1, %2" 
941
                  : "=a" (res)
942
                  : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc");
943
    printf("func3() = 0x%08x\n", res);
944
}
945

    
946
extern char func_lret32;
947
extern char func_iret32;
948

    
949
void test_misc(void)
950
{
951
    char table[256];
952
    int res, i;
953

    
954
    for(i=0;i<256;i++) table[i] = 256 - i;
955
    res = 0x12345678;
956
    asm ("xlat" : "=a" (res) : "b" (table), "0" (res));
957
    printf("xlat: EAX=%08x\n", res);
958

    
959
    asm volatile ("pushl %%cs ; call %1" 
960
                  : "=a" (res)
961
                  : "m" (func_lret32): "memory", "cc");
962
    printf("func_lret32=%x\n", res);
963

    
964
    asm volatile ("pushfl ; pushl %%cs ; call %1" 
965
                  : "=a" (res)
966
                  : "m" (func_iret32): "memory", "cc");
967
    printf("func_iret32=%x\n", res);
968

    
969
    /* specific popl test */
970
    asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popl (%%esp) ; popl %0"
971
                  : "=g" (res));
972
    printf("popl esp=%x\n", res);
973

    
974
    /* specific popw test */
975
    asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popw (%%esp) ; addl $2, %%esp ; popl %0"
976
                  : "=g" (res));
977
    printf("popw esp=%x\n", res);
978
}
979

    
980
uint8_t str_buffer[4096];
981

    
982
#define TEST_STRING1(OP, size, DF, REP)\
983
{\
984
    int esi, edi, eax, ecx, eflags;\
985
\
986
    esi = (long)(str_buffer + sizeof(str_buffer) / 2);\
987
    edi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\
988
    eax = 0x12345678;\
989
    ecx = 17;\
990
\
991
    asm volatile ("pushl $0\n\t"\
992
                  "popf\n\t"\
993
                  DF "\n\t"\
994
                  REP #OP size "\n\t"\
995
                  "cld\n\t"\
996
                  "pushf\n\t"\
997
                  "popl %4\n\t"\
998
                  : "=S" (esi), "=D" (edi), "=a" (eax), "=c" (ecx), "=g" (eflags)\
999
                  : "0" (esi), "1" (edi), "2" (eax), "3" (ecx));\
1000
    printf("%-10s ESI=%08x EDI=%08x EAX=%08x ECX=%08x EFL=%04x\n",\
1001
           REP #OP size, esi, edi, eax, ecx,\
1002
           eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\
1003
}
1004

    
1005
#define TEST_STRING(OP, REP)\
1006
    TEST_STRING1(OP, "b", "", REP);\
1007
    TEST_STRING1(OP, "w", "", REP);\
1008
    TEST_STRING1(OP, "l", "", REP);\
1009
    TEST_STRING1(OP, "b", "std", REP);\
1010
    TEST_STRING1(OP, "w", "std", REP);\
1011
    TEST_STRING1(OP, "l", "std", REP)
1012

    
1013
void test_string(void)
1014
{
1015
    int i;
1016
    for(i = 0;i < sizeof(str_buffer); i++)
1017
        str_buffer[i] = i + 0x56;
1018
   TEST_STRING(stos, "");
1019
   TEST_STRING(stos, "rep ");
1020
   TEST_STRING(lods, ""); /* to verify stos */
1021
   TEST_STRING(lods, "rep "); 
1022
   TEST_STRING(movs, "");
1023
   TEST_STRING(movs, "rep ");
1024
   TEST_STRING(lods, ""); /* to verify stos */
1025

    
1026
   /* XXX: better tests */
1027
   TEST_STRING(scas, "");
1028
   TEST_STRING(scas, "repz ");
1029
   TEST_STRING(scas, "repnz ");
1030
   TEST_STRING(cmps, "");
1031
   TEST_STRING(cmps, "repz ");
1032
   TEST_STRING(cmps, "repnz ");
1033
}
1034

    
1035
/* VM86 test */
1036

    
1037
static inline void set_bit(uint8_t *a, unsigned int bit)
1038
{
1039
    a[bit / 8] |= (1 << (bit % 8));
1040
}
1041

    
1042
static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
1043
{
1044
    return (uint8_t *)((seg << 4) + (reg & 0xffff));
1045
}
1046

    
1047
static inline void pushw(struct vm86_regs *r, int val)
1048
{
1049
    r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
1050
    *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
1051
}
1052

    
1053
#undef __syscall_return
1054
#define __syscall_return(type, res) \
1055
do { \
1056
        return (type) (res); \
1057
} while (0)
1058

    
1059
_syscall2(int, vm86, int, func, struct vm86plus_struct *, v86)
1060

    
1061
extern char vm86_code_start;
1062
extern char vm86_code_end;
1063

    
1064
#define VM86_CODE_CS 0x100
1065
#define VM86_CODE_IP 0x100
1066

    
1067
void test_vm86(void)
1068
{
1069
    struct vm86plus_struct ctx;
1070
    struct vm86_regs *r;
1071
    uint8_t *vm86_mem;
1072
    int seg, ret;
1073

    
1074
    vm86_mem = mmap((void *)0x00000000, 0x110000, 
1075
                    PROT_WRITE | PROT_READ | PROT_EXEC, 
1076
                    MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
1077
    if (vm86_mem == MAP_FAILED) {
1078
        printf("ERROR: could not map vm86 memory");
1079
        return;
1080
    }
1081
    memset(&ctx, 0, sizeof(ctx));
1082

    
1083
    /* init basic registers */
1084
    r = &ctx.regs;
1085
    r->eip = VM86_CODE_IP;
1086
    r->esp = 0xfffe;
1087
    seg = VM86_CODE_CS;
1088
    r->cs = seg;
1089
    r->ss = seg;
1090
    r->ds = seg;
1091
    r->es = seg;
1092
    r->fs = seg;
1093
    r->gs = seg;
1094
    r->eflags = VIF_MASK;
1095

    
1096
    /* move code to proper address. We use the same layout as a .com
1097
       dos program. */
1098
    memcpy(vm86_mem + (VM86_CODE_CS << 4) + VM86_CODE_IP, 
1099
           &vm86_code_start, &vm86_code_end - &vm86_code_start);
1100

    
1101
    /* mark int 0x21 as being emulated */
1102
    set_bit((uint8_t *)&ctx.int_revectored, 0x21);
1103

    
1104
    for(;;) {
1105
        ret = vm86(VM86_ENTER, &ctx);
1106
        switch(VM86_TYPE(ret)) {
1107
        case VM86_INTx:
1108
            {
1109
                int int_num, ah;
1110
                
1111
                int_num = VM86_ARG(ret);
1112
                if (int_num != 0x21)
1113
                    goto unknown_int;
1114
                ah = (r->eax >> 8) & 0xff;
1115
                switch(ah) {
1116
                case 0x00: /* exit */
1117
                    goto the_end;
1118
                case 0x02: /* write char */
1119
                    {
1120
                        uint8_t c = r->edx;
1121
                        putchar(c);
1122
                    }
1123
                    break;
1124
                case 0x09: /* write string */
1125
                    {
1126
                        uint8_t c, *ptr;
1127
                        ptr = seg_to_linear(r->ds, r->edx);
1128
                        for(;;) {
1129
                            c = *ptr++;
1130
                            if (c == '$')
1131
                                break;
1132
                            putchar(c);
1133
                        }
1134
                        r->eax = (r->eax & ~0xff) | '$';
1135
                    }
1136
                    break;
1137
                case 0xff: /* extension: write hex number in edx */
1138
                    printf("%08x\n", (int)r->edx);
1139
                    break;
1140
                default:
1141
                unknown_int:
1142
                    printf("unsupported int 0x%02x\n", int_num);
1143
                    goto the_end;
1144
                }
1145
            }
1146
            break;
1147
        case VM86_SIGNAL:
1148
            /* a signal came, we just ignore that */
1149
            break;
1150
        case VM86_STI:
1151
            break;
1152
        default:
1153
            printf("ERROR: unhandled vm86 return code (0x%x)\n", ret);
1154
            goto the_end;
1155
        }
1156
    }
1157
 the_end:
1158
    printf("VM86 end\n");
1159
    munmap(vm86_mem, 0x110000);
1160
}
1161

    
1162
/* exception tests */
1163
#ifndef REG_EAX
1164
#define REG_EAX EAX
1165
#define REG_EBX EBX
1166
#define REG_ECX ECX
1167
#define REG_EDX EDX
1168
#define REG_ESI ESI
1169
#define REG_EDI EDI
1170
#define REG_EBP EBP
1171
#define REG_ESP ESP
1172
#define REG_EIP EIP
1173
#define REG_EFL EFL
1174
#define REG_TRAPNO TRAPNO
1175
#define REG_ERR ERR
1176
#endif
1177

    
1178
jmp_buf jmp_env;
1179
int v1;
1180
int tab[2];
1181

    
1182
void sig_handler(int sig, siginfo_t *info, void *puc)
1183
{
1184
    struct ucontext *uc = puc;
1185

    
1186
    printf("si_signo=%d si_errno=%d si_code=%d",
1187
           info->si_signo, info->si_errno, info->si_code);
1188
    printf(" si_addr=0x%08lx",
1189
           (unsigned long)info->si_addr);
1190
    printf("\n");
1191

    
1192
    printf("trapno=0x%02x err=0x%08x",
1193
           uc->uc_mcontext.gregs[REG_TRAPNO],
1194
           uc->uc_mcontext.gregs[REG_ERR]);
1195
    printf(" EIP=0x%08x", uc->uc_mcontext.gregs[REG_EIP]);
1196
    printf("\n");
1197
    longjmp(jmp_env, 1);
1198
}
1199

    
1200
void test_exceptions(void)
1201
{
1202
    struct modify_ldt_ldt_s ldt;
1203
    struct sigaction act;
1204
    volatile int val;
1205
    
1206
    act.sa_sigaction = sig_handler;
1207
    sigemptyset(&act.sa_mask);
1208
    act.sa_flags = SA_SIGINFO;
1209
    sigaction(SIGFPE, &act, NULL);
1210
    sigaction(SIGILL, &act, NULL);
1211
    sigaction(SIGSEGV, &act, NULL);
1212
    sigaction(SIGBUS, &act, NULL);
1213
    sigaction(SIGTRAP, &act, NULL);
1214

    
1215
    /* test division by zero reporting */
1216
    printf("DIVZ exception:\n");
1217
    if (setjmp(jmp_env) == 0) {
1218
        /* now divide by zero */
1219
        v1 = 0;
1220
        v1 = 2 / v1;
1221
    }
1222

    
1223
    printf("BOUND exception:\n");
1224
    if (setjmp(jmp_env) == 0) {
1225
        /* bound exception */
1226
        tab[0] = 1;
1227
        tab[1] = 10;
1228
        asm volatile ("bound %0, %1" : : "r" (11), "m" (tab));
1229
    }
1230

    
1231
    printf("segment exceptions:\n");
1232
    if (setjmp(jmp_env) == 0) {
1233
        /* load an invalid segment */
1234
        asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 1));
1235
    }
1236
    if (setjmp(jmp_env) == 0) {
1237
        /* null data segment is valid */
1238
        asm volatile ("movl %0, %%fs" : : "r" (3));
1239
        /* null stack segment */
1240
        asm volatile ("movl %0, %%ss" : : "r" (3));
1241
    }
1242

    
1243
    ldt.entry_number = 1;
1244
    ldt.base_addr = (unsigned long)&seg_data1;
1245
    ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
1246
    ldt.seg_32bit = 1;
1247
    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
1248
    ldt.read_exec_only = 0;
1249
    ldt.limit_in_pages = 1;
1250
    ldt.seg_not_present = 1;
1251
    ldt.useable = 1;
1252
    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
1253

    
1254
    if (setjmp(jmp_env) == 0) {
1255
        /* segment not present */
1256
        asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
1257
    }
1258

    
1259
    /* test SEGV reporting */
1260
    printf("PF exception:\n");
1261
    if (setjmp(jmp_env) == 0) {
1262
        val = 1;
1263
        /* we add a nop to test a weird PC retrieval case */
1264
        asm volatile ("nop");
1265
        /* now store in an invalid address */
1266
        *(char *)0x1234 = 1;
1267
    }
1268

    
1269
    /* test SEGV reporting */
1270
    printf("PF exception:\n");
1271
    if (setjmp(jmp_env) == 0) {
1272
        val = 1;
1273
        /* read from an invalid address */
1274
        v1 = *(char *)0x1234;
1275
    }
1276
    
1277
    /* test illegal instruction reporting */
1278
    printf("UD2 exception:\n");
1279
    if (setjmp(jmp_env) == 0) {
1280
        /* now execute an invalid instruction */
1281
        asm volatile("ud2");
1282
    }
1283
    
1284
    printf("INT exception:\n");
1285
    if (setjmp(jmp_env) == 0) {
1286
        asm volatile ("int $0xfd");
1287
    }
1288
    if (setjmp(jmp_env) == 0) {
1289
        asm volatile ("int $0x01");
1290
    }
1291
    if (setjmp(jmp_env) == 0) {
1292
        asm volatile (".byte 0xcd, 0x03");
1293
    }
1294
    if (setjmp(jmp_env) == 0) {
1295
        asm volatile ("int $0x04");
1296
    }
1297
    if (setjmp(jmp_env) == 0) {
1298
        asm volatile ("int $0x05");
1299
    }
1300

    
1301
    printf("INT3 exception:\n");
1302
    if (setjmp(jmp_env) == 0) {
1303
        asm volatile ("int3");
1304
    }
1305

    
1306
    printf("CLI exception:\n");
1307
    if (setjmp(jmp_env) == 0) {
1308
        asm volatile ("cli");
1309
    }
1310

    
1311
    printf("STI exception:\n");
1312
    if (setjmp(jmp_env) == 0) {
1313
        asm volatile ("cli");
1314
    }
1315

    
1316
    printf("INTO exception:\n");
1317
    if (setjmp(jmp_env) == 0) {
1318
        /* overflow exception */
1319
        asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff));
1320
    }
1321

    
1322
    printf("OUTB exception:\n");
1323
    if (setjmp(jmp_env) == 0) {
1324
        asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0));
1325
    }
1326

    
1327
    printf("INB exception:\n");
1328
    if (setjmp(jmp_env) == 0) {
1329
        asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321));
1330
    }
1331

    
1332
    printf("REP OUTSB exception:\n");
1333
    if (setjmp(jmp_env) == 0) {
1334
        asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1));
1335
    }
1336

    
1337
    printf("REP INSB exception:\n");
1338
    if (setjmp(jmp_env) == 0) {
1339
        asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1));
1340
    }
1341

    
1342
    printf("HLT exception:\n");
1343
    if (setjmp(jmp_env) == 0) {
1344
        asm volatile ("hlt");
1345
    }
1346

    
1347
    printf("single step exception:\n");
1348
    val = 0;
1349
    if (setjmp(jmp_env) == 0) {
1350
        asm volatile ("pushf\n"
1351
                      "orl $0x00100, (%%esp)\n"
1352
                      "popf\n"
1353
                      "movl $0xabcd, %0\n" 
1354
                      "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory");
1355
    }
1356
    printf("val=0x%x\n", val);
1357
}
1358

    
1359
/* self modifying code test */
1360
uint8_t code[] = {
1361
    0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */
1362
    0xc3, /* ret */
1363
};
1364

    
1365
typedef int FuncType(void);
1366

    
1367
void test_self_modifying_code(void)
1368
{
1369
    int i;
1370

    
1371
    printf("self modifying code:\n");
1372
    printf("func1 = 0x%x\n", ((FuncType *)code)());
1373
    for(i = 2; i <= 4; i++) {
1374
        code[1] = i;
1375
        printf("func%d = 0x%x\n", i, ((FuncType *)code)());
1376
    }
1377
}
1378
    
1379
static void *call_end __init_call = NULL;
1380

    
1381
int main(int argc, char **argv)
1382
{
1383
    void **ptr;
1384
    void (*func)(void);
1385

    
1386
    ptr = &call_start + 1;
1387
    while (*ptr != NULL) {
1388
        func = *ptr++;
1389
        func();
1390
    }
1391
    test_bsx();
1392
    test_mul();
1393
    test_jcc();
1394
    test_floats();
1395
    test_bcd();
1396
    test_xchg();
1397
    test_string();
1398
    test_misc();
1399
    test_lea();
1400
    test_segs();
1401
    test_code16();
1402
    test_vm86();
1403
    test_exceptions();
1404
    test_self_modifying_code();
1405
    return 0;
1406
}