Inline assembly without inputs considered const/pure?
Matthias Pfaller
leo@marco.de
Tue Feb 23 08:20:00 GMT 2016
Hi,
I'm using __asm on a cortex-m4 to enable/disable/restore interrupts.
I have defined a couple of macros to manipulate registers only available
by using the msr/mrs opcodes:
> #define mrs(x) ({ \
> volatile unsigned int __r = 0; \
> __asm__ __volatile__("" : : : "memory"); \
> __asm__("mrs %[R]," __STRING(x) : [R] "=r" (__r) : : "cc", "memory");\
> __r; \
> })
>
> #define msr(x, r) \
> __asm__ __volatile__("msr " __STRING(x) ",%[R]": : [R] "r" (r) : "cc", "memory");
Using this I define dfi (disable fast/high priority interrupts), efi
(enable fast/high priority interrupts) and rfi (restore fast/high
priority interrupts):
> typedef unsigned int ilevel_t;
> #define dfi() ({ \
> ilevel_t __sr; \
> __sr = mrs(primask); \
> __asm__ __volatile__("" : : : "memory"); \
> __asm__ __volatile__("cpsid i" : : : "memory"); \
> MARK_DFI(); \
> __sr; \
> })
>
> #define efi() ({ \
> ilevel_t __sr; \
> MARK_EFI(); \
> __sr = mrs(primask); \
> __asm__ __volatile__("" : : : "memory"); \
> __asm__ __volatile__("cpsie i" : : : "memory"); \
> __sr; \
> })
>
Because the "mrs" instruction in the mrs(x) macro is not marked as
volatile the compile is free to optimize it away in cases where I just
call something like:
> dfi();
> ... some code ...
> efi();
while it will compile it when I do:
> ilevel_t sr;
> sr = dfi();
> ... some code ...
> rfi(sr)
What I do not like is that gcc considers mrs as constant and will
optimize away "redundant" mrs instructions in cases like:
> ilevel_t sr;
> sr = dfi();
> ... some code ...
> rfi(sr)
> ... some other code ...
> sr = dfi();
> ... some code ...
> rfi(sr)
With code like this, gcc will reuse the return value of the first mrs
instruction and will not generate a second one for the second assignment
to sr. This is correct in most cases, but when "some other code" calls
functions that manipulate primask it will fail...
How can I mark the mrs instruction as being not constant/pure?
Or to give a different example, if I would have a cpu register that
returns random numbers (like e.g. the r on the z80) how could I write a
__asm__ that will get deleted when the return value is not used, but
will never get deleted when the return value is useds?
regards, Matthias
--
Matthias Pfaller Software Entwicklung
marco Systemanalyse und Entwicklung GmbH Tel +49 8131 5161 41
Hans-Böckler-Str. 2, D 85221 Dachau Fax +49 8131 5161 66
http://www.marco.de/ Email leo@marco.de
Geschäftsführer Martin Reuter HRB 171775 Amtsgericht München
More information about the Gcc-help
mailing list