Statistics
| Branch: | Revision:

root / tests / test-i386.c @ 681f8c29

History | View | Annotate | Download (70.1 kB)

1 78d6da97 bellard
/*
2 78d6da97 bellard
 *  x86 CPU test
3 5fafdf24 ths
 *
4 78d6da97 bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 78d6da97 bellard
 *
6 78d6da97 bellard
 *  This program is free software; you can redistribute it and/or modify
7 78d6da97 bellard
 *  it under the terms of the GNU General Public License as published by
8 78d6da97 bellard
 *  the Free Software Foundation; either version 2 of the License, or
9 78d6da97 bellard
 *  (at your option) any later version.
10 78d6da97 bellard
 *
11 78d6da97 bellard
 *  This program is distributed in the hope that it will be useful,
12 78d6da97 bellard
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 78d6da97 bellard
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 78d6da97 bellard
 *  GNU General Public License for more details.
15 78d6da97 bellard
 *
16 78d6da97 bellard
 *  You should have received a copy of the GNU General Public License
17 78d6da97 bellard
 *  along with this program; if not, write to the Free Software
18 78d6da97 bellard
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 78d6da97 bellard
 */
20 3a27ad0b bellard
#define _GNU_SOURCE
21 4d1135e4 bellard
#include <stdlib.h>
22 4d1135e4 bellard
#include <stdio.h>
23 e3e86d56 bellard
#include <string.h>
24 6dbad63e bellard
#include <inttypes.h>
25 4d1135e4 bellard
#include <math.h>
26 3a27ad0b bellard
#include <signal.h>
27 3a27ad0b bellard
#include <setjmp.h>
28 070893f4 bellard
#include <errno.h>
29 3a27ad0b bellard
#include <sys/ucontext.h>
30 3a27ad0b bellard
#include <sys/mman.h>
31 4d1135e4 bellard
32 776f2227 bellard
#if !defined(__x86_64__)
33 a5973fbf bellard
//#define TEST_VM86
34 776f2227 bellard
#define TEST_SEGS
35 776f2227 bellard
#endif
36 3ff0631e bellard
//#define LINUX_VM86_IOPL_FIX
37 791c2261 bellard
//#define TEST_P4_FLAGS
38 a5973fbf bellard
#ifdef __SSE__
39 776f2227 bellard
#define TEST_SSE
40 776f2227 bellard
#define TEST_CMOV  1
41 776f2227 bellard
#define TEST_FCOMI 1
42 776f2227 bellard
#else
43 a5973fbf bellard
#undef TEST_SSE
44 a5973fbf bellard
#define TEST_CMOV  1
45 a5973fbf bellard
#define TEST_FCOMI 1
46 776f2227 bellard
#endif
47 776f2227 bellard
48 776f2227 bellard
#if defined(__x86_64__)
49 776f2227 bellard
#define FMT64X "%016lx"
50 776f2227 bellard
#define FMTLX "%016lx"
51 776f2227 bellard
#define X86_64_ONLY(x) x
52 776f2227 bellard
#else
53 26a76461 bellard
#define FMT64X "%016" PRIx64
54 776f2227 bellard
#define FMTLX "%08lx"
55 776f2227 bellard
#define X86_64_ONLY(x)
56 776f2227 bellard
#endif
57 776f2227 bellard
58 776f2227 bellard
#ifdef TEST_VM86
59 776f2227 bellard
#include <asm/vm86.h>
60 776f2227 bellard
#endif
61 5dd9488c bellard
62 4d1135e4 bellard
#define xglue(x, y) x ## y
63 4d1135e4 bellard
#define glue(x, y) xglue(x, y)
64 4d1135e4 bellard
#define stringify(s)        tostring(s)
65 4d1135e4 bellard
#define tostring(s)        #s
66 4d1135e4 bellard
67 4d1135e4 bellard
#define CC_C           0x0001
68 4d1135e4 bellard
#define CC_P         0x0004
69 4d1135e4 bellard
#define CC_A        0x0010
70 4d1135e4 bellard
#define CC_Z        0x0040
71 4d1135e4 bellard
#define CC_S    0x0080
72 4d1135e4 bellard
#define CC_O    0x0800
73 4d1135e4 bellard
74 776f2227 bellard
#define __init_call        __attribute__ ((unused,__section__ ("initcall")))
75 4d1135e4 bellard
76 4b74fe1f bellard
#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
77 4b74fe1f bellard
78 776f2227 bellard
#if defined(__x86_64__)
79 776f2227 bellard
static inline long i2l(long v)
80 776f2227 bellard
{
81 776f2227 bellard
    return v | ((v ^ 0xabcd) << 32);
82 776f2227 bellard
}
83 776f2227 bellard
#else
84 776f2227 bellard
static inline long i2l(long v)
85 776f2227 bellard
{
86 776f2227 bellard
    return v;
87 776f2227 bellard
}
88 776f2227 bellard
#endif
89 776f2227 bellard
90 4d1135e4 bellard
#define OP add
91 4d1135e4 bellard
#include "test-i386.h"
92 4d1135e4 bellard
93 4d1135e4 bellard
#define OP sub
94 4d1135e4 bellard
#include "test-i386.h"
95 4d1135e4 bellard
96 4d1135e4 bellard
#define OP xor
97 4d1135e4 bellard
#include "test-i386.h"
98 4d1135e4 bellard
99 4d1135e4 bellard
#define OP and
100 4d1135e4 bellard
#include "test-i386.h"
101 4d1135e4 bellard
102 4d1135e4 bellard
#define OP or
103 4d1135e4 bellard
#include "test-i386.h"
104 4d1135e4 bellard
105 4d1135e4 bellard
#define OP cmp
106 4d1135e4 bellard
#include "test-i386.h"
107 4d1135e4 bellard
108 4d1135e4 bellard
#define OP adc
109 4d1135e4 bellard
#define OP_CC
110 4d1135e4 bellard
#include "test-i386.h"
111 4d1135e4 bellard
112 4d1135e4 bellard
#define OP sbb
113 4d1135e4 bellard
#define OP_CC
114 4d1135e4 bellard
#include "test-i386.h"
115 4d1135e4 bellard
116 4d1135e4 bellard
#define OP inc
117 4d1135e4 bellard
#define OP_CC
118 4d1135e4 bellard
#define OP1
119 4d1135e4 bellard
#include "test-i386.h"
120 4d1135e4 bellard
121 4d1135e4 bellard
#define OP dec
122 4d1135e4 bellard
#define OP_CC
123 4d1135e4 bellard
#define OP1
124 4d1135e4 bellard
#include "test-i386.h"
125 4d1135e4 bellard
126 4d1135e4 bellard
#define OP neg
127 4d1135e4 bellard
#define OP_CC
128 4d1135e4 bellard
#define OP1
129 4d1135e4 bellard
#include "test-i386.h"
130 4d1135e4 bellard
131 4d1135e4 bellard
#define OP not
132 4d1135e4 bellard
#define OP_CC
133 4d1135e4 bellard
#define OP1
134 4d1135e4 bellard
#include "test-i386.h"
135 4d1135e4 bellard
136 4b74fe1f bellard
#undef CC_MASK
137 4b74fe1f bellard
#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)
138 4b74fe1f bellard
139 379ca80d bellard
#define OP shl
140 379ca80d bellard
#include "test-i386-shift.h"
141 379ca80d bellard
142 379ca80d bellard
#define OP shr
143 379ca80d bellard
#include "test-i386-shift.h"
144 379ca80d bellard
145 379ca80d bellard
#define OP sar
146 379ca80d bellard
#include "test-i386-shift.h"
147 379ca80d bellard
148 379ca80d bellard
#define OP rol
149 379ca80d bellard
#include "test-i386-shift.h"
150 379ca80d bellard
151 379ca80d bellard
#define OP ror
152 379ca80d bellard
#include "test-i386-shift.h"
153 379ca80d bellard
154 379ca80d bellard
#define OP rcr
155 379ca80d bellard
#define OP_CC
156 379ca80d bellard
#include "test-i386-shift.h"
157 379ca80d bellard
158 379ca80d bellard
#define OP rcl
159 379ca80d bellard
#define OP_CC
160 379ca80d bellard
#include "test-i386-shift.h"
161 379ca80d bellard
162 d57c4e01 bellard
#define OP shld
163 d57c4e01 bellard
#define OP_SHIFTD
164 d57c4e01 bellard
#define OP_NOBYTE
165 d57c4e01 bellard
#include "test-i386-shift.h"
166 d57c4e01 bellard
167 d57c4e01 bellard
#define OP shrd
168 d57c4e01 bellard
#define OP_SHIFTD
169 d57c4e01 bellard
#define OP_NOBYTE
170 d57c4e01 bellard
#include "test-i386-shift.h"
171 d57c4e01 bellard
172 d57c4e01 bellard
/* XXX: should be more precise ? */
173 d57c4e01 bellard
#undef CC_MASK
174 d57c4e01 bellard
#define CC_MASK (CC_C)
175 d57c4e01 bellard
176 d57c4e01 bellard
#define OP bt
177 d57c4e01 bellard
#define OP_NOBYTE
178 d57c4e01 bellard
#include "test-i386-shift.h"
179 d57c4e01 bellard
180 d57c4e01 bellard
#define OP bts
181 d57c4e01 bellard
#define OP_NOBYTE
182 d57c4e01 bellard
#include "test-i386-shift.h"
183 d57c4e01 bellard
184 d57c4e01 bellard
#define OP btr
185 d57c4e01 bellard
#define OP_NOBYTE
186 d57c4e01 bellard
#include "test-i386-shift.h"
187 d57c4e01 bellard
188 d57c4e01 bellard
#define OP btc
189 d57c4e01 bellard
#define OP_NOBYTE
190 d57c4e01 bellard
#include "test-i386-shift.h"
191 379ca80d bellard
192 4d1135e4 bellard
/* lea test (modrm support) */
193 776f2227 bellard
#define TEST_LEAQ(STR)\
194 776f2227 bellard
{\
195 776f2227 bellard
    asm("lea " STR ", %0"\
196 776f2227 bellard
        : "=r" (res)\
197 776f2227 bellard
        : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
198 776f2227 bellard
    printf("lea %s = " FMTLX "\n", STR, res);\
199 776f2227 bellard
}
200 776f2227 bellard
201 4d1135e4 bellard
#define TEST_LEA(STR)\
202 4d1135e4 bellard
{\
203 776f2227 bellard
    asm("lea " STR ", %0"\
204 4d1135e4 bellard
        : "=r" (res)\
205 4d1135e4 bellard
        : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
206 776f2227 bellard
    printf("lea %s = " FMTLX "\n", STR, res);\
207 4d1135e4 bellard
}
208 4d1135e4 bellard
209 4d1135e4 bellard
#define TEST_LEA16(STR)\
210 4d1135e4 bellard
{\
211 4d1135e4 bellard
    asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\
212 4d1135e4 bellard
        : "=wq" (res)\
213 4d1135e4 bellard
        : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
214 776f2227 bellard
    printf("lea %s = %08lx\n", STR, res);\
215 4d1135e4 bellard
}
216 4d1135e4 bellard
217 4d1135e4 bellard
218 4d1135e4 bellard
void test_lea(void)
219 4d1135e4 bellard
{
220 776f2227 bellard
    long eax, ebx, ecx, edx, esi, edi, res;
221 776f2227 bellard
    eax = i2l(0x0001);
222 776f2227 bellard
    ebx = i2l(0x0002);
223 776f2227 bellard
    ecx = i2l(0x0004);
224 776f2227 bellard
    edx = i2l(0x0008);
225 776f2227 bellard
    esi = i2l(0x0010);
226 776f2227 bellard
    edi = i2l(0x0020);
227 4d1135e4 bellard
228 4d1135e4 bellard
    TEST_LEA("0x4000");
229 4d1135e4 bellard
230 4d1135e4 bellard
    TEST_LEA("(%%eax)");
231 4d1135e4 bellard
    TEST_LEA("(%%ebx)");
232 4d1135e4 bellard
    TEST_LEA("(%%ecx)");
233 4d1135e4 bellard
    TEST_LEA("(%%edx)");
234 4d1135e4 bellard
    TEST_LEA("(%%esi)");
235 4d1135e4 bellard
    TEST_LEA("(%%edi)");
236 4d1135e4 bellard
237 4d1135e4 bellard
    TEST_LEA("0x40(%%eax)");
238 4d1135e4 bellard
    TEST_LEA("0x40(%%ebx)");
239 4d1135e4 bellard
    TEST_LEA("0x40(%%ecx)");
240 4d1135e4 bellard
    TEST_LEA("0x40(%%edx)");
241 4d1135e4 bellard
    TEST_LEA("0x40(%%esi)");
242 4d1135e4 bellard
    TEST_LEA("0x40(%%edi)");
243 4d1135e4 bellard
244 4d1135e4 bellard
    TEST_LEA("0x4000(%%eax)");
245 4d1135e4 bellard
    TEST_LEA("0x4000(%%ebx)");
246 4d1135e4 bellard
    TEST_LEA("0x4000(%%ecx)");
247 4d1135e4 bellard
    TEST_LEA("0x4000(%%edx)");
248 4d1135e4 bellard
    TEST_LEA("0x4000(%%esi)");
249 4d1135e4 bellard
    TEST_LEA("0x4000(%%edi)");
250 4d1135e4 bellard
251 4d1135e4 bellard
    TEST_LEA("(%%eax, %%ecx)");
252 4d1135e4 bellard
    TEST_LEA("(%%ebx, %%edx)");
253 4d1135e4 bellard
    TEST_LEA("(%%ecx, %%ecx)");
254 4d1135e4 bellard
    TEST_LEA("(%%edx, %%ecx)");
255 4d1135e4 bellard
    TEST_LEA("(%%esi, %%ecx)");
256 4d1135e4 bellard
    TEST_LEA("(%%edi, %%ecx)");
257 4d1135e4 bellard
258 4d1135e4 bellard
    TEST_LEA("0x40(%%eax, %%ecx)");
259 4d1135e4 bellard
    TEST_LEA("0x4000(%%ebx, %%edx)");
260 4d1135e4 bellard
261 4d1135e4 bellard
    TEST_LEA("(%%ecx, %%ecx, 2)");
262 4d1135e4 bellard
    TEST_LEA("(%%edx, %%ecx, 4)");
263 4d1135e4 bellard
    TEST_LEA("(%%esi, %%ecx, 8)");
264 4d1135e4 bellard
265 4d1135e4 bellard
    TEST_LEA("(,%%eax, 2)");
266 4d1135e4 bellard
    TEST_LEA("(,%%ebx, 4)");
267 4d1135e4 bellard
    TEST_LEA("(,%%ecx, 8)");
268 4d1135e4 bellard
269 4d1135e4 bellard
    TEST_LEA("0x40(,%%eax, 2)");
270 4d1135e4 bellard
    TEST_LEA("0x40(,%%ebx, 4)");
271 4d1135e4 bellard
    TEST_LEA("0x40(,%%ecx, 8)");
272 4d1135e4 bellard
273 4d1135e4 bellard
274 4d1135e4 bellard
    TEST_LEA("-10(%%ecx, %%ecx, 2)");
275 4d1135e4 bellard
    TEST_LEA("-10(%%edx, %%ecx, 4)");
276 4d1135e4 bellard
    TEST_LEA("-10(%%esi, %%ecx, 8)");
277 4d1135e4 bellard
278 4d1135e4 bellard
    TEST_LEA("0x4000(%%ecx, %%ecx, 2)");
279 4d1135e4 bellard
    TEST_LEA("0x4000(%%edx, %%ecx, 4)");
280 4d1135e4 bellard
    TEST_LEA("0x4000(%%esi, %%ecx, 8)");
281 4d1135e4 bellard
282 776f2227 bellard
#if defined(__x86_64__)
283 776f2227 bellard
    TEST_LEAQ("0x4000");
284 776f2227 bellard
    TEST_LEAQ("0x4000(%%rip)");
285 776f2227 bellard
286 776f2227 bellard
    TEST_LEAQ("(%%rax)");
287 776f2227 bellard
    TEST_LEAQ("(%%rbx)");
288 776f2227 bellard
    TEST_LEAQ("(%%rcx)");
289 776f2227 bellard
    TEST_LEAQ("(%%rdx)");
290 776f2227 bellard
    TEST_LEAQ("(%%rsi)");
291 776f2227 bellard
    TEST_LEAQ("(%%rdi)");
292 776f2227 bellard
293 776f2227 bellard
    TEST_LEAQ("0x40(%%rax)");
294 776f2227 bellard
    TEST_LEAQ("0x40(%%rbx)");
295 776f2227 bellard
    TEST_LEAQ("0x40(%%rcx)");
296 776f2227 bellard
    TEST_LEAQ("0x40(%%rdx)");
297 776f2227 bellard
    TEST_LEAQ("0x40(%%rsi)");
298 776f2227 bellard
    TEST_LEAQ("0x40(%%rdi)");
299 776f2227 bellard
300 776f2227 bellard
    TEST_LEAQ("0x4000(%%rax)");
301 776f2227 bellard
    TEST_LEAQ("0x4000(%%rbx)");
302 776f2227 bellard
    TEST_LEAQ("0x4000(%%rcx)");
303 776f2227 bellard
    TEST_LEAQ("0x4000(%%rdx)");
304 776f2227 bellard
    TEST_LEAQ("0x4000(%%rsi)");
305 776f2227 bellard
    TEST_LEAQ("0x4000(%%rdi)");
306 776f2227 bellard
307 776f2227 bellard
    TEST_LEAQ("(%%rax, %%rcx)");
308 776f2227 bellard
    TEST_LEAQ("(%%rbx, %%rdx)");
309 776f2227 bellard
    TEST_LEAQ("(%%rcx, %%rcx)");
310 776f2227 bellard
    TEST_LEAQ("(%%rdx, %%rcx)");
311 776f2227 bellard
    TEST_LEAQ("(%%rsi, %%rcx)");
312 776f2227 bellard
    TEST_LEAQ("(%%rdi, %%rcx)");
313 776f2227 bellard
314 776f2227 bellard
    TEST_LEAQ("0x40(%%rax, %%rcx)");
315 776f2227 bellard
    TEST_LEAQ("0x4000(%%rbx, %%rdx)");
316 776f2227 bellard
317 776f2227 bellard
    TEST_LEAQ("(%%rcx, %%rcx, 2)");
318 776f2227 bellard
    TEST_LEAQ("(%%rdx, %%rcx, 4)");
319 776f2227 bellard
    TEST_LEAQ("(%%rsi, %%rcx, 8)");
320 776f2227 bellard
321 776f2227 bellard
    TEST_LEAQ("(,%%rax, 2)");
322 776f2227 bellard
    TEST_LEAQ("(,%%rbx, 4)");
323 776f2227 bellard
    TEST_LEAQ("(,%%rcx, 8)");
324 776f2227 bellard
325 776f2227 bellard
    TEST_LEAQ("0x40(,%%rax, 2)");
326 776f2227 bellard
    TEST_LEAQ("0x40(,%%rbx, 4)");
327 776f2227 bellard
    TEST_LEAQ("0x40(,%%rcx, 8)");
328 776f2227 bellard
329 776f2227 bellard
330 776f2227 bellard
    TEST_LEAQ("-10(%%rcx, %%rcx, 2)");
331 776f2227 bellard
    TEST_LEAQ("-10(%%rdx, %%rcx, 4)");
332 776f2227 bellard
    TEST_LEAQ("-10(%%rsi, %%rcx, 8)");
333 776f2227 bellard
334 776f2227 bellard
    TEST_LEAQ("0x4000(%%rcx, %%rcx, 2)");
335 776f2227 bellard
    TEST_LEAQ("0x4000(%%rdx, %%rcx, 4)");
336 776f2227 bellard
    TEST_LEAQ("0x4000(%%rsi, %%rcx, 8)");
337 776f2227 bellard
#else
338 4d1135e4 bellard
    /* limited 16 bit addressing test */
339 4d1135e4 bellard
    TEST_LEA16("0x4000");
340 4d1135e4 bellard
    TEST_LEA16("(%%bx)");
341 4d1135e4 bellard
    TEST_LEA16("(%%si)");
342 4d1135e4 bellard
    TEST_LEA16("(%%di)");
343 4d1135e4 bellard
    TEST_LEA16("0x40(%%bx)");
344 4d1135e4 bellard
    TEST_LEA16("0x40(%%si)");
345 4d1135e4 bellard
    TEST_LEA16("0x40(%%di)");
346 4d1135e4 bellard
    TEST_LEA16("0x4000(%%bx)");
347 4d1135e4 bellard
    TEST_LEA16("0x4000(%%si)");
348 4d1135e4 bellard
    TEST_LEA16("(%%bx,%%si)");
349 4d1135e4 bellard
    TEST_LEA16("(%%bx,%%di)");
350 4d1135e4 bellard
    TEST_LEA16("0x40(%%bx,%%si)");
351 4d1135e4 bellard
    TEST_LEA16("0x40(%%bx,%%di)");
352 4d1135e4 bellard
    TEST_LEA16("0x4000(%%bx,%%si)");
353 4d1135e4 bellard
    TEST_LEA16("0x4000(%%bx,%%di)");
354 776f2227 bellard
#endif
355 4d1135e4 bellard
}
356 4d1135e4 bellard
357 4d1135e4 bellard
#define TEST_JCC(JCC, v1, v2)\
358 4d1135e4 bellard
{\
359 5dd9488c bellard
    int res;\
360 4d1135e4 bellard
    asm("movl $1, %0\n\t"\
361 4d1135e4 bellard
        "cmpl %2, %1\n\t"\
362 5dd9488c bellard
        "j" JCC " 1f\n\t"\
363 4d1135e4 bellard
        "movl $0, %0\n\t"\
364 4d1135e4 bellard
        "1:\n\t"\
365 4d1135e4 bellard
        : "=r" (res)\
366 4d1135e4 bellard
        : "r" (v1), "r" (v2));\
367 5dd9488c bellard
    printf("%-10s %d\n", "j" JCC, res);\
368 5dd9488c bellard
\
369 5dd9488c bellard
    asm("movl $0, %0\n\t"\
370 5dd9488c bellard
        "cmpl %2, %1\n\t"\
371 5dd9488c bellard
        "set" JCC " %b0\n\t"\
372 5dd9488c bellard
        : "=r" (res)\
373 5dd9488c bellard
        : "r" (v1), "r" (v2));\
374 5dd9488c bellard
    printf("%-10s %d\n", "set" JCC, res);\
375 5dd9488c bellard
 if (TEST_CMOV) {\
376 776f2227 bellard
    long val = i2l(1);\
377 776f2227 bellard
    long res = i2l(0x12345678);\
378 776f2227 bellard
X86_64_ONLY(\
379 776f2227 bellard
    asm("cmpl %2, %1\n\t"\
380 776f2227 bellard
        "cmov" JCC "q %3, %0\n\t"\
381 5dd9488c bellard
        : "=r" (res)\
382 776f2227 bellard
        : "r" (v1), "r" (v2), "m" (val), "0" (res));\
383 d057099a bellard
        printf("%-10s R=" FMTLX "\n", "cmov" JCC "q", res);)\
384 776f2227 bellard
    asm("cmpl %2, %1\n\t"\
385 776f2227 bellard
        "cmov" JCC "l %k3, %k0\n\t"\
386 776f2227 bellard
        : "=r" (res)\
387 776f2227 bellard
        : "r" (v1), "r" (v2), "m" (val), "0" (res));\
388 776f2227 bellard
        printf("%-10s R=" FMTLX "\n", "cmov" JCC "l", res);\
389 776f2227 bellard
    asm("cmpl %2, %1\n\t"\
390 5dd9488c bellard
        "cmov" JCC "w %w3, %w0\n\t"\
391 5dd9488c bellard
        : "=r" (res)\
392 776f2227 bellard
        : "r" (v1), "r" (v2), "r" (1), "0" (res));\
393 776f2227 bellard
        printf("%-10s R=" FMTLX "\n", "cmov" JCC "w", res);\
394 5dd9488c bellard
 } \
395 4d1135e4 bellard
}
396 4d1135e4 bellard
397 4d1135e4 bellard
/* various jump tests */
398 4d1135e4 bellard
void test_jcc(void)
399 4d1135e4 bellard
{
400 5dd9488c bellard
    TEST_JCC("ne", 1, 1);
401 5dd9488c bellard
    TEST_JCC("ne", 1, 0);
402 4d1135e4 bellard
403 5dd9488c bellard
    TEST_JCC("e", 1, 1);
404 5dd9488c bellard
    TEST_JCC("e", 1, 0);
405 4d1135e4 bellard
406 5dd9488c bellard
    TEST_JCC("l", 1, 1);
407 5dd9488c bellard
    TEST_JCC("l", 1, 0);
408 5dd9488c bellard
    TEST_JCC("l", 1, -1);
409 4d1135e4 bellard
410 5dd9488c bellard
    TEST_JCC("le", 1, 1);
411 5dd9488c bellard
    TEST_JCC("le", 1, 0);
412 5dd9488c bellard
    TEST_JCC("le", 1, -1);
413 4d1135e4 bellard
414 5dd9488c bellard
    TEST_JCC("ge", 1, 1);
415 5dd9488c bellard
    TEST_JCC("ge", 1, 0);
416 5dd9488c bellard
    TEST_JCC("ge", -1, 1);
417 4d1135e4 bellard
418 5dd9488c bellard
    TEST_JCC("g", 1, 1);
419 5dd9488c bellard
    TEST_JCC("g", 1, 0);
420 5dd9488c bellard
    TEST_JCC("g", 1, -1);
421 4d1135e4 bellard
422 5dd9488c bellard
    TEST_JCC("b", 1, 1);
423 5dd9488c bellard
    TEST_JCC("b", 1, 0);
424 5dd9488c bellard
    TEST_JCC("b", 1, -1);
425 4d1135e4 bellard
426 5dd9488c bellard
    TEST_JCC("be", 1, 1);
427 5dd9488c bellard
    TEST_JCC("be", 1, 0);
428 5dd9488c bellard
    TEST_JCC("be", 1, -1);
429 4d1135e4 bellard
430 5dd9488c bellard
    TEST_JCC("ae", 1, 1);
431 5dd9488c bellard
    TEST_JCC("ae", 1, 0);
432 5dd9488c bellard
    TEST_JCC("ae", 1, -1);
433 4d1135e4 bellard
434 5dd9488c bellard
    TEST_JCC("a", 1, 1);
435 5dd9488c bellard
    TEST_JCC("a", 1, 0);
436 5dd9488c bellard
    TEST_JCC("a", 1, -1);
437 4d1135e4 bellard
438 4d1135e4 bellard
439 5dd9488c bellard
    TEST_JCC("p", 1, 1);
440 5dd9488c bellard
    TEST_JCC("p", 1, 0);
441 4d1135e4 bellard
442 5dd9488c bellard
    TEST_JCC("np", 1, 1);
443 5dd9488c bellard
    TEST_JCC("np", 1, 0);
444 4d1135e4 bellard
445 5dd9488c bellard
    TEST_JCC("o", 0x7fffffff, 0);
446 5dd9488c bellard
    TEST_JCC("o", 0x7fffffff, -1);
447 4d1135e4 bellard
448 5dd9488c bellard
    TEST_JCC("no", 0x7fffffff, 0);
449 5dd9488c bellard
    TEST_JCC("no", 0x7fffffff, -1);
450 4d1135e4 bellard
451 5dd9488c bellard
    TEST_JCC("s", 0, 1);
452 5dd9488c bellard
    TEST_JCC("s", 0, -1);
453 5dd9488c bellard
    TEST_JCC("s", 0, 0);
454 4d1135e4 bellard
455 5dd9488c bellard
    TEST_JCC("ns", 0, 1);
456 5dd9488c bellard
    TEST_JCC("ns", 0, -1);
457 5dd9488c bellard
    TEST_JCC("ns", 0, 0);
458 4d1135e4 bellard
}
459 4d1135e4 bellard
460 a5973fbf bellard
#define TEST_LOOP(insn) \
461 a5973fbf bellard
{\
462 a5973fbf bellard
    for(i = 0; i < sizeof(ecx_vals) / sizeof(long); i++) {\
463 a5973fbf bellard
        ecx = ecx_vals[i];\
464 a5973fbf bellard
        for(zf = 0; zf < 2; zf++) {\
465 a5973fbf bellard
    asm("test %2, %2\n\t"\
466 a5973fbf bellard
        "movl $1, %0\n\t"\
467 a5973fbf bellard
          insn " 1f\n\t" \
468 a5973fbf bellard
        "movl $0, %0\n\t"\
469 a5973fbf bellard
        "1:\n\t"\
470 a5973fbf bellard
        : "=a" (res)\
471 a5973fbf bellard
        : "c" (ecx), "b" (!zf)); \
472 a5973fbf bellard
    printf("%-10s ECX=" FMTLX " ZF=%ld r=%d\n", insn, ecx, zf, res);      \
473 a5973fbf bellard
        }\
474 a5973fbf bellard
   }\
475 a5973fbf bellard
}
476 a5973fbf bellard
477 a5973fbf bellard
void test_loop(void)
478 a5973fbf bellard
{
479 a5973fbf bellard
    long ecx, zf;
480 a5973fbf bellard
    const long ecx_vals[] = {
481 a5973fbf bellard
        0,
482 a5973fbf bellard
        1,
483 a5973fbf bellard
        0x10000,
484 a5973fbf bellard
        0x10001,
485 a5973fbf bellard
#if defined(__x86_64__)
486 a5973fbf bellard
        0x100000000L,
487 a5973fbf bellard
        0x100000001L,
488 a5973fbf bellard
#endif
489 a5973fbf bellard
    };
490 a5973fbf bellard
    int i, res;
491 a5973fbf bellard
492 a5973fbf bellard
    TEST_LOOP("jcxz");
493 a5973fbf bellard
    TEST_LOOP("loopw");
494 a5973fbf bellard
    TEST_LOOP("loopzw");
495 a5973fbf bellard
    TEST_LOOP("loopnzw");
496 a5973fbf bellard
497 a5973fbf bellard
    TEST_LOOP("jecxz");
498 a5973fbf bellard
    TEST_LOOP("loopl");
499 a5973fbf bellard
    TEST_LOOP("loopzl");
500 a5973fbf bellard
    TEST_LOOP("loopnzl");
501 a5973fbf bellard
}
502 a5973fbf bellard
503 4b74fe1f bellard
#undef CC_MASK
504 791c2261 bellard
#ifdef TEST_P4_FLAGS
505 791c2261 bellard
#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
506 791c2261 bellard
#else
507 4b74fe1f bellard
#define CC_MASK (CC_O | CC_C)
508 791c2261 bellard
#endif
509 4b74fe1f bellard
510 4b74fe1f bellard
#define OP mul
511 4b74fe1f bellard
#include "test-i386-muldiv.h"
512 4b74fe1f bellard
513 4b74fe1f bellard
#define OP imul
514 4b74fe1f bellard
#include "test-i386-muldiv.h"
515 4b74fe1f bellard
516 5fafdf24 ths
void test_imulw2(long op0, long op1)
517 4b74fe1f bellard
{
518 776f2227 bellard
    long res, s1, s0, flags;
519 4b74fe1f bellard
    s0 = op0;
520 4b74fe1f bellard
    s1 = op1;
521 4b74fe1f bellard
    res = s0;
522 4b74fe1f bellard
    flags = 0;
523 acae4681 bellard
    asm volatile ("push %4\n\t"
524 4b74fe1f bellard
         "popf\n\t"
525 5fafdf24 ths
         "imulw %w2, %w0\n\t"
526 4b74fe1f bellard
         "pushf\n\t"
527 776f2227 bellard
         "pop %1\n\t"
528 4b74fe1f bellard
         : "=q" (res), "=g" (flags)
529 4b74fe1f bellard
         : "q" (s1), "0" (res), "1" (flags));
530 776f2227 bellard
    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
531 4b74fe1f bellard
           "imulw", s0, s1, res, flags & CC_MASK);
532 4b74fe1f bellard
}
533 4b74fe1f bellard
534 5fafdf24 ths
void test_imull2(long op0, long op1)
535 4b74fe1f bellard
{
536 776f2227 bellard
    long res, s1, s0, flags;
537 4b74fe1f bellard
    s0 = op0;
538 4b74fe1f bellard
    s1 = op1;
539 4b74fe1f bellard
    res = s0;
540 4b74fe1f bellard
    flags = 0;
541 acae4681 bellard
    asm volatile ("push %4\n\t"
542 4b74fe1f bellard
         "popf\n\t"
543 5fafdf24 ths
         "imull %k2, %k0\n\t"
544 4b74fe1f bellard
         "pushf\n\t"
545 776f2227 bellard
         "pop %1\n\t"
546 4b74fe1f bellard
         : "=q" (res), "=g" (flags)
547 4b74fe1f bellard
         : "q" (s1), "0" (res), "1" (flags));
548 776f2227 bellard
    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
549 4b74fe1f bellard
           "imull", s0, s1, res, flags & CC_MASK);
550 4b74fe1f bellard
}
551 4b74fe1f bellard
552 776f2227 bellard
#if defined(__x86_64__)
553 5fafdf24 ths
void test_imulq2(long op0, long op1)
554 776f2227 bellard
{
555 776f2227 bellard
    long res, s1, s0, flags;
556 776f2227 bellard
    s0 = op0;
557 776f2227 bellard
    s1 = op1;
558 776f2227 bellard
    res = s0;
559 776f2227 bellard
    flags = 0;
560 776f2227 bellard
    asm volatile ("push %4\n\t"
561 776f2227 bellard
         "popf\n\t"
562 5fafdf24 ths
         "imulq %2, %0\n\t"
563 776f2227 bellard
         "pushf\n\t"
564 776f2227 bellard
         "pop %1\n\t"
565 776f2227 bellard
         : "=q" (res), "=g" (flags)
566 776f2227 bellard
         : "q" (s1), "0" (res), "1" (flags));
567 776f2227 bellard
    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
568 776f2227 bellard
           "imulq", s0, s1, res, flags & CC_MASK);
