OSDN Git Service

* arm.md (movsfcc): Also validate operands[3] when compiling hard float.
authorrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 14 Feb 1998 05:14:13 +0000 (05:14 +0000)
committerrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 14 Feb 1998 05:14:13 +0000 (05:14 +0000)
(movdfcc): Only accept fpu_add_operand for operands[3].

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@17974 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/arm/arm.md

index 5042d58..df8af47 100644 (file)
@@ -1,3 +1,9 @@
+Sat Feb 14 05:08:21 1998  Richard Earnshaw (rearnsha@arm.com)
+
+       * arm.md (movsfcc): Also validate operands[3] when compiling hard
+       float.
+       (movdfcc): Only accept fpu_add_operand for operands[3].
+
 Sat Feb 14 02:02:41 1998  Jeffrey A Law  (law@cygnus.com)
 
        * varasm.c (output_constant_pool): Bring back 'done' label inside
index afc2794..ec70983 100644 (file)
@@ -1,7 +1,7 @@
 ;;- Machine description for Advanced RISC Machines' ARM for GNU compiler
 ;;  Copyright (C) 1991, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
-;;             and Martin Simmons (@harleqn.co.uk).
+;;  and Martin Simmons (@harleqn.co.uk).
 ;;  More major hacks by Richard Earnshaw (rwe11@cl.cam.ac.uk)
 
 ;; This file is part of GNU CC.
   "umull%?\\t%Q0, %R0, %1, %2"
 [(set_attr "type" "mult")])
 
