]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
(storehi_bigend): New expansion pattern.
authorRichard Earnshaw <erich@gnu.org>
Mon, 6 Jun 1994 13:14:03 +0000 (13:14 +0000)
committerRichard Earnshaw <erich@gnu.org>
Mon, 6 Jun 1994 13:14:03 +0000 (13:14 +0000)
(storeinthi): Rework to generate better code, add big-endian support.
(movhi): Add support for processors running in big-endian mode.
(movhi_bigend): New expansion pattern.
(matcher for movhi): Remove incorrect alternative for storing HImode to
memory.  Only match when little endian.
(matcher for big-endian movhi): New pattern.
(matchers/peepholes for extended pre/post increment HImode loads): Only
match when little-endian.
(matcher for operating on adjacent memory locations): Load operation into
arith operands.
(peepholes for extended pre-increment byte loads): New patterns.

From-SVN: r7448

gcc/config/arm/arm.md

index 2c9a8aeefc32cd4095c6f222fa1885444f52e9a2..d860edabe09c6f34f9b9c8434c3c057123d7a1d9 100644 (file)
 }
 ")
 
-;; Subroutine to store a half word integer constant into memory.
-;; Operand 0 is the constant
-;; Operand 1 is the destination address in a register (SImode)
-
-(define_expand "storeinthi"
-  [;; store the low byte
-   (set (mem:QI (match_operand:SI 1 "" "")) (match_operand 0 "" ""))
-   ;; store the high byte
-   (set (mem:QI (match_dup 3)) (match_dup 2))]
+(define_expand "storehi_bigend"
+  [(set (mem:QI (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))]
   ""
   "
 {
-  int value = INTVAL (operands[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]);
+    operands[1] = force_reg (SImode, operands[1]);
 
-  operands[0] = force_reg (QImode, gen_rtx (CONST_INT, VOIDmode, value & 255));
-  operands[2] = force_reg (QImode,
-                          gen_rtx (CONST_INT, VOIDmode,(value>>8) & 255));
-  operands[3] = plus_constant (operands[1], 1);
+  operands[4] = plus_constant (operands[1], 1);
+  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 "" ""))
+       (subreg:QI (match_operand 1 "" "") 0))
+   (set (mem:QI (match_dup 3)) (subreg:QI (match_dup 2) 0))]
+  ""
+  "
+{
+  HOST_WIDE_INT value = INTVAL (operands[1]);
+  enum rtx_code code = GET_CODE (operands[0]);
+
+  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]);
+
+  operands[1] = gen_reg_rtx (SImode);
+  if (BYTES_BIG_ENDIAN)
+    {
+      emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
+      if ((value & 255) == ((value >> 8) & 255))
+       operands[2] = operands[1];
+      else
+       {
+         operands[2] = gen_reg_rtx (SImode);
+         emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
+       }
+    }
+  else
+    {
+      emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
+      if ((value & 255) == ((value >> 8) & 255))
+       operands[2] = operands[1];
+      else
+       {
+         operands[2] = gen_reg_rtx (SImode);
+         emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
+       }
+    }
+
+  operands[3] = plus_constant (operands[0], 1);
 }
 ")
 
 {
   rtx insn;
 
-  if (reload_in_progress || reload_completed)
-    insn = gen_rtx (SET, VOIDmode, operands[0], operands[1]);
-  else
+  if (! (reload_in_progress || reload_completed))
     {
       if (GET_CODE (operands[0]) == MEM)
        {
          if (GET_CODE (operands[1]) == CONST_INT)
-           {
-             insn = gen_storeinthi (operands[1], XEXP (operands[0],0));
-           }
+           emit_insn (gen_storeinthi (XEXP (operands[0], 0), operands[1]));
          else
            {
              if (GET_CODE (operands[1]) == MEM)
                operands[1] = force_reg (HImode, operands[1]);
-             insn = gen_storehi (operands[1], XEXP (operands[0], 0));
+             if (BYTES_BIG_ENDIAN)
+               emit_insn (gen_storehi_bigend (operands[1],
+                                              XEXP (operands[0], 0)));
+             else
+               emit_insn (gen_storehi (operands[1], XEXP (operands[0], 0)));
            }
+         DONE;
        }
-      else if (GET_CODE (operands[1]) == CONST_INT
-              && !(const_ok_for_arm (INTVAL (operands[1]))
-                  || const_ok_for_arm (~INTVAL (operands[1]))))
+      /* Sign extend a constant, and keep it in an SImode reg.  */
+      else if (GET_CODE (operands[1]) == CONST_INT)
        {
-         rtx reg, reg2;
+         rtx reg = gen_reg_rtx (SImode);
+         HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
 
-         /* no need to be clever, this will always take two insns.
-            The top sixteen bits should be all zeros or all ones. */
-         if (INTVAL (operands[1]) < 0)
-           {
-             emit_insn (gen_movsi (reg = gen_reg_rtx (SImode),
-                                   GEN_INT (INTVAL (operands[1])
-                                            | ~(0x0ff00))));
-             emit_insn (gen_addsi3 (reg2 = gen_reg_rtx (SImode), reg,
-                                    GEN_INT (-((~INTVAL (operands[1]))
-                                               & 0xff))));
-           }
-         else
+         /* If the constant is already valid, leave it alone.  */
+         if (! const_ok_for_arm (val))
            {
-             emit_insn (gen_movsi (reg = gen_reg_rtx (SImode),
-                                   GEN_INT (INTVAL (operands[1]) & 0xff00)));
-             emit_insn (gen_addsi3 (reg2 = gen_reg_rtx (SImode), reg,
-                                    GEN_INT (INTVAL (operands[1]) & 0x00ff)));
+             /* If setting all the top bits will make the constant 
+                loadable in a single instruction, then set them.  
+                Otherwise, sign extend the number.  */
+
+             if (const_ok_for_arm (~ (val | ~0xffff)))
+               val |= ~0xffff;
+             else if (val & 0x8000)
+               val |= ~0xffff;
            }
-         insn = gen_rtx (SET, HImode, operands[0],
-                         gen_rtx (SUBREG, HImode, reg2, 0));
+
+         emit_insn (gen_movsi (reg, GEN_INT (val)));
+         operands[1] = gen_rtx (SUBREG, HImode, reg, 0);
+       }
+      else if (BYTES_BIG_ENDIAN && GET_CODE (operands[1]) == MEM)
+       {
+         emit_insn (gen_movhi_bigend (operands[0], operands[1]));
+         DONE;
        }
-      else
-       insn = gen_rtx (SET, VOIDmode, operands[0], operands[1]);
     }
+}
+")
 
