This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[repost] switch() statements on ARM/Thumb


Hi!

Since nobody commented on it last time I posted this I assume it's got
lost in the flood of email...

This patch [attached as I fear inline patches won't survive] corrects
code generation on for switch() statements on ARM/thumb when -fpic is
given. Other cases should not have changed.

Works against cvs, applies cleanly to 3.0.2, too.

greets from Zürich
-- vbi
2001-11-22  Adrian von Bidder   <avbidder@acter.ch>

	* arm.h (CASE_VECTOR_PC_RELATIVE, ASM_OUTPUT_ADDR_DIFF_ELT): define
	* arm.md (thumbpic_casesi): new pattern for switch() statements
	(*thumb_subsi3imm_insn, *thumb_mulsi3_power2, *thumb_adr): referred by
	thumbpic_casesi


diff -bprudN --exclude=*CVS* latest/gcc/config/arm/arm.h latest-uclinux/gcc/config/arm/arm.h
--- latest/gcc/config/arm/arm.h	Tue Oct 30 15:18:33 2001
+++ latest-uclinux/gcc/config/arm/arm.h	Tue Nov 20 15:23:29 2001
@@ -2334,7 +2348,7 @@ typedef struct
    instruction expects the table to contain offsets from the address of the
    table.
    Do not define this if the table should contain absolute addresses. */
-/* #define CASE_VECTOR_PC_RELATIVE 1 */
+#define CASE_VECTOR_PC_RELATIVE flag_pic
 
 /* Specify the tree operation to be used to convert reals to integers.  */
 #define IMPLICIT_FIX_EXPR  FIX_ROUND_EXPR
@@ -2594,6 +2608,14 @@ extern int making_const_table;
     }								\
   while (0)
 
+/* for pc relative jump tables when using pic code: */
+#undef ASM_OUTPUT_ADDR_DIFF_ELT 
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL)      \
+  if (TARGET_ARM)                                               \
+    fprintf (STREAM, "\tb\t.L%d\n", VALUE);                      \
+  else                                                          \
+    fprintf (STREAM, "\t.word\t.L%d-.L%d\n", VALUE, REL)        \
+
 #define ARM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) 	\
   do							\
     {							\
diff -bprudN --exclude=*CVS* latest/gcc/config/arm/arm.md latest-uclinux/gcc/config/arm/arm.md
--- latest/gcc/config/arm/arm.md	Wed Sep 12 19:17:53 2001
+++ latest-uclinux/gcc/config/arm/arm.md	Thu Nov 22 09:02:54 2001
@@ -991,6 +991,17 @@
   [(set_attr "length" "2")]
 )
 
+(define_insn "*thumb_subsi3imm_insn"
+  [(set (match_operand:SI           0 "register_operand" "=l,l")
+	(minus:SI (match_operand:SI 1 "register_operand" "l,0")
+		  (match_operand:SI 2 "const_int_operand" "L,I")))]
+  "TARGET_THUMB && ((unsigned int)INTVAL(operands[2]) < 256)"
+  "@
+  sub\\t%0, %1, %2
+  sub\\t%0, %2"
+  [(set_attr "length" "2")]
+)
+
 (define_insn_and_split "*arm_subsi3_insn"
   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
 	(minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
@@ -1165,6 +1176,16 @@
    (set_attr "type" "mult")]
 )
 