+(define_insn "smulsi3_highpart"
+  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
+       (truncate:SI
+        (lshiftrt:DI
+         (mult:DI (sign_extend:DI
+                   (match_operand:SI 1 "s_register_operand" "%r,0"))
+                  (sign_extend:DI
+                   (match_operand:SI 2 "s_register_operand" "r,r")))
+         (const_int 32))))
+   (clobber (match_scratch:SI 3 "=&r,&r"))]
+  "arm_fast_multiply"
+  "smull%?\\t%3, %0, %2, %1"
+[(set_attr "type" "mult")])
+
+(define_insn "umulsi3_highpart"
+  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
+       (truncate:SI
+        (lshiftrt:DI
+         (mult:DI (zero_extend:DI
+                   (match_operand:SI 1 "s_register_operand" "%r,0"))
+                  (zero_extend:DI
+                   (match_operand:SI 2 "s_register_operand" "r,r")))
+         (const_int 32))))
+   (clobber (match_scratch:SI 3 "=&r,&r"))]
+  "arm_fast_multiply"
+  "umull%?\\t%3, %0, %2, %1"
+[(set_attr "type" "mult")])
+
 (define_insn "mulsf3"
   [(set (match_operand:SF 0 "s_register_operand" "=f")
        (mult:SF (match_operand:SF 1 "s_register_operand" "f")
   "
 {
   HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << INTVAL (operands[1])) - 1;
+  rtx target, subtarget;
 
+  target = operands[0];
+  /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
+     subreg as the final target.  */
+  if (GET_CODE (target) == SUBREG)
+    {
+      subtarget = gen_reg_rtx (SImode);
+      if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
+         < GET_MODE_SIZE (SImode))
+        target = SUBREG_REG (target);
+    }
+  else
+    subtarget = target;    
+    
   if (GET_CODE (operands[3]) == CONST_INT)
     {
       /* Since we are inserting a known constant, we may be able to
                             << INTVAL (operands[2]));
 
       emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
-      emit_insn (gen_iorsi3 (operands[0], op1,
+      emit_insn (gen_iorsi3 (subtarget, op1,
                             GEN_INT (INTVAL (operands[3])
                                      << INTVAL (operands[2]))));
     }
       emit_insn (gen_iorsi3 (op1, gen_rtx (LSHIFTRT, SImode, operands[0],
                                           operands[1]),
                             op0));
-      emit_insn (gen_rotlsi3 (operands[0], op1, operands[1]));
+      emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
     }
   else if ((INTVAL (operands[1]) + INTVAL (operands[2]) == 32)
           && ! (const_ok_for_arm (mask)
       emit_insn (gen_ashlsi3 (op0, operands[3],
                              GEN_INT (32 - INTVAL (operands[1]))));
       emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
-      emit_insn (gen_iorsi3 (operands[0], gen_rtx (LSHIFTRT, SImode, op1,
-                                                  operands[1]), op0));
+      emit_insn (gen_iorsi3 (subtarget,
+                            gen_rtx (LSHIFTRT, SImode, op1,
+                                     operands[1]), op0));
     }
   else
     {
       if (INTVAL (operands[2]) != 0)
        op1 = gen_rtx (ASHIFT, SImode, op1, operands[2]);
 
-      emit_insn (gen_iorsi3 (operands[0], op1, op2));
+      emit_insn (gen_iorsi3 (subtarget, op1, op2));
+    }
+
+  if (subtarget != target)
+    {
+      /* If TARGET is still a SUBREG, then it must be wider than a word,
+        so we must be careful only to set the subword we were asked to. */
+      if (GET_CODE (target) == SUBREG)
+       emit_move_insn (target, subtarget);
+      else
+       emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
     }
 
   DONE;
 
 (define_expand "storehi"
   [;; store the low byte
-   (set (mem:QI (match_operand:SI 1 "" "")) (match_dup 3))
+   (set (match_operand 1 "" "") (match_dup 3))
    ;; extract the high byte
    (set (match_dup 2)
        (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
    ;; store the high byte
-   (set (mem:QI (match_dup 4))
-       (subreg:QI (match_dup 2) 0))]   ;explicit subreg safe
+   (set (match_dup 4) (subreg:QI (match_dup 2) 0))]    ;explicit subreg safe
   ""
   "
 {
-  enum rtx_code code = GET_CODE (operands[1]);
+  rtx addr = XEXP (operands[1], 0);
+  enum rtx_code code = GET_CODE (addr);
 
-  if ((code == PLUS || code == MINUS)
-      && (GET_CODE (XEXP (operands[1], 1)) == REG
-         || GET_CODE (XEXP (operands[1], 0)) != REG))
-    operands[1] = force_reg (SImode, operands[1]);
-  operands[4] = plus_constant (operands[1], 1);
+  if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
+      || code == MINUS)
+    addr = force_reg (SImode, addr);
+
+  operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
+  operands[1] = change_address (operands[1], QImode, NULL_RTX);
   operands[3] = gen_lowpart (QImode, operands[0]);
   operands[0] = gen_lowpart (SImode, operands[0]);
   operands[2] = gen_reg_rtx (SImode); 
 ")
 
 (define_expand "storehi_bigend"
-  [(set (mem:QI (match_dup 4)) (match_dup 3))
+  [(set (match_dup 4) (match_dup 3))
    (set (match_dup 2)
        (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
-   (set (mem:QI (match_operand 1 "" ""))
-       (subreg:QI (match_dup 2) 0))]
+   (set (match_operand 1 "" "")        (subreg:QI (match_dup 2) 0))]
   ""
   "
 {
-  enum rtx_code code = GET_CODE (operands[1]);
-  if ((code == PLUS || code == MINUS)
-      && (GET_CODE (XEXP (operands[1], 1)) == REG
-         || GET_CODE (XEXP (operands[1], 0)) != REG))
-    operands[1] = force_reg (SImode, operands[1]);
+  rtx addr = XEXP (operands[1], 0);
+  enum rtx_code code = GET_CODE (addr);
+
+  if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
+      || code == MINUS)
+    addr = force_reg (SImode, addr);
 
-  operands[4] = plus_constant (operands[1], 1);
+  operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
+  operands[1] = change_address (operands[1], QImode, NULL_RTX);
   operands[3] = gen_lowpart (QImode, operands[0]);
   operands[0] = gen_lowpart (SImode, operands[0]);
   operands[2] = gen_reg_rtx (SImode);
 
 ;; Subroutine to store a half word integer constant into memory.
 (define_expand "storeinthi"
-  [(set (mem:QI (match_operand:SI 0 "" ""))
+  [(set (match_operand 0 "" "")
        (subreg:QI (match_operand 1 "" "") 0))
-   (set (mem:QI (match_dup 3)) (subreg:QI (match_dup 2) 0))]
+   (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
   ""
   "
 {
   HOST_WIDE_INT value = INTVAL (operands[1]);
-  enum rtx_code code = GET_CODE (operands[0]);
+  rtx addr = XEXP (operands[0], 0);
+  enum rtx_code code = GET_CODE (addr);
 
-  if ((code == PLUS || code == MINUS)
-      && (GET_CODE (XEXP (operands[0], 1)) == REG
-         || GET_CODE (XEXP (operands[0], 0)) != REG))
-  operands[0] = force_reg (SImode, operands[0]);
+  if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
+      || code == MINUS)
+    addr = force_reg (SImode, addr);
 
   operands[1] = gen_reg_rtx (SImode);
   if (BYTES_BIG_ENDIAN)
        }
     }
 
-  operands[3] = plus_constant (operands[0], 1);
+  operands[3] = change_address (operands[0], QImode, plus_constant (addr, 1));
+  operands[0] = change_address (operands[0], QImode, NULL_RTX);
 }
 ")
 
              DONE;
            }
          if (GET_CODE (operands[1]) == CONST_INT)
-           emit_insn (gen_storeinthi (XEXP (operands[0], 0), operands[1]));
+           emit_insn (gen_storeinthi (operands[0], operands[1]));
          else
            {
              if (GET_CODE (operands[1]) == MEM)
                operands[1] = force_reg (HImode, operands[1]);
              if (BYTES_BIG_ENDIAN)
-               emit_insn (gen_storehi_bigend (operands[1],
-                                              XEXP (operands[0], 0)));
+               emit_insn (gen_storehi_bigend (operands[1], operands[0]));
              else
-               emit_insn (gen_storehi (operands[1], XEXP (operands[0], 0)));
+               emit_insn (gen_storehi (operands[1], operands[0]));
            }
          DONE;
        }
     FAIL;
 
   operands[3]
-            = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
-                                     force_reg (SImode, XEXP (operands[1], 0)),
-                                     TRUE, FALSE);
+    = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
+                            force_reg (SImode, XEXP (operands[1], 0)),
+                            TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
+                            MEM_IN_STRUCT_P(operands[1]));
 ")
 
 ;; Load multiple with write-back
     FAIL;
 
   operands[3]
-           = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
-                                     force_reg (SImode, XEXP (operands[0], 0)),
-                                     TRUE, FALSE);
+    = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
+                             force_reg (SImode, XEXP (operands[0], 0)),
+                             TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
+                             MEM_IN_STRUCT_P(operands[0]));
 ")
 
 ;; Store multiple with write-back
   "
 {
   enum rtx_code code = GET_CODE (operands[1]);
-  rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
-                              arm_compare_fp);
+  rtx ccreg;
+
+  /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
+     Otherwise, ensure it is a valid FP add operand */
+  if ((! TARGET_HARD_FLOAT)
+      || (! fpu_add_operand (operands[3], SFmode)))
+    operands[3] = force_reg (SFmode, operands[3]);
+
+  ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
+                          arm_compare_fp);
 
   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
 }")
   [(set (match_operand:DF 0 "s_register_operand" "")
        (if_then_else:DF (match_operand 1 "comparison_operator" "")
                         (match_operand:DF 2 "s_register_operand" "")
-                        (match_operand:DF 3 "nonmemory_operand" "")))]
+                        (match_operand:DF 3 "fpu_add_operand" "")))]
   "TARGET_HARD_FLOAT"
   "
 {
 }")
 
 (define_insn "*movsicc_insn"
-  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r")
+  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
        (if_then_else:SI
         (match_operator 3 "comparison_operator"
          [(match_operand 4 "cc_register" "") (const_int 0)])
-        (match_operand:SI 1 "arm_not_operand" "0,0,?rI,?rI,K,K")
-        (match_operand:SI 2 "arm_not_operand" "rI,K,rI,K,rI,K")))]
+        (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
+        (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
   ""
   "@
    mov%D3\\t%0, %2
    mvn%D3\\t%0, #%B2
+   mov%d3\\t%0, %1
+   mvn%d3\\t%0, #%B1
    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
-  [(set_attr "length" "4,4,8,8,8,8")
+  [(set_attr "length" "4,4,4,4,8,8,8,8")
    (set_attr "conds" "use")])
 
 (define_insn "*movsfcc_hard_insn"
-  [(set (match_operand:SF 0 "s_register_operand" "=f,f")
-       (if_then_else:SF (match_operator 3 "comparison_operator" 
-                         [(match_operand 4 "cc_register" "") (const_int 0)])
-                        (match_operand:SF 1 "s_register_operand" "0,0")
-                        (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
+  [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
+       (if_then_else:SF
+        (match_operator 3 "comparison_operator" 
+         [(match_operand 4 "cc_register" "") (const_int 0)])
+        (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
+        (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
   "TARGET_HARD_FLOAT"
   "@
    mvf%D3s\\t%0, %2
-   mnf%D3s\\t%0, #%N2"
-  [(set_attr "type" "ffarith")
+   mnf%D3s\\t%0, #%N2
+   mvf%d3s\\t%0, %1
+   mnf%d3s\\t%0, #%N1
+   mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
+   mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
+   mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
+   mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
+  [(set_attr "length" "4,4,4,4,8,8,8,8")
+   (set_attr "type" "ffarith")
    (set_attr "conds" "use")])
 
 (define_insn "*movsfcc_soft_insn"
-  [(set (match_operand:SF 0 "s_register_operand" "=r")
+  [(set (match_operand:SF 0 "s_register_operand" "=r,r")
        (if_then_else:SF (match_operator 3 "comparison_operator"
                          [(match_operand 4 "cc_register" "") (const_int 0)])
-                        (match_operand:SF 1 "s_register_operand" "0")
-                        (match_operand:SF 2 "s_register_operand" "r")))]
+                        (match_operand:SF 1 "s_register_operand" "0,r")
+                        (match_operand:SF 2 "s_register_operand" "r,0")))]
   "TARGET_SOFT_FLOAT"
-  "mov%D3\\t%0, %2"
+  "@
+   mov%D3\\t%0, %2
+   mov%d3\\t%0, %1"
   [(set_attr "conds" "use")])
 
 (define_insn "*movdfcc_insn"
-  [(set (match_operand:DF 0 "s_register_operand" "=f,f")
-       (if_then_else:DF (match_operator 3 "comparison_operator"
-                         [(match_operand 4 "cc_register" "") (const_int 0)])
-                        (match_operand:DF 1 "s_register_operand" "0,0")
-                        (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
+  [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
+       (if_then_else:DF
+        (match_operator 3 "comparison_operator"
+         [(match_operand 4 "cc_register" "") (const_int 0)])
+        (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
+        (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
   "TARGET_HARD_FLOAT"
   "@
    mvf%D3d\\t%0, %2
-   mnf%D3d\\t%0, #%N2"
-  [(set_attr "type" "ffarith")
+   mnf%D3d\\t%0, #%N2
+   mvf%d3d\\t%0, %1
+   mnf%d3d\\t%0, #%N1
+   mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
+   mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
+   mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
+   mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
+  [(set_attr "length" "4,4,4,4,8,8,8,8")
+   (set_attr "type" "ffarith")
    (set_attr "conds" "use")])
 \f
 ;; Jump and linkage insns
   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"
-  [(set (pc)
-       (if_then_else
-        (leu (match_operand:SI 0 "s_register_operand" "r")
-             (match_operand:SI 1 "arm_rhs_operand" "rI"))
-        (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
-                         (label_ref (match_operand 2 "" ""))))
-        (label_ref (match_operand 3 "" ""))))]
+  [(parallel [(set (pc)
+              (if_then_else
+               (leu (match_operand:SI 0 "s_register_operand" "r")
+                    (match_operand:SI 1 "arm_rhs_operand" "rI"))
+               (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
+                                (label_ref (match_operand 2 "" ""))))
+               (label_ref (match_operand 3 "" ""))))
+             (use (label_ref (match_dup 2)))])]
   ""
   "*
   if (flag_pic)
   "sub%?s\\t%0, %1, #0"
 [(set_attr "conds" "set")])
 
-; Peepholes to spot possible load- and store-multiples, if the ordering is
-; reversed, check that the memory references aren't volatile.
+; Peepholes to spot possible load- and store-multiples.
 
 (define_peephole
   [(set (match_operand:SI 0 "s_register_operand" "=r")