-  emit_insn (insn);
-  DONE;
-}")
+(define_expand "movhi_bigend"
+  [(set (match_dup 2)
+       (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
+                  (const_int 16)))
+   (set (match_dup 3)
+       (ashiftrt:SI (match_dup 2) (const_int 16)))
+   (set (match_operand:HI 0 "s_register_operand" "")
+       (subreg:HI (match_dup 3) 0))]
+  ""
+  "
+  operands[2] = gen_reg_rtx (SImode);
+  operands[3] = gen_reg_rtx (SImode);
+")
 
 ;; Pattern to recognise insn generated default case above
 
 (define_insn ""
-  [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
-       (match_operand:HI 1 "general_operand"  "rI,K,m,r"))]
-  "(register_operand (operands[0], HImode)
-    && (GET_CODE (operands[1]) != CONST_INT
-       || const_ok_for_arm (INTVAL (operands[1]))
-       || const_ok_for_arm (~INTVAL (operands[1]))))
-   || register_operand (operands[1], HImode)"
+  [(set (match_operand:HI 0 "general_operand" "=r,r,r")
+       (match_operand:HI 1 "general_operand"  "rI,K,m"))]
+  "(! BYTES_BIG_ENDIAN)
+   && (GET_CODE (operands[1]) != CONST_INT
+       || const_ok_for_arm (INTVAL (operands[1]))
+       || const_ok_for_arm (~INTVAL (operands[1])))"
   "@
    mov%?\\t%0, %1\\t%@ movhi
    mvn%?\\t%0, #%B1\\t%@ movhi
