avr-gcc-list
[Top][All Lists]
Advanced

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

Re: [Fwd: Re: [avr-gcc-list] in-line assembler]


From: Robert von Knobloch
Subject: Re: [Fwd: Re: [avr-gcc-list] in-line assembler]
Date: Tue, 11 Aug 2009 13:56:29 +0200
User-agent: Thunderbird 1.5.0.14 (X11/20060911)

Many thanks for your help Wouter.

No, it's not a pointer to pointer, just:

<load Y-register with address>
< load temp with what is addressed by Y>
<store temp to my return variable>
which is done here :

    "lds r29, ram_address + 1\n\t"      // Load high byte of Y
    "lds r28, ram_address\n\t"          // Load low byte of Y
    "ld __tmp_reg__, Y\n\t"             // Fet value at Y into __tmp_reg__
    "sts rambyte, __tmp_reg__\n\t"      // Store __tmp_reg__ into named 
variable 'rambyte'.
                                        // It's this last line that I have not 
yet achieved using the 'proper' syntax.

but it is wrong.
I seem to have solved my immediate problem but still don't quite understand how 
to save __tmp_reg__ to a named variable.

Just for info, the much simplified:

uint8_t get_ram_byte(uint16_t ram_address)
{
    uint8_t    byte;

    asm  ("ld %0, %a1" : "=&r" (byte) : "e" (ram_address));
    return byte;
}
works fine (I don't really need the temp storage as %0 gets loaded from
the Y-reg directly.
The declaration and usage of 'byte' is completely discarded by the
compiler, it just chooses R24 as %0 and uses that as its uint8_t return:

00000666 <get_ram_byte>:
uint8_t get_ram_byte(uint16_t ram_address)
{
    uint8_t    byte;

    asm  ("ld %0, %a1" : "=&r" (byte) : "e" (ram_address));
 666:    fc 01           movw    r30, r24
 668:    80 81           ld    r24, Z
    return byte;
}
 66a:    08 95           ret

Anyway, many thanks for your help Wouter, I'll try to figure out storage
later.

Robert.

Wouter van Gulik wrote:
> Robert von Knobloch schreef:
>   
>> Hi Wouter,
>>
>> thanks for responding.
>> This is not quite what I want, but your comment about the sts is
>> interesting.
>> I want to achieve this:
>>
>> uint8_t        rambyte;
>> uint16_t ram_address;
>>
>> void get_ram_byte(void)
>> {
>>     asm ("push R28\n\t"
>>     "push R29\n\t"
>>
>>     "lds r29, ram_address + 1\n\t"
>>     "lds r28, ram_address\n\t"
>>     "ld __tmp_reg__, Y\n\t"
>>     "sts rambyte, __tmp_reg__\n\t"
>>
>>     "pop R29\n\t"
>>     "pop R28"::);
>> }
>>
>> Which works but completely ignores the inline-assembler stuff which
>> would do automatic register saving etc.
>> I want to pass a uint16_t address as the argument and get a uint8-t byte
>> returned (which is the contents of the address in ram.
>>     
>
> So you want a pointer to a pointer?
> So in C it would be something like this:
>
> get_ram_byte(char **pp)
> {
>   char c;
>   char *p = *pp;
>   c = *p;
>   *p = c;
>   return c;
> }
>
>   
>> Here is the sts that I want to achieve - namely storing the __tmp_reg__
>> contents into the variable rambyte. Of course this should become the
>> return value (must I store this in a variable first or can the compiler
>> know to return this in whatever the usual register is for a uint8_t () ?.
>>     
>
> You must use a C variable to return the value. Of course you could just 
> tell it to store it to R24 (which is the return register for an 
> uint8_t). But this might will lead to compile warnings and faulty code 
> when GCC decides to inline.
> So don't use __tmp_reg__ but replace it with the construction from my 
> previous mail.
>
>   
>> Btw your example compiled OK but did not assemble.
>>
>> Robert
>>
>> Hi,
>>
>> I don't know what you intended to do but I guess this is more like it 
>> (read the value and write it back):
>> I personally prefer the %[] construction.
>>
>> uint8_t get_ram_byte(uint16_t ram_address)
>> {
>>      uint8_t    byte;
>>
>>      asm  ("ld  %[reg] , %[adr]"  "\n\t"
>>            "sts %[adr] , %[reg]"  "\n\t"
>>      : [reg] "=&r" (byte)
>>      : [adr] "e"   (ram_address));
>>      return byte;
>> }
>>
>> You're construction of "sts %0, __tmp_reg__" is not correct. GCC is 
>> trying to feed sts r24 as first argument, which is invalid.
>> You are feeding him the uninitialized variable 'byte'. Which is also 
>> allocate to R24.
>>
>> HTH,
>>
>> Wouter
>>
>>
>> Robert von Knobloch schreef:
>>     
>>> Hello,
>>> I've been trying to decipher the intricacies of in-line assembler (using
>>> the Inline Assembler Cookbook as my guide).
>>>
>>> I have a very simple application that I cannot seem to realise.
>>>
>>> I want a C function that will return the contents of the RAM address
>>> that I give it as argument.
>>>
>>> My assembler-based function looks like this:
>>>
>>> file is hex.c
>>> =====
>>> uint8_t get_ram_byte(uint16_t ram_address)
>>> {
>>>     uint8_t    byte;
>>>
>>>     asm  ("ld __tmp_reg__, %a1"    "\n\t"
>>>     "sts %0, __tmp_reg__"    "\n\t"
>>>     : "=&r" (byte) : "e" (ram_address));
>>>     return byte;
>>> }
>>>
>>> and is called from
>>>
>>>             rambyte = get_ram_byte(i );
>>>             u_hex8out(rambyte);         // Print byte as 8-bit hex.
>>>
>>> Trying to compile this results in "~/Monitor/hex.c:5: undefined
>>> reference to `r24' "
>>> If I comment out the line "sts %0, __tmp_reg__"    "\n\t" then it
>>> compiles and I see that the parameter is passed in R24,25, copied to
>>> R30,31[Z] and the value is read into R0 [__tmp_reg__].
>>> I cannot see what is wrong with the sts command or why R24 is mentioned.
>>>
>>> Can anybody help me ?
>>>
>>> Many thanks,
>>>
>>> Robert von Knobloch.
>>>
>>>
>>>
>>> _______________________________________________
>>> AVR-GCC-list mailing list
>>> address@hidden
>>> http://lists.nongnu.org/mailman/listinfo/avr-gcc-list
>>>       
>>
>>
>>
>>
>> _______________________________________________
>> AVR-GCC-list mailing list
>> address@hidden
>> http://lists.nongnu.org/mailman/listinfo/avr-gcc-list
>>     
>
>
>
>   





reply via email to

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