avr.c (avr_case_values_threshold): New.
authorMarek Michalkiewicz <marekm@linux.org.pl>
Tue, 14 Nov 2000 19:05:41 +0000 (22:05 +0300)
committerDenis Chertykov <denisc@gcc.gnu.org>
Tue, 14 Nov 2000 19:05:41 +0000 (22:05 +0300)
* 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

gcc/ChangeLog
gcc/config/avr/avr.c
gcc/config/avr/avr.h
gcc/config/avr/avr.md
gcc/config/avr/libgcc.S

index 57c300f5b7dad41323752cb8899c2f9db3b0a509..bc3a9063b35303becbb295b01fb787192b5cf326 100644 (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
index 2854738d00f4d61f3e2363dde65c53271113556c..38cd07819e153f77bdabd71bbd56dec0d8946680 100644 (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;
 }
 
 
index 2a130448b475ce3c85a9b9acb43fd1e7b4d7113c..f5116a92a1750e67153d11ed12f90bd518a847c0 100644 (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
index c774f735d007c3c8ce99985e894ad5598586abe9..325a545fcd87c43a1a554504a7fd1096bd20d25a 100644 (file)
 (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);
index 97811d52b91492a76819023993e7883f0c34e8d3..cd2ab78ca98a50336f573b346b77b44a1d73d73d 100644 (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