+; multiply by power of 2
+(define_insn "*thumb_mulsi3_power2"
+  [(set (match_operand:SI          0 "s_register_operand" "=l")
+	(mult:SI (match_operand:SI 1 "s_register_operand" "0")
+		 (match_operand:SI 2 "const_int_operand" "")))]
+  "TARGET_THUMB && (((INTVAL(operands[2]))&((INTVAL(operands[2]) - 1))) == 0)"
+  "lsl\\t%0, %1, %2"
+  [(set_attr "length" "2")]
+)
+
 (define_insn "*mulsi3_compare0"
   [(set (reg:CC_NOOV CC_REGNUM)
 	(compare:CC_NOOV (mult:SI
@@ -6829,10 +6850,17 @@
    (match_operand:SI 2 "const_int_operand" "")	; total range
    (match_operand:SI 3 "" "")			; table label
    (match_operand:SI 4 "" "")]			; Out of range label
-  "TARGET_ARM"
+  "TARGET_ARM || (TARGET_THUMB && flag_pic)"
   "
   {
     rtx reg;
+
+    if (TARGET_THUMB && flag_pic) {
+      emit_insn (gen_thumbpic_casesi (operands[0], operands[1],
+              operands[2], operands[3], operands[4]));
+      DONE;
+    }
+    
     if (operands[1] != const0_rtx)
       {
 	reg = gen_reg_rtx (SImode);
@@ -6845,15 +6873,15 @@
     if (!const_ok_for_arm (INTVAL (operands[2])))
       operands[2] = force_reg (SImode, operands[2]);
 
-    emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
-					 operands[4]));
+    emit_jump_insn (gen_arm_casesi_internal (operands[0], operands[2],
+                operands[3], operands[4]));
     DONE;
   }"
 )
 
 ;; The USE in this pattern is needed to tell flow analysis that this is
 ;; a CASESI insn.  It has no other purpose.
-(define_insn "casesi_internal"
+(define_insn "arm_casesi_internal"
   [(parallel [(set (pc)
 	       (if_then_else
 		(leu (match_operand:SI 0 "s_register_operand" "r")
@@ -6873,6 +6901,53 @@
    (set_attr "length" "12")]
 )
 
+;; -fpic -mthumb is wrong with just tablejump.
+(define_expand "thumbpic_casesi"
+  [(set (match_dup 5)
+        (minus:SI (match_operand:SI 0 "" "")
+                  (match_operand:SI 1 "" "")))
+   (set (pc)
+        (if_then_else (gtu (match_dup 5)
+                           (match_operand 2 "" ""))
+                      (label_ref (match_operand 4 "" ""))
+                      (pc)))
+   (set (match_dup 7)
+        (label_ref (match_operand 3 "" "")))
+   (set (match_dup 6)
+        (mult:SI (match_dup 5)
+                 (const_int 4)))
+   (set (match_dup 8)
+        (mem:SI (plus:SI (match_dup 6)
+                         (match_dup 7))))
+   (set (match_dup 9)
+        (plus:SI (match_dup 7)
+                 (match_dup 8)))
+   (parallel [
+     (set (pc)
+          (match_dup 9))
+     (use (label_ref (match_dup 3)))])]
+  "TARGET_THUMB && flag_pic"
+  "{
+    operands[5] = gen_reg_rtx (SImode);
+    operands[6] = gen_reg_rtx (SImode);
+    operands[7] = gen_reg_rtx (SImode);
+    operands[8] = gen_reg_rtx (SImode);
+    operands[9] = gen_reg_rtx (SImode);
+
+    operands[1] = force_reg(SImode, operands[1]);
+  }"
+)
+
+; this works only if the label_ref is close enough (10 bit word aligned)
+; but it should only be called from thumbpic_casesi anyway.
+(define_insn "*thumb_adr"
+  [(set (match_operand:SI 0 "s_register_operand" "=l")
+        (label_ref (match_operand 1 "" "")))]
+  "TARGET_THUMB"
+  "adr\\t%0, %a1"
+  [(set_attr "length" "2")]
+)
+
 (define_expand "indirect_jump"
   [(set (pc)
 	(match_operand:SI 0 "s_register_operand" ""))]
@@ -9132,12 +9207,11 @@
 )
 
 ;; Miscellaneous Thumb patterns
-
 (define_insn "tablejump"
   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
    (use (label_ref (match_operand 1 "" "")))]
   "TARGET_THUMB"
-  "mov	pc, %0"
+  "mov\\tpc, %0"
   [(set_attr "length" "2")]
 )
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]