I am trying to write some conditional jumps in AVR assembly using AVR-gcc. According to AVR instruction set manual, the brxx
instructions take in an operand k
, and jumps to PC+k+1
. Also, according to the tutorial PDF from http://www.avrbeginners.net/new/tutorials/jumps-calls-and-the-stack/, I should be able to use the PC
operand to jump like this:
brne PC+2
However, when I write such test code:
#include <avr/io.h>
.section .text
.global main ; Note [5]
main:
sbi _SFR_IO_ADDR(DDRA), PA0
sbi _SFR_IO_ADDR(PORTA), PA0
ldi 16, 0xFF
cpi 16, 0xFF
breq PC + 2
cbi _SFR_IO_ADDR(PORTA), PA0
rjmp end
end:
rjmp end
I get this error:
avr-gcc -mmcu="atmega16" -DF_CPU="16000000UL" -O0 main.S -o main.o
/tmp/ccAa2ySf.o: In function `main':
(.text+0x8): undefined reference to `PC'
collect2: ld returned 1 exit status
make: *** [main.o] Error 1
Apparently PC is not defined in AVR-libc. Then how am I going to do such condition branch? Thanks!
Update 1
I found this question How can I jump relative to the PC using the gnu assembler for AVR? and found that the syntax for gnu as is breq .+2
. However, I get the same error as that question have. When I disassemble using avr-objdump -d main.o
, I do get
74: 01 f0 breq .+0 ; 0x76
Which is the same symptom as that question. I will try using linker script, but I have no experience in that.
Update 2
Actually I found that if I use even numbers in the breq instruction, like breq .+2
or breq .+4
, the objdump shows correct result. However, if I use odd numbers, it will become breq .+0
. Can someone explain why?