EmbDev.net

Forum: ARM programming with GCC/GNU tools inline asm syntax question


von Tat W. (Company: Universiti Sains Malaysia) (tcwan)


Rate this post
useful
not useful
Hi,

I'm trying to use #defines in inline assembly. However, I kept getting 
invalid syntax errors.

The following is hardcoded inline assembly:
1
inline void dbg_breakpoint_arm(void) { asm volatile (".word 0xE127FF7F" /* (BKPT32_INSTR | BKPT32_MANUAL_BKPT) */ ); }
which compiles fine in gcc.

When I write it as follows:
1
inline void dbg_breakpoint_arm(void) { asm volatile (".word %0" : "=i" (0xE127FF7F) /* (BKPT32_INSTR | BKPT32_MANUAL_BKPT) */ ); }

gcc gives the following errors (or some variant thereof, this may not be 
the exact error message for the above statement).
./armdebug/Debugger/debug_stub.h: In function 'dbg_breakpoint_arm':
./armdebug/Debugger/debug_stub.h:162:1: error: lvalue required in asm 
statement.

Is there a way for me to use constant #defines as operands for the asm 
statement? What is the correct gcc syntax?

TIA

von Stefan B. (stefan)


Rate this post
useful
not useful
Instead of
1
inline void dbg_breakpoint_arm(void) { asm volatile (".word %0" : "=i" (0xE127FF7F) /* (BKPT32_INSTR | BKPT32_MANUAL_BKPT) */ ); }

try
1
inline void dbg_breakpoint_arm(void) 
2
{ 
3
  asm volatile (".word %0" 
4
    :                  /* Output (empty) */
5
    : "i" (0xE127FF7F) /* (BKPT32_INSTR | BKPT32_MANUAL_BKPT) */ 
6
  ); 
7
}

http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

von Tat W. (Company: Universiti Sains Malaysia) (tcwan)


Rate this post
useful
not useful
@Stefan,

Thanks, I'm not familiar with inline assembly, the gcc reference manual 
was pretty cryptic and did not provide examples that explained things 
clearly (unfortunately I didn't come across the HOWTO before this).

I tried your suggestion, only change was to use the #defines (but it 
does not make any difference to the generated output).
1
inline void dbg_breakpoint_arm(void)
2
{
3
  asm volatile (".word %0"
4
                  :     /* Output (empty) */
5
                  : "i" /* (0xE127FF7F) */ (BKPT32_INSTR | BKPT32_MANUAL_BKPT)
6
               );
7
}

The assembly output file had:
1
        .word #-517472385

which results in "Error: bad expression."
If I remove the '#' manually from the assembly file it passes assembly 
stage without any syntax errors. It seems like the compiler expects 
operands to be passed to instructions (and hence prepends the '#' 
symbol) instead of being used as data values?

von Stefan B. (Guest)


Rate this post
useful
not useful
That is IMHO a puzzler and i found only one strange solution after a 
long search and a lot of trials. I'm not sure this solution is suitable 
for all arm-gcc versions. Mine is 4.1.1 (WinARM) and this works:

1
// I assume your defines look like these
2
#define BKPT32_INSTR        0xE1270000 // BKPT
3
#define BKPT32_MANUAL_BKPT  0x0000FF7F // Argument of BKPT
4
5
int main(void)
6
{
7
  asm volatile (".word %a0" : : "X" (BKPT32_INSTR | BKPT32_MANUAL_BKPT) );
8
}


The usage of modifier in %a0 is based on an old gcc manual
http://sunsite.ualberta.ca/Documentation/Gnu/gcc-2.8.1/html_chapter/gcc_16.html

The c modifier from the same manual doesn't work at all.

von Stefan B. (Guest)


Rate this post
useful
not useful
ADD: Sorry, i wrote main() instead of inline void 
dbg_breakpoint_arm(void). This comes from the tests.

von Tat W. (Company: Universiti Sains Malaysia) (tcwan)


Rate this post
useful
not useful
@Stefan,

Thanks! This works in gcc-4.5.1 as well.

T.C.

von Andreas B. (Guest)


Rate this post
useful
not useful
Why don't you simply use the BKPT instruction provided by the assembler 
instead of assembling it yourself?

Also, given that you probably intend to put the function definition in a 
header to inline it always, you should make it "static inline". 
Otherwise you'll get a "multiple definition" error when linking.

von Tat W. (Company: Universiti Sains Malaysia) (tcwan)


Rate this post
useful
not useful
Hmm. I didn't know about the static inline issue. I'll do that.

I'm actually emulating BKPT on ARMv4T which does not support this 
instruction.
The hex value has to be tweaked as the actual BKPT instr value 0xE1xxx 
does not trigger on ARM7 CPU. I'm using 0xE7xxxx (Undef) which works.

T. C.

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.