xref: /qemu/tests/tcg/i386/test-i386.c (revision 4b74fe1f0013c622693b26141c0ed031a284a45a)
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 }
418