569 776f2227 bellard
}
570 776f2227 bellard
#endif
571 776f2227 bellard
572 776f2227 bellard
#define TEST_IMUL_IM(size, rsize, op0, op1)\
573 b5075d29 bellard
{\
574 776f2227 bellard
    long res, flags, s1;\
575 b5075d29 bellard
    flags = 0;\
576 b5075d29 bellard
    res = 0;\
577 776f2227 bellard
    s1 = op1;\
578 acae4681 bellard
    asm volatile ("push %3\n\t"\
579 b5075d29 bellard
         "popf\n\t"\
580 776f2227 bellard
         "imul" size " $" #op0 ", %" rsize "2, %" rsize "0\n\t" \
581 b5075d29 bellard
         "pushf\n\t"\
582 776f2227 bellard
         "pop %1\n\t"\
583 b5075d29 bellard
         : "=r" (res), "=g" (flags)\
584 776f2227 bellard
         : "r" (s1), "1" (flags), "0" (res));\
585 776f2227 bellard
    printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",\
586 776f2227 bellard
           "imul" size " im", (long)op0, (long)op1, res, flags & CC_MASK);\
587 b5075d29 bellard
}
588 b5075d29 bellard
589 b5075d29 bellard
590 791c2261 bellard
#undef CC_MASK
591 791c2261 bellard
#define CC_MASK (0)
592 791c2261 bellard
593 791c2261 bellard
#define OP div
594 791c2261 bellard
#include "test-i386-muldiv.h"
595 791c2261 bellard
596 791c2261 bellard
#define OP idiv
597 791c2261 bellard
#include "test-i386-muldiv.h"
598 791c2261 bellard
599 4b74fe1f bellard
void test_mul(void)
600 4b74fe1f bellard
{
601 4b74fe1f bellard
    test_imulb(0x1234561d, 4);
602 4b74fe1f bellard
    test_imulb(3, -4);
603 4b74fe1f bellard
    test_imulb(0x80, 0x80);
604 4b74fe1f bellard
    test_imulb(0x10, 0x10);
605 4b74fe1f bellard
606 4b74fe1f bellard
    test_imulw(0, 0x1234001d, 45);
607 4b74fe1f bellard
    test_imulw(0, 23, -45);
608 4b74fe1f bellard
    test_imulw(0, 0x8000, 0x8000);
609 4b74fe1f bellard
    test_imulw(0, 0x100, 0x100);
610 4b74fe1f bellard
611 4b74fe1f bellard
    test_imull(0, 0x1234001d, 45);
612 4b74fe1f bellard
    test_imull(0, 23, -45);
613 4b74fe1f bellard
    test_imull(0, 0x80000000, 0x80000000);
614 4b74fe1f bellard
    test_imull(0, 0x10000, 0x10000);
615 4b74fe1f bellard
616 4b74fe1f bellard
    test_mulb(0x1234561d, 4);
617 4b74fe1f bellard
    test_mulb(3, -4);
618 4b74fe1f bellard
    test_mulb(0x80, 0x80);
619 4b74fe1f bellard
    test_mulb(0x10, 0x10);
620 4b74fe1f bellard
621 4b74fe1f bellard
    test_mulw(0, 0x1234001d, 45);
622 4b74fe1f bellard
    test_mulw(0, 23, -45);
623 4b74fe1f bellard
    test_mulw(0, 0x8000, 0x8000);
624 4b74fe1f bellard
    test_mulw(0, 0x100, 0x100);
625 4b74fe1f bellard
626 4b74fe1f bellard
    test_mull(0, 0x1234001d, 45);
627 4b74fe1f bellard
    test_mull(0, 23, -45);
628 4b74fe1f bellard
    test_mull(0, 0x80000000, 0x80000000);
629 4b74fe1f bellard
    test_mull(0, 0x10000, 0x10000);
630 4b74fe1f bellard
631 4b74fe1f bellard
    test_imulw2(0x1234001d, 45);
632 4b74fe1f bellard
    test_imulw2(23, -45);
633 4b74fe1f bellard
    test_imulw2(0x8000, 0x8000);
634 4b74fe1f bellard
    test_imulw2(0x100, 0x100);
635 4b74fe1f bellard
636 4b74fe1f bellard
    test_imull2(0x1234001d, 45);
637 4b74fe1f bellard
    test_imull2(23, -45);
638 4b74fe1f bellard
    test_imull2(0x80000000, 0x80000000);
639 4b74fe1f bellard
    test_imull2(0x10000, 0x10000);
640 4b74fe1f bellard
641 b5075d29 bellard
    TEST_IMUL_IM("w", "w", 45, 0x1234);
642 b5075d29 bellard
    TEST_IMUL_IM("w", "w", -45, 23);
643 b5075d29 bellard
    TEST_IMUL_IM("w", "w", 0x8000, 0x80000000);
644 b5075d29 bellard
    TEST_IMUL_IM("w", "w", 0x7fff, 0x1000);
645 b5075d29 bellard
646 776f2227 bellard
    TEST_IMUL_IM("l", "k", 45, 0x1234);
647 776f2227 bellard
    TEST_IMUL_IM("l", "k", -45, 23);
648 776f2227 bellard
    TEST_IMUL_IM("l", "k", 0x8000, 0x80000000);
649 776f2227 bellard
    TEST_IMUL_IM("l", "k", 0x7fff, 0x1000);
650 b5075d29 bellard
651 4b74fe1f bellard
    test_idivb(0x12341678, 0x127e);
652 4b74fe1f bellard
    test_idivb(0x43210123, -5);
653 4b74fe1f bellard
    test_idivb(0x12340004, -1);
654 4b74fe1f bellard
655 4b74fe1f bellard
    test_idivw(0, 0x12345678, 12347);
656 4b74fe1f bellard
    test_idivw(0, -23223, -45);
657 4b74fe1f bellard
    test_idivw(0, 0x12348000, -1);
658 4b74fe1f bellard
    test_idivw(0x12343, 0x12345678, 0x81238567);
659 4b74fe1f bellard
660 4b74fe1f bellard
    test_idivl(0, 0x12345678, 12347);
661 4b74fe1f bellard
    test_idivl(0, -233223, -45);
662 4b74fe1f bellard
    test_idivl(0, 0x80000000, -1);
663 4b74fe1f bellard
    test_idivl(0x12343, 0x12345678, 0x81234567);
664 4b74fe1f bellard
665 4b74fe1f bellard
    test_divb(0x12341678, 0x127e);
666 4b74fe1f bellard
    test_divb(0x43210123, -5);
667 4b74fe1f bellard
    test_divb(0x12340004, -1);
668 4b74fe1f bellard
669 4b74fe1f bellard
    test_divw(0, 0x12345678, 12347);
670 4b74fe1f bellard
    test_divw(0, -23223, -45);
671 4b74fe1f bellard
    test_divw(0, 0x12348000, -1);
672 4b74fe1f bellard
    test_divw(0x12343, 0x12345678, 0x81238567);
673 4b74fe1f bellard
674 4b74fe1f bellard
    test_divl(0, 0x12345678, 12347);
675 4b74fe1f bellard
    test_divl(0, -233223, -45);
676 4b74fe1f bellard
    test_divl(0, 0x80000000, -1);
677 4b74fe1f bellard
    test_divl(0x12343, 0x12345678, 0x81234567);
678 776f2227 bellard
679 776f2227 bellard
#if defined(__x86_64__)
680 776f2227 bellard
    test_imulq(0, 0x1234001d1234001d, 45);
681 776f2227 bellard
    test_imulq(0, 23, -45);
682 776f2227 bellard
    test_imulq(0, 0x8000000000000000, 0x8000000000000000);
683 776f2227 bellard
    test_imulq(0, 0x100000000, 0x100000000);
684 776f2227 bellard
685 776f2227 bellard
    test_mulq(0, 0x1234001d1234001d, 45);
686 776f2227 bellard
    test_mulq(0, 23, -45);
687 776f2227 bellard
    test_mulq(0, 0x8000000000000000, 0x8000000000000000);
688 776f2227 bellard
    test_mulq(0, 0x100000000, 0x100000000);
689 776f2227 bellard
690 776f2227 bellard
    test_imulq2(0x1234001d1234001d, 45);
691 776f2227 bellard
    test_imulq2(23, -45);
692 776f2227 bellard
    test_imulq2(0x8000000000000000, 0x8000000000000000);
693 776f2227 bellard
    test_imulq2(0x100000000, 0x100000000);
694 776f2227 bellard
695 776f2227 bellard
    TEST_IMUL_IM("q", "", 45, 0x12341234);
696 776f2227 bellard
    TEST_IMUL_IM("q", "", -45, 23);
697 776f2227 bellard
    TEST_IMUL_IM("q", "", 0x8000, 0x8000000000000000);
698 776f2227 bellard
    TEST_IMUL_IM("q", "", 0x7fff, 0x10000000);
699 776f2227 bellard
700 776f2227 bellard
    test_idivq(0, 0x12345678abcdef, 12347);
701 776f2227 bellard
    test_idivq(0, -233223, -45);
702 776f2227 bellard
    test_idivq(0, 0x8000000000000000, -1);
703 776f2227 bellard
    test_idivq(0x12343, 0x12345678, 0x81234567);
704 776f2227 bellard
705 776f2227 bellard
    test_divq(0, 0x12345678abcdef, 12347);
706 776f2227 bellard
    test_divq(0, -233223, -45);
707 776f2227 bellard
    test_divq(0, 0x8000000000000000, -1);
708 776f2227 bellard
    test_divq(0x12343, 0x12345678, 0x81234567);
709 776f2227 bellard
#endif
710 4b74fe1f bellard
}
711 4b74fe1f bellard
712 9d8e9c09 bellard
#define TEST_BSX(op, size, op0)\
713 9d8e9c09 bellard
{\
714 776f2227 bellard
    long res, val, resz;\
715 9d8e9c09 bellard
    val = op0;\
716 776f2227 bellard
    asm("xor %1, %1\n"\
717 776f2227 bellard
        "mov $0x12345678, %0\n"\
718 7f5e1452 bellard
        #op " %" size "2, %" size "0 ; setz %b1" \
719 9d8e9c09 bellard
        : "=r" (res), "=q" (resz)\
720 9d8e9c09 bellard
        : "g" (val));\
721 776f2227 bellard
    printf("%-10s A=" FMTLX " R=" FMTLX " %ld\n", #op, val, res, resz);\
722 9d8e9c09 bellard
}
723 9d8e9c09 bellard
724 9d8e9c09 bellard
void test_bsx(void)
725 9d8e9c09 bellard
{
726 9d8e9c09 bellard
    TEST_BSX(bsrw, "w", 0);
727 9d8e9c09 bellard
    TEST_BSX(bsrw, "w", 0x12340128);
728 9d8e9c09 bellard
    TEST_BSX(bsfw, "w", 0);
729 9d8e9c09 bellard
    TEST_BSX(bsfw, "w", 0x12340128);
730 776f2227 bellard
    TEST_BSX(bsrl, "k", 0);
731 776f2227 bellard
    TEST_BSX(bsrl, "k", 0x00340128);
732 776f2227 bellard
    TEST_BSX(bsfl, "k", 0);
733 776f2227 bellard
    TEST_BSX(bsfl, "k", 0x00340128);
734 776f2227 bellard
#if defined(__x86_64__)
735 776f2227 bellard
    TEST_BSX(bsrq, "", 0);
736 776f2227 bellard
    TEST_BSX(bsrq, "", 0x003401281234);
737 776f2227 bellard
    TEST_BSX(bsfq, "", 0);
738 776f2227 bellard
    TEST_BSX(bsfq, "", 0x003401281234);
739 776f2227 bellard
#endif
740 9d8e9c09 bellard
}
741 9d8e9c09 bellard
742 55480af8 bellard
/**********************************************/
743 55480af8 bellard
744 86bd2ca5 bellard
union float64u {
745 86bd2ca5 bellard
    double d;
746 86bd2ca5 bellard
    uint64_t l;
747 86bd2ca5 bellard
};
748 86bd2ca5 bellard
749 be98f1f8 bellard
union float64u q_nan = { .l = 0xFFF8000000000000LL };
750 be98f1f8 bellard
union float64u s_nan = { .l = 0xFFF0000000000000LL };
751 86bd2ca5 bellard
752 9d8e9c09 bellard
void test_fops(double a, double b)
753 9d8e9c09 bellard
{
754 9d8e9c09 bellard
    printf("a=%f b=%f a+b=%f\n", a, b, a + b);
755 9d8e9c09 bellard
    printf("a=%f b=%f a-b=%f\n", a, b, a - b);
756 9d8e9c09 bellard
    printf("a=%f b=%f a*b=%f\n", a, b, a * b);
757 9d8e9c09 bellard
    printf("a=%f b=%f a/b=%f\n", a, b, a / b);
758 9d8e9c09 bellard
    printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b));
