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

Unexpected assembly output using relative offsets in inline assembler #47093

Closed
s-ol opened this issue Oct 6, 2020 · 7 comments
Closed

Unexpected assembly output using relative offsets in inline assembler #47093

s-ol opened this issue Oct 6, 2020 · 7 comments
Assignees
Labels
backend:AVR bugzilla Issues migrated from bugzilla duplicate Resolved as duplicate

Comments

@s-ol
Copy link

s-ol commented Oct 6, 2020

Bugzilla Link 47749
Version 10.0
OS Linux
Attachments Example Program showing the unexpected behaviour

Extended Description

While porting C source (https://github.com/cpldcpu/light_ws2812/blob/master/light_ws2812_AVR/Light_WS2812/light_ws2812.c) to Zig, which uses LLVM as a backend, I noticed that the "rjmp .+0" instructions that are used as 2-cycle NOPs under avr-gcc assembled to "rjmp .-2" (infinite loops) under Zig and LLVM/Clang.

Here is some code to reproduce:

/*
$ clang -target avr-freestanding-eabi -mmcu=atmega32u2 demo_c.c -c -o demo_c.o
$ avr-gcc -mmcu=atmega32u2 demo_c.o -o demo_c.elf
$ avr-objdump --siassemble=main demo_c.elf

  demo_c.elf:     file format elf32-avr


  Disassembly of section .text:

  00000000 <main>:
     0:	fe cf       	rjmp	.-4      	; 0xfffffffe <__eeprom_end+0xff7efffe>
     2:	ff cf       	rjmp	.-2      	; 0x2 <main+0x2>
     4:	00 c0       	rjmp	.+0      	; 0x6 <main+0x6>
     6:	80 e0       	ldi	r24, 0x00	; 0
     8:	90 e0       	ldi	r25, 0x00	; 0
     a:	08 95       	ret

*/

int main() {
  asm("rjmp .-2");
  asm("rjmp .+0");
  asm("rjmp .+2");
}

(this file is also attached as demo_c.c)

Note that just inspecting the object file created using clang will confusingly show "rjmp .+0" thrice since the actual offset is set using relocation fixups at that stage.

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
@s-ol s-ol changed the title Unexpected assmbly output using relative offsets in inline assembler Unexpected assembly output using relative offsets in inline assembler Dec 16, 2021
@benshi001
Copy link
Member

rjmp seems can not be decoded correctly, for the following assembly program avr5.S,

        .text
        .globl main
        .p2align 1
main:
        ldi   r24, lo8(def) ; Load lower byte of variable def 16-bit address to r24
        ldi   r25, hi8(def) ; Load higher byte of variable def 16-bit address to r25
        rjmp  main

        .section .data
        .type abc, @object
        .type def, @object
        .globl abc
        .globl def
abc:
        .short 100
def:
        .short 200

Build it with command clang avr5.S --target=avr -mmcu=atmega328 -o avr5.out.

avr-objdump can correctly decode the generated avr5.out

0000007c <main>:
  7c:   82 e0           ldi     r24, 0x02       ; 2
  7e:   91 e0           ldi     r25, 0x01       ; 1
  80:   fd cf           rjmp    .-6             ; 0x7c <main>

But llvm-objdump -d avr5.out --mcpu=atmega328 can not decode the rjmp instruction correctly.

0000007c <main>:
      7c: 82 e0         ldi     r24, 2
      7e: 91 e0         ldi     r25, 1
      80: fd cf         rjmp    <unknown>

@benshi001 benshi001 self-assigned this May 16, 2022
@benshi001 benshi001 removed their assignment Aug 15, 2022
@benshi001 benshi001 self-assigned this Jan 1, 2023
@benshi001
Copy link
Member

benshi001 commented Jan 1, 2023

@benshi001
Copy link
Member

@benshi001
Copy link
Member

The above patches fix the bug that the llvm-objdump can not correctly decode RJMP/RCALL and the relative branch instructions.

However clang still emits wrong addend field in the .rela.text of AVR relocatable ELF files, which leads to the original bug reported by @s-ol . I guess the bug may be inside the AVR MC layer.

@gergoerdi
Copy link

In #59962 I have an example which has nothing to do with clang, it shows that llvm-mc generates object file output which doesn't match llc's output for the same input.

@benshi001
Copy link
Member

duplicate to #60019 .

@gergoerdi
Copy link

Input:

	.text
	.globl	main
main:
	rjmp	.-6

llvm-mc output, linked with avr-gcc:

$ llvm-mc --arch=avr --mcpu=atmega32u4 -filetype=obj blah.s -o blah.s.o
$ avr-gcc -mmcu=atmega32u4 blah.s.o -o blah.s.o.elf
$ avr-objdump -d -r blah.s.o.elf 
...
000000c4 <main>:
  c4:	fc cf       	rjmp	.-8      	; 0xbe <__ctors_end+0x12>

@EugeneZelenko EugeneZelenko added the duplicate Resolved as duplicate label Jan 14, 2023
@EugeneZelenko EugeneZelenko closed this as not planned Won't fix, can't repro, duplicate, stale Jan 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AVR bugzilla Issues migrated from bugzilla duplicate Resolved as duplicate
Projects
None yet
Development

No branches or pull requests

4 participants