1

The closest threads to my question are these Escaping a # symbol in a #define macro? and How to print a pound / hash via C preprocessor?, but they don't exactly answer my question. More explicitly, the second doesn't seem to work with the armcc compiler; it just prints hash4 and not the symbol defined by hash. Chris Lutz was especially disparaging of trying use a macro for this functionality in the second post, so maybe this is the incorrect method all together. I would like more thoughts than just one persons, though.

The problem is the following: I'm trying to write a macro that defines an embedded asm C function utilizing a macro. I've essentially implemented it except for one issue... expressing an immediate value. Immediate values' syntax requires (I believe) a pound symbol which is also the "stringify" symbol for the preprocessor. So, is it possible to escape a # symbol in a C macro?

The primary purpose behind this is to wrap an isr with a pico kernels thread context management procedures and that new procedure's function pointer will eventually be passed to the vectored interrupt controller.

Here's the code:

#define ISR_THREAD_MGMT(ISR_FUNC,FUNC_NAME) \
__asm void FUNC_NAME ( void ); \
__asm void FUNC_NAME (void ) \
{ \
    STMDB sp!, {r0-r3}; \
    MRS   r0, SPSR; \
    SUB   lr, lr, #4; \        <----- Heres the problem
    STMDB sp!, {r0, r10, r12, lr}; \
    bl _thread_vectored_context_save; \
    bl ISR_FUNC; \
    b _thread_context_restore; \
}

I hope I've explained everything in sufficient detail. If not, please don't hesitate to ask for any more details.

Community
  • 1
  • 1
Soeldner
  • 13
  • 4
  • My first instinct was "don't use a macro for this", but clearly you've already seen someone else say that, so I'm not sure what you expect us to say - you are trying to use a macro pre-processor to do things it was never designed to do. If you were using at&t syntax, if would magically work because $ [indication of constant] is not a preprocessor "special character". One solution would of course be to actually write out FUNC_NAME and ISR_FUNC in individual functions - or not use the C compiler for assembler code... – Mats Petersson Jan 31 '13 at 01:36
  • Overall, I was wanting a larger consensus than one person's thoughts. So, you are saying specifying embedded assembly instructions as a macro is outside its intended use? Weren't macros originally written to inline function calls? Furthermore, a text preprocessor that doesn't let you write all symbols? Seems strange to me... – Soeldner Jan 31 '13 at 02:00
  • 1
    The C preprocessor is intended for C - it's part of its name. When C was designed, inline assembler was not part of the scope - the compiler would produce assembler, and then assemble through the system assembler - if you wanted to add assembler code yourself, you wrote a `something.s` file - which is still a valid option. Most assemblers do have a macro functionality to let you produce the same code over and over with variations. – Mats Petersson Jan 31 '13 at 02:04
  • Yes, I have it implemented through that method, I just felt since arm has an embedded assembler it wasn't as concise to have extra asm files lying around. I just find it strange that a text preprocessor doesn't allow you to print any characater. Why the restriction do you think? Ease of coding on the parser side? Or they just never saw the use case? – Soeldner Jan 31 '13 at 02:08
  • I guess what I'm saying is, why restrict potential functionality? – Soeldner Jan 31 '13 at 02:14
  • 1
    Well, your use-case isn't exactly "mainstream", is it? But by all means contact ARM and say "Can you please make sure I can use your preprocessor to make inline assembler with # work" - they may add an extension of some sort. I don't see having a "interrupts.s" or something similar in an operating system as "extra asm files" - it's what I expect. Linux has it, Symbian OS has it, as far as I understand, Windows does the same, as does OSE - along with a proprietary OS for Xerox that I don't remember the name of [but I ported the code for]. – Mats Petersson Jan 31 '13 at 02:19
  • Well, I respectfully disagree. Seems to me a text pre processor should allow you to display whatever text you desire. Let the compilers/assemblers decide what works. If I want to display a comment with a pound in without quotation marks, I see no reason that it should be disallowed at that level. Thanks for the discourse. – Soeldner Jan 31 '13 at 02:23
  • Also, my request would be "allow me to specify whatever character I want at the preprocessor stage", not so specific as "make inline assemblers work." Once again, the resolution of whether there is a problem should be handled at a later stage in my mind. – Soeldner Jan 31 '13 at 03:09
  • Yes, but the C preoprocessor will need SOME characters that it uses for it's own purposes. You can use ALMOST any nonsense you like in a preprocessor - as long as it's within valid C character set in general [that is, you MAY not be able to use simplified chineese or russian in the preprocessor]. There is, as far as I understand, only a few exceptions to that - # being the one that comes to mind immediately. – Mats Petersson Jan 31 '13 at 03:12
  • I see what you are saying, but isn't that usually the point of having some sort of escape sequence? So you can have your cake and eat it too? – Soeldner Jan 31 '13 at 03:19

1 Answers1

1

The second of your referenced questions shows you how to do it:

#define hash #
#define mash(x) x
#define immediate(a) mash(hash)a
#define ISR_THREAD_MGMT(ISR_FUNC,FUNC_NAME) \
__asm void FUNC_NAME ( void ); \
__asm void FUNC_NAME ( void ) \
{ \
    STMDB sp!, {r0-r3}; \
    MRS   r0, SPSR; \
    SUB   lr, lr, immediate(4); \
    STMDB sp!, {r0, r10, r12, lr}; \
    bl _thread_vectored_context_save; \
    bl ISR_FUNC; \
    b _thread_context_restore; \
}

ISR_THREAD_MGMT(abc,def)

Output:

# 1 "x.c"
# 1 "<command-line>"
# 1 "x.c"
# 17 "x.c"
__asm void def ( void ); __asm void def ( void ) { STMDB sp!, {r0-r3}; MRS r0, SPSR; SUB lr, lr, #4; STMDB sp!, {r0, r10, r12, lr}; bl _thread_vectored_context_save; bl abc; b _thread_context_restore; }

Output reformatted:

# 1 "x.c"
# 1 "<command-line>"
# 1 "x.c"
# 17 "x.c"
__asm void def ( void );
__asm void def ( void )
{
    STMDB sp!, {r0-r3};
    MRS r0, SPSR;
    SUB lr, lr, #4;
    STMDB sp!, {r0, r10, r12, lr};
    bl _thread_vectored_context_save;
    bl abc;
    b _thread_context_restore;
}

I'm not convinced it is a good idea, but it does at least work.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • I tried that using the armcc compiler to no avail. Are you using gcc? Thanks for the response. – Soeldner Jan 31 '13 at 02:01
  • Do you really need `immediate(4)`? Perhaps `mash(hash)4` would work just as well? A quick test, using `gcc -E ...`, seems to show this. – Joseph Quinsey Jan 31 '13 at 02:27
  • armcc doesn't seem to resolve the hash define properly within function-like macros, unfortunately. It simply prints the parameter 'hash' – Soeldner Jan 31 '13 at 02:39
  • I don't know what `armcc` is up to...but I don't think it is following the C standard. @JosephQuinsey: The notation `immediate(4)` looks to me more recognizable than `mash(hash)4`, so I'd rather use it — if only the relevant C preprocessor worked with it. – Jonathan Leffler Jan 31 '13 at 02:57
  • I think I'm going to contact an ARM representative tomorrow, if I don't have a solution by then. They'll most likely say it is nonexistent functionality, but I'll keep you informed regardless of the response. Thanks for the effort, guys. – Soeldner Jan 31 '13 at 03:02
  • Crap, the method described here works... I had hash undef'd below it. Sign, this is a non issue. Sorry, guys. – Soeldner Feb 01 '13 at 22:13