759 9d8e9c09 bellard
    printf("a=%f sqrt(a)=%f\n", a, sqrt(a));
760 9d8e9c09 bellard
    printf("a=%f sin(a)=%f\n", a, sin(a));
761 9d8e9c09 bellard
    printf("a=%f cos(a)=%f\n", a, cos(a));
762 9d8e9c09 bellard
    printf("a=%f tan(a)=%f\n", a, tan(a));
763 9d8e9c09 bellard
    printf("a=%f log(a)=%f\n", a, log(a));
764 9d8e9c09 bellard
    printf("a=%f exp(a)=%f\n", a, exp(a));
765 9d8e9c09 bellard
    printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
766 9d8e9c09 bellard
    /* just to test some op combining */
767 9d8e9c09 bellard
    printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a)));
768 9d8e9c09 bellard
    printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a)));
769 9d8e9c09 bellard
    printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));
770 9d8e9c09 bellard
771 9d8e9c09 bellard
}
772 9d8e9c09 bellard
773 86bd2ca5 bellard
void fpu_clear_exceptions(void)
774 86bd2ca5 bellard
{
775 86bd2ca5 bellard
    struct __attribute__((packed)) {
776 86bd2ca5 bellard
        uint16_t fpuc;
777 86bd2ca5 bellard
        uint16_t dummy1;
778 86bd2ca5 bellard
        uint16_t fpus;
779 86bd2ca5 bellard
        uint16_t dummy2;
780 86bd2ca5 bellard
        uint16_t fptag;
781 86bd2ca5 bellard
        uint16_t dummy3;
782 86bd2ca5 bellard
        uint32_t ignored[4];
783 86bd2ca5 bellard
        long double fpregs[8];
784 86bd2ca5 bellard
    } float_env32;
785 3b46e624 ths
786 86bd2ca5 bellard
    asm volatile ("fnstenv %0\n" : : "m" (float_env32));
787 86bd2ca5 bellard
    float_env32.fpus &= ~0x7f;
788 86bd2ca5 bellard
    asm volatile ("fldenv %0\n" : : "m" (float_env32));
789 86bd2ca5 bellard
}
790 86bd2ca5 bellard
791 86bd2ca5 bellard
/* XXX: display exception bits when supported */
792 86bd2ca5 bellard
#define FPUS_EMASK 0x0000
793 86bd2ca5 bellard
//#define FPUS_EMASK 0x007f
794 86bd2ca5 bellard
795 9d8e9c09 bellard
void test_fcmp(double a, double b)
796 9d8e9c09 bellard
{
797 86bd2ca5 bellard
    long eflags, fpus;
798 86bd2ca5 bellard
799 86bd2ca5 bellard
    fpu_clear_exceptions();
800 86bd2ca5 bellard
    asm("fcom %2\n"
801 86bd2ca5 bellard
        "fstsw %%ax\n"
802 86bd2ca5 bellard
        : "=a" (fpus)
803 86bd2ca5 bellard
        : "t" (a), "u" (b));
804 5fafdf24 ths
    printf("fcom(%f %f)=%04lx \n",
805 86bd2ca5 bellard
           a, b, fpus & (0x4500 | FPUS_EMASK));
806 86bd2ca5 bellard
    fpu_clear_exceptions();
807 86bd2ca5 bellard
    asm("fucom %2\n"
808 86bd2ca5 bellard
        "fstsw %%ax\n"
809 86bd2ca5 bellard
        : "=a" (fpus)
810 86bd2ca5 bellard
        : "t" (a), "u" (b));
811 5fafdf24 ths
    printf("fucom(%f %f)=%04lx\n",
812 86bd2ca5 bellard
           a, b, fpus & (0x4500 | FPUS_EMASK));
813 03bfca94 bellard
    if (TEST_FCOMI) {
814 03bfca94 bellard
        /* test f(u)comi instruction */
815 86bd2ca5 bellard
        fpu_clear_exceptions();
816 86bd2ca5 bellard
        asm("fcomi %3, %2\n"
817 86bd2ca5 bellard
            "fstsw %%ax\n"
818 03bfca94 bellard
            "pushf\n"
819 03bfca94 bellard
            "pop %0\n"
820 86bd2ca5 bellard
            : "=r" (eflags), "=a" (fpus)
821 03bfca94 bellard
            : "t" (a), "u" (b));
822 5fafdf24 ths
        printf("fcomi(%f %f)=%04lx %02lx\n",
823 86bd2ca5 bellard
               a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C));
824 86bd2ca5 bellard
        fpu_clear_exceptions();
825 86bd2ca5 bellard
        asm("fucomi %3, %2\n"
826 86bd2ca5 bellard
            "fstsw %%ax\n"
827 86bd2ca5 bellard
            "pushf\n"
828 86bd2ca5 bellard
            "pop %0\n"
829 86bd2ca5 bellard
            : "=r" (eflags), "=a" (fpus)
830 86bd2ca5 bellard
            : "t" (a), "u" (b));
831 5fafdf24 ths
        printf("fucomi(%f %f)=%04lx %02lx\n",
832 86bd2ca5 bellard
               a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C));
833 03bfca94 bellard
    }
834 86bd2ca5 bellard
    fpu_clear_exceptions();
835 b2a8e592 bellard
    asm volatile("fxam\n"
836 b2a8e592 bellard
                 "fstsw %%ax\n"
837 b2a8e592 bellard
                 : "=a" (fpus)
838 b2a8e592 bellard
                 : "t" (a));
839 b2a8e592 bellard
    printf("fxam(%f)=%04lx\n", a, fpus & 0x4700);
840 b2a8e592 bellard
    fpu_clear_exceptions();
841 9d8e9c09 bellard
}
842 9d8e9c09 bellard
843 9d8e9c09 bellard
void test_fcvt(double a)
844 9d8e9c09 bellard
{
845 9d8e9c09 bellard
    float fa;
846 9d8e9c09 bellard
    long double la;
847 ea768640 bellard
    int16_t fpuc;
848 ea768640 bellard
    int i;
849 ea768640 bellard
    int64_t lla;
850 ea768640 bellard
    int ia;
851 ea768640 bellard
    int16_t wa;
852 ea768640 bellard
    double ra;
853 9d8e9c09 bellard
854 9d8e9c09 bellard
    fa = a;
855 9d8e9c09 bellard
    la = a;
856 9d8e9c09 bellard
    printf("(float)%f = %f\n", a, fa);
857 9d8e9c09 bellard
    printf("(long double)%f = %Lf\n", a, la);
858 776f2227 bellard
    printf("a=" FMT64X "\n", *(uint64_t *)&a);
859 5fafdf24 ths
    printf("la=" FMT64X " %04x\n", *(uint64_t *)&la,
860 c5e9815d bellard
           *(unsigned short *)((char *)(&la) + 8));
861 ea768640 bellard
862 ea768640 bellard
    /* test all roundings */
863 ea768640 bellard
    asm volatile ("fstcw %0" : "=m" (fpuc));
864 ea768640 bellard
    for(i=0;i<4;i++) {
865 be98f1f8 bellard
        uint16_t val16;
866 be98f1f8 bellard
        val16 = (fpuc & ~0x0c00) | (i << 10);
867 be98f1f8 bellard
        asm volatile ("fldcw %0" : : "m" (val16));
868 ea768640 bellard
        asm volatile ("fist %0" : "=m" (wa) : "t" (a));
869 ea768640 bellard
        asm volatile ("fistl %0" : "=m" (ia) : "t" (a));
870 ea768640 bellard
        asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st");
871 ea768640 bellard
        asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a));
872 ea768640 bellard
        asm volatile ("fldcw %0" : : "m" (fpuc));
873 ea768640 bellard
        printf("(short)a = %d\n", wa);
874 ea768640 bellard
        printf("(int)a = %d\n", ia);
875 776f2227 bellard
        printf("(int64_t)a = " FMT64X "\n", lla);
876 ea768640 bellard
        printf("rint(a) = %f\n", ra);
877 ea768640 bellard
    }
878 9d8e9c09 bellard
}
879 9d8e9c09 bellard
880 9d8e9c09 bellard
#define TEST(N) \
881 9d8e9c09 bellard
    asm("fld" #N : "=t" (a)); \
882 9d8e9c09 bellard
    printf("fld" #N "= %f\n", a);
883 9d8e9c09 bellard
884 9d8e9c09 bellard
void test_fconst(void)
885 9d8e9c09 bellard
{
886 9d8e9c09 bellard
    double a;
887 9d8e9c09 bellard
    TEST(1);
888 9d8e9c09 bellard
    TEST(l2t);
889 9d8e9c09 bellard
    TEST(l2e);
890 9d8e9c09 bellard
    TEST(pi);
891 9d8e9c09 bellard
    TEST(lg2);
892 9d8e9c09 bellard
    TEST(ln2);
893 9d8e9c09 bellard
    TEST(z);
894 9d8e9c09 bellard
}
895 9d8e9c09 bellard
896 c5e9815d bellard
void test_fbcd(double a)
897 c5e9815d bellard
{
898 c5e9815d bellard
    unsigned short bcd[5];
899 c5e9815d bellard
    double b;
900 c5e9815d bellard
901 c5e9815d bellard
    asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st");
902 c5e9815d bellard
    asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
903 5fafdf24 ths
    printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n",
904 c5e9815d bellard
           a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);
905 c5e9815d bellard
}
906 c5e9815d bellard
907 6b2b6112 bellard
#define TEST_ENV(env, save, restore)\
908 03bfca94 bellard
{\
909 03bfca94 bellard
    memset((env), 0xaa, sizeof(*(env)));\
910 6b2b6112 bellard
    for(i=0;i<5;i++)\
911 6b2b6112 bellard
        asm volatile ("fldl %0" : : "m" (dtab[i]));\
912 085339a1 bellard
    asm volatile (save " %0\n" : : "m" (*(env)));\
913 085339a1 bellard
    asm volatile (restore " %0\n": : "m" (*(env)));\
914 6b2b6112 bellard
    for(i=0;i<5;i++)\
915 6b2b6112 bellard
        asm volatile ("fstpl %0" : "=m" (rtab[i]));\
916 6b2b6112 bellard
    for(i=0;i<5;i++)\
917 6b2b6112 bellard
        printf("res[%d]=%f\n", i, rtab[i]);\
918 03bfca94 bellard
    printf("fpuc=%04x fpus=%04x fptag=%04x\n",\
919 03bfca94 bellard
           (env)->fpuc,\
920 03bfca94 bellard
           (env)->fpus & 0xff00,\
921 03bfca94 bellard
           (env)->fptag);\
922 03bfca94 bellard
}
923 03bfca94 bellard
924 03bfca94 bellard
void test_fenv(void)
925 03bfca94 bellard
{
926 03bfca94 bellard
    struct __attribute__((packed)) {
927 03bfca94 bellard
        uint16_t fpuc;
928 03bfca94 bellard
        uint16_t dummy1;
929 03bfca94 bellard
        uint16_t fpus;
930 03bfca94 bellard
        uint16_t dummy2;
931 03bfca94 bellard
        uint16_t fptag;
932 03bfca94 bellard
        uint16_t dummy3;
933 03bfca94 bellard
        uint32_t ignored[4];
934 03bfca94 bellard
        long double fpregs[8];
935 03bfca94 bellard
    } float_env32;
936 03bfca94 bellard
    struct __attribute__((packed)) {
937 03bfca94 bellard
        uint16_t fpuc;
938 03bfca94 bellard
        uint16_t fpus;
939 03bfca94 bellard
        uint16_t fptag;
940 03bfca94 bellard
        uint16_t ignored[4];
941 03bfca94 bellard
        long double fpregs[8];
942 03bfca94 bellard
    } float_env16;
943 6b2b6112 bellard
    double dtab[8];
944 6b2b6112 bellard
    double rtab[8];
945 6b2b6112 bellard
    int i;
946 6b2b6112 bellard
947 6b2b6112 bellard
    for(i=0;i<8;i++)
948 6b2b6112 bellard
        dtab[i] = i + 1;
949 03bfca94 bellard
950 6b2b6112 bellard
    TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv");
951 6b2b6112 bellard
    TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor");
952 6b2b6112 bellard
    TEST_ENV(&float_env32, "fnstenv", "fldenv");
953 6b2b6112 bellard
    TEST_ENV(&float_env32, "fnsave", "frstor");
954 665656a9 bellard
955 665656a9 bellard
    /* test for ffree */
956 665656a9 bellard
    for(i=0;i<5;i++)
957 665656a9 bellard
        asm volatile ("fldl %0" : : "m" (dtab[i]));
958 665656a9 bellard
    asm volatile("ffree %st(2)");
959 665656a9 bellard
    asm volatile ("fnstenv %0\n" : : "m" (float_env32));
960 665656a9 bellard
    asm volatile ("fninit");
961 665656a9 bellard
    printf("fptag=%04x\n", float_env32.fptag);
962 03bfca94 bellard
}
963 03bfca94 bellard
964 75175024 bellard
965 75175024 bellard
#define TEST_FCMOV(a, b, eflags, CC)\
966 75175024 bellard
{\
967 75175024 bellard
    double res;\
968 75175024 bellard
    asm("push %3\n"\
969 75175024 bellard
        "popf\n"\
970 75175024 bellard
        "fcmov" CC " %2, %0\n"\
971 75175024 bellard
        : "=t" (res)\
972 75175024 bellard
        : "0" (a), "u" (b), "g" (eflags));\
973 776f2227 bellard
    printf("fcmov%s eflags=0x%04lx-> %f\n", \
974 776f2227 bellard
           CC, (long)eflags, res);\
975 75175024 bellard
}
976 75175024 bellard
977 75175024 bellard
void test_fcmov(void)
978 75175024 bellard
{
979 75175024 bellard
    double a, b;
980 776f2227 bellard
    long eflags, i;
981 75175024 bellard
982 75175024 bellard
    a = 1.0;
983 75175024 bellard
    b = 2.0;
984 75175024 bellard
    for(i = 0; i < 4; i++) {
985 75175024 bellard
        eflags = 0;
986 75175024 bellard
        if (i & 1)
987 75175024 bellard
            eflags |= CC_C;
988 75175024 bellard
        if (i & 2)
989 75175024 bellard
            eflags |= CC_Z;
990 75175024 bellard
        TEST_FCMOV(a, b, eflags, "b");
991 75175024 bellard
        TEST_FCMOV(a, b, eflags, "e");
992 75175024 bellard
        TEST_FCMOV(a, b, eflags, "be");
993 75175024 bellard
        TEST_FCMOV(a, b, eflags, "nb");
994 75175024 bellard
        TEST_FCMOV(a, b, eflags, "ne");
995 75175024 bellard
        TEST_FCMOV(a, b, eflags, "nbe");
996 75175024 bellard
    }
997 75175024 bellard
    TEST_FCMOV(a, b, 0, "u");
998 9cdf757f bellard
    TEST_FCMOV(a, b, CC_P, "u");
999 9cdf757f bellard
    TEST_FCMOV(a, b, 0, "nu");
1000 75175024 bellard
    TEST_FCMOV(a, b, CC_P, "nu");
1001 75175024 bellard
}
1002 75175024 bellard
1003 9d8e9c09 bellard
void test_floats(void)
1004 9d8e9c09 bellard
{
1005 9d8e9c09 bellard
    test_fops(2, 3);
1006 9d8e9c09 bellard
    test_fops(1.4, -5);
1007 9d8e9c09 bellard
    test_fcmp(2, -1);
1008 9d8e9c09 bellard
    test_fcmp(2, 2);
1009 9d8e9c09 bellard
    test_fcmp(2, 3);
1010 86bd2ca5 bellard
    test_fcmp(2, q_nan.d);
1011 86bd2ca5 bellard
    test_fcmp(q_nan.d, -1);
1012 b2a8e592 bellard
    test_fcmp(-1.0/0.0, -1);
1013 b2a8e592 bellard
    test_fcmp(1.0/0.0, -1);
1014 ea768640 bellard
    test_fcvt(0.5);
1015 ea768640 bellard
    test_fcvt(-0.5);
1016 9d8e9c09 bellard
    test_fcvt(1.0/7.0);
1017 9d8e9c09 bellard
    test_fcvt(-1.0/9.0);
1018 ea768640 bellard
    test_fcvt(32768);
1019 ea768640 bellard
    test_fcvt(-1e20);
1020 b2a8e592 bellard
    test_fcvt(-1.0/0.0);
1021 b2a8e592 bellard
    test_fcvt(1.0/0.0);
1022 b2a8e592 bellard
    test_fcvt(q_nan.d);
1023 9d8e9c09 bellard
    test_fconst();
1024 be98f1f8 bellard
    test_fbcd(1234567890123456.0);
1025 be98f1f8 bellard
    test_fbcd(-123451234567890.0);
1026 03bfca94 bellard
    test_fenv();
1027 75175024 bellard
    if (TEST_CMOV) {
1028 75175024 bellard
        test_fcmov();
1029 75175024 bellard
    }
1030 9d8e9c09 bellard
}
1031 4b74fe1f bellard
1032 55480af8 bellard
/**********************************************/
1033 776f2227 bellard
#if !defined(__x86_64__)
1034 55480af8 bellard
1035 55480af8 bellard
#define TEST_BCD(op, op0, cc_in, cc_mask)\
1036 55480af8 bellard
{\
1037 55480af8 bellard
    int res, flags;\
1038 55480af8 bellard
    res = op0;\
1039 55480af8 bellard
    flags = cc_in;\
1040 55480af8 bellard
    asm ("push %3\n\t"\
1041 55480af8 bellard
         "popf\n\t"\
1042 55480af8 bellard
         #op "\n\t"\
1043 55480af8 bellard
         "pushf\n\t"\
1044 776f2227 bellard
         "pop %1\n\t"\
1045 55480af8 bellard
        : "=a" (res), "=g" (flags)\
1046 55480af8 bellard
        : "0" (res), "1" (flags));\
1047 55480af8 bellard
    printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\
1048 55480af8 bellard
           #op, op0, res, cc_in, flags & cc_mask);\
1049 55480af8 bellard
}
1050 55480af8 bellard
1051 55480af8 bellard
void test_bcd(void)
1052 55480af8 bellard
{
1053 55480af8 bellard
    TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1054 55480af8 bellard
    TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1055 55480af8 bellard
    TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1056 55480af8 bellard
    TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1057 55480af8 bellard
    TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1058 55480af8 bellard
    TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1059 55480af8 bellard
    TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1060 55480af8 bellard
    TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1061 55480af8 bellard
    TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1062 55480af8 bellard
    TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1063 55480af8 bellard
    TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1064 55480af8 bellard
    TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1065 55480af8 bellard
    TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1066 55480af8 bellard
1067 55480af8 bellard
    TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1068 55480af8 bellard
    TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1069 55480af8 bellard
    TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1070 55480af8 bellard
    TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1071 55480af8 bellard
    TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1072 55480af8 bellard
    TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1073 55480af8 bellard
    TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1074 55480af8 bellard
    TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1075 55480af8 bellard
    TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1076 55480af8 bellard
    TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1077 55480af8 bellard
    TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1078 55480af8 bellard
    TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1079 55480af8 bellard
    TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
1080 55480af8 bellard
1081 55480af8 bellard
    TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A));
