Statistics
| Branch: | Revision:

root / tests / test-i386.c @ 3e11db9a

History | View | Annotate | Download (43.2 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 3a27ad0b bellard
#include <asm/vm86.h>
32 4d1135e4 bellard
33 03bfca94 bellard
#define TEST_CMOV  0
34 03bfca94 bellard
#define TEST_FCOMI 0
35 3ff0631e bellard
//#define LINUX_VM86_IOPL_FIX
36 791c2261 bellard
//#define TEST_P4_FLAGS
37 5dd9488c bellard
38 4d1135e4 bellard
#define xglue(x, y) x ## y
39 4d1135e4 bellard
#define glue(x, y) xglue(x, y)
40 4d1135e4 bellard
#define stringify(s)        tostring(s)
41 4d1135e4 bellard
#define tostring(s)        #s
42 4d1135e4 bellard
43 4d1135e4 bellard
#define CC_C           0x0001
44 4d1135e4 bellard
#define CC_P         0x0004
45 4d1135e4 bellard
#define CC_A        0x0010
46 4d1135e4 bellard
#define CC_Z        0x0040
47 4d1135e4 bellard
#define CC_S    0x0080
48 4d1135e4 bellard
#define CC_O    0x0800
49 4d1135e4 bellard
50 4d1135e4 bellard
#define __init_call        __attribute__ ((unused,__section__ (".initcall.init")))
51 4d1135e4 bellard
52 4d1135e4 bellard
static void *call_start __init_call = NULL;
53 4d1135e4 bellard
54 4b74fe1f bellard
#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
55 4b74fe1f bellard
56 4d1135e4 bellard
#define OP add
57 4d1135e4 bellard
#include "test-i386.h"
58 4d1135e4 bellard
59 4d1135e4 bellard
#define OP sub
60 4d1135e4 bellard
#include "test-i386.h"
61 4d1135e4 bellard
62 4d1135e4 bellard
#define OP xor
63 4d1135e4 bellard
#include "test-i386.h"
64 4d1135e4 bellard
65 4d1135e4 bellard
#define OP and
66 4d1135e4 bellard
#include "test-i386.h"
67 4d1135e4 bellard
68 4d1135e4 bellard
#define OP or
69 4d1135e4 bellard
#include "test-i386.h"
70 4d1135e4 bellard
71 4d1135e4 bellard
#define OP cmp
72 4d1135e4 bellard
#include "test-i386.h"
73 4d1135e4 bellard
74 4d1135e4 bellard
#define OP adc
75 4d1135e4 bellard
#define OP_CC
76 4d1135e4 bellard
#include "test-i386.h"
77 4d1135e4 bellard
78 4d1135e4 bellard
#define OP sbb
79 4d1135e4 bellard
#define OP_CC
80 4d1135e4 bellard
#include "test-i386.h"
81 4d1135e4 bellard
82 4d1135e4 bellard
#define OP inc
83 4d1135e4 bellard
#define OP_CC
84 4d1135e4 bellard
#define OP1
85 4d1135e4 bellard
#include "test-i386.h"
86 4d1135e4 bellard
87 4d1135e4 bellard
#define OP dec
88 4d1135e4 bellard
#define OP_CC
89 4d1135e4 bellard
#define OP1
90 4d1135e4 bellard
#include "test-i386.h"
91 4d1135e4 bellard
92 4d1135e4 bellard
#define OP neg
93 4d1135e4 bellard
#define OP_CC
94 4d1135e4 bellard
#define OP1
95 4d1135e4 bellard
#include "test-i386.h"
96 4d1135e4 bellard
97 4d1135e4 bellard
#define OP not
98 4d1135e4 bellard
#define OP_CC
99 4d1135e4 bellard
#define OP1
100 4d1135e4 bellard
#include "test-i386.h"
101 4d1135e4 bellard
102 4b74fe1f bellard
#undef CC_MASK
103 4b74fe1f bellard
#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)
104 4b74fe1f bellard
105 379ca80d bellard
#define OP shl
106 379ca80d bellard
#include "test-i386-shift.h"
107 379ca80d bellard
108 379ca80d bellard
#define OP shr
109 379ca80d bellard
#include "test-i386-shift.h"
110 379ca80d bellard
111 379ca80d bellard
#define OP sar
112 379ca80d bellard
#include "test-i386-shift.h"
113 379ca80d bellard
114 379ca80d bellard
#define OP rol
115 379ca80d bellard
#include "test-i386-shift.h"
116 379ca80d bellard
117 379ca80d bellard
#define OP ror
118 379ca80d bellard
#include "test-i386-shift.h"
119 379ca80d bellard
120 379ca80d bellard
#define OP rcr
121 379ca80d bellard
#define OP_CC
122 379ca80d bellard
#include "test-i386-shift.h"
123 379ca80d bellard
124 379ca80d bellard
#define OP rcl
125 379ca80d bellard
#define OP_CC
126 379ca80d bellard
#include "test-i386-shift.h"
127 379ca80d bellard
128 d57c4e01 bellard
#define OP shld
129 d57c4e01 bellard
#define OP_SHIFTD
130 d57c4e01 bellard
#define OP_NOBYTE
131 d57c4e01 bellard
#include "test-i386-shift.h"
132 d57c4e01 bellard
133 d57c4e01 bellard
#define OP shrd
134 d57c4e01 bellard
#define OP_SHIFTD
135 d57c4e01 bellard
#define OP_NOBYTE
136 d57c4e01 bellard
#include "test-i386-shift.h"
137 d57c4e01 bellard
138 d57c4e01 bellard
/* XXX: should be more precise ? */
139 d57c4e01 bellard
#undef CC_MASK
140 d57c4e01 bellard
#define CC_MASK (CC_C)
141 d57c4e01 bellard
142 d57c4e01 bellard
#define OP bt
143 d57c4e01 bellard
#define OP_NOBYTE
144 d57c4e01 bellard
#include "test-i386-shift.h"
145 d57c4e01 bellard
146 d57c4e01 bellard
#define OP bts
147 d57c4e01 bellard
#define OP_NOBYTE
148 d57c4e01 bellard
#include "test-i386-shift.h"
149 d57c4e01 bellard
150 d57c4e01 bellard
#define OP btr
151 d57c4e01 bellard
#define OP_NOBYTE
152 d57c4e01 bellard
#include "test-i386-shift.h"
153 d57c4e01 bellard
154 d57c4e01 bellard
#define OP btc
155 d57c4e01 bellard
#define OP_NOBYTE
156 d57c4e01 bellard
#include "test-i386-shift.h"
157 379ca80d bellard
158 4d1135e4 bellard
/* lea test (modrm support) */
159 4d1135e4 bellard
#define TEST_LEA(STR)\
160 4d1135e4 bellard
{\
161 4d1135e4 bellard
    asm("leal " STR ", %0"\
162 4d1135e4 bellard
        : "=r" (res)\
163 4d1135e4 bellard
        : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
164 4d1135e4 bellard
    printf("lea %s = %08x\n", STR, res);\
165 4d1135e4 bellard
}
166 4d1135e4 bellard
167 4d1135e4 bellard
#define TEST_LEA16(STR)\
168 4d1135e4 bellard
{\
169 4d1135e4 bellard
    asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\
170 4d1135e4 bellard
        : "=wq" (res)\
171 4d1135e4 bellard
        : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
172 4d1135e4 bellard
    printf("lea %s = %08x\n", STR, res);\
173 4d1135e4 bellard
}
174 4d1135e4 bellard
175 4d1135e4 bellard
176 4d1135e4 bellard
void test_lea(void)
177 4d1135e4 bellard
{
178 4d1135e4 bellard
    int eax, ebx, ecx, edx, esi, edi, res;
179 4d1135e4 bellard
    eax = 0x0001;
180 4d1135e4 bellard
    ebx = 0x0002;
181 4d1135e4 bellard
    ecx = 0x0004;
182 4d1135e4 bellard
    edx = 0x0008;
183 4d1135e4 bellard
    esi = 0x0010;
184 4d1135e4 bellard
    edi = 0x0020;
185 4d1135e4 bellard
186 4d1135e4 bellard
    TEST_LEA("0x4000");
187 4d1135e4 bellard
188 4d1135e4 bellard
    TEST_LEA("(%%eax)");
189 4d1135e4 bellard
    TEST_LEA("(%%ebx)");
190 4d1135e4 bellard
    TEST_LEA("(%%ecx)");
191 4d1135e4 bellard
    TEST_LEA("(%%edx)");
192 4d1135e4 bellard
    TEST_LEA("(%%esi)");
193 4d1135e4 bellard
    TEST_LEA("(%%edi)");
194 4d1135e4 bellard
195 4d1135e4 bellard
    TEST_LEA("0x40(%%eax)");
196 4d1135e4 bellard
    TEST_LEA("0x40(%%ebx)");
197 4d1135e4 bellard
    TEST_LEA("0x40(%%ecx)");
198 4d1135e4 bellard
    TEST_LEA("0x40(%%edx)");
199 4d1135e4 bellard
    TEST_LEA("0x40(%%esi)");
200 4d1135e4 bellard
    TEST_LEA("0x40(%%edi)");
201 4d1135e4 bellard
202 4d1135e4 bellard
    TEST_LEA("0x4000(%%eax)");
203 4d1135e4 bellard
    TEST_LEA("0x4000(%%ebx)");
204 4d1135e4 bellard
    TEST_LEA("0x4000(%%ecx)");
205 4d1135e4 bellard
    TEST_LEA("0x4000(%%edx)");
206 4d1135e4 bellard
    TEST_LEA("0x4000(%%esi)");
207 4d1135e4 bellard
    TEST_LEA("0x4000(%%edi)");
208 4d1135e4 bellard
209 4d1135e4 bellard
    TEST_LEA("(%%eax, %%ecx)");
210 4d1135e4 bellard
    TEST_LEA("(%%ebx, %%edx)");
211 4d1135e4 bellard
    TEST_LEA("(%%ecx, %%ecx)");
212 4d1135e4 bellard
    TEST_LEA("(%%edx, %%ecx)");
213 4d1135e4 bellard
    TEST_LEA("(%%esi, %%ecx)");
214 4d1135e4 bellard
    TEST_LEA("(%%edi, %%ecx)");
215 4d1135e4 bellard
216 4d1135e4 bellard
    TEST_LEA("0x40(%%eax, %%ecx)");
217 4d1135e4 bellard
    TEST_LEA("0x4000(%%ebx, %%edx)");
218 4d1135e4 bellard
219 4d1135e4 bellard
    TEST_LEA("(%%ecx, %%ecx, 2)");
220 4d1135e4 bellard
    TEST_LEA("(%%edx, %%ecx, 4)");
221 4d1135e4 bellard
    TEST_LEA("(%%esi, %%ecx, 8)");
222 4d1135e4 bellard
223 4d1135e4 bellard
    TEST_LEA("(,%%eax, 2)");
224 4d1135e4 bellard
    TEST_LEA("(,%%ebx, 4)");
225 4d1135e4 bellard
    TEST_LEA("(,%%ecx, 8)");
226 4d1135e4 bellard
227 4d1135e4 bellard
    TEST_LEA("0x40(,%%eax, 2)");
228 4d1135e4 bellard
    TEST_LEA("0x40(,%%ebx, 4)");
229 4d1135e4 bellard
    TEST_LEA("0x40(,%%ecx, 8)");
230 4d1135e4 bellard
231 4d1135e4 bellard
232 4d1135e4 bellard
    TEST_LEA("-10(%%ecx, %%ecx, 2)");
233 4d1135e4 bellard
    TEST_LEA("-10(%%edx, %%ecx, 4)");
234 4d1135e4 bellard
    TEST_LEA("-10(%%esi, %%ecx, 8)");
235 4d1135e4 bellard
236 4d1135e4 bellard
    TEST_LEA("0x4000(%%ecx, %%ecx, 2)");
237 4d1135e4 bellard
    TEST_LEA("0x4000(%%edx, %%ecx, 4)");
238 4d1135e4 bellard
    TEST_LEA("0x4000(%%esi, %%ecx, 8)");
239 4d1135e4 bellard
240 4d1135e4 bellard
    /* limited 16 bit addressing test */
241 4d1135e4 bellard
    TEST_LEA16("0x4000");
242 4d1135e4 bellard
    TEST_LEA16("(%%bx)");
243 4d1135e4 bellard
    TEST_LEA16("(%%si)");
244 4d1135e4 bellard
    TEST_LEA16("(%%di)");
245 4d1135e4 bellard
    TEST_LEA16("0x40(%%bx)");
246 4d1135e4 bellard
    TEST_LEA16("0x40(%%si)");
247 4d1135e4 bellard
    TEST_LEA16("0x40(%%di)");
248 4d1135e4 bellard
    TEST_LEA16("0x4000(%%bx)");
249 4d1135e4 bellard
    TEST_LEA16("0x4000(%%si)");
250 4d1135e4 bellard
    TEST_LEA16("(%%bx,%%si)");
251 4d1135e4 bellard
    TEST_LEA16("(%%bx,%%di)");
252 4d1135e4 bellard
    TEST_LEA16("0x40(%%bx,%%si)");
253 4d1135e4 bellard
    TEST_LEA16("0x40(%%bx,%%di)");
254 4d1135e4 bellard
    TEST_LEA16("0x4000(%%bx,%%si)");
255 4d1135e4 bellard
    TEST_LEA16("0x4000(%%bx,%%di)");
256 4d1135e4 bellard
}
257 4d1135e4 bellard
258 4d1135e4 bellard
#define TEST_JCC(JCC, v1, v2)\
259 4d1135e4 bellard
{\
260 5dd9488c bellard
    int res;\
261 4d1135e4 bellard
    asm("movl $1, %0\n\t"\
262 4d1135e4 bellard
        "cmpl %2, %1\n\t"\
263 5dd9488c bellard
        "j" JCC " 1f\n\t"\
264 4d1135e4 bellard
        "movl $0, %0\n\t"\
265 4d1135e4 bellard
        "1:\n\t"\
266 4d1135e4 bellard
        : "=r" (res)\
267 4d1135e4 bellard
        : "r" (v1), "r" (v2));\
268 5dd9488c bellard
    printf("%-10s %d\n", "j" JCC, res);\
269 5dd9488c bellard
\
270 5dd9488c bellard
    asm("movl $0, %0\n\t"\
271 5dd9488c bellard
        "cmpl %2, %1\n\t"\
272 5dd9488c bellard
        "set" JCC " %b0\n\t"\
273 5dd9488c bellard
        : "=r" (res)\
274 5dd9488c bellard
        : "r" (v1), "r" (v2));\
275 5dd9488c bellard
    printf("%-10s %d\n", "set" JCC, res);\
276 5dd9488c bellard
 if (TEST_CMOV) {\
277 5dd9488c bellard
    asm("movl $0x12345678, %0\n\t"\
278 5dd9488c bellard
        "cmpl %2, %1\n\t"\
279 5dd9488c bellard
        "cmov" JCC "l %3, %0\n\t"\
280 5dd9488c bellard
        : "=r" (res)\
281 5dd9488c bellard
        : "r" (v1), "r" (v2), "m" (1));\
282 5dd9488c bellard
        printf("%-10s R=0x%08x\n", "cmov" JCC "l", res);\
283 5dd9488c bellard
    asm("movl $0x12345678, %0\n\t"\
284 5dd9488c bellard
        "cmpl %2, %1\n\t"\
285 5dd9488c bellard
        "cmov" JCC "w %w3, %w0\n\t"\
286 5dd9488c bellard
        : "=r" (res)\
287 5dd9488c bellard
        : "r" (v1), "r" (v2), "r" (1));\
288 5dd9488c bellard
        printf("%-10s R=0x%08x\n", "cmov" JCC "w", res);\
289 5dd9488c bellard
 } \
290 4d1135e4 bellard
}
291 4d1135e4 bellard
292 4d1135e4 bellard
/* various jump tests */
293 4d1135e4 bellard
void test_jcc(void)
294 4d1135e4 bellard
{
295 5dd9488c bellard
    TEST_JCC("ne", 1, 1);
296 5dd9488c bellard
    TEST_JCC("ne", 1, 0);
297 4d1135e4 bellard
298 5dd9488c bellard
    TEST_JCC("e", 1, 1);
299 5dd9488c bellard
    TEST_JCC("e", 1, 0);
300 4d1135e4 bellard
301 5dd9488c bellard
    TEST_JCC("l", 1, 1);
302 5dd9488c bellard
    TEST_JCC("l", 1, 0);
303 5dd9488c bellard
    TEST_JCC("l", 1, -1);
304 4d1135e4 bellard
305 5dd9488c bellard
    TEST_JCC("le", 1, 1);
306 5dd9488c bellard
    TEST_JCC("le", 1, 0);
307 5dd9488c bellard
    TEST_JCC("le", 1, -1);
308 4d1135e4 bellard
309 5dd9488c bellard
    TEST_JCC("ge", 1, 1);
310 5dd9488c bellard
    TEST_JCC("ge", 1, 0);
311 5dd9488c bellard
    TEST_JCC("ge", -1, 1);
312 4d1135e4 bellard
313 5dd9488c bellard
    TEST_JCC("g", 1, 1);
314 5dd9488c bellard
    TEST_JCC("g", 1, 0);
315 5dd9488c bellard
    TEST_JCC("g", 1, -1);
316 4d1135e4 bellard
317 5dd9488c bellard
    TEST_JCC("b", 1, 1);
318 5dd9488c bellard
    TEST_JCC("b", 1, 0);
319 5dd9488c bellard
    TEST_JCC("b", 1, -1);
320 4d1135e4 bellard
321 5dd9488c bellard
    TEST_JCC("be", 1, 1);
322 5dd9488c bellard
    TEST_JCC("be", 1, 0);
323 5dd9488c bellard
    TEST_JCC("be", 1, -1);
324 4d1135e4 bellard
325 5dd9488c bellard
    TEST_JCC("ae", 1, 1);
326 5dd9488c bellard
    TEST_JCC("ae", 1, 0);
327 5dd9488c bellard
    TEST_JCC("ae", 1, -1);
328 4d1135e4 bellard
329 5dd9488c bellard
    TEST_JCC("a", 1, 1);
330 5dd9488c bellard
    TEST_JCC("a", 1, 0);
331 5dd9488c bellard
    TEST_JCC("a", 1, -1);
332 4d1135e4 bellard
333 4d1135e4 bellard
334 5dd9488c bellard
    TEST_JCC("p", 1, 1);
335 5dd9488c bellard
    TEST_JCC("p", 1, 0);
336 4d1135e4 bellard
337 5dd9488c bellard
    TEST_JCC("np", 1, 1);
338 5dd9488c bellard
    TEST_JCC("np", 1, 0);
339 4d1135e4 bellard
340 5dd9488c bellard
    TEST_JCC("o", 0x7fffffff, 0);
341 5dd9488c bellard
    TEST_JCC("o", 0x7fffffff, -1);
342 4d1135e4 bellard
343 5dd9488c bellard
    TEST_JCC("no", 0x7fffffff, 0);
344 5dd9488c bellard
    TEST_JCC("no", 0x7fffffff, -1);
345 4d1135e4 bellard
346 5dd9488c bellard
    TEST_JCC("s", 0, 1);
347 5dd9488c bellard
    TEST_JCC("s", 0, -1);
348 5dd9488c bellard
    TEST_JCC("s", 0, 0);
349 4d1135e4 bellard
350 5dd9488c bellard
    TEST_JCC("ns", 0, 1);
351 5dd9488c bellard
    TEST_JCC("ns", 0, -1);
352 5dd9488c bellard
    TEST_JCC("ns", 0, 0);
353 4d1135e4 bellard
}
354 4d1135e4 bellard
355 4b74fe1f bellard
#undef CC_MASK
356 791c2261 bellard
#ifdef TEST_P4_FLAGS
357 791c2261 bellard
#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
358 791c2261 bellard
#else
359 4b74fe1f bellard
#define CC_MASK (CC_O | CC_C)
360 791c2261 bellard
#endif
361 4b74fe1f bellard
362 4b74fe1f bellard
#define OP mul
363 4b74fe1f bellard
#include "test-i386-muldiv.h"
364 4b74fe1f bellard
365 4b74fe1f bellard
#define OP imul
366 4b74fe1f bellard
#include "test-i386-muldiv.h"
367 4b74fe1f bellard
368 4b74fe1f bellard
void test_imulw2(int op0, int op1) 
369 4b74fe1f bellard
{
370 4b74fe1f bellard
    int res, s1, s0, flags;
371 4b74fe1f bellard
    s0 = op0;
372 4b74fe1f bellard
    s1 = op1;
373 4b74fe1f bellard
    res = s0;
374 4b74fe1f bellard
    flags = 0;
375 4b74fe1f bellard
    asm ("push %4\n\t"
376 4b74fe1f bellard
         "popf\n\t"
377 4b74fe1f bellard
         "imulw %w2, %w0\n\t" 
378 4b74fe1f bellard
         "pushf\n\t"
379 4b74fe1f bellard
         "popl %1\n\t"
380 4b74fe1f bellard
         : "=q" (res), "=g" (flags)
381 4b74fe1f bellard
         : "q" (s1), "0" (res), "1" (flags));
382 4b74fe1f bellard
    printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
383 4b74fe1f bellard
           "imulw", s0, s1, res, flags & CC_MASK);
384 4b74fe1f bellard
}
385 4b74fe1f bellard
386 4b74fe1f bellard
void test_imull2(int op0, int op1) 
387 4b74fe1f bellard
{
388 4b74fe1f bellard
    int res, s1, s0, flags;
389 4b74fe1f bellard
    s0 = op0;
390 4b74fe1f bellard
    s1 = op1;
391 4b74fe1f bellard
    res = s0;
392 4b74fe1f bellard
    flags = 0;
393 4b74fe1f bellard
    asm ("push %4\n\t"
394 4b74fe1f bellard
         "popf\n\t"
395 4b74fe1f bellard
         "imull %2, %0\n\t" 
396 4b74fe1f bellard
         "pushf\n\t"
397 4b74fe1f bellard
         "popl %1\n\t"
398 4b74fe1f bellard
         : "=q" (res), "=g" (flags)
399 4b74fe1f bellard
         : "q" (s1), "0" (res), "1" (flags));
400 4b74fe1f bellard
    printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
401 4b74fe1f bellard
           "imull", s0, s1, res, flags & CC_MASK);
402 4b74fe1f bellard
}
403 4b74fe1f bellard
404 b5075d29 bellard
#define TEST_IMUL_IM(size, size1, op0, op1)\
405 b5075d29 bellard
{\
406 b5075d29 bellard
    int res, flags;\
407 b5075d29 bellard
    flags = 0;\
408 b5075d29 bellard
    res = 0;\
409 b5075d29 bellard
    asm ("push %3\n\t"\
410 b5075d29 bellard
         "popf\n\t"\
411 b5075d29 bellard
         "imul" size " $" #op0 ", %" size1 "2, %" size1 "0\n\t" \
412 b5075d29 bellard
         "pushf\n\t"\
413 b5075d29 bellard
         "popl %1\n\t"\
414 b5075d29 bellard
         : "=r" (res), "=g" (flags)\
415 b5075d29 bellard
         : "r" (op1), "1" (flags), "0" (res));\
416 b5075d29 bellard
    printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",\
417 b5075d29 bellard
           "imul" size, op0, op1, res, flags & CC_MASK);\
