diff options
-rw-r--r-- | gcc/ChangeLog | 24 | ||||
-rw-r--r-- | gcc/config/avr/avr.c | 5 | ||||
-rw-r--r-- | gcc/config/avr/avr.h | 24 | ||||
-rw-r--r-- | gcc/config/avr/avr.md | 68 | ||||
-rw-r--r-- | gcc/config/avr/libgcc.S | 10 |
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 |