1082 55480af8 bellard
    TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A));
1083 55480af8 bellard
    TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A));
1084 55480af8 bellard
    TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A));
1085 55480af8 bellard
    TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A));
1086 55480af8 bellard
    TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A));
1087 55480af8 bellard
    TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A));
1088 55480af8 bellard
    TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A));
1089 3b46e624 ths
1090 55480af8 bellard
    TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A));
1091 55480af8 bellard
    TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A));
1092 55480af8 bellard
    TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A));
1093 55480af8 bellard
    TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A));
1094 55480af8 bellard
    TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A));
1095 55480af8 bellard
    TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A));
1096 55480af8 bellard
    TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A));
1097 55480af8 bellard
    TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A));
1098 55480af8 bellard
1099 55480af8 bellard
    TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
1100 55480af8 bellard
    TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
1101 55480af8 bellard
}
1102 776f2227 bellard
#endif
1103 55480af8 bellard
1104 e5918247 bellard
#define TEST_XCHG(op, size, opconst)\
1105 e5918247 bellard
{\
1106 776f2227 bellard
    long op0, op1;\
1107 776f2227 bellard
    op0 = i2l(0x12345678);\
1108 776f2227 bellard
    op1 = i2l(0xfbca7654);\
1109 e5918247 bellard
    asm(#op " %" size "0, %" size "1" \
1110 e5918247 bellard
        : "=q" (op0), opconst (op1) \
1111 8aadfbf0 bellard
        : "0" (op0));\
1112 776f2227 bellard
    printf("%-10s A=" FMTLX " B=" FMTLX "\n",\
1113 e5918247 bellard
           #op, op0, op1);\
1114 e5918247 bellard
}
1115 e5918247 bellard
1116 e5918247 bellard
#define TEST_CMPXCHG(op, size, opconst, eax)\
1117 e5918247 bellard
{\
1118 776f2227 bellard
    long op0, op1, op2;\
1119 776f2227 bellard
    op0 = i2l(0x12345678);\
1120 776f2227 bellard
    op1 = i2l(0xfbca7654);\
1121 776f2227 bellard
    op2 = i2l(eax);\
1122 e5918247 bellard
    asm(#op " %" size "0, %" size "1" \
1123 e5918247 bellard
        : "=q" (op0), opconst (op1) \
1124 8aadfbf0 bellard
        : "0" (op0), "a" (op2));\
1125 776f2227 bellard
    printf("%-10s EAX=" FMTLX " A=" FMTLX " C=" FMTLX "\n",\
1126 776f2227 bellard
           #op, op2, op0, op1);\
1127 e5918247 bellard
}
1128 e5918247 bellard
1129 e5918247 bellard
void test_xchg(void)
1130 e5918247 bellard
{
1131 776f2227 bellard
#if defined(__x86_64__)
1132 8aadfbf0 bellard
    TEST_XCHG(xchgq, "", "+q");
1133 776f2227 bellard
#endif
1134 8aadfbf0 bellard
    TEST_XCHG(xchgl, "k", "+q");
1135 8aadfbf0 bellard
    TEST_XCHG(xchgw, "w", "+q");
1136 8aadfbf0 bellard
    TEST_XCHG(xchgb, "b", "+q");
1137 e5918247 bellard
1138 776f2227 bellard
#if defined(__x86_64__)
1139 776f2227 bellard
    TEST_XCHG(xchgq, "", "=m");
1140 776f2227 bellard
#endif
1141 8aadfbf0 bellard
    TEST_XCHG(xchgl, "k", "+m");
1142 8aadfbf0 bellard
    TEST_XCHG(xchgw, "w", "+m");
1143 8aadfbf0 bellard
    TEST_XCHG(xchgb, "b", "+m");
1144 e5918247 bellard
1145 776f2227 bellard
#if defined(__x86_64__)
1146 8aadfbf0 bellard
    TEST_XCHG(xaddq, "", "+q");
1147 776f2227 bellard
#endif
1148 8aadfbf0 bellard
    TEST_XCHG(xaddl, "k", "+q");
1149 8aadfbf0 bellard
    TEST_XCHG(xaddw, "w", "+q");
1150 8aadfbf0 bellard
    TEST_XCHG(xaddb, "b", "+q");
1151 e5918247 bellard
1152 d575b78a bellard
    {
1153 d575b78a bellard
        int res;
1154 d575b78a bellard
        res = 0x12345678;
1155 d575b78a bellard
        asm("xaddl %1, %0" : "=r" (res) : "0" (res));
1156 d575b78a bellard
        printf("xaddl same res=%08x\n", res);
1157 d575b78a bellard
    }
1158 d575b78a bellard
1159 776f2227 bellard
#if defined(__x86_64__)
1160 8aadfbf0 bellard
    TEST_XCHG(xaddq, "", "+m");
1161 776f2227 bellard
#endif
1162 8aadfbf0 bellard
    TEST_XCHG(xaddl, "k", "+m");
1163 8aadfbf0 bellard
    TEST_XCHG(xaddw, "w", "+m");
1164 8aadfbf0 bellard
    TEST_XCHG(xaddb, "b", "+m");
1165 e5918247 bellard
1166 776f2227 bellard
#if defined(__x86_64__)
1167 8aadfbf0 bellard
    TEST_CMPXCHG(cmpxchgq, "", "+q", 0xfbca7654);
1168 776f2227 bellard
#endif
1169 8aadfbf0 bellard
    TEST_CMPXCHG(cmpxchgl, "k", "+q", 0xfbca7654);
1170 8aadfbf0 bellard
    TEST_CMPXCHG(cmpxchgw, "w", "+q", 0xfbca7654);
1171 8aadfbf0 bellard
    TEST_CMPXCHG(cmpxchgb, "b", "+q", 0xfbca7654);
1172 e5918247 bellard
1173 776f2227 bellard
#if defined(__x86_64__)
1174 8aadfbf0 bellard
    TEST_CMPXCHG(cmpxchgq, "", "+q", 0xfffefdfc);
1175 776f2227 bellard
#endif
1176 8aadfbf0 bellard
    TEST_CMPXCHG(cmpxchgl, "k", "+q", 0xfffefdfc);
1177 8aadfbf0 bellard
    TEST_CMPXCHG(cmpxchgw, "w", "+q", 0xfffefdfc);
1178 8aadfbf0 bellard
    TEST_CMPXCHG(cmpxchgb, "b", "+q", 0xfffefdfc);
1179 e5918247 bellard
1180 776f2227 bellard
#if defined(__x86_64__)
1181 8aadfbf0 bellard
    TEST_CMPXCHG(cmpxchgq, "", "+m", 0xfbca7654);
1182 776f2227 bellard
#endif
1183 8aadfbf0 bellard
    TEST_CMPXCHG(cmpxchgl, "k", "+m", 0xfbca7654);
1184 8aadfbf0 bellard
    TEST_CMPXCHG(cmpxchgw, "w", "+m", 0xfbca7654);
1185 8aadfbf0 bellard
    TEST_CMPXCHG(cmpxchgb, "b", "+m", 0xfbca7654);
1186 e5918247 bellard
1187 776f2227 bellard
#if defined(__x86_64__)
1188 8aadfbf0 bellard
    TEST_CMPXCHG(cmpxchgq, "", "+m", 0xfffefdfc);
1189 776f2227 bellard
#endif
1190 8aadfbf0 bellard
    TEST_CMPXCHG(cmpxchgl, "k", "+m", 0xfffefdfc);
1191 8aadfbf0 bellard
    TEST_CMPXCHG(cmpxchgw, "w", "+m", 0xfffefdfc);
1192 8aadfbf0 bellard
    TEST_CMPXCHG(cmpxchgb, "b", "+m", 0xfffefdfc);
1193 d575b78a bellard
1194 d575b78a bellard
    {
1195 d575b78a bellard
        uint64_t op0, op1, op2;
1196 a5973fbf bellard
        long eax, edx;
1197 776f2227 bellard
        long i, eflags;
1198 d575b78a bellard
1199 d575b78a bellard
        for(i = 0; i < 2; i++) {
1200 be98f1f8 bellard
            op0 = 0x123456789abcdLL;
1201 a5973fbf bellard
            eax = i2l(op0 & 0xffffffff);
1202 a5973fbf bellard
            edx = i2l(op0 >> 32);
1203 d575b78a bellard
            if (i == 0)
1204 be98f1f8 bellard
                op1 = 0xfbca765423456LL;
1205 d575b78a bellard
            else
1206 d575b78a bellard
                op1 = op0;
1207 be98f1f8 bellard
            op2 = 0x6532432432434LL;
1208 a5973fbf bellard
            asm("cmpxchg8b %2\n"
1209 d575b78a bellard
                "pushf\n"
1210 a5973fbf bellard
                "pop %3\n"
1211 a5973fbf bellard
                : "=a" (eax), "=d" (edx), "=m" (op1), "=g" (eflags)
1212 a5973fbf bellard
                : "0" (eax), "1" (edx), "m" (op1), "b" ((int)op2), "c" ((int)(op2 >> 32)));
1213 a5973fbf bellard
            printf("cmpxchg8b: eax=" FMTLX " edx=" FMTLX " op1=" FMT64X " CC=%02lx\n",
1214 a5973fbf bellard
                   eax, edx, op1, eflags & CC_Z);
1215 d575b78a bellard
        }
1216 d575b78a bellard
    }
1217 e5918247 bellard
}
1218 e5918247 bellard
1219 776f2227 bellard
#ifdef TEST_SEGS
1220 6dbad63e bellard
/**********************************************/
1221 6dbad63e bellard
/* segmentation tests */
1222 6dbad63e bellard
1223 be98f1f8 bellard
#include <sys/syscall.h>
1224 be98f1f8 bellard
#include <unistd.h>
1225 6dbad63e bellard
#include <asm/ldt.h>
1226 73bdea19 bellard
#include <linux/version.h>
1227 6dbad63e bellard
1228 be98f1f8 bellard
static inline int modify_ldt(int func, void * ptr, unsigned long bytecount)
1229 be98f1f8 bellard
{
1230 be98f1f8 bellard
    return syscall(__NR_modify_ldt, func, ptr, bytecount);
1231 be98f1f8 bellard
}
1232 6dbad63e bellard
1233 73bdea19 bellard
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
1234 73bdea19 bellard
#define modify_ldt_ldt_s user_desc
1235 73bdea19 bellard
#endif
1236 73bdea19 bellard
1237 776f2227 bellard
#define MK_SEL(n) (((n) << 3) | 7)
1238 776f2227 bellard
1239 6dbad63e bellard
uint8_t seg_data1[4096];
1240 6dbad63e bellard
uint8_t seg_data2[4096];
1241 6dbad63e bellard
1242 288426fe bellard
#define TEST_LR(op, size, seg, mask)\
1243 288426fe bellard
{\
1244 288426fe bellard
    int res, res2;\
1245 a5973fbf bellard
    uint16_t mseg = seg;\
1246 288426fe bellard
    res = 0x12345678;\
1247 288426fe bellard
    asm (op " %" size "2, %" size "0\n" \
1248 288426fe bellard
         "movl $0, %1\n"\
1249 288426fe bellard
         "jnz 1f\n"\
1250 288426fe bellard
         "movl $1, %1\n"\
1251 288426fe bellard
         "1:\n"\
1252 a5973fbf bellard
         : "=r" (res), "=r" (res2) : "m" (mseg), "0" (res));\
1253 288426fe bellard
    printf(op ": Z=%d %08x\n", res2, res & ~(mask));\
1254 288426fe bellard
}
1255 288426fe bellard
1256 a5973fbf bellard
#define TEST_ARPL(op, size, op1, op2)\
1257 a5973fbf bellard
{\
1258 a5973fbf bellard
    long a, b, c;                               \
1259 a5973fbf bellard
    a = (op1);                                  \
1260 a5973fbf bellard
    b = (op2);                                  \
1261 a5973fbf bellard
    asm volatile(op " %" size "3, %" size "0\n"\
1262 a5973fbf bellard
                 "movl $0,%1\n"\
1263 a5973fbf bellard
                 "jnz 1f\n"\
1264 a5973fbf bellard
                 "movl $1,%1\n"\
1265 a5973fbf bellard
                 "1:\n"\
1266 a5973fbf bellard
                 : "=r" (a), "=r" (c) : "0" (a), "r" (b));    \
1267 a5973fbf bellard
    printf(op size " A=" FMTLX " B=" FMTLX " R=" FMTLX " z=%ld\n",\
1268 a5973fbf bellard
           (long)(op1), (long)(op2), a, c);\
1269 a5973fbf bellard
}
1270 a5973fbf bellard
1271 6dbad63e bellard
/* NOTE: we use Linux modify_ldt syscall */
1272 6dbad63e bellard
void test_segs(void)
1273 6dbad63e bellard
{
1274 6dbad63e bellard
    struct modify_ldt_ldt_s ldt;
1275 6dbad63e bellard
    long long ldt_table[3];
1276 04369ff2 bellard
    int res, res2;
1277 6dbad63e bellard
    char tmp;
1278 e1d4294a bellard
    struct {
1279 e1d4294a bellard
        uint32_t offset;
1280 e1d4294a bellard
        uint16_t seg;
1281 e1d4294a bellard
    } __attribute__((packed)) segoff;
1282 6dbad63e bellard
1283 6dbad63e bellard
    ldt.entry_number = 1;
1284 6dbad63e bellard
    ldt.base_addr = (unsigned long)&seg_data1;
1285 6dbad63e bellard
    ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
1286 6dbad63e bellard
    ldt.seg_32bit = 1;
1287 6dbad63e bellard
    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
1288 6dbad63e bellard
    ldt.read_exec_only = 0;
1289 6dbad63e bellard
    ldt.limit_in_pages = 1;
1290 6dbad63e bellard
    ldt.seg_not_present = 0;
1291 6dbad63e bellard
    ldt.useable = 1;
1292 6dbad63e bellard
    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
1293 6dbad63e bellard
1294 6dbad63e bellard
    ldt.entry_number = 2;
1295 6dbad63e bellard
    ldt.base_addr = (unsigned long)&seg_data2;
1296 6dbad63e bellard
    ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12;
1297 6dbad63e bellard
    ldt.seg_32bit = 1;
1298 6dbad63e bellard
    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
1299 6dbad63e bellard
    ldt.read_exec_only = 0;
1300 6dbad63e bellard
    ldt.limit_in_pages = 1;
1301 6dbad63e bellard
    ldt.seg_not_present = 0;
1302 6dbad63e bellard
    ldt.useable = 1;
1303 6dbad63e bellard
    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
1304 6dbad63e bellard
1305 6dbad63e bellard
    modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */
1306 04369ff2 bellard
#if 0
1307 04369ff2 bellard
    {
1308 04369ff2 bellard
        int i;
1309 04369ff2 bellard
        for(i=0;i<3;i++)
1310 04369ff2 bellard
            printf("%d: %016Lx\n", i, ldt_table[i]);
1311 04369ff2 bellard
    }
1312 04369ff2 bellard
#endif
1313 6dbad63e bellard
    /* do some tests with fs or gs */
1314 6dbad63e bellard
    asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
1315 6dbad63e bellard
1316 6dbad63e bellard
    seg_data1[1] = 0xaa;
1317 6dbad63e bellard
    seg_data2[1] = 0x55;
1318 6dbad63e bellard
1319 6dbad63e bellard
    asm volatile ("fs movzbl 0x1, %0" : "=r" (res));
1320 6dbad63e bellard
    printf("FS[1] = %02x\n", res);
1321 6dbad63e bellard
1322 070893f4 bellard
    asm volatile ("pushl %%gs\n"
1323 070893f4 bellard
                  "movl %1, %%gs\n"
1324 070893f4 bellard
                  "gs movzbl 0x1, %0\n"
1325 070893f4 bellard
                  "popl %%gs\n"
1326 070893f4 bellard
                  : "=r" (res)
1327 070893f4 bellard
                  : "r" (MK_SEL(2)));
1328 6dbad63e bellard
    printf("GS[1] = %02x\n", res);
1329 6dbad63e bellard
1330 6dbad63e bellard
    /* tests with ds/ss (implicit segment case) */
1331 6dbad63e bellard
    tmp = 0xa5;
1332 6dbad63e bellard
    asm volatile ("pushl %%ebp\n\t"
1333 6dbad63e bellard
                  "pushl %%ds\n\t"
1334 6dbad63e bellard
                  "movl %2, %%ds\n\t"
1335 6dbad63e bellard
                  "movl %3, %%ebp\n\t"
1336 6dbad63e bellard
                  "movzbl 0x1, %0\n\t"
1337 6dbad63e bellard
                  "movzbl (%%ebp), %1\n\t"
1338 6dbad63e bellard
                  "popl %%ds\n\t"
1339 6dbad63e bellard
                  "popl %%ebp\n\t"
1340 6dbad63e bellard
                  : "=r" (res), "=r" (res2)
1341 6dbad63e bellard
                  : "r" (MK_SEL(1)), "r" (&tmp));
1342 6dbad63e bellard
    printf("DS[1] = %02x\n", res);
1343 6dbad63e bellard
    printf("SS[tmp] = %02x\n", res2);
1344 e1d4294a bellard
1345 e1d4294a bellard
    segoff.seg = MK_SEL(2);
1346 e1d4294a bellard
    segoff.offset = 0xabcdef12;
1347 5fafdf24 ths
    asm volatile("lfs %2, %0\n\t"
1348 e1d4294a bellard
                 "movl %%fs, %1\n\t"
1349 5fafdf24 ths
                 : "=r" (res), "=g" (res2)
1350 e1d4294a bellard
                 : "m" (segoff));
1351 e1d4294a bellard
    printf("FS:reg = %04x:%08x\n", res2, res);
1352 288426fe bellard
1353 288426fe bellard
    TEST_LR("larw", "w", MK_SEL(2), 0x0100);
1354 288426fe bellard
    TEST_LR("larl", "", MK_SEL(2), 0x0100);
1355 288426fe bellard
    TEST_LR("lslw", "w", MK_SEL(2), 0);
1356 288426fe bellard
    TEST_LR("lsll", "", MK_SEL(2), 0);
1357 288426fe bellard
1358 288426fe bellard
    TEST_LR("larw", "w", 0xfff8, 0);
1359 288426fe bellard
    TEST_LR("larl", "", 0xfff8, 0);
1360 288426fe bellard
    TEST_LR("lslw", "w", 0xfff8, 0);
1361 288426fe bellard
    TEST_LR("lsll", "", 0xfff8, 0);
1362 a5973fbf bellard
1363 a5973fbf bellard
    TEST_ARPL("arpl", "w", 0x12345678 | 3, 0x762123c | 1);
1364 a5973fbf bellard
    TEST_ARPL("arpl", "w", 0x12345678 | 1, 0x762123c | 3);
1365 a5973fbf bellard
    TEST_ARPL("arpl", "w", 0x12345678 | 1, 0x762123c | 1);
1366 6dbad63e bellard
}
1367 55480af8 bellard
1368 e5918247 bellard
/* 16 bit code test */
1369 e5918247 bellard
extern char code16_start, code16_end;
1370 e5918247 bellard
extern char code16_func1;
1371 e5918247 bellard
extern char code16_func2;
1372 e5918247 bellard
extern char code16_func3;
1373 a300e691 bellard
1374 e5918247 bellard
void test_code16(void)
1375 1a9353d2 bellard
{
1376 e5918247 bellard
    struct modify_ldt_ldt_s ldt;
1377 e5918247 bellard
    int res, res2;
1378 a300e691 bellard
1379 e5918247 bellard
    /* build a code segment */
1380 e5918247 bellard
    ldt.entry_number = 1;
1381 e5918247 bellard
    ldt.base_addr = (unsigned long)&code16_start;
1382 e5918247 bellard
    ldt.limit = &code16_end - &code16_start;
1383 e5918247 bellard
    ldt.seg_32bit = 0;
1384 e5918247 bellard
    ldt.contents = MODIFY_LDT_CONTENTS_CODE;
1385 e5918247 bellard
    ldt.read_exec_only = 0;
1386 e5918247 bellard
    ldt.limit_in_pages = 0;
1387 e5918247 bellard
    ldt.seg_not_present = 0;
1388 e5918247 bellard
    ldt.useable = 1;
1389 e5918247 bellard
    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
1390 a300e691 bellard
1391 e5918247 bellard
    /* call the first function */
1392 5fafdf24 ths
    asm volatile ("lcall %1, %2"
1393 e5918247 bellard
                  : "=a" (res)
1394 e5918247 bellard
                  : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc");
1395 e5918247 bellard
    printf("func1() = 0x%08x\n", res);
1396 5fafdf24 ths
    asm volatile ("lcall %2, %3"
1397 e5918247 bellard
                  : "=a" (res), "=c" (res2)
1398 e5918247 bellard
                  : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc");
1399 e5918247 bellard
    printf("func2() = 0x%08x spdec=%d\n", res, res2);
1400 5fafdf24 ths
    asm volatile ("lcall %1, %2"
1401 e5918247 bellard
                  : "=a" (res)
1402 e5918247 bellard
                  : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc");
1403 e5918247 bellard
    printf("func3() = 0x%08x\n", res);
1404 1a9353d2 bellard
}
1405 776f2227 bellard
#endif
1406 1a9353d2 bellard
1407 e06e5259 bellard
#if defined(__x86_64__)
1408 e06e5259 bellard
asm(".globl func_lret\n"
1409 e06e5259 bellard
    "func_lret:\n"
1410 e06e5259 bellard
    "movl $0x87654641, %eax\n"
1411 e06e5259 bellard
    "lretq\n");
1412 e06e5259 bellard
#else
1413 e06e5259 bellard
asm(".globl func_lret\n"
1414 e06e5259 bellard
    "func_lret:\n"
1415 e06e5259 bellard
    "movl $0x87654321, %eax\n"
1416 e06e5259 bellard
    "lret\n"
1417 e06e5259 bellard
1418 e06e5259 bellard
    ".globl func_iret\n"
1419 e06e5259 bellard
    "func_iret:\n"
1420 e06e5259 bellard
    "movl $0xabcd4321, %eax\n"
1421 e06e5259 bellard
    "iret\n");
1422 e06e5259 bellard
#endif
1423 e06e5259 bellard
1424 e06e5259 bellard
extern char func_lret;
1425 e06e5259 bellard
extern char func_iret;
1426 dd3587f3 bellard
1427 e1d4294a bellard
void test_misc(void)
1428 e1d4294a bellard
{
1429 e1d4294a bellard
    char table[256];
1430 776f2227 bellard
    long res, i;
1431 e1d4294a bellard
1432 e1d4294a bellard
    for(i=0;i<256;i++) table[i] = 256 - i;
1433 e1d4294a bellard
    res = 0x12345678;
1434 e1d4294a bellard
    asm ("xlat" : "=a" (res) : "b" (table), "0" (res));
1435 776f2227 bellard
    printf("xlat: EAX=" FMTLX "\n", res);
1436 dd3587f3 bellard
1437 e06e5259 bellard
#if defined(__x86_64__)
1438 8aadfbf0 bellard
#if 0
1439 e06e5259 bellard
    {
1440 8aadfbf0 bellard
        /* XXX: see if Intel Core2 and AMD64 behavior really
1441 8aadfbf0 bellard
           differ. Here we implemented the Intel way which is not
1442 8aadfbf0 bellard
           compatible yet with QEMU. */
1443 e06e5259 bellard
        static struct __attribute__((packed)) {
1444 8aadfbf0 bellard
            uint64_t offset;
1445 e06e5259 bellard
            uint16_t seg;
1446 e06e5259 bellard
        } desc;
1447 e06e5259 bellard
        long cs_sel;
1448 e06e5259 bellard

1449 e06e5259 bellard
        asm volatile ("mov %%cs, %0" : "=r" (cs_sel));
1450 e06e5259 bellard

1451 e06e5259 bellard
        asm volatile ("push %1\n"
1452 5fafdf24 ths
                      "call func_lret\n"
1453 e06e5259 bellard
                      : "=a" (res)
1454 e06e5259 bellard
                      : "r" (cs_sel) : "memory", "cc");
1455 e06e5259 bellard
        printf("func_lret=" FMTLX "\n", res);
1456 e06e5259 bellard

1457 e06e5259 bellard
        desc.offset = (long)&func_lret;
1458 e06e5259 bellard
        desc.seg = cs_sel;
1459 3b46e624 ths

1460 e06e5259 bellard
        asm volatile ("xor %%rax, %%rax\n"
1461 8aadfbf0 bellard
                      "rex64 lcall *(%%rcx)\n"
1462 e06e5259 bellard
                      : "=a" (res)
1463 8aadfbf0 bellard
                      : "c" (&desc)
1464 e06e5259 bellard
                      : "memory", "cc");
1465 e06e5259 bellard
        printf("func_lret2=" FMTLX "\n", res);
1466 e06e5259 bellard

1467 e06e5259 bellard
        asm volatile ("push %2\n"
1468 e06e5259 bellard
                      "mov $ 1f, %%rax\n"
1469 e06e5259 bellard
                      "push %%rax\n"
1470 8aadfbf0 bellard
                      "rex64 ljmp *(%%rcx)\n"
1471 e06e5259 bellard
                      "1:\n"
1472 e06e5259 bellard
                      : "=a" (res)
1473 8aadfbf0 bellard
                      : "c" (&desc), "b" (cs_sel)
1474 e06e5259 bellard
                      : "memory", "cc");
1475 e06e5259 bellard
        printf("func_lret3=" FMTLX "\n", res);
1476 e06e5259 bellard
    }
1477 8aadfbf0 bellard
#endif
1478 e06e5259 bellard
#else
1479 5fafdf24 ths
    asm volatile ("push %%cs ; call %1"
1480 dd3587f3 bellard
                  : "=a" (res)
1481 e06e5259 bellard
                  : "m" (func_lret): "memory", "cc");
1482 e06e5259 bellard
    printf("func_lret=" FMTLX "\n", res);
1483 dd3587f3 bellard
1484 5fafdf24 ths
    asm volatile ("pushf ; push %%cs ; call %1"
1485 dd3587f3 bellard
                  : "=a" (res)
1486 e06e5259 bellard
                  : "m" (func_iret): "memory", "cc");
1487 e06e5259 bellard
    printf("func_iret=" FMTLX "\n", res);
1488 776f2227 bellard
#endif
1489 dd3587f3 bellard
1490 776f2227 bellard
#if defined(__x86_64__)
1491 776f2227 bellard
    /* specific popl test */
1492 776f2227 bellard
    asm volatile ("push $12345432 ; push $0x9abcdef ; pop (%%rsp) ; pop %0"
1493 776f2227 bellard
                  : "=g" (res));
1494 776f2227 bellard
    printf("popl esp=" FMTLX "\n", res);
1495 776f2227 bellard
#else
1496 dd3587f3 bellard
    /* specific popl test */
1497 dd3587f3 bellard
    asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popl (%%esp) ; popl %0"
1498 dd3587f3 bellard
                  : "=g" (res));
1499 776f2227 bellard
    printf("popl esp=" FMTLX "\n", res);
1500 b2b5fb22 bellard
1501 b2b5fb22 bellard
    /* specific popw test */
1502 b2b5fb22 bellard
    asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popw (%%esp) ; addl $2, %%esp ; popl %0"
1503 b2b5fb22 bellard
                  : "=g" (res));
1504 776f2227 bellard
    printf("popw esp=" FMTLX "\n", res);
1505 776f2227 bellard
#endif
1506 e1d4294a bellard
}
1507 e1d4294a bellard
1508 e1d4294a bellard
uint8_t str_buffer[4096];
1509 e1d4294a bellard
1510 e1d4294a bellard
#define TEST_STRING1(OP, size, DF, REP)\
1511 e1d4294a bellard
{\
1512 776f2227 bellard
    long esi, edi, eax, ecx, eflags;\
1513 e1d4294a bellard
\
1514 e1d4294a bellard
    esi = (long)(str_buffer + sizeof(str_buffer) / 2);\
1515 e1d4294a bellard
    edi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\
1516 776f2227 bellard
    eax = i2l(0x12345678);\
1517 e1d4294a bellard
    ecx = 17;\
1518 e1d4294a bellard
\
1519 776f2227 bellard
    asm volatile ("push $0\n\t"\
1520 e1d4294a bellard
                  "popf\n\t"\
1521 e1d4294a bellard
                  DF "\n\t"\
1522 e1d4294a bellard
                  REP #OP size "\n\t"\
1523 e1d4294a bellard
                  "cld\n\t"\
1524 e1d4294a bellard
                  "pushf\n\t"\
1525 776f2227 bellard
                  "pop %4\n\t"\
1526 e1d4294a bellard
                  : "=S" (esi), "=D" (edi), "=a" (eax), "=c" (ecx), "=g" (eflags)\
1527 e1d4294a bellard
                  : "0" (esi), "1" (edi), "2" (eax), "3" (ecx));\
1528 776f2227 bellard
    printf("%-10s ESI=" FMTLX " EDI=" FMTLX " EAX=" FMTLX " ECX=" FMTLX " EFL=%04x\n",\
1529 e1d4294a bellard
           REP #OP size, esi, edi, eax, ecx,\
1530 776f2227 bellard
           (int)(eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)));\
1531 e1d4294a bellard
}
1532 e1d4294a bellard
1533 e1d4294a bellard
#define TEST_STRING(OP, REP)\
1534 e1d4294a bellard
    TEST_STRING1(OP, "b", "", REP);\
1535 e1d4294a bellard
    TEST_STRING1(OP, "w", "", REP);\
1536 e1d4294a bellard
    TEST_STRING1(OP, "l", "", REP);\
1537 776f2227 bellard
    X86_64_ONLY(TEST_STRING1(OP, "q", "", REP));\
1538 e1d4294a bellard
    TEST_STRING1(OP, "b", "std", REP);\
1539 e1d4294a bellard
    TEST_STRING1(OP, "w", "std", REP);\
1540 776f2227 bellard
    TEST_STRING1(OP, "l", "std", REP);\
1541 776f2227 bellard
    X86_64_ONLY(TEST_STRING1(OP, "q", "std", REP))
1542 e1d4294a bellard
1543 e1d4294a bellard
void test_string(void)
1544 e1d4294a bellard
{
1545 e1d4294a bellard
    int i;
1546 e1d4294a bellard
    for(i = 0;i < sizeof(str_buffer); i++)
1547 e1d4294a bellard
        str_buffer[i] = i + 0x56;
1548 e1d4294a bellard
   TEST_STRING(stos, "");
1549 e1d4294a bellard
   TEST_STRING(stos, "rep ");
1550 e1d4294a bellard
   TEST_STRING(lods, ""); /* to verify stos */
1551 5fafdf24 ths
   TEST_STRING(lods, "rep ");
1552 e1d4294a bellard
   TEST_STRING(movs, "");
1553 e1d4294a bellard
   TEST_STRING(movs, "rep ");
1554 e1d4294a bellard
   TEST_STRING(lods, ""); /* to verify stos */
1555 e1d4294a bellard
1556 e1d4294a bellard
   /* XXX: better tests */
1557 e1d4294a bellard
   TEST_STRING(scas, "");
1558 e1d4294a bellard
   TEST_STRING(scas, "repz ");
1559 e1d4294a bellard
   TEST_STRING(scas, "repnz ");
1560 e1d4294a bellard
   TEST_STRING(cmps, "");
1561 e1d4294a bellard
   TEST_STRING(cmps, "repz ");
1562 e1d4294a bellard
   TEST_STRING(cmps, "repnz ");
1563 e1d4294a bellard
}
1564 e5918247 bellard
1565 776f2227 bellard
#ifdef TEST_VM86
1566 3a27ad0b bellard
/* VM86 test */
1567 3a27ad0b bellard
1568 3a27ad0b bellard
static inline void set_bit(uint8_t *a, unsigned int bit)
1569 3a27ad0b bellard
{
1570 3a27ad0b bellard
    a[bit / 8] |= (1 << (bit % 8));
1571 3a27ad0b bellard
}
1572 3a27ad0b bellard
1573 3a27ad0b bellard
static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
1574 3a27ad0b bellard
{
1575 3a27ad0b bellard
    return (uint8_t *)((seg << 4) + (reg & 0xffff));
1576 3a27ad0b bellard
}
1577 3a27ad0b bellard
1578 3a27ad0b bellard
static inline void pushw(struct vm86_regs *r, int val)
1579 3a27ad0b bellard
{
1580 3a27ad0b bellard
    r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
1581 3a27ad0b bellard
    *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
1582 3a27ad0b bellard
}
1583 3a27ad0b bellard
1584 be98f1f8 bellard
static inline int vm86(int func, struct vm86plus_struct *v86)
1585 be98f1f8 bellard
{
1586 be98f1f8 bellard
    return syscall(__NR_vm86, func, v86);
1587 be98f1f8 bellard
}
1588 3a27ad0b bellard
1589 3a27ad0b bellard
extern char vm86_code_start;
1590 3a27ad0b bellard
extern char vm86_code_end;
1591 3a27ad0b bellard
1592 3a27ad0b bellard
#define VM86_CODE_CS 0x100
1593 3a27ad0b bellard
#define VM86_CODE_IP 0x100
1594 3a27ad0b bellard
1595 3a27ad0b bellard
void test_vm86(void)
1596 3a27ad0b bellard
{
1597 3a27ad0b bellard
    struct vm86plus_struct ctx;
1598 3a27ad0b bellard
    struct vm86_regs *r;
1599 3a27ad0b bellard
    uint8_t *vm86_mem;
1600 3a27ad0b bellard
    int seg, ret;
1601 3a27ad0b bellard
1602 5fafdf24 ths
    vm86_mem = mmap((void *)0x00000000, 0x110000,
1603 5fafdf24 ths
                    PROT_WRITE | PROT_READ | PROT_EXEC,
1604 3a27ad0b bellard
                    MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
1605 3a27ad0b bellard
    if (vm86_mem == MAP_FAILED) {
1606 3a27ad0b bellard
        printf("ERROR: could not map vm86 memory");
1607 3a27ad0b bellard
        return;
1608 3a27ad0b bellard
    }
1609 3a27ad0b bellard
    memset(&ctx, 0, sizeof(ctx));
1610 3a27ad0b bellard
1611 3a27ad0b bellard
    /* init basic registers */
1612 3a27ad0b bellard
    r = &ctx.regs;
1613 3a27ad0b bellard
    r->eip = VM86_CODE_IP;
1614 3a27ad0b bellard
    r->esp = 0xfffe;
1615 3a27ad0b bellard
    seg = VM86_CODE_CS;
1616 3a27ad0b bellard
    r->cs = seg;
1617 3a27ad0b bellard
    r->ss = seg;
1618 3a27ad0b bellard
    r->ds = seg;
1619 3a27ad0b bellard
    r->es = seg;
1620 3a27ad0b bellard
    r->fs = seg;
1621 3a27ad0b bellard
    r->gs = seg;
1622 3a27ad0b bellard
    r->eflags = VIF_MASK;
1623 3a27ad0b bellard
1624 3a27ad0b bellard
    /* move code to proper address. We use the same layout as a .com
1625 3a27ad0b bellard
       dos program. */
1626 5fafdf24 ths
    memcpy(vm86_mem + (VM86_CODE_CS << 4) + VM86_CODE_IP,
1627 3a27ad0b bellard
           &vm86_code_start, &vm86_code_end - &vm86_code_start);
1628 3a27ad0b bellard
1629 3a27ad0b bellard
    /* mark int 0x21 as being emulated */
1630 3a27ad0b bellard
    set_bit((uint8_t *)&ctx.int_revectored, 0x21);
1631 3a27ad0b bellard
1632 3a27ad0b bellard
    for(;;) {
1633 3a27ad0b bellard
        ret = vm86(VM86_ENTER, &ctx);
1634 3a27ad0b bellard
        switch(VM86_TYPE(ret)) {
1635 3a27ad0b bellard
        case VM86_INTx:
1636 3a27ad0b bellard
            {
1637 3ff0631e bellard
                int int_num, ah, v;
1638 3b46e624 ths
1639 3a27ad0b bellard
                int_num = VM86_ARG(ret);
1640 3a27ad0b bellard
                if (int_num != 0x21)
1641 3a27ad0b bellard
                    goto unknown_int;
1642 3a27ad0b bellard
                ah = (r->eax >> 8) & 0xff;
1643 3a27ad0b bellard
                switch(ah) {
1644 3a27ad0b bellard
                case 0x00: /* exit */
1645 3a27ad0b bellard
                    goto the_end;
1646 3a27ad0b bellard
                case 0x02: /* write char */
1647 3a27ad0b bellard
                    {
1648 3a27ad0b bellard
                        uint8_t c = r->edx;
1649 3a27ad0b bellard
                        putchar(c);
1650 3a27ad0b bellard
                    }
1651 3a27ad0b bellard
                    break;
1652 3a27ad0b bellard
                case 0x09: /* write string */
1653 3a27ad0b bellard
                    {
1654 3a27ad0b bellard
                        uint8_t c, *ptr;
1655 3a27ad0b bellard
                        ptr = seg_to_linear(r->ds, r->edx);
1656 3a27ad0b bellard
                        for(;;) {
1657 3a27ad0b bellard
                            c = *ptr++;
1658 3a27ad0b bellard
                            if (c == '$')
1659 3a27ad0b bellard
                                break;
1660 3a27ad0b bellard
                            putchar(c);
1661 3a27ad0b bellard
                        }
1662 3a27ad0b bellard
                        r->eax = (r->eax & ~0xff) | '$';
1663 3a27ad0b bellard
                    }
1664 3a27ad0b bellard
                    break;
1665 3ff0631e bellard
                case 0xff: /* extension: write eflags number in edx */
1666 3ff0631e bellard
                    v = (int)r->edx;
1667 3ff0631e bellard
#ifndef LINUX_VM86_IOPL_FIX
1668 3ff0631e bellard
                    v &= ~0x3000;
1669 3ff0631e bellard
#endif
1670 3ff0631e bellard
                    printf("%08x\n", v);
1671 3a27ad0b bellard
                    break;
1672 3a27ad0b bellard
                default:
1673 3a27ad0b bellard
                unknown_int:
1674 3a27ad0b bellard
                    printf("unsupported int 0x%02x\n", int_num);
1675 3a27ad0b bellard
                    goto the_end;
1676 3a27ad0b bellard
                }
1677 3a27ad0b bellard
            }
1678 3a27ad0b bellard
            break;
1679 3a27ad0b bellard
        case VM86_SIGNAL:
1680 3a27ad0b bellard
            /* a signal came, we just ignore that */
1681 3a27ad0b bellard
            break;
1682 3a27ad0b bellard
        case VM86_STI:
1683 3a27ad0b bellard
            break;
1684 3a27ad0b bellard
        default:
1685 3a27ad0b bellard
            printf("ERROR: unhandled vm86 return code (0x%x)\n", ret);
1686 3a27ad0b bellard
            goto the_end;
1687 3a27ad0b bellard
        }
1688 3a27ad0b bellard
    }
1689 3a27ad0b bellard
 the_end:
1690 3a27ad0b bellard
    printf("VM86 end\n");
1691 3a27ad0b bellard
    munmap(vm86_mem, 0x110000);
1692 3a27ad0b bellard
}
1693 776f2227 bellard
#endif
1694 3a27ad0b bellard
1695 3a27ad0b bellard
/* exception tests */
1696 776f2227 bellard
#if defined(__i386__) && !defined(REG_EAX)
1697 3a27ad0b bellard
#define REG_EAX EAX
1698 3a27ad0b bellard
#define REG_EBX EBX
1699 3a27ad0b bellard
#define REG_ECX ECX
1700 3a27ad0b bellard
#define REG_EDX EDX
1701 3a27ad0b bellard
#define REG_ESI ESI
1702 3a27ad0b bellard
#define REG_EDI EDI
1703 3a27ad0b bellard
#define REG_EBP EBP
1704 3a27ad0b bellard
#define REG_ESP ESP
1705 3a27ad0b bellard
#define REG_EIP EIP
1706 3a27ad0b bellard
#define REG_EFL EFL
1707 3a27ad0b bellard
#define REG_TRAPNO TRAPNO
1708 3a27ad0b bellard
#define REG_ERR ERR
1709 3a27ad0b bellard
#endif
1710 3a27ad0b bellard
1711 776f2227 bellard
#if defined(__x86_64__)
1712 776f2227 bellard
#define REG_EIP REG_RIP
1713 776f2227 bellard
#endif
1714 776f2227 bellard
1715 3a27ad0b bellard
jmp_buf jmp_env;
1716 3a27ad0b bellard
int v1;
1717 3a27ad0b bellard
int tab[2];
1718 3a27ad0b bellard
1719 3a27ad0b bellard
void sig_handler(int sig, siginfo_t *info, void *puc)
1720 3a27ad0b bellard
{
1721 3a27ad0b bellard
    struct ucontext *uc = puc;
1722 3a27ad0b bellard
1723 3a27ad0b bellard
    printf("si_signo=%d si_errno=%d si_code=%d",
1724 3a27ad0b bellard
           info->si_signo, info->si_errno, info->si_code);
1725 e3b32540 bellard
    printf(" si_addr=0x%08lx",
1726 e3b32540 bellard
           (unsigned long)info->si_addr);
1727 3a27ad0b bellard
    printf("\n");
1728 3a27ad0b bellard
1729 776f2227 bellard
    printf("trapno=" FMTLX " err=" FMTLX,
1730 776f2227 bellard
           (long)uc->uc_mcontext.gregs[REG_TRAPNO],
1731 776f2227 bellard
           (long)uc->uc_mcontext.gregs[REG_ERR]);
1732 776f2227 bellard
    printf(" EIP=" FMTLX, (long)uc->uc_mcontext.gregs[REG_EIP]);
1733 3a27ad0b bellard
    printf("\n");
1734 3a27ad0b bellard
    longjmp(jmp_env, 1);
1735 3a27ad0b bellard
}
1736 3a27ad0b bellard
1737 3a27ad0b bellard
void test_exceptions(void)
1738 3a27ad0b bellard
{
1739 3a27ad0b bellard
    struct sigaction act;
1740 3a27ad0b bellard
    volatile int val;
1741 3b46e624 ths
1742 3a27ad0b bellard
    act.sa_sigaction = sig_handler;
1743 3a27ad0b bellard
    sigemptyset(&act.sa_mask);
1744 776f2227 bellard
    act.sa_flags = SA_SIGINFO | SA_NODEFER;
1745 3a27ad0b bellard
    sigaction(SIGFPE, &act, NULL);
1746 3a27ad0b bellard
    sigaction(SIGILL, &act, NULL);
1747 3a27ad0b bellard
    sigaction(SIGSEGV, &act, NULL);
1748 e3b32540 bellard
    sigaction(SIGBUS, &act, NULL);
1749 3a27ad0b bellard
    sigaction(SIGTRAP, &act, NULL);
1750 3a27ad0b bellard
1751 3a27ad0b bellard
    /* test division by zero reporting */
1752 e3b32540 bellard
    printf("DIVZ exception:\n");
1753 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1754 3a27ad0b bellard
        /* now divide by zero */
1755 3a27ad0b bellard
        v1 = 0;
1756 3a27ad0b bellard
        v1 = 2 / v1;
1757 3a27ad0b bellard
    }
1758 3a27ad0b bellard
1759 776f2227 bellard
#if !defined(__x86_64__)
1760 e3b32540 bellard
    printf("BOUND exception:\n");
1761 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1762 3a27ad0b bellard
        /* bound exception */
1763 3a27ad0b bellard
        tab[0] = 1;
1764 3a27ad0b bellard
        tab[1] = 10;
1765 e82d8ade bellard
        asm volatile ("bound %0, %1" : : "r" (11), "m" (tab[0]));
1766 3a27ad0b bellard
    }
1767 776f2227 bellard
#endif
1768 3a27ad0b bellard
1769 776f2227 bellard
#ifdef TEST_SEGS
1770 e3b32540 bellard
    printf("segment exceptions:\n");
1771 e3b32540 bellard
    if (setjmp(jmp_env) == 0) {
1772 e3b32540 bellard
        /* load an invalid segment */
1773 e3b32540 bellard
        asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 1));
1774 e3b32540 bellard
    }
