* 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
+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
{ NULL, 0 }
};
+int avr_case_values_threshold = 30000;
+
void
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;
}
#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
#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. */
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") }, \
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; \
} \
}
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.
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.
/* 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
(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"
(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"
(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 "" ""))))
(plus:HI (match_dup 6)
(label_ref (match_operand:HI 3 "" "")))))
(use (label_ref (match_dup 3)))])]
- "!optimize"
+ ""
"
{
operands[6] = gen_reg_rtx (HImode);
#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
#else
lpm
push r0
- adiw r30, 1
+ inc r30 ; table is word aligned, no carry to high byte
lpm
push r0
ret