VirtualBox

source: vbox/trunk/src/recompiler/tests/test-i386.c@ 9663

Last change on this file since 9663 was 2426, checked in by vboxsync, 18 years ago

Removed the old recompiler code. (wonder why subversion didn't pick up these changes right way)

  • Property svn:eol-style set to native
File size: 67.0 KB
Line 
1/*
2 * x86 CPU test
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20#define _GNU_SOURCE
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24#include <inttypes.h>
25#include <math.h>
26#include <signal.h>
27#include <setjmp.h>
28#include <errno.h>
29#include <sys/ucontext.h>
30#include <sys/mman.h>
31
32#if !defined(__x86_64__)
33#define TEST_VM86
34#define TEST_SEGS
35#endif
36//#define LINUX_VM86_IOPL_FIX
37//#define TEST_P4_FLAGS
38#if defined(__x86_64__)
39#define TEST_SSE
40#define TEST_CMOV 1
41#define TEST_FCOMI 1
42#else
43//#define TEST_SSE
44#define TEST_CMOV 0
45#define TEST_FCOMI 0
46#endif
47
48#if defined(__x86_64__)
49#define FMT64X "%016lx"
50#define FMTLX "%016lx"
51#define X86_64_ONLY(x) x
52#else
53#define FMT64X "%016" PRIx64
54#define FMTLX "%08lx"
55#define X86_64_ONLY(x)
56#endif
57
58#ifdef TEST_VM86
59#include <asm/vm86.h>
60#endif
61
62#define xglue(x, y) x ## y
63#define glue(x, y) xglue(x, y)
64#define stringify(s) tostring(s)
65#define tostring(s) #s
66
67#define CC_C 0x0001
68#define CC_P 0x0004
69#define CC_A 0x0010
70#define CC_Z 0x0040
71#define CC_S 0x0080
72#define CC_O 0x0800
73
74#define __init_call __attribute__ ((unused,__section__ ("initcall")))
75
76#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
77
78#if defined(__x86_64__)
79static inline long i2l(long v)
80{
81 return v | ((v ^ 0xabcd) << 32);
82}
83#else
84static inline long i2l(long v)
85{
86 return v;
87}
88#endif
89
90#define OP add
91#include "test-i386.h"
92
93#define OP sub
94#include "test-i386.h"
95
96#define OP xor
97#include "test-i386.h"
98
99#define OP and
100#include "test-i386.h"
101
102#define OP or
103#include "test-i386.h"
104
105#define OP cmp
106#include "test-i386.h"
107
108#define OP adc
109#define OP_CC
110#include "test-i386.h"
111
112#define OP sbb
113#define OP_CC
114#include "test-i386.h"
115
116#define OP inc
117#define OP_CC
118#define OP1
119#include "test-i386.h"
120
121#define OP dec
122#define OP_CC
123#define OP1
124#include "test-i386.h"
125
126#define OP neg
127#define OP_CC
128#define OP1
129#include "test-i386.h"
130
131#define OP not
132#define OP_CC
133#define OP1
134#include "test-i386.h"
135
136#undef CC_MASK
137#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)
138
139#define OP shl
140#include "test-i386-shift.h"
141
142#define OP shr
143#include "test-i386-shift.h"
144
145#define OP sar
146#include "test-i386-shift.h"
147
148#define OP rol
149#include "test-i386-shift.h"
150
151#define OP ror
152#include "test-i386-shift.h"
153
154#define OP rcr
155#define OP_CC
156#include "test-i386-shift.h"
157
158#define OP rcl
159#define OP_CC
160#include "test-i386-shift.h"
161
162#define OP shld
163#define OP_SHIFTD
164#define OP_NOBYTE
165#include "test-i386-shift.h"
166
167#define OP shrd
168#define OP_SHIFTD
169#define OP_NOBYTE
170#include "test-i386-shift.h"
171
172/* XXX: should be more precise ? */
173#undef CC_MASK
174#define CC_MASK (CC_C)
175
176#define OP bt
177#define OP_NOBYTE
178#include "test-i386-shift.h"
179
180#define OP bts
181#define OP_NOBYTE
182#include "test-i386-shift.h"
183
184#define OP btr
185#define OP_NOBYTE
186#include "test-i386-shift.h"
187
188#define OP btc
189#define OP_NOBYTE
190#include "test-i386-shift.h"
191
192/* lea test (modrm support) */
193#define TEST_LEAQ(STR)\
194{\
195 asm("lea " STR ", %0"\
196 : "=r" (res)\
197 : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
198 printf("lea %s = " FMTLX "\n", STR, res);\
199}
200
201#define TEST_LEA(STR)\
202{\
203 asm("lea " STR ", %0"\
204 : "=r" (res)\
205 : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
206 printf("lea %s = " FMTLX "\n", STR, res);\
207}
208
209#define TEST_LEA16(STR)\
210{\
211 asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\
212 : "=wq" (res)\
213 : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
214 printf("lea %s = %08lx\n", STR, res);\
215}
216
217
218void test_lea(void)
219{
220 long eax, ebx, ecx, edx, esi, edi, res;
221 eax = i2l(0x0001);
222 ebx = i2l(0x0002);
223 ecx = i2l(0x0004);
224 edx = i2l(0x0008);
225 esi = i2l(0x0010);
226 edi = i2l(0x0020);
227
228 TEST_LEA("0x4000");
229
230 TEST_LEA("(%%eax)");
231 TEST_LEA("(%%ebx)");
232 TEST_LEA("(%%ecx)");
233 TEST_LEA("(%%edx)");
234 TEST_LEA("(%%esi)");
235 TEST_LEA("(%%edi)");
236
237 TEST_LEA("0x40(%%eax)");
238 TEST_LEA("0x40(%%ebx)");
239 TEST_LEA("0x40(%%ecx)");
240 TEST_LEA("0x40(%%edx)");
241 TEST_LEA("0x40(%%esi)");
242 TEST_LEA("0x40(%%edi)");
243
244 TEST_LEA("0x4000(%%eax)");
245 TEST_LEA("0x4000(%%ebx)");
246 TEST_LEA("0x4000(%%ecx)");
247 TEST_LEA("0x4000(%%edx)");
248 TEST_LEA("0x4000(%%esi)");
249 TEST_LEA("0x4000(%%edi)");
250
251 TEST_LEA("(%%eax, %%ecx)");
252 TEST_LEA("(%%ebx, %%edx)");
253 TEST_LEA("(%%ecx, %%ecx)");
254 TEST_LEA("(%%edx, %%ecx)");
255 TEST_LEA("(%%esi, %%ecx)");
256 TEST_LEA("(%%edi, %%ecx)");
257
258 TEST_LEA("0x40(%%eax, %%ecx)");
259 TEST_LEA("0x4000(%%ebx, %%edx)");
260
261 TEST_LEA("(%%ecx, %%ecx, 2)");
262 TEST_LEA("(%%edx, %%ecx, 4)");
263 TEST_LEA("(%%esi, %%ecx, 8)");
264
265 TEST_LEA("(,%%eax, 2)");
266 TEST_LEA("(,%%ebx, 4)");
267 TEST_LEA("(,%%ecx, 8)");
268
269 TEST_LEA("0x40(,%%eax, 2)");
270 TEST_LEA("0x40(,%%ebx, 4)");
271 TEST_LEA("0x40(,%%ecx, 8)");
272
273
274 TEST_LEA("-10(%%ecx, %%ecx, 2)");
275 TEST_LEA("-10(%%edx, %%ecx, 4)");
276 TEST_LEA("-10(%%esi, %%ecx, 8)");
277
278 TEST_LEA("0x4000(%%ecx, %%ecx, 2)");
279 TEST_LEA("0x4000(%%edx, %%ecx, 4)");
280 TEST_LEA("0x4000(%%esi, %%ecx, 8)");
281
282#if defined(__x86_64__)
283 TEST_LEAQ("0x4000");
284 TEST_LEAQ("0x4000(%%rip)");
285
286 TEST_LEAQ("(%%rax)");
287 TEST_LEAQ("(%%rbx)");
288 TEST_LEAQ("(%%rcx)");
289 TEST_LEAQ("(%%rdx)");
290 TEST_LEAQ("(%%rsi)");
291 TEST_LEAQ("(%%rdi)");
292
293 TEST_LEAQ("0x40(%%rax)");
294 TEST_LEAQ("0x40(%%rbx)");
295 TEST_LEAQ("0x40(%%rcx)");
296 TEST_LEAQ("0x40(%%rdx)");
297 TEST_LEAQ("0x40(%%rsi)");
298 TEST_LEAQ("0x40(%%rdi)");
299
300 TEST_LEAQ("0x4000(%%rax)");
301 TEST_LEAQ("0x4000(%%rbx)");
302 TEST_LEAQ("0x4000(%%rcx)");
303 TEST_LEAQ("0x4000(%%rdx)");
304 TEST_LEAQ("0x4000(%%rsi)");
305 TEST_LEAQ("0x4000(%%rdi)");
306
307 TEST_LEAQ("(%%rax, %%rcx)");
308 TEST_LEAQ("(%%rbx, %%rdx)");
309 TEST_LEAQ("(%%rcx, %%rcx)");
310 TEST_LEAQ("(%%rdx, %%rcx)");
311 TEST_LEAQ("(%%rsi, %%rcx)");
312 TEST_LEAQ("(%%rdi, %%rcx)");
313
314 TEST_LEAQ("0x40(%%rax, %%rcx)");
315 TEST_LEAQ("0x4000(%%rbx, %%rdx)");
316
317 TEST_LEAQ("(%%rcx, %%rcx, 2)");
318 TEST_LEAQ("(%%rdx, %%rcx, 4)");
319 TEST_LEAQ("(%%rsi, %%rcx, 8)");
320
321 TEST_LEAQ("(,%%rax, 2)");
322 TEST_LEAQ("(,%%rbx, 4)");
323 TEST_LEAQ("(,%%rcx, 8)");
324
325 TEST_LEAQ("0x40(,%%rax, 2)");
326 TEST_LEAQ("0x40(,%%rbx, 4)");
327 TEST_LEAQ("0x40(,%%rcx, 8)");
328
329
330 TEST_LEAQ("-10(%%rcx, %%rcx, 2)");
331 TEST_LEAQ("-10(%%rdx, %%rcx, 4)");
332 TEST_LEAQ("-10(%%rsi, %%rcx, 8)");
333
334 TEST_LEAQ("0x4000(%%rcx, %%rcx, 2)");
335 TEST_LEAQ("0x4000(%%rdx, %%rcx, 4)");
336 TEST_LEAQ("0x4000(%%rsi, %%rcx, 8)");
337#else
338 /* limited 16 bit addressing test */
339 TEST_LEA16("0x4000");
340 TEST_LEA16("(%%bx)");
341 TEST_LEA16("(%%si)");
342 TEST_LEA16("(%%di)");
343 TEST_LEA16("0x40(%%bx)");
344 TEST_LEA16("0x40(%%si)");
345 TEST_LEA16("0x40(%%di)");
346 TEST_LEA16("0x4000(%%bx)");
347 TEST_LEA16("0x4000(%%si)");
348 TEST_LEA16("(%%bx,%%si)");
349 TEST_LEA16("(%%bx,%%di)");
350 TEST_LEA16("0x40(%%bx,%%si)");
351 TEST_LEA16("0x40(%%bx,%%di)");
352 TEST_LEA16("0x4000(%%bx,%%si)");
353 TEST_LEA16("0x4000(%%bx,%%di)");
354#endif
355}
356
357#define TEST_JCC(JCC, v1, v2)\
358{\
359 int res;\
360 asm("movl $1, %0\n\t"\
361 "cmpl %2, %1\n\t"\
362 "j" JCC " 1f\n\t"\
363 "movl $0, %0\n\t"\
364 "1:\n\t"\
365 : "=r" (res)\
366 : "r" (v1), "r" (v2));\
367 printf("%-10s %d\n", "j" JCC, res);\
368\
369 asm("movl $0, %0\n\t"\
370 "cmpl %2, %1\n\t"\
371 "set" JCC " %b0\n\t"\
372 : "=r" (res)\
373 : "r" (v1), "r" (v2));\
374 printf("%-10s %d\n", "set" JCC, res);\
375 if (TEST_CMOV) {\
376 long val = i2l(1);\
377 long res = i2l(0x12345678);\
378X86_64_ONLY(\
379 asm("cmpl %2, %1\n\t"\
380 "cmov" JCC "q %3, %0\n\t"\
381 : "=r" (res)\
382 : "r" (v1), "r" (v2), "m" (val), "0" (res));\
383 printf("%-10s R=" FMTLX "\n", "cmov" JCC "q", res);)\
384 asm("cmpl %2, %1\n\t"\
385 "cmov" JCC "l %k3, %k0\n\t"\
386 : "=r" (res)\
387 : "r" (v1), "r" (v2), "m" (val), "0" (res));\
388 printf("%-10s R=" FMTLX "\n", "cmov" JCC "l", res);\
389 asm("cmpl %2, %1\n\t"\
390 "cmov" JCC "w %w3, %w0\n\t"\
391 : "=r" (res)\
392 : "r" (v1), "r" (v2), "r" (1), "0" (res));\
393 printf("%-10s R=" FMTLX "\n", "cmov" JCC "w", res);\
394 } \
395}
396
397/* various jump tests */
398void test_jcc(void)
399{
400 TEST_JCC("ne", 1, 1);
401 TEST_JCC("ne", 1, 0);
402
403 TEST_JCC("e", 1, 1);
404 TEST_JCC("e", 1, 0);
405
406 TEST_JCC("l", 1, 1);
407 TEST_JCC("l", 1, 0);
408 TEST_JCC("l", 1, -1);
409
410 TEST_JCC("le", 1, 1);
411 TEST_JCC("le", 1, 0);
412 TEST_JCC("le", 1, -1);
413
414 TEST_JCC("ge", 1, 1);
415 TEST_JCC("ge", 1, 0);
416 TEST_JCC("ge", -1, 1);
417
418 TEST_JCC("g", 1, 1);
419 TEST_JCC("g", 1, 0);
420 TEST_JCC("g", 1, -1);
421
422 TEST_JCC("b", 1, 1);
423 TEST_JCC("b", 1, 0);
424 TEST_JCC("b", 1, -1);
425
426 TEST_JCC("be", 1, 1);
427 TEST_JCC("be", 1, 0);
428 TEST_JCC("be", 1, -1);
429
430 TEST_JCC("ae", 1, 1);
431 TEST_JCC("ae", 1, 0);
432 TEST_JCC("ae", 1, -1);
433
434 TEST_JCC("a", 1, 1);
435 TEST_JCC("a", 1, 0);
436 TEST_JCC("a", 1, -1);
437
438
439 TEST_JCC("p", 1, 1);
440 TEST_JCC("p", 1, 0);
441
442 TEST_JCC("np", 1, 1);
443 TEST_JCC("np", 1, 0);
444
445 TEST_JCC("o", 0x7fffffff, 0);
446 TEST_JCC("o", 0x7fffffff, -1);
447
448 TEST_JCC("no", 0x7fffffff, 0);
449 TEST_JCC("no", 0x7fffffff, -1);
450
451 TEST_JCC("s", 0, 1);
452 TEST_JCC("s", 0, -1);
453 TEST_JCC("s", 0, 0);
454
455 TEST_JCC("ns", 0, 1);
456 TEST_JCC("ns", 0, -1);
457 TEST_JCC("ns", 0, 0);
458}
459
460#undef CC_MASK
461#ifdef TEST_P4_FLAGS
462#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
463#else
464#define CC_MASK (CC_O | CC_C)
465#endif
466
467#define OP mul
468#include "test-i386-muldiv.h"
469
470#define OP imul
471#include "test-i386-muldiv.h"
472
473void test_imulw2(long op0, long op1)
474{
475 long res, s1, s0, flags;
476 s0 = op0;
477 s1 = op1;
478 res = s0;
479 flags = 0;
480 asm volatile ("push %4\n\t"
481 "popf\n\t"
482 "imulw %w2, %w0\n\t"
483 "pushf\n\t"
484 "pop %1\n\t"
485 : "=q" (res), "=g" (flags)
486 : "q" (s1), "0" (res), "1" (flags));
487 printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
488 "imulw", s0, s1, res, flags & CC_MASK);
489}
490
491void test_imull2(long op0, long op1)
492{
493 long res, s1, s0, flags;
494 s0 = op0;
495 s1 = op1;
496 res = s0;
497 flags = 0;
498 asm volatile ("push %4\n\t"
499 "popf\n\t"
500 "imull %k2, %k0\n\t"
501 "pushf\n\t"
502 "pop %1\n\t"
503 : "=q" (res), "=g" (flags)
504 : "q" (s1), "0" (res), "1" (flags));
505 printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
506 "imull", s0, s1, res, flags & CC_MASK);
507}
508
509#if defined(__x86_64__)
510void test_imulq2(long op0, long op1)
511{
512 long res, s1, s0, flags;
513 s0 = op0;
514 s1 = op1;
515 res = s0;
516 flags = 0;
517 asm volatile ("push %4\n\t"
518 "popf\n\t"
519 "imulq %2, %0\n\t"
520 "pushf\n\t"
521 "pop %1\n\t"
522 : "=q" (res), "=g" (flags)
523 : "q" (s1), "0" (res), "1" (flags));
524 printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
525 "imulq", s0, s1, res, flags & CC_MASK);
526}
527#endif
528
529#define TEST_IMUL_IM(size, rsize, op0, op1)\
530{\
531 long res, flags, s1;\
532 flags = 0;\
533 res = 0;\
534 s1 = op1;\
535 asm volatile ("push %3\n\t"\
536 "popf\n\t"\
537 "imul" size " $" #op0 ", %" rsize "2, %" rsize "0\n\t" \
538 "pushf\n\t"\
539 "pop %1\n\t"\
540 : "=r" (res), "=g" (flags)\
541 : "r" (s1), "1" (flags), "0" (res));\
542 printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",\
543 "imul" size " im", (long)op0, (long)op1, res, flags & CC_MASK);\
544}
545
546
547#undef CC_MASK
548#define CC_MASK (0)
549
550#define OP div
551#include "test-i386-muldiv.h"
552
553#define OP idiv
554#include "test-i386-muldiv.h"
555
556void test_mul(void)
557{
558 test_imulb(0x1234561d, 4);
559 test_imulb(3, -4);
560 test_imulb(0x80, 0x80);
561 test_imulb(0x10, 0x10);
562
563 test_imulw(0, 0x1234001d, 45);
564 test_imulw(0, 23, -45);
565 test_imulw(0, 0x8000, 0x8000);
566 test_imulw(0, 0x100, 0x100);
567
568 test_imull(0, 0x1234001d, 45);
569 test_imull(0, 23, -45);
570 test_imull(0, 0x80000000, 0x80000000);
571 test_imull(0, 0x10000, 0x10000);
572
573 test_mulb(0x1234561d, 4);
574 test_mulb(3, -4);
575 test_mulb(0x80, 0x80);
576 test_mulb(0x10, 0x10);
577
578 test_mulw(0, 0x1234001d, 45);
579 test_mulw(0, 23, -45);
580 test_mulw(0, 0x8000, 0x8000);
581 test_mulw(0, 0x100, 0x100);
582
583 test_mull(0, 0x1234001d, 45);
584 test_mull(0, 23, -45);
585 test_mull(0, 0x80000000, 0x80000000);
586 test_mull(0, 0x10000, 0x10000);
587
588 test_imulw2(0x1234001d, 45);
589 test_imulw2(23, -45);
590 test_imulw2(0x8000, 0x8000);
591 test_imulw2(0x100, 0x100);
592
593 test_imull2(0x1234001d, 45);
594 test_imull2(23, -45);
595 test_imull2(0x80000000, 0x80000000);
596 test_imull2(0x10000, 0x10000);
597
598 TEST_IMUL_IM("w", "w", 45, 0x1234);
599 TEST_IMUL_IM("w", "w", -45, 23);
600 TEST_IMUL_IM("w", "w", 0x8000, 0x80000000);
601 TEST_IMUL_IM("w", "w", 0x7fff, 0x1000);
602
603 TEST_IMUL_IM("l", "k", 45, 0x1234);
604 TEST_IMUL_IM("l", "k", -45, 23);
605 TEST_IMUL_IM("l", "k", 0x8000, 0x80000000);
606 TEST_IMUL_IM("l", "k", 0x7fff, 0x1000);
607
608 test_idivb(0x12341678, 0x127e);
609 test_idivb(0x43210123, -5);
610 test_idivb(0x12340004, -1);
611
612 test_idivw(0, 0x12345678, 12347);
613 test_idivw(0, -23223, -45);
614 test_idivw(0, 0x12348000, -1);
615 test_idivw(0x12343, 0x12345678, 0x81238567);
616
617 test_idivl(0, 0x12345678, 12347);
618 test_idivl(0, -233223, -45);
619 test_idivl(0, 0x80000000, -1);
620 test_idivl(0x12343, 0x12345678, 0x81234567);
621
622 test_divb(0x12341678, 0x127e);
623 test_divb(0x43210123, -5);
624 test_divb(0x12340004, -1);
625
626 test_divw(0, 0x12345678, 12347);
627 test_divw(0, -23223, -45);
628 test_divw(0, 0x12348000, -1);
629 test_divw(0x12343, 0x12345678, 0x81238567);
630
631 test_divl(0, 0x12345678, 12347);
632 test_divl(0, -233223, -45);
633 test_divl(0, 0x80000000, -1);
634 test_divl(0x12343, 0x12345678, 0x81234567);
635
636#if defined(__x86_64__)
637 test_imulq(0, 0x1234001d1234001d, 45);
638 test_imulq(0, 23, -45);
639 test_imulq(0, 0x8000000000000000, 0x8000000000000000);
640 test_imulq(0, 0x100000000, 0x100000000);
641
642 test_mulq(0, 0x1234001d1234001d, 45);
643 test_mulq(0, 23, -45);
644 test_mulq(0, 0x8000000000000000, 0x8000000000000000);
645 test_mulq(0, 0x100000000, 0x100000000);
646
647 test_imulq2(0x1234001d1234001d, 45);
648 test_imulq2(23, -45);
649 test_imulq2(0x8000000000000000, 0x8000000000000000);
650 test_imulq2(0x100000000, 0x100000000);
651
652 TEST_IMUL_IM("q", "", 45, 0x12341234);
653 TEST_IMUL_IM("q", "", -45, 23);
654 TEST_IMUL_IM("q", "", 0x8000, 0x8000000000000000);
655 TEST_IMUL_IM("q", "", 0x7fff, 0x10000000);
656
657 test_idivq(0, 0x12345678abcdef, 12347);
658 test_idivq(0, -233223, -45);
659 test_idivq(0, 0x8000000000000000, -1);
660 test_idivq(0x12343, 0x12345678, 0x81234567);
661
662 test_divq(0, 0x12345678abcdef, 12347);
663 test_divq(0, -233223, -45);
664 test_divq(0, 0x8000000000000000, -1);
665 test_divq(0x12343, 0x12345678, 0x81234567);
666#endif
667}
668
669#define TEST_BSX(op, size, op0)\
670{\
671 long res, val, resz;\
672 val = op0;\
673 asm("xor %1, %1\n"\
674 "mov $0x12345678, %0\n"\
675 #op " %" size "2, %" size "0 ; setz %b1" \
676 : "=r" (res), "=q" (resz)\
677 : "g" (val));\
678 printf("%-10s A=" FMTLX " R=" FMTLX " %ld\n", #op, val, res, resz);\
679}
680
681void test_bsx(void)
682{
683 TEST_BSX(bsrw, "w", 0);
684 TEST_BSX(bsrw, "w", 0x12340128);
685 TEST_BSX(bsfw, "w", 0);
686 TEST_BSX(bsfw, "w", 0x12340128);
687 TEST_BSX(bsrl, "k", 0);
688 TEST_BSX(bsrl, "k", 0x00340128);
689 TEST_BSX(bsfl, "k", 0);
690 TEST_BSX(bsfl, "k", 0x00340128);
691#if defined(__x86_64__)
692 TEST_BSX(bsrq, "", 0);
693 TEST_BSX(bsrq, "", 0x003401281234);
694 TEST_BSX(bsfq, "", 0);
695 TEST_BSX(bsfq, "", 0x003401281234);
696#endif
697}
698
699/**********************************************/
700
701union float64u {
702 double d;
703 uint64_t l;
704};
705
706union float64u q_nan = { .l = 0xFFF8000000000000 };
707union float64u s_nan = { .l = 0xFFF0000000000000 };
708
709void test_fops(double a, double b)
710{
711 printf("a=%f b=%f a+b=%f\n", a, b, a + b);
712 printf("a=%f b=%f a-b=%f\n", a, b, a - b);
713 printf("a=%f b=%f a*b=%f\n", a, b, a * b);
714 printf("a=%f b=%f a/b=%f\n", a, b, a / b);
715 printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b));
716 printf("a=%f sqrt(a)=%f\n", a, sqrt(a));
717 printf("a=%f sin(a)=%f\n", a, sin(a));
718 printf("a=%f cos(a)=%f\n", a, cos(a));
719 printf("a=%f tan(a)=%f\n", a, tan(a));
720 printf("a=%f log(a)=%f\n", a, log(a));
721 printf("a=%f exp(a)=%f\n", a, exp(a));
722 printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
723 /* just to test some op combining */
724 printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a)));
725 printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a)));
726 printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));
727
728}
729
730void fpu_clear_exceptions(void)
731{
732 struct __attribute__((packed)) {
733 uint16_t fpuc;
734 uint16_t dummy1;
735 uint16_t fpus;
736 uint16_t dummy2;
737 uint16_t fptag;
738 uint16_t dummy3;
739 uint32_t ignored[4];
740 long double fpregs[8];
741 } float_env32;
742
743 asm volatile ("fnstenv %0\n" : : "m" (float_env32));
744 float_env32.fpus &= ~0x7f;
745 asm volatile ("fldenv %0\n" : : "m" (float_env32));
746}
747
748/* XXX: display exception bits when supported */
749#define FPUS_EMASK 0x0000
750//#define FPUS_EMASK 0x007f
751
752void test_fcmp(double a, double b)
753{
754 long eflags, fpus;
755
756 fpu_clear_exceptions();
757 asm("fcom %2\n"
758 "fstsw %%ax\n"
759 : "=a" (fpus)
760 : "t" (a), "u" (b));
761 printf("fcom(%f %f)=%04lx \n",
762 a, b, fpus & (0x4500 | FPUS_EMASK));
763 fpu_clear_exceptions();
764 asm("fucom %2\n"
765 "fstsw %%ax\n"
766 : "=a" (fpus)
767 : "t" (a), "u" (b));
768 printf("fucom(%f %f)=%04lx\n",
769 a, b, fpus & (0x4500 | FPUS_EMASK));
770 if (TEST_FCOMI) {
771 /* test f(u)comi instruction */
772 fpu_clear_exceptions();
773 asm("fcomi %3, %2\n"
774 "fstsw %%ax\n"
775 "pushf\n"
776 "pop %0\n"
777 : "=r" (eflags), "=a" (fpus)
778 : "t" (a), "u" (b));
779 printf("fcomi(%f %f)=%04lx %02lx\n",
780 a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C));
781 fpu_clear_exceptions();
782 asm("fucomi %3, %2\n"
783 "fstsw %%ax\n"
784 "pushf\n"
785 "pop %0\n"
786 : "=r" (eflags), "=a" (fpus)
787 : "t" (a), "u" (b));
788 printf("fucomi(%f %f)=%04lx %02lx\n",
789 a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C));
790 }
791 fpu_clear_exceptions();
792 asm volatile("fxam\n"
793 "fstsw %%ax\n"
794 : "=a" (fpus)
795 : "t" (a));
796 printf("fxam(%f)=%04lx\n", a, fpus & 0x4700);
797 fpu_clear_exceptions();
798}
799
800void test_fcvt(double a)
801{
802 float fa;
803 long double la;
804 int16_t fpuc;
805 int i;
806 int64_t lla;
807 int ia;
808 int16_t wa;
809 double ra;
810
811 fa = a;
812 la = a;
813 printf("(float)%f = %f\n", a, fa);
814 printf("(long double)%f = %Lf\n", a, la);
815 printf("a=" FMT64X "\n", *(uint64_t *)&a);
816 printf("la=" FMT64X " %04x\n", *(uint64_t *)&la,
817 *(unsigned short *)((char *)(&la) + 8));
818
819 /* test all roundings */
820 asm volatile ("fstcw %0" : "=m" (fpuc));
821 for(i=0;i<4;i++) {
822 asm volatile ("fldcw %0" : : "m" ((fpuc & ~0x0c00) | (i << 10)));
823 asm volatile ("fist %0" : "=m" (wa) : "t" (a));
824 asm volatile ("fistl %0" : "=m" (ia) : "t" (a));
825 asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st");
826 asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a));
827 asm volatile ("fldcw %0" : : "m" (fpuc));
828 printf("(short)a = %d\n", wa);
829 printf("(int)a = %d\n", ia);
830 printf("(int64_t)a = " FMT64X "\n", lla);
831 printf("rint(a) = %f\n", ra);
832 }
833}
834
835#define TEST(N) \
836 asm("fld" #N : "=t" (a)); \
837 printf("fld" #N "= %f\n", a);
838
839void test_fconst(void)
840{
841 double a;
842 TEST(1);
843 TEST(l2t);
844 TEST(l2e);
845 TEST(pi);
846 TEST(lg2);
847 TEST(ln2);
848 TEST(z);
849}
850
851void test_fbcd(double a)
852{
853 unsigned short bcd[5];
854 double b;
855
856 asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st");
857 asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
858 printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n",
859 a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);
860}
861
862#define TEST_ENV(env, save, restore)\
863{\
864 memset((env), 0xaa, sizeof(*(env)));\
865 for(i=0;i<5;i++)\
866 asm volatile ("fldl %0" : : "m" (dtab[i]));\
867 asm volatile (save " %0\n" : : "m" (*(env)));\
868 asm volatile (restore " %0\n": : "m" (*(env)));\
869 for(i=0;i<5;i++)\
870 asm volatile ("fstpl %0" : "=m" (rtab[i]));\
871 for(i=0;i<5;i++)\
872 printf("res[%d]=%f\n", i, rtab[i]);\
873 printf("fpuc=%04x fpus=%04x fptag=%04x\n",\
874 (env)->fpuc,\
875 (env)->fpus & 0xff00,\
876 (env)->fptag);\
877}
878
879void test_fenv(void)
880{
881 struct __attribute__((packed)) {
882 uint16_t fpuc;
883 uint16_t dummy1;
884 uint16_t fpus;
885 uint16_t dummy2;
886 uint16_t fptag;
887 uint16_t dummy3;
888 uint32_t ignored[4];
889 long double fpregs[8];
890 } float_env32;
891 struct __attribute__((packed)) {
892 uint16_t fpuc;
893 uint16_t fpus;
894 uint16_t fptag;
895 uint16_t ignored[4];
896 long double fpregs[8];
897 } float_env16;
898 double dtab[8];
899 double rtab[8];
900 int i;
901
902 for(i=0;i<8;i++)
903 dtab[i] = i + 1;
904
905 TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv");
906 TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor");
907 TEST_ENV(&float_env32, "fnstenv", "fldenv");
908 TEST_ENV(&float_env32, "fnsave", "frstor");
909
910 /* test for ffree */
911 for(i=0;i<5;i++)
912 asm volatile ("fldl %0" : : "m" (dtab[i]));
913 asm volatile("ffree %st(2)");
914 asm volatile ("fnstenv %0\n" : : "m" (float_env32));
915 asm volatile ("fninit");
916 printf("fptag=%04x\n", float_env32.fptag);
917}
918
919
920#define TEST_FCMOV(a, b, eflags, CC)\
921{\
922 double res;\
923 asm("push %3\n"\
924 "popf\n"\
925 "fcmov" CC " %2, %0\n"\
926 : "=t" (res)\
927 : "0" (a), "u" (b), "g" (eflags));\
928 printf("fcmov%s eflags=0x%04lx-> %f\n", \
929 CC, (long)eflags, res);\
930}
931
932void test_fcmov(void)
933{
934 double a, b;
935 long eflags, i;
936
937 a = 1.0;
938 b = 2.0;
939 for(i = 0; i < 4; i++) {
940 eflags = 0;
941 if (i & 1)
942 eflags |= CC_C;
943 if (i & 2)
944 eflags |= CC_Z;
945 TEST_FCMOV(a, b, eflags, "b");
946 TEST_FCMOV(a, b, eflags, "e");
947 TEST_FCMOV(a, b, eflags, "be");
948 TEST_FCMOV(a, b, eflags, "nb");
949 TEST_FCMOV(a, b, eflags, "ne");
950 TEST_FCMOV(a, b, eflags, "nbe");
951 }
952 TEST_FCMOV(a, b, 0, "u");
953 TEST_FCMOV(a, b, CC_P, "u");
954 TEST_FCMOV(a, b, 0, "nu");
955 TEST_FCMOV(a, b, CC_P, "nu");
956}
957
958void test_floats(void)
959{
960 test_fops(2, 3);
961 test_fops(1.4, -5);
962 test_fcmp(2, -1);
963 test_fcmp(2, 2);
964 test_fcmp(2, 3);
965 test_fcmp(2, q_nan.d);
966 test_fcmp(q_nan.d, -1);
967 test_fcmp(-1.0/0.0, -1);
968 test_fcmp(1.0/0.0, -1);
969 test_fcvt(0.5);
970 test_fcvt(-0.5);
971 test_fcvt(1.0/7.0);
972 test_fcvt(-1.0/9.0);
973 test_fcvt(32768);
974 test_fcvt(-1e20);
975 test_fcvt(-1.0/0.0);
976 test_fcvt(1.0/0.0);
977 test_fcvt(q_nan.d);
978 test_fconst();
979 test_fbcd(1234567890123456);
980 test_fbcd(-123451234567890);
981 test_fenv();
982 if (TEST_CMOV) {
983 test_fcmov();
984 }
985}
986
987/**********************************************/
988#if !defined(__x86_64__)
989
990#define TEST_BCD(op, op0, cc_in, cc_mask)\
991{\
992 int res, flags;\
993 res = op0;\
994 flags = cc_in;\
995 asm ("push %3\n\t"\
996 "popf\n\t"\
997 #op "\n\t"\
998 "pushf\n\t"\
999 "pop %1\n\t"\
1000 : "=a" (res), "=g" (flags)\
1001 : "0" (res), "1" (flags));\
1002 printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\
1003 #op, op0, res, cc_in, flags & cc_mask);\
1004}
1005
1006void test_bcd(void)
1007{
1008 TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1009 TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1010 TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1011 TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1012 TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1013 TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1014 TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1015 TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1016 TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1017 TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1018 TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1019 TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1020 TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1021
1022 TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1023 TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1024 TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1025 TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1026 TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1027 TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1028 TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1029 TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1030 TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1031 TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1032 TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1033 TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1034 TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1035
1036 TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A));
1037 TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A));
1038 TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A));
1039 TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A));
1040 TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A));
1041 TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A));
1042 TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A));
1043 TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A));
1044
1045 TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A));
1046 TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A));
1047 TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A));
1048 TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A));
1049 TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A));
1050 TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A));
1051 TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A));
1052 TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A));
1053
1054 TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
1055 TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
1056}
1057#endif
1058
1059#define TEST_XCHG(op, size, opconst)\
1060{\
1061 long op0, op1;\
1062 op0 = i2l(0x12345678);\
1063 op1 = i2l(0xfbca7654);\
1064 asm(#op " %" size "0, %" size "1" \
1065 : "=q" (op0), opconst (op1) \
1066 : "0" (op0), "1" (op1));\
1067 printf("%-10s A=" FMTLX " B=" FMTLX "\n",\
1068 #op, op0, op1);\
1069}
1070
1071#define TEST_CMPXCHG(op, size, opconst, eax)\
1072{\
1073 long op0, op1, op2;\
1074 op0 = i2l(0x12345678);\
1075 op1 = i2l(0xfbca7654);\
1076 op2 = i2l(eax);\
1077 asm(#op " %" size "0, %" size "1" \
1078 : "=q" (op0), opconst (op1) \
1079 : "0" (op0), "1" (op1), "a" (op2));\
1080 printf("%-10s EAX=" FMTLX " A=" FMTLX " C=" FMTLX "\n",\
1081 #op, op2, op0, op1);\
1082}
1083
1084void test_xchg(void)
1085{
1086#if defined(__x86_64__)
1087 TEST_XCHG(xchgq, "", "=q");
1088#endif
1089 TEST_XCHG(xchgl, "k", "=q");
1090 TEST_XCHG(xchgw, "w", "=q");
1091 TEST_XCHG(xchgb, "b", "=q");
1092
1093#if defined(__x86_64__)
1094 TEST_XCHG(xchgq, "", "=m");
1095#endif
1096 TEST_XCHG(xchgl, "k", "=m");
1097 TEST_XCHG(xchgw, "w", "=m");
1098 TEST_XCHG(xchgb, "b", "=m");
1099
1100#if defined(__x86_64__)
1101 TEST_XCHG(xaddq, "", "=q");
1102#endif
1103 TEST_XCHG(xaddl, "k", "=q");
1104 TEST_XCHG(xaddw, "w", "=q");
1105 TEST_XCHG(xaddb, "b", "=q");
1106
1107 {
1108 int res;
1109 res = 0x12345678;
1110 asm("xaddl %1, %0" : "=r" (res) : "0" (res));
1111 printf("xaddl same res=%08x\n", res);
1112 }
1113
1114#if defined(__x86_64__)
1115 TEST_XCHG(xaddq, "", "=m");
1116#endif
1117 TEST_XCHG(xaddl, "k", "=m");
1118 TEST_XCHG(xaddw, "w", "=m");
1119 TEST_XCHG(xaddb, "b", "=m");
1120
1121#if defined(__x86_64__)
1122 TEST_CMPXCHG(cmpxchgq, "", "=q", 0xfbca7654);
1123#endif
1124 TEST_CMPXCHG(cmpxchgl, "k", "=q", 0xfbca7654);
1125 TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfbca7654);
1126 TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfbca7654);
1127
1128#if defined(__x86_64__)
1129 TEST_CMPXCHG(cmpxchgq, "", "=q", 0xfffefdfc);
1130#endif
1131 TEST_CMPXCHG(cmpxchgl, "k", "=q", 0xfffefdfc);
1132 TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfffefdfc);
1133 TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfffefdfc);
1134
1135#if defined(__x86_64__)
1136 TEST_CMPXCHG(cmpxchgq, "", "=m", 0xfbca7654);
1137#endif
1138 TEST_CMPXCHG(cmpxchgl, "k", "=m", 0xfbca7654);
1139 TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfbca7654);
1140 TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfbca7654);
1141
1142#if defined(__x86_64__)
1143 TEST_CMPXCHG(cmpxchgq, "", "=m", 0xfffefdfc);
1144#endif
1145 TEST_CMPXCHG(cmpxchgl, "k", "=m", 0xfffefdfc);
1146 TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfffefdfc);
1147 TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfffefdfc);
1148
1149 {
1150 uint64_t op0, op1, op2;
1151 long i, eflags;
1152
1153 for(i = 0; i < 2; i++) {
1154 op0 = 0x123456789abcd;
1155 if (i == 0)
1156 op1 = 0xfbca765423456;
1157 else
1158 op1 = op0;
1159 op2 = 0x6532432432434;
1160 asm("cmpxchg8b %1\n"
1161 "pushf\n"
1162 "pop %2\n"
1163 : "=A" (op0), "=m" (op1), "=g" (eflags)
1164 : "0" (op0), "m" (op1), "b" ((int)op2), "c" ((int)(op2 >> 32)));
1165 printf("cmpxchg8b: op0=" FMT64X " op1=" FMT64X " CC=%02lx\n",
1166 op0, op1, eflags & CC_Z);
1167 }
1168 }
1169}
1170
1171#ifdef TEST_SEGS
1172/**********************************************/
1173/* segmentation tests */
1174
1175#include <asm/ldt.h>
1176#include <linux/unistd.h>
1177#include <linux/version.h>
1178
1179_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
1180
1181#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
1182#define modify_ldt_ldt_s user_desc
1183#endif
1184
1185#define MK_SEL(n) (((n) << 3) | 7)
1186
1187uint8_t seg_data1[4096];
1188uint8_t seg_data2[4096];
1189
1190#define TEST_LR(op, size, seg, mask)\
1191{\
1192 int res, res2;\
1193 res = 0x12345678;\
1194 asm (op " %" size "2, %" size "0\n" \
1195 "movl $0, %1\n"\
1196 "jnz 1f\n"\
1197 "movl $1, %1\n"\
1198 "1:\n"\
1199 : "=r" (res), "=r" (res2) : "m" (seg), "0" (res));\
1200 printf(op ": Z=%d %08x\n", res2, res & ~(mask));\
1201}
1202
1203/* NOTE: we use Linux modify_ldt syscall */
1204void test_segs(void)
1205{
1206 struct modify_ldt_ldt_s ldt;
1207 long long ldt_table[3];
1208 int res, res2;
1209 char tmp;
1210 struct {
1211 uint32_t offset;
1212 uint16_t seg;
1213 } __attribute__((packed)) segoff;
1214
1215 ldt.entry_number = 1;
1216 ldt.base_addr = (unsigned long)&seg_data1;
1217 ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
1218 ldt.seg_32bit = 1;
1219 ldt.contents = MODIFY_LDT_CONTENTS_DATA;
1220 ldt.read_exec_only = 0;
1221 ldt.limit_in_pages = 1;
1222 ldt.seg_not_present = 0;
1223 ldt.useable = 1;
1224 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
1225
1226 ldt.entry_number = 2;
1227 ldt.base_addr = (unsigned long)&seg_data2;
1228 ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12;
1229 ldt.seg_32bit = 1;
1230 ldt.contents = MODIFY_LDT_CONTENTS_DATA;
1231 ldt.read_exec_only = 0;
1232 ldt.limit_in_pages = 1;
1233 ldt.seg_not_present = 0;
1234 ldt.useable = 1;
1235 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
1236
1237 modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */
1238#if 0
1239 {
1240 int i;
1241 for(i=0;i<3;i++)
1242 printf("%d: %016Lx\n", i, ldt_table[i]);
1243 }
1244#endif
1245 /* do some tests with fs or gs */
1246 asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
1247
1248 seg_data1[1] = 0xaa;
1249 seg_data2[1] = 0x55;
1250
1251 asm volatile ("fs movzbl 0x1, %0" : "=r" (res));
1252 printf("FS[1] = %02x\n", res);
1253
1254 asm volatile ("pushl %%gs\n"
1255 "movl %1, %%gs\n"
1256 "gs movzbl 0x1, %0\n"
1257 "popl %%gs\n"
1258 : "=r" (res)
1259 : "r" (MK_SEL(2)));
1260 printf("GS[1] = %02x\n", res);
1261
1262 /* tests with ds/ss (implicit segment case) */
1263 tmp = 0xa5;
1264 asm volatile ("pushl %%ebp\n\t"
1265 "pushl %%ds\n\t"
1266 "movl %2, %%ds\n\t"
1267 "movl %3, %%ebp\n\t"
1268 "movzbl 0x1, %0\n\t"
1269 "movzbl (%%ebp), %1\n\t"
1270 "popl %%ds\n\t"
1271 "popl %%ebp\n\t"
1272 : "=r" (res), "=r" (res2)
1273 : "r" (MK_SEL(1)), "r" (&tmp));
1274 printf("DS[1] = %02x\n", res);
1275 printf("SS[tmp] = %02x\n", res2);
1276
1277 segoff.seg = MK_SEL(2);
1278 segoff.offset = 0xabcdef12;
1279 asm volatile("lfs %2, %0\n\t"
1280 "movl %%fs, %1\n\t"
1281 : "=r" (res), "=g" (res2)
1282 : "m" (segoff));
1283 printf("FS:reg = %04x:%08x\n", res2, res);
1284
1285 TEST_LR("larw", "w", MK_SEL(2), 0x0100);
1286 TEST_LR("larl", "", MK_SEL(2), 0x0100);
1287 TEST_LR("lslw", "w", MK_SEL(2), 0);
1288 TEST_LR("lsll", "", MK_SEL(2), 0);
1289
1290 TEST_LR("larw", "w", 0xfff8, 0);
1291 TEST_LR("larl", "", 0xfff8, 0);
1292 TEST_LR("lslw", "w", 0xfff8, 0);
1293 TEST_LR("lsll", "", 0xfff8, 0);
1294}
1295
1296/* 16 bit code test */
1297extern char code16_start, code16_end;
1298extern char code16_func1;
1299extern char code16_func2;
1300extern char code16_func3;
1301
1302void test_code16(void)
1303{
1304 struct modify_ldt_ldt_s ldt;
1305 int res, res2;
1306
1307 /* build a code segment */
1308 ldt.entry_number = 1;
1309 ldt.base_addr = (unsigned long)&code16_start;
1310 ldt.limit = &code16_end - &code16_start;
1311 ldt.seg_32bit = 0;
1312 ldt.contents = MODIFY_LDT_CONTENTS_CODE;
1313 ldt.read_exec_only = 0;
1314 ldt.limit_in_pages = 0;
1315 ldt.seg_not_present = 0;
1316 ldt.useable = 1;
1317 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
1318
1319 /* call the first function */
1320 asm volatile ("lcall %1, %2"
1321 : "=a" (res)
1322 : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc");
1323 printf("func1() = 0x%08x\n", res);
1324 asm volatile ("lcall %2, %3"
1325 : "=a" (res), "=c" (res2)
1326 : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc");
1327 printf("func2() = 0x%08x spdec=%d\n", res, res2);
1328 asm volatile ("lcall %1, %2"
1329 : "=a" (res)
1330 : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc");
1331 printf("func3() = 0x%08x\n", res);
1332}
1333#endif
1334
1335#if defined(__x86_64__)
1336asm(".globl func_lret\n"
1337 "func_lret:\n"
1338 "movl $0x87654641, %eax\n"
1339 "lretq\n");
1340#else
1341asm(".globl func_lret\n"
1342 "func_lret:\n"
1343 "movl $0x87654321, %eax\n"
1344 "lret\n"
1345
1346 ".globl func_iret\n"
1347 "func_iret:\n"
1348 "movl $0xabcd4321, %eax\n"
1349 "iret\n");
1350#endif
1351
1352extern char func_lret;
1353extern char func_iret;
1354
1355void test_misc(void)
1356{
1357 char table[256];
1358 long res, i;
1359
1360 for(i=0;i<256;i++) table[i] = 256 - i;
1361 res = 0x12345678;
1362 asm ("xlat" : "=a" (res) : "b" (table), "0" (res));
1363 printf("xlat: EAX=" FMTLX "\n", res);
1364
1365#if defined(__x86_64__)
1366 {
1367 static struct __attribute__((packed)) {
1368 uint32_t offset;
1369 uint16_t seg;
1370 } desc;
1371 long cs_sel;
1372
1373 asm volatile ("mov %%cs, %0" : "=r" (cs_sel));
1374
1375 asm volatile ("push %1\n"
1376 "call func_lret\n"
1377 : "=a" (res)
1378 : "r" (cs_sel) : "memory", "cc");
1379 printf("func_lret=" FMTLX "\n", res);
1380
1381 /* NOTE: we assume that &func_lret < 4GB */
1382 desc.offset = (long)&func_lret;
1383 desc.seg = cs_sel;
1384
1385 asm volatile ("xor %%rax, %%rax\n"
1386 "rex64 lcall %1\n"
1387 : "=a" (res)
1388 : "m" (desc)
1389 : "memory", "cc");
1390 printf("func_lret2=" FMTLX "\n", res);
1391
1392 asm volatile ("push %2\n"
1393 "mov $ 1f, %%rax\n"
1394 "push %%rax\n"
1395 "ljmp %1\n"
1396 "1:\n"
1397 : "=a" (res)
1398 : "m" (desc), "b" (cs_sel)
1399 : "memory", "cc");
1400 printf("func_lret3=" FMTLX "\n", res);
1401 }
1402#else
1403 asm volatile ("push %%cs ; call %1"
1404 : "=a" (res)
1405 : "m" (func_lret): "memory", "cc");
1406 printf("func_lret=" FMTLX "\n", res);
1407
1408 asm volatile ("pushf ; push %%cs ; call %1"
1409 : "=a" (res)
1410 : "m" (func_iret): "memory", "cc");
1411 printf("func_iret=" FMTLX "\n", res);
1412#endif
1413
1414#if defined(__x86_64__)
1415 /* specific popl test */
1416 asm volatile ("push $12345432 ; push $0x9abcdef ; pop (%%rsp) ; pop %0"
1417 : "=g" (res));
1418 printf("popl esp=" FMTLX "\n", res);
1419#else
1420 /* specific popl test */
1421 asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popl (%%esp) ; popl %0"
1422 : "=g" (res));
1423 printf("popl esp=" FMTLX "\n", res);
1424
1425 /* specific popw test */
1426 asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popw (%%esp) ; addl $2, %%esp ; popl %0"
1427 : "=g" (res));
1428 printf("popw esp=" FMTLX "\n", res);
1429#endif
1430}
1431
1432uint8_t str_buffer[4096];
1433
1434#define TEST_STRING1(OP, size, DF, REP)\
1435{\
1436 long esi, edi, eax, ecx, eflags;\
1437\
1438 esi = (long)(str_buffer + sizeof(str_buffer) / 2);\
1439 edi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\
1440 eax = i2l(0x12345678);\
1441 ecx = 17;\
1442\
1443 asm volatile ("push $0\n\t"\
1444 "popf\n\t"\
1445 DF "\n\t"\
1446 REP #OP size "\n\t"\
1447 "cld\n\t"\
1448 "pushf\n\t"\
1449 "pop %4\n\t"\
1450 : "=S" (esi), "=D" (edi), "=a" (eax), "=c" (ecx), "=g" (eflags)\
1451 : "0" (esi), "1" (edi), "2" (eax), "3" (ecx));\
1452 printf("%-10s ESI=" FMTLX " EDI=" FMTLX " EAX=" FMTLX " ECX=" FMTLX " EFL=%04x\n",\
1453 REP #OP size, esi, edi, eax, ecx,\
1454 (int)(eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)));\
1455}
1456
1457#define TEST_STRING(OP, REP)\
1458 TEST_STRING1(OP, "b", "", REP);\
1459 TEST_STRING1(OP, "w", "", REP);\
1460 TEST_STRING1(OP, "l", "", REP);\
1461 X86_64_ONLY(TEST_STRING1(OP, "q", "", REP));\
1462 TEST_STRING1(OP, "b", "std", REP);\
1463 TEST_STRING1(OP, "w", "std", REP);\
1464 TEST_STRING1(OP, "l", "std", REP);\
1465 X86_64_ONLY(TEST_STRING1(OP, "q", "std", REP))
1466
1467void test_string(void)
1468{
1469 int i;
1470 for(i = 0;i < sizeof(str_buffer); i++)
1471 str_buffer[i] = i + 0x56;
1472 TEST_STRING(stos, "");
1473 TEST_STRING(stos, "rep ");
1474 TEST_STRING(lods, ""); /* to verify stos */
1475 TEST_STRING(lods, "rep ");
1476 TEST_STRING(movs, "");
1477 TEST_STRING(movs, "rep ");
1478 TEST_STRING(lods, ""); /* to verify stos */
1479
1480 /* XXX: better tests */
1481 TEST_STRING(scas, "");
1482 TEST_STRING(scas, "repz ");
1483 TEST_STRING(scas, "repnz ");
1484 TEST_STRING(cmps, "");
1485 TEST_STRING(cmps, "repz ");
1486 TEST_STRING(cmps, "repnz ");
1487}
1488
1489#ifdef TEST_VM86
1490/* VM86 test */
1491
1492static inline void set_bit(uint8_t *a, unsigned int bit)
1493{
1494 a[bit / 8] |= (1 << (bit % 8));
1495}
1496
1497static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
1498{
1499 return (uint8_t *)((seg << 4) + (reg & 0xffff));
1500}
1501
1502static inline void pushw(struct vm86_regs *r, int val)
1503{
1504 r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
1505 *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
1506}
1507
1508#undef __syscall_return
1509#define __syscall_return(type, res) \
1510do { \
1511 return (type) (res); \
1512} while (0)
1513
1514_syscall2(int, vm86, int, func, struct vm86plus_struct *, v86)
1515
1516extern char vm86_code_start;
1517extern char vm86_code_end;
1518
1519#define VM86_CODE_CS 0x100
1520#define VM86_CODE_IP 0x100
1521
1522void test_vm86(void)
1523{
1524 struct vm86plus_struct ctx;
1525 struct vm86_regs *r;
1526 uint8_t *vm86_mem;
1527 int seg, ret;
1528
1529 vm86_mem = mmap((void *)0x00000000, 0x110000,
1530 PROT_WRITE | PROT_READ | PROT_EXEC,
1531 MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
1532 if (vm86_mem == MAP_FAILED) {
1533 printf("ERROR: could not map vm86 memory");
1534 return;
1535 }
1536 memset(&ctx, 0, sizeof(ctx));
1537
1538 /* init basic registers */
1539 r = &ctx.regs;
1540 r->eip = VM86_CODE_IP;
1541 r->esp = 0xfffe;
1542 seg = VM86_CODE_CS;
1543 r->cs = seg;
1544 r->ss = seg;
1545 r->ds = seg;
1546 r->es = seg;
1547 r->fs = seg;
1548 r->gs = seg;
1549 r->eflags = VIF_MASK;
1550
1551 /* move code to proper address. We use the same layout as a .com
1552 dos program. */
1553 memcpy(vm86_mem + (VM86_CODE_CS << 4) + VM86_CODE_IP,
1554 &vm86_code_start, &vm86_code_end - &vm86_code_start);
1555
1556 /* mark int 0x21 as being emulated */
1557 set_bit((uint8_t *)&ctx.int_revectored, 0x21);
1558
1559 for(;;) {
1560 ret = vm86(VM86_ENTER, &ctx);
1561 switch(VM86_TYPE(ret)) {
1562 case VM86_INTx:
1563 {
1564 int int_num, ah, v;
1565
1566 int_num = VM86_ARG(ret);
1567 if (int_num != 0x21)
1568 goto unknown_int;
1569 ah = (r->eax >> 8) & 0xff;
1570 switch(ah) {
1571 case 0x00: /* exit */
1572 goto the_end;
1573 case 0x02: /* write char */
1574 {
1575 uint8_t c = r->edx;
1576 putchar(c);
1577 }
1578 break;
1579 case 0x09: /* write string */
1580 {
1581 uint8_t c, *ptr;
1582 ptr = seg_to_linear(r->ds, r->edx);
1583 for(;;) {
1584 c = *ptr++;
1585 if (c == '$')
1586 break;
1587 putchar(c);
1588 }
1589 r->eax = (r->eax & ~0xff) | '$';
1590 }
1591 break;
1592 case 0xff: /* extension: write eflags number in edx */
1593 v = (int)r->edx;
1594#ifndef LINUX_VM86_IOPL_FIX
1595 v &= ~0x3000;
1596#endif
1597 printf("%08x\n", v);
1598 break;
1599 default:
1600 unknown_int:
1601 printf("unsupported int 0x%02x\n", int_num);
1602 goto the_end;
1603 }
1604 }
1605 break;
1606 case VM86_SIGNAL:
1607 /* a signal came, we just ignore that */
1608 break;
1609 case VM86_STI:
1610 break;
1611 default:
1612 printf("ERROR: unhandled vm86 return code (0x%x)\n", ret);
1613 goto the_end;
1614 }
1615 }
1616 the_end:
1617 printf("VM86 end\n");
1618 munmap(vm86_mem, 0x110000);
1619}
1620#endif
1621
1622/* exception tests */
1623#if defined(__i386__) && !defined(REG_EAX)
1624#define REG_EAX EAX
1625#define REG_EBX EBX
1626#define REG_ECX ECX
1627#define REG_EDX EDX
1628#define REG_ESI ESI
1629#define REG_EDI EDI
1630#define REG_EBP EBP
1631#define REG_ESP ESP
1632#define REG_EIP EIP
1633#define REG_EFL EFL
1634#define REG_TRAPNO TRAPNO
1635#define REG_ERR ERR
1636#endif
1637
1638#if defined(__x86_64__)
1639#define REG_EIP REG_RIP
1640#endif
1641
1642jmp_buf jmp_env;
1643int v1;
1644int tab[2];
1645
1646void sig_handler(int sig, siginfo_t *info, void *puc)
1647{
1648 struct ucontext *uc = puc;
1649
1650 printf("si_signo=%d si_errno=%d si_code=%d",
1651 info->si_signo, info->si_errno, info->si_code);
1652 printf(" si_addr=0x%08lx",
1653 (unsigned long)info->si_addr);
1654 printf("\n");
1655
1656 printf("trapno=" FMTLX " err=" FMTLX,
1657 (long)uc->uc_mcontext.gregs[REG_TRAPNO],
1658 (long)uc->uc_mcontext.gregs[REG_ERR]);
1659 printf(" EIP=" FMTLX, (long)uc->uc_mcontext.gregs[REG_EIP]);
1660 printf("\n");
1661 longjmp(jmp_env, 1);
1662}
1663
1664void test_exceptions(void)
1665{
1666 struct sigaction act;
1667 volatile int val;
1668
1669 act.sa_sigaction = sig_handler;
1670 sigemptyset(&act.sa_mask);
1671 act.sa_flags = SA_SIGINFO | SA_NODEFER;
1672 sigaction(SIGFPE, &act, NULL);
1673 sigaction(SIGILL, &act, NULL);
1674 sigaction(SIGSEGV, &act, NULL);
1675 sigaction(SIGBUS, &act, NULL);
1676 sigaction(SIGTRAP, &act, NULL);
1677
1678 /* test division by zero reporting */
1679 printf("DIVZ exception:\n");
1680 if (setjmp(jmp_env) == 0) {
1681 /* now divide by zero */
1682 v1 = 0;
1683 v1 = 2 / v1;
1684 }
1685
1686#if !defined(__x86_64__)
1687 printf("BOUND exception:\n");
1688 if (setjmp(jmp_env) == 0) {
1689 /* bound exception */
1690 tab[0] = 1;
1691 tab[1] = 10;
1692 asm volatile ("bound %0, %1" : : "r" (11), "m" (tab[0]));
1693 }
1694#endif
1695
1696#ifdef TEST_SEGS
1697 printf("segment exceptions:\n");
1698 if (setjmp(jmp_env) == 0) {
1699 /* load an invalid segment */
1700 asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 1));
1701 }
1702 if (setjmp(jmp_env) == 0) {
1703 /* null data segment is valid */
1704 asm volatile ("movl %0, %%fs" : : "r" (3));
1705 /* null stack segment */
1706 asm volatile ("movl %0, %%ss" : : "r" (3));
1707 }
1708
1709 {
1710 struct modify_ldt_ldt_s ldt;
1711 ldt.entry_number = 1;
1712 ldt.base_addr = (unsigned long)&seg_data1;
1713 ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
1714 ldt.seg_32bit = 1;
1715 ldt.contents = MODIFY_LDT_CONTENTS_DATA;
1716 ldt.read_exec_only = 0;
1717 ldt.limit_in_pages = 1;
1718 ldt.seg_not_present = 1;
1719 ldt.useable = 1;
1720 modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
1721
1722 if (setjmp(jmp_env) == 0) {
1723 /* segment not present */
1724 asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
1725 }
1726 }
1727#endif
1728
1729 /* test SEGV reporting */
1730 printf("PF exception:\n");
1731 if (setjmp(jmp_env) == 0) {
1732 val = 1;
1733 /* we add a nop to test a weird PC retrieval case */
1734 asm volatile ("nop");
1735 /* now store in an invalid address */
1736 *(char *)0x1234 = 1;
1737 }
1738
1739 /* test SEGV reporting */
1740 printf("PF exception:\n");
1741 if (setjmp(jmp_env) == 0) {
1742 val = 1;
1743 /* read from an invalid address */
1744 v1 = *(char *)0x1234;
1745 }
1746
1747 /* test illegal instruction reporting */
1748 printf("UD2 exception:\n");
1749 if (setjmp(jmp_env) == 0) {
1750 /* now execute an invalid instruction */
1751 asm volatile("ud2");
1752 }
1753 printf("lock nop exception:\n");
1754 if (setjmp(jmp_env) == 0) {
1755 /* now execute an invalid instruction */
1756 asm volatile("lock nop");
1757 }
1758
1759 printf("INT exception:\n");
1760 if (setjmp(jmp_env) == 0) {
1761 asm volatile ("int $0xfd");
1762 }
1763 if (setjmp(jmp_env) == 0) {
1764 asm volatile ("int $0x01");
1765 }
1766 if (setjmp(jmp_env) == 0) {
1767 asm volatile (".byte 0xcd, 0x03");
1768 }
1769 if (setjmp(jmp_env) == 0) {
1770 asm volatile ("int $0x04");
1771 }
1772 if (setjmp(jmp_env) == 0) {
1773 asm volatile ("int $0x05");
1774 }
1775
1776 printf("INT3 exception:\n");
1777 if (setjmp(jmp_env) == 0) {
1778 asm volatile ("int3");
1779 }
1780
1781 printf("CLI exception:\n");
1782 if (setjmp(jmp_env) == 0) {
1783 asm volatile ("cli");
1784 }
1785
1786 printf("STI exception:\n");
1787 if (setjmp(jmp_env) == 0) {
1788 asm volatile ("cli");
1789 }
1790
1791#if !defined(__x86_64__)
1792 printf("INTO exception:\n");
1793 if (setjmp(jmp_env) == 0) {
1794 /* overflow exception */
1795 asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff));
1796 }
1797#endif
1798
1799 printf("OUTB exception:\n");
1800 if (setjmp(jmp_env) == 0) {
1801 asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0));
1802 }
1803
1804 printf("INB exception:\n");
1805 if (setjmp(jmp_env) == 0) {
1806 asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321));
1807 }
1808
1809 printf("REP OUTSB exception:\n");
1810 if (setjmp(jmp_env) == 0) {
1811 asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1));
1812 }
1813
1814 printf("REP INSB exception:\n");
1815 if (setjmp(jmp_env) == 0) {
1816 asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1));
1817 }
1818
1819 printf("HLT exception:\n");
1820 if (setjmp(jmp_env) == 0) {
1821 asm volatile ("hlt");
1822 }
1823
1824 printf("single step exception:\n");
1825 val = 0;
1826 if (setjmp(jmp_env) == 0) {
1827 asm volatile ("pushf\n"
1828 "orl $0x00100, (%%esp)\n"
1829 "popf\n"
1830 "movl $0xabcd, %0\n"
1831 "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory");
1832 }
1833 printf("val=0x%x\n", val);
1834}
1835
1836#if !defined(__x86_64__)
1837/* specific precise single step test */
1838void sig_trap_handler(int sig, siginfo_t *info, void *puc)
1839{
1840 struct ucontext *uc = puc;
1841 printf("EIP=" FMTLX "\n", (long)uc->uc_mcontext.gregs[REG_EIP]);
1842}
1843
1844const uint8_t sstep_buf1[4] = { 1, 2, 3, 4};
1845uint8_t sstep_buf2[4];
1846
1847void test_single_step(void)
1848{
1849 struct sigaction act;
1850 volatile int val;
1851 int i;
1852
1853 val = 0;
1854 act.sa_sigaction = sig_trap_handler;
1855 sigemptyset(&act.sa_mask);
1856 act.sa_flags = SA_SIGINFO;
1857 sigaction(SIGTRAP, &act, NULL);
1858 asm volatile ("pushf\n"
1859 "orl $0x00100, (%%esp)\n"
1860 "popf\n"
1861 "movl $0xabcd, %0\n"
1862
1863 /* jmp test */
1864 "movl $3, %%ecx\n"
1865 "1:\n"
1866 "addl $1, %0\n"
1867 "decl %%ecx\n"
1868 "jnz 1b\n"
1869
1870 /* movsb: the single step should stop at each movsb iteration */
1871 "movl $sstep_buf1, %%esi\n"
1872 "movl $sstep_buf2, %%edi\n"
1873 "movl $0, %%ecx\n"
1874 "rep movsb\n"
1875 "movl $3, %%ecx\n"
1876 "rep movsb\n"
1877 "movl $1, %%ecx\n"
1878 "rep movsb\n"
1879
1880 /* cmpsb: the single step should stop at each cmpsb iteration */
1881 "movl $sstep_buf1, %%esi\n"
1882 "movl $sstep_buf2, %%edi\n"
1883 "movl $0, %%ecx\n"
1884 "rep cmpsb\n"
1885 "movl $4, %%ecx\n"
1886 "rep cmpsb\n"
1887
1888 /* getpid() syscall: single step should skip one
1889 instruction */
1890 "movl $20, %%eax\n"
1891 "int $0x80\n"
1892 "movl $0, %%eax\n"
1893
1894 /* when modifying SS, trace is not done on the next
1895 instruction */
1896 "movl %%ss, %%ecx\n"
1897 "movl %%ecx, %%ss\n"
1898 "addl $1, %0\n"
1899 "movl $1, %%eax\n"
1900 "movl %%ecx, %%ss\n"
1901 "jmp 1f\n"
1902 "addl $1, %0\n"
1903 "1:\n"
1904 "movl $1, %%eax\n"
1905 "pushl %%ecx\n"
1906 "popl %%ss\n"
1907 "addl $1, %0\n"
1908 "movl $1, %%eax\n"
1909
1910 "pushf\n"
1911 "andl $~0x00100, (%%esp)\n"
1912 "popf\n"
1913 : "=m" (val)
1914 :
1915 : "cc", "memory", "eax", "ecx", "esi", "edi");
1916 printf("val=%d\n", val);
1917 for(i = 0; i < 4; i++)
1918 printf("sstep_buf2[%d] = %d\n", i, sstep_buf2[i]);
1919}
1920
1921/* self modifying code test */
1922uint8_t code[] = {
1923 0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */
1924 0xc3, /* ret */
1925};
1926
1927asm("smc_code2:\n"
1928 "movl 4(%esp), %eax\n"
1929 "movl %eax, smc_patch_addr2 + 1\n"
1930 "nop\n"
1931 "nop\n"
1932 "nop\n"
1933 "nop\n"
1934 "nop\n"
1935 "nop\n"
1936 "nop\n"
1937 "nop\n"
1938 "smc_patch_addr2:\n"
1939 "movl $1, %eax\n"
1940 "ret\n");
1941
1942typedef int FuncType(void);
1943extern int smc_code2(int);
1944void test_self_modifying_code(void)
1945{
1946 int i;
1947
1948 printf("self modifying code:\n");
1949 printf("func1 = 0x%x\n", ((FuncType *)code)());
1950 for(i = 2; i <= 4; i++) {
1951 code[1] = i;
1952 printf("func%d = 0x%x\n", i, ((FuncType *)code)());
1953 }
1954
1955 /* more difficult test : the modified code is just after the
1956 modifying instruction. It is forbidden in Intel specs, but it
1957 is used by old DOS programs */
1958 for(i = 2; i <= 4; i++) {
1959 printf("smc_code2(%d) = %d\n", i, smc_code2(i));
1960 }
1961}
1962#endif
1963
1964long enter_stack[4096];
1965
1966#if defined(__x86_64__)
1967#define RSP "%%rsp"
1968#define RBP "%%rbp"
1969#else
1970#define RSP "%%esp"
1971#define RBP "%%ebp"
1972#endif
1973
1974#define TEST_ENTER(size, stack_type, level)\
1975{\
1976 long esp_save, esp_val, ebp_val, ebp_save, i;\
1977 stack_type *ptr, *stack_end, *stack_ptr;\
1978 memset(enter_stack, 0, sizeof(enter_stack));\
1979 stack_end = stack_ptr = (stack_type *)(enter_stack + 4096);\
1980 ebp_val = (long)stack_ptr;\
1981 for(i=1;i<=32;i++)\
1982 *--stack_ptr = i;\
1983 esp_val = (long)stack_ptr;\
1984 asm("mov " RSP ", %[esp_save]\n"\
1985 "mov " RBP ", %[ebp_save]\n"\
1986 "mov %[esp_val], " RSP "\n"\
1987 "mov %[ebp_val], " RBP "\n"\
1988 "enter" size " $8, $" #level "\n"\
1989 "mov " RSP ", %[esp_val]\n"\
1990 "mov " RBP ", %[ebp_val]\n"\
1991 "mov %[esp_save], " RSP "\n"\
1992 "mov %[ebp_save], " RBP "\n"\
1993 : [esp_save] "=r" (esp_save),\
1994 [ebp_save] "=r" (ebp_save),\
1995 [esp_val] "=r" (esp_val),\
1996 [ebp_val] "=r" (ebp_val)\
1997 : "[esp_val]" (esp_val),\
1998 "[ebp_val]" (ebp_val));\
1999 printf("level=%d:\n", level);\
2000 printf("esp_val=" FMTLX "\n", esp_val - (long)stack_end);\
2001 printf("ebp_val=" FMTLX "\n", ebp_val - (long)stack_end);\
2002 for(ptr = (stack_type *)esp_val; ptr < stack_end; ptr++)\
2003 printf(FMTLX "\n", (long)ptr[0]);\
2004}
2005
2006static void test_enter(void)
2007{
2008#if defined(__x86_64__)
2009 TEST_ENTER("q", uint64_t, 0);
2010 TEST_ENTER("q", uint64_t, 1);
2011 TEST_ENTER("q", uint64_t, 2);
2012 TEST_ENTER("q", uint64_t, 31);
2013#else
2014 TEST_ENTER("l", uint32_t, 0);
2015 TEST_ENTER("l", uint32_t, 1);
2016 TEST_ENTER("l", uint32_t, 2);
2017 TEST_ENTER("l", uint32_t, 31);
2018#endif
2019
2020 TEST_ENTER("w", uint16_t, 0);
2021 TEST_ENTER("w", uint16_t, 1);
2022 TEST_ENTER("w", uint16_t, 2);
2023 TEST_ENTER("w", uint16_t, 31);
2024}
2025
2026#ifdef TEST_SSE
2027
2028typedef int __m64 __attribute__ ((__mode__ (__V2SI__)));
2029typedef int __m128 __attribute__ ((__mode__(__V4SF__)));
2030
2031typedef union {
2032 double d[2];
2033 float s[4];
2034 uint32_t l[4];
2035 uint64_t q[2];
2036 __m128 dq;
2037} XMMReg;
2038
2039static uint64_t __attribute__((aligned(16))) test_values[4][2] = {
2040 { 0x456723c698694873, 0xdc515cff944a58ec },
2041 { 0x1f297ccd58bad7ab, 0x41f21efba9e3e146 },
2042 { 0x007c62c2085427f8, 0x231be9e8cde7438d },
2043 { 0x0f76255a085427f8, 0xc233e9e8c4c9439a },
2044};
2045
2046#define SSE_OP(op)\
2047{\
2048 asm volatile (#op " %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
2049 printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
2050 #op,\
2051 a.q[1], a.q[0],\
2052 b.q[1], b.q[0],\
2053 r.q[1], r.q[0]);\
2054}
2055
2056#define SSE_OP2(op)\
2057{\
2058 int i;\
2059 for(i=0;i<2;i++) {\
2060 a.q[0] = test_values[2*i][0];\
2061 a.q[1] = test_values[2*i][1];\
2062 b.q[0] = test_values[2*i+1][0];\
2063 b.q[1] = test_values[2*i+1][1];\
2064 SSE_OP(op);\
2065 }\
2066}
2067
2068#define MMX_OP2(op)\
2069{\
2070 int i;\
2071 for(i=0;i<2;i++) {\
2072 a.q[0] = test_values[2*i][0];\
2073 b.q[0] = test_values[2*i+1][0];\
2074 asm volatile (#op " %2, %0" : "=y" (r.q[0]) : "0" (a.q[0]), "y" (b.q[0]));\
2075 printf("%-9s: a=" FMT64X " b=" FMT64X " r=" FMT64X "\n",\
2076 #op,\
2077 a.q[0],\
2078 b.q[0],\
2079 r.q[0]);\
2080 }\
2081 SSE_OP2(op);\
2082}
2083
2084#define SHUF_OP(op, ib)\
2085{\
2086 a.q[0] = test_values[0][0];\
2087 a.q[1] = test_values[0][1];\
2088 b.q[0] = test_values[1][0];\
2089 b.q[1] = test_values[1][1];\
2090 asm volatile (#op " $" #ib ", %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
2091 printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
2092 #op,\
2093 a.q[1], a.q[0],\
2094 b.q[1], b.q[0],\
2095 ib,\
2096 r.q[1], r.q[0]);\
2097}
2098
2099#define PSHUF_OP(op, ib)\
2100{\
2101 int i;\
2102 for(i=0;i<2;i++) {\
2103 a.q[0] = test_values[2*i][0];\
2104 a.q[1] = test_values[2*i][1];\
2105 asm volatile (#op " $" #ib ", %1, %0" : "=x" (r.dq) : "x" (a.dq));\
2106 printf("%-9s: a=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
2107 #op,\
2108 a.q[1], a.q[0],\
2109 ib,\
2110 r.q[1], r.q[0]);\
2111 }\
2112}
2113
2114#define SHIFT_IM(op, ib)\
2115{\
2116 int i;\
2117 for(i=0;i<2;i++) {\
2118 a.q[0] = test_values[2*i][0];\
2119 a.q[1] = test_values[2*i][1];\
2120 asm volatile (#op " $" #ib ", %0" : "=x" (r.dq) : "0" (a.dq));\
2121 printf("%-9s: a=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
2122 #op,\
2123 a.q[1], a.q[0],\
2124 ib,\
2125 r.q[1], r.q[0]);\
2126 }\
2127}
2128
2129#define SHIFT_OP(op, ib)\
2130{\
2131 int i;\
2132 SHIFT_IM(op, ib);\
2133 for(i=0;i<2;i++) {\
2134 a.q[0] = test_values[2*i][0];\
2135 a.q[1] = test_values[2*i][1];\
2136 b.q[0] = ib;\
2137 b.q[1] = 0;\
2138 asm volatile (#op " %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
2139 printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
2140 #op,\
2141 a.q[1], a.q[0],\
2142 b.q[1], b.q[0],\
2143 r.q[1], r.q[0]);\
2144 }\
2145}
2146
2147#define MOVMSK(op)\
2148{\
2149 int i, reg;\
2150 for(i=0;i<2;i++) {\
2151 a.q[0] = test_values[2*i][0];\
2152 a.q[1] = test_values[2*i][1];\
2153 asm volatile (#op " %1, %0" : "=r" (reg) : "x" (a.dq));\
2154 printf("%-9s: a=" FMT64X "" FMT64X " r=%08x\n",\
2155 #op,\
2156 a.q[1], a.q[0],\
2157 reg);\
2158 }\
2159}
2160
2161#define SSE_OPS(a) \
2162SSE_OP(a ## ps);\
2163SSE_OP(a ## ss);
2164
2165#define SSE_OPD(a) \
2166SSE_OP(a ## pd);\
2167SSE_OP(a ## sd);
2168
2169#define SSE_COMI(op, field)\
2170{\
2171 unsigned int eflags;\
2172 XMMReg a, b;\
2173 a.field[0] = a1;\
2174 b.field[0] = b1;\
2175 asm volatile (#op " %2, %1\n"\
2176 "pushf\n"\
2177 "pop %0\n"\
2178 : "=m" (eflags)\
2179 : "x" (a.dq), "x" (b.dq));\
2180 printf("%-9s: a=%f b=%f cc=%04x\n",\
2181 #op, a1, b1,\
2182 eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\
2183}
2184
2185void test_sse_comi(double a1, double b1)
2186{
2187 SSE_COMI(ucomiss, s);
2188 SSE_COMI(ucomisd, d);
2189 SSE_COMI(comiss, s);
2190 SSE_COMI(comisd, d);
2191}
2192
2193#define CVT_OP_XMM(op)\
2194{\
2195 asm volatile (#op " %1, %0" : "=x" (r.dq) : "x" (a.dq));\
2196 printf("%-9s: a=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
2197 #op,\
2198 a.q[1], a.q[0],\
2199 r.q[1], r.q[0]);\
2200}
2201
2202/* Force %xmm0 usage to avoid the case where both register index are 0
2203 to test intruction decoding more extensively */
2204#define CVT_OP_XMM2MMX(op)\
2205{\
2206 asm volatile (#op " %1, %0" : "=y" (r.q[0]) : "x" (a.dq) \
2207 : "%xmm0");\
2208 printf("%-9s: a=" FMT64X "" FMT64X " r=" FMT64X "\n",\
2209 #op,\
2210 a.q[1], a.q[0],\
2211 r.q[0]);\
2212}
2213
2214#define CVT_OP_MMX2XMM(op)\
2215{\
2216 asm volatile (#op " %1, %0" : "=x" (r.dq) : "y" (a.q[0]));\
2217 printf("%-9s: a=" FMT64X " r=" FMT64X "" FMT64X "\n",\
2218 #op,\
2219 a.q[0],\
2220 r.q[1], r.q[0]);\
2221}
2222
2223#define CVT_OP_REG2XMM(op)\
2224{\
2225 asm volatile (#op " %1, %0" : "=x" (r.dq) : "r" (a.l[0]));\
2226 printf("%-9s: a=%08x r=" FMT64X "" FMT64X "\n",\
2227 #op,\
2228 a.l[0],\
2229 r.q[1], r.q[0]);\
2230}
2231
2232#define CVT_OP_XMM2REG(op)\
2233{\
2234 asm volatile (#op " %1, %0" : "=r" (r.l[0]) : "x" (a.dq));\
2235 printf("%-9s: a=" FMT64X "" FMT64X " r=%08x\n",\
2236 #op,\
2237 a.q[1], a.q[0],\
2238 r.l[0]);\
2239}
2240
2241struct fpxstate {
2242 uint16_t fpuc;
2243 uint16_t fpus;
2244 uint16_t fptag;
2245 uint16_t fop;
2246 uint32_t fpuip;
2247 uint16_t cs_sel;
2248 uint16_t dummy0;
2249 uint32_t fpudp;
2250 uint16_t ds_sel;
2251 uint16_t dummy1;
2252 uint32_t mxcsr;
2253 uint32_t mxcsr_mask;
2254 uint8_t fpregs1[8 * 16];
2255 uint8_t xmm_regs[8 * 16];
2256 uint8_t dummy2[224];
2257};
2258
2259static struct fpxstate fpx_state __attribute__((aligned(16)));
2260static struct fpxstate fpx_state2 __attribute__((aligned(16)));
2261
2262void test_fxsave(void)
2263{
2264 struct fpxstate *fp = &fpx_state;
2265 struct fpxstate *fp2 = &fpx_state2;
2266 int i, nb_xmm;
2267 XMMReg a, b;
2268 a.q[0] = test_values[0][0];
2269 a.q[1] = test_values[0][1];
2270 b.q[0] = test_values[1][0];
2271 b.q[1] = test_values[1][1];
2272
2273 asm("movdqa %2, %%xmm0\n"
2274 "movdqa %3, %%xmm7\n"
2275#if defined(__x86_64__)
2276 "movdqa %2, %%xmm15\n"
2277#endif
2278 " fld1\n"
2279 " fldpi\n"
2280 " fldln2\n"
2281 " fxsave %0\n"
2282 " fxrstor %0\n"
2283 " fxsave %1\n"
2284 " fninit\n"
2285 : "=m" (*(uint32_t *)fp2), "=m" (*(uint32_t *)fp)
2286 : "m" (a), "m" (b));
2287 printf("fpuc=%04x\n", fp->fpuc);
2288 printf("fpus=%04x\n", fp->fpus);
2289 printf("fptag=%04x\n", fp->fptag);
2290 for(i = 0; i < 3; i++) {
2291 printf("ST%d: " FMT64X " %04x\n",
2292 i,
2293 *(uint64_t *)&fp->fpregs1[i * 16],
2294 *(uint16_t *)&fp->fpregs1[i * 16 + 8]);
2295 }
2296 printf("mxcsr=%08x\n", fp->mxcsr & 0x1f80);
2297#if defined(__x86_64__)
2298 nb_xmm = 16;
2299#else
2300 nb_xmm = 8;
2301#endif
2302 for(i = 0; i < nb_xmm; i++) {
2303 printf("xmm%d: " FMT64X "" FMT64X "\n",
2304 i,
2305 *(uint64_t *)&fp->xmm_regs[i * 16],
2306 *(uint64_t *)&fp->xmm_regs[i * 16 + 8]);
2307 }
2308}
2309
2310void test_sse(void)
2311{
2312 XMMReg r, a, b;
2313 int i;
2314
2315 MMX_OP2(punpcklbw);
2316 MMX_OP2(punpcklwd);
2317 MMX_OP2(punpckldq);
2318 MMX_OP2(packsswb);
2319 MMX_OP2(pcmpgtb);
2320 MMX_OP2(pcmpgtw);
2321 MMX_OP2(pcmpgtd);
2322 MMX_OP2(packuswb);
2323 MMX_OP2(punpckhbw);
2324 MMX_OP2(punpckhwd);
2325 MMX_OP2(punpckhdq);
2326 MMX_OP2(packssdw);
2327 MMX_OP2(pcmpeqb);
2328 MMX_OP2(pcmpeqw);
2329 MMX_OP2(pcmpeqd);
2330
2331 MMX_OP2(paddq);
2332 MMX_OP2(pmullw);
2333 MMX_OP2(psubusb);
2334 MMX_OP2(psubusw);
2335 MMX_OP2(pminub);
2336 MMX_OP2(pand);
2337 MMX_OP2(paddusb);
2338 MMX_OP2(paddusw);
2339 MMX_OP2(pmaxub);
2340 MMX_OP2(pandn);
2341
2342 MMX_OP2(pmulhuw);
2343 MMX_OP2(pmulhw);
2344
2345 MMX_OP2(psubsb);
2346 MMX_OP2(psubsw);
2347 MMX_OP2(pminsw);
2348 MMX_OP2(por);
2349 MMX_OP2(paddsb);
2350 MMX_OP2(paddsw);
2351 MMX_OP2(pmaxsw);
2352 MMX_OP2(pxor);
2353 MMX_OP2(pmuludq);
2354 MMX_OP2(pmaddwd);
2355 MMX_OP2(psadbw);
2356 MMX_OP2(psubb);
2357 MMX_OP2(psubw);
2358 MMX_OP2(psubd);
2359 MMX_OP2(psubq);
2360 MMX_OP2(paddb);
2361 MMX_OP2(paddw);
2362 MMX_OP2(paddd);
2363
2364 MMX_OP2(pavgb);
2365 MMX_OP2(pavgw);
2366
2367 asm volatile ("pinsrw $1, %1, %0" : "=y" (r.q[0]) : "r" (0x12345678));
2368 printf("%-9s: r=" FMT64X "\n", "pinsrw", r.q[0]);
2369
2370 asm volatile ("pinsrw $5, %1, %0" : "=x" (r.dq) : "r" (0x12345678));
2371 printf("%-9s: r=" FMT64X "" FMT64X "\n", "pinsrw", r.q[1], r.q[0]);
2372
2373 a.q[0] = test_values[0][0];
2374 a.q[1] = test_values[0][1];
2375 asm volatile ("pextrw $1, %1, %0" : "=r" (r.l[0]) : "y" (a.q[0]));
2376 printf("%-9s: r=%08x\n", "pextrw", r.l[0]);
2377
2378 asm volatile ("pextrw $5, %1, %0" : "=r" (r.l[0]) : "x" (a.dq));
2379 printf("%-9s: r=%08x\n", "pextrw", r.l[0]);
2380
2381 asm volatile ("pmovmskb %1, %0" : "=r" (r.l[0]) : "y" (a.q[0]));
2382 printf("%-9s: r=%08x\n", "pmovmskb", r.l[0]);
2383
2384 asm volatile ("pmovmskb %1, %0" : "=r" (r.l[0]) : "x" (a.dq));
2385 printf("%-9s: r=%08x\n", "pmovmskb", r.l[0]);
2386
2387 {
2388 r.q[0] = -1;
2389 r.q[1] = -1;
2390
2391 a.q[0] = test_values[0][0];
2392 a.q[1] = test_values[0][1];
2393 b.q[0] = test_values[1][0];
2394 b.q[1] = test_values[1][1];
2395 asm volatile("maskmovq %1, %0" :
2396 : "y" (a.q[0]), "y" (b.q[0]), "D" (&r)
2397 : "memory");
2398 printf("%-9s: r=" FMT64X " a=" FMT64X " b=" FMT64X "\n",
2399 "maskmov",
2400 r.q[0],
2401 a.q[0],
2402 b.q[0]);
2403 asm volatile("maskmovdqu %1, %0" :
2404 : "x" (a.dq), "x" (b.dq), "D" (&r)
2405 : "memory");
2406 printf("%-9s: r=" FMT64X "" FMT64X " a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X "\n",
2407 "maskmov",
2408 r.q[1], r.q[0],
2409 a.q[1], a.q[0],
2410 b.q[1], b.q[0]);
2411 }
2412
2413 asm volatile ("emms");
2414
2415 SSE_OP2(punpcklqdq);
2416 SSE_OP2(punpckhqdq);
2417 SSE_OP2(andps);
2418 SSE_OP2(andpd);
2419 SSE_OP2(andnps);
2420 SSE_OP2(andnpd);
2421 SSE_OP2(orps);
2422 SSE_OP2(orpd);
2423 SSE_OP2(xorps);
2424 SSE_OP2(xorpd);
2425
2426 SSE_OP2(unpcklps);
2427 SSE_OP2(unpcklpd);
2428 SSE_OP2(unpckhps);
2429 SSE_OP2(unpckhpd);
2430
2431 SHUF_OP(shufps, 0x78);
2432 SHUF_OP(shufpd, 0x02);
2433
2434 PSHUF_OP(pshufd, 0x78);
2435 PSHUF_OP(pshuflw, 0x78);
2436 PSHUF_OP(pshufhw, 0x78);
2437
2438 SHIFT_OP(psrlw, 7);
2439 SHIFT_OP(psrlw, 16);
2440 SHIFT_OP(psraw, 7);
2441 SHIFT_OP(psraw, 16);
2442 SHIFT_OP(psllw, 7);
2443 SHIFT_OP(psllw, 16);
2444
2445 SHIFT_OP(psrld, 7);
2446 SHIFT_OP(psrld, 32);
2447 SHIFT_OP(psrad, 7);
2448 SHIFT_OP(psrad, 32);
2449 SHIFT_OP(pslld, 7);
2450 SHIFT_OP(pslld, 32);
2451
2452 SHIFT_OP(psrlq, 7);
2453 SHIFT_OP(psrlq, 32);
2454 SHIFT_OP(psllq, 7);
2455 SHIFT_OP(psllq, 32);
2456
2457 SHIFT_IM(psrldq, 16);
2458 SHIFT_IM(psrldq, 7);
2459 SHIFT_IM(pslldq, 16);
2460 SHIFT_IM(pslldq, 7);
2461
2462 MOVMSK(movmskps);
2463 MOVMSK(movmskpd);
2464
2465 /* FPU specific ops */
2466
2467 {
2468 uint32_t mxcsr;
2469 asm volatile("stmxcsr %0" : "=m" (mxcsr));
2470 printf("mxcsr=%08x\n", mxcsr & 0x1f80);
2471 asm volatile("ldmxcsr %0" : : "m" (mxcsr));
2472 }
2473
2474 test_sse_comi(2, -1);
2475 test_sse_comi(2, 2);
2476 test_sse_comi(2, 3);
2477 test_sse_comi(2, q_nan.d);
2478 test_sse_comi(q_nan.d, -1);
2479
2480 for(i = 0; i < 2; i++) {
2481 a.s[0] = 2.7;
2482 a.s[1] = 3.4;
2483 a.s[2] = 4;
2484 a.s[3] = -6.3;
2485 b.s[0] = 45.7;
2486 b.s[1] = 353.4;
2487 b.s[2] = 4;
2488 b.s[3] = 56.3;
2489 if (i == 1) {
2490 a.s[0] = q_nan.d;
2491 b.s[3] = q_nan.d;
2492 }
2493
2494 SSE_OPS(add);
2495 SSE_OPS(mul);
2496 SSE_OPS(sub);
2497 SSE_OPS(min);
2498 SSE_OPS(div);
2499 SSE_OPS(max);
2500 SSE_OPS(sqrt);
2501 SSE_OPS(cmpeq);
2502 SSE_OPS(cmplt);
2503 SSE_OPS(cmple);
2504 SSE_OPS(cmpunord);
2505 SSE_OPS(cmpneq);
2506 SSE_OPS(cmpnlt);
2507 SSE_OPS(cmpnle);
2508 SSE_OPS(cmpord);
2509
2510
2511 a.d[0] = 2.7;
2512 a.d[1] = -3.4;
2513 b.d[0] = 45.7;
2514 b.d[1] = -53.4;
2515 if (i == 1) {
2516 a.d[0] = q_nan.d;
2517 b.d[1] = q_nan.d;
2518 }
2519 SSE_OPD(add);
2520 SSE_OPD(mul);
2521 SSE_OPD(sub);
2522 SSE_OPD(min);
2523 SSE_OPD(div);
2524 SSE_OPD(max);
2525 SSE_OPD(sqrt);
2526 SSE_OPD(cmpeq);
2527 SSE_OPD(cmplt);
2528 SSE_OPD(cmple);
2529 SSE_OPD(cmpunord);
2530 SSE_OPD(cmpneq);
2531 SSE_OPD(cmpnlt);
2532 SSE_OPD(cmpnle);
2533 SSE_OPD(cmpord);
2534 }
2535
2536 /* float to float/int */
2537 a.s[0] = 2.7;
2538 a.s[1] = 3.4;
2539 a.s[2] = 4;
2540 a.s[3] = -6.3;
2541 CVT_OP_XMM(cvtps2pd);
2542 CVT_OP_XMM(cvtss2sd);
2543 CVT_OP_XMM2MMX(cvtps2pi);
2544 CVT_OP_XMM2MMX(cvttps2pi);
2545 CVT_OP_XMM2REG(cvtss2si);
2546 CVT_OP_XMM2REG(cvttss2si);
2547 CVT_OP_XMM(cvtps2dq);
2548 CVT_OP_XMM(cvttps2dq);
2549
2550 a.d[0] = 2.6;
2551 a.d[1] = -3.4;
2552 CVT_OP_XMM(cvtpd2ps);
2553 CVT_OP_XMM(cvtsd2ss);
2554 CVT_OP_XMM2MMX(cvtpd2pi);
2555 CVT_OP_XMM2MMX(cvttpd2pi);
2556 CVT_OP_XMM2REG(cvtsd2si);
2557 CVT_OP_XMM2REG(cvttsd2si);
2558 CVT_OP_XMM(cvtpd2dq);
2559 CVT_OP_XMM(cvttpd2dq);
2560
2561 /* sse/mmx moves */
2562 CVT_OP_XMM2MMX(movdq2q);
2563 CVT_OP_MMX2XMM(movq2dq);
2564
2565 /* int to float */
2566 a.l[0] = -6;
2567 a.l[1] = 2;
2568 a.l[2] = 100;
2569 a.l[3] = -60000;
2570 CVT_OP_MMX2XMM(cvtpi2ps);
2571 CVT_OP_MMX2XMM(cvtpi2pd);
2572 CVT_OP_REG2XMM(cvtsi2ss);
2573 CVT_OP_REG2XMM(cvtsi2sd);
2574 CVT_OP_XMM(cvtdq2ps);
2575 CVT_OP_XMM(cvtdq2pd);
2576
2577 /* XXX: test PNI insns */
2578#if 0
2579 SSE_OP2(movshdup);
2580#endif
2581 asm volatile ("emms");
2582}
2583
2584#endif
2585
2586extern void *__start_initcall;
2587extern void *__stop_initcall;
2588
2589
2590int main(int argc, char **argv)
2591{
2592 void **ptr;
2593 void (*func)(void);
2594
2595 ptr = &__start_initcall;
2596 while (ptr != &__stop_initcall) {
2597 func = *ptr++;
2598 func();
2599 }
2600 test_bsx();
2601 test_mul();
2602 test_jcc();
2603 test_floats();
2604#if !defined(__x86_64__)
2605 test_bcd();
2606#endif
2607 test_xchg();
2608 test_string();
2609 test_misc();
2610 test_lea();
2611#ifdef TEST_SEGS
2612 test_segs();
2613 test_code16();
2614#endif
2615#ifdef TEST_VM86
2616 test_vm86();
2617#endif
2618 test_exceptions();
2619#if !defined(__x86_64__)
2620 test_self_modifying_code();
2621 test_single_step();
2622#endif
2623 test_enter();
2624#ifdef TEST_SSE
2625 test_sse();
2626 test_fxsave();
2627#endif
2628 return 0;
2629}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette