> can anyone help me to translate the following function using
> mspgcc's inline assembly language.
> __asm__ __volatile__()
>
> uint16_t
> convert_endian
> (
> register uint16_t dt
> )
> {
> /$
> swpb @dt
> $/
>
> return( dt );
> }
Well, first there's the obvious:
uint16_t
convert_endian(uint16_t dt)
{
asm("swpb %0" : "+g" (dt));
return dt;
}
The asm() lists a format string (where "%0" is replaced by the first
operand), then a colon, then all values that are written by the
instruction. The letters in quotes describe what effective addresses
are legal. The "+" means that the operand is read as well as written,
and the "g" means that any effective address is okay.
Compiled with optimization, mspgcc will produce just
convert_endian:
swpb r15
ret
You can elaborate on it in a couple of ways:
1) In the declartion, add "__attribute__((const))", which says that it
reads no memory and has no side effects. The compiler can then
reorder it more freely, hoist it out of loops, etc.
2) Mark it as inline. E.g. in a header file, include
static inline uint16_t __attribute__((const))
convert_endian(uint16_t dt)
{
asm("swpb %0" : "+g" (dt));
return dt;
}
Since it's only one instruction anyway, that will let mspgcc just
drop that one instruction in wherever it's needed.
(Unfortunately, while it does a good job with register variables,
I haven't managed to convince it to generate "swpb @r15+" even when
spoon-fed code that should generate it. Oh, well.)