x86_64-asm: =m operand fixes

The problem was with tcctest.c:

    unsigned set;
    __asm__("btsl %1,%0" : "=m"(set) : "Ir"(20) : "cc");

when with tcc compiled with the HAVE_SELINUX option, run with
tcc -run, it would use large addresses far beyond the 32bits
range when tcc did not use the pc-relative mode for accessing
'set' in global data memory.  In fact the assembler did not
know about %rip at all.

Changes:
- memory operands use (%rax) not (%eax)
- conversion from VT_LLOCAL: use type VT_PTR
- support 'k' modifier
- support %rip register
- support X(%rip) pc-relative addresses

The test in tcctest.c is from Michael Matz.
This commit is contained in:
grischka
2016-11-20 14:50:56 +01:00
parent 47fd807f9b
commit 4a3741bf02
6 changed files with 81 additions and 33 deletions

View File

@ -2565,12 +2565,33 @@ static __inline__ unsigned long long inc64(unsigned long long a)
__asm__("addl $1, %%eax ; adcl $0, %%edx" : "=A" (res) : "A" (a));
#endif
return res;
}
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 ("lea %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 };
@ -2592,6 +2613,10 @@ void asm_test(void)
/* 'A' constraint test */
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;
@ -2600,9 +2625,6 @@ void asm_test(void)
/* NOTE: we test here if C labels are correctly restored after the
asm statement */
goto label1;
label2:
__asm__("btsl %1,%0" : "=m"(set) : "Ir"(20) : "cc");
#ifdef __GNUC__ // works strange with GCC 4.3
label2:
__asm__("btsl %1,%0" : "=m"(set) : "Ir"(20) : "cc");
printf("set=0x%x\n", set);