diff mbox

[AVR] : Reuse __tablejump2__

Message ID 4E92F2AF.3000405@gjlay.de
State New
Headers show

Commit Message

Georg-Johann Lay Oct. 10, 2011, 1:27 p.m. UTC
This patch does better re-usage of __tablejump2__ from libgcc so that
switch/case statements with jump tables become smaller because the sequence
needs 6 to 9 words compared to 2 when JMPing to __tablejump2__.

Moreover, __tablejump2__ does no more rely in the content of EIND (by using
EIJMP) and uses RET instead.

The insn conditions of tablejump insns now are the same as in
avr_output_addr_vec_elt.

Ok for trunk?

Johann

	* config/avr/avr.md (*tablejump_rjmp): Change insn condition to
	!AVR_HAVE_JMP_CALL.
	(*tablejump_lib): Change insn condition to AVR_HAVE_JMP_CALL.
	(*tablejump_enh, *tablejump): Remove insns.
	* config/avr/libgcc.S (__tablejump__): Use RET instead of EIND +
	EIJM for indirect jump.  Use LPM Z+ where available.

Comments

Denis Chertykov Oct. 10, 2011, 3:52 p.m. UTC | #1
2011/10/10 Georg-Johann Lay <avr@gjlay.de>:
> This patch does better re-usage of __tablejump2__ from libgcc so that
> switch/case statements with jump tables become smaller because the sequence
> needs 6 to 9 words compared to 2 when JMPing to __tablejump2__.
>
> Moreover, __tablejump2__ does no more rely in the content of EIND (by using
> EIJMP) and uses RET instead.
>
> The insn conditions of tablejump insns now are the same as in
> avr_output_addr_vec_elt.
>
> Ok for trunk?

Approved.

Denis.
diff mbox

Patch

Index: config/avr/libgcc.S
===================================================================
--- config/avr/libgcc.S	(revision 179744)
+++ config/avr/libgcc.S	(working copy)
@@ -821,13 +821,17 @@  ENDF __tablejump2__
 
 DEFUN __tablejump__
 #if defined (__AVR_HAVE_LPMX__)
+#if defined (__AVR_HAVE_EIJMP_EICALL__)
+	lpm  __tmp_reg__, Z+		
+	push __tmp_reg__
+	lpm  __tmp_reg__, Z		
+	push __tmp_reg__
+	push __zero_reg__
+	ret
+#else    
 	lpm	__tmp_reg__, Z+
 	lpm	r31, Z
 	mov	r30, __tmp_reg__
-
-#if defined (__AVR_HAVE_EIJMP_EICALL__)
-	eijmp
-#else
 	ijmp
 #endif
 
Index: config/avr/avr.md
===================================================================
--- config/avr/avr.md	(revision 179744)
+++ config/avr/avr.md	(working copy)
@@ -3719,62 +3719,36 @@  (define_insn "*indirect_jump_avr6"
    (set_attr "cc" "none")])
 
 ;; table jump
+;; For entries in jump table see avr_output_addr_vec_elt.
 
-;; Table made from "rjmp" instructions for <=8K devices.
+;; Table made from "rjmp .L<n>" instructions for <= 8K devices.
 (define_insn "*tablejump_rjmp"
-  [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r")]
-			UNSPEC_INDEX_JMP))
+  [(set (pc)
+        (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r")]
+                   UNSPEC_INDEX_JMP))
    (use (label_ref (match_operand 1 "" "")))
    (clobber (match_dup 0))]
-  "(!AVR_HAVE_JMP_CALL) && (!AVR_HAVE_EIJMP_EICALL)"
+  "!AVR_HAVE_JMP_CALL"
   "@
 	ijmp
 	push %A0\;push %B0\;ret"
   [(set_attr "length" "1,3")
    (set_attr "cc" "none,none")])
 
-;; Not a prologue, but similar idea - move the common piece of code to libgcc.
+;; Move the common piece of code to libgcc.
+;; Table made from ".word gs(.L<n>)" addresses for > 8K devices.
+;; Read jump address from table and perform indirect jump.
 (define_insn "*tablejump_lib"
-  [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "z")]
-			UNSPEC_INDEX_JMP))
+  [(set (pc)
+        (unspec:HI [(match_operand:HI 0 "register_operand" "z")]
+                   UNSPEC_INDEX_JMP))
    (use (label_ref (match_operand 1 "" "")))
    (clobber (match_dup 0))]
-  "AVR_HAVE_JMP_CALL && TARGET_CALL_PROLOGUES"
-  "%~jmp __tablejump2__"
+  "AVR_HAVE_JMP_CALL"
+  "jmp __tablejump2__"
   [(set_attr "length" "2")
    (set_attr "cc" "clobber")])
 
-(define_insn "*tablejump_enh"
-  [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "z")]
-			UNSPEC_INDEX_JMP))
-   (use (label_ref (match_operand 1 "" "")))
-   (clobber (match_dup 0))]
-  "AVR_HAVE_JMP_CALL && AVR_HAVE_LPMX"
-  "lsl r30
-	rol r31
-	lpm __tmp_reg__,Z+
-	lpm r31,Z
-	mov r30,__tmp_reg__
-	%!ijmp"
-  [(set_attr "length" "6")
-   (set_attr "cc" "clobber")])
-
-(define_insn "*tablejump"
-  [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "z")]
-			UNSPEC_INDEX_JMP))
-   (use (label_ref (match_operand 1 "" "")))
-   (clobber (match_dup 0))]
-  "AVR_HAVE_JMP_CALL && !AVR_HAVE_EIJMP_EICALL"
-  "lsl r30
-	rol r31
-	lpm
-	inc r30
-	push r0
-	lpm
-	push r0
-	ret"
-  [(set_attr "length" "8")
-   (set_attr "cc" "clobber")])
 
 (define_expand "casesi"
   [(set (match_dup 6)