1775 e3b32540 bellard
    if (setjmp(jmp_env) == 0) {
1776 e3b32540 bellard
        /* null data segment is valid */
1777 e3b32540 bellard
        asm volatile ("movl %0, %%fs" : : "r" (3));
1778 e3b32540 bellard
        /* null stack segment */
1779 e3b32540 bellard
        asm volatile ("movl %0, %%ss" : : "r" (3));
1780 e3b32540 bellard
    }
1781 e3b32540 bellard
1782 776f2227 bellard
    {
1783 776f2227 bellard
        struct modify_ldt_ldt_s ldt;
1784 776f2227 bellard
        ldt.entry_number = 1;
1785 776f2227 bellard
        ldt.base_addr = (unsigned long)&seg_data1;
1786 776f2227 bellard
        ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
1787 776f2227 bellard
        ldt.seg_32bit = 1;
1788 776f2227 bellard
        ldt.contents = MODIFY_LDT_CONTENTS_DATA;
1789 776f2227 bellard
        ldt.read_exec_only = 0;
1790 776f2227 bellard
        ldt.limit_in_pages = 1;
1791 776f2227 bellard
        ldt.seg_not_present = 1;
1792 776f2227 bellard
        ldt.useable = 1;
1793 776f2227 bellard
        modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
1794 3b46e624 ths
1795 776f2227 bellard
        if (setjmp(jmp_env) == 0) {
1796 776f2227 bellard
            /* segment not present */
1797 776f2227 bellard
            asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
1798 776f2227 bellard
        }
1799 e3b32540 bellard
    }
