relative jumps with AVR-GCC inline assembler
I've just started experimenting with inline assembler in AVR-GCC. I'm working on a macro that multiplies two 8 bit unsigned integers and stores the result in a 16 bit unsigned integer for AVRs that don't have a hardware multiply, for greater speed than using the standard C function. The code is:
#ifndef UMULTFIX_H_
#define UMULTFIX_H_
#include <inttypes.h>
#define umultfix(a,b) \
({ \
uint16_t product; \
uint8_t multiplier = a, multiplicand = b, count = 9;\
asm volatile ( \
"mov %A0, %1 \n\t" \
"ldi %B0, 0 \n\t" \
"clc \n\t" \
"mult: ror %B0 \n\t" \
"ror %A0 \n\t" \
"dec %3 \n\t" \
"breq end \n\t" \
"brcc mult \n\t" \
"clc \n\t" \
"adc %B0, %2 \n\t" \
"rjmp mult \n\t" \
"end: \n\t" \
:"=&r" (product): "a" (multiplier), "a" (multiplicand), "a" (count)\
); \
product; \
})
#endif /* UMULTFIX_H_ 开发者_Go百科*/
The problem is I can only use this macro once - the complier doesn't like "mult:" and "end:" being redefined when the macro is inserted to do a multiplication on a different set of arguments. Is there any way around this?
Actually, in AVR gcc inline assembler, you should
make use of the special pattern %=, which is replaced by a unique number on each asm statement
as described, e.g., in the "Cookbook".
Then you would write something like:
jmp someLabel_%=
...
someLabel_%=:
...
The "%=" is automatically replaced by some arbitrary number which makes your label unique.
(Note: You may be heading for trouble when using labels ending in numeric literals: myLabel_1%=
and myLabel_12%=
, for instance, may cause conflicts.)
If you define the following macros:
#define QUOTE_(x) #x
#define QUOTE(x) QUOTE_(x)
Then you can then build the line-number into the assembler label:
...
"mult_" QUOTE(__LINE__) ": ror %B0 \n\t"
...
精彩评论