aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog24
-rw-r--r--gcc/config/avr/avr.c5
-rw-r--r--gcc/config/avr/avr.h24
-rw-r--r--gcc/config/avr/avr.md68
-rw-r--r--gcc/config/avr/libgcc.S10
5 files changed, 95 insertions, 36 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 57c300f..bc3a906 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 2854738..38cd078 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -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;
}
diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
index 2a13044..f5116a9 100644
--- a/gcc/config/avr/avr.h
+++ b/gcc/config/avr/avr.h
@@ -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
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index c774f73..325a545 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -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);
diff --git a/gcc/config/avr/libgcc.S b/gcc/config/avr/libgcc.S
index 97811d5..cd2ab78 100644
--- a/gcc/config/avr/libgcc.S
+++ b/gcc/config/avr/libgcc.S
@@ -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