7 #define TEST_FILE "test-mmx.h"
13 typedef void (*testfn
)(void);
17 } __attribute__((aligned(16))) v2di
;
41 static void dump_mmx(int n
, const uint64_t *r
, int ff
)
45 memcpy(v
, r
, sizeof(v
));
46 printf("MM%d = %016lx %8g %8g\n", n
, *r
, v
[1], v
[0]);
48 printf("MM%d = %016lx\n", n
, *r
);
52 static void dump_xmm(const char *name
, int n
, const v2di
*r
, int ff
)
54 printf("%s%d = %016lx %016lx\n",
55 name
, n
, r
->q1
, r
->q0
);
58 memcpy(v
, r
, sizeof(v
));
59 printf(" %8g %8g %8g %8g\n",
60 v
[3], v
[2], v
[1], v
[0]);
64 static void dump_regs(reg_state
*s
, int ff
)
68 for (i
= 0; i
< 8; i
++) {
69 dump_mmx(i
, &s
->mm
[i
], ff
);
71 for (i
= 0; i
< 4; i
++) {
72 dump_xmm("mem", i
, &s
->mem0
[i
], 0);
76 static void compare_state(const reg_state
*a
, const reg_state
*b
)
79 for (i
= 0; i
< 8; i
++) {
80 if (a
->mm
[i
] != b
->mm
[i
]) {
81 printf("MM%d = %016lx\n", i
, b
->mm
[i
]);
84 for (i
= 0; i
< 16; i
++) {
85 if (a
->r
[i
] != b
->r
[i
]) {
86 printf("r%d = %016lx\n", i
, b
->r
[i
]);
89 for (i
= 0; i
< 8; i
++) {
90 if (memcmp(&a
->xmm
[i
], &b
->xmm
[i
], 8)) {
91 dump_xmm("xmm", i
, &b
->xmm
[i
], a
->ff
);
94 for (i
= 0; i
< 4; i
++) {
95 if (memcmp(&a
->mem0
[i
], &a
->mem
[i
], 16)) {
96 dump_xmm("mem", i
, &a
->mem
[i
], a
->ff
);
99 if (a
->flags
!= b
->flags
) {
100 printf("FLAGS = %016lx\n", b
->flags
);
104 #define LOADMM(r, o) "movq " #r ", " #o "[%0]\n\t"
105 #define LOADXMM(r, o) "movdqa " #r ", " #o "[%0]\n\t"
106 #define STOREMM(r, o) "movq " #o "[%1], " #r "\n\t"
107 #define STOREXMM(r, o) "movdqa " #o "[%1], " #r "\n\t"
126 #define LOADREG(r, o) "mov " #r ", " #o "[rax]\n\t"
127 #define STOREREG(r, o) "mov " #o "[rax], " #r "\n\t"
143 static void run_test(const TestDef *t)
146 reg_state
*init
= t
->init
;
147 memcpy(init
->mem
, init
->mem0
, sizeof(init
->mem
));
148 printf("%5d %s\n", t
->n
, t
->s
);
164 "mov rcx, 0x140[rax]\n\t"
170 "mov rax, 0xc0[rax]\n\t"
173 "mov rax, 8[rsp]\n\t"
176 "mov 0xc0[rax], rbx\n\t"
178 "mov 0xf0[rax], rbx\n\t"
179 "mov 0xf8[rax], rbx\n\t"
183 "mov 0x140[rax], rbx\n\t"
193 : : "r"(init
), "r"(&result
), "r"(t
->fn
)
196 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
197 "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
198 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5",
199 "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11",
200 "xmm12", "xmm13", "xmm14", "xmm15"
202 compare_state(init
, &result
);
205 #define TEST(n, cmd, type) \
206 static void __attribute__((naked)) test_##n(void) \
209 asm volatile("ret"); \
214 static const TestDef test_table
[] = {
215 #define TEST(n, cmd, type) {n, test_##n, cmd, &init##type},
220 static void run_all(void)
223 for (t
= test_table
; t
->fn
; t
++) {
228 #define ARRAY_LEN(x) (sizeof(x) / sizeof(x[0]))
230 float val_f32
[] = {2.0, -1.0, 4.8, 0.8, 3, -42.0, 5e6
, 7.5, 8.3};
231 uint64_t val_i64
[] = {
232 0x3d6b3b6a9e4118f2lu
, 0x355ae76d2774d78clu
,
233 0xd851c54a56bf1f29lu
, 0x4a84d1d50bf4c4fflu
,
234 0x5826475e2c5fd799lu
, 0xfd32edc01243f5e9lu
,
237 v2di deadbeef
= {0xa5a5a5a5deadbeefull
, 0xa5a5a5a5deadbeefull
};
239 void init_f32reg(uint64_t *r
)
244 for (i
= 0; i
< 2; i
++) {
246 if (n
== ARRAY_LEN(val_f32
)) {
250 memcpy(r
, v
, sizeof(*r
));
253 void init_intreg(uint64_t *r
)
255 static uint64_t mask
;
258 *r
= val_i64
[n
] ^ mask
;
260 if (n
== ARRAY_LEN(val_i64
)) {
266 static void init_all(reg_state
*s
)
270 for (i
= 0; i
< 16; i
++) {
271 init_intreg(&s
->r
[i
]);
273 s
->r
[3] = (uint64_t)&s
->mem
[0]; /* rdx */
274 s
->r
[5] = (uint64_t)&s
->mem
[2]; /* rdi */
278 for (i
= 0; i
< 8; i
++) {
279 s
->xmm
[i
] = deadbeef
;
280 memcpy(&s
->mm
[i
], &s
->xmm
[i
], sizeof(s
->mm
[i
]));
282 for (i
= 0; i
< 2; i
++) {
283 s
->mem0
[i
] = deadbeef
;
287 int main(int argc
, char *argv
[])
290 init_intreg(&initI
.mm
[5]);
291 init_intreg(&initI
.mm
[6]);
292 init_intreg(&initI
.mm
[7]);
293 init_intreg(&initI
.mem0
[1].q0
);
294 init_intreg(&initI
.mem0
[1].q1
);
296 dump_regs(&initI
, 0);
299 init_f32reg(&initF32
.mm
[5]);
300 init_f32reg(&initF32
.mm
[6]);
301 init_f32reg(&initF32
.mm
[7]);
302 init_f32reg(&initF32
.mem0
[1].q0
);
303 init_f32reg(&initF32
.mem0
[1].q1
);
306 dump_regs(&initF32
, 32);
309 int n
= atoi(argv
[1]);
310 run_test(&test_table
[n
]);