C/C++ macro to repeat code
The following code works with GNU C,
#define NOP __asm__("nop")
#define ten(a) a;a;a;a;a;a;a;a;a;a
#define handred(a) ten(ten(a))
int
main()
{
handred(NOP);
return 0;
}
Compile and debug:
code@lab:~/debug$ gcc -g -o debug_NOP debug_NOP.c
code@lab:~/debug$ gdb -q --nh debug_NOP
Reading symbols from debug_NOP...done.
(gdb) set disassembly-flavor intel
(gdb) start
Temporary breakpoint 1 at 0x664: file debug_NOP.c, line 10.
Starting program: /home/code/debug/debug_NOP
Temporary breakpoint 1, main () at debug_NOP.c:10
10 handred(NOP);
(gdb) disassemble
Dump of assembler code for function main:
0x0000555555554660 <+0>: push rbp
0x0000555555554661 <+1>: mov rbp,rsp
=> 0x0000555555554664 <+4>: nop
0x0000555555554665 <+5>: nop
0x0000555555554666 <+6>: nop
0x0000555555554667 <+7>: nop
0x0000555555554668 <+8>: nop
0x0000555555554669 <+9>: nop
....
0x00005555555546c6 <+102>: nop
0x00005555555546c7 <+103>: nop
0x00005555555546c8 <+104>: mov eax,0x0
0x00005555555546cd <+109>: pop rbp
0x00005555555546ce <+110>: ret
End of assembler dump.
If you want to do it without including a whole library or using define, you can use a simple recursive template:
//By Christopher Andrews, released under MIT licence.
template< unsigned N > struct Nops{
static void generate() __attribute__((always_inline)){
__asm__ volatile ("nop");
Nops< N - 1 >::generate();
}
};
template<> struct Nops<0>{ static inline void generate(){} };
void setup() {
Nops<10>::generate();
}
void loop(){}
This will generate the exact number of nop's required.
0000010a setup:
10a: 00 00 nop
10c: 00 00 nop
10e: 00 00 nop
110: 00 00 nop
112: 00 00 nop
114: 00 00 nop
116: 00 00 nop
118: 00 00 nop
11a: 00 00 nop
11c: 00 00 nop
11e: 08 95 ret
I have used this method in a TFT driver for Arduino.
EDIT:
There is another way to easily do this on an AVR compiled with avr-gcc. I'm assuming this may not be available on older toolchains.
In order to delay execution for a specific number of cycles, GCC implements
void __builtin_avr_delay_cycles (unsigned long ticks)
ticks is the number of ticks to delay execution. Note that this built-in does not take into account the effect of interrupts which might increase delay time. ticks must be a compile time integer constant; delays with a variable number of cycles are not supported
From here: https://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/AVR-Built_002din-Functions.html
Boost has Boost.Preprocessor which does this among other things. From:
http://www.boost.org/doc/libs/1_57_0/libs/preprocessor/doc/index.html
BOOST_PP_REPEAT
For your code:
#include <boost/preprocessor/repetition/repeat.hpp>
#define OP(z, n, text) text
...
__asm__( BOOST_PP_REPEAT(5, OP, "noop\n"\t);