mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-08 14:17:36 +08:00
avr.c (avr_case_values_threshold): New.
* config/avr/avr.c (avr_case_values_threshold): New. (avr_override_options): Set it depending on options, make it large when not optimizing to work around "unable to generate reloads". * config/avr/avr.h (TARGET_SWITCHES): Add -mno-tablejump option. (EXTRA_SECTION_FUNCTIONS): Make the .progmem.gcc_sw_table section executable if not AVR_MEGA. Make sure jump tables are word-aligned. (JUMP_TABLES_IN_TEXT_SECTION): Define as 0, not 1. (ASM_OUTPUT_ADDR_VEC_ELT): Optimize, use "rjmp" if not AVR_MEGA. (avr_case_values_threshold): Declare as extern int. (CASE_VALUES_THRESHOLD): Define as avr_case_values_threshold. * config/avr/avr.md (tablejump): Removed. (*tablejump_rjmp): New for jump tables made from "rjmp" instructions. (*tablejump_lib, *tablejump_enh, *tablejump): Change to expect the index in the table, not multiplied by 2. (casesi): Change to match the above insns. Always enable. * config/avr/libgcc.S (__tablejump__): Rename to __tablejump2__. Change to expect the word address of the table, multiply it by 2 here and not in the caller. Change "adiw" to faster "inc". From-SVN: r37465
This commit is contained in:
parent
09ad474947
commit
1268b05f5a
@ -1,3 +1,27 @@
|
||||
Tue Nov 14 21:54:31 2000 Marek Michalkiewicz <marekm@linux.org.pl> & Denis Chertykov <denisc@overta.ru>
|
||||
|
||||
* config/avr/avr.c (avr_case_values_threshold): New.
|
||||
(avr_override_options): Set it depending on options, make it large
|
||||
when not optimizing to work around "unable to generate reloads".
|
||||
|
||||
* config/avr/avr.h (TARGET_SWITCHES): Add -mno-tablejump option.
|
||||
(EXTRA_SECTION_FUNCTIONS): Make the .progmem.gcc_sw_table section
|
||||
executable if not AVR_MEGA. Make sure jump tables are word-aligned.
|
||||
(JUMP_TABLES_IN_TEXT_SECTION): Define as 0, not 1.
|
||||
(ASM_OUTPUT_ADDR_VEC_ELT): Optimize, use "rjmp" if not AVR_MEGA.
|
||||
(avr_case_values_threshold): Declare as extern int.
|
||||
(CASE_VALUES_THRESHOLD): Define as avr_case_values_threshold.
|
||||
|
||||
* config/avr/avr.md (tablejump): Removed.
|
||||
(*tablejump_rjmp): New for jump tables made from "rjmp" instructions.
|
||||
(*tablejump_lib, *tablejump_enh, *tablejump): Change to expect the
|
||||
index in the table, not multiplied by 2.
|
||||
(casesi): Change to match the above insns. Always enable.
|
||||
|
||||
* config/avr/libgcc.S (__tablejump__): Rename to __tablejump2__.
|
||||
Change to expect the word address of the table, multiply it by 2
|
||||
here and not in the caller. Change "adiw" to faster "inc".
|
||||
|
||||
2000-11-14 Neil Booth <neilb@earthling.net>
|
||||
|
||||
* cppexp.c (parse_defined): Call cpp_get_token not
|
||||
|
@ -160,6 +160,8 @@ static const struct mcu_type_s avr_mcu_types[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
int avr_case_values_threshold = 30000;
|
||||
|
||||
void
|
||||
avr_override_options ()
|
||||
{
|
||||
@ -188,6 +190,9 @@ avr_override_options ()
|
||||
case AVR4: avr_enhanced_p = 1; avr_mega_p = 0; break;
|
||||
case AVR5: avr_enhanced_p = 1; avr_mega_p = 1; break;
|
||||
}
|
||||
|
||||
if (optimize && !TARGET_NO_TABLEJUMP)
|
||||
avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
|
||||
}
|
||||
|
||||
|
||||
|
@ -51,6 +51,7 @@ extern int target_flags;
|
||||
#define MASK_ORDER_1 0x00001000
|
||||
#define MASK_INSN_SIZE_DUMP 0x00002000
|
||||
#define MASK_ORDER_2 0x00004000
|
||||
#define MASK_NO_TABLEJUMP 0x00008000
|
||||
#define MASK_INT8 0x00010000
|
||||
#define MASK_NO_INTERRUPTS 0x00020000
|
||||
#define MASK_CALL_PROLOGUES 0x00040000
|
||||
@ -63,6 +64,7 @@ extern int target_flags;
|
||||
#define TARGET_INSN_SIZE_DUMP (target_flags & MASK_INSN_SIZE_DUMP)
|
||||
#define TARGET_CALL_PROLOGUES (target_flags & MASK_CALL_PROLOGUES)
|
||||
#define TARGET_TINY_STACK (target_flags & MASK_TINY_STACK)
|
||||
#define TARGET_NO_TABLEJUMP (target_flags & MASK_NO_TABLEJUMP)
|
||||
|
||||
/* Dump each assembler insn's rtl into the output file.
|
||||
This is for debugging the compiler itself. */
|
||||
@ -102,6 +104,8 @@ extern int target_flags;
|
||||
N_("Use subroutines for function prologue/epilogue") }, \
|
||||
{ "tiny-stack", MASK_TINY_STACK, \
|
||||
N_("Change only the low 8 bits of the stack pointer") }, \
|
||||
{ "no-tablejump", MASK_NO_TABLEJUMP, \
|
||||
N_("Do not generate tablejump insns") }, \
|
||||
{ "rtl", MASK_RTL_DUMP, NULL }, \
|
||||
{ "size", MASK_INSN_SIZE_DUMP, \
|
||||
N_("Output instruction sizes to the asm file") }, \
|
||||
@ -2001,7 +2005,10 @@ progmem_section (void) \
|
||||
if (in_section != in_progmem) \
|
||||
{ \
|
||||
fprintf (asm_out_file, \
|
||||
".section .progmem.gcc_sw_table, \"a\", @progbits\n"); \
|
||||
"\t.section .progmem.gcc_sw_table, \"%s\", @progbits\n", \
|
||||
AVR_MEGA ? "a" : "ax"); \
|
||||
/* Should already be aligned, this is just to be safe if it isn't. */ \
|
||||
fprintf (asm_out_file, "\t.p2align 1\n"); \
|
||||
in_section = in_progmem; \
|
||||
} \
|
||||
}
|
||||
@ -2042,7 +2049,7 @@ progmem_section (void) \
|
||||
Do not define this macro if you put all constants in the read-only
|
||||
data section. */
|
||||
|
||||
#define JUMP_TABLES_IN_TEXT_SECTION 1
|
||||
#define JUMP_TABLES_IN_TEXT_SECTION 0
|
||||
/* Define this macro if jump tables (for `tablejump' insns) should be
|
||||
output in the text section, along with the assembler instructions.
|
||||
Otherwise, the readonly data section is used.
|
||||
@ -2705,8 +2712,13 @@ sprintf (STRING, "*.%s%d", PREFIX, NUM)
|
||||
pop hard register number REGNO off of the stack. The code need
|
||||
not be optimal, since this macro is used only when profiling. */
|
||||
|
||||
#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
|
||||
fprintf (STREAM, "\t.word pm(.L%d)\n", VALUE);
|
||||
#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
|
||||
do { \
|
||||
if (AVR_MEGA) \
|
||||
fprintf (STREAM, "\t.word pm(.L%d)\n", VALUE); \
|
||||
else \
|
||||
fprintf (STREAM, "\trjmp .L%d\n", VALUE); \
|
||||
} while (0)
|
||||
/* This macro should be provided on machines where the addresses in a
|
||||
dispatch table are absolute.
|
||||
|
||||
@ -2761,7 +2773,9 @@ fprintf (STREAM, "\t.skip %d,0\n", n)
|
||||
/* An alias for a machine mode name. This is the machine mode that
|
||||
elements of a jump-table should have. */
|
||||
|
||||
#define CASE_VALUES_THRESHOLD 17
|
||||
extern int avr_case_values_threshold;
|
||||
|
||||
#define CASE_VALUES_THRESHOLD avr_case_values_threshold
|
||||
/* `CASE_VALUES_THRESHOLD'
|
||||
Define this to be the smallest number of different values for
|
||||
which it is best to use a jump-table instead of a tree of
|
||||
|
@ -1852,41 +1852,53 @@
|
||||
(define_expand "tablejump"
|
||||
[(parallel [(set (pc) (match_operand:HI 0 "register_operand" ""))
|
||||
(use (label_ref (match_operand 1 "" "")))])]
|
||||
"optimize"
|
||||
"0 && optimize"
|
||||
"")
|
||||
|
||||
;; Note: the (mem:HI (...)) memory references here are special - actually
|
||||
;; the data is read from a word address in program memory (r31:r30 is the
|
||||
;; index in the table, not multiplied by 2 - see the "casesi" pattern).
|
||||
|
||||
;; Table made from "rjmp" instructions for <=8K devices.
|
||||
(define_insn "*tablejump_rjmp"
|
||||
[(set (pc) (mem:HI
|
||||
(plus:HI (match_operand:HI 0 "register_operand" "=&z")
|
||||
(label_ref (match_operand 2 "" "")))))
|
||||
(use (label_ref (match_operand 1 "" "")))]
|
||||
"!AVR_MEGA"
|
||||
"subi r30,pm_lo8(-(%2))
|
||||
sbci r31,pm_hi8(-(%2))
|
||||
ijmp"
|
||||
[(set_attr "length" "3")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
;; Not a prologue, but similar idea - move the common piece of code to libgcc.
|
||||
(define_insn "*tablejump_lib"
|
||||
[(set (pc) (mem:HI (plus:HI (match_operand:HI 0 "register_operand" "=&z")
|
||||
(label_ref (match_operand 2 "" "")))))
|
||||
(use (label_ref (match_operand 1 "" "")))]
|
||||
"TARGET_CALL_PROLOGUES"
|
||||
"*{
|
||||
output_asm_insn (AS2 (subi,r30,lo8(-(%2))) CR_TAB
|
||||
AS2 (sbci,r31,hi8(-(%2))), operands);
|
||||
return (AVR_MEGA
|
||||
? AS1 (jmp,__tablejump__)
|
||||
: AS1 (rjmp,__tablejump__));
|
||||
}"
|
||||
[(set_attr "cc" "clobber")
|
||||
(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no")
|
||||
(const_int 3)
|
||||
(const_int 4)))])
|
||||
|
||||
"AVR_MEGA && TARGET_CALL_PROLOGUES"
|
||||
"subi r30,pm_lo8(-(%2))
|
||||
sbci r31,pm_hi8(-(%2))
|
||||
jmp __tablejump2__"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
(define_insn "*tablejump_enh"
|
||||
[(set (pc) (mem:HI
|
||||
(plus:HI (match_operand:HI 0 "register_operand" "=&z")
|
||||
(label_ref (match_operand 2 "" "")))))
|
||||
(use (label_ref (match_operand 1 "" "")))]
|
||||
"AVR_ENHANCED"
|
||||
"subi r30,lo8(-(%2))
|
||||
sbci r31,hi8(-(%2))
|
||||
"AVR_MEGA && AVR_ENHANCED"
|
||||
"subi r30,pm_lo8(-(%2))
|
||||
sbci r31,pm_hi8(-(%2))
|
||||
lsl r30
|
||||
rol r31
|
||||
lpm __tmp_reg__,Z+
|
||||
lpm r31,Z
|
||||
mov r30,__tmp_reg__
|
||||
ijmp"
|
||||
[(set_attr "length" "6")
|
||||
[(set_attr "length" "8")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
(define_insn "*tablejump"
|
||||
@ -1894,16 +1906,18 @@
|
||||
(plus:HI (match_operand:HI 0 "register_operand" "=&z")
|
||||
(label_ref (match_operand 2 "" "")))))
|
||||
(use (label_ref (match_operand 1 "" "")))]
|
||||
""
|
||||
"subi r30,lo8(-(%2))
|
||||
sbci r31,hi8(-(%2))
|
||||
"AVR_MEGA"
|
||||
"subi r30,pm_lo8(-(%2))
|
||||
sbci r31,pm_hi8(-(%2))
|
||||
lsl r30
|
||||
rol r31
|
||||
lpm
|
||||
inc r30
|
||||
push r0
|
||||
adiw r30,1
|
||||
lpm
|
||||
push r0
|
||||
ret"
|
||||
[(set_attr "length" "8")
|
||||
[(set_attr "length" "10")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
(define_expand "casesi"
|
||||
@ -1920,9 +1934,9 @@
|
||||
(const_int 0))
|
||||
(label_ref (match_operand 4 "" ""))
|
||||
(pc)))
|
||||
(set (match_dup 6)
|
||||
(plus:HI (match_dup 6)
|
||||
(match_dup 6)))
|
||||
;; (set (match_dup 6)
|
||||
;; (plus:HI (match_dup 6)
|
||||
;; (match_dup 6)))
|
||||
;; (set (match_dup 6)
|
||||
;; (plus:HI (match_dup 6) (label_ref (match_operand:HI 3 "" ""))))
|
||||
|
||||
@ -1930,7 +1944,7 @@
|
||||
(plus:HI (match_dup 6)
|
||||
(label_ref (match_operand:HI 3 "" "")))))
|
||||
(use (label_ref (match_dup 3)))])]
|
||||
"!optimize"
|
||||
""
|
||||
"
|
||||
{
|
||||
operands[6] = gen_reg_rtx (HImode);
|
||||
|
@ -691,9 +691,11 @@ _cleanup:
|
||||
#endif /* defined (L_cleanup) */
|
||||
|
||||
#ifdef L_tablejump
|
||||
.global __tablejump__
|
||||
.func __tablejump__
|
||||
__tablejump__:
|
||||
.global __tablejump2__
|
||||
.func __tablejump2__
|
||||
__tablejump2__:
|
||||
lsl r30
|
||||
rol r31
|
||||
#if defined (__AVR_ENHANCED__)
|
||||
lpm __tmp_reg__, Z+
|
||||
lpm r31, Z
|
||||
@ -702,7 +704,7 @@ __tablejump__:
|
||||
#else
|
||||
lpm
|
||||
push r0
|
||||
adiw r30, 1
|
||||
inc r30 ; table is word aligned, no carry to high byte
|
||||
lpm
|
||||
push r0
|
||||
ret
|
||||
|
Loading…
Reference in New Issue
Block a user