Statistics
| Branch: | Revision:

root / tests / test-i386.c @ 2792c4f2

History | View | Annotate | Download (23.2 kB)

1
#include <stdlib.h>
2
#include <stdio.h>
3
#include <inttypes.h>
4
#include <math.h>
5

    
6
#define TEST_CMOV 0
7

    
8
#define xglue(x, y) x ## y
9
#define glue(x, y) xglue(x, y)
10
#define stringify(s)        tostring(s)
11
#define tostring(s)        #s
12

    
13
#define CC_C           0x0001
14
#define CC_P         0x0004
15
#define CC_A        0x0010
16
#define CC_Z        0x0040
17
#define CC_S    0x0080
18
#define CC_O    0x0800
19

    
20
#define __init_call        __attribute__ ((unused,__section__ (".initcall.init")))
21

    
22
static void *call_start __init_call = NULL;
23

    
24
#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
25

    
26
#define OP add
27
#include "test-i386.h"
28

    
29
#define OP sub
30
#include "test-i386.h"
31

    
32
#define OP xor
33
#include "test-i386.h"
34

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

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

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

    
44
#define OP adc
45
#define OP_CC
46
#include "test-i386.h"
47

    
48
#define OP sbb
49
#define OP_CC
50
#include "test-i386.h"
51

    
52
#define OP inc
53
#define OP_CC
54
#define OP1
55
#include "test-i386.h"
56

    
57
#define OP dec
58
#define OP_CC
59
#define OP1
60
#include "test-i386.h"
61

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

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

    
72
#undef CC_MASK
73
#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)
74

    
75
#define OP shl
76
#include "test-i386-shift.h"
77

    
78
#define OP shr
79
#include "test-i386-shift.h"
80

    
81
#define OP sar
82
#include "test-i386-shift.h"
83

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

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

    
90
#define OP rcr
91
#define OP_CC
92
#include "test-i386-shift.h"
93

    
94
#define OP rcl
95
#define OP_CC
96
#include "test-i386-shift.h"
97

    
98
#define OP shld
99
#define OP_SHIFTD
100
#define OP_NOBYTE
101
#include "test-i386-shift.h"
102

    
103
#define OP shrd
104
#define OP_SHIFTD
105
#define OP_NOBYTE
106
#include "test-i386-shift.h"
107

    
108
/* XXX: should be more precise ? */
109
#undef CC_MASK
110
#define CC_MASK (CC_C)
111

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

    
116
#define OP bts
117
#define OP_NOBYTE
118
#include "test-i386-shift.h"
119

    
120
#define OP btr
121
#define OP_NOBYTE
122
#include "test-i386-shift.h"
123

    
124
#define OP btc
125
#define OP_NOBYTE
126
#include "test-i386-shift.h"
127

    
128
/* lea test (modrm support) */
129
#define TEST_LEA(STR)\
130
{\
131
    asm("leal " STR ", %0"\
132
        : "=r" (res)\
133
        : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
134
    printf("lea %s = %08x\n", STR, res);\
135
}
136

    
137
#define TEST_LEA16(STR)\
138
{\
139
    asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\
140
        : "=wq" (res)\
141
        : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
142
    printf("lea %s = %08x\n", STR, res);\
143
}
144

    
145

    
146
void test_lea(void)
147
{
148
    int eax, ebx, ecx, edx, esi, edi, res;
149
    eax = 0x0001;
150
    ebx = 0x0002;
151
    ecx = 0x0004;
152
    edx = 0x0008;
153
    esi = 0x0010;
154
    edi = 0x0020;
155

    
156
    TEST_LEA("0x4000");
157

    
158
    TEST_LEA("(%%eax)");
159
    TEST_LEA("(%%ebx)");
160
    TEST_LEA("(%%ecx)");
161
    TEST_LEA("(%%edx)");
162
    TEST_LEA("(%%esi)");
163
    TEST_LEA("(%%edi)");
164

    
165
    TEST_LEA("0x40(%%eax)");
166
    TEST_LEA("0x40(%%ebx)");
167
    TEST_LEA("0x40(%%ecx)");
168
    TEST_LEA("0x40(%%edx)");
169
    TEST_LEA("0x40(%%esi)");
170
    TEST_LEA("0x40(%%edi)");
171

    
172
    TEST_LEA("0x4000(%%eax)");
173
    TEST_LEA("0x4000(%%ebx)");
174
    TEST_LEA("0x4000(%%ecx)");
175
    TEST_LEA("0x4000(%%edx)");
176
    TEST_LEA("0x4000(%%esi)");
177
    TEST_LEA("0x4000(%%edi)");
178

    
179
    TEST_LEA("(%%eax, %%ecx)");
180
    TEST_LEA("(%%ebx, %%edx)");
181
    TEST_LEA("(%%ecx, %%ecx)");
182
    TEST_LEA("(%%edx, %%ecx)");
183
    TEST_LEA("(%%esi, %%ecx)");
184
    TEST_LEA("(%%edi, %%ecx)");
185

    
186
    TEST_LEA("0x40(%%eax, %%ecx)");
187
    TEST_LEA("0x4000(%%ebx, %%edx)");
188

    
189
    TEST_LEA("(%%ecx, %%ecx, 2)");
190
    TEST_LEA("(%%edx, %%ecx, 4)");
191
    TEST_LEA("(%%esi, %%ecx, 8)");
192

    
193
    TEST_LEA("(,%%eax, 2)");
194
    TEST_LEA("(,%%ebx, 4)");
195
    TEST_LEA("(,%%ecx, 8)");
196

    
197
    TEST_LEA("0x40(,%%eax, 2)");
198
    TEST_LEA("0x40(,%%ebx, 4)");
199
    TEST_LEA("0x40(,%%ecx, 8)");
200

    
201

    
202
    TEST_LEA("-10(%%ecx, %%ecx, 2)");
203
    TEST_LEA("-10(%%edx, %%ecx, 4)");
204
    TEST_LEA("-10(%%esi, %%ecx, 8)");
205

    
206
    TEST_LEA("0x4000(%%ecx, %%ecx, 2)");
207
    TEST_LEA("0x4000(%%edx, %%ecx, 4)");
208
    TEST_LEA("0x4000(%%esi, %%ecx, 8)");
209

    
210
    /* limited 16 bit addressing test */
211
    TEST_LEA16("0x4000");
212
    TEST_LEA16("(%%bx)");
213
    TEST_LEA16("(%%si)");
214
    TEST_LEA16("(%%di)");
215
    TEST_LEA16("0x40(%%bx)");
216
    TEST_LEA16("0x40(%%si)");
217
    TEST_LEA16("0x40(%%di)");
218
    TEST_LEA16("0x4000(%%bx)");
219
    TEST_LEA16("0x4000(%%si)");
220
    TEST_LEA16("(%%bx,%%si)");
221
    TEST_LEA16("(%%bx,%%di)");
222
    TEST_LEA16("0x40(%%bx,%%si)");
223
    TEST_LEA16("0x40(%%bx,%%di)");
224
    TEST_LEA16("0x4000(%%bx,%%si)");
225
    TEST_LEA16("0x4000(%%bx,%%di)");
226
}
227

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

    
262
/* various jump tests */
263
void test_jcc(void)
264
{
265
    TEST_JCC("ne", 1, 1);
266
    TEST_JCC("ne", 1, 0);
267

    
268
    TEST_JCC("e", 1, 1);
269
    TEST_JCC("e", 1, 0);
270

    
271
    TEST_JCC("l", 1, 1);
272
    TEST_JCC("l", 1, 0);
273
    TEST_JCC("l", 1, -1);
274

    
275
    TEST_JCC("le", 1, 1);
276
    TEST_JCC("le", 1, 0);
277
    TEST_JCC("le", 1, -1);
278

    
279
    TEST_JCC("ge", 1, 1);
280
    TEST_JCC("ge", 1, 0);
281
    TEST_JCC("ge", -1, 1);
282

    
283
    TEST_JCC("g", 1, 1);
284
    TEST_JCC("g", 1, 0);
285
    TEST_JCC("g", 1, -1);
286

    
287
    TEST_JCC("b", 1, 1);
288
    TEST_JCC("b", 1, 0);
289
    TEST_JCC("b", 1, -1);
290

    
291
    TEST_JCC("be", 1, 1);
292
    TEST_JCC("be", 1, 0);
293
    TEST_JCC("be", 1, -1);
294

    
295
    TEST_JCC("ae", 1, 1);
296
    TEST_JCC("ae", 1, 0);
297
    TEST_JCC("ae", 1, -1);
298

    
299
    TEST_JCC("a", 1, 1);
300
    TEST_JCC("a", 1, 0);
301
    TEST_JCC("a", 1, -1);
302

    
303

    
304
    TEST_JCC("p", 1, 1);
305
    TEST_JCC("p", 1, 0);
306

    
307
    TEST_JCC("np", 1, 1);
308
    TEST_JCC("np", 1, 0);
309

    
310
    TEST_JCC("o", 0x7fffffff, 0);
311
    TEST_JCC("o", 0x7fffffff, -1);
312

    
313
    TEST_JCC("no", 0x7fffffff, 0);
314
    TEST_JCC("no", 0x7fffffff, -1);
315

    
316
    TEST_JCC("s", 0, 1);
317
    TEST_JCC("s", 0, -1);
318
    TEST_JCC("s", 0, 0);
319

    
320
    TEST_JCC("ns", 0, 1);
321
    TEST_JCC("ns", 0, -1);
322
    TEST_JCC("ns", 0, 0);
323
}
324

    
325
#undef CC_MASK
326
#define CC_MASK (CC_O | CC_C)
327

    
328
#define OP mul
329
#include "test-i386-muldiv.h"
330

    
331
#define OP imul
332
#include "test-i386-muldiv.h"
333

    
334
#undef CC_MASK
335
#define CC_MASK (0)
336

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

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

    
343
void test_imulw2(int op0, int op1) 
344
{
345
    int res, s1, s0, flags;
346
    s0 = op0;
347
    s1 = op1;
348
    res = s0;
349
    flags = 0;
350
    asm ("push %4\n\t"
351
         "popf\n\t"
352
         "imulw %w2, %w0\n\t" 
353
         "pushf\n\t"
354
         "popl %1\n\t"
355
         : "=q" (res), "=g" (flags)
356
         : "q" (s1), "0" (res), "1" (flags));
357
    printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
358
           "imulw", s0, s1, res, flags & CC_MASK);
359
}
360

    
361
void test_imull2(int op0, int op1) 
362
{
363
    int res, s1, s0, flags;
364
    s0 = op0;
365
    s1 = op1;
366
    res = s0;
367
    flags = 0;
368
    asm ("push %4\n\t"
369
         "popf\n\t"
370
         "imull %2, %0\n\t" 
371
         "pushf\n\t"
372
         "popl %1\n\t"
373
         : "=q" (res), "=g" (flags)
374
         : "q" (s1), "0" (res), "1" (flags));
375
    printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
376
           "imull", s0, s1, res, flags & CC_MASK);
