sh.md (movdf_k, [...]): new alternative for pc-relative load.
authorJoern Rennecke <amylaar@gcc.gnu.org>
Thu, 24 Oct 1996 00:40:58 +0000 (01:40 +0100)
committerJoern Rennecke <amylaar@gcc.gnu.org>
Thu, 24 Oct 1996 00:40:58 +0000 (01:40 +0100)
        * sh.md (movdf_k, movsf_i, movsf_ie): new alternative for
        pc-relative load.
        (movsf_ieq): new define_insn with matching define_split.
        (movsf): use it where appropriate.
        (consttable_sf, consttable_df): new define_insns.

From-SVN: r13022

gcc/config/sh/sh.md

index 2c100ff3bb54adad54155777dd5b65a415cbb2ab..76d0a5b724e8db69f5b08f84c80db865aa145840 100644 (file)
 ;; ??? This should be a define expand.
 
 (define_insn "movdf_k"
-  [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,m")
-       (match_operand:DF 1 "general_movsrc_operand" "r,m,r"))]
+  [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
+       (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
   "arith_reg_operand (operands[0], DFmode)
    || arith_reg_operand (operands[1], DFmode)"
   "* return output_movedouble (insn, operands, DFmode);"
   [(set_attr "length" "4")
-   (set_attr "type" "move,load,store")])
+   (set_attr "type" "move,pcload,load,store")])
 
 ;; If the output is a register and the input is memory or a register, we have
 ;; to be careful and see which word needs to be loaded first.  
   "{ if (prepare_move_operands (operands, DFmode)) DONE; }")
 
 (define_insn "movsf_i"
-  [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m,l,r")
-       (match_operand:SF 1 "general_movsrc_operand"  "r,I,m,r,r,l"))]
+  [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
+       (match_operand:SF 1 "general_movsrc_operand"  "r,I,FQ,m,r,r,l"))]
   "
    ! TARGET_SH3E &&
    (arith_reg_operand (operands[0], SFmode)
        mov     %1,%0
        mov.l   %1,%0
        mov.l   %1,%0
+       mov.l   %1,%0
        lds     %1,%0
        sts     %1,%0"
-  [(set_attr "type" "move,move,load,store,move,move")])
+  [(set_attr "type" "move,move,pcload,load,store,move,move")])
 
 (define_insn "movsf_ie"
-  [(set (match_operand:SF 0 "general_movdst_operand" "=f,r,f,f,f,m,r,m,!r,!f")
-       (match_operand:SF 1 "general_movsrc_operand"  "f,r,G,H,m,f,m,r,f,r"))]
+  [(set (match_operand:SF 0 "general_movdst_operand" "=f,r,f,f,f,m,r,r,m,!r,!f")
+       (match_operand:SF 1 "general_movsrc_operand"  "f,r,G,H,m,f,FQ,m,r,f,r"))]
   "TARGET_SH3E
    && (arith_reg_operand (operands[0], SFmode)
        || arith_reg_operand (operands[1], SFmode))"
        fmov.s  %1,%0
        mov.l   %1,%0
        mov.l   %1,%0
+       mov.l   %1,%0
        flds    %1,fpul\;sts    fpul,%0
        lds     %1,fpul\;fsts   fpul,%0"
-  [(set_attr "type" "move,move,fp,fp,load,store,load,store,move,fp")
-   (set_attr "length" "*,*,*,*,*,*,*,*,4,4")])
+  [(set_attr "type" "move,move,fp,fp,load,store,pcload,load,store,move,fp")
+   (set_attr "length" "*,*,*,*,*,*,*,*,*,4,4")])
+
+(define_insn "movsf_ieq"
+  [(set (match_operand:SF 0 "general_movdst_operand" "=f")
+       (match_operand:SF 1 "general_movsrc_operand"  "FQ"))
+   (clobber (reg:SI 0))]
+  "TARGET_SH3E
+   && (arith_reg_operand (operands[0], SFmode)
+       || arith_reg_operand (operands[1], SFmode))"
+  "#"
+  [(set_attr "type" "pcload") (set_attr "length" "4")])
+
+(define_split
+  [(set (match_operand:SF 0 "general_movdst_operand" "")
+       (match_operand:SF 1 "general_movsrc_operand"  ""))
+   (clobber (reg:SI 0))]
+  "GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER"
+  [(set (match_dup 0) (match_dup 1))]
+  "
+{
+  if (REGNO (operands[0]) >= FIRST_FP_REG && REGNO (operands[0]) <= LAST_FP_REG)
+    {
+      emit_insn (gen_mova (XEXP (operands[1], 0)));
+      XEXP (operands[1], 0) = gen_rtx (REG, Pmode, 0);
+    }
+}")
 
 (define_expand "movsf"
   [(set (match_operand:SF 0 "general_movdst_operand" "")
-       (match_operand:SF 1 "general_movsrc_operand" ""))]
+        (match_operand:SF 1 "general_movsrc_operand" ""))]
   ""
-  "{ if (prepare_move_operands (operands, SFmode)) DONE; }")
+  "
+{
+  if (prepare_move_operands (operands, SFmode))
+    DONE;
+  if (TARGET_SH3E && GET_CODE (operands[1]) == CONST_DOUBLE
+      && ! fp_zero_operand (operands[1]) && ! fp_one_operand (operands[1])
+      && GET_CODE (operands[0]) == REG
+      && (REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER
+         || (REGNO (operands[0]) >= FIRST_FP_REG
+             && REGNO (operands[0]) <= LAST_FP_REG)))
+    {
+      emit_insn (gen_movsf_ieq (operands[0], operands[1]));
+      DONE;
+    }
+}")
 \f
 ;; ------------------------------------------------------------------------
 ;; Define the real conditional branch instructions.
  [(set_attr "length" "8")
   (set_attr "in_delay_slot" "no")])
 
+; 4 byte floating point
+
+(define_insn "consttable_sf"
+ [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")] 4)]
+ ""
+ "*
+{
+  union real_extract u;
+  bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
+  assemble_real (u.d, SFmode);
+  return \"\";
+}"
+ [(set_attr "length" "4")
+  (set_attr "in_delay_slot" "no")])
+
+; 8 byte floating point
+
+(define_insn "consttable_df"
+ [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")] 6)]
+ ""
+ "*
+{
+  union real_extract u;
+  bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
+  assemble_real (u.d, DFmode);
+  return \"\";
+}"
+ [(set_attr "length" "8")
+  (set_attr "in_delay_slot" "no")])
+
 ; align to a two byte boundary
 
 (define_insn "align_2"