many fixes
[qemu] / tests / test-i386.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <math.h>
4
5 #define xglue(x, y) x ## y
6 #define glue(x, y) xglue(x, y)
7 #define stringify(s)    tostring(s)
8 #define tostring(s)     #s
9
10 #define CC_C    0x0001
11 #define CC_P    0x0004
12 #define CC_A    0x0010
13 #define CC_Z    0x0040
14 #define CC_S    0x0080
15 #define CC_O    0x0800
16
17 #define __init_call     __attribute__ ((unused,__section__ (".initcall.init")))
18
19 static void *call_start __init_call = NULL;
20
21 #define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
22
23 #define OP add
24 #include "test-i386.h"
25
26 #define OP sub
27 #include "test-i386.h"
28
29 #define OP xor
30 #include "test-i386.h"
31
32 #define OP and
33 #include "test-i386.h"
34
35 #define OP or
36 #include "test-i386.h"
37
38 #define OP cmp
39 #include "test-i386.h"
40
41 #define OP adc
42 #define OP_CC
43 #include "test-i386.h"
44
45 #define OP sbb
46 #define OP_CC
47 #include "test-i386.h"
48
49 #define OP inc
50 #define OP_CC
51 #define OP1
52 #include "test-i386.h"
53
54 #define OP dec
55 #define OP_CC
56 #define OP1
57 #include "test-i386.h"
58
59 #define OP neg
60 #define OP_CC
61 #define OP1
62 #include "test-i386.h"
63
64 #define OP not
65 #define OP_CC
66 #define OP1
67 #include "test-i386.h"
68
69 #undef CC_MASK
70 #define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)
71
72 #define OP shl
73 #include "test-i386-shift.h"
74
75 #define OP shr
76 #include "test-i386-shift.h"
77
78 #define OP sar
79 #include "test-i386-shift.h"
80
81 #define OP rol
82 #include "test-i386-shift.h"
83
84 #define OP ror
85 #include "test-i386-shift.h"
86
87 #define OP rcr
88 #define OP_CC
89 #include "test-i386-shift.h"
90
91 #define OP rcl
92 #define OP_CC
93 #include "test-i386-shift.h"
94
95
96 /* lea test (modrm support) */
97 #define TEST_LEA(STR)\
98 {\
99     asm("leal " STR ", %0"\
100         : "=r" (res)\
101         : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
102     printf("lea %s = %08x\n", STR, res);\
103 }
104
105 #define TEST_LEA16(STR)\
106 {\
107     asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\
108         : "=wq" (res)\
109         : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
110     printf("lea %s = %08x\n", STR, res);\
111 }
112
113
114 void test_lea(void)
115 {
116     int eax, ebx, ecx, edx, esi, edi, res;
117     eax = 0x0001;
118     ebx = 0x0002;
119     ecx = 0x0004;
120     edx = 0x0008;
121     esi = 0x0010;
122     edi = 0x0020;
123
124     TEST_LEA("0x4000");
125
126     TEST_LEA("(%%eax)");
127     TEST_LEA("(%%ebx)");
128     TEST_LEA("(%%ecx)");
129     TEST_LEA("(%%edx)");
130     TEST_LEA("(%%esi)");
131     TEST_LEA("(%%edi)");
132
133     TEST_LEA("0x40(%%eax)");
134     TEST_LEA("0x40(%%ebx)");
135     TEST_LEA("0x40(%%ecx)");
136     TEST_LEA("0x40(%%edx)");
137     TEST_LEA("0x40(%%esi)");
138     TEST_LEA("0x40(%%edi)");
139
140     TEST_LEA("0x4000(%%eax)");
141     TEST_LEA("0x4000(%%ebx)");
142     TEST_LEA("0x4000(%%ecx)");
143     TEST_LEA("0x4000(%%edx)");
144     TEST_LEA("0x4000(%%esi)");
145     TEST_LEA("0x4000(%%edi)");
146
147     TEST_LEA("(%%eax, %%ecx)");
148     TEST_LEA("(%%ebx, %%edx)");
149     TEST_LEA("(%%ecx, %%ecx)");
150     TEST_LEA("(%%edx, %%ecx)");
151     TEST_LEA("(%%esi, %%ecx)");
152     TEST_LEA("(%%edi, %%ecx)");
153
154     TEST_LEA("0x40(%%eax, %%ecx)");
155     TEST_LEA("0x4000(%%ebx, %%edx)");
156
157     TEST_LEA("(%%ecx, %%ecx, 2)");
158     TEST_LEA("(%%edx, %%ecx, 4)");
159     TEST_LEA("(%%esi, %%ecx, 8)");
160
161     TEST_LEA("(,%%eax, 2)");
162     TEST_LEA("(,%%ebx, 4)");
163     TEST_LEA("(,%%ecx, 8)");
164
165     TEST_LEA("0x40(,%%eax, 2)");
166     TEST_LEA("0x40(,%%ebx, 4)");
167     TEST_LEA("0x40(,%%ecx, 8)");
168
169
170     TEST_LEA("-10(%%ecx, %%ecx, 2)");
171     TEST_LEA("-10(%%edx, %%ecx, 4)");
172     TEST_LEA("-10(%%esi, %%ecx, 8)");
173
174     TEST_LEA("0x4000(%%ecx, %%ecx, 2)");
175     TEST_LEA("0x4000(%%edx, %%ecx, 4)");
176     TEST_LEA("0x4000(%%esi, %%ecx, 8)");
177
178     /* limited 16 bit addressing test */
179     TEST_LEA16("0x4000");
180     TEST_LEA16("(%%bx)");
181     TEST_LEA16("(%%si)");
182     TEST_LEA16("(%%di)");
183     TEST_LEA16("0x40(%%bx)");
184     TEST_LEA16("0x40(%%si)");
185     TEST_LEA16("0x40(%%di)");
186     TEST_LEA16("0x4000(%%bx)");
187     TEST_LEA16("0x4000(%%si)");
188     TEST_LEA16("(%%bx,%%si)");
189     TEST_LEA16("(%%bx,%%di)");
190     TEST_LEA16("0x40(%%bx,%%si)");
191     TEST_LEA16("0x40(%%bx,%%di)");
192     TEST_LEA16("0x4000(%%bx,%%si)");
193     TEST_LEA16("0x4000(%%bx,%%di)");
194 }
195
196 #define TEST_JCC(JCC, v1, v2)\
197 {\
198     asm("movl $1, %0\n\t"\
199         "cmpl %2, %1\n\t"\
200         JCC " 1f\n\t"\
201         "movl $0, %0\n\t"\
202         "1:\n\t"\
203         : "=r" (res)\
204         : "r" (v1), "r" (v2));\
205     printf("%-10s %d\n", JCC, res);\
206 }
207
208 /* various jump tests */
209 void test_jcc(void)
210 {
211     int res;
212
213     TEST_JCC("jne", 1, 1);
214     TEST_JCC("jne", 1, 0);
215
216     TEST_JCC("je", 1, 1);
217     TEST_JCC("je", 1, 0);
218
219     TEST_JCC("jl", 1, 1);
220     TEST_JCC("jl", 1, 0);
221     TEST_JCC("jl", 1, -1);
222
223     TEST_JCC("jle", 1, 1);
224     TEST_JCC("jle", 1, 0);
225     TEST_JCC("jle", 1, -1);
226
227     TEST_JCC("jge", 1, 1);
228     TEST_JCC("jge", 1, 0);
229     TEST_JCC("jge", -1, 1);
230
231     TEST_JCC("jg", 1, 1);
232     TEST_JCC("jg", 1, 0);
233     TEST_JCC("jg", 1, -1);
234
235     TEST_JCC("jb", 1, 1);
236     TEST_JCC("jb", 1, 0);
237     TEST_JCC("jb", 1, -1);
238
239     TEST_JCC("jbe", 1, 1);
240     TEST_JCC("jbe", 1, 0);
241     TEST_JCC("jbe", 1, -1);
242
243     TEST_JCC("jae", 1, 1);
244     TEST_JCC("jae", 1, 0);
245     TEST_JCC("jae", 1, -1);
246
247     TEST_JCC("ja", 1, 1);
248     TEST_JCC("ja", 1, 0);
249     TEST_JCC("ja", 1, -1);
250
251
252     TEST_JCC("jp", 1, 1);
253     TEST_JCC("jp", 1, 0);
254
255     TEST_JCC("jnp", 1, 1);
256     TEST_JCC("jnp", 1, 0);
257
258     TEST_JCC("jo", 0x7fffffff, 0);
259     TEST_JCC("jo", 0x7fffffff, -1);
260
261     TEST_JCC("jno", 0x7fffffff, 0);
262     TEST_JCC("jno", 0x7fffffff, -1);
263
264     TEST_JCC("js", 0, 1);
265     TEST_JCC("js", 0, -1);
266     TEST_JCC("js", 0, 0);
267
268     TEST_JCC("jns", 0, 1);
269     TEST_JCC("jns", 0, -1);
270     TEST_JCC("jns", 0, 0);
271 }
272
273 #undef CC_MASK
274 #define CC_MASK (CC_O | CC_C)
275
276 #define OP mul
277 #include "test-i386-muldiv.h"
278
279 #define OP imul
280 #include "test-i386-muldiv.h"
281
282 #undef CC_MASK
283 #define CC_MASK (0)
284
285 #define OP div
286 #include "test-i386-muldiv.h"
287
288 #define OP idiv
289 #include "test-i386-muldiv.h"
290
291 void test_imulw2(int op0, int op1) 
292 {
293     int res, s1, s0, flags;
294     s0 = op0;
295     s1 = op1;
296     res = s0;
297     flags = 0;
298     asm ("push %4\n\t"
299          "popf\n\t"
300          "imulw %w2, %w0\n\t" 
301          "pushf\n\t"
302          "popl %1\n\t"
303          : "=q" (res), "=g" (flags)
304          : "q" (s1), "0" (res), "1" (flags));
305     printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
306            "imulw", s0, s1, res, flags & CC_MASK);
307 }
308
309 void test_imull2(int op0, int op1) 
310 {
311     int res, s1, s0, flags;
312     s0 = op0;
313     s1 = op1;
314     res = s0;
315     flags = 0;
316     asm ("push %4\n\t"
317          "popf\n\t"
318          "imull %2, %0\n\t" 
319          "pushf\n\t"
320          "popl %1\n\t"
321          : "=q" (res), "=g" (flags)
322          : "q" (s1), "0" (res), "1" (flags));
323     printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
324            "imull", s0, s1, res, flags & CC_MASK);
325 }
326
327 void test_mul(void)
328 {
329     test_imulb(0x1234561d, 4);
330     test_imulb(3, -4);
331     test_imulb(0x80, 0x80);
332     test_imulb(0x10, 0x10);
333
334     test_imulw(0, 0x1234001d, 45);
335     test_imulw(0, 23, -45);
336     test_imulw(0, 0x8000, 0x8000);
337     test_imulw(0, 0x100, 0x100);
338
339     test_imull(0, 0x1234001d, 45);
340     test_imull(0, 23, -45);
341     test_imull(0, 0x80000000, 0x80000000);
342     test_imull(0, 0x10000, 0x10000);
343
344     test_mulb(0x1234561d, 4);
345     test_mulb(3, -4);
346     test_mulb(0x80, 0x80);
347     test_mulb(0x10, 0x10);
348
349     test_mulw(0, 0x1234001d, 45);
350     test_mulw(0, 23, -45);
351     test_mulw(0, 0x8000, 0x8000);
352     test_mulw(0, 0x100, 0x100);
353
354     test_mull(0, 0x1234001d, 45);
355     test_mull(0, 23, -45);
356     test_mull(0, 0x80000000, 0x80000000);
357     test_mull(0, 0x10000, 0x10000);
358
359     test_imulw2(0x1234001d, 45);
360     test_imulw2(23, -45);
361     test_imulw2(0x8000, 0x8000);
362     test_imulw2(0x100, 0x100);
363
364     test_imull2(0x1234001d, 45);
365     test_imull2(23, -45);
366     test_imull2(0x80000000, 0x80000000);
367     test_imull2(0x10000, 0x10000);
368
369     test_idivb(0x12341678, 0x127e);
370     test_idivb(0x43210123, -5);
371     test_idivb(0x12340004, -1);
372
373     test_idivw(0, 0x12345678, 12347);
374     test_idivw(0, -23223, -45);
375     test_idivw(0, 0x12348000, -1);
376     test_idivw(0x12343, 0x12345678, 0x81238567);
377
378     test_idivl(0, 0x12345678, 12347);
379     test_idivl(0, -233223, -45);
380     test_idivl(0, 0x80000000, -1);
381     test_idivl(0x12343, 0x12345678, 0x81234567);
382
383     test_divb(0x12341678, 0x127e);
384     test_divb(0x43210123, -5);
385     test_divb(0x12340004, -1);
386
387     test_divw(0, 0x12345678, 12347);
388     test_divw(0, -23223, -45);
389     test_divw(0, 0x12348000, -1);
390     test_divw(0x12343, 0x12345678, 0x81238567);
391
392     test_divl(0, 0x12345678, 12347);
393     test_divl(0, -233223, -45);
394     test_divl(0, 0x80000000, -1);
395     test_divl(0x12343, 0x12345678, 0x81234567);
396 }
397
398
399 static void *call_end __init_call = NULL;
400
401 int main(int argc, char **argv)
402 {
403     void **ptr;
404     void (*func)(void);
405
406     test_mul();
407 #if 0
408     ptr = &call_start + 1;
409     while (*ptr != NULL) {
410         func = *ptr++;
411         func();
412     }
413     test_jcc();
414     test_lea();
415 #endif
416     return 0;
417 }