418 b5075d29 bellard
}
419 b5075d29 bellard
420 b5075d29 bellard
421 791c2261 bellard
#undef CC_MASK
422 791c2261 bellard
#define CC_MASK (0)
423 791c2261 bellard
424 791c2261 bellard
#define OP div
425 791c2261 bellard
#include "test-i386-muldiv.h"
426 791c2261 bellard
427 791c2261 bellard
#define OP idiv
428 791c2261 bellard
#include "test-i386-muldiv.h"
429 791c2261 bellard
430 4b74fe1f bellard
void test_mul(void)
431 4b74fe1f bellard
{
432 4b74fe1f bellard
    test_imulb(0x1234561d, 4);
433 4b74fe1f bellard
    test_imulb(3, -4);
434 4b74fe1f bellard
    test_imulb(0x80, 0x80);
435 4b74fe1f bellard
    test_imulb(0x10, 0x10);
436 4b74fe1f bellard
437 4b74fe1f bellard
    test_imulw(0, 0x1234001d, 45);
438 4b74fe1f bellard
    test_imulw(0, 23, -45);
439 4b74fe1f bellard
    test_imulw(0, 0x8000, 0x8000);
440 4b74fe1f bellard
    test_imulw(0, 0x100, 0x100);
441 4b74fe1f bellard
442 4b74fe1f bellard
    test_imull(0, 0x1234001d, 45);
443 4b74fe1f bellard
    test_imull(0, 23, -45);
444 4b74fe1f bellard
    test_imull(0, 0x80000000, 0x80000000);
445 4b74fe1f bellard
    test_imull(0, 0x10000, 0x10000);
446 4b74fe1f bellard
447 4b74fe1f bellard
    test_mulb(0x1234561d, 4);
448 4b74fe1f bellard
    test_mulb(3, -4);
449 4b74fe1f bellard
    test_mulb(0x80, 0x80);
450 4b74fe1f bellard
    test_mulb(0x10, 0x10);
451 4b74fe1f bellard
452 4b74fe1f bellard
    test_mulw(0, 0x1234001d, 45);
453 4b74fe1f bellard
    test_mulw(0, 23, -45);
454 4b74fe1f bellard
    test_mulw(0, 0x8000, 0x8000);
455 4b74fe1f bellard
    test_mulw(0, 0x100, 0x100);
456 4b74fe1f bellard
457 4b74fe1f bellard
    test_mull(0, 0x1234001d, 45);
458 4b74fe1f bellard
    test_mull(0, 23, -45);
459 4b74fe1f bellard
    test_mull(0, 0x80000000, 0x80000000);
460 4b74fe1f bellard
    test_mull(0, 0x10000, 0x10000);
461 4b74fe1f bellard
462 4b74fe1f bellard
    test_imulw2(0x1234001d, 45);
463 4b74fe1f bellard
    test_imulw2(23, -45);
464 4b74fe1f bellard
    test_imulw2(0x8000, 0x8000);
465 4b74fe1f bellard
    test_imulw2(0x100, 0x100);
466 4b74fe1f bellard
467 4b74fe1f bellard
    test_imull2(0x1234001d, 45);
468 4b74fe1f bellard
    test_imull2(23, -45);
469 4b74fe1f bellard
    test_imull2(0x80000000, 0x80000000);
470 4b74fe1f bellard
    test_imull2(0x10000, 0x10000);
471 4b74fe1f bellard
472 b5075d29 bellard
    TEST_IMUL_IM("w", "w", 45, 0x1234);
473 b5075d29 bellard
    TEST_IMUL_IM("w", "w", -45, 23);
474 b5075d29 bellard
    TEST_IMUL_IM("w", "w", 0x8000, 0x80000000);
475 b5075d29 bellard
    TEST_IMUL_IM("w", "w", 0x7fff, 0x1000);
476 b5075d29 bellard
477 b5075d29 bellard
    TEST_IMUL_IM("l", "", 45, 0x1234);
478 b5075d29 bellard
    TEST_IMUL_IM("l", "", -45, 23);
479 b5075d29 bellard
    TEST_IMUL_IM("l", "", 0x8000, 0x80000000);
480 b5075d29 bellard
    TEST_IMUL_IM("l", "", 0x7fff, 0x1000);
481 b5075d29 bellard
482 4b74fe1f bellard
    test_idivb(0x12341678, 0x127e);
483 4b74fe1f bellard
    test_idivb(0x43210123, -5);
484 4b74fe1f bellard
    test_idivb(0x12340004, -1);
485 4b74fe1f bellard
486 4b74fe1f bellard
    test_idivw(0, 0x12345678, 12347);
487 4b74fe1f bellard
    test_idivw(0, -23223, -45);
488 4b74fe1f bellard
    test_idivw(0, 0x12348000, -1);
489 4b74fe1f bellard
    test_idivw(0x12343, 0x12345678, 0x81238567);
490 4b74fe1f bellard
491 4b74fe1f bellard
    test_idivl(0, 0x12345678, 12347);
492 4b74fe1f bellard
    test_idivl(0, -233223, -45);
493 4b74fe1f bellard
    test_idivl(0, 0x80000000, -1);
494 4b74fe1f bellard
    test_idivl(0x12343, 0x12345678, 0x81234567);
495 4b74fe1f bellard
496 4b74fe1f bellard
    test_divb(0x12341678, 0x127e);
497 4b74fe1f bellard
    test_divb(0x43210123, -5);
498 4b74fe1f bellard
    test_divb(0x12340004, -1);
499 4b74fe1f bellard
500 4b74fe1f bellard
    test_divw(0, 0x12345678, 12347);
501 4b74fe1f bellard
    test_divw(0, -23223, -45);
502 4b74fe1f bellard
    test_divw(0, 0x12348000, -1);
503 4b74fe1f bellard
    test_divw(0x12343, 0x12345678, 0x81238567);
504 4b74fe1f bellard
505 4b74fe1f bellard
    test_divl(0, 0x12345678, 12347);
506 4b74fe1f bellard
    test_divl(0, -233223, -45);
507 4b74fe1f bellard
    test_divl(0, 0x80000000, -1);
508 4b74fe1f bellard
    test_divl(0x12343, 0x12345678, 0x81234567);
509 4b74fe1f bellard
}
510 4b74fe1f bellard
511 9d8e9c09 bellard
#define TEST_BSX(op, size, op0)\
512 9d8e9c09 bellard
{\
513 9d8e9c09 bellard
    int res, val, resz;\
514 9d8e9c09 bellard
    val = op0;\
515 7f5e1452 bellard
    asm("xorl %1, %1\n"\
516 7f5e1452 bellard
        "movl $0x12345678, %0\n"\
517 7f5e1452 bellard
        #op " %" size "2, %" size "0 ; setz %b1" \
518 9d8e9c09 bellard
        : "=r" (res), "=q" (resz)\
519 9d8e9c09 bellard
        : "g" (val));\
520 7f5e1452 bellard
    printf("%-10s A=%08x R=%08x %d\n", #op, val, res, resz);\
521 9d8e9c09 bellard
}
522 9d8e9c09 bellard
523 9d8e9c09 bellard
void test_bsx(void)
524 9d8e9c09 bellard
{
525 9d8e9c09 bellard
    TEST_BSX(bsrw, "w", 0);
526 9d8e9c09 bellard
    TEST_BSX(bsrw, "w", 0x12340128);
527 9d8e9c09 bellard
    TEST_BSX(bsrl, "", 0);
528 9d8e9c09 bellard
    TEST_BSX(bsrl, "", 0x00340128);
529 9d8e9c09 bellard
    TEST_BSX(bsfw, "w", 0);
530 9d8e9c09 bellard
    TEST_BSX(bsfw, "w", 0x12340128);
531 9d8e9c09 bellard
    TEST_BSX(bsfl, "", 0);
532 9d8e9c09 bellard
    TEST_BSX(bsfl, "", 0x00340128);
533 9d8e9c09 bellard
}
534 9d8e9c09 bellard
535 55480af8 bellard
/**********************************************/
536 55480af8 bellard
537 9d8e9c09 bellard
void test_fops(double a, double b)
538 9d8e9c09 bellard
{
539 9d8e9c09 bellard
    printf("a=%f b=%f a+b=%f\n", a, b, a + b);
540 9d8e9c09 bellard
    printf("a=%f b=%f a-b=%f\n", a, b, a - b);
541 9d8e9c09 bellard
    printf("a=%f b=%f a*b=%f\n", a, b, a * b);
542 9d8e9c09 bellard
    printf("a=%f b=%f a/b=%f\n", a, b, a / b);
543 9d8e9c09 bellard
    printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b));
544 9d8e9c09 bellard
    printf("a=%f sqrt(a)=%f\n", a, sqrt(a));
545 9d8e9c09 bellard
    printf("a=%f sin(a)=%f\n", a, sin(a));
546 9d8e9c09 bellard
    printf("a=%f cos(a)=%f\n", a, cos(a));
547 9d8e9c09 bellard
    printf("a=%f tan(a)=%f\n", a, tan(a));
548 9d8e9c09 bellard
    printf("a=%f log(a)=%f\n", a, log(a));
549 9d8e9c09 bellard
    printf("a=%f exp(a)=%f\n", a, exp(a));
550 9d8e9c09 bellard
    printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
551 9d8e9c09 bellard
    /* just to test some op combining */
552 9d8e9c09 bellard
    printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a)));
553 9d8e9c09 bellard
    printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a)));
554 9d8e9c09 bellard
    printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));
555 9d8e9c09 bellard
556 9d8e9c09 bellard
}
557 9d8e9c09 bellard
558 9d8e9c09 bellard
void test_fcmp(double a, double b)
559 9d8e9c09 bellard
{
560 9d8e9c09 bellard
    printf("(%f<%f)=%d\n",
561 9d8e9c09 bellard
           a, b, a < b);
562 9d8e9c09 bellard
    printf("(%f<=%f)=%d\n",
563 9d8e9c09 bellard
           a, b, a <= b);
564 9d8e9c09 bellard
    printf("(%f==%f)=%d\n",
565 9d8e9c09 bellard
           a, b, a == b);
566 9d8e9c09 bellard
    printf("(%f>%f)=%d\n",
567 9d8e9c09 bellard
           a, b, a > b);
568 9d8e9c09 bellard
    printf("(%f<=%f)=%d\n",
569 9d8e9c09 bellard
           a, b, a >= b);
570 03bfca94 bellard
    if (TEST_FCOMI) {
571 03bfca94 bellard
        unsigned int eflags;
572 03bfca94 bellard
        /* test f(u)comi instruction */
573 03bfca94 bellard
        asm("fcomi %2, %1\n"
574 03bfca94 bellard
            "pushf\n"
575 03bfca94 bellard
            "pop %0\n"
576 03bfca94 bellard
            : "=r" (eflags)
577 03bfca94 bellard
            : "t" (a), "u" (b));
578 03bfca94 bellard
        printf("fcomi(%f %f)=%08x\n", a, b, eflags & (CC_Z | CC_P | CC_C));
579 03bfca94 bellard
    }
580 9d8e9c09 bellard
}
581 9d8e9c09 bellard
582 9d8e9c09 bellard
void test_fcvt(double a)
583 9d8e9c09 bellard
{
584 9d8e9c09 bellard
    float fa;
585 9d8e9c09 bellard
    long double la;
586 ea768640 bellard
    int16_t fpuc;
587 ea768640 bellard
    int i;
588 ea768640 bellard
    int64_t lla;
589 ea768640 bellard
    int ia;
590 ea768640 bellard
    int16_t wa;
591 ea768640 bellard
    double ra;
592 9d8e9c09 bellard
593 9d8e9c09 bellard
    fa = a;
594 9d8e9c09 bellard
    la = a;
595 9d8e9c09 bellard
    printf("(float)%f = %f\n", a, fa);
596 9d8e9c09 bellard
    printf("(long double)%f = %Lf\n", a, la);
597 c5e9815d bellard
    printf("a=%016Lx\n", *(long long *)&a);
598 c5e9815d bellard
    printf("la=%016Lx %04x\n", *(long long *)&la, 
599 c5e9815d bellard
           *(unsigned short *)((char *)(&la) + 8));
600 ea768640 bellard
601 ea768640 bellard
    /* test all roundings */
602 ea768640 bellard
    asm volatile ("fstcw %0" : "=m" (fpuc));
603 ea768640 bellard
    for(i=0;i<4;i++) {
604 ea768640 bellard
        asm volatile ("fldcw %0" : : "m" ((fpuc & ~0x0c00) | (i << 10)));
605 ea768640 bellard
        asm volatile ("fist %0" : "=m" (wa) : "t" (a));
606 ea768640 bellard
        asm volatile ("fistl %0" : "=m" (ia) : "t" (a));
607 ea768640 bellard
        asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st");
608 ea768640 bellard
        asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a));
609 ea768640 bellard
        asm volatile ("fldcw %0" : : "m" (fpuc));
610 ea768640 bellard
        printf("(short)a = %d\n", wa);
611 ea768640 bellard
        printf("(int)a = %d\n", ia);
612 ea768640 bellard
        printf("(int64_t)a = %Ld\n", lla);
613 ea768640 bellard
        printf("rint(a) = %f\n", ra);
614 ea768640 bellard
    }
615 9d8e9c09 bellard
}
616 9d8e9c09 bellard
617 9d8e9c09 bellard
#define TEST(N) \
618 9d8e9c09 bellard
    asm("fld" #N : "=t" (a)); \
619 9d8e9c09 bellard
    printf("fld" #N "= %f\n", a);
620 9d8e9c09 bellard
621 9d8e9c09 bellard
void test_fconst(void)
622 9d8e9c09 bellard
{
623 9d8e9c09 bellard
    double a;
624 9d8e9c09 bellard
    TEST(1);
625 9d8e9c09 bellard
    TEST(l2t);
626 9d8e9c09 bellard
    TEST(l2e);
627 9d8e9c09 bellard
    TEST(pi);
628 9d8e9c09 bellard
    TEST(lg2);
629 9d8e9c09 bellard
    TEST(ln2);
630 9d8e9c09 bellard
    TEST(z);
631 9d8e9c09 bellard
}
632 9d8e9c09 bellard
633 c5e9815d bellard
void test_fbcd(double a)
634 c5e9815d bellard
{
635 c5e9815d bellard
    unsigned short bcd[5];
636 c5e9815d bellard
    double b;
637 c5e9815d bellard
638 c5e9815d bellard
    asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st");
639 c5e9815d bellard
    asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
640 c5e9815d bellard
    printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n", 
641 c5e9815d bellard
           a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);
642 c5e9815d bellard
}
643 c5e9815d bellard
644 6b2b6112 bellard
#define TEST_ENV(env, save, restore)\
645 03bfca94 bellard
{\
646 03bfca94 bellard
    memset((env), 0xaa, sizeof(*(env)));\
647 6b2b6112 bellard
    for(i=0;i<5;i++)\
648 6b2b6112 bellard
        asm volatile ("fldl %0" : : "m" (dtab[i]));\
649 6b2b6112 bellard
    asm(save " %0\n" : : "m" (*(env)));\
650 6b2b6112 bellard
    asm(restore " %0\n": : "m" (*(env)));\
651 6b2b6112 bellard
    for(i=0;i<5;i++)\
652 6b2b6112 bellard
        asm volatile ("fstpl %0" : "=m" (rtab[i]));\
653 6b2b6112 bellard
    for(i=0;i<5;i++)\
654 6b2b6112 bellard
        printf("res[%d]=%f\n", i, rtab[i]);\
655 03bfca94 bellard
    printf("fpuc=%04x fpus=%04x fptag=%04x\n",\
656 03bfca94 bellard
           (env)->fpuc,\
657 03bfca94 bellard
           (env)->fpus & 0xff00,\
658 03bfca94 bellard
           (env)->fptag);\
659 03bfca94 bellard
}
660 03bfca94 bellard
661 03bfca94 bellard
void test_fenv(void)
662 03bfca94 bellard
{
663 03bfca94 bellard
    struct __attribute__((packed)) {
664 03bfca94 bellard
        uint16_t fpuc;
665 03bfca94 bellard
        uint16_t dummy1;
666 03bfca94 bellard
        uint16_t fpus;
667 03bfca94 bellard
        uint16_t dummy2;
668 03bfca94 bellard
        uint16_t fptag;
669 03bfca94 bellard
        uint16_t dummy3;
670 03bfca94 bellard
        uint32_t ignored[4];
671 03bfca94 bellard
        long double fpregs[8];
672 03bfca94 bellard
    } float_env32;
673 03bfca94 bellard
    struct __attribute__((packed)) {
674 03bfca94 bellard
        uint16_t fpuc;
675 03bfca94 bellard
        uint16_t fpus;
676 03bfca94 bellard
        uint16_t fptag;
677 03bfca94 bellard
        uint16_t ignored[4];
678 03bfca94 bellard
        long double fpregs[8];
679 03bfca94 bellard
    } float_env16;
680 6b2b6112 bellard
    double dtab[8];
681 6b2b6112 bellard
    double rtab[8];
682 6b2b6112 bellard
    int i;
683 6b2b6112 bellard
684 6b2b6112 bellard
    for(i=0;i<8;i++)
685 6b2b6112 bellard
        dtab[i] = i + 1;
686 03bfca94 bellard
687 6b2b6112 bellard
    TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv");
688 6b2b6112 bellard
    TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor");
689 6b2b6112 bellard
    TEST_ENV(&float_env32, "fnstenv", "fldenv");
690 6b2b6112 bellard
    TEST_ENV(&float_env32, "fnsave", "frstor");
691 665656a9 bellard
692 665656a9 bellard
    /* test for ffree */
693 665656a9 bellard
    for(i=0;i<5;i++)
694 665656a9 bellard
        asm volatile ("fldl %0" : : "m" (dtab[i]));
695 665656a9 bellard
    asm volatile("ffree %st(2)");
696 665656a9 bellard
    asm volatile ("fnstenv %0\n" : : "m" (float_env32));
697 665656a9 bellard
    asm volatile ("fninit");
698 665656a9 bellard
    printf("fptag=%04x\n", float_env32.fptag);
699 03bfca94 bellard
}
700 03bfca94 bellard
701 75175024 bellard
702 75175024 bellard
#define TEST_FCMOV(a, b, eflags, CC)\
703 75175024 bellard
{\
704 75175024 bellard
    double res;\
705 75175024 bellard
    asm("push %3\n"\
706 75175024 bellard
        "popf\n"\
707 75175024 bellard
        "fcmov" CC " %2, %0\n"\
708 75175024 bellard
        : "=t" (res)\
709 75175024 bellard
        : "0" (a), "u" (b), "g" (eflags));\
710 75175024 bellard
    printf("fcmov%s eflags=0x%04x-> %f\n", \
711 75175024 bellard
           CC, eflags, res);\
712 75175024 bellard
}
713 75175024 bellard
714 75175024 bellard
void test_fcmov(void)
715 75175024 bellard
{
716 75175024 bellard
    double a, b;
717 75175024 bellard
    int eflags, i;
718 75175024 bellard
719 75175024 bellard
    a = 1.0;
720 75175024 bellard
    b = 2.0;
721 75175024 bellard
    for(i = 0; i < 4; i++) {
722 75175024 bellard
        eflags = 0;
723 75175024 bellard
        if (i & 1)
724 75175024 bellard
            eflags |= CC_C;
725 75175024 bellard
        if (i & 2)
726 75175024 bellard
            eflags |= CC_Z;
727 75175024 bellard
        TEST_FCMOV(a, b, eflags, "b");
728 75175024 bellard
        TEST_FCMOV(a, b, eflags, "e");
729 75175024 bellard
        TEST_FCMOV(a, b, eflags, "be");
730 75175024 bellard
        TEST_FCMOV(a, b, eflags, "nb");
731 75175024 bellard
        TEST_FCMOV(a, b, eflags, "ne");
732 75175024 bellard
        TEST_FCMOV(a, b, eflags, "nbe");
733 75175024 bellard
    }
734 75175024 bellard
    TEST_FCMOV(a, b, 0, "u");
735 9cdf757f bellard
    TEST_FCMOV(a, b, CC_P, "u");
736 9cdf757f bellard
    TEST_FCMOV(a, b, 0, "nu");
737 75175024 bellard
    TEST_FCMOV(a, b, CC_P, "nu");
738 75175024 bellard
}
739 75175024 bellard
740 9d8e9c09 bellard
void test_floats(void)
741 9d8e9c09 bellard
{
742 9d8e9c09 bellard
    test_fops(2, 3);
743 9d8e9c09 bellard
    test_fops(1.4, -5);
744 9d8e9c09 bellard
    test_fcmp(2, -1);
745 9d8e9c09 bellard
    test_fcmp(2, 2);
746 9d8e9c09 bellard
    test_fcmp(2, 3);
747 ea768640 bellard
    test_fcvt(0.5);
748 ea768640 bellard
    test_fcvt(-0.5);
749 9d8e9c09 bellard
    test_fcvt(1.0/7.0);
750 9d8e9c09 bellard
    test_fcvt(-1.0/9.0);
751 ea768640 bellard
    test_fcvt(32768);
752 ea768640 bellard
    test_fcvt(-1e20);
753 9d8e9c09 bellard
    test_fconst();
754 c5e9815d bellard
    test_fbcd(1234567890123456);
755 c5e9815d bellard
    test_fbcd(-123451234567890);
756 03bfca94 bellard
    test_fenv();
757 75175024 bellard
    if (TEST_CMOV) {
758 75175024 bellard
        test_fcmov();
759 75175024 bellard
    }
760 9d8e9c09 bellard
}
761 4b74fe1f bellard
762 55480af8 bellard
/**********************************************/
763 55480af8 bellard
764 55480af8 bellard
#define TEST_BCD(op, op0, cc_in, cc_mask)\
765 55480af8 bellard
{\
766 55480af8 bellard
    int res, flags;\
767 55480af8 bellard
    res = op0;\
768 55480af8 bellard
    flags = cc_in;\
769 55480af8 bellard
    asm ("push %3\n\t"\
770 55480af8 bellard
         "popf\n\t"\
771 55480af8 bellard
         #op "\n\t"\
772 55480af8 bellard
         "pushf\n\t"\
773 55480af8 bellard
         "popl %1\n\t"\
774 55480af8 bellard
        : "=a" (res), "=g" (flags)\
775 55480af8 bellard
        : "0" (res), "1" (flags));\
776 55480af8 bellard
    printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\
777 55480af8 bellard
           #op, op0, res, cc_in, flags & cc_mask);\
778 55480af8 bellard
}
779 55480af8 bellard
780 55480af8 bellard
void test_bcd(void)
781 55480af8 bellard
{
782 55480af8 bellard
    TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
783 55480af8 bellard
    TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
784 55480af8 bellard
    TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
785 55480af8 bellard
    TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
786 55480af8 bellard
    TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
787 55480af8 bellard
    TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
788 55480af8 bellard
    TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
789 55480af8 bellard
    TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
790 55480af8 bellard
    TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
791 55480af8 bellard
    TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
792 55480af8 bellard
    TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
793 55480af8 bellard
    TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
794 55480af8 bellard
    TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
795 55480af8 bellard
796 55480af8 bellard
    TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
797 55480af8 bellard
    TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
798 55480af8 bellard
    TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
799 55480af8 bellard
    TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
800 55480af8 bellard
    TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
801 55480af8 bellard
    TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
802 55480af8 bellard
    TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
803 55480af8 bellard
    TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
804 55480af8 bellard
    TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
805 55480af8 bellard
    TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
806 55480af8 bellard
    TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
807 55480af8 bellard
    TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
808 55480af8 bellard
    TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
809 55480af8 bellard
810 55480af8 bellard
    TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A));
811 55480af8 bellard
    TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A));
812 55480af8 bellard
    TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A));
813 55480af8 bellard
    TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A));
814 55480af8 bellard
    TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A));
815 55480af8 bellard
    TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A));
816 55480af8 bellard
    TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A));
817 55480af8 bellard
    TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A));
818 55480af8 bellard
    
819 55480af8 bellard
    TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A));
820 55480af8 bellard
    TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A));
821 55480af8 bellard
    TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A));
822 55480af8 bellard
    TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A));
823 55480af8 bellard
    TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A));
824 55480af8 bellard
    TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A));
825 55480af8 bellard
    TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A));
826 55480af8 bellard
    TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A));
827 55480af8 bellard
828 55480af8 bellard
    TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
829 55480af8 bellard
    TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