-   ldr%?\\t%0, %1\\t%@ movhi
-   bogus code str%?\\t%1, %0\\t%@ movhi"
-[(set_attr "type" "*,*,load,store1")])
+   ldr%?\\t%0, %1\\t%@ movhi"
+[(set_attr "type" "*,*,load")])
+
+(define_insn ""
+  [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
+       (match_operand:HI 1 "general_operand"  "rI,K,m"))]
+  "BYTES_BIG_ENDIAN
+   && (GET_CODE (operands[1]) != CONST_INT
+       || const_ok_for_arm (INTVAL (operands[1]))
+       || const_ok_for_arm (~INTVAL (operands[1])))"
+  "@
+   mov%?\\t%0, %1\\t%@ movhi
+   mvn%?\\t%0, #%B1\\t%@ movhi
+   ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
+[(set_attr "type" "*,*,load")
+ (set_attr "length" "4,4,8")])
+
+(define_insn ""
+  [(set (match_operand:SI 0 "s_register_operand" "=r")
+       (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
+                  (const_int 16)))]
+  "BYTES_BIG_ENDIAN"
+  "ldr%?\\t%0, %1\\t%@ movhi_bigend"
+[(set_attr "type" "load")])
 
 (define_expand "reload_outhi"
   [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
 
   if (!(reload_in_progress || reload_completed))
     {
-      rtx reg;
       if (GET_CODE (operands[1]) == CONST_INT)
        {
-         emit_insn (gen_movsi (reg = gen_reg_rtx (SImode), operands[1]));
+         rtx reg = gen_reg_rtx (SImode);
+
+         emit_insn (gen_movsi (reg, operands[1]));
          operands[1] = gen_rtx (SUBREG, QImode, reg, 0);
        }
     }
   "*
 {
   rtx ldm[3];
-  rtx arith[3];
+  rtx arith[4];
   int val1 = 0, val2 = 0;
 
   if (REGNO (operands[0]) > REGNO (operands[4]))
   if (GET_CODE (XEXP (operands[3], 0)) != REG)
     val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
   arith[0] = operands[0];
+  arith[3] = operands[1];
   if (val1 < val2)
     {
       arith[1] = ldm[1];
       else
        output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
     }
-  output_asm_insn (\"%I1%?\\t%0, %1, %2\", arith);
+  output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
   return \"\";
 }
 "
                         (match_operand:SI 2 "index_operand" "rJ"))))
    (set (match_operand:SI 0 "s_register_operand" "=r")
        (plus:SI (match_dup 1) (match_dup 2)))]
-  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
+  "(! BYTES_BIG_ENDIAN)
+   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
    && (GET_CODE (operands[2]) != REG
        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
                          (match_operand:SI 2 "s_register_operand" "r"))))
    (set (match_operand:SI 0 "s_register_operand" "=r")
        (minus:SI (match_dup 1) (match_dup 2)))]
-  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
+  "(!BYTES_BIG_ENDIAN)
+   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
    && (GET_CODE (operands[2]) != REG
        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
    (set (match_operand:SI 0 "s_register_operand" "=r")
        (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
                 (match_dup 1)))]
-  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
+  "(! BYTES_BIG_ENDIAN)
+   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
   "ldr%?\\t%5, [%0, %3, %S2]!\\t%@ loadhi"
    (set (match_operand:SI 0 "s_register_operand" "=r")
        (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
                                                 (match_dup 4)])))]
-  "REGNO (operands[0]) != FRAME_POINTER_REGNUM
+  "(! BYTES_BIG_ENDIAN)
+   && REGNO (operands[0]) != FRAME_POINTER_REGNUM
    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
   "ldr%?\\t%5, [%0, -%3, %S2]!\\t%@ loadhi"
    (set (match_dup 0)
        (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
   ""
-  "strb\\t%2, [%0], %1")
+  "str%?b\\t%2, [%0], %1")
 
 (define_peephole
   [(set (match_operand:QI 0 "s_register_operand" "=r")
        (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
    (set (match_dup 1)
        (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
-  "REGNO(operands[0]) != REGNO(operands[1])
+  "(! BYTES_BIG_ENDIAN)
+   && REGNO(operands[0]) != REGNO(operands[1])
    && (GET_CODE (operands[2]) != REG
        || REGNO(operands[0]) != REGNO (operands[2]))"
   "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
        || REGNO(operands[0]) != REGNO (operands[2]))"
   "ldr%?\\t%0, [%1], %2")
 
+(define_peephole
+  [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
+                        (match_operand:SI 1 "index_operand" "rJ")))
+       (match_operand:QI 2 "s_register_operand" "r"))
+   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
+  ""
+  "str%?b\\t%2, [%0, %1]!")
+
+(define_peephole
+  [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
+                         [(match_operand:SI 0 "s_register_operand" "r")
+                          (match_operand 1 "const_int_operand" "n")])
+                        (match_operand:SI 2 "s_register_operand" "+r")))
+       (match_operand:QI 3 "s_register_operand" "r"))
+   (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
+                              (match_dup 2)))]
+  ""
+  "str%?b\\t%3, [%2, %0, %S4]!")
+
 ; This pattern is never tried by combine, so do it as a peephole
 
 (define_peephole