avr-libc-dev
[Top][All Lists]
Advanced

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

Re: [avr-libc-dev] volatile in pgmspace.h ?


From: E. Weddington
Subject: Re: [avr-libc-dev] volatile in pgmspace.h ?
Date: Tue, 17 Jun 2003 21:39:00 GMT

> On Tue, Jun 17, 2003 at 07:13:22PM +0000, E. Weddington 
wrote:
> > Again, your comment about how it cannot be guaranteed 
that 
> > gcc will keep the value of Z in between calls to the 
macros 
> > is a strong argument against inclusion of _next() 
macros.
> 
> Hmm... perhaps I was not clear enough, here is an example 
of what
> I'm talking about (enhanced core only, not tested):
> 
> /* byte read with no post-increment, easy */
> #define __LPM_enhanced__(addr) ({                     \
>       uint16_t __addr16 = (uint16_t)(addr);   
        \
>       uint8_t __result;                               \
>       __asm__ (                                       \
>               "lpm %0,Z"                      
        \
>               : "=r" (__result)                       \
>               : "z" (__addr16)                        \
>       );                                      
        \
>       __result;                                       \
> })
> 
> /* byte read with post-increment, ADDR must be a variable 
*/
> #define __LPM_postinc_enhanced__(addr) ({             \
>       uint16_t __addr16 = (uint16_t)(addr);   
        \
>       uint8_t __result;                               \
>       __asm__ (                                       \
>               "lpm %0,Z+"                     
        \
>               : "=r" (__result), "=z" (__addr16)      \
>               : "1" (__addr16)                        \
>       );                                      
        \
>       (addr) = (__typeof__ (addr)) __addr16;  
        \
>       __result;                                       \
> })
> 
> /* word read with no post-increment, the asm code 
clobbers Z
>    so we need a dummy output operand to tell GCC about it 
*/
> #define __LPM_word_enhanced__(addr) ({                
        \
>       uint16_t __addr16 = (uint16_t)(addr);   
        \
>       uint16_t __result;                              \
>       __asm__ (                                       \
>               "lpm %A0,Z+" "\n\t"             
        \
>               "lpm %B0,Z"                     
        \
>               : "=r" (__result), "=z" (__addr16)      \
>               : "1" (__addr16)                        \
>       );                                      
        \
>       __result;                                       \
> })
> 
> /* word read with post-increment, ADDR must be a variable 
*/
> #define __LPM_word_postinc_enhanced__(addr) ({        
        \
>       uint16_t __addr16 = (uint16_t)(addr);   
        \
>       uint16_t __result;                              \
>       __asm__ (                                       \
>               "lpm %A0,Z+" "\n\t"             
        \
>               "lpm %B0,Z+"                    
        \
>               : "=r" (__result), "=z" (__addr16)      \
>               : "1" (__addr16)                        \
>       );                                      
        \
>       (addr) = (__typeof__ (addr)) __addr16;  
        \
>       __result;                                       \
> })
> 
> The _postinc macros expect the ADDR argument to be a 
variable, which
> is incremented during the operation.  The "typeof" is 
here to avoid
> warnings - the address could be a pointer, or integer.
> 
> > then you will probably run into problems as stated: it 
> > cannot be guaranteed that gcc will keep the value of Z 
in 
> > between calls.
> 
> But it can be guaranteed that GCC will keep the value of 
a local
> variable between calls, and that variable will happen to 
be in Z
> at the right time (forced by the "z" constraint for both 
input and
> output of the "asm").  You could even interleave reads 
from two
> or more different arrays in program memory, and GCC 
should do the
> right thing (reload Z as needed).
> 
> If that looks too complicated, well it is... :) so it is 
up to you
> if you want to implement this or not.  I just wanted to 
show that
> it _can_ be done safely, at least I think so...
> 
> Marek
> 


I'm sorry, I didn't mean to cause confusion. Yes, I did 
understand how this could be implemented, and you're right 
that if the macros were written such that a variable was 
passed, then the state of Z is saved to the local var. This 
gets around the non-guarantee issue.

However, this brings up a user issue: we define a macro 
which should only accept a variable and would give an error 
if passed a constant. I don't feel that this would be 
acceptable as a general purpose function for inclusion. 
There would have to be a major "caveat emptor" in the docs, 
which I don't think it would be worth having to explain how 
it works compared to the small amount of optimization it 
provides (doing the post-increment for you). IMHO. YMMV. :)

But as I've also said, I'm not very attached either way. 
Currently I'm not thrilled about implementing them. But I 
won't object to their inclusion as long as it's explained 
in the docs.

Eric

 
 







reply via email to

[Prev in Thread] Current Thread [Next in Thread]