xref: /openbmc/qemu/tests/tcg/i386/test-i386.c (revision 9360070196789cc8b9404b2efaf319384e64b107)
14132431fSAlex Bennée /*
24132431fSAlex Bennée  *  x86 CPU test
34132431fSAlex Bennée  *
44132431fSAlex Bennée  *  Copyright (c) 2003 Fabrice Bellard
54132431fSAlex Bennée  *
64132431fSAlex Bennée  *  This program is free software; you can redistribute it and/or modify
74132431fSAlex Bennée  *  it under the terms of the GNU General Public License as published by
84132431fSAlex Bennée  *  the Free Software Foundation; either version 2 of the License, or
94132431fSAlex Bennée  *  (at your option) any later version.
104132431fSAlex Bennée  *
114132431fSAlex Bennée  *  This program is distributed in the hope that it will be useful,
124132431fSAlex Bennée  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
134132431fSAlex Bennée  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
144132431fSAlex Bennée  *  GNU General Public License for more details.
154132431fSAlex Bennée  *
164132431fSAlex Bennée  *  You should have received a copy of the GNU General Public License
174132431fSAlex Bennée  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
184132431fSAlex Bennée  */
194132431fSAlex Bennée #define _GNU_SOURCE
204132431fSAlex Bennée #include <stdlib.h>
214132431fSAlex Bennée #include <stdio.h>
224132431fSAlex Bennée #include <string.h>
234132431fSAlex Bennée #include <inttypes.h>
244132431fSAlex Bennée #include <math.h>
254132431fSAlex Bennée #include <signal.h>
264132431fSAlex Bennée #include <setjmp.h>
274132431fSAlex Bennée #include <errno.h>
284132431fSAlex Bennée #include <sys/ucontext.h>
294132431fSAlex Bennée #include <sys/mman.h>
304132431fSAlex Bennée 
314132431fSAlex Bennée #if !defined(__x86_64__)
324132431fSAlex Bennée //#define TEST_VM86
334132431fSAlex Bennée #define TEST_SEGS
344132431fSAlex Bennée #endif
354132431fSAlex Bennée //#define LINUX_VM86_IOPL_FIX
364132431fSAlex Bennée //#define TEST_P4_FLAGS
374132431fSAlex Bennée #define TEST_CMOV  1
384132431fSAlex Bennée #define TEST_FCOMI 1
394132431fSAlex Bennée 
404132431fSAlex Bennée #if defined(__x86_64__)
414132431fSAlex Bennée #define FMT64X "%016lx"
424132431fSAlex Bennée #define FMTLX "%016lx"
434132431fSAlex Bennée #define X86_64_ONLY(x) x
444132431fSAlex Bennée #else
454132431fSAlex Bennée #define FMT64X "%016" PRIx64
464132431fSAlex Bennée #define FMTLX "%08lx"
474132431fSAlex Bennée #define X86_64_ONLY(x)
484132431fSAlex Bennée #endif
494132431fSAlex Bennée 
504132431fSAlex Bennée #ifdef TEST_VM86
514132431fSAlex Bennée #include <asm/vm86.h>
524132431fSAlex Bennée #endif
534132431fSAlex Bennée 
544132431fSAlex Bennée #define xglue(x, y) x ## y
554132431fSAlex Bennée #define glue(x, y) xglue(x, y)
564132431fSAlex Bennée #define stringify(s)	tostring(s)
574132431fSAlex Bennée #define tostring(s)	#s
584132431fSAlex Bennée 
594132431fSAlex Bennée #define CC_C   	0x0001
604132431fSAlex Bennée #define CC_P 	0x0004
614132431fSAlex Bennée #define CC_A	0x0010
624132431fSAlex Bennée #define CC_Z	0x0040
634132431fSAlex Bennée #define CC_S    0x0080
644132431fSAlex Bennée #define CC_O    0x0800
654132431fSAlex Bennée 
664132431fSAlex Bennée #define __init_call	__attribute__ ((unused,__section__ ("initcall")))
674132431fSAlex Bennée 
684132431fSAlex Bennée #define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
694132431fSAlex Bennée 
704132431fSAlex Bennée #if defined(__x86_64__)
i2l(long v)714132431fSAlex Bennée static inline long i2l(long v)
724132431fSAlex Bennée {
734132431fSAlex Bennée     return v | ((v ^ 0xabcd) << 32);
744132431fSAlex Bennée }
754132431fSAlex Bennée #else
i2l(long v)764132431fSAlex Bennée static inline long i2l(long v)
774132431fSAlex Bennée {
784132431fSAlex Bennée     return v;
794132431fSAlex Bennée }
804132431fSAlex Bennée #endif
814132431fSAlex Bennée 
824132431fSAlex Bennée #define OP add
834132431fSAlex Bennée #include "test-i386.h"
844132431fSAlex Bennée 
854132431fSAlex Bennée #define OP sub
864132431fSAlex Bennée #include "test-i386.h"
874132431fSAlex Bennée 
884132431fSAlex Bennée #define OP xor
894132431fSAlex Bennée #include "test-i386.h"
904132431fSAlex Bennée 
914132431fSAlex Bennée #define OP and
924132431fSAlex Bennée #include "test-i386.h"
934132431fSAlex Bennée 
944132431fSAlex Bennée #define OP or
954132431fSAlex Bennée #include "test-i386.h"
964132431fSAlex Bennée 
974132431fSAlex Bennée #define OP cmp
984132431fSAlex Bennée #include "test-i386.h"
994132431fSAlex Bennée 
1004132431fSAlex Bennée #define OP adc
1014132431fSAlex Bennée #define OP_CC
1024132431fSAlex Bennée #include "test-i386.h"
1034132431fSAlex Bennée 
1044132431fSAlex Bennée #define OP sbb
1054132431fSAlex Bennée #define OP_CC
1064132431fSAlex Bennée #include "test-i386.h"
1074132431fSAlex Bennée 
1084132431fSAlex Bennée #define OP inc
1094132431fSAlex Bennée #define OP_CC
1104132431fSAlex Bennée #define OP1
1114132431fSAlex Bennée #include "test-i386.h"
1124132431fSAlex Bennée 
1134132431fSAlex Bennée #define OP dec
1144132431fSAlex Bennée #define OP_CC
1154132431fSAlex Bennée #define OP1
1164132431fSAlex Bennée #include "test-i386.h"
1174132431fSAlex Bennée 
1184132431fSAlex Bennée #define OP neg
1194132431fSAlex Bennée #define OP_CC
1204132431fSAlex Bennée #define OP1
1214132431fSAlex Bennée #include "test-i386.h"
1224132431fSAlex Bennée 
1234132431fSAlex Bennée #define OP not
1244132431fSAlex Bennée #define OP_CC
1254132431fSAlex Bennée #define OP1
1264132431fSAlex Bennée #include "test-i386.h"
1274132431fSAlex Bennée 
1284132431fSAlex Bennée #undef CC_MASK
1294132431fSAlex Bennée #define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)
1304132431fSAlex Bennée 
1314132431fSAlex Bennée #define OP shl
1324132431fSAlex Bennée #include "test-i386-shift.h"
1334132431fSAlex Bennée 
1344132431fSAlex Bennée #define OP shr
1354132431fSAlex Bennée #include "test-i386-shift.h"
1364132431fSAlex Bennée 
1374132431fSAlex Bennée #define OP sar
1384132431fSAlex Bennée #include "test-i386-shift.h"
1394132431fSAlex Bennée 
1404132431fSAlex Bennée #define OP rol
1414132431fSAlex Bennée #include "test-i386-shift.h"
1424132431fSAlex Bennée 
1434132431fSAlex Bennée #define OP ror
1444132431fSAlex Bennée #include "test-i386-shift.h"
1454132431fSAlex Bennée 
1464132431fSAlex Bennée #define OP rcr
1474132431fSAlex Bennée #define OP_CC
1484132431fSAlex Bennée #include "test-i386-shift.h"
1494132431fSAlex Bennée 
1504132431fSAlex Bennée #define OP rcl
1514132431fSAlex Bennée #define OP_CC
1524132431fSAlex Bennée #include "test-i386-shift.h"
1534132431fSAlex Bennée 
1544132431fSAlex Bennée #define OP shld
1554132431fSAlex Bennée #define OP_SHIFTD
1564132431fSAlex Bennée #define OP_NOBYTE
1574132431fSAlex Bennée #include "test-i386-shift.h"
1584132431fSAlex Bennée 
1594132431fSAlex Bennée #define OP shrd
1604132431fSAlex Bennée #define OP_SHIFTD
1614132431fSAlex Bennée #define OP_NOBYTE
1624132431fSAlex Bennée #include "test-i386-shift.h"
1634132431fSAlex Bennée 
1644132431fSAlex Bennée /* XXX: should be more precise ? */
1654132431fSAlex Bennée #undef CC_MASK
1664132431fSAlex Bennée #define CC_MASK (CC_C)
1674132431fSAlex Bennée 
1684132431fSAlex Bennée #define OP bt
1694132431fSAlex Bennée #define OP_NOBYTE
1704132431fSAlex Bennée #include "test-i386-shift.h"
1714132431fSAlex Bennée 
1724132431fSAlex Bennée #define OP bts
1734132431fSAlex Bennée #define OP_NOBYTE
1744132431fSAlex Bennée #include "test-i386-shift.h"
1754132431fSAlex Bennée 
1764132431fSAlex Bennée #define OP btr
1774132431fSAlex Bennée #define OP_NOBYTE
1784132431fSAlex Bennée #include "test-i386-shift.h"
1794132431fSAlex Bennée 
1804132431fSAlex Bennée #define OP btc
1814132431fSAlex Bennée #define OP_NOBYTE
1824132431fSAlex Bennée #include "test-i386-shift.h"
1834132431fSAlex Bennée 
1844132431fSAlex Bennée /* lea test (modrm support) */
1854132431fSAlex Bennée #define TEST_LEAQ(STR)\
1864132431fSAlex Bennée {\
1874132431fSAlex Bennée     asm("lea " STR ", %0"\
1884132431fSAlex Bennée         : "=r" (res)\
1894132431fSAlex Bennée         : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
1904132431fSAlex Bennée     printf("lea %s = " FMTLX "\n", STR, res);\
1914132431fSAlex Bennée }
1924132431fSAlex Bennée 
1934132431fSAlex Bennée #define TEST_LEA(STR)\
1944132431fSAlex Bennée {\
1954132431fSAlex Bennée     asm("lea " STR ", %0"\
1964132431fSAlex Bennée         : "=r" (res)\
1974132431fSAlex Bennée         : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
1984132431fSAlex Bennée     printf("lea %s = " FMTLX "\n", STR, res);\
1994132431fSAlex Bennée }
2004132431fSAlex Bennée 
2014132431fSAlex Bennée #define TEST_LEA16(STR)\
2024132431fSAlex Bennée {\
2034132431fSAlex Bennée     asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\
2044132431fSAlex Bennée         : "=r" (res)\
2054132431fSAlex Bennée         : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
2064132431fSAlex Bennée     printf("lea %s = %08lx\n", STR, res);\
2074132431fSAlex Bennée }
2084132431fSAlex Bennée 
2094132431fSAlex Bennée 
test_lea(void)2104132431fSAlex Bennée void test_lea(void)
2114132431fSAlex Bennée {
2124132431fSAlex Bennée     long eax, ebx, ecx, edx, esi, edi, res;
2134132431fSAlex Bennée     eax = i2l(0x0001);
2144132431fSAlex Bennée     ebx = i2l(0x0002);
2154132431fSAlex Bennée     ecx = i2l(0x0004);
2164132431fSAlex Bennée     edx = i2l(0x0008);
2174132431fSAlex Bennée     esi = i2l(0x0010);
2184132431fSAlex Bennée     edi = i2l(0x0020);
2194132431fSAlex Bennée 
2204132431fSAlex Bennée     TEST_LEA("0x4000");
2214132431fSAlex Bennée 
2224132431fSAlex Bennée     TEST_LEA("(%%eax)");
2234132431fSAlex Bennée     TEST_LEA("(%%ebx)");
2244132431fSAlex Bennée     TEST_LEA("(%%ecx)");
2254132431fSAlex Bennée     TEST_LEA("(%%edx)");
2264132431fSAlex Bennée     TEST_LEA("(%%esi)");
2274132431fSAlex Bennée     TEST_LEA("(%%edi)");
2284132431fSAlex Bennée 
2294132431fSAlex Bennée     TEST_LEA("0x40(%%eax)");
2304132431fSAlex Bennée     TEST_LEA("0x40(%%ebx)");
2314132431fSAlex Bennée     TEST_LEA("0x40(%%ecx)");
2324132431fSAlex Bennée     TEST_LEA("0x40(%%edx)");
2334132431fSAlex Bennée     TEST_LEA("0x40(%%esi)");
2344132431fSAlex Bennée     TEST_LEA("0x40(%%edi)");
2354132431fSAlex Bennée 
2364132431fSAlex Bennée     TEST_LEA("0x4000(%%eax)");
2374132431fSAlex Bennée     TEST_LEA("0x4000(%%ebx)");
2384132431fSAlex Bennée     TEST_LEA("0x4000(%%ecx)");
2394132431fSAlex Bennée     TEST_LEA("0x4000(%%edx)");
2404132431fSAlex Bennée     TEST_LEA("0x4000(%%esi)");
2414132431fSAlex Bennée     TEST_LEA("0x4000(%%edi)");
2424132431fSAlex Bennée 
2434132431fSAlex Bennée     TEST_LEA("(%%eax, %%ecx)");
2444132431fSAlex Bennée     TEST_LEA("(%%ebx, %%edx)");
2454132431fSAlex Bennée     TEST_LEA("(%%ecx, %%ecx)");
2464132431fSAlex Bennée     TEST_LEA("(%%edx, %%ecx)");
2474132431fSAlex Bennée     TEST_LEA("(%%esi, %%ecx)");
2484132431fSAlex Bennée     TEST_LEA("(%%edi, %%ecx)");
2494132431fSAlex Bennée 
2504132431fSAlex Bennée     TEST_LEA("0x40(%%eax, %%ecx)");
2514132431fSAlex Bennée     TEST_LEA("0x4000(%%ebx, %%edx)");
2524132431fSAlex Bennée 
2534132431fSAlex Bennée     TEST_LEA("(%%ecx, %%ecx, 2)");
2544132431fSAlex Bennée     TEST_LEA("(%%edx, %%ecx, 4)");
2554132431fSAlex Bennée     TEST_LEA("(%%esi, %%ecx, 8)");
2564132431fSAlex Bennée 
2574132431fSAlex Bennée     TEST_LEA("(,%%eax, 2)");
2584132431fSAlex Bennée     TEST_LEA("(,%%ebx, 4)");
2594132431fSAlex Bennée     TEST_LEA("(,%%ecx, 8)");
2604132431fSAlex Bennée 
2614132431fSAlex Bennée     TEST_LEA("0x40(,%%eax, 2)");
2624132431fSAlex Bennée     TEST_LEA("0x40(,%%ebx, 4)");
2634132431fSAlex Bennée     TEST_LEA("0x40(,%%ecx, 8)");
2644132431fSAlex Bennée 
2654132431fSAlex Bennée 
2664132431fSAlex Bennée     TEST_LEA("-10(%%ecx, %%ecx, 2)");
2674132431fSAlex Bennée     TEST_LEA("-10(%%edx, %%ecx, 4)");
2684132431fSAlex Bennée     TEST_LEA("-10(%%esi, %%ecx, 8)");
2694132431fSAlex Bennée 
2704132431fSAlex Bennée     TEST_LEA("0x4000(%%ecx, %%ecx, 2)");
2714132431fSAlex Bennée     TEST_LEA("0x4000(%%edx, %%ecx, 4)");
2724132431fSAlex Bennée     TEST_LEA("0x4000(%%esi, %%ecx, 8)");
2734132431fSAlex Bennée 
2744132431fSAlex Bennée #if defined(__x86_64__)
2754132431fSAlex Bennée     TEST_LEAQ("0x4000");
2764132431fSAlex Bennée     TEST_LEAQ("0x4000(%%rip)");
2774132431fSAlex Bennée 
2784132431fSAlex Bennée     TEST_LEAQ("(%%rax)");
2794132431fSAlex Bennée     TEST_LEAQ("(%%rbx)");
2804132431fSAlex Bennée     TEST_LEAQ("(%%rcx)");
2814132431fSAlex Bennée     TEST_LEAQ("(%%rdx)");
2824132431fSAlex Bennée     TEST_LEAQ("(%%rsi)");
2834132431fSAlex Bennée     TEST_LEAQ("(%%rdi)");
2844132431fSAlex Bennée 
2854132431fSAlex Bennée     TEST_LEAQ("0x40(%%rax)");
2864132431fSAlex Bennée     TEST_LEAQ("0x40(%%rbx)");
2874132431fSAlex Bennée     TEST_LEAQ("0x40(%%rcx)");
2884132431fSAlex Bennée     TEST_LEAQ("0x40(%%rdx)");
2894132431fSAlex Bennée     TEST_LEAQ("0x40(%%rsi)");
2904132431fSAlex Bennée     TEST_LEAQ("0x40(%%rdi)");
2914132431fSAlex Bennée 
2924132431fSAlex Bennée     TEST_LEAQ("0x4000(%%rax)");
2934132431fSAlex Bennée     TEST_LEAQ("0x4000(%%rbx)");
2944132431fSAlex Bennée     TEST_LEAQ("0x4000(%%rcx)");
2954132431fSAlex Bennée     TEST_LEAQ("0x4000(%%rdx)");
2964132431fSAlex Bennée     TEST_LEAQ("0x4000(%%rsi)");
2974132431fSAlex Bennée     TEST_LEAQ("0x4000(%%rdi)");
2984132431fSAlex Bennée 
2994132431fSAlex Bennée     TEST_LEAQ("(%%rax, %%rcx)");
3004132431fSAlex Bennée     TEST_LEAQ("(%%rbx, %%rdx)");
3014132431fSAlex Bennée     TEST_LEAQ("(%%rcx, %%rcx)");
3024132431fSAlex Bennée     TEST_LEAQ("(%%rdx, %%rcx)");
3034132431fSAlex Bennée     TEST_LEAQ("(%%rsi, %%rcx)");
3044132431fSAlex Bennée     TEST_LEAQ("(%%rdi, %%rcx)");
3054132431fSAlex Bennée 
3064132431fSAlex Bennée     TEST_LEAQ("0x40(%%rax, %%rcx)");
3074132431fSAlex Bennée     TEST_LEAQ("0x4000(%%rbx, %%rdx)");
3084132431fSAlex Bennée 
3094132431fSAlex Bennée     TEST_LEAQ("(%%rcx, %%rcx, 2)");
3104132431fSAlex Bennée     TEST_LEAQ("(%%rdx, %%rcx, 4)");
3114132431fSAlex Bennée     TEST_LEAQ("(%%rsi, %%rcx, 8)");
3124132431fSAlex Bennée 
3134132431fSAlex Bennée     TEST_LEAQ("(,%%rax, 2)");
3144132431fSAlex Bennée     TEST_LEAQ("(,%%rbx, 4)");
3154132431fSAlex Bennée     TEST_LEAQ("(,%%rcx, 8)");
3164132431fSAlex Bennée 
3174132431fSAlex Bennée     TEST_LEAQ("0x40(,%%rax, 2)");
3184132431fSAlex Bennée     TEST_LEAQ("0x40(,%%rbx, 4)");
3194132431fSAlex Bennée     TEST_LEAQ("0x40(,%%rcx, 8)");
3204132431fSAlex Bennée 
3214132431fSAlex Bennée 
3224132431fSAlex Bennée     TEST_LEAQ("-10(%%rcx, %%rcx, 2)");
3234132431fSAlex Bennée     TEST_LEAQ("-10(%%rdx, %%rcx, 4)");
3244132431fSAlex Bennée     TEST_LEAQ("-10(%%rsi, %%rcx, 8)");
3254132431fSAlex Bennée 
3264132431fSAlex Bennée     TEST_LEAQ("0x4000(%%rcx, %%rcx, 2)");
3274132431fSAlex Bennée     TEST_LEAQ("0x4000(%%rdx, %%rcx, 4)");
3284132431fSAlex Bennée     TEST_LEAQ("0x4000(%%rsi, %%rcx, 8)");
3294132431fSAlex Bennée #else
3304132431fSAlex Bennée     /* limited 16 bit addressing test */
3314132431fSAlex Bennée     TEST_LEA16("0x4000");
3324132431fSAlex Bennée     TEST_LEA16("(%%bx)");
3334132431fSAlex Bennée     TEST_LEA16("(%%si)");
3344132431fSAlex Bennée     TEST_LEA16("(%%di)");
3354132431fSAlex Bennée     TEST_LEA16("0x40(%%bx)");
3364132431fSAlex Bennée     TEST_LEA16("0x40(%%si)");
3374132431fSAlex Bennée     TEST_LEA16("0x40(%%di)");
3384132431fSAlex Bennée     TEST_LEA16("0x4000(%%bx)");
3394132431fSAlex Bennée     TEST_LEA16("0x4000(%%si)");
3404132431fSAlex Bennée     TEST_LEA16("(%%bx,%%si)");
3414132431fSAlex Bennée     TEST_LEA16("(%%bx,%%di)");
3424132431fSAlex Bennée     TEST_LEA16("0x40(%%bx,%%si)");
3434132431fSAlex Bennée     TEST_LEA16("0x40(%%bx,%%di)");
3444132431fSAlex Bennée     TEST_LEA16("0x4000(%%bx,%%si)");
3454132431fSAlex Bennée     TEST_LEA16("0x4000(%%bx,%%di)");
3464132431fSAlex Bennée #endif
3474132431fSAlex Bennée }
3484132431fSAlex Bennée 
3494132431fSAlex Bennée #define TEST_JCC(JCC, v1, v2)\
3504132431fSAlex Bennée {\
3514132431fSAlex Bennée     int res;\
3524132431fSAlex Bennée     asm("movl $1, %0\n\t"\
3534132431fSAlex Bennée         "cmpl %2, %1\n\t"\
3544132431fSAlex Bennée         "j" JCC " 1f\n\t"\
3554132431fSAlex Bennée         "movl $0, %0\n\t"\
3564132431fSAlex Bennée         "1:\n\t"\
3574132431fSAlex Bennée         : "=r" (res)\
3584132431fSAlex Bennée         : "r" (v1), "r" (v2));\
3594132431fSAlex Bennée     printf("%-10s %d\n", "j" JCC, res);\
3604132431fSAlex Bennée \
3614132431fSAlex Bennée     asm("movl $0, %0\n\t"\
3624132431fSAlex Bennée         "cmpl %2, %1\n\t"\
3634132431fSAlex Bennée         "set" JCC " %b0\n\t"\
3644132431fSAlex Bennée         : "=r" (res)\
3654132431fSAlex Bennée         : "r" (v1), "r" (v2));\
3664132431fSAlex Bennée     printf("%-10s %d\n", "set" JCC, res);\
3674132431fSAlex Bennée  if (TEST_CMOV) {\
3684132431fSAlex Bennée     long val = i2l(1);\
3694132431fSAlex Bennée     long res = i2l(0x12345678);\
3704132431fSAlex Bennée X86_64_ONLY(\
3714132431fSAlex Bennée     asm("cmpl %2, %1\n\t"\
3724132431fSAlex Bennée         "cmov" JCC "q %3, %0\n\t"\
3734132431fSAlex Bennée         : "=r" (res)\
3744132431fSAlex Bennée         : "r" (v1), "r" (v2), "m" (val), "0" (res));\
3754132431fSAlex Bennée         printf("%-10s R=" FMTLX "\n", "cmov" JCC "q", res);)\
3764132431fSAlex Bennée     asm("cmpl %2, %1\n\t"\
3774132431fSAlex Bennée         "cmov" JCC "l %k3, %k0\n\t"\
3784132431fSAlex Bennée         : "=r" (res)\
3794132431fSAlex Bennée         : "r" (v1), "r" (v2), "m" (val), "0" (res));\
3804132431fSAlex Bennée         printf("%-10s R=" FMTLX "\n", "cmov" JCC "l", res);\
3814132431fSAlex Bennée     asm("cmpl %2, %1\n\t"\
3824132431fSAlex Bennée         "cmov" JCC "w %w3, %w0\n\t"\
3834132431fSAlex Bennée         : "=r" (res)\
3844132431fSAlex Bennée         : "r" (v1), "r" (v2), "r" (1), "0" (res));\
3854132431fSAlex Bennée         printf("%-10s R=" FMTLX "\n", "cmov" JCC "w", res);\
3864132431fSAlex Bennée  } \
3874132431fSAlex Bennée }
3884132431fSAlex Bennée 
3894132431fSAlex Bennée /* various jump tests */
test_jcc(void)3904132431fSAlex Bennée void test_jcc(void)
3914132431fSAlex Bennée {
3924132431fSAlex Bennée     TEST_JCC("ne", 1, 1);
3934132431fSAlex Bennée     TEST_JCC("ne", 1, 0);
3944132431fSAlex Bennée 
3954132431fSAlex Bennée     TEST_JCC("e", 1, 1);
3964132431fSAlex Bennée     TEST_JCC("e", 1, 0);
3974132431fSAlex Bennée 
3984132431fSAlex Bennée     TEST_JCC("l", 1, 1);
3994132431fSAlex Bennée     TEST_JCC("l", 1, 0);
4004132431fSAlex Bennée     TEST_JCC("l", 1, -1);
4014132431fSAlex Bennée 
4024132431fSAlex Bennée     TEST_JCC("le", 1, 1);
4034132431fSAlex Bennée     TEST_JCC("le", 1, 0);
4044132431fSAlex Bennée     TEST_JCC("le", 1, -1);
4054132431fSAlex Bennée 
4064132431fSAlex Bennée     TEST_JCC("ge", 1, 1);
4074132431fSAlex Bennée     TEST_JCC("ge", 1, 0);
4084132431fSAlex Bennée     TEST_JCC("ge", -1, 1);
4094132431fSAlex Bennée 
4104132431fSAlex Bennée     TEST_JCC("g", 1, 1);
4114132431fSAlex Bennée     TEST_JCC("g", 1, 0);
4124132431fSAlex Bennée     TEST_JCC("g", 1, -1);
4134132431fSAlex Bennée 
4144132431fSAlex Bennée     TEST_JCC("b", 1, 1);
4154132431fSAlex Bennée     TEST_JCC("b", 1, 0);
4164132431fSAlex Bennée     TEST_JCC("b", 1, -1);
4174132431fSAlex Bennée 
4184132431fSAlex Bennée     TEST_JCC("be", 1, 1);
4194132431fSAlex Bennée     TEST_JCC("be", 1, 0);
4204132431fSAlex Bennée     TEST_JCC("be", 1, -1);
4214132431fSAlex Bennée 
4224132431fSAlex Bennée     TEST_JCC("ae", 1, 1);
4234132431fSAlex Bennée     TEST_JCC("ae", 1, 0);
4244132431fSAlex Bennée     TEST_JCC("ae", 1, -1);
4254132431fSAlex Bennée 
4264132431fSAlex Bennée     TEST_JCC("a", 1, 1);
4274132431fSAlex Bennée     TEST_JCC("a", 1, 0);
4284132431fSAlex Bennée     TEST_JCC("a", 1, -1);
4294132431fSAlex Bennée 
4304132431fSAlex Bennée 
4314132431fSAlex Bennée     TEST_JCC("p", 1, 1);
4324132431fSAlex Bennée     TEST_JCC("p", 1, 0);
4334132431fSAlex Bennée 
4344132431fSAlex Bennée     TEST_JCC("np", 1, 1);
4354132431fSAlex Bennée     TEST_JCC("np", 1, 0);
4364132431fSAlex Bennée 
4374132431fSAlex Bennée     TEST_JCC("o", 0x7fffffff, 0);
4384132431fSAlex Bennée     TEST_JCC("o", 0x7fffffff, -1);
4394132431fSAlex Bennée 
4404132431fSAlex Bennée     TEST_JCC("no", 0x7fffffff, 0);
4414132431fSAlex Bennée     TEST_JCC("no", 0x7fffffff, -1);
4424132431fSAlex Bennée 
4434132431fSAlex Bennée     TEST_JCC("s", 0, 1);
4444132431fSAlex Bennée     TEST_JCC("s", 0, -1);
4454132431fSAlex Bennée     TEST_JCC("s", 0, 0);
4464132431fSAlex Bennée 
4474132431fSAlex Bennée     TEST_JCC("ns", 0, 1);
4484132431fSAlex Bennée     TEST_JCC("ns", 0, -1);
4494132431fSAlex Bennée     TEST_JCC("ns", 0, 0);
4504132431fSAlex Bennée }
4514132431fSAlex Bennée 
4524132431fSAlex Bennée #define TEST_LOOP(insn) \
4534132431fSAlex Bennée {\
4544132431fSAlex Bennée     for(i = 0; i < sizeof(ecx_vals) / sizeof(long); i++) {\
4554132431fSAlex Bennée         ecx = ecx_vals[i];\
4564132431fSAlex Bennée         for(zf = 0; zf < 2; zf++) {\
4574132431fSAlex Bennée     asm("test %2, %2\n\t"\
4584132431fSAlex Bennée         "movl $1, %0\n\t"\
4594132431fSAlex Bennée           insn " 1f\n\t" \
4604132431fSAlex Bennée         "movl $0, %0\n\t"\
4614132431fSAlex Bennée         "1:\n\t"\
4624132431fSAlex Bennée         : "=a" (res)\
4634132431fSAlex Bennée         : "c" (ecx), "b" (!zf)); \
4644132431fSAlex Bennée     printf("%-10s ECX=" FMTLX " ZF=%ld r=%d\n", insn, ecx, zf, res);      \
4654132431fSAlex Bennée         }\
4664132431fSAlex Bennée    }\
4674132431fSAlex Bennée }
4684132431fSAlex Bennée 
test_loop(void)4694132431fSAlex Bennée void test_loop(void)
4704132431fSAlex Bennée {
4714132431fSAlex Bennée     long ecx, zf;
4724132431fSAlex Bennée     const long ecx_vals[] = {
4734132431fSAlex Bennée         0,
4744132431fSAlex Bennée         1,
4754132431fSAlex Bennée         0x10000,
4764132431fSAlex Bennée         0x10001,
4774132431fSAlex Bennée #if defined(__x86_64__)
4784132431fSAlex Bennée         0x100000000L,
4794132431fSAlex Bennée         0x100000001L,
4804132431fSAlex Bennée #endif
4814132431fSAlex Bennée     };
4824132431fSAlex Bennée     int i, res;
4834132431fSAlex Bennée 
4844132431fSAlex Bennée #if !defined(__x86_64__)
4854132431fSAlex Bennée     TEST_LOOP("jcxz");
4864132431fSAlex Bennée     TEST_LOOP("loopw");
4874132431fSAlex Bennée     TEST_LOOP("loopzw");
4884132431fSAlex Bennée     TEST_LOOP("loopnzw");
4894132431fSAlex Bennée #endif
4904132431fSAlex Bennée 
4914132431fSAlex Bennée     TEST_LOOP("jecxz");
4924132431fSAlex Bennée     TEST_LOOP("loopl");
4934132431fSAlex Bennée     TEST_LOOP("loopzl");
4944132431fSAlex Bennée     TEST_LOOP("loopnzl");
4954132431fSAlex Bennée }
4964132431fSAlex Bennée 
4974132431fSAlex Bennée #undef CC_MASK
4984132431fSAlex Bennée #ifdef TEST_P4_FLAGS
4994132431fSAlex Bennée #define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
5004132431fSAlex Bennée #else
5014132431fSAlex Bennée #define CC_MASK (CC_O | CC_C)
5024132431fSAlex Bennée #endif
5034132431fSAlex Bennée 
5044132431fSAlex Bennée #define OP mul
5054132431fSAlex Bennée #include "test-i386-muldiv.h"
5064132431fSAlex Bennée 
5074132431fSAlex Bennée #define OP imul
5084132431fSAlex Bennée #include "test-i386-muldiv.h"
5094132431fSAlex Bennée 
test_imulw2(long op0,long op1)5104132431fSAlex Bennée void test_imulw2(long op0, long op1)
5114132431fSAlex Bennée {
5124132431fSAlex Bennée     long res, s1, s0, flags;
5134132431fSAlex Bennée     s0 = op0;
5144132431fSAlex Bennée     s1 = op1;
5154132431fSAlex Bennée     res = s0;
5164132431fSAlex Bennée     flags = 0;
5174132431fSAlex Bennée     asm volatile ("push %4\n\t"
5184132431fSAlex Bennée          "popf\n\t"
5194132431fSAlex Bennée          "imulw %w2, %w0\n\t"
5204132431fSAlex Bennée          "pushf\n\t"
5214132431fSAlex Bennée          "pop %1\n\t"
5224132431fSAlex Bennée          : "=q" (res), "=g" (flags)
5234132431fSAlex Bennée          : "q" (s1), "0" (res), "1" (flags));
5244132431fSAlex Bennée     printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
5254132431fSAlex Bennée            "imulw", s0, s1, res, flags & CC_MASK);
5264132431fSAlex Bennée }
5274132431fSAlex Bennée 
test_imull2(long op0,long op1)5284132431fSAlex Bennée void test_imull2(long op0, long op1)
5294132431fSAlex Bennée {
5304132431fSAlex Bennée     long res, s1, s0, flags;
5314132431fSAlex Bennée     s0 = op0;
5324132431fSAlex Bennée     s1 = op1;
5334132431fSAlex Bennée     res = s0;
5344132431fSAlex Bennée     flags = 0;
5354132431fSAlex Bennée     asm volatile ("push %4\n\t"
5364132431fSAlex Bennée          "popf\n\t"
5374132431fSAlex Bennée          "imull %k2, %k0\n\t"
5384132431fSAlex Bennée          "pushf\n\t"
5394132431fSAlex Bennée          "pop %1\n\t"
5404132431fSAlex Bennée          : "=q" (res), "=g" (flags)
5414132431fSAlex Bennée          : "q" (s1), "0" (res), "1" (flags));
5424132431fSAlex Bennée     printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
5434132431fSAlex Bennée            "imull", s0, s1, res, flags & CC_MASK);
5444132431fSAlex Bennée }
5454132431fSAlex Bennée 
5464132431fSAlex Bennée #if defined(__x86_64__)
test_imulq2(long op0,long op1)5474132431fSAlex Bennée void test_imulq2(long op0, long op1)
5484132431fSAlex Bennée {
5494132431fSAlex Bennée     long res, s1, s0, flags;
5504132431fSAlex Bennée     s0 = op0;
5514132431fSAlex Bennée     s1 = op1;
5524132431fSAlex Bennée     res = s0;
5534132431fSAlex Bennée     flags = 0;
5544132431fSAlex Bennée     asm volatile ("push %4\n\t"
5554132431fSAlex Bennée          "popf\n\t"
5564132431fSAlex Bennée          "imulq %2, %0\n\t"
5574132431fSAlex Bennée          "pushf\n\t"
5584132431fSAlex Bennée          "pop %1\n\t"
5594132431fSAlex Bennée          : "=q" (res), "=g" (flags)
5604132431fSAlex Bennée          : "q" (s1), "0" (res), "1" (flags));
5614132431fSAlex Bennée     printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
5624132431fSAlex Bennée            "imulq", s0, s1, res, flags & CC_MASK);
5634132431fSAlex Bennée }
5644132431fSAlex Bennée #endif
5654132431fSAlex Bennée 
5664132431fSAlex Bennée #define TEST_IMUL_IM(size, rsize, op0, op1)\
5674132431fSAlex Bennée {\
5684132431fSAlex Bennée     long res, flags, s1;\
5694132431fSAlex Bennée     flags = 0;\
5704132431fSAlex Bennée     res = 0;\
5714132431fSAlex Bennée     s1 = op1;\
5724132431fSAlex Bennée     asm volatile ("push %3\n\t"\
5734132431fSAlex Bennée          "popf\n\t"\
5744132431fSAlex Bennée          "imul" size " $" #op0 ", %" rsize "2, %" rsize "0\n\t" \
5754132431fSAlex Bennée          "pushf\n\t"\
5764132431fSAlex Bennée          "pop %1\n\t"\
5774132431fSAlex Bennée          : "=r" (res), "=g" (flags)\
5784132431fSAlex Bennée          : "r" (s1), "1" (flags), "0" (res));\
5794132431fSAlex Bennée     printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",\
5804132431fSAlex Bennée            "imul" size " im", (long)op0, (long)op1, res, flags & CC_MASK);\
5814132431fSAlex Bennée }
5824132431fSAlex Bennée 
5834132431fSAlex Bennée 
5844132431fSAlex Bennée #undef CC_MASK
5854132431fSAlex Bennée #define CC_MASK (0)
5864132431fSAlex Bennée 
5874132431fSAlex Bennée #define OP div
5884132431fSAlex Bennée #include "test-i386-muldiv.h"
5894132431fSAlex Bennée 
5904132431fSAlex Bennée #define OP idiv
5914132431fSAlex Bennée #include "test-i386-muldiv.h"
5924132431fSAlex Bennée 
test_mul(void)5934132431fSAlex Bennée void test_mul(void)
5944132431fSAlex Bennée {
5954132431fSAlex Bennée     test_imulb(0x1234561d, 4);
5964132431fSAlex Bennée     test_imulb(3, -4);
5974132431fSAlex Bennée     test_imulb(0x80, 0x80);
5984132431fSAlex Bennée     test_imulb(0x10, 0x10);
5994132431fSAlex Bennée 
6004132431fSAlex Bennée     test_imulw(0, 0x1234001d, 45);
6014132431fSAlex Bennée     test_imulw(0, 23, -45);
6024132431fSAlex Bennée     test_imulw(0, 0x8000, 0x8000);
6034132431fSAlex Bennée     test_imulw(0, 0x100, 0x100);
6044132431fSAlex Bennée 
6054132431fSAlex Bennée     test_imull(0, 0x1234001d, 45);
6064132431fSAlex Bennée     test_imull(0, 23, -45);
6074132431fSAlex Bennée     test_imull(0, 0x80000000, 0x80000000);
6084132431fSAlex Bennée     test_imull(0, 0x10000, 0x10000);
6094132431fSAlex Bennée 
6104132431fSAlex Bennée     test_mulb(0x1234561d, 4);
6114132431fSAlex Bennée     test_mulb(3, -4);
6124132431fSAlex Bennée     test_mulb(0x80, 0x80);
6134132431fSAlex Bennée     test_mulb(0x10, 0x10);
6144132431fSAlex Bennée 
6154132431fSAlex Bennée     test_mulw(0, 0x1234001d, 45);
6164132431fSAlex Bennée     test_mulw(0, 23, -45);
6174132431fSAlex Bennée     test_mulw(0, 0x8000, 0x8000);
6184132431fSAlex Bennée     test_mulw(0, 0x100, 0x100);
6194132431fSAlex Bennée 
6204132431fSAlex Bennée     test_mull(0, 0x1234001d, 45);
6214132431fSAlex Bennée     test_mull(0, 23, -45);
6224132431fSAlex Bennée     test_mull(0, 0x80000000, 0x80000000);
6234132431fSAlex Bennée     test_mull(0, 0x10000, 0x10000);
6244132431fSAlex Bennée 
6254132431fSAlex Bennée     test_imulw2(0x1234001d, 45);
6264132431fSAlex Bennée     test_imulw2(23, -45);
6274132431fSAlex Bennée     test_imulw2(0x8000, 0x8000);
6284132431fSAlex Bennée     test_imulw2(0x100, 0x100);
6294132431fSAlex Bennée 
6304132431fSAlex Bennée     test_imull2(0x1234001d, 45);
6314132431fSAlex Bennée     test_imull2(23, -45);
6324132431fSAlex Bennée     test_imull2(0x80000000, 0x80000000);
6334132431fSAlex Bennée     test_imull2(0x10000, 0x10000);
6344132431fSAlex Bennée 
6354132431fSAlex Bennée     TEST_IMUL_IM("w", "w", 45, 0x1234);
6364132431fSAlex Bennée     TEST_IMUL_IM("w", "w", -45, 23);
6374132431fSAlex Bennée     TEST_IMUL_IM("w", "w", 0x8000, 0x80000000);
6384132431fSAlex Bennée     TEST_IMUL_IM("w", "w", 0x7fff, 0x1000);
6394132431fSAlex Bennée 
6404132431fSAlex Bennée     TEST_IMUL_IM("l", "k", 45, 0x1234);
6414132431fSAlex Bennée     TEST_IMUL_IM("l", "k", -45, 23);
6424132431fSAlex Bennée     TEST_IMUL_IM("l", "k", 0x8000, 0x80000000);
6434132431fSAlex Bennée     TEST_IMUL_IM("l", "k", 0x7fff, 0x1000);
6444132431fSAlex Bennée 
6454132431fSAlex Bennée     test_idivb(0x12341678, 0x127e);
6464132431fSAlex Bennée     test_idivb(0x43210123, -5);
6474132431fSAlex Bennée     test_idivb(0x12340004, -1);
6484132431fSAlex Bennée 
6494132431fSAlex Bennée     test_idivw(0, 0x12345678, 12347);
6504132431fSAlex Bennée     test_idivw(0, -23223, -45);
6514132431fSAlex Bennée     test_idivw(0, 0x12348000, -1);
6524132431fSAlex Bennée     test_idivw(0x12343, 0x12345678, 0x81238567);
6534132431fSAlex Bennée 
6544132431fSAlex Bennée     test_idivl(0, 0x12345678, 12347);
6554132431fSAlex Bennée     test_idivl(0, -233223, -45);
6564132431fSAlex Bennée     test_idivl(0, 0x80000000, -1);
6574132431fSAlex Bennée     test_idivl(0x12343, 0x12345678, 0x81234567);
6584132431fSAlex Bennée 
6594132431fSAlex Bennée     test_divb(0x12341678, 0x127e);
6604132431fSAlex Bennée     test_divb(0x43210123, -5);
6614132431fSAlex Bennée     test_divb(0x12340004, -1);
6624132431fSAlex Bennée 
6634132431fSAlex Bennée     test_divw(0, 0x12345678, 12347);
6644132431fSAlex Bennée     test_divw(0, -23223, -45);
6654132431fSAlex Bennée     test_divw(0, 0x12348000, -1);
6664132431fSAlex Bennée     test_divw(0x12343, 0x12345678, 0x81238567);
6674132431fSAlex Bennée 
6684132431fSAlex Bennée     test_divl(0, 0x12345678, 12347);
6694132431fSAlex Bennée     test_divl(0, -233223, -45);
6704132431fSAlex Bennée     test_divl(0, 0x80000000, -1);
6714132431fSAlex Bennée     test_divl(0x12343, 0x12345678, 0x81234567);
6724132431fSAlex Bennée 
6734132431fSAlex Bennée #if defined(__x86_64__)
6744132431fSAlex Bennée     test_imulq(0, 0x1234001d1234001d, 45);
6754132431fSAlex Bennée     test_imulq(0, 23, -45);
6764132431fSAlex Bennée     test_imulq(0, 0x8000000000000000, 0x8000000000000000);
6774132431fSAlex Bennée     test_imulq(0, 0x100000000, 0x100000000);
6784132431fSAlex Bennée 
6794132431fSAlex Bennée     test_mulq(0, 0x1234001d1234001d, 45);
6804132431fSAlex Bennée     test_mulq(0, 23, -45);
6814132431fSAlex Bennée     test_mulq(0, 0x8000000000000000, 0x8000000000000000);
6824132431fSAlex Bennée     test_mulq(0, 0x100000000, 0x100000000);
6834132431fSAlex Bennée 
6844132431fSAlex Bennée     test_imulq2(0x1234001d1234001d, 45);
6854132431fSAlex Bennée     test_imulq2(23, -45);
6864132431fSAlex Bennée     test_imulq2(0x8000000000000000, 0x8000000000000000);
6874132431fSAlex Bennée     test_imulq2(0x100000000, 0x100000000);
6884132431fSAlex Bennée 
6894132431fSAlex Bennée     TEST_IMUL_IM("q", "", 45, 0x12341234);
6904132431fSAlex Bennée     TEST_IMUL_IM("q", "", -45, 23);
6914132431fSAlex Bennée     TEST_IMUL_IM("q", "", 0x8000, 0x8000000000000000);
6924132431fSAlex Bennée     TEST_IMUL_IM("q", "", 0x7fff, 0x10000000);
6934132431fSAlex Bennée 
6944132431fSAlex Bennée     test_idivq(0, 0x12345678abcdef, 12347);
6954132431fSAlex Bennée     test_idivq(0, -233223, -45);
6964132431fSAlex Bennée     test_idivq(0, 0x8000000000000000, -1);
6974132431fSAlex Bennée     test_idivq(0x12343, 0x12345678, 0x81234567);
6984132431fSAlex Bennée 
6994132431fSAlex Bennée     test_divq(0, 0x12345678abcdef, 12347);
7004132431fSAlex Bennée     test_divq(0, -233223, -45);
7014132431fSAlex Bennée     test_divq(0, 0x8000000000000000, -1);
7024132431fSAlex Bennée     test_divq(0x12343, 0x12345678, 0x81234567);
7034132431fSAlex Bennée #endif
7044132431fSAlex Bennée }
7054132431fSAlex Bennée 
7064132431fSAlex Bennée #define TEST_BSX(op, size, op0)\
7074132431fSAlex Bennée {\
7084132431fSAlex Bennée     long res, val, resz;\
7094132431fSAlex Bennée     val = op0;\
7104132431fSAlex Bennée     asm("xor %1, %1\n"\
7114132431fSAlex Bennée         "mov $0x12345678, %0\n"\
7124132431fSAlex Bennée         #op " %" size "2, %" size "0 ; setz %b1" \
7134132431fSAlex Bennée         : "=&r" (res), "=&q" (resz)\
7144132431fSAlex Bennée         : "r" (val));\
7154132431fSAlex Bennée     printf("%-10s A=" FMTLX " R=" FMTLX " %ld\n", #op, val, res, resz);\
7164132431fSAlex Bennée }
7174132431fSAlex Bennée 
test_xcnt(void)718*ff5b5739SPaolo Bonzini void test_xcnt(void)
719*ff5b5739SPaolo Bonzini {
720*ff5b5739SPaolo Bonzini     TEST_BSX(tzcntw, "w", 0);
721*ff5b5739SPaolo Bonzini     TEST_BSX(tzcntw, "w", 0x12340128);
722*ff5b5739SPaolo Bonzini     TEST_BSX(lzcntw, "w", 0);
723*ff5b5739SPaolo Bonzini     TEST_BSX(lzcntw, "w", 0x12340128);
724*ff5b5739SPaolo Bonzini     TEST_BSX(popcntw, "w", 0);
725*ff5b5739SPaolo Bonzini     TEST_BSX(popcntw, "w", 0x12340128);
726*ff5b5739SPaolo Bonzini     TEST_BSX(tzcntl, "k", 0);
727*ff5b5739SPaolo Bonzini     TEST_BSX(tzcntl, "k", 0x00340128);
728*ff5b5739SPaolo Bonzini     TEST_BSX(lzcntl, "k", 0);
729*ff5b5739SPaolo Bonzini     TEST_BSX(lzcntl, "k", 0x00340128);
730*ff5b5739SPaolo Bonzini     TEST_BSX(popcntl, "k", 0);
731*ff5b5739SPaolo Bonzini     TEST_BSX(popcntl, "k", 0x00340128);
732*ff5b5739SPaolo Bonzini #if defined(__x86_64__)
733*ff5b5739SPaolo Bonzini     TEST_BSX(tzcntq, "", 0);
734*ff5b5739SPaolo Bonzini     TEST_BSX(tzcntq, "", 0x003401281234);
735*ff5b5739SPaolo Bonzini     TEST_BSX(lzcntq, "", 0);
736*ff5b5739SPaolo Bonzini     TEST_BSX(lzcntq, "", 0x003401281234);
737*ff5b5739SPaolo Bonzini     TEST_BSX(popcntq, "", 0);
738*ff5b5739SPaolo Bonzini     TEST_BSX(popcntq, "", 0x003401281234);
739*ff5b5739SPaolo Bonzini #endif
740*ff5b5739SPaolo Bonzini }
741*ff5b5739SPaolo Bonzini 
test_bsx(void)7424132431fSAlex Bennée void test_bsx(void)
7434132431fSAlex Bennée {
7444132431fSAlex Bennée     TEST_BSX(bsrw, "w", 0);
7454132431fSAlex Bennée     TEST_BSX(bsrw, "w", 0x12340128);
7464132431fSAlex Bennée     TEST_BSX(bsfw, "w", 0);
7474132431fSAlex Bennée     TEST_BSX(bsfw, "w", 0x12340128);
7484132431fSAlex Bennée     TEST_BSX(bsrl, "k", 0);
7494132431fSAlex Bennée     TEST_BSX(bsrl, "k", 0x00340128);
7504132431fSAlex Bennée     TEST_BSX(bsfl, "k", 0);
7514132431fSAlex Bennée     TEST_BSX(bsfl, "k", 0x00340128);
7524132431fSAlex Bennée #if defined(__x86_64__)
7534132431fSAlex Bennée     TEST_BSX(bsrq, "", 0);
7544132431fSAlex Bennée     TEST_BSX(bsrq, "", 0x003401281234);
7554132431fSAlex Bennée     TEST_BSX(bsfq, "", 0);
7564132431fSAlex Bennée     TEST_BSX(bsfq, "", 0x003401281234);
7574132431fSAlex Bennée #endif
7584132431fSAlex Bennée }
7594132431fSAlex Bennée 
7604132431fSAlex Bennée /**********************************************/
7614132431fSAlex Bennée 
7624132431fSAlex Bennée union float64u {
7634132431fSAlex Bennée     double d;
7644132431fSAlex Bennée     uint64_t l;
7654132431fSAlex Bennée };
7664132431fSAlex Bennée 
7674132431fSAlex Bennée union float64u q_nan = { .l = 0xFFF8000000000000LL };
7684132431fSAlex Bennée union float64u s_nan = { .l = 0xFFF0000000000000LL };
7694132431fSAlex Bennée 
test_fops(double a,double b)7704132431fSAlex Bennée void test_fops(double a, double b)
7714132431fSAlex Bennée {
7724132431fSAlex Bennée     printf("a=%f b=%f a+b=%f\n", a, b, a + b);
7734132431fSAlex Bennée     printf("a=%f b=%f a-b=%f\n", a, b, a - b);
7744132431fSAlex Bennée     printf("a=%f b=%f a*b=%f\n", a, b, a * b);
7754132431fSAlex Bennée     printf("a=%f b=%f a/b=%f\n", a, b, a / b);
7764132431fSAlex Bennée     printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b));
7774132431fSAlex Bennée     printf("a=%f sqrt(a)=%f\n", a, sqrt(a));
7784132431fSAlex Bennée     printf("a=%f sin(a)=%f\n", a, sin(a));
7794132431fSAlex Bennée     printf("a=%f cos(a)=%f\n", a, cos(a));
7804132431fSAlex Bennée     printf("a=%f tan(a)=%f\n", a, tan(a));
7814132431fSAlex Bennée     printf("a=%f log(a)=%f\n", a, log(a));
7824132431fSAlex Bennée     printf("a=%f exp(a)=%f\n", a, exp(a));
7834132431fSAlex Bennée     printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
7844132431fSAlex Bennée     /* just to test some op combining */
7854132431fSAlex Bennée     printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a)));
7864132431fSAlex Bennée     printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a)));
7874132431fSAlex Bennée     printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));
7884132431fSAlex Bennée 
7894132431fSAlex Bennée }
7904132431fSAlex Bennée 
fpu_clear_exceptions(void)7914132431fSAlex Bennée void fpu_clear_exceptions(void)
7924132431fSAlex Bennée {
7934132431fSAlex Bennée     struct QEMU_PACKED {
7944132431fSAlex Bennée         uint16_t fpuc;
7954132431fSAlex Bennée         uint16_t dummy1;
7964132431fSAlex Bennée         uint16_t fpus;
7974132431fSAlex Bennée         uint16_t dummy2;
7984132431fSAlex Bennée         uint16_t fptag;
7994132431fSAlex Bennée         uint16_t dummy3;
8004132431fSAlex Bennée         uint32_t ignored[4];
8014132431fSAlex Bennée         long double fpregs[8];
8024132431fSAlex Bennée     } float_env32;
8034132431fSAlex Bennée 
8044132431fSAlex Bennée     asm volatile ("fnstenv %0\n" : "=m" (float_env32));
8054132431fSAlex Bennée     float_env32.fpus &= ~0x7f;
8064132431fSAlex Bennée     asm volatile ("fldenv %0\n" : : "m" (float_env32));
8074132431fSAlex Bennée }
8084132431fSAlex Bennée 
8094132431fSAlex Bennée /* XXX: display exception bits when supported */
8104132431fSAlex Bennée #define FPUS_EMASK 0x0000
8114132431fSAlex Bennée //#define FPUS_EMASK 0x007f
8124132431fSAlex Bennée 
test_fcmp(double a,double b)8134132431fSAlex Bennée void test_fcmp(double a, double b)
8144132431fSAlex Bennée {
8154132431fSAlex Bennée     long eflags, fpus;
8164132431fSAlex Bennée 
8174132431fSAlex Bennée     fpu_clear_exceptions();
8184132431fSAlex Bennée     asm("fcom %2\n"
8194132431fSAlex Bennée         "fstsw %%ax\n"
8204132431fSAlex Bennée         : "=a" (fpus)
8214132431fSAlex Bennée         : "t" (a), "u" (b));
8224132431fSAlex Bennée     printf("fcom(%f %f)=%04lx\n",
8234132431fSAlex Bennée            a, b, fpus & (0x4500 | FPUS_EMASK));
8244132431fSAlex Bennée     fpu_clear_exceptions();
8254132431fSAlex Bennée     asm("fucom %2\n"
8264132431fSAlex Bennée         "fstsw %%ax\n"
8274132431fSAlex Bennée         : "=a" (fpus)
8284132431fSAlex Bennée         : "t" (a), "u" (b));
8294132431fSAlex Bennée     printf("fucom(%f %f)=%04lx\n",
8304132431fSAlex Bennée            a, b, fpus & (0x4500 | FPUS_EMASK));
8314132431fSAlex Bennée     if (TEST_FCOMI) {
8324132431fSAlex Bennée         /* test f(u)comi instruction */
8334132431fSAlex Bennée         fpu_clear_exceptions();
8344132431fSAlex Bennée         asm("fcomi %3, %2\n"
8354132431fSAlex Bennée             "fstsw %%ax\n"
8364132431fSAlex Bennée             "pushf\n"
8374132431fSAlex Bennée             "pop %0\n"
8384132431fSAlex Bennée             : "=r" (eflags), "=a" (fpus)
8394132431fSAlex Bennée             : "t" (a), "u" (b));
8404132431fSAlex Bennée         printf("fcomi(%f %f)=%04lx %02lx\n",
8414132431fSAlex Bennée                a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C));
8424132431fSAlex Bennée         fpu_clear_exceptions();
8434132431fSAlex Bennée         asm("fucomi %3, %2\n"
8444132431fSAlex Bennée             "fstsw %%ax\n"
8454132431fSAlex Bennée             "pushf\n"
8464132431fSAlex Bennée             "pop %0\n"
8474132431fSAlex Bennée             : "=r" (eflags), "=a" (fpus)
8484132431fSAlex Bennée             : "t" (a), "u" (b));
8494132431fSAlex Bennée         printf("fucomi(%f %f)=%04lx %02lx\n",
8504132431fSAlex Bennée                a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C));
8514132431fSAlex Bennée     }
8524132431fSAlex Bennée     fpu_clear_exceptions();
8534132431fSAlex Bennée     asm volatile("fxam\n"
8544132431fSAlex Bennée                  "fstsw %%ax\n"
8554132431fSAlex Bennée                  : "=a" (fpus)
8564132431fSAlex Bennée                  : "t" (a));
8574132431fSAlex Bennée     printf("fxam(%f)=%04lx\n", a, fpus & 0x4700);
8584132431fSAlex Bennée     fpu_clear_exceptions();
8594132431fSAlex Bennée }
8604132431fSAlex Bennée 
test_fcvt(double a)8614132431fSAlex Bennée void test_fcvt(double a)
8624132431fSAlex Bennée {
8634132431fSAlex Bennée     float fa;
8644132431fSAlex Bennée     long double la;
8654132431fSAlex Bennée     int16_t fpuc;
8664132431fSAlex Bennée     int i;
8674132431fSAlex Bennée     int64_t lla;
8684132431fSAlex Bennée     int ia;
8694132431fSAlex Bennée     int16_t wa;
8704132431fSAlex Bennée     double ra;
8714132431fSAlex Bennée 
8724132431fSAlex Bennée     fa = a;
8734132431fSAlex Bennée     la = a;
8744132431fSAlex Bennée     printf("(float)%f = %f\n", a, fa);
8754132431fSAlex Bennée     printf("(long double)%f = %Lf\n", a, la);
8764132431fSAlex Bennée     printf("a=" FMT64X "\n", *(uint64_t *)&a);
8774132431fSAlex Bennée     printf("la=" FMT64X " %04x\n", *(uint64_t *)&la,
8784132431fSAlex Bennée            *(unsigned short *)((char *)(&la) + 8));
8794132431fSAlex Bennée 
8804132431fSAlex Bennée     /* test all roundings */
8814132431fSAlex Bennée     asm volatile ("fstcw %0" : "=m" (fpuc));
8824132431fSAlex Bennée     for(i=0;i<4;i++) {
8834132431fSAlex Bennée         uint16_t val16;
8844132431fSAlex Bennée         val16 = (fpuc & ~0x0c00) | (i << 10);
8854132431fSAlex Bennée         asm volatile ("fldcw %0" : : "m" (val16));
8866012d963SRichard Henderson         asm volatile ("fists %0" : "=m" (wa) : "t" (a));
8874132431fSAlex Bennée         asm volatile ("fistl %0" : "=m" (ia) : "t" (a));
8884132431fSAlex Bennée         asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st");
8894132431fSAlex Bennée         asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a));
8904132431fSAlex Bennée         asm volatile ("fldcw %0" : : "m" (fpuc));
8914132431fSAlex Bennée         printf("(short)a = %d\n", wa);
8924132431fSAlex Bennée         printf("(int)a = %d\n", ia);
8934132431fSAlex Bennée         printf("(int64_t)a = " FMT64X "\n", lla);
8944132431fSAlex Bennée         printf("rint(a) = %f\n", ra);
8954132431fSAlex Bennée     }
8964132431fSAlex Bennée }
8974132431fSAlex Bennée 
8984132431fSAlex Bennée #define TEST(N) \
8994132431fSAlex Bennée     asm("fld" #N : "=t" (a)); \
9004132431fSAlex Bennée     printf("fld" #N "= %f\n", a);
9014132431fSAlex Bennée 
test_fconst(void)9024132431fSAlex Bennée void test_fconst(void)
9034132431fSAlex Bennée {
9044132431fSAlex Bennée     double a;
9054132431fSAlex Bennée     TEST(1);
9064132431fSAlex Bennée     TEST(l2t);
9074132431fSAlex Bennée     TEST(l2e);
9084132431fSAlex Bennée     TEST(pi);
9094132431fSAlex Bennée     TEST(lg2);
9104132431fSAlex Bennée     TEST(ln2);
9114132431fSAlex Bennée     TEST(z);
9124132431fSAlex Bennée }
9134132431fSAlex Bennée 
test_fbcd(double a)9144132431fSAlex Bennée void test_fbcd(double a)
9154132431fSAlex Bennée {
9164132431fSAlex Bennée     unsigned short bcd[5];
9174132431fSAlex Bennée     double b;
9184132431fSAlex Bennée 
9194132431fSAlex Bennée     asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st");
9204132431fSAlex Bennée     asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
9214132431fSAlex Bennée     printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n",
9224132431fSAlex Bennée            a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);
9234132431fSAlex Bennée }
9244132431fSAlex Bennée 
9254132431fSAlex Bennée #define TEST_ENV(env, save, restore)\
9264132431fSAlex Bennée {\
9274132431fSAlex Bennée     memset((env), 0xaa, sizeof(*(env)));\
9284132431fSAlex Bennée     for(i=0;i<5;i++)\
9294132431fSAlex Bennée         asm volatile ("fldl %0" : : "m" (dtab[i]));\
9304132431fSAlex Bennée     asm volatile (save " %0\n" : : "m" (*(env)));\
9314132431fSAlex Bennée     asm volatile (restore " %0\n": : "m" (*(env)));\
9324132431fSAlex Bennée     for(i=0;i<5;i++)\
9334132431fSAlex Bennée         asm volatile ("fstpl %0" : "=m" (rtab[i]));\
9344132431fSAlex Bennée     for(i=0;i<5;i++)\
9354132431fSAlex Bennée         printf("res[%d]=%f\n", i, rtab[i]);\
9364132431fSAlex Bennée     printf("fpuc=%04x fpus=%04x fptag=%04x\n",\
9374132431fSAlex Bennée            (env)->fpuc,\
9384132431fSAlex Bennée            (env)->fpus & 0xff00,\
9394132431fSAlex Bennée            (env)->fptag);\
9404132431fSAlex Bennée }
9414132431fSAlex Bennée 
test_fenv(void)9424132431fSAlex Bennée void test_fenv(void)
9434132431fSAlex Bennée {
9444132431fSAlex Bennée     struct __attribute__((__packed__)) {
9454132431fSAlex Bennée         uint16_t fpuc;
9464132431fSAlex Bennée         uint16_t dummy1;
9474132431fSAlex Bennée         uint16_t fpus;
9484132431fSAlex Bennée         uint16_t dummy2;
9494132431fSAlex Bennée         uint16_t fptag;
9504132431fSAlex Bennée         uint16_t dummy3;
9514132431fSAlex Bennée         uint32_t ignored[4];
9524132431fSAlex Bennée         long double fpregs[8];
9534132431fSAlex Bennée     } float_env32;
9544132431fSAlex Bennée     struct __attribute__((__packed__)) {
9554132431fSAlex Bennée         uint16_t fpuc;
9564132431fSAlex Bennée         uint16_t fpus;
9574132431fSAlex Bennée         uint16_t fptag;
9584132431fSAlex Bennée         uint16_t ignored[4];
9594132431fSAlex Bennée         long double fpregs[8];
9604132431fSAlex Bennée     } float_env16;
9614132431fSAlex Bennée     double dtab[8];
9624132431fSAlex Bennée     double rtab[8];
9634132431fSAlex Bennée     int i;
9644132431fSAlex Bennée 
9654132431fSAlex Bennée     for(i=0;i<8;i++)
9664132431fSAlex Bennée         dtab[i] = i + 1;
9674132431fSAlex Bennée 
9684132431fSAlex Bennée     TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv");
9694132431fSAlex Bennée     TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor");
9704132431fSAlex Bennée     TEST_ENV(&float_env32, "fnstenv", "fldenv");
9714132431fSAlex Bennée     TEST_ENV(&float_env32, "fnsave", "frstor");
9724132431fSAlex Bennée 
9734132431fSAlex Bennée     /* test for ffree */
9744132431fSAlex Bennée     for(i=0;i<5;i++)
9754132431fSAlex Bennée         asm volatile ("fldl %0" : : "m" (dtab[i]));
9764132431fSAlex Bennée     asm volatile("ffree %st(2)");
9774132431fSAlex Bennée     asm volatile ("fnstenv %0\n" : : "m" (float_env32));
9784132431fSAlex Bennée     asm volatile ("fninit");
9794132431fSAlex Bennée     printf("fptag=%04x\n", float_env32.fptag);
9804132431fSAlex Bennée }
9814132431fSAlex Bennée 
9824132431fSAlex Bennée 
9834132431fSAlex Bennée #define TEST_FCMOV(a, b, eflags, CC)\
9844132431fSAlex Bennée {\
9854132431fSAlex Bennée     double res;\
9864132431fSAlex Bennée     asm("push %3\n"\
9874132431fSAlex Bennée         "popf\n"\
9884132431fSAlex Bennée         "fcmov" CC " %2, %0\n"\
9894132431fSAlex Bennée         : "=t" (res)\
9904132431fSAlex Bennée         : "0" (a), "u" (b), "g" (eflags));\
9914132431fSAlex Bennée     printf("fcmov%s eflags=0x%04lx-> %f\n", \
9924132431fSAlex Bennée            CC, (long)eflags, res);\
9934132431fSAlex Bennée }
9944132431fSAlex Bennée 
test_fcmov(void)9954132431fSAlex Bennée void test_fcmov(void)
9964132431fSAlex Bennée {
9974132431fSAlex Bennée     double a, b;
9984132431fSAlex Bennée     long eflags, i;
9994132431fSAlex Bennée 
10004132431fSAlex Bennée     a = 1.0;
10014132431fSAlex Bennée     b = 2.0;
10024132431fSAlex Bennée     for(i = 0; i < 4; i++) {
10034132431fSAlex Bennée         eflags = 0;
10044132431fSAlex Bennée         if (i & 1)
10054132431fSAlex Bennée             eflags |= CC_C;
10064132431fSAlex Bennée         if (i & 2)
10074132431fSAlex Bennée             eflags |= CC_Z;
10084132431fSAlex Bennée         TEST_FCMOV(a, b, eflags, "b");
10094132431fSAlex Bennée         TEST_FCMOV(a, b, eflags, "e");
10104132431fSAlex Bennée         TEST_FCMOV(a, b, eflags, "be");
10114132431fSAlex Bennée         TEST_FCMOV(a, b, eflags, "nb");
10124132431fSAlex Bennée         TEST_FCMOV(a, b, eflags, "ne");
10134132431fSAlex Bennée         TEST_FCMOV(a, b, eflags, "nbe");
10144132431fSAlex Bennée     }
10154132431fSAlex Bennée     TEST_FCMOV(a, b, 0, "u");
10164132431fSAlex Bennée     TEST_FCMOV(a, b, CC_P, "u");
10174132431fSAlex Bennée     TEST_FCMOV(a, b, 0, "nu");
10184132431fSAlex Bennée     TEST_FCMOV(a, b, CC_P, "nu");
10194132431fSAlex Bennée }
10204132431fSAlex Bennée 
test_floats(void)10214132431fSAlex Bennée void test_floats(void)
10224132431fSAlex Bennée {
10234132431fSAlex Bennée     test_fops(2, 3);
10244132431fSAlex Bennée     test_fops(1.4, -5);
10254132431fSAlex Bennée     test_fcmp(2, -1);
10264132431fSAlex Bennée     test_fcmp(2, 2);
10274132431fSAlex Bennée     test_fcmp(2, 3);
10284132431fSAlex Bennée     test_fcmp(2, q_nan.d);
10294132431fSAlex Bennée     test_fcmp(q_nan.d, -1);
10304132431fSAlex Bennée     test_fcmp(-1.0/0.0, -1);
10314132431fSAlex Bennée     test_fcmp(1.0/0.0, -1);
10324132431fSAlex Bennée     test_fcvt(0.5);
10334132431fSAlex Bennée     test_fcvt(-0.5);
10344132431fSAlex Bennée     test_fcvt(1.0/7.0);
10354132431fSAlex Bennée     test_fcvt(-1.0/9.0);
10364132431fSAlex Bennée     test_fcvt(32768);
10374132431fSAlex Bennée     test_fcvt(-1e20);
10384132431fSAlex Bennée     test_fcvt(-1.0/0.0);
10394132431fSAlex Bennée     test_fcvt(1.0/0.0);
10404132431fSAlex Bennée     test_fcvt(q_nan.d);
10414132431fSAlex Bennée     test_fconst();
10424132431fSAlex Bennée     test_fbcd(1234567890123456.0);
10434132431fSAlex Bennée     test_fbcd(-123451234567890.0);
10444132431fSAlex Bennée     test_fenv();
10454132431fSAlex Bennée     if (TEST_CMOV) {
10464132431fSAlex Bennée         test_fcmov();
10474132431fSAlex Bennée     }
10484132431fSAlex Bennée }
10494132431fSAlex Bennée 
10504132431fSAlex Bennée /**********************************************/
10514132431fSAlex Bennée #if !defined(__x86_64__)
10524132431fSAlex Bennée 
10534132431fSAlex Bennée #define TEST_BCD(op, op0, cc_in, cc_mask)\
10544132431fSAlex Bennée {\
10554132431fSAlex Bennée     int res, flags;\
10564132431fSAlex Bennée     res = op0;\
10574132431fSAlex Bennée     flags = cc_in;\
10584132431fSAlex Bennée     asm ("push %3\n\t"\
10594132431fSAlex Bennée          "popf\n\t"\
10604132431fSAlex Bennée          #op "\n\t"\
10614132431fSAlex Bennée          "pushf\n\t"\
10624132431fSAlex Bennée          "pop %1\n\t"\
10634132431fSAlex Bennée         : "=a" (res), "=g" (flags)\
10644132431fSAlex Bennée         : "0" (res), "1" (flags));\
10654132431fSAlex Bennée     printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\
10664132431fSAlex Bennée            #op, op0, res, cc_in, flags & cc_mask);\
10674132431fSAlex Bennée }
10684132431fSAlex Bennée 
test_bcd(void)10694132431fSAlex Bennée void test_bcd(void)
10704132431fSAlex Bennée {
10714132431fSAlex Bennée     TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10724132431fSAlex Bennée     TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10734132431fSAlex Bennée     TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10744132431fSAlex Bennée     TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10754132431fSAlex Bennée     TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10764132431fSAlex Bennée     TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10774132431fSAlex Bennée     TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10784132431fSAlex Bennée     TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10794132431fSAlex Bennée     TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10804132431fSAlex Bennée     TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10814132431fSAlex Bennée     TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10824132431fSAlex Bennée     TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10834132431fSAlex Bennée     TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10844132431fSAlex Bennée 
10854132431fSAlex Bennée     TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10864132431fSAlex Bennée     TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10874132431fSAlex Bennée     TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10884132431fSAlex Bennée     TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10894132431fSAlex Bennée     TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10904132431fSAlex Bennée     TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10914132431fSAlex Bennée     TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10924132431fSAlex Bennée     TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10934132431fSAlex Bennée     TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10944132431fSAlex Bennée     TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10954132431fSAlex Bennée     TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10964132431fSAlex Bennée     TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10974132431fSAlex Bennée     TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
10984132431fSAlex Bennée 
10994132431fSAlex Bennée     TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A));
11004132431fSAlex Bennée     TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A));
11014132431fSAlex Bennée     TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A));
11024132431fSAlex Bennée     TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A));
11034132431fSAlex Bennée     TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A));
11044132431fSAlex Bennée     TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A));
11054132431fSAlex Bennée     TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A));
11064132431fSAlex Bennée     TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A));
11074132431fSAlex Bennée 
11084132431fSAlex Bennée     TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A));
11094132431fSAlex Bennée     TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A));
11104132431fSAlex Bennée     TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A));
11114132431fSAlex Bennée     TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A));
11124132431fSAlex Bennée     TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A));
11134132431fSAlex Bennée     TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A));
11144132431fSAlex Bennée     TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A));
11154132431fSAlex Bennée     TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A));
11164132431fSAlex Bennée 
11174132431fSAlex Bennée     TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
11184132431fSAlex Bennée     TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
11194132431fSAlex Bennée }
11204132431fSAlex Bennée #endif
11214132431fSAlex Bennée 
11224132431fSAlex Bennée #define TEST_XCHG(op, size, opconst)\
11234132431fSAlex Bennée {\
11244132431fSAlex Bennée     long op0, op1;\
11254132431fSAlex Bennée     op0 = i2l(0x12345678);\
11264132431fSAlex Bennée     op1 = i2l(0xfbca7654);\
11274132431fSAlex Bennée     asm(#op " %" size "0, %" size "1" \
11284132431fSAlex Bennée         : "=q" (op0), opconst (op1) \
11294132431fSAlex Bennée         : "0" (op0));\
11304132431fSAlex Bennée     printf("%-10s A=" FMTLX " B=" FMTLX "\n",\
11314132431fSAlex Bennée            #op, op0, op1);\
11324132431fSAlex Bennée }
11334132431fSAlex Bennée 
11344132431fSAlex Bennée #define TEST_CMPXCHG(op, size, opconst, eax)\
11354132431fSAlex Bennée {\
11364132431fSAlex Bennée     long op0, op1, op2;\
11374132431fSAlex Bennée     op0 = i2l(0x12345678);\
11384132431fSAlex Bennée     op1 = i2l(0xfbca7654);\
11394132431fSAlex Bennée     op2 = i2l(eax);\
11404132431fSAlex Bennée     asm(#op " %" size "0, %" size "1" \
11414132431fSAlex Bennée         : "=q" (op0), opconst (op1) \
11424132431fSAlex Bennée         : "0" (op0), "a" (op2));\
11434132431fSAlex Bennée     printf("%-10s EAX=" FMTLX " A=" FMTLX " C=" FMTLX "\n",\
11444132431fSAlex Bennée            #op, op2, op0, op1);\
11454132431fSAlex Bennée }
11464132431fSAlex Bennée 
test_xchg(void)11474132431fSAlex Bennée void test_xchg(void)
11484132431fSAlex Bennée {
11494132431fSAlex Bennée #if defined(__x86_64__)
11504132431fSAlex Bennée     TEST_XCHG(xchgq, "", "+q");
11514132431fSAlex Bennée #endif
11524132431fSAlex Bennée     TEST_XCHG(xchgl, "k", "+q");
11534132431fSAlex Bennée     TEST_XCHG(xchgw, "w", "+q");
11544132431fSAlex Bennée     TEST_XCHG(xchgb, "b", "+q");
11554132431fSAlex Bennée 
11564132431fSAlex Bennée #if defined(__x86_64__)
115782c48fb7Sfabrice.desclaux@cea.fr     TEST_XCHG(xchgq, "", "+m");
11584132431fSAlex Bennée #endif
11594132431fSAlex Bennée     TEST_XCHG(xchgl, "k", "+m");
11604132431fSAlex Bennée     TEST_XCHG(xchgw, "w", "+m");
11614132431fSAlex Bennée     TEST_XCHG(xchgb, "b", "+m");
11624132431fSAlex Bennée 
11634132431fSAlex Bennée #if defined(__x86_64__)
11644132431fSAlex Bennée     TEST_XCHG(xaddq, "", "+q");
11654132431fSAlex Bennée #endif
11664132431fSAlex Bennée     TEST_XCHG(xaddl, "k", "+q");
11674132431fSAlex Bennée     TEST_XCHG(xaddw, "w", "+q");
11684132431fSAlex Bennée     TEST_XCHG(xaddb, "b", "+q");
11694132431fSAlex Bennée 
11704132431fSAlex Bennée     {
11714132431fSAlex Bennée         int res;
11724132431fSAlex Bennée         res = 0x12345678;
11734132431fSAlex Bennée         asm("xaddl %1, %0" : "=r" (res) : "0" (res));
11744132431fSAlex Bennée         printf("xaddl same res=%08x\n", res);
11754132431fSAlex Bennée     }
11764132431fSAlex Bennée 
11774132431fSAlex Bennée #if defined(__x86_64__)
11784132431fSAlex Bennée     TEST_XCHG(xaddq, "", "+m");
11794132431fSAlex Bennée #endif
11804132431fSAlex Bennée     TEST_XCHG(xaddl, "k", "+m");
11814132431fSAlex Bennée     TEST_XCHG(xaddw, "w", "+m");
11824132431fSAlex Bennée     TEST_XCHG(xaddb, "b", "+m");
11834132431fSAlex Bennée 
11844132431fSAlex Bennée #if defined(__x86_64__)
11854132431fSAlex Bennée     TEST_CMPXCHG(cmpxchgq, "", "+q", 0xfbca7654);
11864132431fSAlex Bennée #endif
11874132431fSAlex Bennée     TEST_CMPXCHG(cmpxchgl, "k", "+q", 0xfbca7654);
11884132431fSAlex Bennée     TEST_CMPXCHG(cmpxchgw, "w", "+q", 0xfbca7654);
11894132431fSAlex Bennée     TEST_CMPXCHG(cmpxchgb, "b", "+q", 0xfbca7654);
11904132431fSAlex Bennée 
11914132431fSAlex Bennée #if defined(__x86_64__)
11924132431fSAlex Bennée     TEST_CMPXCHG(cmpxchgq, "", "+q", 0xfffefdfc);
11934132431fSAlex Bennée #endif
11944132431fSAlex Bennée     TEST_CMPXCHG(cmpxchgl, "k", "+q", 0xfffefdfc);
11954132431fSAlex Bennée     TEST_CMPXCHG(cmpxchgw, "w", "+q", 0xfffefdfc);
11964132431fSAlex Bennée     TEST_CMPXCHG(cmpxchgb, "b", "+q", 0xfffefdfc);
11974132431fSAlex Bennée 
11984132431fSAlex Bennée #if defined(__x86_64__)
11994132431fSAlex Bennée     TEST_CMPXCHG(cmpxchgq, "", "+m", 0xfbca7654);
12004132431fSAlex Bennée #endif
12014132431fSAlex Bennée     TEST_CMPXCHG(cmpxchgl, "k", "+m", 0xfbca7654);
12024132431fSAlex Bennée     TEST_CMPXCHG(cmpxchgw, "w", "+m", 0xfbca7654);
12034132431fSAlex Bennée     TEST_CMPXCHG(cmpxchgb, "b", "+m", 0xfbca7654);
12044132431fSAlex Bennée 
12054132431fSAlex Bennée #if defined(__x86_64__)
12064132431fSAlex Bennée     TEST_CMPXCHG(cmpxchgq, "", "+m", 0xfffefdfc);
12074132431fSAlex Bennée #endif
12084132431fSAlex Bennée     TEST_CMPXCHG(cmpxchgl, "k", "+m", 0xfffefdfc);
12094132431fSAlex Bennée     TEST_CMPXCHG(cmpxchgw, "w", "+m", 0xfffefdfc);
12104132431fSAlex Bennée     TEST_CMPXCHG(cmpxchgb, "b", "+m", 0xfffefdfc);
12114132431fSAlex Bennée 
12124132431fSAlex Bennée     {
12134132431fSAlex Bennée         uint64_t op0, op1, op2;
12144132431fSAlex Bennée         long eax, edx;
12154132431fSAlex Bennée         long i, eflags;
12164132431fSAlex Bennée 
12174132431fSAlex Bennée         for(i = 0; i < 2; i++) {
12184132431fSAlex Bennée             op0 = 0x123456789abcdLL;
12194132431fSAlex Bennée             eax = i2l(op0 & 0xffffffff);
12204132431fSAlex Bennée             edx = i2l(op0 >> 32);
12214132431fSAlex Bennée             if (i == 0)
12224132431fSAlex Bennée                 op1 = 0xfbca765423456LL;
12234132431fSAlex Bennée             else
12244132431fSAlex Bennée                 op1 = op0;
12254132431fSAlex Bennée             op2 = 0x6532432432434LL;
12264132431fSAlex Bennée             asm("cmpxchg8b %2\n"
12274132431fSAlex Bennée                 "pushf\n"
12284132431fSAlex Bennée                 "pop %3\n"
12294132431fSAlex Bennée                 : "=a" (eax), "=d" (edx), "=m" (op1), "=g" (eflags)
12304132431fSAlex Bennée                 : "0" (eax), "1" (edx), "m" (op1), "b" ((int)op2), "c" ((int)(op2 >> 32)));
12314132431fSAlex Bennée             printf("cmpxchg8b: eax=" FMTLX " edx=" FMTLX " op1=" FMT64X " CC=%02lx\n",
12324132431fSAlex Bennée                    eax, edx, op1, eflags & CC_Z);
12334132431fSAlex Bennée         }
12344132431fSAlex Bennée     }
12354132431fSAlex Bennée }
12364132431fSAlex Bennée 
12374132431fSAlex Bennée #ifdef TEST_SEGS
12384132431fSAlex Bennée /**********************************************/
12394132431fSAlex Bennée /* segmentation tests */
12404132431fSAlex Bennée 
12414132431fSAlex Bennée #include <sys/syscall.h>
12424132431fSAlex Bennée #include <unistd.h>
12434132431fSAlex Bennée #include <asm/ldt.h>
12444132431fSAlex Bennée #include <linux/version.h>
12454132431fSAlex Bennée 
modify_ldt(int func,void * ptr,unsigned long bytecount)12464132431fSAlex Bennée static inline int modify_ldt(int func, void * ptr, unsigned long bytecount)
12474132431fSAlex Bennée {
12484132431fSAlex Bennée     return syscall(__NR_modify_ldt, func, ptr, bytecount);
12494132431fSAlex Bennée }
12504132431fSAlex Bennée 
12514132431fSAlex Bennée #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
12524132431fSAlex Bennée #define modify_ldt_ldt_s user_desc
12534132431fSAlex Bennée #endif
12544132431fSAlex Bennée 
12554132431fSAlex Bennée #define MK_SEL(n) (((n) << 3) | 7)
12564132431fSAlex Bennée 
12574132431fSAlex Bennée uint8_t seg_data1[4096];
12584132431fSAlex Bennée uint8_t seg_data2[4096];
12594132431fSAlex Bennée 
12604132431fSAlex Bennée #define TEST_LR(op, size, seg, mask)\
12614132431fSAlex Bennée {\
12624132431fSAlex Bennée     int res, res2;\
12634132431fSAlex Bennée     uint16_t mseg = seg;\
12644132431fSAlex Bennée     res = 0x12345678;\
12654132431fSAlex Bennée     asm (op " %" size "2, %" size "0\n" \
12664132431fSAlex Bennée          "movl $0, %1\n"\
12674132431fSAlex Bennée          "jnz 1f\n"\
12684132431fSAlex Bennée          "movl $1, %1\n"\
12694132431fSAlex Bennée          "1:\n"\
12704132431fSAlex Bennée          : "=r" (res), "=r" (res2) : "m" (mseg), "0" (res));\
12714132431fSAlex Bennée     printf(op ": Z=%d %08x\n", res2, res & ~(mask));\
12724132431fSAlex Bennée }
12734132431fSAlex Bennée 
12744132431fSAlex Bennée #define TEST_ARPL(op, size, op1, op2)\
12754132431fSAlex Bennée {\
12764132431fSAlex Bennée     long a, b, c;                               \
12774132431fSAlex Bennée     a = (op1);                                  \
12784132431fSAlex Bennée     b = (op2);                                  \
12794132431fSAlex Bennée     asm volatile(op " %" size "3, %" size "0\n"\
12804132431fSAlex Bennée                  "movl $0,%1\n"\
12814132431fSAlex Bennée                  "jnz 1f\n"\
12824132431fSAlex Bennée                  "movl $1,%1\n"\
12834132431fSAlex Bennée                  "1:\n"\
12844132431fSAlex Bennée                  : "=r" (a), "=r" (c) : "0" (a), "r" (b));    \
12854132431fSAlex Bennée     printf(op size " A=" FMTLX " B=" FMTLX " R=" FMTLX " z=%ld\n",\
12864132431fSAlex Bennée            (long)(op1), (long)(op2), a, c);\
12874132431fSAlex Bennée }
12884132431fSAlex Bennée 
12894132431fSAlex Bennée /* NOTE: we use Linux modify_ldt syscall */
test_segs(void)12904132431fSAlex Bennée void test_segs(void)
12914132431fSAlex Bennée {
12924132431fSAlex Bennée     struct modify_ldt_ldt_s ldt;
12934132431fSAlex Bennée     long long ldt_table[3];
12944132431fSAlex Bennée     int res, res2;
12954132431fSAlex Bennée     char tmp;
12964132431fSAlex Bennée     struct {
12974132431fSAlex Bennée         uint32_t offset;
12984132431fSAlex Bennée         uint16_t seg;
12994132431fSAlex Bennée     } __attribute__((__packed__)) segoff;
13004132431fSAlex Bennée 
13014132431fSAlex Bennée     ldt.entry_number = 1;
13024132431fSAlex Bennée     ldt.base_addr = (unsigned long)&seg_data1;
13034132431fSAlex Bennée     ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
13044132431fSAlex Bennée     ldt.seg_32bit = 1;
13054132431fSAlex Bennée     ldt.contents = MODIFY_LDT_CONTENTS_DATA;
13064132431fSAlex Bennée     ldt.read_exec_only = 0;
13074132431fSAlex Bennée     ldt.limit_in_pages = 1;
13084132431fSAlex Bennée     ldt.seg_not_present = 0;
13094132431fSAlex Bennée     ldt.useable = 1;
13104132431fSAlex Bennée     modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
13114132431fSAlex Bennée 
13124132431fSAlex Bennée     ldt.entry_number = 2;
13134132431fSAlex Bennée     ldt.base_addr = (unsigned long)&seg_data2;
13144132431fSAlex Bennée     ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12;
13154132431fSAlex Bennée     ldt.seg_32bit = 1;
13164132431fSAlex Bennée     ldt.contents = MODIFY_LDT_CONTENTS_DATA;
13174132431fSAlex Bennée     ldt.read_exec_only = 0;
13184132431fSAlex Bennée     ldt.limit_in_pages = 1;
13194132431fSAlex Bennée     ldt.seg_not_present = 0;
13204132431fSAlex Bennée     ldt.useable = 1;
13214132431fSAlex Bennée     modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
13224132431fSAlex Bennée 
13234132431fSAlex Bennée     modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */
13244132431fSAlex Bennée #if 0
13254132431fSAlex Bennée     {
13264132431fSAlex Bennée         int i;
13274132431fSAlex Bennée         for(i=0;i<3;i++)
13284132431fSAlex Bennée             printf("%d: %016Lx\n", i, ldt_table[i]);
13294132431fSAlex Bennée     }
13304132431fSAlex Bennée #endif
13314132431fSAlex Bennée     /* do some tests with fs or gs */
13324132431fSAlex Bennée     asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
13334132431fSAlex Bennée 
13344132431fSAlex Bennée     seg_data1[1] = 0xaa;
13354132431fSAlex Bennée     seg_data2[1] = 0x55;
13364132431fSAlex Bennée 
13374132431fSAlex Bennée     asm volatile ("fs movzbl 0x1, %0" : "=r" (res));
13384132431fSAlex Bennée     printf("FS[1] = %02x\n", res);
13394132431fSAlex Bennée 
13404132431fSAlex Bennée     asm volatile ("pushl %%gs\n"
13414132431fSAlex Bennée                   "movl %1, %%gs\n"
13424132431fSAlex Bennée                   "gs movzbl 0x1, %0\n"
13434132431fSAlex Bennée                   "popl %%gs\n"
13444132431fSAlex Bennée                   : "=r" (res)
13454132431fSAlex Bennée                   : "r" (MK_SEL(2)));
13464132431fSAlex Bennée     printf("GS[1] = %02x\n", res);
13474132431fSAlex Bennée 
13484132431fSAlex Bennée     /* tests with ds/ss (implicit segment case) */
13494132431fSAlex Bennée     tmp = 0xa5;
13504132431fSAlex Bennée     asm volatile ("pushl %%ebp\n\t"
13514132431fSAlex Bennée                   "pushl %%ds\n\t"
13524132431fSAlex Bennée                   "movl %2, %%ds\n\t"
13534132431fSAlex Bennée                   "movl %3, %%ebp\n\t"
13544132431fSAlex Bennée                   "movzbl 0x1, %0\n\t"
13554132431fSAlex Bennée                   "movzbl (%%ebp), %1\n\t"
13564132431fSAlex Bennée                   "popl %%ds\n\t"
13574132431fSAlex Bennée                   "popl %%ebp\n\t"
13584132431fSAlex Bennée                   : "=r" (res), "=r" (res2)
13594132431fSAlex Bennée                   : "r" (MK_SEL(1)), "r" (&tmp));
13604132431fSAlex Bennée     printf("DS[1] = %02x\n", res);
13614132431fSAlex Bennée     printf("SS[tmp] = %02x\n", res2);
13624132431fSAlex Bennée 
13634132431fSAlex Bennée     segoff.seg = MK_SEL(2);
13644132431fSAlex Bennée     segoff.offset = 0xabcdef12;
13654132431fSAlex Bennée     asm volatile("lfs %2, %0\n\t"
13664132431fSAlex Bennée                  "movl %%fs, %1\n\t"
13674132431fSAlex Bennée                  : "=r" (res), "=g" (res2)
13684132431fSAlex Bennée                  : "m" (segoff));
13694132431fSAlex Bennée     printf("FS:reg = %04x:%08x\n", res2, res);
13704132431fSAlex Bennée 
13714132431fSAlex Bennée     TEST_LR("larw", "w", MK_SEL(2), 0x0100);
13724132431fSAlex Bennée     TEST_LR("larl", "", MK_SEL(2), 0x0100);
13734132431fSAlex Bennée     TEST_LR("lslw", "w", MK_SEL(2), 0);
13744132431fSAlex Bennée     TEST_LR("lsll", "", MK_SEL(2), 0);
13754132431fSAlex Bennée 
13764132431fSAlex Bennée     TEST_LR("larw", "w", 0xfff8, 0);
13774132431fSAlex Bennée     TEST_LR("larl", "", 0xfff8, 0);
13784132431fSAlex Bennée     TEST_LR("lslw", "w", 0xfff8, 0);
13794132431fSAlex Bennée     TEST_LR("lsll", "", 0xfff8, 0);
13804132431fSAlex Bennée 
13814132431fSAlex Bennée     TEST_ARPL("arpl", "w", 0x12345678 | 3, 0x762123c | 1);
13824132431fSAlex Bennée     TEST_ARPL("arpl", "w", 0x12345678 | 1, 0x762123c | 3);
13834132431fSAlex Bennée     TEST_ARPL("arpl", "w", 0x12345678 | 1, 0x762123c | 1);
13844132431fSAlex Bennée }
13854132431fSAlex Bennée 
13864132431fSAlex Bennée /* 16 bit code test */
13874132431fSAlex Bennée extern char code16_start, code16_end;
13884132431fSAlex Bennée extern char code16_func1;
13894132431fSAlex Bennée extern char code16_func2;
13904132431fSAlex Bennée extern char code16_func3;
13914132431fSAlex Bennée 
test_code16(void)13924132431fSAlex Bennée void test_code16(void)
13934132431fSAlex Bennée {
13944132431fSAlex Bennée     struct modify_ldt_ldt_s ldt;
13954132431fSAlex Bennée     int res, res2;
13964132431fSAlex Bennée 
13974132431fSAlex Bennée     /* build a code segment */
13984132431fSAlex Bennée     ldt.entry_number = 1;
13994132431fSAlex Bennée     ldt.base_addr = (unsigned long)&code16_start;
14004132431fSAlex Bennée     ldt.limit = &code16_end - &code16_start;
14014132431fSAlex Bennée     ldt.seg_32bit = 0;
14024132431fSAlex Bennée     ldt.contents = MODIFY_LDT_CONTENTS_CODE;
14034132431fSAlex Bennée     ldt.read_exec_only = 0;
14044132431fSAlex Bennée     ldt.limit_in_pages = 0;
14054132431fSAlex Bennée     ldt.seg_not_present = 0;
14064132431fSAlex Bennée     ldt.useable = 1;
14074132431fSAlex Bennée     modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
14084132431fSAlex Bennée 
14094132431fSAlex Bennée     /* call the first function */
14104132431fSAlex Bennée     asm volatile ("lcall %1, %2"
14114132431fSAlex Bennée                   : "=a" (res)
14124132431fSAlex Bennée                   : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc");
14134132431fSAlex Bennée     printf("func1() = 0x%08x\n", res);
14144132431fSAlex Bennée     asm volatile ("lcall %2, %3"
14154132431fSAlex Bennée                   : "=a" (res), "=c" (res2)
14164132431fSAlex Bennée                   : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc");
14174132431fSAlex Bennée     printf("func2() = 0x%08x spdec=%d\n", res, res2);
14184132431fSAlex Bennée     asm volatile ("lcall %1, %2"
14194132431fSAlex Bennée                   : "=a" (res)
14204132431fSAlex Bennée                   : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc");
14214132431fSAlex Bennée     printf("func3() = 0x%08x\n", res);
14224132431fSAlex Bennée }
14234132431fSAlex Bennée #endif
14244132431fSAlex Bennée 
14254132431fSAlex Bennée #if defined(__x86_64__)
14264132431fSAlex Bennée asm(".globl func_lret\n"
14274132431fSAlex Bennée     "func_lret:\n"
14284132431fSAlex Bennée     "movl $0x87654641, %eax\n"
14294132431fSAlex Bennée     "lretq\n");
14304132431fSAlex Bennée #else
14314132431fSAlex Bennée asm(".globl func_lret\n"
14324132431fSAlex Bennée     "func_lret:\n"
14334132431fSAlex Bennée     "movl $0x87654321, %eax\n"
14344132431fSAlex Bennée     "lret\n"
14354132431fSAlex Bennée 
14364132431fSAlex Bennée     ".globl func_iret\n"
14374132431fSAlex Bennée     "func_iret:\n"
14384132431fSAlex Bennée     "movl $0xabcd4321, %eax\n"
14394132431fSAlex Bennée     "iret\n");
14404132431fSAlex Bennée #endif
14414132431fSAlex Bennée 
14424132431fSAlex Bennée extern char func_lret;
14434132431fSAlex Bennée extern char func_iret;
14444132431fSAlex Bennée 
test_misc(void)14454132431fSAlex Bennée void test_misc(void)
14464132431fSAlex Bennée {
14474132431fSAlex Bennée     char table[256];
14484132431fSAlex Bennée     long res, i;
14494132431fSAlex Bennée 
14504132431fSAlex Bennée     for(i=0;i<256;i++) table[i] = 256 - i;
14514132431fSAlex Bennée     res = 0x12345678;
14524132431fSAlex Bennée     asm ("xlat" : "=a" (res) : "b" (table), "0" (res));
14534132431fSAlex Bennée     printf("xlat: EAX=" FMTLX "\n", res);
14544132431fSAlex Bennée 
14554132431fSAlex Bennée #if defined(__x86_64__)
14564132431fSAlex Bennée #if 0
14574132431fSAlex Bennée     {
14584132431fSAlex Bennée         /* XXX: see if Intel Core2 and AMD64 behavior really
14594132431fSAlex Bennée            differ. Here we implemented the Intel way which is not
14604132431fSAlex Bennée            compatible yet with QEMU. */
14614132431fSAlex Bennée         static struct QEMU_PACKED {
14624132431fSAlex Bennée             uint64_t offset;
14634132431fSAlex Bennée             uint16_t seg;
14644132431fSAlex Bennée         } desc;
14654132431fSAlex Bennée         long cs_sel;
14664132431fSAlex Bennée 
14674132431fSAlex Bennée         asm volatile ("mov %%cs, %0" : "=r" (cs_sel));
14684132431fSAlex Bennée 
14694132431fSAlex Bennée         asm volatile ("push %1\n"
14704132431fSAlex Bennée                       "call func_lret\n"
14714132431fSAlex Bennée                       : "=a" (res)
14724132431fSAlex Bennée                       : "r" (cs_sel) : "memory", "cc");
14734132431fSAlex Bennée         printf("func_lret=" FMTLX "\n", res);
14744132431fSAlex Bennée 
14754132431fSAlex Bennée         desc.offset = (long)&func_lret;
14764132431fSAlex Bennée         desc.seg = cs_sel;
14774132431fSAlex Bennée 
14784132431fSAlex Bennée         asm volatile ("xor %%rax, %%rax\n"
14794132431fSAlex Bennée                       "rex64 lcall *(%%rcx)\n"
14804132431fSAlex Bennée                       : "=a" (res)
14814132431fSAlex Bennée                       : "c" (&desc)
14824132431fSAlex Bennée                       : "memory", "cc");
14834132431fSAlex Bennée         printf("func_lret2=" FMTLX "\n", res);
14844132431fSAlex Bennée 
14854132431fSAlex Bennée         asm volatile ("push %2\n"
14864132431fSAlex Bennée                       "mov $ 1f, %%rax\n"
14874132431fSAlex Bennée                       "push %%rax\n"
14884132431fSAlex Bennée                       "rex64 ljmp *(%%rcx)\n"
14894132431fSAlex Bennée                       "1:\n"
14904132431fSAlex Bennée                       : "=a" (res)
14914132431fSAlex Bennée                       : "c" (&desc), "b" (cs_sel)
14924132431fSAlex Bennée                       : "memory", "cc");
14934132431fSAlex Bennée         printf("func_lret3=" FMTLX "\n", res);
14944132431fSAlex Bennée     }
14954132431fSAlex Bennée #endif
14964132431fSAlex Bennée #else
14974132431fSAlex Bennée     asm volatile ("push %%cs ; call %1"
14984132431fSAlex Bennée                   : "=a" (res)
14994132431fSAlex Bennée                   : "m" (func_lret): "memory", "cc");
15004132431fSAlex Bennée     printf("func_lret=" FMTLX "\n", res);
15014132431fSAlex Bennée 
15024132431fSAlex Bennée     asm volatile ("pushf ; push %%cs ; call %1"
15034132431fSAlex Bennée                   : "=a" (res)
15044132431fSAlex Bennée                   : "m" (func_iret): "memory", "cc");
15054132431fSAlex Bennée     printf("func_iret=" FMTLX "\n", res);
15064132431fSAlex Bennée #endif
15074132431fSAlex Bennée 
15084132431fSAlex Bennée #if defined(__x86_64__)
15094132431fSAlex Bennée     /* specific popl test */
15104132431fSAlex Bennée     asm volatile ("push $12345432 ; push $0x9abcdef ; pop (%%rsp) ; pop %0"
15114132431fSAlex Bennée                   : "=g" (res));
15124132431fSAlex Bennée     printf("popl esp=" FMTLX "\n", res);
15134132431fSAlex Bennée #else
15144132431fSAlex Bennée     /* specific popl test */
15154132431fSAlex Bennée     asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popl (%%esp) ; popl %0"
15164132431fSAlex Bennée                   : "=g" (res));
15174132431fSAlex Bennée     printf("popl esp=" FMTLX "\n", res);
15184132431fSAlex Bennée 
15194132431fSAlex Bennée     /* specific popw test */
15204132431fSAlex Bennée     asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popw (%%esp) ; addl $2, %%esp ; popl %0"
15214132431fSAlex Bennée                   : "=g" (res));
15224132431fSAlex Bennée     printf("popw esp=" FMTLX "\n", res);
15234132431fSAlex Bennée #endif
15244132431fSAlex Bennée }
15254132431fSAlex Bennée 
15264132431fSAlex Bennée uint8_t str_buffer[4096];
15274132431fSAlex Bennée 
15284132431fSAlex Bennée #define TEST_STRING1(OP, size, DF, REP)\
15294132431fSAlex Bennée {\
15304132431fSAlex Bennée     long esi, edi, eax, ecx, eflags;\
15314132431fSAlex Bennée \
15324132431fSAlex Bennée     esi = (long)(str_buffer + sizeof(str_buffer) / 2);\
15334132431fSAlex Bennée     edi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\
15344132431fSAlex Bennée     eax = i2l(0x12345678);\
15354132431fSAlex Bennée     ecx = 17;\
15364132431fSAlex Bennée \
15374132431fSAlex Bennée     asm volatile ("push $0\n\t"\
15384132431fSAlex Bennée                   "popf\n\t"\
15394132431fSAlex Bennée                   DF "\n\t"\
15404132431fSAlex Bennée                   REP #OP size "\n\t"\
15414132431fSAlex Bennée                   "cld\n\t"\
15424132431fSAlex Bennée                   "pushf\n\t"\
15434132431fSAlex Bennée                   "pop %4\n\t"\
15444132431fSAlex Bennée                   : "=S" (esi), "=D" (edi), "=a" (eax), "=c" (ecx), "=g" (eflags)\
15454132431fSAlex Bennée                   : "0" (esi), "1" (edi), "2" (eax), "3" (ecx));\
15464132431fSAlex Bennée     printf("%-10s ESI=" FMTLX " EDI=" FMTLX " EAX=" FMTLX " ECX=" FMTLX " EFL=%04x\n",\
15474132431fSAlex Bennée            REP #OP size, esi, edi, eax, ecx,\
15484132431fSAlex Bennée            (int)(eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)));\
15494132431fSAlex Bennée }
15504132431fSAlex Bennée 
15514132431fSAlex Bennée #define TEST_STRING(OP, REP)\
15524132431fSAlex Bennée     TEST_STRING1(OP, "b", "", REP);\
15534132431fSAlex Bennée     TEST_STRING1(OP, "w", "", REP);\
15544132431fSAlex Bennée     TEST_STRING1(OP, "l", "", REP);\
15554132431fSAlex Bennée     X86_64_ONLY(TEST_STRING1(OP, "q", "", REP));\
15564132431fSAlex Bennée     TEST_STRING1(OP, "b", "std", REP);\
15574132431fSAlex Bennée     TEST_STRING1(OP, "w", "std", REP);\
15584132431fSAlex Bennée     TEST_STRING1(OP, "l", "std", REP);\
15594132431fSAlex Bennée     X86_64_ONLY(TEST_STRING1(OP, "q", "std", REP))
15604132431fSAlex Bennée 
test_string(void)15614132431fSAlex Bennée void test_string(void)
15624132431fSAlex Bennée {
15634132431fSAlex Bennée     int i;
15644132431fSAlex Bennée     for(i = 0;i < sizeof(str_buffer); i++)
15654132431fSAlex Bennée         str_buffer[i] = i + 0x56;
15664132431fSAlex Bennée    TEST_STRING(stos, "");
15674132431fSAlex Bennée    TEST_STRING(stos, "rep ");
15684132431fSAlex Bennée    TEST_STRING(lods, ""); /* to verify stos */
15694132431fSAlex Bennée    TEST_STRING(lods, "rep ");
15704132431fSAlex Bennée    TEST_STRING(movs, "");
15714132431fSAlex Bennée    TEST_STRING(movs, "rep ");
15724132431fSAlex Bennée    TEST_STRING(lods, ""); /* to verify stos */
15734132431fSAlex Bennée 
15744132431fSAlex Bennée    /* XXX: better tests */
15754132431fSAlex Bennée    TEST_STRING(scas, "");
15764132431fSAlex Bennée    TEST_STRING(scas, "repz ");
15774132431fSAlex Bennée    TEST_STRING(scas, "repnz ");
15784132431fSAlex Bennée    TEST_STRING(cmps, "");
15794132431fSAlex Bennée    TEST_STRING(cmps, "repz ");
15804132431fSAlex Bennée    TEST_STRING(cmps, "repnz ");
15814132431fSAlex Bennée }
15824132431fSAlex Bennée 
15834132431fSAlex Bennée #ifdef TEST_VM86
15844132431fSAlex Bennée /* VM86 test */
15854132431fSAlex Bennée 
set_bit(uint8_t * a,unsigned int bit)15864132431fSAlex Bennée static inline void set_bit(uint8_t *a, unsigned int bit)
15874132431fSAlex Bennée {
15884132431fSAlex Bennée     a[bit / 8] |= (1 << (bit % 8));
15894132431fSAlex Bennée }
15904132431fSAlex Bennée 
seg_to_linear(unsigned int seg,unsigned int reg)15914132431fSAlex Bennée static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
15924132431fSAlex Bennée {
15934132431fSAlex Bennée     return (uint8_t *)((seg << 4) + (reg & 0xffff));
15944132431fSAlex Bennée }
15954132431fSAlex Bennée 
pushw(struct vm86_regs * r,int val)15964132431fSAlex Bennée static inline void pushw(struct vm86_regs *r, int val)
15974132431fSAlex Bennée {
15984132431fSAlex Bennée     r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
15994132431fSAlex Bennée     *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
16004132431fSAlex Bennée }
16014132431fSAlex Bennée 
vm86(int func,struct vm86plus_struct * v86)16024132431fSAlex Bennée static inline int vm86(int func, struct vm86plus_struct *v86)
16034132431fSAlex Bennée {
16044132431fSAlex Bennée     return syscall(__NR_vm86, func, v86);
16054132431fSAlex Bennée }
16064132431fSAlex Bennée 
16074132431fSAlex Bennée extern char vm86_code_start;
16084132431fSAlex Bennée extern char vm86_code_end;
16094132431fSAlex Bennée 
16104132431fSAlex Bennée #define VM86_CODE_CS 0x100
16114132431fSAlex Bennée #define VM86_CODE_IP 0x100
16124132431fSAlex Bennée 
test_vm86(void)16134132431fSAlex Bennée void test_vm86(void)
16144132431fSAlex Bennée {
16154132431fSAlex Bennée     struct vm86plus_struct ctx;
16164132431fSAlex Bennée     struct vm86_regs *r;
16174132431fSAlex Bennée     uint8_t *vm86_mem;
16184132431fSAlex Bennée     int seg, ret;
16194132431fSAlex Bennée 
16204132431fSAlex Bennée     vm86_mem = mmap((void *)0x00000000, 0x110000,
16214132431fSAlex Bennée                     PROT_WRITE | PROT_READ | PROT_EXEC,
16224132431fSAlex Bennée                     MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
16234132431fSAlex Bennée     if (vm86_mem == MAP_FAILED) {
16244132431fSAlex Bennée         printf("ERROR: could not map vm86 memory");
16254132431fSAlex Bennée         return;
16264132431fSAlex Bennée     }
16274132431fSAlex Bennée     memset(&ctx, 0, sizeof(ctx));
16284132431fSAlex Bennée 
16294132431fSAlex Bennée     /* init basic registers */
16304132431fSAlex Bennée     r = &ctx.regs;
16314132431fSAlex Bennée     r->eip = VM86_CODE_IP;
16324132431fSAlex Bennée     r->esp = 0xfffe;
16334132431fSAlex Bennée     seg = VM86_CODE_CS;
16344132431fSAlex Bennée     r->cs = seg;
16354132431fSAlex Bennée     r->ss = seg;
16364132431fSAlex Bennée     r->ds = seg;
16374132431fSAlex Bennée     r->es = seg;
16384132431fSAlex Bennée     r->fs = seg;
16394132431fSAlex Bennée     r->gs = seg;
16404132431fSAlex Bennée     r->eflags = VIF_MASK;
16414132431fSAlex Bennée 
16424132431fSAlex Bennée     /* move code to proper address. We use the same layout as a .com
16434132431fSAlex Bennée        dos program. */
16444132431fSAlex Bennée     memcpy(vm86_mem + (VM86_CODE_CS << 4) + VM86_CODE_IP,
16454132431fSAlex Bennée            &vm86_code_start, &vm86_code_end - &vm86_code_start);
16464132431fSAlex Bennée 
16474132431fSAlex Bennée     /* mark int 0x21 as being emulated */
16484132431fSAlex Bennée     set_bit((uint8_t *)&ctx.int_revectored, 0x21);
16494132431fSAlex Bennée 
16504132431fSAlex Bennée     for(;;) {
16514132431fSAlex Bennée         ret = vm86(VM86_ENTER, &ctx);
16524132431fSAlex Bennée         switch(VM86_TYPE(ret)) {
16534132431fSAlex Bennée         case VM86_INTx:
16544132431fSAlex Bennée             {
16554132431fSAlex Bennée                 int int_num, ah, v;
16564132431fSAlex Bennée 
16574132431fSAlex Bennée                 int_num = VM86_ARG(ret);
16584132431fSAlex Bennée                 if (int_num != 0x21)
16594132431fSAlex Bennée                     goto unknown_int;
16604132431fSAlex Bennée                 ah = (r->eax >> 8) & 0xff;
16614132431fSAlex Bennée                 switch(ah) {
16624132431fSAlex Bennée                 case 0x00: /* exit */
16634132431fSAlex Bennée                     goto the_end;
16644132431fSAlex Bennée                 case 0x02: /* write char */
16654132431fSAlex Bennée                     {
16664132431fSAlex Bennée                         uint8_t c = r->edx;
16674132431fSAlex Bennée                         putchar(c);
16684132431fSAlex Bennée                     }
16694132431fSAlex Bennée                     break;
16704132431fSAlex Bennée                 case 0x09: /* write string */
16714132431fSAlex Bennée                     {
16724132431fSAlex Bennée                         uint8_t c, *ptr;
16734132431fSAlex Bennée                         ptr = seg_to_linear(r->ds, r->edx);
16744132431fSAlex Bennée                         for(;;) {
16754132431fSAlex Bennée                             c = *ptr++;
16764132431fSAlex Bennée                             if (c == '$')
16774132431fSAlex Bennée                                 break;
16784132431fSAlex Bennée                             putchar(c);
16794132431fSAlex Bennée                         }
16804132431fSAlex Bennée                         r->eax = (r->eax & ~0xff) | '$';
16814132431fSAlex Bennée                     }
16824132431fSAlex Bennée                     break;
16834132431fSAlex Bennée                 case 0xff: /* extension: write eflags number in edx */
16844132431fSAlex Bennée                     v = (int)r->edx;
16854132431fSAlex Bennée #ifndef LINUX_VM86_IOPL_FIX
16864132431fSAlex Bennée                     v &= ~0x3000;
16874132431fSAlex Bennée #endif
16884132431fSAlex Bennée                     printf("%08x\n", v);
16894132431fSAlex Bennée                     break;
16904132431fSAlex Bennée                 default:
16914132431fSAlex Bennée                 unknown_int:
16924132431fSAlex Bennée                     printf("unsupported int 0x%02x\n", int_num);
16934132431fSAlex Bennée                     goto the_end;
16944132431fSAlex Bennée                 }
16954132431fSAlex Bennée             }
16964132431fSAlex Bennée             break;
16974132431fSAlex Bennée         case VM86_SIGNAL:
16984132431fSAlex Bennée             /* a signal came, we just ignore that */
16994132431fSAlex Bennée             break;
17004132431fSAlex Bennée         case VM86_STI:
17014132431fSAlex Bennée             break;
17024132431fSAlex Bennée         default:
17034132431fSAlex Bennée             printf("ERROR: unhandled vm86 return code (0x%x)\n", ret);
17044132431fSAlex Bennée             goto the_end;
17054132431fSAlex Bennée         }
17064132431fSAlex Bennée     }
17074132431fSAlex Bennée  the_end:
17084132431fSAlex Bennée     printf("VM86 end\n");
17094132431fSAlex Bennée     munmap(vm86_mem, 0x110000);
17104132431fSAlex Bennée }
17114132431fSAlex Bennée #endif
17124132431fSAlex Bennée 
17134132431fSAlex Bennée /* exception tests */
17144132431fSAlex Bennée #if defined(__i386__) && !defined(REG_EAX)
17154132431fSAlex Bennée #define REG_EAX EAX
17164132431fSAlex Bennée #define REG_EBX EBX
17174132431fSAlex Bennée #define REG_ECX ECX
17184132431fSAlex Bennée #define REG_EDX EDX
17194132431fSAlex Bennée #define REG_ESI ESI
17204132431fSAlex Bennée #define REG_EDI EDI
17214132431fSAlex Bennée #define REG_EBP EBP
17224132431fSAlex Bennée #define REG_ESP ESP
17234132431fSAlex Bennée #define REG_EIP EIP
17244132431fSAlex Bennée #define REG_EFL EFL
17254132431fSAlex Bennée #define REG_TRAPNO TRAPNO
17264132431fSAlex Bennée #define REG_ERR ERR
17274132431fSAlex Bennée #endif
17284132431fSAlex Bennée 
17294132431fSAlex Bennée #if defined(__x86_64__)
17304132431fSAlex Bennée #define REG_EIP REG_RIP
17314132431fSAlex Bennée #endif
17324132431fSAlex Bennée 
17334132431fSAlex Bennée jmp_buf jmp_env;
17344132431fSAlex Bennée int v1;
17354132431fSAlex Bennée int tab[2];
17364132431fSAlex Bennée 
sig_handler(int sig,siginfo_t * info,void * puc)17374132431fSAlex Bennée void sig_handler(int sig, siginfo_t *info, void *puc)
17384132431fSAlex Bennée {
17394132431fSAlex Bennée     ucontext_t *uc = puc;
17404132431fSAlex Bennée 
17414132431fSAlex Bennée     printf("si_signo=%d si_errno=%d si_code=%d",
17424132431fSAlex Bennée            info->si_signo, info->si_errno, info->si_code);
17434132431fSAlex Bennée     printf(" si_addr=0x%08lx",
17444132431fSAlex Bennée            (unsigned long)info->si_addr);
17454132431fSAlex Bennée     printf("\n");
17464132431fSAlex Bennée 
17474132431fSAlex Bennée     printf("trapno=" FMTLX " err=" FMTLX,
17484132431fSAlex Bennée            (long)uc->uc_mcontext.gregs[REG_TRAPNO],
17494132431fSAlex Bennée            (long)uc->uc_mcontext.gregs[REG_ERR]);
17504132431fSAlex Bennée     printf(" EIP=" FMTLX, (long)uc->uc_mcontext.gregs[REG_EIP]);
17514132431fSAlex Bennée     printf("\n");
17524132431fSAlex Bennée     longjmp(jmp_env, 1);
17534132431fSAlex Bennée }
17544132431fSAlex Bennée 
test_exceptions(void)17554132431fSAlex Bennée void test_exceptions(void)
17564132431fSAlex Bennée {
17574132431fSAlex Bennée     struct sigaction act;
17584132431fSAlex Bennée     volatile int val;
17594132431fSAlex Bennée 
17604132431fSAlex Bennée     act.sa_sigaction = sig_handler;
17614132431fSAlex Bennée     sigemptyset(&act.sa_mask);
17624132431fSAlex Bennée     act.sa_flags = SA_SIGINFO | SA_NODEFER;
17634132431fSAlex Bennée     sigaction(SIGFPE, &act, NULL);
17644132431fSAlex Bennée     sigaction(SIGILL, &act, NULL);
17654132431fSAlex Bennée     sigaction(SIGSEGV, &act, NULL);
17664132431fSAlex Bennée     sigaction(SIGBUS, &act, NULL);
17674132431fSAlex Bennée     sigaction(SIGTRAP, &act, NULL);
17684132431fSAlex Bennée 
17694132431fSAlex Bennée     /* test division by zero reporting */
17704132431fSAlex Bennée     printf("DIVZ exception:\n");
17714132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
17724132431fSAlex Bennée         /* now divide by zero */
17734132431fSAlex Bennée         v1 = 0;
17744132431fSAlex Bennée         v1 = 2 / v1;
17754132431fSAlex Bennée     }
17764132431fSAlex Bennée 
17774132431fSAlex Bennée #if !defined(__x86_64__)
17784132431fSAlex Bennée     printf("BOUND exception:\n");
17794132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
17804132431fSAlex Bennée         /* bound exception */
17814132431fSAlex Bennée         tab[0] = 1;
17824132431fSAlex Bennée         tab[1] = 10;
17834132431fSAlex Bennée         asm volatile ("bound %0, %1" : : "r" (11), "m" (tab[0]));
17844132431fSAlex Bennée     }
17854132431fSAlex Bennée #endif
17864132431fSAlex Bennée 
17874132431fSAlex Bennée #ifdef TEST_SEGS
17884132431fSAlex Bennée     printf("segment exceptions:\n");
17894132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
17904132431fSAlex Bennée         /* load an invalid segment */
17914132431fSAlex Bennée         asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 1));
17924132431fSAlex Bennée     }
17934132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
17944132431fSAlex Bennée         /* null data segment is valid */
17954132431fSAlex Bennée         asm volatile ("movl %0, %%fs" : : "r" (3));
17964132431fSAlex Bennée         /* null stack segment */
17974132431fSAlex Bennée         asm volatile ("movl %0, %%ss" : : "r" (3));
17984132431fSAlex Bennée     }
17994132431fSAlex Bennée 
18004132431fSAlex Bennée     {
18014132431fSAlex Bennée         struct modify_ldt_ldt_s ldt;
18024132431fSAlex Bennée         ldt.entry_number = 1;
18034132431fSAlex Bennée         ldt.base_addr = (unsigned long)&seg_data1;
18044132431fSAlex Bennée         ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
18054132431fSAlex Bennée         ldt.seg_32bit = 1;
18064132431fSAlex Bennée         ldt.contents = MODIFY_LDT_CONTENTS_DATA;
18074132431fSAlex Bennée         ldt.read_exec_only = 0;
18084132431fSAlex Bennée         ldt.limit_in_pages = 1;
18094132431fSAlex Bennée         ldt.seg_not_present = 1;
18104132431fSAlex Bennée         ldt.useable = 1;
18114132431fSAlex Bennée         modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
18124132431fSAlex Bennée 
18134132431fSAlex Bennée         if (setjmp(jmp_env) == 0) {
18144132431fSAlex Bennée             /* segment not present */
18154132431fSAlex Bennée             asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
18164132431fSAlex Bennée         }
18174132431fSAlex Bennée     }
18184132431fSAlex Bennée #endif
18194132431fSAlex Bennée 
18204132431fSAlex Bennée     /* test SEGV reporting */
18214132431fSAlex Bennée     printf("PF exception:\n");
18224132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
18234132431fSAlex Bennée         val = 1;
18244132431fSAlex Bennée         /* we add a nop to test a weird PC retrieval case */
18254132431fSAlex Bennée         asm volatile ("nop");
18264132431fSAlex Bennée         /* now store in an invalid address */
18274132431fSAlex Bennée         *(char *)0x1234 = 1;
18284132431fSAlex Bennée     }
18294132431fSAlex Bennée 
18304132431fSAlex Bennée     /* test SEGV reporting */
18314132431fSAlex Bennée     printf("PF exception:\n");
18324132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
18334132431fSAlex Bennée         val = 1;
18344132431fSAlex Bennée         /* read from an invalid address */
18354132431fSAlex Bennée         v1 = *(char *)0x1234;
18364132431fSAlex Bennée     }
18374132431fSAlex Bennée 
18384132431fSAlex Bennée     /* test illegal instruction reporting */
18394132431fSAlex Bennée     printf("UD2 exception:\n");
18404132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
18414132431fSAlex Bennée         /* now execute an invalid instruction */
18424132431fSAlex Bennée         asm volatile("ud2");
18434132431fSAlex Bennée     }
18444132431fSAlex Bennée     printf("lock nop exception:\n");
18454132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
18464132431fSAlex Bennée         /* now execute an invalid instruction */
18474132431fSAlex Bennée         asm volatile(".byte 0xf0, 0x90");
18484132431fSAlex Bennée     }
18494132431fSAlex Bennée 
18504132431fSAlex Bennée     printf("INT exception:\n");
18514132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
18524132431fSAlex Bennée         asm volatile ("int $0xfd");
18534132431fSAlex Bennée     }
18544132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
18554132431fSAlex Bennée         asm volatile ("int $0x01");
18564132431fSAlex Bennée     }
18574132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
18584132431fSAlex Bennée         asm volatile (".byte 0xcd, 0x03");
18594132431fSAlex Bennée     }
18604132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
18614132431fSAlex Bennée         asm volatile ("int $0x04");
18624132431fSAlex Bennée     }
18634132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
18644132431fSAlex Bennée         asm volatile ("int $0x05");
18654132431fSAlex Bennée     }
18664132431fSAlex Bennée 
18674132431fSAlex Bennée     printf("INT3 exception:\n");
18684132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
18694132431fSAlex Bennée         asm volatile ("int3");
18704132431fSAlex Bennée     }
18714132431fSAlex Bennée 
18724132431fSAlex Bennée     printf("CLI exception:\n");
18734132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
18744132431fSAlex Bennée         asm volatile ("cli");
18754132431fSAlex Bennée     }
18764132431fSAlex Bennée 
18774132431fSAlex Bennée     printf("STI exception:\n");
18784132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
18794132431fSAlex Bennée         asm volatile ("cli");
18804132431fSAlex Bennée     }
18814132431fSAlex Bennée 
18824132431fSAlex Bennée #if !defined(__x86_64__)
18834132431fSAlex Bennée     printf("INTO exception:\n");
18844132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
18854132431fSAlex Bennée         /* overflow exception */
18864132431fSAlex Bennée         asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff));
18874132431fSAlex Bennée     }
18884132431fSAlex Bennée #endif
18894132431fSAlex Bennée 
18904132431fSAlex Bennée     printf("OUTB exception:\n");
18914132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
18924132431fSAlex Bennée         asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0));
18934132431fSAlex Bennée     }
18944132431fSAlex Bennée 
18954132431fSAlex Bennée     printf("INB exception:\n");
18964132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
18974132431fSAlex Bennée         asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321));
18984132431fSAlex Bennée     }
18994132431fSAlex Bennée 
19004132431fSAlex Bennée     printf("REP OUTSB exception:\n");
19014132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
19024132431fSAlex Bennée         asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1));
19034132431fSAlex Bennée     }
19044132431fSAlex Bennée 
19054132431fSAlex Bennée     printf("REP INSB exception:\n");
19064132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
19074132431fSAlex Bennée         asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1));
19084132431fSAlex Bennée     }
19094132431fSAlex Bennée 
19104132431fSAlex Bennée     printf("HLT exception:\n");
19114132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
19124132431fSAlex Bennée         asm volatile ("hlt");
19134132431fSAlex Bennée     }
19144132431fSAlex Bennée 
19154132431fSAlex Bennée     printf("single step exception:\n");
19164132431fSAlex Bennée     val = 0;
19174132431fSAlex Bennée     if (setjmp(jmp_env) == 0) {
19184132431fSAlex Bennée         asm volatile ("pushf\n"
19194132431fSAlex Bennée                       "orl $0x00100, (%%esp)\n"
19204132431fSAlex Bennée                       "popf\n"
19214132431fSAlex Bennée                       "movl $0xabcd, %0\n"
19224132431fSAlex Bennée                       "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory");
19234132431fSAlex Bennée     }
19244132431fSAlex Bennée     printf("val=0x%x\n", val);
19254132431fSAlex Bennée }
19264132431fSAlex Bennée 
19274132431fSAlex Bennée #if !defined(__x86_64__)
19284132431fSAlex Bennée /* specific precise single step test */
sig_trap_handler(int sig,siginfo_t * info,void * puc)19294132431fSAlex Bennée void sig_trap_handler(int sig, siginfo_t *info, void *puc)
19304132431fSAlex Bennée {
19314132431fSAlex Bennée     ucontext_t *uc = puc;
19324132431fSAlex Bennée     printf("EIP=" FMTLX "\n", (long)uc->uc_mcontext.gregs[REG_EIP]);
19334132431fSAlex Bennée }
19344132431fSAlex Bennée 
19354132431fSAlex Bennée const uint8_t sstep_buf1[4] = { 1, 2, 3, 4};
19364132431fSAlex Bennée uint8_t sstep_buf2[4];
19374132431fSAlex Bennée 
test_single_step(void)19384132431fSAlex Bennée void test_single_step(void)
19394132431fSAlex Bennée {
19404132431fSAlex Bennée     struct sigaction act;
19414132431fSAlex Bennée     volatile int val;
19424132431fSAlex Bennée     int i;
19434132431fSAlex Bennée 
19444132431fSAlex Bennée     val = 0;
19454132431fSAlex Bennée     act.sa_sigaction = sig_trap_handler;
19464132431fSAlex Bennée     sigemptyset(&act.sa_mask);
19474132431fSAlex Bennée     act.sa_flags = SA_SIGINFO;
19484132431fSAlex Bennée     sigaction(SIGTRAP, &act, NULL);
19494132431fSAlex Bennée     asm volatile ("pushf\n"
19504132431fSAlex Bennée                   "orl $0x00100, (%%esp)\n"
19514132431fSAlex Bennée                   "popf\n"
19524132431fSAlex Bennée                   "movl $0xabcd, %0\n"
19534132431fSAlex Bennée 
19544132431fSAlex Bennée                   /* jmp test */
19554132431fSAlex Bennée                   "movl $3, %%ecx\n"
19564132431fSAlex Bennée                   "1:\n"
19574132431fSAlex Bennée                   "addl $1, %0\n"
19584132431fSAlex Bennée                   "decl %%ecx\n"
19594132431fSAlex Bennée                   "jnz 1b\n"
19604132431fSAlex Bennée 
19614132431fSAlex Bennée                   /* movsb: the single step should stop at each movsb iteration */
19624132431fSAlex Bennée                   "movl $sstep_buf1, %%esi\n"
19634132431fSAlex Bennée                   "movl $sstep_buf2, %%edi\n"
19644132431fSAlex Bennée                   "movl $0, %%ecx\n"
19654132431fSAlex Bennée                   "rep movsb\n"
19664132431fSAlex Bennée                   "movl $3, %%ecx\n"
19674132431fSAlex Bennée                   "rep movsb\n"
19684132431fSAlex Bennée                   "movl $1, %%ecx\n"
19694132431fSAlex Bennée                   "rep movsb\n"
19704132431fSAlex Bennée 
19714132431fSAlex Bennée                   /* cmpsb: the single step should stop at each cmpsb iteration */
19724132431fSAlex Bennée                   "movl $sstep_buf1, %%esi\n"
19734132431fSAlex Bennée                   "movl $sstep_buf2, %%edi\n"
19744132431fSAlex Bennée                   "movl $0, %%ecx\n"
19754132431fSAlex Bennée                   "rep cmpsb\n"
19764132431fSAlex Bennée                   "movl $4, %%ecx\n"
19774132431fSAlex Bennée                   "rep cmpsb\n"
19784132431fSAlex Bennée 
19794132431fSAlex Bennée                   /* getpid() syscall: single step should skip one
19804132431fSAlex Bennée                      instruction */
19814132431fSAlex Bennée                   "movl $20, %%eax\n"
19824132431fSAlex Bennée                   "int $0x80\n"
19834132431fSAlex Bennée                   "movl $0, %%eax\n"
19844132431fSAlex Bennée 
19854132431fSAlex Bennée                   /* when modifying SS, trace is not done on the next
19864132431fSAlex Bennée                      instruction */
19874132431fSAlex Bennée                   "movl %%ss, %%ecx\n"
19884132431fSAlex Bennée                   "movl %%ecx, %%ss\n"
19894132431fSAlex Bennée                   "addl $1, %0\n"
19904132431fSAlex Bennée                   "movl $1, %%eax\n"
19914132431fSAlex Bennée                   "movl %%ecx, %%ss\n"
19924132431fSAlex Bennée                   "jmp 1f\n"
19934132431fSAlex Bennée                   "addl $1, %0\n"
19944132431fSAlex Bennée                   "1:\n"
19954132431fSAlex Bennée                   "movl $1, %%eax\n"
19964132431fSAlex Bennée                   "pushl %%ecx\n"
19974132431fSAlex Bennée                   "popl %%ss\n"
19984132431fSAlex Bennée                   "addl $1, %0\n"
19994132431fSAlex Bennée                   "movl $1, %%eax\n"
20004132431fSAlex Bennée 
20014132431fSAlex Bennée                   "pushf\n"
20024132431fSAlex Bennée                   "andl $~0x00100, (%%esp)\n"
20034132431fSAlex Bennée                   "popf\n"
20044132431fSAlex Bennée                   : "=m" (val)
20054132431fSAlex Bennée                   :
20064132431fSAlex Bennée                   : "cc", "memory", "eax", "ecx", "esi", "edi");
20074132431fSAlex Bennée     printf("val=%d\n", val);
20084132431fSAlex Bennée     for(i = 0; i < 4; i++)
20094132431fSAlex Bennée         printf("sstep_buf2[%d] = %d\n", i, sstep_buf2[i]);
20104132431fSAlex Bennée }
20114132431fSAlex Bennée 
20124132431fSAlex Bennée /* self modifying code test */
20134132431fSAlex Bennée uint8_t code[] = {
20144132431fSAlex Bennée     0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */
20154132431fSAlex Bennée     0xc3, /* ret */
20164132431fSAlex Bennée };
20174132431fSAlex Bennée 
2018d64655c2SRichard Henderson asm(".section \".data_x\",\"awx\"\n"
20194132431fSAlex Bennée     "smc_code2:\n"
20204132431fSAlex Bennée     "movl 4(%esp), %eax\n"
20214132431fSAlex Bennée     "movl %eax, smc_patch_addr2 + 1\n"
20224132431fSAlex Bennée     "nop\n"
20234132431fSAlex Bennée     "nop\n"
20244132431fSAlex Bennée     "nop\n"
20254132431fSAlex Bennée     "nop\n"
20264132431fSAlex Bennée     "nop\n"
20274132431fSAlex Bennée     "nop\n"
20284132431fSAlex Bennée     "nop\n"
20294132431fSAlex Bennée     "nop\n"
20304132431fSAlex Bennée     "smc_patch_addr2:\n"
20314132431fSAlex Bennée     "movl $1, %eax\n"
20324132431fSAlex Bennée     "ret\n"
20334132431fSAlex Bennée     ".previous\n"
20344132431fSAlex Bennée     );
20354132431fSAlex Bennée 
20364132431fSAlex Bennée typedef int FuncType(void);
20374132431fSAlex Bennée extern int smc_code2(int);
test_self_modifying_code(void)20384132431fSAlex Bennée void test_self_modifying_code(void)
20394132431fSAlex Bennée {
20404132431fSAlex Bennée     int i;
20414132431fSAlex Bennée     printf("self modifying code:\n");
20424132431fSAlex Bennée     printf("func1 = 0x%x\n", ((FuncType *)code)());
20434132431fSAlex Bennée     for(i = 2; i <= 4; i++) {
20444132431fSAlex Bennée         code[1] = i;
20454132431fSAlex Bennée         printf("func%d = 0x%x\n", i, ((FuncType *)code)());
20464132431fSAlex Bennée     }
20474132431fSAlex Bennée 
20484132431fSAlex Bennée     /* more difficult test : the modified code is just after the
20494132431fSAlex Bennée        modifying instruction. It is forbidden in Intel specs, but it
20504132431fSAlex Bennée        is used by old DOS programs */
20514132431fSAlex Bennée     for(i = 2; i <= 4; i++) {
20524132431fSAlex Bennée         printf("smc_code2(%d) = %d\n", i, smc_code2(i));
20534132431fSAlex Bennée     }
20544132431fSAlex Bennée }
20554132431fSAlex Bennée #endif
20564132431fSAlex Bennée 
20574132431fSAlex Bennée long enter_stack[4096];
20584132431fSAlex Bennée 
20594132431fSAlex Bennée #if defined(__x86_64__)
20604132431fSAlex Bennée #define RSP "%%rsp"
20614132431fSAlex Bennée #define RBP "%%rbp"
20624132431fSAlex Bennée #else
20634132431fSAlex Bennée #define RSP "%%esp"
20644132431fSAlex Bennée #define RBP "%%ebp"
20654132431fSAlex Bennée #endif
20664132431fSAlex Bennée 
20674132431fSAlex Bennée #if !defined(__x86_64__)
20684132431fSAlex Bennée /* causes an infinite loop, disable it for now.  */
20694132431fSAlex Bennée #define TEST_ENTER(size, stack_type, level)
20704132431fSAlex Bennée #else
20714132431fSAlex Bennée #define TEST_ENTER(size, stack_type, level)\
20724132431fSAlex Bennée {\
20734132431fSAlex Bennée     long esp_save, esp_val, ebp_val, ebp_save, i;\
20744132431fSAlex Bennée     stack_type *ptr, *stack_end, *stack_ptr;\
20754132431fSAlex Bennée     memset(enter_stack, 0, sizeof(enter_stack));\
20764132431fSAlex Bennée     stack_end = stack_ptr = (stack_type *)(enter_stack + 4096);\
20774132431fSAlex Bennée     ebp_val = (long)stack_ptr;\
20784132431fSAlex Bennée     for(i=1;i<=32;i++)\
20794132431fSAlex Bennée        *--stack_ptr = i;\
20804132431fSAlex Bennée     esp_val = (long)stack_ptr;\
20814132431fSAlex Bennée     asm("mov " RSP ", %[esp_save]\n"\
20824132431fSAlex Bennée         "mov " RBP ", %[ebp_save]\n"\
20834132431fSAlex Bennée         "mov %[esp_val], " RSP "\n"\
20844132431fSAlex Bennée         "mov %[ebp_val], " RBP "\n"\
20854132431fSAlex Bennée         "enter" size " $8, $" #level "\n"\
20864132431fSAlex Bennée         "mov " RSP ", %[esp_val]\n"\
20874132431fSAlex Bennée         "mov " RBP ", %[ebp_val]\n"\
20884132431fSAlex Bennée         "mov %[esp_save], " RSP "\n"\
20894132431fSAlex Bennée         "mov %[ebp_save], " RBP "\n"\
20904132431fSAlex Bennée         : [esp_save] "=r" (esp_save),\
20914132431fSAlex Bennée         [ebp_save] "=r" (ebp_save),\
20924132431fSAlex Bennée         [esp_val] "=r" (esp_val),\
20934132431fSAlex Bennée         [ebp_val] "=r" (ebp_val)\
20944132431fSAlex Bennée         :  "[esp_val]" (esp_val),\
20954132431fSAlex Bennée         "[ebp_val]" (ebp_val));\
20964132431fSAlex Bennée     printf("level=%d:\n", level);\
20974132431fSAlex Bennée     printf("esp_val=" FMTLX "\n", esp_val - (long)stack_end);\
20984132431fSAlex Bennée     printf("ebp_val=" FMTLX "\n", ebp_val - (long)stack_end);\
20994132431fSAlex Bennée     for(ptr = (stack_type *)esp_val; ptr < stack_end; ptr++)\
21004132431fSAlex Bennée         printf(FMTLX "\n", (long)ptr[0]);\
21014132431fSAlex Bennée }
21024132431fSAlex Bennée #endif
21034132431fSAlex Bennée 
test_enter(void)21044132431fSAlex Bennée static void test_enter(void)
21054132431fSAlex Bennée {
21064132431fSAlex Bennée #if defined(__x86_64__)
21074132431fSAlex Bennée     TEST_ENTER("q", uint64_t, 0);
21084132431fSAlex Bennée     TEST_ENTER("q", uint64_t, 1);
21094132431fSAlex Bennée     TEST_ENTER("q", uint64_t, 2);
21104132431fSAlex Bennée     TEST_ENTER("q", uint64_t, 31);
21114132431fSAlex Bennée #else
21124132431fSAlex Bennée     TEST_ENTER("l", uint32_t, 0);
21134132431fSAlex Bennée     TEST_ENTER("l", uint32_t, 1);
21144132431fSAlex Bennée     TEST_ENTER("l", uint32_t, 2);
21154132431fSAlex Bennée     TEST_ENTER("l", uint32_t, 31);
21164132431fSAlex Bennée #endif
21174132431fSAlex Bennée 
21184132431fSAlex Bennée     TEST_ENTER("w", uint16_t, 0);
21194132431fSAlex Bennée     TEST_ENTER("w", uint16_t, 1);
21204132431fSAlex Bennée     TEST_ENTER("w", uint16_t, 2);
21214132431fSAlex Bennée     TEST_ENTER("w", uint16_t, 31);
21224132431fSAlex Bennée }
21234132431fSAlex Bennée 
21244132431fSAlex Bennée #define TEST_CONV_RAX(op)\
21254132431fSAlex Bennée {\
21264132431fSAlex Bennée     unsigned long a, r;\
21274132431fSAlex Bennée     a = i2l(0x8234a6f8);\
21284132431fSAlex Bennée     r = a;\
21294132431fSAlex Bennée     asm volatile(#op : "=a" (r) : "0" (r));\
21304132431fSAlex Bennée     printf("%-10s A=" FMTLX " R=" FMTLX "\n", #op, a, r);\
21314132431fSAlex Bennée }
21324132431fSAlex Bennée 
21334132431fSAlex Bennée #define TEST_CONV_RAX_RDX(op)\
21344132431fSAlex Bennée {\
21354132431fSAlex Bennée     unsigned long a, d, r, rh;                   \
21364132431fSAlex Bennée     a = i2l(0x8234a6f8);\
21374132431fSAlex Bennée     d = i2l(0x8345a1f2);\
21384132431fSAlex Bennée     r = a;\
21394132431fSAlex Bennée     rh = d;\
21404132431fSAlex Bennée     asm volatile(#op : "=a" (r), "=d" (rh) : "0" (r), "1" (rh));   \
21414132431fSAlex Bennée     printf("%-10s A=" FMTLX " R=" FMTLX ":" FMTLX "\n", #op, a, r, rh);  \
21424132431fSAlex Bennée }
21434132431fSAlex Bennée 
test_conv(void)21444132431fSAlex Bennée void test_conv(void)
21454132431fSAlex Bennée {
21464132431fSAlex Bennée     TEST_CONV_RAX(cbw);
21474132431fSAlex Bennée     TEST_CONV_RAX(cwde);
21484132431fSAlex Bennée #if defined(__x86_64__)
21494132431fSAlex Bennée     TEST_CONV_RAX(cdqe);
21504132431fSAlex Bennée #endif
21514132431fSAlex Bennée 
21524132431fSAlex Bennée     TEST_CONV_RAX_RDX(cwd);
21534132431fSAlex Bennée     TEST_CONV_RAX_RDX(cdq);
21544132431fSAlex Bennée #if defined(__x86_64__)
21554132431fSAlex Bennée     TEST_CONV_RAX_RDX(cqo);
21564132431fSAlex Bennée #endif
21574132431fSAlex Bennée 
21584132431fSAlex Bennée     {
21594132431fSAlex Bennée         unsigned long a, r;
21604132431fSAlex Bennée         a = i2l(0x12345678);
21614132431fSAlex Bennée         asm volatile("bswapl %k0" : "=r" (r) : "0" (a));
21624132431fSAlex Bennée         printf("%-10s: A=" FMTLX " R=" FMTLX "\n", "bswapl", a, r);
21634132431fSAlex Bennée     }
21644132431fSAlex Bennée #if defined(__x86_64__)
21654132431fSAlex Bennée     {
21664132431fSAlex Bennée         unsigned long a, r;
21674132431fSAlex Bennée         a = i2l(0x12345678);
21684132431fSAlex Bennée         asm volatile("bswapq %0" : "=r" (r) : "0" (a));
21694132431fSAlex Bennée         printf("%-10s: A=" FMTLX " R=" FMTLX "\n", "bswapq", a, r);
21704132431fSAlex Bennée     }
21714132431fSAlex Bennée #endif
21724132431fSAlex Bennée }
21734132431fSAlex Bennée 
21744132431fSAlex Bennée extern void *__start_initcall;
21754132431fSAlex Bennée extern void *__stop_initcall;
21764132431fSAlex Bennée 
21774132431fSAlex Bennée 
main(int argc,char ** argv)21784132431fSAlex Bennée int main(int argc, char **argv)
21794132431fSAlex Bennée {
21804132431fSAlex Bennée     void **ptr;
21814132431fSAlex Bennée     void (*func)(void);
21824132431fSAlex Bennée 
21834132431fSAlex Bennée     ptr = &__start_initcall;
21844132431fSAlex Bennée     while (ptr != &__stop_initcall) {
21854132431fSAlex Bennée         func = *ptr++;
21864132431fSAlex Bennée         func();
21874132431fSAlex Bennée     }
21884132431fSAlex Bennée     test_bsx();
2189*ff5b5739SPaolo Bonzini     test_xcnt();
21904132431fSAlex Bennée     test_mul();
21914132431fSAlex Bennée     test_jcc();
21924132431fSAlex Bennée     test_loop();
21934132431fSAlex Bennée     test_floats();
21944132431fSAlex Bennée #if !defined(__x86_64__)
21954132431fSAlex Bennée     test_bcd();
21964132431fSAlex Bennée #endif
21974132431fSAlex Bennée     test_xchg();
21984132431fSAlex Bennée     test_string();
21994132431fSAlex Bennée     test_misc();
22004132431fSAlex Bennée     test_lea();
22014132431fSAlex Bennée #ifdef TEST_SEGS
22024132431fSAlex Bennée     test_segs();
22034132431fSAlex Bennée     test_code16();
22044132431fSAlex Bennée #endif
22054132431fSAlex Bennée #ifdef TEST_VM86
22064132431fSAlex Bennée     test_vm86();
22074132431fSAlex Bennée #endif
22084132431fSAlex Bennée #if !defined(__x86_64__)
22094132431fSAlex Bennée     test_exceptions();
22104132431fSAlex Bennée     test_self_modifying_code();
22114132431fSAlex Bennée     test_single_step();
22124132431fSAlex Bennée #endif
22134132431fSAlex Bennée     test_enter();
22144132431fSAlex Bennée     test_conv();
22154132431fSAlex Bennée     return 0;
22164132431fSAlex Bennée }
2217