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:
Marek Michalkiewicz 2000-11-14 22:05:41 +03:00 committed by Denis Chertykov
parent 09ad474947
commit 1268b05f5a
5 changed files with 95 additions and 36 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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