Domanda

Below atomic64_read code works in x86 environment but fails for x64.

    asm volatile(
        "mov %%ebx, %%eax\n"
        "mov %%ecx, %%edx\n"
        "lock cmpxchg8b %1\n"
        : "=&A" (ret)
        : "m" (v->counter64)
        );

interestingly, lock operation refer to register 'ecx'( : edx) in x86, but in x64 it refer to 'rax' register.

lock cmpxchg8b (%ecx) => x86

lock cmpxchg8b (%rax) => x64

I also tried to convert above code as given below, considering rax and rcx are 64 bit register. It correctly mov value to rax register but gives segmentation fault at lock statement.

asm volatile(
    "mov %%rcx, %%rax\n"
    "lock cmpxchg8b %1\n"
    : "=&A" (ret)
    : "m" (v->counter64)
    );
È stato utile?

Soluzione

The original fails because the "A" constraints means rax/eax/ax/al and/or rdx/edx/dx/dl and on x64 rdx only is allocated for the result, and the mov instructions therefore overwrite the address in rax.

You can get the result in two halves:

uint32_t lo, hi;
asm volatile(
    "mov %%ebx, %%eax\n"
    "mov %%ecx, %%edx\n"
    "lock cmpxchg8b %2\n"
    : "=&a" (lo), "=&d" (hi)
    : "m" (v->counter64)
    );
ret = lo | ((uint64_t)hi << 32);

However would an ordinary read suffice?

ret = *(volatile uint64_t)&v->counter64

Or are the memory ordering insufficient?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top