avr: fix .data initialization for binaries over 64kB
I found that .data is not correctly initialized with firmware images
that use over 64kB of flash. The problem is that the data in .data
(which is stored in flash, and copied to RAM at reset) is beyond the
64kB limit and must therefore be loaded using the elpm instruction
instead of the lpm instruction.
I encountered this issue while getting testdata/math.go to work for AVR.
The following command mostly works with this patch, while it prints
garbage withtout it:
tinygo run -target=simavr -size=short -scheduler=none ./testdata/math.go
(This also requires a patch to picolibc to work, see
https://github.com/picolibc/picolibc/pull/371)
It still doesn't work entirely with this patch: some of the math
operations have an incorrect result. But at least it's an improvement as
it won't print garbage anymore.
Этот коммит содержится в:
родитель
73b368270c
коммит
bb5050a50d
1 изменённых файлов: 13 добавлений и 0 удалений
|
|
@ -11,6 +11,11 @@
|
|||
#define zl r30
|
||||
#define zh r31
|
||||
|
||||
; Ugly hack until https://reviews.llvm.org/D137572 is merged.
|
||||
#if !defined(__AVR_HAVE_ELPM__) && defined(__flash1)
|
||||
#define __AVR_HAVE_ELPM__
|
||||
#endif
|
||||
|
||||
; Startup code
|
||||
.section .text.__vector_RESET
|
||||
.global __vector_RESET
|
||||
|
|
@ -34,11 +39,19 @@ init_data:
|
|||
ldi yh, hi8(_edata)
|
||||
ldi zl, lo8(_sidata)
|
||||
ldi zh, hi8(_sidata)
|
||||
#ifdef __AVR_HAVE_ELPM__
|
||||
ldi r16, hh8(_sidata) ; RAMPZ = hh8(_sidata)
|
||||
out 0x3b, r16
|
||||
#endif
|
||||
init_data_loop:
|
||||
cp xl, yl ; if x == y
|
||||
cpc xh, yh
|
||||
breq init_data_end ; goto main
|
||||
#ifdef __AVR_HAVE_ELPM__
|
||||
elpm r0, Z+ ; r0 = *(z++)
|
||||
#else
|
||||
lpm r0, Z+ ; r0 = *(z++)
|
||||
#endif
|
||||
st X+, r0 ; *(x++) = r0
|
||||
rjmp init_data_loop ; goto init_data_loop
|
||||
init_data_end:
|
||||
|
|
|
|||
Загрузка…
Создание таблицы
Сослаться в новой задаче