Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allocating 32 bit number as registers in AVR inline assembly fails #55159

Open
maribu opened this issue Apr 28, 2022 · 4 comments
Open

allocating 32 bit number as registers in AVR inline assembly fails #55159

maribu opened this issue Apr 28, 2022 · 4 comments
Assignees

Comments

@maribu
Copy link
Contributor

maribu commented Apr 28, 2022

The following proof of concept shows the issue:

#include <stdint.h>

uint32_t foo(void)
{
    uint32_t result;
    __asm__ volatile(
        "ldi %A0, 1"                    "\n\t"
        "ldi %B0, 2"                    "\n\t"
        "ldi %C0, 3"                    "\n\t"
        "ldi %D0, 4"                    "\n\t"
        : "=r"(result)
        : /* no inputs */
        : /* no clobbers */
    );

    return result;
}

Compiling this with avr-gcc -mmcu=atmega328p -Os -S poc.c yields:

	.file	"poc.c"
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__SREG__ = 0x3f
__tmp_reg__ = 0
__zero_reg__ = 1
	.text
.global	foo
	.type	foo, @function
foo:
	push r28
	push r29
	rcall .
	rcall .
	in r28,__SP_L__
	in r29,__SP_H__
/* prologue: function */
/* frame size = 4 */
/* stack size = 6 */
.L__stack_usage = 6
/* #APP */
 ;  6 "poc.c" 1
	ldi r24, 1
	ldi r25, 2
	ldi r26, 3
	ldi r27, 4
	
 ;  0 "" 2
/* #NOAPP */
	movw r22,r24
	movw r24,r26
/* epilogue start */
	pop __tmp_reg__
	pop __tmp_reg__
	pop __tmp_reg__
	pop __tmp_reg__
	pop r29
	pop r28
	ret
	.size	foo, .-foo
	.ident	"GCC: (Alpine Linux) 11.3.0"

However, compilation with clang fails:

 $ clang -target avr -mmcu=atmega328p -Os -S poc.c
poc.c:7:9: error: couldn't allocate output register for constraint 'r'
        "ldi %A0, 1"                    "\n\t"
        ^
1 error generated.
@maribu
Copy link
Contributor Author

maribu commented Apr 28, 2022

Maybe @benshi001 could take a look?

@benshi001
Copy link
Member

Current inline assembly only support the i16 and i8 types. I may need more time to fix that.

@benshi001 benshi001 self-assigned this May 4, 2022
@benshi001
Copy link
Member

Maybe we need to introduce 32-bit register classes.

@sprintersb
Copy link

Maybe we need to introduce 32-bit register classes.

Would be great if this would also work for 64-bit types and aggregates like with avr-gcc. Here is a sample code that compiles with avr-gcc and executes fine with, say avrtest.

typedef __UINT8_TYPE__ uint8_t;
typedef __UINT32_TYPE__ uint32_t;
typedef __UINT64_TYPE__ uint64_t;

typedef struct { uint8_t r, g, b; } rgb_t;

uint32_t get_u32 (void)
{
    uint32_t val;
    __asm ("ldi %A0, lo8(%1)"  "\n\t"
           "ldi %B0, hi8(%1)"  "\n\t"
           "ldi %C0, hlo8(%1)" "\n\t"
           "ldi %D0, hhi8(%1)"
           : "=d" (val)
           : "n" (0xddccbbaa));
    return val;
}

uint64_t get_u64 (void)
{
    uint64_t val;
    __asm ("ldi %A0, 0x11" "\n\t"
           "ldi %B0, 0x22" "\n\t"
           "ldi %C0, 0x33" "\n\t"
           "ldi %D0, 0x44" "\n\t"
           // %r: Print operand without register prefix "r" which allows
           // simple arithmetic on register numbers.  You can find similar
           // code for 64-bit types in AVR-LibC headers for example.
           "ldi %r0+%1-1, 0x88" "\n\t"
           "ldi %r0+%1-2, 0x77" "\n\t"
           "ldi %r0+%1-3, 0x66" "\n\t"
           "ldi %r0+%1-4, 0x55"
           : "=d" (val)
           : "n" (sizeof (val)));
    return val;
}

rgb_t func_rgb (rgb_t rgb)
{
    __asm ("dec %A0" "\n\t"
           "inc %C0"
           : "+r" (rgb));
    return rgb;
}

int main (void)
{
    rgb_t rgb = { 4, 5, 6 };
    rgb = func_rgb (rgb);
    if (rgb.r != 3 || rgb.b != 7)
        __builtin_abort();

    if (get_u32() != 0xddccbbaa)
      __builtin_abort();

    if (get_u64() != 0x8877665544332211)
      __builtin_abort();

    return 0;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants