Author Topic: avr-gcc under linux generating incorrect code from assembly  (Read 7913 times)

CBcracker

  • Jr. Member
  • **
  • Posts: 80
avr-gcc under linux generating incorrect code from assembly
« on: August 17, 2013, 03:38:20 pm »
I ran into problems with a simple led flashing program written in assembly;  after a dozen or so tries of flashing slightly different versions of the code, I started looking at the generated code and realized avr-gcc was not putting in proper branch and jump offsets.  I'm running 32-bit OpenSuse, and was initially using the cross-avr-gcc package (which includes avr-gcc-433).  I uninstalled that and installed an rpm of avr-gcc-453; still no go.  And avr-gcc 47.
Next I tried DigisparkArduino-Linux32-1.0.4-May19 (which includes an old avr-gcc-4.3.2).  As expected, no go.
Here's the assembly code:

/* needed for <avr/io.h> to give io constant addresses */
#define __SFR_OFFSET 0

/* AVR CPU definitions based on -mmcu flag */
#include <avr/io.h>


.text
.org 0x0000
        sbi DDRB, DDB0                                  ; set BP0 to output
        ldi r16, 0xff
        sbi PORTB, PORTB0                               ; turn on LED
Delay1:
        adiw XL, 1
        brne Delay1
        cbi PORTB, PORTB0                               ; turn off LED
Delay2:
        adiw XL, 1
        brne Delay2
        inc r0
        brne Delay2
        sbi PORTB, PORTB0                               ; turn on LED
        rjmp Delay1
        rjmp Delay2                                             ; just to check compiler output
;       sbi PINB, PINB0                                 ; toggle pin

Here's a snippet of the dissassembled output (avr-objdump -D)
I'm compiling with -mmcu=attiny85 -x assembler-with-cpp
00000006 <Delay1>:
   6:   11 96           adiw    r26, 0x01       ; 1
   8:   01 f4           brne    .+0             ; 0xa <Delay1+0x4>
   a:   c0 98           cbi     0x18, 0 ; 24

0000000c <Delay2>:
   c:   11 96           adiw    r26, 0x01       ; 1
   e:   01 f4           brne    .+0             ; 0x10 <Delay2+0x4>
  10:   03 94           inc     r0
  12:   01 f4           brne    .+0             ; 0x14 <Delay2+0x8>
  14:   c0 9a           sbi     0x18, 0 ; 24
  16:   00 c0           rjmp    .+0             ; 0x18 <Delay2+0xc>
  18:   00 c0           rjmp    .+0             ; 0x1a <Delay2+0xe>

The brne instructions all generate 01 f4, (offset 0), and the rjmp offsets are both zero as well (actually absolute address 0 since the 12-bit "offset" covers the full 8K (4K word) address space on the tiny85).

Any ideas on how I get a working avr-gcc?


CBcracker

  • Jr. Member
  • **
  • Posts: 80
Re: avr-gcc under linux generating incorrect code from assembly
« Reply #1 on: August 17, 2013, 05:41:19 pm »
Stephan Bärwolf (USBaspLoader author) helped me figure it out.  I didn't link the .o before generating the .hex (doh!).
I added a rule for .bin from .o to the makefile:
 $(CC) -o $@ $<
and then generate the hex
avr-objcopy -j .text -j .data -O ihex $< $@

I had stupidly been creating the .bin from the .o with avr-objcopy (avr-objcopy -j .text -j .data -O binary $< $@)