830 55480af8 bellard
}
831 55480af8 bellard
832 e5918247 bellard
#define TEST_XCHG(op, size, opconst)\
833 e5918247 bellard
{\
834 e5918247 bellard
    int op0, op1;\
835 e5918247 bellard
    op0 = 0x12345678;\
836 e5918247 bellard
    op1 = 0xfbca7654;\
837 e5918247 bellard
    asm(#op " %" size "0, %" size "1" \
838 e5918247 bellard
        : "=q" (op0), opconst (op1) \
839 e5918247 bellard
        : "0" (op0), "1" (op1));\
840 e5918247 bellard
    printf("%-10s A=%08x B=%08x\n",\
841 e5918247 bellard
           #op, op0, op1);\
842 e5918247 bellard
}
843 e5918247 bellard
844 e5918247 bellard
#define TEST_CMPXCHG(op, size, opconst, eax)\
845 e5918247 bellard
{\
846 e5918247 bellard
    int op0, op1;\
847 e5918247 bellard
    op0 = 0x12345678;\
848 e5918247 bellard
    op1 = 0xfbca7654;\
849 e5918247 bellard
    asm(#op " %" size "0, %" size "1" \
850 e5918247 bellard
        : "=q" (op0), opconst (op1) \
851 e5918247 bellard
        : "0" (op0), "1" (op1), "a" (eax));\
852 e5918247 bellard
    printf("%-10s EAX=%08x A=%08x C=%08x\n",\
853 e5918247 bellard
           #op, eax, op0, op1);\
854 e5918247 bellard
}
855 e5918247 bellard
856 e5918247 bellard
void test_xchg(void)
857 e5918247 bellard
{
858 e5918247 bellard
    TEST_XCHG(xchgl, "", "=q");
859 e5918247 bellard
    TEST_XCHG(xchgw, "w", "=q");
860 e5918247 bellard
    TEST_XCHG(xchgb, "b", "=q");
861 e5918247 bellard
862 e5918247 bellard
    TEST_XCHG(xchgl, "", "=m");
863 e5918247 bellard
    TEST_XCHG(xchgw, "w", "=m");
864 e5918247 bellard
    TEST_XCHG(xchgb, "b", "=m");
865 e5918247 bellard
866 e5918247 bellard
    TEST_XCHG(xaddl, "", "=q");
867 e5918247 bellard
    TEST_XCHG(xaddw, "w", "=q");
868 e5918247 bellard
    TEST_XCHG(xaddb, "b", "=q");
869 e5918247 bellard
870 d575b78a bellard
    {
871 d575b78a bellard
        int res;
872 d575b78a bellard
        res = 0x12345678;
873 d575b78a bellard
        asm("xaddl %1, %0" : "=r" (res) : "0" (res));
874 d575b78a bellard
        printf("xaddl same res=%08x\n", res);
875 d575b78a bellard
    }
876 d575b78a bellard
877 e5918247 bellard
    TEST_XCHG(xaddl, "", "=m");
878 e5918247 bellard
    TEST_XCHG(xaddw, "w", "=m");
879 e5918247 bellard
    TEST_XCHG(xaddb, "b", "=m");
880 e5918247 bellard
881 e5918247 bellard
    TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfbca7654);
882 e5918247 bellard
    TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfbca7654);
883 e5918247 bellard
    TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfbca7654);
884 e5918247 bellard
885 e5918247 bellard
    TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfffefdfc);
886 e5918247 bellard
    TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfffefdfc);
887 e5918247 bellard
    TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfffefdfc);
888 e5918247 bellard
889 e5918247 bellard
    TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfbca7654);
890 e5918247 bellard
    TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfbca7654);
891 e5918247 bellard
    TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfbca7654);
892 e5918247 bellard
893 e5918247 bellard
    TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfffefdfc);
894 e5918247 bellard
    TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfffefdfc);
895 e5918247 bellard
    TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfffefdfc);
896 d575b78a bellard
897 d575b78a bellard
    {
898 d575b78a bellard
        uint64_t op0, op1, op2;
899 d575b78a bellard
        int i, eflags;
900 d575b78a bellard
901 d575b78a bellard
        for(i = 0; i < 2; i++) {
902 d575b78a bellard
            op0 = 0x123456789abcd;
903 d575b78a bellard
            if (i == 0)
904 d575b78a bellard
                op1 = 0xfbca765423456;
905 d575b78a bellard
            else
906 d575b78a bellard
                op1 = op0;
907 d575b78a bellard
            op2 = 0x6532432432434;
908 d575b78a bellard
            asm("cmpxchg8b %1\n" 
909 d575b78a bellard
                "pushf\n"
910 d575b78a bellard
                "popl %2\n"
911 d575b78a bellard
                : "=A" (op0), "=m" (op1), "=g" (eflags)
912 d575b78a bellard
                : "0" (op0), "m" (op1), "b" ((int)op2), "c" ((int)(op2 >> 32)));
913 d575b78a bellard
            printf("cmpxchg8b: op0=%016llx op1=%016llx CC=%02x\n", 
914 d575b78a bellard
                    op0, op1, eflags & CC_Z);
915 d575b78a bellard
        }
916 d575b78a bellard
    }
