aboutsummaryrefslogtreecommitdiff
path: root/libgcc
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2024-12-11 13:28:47 +0100
committerGeorg-Johann Lay <avr@gjlay.de>2024-12-12 14:58:48 +0100
commitf8a602ce5394ef7e0c56b48e3bd89f97f0411c45 (patch)
tree1dd31b86cb3acae79518ae76ba42d1e750bddc62 /libgcc
parentd46c7f313b5a30ee04080f249e31e12987d50aa2 (diff)
downloadgcc-f8a602ce5394ef7e0c56b48e3bd89f97f0411c45.zip
gcc-f8a602ce5394ef7e0c56b48e3bd89f97f0411c45.tar.gz
gcc-f8a602ce5394ef7e0c56b48e3bd89f97f0411c45.tar.bz2
AVR: target/118001 - Add __flashx as 24-bit named address space.
This patch adds __flashx as a new named address space that allocates objects in .progmemx.data. The handling is mostly the same or similar to that of 24-bit space __memx, except that the asm routines are simpler and more efficient. Loads are emit inline when ELPMX or LPMX is available. The address space uses a 24-bit addresses even on devices with a program memory size of 64 KiB or less. PR target/118001 gcc/ * doc/extend.texi (AVR Named Address Spaces): Document __flashx. * config/avr/avr.h (ADDR_SPACE_FLASHX): New enum value. * config/avr/avr-protos.h (avr_out_fload, avr_mem_flashx_p) (avr_fload_libgcc_p, avr_load_libgcc_mem_p) (avr_load_libgcc_insn_p): New. * config/avr/avr.cc (avr_addrspace): Add ADDR_SPACE_FLASHX. (avr_decl_flashx_p, avr_mem_flashx_p, avr_fload_libgcc_p) (avr_load_libgcc_mem_p, avr_load_libgcc_insn_p, avr_out_fload): New functions. (avr_adjust_insn_length) [ADJUST_LEN_FLOAD]: Handle case. (avr_progmem_p) [avr_decl_flashx_p]: return 2. (avr_addr_space_legitimate_address_p) [ADDR_SPACE_FLASHX]: Has same behavior like ADDR_SPACE_MEMX. (avr_addr_space_convert): Use pointer sizes rather then ASes. (avr_addr_space_contains): New function. (avr_convert_to_type): Use it. (avr_emit_cpymemhi): Handle ADDR_SPACE_FLASHX. * config/avr/avr.md (adjust_len) <fload>: New attr value. (gen_load<mode>_libgcc): Renamed from load<mode>_libgcc. (xload8<mode>_A): Iterate over MOVMODE rather than over ALL1. (fxmov<mode>_A): New from xloadv<mode>_A. (xmov<mode>_8): New from xload<mode>_A. (fmov<mode>): New insns. (fxload<mode>_A): New from xload<mode>_A. (fxload_<mode>_libgcc): New from xload_<mode>_libgcc. (*fxload_<mode>_libgcc): New from *xload_<mode>_libgcc. (mov<mode>) [avr_mem_flashx_p]: Hande ADDR_SPACE_FLASHX. (cpymemx_<mode>): Make sure the address space is not lost when splitting. (*cpymemx_<mode>) [ADDR_SPACE_FLASHX]: Use __movmemf_<mode> for asm. (*ashlqi.1.zextpsi_split): New combine pattern. * config/avr/predicates.md (nox_general_operand): Don't match when avr_mem_flashx_p is true. * config/avr/avr-passes.cc (AVR_LdSt_Props): ADDR_SPACE_FLASHX has no post_inc. gcc/testsuite/ * gcc.target/avr/torture/addr-space-1.h [AVR_HAVE_ELPM]: Use a function to bump .progmemx.data to a high address. * gcc.target/avr/torture/addr-space-2.h: Same. * gcc.target/avr/torture/addr-space-1-fx.c: New test. * gcc.target/avr/torture/addr-space-2-fx.c: New test. libgcc/ * config/avr/t-avr (LIB1ASMFUNCS): Add _fload_1, _fload_2, _fload_3, _fload_4, _movmemf. * config/avr/lib1funcs.S (.branch_plus): New .macro. (__xload_1, __xload_2, __xload_3, __xload_4): When the address is located in flash, then forward to... (__fload_1, __fload_2, __fload_3, __fload_4): ...these new functions, respectively. (__movmemx_hi): When the address is located in flash, forward to... (__movmemf_hi): ...this new function.
Diffstat (limited to 'libgcc')
-rw-r--r--libgcc/config/avr/lib1funcs.S240
-rw-r--r--libgcc/config/avr/t-avr9
2 files changed, 162 insertions, 87 deletions
diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index d48b047..ee33277 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -101,6 +101,20 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define XIJMP ijmp
#endif
+;;; [R]JMP to label \labl when \reg is positive (\reg.7 = 0).
+;;; Otherwise, fallthrough.
+.macro .branch_plus reg, labl
+#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
+ ;; Some cores have a problem skipping 2-word instructions
+ tst \reg
+ brmi .L..\@
+#else
+ sbrs \reg, 7
+#endif /* skip erratum */
+ XJMP \labl
+.L..\@:
+.endm ; .branch_plus
+
;; Prologue stuff
.macro do_prologue_saves n_pushed n_frame=0
@@ -2596,34 +2610,6 @@ ENDF __load_4
#define HHI8 21
-.macro .xload dest, n
-#if defined (__AVR_HAVE_ELPMX__)
- elpm \dest, Z+
-#elif defined (__AVR_HAVE_ELPM__)
- elpm
- mov \dest, r0
-.if \dest != D0+\n-1
- adiw r30, 1
- adc HHI8, __zero_reg__
- out __RAMPZ__, HHI8
-.endif
-#elif defined (__AVR_HAVE_LPMX__)
- lpm \dest, Z+
-#else
- lpm
- mov \dest, r0
-.if \dest != D0+\n-1
- adiw r30, 1
-.endif
-#endif
-#if defined (__AVR_HAVE_ELPM__) && defined (__AVR_HAVE_RAMPD__)
-.if \dest == D0+\n-1
- ;; Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM
- out __RAMPZ__, __zero_reg__
-.endif
-#endif
-.endm ; .xload
-
#if defined (L_xload_1)
DEFUN __xload_1
#if defined (__AVR_HAVE_LPMX__) && !defined (__AVR_HAVE_ELPM__)
@@ -2633,14 +2619,8 @@ DEFUN __xload_1
lpm D0, Z
ret
#else
- sbrc HHI8, 7
- rjmp 1f
-#if defined (__AVR_HAVE_ELPM__)
- out __RAMPZ__, HHI8
-#endif /* __AVR_HAVE_ELPM__ */
- .xload D0, 1
- ret
-1: ld D0, Z
+ .branch_plus HHI8, __fload_1
+ ld D0, Z
ret
#endif /* LPMx && ! ELPM */
ENDF __xload_1
@@ -2648,15 +2628,8 @@ ENDF __xload_1
#if defined (L_xload_2)
DEFUN __xload_2
- sbrc HHI8, 7
- rjmp 1f
-#if defined (__AVR_HAVE_ELPM__)
- out __RAMPZ__, HHI8
-#endif /* __AVR_HAVE_ELPM__ */
- .xload D0, 2
- .xload D1, 2
- ret
-1: ld D0, Z+
+ .branch_plus HHI8, __fload_2
+ ld D0, Z+
ld D1, Z+
ret
ENDF __xload_2
@@ -2664,16 +2637,8 @@ ENDF __xload_2
#if defined (L_xload_3)
DEFUN __xload_3
- sbrc HHI8, 7
- rjmp 1f
-#if defined (__AVR_HAVE_ELPM__)
- out __RAMPZ__, HHI8
-#endif /* __AVR_HAVE_ELPM__ */
- .xload D0, 3
- .xload D1, 3
- .xload D2, 3
- ret
-1: ld D0, Z+
+ .branch_plus HHI8, __fload_3
+ ld D0, Z+
ld D1, Z+
ld D2, Z+
ret
@@ -2682,17 +2647,8 @@ ENDF __xload_3
#if defined (L_xload_4)
DEFUN __xload_4
- sbrc HHI8, 7
- rjmp 1f
-#if defined (__AVR_HAVE_ELPM__)
- out __RAMPZ__, HHI8
-#endif /* __AVR_HAVE_ELPM__ */
- .xload D0, 4
- .xload D1, 4
- .xload D2, 4
- .xload D3, 4
- ret
-1: ld D0, Z+
+ .branch_plus HHI8, __fload_4
+ ld D0, Z+
ld D1, Z+
ld D2, Z+
ld D3, Z+
@@ -2705,7 +2661,103 @@ ENDF __xload_4
#if !defined (__AVR_TINY__)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; memcopy from Address Space __pgmx to RAM
+;; Loading n bytes from Flash; n = 1,2,3,4
+;; R22... = Flash[R21:Z]
+;; Clobbers: __tmp_reg__, R21, R30, R31
+
+#if (defined (L_fload_1) \
+ || defined (L_fload_2) \
+ || defined (L_fload_3) \
+ || defined (L_fload_4))
+
+;; Destination
+#define D0 22
+#define D1 D0+1
+#define D2 D0+2
+#define D3 D0+3
+
+;; Register containing bits 16+ of the address
+
+#define HHI8 21
+
+.macro .fload dest, n
+#if defined (__AVR_HAVE_ELPM__)
+.if \dest == D0
+ out __RAMPZ__, HHI8
+.endif
+#endif /* __AVR_HAVE_ELPM__ */
+#if defined (__AVR_HAVE_ELPMX__)
+ elpm \dest, Z+
+#elif defined (__AVR_HAVE_ELPM__)
+ elpm
+ mov \dest, r0
+.if \dest != D0+\n-1
+ adiw r30, 1
+ adc HHI8, __zero_reg__
+ out __RAMPZ__, HHI8
+.endif
+#elif defined (__AVR_HAVE_LPMX__)
+ lpm \dest, Z+
+#else
+ lpm
+ mov \dest, r0
+.if \dest != D0+\n-1
+ adiw r30, 1
+.endif
+#endif
+#if defined (__AVR_HAVE_ELPM__) && defined (__AVR_HAVE_RAMPD__)
+.if \dest == D0+\n-1
+ ;; Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM
+ out __RAMPZ__, __zero_reg__
+.endif
+#endif
+.endm ; .fload
+
+#if defined (L_fload_1)
+DEFUN __fload_1
+#if defined (__AVR_HAVE_LPMX__) && !defined (__AVR_HAVE_ELPM__)
+ lpm D0, Z
+ ret
+#else
+ .fload D0, 1
+ ret
+#endif /* LPMx && ! ELPM */
+ENDF __fload_1
+#endif /* L_fload_1 */
+
+#if defined (L_fload_2)
+DEFUN __fload_2
+ .fload D0, 2
+ .fload D1, 2
+ ret
+ENDF __fload_2
+#endif /* L_fload_2 */
+
+#if defined (L_fload_3)
+DEFUN __fload_3
+ .fload D0, 3
+ .fload D1, 3
+ .fload D2, 3
+ ret
+ENDF __fload_3
+#endif /* L_fload_3 */
+
+#if defined (L_fload_4)
+DEFUN __fload_4
+ .fload D0, 4
+ .fload D1, 4
+ .fload D2, 4
+ .fload D3, 4
+ ret
+ENDF __fload_4
+#endif /* L_fload_4 */
+
+#endif /* L_fload_{1|2|3|4} */
+#endif /* if !defined (__AVR_TINY__) */
+
+#if !defined (__AVR_TINY__)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; memcopy from Address Space __memx to RAM
;; R23:Z = Source Address
;; X = Destination Address
;; Clobbers: __tmp_reg__, R23, R24, R25, X, Z
@@ -2716,7 +2768,7 @@ ENDF __xload_4
#define LOOP 24
DEFUN __movmemx_qi
- ;; #Bytes to copy fity in 8 Bits (1..255)
+ ;; #Bytes to copy fits in 8 Bits (1..255)
;; Zero-extend Loop Counter
clr LOOP+1
;; FALLTHRU
@@ -2724,9 +2776,41 @@ ENDF __movmemx_qi
DEFUN __movmemx_hi
-;; Read from where?
- sbrc HHI8, 7
- rjmp 1f
+ .branch_plus HHI8, __movmemf_hi
+
+ ;; Read 1 Byte from RAM...
+1: ld r0, Z+
+ ;; and store that Byte to RAM Destination
+ st X+, r0
+ sbiw LOOP, 1
+ brne 1b
+ ret
+ENDF __movmemx_hi
+
+#undef HHI8
+#undef LOOP
+
+#endif /* L_movmemx */
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; memcopy from Address Space __flashx to RAM
+;; R23:Z = Source Address
+;; X = Destination Address
+;; Clobbers: __tmp_reg__, R23, R24, R25, X, Z
+
+#if defined (L_movmemf)
+
+#define HHI8 23
+#define LOOP 24
+
+DEFUN __movmemf_qi
+ ;; #Bytes to copy fits in 8 Bits (1..255)
+ ;; Zero-extend Loop Counter
+ clr LOOP+1
+ ;; FALLTHRU
+ENDF __movmemf_qi
+
+DEFUN __movmemf_hi
;; Read from Flash
@@ -2759,22 +2843,12 @@ DEFUN __movmemx_hi
out __RAMPZ__, __zero_reg__
#endif /* ELPM && RAMPD */
ret
-
-;; Read from RAM
-
-1: ;; Read 1 Byte from RAM...
- ld r0, Z+
- ;; and store that Byte to RAM Destination
- st X+, r0
- sbiw LOOP, 1
- brne 1b
- ret
-ENDF __movmemx_hi
+ENDF __movmemf_hi
#undef HHI8
#undef LOOP
-#endif /* L_movmemx */
+#endif /* L_movmemf */
#endif /* !defined (__AVR_TINY__) */
diff --git a/libgcc/config/avr/t-avr b/libgcc/config/avr/t-avr
index 971a092..e9fdb98 100644
--- a/libgcc/config/avr/t-avr
+++ b/libgcc/config/avr/t-avr
@@ -36,13 +36,13 @@ LIB1ASMFUNCS = \
_fmul _fmuls _fmulsu
# The below functions either use registers that are not present
-# in tiny core, or use a different register conventions (don't save
+# in tiny core, or use a different register convention (don't save
# callee saved regs, for example)
# _mulhisi3 and variations - clobber R18, R19
# All *di funcs - use regs < R16 or expect args in regs < R20
# _prologue and _epilogue save registers < R16
-# _load ad _xload variations - expect lpm and elpm support
-# _movmemx - expects elpm/lpm
+# _load, __fload and _xload variations - expect lpm and elpm support
+# _movmemx and _movmemf - expect elpm/lpm
ifneq ($(MULTIFLAGS),-mmcu=avrtiny)
LIB1ASMFUNCS += \
@@ -61,7 +61,8 @@ LIB1ASMFUNCS += \
_epilogue \
_load_3 _load_4 \
_xload_1 _xload_2 _xload_3 _xload_4 \
- _movmemx \
+ _fload_1 _fload_2 _fload_3 _fload_4 \
+ _movmemx _movmemf \
_clzdi2 \
_paritydi2 \
_popcountdi2 \