mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-14 04:20:25 +08:00
re PR target/49868 (Implement named address space to place/access data in flash memory)
gcc/ PR target/49868 * config/avr/avr.h (base_arch_s): Add field n_segments. (ADDR_SPACE_PGM1, ADDR_SPACE_PGM2, ADDR_SPACE_PGM3, ADDR_SPACE_PGM4, ADDR_SPACE_PGM5, ADDR_SPACE_PGMX): New address spaces. (AVR_HAVE_ELPM, AVR_HAVE_ELPMX): New defines. (INIT_EXPANDERS): New define. * config/avr/avr-protos.h (avr_mem_pgmx_p): New. (avr_init_expanders): New. (avr_emit_movmemhi, avr_out_movmem): New. (avr_xload_libgcc_p): New. * config/avr/avr-c.c (avr_register_target_pragmas): Register address spaces __pgm1, __pgm2, __pgm3, __pgm4 __pgm5, __pgmx. (avr_cpu_cpp_builtins): Add built-in defines __PGM1, __PGM2, __PGM3, __PGM4, __PGM5, __PGMX. * config/avr/avr-devices.c (avr_arch_types): Set field n_segments. * config/avr/avr.c (AVR_SECTION_PROGMEM): Change define to cover 3 bits instead of just 1. (xstring_empty, xstring_e, rampz_rtx): New static GTYed variables. (progmem_section): Change from section to array of sections. (progmem_section_prefix): New static variable. (avr_file_start): Print set for __RAMPZ__ (avr_option_override): Move initialization of RTXes from here... (avr_init_expanders): ...to this new function. (avr_pgm_segment): New static function. (avr_decl_pgm_p): Handle error_mark_node. (avr_mem_pgmx_p, avr_decl_pgmx_p): New static functions. (avr_out_xload, avr_find_unused_d_reg): New static functions. (expand_prologue, expand_epilogue): Use rampz_rtx. (print_operand): Hande CONST_STRING. (avr_xload_libgcc_p): New static function. (avr_out_lpm_no_lpmx, avr_out_lpm): Handle ELPM. (avr_progmem_p): Return 2 for 24-bit flash address space. (avr_out_sbxx_branch): Clean-up code from ASn macros. (out_movqi_r_mr, out_movqi_mr_r): Ditto. And recognize RAMPZ's address and print symbolically. (avr_asm_named_section, avr_section_type_flags, avr_encode_section_info, avr_asm_select_section, avr_addr_space_address_mode, avr_addr_space_pointer_mode, avr_addr_space_legitimate_address_p, avr_addr_space_convert, avr_addr_space_legitimize_address): Handle new address spaces. (avr_output_progmem_section_asm_op): New static function. (avr_asm_init_sections): Initialize progmem_section[]. (adjust_insn_length): Handle ADJUST_LEN_XLOAD, ADJUST_LEN_MOVMEM. (avr_const_address_lo16): New static function. (avr_assemble_integer): Use it to handle 3-byte integers. (avr_emit_movmemhi, avr_out_movmem): New functions. * config/avr/predicates.md (nox_general_operand): Handle new address spaces. * config/avr/avr.md (unspec): Add UNSPEC_MOVMEM. (adjust_len): Add xload, movmem. (SP_ADDR): New define_constants. (isa): Add "lpm", "lpmx", "elpm", "elpmx". (enabled): Handle them. (load<mode>_libgcc): New expander. (*load.<mode>.libgcc): Rename to load_<mode>_libgcc. (xload8_A, xload<mode>_A): New insn-and-splits. (xload_8, xload_<mode>_libgcc, xload_<mode>, loadmem_elpm): New insns. (mov<mode>): Handle new address spaces. (movmemhi): Rewrite using avr_emit_movmemhi. (MOVMEM_r_d): New mode attribute. (movmem_<mode>, movmem_qi_elpm): New insns. (setmemhi, *clrmemqi, *clrmemhi, strlenhi, *strlenhi): Unquote C-code. Use label instead of hard-coded instrunction lengths. libgcc/ PR target/49868 * config/avr/t-avr (LIB1ASMFUNCS): Add _xload_2 _xload_3 _xload_4. * config/avr/lib1funcs.S (__xload_2, __xload_3, __xload_4): New functions. From-SVN: r181482
This commit is contained in:
parent
59659b5967
commit
7bc6df2ca1
@ -1,3 +1,71 @@
|
||||
2011-11-18 Georg-Johann Lay <avr@gjlay.de>
|
||||
|
||||
PR target/49868
|
||||
* config/avr/avr.h (base_arch_s): Add field n_segments.
|
||||
(ADDR_SPACE_PGM1, ADDR_SPACE_PGM2, ADDR_SPACE_PGM3,
|
||||
ADDR_SPACE_PGM4, ADDR_SPACE_PGM5, ADDR_SPACE_PGMX): New address spaces.
|
||||
(AVR_HAVE_ELPM, AVR_HAVE_ELPMX): New defines.
|
||||
(INIT_EXPANDERS): New define.
|
||||
* config/avr/avr-protos.h (avr_mem_pgmx_p): New.
|
||||
(avr_init_expanders): New.
|
||||
(avr_emit_movmemhi, avr_out_movmem): New.
|
||||
(avr_xload_libgcc_p): New.
|
||||
* config/avr/avr-c.c (avr_register_target_pragmas): Register
|
||||
address spaces __pgm1, __pgm2, __pgm3, __pgm4 __pgm5, __pgmx.
|
||||
(avr_cpu_cpp_builtins): Add built-in defines __PGM1,
|
||||
__PGM2, __PGM3, __PGM4, __PGM5, __PGMX.
|
||||
* config/avr/avr-devices.c (avr_arch_types): Set field n_segments.
|
||||
|
||||
* config/avr/avr.c (AVR_SECTION_PROGMEM): Change define to cover
|
||||
3 bits instead of just 1.
|
||||
(xstring_empty, xstring_e, rampz_rtx): New static GTYed variables.
|
||||
(progmem_section): Change from section to array of sections.
|
||||
(progmem_section_prefix): New static variable.
|
||||
(avr_file_start): Print set for __RAMPZ__
|
||||
(avr_option_override): Move initialization of RTXes from here...
|
||||
(avr_init_expanders): ...to this new function.
|
||||
(avr_pgm_segment): New static function.
|
||||
(avr_decl_pgm_p): Handle error_mark_node.
|
||||
(avr_mem_pgmx_p, avr_decl_pgmx_p): New static functions.
|
||||
(avr_out_xload, avr_find_unused_d_reg): New static functions.
|
||||
(expand_prologue, expand_epilogue): Use rampz_rtx.
|
||||
(print_operand): Hande CONST_STRING.
|
||||
(avr_xload_libgcc_p): New static function.
|
||||
(avr_out_lpm_no_lpmx, avr_out_lpm): Handle ELPM.
|
||||
(avr_progmem_p): Return 2 for 24-bit flash address space.
|
||||
(avr_out_sbxx_branch): Clean-up code from ASn macros.
|
||||
(out_movqi_r_mr, out_movqi_mr_r): Ditto. And recognize RAMPZ's
|
||||
address and print symbolically.
|
||||
(avr_asm_named_section, avr_section_type_flags,
|
||||
avr_encode_section_info, avr_asm_select_section,
|
||||
avr_addr_space_address_mode, avr_addr_space_pointer_mode,
|
||||
avr_addr_space_legitimate_address_p, avr_addr_space_convert,
|
||||
avr_addr_space_legitimize_address): Handle new address spaces.
|
||||
(avr_output_progmem_section_asm_op): New static function.
|
||||
(avr_asm_init_sections): Initialize progmem_section[].
|
||||
(adjust_insn_length): Handle ADJUST_LEN_XLOAD, ADJUST_LEN_MOVMEM.
|
||||
(avr_const_address_lo16): New static function.
|
||||
(avr_assemble_integer): Use it to handle 3-byte integers.
|
||||
(avr_emit_movmemhi, avr_out_movmem): New functions.
|
||||
|
||||
* config/avr/predicates.md (nox_general_operand): Handle new
|
||||
address spaces.
|
||||
* config/avr/avr.md (unspec): Add UNSPEC_MOVMEM.
|
||||
(adjust_len): Add xload, movmem.
|
||||
(SP_ADDR): New define_constants.
|
||||
(isa): Add "lpm", "lpmx", "elpm", "elpmx".
|
||||
(enabled): Handle them.
|
||||
(load<mode>_libgcc): New expander.
|
||||
(*load.<mode>.libgcc): Rename to load_<mode>_libgcc.
|
||||
(xload8_A, xload<mode>_A): New insn-and-splits.
|
||||
(xload_8, xload_<mode>_libgcc, xload_<mode>, loadmem_elpm): New insns.
|
||||
(mov<mode>): Handle new address spaces.
|
||||
(movmemhi): Rewrite using avr_emit_movmemhi.
|
||||
(MOVMEM_r_d): New mode attribute.
|
||||
(movmem_<mode>, movmem_qi_elpm): New insns.
|
||||
(setmemhi, *clrmemqi, *clrmemhi, strlenhi, *strlenhi): Unquote
|
||||
C-code. Use label instead of hard-coded instrunction lengths.
|
||||
|
||||
2011-11-18 Martin Jambor <mjambor@suse.cz>
|
||||
|
||||
PR tree-optimization/50605
|
||||
|
@ -37,6 +37,12 @@ void
|
||||
avr_register_target_pragmas (void)
|
||||
{
|
||||
c_register_addr_space ("__pgm", ADDR_SPACE_PGM);
|
||||
c_register_addr_space ("__pgm1", ADDR_SPACE_PGM1);
|
||||
c_register_addr_space ("__pgm2", ADDR_SPACE_PGM2);
|
||||
c_register_addr_space ("__pgm3", ADDR_SPACE_PGM3);
|
||||
c_register_addr_space ("__pgm4", ADDR_SPACE_PGM4);
|
||||
c_register_addr_space ("__pgm5", ADDR_SPACE_PGM5);
|
||||
c_register_addr_space ("__pgmx", ADDR_SPACE_PGMX);
|
||||
}
|
||||
|
||||
|
||||
@ -109,6 +115,12 @@ avr_cpu_cpp_builtins (struct cpp_reader *pfile)
|
||||
if (!strcmp (lang_hooks.name, "GNU C"))
|
||||
{
|
||||
cpp_define (pfile, "__PGM=__pgm");
|
||||
cpp_define (pfile, "__PGM1=__pgm1");
|
||||
cpp_define (pfile, "__PGM2=__pgm2");
|
||||
cpp_define (pfile, "__PGM3=__pgm3");
|
||||
cpp_define (pfile, "__PGM4=__pgm4");
|
||||
cpp_define (pfile, "__PGM5=__pgm5");
|
||||
cpp_define (pfile, "__PGMX=__pgmx");
|
||||
}
|
||||
|
||||
/* Define builtin macros so that the user can
|
||||
|
@ -25,18 +25,27 @@
|
||||
|
||||
/* List of all known AVR MCU architectures. */
|
||||
|
||||
const struct base_arch_s avr_arch_types[] = {
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, NULL, "avr2" }, /* unknown device specified */
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, "__AVR_ARCH__=1", "avr1" },
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, "__AVR_ARCH__=2", "avr2" },
|
||||
{ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0x0060, "__AVR_ARCH__=25", "avr25" },
|
||||
{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, "__AVR_ARCH__=3", "avr3" },
|
||||
{ 0, 0, 1, 0, 1, 0, 0, 0, 0, 0x0060, "__AVR_ARCH__=31", "avr31" },
|
||||
{ 0, 0, 1, 1, 0, 0, 0, 0, 0, 0x0060, "__AVR_ARCH__=35", "avr35" },
|
||||
{ 0, 1, 0, 1, 0, 0, 0, 0, 0, 0x0060, "__AVR_ARCH__=4", "avr4" },
|
||||
{ 0, 1, 1, 1, 0, 0, 0, 0, 0, 0x0060, "__AVR_ARCH__=5", "avr5" },
|
||||
{ 0, 1, 1, 1, 1, 1, 0, 0, 0, 0x0060, "__AVR_ARCH__=51", "avr51" },
|
||||
{ 0, 1, 1, 1, 1, 1, 1, 0, 0, 0x0060, "__AVR_ARCH__=6", "avr6" }
|
||||
const struct base_arch_s
|
||||
avr_arch_types[] =
|
||||
{
|
||||
/* unknown device specified */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 1, NULL, "avr2" },
|
||||
/*
|
||||
A M J L E E E d S # F
|
||||
S U M P L L I a t 6 l
|
||||
M L P M P P J - - t a 4 a
|
||||
X M M M a r s
|
||||
X P t k h */
|
||||
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 1, "__AVR_ARCH__=1", "avr1" },
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 1, "__AVR_ARCH__=2", "avr2" },
|
||||
{ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0x0060, 1, "__AVR_ARCH__=25", "avr25" },
|
||||
{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 1, "__AVR_ARCH__=3", "avr3" },
|
||||
{ 0, 0, 1, 0, 1, 0, 0, 0, 0, 0x0060, 2, "__AVR_ARCH__=31", "avr31" },
|
||||
{ 0, 0, 1, 1, 0, 0, 0, 0, 0, 0x0060, 1, "__AVR_ARCH__=35", "avr35" },
|
||||
{ 0, 1, 0, 1, 0, 0, 0, 0, 0, 0x0060, 1, "__AVR_ARCH__=4", "avr4" },
|
||||
{ 0, 1, 1, 1, 0, 0, 0, 0, 0, 0x0060, 1, "__AVR_ARCH__=5", "avr5" },
|
||||
{ 0, 1, 1, 1, 1, 1, 0, 0, 0, 0x0060, 2, "__AVR_ARCH__=51", "avr51" },
|
||||
{ 0, 1, 1, 1, 1, 1, 1, 0, 0, 0x0060, 4, "__AVR_ARCH__=6", "avr6" }
|
||||
};
|
||||
|
||||
const struct mcu_type_s avr_mcu_types[] = {
|
||||
|
@ -34,6 +34,7 @@ extern int avr_hard_regno_rename_ok (unsigned int, unsigned int);
|
||||
extern rtx avr_return_addr_rtx (int count, rtx tem);
|
||||
extern void avr_register_target_pragmas (void);
|
||||
extern bool avr_accumulate_outgoing_args (void);
|
||||
extern void avr_init_expanders (void);
|
||||
|
||||
#ifdef TREE_CODE
|
||||
extern void avr_asm_output_aligned_decl_common (FILE*, const_tree, const char*, unsigned HOST_WIDE_INT, unsigned int, bool);
|
||||
@ -84,6 +85,7 @@ extern bool avr_rotate_bytes (rtx operands[]);
|
||||
|
||||
extern void expand_prologue (void);
|
||||
extern void expand_epilogue (bool);
|
||||
extern bool avr_emit_movmemhi (rtx*);
|
||||
extern int avr_epilogue_uses (int regno);
|
||||
extern int avr_starting_frame_offset (void);
|
||||
|
||||
@ -94,6 +96,8 @@ extern const char* avr_out_bitop (rtx, rtx*, int*);
|
||||
extern const char* avr_out_plus (rtx*, int*, int*);
|
||||
extern const char* avr_out_plus_noclobber (rtx*, int*, int*);
|
||||
extern const char* avr_out_addto_sp (rtx*, int*);
|
||||
extern const char* avr_out_xload (rtx, rtx*, int*);
|
||||
extern const char* avr_out_movmem (rtx, rtx*, int*);
|
||||
extern bool avr_popcount_each_byte (rtx, int, int);
|
||||
|
||||
extern int extra_constraint_Q (rtx x);
|
||||
@ -122,7 +126,9 @@ extern bool avr_regno_mode_code_ok_for_base_p (int, enum machine_mode, addr_spac
|
||||
extern rtx avr_incoming_return_addr_rtx (void);
|
||||
extern rtx avr_legitimize_reload_address (rtx*, enum machine_mode, int, int, int, int, rtx (*)(rtx,int));
|
||||
extern bool avr_mem_pgm_p (rtx);
|
||||
extern bool avr_mem_pgmx_p (rtx);
|
||||
extern bool avr_load_libgcc_p (rtx);
|
||||
extern bool avr_xload_libgcc_p (enum machine_mode);
|
||||
#endif /* RTX_CODE */
|
||||
|
||||
#ifdef REAL_VALUE_TYPE
|
||||
|
1193
gcc/config/avr/avr.c
1193
gcc/config/avr/avr.c
File diff suppressed because it is too large
Load Diff
@ -54,6 +54,9 @@ struct base_arch_s {
|
||||
/* Default start of data section address for architecture. */
|
||||
int default_data_section_start;
|
||||
|
||||
/* Number of 64k segments in the flash. */
|
||||
int n_segments;
|
||||
|
||||
const char *const macro;
|
||||
|
||||
/* Architecture name. */
|
||||
@ -131,6 +134,8 @@ extern const struct base_arch_s avr_arch_types[];
|
||||
#define AVR_HAVE_MUL (avr_current_arch->have_mul)
|
||||
#define AVR_HAVE_MOVW (avr_current_arch->have_movw_lpmx)
|
||||
#define AVR_HAVE_LPMX (avr_current_arch->have_movw_lpmx)
|
||||
#define AVR_HAVE_ELPM (avr_current_arch->have_elpm)
|
||||
#define AVR_HAVE_ELPMX (avr_current_arch->have_elpmx)
|
||||
#define AVR_HAVE_RAMPZ (avr_current_arch->have_elpm)
|
||||
#define AVR_HAVE_EIJMP_EICALL (avr_current_arch->have_eijmp_eicall)
|
||||
#define AVR_HAVE_8BIT_SP (avr_current_device->short_sp || TARGET_TINY_STACK)
|
||||
@ -393,6 +398,12 @@ typedef struct avr_args {
|
||||
|
||||
|
||||
#define ADDR_SPACE_PGM 1
|
||||
#define ADDR_SPACE_PGM1 2
|
||||
#define ADDR_SPACE_PGM2 3
|
||||
#define ADDR_SPACE_PGM3 4
|
||||
#define ADDR_SPACE_PGM4 5
|
||||
#define ADDR_SPACE_PGM5 6
|
||||
#define ADDR_SPACE_PGMX 7
|
||||
|
||||
#define REGISTER_TARGET_PRAGMAS() \
|
||||
do { \
|
||||
@ -645,3 +656,5 @@ struct GTY(()) machine_function
|
||||
#define PUSH_ROUNDING(X) (X)
|
||||
|
||||
#define ACCUMULATE_OUTGOING_ARGS avr_accumulate_outgoing_args()
|
||||
|
||||
#define INIT_EXPANDERS avr_init_expanders()
|
||||
|
@ -47,11 +47,15 @@
|
||||
(ZERO_REGNO 1) ; zero register r1
|
||||
|
||||
(SREG_ADDR 0x5F)
|
||||
(SP_ADDR 0x5D)
|
||||
|
||||
;; Register holding the address' high part when loading via ELPM
|
||||
(RAMPZ_ADDR 0x5B)
|
||||
])
|
||||
|
||||
(define_c_enum "unspec"
|
||||
[UNSPEC_STRLEN
|
||||
UNSPEC_MOVMEM
|
||||
UNSPEC_INDEX_JMP
|
||||
UNSPEC_FMUL
|
||||
UNSPEC_FMULS
|
||||
@ -128,6 +132,7 @@
|
||||
"out_bitop, out_plus, out_plus_noclobber, addto_sp,
|
||||
tsthi, tstpsi, tstsi, compare, call,
|
||||
mov8, mov16, mov24, mov32, reload_in16, reload_in24, reload_in32,
|
||||
xload, movmem,
|
||||
ashlqi, ashrqi, lshrqi,
|
||||
ashlhi, ashrhi, lshrhi,
|
||||
ashlsi, ashrsi, lshrsi,
|
||||
@ -137,15 +142,14 @@
|
||||
|
||||
;; Flavours of instruction set architecture (ISA), used in enabled attribute
|
||||
|
||||
;; mov: ISA has no MOVW
|
||||
;; movw: ISA has MOVW
|
||||
;; rjmp: ISA has no CALL/JMP
|
||||
;; jmp: ISA has CALL/JMP
|
||||
;; ijmp: ISA has no EICALL/EIJMP
|
||||
;; eijmp: ISA has EICALL/EIJMP
|
||||
;; mov : ISA has no MOVW movw : ISA has MOVW
|
||||
;; rjmp : ISA has no CALL/JMP jmp : ISA has CALL/JMP
|
||||
;; ijmp : ISA has no EICALL/EIJMP eijmp : ISA has EICALL/EIJMP
|
||||
;; lpm : ISA has no LPMX lpmx : ISA has LPMX
|
||||
;; elpm : ISA has ELPM but no ELPMX elpmx : ISA has ELPMX
|
||||
|
||||
(define_attr "isa"
|
||||
"mov,movw, rjmp,jmp, ijmp,eijmp,
|
||||
"mov,movw, rjmp,jmp, ijmp,eijmp, lpm,lpmx, elpm,elpmx,
|
||||
standard"
|
||||
(const_string "standard"))
|
||||
|
||||
@ -176,6 +180,22 @@
|
||||
(and (eq_attr "isa" "eijmp")
|
||||
(match_test "AVR_HAVE_EIJMP_EICALL"))
|
||||
(const_int 1)
|
||||
|
||||
(and (eq_attr "isa" "lpm")
|
||||
(match_test "!AVR_HAVE_LPMX"))
|
||||
(const_int 1)
|
||||
|
||||
(and (eq_attr "isa" "lpmx")
|
||||
(match_test "AVR_HAVE_LPMX"))
|
||||
(const_int 1)
|
||||
|
||||
(and (eq_attr "isa" "elpm")
|
||||
(match_test "AVR_HAVE_ELPM && !AVR_HAVE_ELPMX"))
|
||||
(const_int 1)
|
||||
|
||||
(and (eq_attr "isa" "elpmx")
|
||||
(match_test "AVR_HAVE_ELPMX"))
|
||||
(const_int 1)
|
||||
] (const_int 0)))
|
||||
|
||||
|
||||
@ -243,12 +263,10 @@
|
||||
;; even though its function is identical to that in builtins.c
|
||||
|
||||
(define_expand "nonlocal_goto"
|
||||
[
|
||||
(use (match_operand 0 "general_operand"))
|
||||
(use (match_operand 1 "general_operand"))
|
||||
(use (match_operand 2 "general_operand"))
|
||||
(use (match_operand 3 "general_operand"))
|
||||
]
|
||||
[(use (match_operand 0 "general_operand"))
|
||||
(use (match_operand 1 "general_operand"))
|
||||
(use (match_operand 2 "general_operand"))
|
||||
(use (match_operand 3 "general_operand"))]
|
||||
""
|
||||
{
|
||||
rtx r_label = copy_to_reg (operands[1]);
|
||||
@ -333,7 +351,7 @@
|
||||
set_mem_addr_space (operands[1], ADDR_SPACE_PGM);
|
||||
})
|
||||
|
||||
(define_insn "*load.<mode>.libgcc"
|
||||
(define_insn "load_<mode>_libgcc"
|
||||
[(set (reg:MOVMODE 22)
|
||||
(match_operand:MOVMODE 0 "memory_operand" "m,m"))]
|
||||
"avr_load_libgcc_p (operands[0])
|
||||
@ -348,6 +366,135 @@
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
|
||||
(define_insn_and_split "xload8_A"
|
||||
[(set (match_operand:QI 0 "register_operand" "=r")
|
||||
(match_operand:QI 1 "memory_operand" "m"))
|
||||
(clobber (reg:HI REG_Z))]
|
||||
"can_create_pseudo_p()
|
||||
&& avr_mem_pgmx_p (operands[1])
|
||||
&& REG_P (XEXP (operands[1], 0))"
|
||||
{ gcc_unreachable(); }
|
||||
"&& 1"
|
||||
[(clobber (const_int 0))]
|
||||
{
|
||||
rtx insn, addr = XEXP (operands[1], 0);
|
||||
rtx hi8 = gen_reg_rtx (QImode);
|
||||
rtx reg_z = gen_rtx_REG (HImode, REG_Z);
|
||||
|
||||
emit_move_insn (reg_z, simplify_gen_subreg (HImode, addr, PSImode, 0));
|
||||
emit_move_insn (hi8, simplify_gen_subreg (QImode, addr, PSImode, 2));
|
||||
|
||||
insn = emit_insn (gen_xload_8 (operands[0], hi8));
|
||||
set_mem_addr_space (SET_SRC (single_set (insn)),
|
||||
MEM_ADDR_SPACE (operands[1]));
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_insn_and_split "xload<mode>_A"
|
||||
[(set (match_operand:MOVMODE 0 "register_operand" "=r")
|
||||
(match_operand:MOVMODE 1 "memory_operand" "m"))
|
||||
(clobber (reg:QI 21))
|
||||
(clobber (reg:HI REG_Z))]
|
||||
"QImode != <MODE>mode
|
||||
&& can_create_pseudo_p()
|
||||
&& avr_mem_pgmx_p (operands[1])
|
||||
&& REG_P (XEXP (operands[1], 0))"
|
||||
{ gcc_unreachable(); }
|
||||
"&& 1"
|
||||
[(clobber (const_int 0))]
|
||||
{
|
||||
rtx addr = XEXP (operands[1], 0);
|
||||
rtx reg_z = gen_rtx_REG (HImode, REG_Z);
|
||||
rtx addr_hi8 = simplify_gen_subreg (QImode, addr, PSImode, 2);
|
||||
addr_space_t as = MEM_ADDR_SPACE (operands[1]);
|
||||
rtx hi8, insn;
|
||||
|
||||
emit_move_insn (reg_z, simplify_gen_subreg (HImode, addr, PSImode, 0));
|
||||
|
||||
if (avr_xload_libgcc_p (<MODE>mode))
|
||||
{
|
||||
emit_move_insn (gen_rtx_REG (QImode, 21), addr_hi8);
|
||||
insn = emit_insn (gen_xload_<mode>_libgcc ());
|
||||
emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, 22));
|
||||
}
|
||||
else if (avr_current_arch->n_segments == 1
|
||||
&& GET_MODE_SIZE (<MODE>mode) > 2
|
||||
&& !AVR_HAVE_LPMX)
|
||||
{
|
||||
rtx src = gen_rtx_MEM (<MODE>mode, reg_z);
|
||||
|
||||
as = ADDR_SPACE_PGM;
|
||||
insn = emit_insn (gen_load_<mode>_libgcc (src));
|
||||
emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, 22));
|
||||
}
|
||||
else
|
||||
{
|
||||
hi8 = gen_reg_rtx (QImode);
|
||||
emit_move_insn (hi8, addr_hi8);
|
||||
insn = emit_insn (gen_xload_<mode> (operands[0], hi8));
|
||||
}
|
||||
|
||||
set_mem_addr_space (SET_SRC (single_set (insn)), as);
|
||||
|
||||
DONE;
|
||||
})
|
||||
|
||||
;; Move value from address space pgmx to a register
|
||||
;; These insns must be prior to respective generic move insn.
|
||||
|
||||
(define_insn "xload_8"
|
||||
[(set (match_operand:QI 0 "register_operand" "=r")
|
||||
(mem:QI (lo_sum:PSI (match_operand:QI 1 "register_operand" "r")
|
||||
(reg:HI REG_Z))))]
|
||||
""
|
||||
{
|
||||
return avr_out_xload (insn, operands, NULL);
|
||||
}
|
||||
[(set_attr "adjust_len" "xload")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
;; "xload_hi_libgcc"
|
||||
;; "xload_psi_libgcc"
|
||||
;; "xload_si_libgcc"
|
||||
;; "xload_sf_libgcc"
|
||||
(define_insn "xload_<mode>_libgcc"
|
||||
[(set (reg:MOVMODE 22)
|
||||
(mem:MOVMODE (lo_sum:PSI (reg:QI 21)
|
||||
(reg:HI REG_Z))))
|
||||
(clobber (reg:QI 21))
|
||||
(clobber (reg:HI REG_Z))]
|
||||
"<MODE>mode != QImode
|
||||
&& avr_xload_libgcc_p (<MODE>mode)"
|
||||
{
|
||||
rtx x_bytes = GEN_INT (GET_MODE_SIZE (<MODE>mode));
|
||||
|
||||
/* Devices with ELPM* also have CALL. */
|
||||
|
||||
output_asm_insn ("call __xload_%0", &x_bytes);
|
||||
return "";
|
||||
}
|
||||
[(set_attr "length" "2")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
;; "xload_hi"
|
||||
;; "xload_psi"
|
||||
;; "xload_si"
|
||||
;; "xload_sf"
|
||||
(define_insn "xload_<mode>"
|
||||
[(set (match_operand:MOVMODE 0 "register_operand" "=r")
|
||||
(mem:MOVMODE (lo_sum:PSI (match_operand:QI 1 "register_operand" "r")
|
||||
(reg:HI REG_Z))))
|
||||
(clobber (scratch:HI))
|
||||
(clobber (reg:HI REG_Z))]
|
||||
"<MODE>mode != QImode
|
||||
&& !avr_xload_libgcc_p (<MODE>mode)"
|
||||
{
|
||||
return avr_out_xload (insn, operands, NULL);
|
||||
}
|
||||
[(set_attr "adjust_len" "xload")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
|
||||
;; General move expanders
|
||||
|
||||
;; "movqi"
|
||||
@ -375,6 +522,21 @@
|
||||
operands[1] = src = copy_to_mode_reg (<MODE>mode, src);
|
||||
}
|
||||
|
||||
if (avr_mem_pgmx_p (src))
|
||||
{
|
||||
rtx addr = XEXP (src, 0);
|
||||
|
||||
if (!REG_P (addr))
|
||||
src = replace_equiv_address (src, copy_to_mode_reg (PSImode, addr));
|
||||
|
||||
if (QImode == <MODE>mode)
|
||||
emit_insn (gen_xload8_A (dest, src));
|
||||
else
|
||||
emit_insn (gen_xload<mode>_A (dest, src));
|
||||
|
||||
DONE;
|
||||
}
|
||||
|
||||
if (avr_load_libgcc_p (src))
|
||||
{
|
||||
/* For the small devices, do loads per libgcc call. */
|
||||
@ -673,171 +835,164 @@
|
||||
|
||||
;;=========================================================================
|
||||
;; move string (like memcpy)
|
||||
;; implement as RTL loop
|
||||
|
||||
(define_expand "movmemhi"
|
||||
[(parallel [(set (match_operand:BLK 0 "memory_operand" "")
|
||||
(match_operand:BLK 1 "memory_operand" ""))
|
||||
(use (match_operand:HI 2 "const_int_operand" ""))
|
||||
(use (match_operand:HI 3 "const_int_operand" ""))])]
|
||||
(match_operand:BLK 1 "memory_operand" ""))
|
||||
(use (match_operand:HI 2 "const_int_operand" ""))
|
||||
(use (match_operand:HI 3 "const_int_operand" ""))])]
|
||||
""
|
||||
"{
|
||||
int prob;
|
||||
HOST_WIDE_INT count;
|
||||
enum machine_mode mode;
|
||||
rtx label = gen_label_rtx ();
|
||||
rtx loop_reg;
|
||||
rtx jump, src;
|
||||
|
||||
/* Copy pointers into new psuedos - they will be changed. */
|
||||
rtx addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
|
||||
rtx addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
|
||||
|
||||
/* Create rtx for tmp register - we use this as scratch. */
|
||||
rtx tmp_reg_rtx = gen_rtx_REG (QImode, TMP_REGNO);
|
||||
|
||||
if (avr_mem_pgm_p (operands[0]))
|
||||
DONE;
|
||||
|
||||
if (GET_CODE (operands[2]) != CONST_INT)
|
||||
{
|
||||
if (avr_emit_movmemhi (operands))
|
||||
DONE;
|
||||
|
||||
FAIL;
|
||||
})
|
||||
|
||||
count = INTVAL (operands[2]);
|
||||
if (count <= 0)
|
||||
FAIL;
|
||||
(define_mode_attr MOVMEM_r_d [(QI "r")
|
||||
(HI "d")])
|
||||
|
||||
/* Work out branch probability for latter use. */
|
||||
prob = REG_BR_PROB_BASE - REG_BR_PROB_BASE / count;
|
||||
;; $0, $4 : & dest
|
||||
;; $1, $5 : & src
|
||||
;; $2 : Address Space
|
||||
;; $3, $7 : Loop register
|
||||
;; $6 : Scratch register
|
||||
|
||||
/* See if constant fit 8 bits. */
|
||||
mode = (count < 0x100) ? QImode : HImode;
|
||||
/* Create loop counter register. */
|
||||
loop_reg = copy_to_mode_reg (mode, gen_int_mode (count, mode));
|
||||
;; "movmem_qi"
|
||||
;; "movmem_hi"
|
||||
(define_insn "movmem_<mode>"
|
||||
[(set (mem:BLK (match_operand:HI 0 "register_operand" "x"))
|
||||
(mem:BLK (match_operand:HI 1 "register_operand" "z")))
|
||||
(unspec [(match_operand:QI 2 "const_int_operand" "LP")]
|
||||
UNSPEC_MOVMEM)
|
||||
(use (match_operand:QIHI 3 "register_operand" "<MOVMEM_r_d>"))
|
||||
(clobber (match_operand:HI 4 "register_operand" "=0"))
|
||||
(clobber (match_operand:HI 5 "register_operand" "=1"))
|
||||
(clobber (match_operand:QI 6 "register_operand" "=&r"))
|
||||
(clobber (match_operand:QIHI 7 "register_operand" "=3"))]
|
||||
""
|
||||
{
|
||||
return avr_out_movmem (insn, operands, NULL);
|
||||
}
|
||||
[(set_attr "adjust_len" "movmem")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
/* Now create RTL code for move loop. */
|
||||
/* Label at top of loop. */
|
||||
emit_label (label);
|
||||
;; Ditto and
|
||||
;; $8, $9 : hh8 (& src)
|
||||
;; $10 : RAMPZ_ADDR
|
||||
|
||||
/* Move one byte into scratch and inc pointer. */
|
||||
src = gen_rtx_MEM (QImode, addr1);
|
||||
set_mem_addr_space (src, MEM_ADDR_SPACE (operands[1]));
|
||||
emit_move_insn (tmp_reg_rtx, src);
|
||||
emit_move_insn (addr1, gen_rtx_PLUS (Pmode, addr1, const1_rtx));
|
||||
;; "movmem_qi_elpm"
|
||||
;; "movmem_hi_elpm"
|
||||
(define_insn "movmem_<mode>_elpm"
|
||||
[(set (mem:BLK (match_operand:HI 0 "register_operand" "x"))
|
||||
(mem:BLK (lo_sum:PSI (match_operand:QI 8 "register_operand" "r")
|
||||
(match_operand:HI 1 "register_operand" "z"))))
|
||||
(unspec [(match_operand:QI 2 "const_int_operand" "n")]
|
||||
UNSPEC_MOVMEM)
|
||||
(use (match_operand:QIHI 3 "register_operand" "<MOVMEM_r_d>"))
|
||||
(clobber (match_operand:HI 4 "register_operand" "=0"))
|
||||
(clobber (match_operand:HI 5 "register_operand" "=1"))
|
||||
(clobber (match_operand:QI 6 "register_operand" "=&r"))
|
||||
(clobber (match_operand:QIHI 7 "register_operand" "=3"))
|
||||
(clobber (match_operand:QI 9 "register_operand" "=8"))
|
||||
(clobber (mem:QI (match_operand:QI 10 "io_address_operand" "n")))]
|
||||
""
|
||||
{
|
||||
return avr_out_movmem (insn, operands, NULL);
|
||||
}
|
||||
[(set_attr "adjust_len" "movmem")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
/* Move to mem and inc pointer. */
|
||||
emit_move_insn (gen_rtx_MEM (QImode, addr0), tmp_reg_rtx);
|
||||
emit_move_insn (addr0, gen_rtx_PLUS (Pmode, addr0, const1_rtx));
|
||||
|
||||
/* Decrement count. */
|
||||
emit_move_insn (loop_reg, gen_rtx_PLUS (mode, loop_reg, constm1_rtx));
|
||||
|
||||
/* Compare with zero and jump if not equal. */
|
||||
emit_cmp_and_jump_insns (loop_reg, const0_rtx, NE, NULL_RTX, mode, 1,
|
||||
label);
|
||||
/* Set jump probability based on loop count. */
|
||||
jump = get_last_insn ();
|
||||
add_reg_note (jump, REG_BR_PROB, GEN_INT (prob));
|
||||
DONE;
|
||||
}")
|
||||
|
||||
;; =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2
|
||||
;; =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2
|
||||
;; memset (%0, %2, %1)
|
||||
|
||||
(define_expand "setmemhi"
|
||||
[(parallel [(set (match_operand:BLK 0 "memory_operand" "")
|
||||
(match_operand 2 "const_int_operand" ""))
|
||||
(use (match_operand:HI 1 "const_int_operand" ""))
|
||||
(use (match_operand:HI 3 "const_int_operand" "n"))
|
||||
(clobber (match_scratch:HI 4 ""))
|
||||
(clobber (match_dup 5))])]
|
||||
(match_operand 2 "const_int_operand" ""))
|
||||
(use (match_operand:HI 1 "const_int_operand" ""))
|
||||
(use (match_operand:HI 3 "const_int_operand" ""))
|
||||
(clobber (match_scratch:HI 4 ""))
|
||||
(clobber (match_dup 5))])]
|
||||
""
|
||||
"{
|
||||
rtx addr0;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
rtx addr0;
|
||||
enum machine_mode mode;
|
||||
|
||||
/* If value to set is not zero, use the library routine. */
|
||||
if (operands[2] != const0_rtx)
|
||||
FAIL;
|
||||
/* If value to set is not zero, use the library routine. */
|
||||
if (operands[2] != const0_rtx)
|
||||
FAIL;
|
||||
|
||||
if (!CONST_INT_P (operands[1]))
|
||||
FAIL;
|
||||
if (!CONST_INT_P (operands[1]))
|
||||
FAIL;
|
||||
|
||||
mode = u8_operand (operands[1], VOIDmode) ? QImode : HImode;
|
||||
operands[5] = gen_rtx_SCRATCH (mode);
|
||||
operands[1] = copy_to_mode_reg (mode,
|
||||
gen_int_mode (INTVAL (operands[1]), mode));
|
||||
addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
|
||||
operands[0] = gen_rtx_MEM (BLKmode, addr0);
|
||||
})
|
||||
|
||||
mode = u8_operand (operands[1], VOIDmode) ? QImode : HImode;
|
||||
operands[5] = gen_rtx_SCRATCH (mode);
|
||||
operands[1] = copy_to_mode_reg (mode,
|
||||
gen_int_mode (INTVAL (operands[1]), mode));
|
||||
addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
|
||||
operands[0] = gen_rtx_MEM (BLKmode, addr0);
|
||||
}")
|
||||
|
||||
(define_insn "*clrmemqi"
|
||||
[(set (mem:BLK (match_operand:HI 0 "register_operand" "e"))
|
||||
(const_int 0))
|
||||
(const_int 0))
|
||||
(use (match_operand:QI 1 "register_operand" "r"))
|
||||
(use (match_operand:QI 2 "const_int_operand" "n"))
|
||||
(clobber (match_scratch:HI 3 "=0"))
|
||||
(clobber (match_scratch:QI 4 "=&1"))]
|
||||
""
|
||||
"st %a0+,__zero_reg__
|
||||
dec %1
|
||||
brne .-6"
|
||||
"0:\;st %a0+,__zero_reg__\;dec %1\;brne 0b"
|
||||
[(set_attr "length" "3")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
|
||||
(define_insn "*clrmemhi"
|
||||
[(set (mem:BLK (match_operand:HI 0 "register_operand" "e,e"))
|
||||
(const_int 0))
|
||||
(const_int 0))
|
||||
(use (match_operand:HI 1 "register_operand" "!w,d"))
|
||||
(use (match_operand:HI 2 "const_int_operand" "n,n"))
|
||||
(clobber (match_scratch:HI 3 "=0,0"))
|
||||
(clobber (match_scratch:HI 4 "=&1,&1"))]
|
||||
""
|
||||
"*{
|
||||
if (which_alternative==0)
|
||||
return (AS2 (st,%a0+,__zero_reg__) CR_TAB
|
||||
AS2 (sbiw,%A1,1) CR_TAB
|
||||
AS1 (brne,.-6));
|
||||
else
|
||||
return (AS2 (st,%a0+,__zero_reg__) CR_TAB
|
||||
AS2 (subi,%A1,1) CR_TAB
|
||||
AS2 (sbci,%B1,0) CR_TAB
|
||||
AS1 (brne,.-8));
|
||||
}"
|
||||
"@
|
||||
0:\;st %a0+,__zero_reg__\;sbiw %A1,1\;brne 0b
|
||||
0:\;st %a0+,__zero_reg__\;subi %A1,1\;sbci %B1,0\;brne 0b"
|
||||
[(set_attr "length" "3,4")
|
||||
(set_attr "cc" "clobber,clobber")])
|
||||
|
||||
(define_expand "strlenhi"
|
||||
[(set (match_dup 4)
|
||||
(unspec:HI [(match_operand:BLK 1 "memory_operand" "")
|
||||
(match_operand:QI 2 "const_int_operand" "")
|
||||
(match_operand:HI 3 "immediate_operand" "")]
|
||||
UNSPEC_STRLEN))
|
||||
(set (match_dup 4) (plus:HI (match_dup 4)
|
||||
(const_int -1)))
|
||||
(set (match_operand:HI 0 "register_operand" "")
|
||||
(minus:HI (match_dup 4)
|
||||
(match_dup 5)))]
|
||||
""
|
||||
"{
|
||||
rtx addr;
|
||||
if (operands[2] != const0_rtx)
|
||||
FAIL;
|
||||
addr = copy_to_mode_reg (Pmode, XEXP (operands[1],0));
|
||||
operands[1] = gen_rtx_MEM (BLKmode, addr);
|
||||
operands[5] = addr;
|
||||
operands[4] = gen_reg_rtx (HImode);
|
||||
}")
|
||||
[(set (match_dup 4)
|
||||
(unspec:HI [(match_operand:BLK 1 "memory_operand" "")
|
||||
(match_operand:QI 2 "const_int_operand" "")
|
||||
(match_operand:HI 3 "immediate_operand" "")]
|
||||
UNSPEC_STRLEN))
|
||||
(set (match_dup 4)
|
||||
(plus:HI (match_dup 4)
|
||||
(const_int -1)))
|
||||
(set (match_operand:HI 0 "register_operand" "")
|
||||
(minus:HI (match_dup 4)
|
||||
(match_dup 5)))]
|
||||
""
|
||||
{
|
||||
rtx addr;
|
||||
if (operands[2] != const0_rtx)
|
||||
FAIL;
|
||||
addr = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
|
||||
operands[1] = gen_rtx_MEM (BLKmode, addr);
|
||||
operands[5] = addr;
|
||||
operands[4] = gen_reg_rtx (HImode);
|
||||
})
|
||||
|
||||
(define_insn "*strlenhi"
|
||||
[(set (match_operand:HI 0 "register_operand" "=e")
|
||||
(unspec:HI [(mem:BLK (match_operand:HI 1 "register_operand" "%0"))
|
||||
(const_int 0)
|
||||
(match_operand:HI 2 "immediate_operand" "i")]
|
||||
UNSPEC_STRLEN))]
|
||||
[(set (match_operand:HI 0 "register_operand" "=e")
|
||||
(unspec:HI [(mem:BLK (match_operand:HI 1 "register_operand" "0"))
|
||||
(const_int 0)
|
||||
(match_operand:HI 2 "immediate_operand" "i")]
|
||||
UNSPEC_STRLEN))]
|
||||
""
|
||||
"ld __tmp_reg__,%a0+
|
||||
tst __tmp_reg__
|
||||
brne .-6"
|
||||
"0:\;ld __tmp_reg__,%a0+\;tst __tmp_reg__\;brne 0b"
|
||||
[(set_attr "length" "3")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
|
@ -63,10 +63,11 @@
|
||||
(match_test "!avr_mem_pgm_p (op)")))
|
||||
|
||||
;; Return 1 if OP is an "ordinary" general operand, i.e. a general
|
||||
;; operand whose load is not handled by a libgcc call.
|
||||
;; operand whose load is not handled by a libgcc call or ELPM.
|
||||
(define_predicate "nox_general_operand"
|
||||
(and (match_operand 0 "general_operand")
|
||||
(match_test "!avr_load_libgcc_p (op)")))
|
||||
(not (match_test "avr_load_libgcc_p (op)"))
|
||||
(not (match_test "avr_mem_pgmx_p (op)"))))
|
||||
|
||||
;; Return 1 if OP is the zero constant for MODE.
|
||||
(define_predicate "const0_operand"
|
||||
|
@ -1,3 +1,10 @@
|
||||
2011-11-18 Georg-Johann Lay <avr@gjlay.de>
|
||||
|
||||
PR target/49868
|
||||
* config/avr/t-avr (LIB1ASMFUNCS): Add _xload_2 _xload_3 _xload_4.
|
||||
* config/avr/lib1funcs.S (__xload_2, __xload_3, __xload_4):
|
||||
New functions.
|
||||
|
||||
2011-11-16 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
|
||||
|
||||
* config/arm/lib1funcs.asm (udivsi3): Add support for divide
|
||||
|
@ -1227,6 +1227,73 @@ ENDF __load_4
|
||||
|
||||
#endif /* L_load_3 || L_load_3 */
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Loading n bytes from Flash; n = 2,3,4
|
||||
;; R22... = Flash[R21:Z]
|
||||
;; Clobbers: __tmp_reg__, R21, R30, R31
|
||||
|
||||
#if (defined (L_xload_2) \
|
||||
|| defined (L_xload_3) \
|
||||
|| defined (L_xload_4)) \
|
||||
&& defined (__AVR_HAVE_ELPM__) \
|
||||
&& !defined (__AVR_HAVE_ELPMX__)
|
||||
|
||||
#if !defined (__AVR_HAVE_RAMPZ__)
|
||||
#error Need RAMPZ
|
||||
#endif /* have RAMPZ */
|
||||
|
||||
;; 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 .xload dest, n
|
||||
elpm
|
||||
mov \dest, r0
|
||||
.if \dest != D0+\n-1
|
||||
adiw r30, 1
|
||||
adc HHI8, __zero_reg__
|
||||
out __RAMPZ__, HHI8
|
||||
.endif
|
||||
.endm
|
||||
|
||||
#if defined (L_xload_2)
|
||||
DEFUN __xload_2
|
||||
out __RAMPZ__, HHI8
|
||||
.xload D0, 2
|
||||
.xload D1, 2
|
||||
ret
|
||||
ENDF __xload_2
|
||||
#endif /* L_xload_2 */
|
||||
|
||||
#if defined (L_xload_3)
|
||||
DEFUN __xload_3
|
||||
out __RAMPZ__, HHI8
|
||||
.xload D0, 3
|
||||
.xload D1, 3
|
||||
.xload D2, 3
|
||||
ret
|
||||
ENDF __xload_3
|
||||
#endif /* L_xload_3 */
|
||||
|
||||
#if defined (L_xload_4)
|
||||
DEFUN __xload_4
|
||||
out __RAMPZ__, HHI8
|
||||
.xload D0, 4
|
||||
.xload D1, 4
|
||||
.xload D2, 4
|
||||
.xload D3, 4
|
||||
ret
|
||||
ENDF __xload_4
|
||||
#endif /* L_xload_4 */
|
||||
|
||||
#endif /* L_xload_{2|3|4} && ELPM */
|
||||
|
||||
|
||||
.section .text.libgcc.builtins, "ax", @progbits
|
||||
|
||||
|
@ -22,6 +22,7 @@ LIB1ASMFUNCS = \
|
||||
_tablejump \
|
||||
_tablejump_elpm \
|
||||
_load_3 _load_4 \
|
||||
_xload_2 _xload_3 _xload_4 \
|
||||
_copy_data \
|
||||
_clear_bss \
|
||||
_ctors \
|
||||
|
Loading…
x
Reference in New Issue
Block a user