Search code examples
assemblyavr-gcc

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_ */

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?


Solution

  • 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" 
    ...