917 e5918247 bellard
}
918 e5918247 bellard
919 6dbad63e bellard
/**********************************************/
920 6dbad63e bellard
/* segmentation tests */
921 6dbad63e bellard
922 6dbad63e bellard
#include <asm/ldt.h>
923 6dbad63e bellard
#include <linux/unistd.h>
924 73bdea19 bellard
#include <linux/version.h>
925 6dbad63e bellard
926 6dbad63e bellard
_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
927 6dbad63e bellard
928 73bdea19 bellard
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
929 73bdea19 bellard
#define modify_ldt_ldt_s user_desc
930 73bdea19 bellard
#endif
931 73bdea19 bellard
932 6dbad63e bellard
uint8_t seg_data1[4096];
933 6dbad63e bellard
uint8_t seg_data2[4096];
934 6dbad63e bellard
935 e5918247 bellard
#define MK_SEL(n) (((n) << 3) | 7)
936 6dbad63e bellard
937 288426fe bellard
#define TEST_LR(op, size, seg, mask)\
938 288426fe bellard
{\
939 288426fe bellard
    int res, res2;\
940 288426fe bellard
    res = 0x12345678;\
941 288426fe bellard
    asm (op " %" size "2, %" size "0\n" \
942 288426fe bellard
         "movl $0, %1\n"\
943 288426fe bellard
         "jnz 1f\n"\
944 288426fe bellard
         "movl $1, %1\n"\
945 288426fe bellard
         "1:\n"\
946 288426fe bellard
         : "=r" (res), "=r" (res2) : "m" (seg), "0" (res));\
947 288426fe bellard
    printf(op ": Z=%d %08x\n", res2, res & ~(mask));\
948 288426fe bellard
}
949 288426fe bellard
950 6dbad63e bellard
/* NOTE: we use Linux modify_ldt syscall */
951 6dbad63e bellard
void test_segs(void)
952 6dbad63e bellard
{
953 6dbad63e bellard
    struct modify_ldt_ldt_s ldt;
954 6dbad63e bellard
    long long ldt_table[3];
955 04369ff2 bellard
    int res, res2;
956 6dbad63e bellard
    char tmp;
957 e1d4294a bellard
    struct {
958 e1d4294a bellard
        uint32_t offset;
959 e1d4294a bellard
        uint16_t seg;
960 e1d4294a bellard
    } __attribute__((packed)) segoff;
961 6dbad63e bellard
962 6dbad63e bellard
    ldt.entry_number = 1;
963 6dbad63e bellard
    ldt.base_addr = (unsigned long)&seg_data1;
964 6dbad63e bellard
    ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
965 6dbad63e bellard
    ldt.seg_32bit = 1;
966 6dbad63e bellard
    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
967 6dbad63e bellard
    ldt.read_exec_only = 0;
968 6dbad63e bellard
    ldt.limit_in_pages = 1;
969 6dbad63e bellard
    ldt.seg_not_present = 0;
970 6dbad63e bellard
    ldt.useable = 1;
971 6dbad63e bellard
    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
972 6dbad63e bellard
973 6dbad63e bellard
    ldt.entry_number = 2;
974 6dbad63e bellard
    ldt.base_addr = (unsigned long)&seg_data2;
975 6dbad63e bellard
    ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12;
976 6dbad63e bellard
    ldt.seg_32bit = 1;
977 6dbad63e bellard
    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
978 6dbad63e bellard
    ldt.read_exec_only = 0;
979 6dbad63e bellard
    ldt.limit_in_pages = 1;
980 6dbad63e bellard
    ldt.seg_not_present = 0;
981 6dbad63e bellard
    ldt.useable = 1;
982 6dbad63e bellard
    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
983 6dbad63e bellard
984 6dbad63e bellard
    modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */
985 04369ff2 bellard
#if 0
986 04369ff2 bellard
    {
987 04369ff2 bellard
        int i;
988 04369ff2 bellard
        for(i=0;i<3;i++)
989 04369ff2 bellard
            printf("%d: %016Lx\n", i, ldt_table[i]);
990 04369ff2 bellard
    }
991 04369ff2 bellard
#endif
992 6dbad63e bellard
    /* do some tests with fs or gs */
993 6dbad63e bellard
    asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
994 6dbad63e bellard
995 6dbad63e bellard
    seg_data1[1] = 0xaa;
996 6dbad63e bellard
    seg_data2[1] = 0x55;
997 6dbad63e bellard
998 6dbad63e bellard
    asm volatile ("fs movzbl 0x1, %0" : "=r" (res));
999 6dbad63e bellard
    printf("FS[1] = %02x\n", res);
1000 6dbad63e bellard
1001 070893f4 bellard
    asm volatile ("pushl %%gs\n"
1002 070893f4 bellard
                  "movl %1, %%gs\n"
1003 070893f4 bellard
                  "gs movzbl 0x1, %0\n"
1004 070893f4 bellard
                  "popl %%gs\n"
1005 070893f4 bellard
                  : "=r" (res)
1006 070893f4 bellard
                  : "r" (MK_SEL(2)));
1007 6dbad63e bellard
    printf("GS[1] = %02x\n", res);
1008 6dbad63e bellard
1009 6dbad63e bellard
    /* tests with ds/ss (implicit segment case) */
1010 6dbad63e bellard
    tmp = 0xa5;
1011 6dbad63e bellard
    asm volatile ("pushl %%ebp\n\t"
1012 6dbad63e bellard
                  "pushl %%ds\n\t"
1013 6dbad63e bellard
                  "movl %2, %%ds\n\t"
1014 6dbad63e bellard
                  "movl %3, %%ebp\n\t"
1015 6dbad63e bellard
                  "movzbl 0x1, %0\n\t"
1016 6dbad63e bellard
                  "movzbl (%%ebp), %1\n\t"
1017 6dbad63e bellard
                  "popl %%ds\n\t"
1018 6dbad63e bellard
                  "popl %%ebp\n\t"
1019 6dbad63e bellard
                  : "=r" (res), "=r" (res2)
1020 6dbad63e bellard
                  : "r" (MK_SEL(1)), "r" (&tmp));
1021 6dbad63e bellard
    printf("DS[1] = %02x\n", res);
1022 6dbad63e bellard
    printf("SS[tmp] = %02x\n", res2);
1023 e1d4294a bellard
1024 e1d4294a bellard
    segoff.seg = MK_SEL(2);
1025 e1d4294a bellard
    segoff.offset = 0xabcdef12;
1026 e1d4294a bellard
    asm volatile("lfs %2, %0\n\t" 
1027 e1d4294a bellard
                 "movl %%fs, %1\n\t"
1028 e1d4294a bellard
                 : "=r" (res), "=g" (res2) 
1029 e1d4294a bellard
                 : "m" (segoff));
1030 e1d4294a bellard
    printf("FS:reg = %04x:%08x\n", res2, res);
1031 288426fe bellard
1032 288426fe bellard
    TEST_LR("larw", "w", MK_SEL(2), 0x0100);
1033 288426fe bellard
    TEST_LR("larl", "", MK_SEL(2), 0x0100);
1034 288426fe bellard
    TEST_LR("lslw", "w", MK_SEL(2), 0);
1035 288426fe bellard
    TEST_LR("lsll", "", MK_SEL(2), 0);
1036 288426fe bellard
1037 288426fe bellard
    TEST_LR("larw", "w", 0xfff8, 0);
1038 288426fe bellard
    TEST_LR("larl", "", 0xfff8, 0);
1039 288426fe bellard
    TEST_LR("lslw", "w", 0xfff8, 0);
1040 288426fe bellard
    TEST_LR("lsll", "", 0xfff8, 0);
1041 6dbad63e bellard
}
1042 55480af8 bellard
1043 e5918247 bellard
/* 16 bit code test */
1044 e5918247 bellard
extern char code16_start, code16_end;
1045 e5918247 bellard
extern char code16_func1;
1046 e5918247 bellard
extern char code16_func2;
1047 e5918247 bellard
extern char code16_func3;
1048 a300e691 bellard
1049 e5918247 bellard
void test_code16(void)
1050 1a9353d2 bellard
{
1051 e5918247 bellard
    struct modify_ldt_ldt_s ldt;
1052 e5918247 bellard
    int res, res2;
1053 a300e691 bellard
1054 e5918247 bellard
    /* build a code segment */
1055 e5918247 bellard
    ldt.entry_number = 1;
1056 e5918247 bellard
    ldt.base_addr = (unsigned long)&code16_start;
1057 e5918247 bellard
    ldt.limit = &code16_end - &code16_start;
1058 e5918247 bellard
    ldt.seg_32bit = 0;
1059 e5918247 bellard
    ldt.contents = MODIFY_LDT_CONTENTS_CODE;
1060 e5918247 bellard
    ldt.read_exec_only = 0;
1061 e5918247 bellard
    ldt.limit_in_pages = 0;
1062 e5918247 bellard
    ldt.seg_not_present = 0;
1063 e5918247 bellard
    ldt.useable = 1;
1064 e5918247 bellard
    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
1065 a300e691 bellard
1066 e5918247 bellard
    /* call the first function */
1067 e5918247 bellard
    asm volatile ("lcall %1, %2" 
1068 e5918247 bellard
                  : "=a" (res)
1069 e5918247 bellard
                  : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc");
1070 e5918247 bellard
    printf("func1() = 0x%08x\n", res);
1071 e5918247 bellard
    asm volatile ("lcall %2, %3" 
1072 e5918247 bellard
                  : "=a" (res), "=c" (res2)
1073 e5918247 bellard
                  : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc");
1074 e5918247 bellard
    printf("func2() = 0x%08x spdec=%d\n", res, res2);
1075 e5918247 bellard
    asm volatile ("lcall %1, %2" 
1076 e5918247 bellard
                  : "=a" (res)
1077 e5918247 bellard
                  : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc");
1078 e5918247 bellard
    printf("func3() = 0x%08x\n", res);
1079 1a9353d2 bellard
}
1080 1a9353d2 bellard
1081 dd3587f3 bellard
extern char func_lret32;
1082 dd3587f3 bellard
extern char func_iret32;
1083 dd3587f3 bellard
1084 e1d4294a bellard
void test_misc(void)
1085 e1d4294a bellard
{
1086 e1d4294a bellard
    char table[256];
1087 e1d4294a bellard
    int res, i;
1088 e1d4294a bellard
1089 e1d4294a bellard
    for(i=0;i<256;i++) table[i] = 256 - i;
1090 e1d4294a bellard
    res = 0x12345678;
1091 e1d4294a bellard
    asm ("xlat" : "=a" (res) : "b" (table), "0" (res));
1092 e1d4294a bellard
    printf("xlat: EAX=%08x\n", res);
1093 dd3587f3 bellard
1094 dd3587f3 bellard
    asm volatile ("pushl %%cs ; call %1" 
1095 dd3587f3 bellard
                  : "=a" (res)
1096 dd3587f3 bellard
                  : "m" (func_lret32): "memory", "cc");
1097 dd3587f3 bellard
    printf("func_lret32=%x\n", res);
1098 dd3587f3 bellard
1099 dd3587f3 bellard
    asm volatile ("pushfl ; pushl %%cs ; call %1" 
1100 dd3587f3 bellard
                  : "=a" (res)
1101 dd3587f3 bellard
                  : "m" (func_iret32): "memory", "cc");
1102 dd3587f3 bellard
    printf("func_iret32=%x\n", res);
1103 dd3587f3 bellard
1104 dd3587f3 bellard
    /* specific popl test */
1105 dd3587f3 bellard
    asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popl (%%esp) ; popl %0"
1106 dd3587f3 bellard
                  : "=g" (res));
1107 dd3587f3 bellard
    printf("popl esp=%x\n", res);
1108 b2b5fb22 bellard
1109 b2b5fb22 bellard
    /* specific popw test */
1110 b2b5fb22 bellard
    asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popw (%%esp) ; addl $2, %%esp ; popl %0"
1111 b2b5fb22 bellard
                  : "=g" (res));
1112 b2b5fb22 bellard
    printf("popw esp=%x\n", res);
1113 e1d4294a bellard
}
1114 e1d4294a bellard
1115 e1d4294a bellard
uint8_t str_buffer[4096];
1116 e1d4294a bellard
1117 e1d4294a bellard
#define TEST_STRING1(OP, size, DF, REP)\
1118 e1d4294a bellard
{\
1119 e1d4294a bellard
    int esi, edi, eax, ecx, eflags;\
1120 e1d4294a bellard
\
1121 e1d4294a bellard
    esi = (long)(str_buffer + sizeof(str_buffer) / 2);\
1122 e1d4294a bellard
    edi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\
1123 e1d4294a bellard
    eax = 0x12345678;\
1124 e1d4294a bellard
    ecx = 17;\
1125 e1d4294a bellard
\
1126 e1d4294a bellard
    asm volatile ("pushl $0\n\t"\
1127 e1d4294a bellard
                  "popf\n\t"\
1128 e1d4294a bellard
                  DF "\n\t"\
1129 e1d4294a bellard
                  REP #OP size "\n\t"\
1130 e1d4294a bellard
                  "cld\n\t"\
1131 e1d4294a bellard
                  "pushf\n\t"\
1132 e1d4294a bellard
                  "popl %4\n\t"\
1133 e1d4294a bellard
                  : "=S" (esi), "=D" (edi), "=a" (eax), "=c" (ecx), "=g" (eflags)\
1134 e1d4294a bellard
                  : "0" (esi), "1" (edi), "2" (eax), "3" (ecx));\
1135 e1d4294a bellard
    printf("%-10s ESI=%08x EDI=%08x EAX=%08x ECX=%08x EFL=%04x\n",\
1136 e1d4294a bellard
           REP #OP size, esi, edi, eax, ecx,\
1137 e1d4294a bellard
           eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\
1138 e1d4294a bellard
}
1139 e1d4294a bellard
1140 e1d4294a bellard
#define TEST_STRING(OP, REP)\
1141 e1d4294a bellard
    TEST_STRING1(OP, "b", "", REP);\
1142 e1d4294a bellard
    TEST_STRING1(OP, "w", "", REP);\
1143 e1d4294a bellard
    TEST_STRING1(OP, "l", "", REP);\
1144 e1d4294a bellard
    TEST_STRING1(OP, "b", "std", REP);\
1145 e1d4294a bellard
    TEST_STRING1(OP, "w", "std", REP);\
1146 e1d4294a bellard
    TEST_STRING1(OP, "l", "std", REP)
1147 e1d4294a bellard
1148 e1d4294a bellard
void test_string(void)
1149 e1d4294a bellard
{
1150 e1d4294a bellard
    int i;
1151 e1d4294a bellard
    for(i = 0;i < sizeof(str_buffer); i++)
1152 e1d4294a bellard
        str_buffer[i] = i + 0x56;
1153 e1d4294a bellard
   TEST_STRING(stos, "");
1154 e1d4294a bellard
   TEST_STRING(stos, "rep ");
1155 e1d4294a bellard
   TEST_STRING(lods, ""); /* to verify stos */
1156 e1d4294a bellard
   TEST_STRING(lods, "rep "); 
1157 e1d4294a bellard
   TEST_STRING(movs, "");
1158 e1d4294a bellard
   TEST_STRING(movs, "rep ");
1159 e1d4294a bellard
   TEST_STRING(lods, ""); /* to verify stos */
1160 e1d4294a bellard
1161 e1d4294a bellard
   /* XXX: better tests */
1162 e1d4294a bellard
   TEST_STRING(scas, "");
1163 e1d4294a bellard
   TEST_STRING(scas, "repz ");
1164 e1d4294a bellard
   TEST_STRING(scas, "repnz ");
1165 e1d4294a bellard
   TEST_STRING(cmps, "");
1166 e1d4294a bellard
   TEST_STRING(cmps, "repz ");
1167 e1d4294a bellard
   TEST_STRING(cmps, "repnz ");
1168 e1d4294a bellard
}
1169 e5918247 bellard
1170 3a27ad0b bellard
/* VM86 test */
1171 3a27ad0b bellard
1172 3a27ad0b bellard
static inline void set_bit(uint8_t *a, unsigned int bit)
1173 3a27ad0b bellard
{
1174 3a27ad0b bellard
    a[bit / 8] |= (1 << (bit % 8));
1175 3a27ad0b bellard
}
1176 3a27ad0b bellard
1177 3a27ad0b bellard
static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
1178 3a27ad0b bellard
{
1179 3a27ad0b bellard
    return (uint8_t *)((seg << 4) + (reg & 0xffff));
1180 3a27ad0b bellard
}
1181 3a27ad0b bellard
1182 3a27ad0b bellard
static inline void pushw(struct vm86_regs *r, int val)
1183 3a27ad0b bellard
{
1184 3a27ad0b bellard
    r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
1185 3a27ad0b bellard
    *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
1186 3a27ad0b bellard
}
1187 3a27ad0b bellard
1188 3a27ad0b bellard
#undef __syscall_return
1189 3a27ad0b bellard
#define __syscall_return(type, res) \
1190 3a27ad0b bellard
do { \
1191 3a27ad0b bellard
        return (type) (res); \
1192 3a27ad0b bellard
} while (0)
1193 3a27ad0b bellard
1194 3a27ad0b bellard
_syscall2(int, vm86, int, func, struct vm86plus_struct *, v86)
1195 3a27ad0b bellard
1196 3a27ad0b bellard
extern char vm86_code_start;
1197 3a27ad0b bellard
extern char vm86_code_end;
1198 3a27ad0b bellard
1199 3a27ad0b bellard
#define VM86_CODE_CS 0x100
1200 3a27ad0b bellard
#define VM86_CODE_IP 0x100
1201 3a27ad0b bellard
1202 3a27ad0b bellard
void test_vm86(void)
1203 3a27ad0b bellard
{
1204 3a27ad0b bellard
    struct vm86plus_struct ctx;
1205 3a27ad0b bellard
    struct vm86_regs *r;
1206 3a27ad0b bellard
    uint8_t *vm86_mem;
1207 3a27ad0b bellard
    int seg, ret;
1208 3a27ad0b bellard
1209 3a27ad0b bellard
    vm86_mem = mmap((void *)0x00000000, 0x110000, 
1210 3a27ad0b bellard
                    PROT_WRITE | PROT_READ | PROT_EXEC, 
1211 3a27ad0b bellard
                    MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
1212 3a27ad0b bellard
    if (vm86_mem == MAP_FAILED) {
1213 3a27ad0b bellard
        printf("ERROR: could not map vm86 memory");
1214 3a27ad0b bellard
        return;
1215 3a27ad0b bellard
    }
1216 3a27ad0b bellard
    memset(&ctx, 0, sizeof(ctx));
1217 3a27ad0b bellard
1218 3a27ad0b bellard
    /* init basic registers */
1219 3a27ad0b bellard
    r = &ctx.regs;
1220 3a27ad0b bellard
    r->eip = VM86_CODE_IP;
1221 3a27ad0b bellard
    r->esp = 0xfffe;
1222 3a27ad0b bellard
    seg = VM86_CODE_CS;
1223 3a27ad0b bellard
    r->cs = seg;
1224 3a27ad0b bellard
    r->ss = seg;
1225 3a27ad0b bellard
    r->ds = seg;
1226 3a27ad0b bellard
    r->es = seg;
1227 3a27ad0b bellard
    r->fs = seg;
1228 3a27ad0b bellard
    r->gs = seg;
1229 3a27ad0b bellard
    r->eflags = VIF_MASK;
1230 3a27ad0b bellard
1231 3a27ad0b bellard
    /* move code to proper address. We use the same layout as a .com
1232 3a27ad0b bellard
       dos program. */
1233 3a27ad0b bellard
    memcpy(vm86_mem + (VM86_CODE_CS << 4) + VM86_CODE_IP, 
1234 3a27ad0b bellard
           &vm86_code_start, &vm86_code_end - &vm86_code_start);
1235 3a27ad0b bellard
1236 3a27ad0b bellard
    /* mark int 0x21 as being emulated */
1237 3a27ad0b bellard
    set_bit((uint8_t *)&ctx.int_revectored, 0x21);
1238 3a27ad0b bellard
1239 3a27ad0b bellard
    for(;;) {
1240 3a27ad0b bellard
        ret = vm86(VM86_ENTER, &ctx);
1241 3a27ad0b bellard
        switch(VM86_TYPE(ret)) {
1242 3a27ad0b bellard
        case VM86_INTx:
1243 3a27ad0b bellard
            {
1244 3ff0631e bellard
                int int_num, ah, v;
1245 3a27ad0b bellard
                
1246 3a27ad0b bellard
                int_num = VM86_ARG(ret);
1247 3a27ad0b bellard
                if (int_num != 0x21)
1248 3a27ad0b bellard
                    goto unknown_int;
1249 3a27ad0b bellard
                ah = (r->eax >> 8) & 0xff;
1250 3a27ad0b bellard
                switch(ah) {
1251 3a27ad0b bellard
                case 0x00: /* exit */
1252 3a27ad0b bellard
                    goto the_end;
1253 3a27ad0b bellard
                case 0x02: /* write char */
1254 3a27ad0b bellard
                    {
1255 3a27ad0b bellard
                        uint8_t c = r->edx;
1256 3a27ad0b bellard
                        putchar(c);
1257 3a27ad0b bellard
                    }
1258 3a27ad0b bellard
                    break;
1259 3a27ad0b bellard
                case 0x09: /* write string */
1260 3a27ad0b bellard
                    {
1261 3a27ad0b bellard
                        uint8_t c, *ptr;
1262 3a27ad0b bellard
                        ptr = seg_to_linear(r->ds, r->edx);
1263 3a27ad0b bellard
                        for(;;) {
1264 3a27ad0b bellard
                            c = *ptr++;
1265 3a27ad0b bellard
                            if (c == '$')
1266 3a27ad0b bellard
                                break;
1267 3a27ad0b bellard
                            putchar(c);
1268 3a27ad0b bellard
                        }
1269 3a27ad0b bellard
                        r->eax = (r->eax & ~0xff) | '$';
1270 3a27ad0b bellard
                    }
1271 3a27ad0b bellard
                    break;
1272 3ff0631e bellard
                case 0xff: /* extension: write eflags number in edx */
1273 3ff0631e bellard
                    v = (int)r->edx;
1274 3ff0631e bellard
#ifndef LINUX_VM86_IOPL_FIX
1275 3ff0631e bellard
                    v &= ~0x3000;
1276 3ff0631e bellard
#endif
1277 3ff0631e bellard
                    printf("%08x\n", v);
1278 3a27ad0b bellard
                    break;
1279 3a27ad0b bellard
                default:
1280 3a27ad0b bellard
                unknown_int:
1281 3a27ad0b bellard
                    printf("unsupported int 0x%02x\n", int_num);
1282 3a27ad0b bellard
                    goto the_end;
1283 3a27ad0b bellard
                }
1284 3a27ad0b bellard
            }
1285 3a27ad0b bellard
            break;
1286 3a27ad0b bellard
        case VM86_SIGNAL:
1287 3a27ad0b bellard
            /* a signal came, we just ignore that */
1288 3a27ad0b bellard
            break;
1289 3a27ad0b bellard
        case VM86_STI:
1290 3a27ad0b bellard
            break;
1291 3a27ad0b bellard
        default:
1292 3a27ad0b bellard
            printf("ERROR: unhandled vm86 return code (0x%x)\n", ret);
1293 3a27ad0b bellard
            goto the_end;
1294 3a27ad0b bellard
        }
1295 3a27ad0b bellard
    }
1296 3a27ad0b bellard
 the_end:
1297 3a27ad0b bellard
    printf("VM86 end\n");
1298 3a27ad0b bellard
    munmap(vm86_mem, 0x110000);
1299 3a27ad0b bellard
}
1300 3a27ad0b bellard
1301 3a27ad0b bellard
/* exception tests */
1302 3a27ad0b bellard
#ifndef REG_EAX
1303 3a27ad0b bellard
#define REG_EAX EAX
1304 3a27ad0b bellard
#define REG_EBX EBX
1305 3a27ad0b bellard
#define REG_ECX ECX
1306 3a27ad0b bellard
#define REG_EDX EDX
1307 3a27ad0b bellard
#define REG_ESI ESI
1308 3a27ad0b bellard
#define REG_EDI EDI
1309 3a27ad0b bellard
#define REG_EBP EBP
1310 3a27ad0b bellard
#define REG_ESP ESP
1311 3a27ad0b bellard
#define REG_EIP EIP
1312 3a27ad0b bellard
#define REG_EFL EFL
1313 3a27ad0b bellard
#define REG_TRAPNO TRAPNO
1314 3a27ad0b bellard
#define REG_ERR ERR
1315 3a27ad0b bellard
#endif
1316 3a27ad0b bellard
1317 3a27ad0b bellard
jmp_buf jmp_env;
1318 3a27ad0b bellard
int v1;
1319 3a27ad0b bellard
int tab[2];
1320 3a27ad0b bellard
1321 3a27ad0b bellard
void sig_handler(int sig, siginfo_t *info, void *puc)
1322 3a27ad0b bellard
{
1323 3a27ad0b bellard
    struct ucontext *uc = puc;
1324 3a27ad0b bellard
1325 3a27ad0b bellard
    printf("si_signo=%d si_errno=%d si_code=%d",
1326 3a27ad0b bellard
           info->si_signo, info->si_errno, info->si_code);
1327 e3b32540 bellard
    printf(" si_addr=0x%08lx",
1328 e3b32540 bellard
           (unsigned long)info->si_addr);
1329 3a27ad0b bellard
    printf("\n");
1330 3a27ad0b bellard
1331 3a27ad0b bellard
    printf("trapno=0x%02x err=0x%08x",
1332 3a27ad0b bellard
           uc->uc_mcontext.gregs[REG_TRAPNO],
1333 3a27ad0b bellard
           uc->uc_mcontext.gregs[REG_ERR]);
1334 e3b32540 bellard
    printf(" EIP=0x%08x", uc->uc_mcontext.gregs[REG_EIP]);
1335 3a27ad0b bellard
    printf("\n");
1336 3a27ad0b bellard
    longjmp(jmp_env, 1);
1337 3a27ad0b bellard
}
1338 3a27ad0b bellard
1339 3a27ad0b bellard
void test_exceptions(void)
1340 3a27ad0b bellard
{
1341 e3b32540 bellard
    struct modify_ldt_ldt_s ldt;
1342 3a27ad0b bellard
    struct sigaction act;
1343 3a27ad0b bellard
    volatile int val;
1344 3a27ad0b bellard
    
1345 3a27ad0b bellard
    act.sa_sigaction = sig_handler;
1346 3a27ad0b bellard
    sigemptyset(&act.sa_mask);
1347 3a27ad0b bellard
    act.sa_flags = SA_SIGINFO;
1348 3a27ad0b bellard
    sigaction(SIGFPE, &act, NULL);
1349 3a27ad0b bellard
    sigaction(SIGILL, &act, NULL);
1350 3a27ad0b bellard
    sigaction(SIGSEGV, &act, NULL);
1351 e3b32540 bellard
    sigaction(SIGBUS, &act, NULL);
1352 3a27ad0b bellard
    sigaction(SIGTRAP, &act, NULL);
1353 3a27ad0b bellard
1354 3a27ad0b bellard
    /* test division by zero reporting */
1355 e3b32540 bellard
    printf("DIVZ exception:\n");
1356 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1357 3a27ad0b bellard
        /* now divide by zero */
1358 3a27ad0b bellard
        v1 = 0;
1359 3a27ad0b bellard
        v1 = 2 / v1;
1360 3a27ad0b bellard
    }
1361 3a27ad0b bellard
1362 e3b32540 bellard
    printf("BOUND exception:\n");
1363 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1364 3a27ad0b bellard
        /* bound exception */
1365 3a27ad0b bellard
        tab[0] = 1;
1366 3a27ad0b bellard
        tab[1] = 10;
1367 3a27ad0b bellard
        asm volatile ("bound %0, %1" : : "r" (11), "m" (tab));
1368 3a27ad0b bellard
    }
1369 3a27ad0b bellard
1370 e3b32540 bellard
    printf("segment exceptions:\n");
1371 e3b32540 bellard
    if (setjmp(jmp_env) == 0) {
1372 e3b32540 bellard
        /* load an invalid segment */
1373 e3b32540 bellard
        asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 1));
1374 e3b32540 bellard
    }
