VirtualBox

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

Last change on this file since 36143 was 36140, checked in by vboxsync, 14 years ago

rem: Re-synced to svn://svn.savannah.nongnu.org/qemu/trunk@5495 (repo UUID c046a42c-6fe2-441c-8c8c-71466251a162).

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