377
}
378

    
379
void test_mul(void)
380
{
381
    test_imulb(0x1234561d, 4);
382
    test_imulb(3, -4);
383
    test_imulb(0x80, 0x80);
384
    test_imulb(0x10, 0x10);
385

    
386
    test_imulw(0, 0x1234001d, 45);
387
    test_imulw(0, 23, -45);
388
    test_imulw(0, 0x8000, 0x8000);
389
    test_imulw(0, 0x100, 0x100);
390

    
391
    test_imull(0, 0x1234001d, 45);
392
    test_imull(0, 23, -45);
393
    test_imull(0, 0x80000000, 0x80000000);
394
    test_imull(0, 0x10000, 0x10000);
395

    
396
    test_mulb(0x1234561d, 4);
397
    test_mulb(3, -4);
398
    test_mulb(0x80, 0x80);
399
    test_mulb(0x10, 0x10);
400

    
401
    test_mulw(0, 0x1234001d, 45);
402
    test_mulw(0, 23, -45);
403
    test_mulw(0, 0x8000, 0x8000);
404
    test_mulw(0, 0x100, 0x100);
405

    
406
    test_mull(0, 0x1234001d, 45);
407
    test_mull(0, 23, -45);
408
    test_mull(0, 0x80000000, 0x80000000);
409
    test_mull(0, 0x10000, 0x10000);
410

    
411
    test_imulw2(0x1234001d, 45);
412
    test_imulw2(23, -45);
413
    test_imulw2(0x8000, 0x8000);
414
    test_imulw2(0x100, 0x100);
415

    
416
    test_imull2(0x1234001d, 45);
417
    test_imull2(23, -45);
418
    test_imull2(0x80000000, 0x80000000);
419
    test_imull2(0x10000, 0x10000);
420

    
421
    test_idivb(0x12341678, 0x127e);
422
    test_idivb(0x43210123, -5);
423
    test_idivb(0x12340004, -1);
424

    
425
    test_idivw(0, 0x12345678, 12347);
426
    test_idivw(0, -23223, -45);
427
    test_idivw(0, 0x12348000, -1);
428
    test_idivw(0x12343, 0x12345678, 0x81238567);
429

    
430
    test_idivl(0, 0x12345678, 12347);
431
    test_idivl(0, -233223, -45);
432
    test_idivl(0, 0x80000000, -1);
433
    test_idivl(0x12343, 0x12345678, 0x81234567);
434

    
435
    test_divb(0x12341678, 0x127e);
436
    test_divb(0x43210123, -5);
437
    test_divb(0x12340004, -1);
438

    
439
    test_divw(0, 0x12345678, 12347);
440
    test_divw(0, -23223, -45);
441
    test_divw(0, 0x12348000, -1);
442
    test_divw(0x12343, 0x12345678, 0x81238567);
443

    
444
    test_divl(0, 0x12345678, 12347);
445
    test_divl(0, -233223, -45);
446
    test_divl(0, 0x80000000, -1);
447
    test_divl(0x12343, 0x12345678, 0x81234567);
448
}
449

    
450
#define TEST_BSX(op, size, op0)\
451
{\
452
    int res, val, resz;\
453
    val = op0;\
454
    asm("xorl %1, %1 ; " #op " %" size "2, %" size "0 ; setz %b1" \
455
        : "=r" (res), "=q" (resz)\
456
        : "g" (val));\
457
    printf("%-10s A=%08x R=%08x %d\n", #op, val, resz ? 0 : res, resz);\
458
}
459

    
460
void test_bsx(void)
461
{
462
    TEST_BSX(bsrw, "w", 0);
463
    TEST_BSX(bsrw, "w", 0x12340128);
464
    TEST_BSX(bsrl, "", 0);
465
    TEST_BSX(bsrl, "", 0x00340128);
466
    TEST_BSX(bsfw, "w", 0);
467
    TEST_BSX(bsfw, "w", 0x12340128);
468
    TEST_BSX(bsfl, "", 0);
469
    TEST_BSX(bsfl, "", 0x00340128);
470
}
471

    
472
/**********************************************/
473

    
474
void test_fops(double a, double b)
475
{
476
    printf("a=%f b=%f a+b=%f\n", a, b, a + b);
477
    printf("a=%f b=%f a-b=%f\n", a, b, a - b);
478
    printf("a=%f b=%f a*b=%f\n", a, b, a * b);
479
    printf("a=%f b=%f a/b=%f\n", a, b, a / b);
480
    printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b));
481
    printf("a=%f sqrt(a)=%f\n", a, sqrt(a));
482
    printf("a=%f sin(a)=%f\n", a, sin(a));
483
    printf("a=%f cos(a)=%f\n", a, cos(a));
484
    printf("a=%f tan(a)=%f\n", a, tan(a));
485
    printf("a=%f log(a)=%f\n", a, log(a));
486
    printf("a=%f exp(a)=%f\n", a, exp(a));
487
    printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
488
    /* just to test some op combining */
489
    printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a)));
490
    printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a)));
491
    printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));
492

    
493
}
494

    
495
void test_fcmp(double a, double b)
496
{
497
    printf("(%f<%f)=%d\n",
498
           a, b, a < b);
499
    printf("(%f<=%f)=%d\n",
500
           a, b, a <= b);
501
    printf("(%f==%f)=%d\n",
502
           a, b, a == b);
503
    printf("(%f>%f)=%d\n",
504
           a, b, a > b);
505
    printf("(%f<=%f)=%d\n",
506
           a, b, a >= b);
507
}
508

    
509
void test_fcvt(double a)
510
{
511
    float fa;
512
    long double la;
513

    
514
    fa = a;
515
    la = a;
516
    printf("(float)%f = %f\n", a, fa);
517
    printf("(long double)%f = %Lf\n", a, la);
518
    printf("a=%016Lx\n", *(long long *)&a);
519
    printf("la=%016Lx %04x\n", *(long long *)&la, 
520
           *(unsigned short *)((char *)(&la) + 8));
521
    printf("a=%f floor(a)=%f\n", a, floor(a));
522
    printf("a=%f ceil(a)=%f\n", a, ceil(a));
523
    printf("a=%f rint(a)=%f\n", a, rint(a));
524
}
525

    
526
#define TEST(N) \
527
    asm("fld" #N : "=t" (a)); \
528
    printf("fld" #N "= %f\n", a);
529

    
530
void test_fconst(void)
531
{
532
    double a;
533
    TEST(1);
534
    TEST(l2t);
535
    TEST(l2e);
536
    TEST(pi);
537
    TEST(lg2);
538
    TEST(ln2);
539
    TEST(z);
540
}
541

    
542
void test_fbcd(double a)
543
{
544
    unsigned short bcd[5];
545
    double b;
546

    
547
    asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st");
548
    asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
549
    printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n", 
550
           a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);
551
}
552

    
553
void test_floats(void)
554
{
555
    test_fops(2, 3);
556
    test_fops(1.4, -5);
557
    test_fcmp(2, -1);
558
    test_fcmp(2, 2);
559
    test_fcmp(2, 3);
560
    test_fcvt(1.0/7.0);
561
    test_fcvt(-1.0/9.0);
562
    test_fcvt(1e30);
563
    test_fconst();
564
    test_fbcd(1234567890123456);
565
    test_fbcd(-123451234567890);
566
}
567

    
568
/**********************************************/
569

    
570
#define TEST_BCD(op, op0, cc_in, cc_mask)\
571
{\
572
    int res, flags;\
573
    res = op0;\
574
    flags = cc_in;\
575
    asm ("push %3\n\t"\
576
         "popf\n\t"\
577
         #op "\n\t"\
578
         "pushf\n\t"\
579
         "popl %1\n\t"\
580
        : "=a" (res), "=g" (flags)\
581
        : "0" (res), "1" (flags));\
582
    printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\
583
           #op, op0, res, cc_in, flags & cc_mask);\
584
}
585

    
586
void test_bcd(void)
587
{
588
    TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
589
    TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
590
    TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
591
    TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
592
    TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
593
    TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
594
    TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
595
    TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
596
    TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
597
    TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
598
    TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
599
    TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
600
    TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
601

    
602
    TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
603
    TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
604
    TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
605
    TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
606
    TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
607
    TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
608
    TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
609
    TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
610
    TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
611
    TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
612
    TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
613
    TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
614
    TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
615

    
616
    TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A));
