Statistics
| Branch: | Revision:

root / tests / test-i386.c @ ed96ca35

History | View | Annotate | Download (66.5 kB)

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