Commit 1268b05f by Marek Michalkiewicz Committed by Denis Chertykov

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
parent 09ad4749
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> 2000-11-14 Neil Booth <neilb@earthling.net>
* cppexp.c (parse_defined): Call cpp_get_token not * cppexp.c (parse_defined): Call cpp_get_token not
......
...@@ -160,6 +160,8 @@ static const struct mcu_type_s avr_mcu_types[] = { ...@@ -160,6 +160,8 @@ static const struct mcu_type_s avr_mcu_types[] = {
{ NULL, 0 } { NULL, 0 }
}; };
int avr_case_values_threshold = 30000;
void void
avr_override_options () avr_override_options ()
{ {
...@@ -188,6 +190,9 @@ avr_override_options () ...@@ -188,6 +190,9 @@ avr_override_options ()
case AVR4: avr_enhanced_p = 1; avr_mega_p = 0; break; case AVR4: avr_enhanced_p = 1; avr_mega_p = 0; break;
case AVR5: avr_enhanced_p = 1; avr_mega_p = 1; 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; ...@@ -51,6 +51,7 @@ extern int target_flags;
#define MASK_ORDER_1 0x00001000 #define MASK_ORDER_1 0x00001000
#define MASK_INSN_SIZE_DUMP 0x00002000 #define MASK_INSN_SIZE_DUMP 0x00002000
#define MASK_ORDER_2 0x00004000 #define MASK_ORDER_2 0x00004000
#define MASK_NO_TABLEJUMP 0x00008000
#define MASK_INT8 0x00010000 #define MASK_INT8 0x00010000
#define MASK_NO_INTERRUPTS 0x00020000 #define MASK_NO_INTERRUPTS 0x00020000
#define MASK_CALL_PROLOGUES 0x00040000 #define MASK_CALL_PROLOGUES 0x00040000
...@@ -63,6 +64,7 @@ extern int target_flags; ...@@ -63,6 +64,7 @@ extern int target_flags;
#define TARGET_INSN_SIZE_DUMP (target_flags & MASK_INSN_SIZE_DUMP) #define TARGET_INSN_SIZE_DUMP (target_flags & MASK_INSN_SIZE_DUMP)
#define TARGET_CALL_PROLOGUES (target_flags & MASK_CALL_PROLOGUES) #define TARGET_CALL_PROLOGUES (target_flags & MASK_CALL_PROLOGUES)
#define TARGET_TINY_STACK (target_flags & MASK_TINY_STACK) #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. /* Dump each assembler insn's rtl into the output file.
This is for debugging the compiler itself. */ This is for debugging the compiler itself. */
...@@ -102,6 +104,8 @@ extern int target_flags; ...@@ -102,6 +104,8 @@ extern int target_flags;
N_("Use subroutines for function prologue/epilogue") }, \ N_("Use subroutines for function prologue/epilogue") }, \
{ "tiny-stack", MASK_TINY_STACK, \ { "tiny-stack", MASK_TINY_STACK, \
N_("Change only the low 8 bits of the stack pointer") }, \ 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 }, \ { "rtl", MASK_RTL_DUMP, NULL }, \
{ "size", MASK_INSN_SIZE_DUMP, \ { "size", MASK_INSN_SIZE_DUMP, \
N_("Output instruction sizes to the asm file") }, \ N_("Output instruction sizes to the asm file") }, \
...@@ -2001,7 +2005,10 @@ progmem_section (void) \ ...@@ -2001,7 +2005,10 @@ progmem_section (void) \
if (in_section != in_progmem) \ if (in_section != in_progmem) \
{ \ { \
fprintf (asm_out_file, \ 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; \ in_section = in_progmem; \
} \ } \
} }
...@@ -2042,7 +2049,7 @@ progmem_section (void) \ ...@@ -2042,7 +2049,7 @@ progmem_section (void) \
Do not define this macro if you put all constants in the read-only Do not define this macro if you put all constants in the read-only
data section. */ 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 /* Define this macro if jump tables (for `tablejump' insns) should be
output in the text section, along with the assembler instructions. output in the text section, along with the assembler instructions.
Otherwise, the readonly data section is used. Otherwise, the readonly data section is used.
...@@ -2705,8 +2712,13 @@ sprintf (STRING, "*.%s%d", PREFIX, NUM) ...@@ -2705,8 +2712,13 @@ sprintf (STRING, "*.%s%d", PREFIX, NUM)
pop hard register number REGNO off of the stack. The code need pop hard register number REGNO off of the stack. The code need
not be optimal, since this macro is used only when profiling. */ not be optimal, since this macro is used only when profiling. */
#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \ #define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
fprintf (STREAM, "\t.word pm(.L%d)\n", 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 /* This macro should be provided on machines where the addresses in a
dispatch table are absolute. dispatch table are absolute.
...@@ -2761,7 +2773,9 @@ fprintf (STREAM, "\t.skip %d,0\n", n) ...@@ -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 /* An alias for a machine mode name. This is the machine mode that
elements of a jump-table should have. */ 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' /* `CASE_VALUES_THRESHOLD'
Define this to be the smallest number of different values for 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 which it is best to use a jump-table instead of a tree of
......
...@@ -1852,41 +1852,53 @@ ...@@ -1852,41 +1852,53 @@
(define_expand "tablejump" (define_expand "tablejump"
[(parallel [(set (pc) (match_operand:HI 0 "register_operand" "")) [(parallel [(set (pc) (match_operand:HI 0 "register_operand" ""))
(use (label_ref (match_operand 1 "" "")))])] (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. ;; Not a prologue, but similar idea - move the common piece of code to libgcc.
(define_insn "*tablejump_lib" (define_insn "*tablejump_lib"
[(set (pc) (mem:HI (plus:HI (match_operand:HI 0 "register_operand" "=&z") [(set (pc) (mem:HI (plus:HI (match_operand:HI 0 "register_operand" "=&z")
(label_ref (match_operand 2 "" ""))))) (label_ref (match_operand 2 "" "")))))
(use (label_ref (match_operand 1 "" "")))] (use (label_ref (match_operand 1 "" "")))]
"TARGET_CALL_PROLOGUES" "AVR_MEGA && TARGET_CALL_PROLOGUES"
"*{ "subi r30,pm_lo8(-(%2))
output_asm_insn (AS2 (subi,r30,lo8(-(%2))) CR_TAB sbci r31,pm_hi8(-(%2))
AS2 (sbci,r31,hi8(-(%2))), operands); jmp __tablejump2__"
return (AVR_MEGA [(set_attr "length" "4")
? AS1 (jmp,__tablejump__) (set_attr "cc" "clobber")])
: AS1 (rjmp,__tablejump__));
}"
[(set_attr "cc" "clobber")
(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no")
(const_int 3)
(const_int 4)))])
(define_insn "*tablejump_enh" (define_insn "*tablejump_enh"
[(set (pc) (mem:HI [(set (pc) (mem:HI
(plus:HI (match_operand:HI 0 "register_operand" "=&z") (plus:HI (match_operand:HI 0 "register_operand" "=&z")
(label_ref (match_operand 2 "" ""))))) (label_ref (match_operand 2 "" "")))))
(use (label_ref (match_operand 1 "" "")))] (use (label_ref (match_operand 1 "" "")))]
"AVR_ENHANCED" "AVR_MEGA && AVR_ENHANCED"
"subi r30,lo8(-(%2)) "subi r30,pm_lo8(-(%2))
sbci r31,hi8(-(%2)) sbci r31,pm_hi8(-(%2))
lsl r30
rol r31
lpm __tmp_reg__,Z+ lpm __tmp_reg__,Z+
lpm r31,Z lpm r31,Z
mov r30,__tmp_reg__ mov r30,__tmp_reg__
ijmp" ijmp"
[(set_attr "length" "6") [(set_attr "length" "8")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
(define_insn "*tablejump" (define_insn "*tablejump"
...@@ -1894,16 +1906,18 @@ ...@@ -1894,16 +1906,18 @@
(plus:HI (match_operand:HI 0 "register_operand" "=&z") (plus:HI (match_operand:HI 0 "register_operand" "=&z")
(label_ref (match_operand 2 "" ""))))) (label_ref (match_operand 2 "" "")))))
(use (label_ref (match_operand 1 "" "")))] (use (label_ref (match_operand 1 "" "")))]
"" "AVR_MEGA"
"subi r30,lo8(-(%2)) "subi r30,pm_lo8(-(%2))
sbci r31,hi8(-(%2)) sbci r31,pm_hi8(-(%2))
lsl r30
rol r31
lpm lpm
inc r30
push r0 push r0
adiw r30,1
lpm lpm
push r0 push r0
ret" ret"
[(set_attr "length" "8") [(set_attr "length" "10")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
(define_expand "casesi" (define_expand "casesi"
...@@ -1920,9 +1934,9 @@ ...@@ -1920,9 +1934,9 @@
(const_int 0)) (const_int 0))
(label_ref (match_operand 4 "" "")) (label_ref (match_operand 4 "" ""))
(pc))) (pc)))
(set (match_dup 6) ;; (set (match_dup 6)
(plus:HI (match_dup 6) ;; (plus:HI (match_dup 6)
(match_dup 6))) ;; (match_dup 6)))
;; (set (match_dup 6) ;; (set (match_dup 6)
;; (plus:HI (match_dup 6) (label_ref (match_operand:HI 3 "" "")))) ;; (plus:HI (match_dup 6) (label_ref (match_operand:HI 3 "" ""))))
...@@ -1930,7 +1944,7 @@ ...@@ -1930,7 +1944,7 @@
(plus:HI (match_dup 6) (plus:HI (match_dup 6)
(label_ref (match_operand:HI 3 "" ""))))) (label_ref (match_operand:HI 3 "" "")))))
(use (label_ref (match_dup 3)))])] (use (label_ref (match_dup 3)))])]
"!optimize" ""
" "
{ {
operands[6] = gen_reg_rtx (HImode); operands[6] = gen_reg_rtx (HImode);
......
...@@ -691,9 +691,11 @@ _cleanup: ...@@ -691,9 +691,11 @@ _cleanup:
#endif /* defined (L_cleanup) */ #endif /* defined (L_cleanup) */
#ifdef L_tablejump #ifdef L_tablejump
.global __tablejump__ .global __tablejump2__
.func __tablejump__ .func __tablejump2__
__tablejump__: __tablejump2__:
lsl r30
rol r31
#if defined (__AVR_ENHANCED__) #if defined (__AVR_ENHANCED__)
lpm __tmp_reg__, Z+ lpm __tmp_reg__, Z+
lpm r31, Z lpm r31, Z
...@@ -702,7 +704,7 @@ __tablejump__: ...@@ -702,7 +704,7 @@ __tablejump__:
#else #else
lpm lpm
push r0 push r0
adiw r30, 1 inc r30 ; table is word aligned, no carry to high byte
lpm lpm
push r0 push r0
ret ret
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment