Reputation: 384
I'm working with a microcontroller and want to write a macro that inserts a specific number of wait cycles. I want
DELAY_CYCLES(40)
to expand to
__asm(" RPT #40 || NOP");
Additional restrictions:
Since this is a compiler-specific intrinsic it needs to match exactly. I can't rely on the compiler to merge strings. E.g. __asm(" RPT #""40"" || NOP");
is not correct.
The manufacturer headers already define: #define NOP __asm(" NOP")
I can't pass a string to the intrinsic. char str = " RPT #40 || NOP"; __asm(str);
is not allowed.
At the moment I am not even sure if there is a solution to this special case.
Upvotes: 0
Views: 430
Reputation: 179382
It's quite probable that your compiler will concatenate the string literals properly (despite point #1); GCC and Clang, for instance, will do this. In this case, the simple solution is the following macro:
#define DELAY_CYCLES(X) __asm(" RPT #" #X " || NOP");
But, on the rare occasion when you really need to create a single string, then you may consider some hackery like this:
#define A(X) __asm(#X)
#define B(X) A(X || NOP)
#define HASH #
#define DELAY_CYCLES(X) B(RPT HASH X)
DELAY_CYCLES(40)
expands to __asm("RPT # 40 || NOP")
, even with NOP
defined as something else. The space between #
and 40
cannot, to my knowledge, be elided with this technique unless you want to write DELAY_CYCLES(#40)
or your preprocessor allows you to paste #
and 40
together (GCC does not).
Upvotes: 2