diff options
author | Georg-Johann Lay <avr@gjlay.de> | 2024-12-11 13:28:47 +0100 |
---|---|---|
committer | Georg-Johann Lay <avr@gjlay.de> | 2024-12-12 14:58:48 +0100 |
commit | f8a602ce5394ef7e0c56b48e3bd89f97f0411c45 (patch) | |
tree | 1dd31b86cb3acae79518ae76ba42d1e750bddc62 /libgcc | |
parent | d46c7f313b5a30ee04080f249e31e12987d50aa2 (diff) | |
download | gcc-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.S | 240 | ||||
-rw-r--r-- | libgcc/config/avr/t-avr | 9 |
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 \ |