1375 e3b32540 bellard
    if (setjmp(jmp_env) == 0) {
1376 e3b32540 bellard
        /* null data segment is valid */
1377 e3b32540 bellard
        asm volatile ("movl %0, %%fs" : : "r" (3));
1378 e3b32540 bellard
        /* null stack segment */
1379 e3b32540 bellard
        asm volatile ("movl %0, %%ss" : : "r" (3));
1380 e3b32540 bellard
    }
1381 e3b32540 bellard
1382 e3b32540 bellard
    ldt.entry_number = 1;
1383 e3b32540 bellard
    ldt.base_addr = (unsigned long)&seg_data1;
1384 e3b32540 bellard
    ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
1385 e3b32540 bellard
    ldt.seg_32bit = 1;
1386 e3b32540 bellard
    ldt.contents = MODIFY_LDT_CONTENTS_DATA;
1387 e3b32540 bellard
    ldt.read_exec_only = 0;
1388 e3b32540 bellard
    ldt.limit_in_pages = 1;
1389 e3b32540 bellard
    ldt.seg_not_present = 1;
1390 e3b32540 bellard
    ldt.useable = 1;
1391 e3b32540 bellard
    modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
1392 e3b32540 bellard
1393 e3b32540 bellard
    if (setjmp(jmp_env) == 0) {
1394 e3b32540 bellard
        /* segment not present */
1395 e3b32540 bellard
        asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
1396 e3b32540 bellard
    }
1397 e3b32540 bellard
1398 3a27ad0b bellard
    /* test SEGV reporting */
1399 e3b32540 bellard
    printf("PF exception:\n");
1400 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1401 e3b32540 bellard
        val = 1;
1402 ede28208 bellard
        /* we add a nop to test a weird PC retrieval case */
1403 ede28208 bellard
        asm volatile ("nop");
1404 3a27ad0b bellard
        /* now store in an invalid address */
1405 3a27ad0b bellard
        *(char *)0x1234 = 1;
1406 3a27ad0b bellard
    }
1407 3a27ad0b bellard
1408 3a27ad0b bellard
    /* test SEGV reporting */
1409 e3b32540 bellard
    printf("PF exception:\n");
1410 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1411 e3b32540 bellard
        val = 1;
1412 3a27ad0b bellard
        /* read from an invalid address */
1413 3a27ad0b bellard
        v1 = *(char *)0x1234;
1414 3a27ad0b bellard
    }
1415 3a27ad0b bellard
    
1416 3a27ad0b bellard
    /* test illegal instruction reporting */
1417 3a27ad0b bellard
    printf("UD2 exception:\n");
1418 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1419 3a27ad0b bellard
        /* now execute an invalid instruction */
1420 3a27ad0b bellard
        asm volatile("ud2");
1421 3a27ad0b bellard
    }
1422 4120b61d bellard
    printf("lock nop exception:\n");
1423 4120b61d bellard
    if (setjmp(jmp_env) == 0) {
1424 4120b61d bellard
        /* now execute an invalid instruction */
1425 4120b61d bellard
        asm volatile("lock nop");
1426 4120b61d bellard
    }
1427 3a27ad0b bellard
    
1428 3a27ad0b bellard
    printf("INT exception:\n");
1429 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1430 3a27ad0b bellard
        asm volatile ("int $0xfd");
1431 3a27ad0b bellard
    }
1432 e3b32540 bellard
    if (setjmp(jmp_env) == 0) {
1433 e3b32540 bellard
        asm volatile ("int $0x01");
1434 e3b32540 bellard
    }
1435 e3b32540 bellard
    if (setjmp(jmp_env) == 0) {
1436 e3b32540 bellard
        asm volatile (".byte 0xcd, 0x03");
1437 e3b32540 bellard
    }
1438 e3b32540 bellard
    if (setjmp(jmp_env) == 0) {
1439 e3b32540 bellard
        asm volatile ("int $0x04");
1440 e3b32540 bellard
    }
1441 e3b32540 bellard
    if (setjmp(jmp_env) == 0) {
1442 e3b32540 bellard
        asm volatile ("int $0x05");
1443 e3b32540 bellard
    }
