tinycc-devel
[Top][All Lists]
Advanced

[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);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]