aboutsummaryrefslogtreecommitdiff
path: root/tests/tcctest.c
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2016-10-08 22:50:16 +0200
committerMichael Matz <matz@suse.de>2016-12-15 17:49:55 +0100
commita2a596e76724a7915361b4d0f1b5553929d26a31 (patch)
tree2cc4185467b9003c95ce8e079dd11f9723e8c1d6 /tests/tcctest.c
parentddd461dcc866d17f1c89137dc275ce1da95e7be2 (diff)
downloadtinycc-a2a596e76724a7915361b4d0f1b5553929d26a31.tar.gz
tinycc-a2a596e76724a7915361b4d0f1b5553929d26a31.tar.bz2
x86-64-asm: Accept high register in clobbers
The callee saved registers (among them r12-r15) really need saving/restoring if mentioned in asm clobbers, even if TCC itself doesn't use them. E.g. the linux kernel relies on that in its switch_to() implementation.
Diffstat (limited to 'tests/tcctest.c')
-rw-r--r--tests/tcctest.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/tests/tcctest.c b/tests/tcctest.c
index d4a6a5a..5124a4f 100644
--- a/tests/tcctest.c
+++ b/tests/tcctest.c
@@ -2925,6 +2925,29 @@ void fancy_copy2 (unsigned *in, unsigned *out)
asm volatile ("mov %0,(%1)" : : "r" (*in), "r" (out) : "memory");
}
+#ifdef __x86_64__
+void clobber_r12(void)
+{
+ asm volatile("mov $1, %%r12" ::: "r12");
+}
+#endif
+
+void test_high_clobbers(void)
+{
+#ifdef __x86_64__
+ register long val asm("r12");
+ long val2;
+ /* This tests if asm clobbers correctly save/restore callee saved
+ registers if they are clobbered and if it's the high 8 x86-64
+ registers. This is fragile for GCC as the constraints do not
+ correctly capture the data flow, but good enough for us. */
+ asm volatile("mov $0x4542, %%r12" : "=r" (val):: "memory");
+ clobber_r12();
+ asm volatile("mov %%r12, %0" : "=r" (val2) : "r" (val): "memory");
+ printf("asmhc: 0x%x\n", val2);
+#endif
+}
+
void asm_test(void)
{
char buf[128];
@@ -3004,6 +3027,7 @@ void asm_test(void)
printf ("fancycpy2(%d)=%d\n", val, val2);
asm volatile ("mov $0x4243, %%esi" : "=r" (regvar));
printf ("regvar=%x\n", regvar);
+ test_high_clobbers();
return;
label1:
goto label2;