OSDN Git Service

movdi 64 bit constants, use HOST_WIDE_INT, update tablejump
authoredelsohn <edelsohn@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Feb 1996 21:57:54 +0000 (21:57 +0000)
committeredelsohn <edelsohn@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Feb 1996 21:57:54 +0000 (21:57 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@11178 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/config/rs6000/rs6000.md

index aaa412b..4969fc8 100644 (file)
    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4)))]
 "
 {
-  int low = INTVAL (operands[2]) & 0xffff;
-  int high = (unsigned) INTVAL (operands[2]) >> 16;
+  HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
+  HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
 
   if (low & 0x8000)
-    high++, low |= 0xffff0000;
+    high += 0x10000, low |= ((HOST_WIDE_INT) -1) << 16;
 
-  operands[3] = gen_rtx (CONST_INT, VOIDmode, high << 16);
-  operands[4] = gen_rtx (CONST_INT, VOIDmode, low);
+  operands[3] = GEN_INT (high);
+  operands[4] = GEN_INT (low);
 }")
 
 (define_insn "one_cmplsi2"
    (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))]
 "
 {
-  int low = INTVAL (operands[2]) & 0xffff;
-  int high = (unsigned) INTVAL (operands[2]) >> 16;
+  HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
+  HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
 
   if (low & 0x8000)
-    high++, low |= 0xffff0000;
+    high+=0x10000, low |= ((HOST_WIDE_INT) -1) << 16;
 
-  operands[3] = gen_rtx (CONST_INT, VOIDmode, high << 16);
-  operands[4] = gen_rtx (CONST_INT, VOIDmode, low);
+  operands[3] = GEN_INT (high);
+  operands[4] = GEN_INT (low);
 }")
 
 (define_insn "one_cmpldi2"
 "
 {
   operands[3] = gen_rtx (CONST_INT, VOIDmode,
-                        INTVAL (operands[2]) & 0xffff0000);
+                        INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff));
   operands[4] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff);
 }")
 
 ;; multiple insns.
 (define_expand "movdi"
   [(set (match_operand:DI 0 "general_operand" "")
-       (match_operand:DI 1 "general_operand" ""))]
+       (match_operand:DI 1 "any_operand" ""))]
   ""
   "
 {
-  if (GET_CODE (operands[0]) == MEM)
+  if (! TARGET_64BIT && ! general_operand (operands[1], DImode))
+    FAIL;
+
+  if (GET_CODE (operands[0]) != REG)
     operands[1] = force_reg (DImode, operands[1]);
 
   if (GET_CODE (operands[1]) == CONST_DOUBLE
          low = CONST_DOUBLE_LOW (operands[1]);
          high = CONST_DOUBLE_HIGH (operands[1]);
        }
-      else
+      else if (HOST_BITS_PER_WIDE_INT <= 32)
        {
          low = INTVAL (operands[1]);
          high = (low < 0) ? ~0 : 0;
        }
+      else
+       {
+          low = INTVAL (operands[1]) & 0xffffffff;
+          high = (unsigned long long) INTVAL (operands[1]) >> 32;
+       }
 
-      emit_move_insn (gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN),
-                     GEN_INT (low));
+      if (! TARGET_POWERPC64)
+       {
+         emit_move_insn (gen_rtx (SUBREG, SImode, operands[0],
+                         WORDS_BIG_ENDIAN), GEN_INT (low));
 
-      emit_move_insn (gen_rtx (SUBREG, SImode, operands[0], !WORDS_BIG_ENDIAN),
-                     GEN_INT (high));
-      DONE;
+         emit_move_insn (gen_rtx (SUBREG, SImode, operands[0],
+                         ! WORDS_BIG_ENDIAN), GEN_INT (high));
+         DONE;
+       }
+      else
+       {
+         if (high + 0x8000 >= 0x10000)
+           {
+             emit_move_insn (gen_rtx (SUBREG, SImode, operands[0], 1),
+                             GEN_INT (high));
+             emit_insn (gen_ashldi3 (operands[0], operands[0], GEN_INT(32)));
+             if (low)
+               {
+                 HOST_WIDE_INT low_low = low & 0xffff;
+                 HOST_WIDE_INT low_high = low & (~ (HOST_WIDE_INT) 0xffff);
+                 if (low_high)
+                   emit_insn (gen_iordi3 (operands[0], operands[0],
+                                          GEN_INT (low_high)));
+                 if (low_low)
+                   emit_insn (gen_iordi3 (operands[0], operands[0],
+                                          GEN_INT (low_low)));
+               }
+           }
+         else if (low)
+           emit_move_insn (gen_rtx (SUBREG, SImode, operands[0], 1),
+                           GEN_INT (low));
+         DONE;
+        }
     }
 
       /* Stores between FPR and any non-FPR registers must go through a
    (set_attr "length" "8,8,8,*,*,*")])
 
 (define_insn ""
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,f,f,m,r,*h,*h")
-       (match_operand:DI 1 "input_operand" "r,m,r,I,J,R,f,m,f,*h,r,0"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,f,f,m,r,*h,*h")
+       (match_operand:DI 1 "input_operand" "r,m,r,I,J,n,R,f,m,f,*h,r,0"))]
   "TARGET_POWERPC64 && (gpc_reg_operand (operands[0], DImode)
    || gpc_reg_operand (operands[1], DImode))"
   "@
    std%U0%X0 %1,%0
    li %0,%1
    lis %0,%u1
+   #
    {cal|la} %0,%1(%*)
    fmr %0,%1
    lfd%U1%X1 %0,%1
    mf%1 %0
    mt%0 %1
    cror 0,0,0"
-  [(set_attr "type" "*,load,*,*,*,*,fp,fpload,*,*,mtjmpr,*")])
+  [(set_attr "type" "*,load,*,*,*,*,*,fp,fpload,*,*,mtjmpr,*")
+   (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4")])
+
+;; Split a load of a large constant into the appropriate five-instruction
+;; sequence.  The expansion in movdi tries to perform the minimum number of
+;; steps, but here we have to handle anything in a constant number of insns.
+
+(define_split
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+       (match_operand:DI 1 "const_double_operand" ""))]
+  "TARGET_POWERPC64"
+  [(set (match_dup 0)
+       (match_dup 2))
+   (set (match_dup 0)
+       (ior:DI (match_dup 0)
+               (match_dup 3)))
+   (set (match_dup 0)
+       (ashift:DI (match_dup 0)
+                  (const_int 32)))
+   (set (match_dup 0)
+       (ior:DI (match_dup 0)
+               (match_dup 4)))
+   (set (match_dup 0)
+       (ior:DI (match_dup 0)
+               (match_dup 5)))]
+  "
+{
+  HOST_WIDE_INT low;
+  HOST_WIDE_INT high;
+
+  if (GET_CODE (operands[1]) == CONST_DOUBLE)
+    {
+      low = CONST_DOUBLE_LOW (operands[1]);
+      high = CONST_DOUBLE_HIGH (operands[1]);
+    }
+  else if (HOST_BITS_PER_WIDE_INT <= 32)
+    {
+      low = INTVAL (operands[1]);
+      high = (low < 0) ? ~0 : 0;
+    }
+  else
+    {
+      low = INTVAL (operands[1]) & 0xffffffff;
+      high = (unsigned long long) INTVAL (operands[1]) >> 32;
+    }
+
+  if ((high + 0x8000) < 0x10000
+      && ((low & 0xffff) == 0 || (low & (~ (HOST_WIDE_INT) 0xffff)) == 0))
+    FAIL;
+
+  operands[2] = GEN_INT (high & (~ (HOST_WIDE_INT) 0xffff));
+  operands[3] = GEN_INT (high & 0xffff);
+  operands[4] = GEN_INT (low & (~ (HOST_WIDE_INT) 0xffff));
+  operands[5] = GEN_INT (low & 0xffff);
+}")
 
 (define_insn ""
   [(set (match_operand:CC 2 "cc_reg_operand" "=x")
       || INTVAL (operands[0]) > 32768)
     {
       neg_op0 = gen_reg_rtx (Pmode);
-      if (TARGET_POWERPC64)
-       emit_insn (gen_negdi2 (neg_op0, operands[0]));
-      else
+      if (TARGET_32BIT)
        emit_insn (gen_negsi2 (neg_op0, operands[0]));
+      else
+       emit_insn (gen_negdi2 (neg_op0, operands[0]));
     }
   else
     neg_op0 = GEN_INT (- INTVAL (operands[0]));
 
-  if (TARGET_POWERPC64)
-    emit_insn (gen_movdi_update (stack_pointer_rtx, stack_pointer_rtx, neg_op0, chain));
-  else
+  if (TARGET_32BIT)
     emit_insn (gen_movsi_update (stack_pointer_rtx, stack_pointer_rtx, neg_op0, chain));
+  else
+    emit_insn (gen_movdi_update (stack_pointer_rtx, stack_pointer_rtx, neg_op0, chain));
 
   DONE;
 }")
 
 ;; Table jump for switch statements:
 (define_expand "tablejump"
+  [(use (match_operand 0 "" ""))
+   (use (label_ref (match_operand 1 "" "")))]
+  ""
+  "
+{
+  if (TARGET_32BIT)
+    emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
+  else
+    emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
+  DONE;
+}")
+
+(define_expand "tablejumpsi"
   [(set (match_dup 3)
        (plus:SI (match_operand:SI 0 "" "")
                 (match_dup 2)))
   operands[3] = gen_reg_rtx (SImode);
 }")
 
+(define_expand "tablejumpdi"
+  [(set (match_dup 3)
+       (plus:DI (match_operand:DI 0 "" "")
+                (match_dup 2)))
+   (parallel [(set (pc) (match_dup 3))
+             (use (label_ref (match_operand 1 "" "")))])]
+  ""
+  "
+{ operands[0] = force_reg (DImode, operands[0]);
+  operands[2] = force_reg (DImode, gen_rtx (LABEL_REF, VOIDmode, operands[1]));
+  operands[3] = gen_reg_rtx (DImode);
+}")
+
 (define_insn ""
   [(set (pc)
        (match_operand:SI 0 "register_operand" "c,l"))