This is the mail archive of the gcc@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]

Re: writing casesi (was: Re: arm/thumb bugs)


Hi again!

Attached is a first cut on the casesi-on-thumb-with-fpic problem. The
patch is not yet tested - I'll do that asap - but the code should work
in theory (an improvement on the current state, I'd say). Patch is
against 3.0.2, but does apply to current cvs.

Alexandre Oliva wrote:
> 
> On Nov 15, 2001, Adrian von Bidder <avbidder@acter.ch> wrote:
> 
> >    (set (match_dup 7)
> >         (label_ref (match_operand 3 "" "")))
> 
> As far as I can tell, this is not a valid instruction, at least not in
> PIC mode.  You should probably built it as the PIC register plus the
> GOTOFF of the label.  I don't know details about the implementation of
> PIC in the ARM back-end, but it appears to me that pic_load_addr_thumb
> may be the insn you're looking for.

The label_ref in question is very close to the current pc, so I can use
"adr rx, #offset" (which is rx = pc + offset). Pattern *thumb_movaddr in
the patch.

It would perhaps be better if I'd call gen_thumb_movaddr directly from
the preparation statements. But how do I indicate in the template that
this operand has been set up? dce will delete the adr instruction if I
don't.
(Best would probably be to specify the range in the condition to the adr
instruction, so it could be used generally if the necessity arised. But
that's beyond me).

Probably there is no need to add pattern *thumb_mulsi3_power2 and the
modification to *thumb_subsi3_insn, if the template were written the
Right[tm] way.

All in all: I'm still hacking away without understanding half of what's
going on behind the scene, so any hand-holding will be appreciated.

greets from Zürich
-- vbi
--- gcc-3.0.2.orig/gcc/config/arm/arm.md	Fri May 18 14:45:22 2001
+++ gcc-3.0.2/gcc/config/arm/arm.md	Mon Nov 19 16:13:59 2001
@@ -983,11 +983,13 @@
 )
 
 (define_insn "*thumb_subsi3_insn"
-  [(set (match_operand:SI           0 "register_operand" "=l")
-	(minus:SI (match_operand:SI 1 "register_operand" "l")
-		  (match_operand:SI 2 "register_operand" "l")))]
+  [(set (match_operand:SI           0 "register_operand" "=l,l")
+	(minus:SI (match_operand:SI 1 "register_operand" "l,0")
+		  (match_operand:SI 2 "register_operand" "l,I")))]
   "TARGET_THUMB"
-  "sub\\t%0, %1, %2"
+  "@
+   sub\\t%0, %1, %2
+   sub\\t%0, %2"
   [(set_attr "length" "2")]
 )
 
@@ -1165,6 +1167,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
@@ -6833,10 +6845,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);
@@ -6849,15 +6868,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")
@@ -6875,6 +6894,47 @@
   "
   [(set_attr "conds" "clob")
    (set_attr "length" "12")]
+)
+
+;; tablejump seems to produce wrong code for thumb with -fpic. Fix this:
+(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 6)
+        (mult:SI (match_dup 5)
+                 (const_int 2)))
+   (set (match_dup 7)
+        (label_ref (match_operand 3 "" "")))
+   (set (match_dup 8)
+        (plus:SI (match_dup 6)
+                 (match_dup 7)))
+   (parallel [
+     (set (pc)
+          (match_dup 8))
+     (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);
+  }"
+)
+
+; 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 "*thumbpic_movaddr"
+  [(set (match_operand:SI 0 "s_register_operand" "=l")
+        (label_ref (match_operand 1 "" "")))]
+  "TARGET_THUMB && flag_pic"
+  "adr\\t%0, %a1"
+  [(set_attr "length" "2")]
 )
 
 (define_expand "indirect_jump"

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