4

I saw the following question: How to generate a newline in a cpp macro?

Let me give a brief requirement of a need in newline in a C++ preprocessor. Am working on ARM Realview compiler 3.1 on a code which uses embedded assembly code with C++ code.

#define DEFINE_FUNCTION(rtype, op, val) \
    __asm rtype nt_##op(void*) { \   
      str lr, [sp, ##val];bl vThunk_##op;ldr lr, [sp,##val];bx lr; \
    } \
   void vThunk_##op(void*)

DEFINE_FUNCTION(void*, mov_lt, #0x04)
{
     // do some operation
}

The above macro declares a embedded assembly function which forcefully requires newline between each statements in the function body.

I think this is because the text in the function body is sent blindly to ARM assembler by ARM compiler.

Why C++ preprocessor is still now not supporting multi-line replacements ? and also i cannot use # in the replacement string. for example, for this kind of assembly,

str lr, [sp, #0x04]

I tried lots of methods and ways, but nothing really worked out. ARM assembler/compiler is so basic that there is no API like asm volatile in GCC.

DEFINE_FUNCTION macro is used at lots of places, so cannot ignore it also.

So, at final resort thinking about the following solutions:

  • Using m4 preprocessor instead of C++ preprocesser
  • Use C++ templates to somehow achieve this and replace DEFINE_FUNCTION using grep/sed

Can anyone give me pointers or ways to do the above things ? I cannot use any compiler other than ARM Realview compiler 3.1.

I need some expansion like below with new line for, DEFINE_FUNCTION(void*, mov_lt, #0x04) {},

__asm void* nt_mov_lt(void*) {   
      str lr, [sp, 0x04];
      bl vThunk_mov_lt;
      ldr lr, [sp,0x04];
      bx lr;
    }
 void vThunk_mov_lt(void*)
 {
     // do something
  }
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
vprajan
  • 1,147
  • 1
  • 11
  • 19

4 Answers4

4

I solved the above problem using GNU m4 preprocessor successfully.

m4_define('DEFINE_FUNCTION','
     __asm rtype nt_$2(void*) {  
      str lr, [sp, $3];
      bl vThunk_$1;
      ldr lr, [sp,$3];
      bx lr;
    } 
   void vThunk_$2(void*)')

DEFINE_FUNCTION(void*, mov_lt, 0x04)
{
}

Preprocessing the above code using m4 solved my problem of newline requirement in code. Ran m4 -P as a prebuild event so that source file is processed even before C preprocessor and compilation stage comes into picture.

Thanks for the help and sorry for confusing a lot. But there is really a scope for good macro pre-processor in latest C++ compilers.

vprajan
  • 1,147
  • 1
  • 11
  • 19
2

every gas version has different newline substitution character e.g. AVR has $ look for the character for ARM gas version

trzeci
  • 21
  • 1
0

I don't know the various C and C++ compilers for ARM, but the following works in 2022 at least with Microsoft compilers for Windows x86 / x64, as well as with Open Watcom compilers (even for DOS):

#define MY_MACRO { \
  _asm { \
    _asm MOV AX, 0 \
    _asm MOV BX, 1 \
  } \
}

The preprocessor turns this into one line, removing the continuation characters and the newline characters, but each _asm token separates the instructions as if there was a newline.

To stress it again, I have no clue about ARM, and the syntax for GCC x86 / x64 is different anyway, but maybe you can apply this idea to your problem.

P.S. I am aware that the outmost curly braces are superfluous, but that's the way I prefer when writing macros like that.

Binarus
  • 4,005
  • 3
  • 25
  • 41
  • This isn't an answer to the question - you're using compilers which are NOT stupid. The problem back in 2009 was that the ARM assembler needed newlines, and the ARM C/C++ compiler wouldn't insert newlines for the ARM assembler so you had to do it manually. – MSalters May 03 '22 at 14:25
  • Please forgive me, but I think that this is an answer to the question. The point of my answer is that with some compilers the `_asm` tokens act like newlines, and that every preprocessor removes the line continuations and newlines, but not the `_asm` tokens. The semicola the OP used are for comments in many assemblers. Coming back to the OP's example, the OP might simply not have come to the idea to try something like that: `__asm str lr, [sp, ##val] __asm bl vThunk_##op __asm ldr lr, [sp,##val] __asm bx lr`. No idea if that would have worked for him, but it might have been worth a try. – Binarus May 03 '22 at 14:44
-1

Your example is extremely confusing, but wouldn't this work?

#define DEFINE_FUNCTION(rtype, op, val) \
    __asm rtype nt_##op(void*) { \   
      str lr, [sp, val];\
      bl vThunk_##op;\
      ldr lr, [sp,val];\
      bx lr;\
    }\
   void vThunk_##op(void*)

and when called like

DEFINE_FUNCTION(void*, mov_lt, 0x04)  // notice no # here
{
     // do some operation
}

you'd get

__asm void* nt_mov_lt(void*) {   
      str lr, [sp, 0x04];
      bl vThunk_mov_lt;
      ldr lr, [sp,0x04];
      bx lr;
    }
 void vThunk_mov_lt(void*)
 {
     // do something
 }

which is exactly what you're asking for.

Blindy
  • 65,249
  • 10
  • 91
  • 131