1800 776f2227 bellard
#endif
1801 e3b32540 bellard
1802 3a27ad0b bellard
    /* test SEGV reporting */
1803 e3b32540 bellard
    printf("PF exception:\n");
1804 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1805 e3b32540 bellard
        val = 1;
1806 ede28208 bellard
        /* we add a nop to test a weird PC retrieval case */
1807 ede28208 bellard
        asm volatile ("nop");
1808 3a27ad0b bellard
        /* now store in an invalid address */
1809 3a27ad0b bellard
        *(char *)0x1234 = 1;
1810 3a27ad0b bellard
    }
1811 3a27ad0b bellard
1812 3a27ad0b bellard
    /* test SEGV reporting */
1813 e3b32540 bellard
    printf("PF exception:\n");
1814 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1815 e3b32540 bellard
        val = 1;
1816 3a27ad0b bellard
        /* read from an invalid address */
1817 3a27ad0b bellard
        v1 = *(char *)0x1234;
1818 3a27ad0b bellard
    }
1819 3b46e624 ths
1820 3a27ad0b bellard
    /* test illegal instruction reporting */
1821 3a27ad0b bellard
    printf("UD2 exception:\n");
1822 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1823 3a27ad0b bellard
        /* now execute an invalid instruction */
1824 3a27ad0b bellard
        asm volatile("ud2");
1825 3a27ad0b bellard
    }
1826 4120b61d bellard
    printf("lock nop exception:\n");
1827 4120b61d bellard
    if (setjmp(jmp_env) == 0) {
1828 4120b61d bellard
        /* now execute an invalid instruction */
1829 4120b61d bellard
        asm volatile("lock nop");
1830 4120b61d bellard
    }
1831 3b46e624 ths
1832 3a27ad0b bellard
    printf("INT exception:\n");
1833 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1834 3a27ad0b bellard
        asm volatile ("int $0xfd");
1835 3a27ad0b bellard
    }
1836 e3b32540 bellard
    if (setjmp(jmp_env) == 0) {
1837 e3b32540 bellard
        asm volatile ("int $0x01");
1838 e3b32540 bellard
    }
1839 e3b32540 bellard
    if (setjmp(jmp_env) == 0) {
1840 e3b32540 bellard
        asm volatile (".byte 0xcd, 0x03");
1841 e3b32540 bellard
    }
1842 e3b32540 bellard
    if (setjmp(jmp_env) == 0) {
1843 e3b32540 bellard
        asm volatile ("int $0x04");
1844 e3b32540 bellard
    }
1845 e3b32540 bellard
    if (setjmp(jmp_env) == 0) {
1846 e3b32540 bellard
        asm volatile ("int $0x05");
1847 e3b32540 bellard
    }
1848 3a27ad0b bellard
1849 3a27ad0b bellard
    printf("INT3 exception:\n");
1850 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1851 3a27ad0b bellard
        asm volatile ("int3");
1852 3a27ad0b bellard
    }
1853 3a27ad0b bellard
1854 3a27ad0b bellard
    printf("CLI exception:\n");
1855 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1856 3a27ad0b bellard
        asm volatile ("cli");
1857 3a27ad0b bellard
    }
1858 3a27ad0b bellard
1859 3a27ad0b bellard
    printf("STI exception:\n");
1860 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1861 3a27ad0b bellard
        asm volatile ("cli");
1862 3a27ad0b bellard
    }
1863 3a27ad0b bellard
1864 776f2227 bellard
#if !defined(__x86_64__)
1865 3a27ad0b bellard
    printf("INTO exception:\n");
1866 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1867 3a27ad0b bellard
        /* overflow exception */
1868 3a27ad0b bellard
        asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff));
1869 3a27ad0b bellard
    }
1870 776f2227 bellard
#endif
1871 3a27ad0b bellard
1872 3a27ad0b bellard
    printf("OUTB exception:\n");
1873 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1874 3a27ad0b bellard
        asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0));
1875 3a27ad0b bellard
    }
1876 3a27ad0b bellard
1877 3a27ad0b bellard
    printf("INB exception:\n");
1878 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1879 3a27ad0b bellard
        asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321));
1880 3a27ad0b bellard
    }
1881 3a27ad0b bellard
1882 3a27ad0b bellard
    printf("REP OUTSB exception:\n");
1883 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1884 3a27ad0b bellard
        asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1));
1885 3a27ad0b bellard
    }
1886 3a27ad0b bellard
1887 3a27ad0b bellard
    printf("REP INSB exception:\n");
1888 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1889 3a27ad0b bellard
        asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1));
1890 3a27ad0b bellard
    }
1891 3a27ad0b bellard
1892 3a27ad0b bellard
    printf("HLT exception:\n");
1893 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1894 3a27ad0b bellard
        asm volatile ("hlt");
1895 3a27ad0b bellard
    }
1896 3a27ad0b bellard
1897 3a27ad0b bellard
    printf("single step exception:\n");
1898 3a27ad0b bellard
    val = 0;
1899 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1900 3a27ad0b bellard
        asm volatile ("pushf\n"
1901 3a27ad0b bellard
                      "orl $0x00100, (%%esp)\n"
1902 3a27ad0b bellard
                      "popf\n"
1903 5fafdf24 ths
                      "movl $0xabcd, %0\n"
1904 3a27ad0b bellard
                      "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory");
1905 3a27ad0b bellard
    }
1906 3a27ad0b bellard
    printf("val=0x%x\n", val);
1907 3a27ad0b bellard
}
1908 3a27ad0b bellard
1909 776f2227 bellard
#if !defined(__x86_64__)
1910 3ff0631e bellard
/* specific precise single step test */
1911 3ff0631e bellard
void sig_trap_handler(int sig, siginfo_t *info, void *puc)
1912 3ff0631e bellard
{
1913 3ff0631e bellard
    struct ucontext *uc = puc;
1914 776f2227 bellard
    printf("EIP=" FMTLX "\n", (long)uc->uc_mcontext.gregs[REG_EIP]);
1915 3ff0631e bellard
}
1916 3ff0631e bellard
1917 3ff0631e bellard
const uint8_t sstep_buf1[4] = { 1, 2, 3, 4};
1918 3ff0631e bellard
uint8_t sstep_buf2[4];
1919 3ff0631e bellard
1920 3ff0631e bellard
void test_single_step(void)
1921 3ff0631e bellard
{
1922 3ff0631e bellard
    struct sigaction act;
1923 3ff0631e bellard
    volatile int val;
1924 3ff0631e bellard
    int i;
1925 3ff0631e bellard
1926 3ff0631e bellard
    val = 0;
1927 3ff0631e bellard
    act.sa_sigaction = sig_trap_handler;
1928 3ff0631e bellard
    sigemptyset(&act.sa_mask);
1929 3ff0631e bellard
    act.sa_flags = SA_SIGINFO;
1930 3ff0631e bellard
    sigaction(SIGTRAP, &act, NULL);
1931 3ff0631e bellard
    asm volatile ("pushf\n"
1932 3ff0631e bellard
                  "orl $0x00100, (%%esp)\n"
1933 3ff0631e bellard
                  "popf\n"
1934 5fafdf24 ths
                  "movl $0xabcd, %0\n"
1935 3ff0631e bellard
1936 3ff0631e bellard
                  /* jmp test */
1937 3ff0631e bellard
                  "movl $3, %%ecx\n"
1938 3ff0631e bellard
                  "1:\n"
1939 3ff0631e bellard
                  "addl $1, %0\n"
1940 3ff0631e bellard
                  "decl %%ecx\n"
1941 3ff0631e bellard
                  "jnz 1b\n"
1942 3ff0631e bellard
1943 3ff0631e bellard
                  /* movsb: the single step should stop at each movsb iteration */
1944 3ff0631e bellard
                  "movl $sstep_buf1, %%esi\n"
1945 3ff0631e bellard
                  "movl $sstep_buf2, %%edi\n"
1946 3ff0631e bellard
                  "movl $0, %%ecx\n"
1947 3ff0631e bellard
                  "rep movsb\n"
1948 3ff0631e bellard
                  "movl $3, %%ecx\n"
1949 3ff0631e bellard
                  "rep movsb\n"
1950 3ff0631e bellard
                  "movl $1, %%ecx\n"
1951 3ff0631e bellard
                  "rep movsb\n"
1952 3ff0631e bellard
1953 3ff0631e bellard
                  /* cmpsb: the single step should stop at each cmpsb iteration */
1954 3ff0631e bellard
                  "movl $sstep_buf1, %%esi\n"
1955 3ff0631e bellard
                  "movl $sstep_buf2, %%edi\n"
1956 3ff0631e bellard
                  "movl $0, %%ecx\n"
1957 3ff0631e bellard
                  "rep cmpsb\n"
1958 3ff0631e bellard
                  "movl $4, %%ecx\n"
1959 3ff0631e bellard
                  "rep cmpsb\n"
1960 3b46e624 ths
1961 3ff0631e bellard
                  /* getpid() syscall: single step should skip one
1962 3ff0631e bellard
                     instruction */
1963 3ff0631e bellard
                  "movl $20, %%eax\n"
1964 3ff0631e bellard
                  "int $0x80\n"
1965 3ff0631e bellard
                  "movl $0, %%eax\n"
1966 3b46e624 ths
1967 3ff0631e bellard
                  /* when modifying SS, trace is not done on the next
1968 3ff0631e bellard
                     instruction */
1969 3ff0631e bellard
                  "movl %%ss, %%ecx\n"
1970 3ff0631e bellard
                  "movl %%ecx, %%ss\n"
1971 3ff0631e bellard
                  "addl $1, %0\n"
1972 3ff0631e bellard
                  "movl $1, %%eax\n"
1973 3ff0631e bellard
                  "movl %%ecx, %%ss\n"
1974 3ff0631e bellard
                  "jmp 1f\n"
1975 3ff0631e bellard
                  "addl $1, %0\n"
1976 3ff0631e bellard
                  "1:\n"
1977 3ff0631e bellard
                  "movl $1, %%eax\n"
1978 3ff0631e bellard
                  "pushl %%ecx\n"
1979 3ff0631e bellard
                  "popl %%ss\n"
1980 3ff0631e bellard
                  "addl $1, %0\n"
1981 3ff0631e bellard
                  "movl $1, %%eax\n"
1982 3b46e624 ths
1983 3ff0631e bellard
                  "pushf\n"
1984 3ff0631e bellard
                  "andl $~0x00100, (%%esp)\n"
1985 3ff0631e bellard
                  "popf\n"
1986 5fafdf24 ths
                  : "=m" (val)
1987 5fafdf24 ths
                  :
1988 3ff0631e bellard
                  : "cc", "memory", "eax", "ecx", "esi", "edi");
1989 3ff0631e bellard
    printf("val=%d\n", val);
1990 3ff0631e bellard
    for(i = 0; i < 4; i++)
1991 3ff0631e bellard
        printf("sstep_buf2[%d] = %d\n", i, sstep_buf2[i]);
1992 3ff0631e bellard
}
1993 3ff0631e bellard
1994 3a27ad0b bellard
/* self modifying code test */
1995 3a27ad0b bellard
uint8_t code[] = {
1996 3a27ad0b bellard
    0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */
1997 3a27ad0b bellard
    0xc3, /* ret */
1998 3a27ad0b bellard
};
1999 3a27ad0b bellard
2000 a5973fbf bellard
asm(".section \".data\"\n"
2001 a5973fbf bellard
    "smc_code2:\n"
2002 1190935d bellard
    "movl 4(%esp), %eax\n"
2003 1190935d bellard
    "movl %eax, smc_patch_addr2 + 1\n"
2004 1190935d bellard
    "nop\n"
2005 1190935d bellard
    "nop\n"
2006 1190935d bellard
    "nop\n"
2007 1190935d bellard
    "nop\n"
2008 1190935d bellard
    "nop\n"
2009 1190935d bellard
    "nop\n"
2010 1190935d bellard
    "nop\n"
2011 1190935d bellard
    "nop\n"
2012 1190935d bellard
    "smc_patch_addr2:\n"
2013 1190935d bellard
    "movl $1, %eax\n"
2014 a5973fbf bellard
    "ret\n"
2015 a5973fbf bellard
    ".previous\n"
2016 a5973fbf bellard
    );