1444 3a27ad0b bellard
1445 3a27ad0b bellard
    printf("INT3 exception:\n");
1446 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1447 3a27ad0b bellard
        asm volatile ("int3");
1448 3a27ad0b bellard
    }
1449 3a27ad0b bellard
1450 3a27ad0b bellard
    printf("CLI exception:\n");
1451 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1452 3a27ad0b bellard
        asm volatile ("cli");
1453 3a27ad0b bellard
    }
1454 3a27ad0b bellard
1455 3a27ad0b bellard
    printf("STI exception:\n");
1456 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1457 3a27ad0b bellard
        asm volatile ("cli");
1458 3a27ad0b bellard
    }
1459 3a27ad0b bellard
1460 3a27ad0b bellard
    printf("INTO exception:\n");
1461 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1462 3a27ad0b bellard
        /* overflow exception */
1463 3a27ad0b bellard
        asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff));
1464 3a27ad0b bellard
    }
1465 3a27ad0b bellard
1466 3a27ad0b bellard
    printf("OUTB exception:\n");
1467 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1468 3a27ad0b bellard
        asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0));
1469 3a27ad0b bellard
    }
1470 3a27ad0b bellard
1471 3a27ad0b bellard
    printf("INB exception:\n");
1472 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1473 3a27ad0b bellard
        asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321));
1474 3a27ad0b bellard
    }
1475 3a27ad0b bellard
1476 3a27ad0b bellard
    printf("REP OUTSB exception:\n");
1477 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1478 3a27ad0b bellard
        asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1));
1479 3a27ad0b bellard
    }
1480 3a27ad0b bellard
1481 3a27ad0b bellard
    printf("REP INSB exception:\n");
1482 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1483 3a27ad0b bellard
        asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1));
1484 3a27ad0b bellard
    }
1485 3a27ad0b bellard
1486 3a27ad0b bellard
    printf("HLT exception:\n");
1487 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1488 3a27ad0b bellard
        asm volatile ("hlt");
1489 3a27ad0b bellard
    }
1490 3a27ad0b bellard
1491 3a27ad0b bellard
    printf("single step exception:\n");
1492 3a27ad0b bellard
    val = 0;
1493 3a27ad0b bellard
    if (setjmp(jmp_env) == 0) {
1494 3a27ad0b bellard
        asm volatile ("pushf\n"
1495 3a27ad0b bellard
                      "orl $0x00100, (%%esp)\n"
1496 3a27ad0b bellard
                      "popf\n"
1497 3a27ad0b bellard
                      "movl $0xabcd, %0\n" 
1498 3a27ad0b bellard
                      "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory");
1499 3a27ad0b bellard
    }
1500 3a27ad0b bellard
    printf("val=0x%x\n", val);
1501 3a27ad0b bellard
}
1502 3a27ad0b bellard
1503 3ff0631e bellard
/* specific precise single step test */
1504 3ff0631e bellard
void sig_trap_handler(int sig, siginfo_t *info, void *puc)
1505 3ff0631e bellard
{
1506 3ff0631e bellard
    struct ucontext *uc = puc;
1507 3ff0631e bellard
    printf("EIP=0x%08x\n", uc->uc_mcontext.gregs[REG_EIP]);
1508 3ff0631e bellard
}
1509 3ff0631e bellard
1510 3ff0631e bellard
const uint8_t sstep_buf1[4] = { 1, 2, 3, 4};
1511 3ff0631e bellard
uint8_t sstep_buf2[4];
1512 3ff0631e bellard
1513 3ff0631e bellard
void test_single_step(void)
1514 3ff0631e bellard
{
1515 3ff0631e bellard
    struct sigaction act;
1516 3ff0631e bellard
    volatile int val;
1517 3ff0631e bellard
    int i;
1518 3ff0631e bellard
1519 3ff0631e bellard
    val = 0;
1520 3ff0631e bellard
    act.sa_sigaction = sig_trap_handler;
1521 3ff0631e bellard
    sigemptyset(&act.sa_mask);
1522 3ff0631e bellard
    act.sa_flags = SA_SIGINFO;
1523 3ff0631e bellard
    sigaction(SIGTRAP, &act, NULL);
1524 3ff0631e bellard
    asm volatile ("pushf\n"
1525 3ff0631e bellard
                  "orl $0x00100, (%%esp)\n"
1526 3ff0631e bellard
                  "popf\n"
1527 3ff0631e bellard
                  "movl $0xabcd, %0\n" 
1528 3ff0631e bellard
1529 3ff0631e bellard
                  /* jmp test */
1530 3ff0631e bellard
                  "movl $3, %%ecx\n"
1531 3ff0631e bellard
                  "1:\n"
1532 3ff0631e bellard
                  "addl $1, %0\n"
1533 3ff0631e bellard
                  "decl %%ecx\n"
1534 3ff0631e bellard
                  "jnz 1b\n"
1535 3ff0631e bellard
1536 3ff0631e bellard
                  /* movsb: the single step should stop at each movsb iteration */
1537 3ff0631e bellard
                  "movl $sstep_buf1, %%esi\n"
1538 3ff0631e bellard
                  "movl $sstep_buf2, %%edi\n"
1539 3ff0631e bellard
                  "movl $0, %%ecx\n"
1540 3ff0631e bellard
                  "rep movsb\n"
1541 3ff0631e bellard
                  "movl $3, %%ecx\n"
1542 3ff0631e bellard
                  "rep movsb\n"
1543 3ff0631e bellard
                  "movl $1, %%ecx\n"
1544 3ff0631e bellard
                  "rep movsb\n"
1545 3ff0631e bellard
1546 3ff0631e bellard
                  /* cmpsb: the single step should stop at each cmpsb iteration */
1547 3ff0631e bellard
                  "movl $sstep_buf1, %%esi\n"
1548 3ff0631e bellard
                  "movl $sstep_buf2, %%edi\n"
1549 3ff0631e bellard
                  "movl $0, %%ecx\n"
1550 3ff0631e bellard
                  "rep cmpsb\n"
1551 3ff0631e bellard
                  "movl $4, %%ecx\n"
1552 3ff0631e bellard
                  "rep cmpsb\n"
1553 3ff0631e bellard
                  
1554 3ff0631e bellard
                  /* getpid() syscall: single step should skip one
1555 3ff0631e bellard
                     instruction */
1556 3ff0631e bellard
                  "movl $20, %%eax\n"
1557 3ff0631e bellard
                  "int $0x80\n"
1558 3ff0631e bellard
                  "movl $0, %%eax\n"
1559 3ff0631e bellard
                  
1560 3ff0631e bellard
                  /* when modifying SS, trace is not done on the next
1561 3ff0631e bellard
                     instruction */
1562 3ff0631e bellard
                  "movl %%ss, %%ecx\n"
1563 3ff0631e bellard
                  "movl %%ecx, %%ss\n"
1564 3ff0631e bellard
                  "addl $1, %0\n"
1565 3ff0631e bellard
                  "movl $1, %%eax\n"
1566 3ff0631e bellard
                  "movl %%ecx, %%ss\n"
1567 3ff0631e bellard
                  "jmp 1f\n"
1568 3ff0631e bellard
                  "addl $1, %0\n"
1569 3ff0631e bellard
                  "1:\n"
1570 3ff0631e bellard
                  "movl $1, %%eax\n"
1571 3ff0631e bellard
                  "pushl %%ecx\n"
1572 3ff0631e bellard
                  "popl %%ss\n"
1573 3ff0631e bellard
                  "addl $1, %0\n"
1574 3ff0631e bellard
                  "movl $1, %%eax\n"
1575 3ff0631e bellard
                  
1576 3ff0631e bellard
                  "pushf\n"
1577 3ff0631e bellard
                  "andl $~0x00100, (%%esp)\n"
1578 3ff0631e bellard
                  "popf\n"
1579 3ff0631e bellard
                  : "=m" (val) 
1580 3ff0631e bellard
                  : 
1581 3ff0631e bellard
                  : "cc", "memory", "eax", "ecx", "esi", "edi");
1582 3ff0631e bellard
    printf("val=%d\n", val);
1583 3ff0631e bellard
    for(i = 0; i < 4; i++)
1584 3ff0631e bellard
        printf("sstep_buf2[%d] = %d\n", i, sstep_buf2[i]);
1585 3ff0631e bellard
}
1586 3ff0631e bellard
1587 3a27ad0b bellard
/* self modifying code test */
1588 3a27ad0b bellard
uint8_t code[] = {
1589 3a27ad0b bellard
    0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */
1590 3a27ad0b bellard
    0xc3, /* ret */
1591 3a27ad0b bellard
};
1592 3a27ad0b bellard
1593 1190935d bellard
asm("smc_code2:\n"
1594 1190935d bellard
    "movl 4(%esp), %eax\n"
1595 1190935d bellard
    "movl %eax, smc_patch_addr2 + 1\n"
1596 1190935d bellard
    "nop\n"
1597 1190935d bellard
    "nop\n"
1598 1190935d bellard
    "nop\n"
1599 1190935d bellard
    "nop\n"
1600 1190935d bellard
    "nop\n"
1601 1190935d bellard
    "nop\n"
1602 1190935d bellard
    "nop\n"
1603 1190935d bellard
    "nop\n"
1604 1190935d bellard
    "smc_patch_addr2:\n"
1605 1190935d bellard
    "movl $1, %eax\n"
1606 1190935d bellard
    "ret\n");
1607 d1fe2b24 bellard
1608 1190935d bellard
typedef int FuncType(void);
1609 1190935d bellard
extern int smc_code2(int);
1610 3a27ad0b bellard
void test_self_modifying_code(void)
1611 3a27ad0b bellard
{
1612 d1fe2b24 bellard
    int i;
1613 3a27ad0b bellard
1614 3a27ad0b bellard
    printf("self modifying code:\n");
1615 d1fe2b24 bellard
    printf("func1 = 0x%x\n", ((FuncType *)code)());
1616 d1fe2b24 bellard
    for(i = 2; i <= 4; i++) {
1617 d1fe2b24 bellard
        code[1] = i;
1618 d1fe2b24 bellard
        printf("func%d = 0x%x\n", i, ((FuncType *)code)());
1619 d1fe2b24 bellard
    }
1620 1190935d bellard
1621 1190935d bellard
    /* more difficult test : the modified code is just after the
1622 1190935d bellard
       modifying instruction. It is forbidden in Intel specs, but it
1623 1190935d bellard
       is used by old DOS programs */
1624 1190935d bellard
    for(i = 2; i <= 4; i++) {
1625 1190935d bellard
        printf("smc_code2(%d) = %d\n", i, smc_code2(i));
1626 1190935d bellard
    }
1627 3a27ad0b bellard
}
1628 3a27ad0b bellard
    
1629 4d1135e4 bellard
static void *call_end __init_call = NULL;
1630 4d1135e4 bellard
1631 4d1135e4 bellard
int main(int argc, char **argv)
1632 4d1135e4 bellard
{
1633 4d1135e4 bellard
    void **ptr;
1634 4d1135e4 bellard
    void (*func)(void);
1635 4b74fe1f bellard
1636 4d1135e4 bellard
    ptr = &call_start + 1;
1637 4d1135e4 bellard
    while (*ptr != NULL) {
1638 4d1135e4 bellard
        func = *ptr++;
1639 4d1135e4 bellard
        func();
1640 4d1135e4 bellard
    }
1641 9d8e9c09 bellard
    test_bsx();
1642 d57c4e01 bellard
    test_mul();
1643 4d1135e4 bellard
    test_jcc();
1644 9d8e9c09 bellard
    test_floats();
1645 55480af8 bellard
    test_bcd();
1646 1a9353d2 bellard
    test_xchg();
1647 e1d4294a bellard
    test_string();
1648 e1d4294a bellard
    test_misc();
1649 6dbad63e bellard
    test_lea();
1650 6dbad63e bellard
    test_segs();
1651 e5918247 bellard
    test_code16();
1652 3a27ad0b bellard
    test_vm86();
1653 3a27ad0b bellard
    test_exceptions();
1654 3a27ad0b bellard
    test_self_modifying_code();
1655 3ff0631e bellard
    test_single_step();
1656 4d1135e4 bellard
    return 0;
1657 4d1135e4 bellard
}