Re: Specifying different registers in inline asm
jh--- via Gcc-help <[email protected]>
| Newsgroups | gmane.comp.gcc.help |
|---|---|
| Message-ID | <[email protected]> |
Le 2025-11-19 16:19, Richard Earnshaw (foss) a écrit :
[snip]
Thank you all very much, I am slowly (the slowness comes entirely from
my side) understanding what I should do, both on a conceptual and on a
practical levels.
I still need a little push.
>>
>> #define byte_from_user(addr) ({uint8_t val; __asm__
>> __volatile__("LDRBT %0, [%1]\n" : "=&r"(val) : "r" (addr),
>> "m"(*addr)); val;})
>>
>> void dump(const uint8_t * src, size_t count;
>> for(size_t cntsrc=0;cntsrc<count;cntsrc++){
>> uint8_t data = byte_from_user(&src[cntsrc]);
>> printf("%02X ", data);
>> }
>> printf("\n");
>> }
>>
>> So the only way to be theoretically correct is to copy addr to a dummy
>> variable and say it will come out of the asm block? Like this:
>>
>> #define byte_from_user(addr) ({uint8_t val; uintptr_t clob_addr =
>> addr; __asm__ __volatile__("LDRBT %0, [%1]\n" : "=&r"(val),
>> "+r"(clob_addr) : "m"(*clob_addr)); val;})
>>
>
> With the '+r' variant you don't need to mention clob_addr twice. You
> also don't need '&' on the first value now because the compiler will
> never assign two outputs to the same register.
>
> So I think you're best solution would be:
>
>
> static inline uint8_t
> byte_from_user(uint8_t *addr)
> {
> uint8_t val;
> void *unused;
> __asm__ __volatile__ ("LDRBT %0, [%1]\n"
> : "=r"(val), "=r" (unused)
> : "1" (addr)
> : "memory");
> return val;
> }
>
> void dump(const uint8_t * src, size_t count;
> for(size_t cntsrc=0;cntsrc<count;cntsrc++){
> uint8_t data = byte_from_user(&src[cntsrc]);
> printf("%02X ", data);
> }
> printf("\n");
> }
>
> You probably won't need the clobber of 'memory' in addition to the
> 'volatile' qualifier, but you certainly need at least one.
>
About memory access, I think I made a mistake, *addr is not clobbered,
but will be read, should that be mentioned in the input list?
In the converse function byte_to_user, *addr would be written, should it
then be marked as clobber?
Is there a sense in saying that my code only reads/writes *addr and not
any other memory (i.e. does it make a difference for clobber to write
"m"(*addr) rather then "memory")?
Cheers,
JH