617
    TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A));
618
    TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A));
619
    TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A));
620
    TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A));
621
    TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A));
622
    TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A));
623
    TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A));
624
    
625
    TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A));
626
    TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A));
627
    TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A));
628
    TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A));
629
    TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A));
630
    TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A));
631
    TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A));
632
    TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A));
633

    
634
    TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
635
    TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
636
}
637

    
638
#define TEST_XCHG(op, size, opconst)\
639
{\
640
    int op0, op1;\
641
    op0 = 0x12345678;\
642
    op1 = 0xfbca7654;\
643
    asm(#op " %" size "0, %" size "1" \
644
        : "=q" (op0), opconst (op1) \
645
        : "0" (op0), "1" (op1));\
646
    printf("%-10s A=%08x B=%08x\n",\
647
           #op, op0, op1);\
648
}
649

    
650
#define TEST_CMPXCHG(op, size, opconst, eax)\
651
{\
652
    int op0, op1;\
653
    op0 = 0x12345678;\
654
    op1 = 0xfbca7654;\
655
    asm(#op " %" size "0, %" size "1" \
656
        : "=q" (op0), opconst (op1) \
657
        : "0" (op0), "1" (op1), "a" (eax));\
658
    printf("%-10s EAX=%08x A=%08x C=%08x\n",\
659
           #op, eax, op0, op1);\
660
}
661

    
662
void test_xchg(void)
663
{
664
    TEST_XCHG(xchgl, "", "=q");
665
    TEST_XCHG(xchgw, "w", "=q");
666
    TEST_XCHG(xchgb, "b", "=q");
667

    
668
    TEST_XCHG(xchgl, "", "=m");
669
    TEST_XCHG(xchgw, "w", "=m");
670
    TEST_XCHG(xchgb, "b", "=m");
671

    
672
    TEST_XCHG(xaddl, "", "=q");
673
    TEST_XCHG(xaddw, "w", "=q");
674
    TEST_XCHG(xaddb, "b", "=q");
675

    
676
    TEST_XCHG(xaddl, "", "=m");
677
    TEST_XCHG(xaddw, "w", "=m");
678
    TEST_XCHG(xaddb, "b", "=m");
679

    
680
    TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfbca7654);
681
    TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfbca7654);
682
    TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfbca7654);
683

    
684
    TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfffefdfc);
685
    TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfffefdfc);
686
    TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfffefdfc);
687

    
688
    TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfbca7654);
689
    TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfbca7654);
690
    TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfbca7654);
691

    
692
    TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfffefdfc);
693
    TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfffefdfc);
694
    TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfffefdfc);
695
}
696

    
697
/**********************************************/
698
/* segmentation tests */
699

    
700
#include <asm/ldt.h>
701
#include <linux/unistd.h>
702

    
703
_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
704

    
705
uint8_t seg_data1[4096];
706
uint8_t seg_data2[4096];
707

    
708
#define MK_SEL(n) (((n) << 3) | 7)
709

    
710
/* NOTE: we use Linux modify_ldt syscall */
711
void test_segs(void)
712
{
713
    struct modify_ldt_ldt_s ldt;
714
    long long ldt_table[3];
715
    int res, res2;
716
    char tmp;
717
    struct {
718
        uint32_t offset;
719
        uint16_t seg;
720
    } __attribute__((packed)) segoff;
721

    
722
    ldt.entry_number = 1;
723
    ldt.base_addr = (unsigned long)&seg_data1;
724
    ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
725
    ldt.seg_32bit = 1;
726
    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
727
    ldt.read_exec_only = 0;
728
    ldt.limit_in_pages = 1;
729
    ldt.seg_not_present = 0;
730
    ldt.useable = 1;
731
    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
732

    
733
    ldt.entry_number = 2;
734
    ldt.base_addr = (unsigned long)&seg_data2;
735
    ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12;
736
    ldt.seg_32bit = 1;
737
    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
738
    ldt.read_exec_only = 0;
739
    ldt.limit_in_pages = 1;
740
    ldt.seg_not_present = 0;
741
    ldt.useable = 1;
742
    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
743

    
744
    modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */
745
#if 0
746
    {
747
        int i;
748
        for(i=0;i<3;i++)
749
            printf("%d: %016Lx\n", i, ldt_table[i]);
750
    }
751
#endif
752
    /* do some tests with fs or gs */
753
    asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
754
    asm volatile ("movl %0, %%gs" : : "r" (MK_SEL(2)));
755

    
756
    seg_data1[1] = 0xaa;
757
    seg_data2[1] = 0x55;
758

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

    
762
    asm volatile ("gs movzbl 0x1, %0" : "=r" (res));
763
    printf("GS[1] = %02x\n", res);
764

    
765
    /* tests with ds/ss (implicit segment case) */
766
    tmp = 0xa5;
767
    asm volatile ("pushl %%ebp\n\t"
768
                  "pushl %%ds\n\t"
769
                  "movl %2, %%ds\n\t"
770
                  "movl %3, %%ebp\n\t"
771
                  "movzbl 0x1, %0\n\t"
772
                  "movzbl (%%ebp), %1\n\t"
773
                  "popl %%ds\n\t"
774
                  "popl %%ebp\n\t"
775
                  : "=r" (res), "=r" (res2)
776
                  : "r" (MK_SEL(1)), "r" (&tmp));
777
    printf("DS[1] = %02x\n", res);
778
    printf("SS[tmp] = %02x\n", res2);
779

    
780
    segoff.seg = MK_SEL(2);
781
    segoff.offset = 0xabcdef12;
782
    asm volatile("lfs %2, %0\n\t" 
783
                 "movl %%fs, %1\n\t"
784
                 : "=r" (res), "=g" (res2) 
785
                 : "m" (segoff));
786
    printf("FS:reg = %04x:%08x\n", res2, res);
787
}
788

    
789
/* 16 bit code test */
790
extern char code16_start, code16_end;
791
extern char code16_func1;
792
extern char code16_func2;
793
extern char code16_func3;
794

    
795
void test_code16(void)
796
{
797
    struct modify_ldt_ldt_s ldt;
798
    int res, res2;
799

    
800
    /* build a code segment */
801
    ldt.entry_number = 1;
802
    ldt.base_addr = (unsigned long)&code16_start;
803
    ldt.limit = &code16_end - &code16_start;
804
    ldt.seg_32bit = 0;
805
    ldt.contents = MODIFY_LDT_CONTENTS_CODE;
806
    ldt.read_exec_only = 0;
807
    ldt.limit_in_pages = 0;
808
    ldt.seg_not_present = 0;
809
    ldt.useable = 1;
810
    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
811

    
812
    /* call the first function */
813
    asm volatile ("lcall %1, %2" 
814
                  : "=a" (res)
815
                  : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc");
816
    printf("func1() = 0x%08x\n", res);
817
    asm volatile ("lcall %2, %3" 
818
                  : "=a" (res), "=c" (res2)
819
                  : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc");
820
    printf("func2() = 0x%08x spdec=%d\n", res, res2);
821
    asm volatile ("lcall %1, %2" 
822
                  : "=a" (res)
823
                  : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc");
824
    printf("func3() = 0x%08x\n", res);
825
}
826

    
827
void test_misc(void)
828
{
829
    char table[256];
830
    int res, i;
831

    
832
    for(i=0;i<256;i++) table[i] = 256 - i;
833
    res = 0x12345678;
834
    asm ("xlat" : "=a" (res) : "b" (table), "0" (res));
835
    printf("xlat: EAX=%08x\n", res);
836
}
837

    
838
uint8_t str_buffer[4096];
839

    
840
#define TEST_STRING1(OP, size, DF, REP)\
841
{\
842
    int esi, edi, eax, ecx, eflags;\
843
\
844
    esi = (long)(str_buffer + sizeof(str_buffer) / 2);\
845
    edi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\
846
    eax = 0x12345678;\
847
    ecx = 17;\
848
\
849
    asm volatile ("pushl $0\n\t"\
850
                  "popf\n\t"\
851
                  DF "\n\t"\
852
                  REP #OP size "\n\t"\
853
                  "cld\n\t"\
854
                  "pushf\n\t"\
855
                  "popl %4\n\t"\
856
                  : "=S" (esi), "=D" (edi), "=a" (eax), "=c" (ecx), "=g" (eflags)\
857
                  : "0" (esi), "1" (edi), "2" (eax), "3" (ecx));\
858
    printf("%-10s ESI=%08x EDI=%08x EAX=%08x ECX=%08x EFL=%04x\n",\
859
           REP #OP size, esi, edi, eax, ecx,\
860
           eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\
861
}
862

    
863
#define TEST_STRING(OP, REP)\
864
    TEST_STRING1(OP, "b", "", REP);\
865
    TEST_STRING1(OP, "w", "", REP);\
866
    TEST_STRING1(OP, "l", "", REP);\
867
    TEST_STRING1(OP, "b", "std", REP);\
868
    TEST_STRING1(OP, "w", "std", REP);\
869
    TEST_STRING1(OP, "l", "std", REP)
870

    
871
void test_string(void)
872
{
873
    int i;
874
    for(i = 0;i < sizeof(str_buffer); i++)
875
        str_buffer[i] = i + 0x56;
876
   TEST_STRING(stos, "");
877
   TEST_STRING(stos, "rep ");
878
   TEST_STRING(lods, ""); /* to verify stos */
879
   TEST_STRING(lods, "rep "); 
880
   TEST_STRING(movs, "");
881
   TEST_STRING(movs, "rep ");
882
   TEST_STRING(lods, ""); /* to verify stos */
883

    
884
   /* XXX: better tests */
885
   TEST_STRING(scas, "");
886
   TEST_STRING(scas, "repz ");
887
   TEST_STRING(scas, "repnz ");
888
   TEST_STRING(cmps, "");
889
   TEST_STRING(cmps, "repz ");
890
   TEST_STRING(cmps, "repnz ");
891
}
892

    
893
static void *call_end __init_call = NULL;
894

    
895
int main(int argc, char **argv)
896
{
897
    void **ptr;
898
    void (*func)(void);
899

    
900
    ptr = &call_start + 1;
901
    while (*ptr != NULL) {
902
        func = *ptr++;
903
        func();
904
    }
905
    test_bsx();
906
    test_mul();
907
    test_jcc();
908
    test_floats();
909
    test_bcd();
910
    test_xchg();
911
    test_string();
912
    test_misc();
913
    test_lea();
914
    test_segs();
915
    test_code16();
916
    return 0;
917
}