Re: avr-gcc ABI: return 8-bit value from function

Georg-Johann Lay <[email protected]> Sat, 23 Jun 2018 10:23:34 +0200
Newsgroups gmane.comp.hardware.avr.gcc
Message-ID <[email protected]>
Benoit Steinmetz schrieb:
> hi all
> 
> I have written a function in AVR assembler that returns an 8-bit 
> result.  The
> function is called from C, so it should respect the avr-gcc ABI.
> 
> I am a bit confused as to whether the function is required to 
> zero/sign-extend the 8-bit result to 16 bits or not.

Yes.

> The AVR-Libc FAQ mentions that "8-bit return values are 
> zero/sign-extended to
> 16 bits by the called function" [1]

Older versions of avr-gcc extended to 16 bits even though the ABI didn't 
impost that.  For example avr-gcc v3.4.6 (e.g. WinAVR-20060421) emits 
code that extends to 16 bits.  As this is sub-optimal and the compiler 
itself didn't exploit this, newer versions of the compiler no more 
extend to 16 bits.

In any case, assuming that [u]int8_t will be returned as [unsigned] 
8-bit value will work, both with the old versions and the new ones, both 
for assembly and C or any mixture thereof.

Johann

> But on the other hand the code generated by avr-gcc (4.9.2) on my 
> machine does
> not extend 8-bit results to 16 bits.
> 
> example:
> ~~~
> int8_t signed8(void)
> {
>     return -1;
> }
> ~~~
> 
> generated:
> ~~~
> 00000034 <signed8>:
>   34:   8f ef           ldi     r24, 0xFF       ; 255
>   36:   08 95           ret
> ~~~
> 
> 
> I would have expected:
> ~~~
> 00000034 <signed8>:
>   34:   8f ef           ldi     r24, 0xFF       ; 255
>   36:   9f ef           ldi     r25, 0xFF       ; 255
>   38:   08 95           ret
> ~~~
> 
> 
> Also a function using the returned result (cast to int16_t) does not 
> rely on
> the called function to already have sign-extended its result; it rather
> performs the sign extension itself:
> 
> ~~~
> #include <stdint.h>
> 
> int8_t signed8(void);
> void write16(int16_t val);
> 
> int main(void)
> {
>     write16(signed8());
>     return 0;
> }
> ~~~
> 
> 
> generated:
> ~~~
> 0000003c <main>:
>   3c:   fb df           rcall   .-10            ; 0x34 <signed8>
>   3e:   08 2e           mov     r0, r24
>   40:   00 0c           add     r0, r0
>   42:   99 0b           sbc     r25, r25
>   44:   f9 df           rcall   .-14            ; 0x38 <write16>
>   46:   80 e0           ldi     r24, 0x00       ; 0
>   48:   90 e0           ldi     r25, 0x00       ; 0
>   4a:   08 95           ret
> ~~~
> 
> 
> I am using avr-gcc 4.9.2  (shipped with Debian 9.4).  
> Has the ABI changed since
> the last update of the AVR-Libc FAQ (Tue Aug 12 2014), 
> and called functions no
> longer need to extend 8-bit results to 16 bits?
> 
> best regards
> 
> Benoit.
> 
> p.s:  I have recently started a topic on avrfreaks about this issue [2].
> 
> [1] https://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_reg_usage
> [2] https://www.avrfreaks.net/forum/avr-gcc-abi-return-8-bit-value-function