Inline assembly without inputs considered const/pure?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxx
Geschäftsführer Martin Reuter             HRB 171775 Amtsgericht München



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux