[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Tinycc-devel] asmtest problem
From: |
Michael Matz |
Subject: |
Re: [Tinycc-devel] asmtest problem |
Date: |
Thu, 20 Oct 2016 17:28:29 +0200 (CEST) |
User-agent: |
Alpine 2.20 (LSU 67 2015-01-07) |
Hello grischka,
On Wed, 19 Oct 2016, grischka wrote:
> There seems to be a asm problem in tcctest.c with the bts
> instruction on x86-64, which crashes it under circumstances.
>
> __asm__("bts %1,%0" : "=m"(*pset) : "Ir"(_sig - 1) : "cc");
>
> From dump:
> 3d: 8b 45 d0 mov -0x30(%rbp),%eax <-- address
> Here it should load the addres into %rax, not %eax
Ah yes, that one. The attached patch should solve this, which also is
part of that mythical larger series that makes us compile the linux x86-64
kernel.
Ciao,
Michael.
commit 70a1dc38908b6ff679f15cf033828afda885d35f
Author: Michael Matz <address@hidden>
Date: Wed Jun 29 18:06:40 2016 +0200
inline asm: Fix 'm' constraints
See testcase. The m constraint actually passes the address
and hence is of pointer type.
diff --git a/i386-asm.c b/i386-asm.c
index c0dd435..cc73320 100644
--- a/i386-asm.c
+++ b/i386-asm.c
@@ -1291,7 +1291,12 @@ ST_FUNC void subst_asm_operand(CString *add_str,
if (reg >= VT_CONST)
tcc_error("internal compiler error");
snprintf(buf, sizeof(buf), "(%%%s)",
- get_tok_str(TOK_ASM_eax + reg, NULL));
+#ifdef TCC_TARGET_X86_64
+ get_tok_str(TOK_ASM_rax + reg, NULL)
+#else
+ get_tok_str(TOK_ASM_eax + reg, NULL)
+#endif
+ );
cstr_cat(add_str, buf, -1);
} else {
/* register case */
@@ -1392,7 +1397,8 @@ ST_FUNC void asm_gen_code(ASMOperand *operands, int
nb_operands,
output cases) */
SValue sv;
sv = *op->vt;
- sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
+ sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
+ sv.type.t = VT_PTR;
load(op->reg, &sv);
} else if (i >= nb_outputs || op->is_rw) {
/* load value in register */
diff --git a/tccasm.c b/tccasm.c
index 55feecf..ad9580a 100644
--- a/tccasm.c
+++ b/tccasm.c
@@ -1043,7 +1043,8 @@ static void parse_asm_operands(ASMOperand *operands, int
*nb_operands_ptr,
skip('(');
gexpr();
if (is_output) {
- test_lvalue();
+ if (!(vtop->type.t & VT_ARRAY))
+ test_lvalue();
} else {
/* we want to avoid LLOCAL case, except when the 'm'
constraint is used. Note that it may come from
diff --git a/tests/tcctest.c b/tests/tcctest.c
index 28ba263..0922d77 100644
--- a/tests/tcctest.c
+++ b/tests/tcctest.c
@@ -2583,12 +2583,33 @@ int fls64(unsigned long long x)
}
#endif
+struct struct123 {
+ int a;
+ int b;
+};
+struct struct1231 {
+ unsigned long addr;
+};
+
+unsigned long mconstraint_test(struct struct1231 *r)
+{
+ unsigned long ret;
+ unsigned int a[2];
+ a[0] = 0;
+ __asm__ volatile ("leaq %2,%0; movl 4(%0),%k0; addl %2,%k0; movl $51,%2;
movl $52,4%2; movl $63,%1"
+ : "=&r" (ret), "=m" (a)
+ : "m" (*(struct struct123 *)r->addr));
+ return ret + a[0];
+}
+
unsigned int set;
void asm_test(void)
{
char buf[128];
unsigned int val;
+ struct struct123 s1;
+ struct struct1231 s2 = { (unsigned long)&s1 };
printf("inline asm:\n");
@@ -2610,6 +2631,10 @@ void asm_test(void)
printf("mul64=0x%Lx\n", mul64(0x12345678, 0xabcd1234));
printf("inc64=0x%Lx\n", inc64(0x12345678ffffffff));
+ s1.a = 42;
+ s1.b = 43;
+ printf("mconstraint: %d", mconstraint_test(&s2));
+ printf(" %d %d\n", s1.a, s1.b);
set = 0xff;
sigdelset1(&set, 2);
sigaddset1(&set, 16);