4

I'd like to clean up my assembly code and povide a way to call "NOP" multiple times through a macro:

#define NOP() asm(" nop")

#define NOP_N( N ) \
    NOP(); \
    NOP(); \
    .... call NOP() N times

I can't figure if this is possible in a macro.

Obviously, for performance reasons, I don't want something like this:

#define NOP_N( n ) { register int i; for(i=0;i<n;i++) asm(" nop"); }

Which defeats the purpose of NOP:

L17:                                    ; NOP_N(3);
        nop
        addi      1,r0                  ; Unsigned
        cmpi      3,r0
        blo       L17

The code is in C and assembly, so no C++ can be involved in here. Also, the compiler is fairly old and doesn't support variadic macros...

5
  • how do you write it as macro for N, call NOP() N times, N has to be know at coding time Commented May 17, 2013 at 8:59
  • 1
    @Mogria: Well if xgbi can use C++, then this could be done fairly simply via template metaprogramming, and no preprocessor trickery would be necessary at all. Commented May 17, 2013 at 9:08
  • Possible duplicate: stackoverflow.com/q/11532883/946850 Commented May 17, 2013 at 9:11
  • Also related: stackoverflow.com/q/319328/946850 Commented May 17, 2013 at 9:16
  • The code is in C and assembly, so no C++ can be involved in here. Also, the compiler is fairly old and doesn't support variadic macros... Commented May 17, 2013 at 9:26

3 Answers 3

7

I don't think a solution for unbounded N is possible. For bounded N you could do something along the following lines:

#define REPEAT_0(WHAT)
#define REPEAT_1(WHAT) WHAT REPEAT_0(WHAT)
#define REPEAT_2(WHAT) WHAT REPEAT_1(WHAT)
#define REPEAT_3(WHAT) WHAT REPEAT_2(WHAT)

#define NOP_N(N) REPEAT_##N(asm("nop");)

The first part can be autogenerated easily. The technique employed for the second part is sometimes called token pasting.

Sign up to request clarification or add additional context in comments.

1 Comment

That's the closest that I can foresee as possible without variadic macros.
2

what about this and Is the C preprocessor Turing complete?:

#define EVAL(...)  EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
#define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
#define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
#define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
#define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__)))
#define EVAL5(...) __VA_ARGS__

AND REPEAT_INDIRECT

#define REPEAT(count, macro, ...) \
    WHEN(count) \
    ( \
        DEFER(REPEAT_INDIRECT) () \
        ( \
            DEC(count), macro, __VA_ARGS__ \
        ) \
        DEFER(macro) \
        ( \
            DEC(count), __VA_ARGS__ \
        ) \
    )
#define REPEAT_INDIRECT() REPEAT

//An example of using this macro
#define M(s, i, _) i
EVAL(REPEAT(8, M, ~)) // 0 1 2 3 4 5 6 7

AND FOREVER:

#define FOREVER() \
    ? \
    DEFER(FOREVER_INDIRECT) () ()
#define FOREVER_INDIRECT() FOREVER
// Outputs question marks forever
EVAL(FOREVER())

1 Comment

Care to elaborate what this code does? Otherwise the link is great in a comment but does not qualify for an answer.
0

If you really want to do this in the preprocessor (and have a C99 compliant compiler) you could use P99_UNROLL from P99.

But you are completely underestimating the optimization that modern compilers are capable. As long as the bounds are compile time constants, a good compiler with optimization should just unroll the code for you. Look into the assembler to be sure (gcc has -S for that).

But you probably could help the compiler a bit by coding this "correctly":

#define NOP_N(N) for(register unsigned i=0; i < (N); i++) asm(" nop")

That is, have the loop counter local to the for and use an unsigned type such that there can't be theoretical issues with overflow.

1 Comment

The thing is that the compiler is old. I checked that using a for loop will actually initialize the integer and not unroll the loop.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.