2017 d1fe2b24 bellard
2018 1190935d bellard
typedef int FuncType(void);
2019 1190935d bellard
extern int smc_code2(int);
2020 3a27ad0b bellard
void test_self_modifying_code(void)
2021 3a27ad0b bellard
{
2022 d1fe2b24 bellard
    int i;
2023 3a27ad0b bellard
    printf("self modifying code:\n");
2024 d1fe2b24 bellard
    printf("func1 = 0x%x\n", ((FuncType *)code)());
2025 d1fe2b24 bellard
    for(i = 2; i <= 4; i++) {
2026 d1fe2b24 bellard
        code[1] = i;
2027 d1fe2b24 bellard
        printf("func%d = 0x%x\n", i, ((FuncType *)code)());
2028 d1fe2b24 bellard
    }
2029 1190935d bellard
2030 1190935d bellard
    /* more difficult test : the modified code is just after the
2031 1190935d bellard
       modifying instruction. It is forbidden in Intel specs, but it
2032 1190935d bellard
       is used by old DOS programs */
2033 1190935d bellard
    for(i = 2; i <= 4; i++) {
2034 1190935d bellard
        printf("smc_code2(%d) = %d\n", i, smc_code2(i));
2035 1190935d bellard
    }
2036 3a27ad0b bellard
}
2037 776f2227 bellard
#endif
2038 61a8c4ec bellard
2039 776f2227 bellard
long enter_stack[4096];
2040 776f2227 bellard
2041 776f2227 bellard
#if defined(__x86_64__)
2042 776f2227 bellard
#define RSP "%%rsp"
2043 776f2227 bellard
#define RBP "%%rbp"
2044 776f2227 bellard
#else
2045 776f2227 bellard
#define RSP "%%esp"
2046 776f2227 bellard
#define RBP "%%ebp"
2047 776f2227 bellard
#endif
2048 61a8c4ec bellard
2049 61a8c4ec bellard
#define TEST_ENTER(size, stack_type, level)\
2050 61a8c4ec bellard
{\
2051 776f2227 bellard
    long esp_save, esp_val, ebp_val, ebp_save, i;\
2052 61a8c4ec bellard
    stack_type *ptr, *stack_end, *stack_ptr;\
2053 61a8c4ec bellard
    memset(enter_stack, 0, sizeof(enter_stack));\
2054 61a8c4ec bellard
    stack_end = stack_ptr = (stack_type *)(enter_stack + 4096);\
2055 61a8c4ec bellard
    ebp_val = (long)stack_ptr;\
2056 61a8c4ec bellard
    for(i=1;i<=32;i++)\
2057 61a8c4ec bellard
       *--stack_ptr = i;\
2058 61a8c4ec bellard
    esp_val = (long)stack_ptr;\
2059 776f2227 bellard
    asm("mov " RSP ", %[esp_save]\n"\
2060 776f2227 bellard
        "mov " RBP ", %[ebp_save]\n"\
2061 776f2227 bellard
        "mov %[esp_val], " RSP "\n"\
2062 776f2227 bellard
        "mov %[ebp_val], " RBP "\n"\
2063 776f2227 bellard
        "enter" size " $8, $" #level "\n"\
2064 776f2227 bellard
        "mov " RSP ", %[esp_val]\n"\
2065 776f2227 bellard
        "mov " RBP ", %[ebp_val]\n"\
2066 776f2227 bellard
        "mov %[esp_save], " RSP "\n"\
2067 776f2227 bellard
        "mov %[ebp_save], " RBP "\n"\
2068 61a8c4ec bellard
        : [esp_save] "=r" (esp_save),\
2069 61a8c4ec bellard
        [ebp_save] "=r" (ebp_save),\
2070 61a8c4ec bellard
        [esp_val] "=r" (esp_val),\
2071 61a8c4ec bellard
        [ebp_val] "=r" (ebp_val)\
2072 61a8c4ec bellard
        :  "[esp_val]" (esp_val),\
2073 61a8c4ec bellard
        "[ebp_val]" (ebp_val));\
2074 61a8c4ec bellard
    printf("level=%d:\n", level);\
2075 776f2227 bellard
    printf("esp_val=" FMTLX "\n", esp_val - (long)stack_end);\
2076 776f2227 bellard
    printf("ebp_val=" FMTLX "\n", ebp_val - (long)stack_end);\
2077 61a8c4ec bellard
    for(ptr = (stack_type *)esp_val; ptr < stack_end; ptr++)\
2078 776f2227 bellard
        printf(FMTLX "\n", (long)ptr[0]);\
2079 61a8c4ec bellard
}
2080 61a8c4ec bellard
2081 61a8c4ec bellard
static void test_enter(void)
2082 61a8c4ec bellard
{
2083 776f2227 bellard
#if defined(__x86_64__)
2084 776f2227 bellard
    TEST_ENTER("q", uint64_t, 0);
2085 776f2227 bellard
    TEST_ENTER("q", uint64_t, 1);
2086 776f2227 bellard
    TEST_ENTER("q", uint64_t, 2);
2087 776f2227 bellard
    TEST_ENTER("q", uint64_t, 31);
2088 776f2227 bellard
#else
2089 61a8c4ec bellard
    TEST_ENTER("l", uint32_t, 0);
2090 61a8c4ec bellard
    TEST_ENTER("l", uint32_t, 1);
2091 61a8c4ec bellard
    TEST_ENTER("l", uint32_t, 2);
2092 61a8c4ec bellard
    TEST_ENTER("l", uint32_t, 31);
2093 776f2227 bellard
#endif
2094 61a8c4ec bellard
2095 61a8c4ec bellard
    TEST_ENTER("w", uint16_t, 0);
2096 61a8c4ec bellard
    TEST_ENTER("w", uint16_t, 1);
2097 61a8c4ec bellard
    TEST_ENTER("w", uint16_t, 2);
2098 61a8c4ec bellard
    TEST_ENTER("w", uint16_t, 31);
2099 61a8c4ec bellard
}
2100 61a8c4ec bellard
2101 085339a1 bellard
#ifdef TEST_SSE
2102 085339a1 bellard
2103 085339a1 bellard
typedef int __m64 __attribute__ ((__mode__ (__V2SI__)));
2104 8aadfbf0 bellard
typedef float __m128 __attribute__ ((__mode__(__V4SF__)));
2105 085339a1 bellard
2106 085339a1 bellard
typedef union {
2107 085339a1 bellard
    double d[2];
2108 085339a1 bellard
    float s[4];
2109 085339a1 bellard
    uint32_t l[4];
2110 085339a1 bellard
    uint64_t q[2];
2111 085339a1 bellard
    __m128 dq;
2112 085339a1 bellard
} XMMReg;
2113 085339a1 bellard
2114 085339a1 bellard
static uint64_t __attribute__((aligned(16))) test_values[4][2] = {
2115 085339a1 bellard
    { 0x456723c698694873, 0xdc515cff944a58ec },
2116 085339a1 bellard
    { 0x1f297ccd58bad7ab, 0x41f21efba9e3e146 },
2117 085339a1 bellard
    { 0x007c62c2085427f8, 0x231be9e8cde7438d },
2118 085339a1 bellard
    { 0x0f76255a085427f8, 0xc233e9e8c4c9439a },
2119 085339a1 bellard
};
2120 085339a1 bellard
2121 085339a1 bellard
#define SSE_OP(op)\
2122 085339a1 bellard
{\
2123 085339a1 bellard
    asm volatile (#op " %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
2124 776f2227 bellard
    printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
2125 085339a1 bellard
           #op,\
2126 085339a1 bellard
           a.q[1], a.q[0],\
2127 085339a1 bellard
           b.q[1], b.q[0],\
2128 085339a1 bellard
           r.q[1], r.q[0]);\
2129 085339a1 bellard
}
2130 085339a1 bellard
2131 085339a1 bellard
#define SSE_OP2(op)\
2132 085339a1 bellard
{\
2133 085339a1 bellard
    int i;\
2134 085339a1 bellard
    for(i=0;i<2;i++) {\
2135 085339a1 bellard
    a.q[0] = test_values[2*i][0];\
2136 085339a1 bellard
    a.q[1] = test_values[2*i][1];\
2137 085339a1 bellard
    b.q[0] = test_values[2*i+1][0];\
2138 085339a1 bellard
    b.q[1] = test_values[2*i+1][1];\
2139 085339a1 bellard
    SSE_OP(op);\
2140 085339a1 bellard
    }\
2141 085339a1 bellard
}
2142 085339a1 bellard
2143 085339a1 bellard
#define MMX_OP2(op)\
2144 085339a1 bellard
{\
2145 085339a1 bellard
    int i;\
2146 085339a1 bellard
    for(i=0;i<2;i++) {\
2147 085339a1 bellard
    a.q[0] = test_values[2*i][0];\
2148 085339a1 bellard
    b.q[0] = test_values[2*i+1][0];\
2149 085339a1 bellard
    asm volatile (#op " %2, %0" : "=y" (r.q[0]) : "0" (a.q[0]), "y" (b.q[0]));\
2150 776f2227 bellard
    printf("%-9s: a=" FMT64X " b=" FMT64X " r=" FMT64X "\n",\
2151 085339a1 bellard
           #op,\
2152 085339a1 bellard
           a.q[0],\
2153 085339a1 bellard
           b.q[0],\
2154 085339a1 bellard
           r.q[0]);\
2155 085339a1 bellard
    }\
2156 085339a1 bellard
    SSE_OP2(op);\
2157 085339a1 bellard
}
2158 085339a1 bellard
2159 97ed14ae bellard
#define SHUF_OP(op, ib)\
2160 97ed14ae bellard
{\
2161 97ed14ae bellard
    a.q[0] = test_values[0][0];\
2162 97ed14ae bellard
    a.q[1] = test_values[0][1];\
2163 97ed14ae bellard
    b.q[0] = test_values[1][0];\
2164 97ed14ae bellard
    b.q[1] = test_values[1][1];\
2165 97ed14ae bellard
    asm volatile (#op " $" #ib ", %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
2166 776f2227 bellard
    printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
2167 97ed14ae bellard
           #op,\
2168 97ed14ae bellard
           a.q[1], a.q[0],\
2169 97ed14ae bellard
           b.q[1], b.q[0],\
2170 97ed14ae bellard
           ib,\
2171 97ed14ae bellard
           r.q[1], r.q[0]);\
2172 97ed14ae bellard
}
2173 97ed14ae bellard
2174 085339a1 bellard
#define PSHUF_OP(op, ib)\
2175 085339a1 bellard
{\
2176 085339a1 bellard
    int i;\
2177 085339a1 bellard
    for(i=0;i<2;i++) {\
2178 085339a1 bellard
    a.q[0] = test_values[2*i][0];\
2179 085339a1 bellard
    a.q[1] = test_values[2*i][1];\
2180 085339a1 bellard
    asm volatile (#op " $" #ib ", %1, %0" : "=x" (r.dq) : "x" (a.dq));\
2181 776f2227 bellard
    printf("%-9s: a=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
2182 085339a1 bellard
           #op,\
2183 085339a1 bellard
           a.q[1], a.q[0],\
2184 085339a1 bellard
           ib,\
2185 085339a1 bellard
           r.q[1], r.q[0]);\
2186 085339a1 bellard
    }\
2187 085339a1 bellard
}
2188 085339a1 bellard
2189 085339a1 bellard
#define SHIFT_IM(op, ib)\
2190 085339a1 bellard
{\
2191 085339a1 bellard
    int i;\
2192 085339a1 bellard
    for(i=0;i<2;i++) {\
2193 085339a1 bellard
    a.q[0] = test_values[2*i][0];\
2194 085339a1 bellard
    a.q[1] = test_values[2*i][1];\
2195 085339a1 bellard
    asm volatile (#op " $" #ib ", %0" : "=x" (r.dq) : "0" (a.dq));\
2196 776f2227 bellard
    printf("%-9s: a=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\
2197 085339a1 bellard
           #op,\
2198 085339a1 bellard
           a.q[1], a.q[0],\
2199 085339a1 bellard
           ib,\
2200 085339a1 bellard
           r.q[1], r.q[0]);\
2201 085339a1 bellard
    }\
2202 085339a1 bellard
}
2203 085339a1 bellard
2204 085339a1 bellard
#define SHIFT_OP(op, ib)\
2205 085339a1 bellard
{\
2206 085339a1 bellard
    int i;\
2207 085339a1 bellard
    SHIFT_IM(op, ib);\
2208 085339a1 bellard
    for(i=0;i<2;i++) {\
2209 085339a1 bellard
    a.q[0] = test_values[2*i][0];\
2210 085339a1 bellard
    a.q[1] = test_values[2*i][1];\
2211 085339a1 bellard
    b.q[0] = ib;\
2212 085339a1 bellard
    b.q[1] = 0;\
2213 085339a1 bellard
    asm volatile (#op " %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\
2214 776f2227 bellard
    printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
2215 085339a1 bellard
           #op,\
2216 085339a1 bellard
           a.q[1], a.q[0],\
2217 085339a1 bellard
           b.q[1], b.q[0],\
2218 085339a1 bellard
           r.q[1], r.q[0]);\
2219 085339a1 bellard
    }\
2220 085339a1 bellard
}
2221 085339a1 bellard
2222 085339a1 bellard
#define MOVMSK(op)\
2223 085339a1 bellard
{\
2224 085339a1 bellard
    int i, reg;\
2225 085339a1 bellard
    for(i=0;i<2;i++) {\
2226 085339a1 bellard
    a.q[0] = test_values[2*i][0];\
2227 085339a1 bellard
    a.q[1] = test_values[2*i][1];\
2228 085339a1 bellard
    asm volatile (#op " %1, %0" : "=r" (reg) : "x" (a.dq));\
2229 776f2227 bellard
    printf("%-9s: a=" FMT64X "" FMT64X " r=%08x\n",\
2230 085339a1 bellard
           #op,\
2231 085339a1 bellard
           a.q[1], a.q[0],\
2232 085339a1 bellard
           reg);\
2233 085339a1 bellard
    }\
2234 085339a1 bellard
}
2235 085339a1 bellard
2236 085339a1 bellard
#define SSE_OPS(a) \
2237 085339a1 bellard
SSE_OP(a ## ps);\
2238 085339a1 bellard
SSE_OP(a ## ss);
2239 085339a1 bellard
2240 085339a1 bellard
#define SSE_OPD(a) \
2241 085339a1 bellard
SSE_OP(a ## pd);\
2242 085339a1 bellard
SSE_OP(a ## sd);
2243 085339a1 bellard
2244 085339a1 bellard
#define SSE_COMI(op, field)\
2245 085339a1 bellard
{\
2246 085339a1 bellard
    unsigned int eflags;\
2247 085339a1 bellard
    XMMReg a, b;\
2248 085339a1 bellard
    a.field[0] = a1;\
2249 085339a1 bellard
    b.field[0] = b1;\
2250 085339a1 bellard
    asm volatile (#op " %2, %1\n"\
2251 085339a1 bellard
        "pushf\n"\
2252 085339a1 bellard
        "pop %0\n"\
2253 085339a1 bellard
        : "=m" (eflags)\
2254 085339a1 bellard
        : "x" (a.dq), "x" (b.dq));\
2255 085339a1 bellard
    printf("%-9s: a=%f b=%f cc=%04x\n",\
2256 085339a1 bellard
           #op, a1, b1,\
2257 085339a1 bellard
           eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\
2258 085339a1 bellard
}
2259 085339a1 bellard
2260 085339a1 bellard
void test_sse_comi(double a1, double b1)
2261 085339a1 bellard
{
2262 085339a1 bellard
    SSE_COMI(ucomiss, s);
2263 085339a1 bellard
    SSE_COMI(ucomisd, d);
2264 085339a1 bellard
    SSE_COMI(comiss, s);
2265 085339a1 bellard
    SSE_COMI(comisd, d);
2266 085339a1 bellard
}
2267 085339a1 bellard
2268 085339a1 bellard
#define CVT_OP_XMM(op)\
2269 085339a1 bellard
{\
2270 085339a1 bellard
    asm volatile (#op " %1, %0" : "=x" (r.dq) : "x" (a.dq));\
2271 776f2227 bellard
    printf("%-9s: a=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\
2272 085339a1 bellard
           #op,\
2273 085339a1 bellard
           a.q[1], a.q[0],\
2274 085339a1 bellard
           r.q[1], r.q[0]);\
2275 085339a1 bellard
}
2276 085339a1 bellard
2277 80e7d521 bellard
/* Force %xmm0 usage to avoid the case where both register index are 0
2278 80e7d521 bellard
   to test intruction decoding more extensively */
2279 085339a1 bellard
#define CVT_OP_XMM2MMX(op)\
2280 085339a1 bellard
{\
2281 80e7d521 bellard
    asm volatile (#op " %1, %0" : "=y" (r.q[0]) : "x" (a.dq) \
2282 a5973fbf bellard
                  : "%xmm0"); \
2283 a5973fbf bellard
    asm volatile("emms\n"); \
2284 776f2227 bellard
    printf("%-9s: a=" FMT64X "" FMT64X " r=" FMT64X "\n",\
2285 085339a1 bellard
           #op,\
2286 085339a1 bellard
           a.q[1], a.q[0],\
2287 085339a1 bellard
           r.q[0]);\
2288 085339a1 bellard
}
2289 085339a1 bellard
2290 085339a1 bellard
#define CVT_OP_MMX2XMM(op)\
2291 085339a1 bellard
{\
2292 085339a1 bellard
    asm volatile (#op " %1, %0" : "=x" (r.dq) : "y" (a.q[0]));\
2293 a5973fbf bellard
    asm volatile("emms\n"); \
2294 776f2227 bellard
    printf("%-9s: a=" FMT64X " r=" FMT64X "" FMT64X "\n",\
2295 085339a1 bellard
           #op,\
2296 085339a1 bellard
           a.q[0],\
2297 085339a1 bellard
           r.q[1], r.q[0]);\
2298 085339a1 bellard
}
2299 085339a1 bellard
2300 085339a1 bellard
#define CVT_OP_REG2XMM(op)\
2301 085339a1 bellard
{\
2302 085339a1 bellard
    asm volatile (#op " %1, %0" : "=x" (r.dq) : "r" (a.l[0]));\
2303 776f2227 bellard
    printf("%-9s: a=%08x r=" FMT64X "" FMT64X "\n",\
2304 085339a1 bellard
           #op,\
2305 085339a1 bellard
           a.l[0],\
2306 085339a1 bellard
           r.q[1], r.q[0]);\
2307 085339a1 bellard
}
2308 085339a1 bellard
2309 085339a1 bellard
#define CVT_OP_XMM2REG(op)\
2310 085339a1 bellard
{\
2311 085339a1 bellard
    asm volatile (#op " %1, %0" : "=r" (r.l[0]) : "x" (a.dq));\
2312 776f2227 bellard
    printf("%-9s: a=" FMT64X "" FMT64X " r=%08x\n",\
2313 085339a1 bellard
           #op,\
2314 085339a1 bellard
           a.q[1], a.q[0],\
2315 085339a1 bellard
           r.l[0]);\
2316 085339a1 bellard
}
2317 085339a1 bellard
2318 a4682cc2 bellard
struct fpxstate {
2319 a4682cc2 bellard
    uint16_t fpuc;
2320 a4682cc2 bellard
    uint16_t fpus;
2321 a4682cc2 bellard
    uint16_t fptag;
2322 a4682cc2 bellard
    uint16_t fop;
2323 a4682cc2 bellard
    uint32_t fpuip;
2324 a4682cc2 bellard
    uint16_t cs_sel;
2325 a4682cc2 bellard
    uint16_t dummy0;
2326 a4682cc2 bellard
    uint32_t fpudp;
2327 a4682cc2 bellard
    uint16_t ds_sel;
2328 a4682cc2 bellard
    uint16_t dummy1;
2329 a4682cc2 bellard
    uint32_t mxcsr;
2330 a4682cc2 bellard
    uint32_t mxcsr_mask;
2331 a4682cc2 bellard
    uint8_t fpregs1[8 * 16];
2332 a4682cc2 bellard
    uint8_t xmm_regs[8 * 16];
2333 a4682cc2 bellard
    uint8_t dummy2[224];
2334 a4682cc2 bellard
};
2335 a4682cc2 bellard
2336 a4682cc2 bellard
static struct fpxstate fpx_state __attribute__((aligned(16)));
2337 a4682cc2 bellard
static struct fpxstate fpx_state2 __attribute__((aligned(16)));
2338 a4682cc2 bellard
2339 a4682cc2 bellard
void test_fxsave(void)
2340 a4682cc2 bellard
{
2341 a4682cc2 bellard
    struct fpxstate *fp = &fpx_state;
2342 a4682cc2 bellard
    struct fpxstate *fp2 = &fpx_state2;
2343 776f2227 bellard
    int i, nb_xmm;
2344 a4682cc2 bellard
    XMMReg a, b;
2345 a4682cc2 bellard
    a.q[0] = test_values[0][0];
2346 a4682cc2 bellard
    a.q[1] = test_values[0][1];
2347 a4682cc2 bellard
    b.q[0] = test_values[1][0];
2348 a4682cc2 bellard
    b.q[1] = test_values[1][1];
2349 a4682cc2 bellard
2350 a4682cc2 bellard
    asm("movdqa %2, %%xmm0\n"
2351 a4682cc2 bellard
        "movdqa %3, %%xmm7\n"
2352 776f2227 bellard
#if defined(__x86_64__)
2353 776f2227 bellard
        "movdqa %2, %%xmm15\n"
2354 776f2227 bellard
#endif
2355 a4682cc2 bellard
        " fld1\n"
2356 a4682cc2 bellard
        " fldpi\n"
2357 a4682cc2 bellard
        " fldln2\n"
2358 a4682cc2 bellard
        " fxsave %0\n"
2359 a4682cc2 bellard
        " fxrstor %0\n"
2360 a4682cc2 bellard
        " fxsave %1\n"
2361 a4682cc2 bellard
        " fninit\n"
2362 5fafdf24 ths
        : "=m" (*(uint32_t *)fp2), "=m" (*(uint32_t *)fp)
2363 a4682cc2 bellard
        : "m" (a), "m" (b));
2364 a4682cc2 bellard
    printf("fpuc=%04x\n", fp->fpuc);
2365 a4682cc2 bellard
    printf("fpus=%04x\n", fp->fpus);
2366 a4682cc2 bellard
    printf("fptag=%04x\n", fp->fptag);
2367 a4682cc2 bellard
    for(i = 0; i < 3; i++) {
2368 776f2227 bellard
        printf("ST%d: " FMT64X " %04x\n",
2369 5fafdf24 ths
               i,
2370 a4682cc2 bellard
               *(uint64_t *)&fp->fpregs1[i * 16],
2371 a4682cc2 bellard
               *(uint16_t *)&fp->fpregs1[i * 16 + 8]);
2372 a4682cc2 bellard
    }
2373 a4682cc2 bellard
    printf("mxcsr=%08x\n", fp->mxcsr & 0x1f80);
2374 776f2227 bellard
#if defined(__x86_64__)
2375 776f2227 bellard
    nb_xmm = 16;
2376 776f2227 bellard
#else
2377 776f2227 bellard
    nb_xmm = 8;
2378 776f2227 bellard
#endif
2379 776f2227 bellard
    for(i = 0; i < nb_xmm; i++) {
2380 776f2227 bellard
        printf("xmm%d: " FMT64X "" FMT64X "\n",
2381 5fafdf24 ths
               i,
2382 a4682cc2 bellard
               *(uint64_t *)&fp->xmm_regs[i * 16],
2383 a4682cc2 bellard
               *(uint64_t *)&fp->xmm_regs[i * 16 + 8]);
2384 a4682cc2 bellard
    }
2385 a4682cc2 bellard
}
2386 a4682cc2 bellard
2387 085339a1 bellard
void test_sse(void)
2388 085339a1 bellard
{
2389 085339a1 bellard
    XMMReg r, a, b;
2390 86bd2ca5 bellard
    int i;
2391 085339a1 bellard
2392 085339a1 bellard
    MMX_OP2(punpcklbw);
2393 085339a1 bellard
    MMX_OP2(punpcklwd);
2394 085339a1 bellard
    MMX_OP2(punpckldq);
2395 085339a1 bellard
    MMX_OP2(packsswb);
2396 085339a1 bellard
    MMX_OP2(pcmpgtb);
2397 085339a1 bellard
    MMX_OP2(pcmpgtw);
2398 085339a1 bellard
    MMX_OP2(pcmpgtd);
2399 085339a1 bellard
    MMX_OP2(packuswb);
2400 085339a1 bellard
    MMX_OP2(punpckhbw);
2401 085339a1 bellard
    MMX_OP2(punpckhwd);
2402 085339a1 bellard
    MMX_OP2(punpckhdq);
2403 085339a1 bellard
    MMX_OP2(packssdw);
2404 085339a1 bellard
    MMX_OP2(pcmpeqb);
2405 085339a1 bellard
    MMX_OP2(pcmpeqw);
2406 085339a1 bellard
    MMX_OP2(pcmpeqd);
2407 085339a1 bellard
2408 085339a1 bellard
    MMX_OP2(paddq);
2409 085339a1 bellard
    MMX_OP2(pmullw);
2410 085339a1 bellard
    MMX_OP2(psubusb);
2411 085339a1 bellard
    MMX_OP2(psubusw);
2412 085339a1 bellard
    MMX_OP2(pminub);
2413 085339a1 bellard
    MMX_OP2(pand);
2414 085339a1 bellard
    MMX_OP2(paddusb);
2415 085339a1 bellard
    MMX_OP2(paddusw);
2416 085339a1 bellard
    MMX_OP2(pmaxub);
2417 085339a1 bellard
    MMX_OP2(pandn);
2418 085339a1 bellard
2419 085339a1 bellard
    MMX_OP2(pmulhuw);
2420 085339a1 bellard
    MMX_OP2(pmulhw);
2421 3b46e624 ths
2422 085339a1 bellard
    MMX_OP2(psubsb);
2423 085339a1 bellard
    MMX_OP2(psubsw);
2424 085339a1 bellard
    MMX_OP2(pminsw);
2425 085339a1 bellard
    MMX_OP2(por);
2426 085339a1 bellard
    MMX_OP2(paddsb);
2427 085339a1 bellard
    MMX_OP2(paddsw);
2428 085339a1 bellard
    MMX_OP2(pmaxsw);
2429 085339a1 bellard
    MMX_OP2(pxor);
2430 085339a1 bellard
    MMX_OP2(pmuludq);
2431 085339a1 bellard
    MMX_OP2(pmaddwd);
2432 085339a1 bellard
    MMX_OP2(psadbw);
2433 085339a1 bellard
    MMX_OP2(psubb);
2434 085339a1 bellard
    MMX_OP2(psubw);
2435 085339a1 bellard
    MMX_OP2(psubd);
2436 085339a1 bellard
    MMX_OP2(psubq);
2437 085339a1 bellard
    MMX_OP2(paddb);
2438 085339a1 bellard
    MMX_OP2(paddw);
2439 085339a1 bellard
    MMX_OP2(paddd);
2440 085339a1 bellard
2441 085339a1 bellard
    MMX_OP2(pavgb);
2442 085339a1 bellard
    MMX_OP2(pavgw);
2443 085339a1 bellard
2444 085339a1 bellard
    asm volatile ("pinsrw $1, %1, %0" : "=y" (r.q[0]) : "r" (0x12345678));
2445 776f2227 bellard
    printf("%-9s: r=" FMT64X "\n", "pinsrw", r.q[0]);
2446 085339a1 bellard
2447 085339a1 bellard
    asm volatile ("pinsrw $5, %1, %0" : "=x" (r.dq) : "r" (0x12345678));
2448 776f2227 bellard
    printf("%-9s: r=" FMT64X "" FMT64X "\n", "pinsrw", r.q[1], r.q[0]);
2449 085339a1 bellard
2450 085339a1 bellard
    a.q[0] = test_values[0][0];
2451 085339a1 bellard
    a.q[1] = test_values[0][1];
2452 085339a1 bellard
    asm volatile ("pextrw $1, %1, %0" : "=r" (r.l[0]) : "y" (a.q[0]));
2453 085339a1 bellard
    printf("%-9s: r=%08x\n", "pextrw", r.l[0]);
2454 085339a1 bellard
2455 085339a1 bellard
    asm volatile ("pextrw $5, %1, %0" : "=r" (r.l[0]) : "x" (a.dq));
2456 085339a1 bellard
    printf("%-9s: r=%08x\n", "pextrw", r.l[0]);
2457 085339a1 bellard
2458 085339a1 bellard
    asm volatile ("pmovmskb %1, %0" : "=r" (r.l[0]) : "y" (a.q[0]));
2459 085339a1 bellard
    printf("%-9s: r=%08x\n", "pmovmskb", r.l[0]);
2460 3b46e624 ths
2461 085339a1 bellard
    asm volatile ("pmovmskb %1, %0" : "=r" (r.l[0]) : "x" (a.dq));
2462 085339a1 bellard
    printf("%-9s: r=%08x\n", "pmovmskb", r.l[0]);
2463 085339a1 bellard
2464 97ed14ae bellard
    {
2465 97ed14ae bellard
        r.q[0] = -1;
2466 97ed14ae bellard
        r.q[1] = -1;
2467 97ed14ae bellard
2468 97ed14ae bellard
        a.q[0] = test_values[0][0];
2469 97ed14ae bellard
        a.q[1] = test_values[0][1];
2470 97ed14ae bellard
        b.q[0] = test_values[1][0];
2471 97ed14ae bellard
        b.q[1] = test_values[1][1];
2472 5fafdf24 ths
        asm volatile("maskmovq %1, %0" :
2473 97ed14ae bellard
                     : "y" (a.q[0]), "y" (b.q[0]), "D" (&r)
2474 5fafdf24 ths
                     : "memory");
2475 5fafdf24 ths
        printf("%-9s: r=" FMT64X " a=" FMT64X " b=" FMT64X "\n",
2476 5fafdf24 ths
               "maskmov",
2477 5fafdf24 ths
               r.q[0],
2478 5fafdf24 ths
               a.q[0],
2479 97ed14ae bellard
               b.q[0]);
2480 5fafdf24 ths
        asm volatile("maskmovdqu %1, %0" :
2481 97ed14ae bellard
                     : "x" (a.dq), "x" (b.dq), "D" (&r)
2482 5fafdf24 ths
                     : "memory");
2483 5fafdf24 ths
        printf("%-9s: r=" FMT64X "" FMT64X " a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X "\n",
2484 5fafdf24 ths
               "maskmov",
2485 5fafdf24 ths
               r.q[1], r.q[0],
2486 5fafdf24 ths
               a.q[1], a.q[0],
2487 97ed14ae bellard
               b.q[1], b.q[0]);
2488 97ed14ae bellard
    }
2489 97ed14ae bellard
2490 085339a1 bellard
    asm volatile ("emms");
2491 085339a1 bellard
2492 085339a1 bellard
    SSE_OP2(punpcklqdq);
2493 085339a1 bellard
    SSE_OP2(punpckhqdq);
2494 085339a1 bellard
    SSE_OP2(andps);
2495 085339a1 bellard
    SSE_OP2(andpd);
2496 085339a1 bellard
    SSE_OP2(andnps);
2497 085339a1 bellard
    SSE_OP2(andnpd);
2498 085339a1 bellard
    SSE_OP2(orps);
2499 085339a1 bellard
    SSE_OP2(orpd);
2500 085339a1 bellard
    SSE_OP2(xorps);
2501 085339a1 bellard
    SSE_OP2(xorpd);
2502 085339a1 bellard
2503 085339a1 bellard
    SSE_OP2(unpcklps);
2504 085339a1 bellard
    SSE_OP2(unpcklpd);
2505 085339a1 bellard
    SSE_OP2(unpckhps);
2506 085339a1 bellard
    SSE_OP2(unpckhpd);
2507 085339a1 bellard
2508 97ed14ae bellard
    SHUF_OP(shufps, 0x78);
2509 97ed14ae bellard
    SHUF_OP(shufpd, 0x02);
2510 085339a1 bellard
2511 085339a1 bellard
    PSHUF_OP(pshufd, 0x78);
2512 085339a1 bellard
    PSHUF_OP(pshuflw, 0x78);
2513 085339a1 bellard
    PSHUF_OP(pshufhw, 0x78);
2514 085339a1 bellard
2515 085339a1 bellard
    SHIFT_OP(psrlw, 7);
2516 085339a1 bellard
    SHIFT_OP(psrlw, 16);
2517 085339a1 bellard
    SHIFT_OP(psraw, 7);
2518 085339a1 bellard
    SHIFT_OP(psraw, 16);
2519 085339a1 bellard
    SHIFT_OP(psllw, 7);
2520 085339a1 bellard
    SHIFT_OP(psllw, 16);
2521 085339a1 bellard
2522 085339a1 bellard
    SHIFT_OP(psrld, 7);
2523 085339a1 bellard
    SHIFT_OP(psrld, 32);
2524 085339a1 bellard
    SHIFT_OP(psrad, 7);
2525 085339a1 bellard
    SHIFT_OP(psrad, 32);
2526 085339a1 bellard
    SHIFT_OP(pslld, 7);
2527 085339a1 bellard
    SHIFT_OP(pslld, 32);
2528 085339a1 bellard
2529 085339a1 bellard
    SHIFT_OP(psrlq, 7);
2530 085339a1 bellard
    SHIFT_OP(psrlq, 32);
2531 085339a1 bellard
    SHIFT_OP(psllq, 7);
2532 085339a1 bellard
    SHIFT_OP(psllq, 32);
2533 085339a1 bellard
2534 085339a1 bellard
    SHIFT_IM(psrldq, 16);
2535 085339a1 bellard
    SHIFT_IM(psrldq, 7);
2536 085339a1 bellard
    SHIFT_IM(pslldq, 16);
2537 085339a1 bellard
    SHIFT_IM(pslldq, 7);
2538 085339a1 bellard
2539 085339a1 bellard
    MOVMSK(movmskps);
2540 085339a1 bellard
    MOVMSK(movmskpd);
2541 085339a1 bellard
2542 085339a1 bellard
    /* FPU specific ops */
2543 085339a1 bellard
2544 085339a1 bellard
    {
2545 085339a1 bellard
        uint32_t mxcsr;
2546 085339a1 bellard
        asm volatile("stmxcsr %0" : "=m" (mxcsr));
2547 085339a1 bellard
        printf("mxcsr=%08x\n", mxcsr & 0x1f80);
2548 085339a1 bellard
        asm volatile("ldmxcsr %0" : : "m" (mxcsr));
2549 085339a1 bellard
    }
2550 085339a1 bellard
2551 085339a1 bellard
    test_sse_comi(2, -1);
2552 085339a1 bellard
    test_sse_comi(2, 2);
2553 085339a1 bellard
    test_sse_comi(2, 3);
2554 86bd2ca5 bellard
    test_sse_comi(2, q_nan.d);
2555 86bd2ca5 bellard
    test_sse_comi(q_nan.d, -1);
2556 86bd2ca5 bellard
2557 86bd2ca5 bellard
    for(i = 0; i < 2; i++) {
2558 86bd2ca5 bellard
        a.s[0] = 2.7;
2559 86bd2ca5 bellard
        a.s[1] = 3.4;
2560 86bd2ca5 bellard
        a.s[2] = 4;
2561 86bd2ca5 bellard
        a.s[3] = -6.3;
2562 86bd2ca5 bellard
        b.s[0] = 45.7;
2563 86bd2ca5 bellard
        b.s[1] = 353.4;
2564 86bd2ca5 bellard
        b.s[2] = 4;
2565 86bd2ca5 bellard
        b.s[3] = 56.3;
2566 86bd2ca5 bellard
        if (i == 1) {
2567 86bd2ca5 bellard
            a.s[0] = q_nan.d;
2568 86bd2ca5 bellard
            b.s[3] = q_nan.d;
2569 86bd2ca5 bellard
        }
2570 86bd2ca5 bellard
2571 86bd2ca5 bellard
        SSE_OPS(add);
2572 86bd2ca5 bellard
        SSE_OPS(mul);
2573 86bd2ca5 bellard
        SSE_OPS(sub);
2574 86bd2ca5 bellard
        SSE_OPS(min);
2575 86bd2ca5 bellard
        SSE_OPS(div);
2576 86bd2ca5 bellard
        SSE_OPS(max);
2577 86bd2ca5 bellard
        SSE_OPS(sqrt);
2578 86bd2ca5 bellard
        SSE_OPS(cmpeq);
2579 86bd2ca5 bellard
        SSE_OPS(cmplt);
2580 86bd2ca5 bellard
        SSE_OPS(cmple);
2581 86bd2ca5 bellard
        SSE_OPS(cmpunord);
2582 86bd2ca5 bellard
        SSE_OPS(cmpneq);
2583 86bd2ca5 bellard
        SSE_OPS(cmpnlt);
2584 86bd2ca5 bellard
        SSE_OPS(cmpnle);
2585 86bd2ca5 bellard
        SSE_OPS(cmpord);
2586 3b46e624 ths
2587 3b46e624 ths
2588 86bd2ca5 bellard
        a.d[0] = 2.7;
2589 86bd2ca5 bellard
        a.d[1] = -3.4;
2590 86bd2ca5 bellard
        b.d[0] = 45.7;
2591 86bd2ca5 bellard
        b.d[1] = -53.4;
2592 86bd2ca5 bellard
        if (i == 1) {
2593 86bd2ca5 bellard
            a.d[0] = q_nan.d;
2594 86bd2ca5 bellard
            b.d[1] = q_nan.d;
2595 86bd2ca5 bellard
        }
2596 86bd2ca5 bellard
        SSE_OPD(add);
2597 86bd2ca5 bellard
        SSE_OPD(mul);
2598 86bd2ca5 bellard
        SSE_OPD(sub);
2599 86bd2ca5 bellard
        SSE_OPD(min);
2600 86bd2ca5 bellard
        SSE_OPD(div);
2601 86bd2ca5 bellard
        SSE_OPD(max);
2602 86bd2ca5 bellard
        SSE_OPD(sqrt);
2603 86bd2ca5 bellard
        SSE_OPD(cmpeq);
2604 86bd2ca5 bellard
        SSE_OPD(cmplt);
2605 86bd2ca5 bellard
        SSE_OPD(cmple);
2606 86bd2ca5 bellard
        SSE_OPD(cmpunord);
2607 86bd2ca5 bellard
        SSE_OPD(cmpneq);
2608 86bd2ca5 bellard
        SSE_OPD(cmpnlt);
2609 86bd2ca5 bellard
        SSE_OPD(cmpnle);
2610 86bd2ca5 bellard
        SSE_OPD(cmpord);
2611 86bd2ca5 bellard
    }
2612 085339a1 bellard
2613 085339a1 bellard
    /* float to float/int */
2614 085339a1 bellard
    a.s[0] = 2.7;
2615 085339a1 bellard
    a.s[1] = 3.4;
2616 085339a1 bellard
    a.s[2] = 4;
2617 085339a1 bellard
    a.s[3] = -6.3;
2618 085339a1 bellard
    CVT_OP_XMM(cvtps2pd);
2619 085339a1 bellard
    CVT_OP_XMM(cvtss2sd);
2620 085339a1 bellard
    CVT_OP_XMM2MMX(cvtps2pi);
2621 085339a1 bellard
    CVT_OP_XMM2MMX(cvttps2pi);
2622 085339a1 bellard
    CVT_OP_XMM2REG(cvtss2si);
2623 085339a1 bellard
    CVT_OP_XMM2REG(cvttss2si);
2624 085339a1 bellard
    CVT_OP_XMM(cvtps2dq);
2625 085339a1 bellard
    CVT_OP_XMM(cvttps2dq);
2626 085339a1 bellard
2627 085339a1 bellard
    a.d[0] = 2.6;
2628 085339a1 bellard
    a.d[1] = -3.4;
2629 085339a1 bellard
    CVT_OP_XMM(cvtpd2ps);
2630 085339a1 bellard
    CVT_OP_XMM(cvtsd2ss);
2631 085339a1 bellard
    CVT_OP_XMM2MMX(cvtpd2pi);
2632 085339a1 bellard
    CVT_OP_XMM2MMX(cvttpd2pi);
2633 085339a1 bellard
    CVT_OP_XMM2REG(cvtsd2si);
2634 085339a1 bellard
    CVT_OP_XMM2REG(cvttsd2si);
2635 085339a1 bellard
    CVT_OP_XMM(cvtpd2dq);
2636 085339a1 bellard
    CVT_OP_XMM(cvttpd2dq);
2637 085339a1 bellard
2638 80e7d521 bellard
    /* sse/mmx moves */
2639 80e7d521 bellard
    CVT_OP_XMM2MMX(movdq2q);
2640 80e7d521 bellard
    CVT_OP_MMX2XMM(movq2dq);
2641 80e7d521 bellard
2642 085339a1 bellard
    /* int to float */
2643 085339a1 bellard
    a.l[0] = -6;
2644 085339a1 bellard
    a.l[1] = 2;
2645 085339a1 bellard
    a.l[2] = 100;
2646 085339a1 bellard
    a.l[3] = -60000;
2647 085339a1 bellard
    CVT_OP_MMX2XMM(cvtpi2ps);
2648 085339a1 bellard
    CVT_OP_MMX2XMM(cvtpi2pd);
2649 085339a1 bellard
    CVT_OP_REG2XMM(cvtsi2ss);
2650 085339a1 bellard
    CVT_OP_REG2XMM(cvtsi2sd);
2651 085339a1 bellard
    CVT_OP_XMM(cvtdq2ps);
2652 085339a1 bellard
    CVT_OP_XMM(cvtdq2pd);
2653 085339a1 bellard
2654 085339a1 bellard
    /* XXX: test PNI insns */
2655 085339a1 bellard
#if 0
2656 085339a1 bellard
    SSE_OP2(movshdup);
2657 085339a1 bellard
#endif
2658 a4682cc2 bellard
    asm volatile ("emms");
2659 085339a1 bellard
}
2660 085339a1 bellard
2661 085339a1 bellard
#endif
2662 085339a1 bellard
2663 df517cec bellard
#define TEST_CONV_RAX(op)\
2664 df517cec bellard
{\
2665 df517cec bellard
    unsigned long a, r;\
2666 df517cec bellard
    a = i2l(0x8234a6f8);\
2667 df517cec bellard
    r = a;\
2668 df517cec bellard
    asm volatile(#op : "=a" (r) : "0" (r));\
2669 df517cec bellard
    printf("%-10s A=" FMTLX " R=" FMTLX "\n", #op, a, r);\
2670 df517cec bellard
}
2671 df517cec bellard
2672 df517cec bellard
#define TEST_CONV_RAX_RDX(op)\
2673 df517cec bellard
{\
2674 df517cec bellard
    unsigned long a, d, r, rh;                   \
2675 df517cec bellard
    a = i2l(0x8234a6f8);\
2676 df517cec bellard
    d = i2l(0x8345a1f2);\
2677 df517cec bellard
    r = a;\
2678 df517cec bellard
    rh = d;\
2679 df517cec bellard
    asm volatile(#op : "=a" (r), "=d" (rh) : "0" (r), "1" (rh));   \
2680 df517cec bellard
    printf("%-10s A=" FMTLX " R=" FMTLX ":" FMTLX "\n", #op, a, r, rh);  \
2681 df517cec bellard
}
2682 df517cec bellard
2683 df517cec bellard
void test_conv(void)
2684 df517cec bellard
{
2685 df517cec bellard
    TEST_CONV_RAX(cbw);
2686 df517cec bellard
    TEST_CONV_RAX(cwde);
2687 df517cec bellard
#if defined(__x86_64__)
2688 df517cec bellard
    TEST_CONV_RAX(cdqe);
2689 df517cec bellard
#endif
2690 df517cec bellard
2691 df517cec bellard
    TEST_CONV_RAX_RDX(cwd);
2692 df517cec bellard
    TEST_CONV_RAX_RDX(cdq);
2693 df517cec bellard
#if defined(__x86_64__)
2694 df517cec bellard
    TEST_CONV_RAX_RDX(cqo);
2695 df517cec bellard
#endif
2696 8aadfbf0 bellard
2697 8aadfbf0 bellard
    {
2698 8aadfbf0 bellard
        unsigned long a, r;
2699 8aadfbf0 bellard
        a = i2l(0x12345678);
2700 8aadfbf0 bellard
        asm volatile("bswapl %k0" : "=r" (r) : "0" (a));
2701 8aadfbf0 bellard
        printf("%-10s: A=" FMTLX " R=" FMTLX "\n", "bswapl", a, r);
2702 8aadfbf0 bellard
    }
2703 8aadfbf0 bellard
#if defined(__x86_64__)
2704 8aadfbf0 bellard
    {
2705 8aadfbf0 bellard
        unsigned long a, r;
2706 8aadfbf0 bellard
        a = i2l(0x12345678);
2707 8aadfbf0 bellard
        asm volatile("bswapq %0" : "=r" (r) : "0" (a));
2708 8aadfbf0 bellard
        printf("%-10s: A=" FMTLX " R=" FMTLX "\n", "bswapq", a, r);
2709 8aadfbf0 bellard
    }
2710 8aadfbf0 bellard
#endif
2711 df517cec bellard
}
2712 df517cec bellard
2713 776f2227 bellard
extern void *__start_initcall;
2714 776f2227 bellard
extern void *__stop_initcall;
2715 776f2227 bellard
2716 4d1135e4 bellard
2717 4d1135e4 bellard
int main(int argc, char **argv)
2718 4d1135e4 bellard
{
2719 4d1135e4 bellard
    void **ptr;
2720 4d1135e4 bellard
    void (*func)(void);
2721 4b74fe1f bellard
2722 776f2227 bellard
    ptr = &__start_initcall;
2723 776f2227 bellard
    while (ptr != &__stop_initcall) {
2724 4d1135e4 bellard
        func = *ptr++;
2725 4d1135e4 bellard
        func();
2726 4d1135e4 bellard
    }
2727 9d8e9c09 bellard
    test_bsx();
2728 d57c4e01 bellard
    test_mul();
2729 4d1135e4 bellard
    test_jcc();
2730 a5973fbf bellard
    test_loop();
2731 9d8e9c09 bellard
    test_floats();
2732 776f2227 bellard
#if !defined(__x86_64__)
2733 55480af8 bellard
    test_bcd();
2734 776f2227 bellard
#endif
2735 1a9353d2 bellard
    test_xchg();
2736 e1d4294a bellard
    test_string();
2737 e1d4294a bellard
    test_misc();
2738 6dbad63e bellard
    test_lea();
2739 776f2227 bellard
#ifdef TEST_SEGS
2740 6dbad63e bellard
    test_segs();
2741 e5918247 bellard
    test_code16();
2742 776f2227 bellard
#endif
2743 acae4681 bellard
#ifdef TEST_VM86
2744 3a27ad0b bellard
    test_vm86();
2745 acae4681 bellard
#endif
2746 776f2227 bellard
#if !defined(__x86_64__)
2747 8aadfbf0 bellard
    test_exceptions();
2748 3a27ad0b bellard
    test_self_modifying_code();
2749 3ff0631e bellard
    test_single_step();
2750 776f2227 bellard
#endif
2751 61a8c4ec bellard
    test_enter();
2752 df517cec bellard
    test_conv();
2753 085339a1 bellard
#ifdef TEST_SSE
2754 085339a1 bellard
    test_sse();
2755 a4682cc2 bellard
    test_fxsave();
2756 085339a1 bellard
#endif
2757 4d1135e4 bellard
    return 0;
2758 4d1135e4 bellard
}