OSDN Git Service

* config/h8300/h8300.md (an anonymous pattern): New.
[pf3gnuchains/gcc-fork.git] / gcc / config / h8300 / h8300.md
index 50d3e4f..a260083 100644 (file)
 ;; "worst case" and then be adjusted to their correct values by
 ;; h8300_adjust_insn_length.
 
-;; On the H8/300H and H8/S, adds/subs operate on the 32bit "er"
+;; On the H8/300H and H8S, adds/subs operate on the 32bit "er"
 ;; registers.  Right now GCC doesn't expose the "e" half to the
 ;; compiler, so using add/subs for addhi and subhi is safe.  Long
 ;; term, we want to expose the "e" half to the compiler (gives us 8
 ;; more 16bit registers).  At that point addhi and subhi can't use
 ;; adds/subs.
 
-;; There's currently no way to have a insv/extzv expander for the H8/300H
+;; There's currently no way to have an insv/extzv expander for the H8/300H
 ;; because word_mode is different for the H8/300 and H8/300H.
 
 ;; Shifts/rotates by small constants should be handled by special
@@ -90,7 +90,7 @@
 
 (define_attr "adjust_length" "yes,no"
   (cond [(eq_attr "type" "branch") (const_string "no")]
-        (const_string "yes")))
+       (const_string "yes")))
 
 ;; Condition code settings.
 ;;
 
 (define_insn "pushqi1_h8300"
   [(parallel [(set (reg:HI SP_REG)
-                   (plus:HI (reg:HI SP_REG) (const_int -2)))
-              (set (mem:QI (plus:HI (reg:HI SP_REG) (const_int -1)))
-                   (match_operand:QI 0 "register_operand" "r"))])]
+                  (plus:HI (reg:HI SP_REG) (const_int -2)))
+             (set (mem:QI (plus:HI (reg:HI SP_REG) (const_int -1)))
+                  (match_operand:QI 0 "register_operand" "r"))])]
   "TARGET_H8300"
   "mov.w\\t%T0,@-r7"
   [(set_attr "length" "2")
 
 (define_insn "pushqi1_h8300hs"
   [(parallel [(set (reg:SI SP_REG)
-                   (plus:SI (reg:SI SP_REG) (const_int -4)))
-              (set (mem:QI (plus:SI (reg:SI SP_REG) (const_int -3)))
-                   (match_operand:QI 0 "register_operand" "r"))])]
+                  (plus:SI (reg:SI SP_REG) (const_int -4)))
+             (set (mem:QI (plus:SI (reg:SI SP_REG) (const_int -3)))
+                  (match_operand:QI 0 "register_operand" "r"))])]
   "TARGET_H8300H || TARGET_H8300S"
   "mov.l\\t%S0,@-er7"
   [(set_attr "length" "4")
 
 (define_expand "pushhi1_h8300"
   [(set (mem:HI (pre_dec:HI (reg:HI SP_REG)))
-        (match_operand:HI 0 "register_operand" ""))]
+       (match_operand:HI 0 "register_operand" ""))]
   "TARGET_H8300"
   "")
 
 (define_insn "pushhi1_h8300hs"
   [(parallel [(set (reg:SI SP_REG)
-                   (plus:SI (reg:SI SP_REG) (const_int -4)))
-              (set (mem:HI (plus:SI (reg:SI SP_REG) (const_int -2)))
-                   (match_operand:HI 0 "register_operand" "r"))])]
+                  (plus:SI (reg:SI SP_REG) (const_int -4)))
+             (set (mem:HI (plus:SI (reg:SI SP_REG) (const_int -2)))
+                  (match_operand:HI 0 "register_operand" "r"))])]
   "TARGET_H8300H || TARGET_H8300S"
   "mov.l\\t%S0,@-er7"
   [(set_attr "length" "4")
            }
 
          /* Look for constants that can be obtained by subs, inc, and
-             dec to 0.  */
+            dec to 0.  */
          switch (val & 0xffffffff)
            {
            case 0xffffffff:
   [(set_attr "length" "2")
    (set_attr "cc" "set_zn")])
 
+(define_insn ""
+  [(set (cc0)
+       (and:HI (match_operand:HI 0 "register_operand" "r")
+               (match_operand:HI 1 "single_one_operand" "n")))]
+  ""
+  "*
+{
+  operands[1] = GEN_INT (INTVAL (operands[1]) & 0xffff);
+  if (INTVAL (operands[1]) > 128)
+    {
+      operands[1] = GEN_INT (INTVAL (operands[1]) >> 8);
+      return \"btst\\t%V1,%t0\";
+    }
+  return \"btst\\t%V1,%s0\";
+}"
+  [(set_attr "length" "2")
+   (set_attr "cc" "set_zn")])
+
+(define_insn ""
+  [(set (cc0)
+       (and:SI (match_operand:SI 0 "register_operand" "r")
+               (match_operand:SI 1 "single_one_operand" "n")))]
+  "(TARGET_H8300H || TARGET_H8300S)
+   && (INTVAL (operands[1]) & 0xffff) != 0"
+  "*
+{
+  operands[1] = GEN_INT (INTVAL (operands[1]) & 0xffff);
+  if (INTVAL (operands[1]) > 128)
+    {
+      operands[1] = GEN_INT (INTVAL (operands[1]) >> 8);
+      return \"btst\\t%V1,%x0\";
+    }
+  return \"btst\\t%V1,%w0\";
+}"
+  [(set_attr "length" "2")
+   (set_attr "cc" "set_zn")])
+
 (define_insn "tstqi"
   [(set (cc0) (match_operand:QI 0 "register_operand" "r"))]
   ""
   [(set_attr "length" "2")
    (set_attr "cc" "set_znv")])
 
+(define_insn ""
+  [(set (cc0)
+       (and:HI (match_operand:HI 0 "register_operand" "r")
+               (const_int -256)))]
+  ""
+  "mov.b       %t0,%t0"
+  [(set_attr "length" "2")
+   (set_attr "cc" "set_znv")])
+
 (define_insn "tstsi"
   [(set (cc0) (match_operand:SI 0 "register_operand" "r"))]
   "TARGET_H8300H || TARGET_H8300S"
   [(set_attr "length" "2")
    (set_attr "cc" "set_znv")])
 
+(define_insn ""
+  [(set (cc0)
+       (and:SI (match_operand:SI 0 "register_operand" "r")
+               (const_int -65536)))]
+  ""
+  "mov.w       %e0,%e0"
+  [(set_attr "length" "2")
+   (set_attr "cc" "set_znv")])
+
 (define_insn "cmpqi"
   [(set (cc0)
        (compare:QI (match_operand:QI 0 "register_operand" "r")
 ;; DIVIDE/MOD INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
-(define_expand "udivmodqi4"
-  [(set (match_operand:HI 1 "register_operand" "")
-       (and:HI (match_dup 1)
-               (const_int 255)))
-   (parallel [(set (match_operand:QI 0 "register_operand" "")
-                  (truncate:QI
-                    (udiv:HI
-                      (match_dup 1)
-                      (zero_extend:HI
-                        (match_operand:QI 2 "register_operand" "")))))
-             (set (match_operand:QI 3 "register_operand" "")
-                  (truncate:QI
-                    (umod:HI
-                      (match_dup 1)
-                      (zero_extend:HI (match_dup 2)))))])]
-  "TARGET_H8300H || TARGET_H8300S"
-  "")
-
-(define_insn ""
+(define_insn "udivmodqi4"
   [(set (match_operand:QI 0 "register_operand" "=r")
        (truncate:QI
          (udiv:HI
          (umod:HI
            (match_dup 1)
            (zero_extend:HI (match_dup 2)))))]
-  "TARGET_H8300H || TARGET_H8300S"
+  ""
   "*
 {
   if (find_reg_note (insn, REG_UNUSED, operands[3]))
   [(set_attr "length" "6")
    (set_attr "cc" "clobber")])
 
-(define_expand "udivmodhi4"
-  [(set (match_operand:SI 1 "register_operand" "")
-       (and:SI (match_dup 1)
-               (const_int 65535)))
-   (parallel [(set (match_operand:HI 0 "register_operand" "")
-                  (truncate:HI
-                    (udiv:SI
-                      (match_dup 1)
-                      (zero_extend:SI
-                        (match_operand:HI 2 "register_operand" "")))))
-             (set (match_operand:HI 3 "register_operand" "")
-                  (truncate:HI
-                    (umod:SI
-                      (match_dup 1)
-                      (zero_extend:SI (match_dup 2)))))])]
-  "TARGET_H8300H || TARGET_H8300S"
-  "")
-
-(define_insn ""
+(define_insn "udivmodhi4"
   [(set (match_operand:HI 0 "register_operand" "=r")
        (truncate:HI
          (udiv:SI
 (define_insn ""
   [(set (match_operand:QI 0 "bit_operand" "=r,U")
        (and:QI (match_operand:QI 1 "bit_operand" "%0,0")
-               (match_operand:QI 2 "nonmemory_operand" "rn,O")))]
+               (match_operand:QI 2 "nonmemory_operand" "rn,n")))]
   "register_operand (operands[0], QImode)
    || single_zero_operand (operands[2], QImode)"
   "@
                        (match_operand:QI 3 "single_one_operand" "n"))
                (match_operand:QI 1 "register_operand" "0")))]
   ""
-  "bld\\t%V3,%X2\;bst\\t%V3,%X0"
-  [(set_attr "length" "4")
+  "bld\\t%V3,%X2\;bor\\t%V3,%X0\;bst\\t%V3,%X0"
+  [(set_attr "length" "6")
    (set_attr "cc" "clobber")])
 
 (define_insn "*andorhi3"
   [(set (match_operand:HI 0 "register_operand" "=r")
        (ior:HI (and:HI (match_operand:HI 2 "register_operand" "r")
                        (match_operand:HI 3 "single_one_operand" "n"))
-       (match_operand:HI 1 "register_operand" "0")))]
+               (match_operand:HI 1 "register_operand" "0")))]
   ""
   "*
 {
   if (INTVAL (operands[3]) > 128)
     {
       operands[3] = GEN_INT (INTVAL (operands[3]) >> 8);
-      return \"bld\\t%V3,%t2\;bst\\t%V3,%t0\";
+      return \"bld\\t%V3,%t2\;bor\\t%V3,%t0\;bst\\t%V3,%t0\";
     }
-  return \"bld\\t%V3,%s2\;bst\\t%V3,%s0\";
+  return \"bld\\t%V3,%s2\;bor\\t%V3,%s0\;bst\\t%V3,%s0\";
 }"
-  [(set_attr "length" "4")
+  [(set_attr "length" "6")
+   (set_attr "cc" "clobber")])
+
+(define_insn "*andorsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ior:SI (and:SI (match_operand:SI 2 "register_operand" "r")
+                       (match_operand:SI 3 "single_one_operand" "n"))
+               (match_operand:SI 1 "register_operand" "0")))]
+  "(INTVAL (operands[3]) & 0xffff) != 0"
+  "*
+{
+  operands[3] = GEN_INT (INTVAL (operands[3]) & 0xffff);
+  if (INTVAL (operands[3]) > 128)
+    {
+      operands[3] = GEN_INT (INTVAL (operands[3]) >> 8);
+      return \"bld\\t%V3,%x2\;bor\\t%V3,%x0\;bst\\t%V3,%x0\";
+    }
+  return \"bld\\t%V3,%w2\;bor\\t%V3,%w0\;bst\\t%V3,%w0\";
+}"
+  [(set_attr "length" "6")
    (set_attr "cc" "clobber")])
 
 (define_expand "andsi3"
 {
   if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0
       && (GET_CODE (operands[1]) == GT
-          || GET_CODE (operands[1]) == GE
-          || GET_CODE (operands[1]) == LE
-          || GET_CODE (operands[1]) == LT))
+         || GET_CODE (operands[1]) == GE
+         || GET_CODE (operands[1]) == LE
+         || GET_CODE (operands[1]) == LT))
     {
       cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
       return 0;
 {
   if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0
       && (GET_CODE (operands[1]) == GT
-          || GET_CODE (operands[1]) == GE
-          || GET_CODE (operands[1]) == LE
-          || GET_CODE (operands[1]) == LT))
+         || GET_CODE (operands[1]) == GE
+         || GET_CODE (operands[1]) == LE
+         || GET_CODE (operands[1]) == LT))
     {
       cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
       return 0;
   [(set_attr "cc" "none")
    (set_attr "length" "2")])
 
+(define_insn "tablejump_normal_mode"
+   [(set (pc) (match_operand:HI 0 "register_operand" "r"))
+    (use (label_ref (match_operand 1 "" "")))]
+   "(TARGET_H8300H || TARGET_H8300S) && TARGET_NORMAL_MODE"
+   "jmp @%S0"
+   [(set_attr "cc" "none")
+    (set_attr "length" "2")])
+
 ;; This is a define expand, because pointers may be either 16 or 32 bits.
 
 (define_expand "indirect_jump"
   [(set_attr "cc" "none")
    (set_attr "length" "2")])
 
+(define_insn "indirect_jump_normal_mode"
+  [(set (pc) (match_operand:HI 0 "jump_address_operand" "Vr"))]
+  "(TARGET_H8300H || TARGET_H8300S) && TARGET_NORMAL_MODE"
+  "jmp @%S0"
+  [(set_attr "cc" "none")
+   (set_attr "length" "2")])
+
 ;; Call subroutine with no return value.
 
-;; ??? Even though we use HImode here, this works on the H8/300H and H8/S.
+;; ??? Even though we use HImode here, this works on the H8/300H and H8S.
 
 (define_insn "call"
   [(call (match_operand:QI 0 "call_insn_operand" "or")
 ;; Call subroutine, returning value in operand 0
 ;; (which must be a hard register).
 
-;; ??? Even though we use HImode here, this works on the H8/300H and H8/S.
+;; ??? Even though we use HImode here, this works on the H8/300H and H8S.
 
 (define_insn "call_value"
   [(set (match_operand 0 "" "=r")
   [(set_attr "length" "2,10")
    (set_attr "cc" "set_znv,set_znv")])
 
-;; The compiler can synthesize a 300H variant of this which is
+;; The compiler can synthesize a H8/300H variant of this which is
 ;; just as efficient as one that we'd create
 (define_insn "zero_extendqisi2"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
   [(set_attr "length" "2")
    (set_attr "cc" "set_znv")])
 
-;; The compiler can synthesize a 300H variant of this which is
+;; The compiler can synthesize a H8/300H variant of this which is
 ;; just as efficient as one that we'd create
 (define_insn "extendqisi2"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
   "TARGET_H8300"
   "
 {
-  /* We only have single bit bitfield instructions.  */
+  /* We only have single bit bit-field instructions.  */
   if (INTVAL (operands[1]) != 1)
     FAIL;
 
   "TARGET_H8300"
   "
 {
-  /* We only have single bit bitfield instructions.  */
+  /* We only have single bit bit-field instructions.  */
   if (INTVAL (operands[2]) != 1)
     FAIL;
 
 
 (define_insn ""
   [(set (match_operand:HI 0 "register_operand" "=r")
-        (ior:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
+       (ior:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
                (match_operand:HI 2 "register_operand" "0")))]
   "REG_P (operands[0])
    && REG_P (operands[1])
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
-        (ior:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
+       (ior:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
                (match_operand:SI 2 "register_operand" "0")))]
   "(TARGET_H8300H || TARGET_H8300S)
    && REG_P (operands[0])
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
-        (ior:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
+       (ior:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
                (match_operand:SI 2 "register_operand" "0")))]
-  "REG_P (operands[0])
-   && REG_P (operands[1])
-   && REGNO (operands[0]) != REGNO (operands[1])"
-  "or\\t%X1,%s0"
+  ""
+  "or\\t%X1,%w0"
   [(set_attr "cc" "clobber")
    (set_attr "length" "2")])
 
 (define_insn ""
   [(set (match_operand:HI 0 "register_operand" "=r")
-        (xor:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
+       (xor:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
                (match_operand:HI 2 "register_operand" "0")))]
   "REG_P (operands[0])
    && REG_P (operands[1])
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
-        (xor:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
+       (xor:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
                (match_operand:SI 2 "register_operand" "0")))]
   "(TARGET_H8300H || TARGET_H8300S)
    && REG_P (operands[0])
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
-        (xor:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
+       (xor:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
                (match_operand:SI 2 "register_operand" "0")))]
   "REG_P (operands[0])
    && REG_P (operands[1])
    && REGNO (operands[0]) != REGNO (operands[1])"
-  "xor\\t%X1,%s0"
+  "xor\\t%X1,%w0"
   [(set_attr "cc" "clobber")
    (set_attr "length" "2")])
 
 (define_insn ""
   [(set (match_operand:HI 0 "register_operand" "=r")
-        (ior:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "0"))
+       (ior:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "0"))
                (ashift:HI (match_operand:HI 2 "register_operand" "r")
                           (const_int 8))))]
   "REG_P (operands[0])
 
 (define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
-        (ior:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "0"))
+       (ior:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "0"))
                (ashift:SI (match_operand:SI 2 "register_operand" "r")
                           (const_int 16))))]
-  "(TARGET_H8300H || TARGET_H8300S)
-   && REG_P (operands[0])
-   && REG_P (operands[2])
-   && (REGNO (operands[0]) != REGNO (operands[2]))"
+  "TARGET_H8300H || TARGET_H8300S"
   "mov.w\\t%f2,%e0"
   [(set_attr "cc" "clobber")
    (set_attr "length" "2")])
 
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
+                          (const_int 16))
+               (match_operand:SI 2 "register_operand" "0")))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "or.w\\t%f1,%e0"
+  [(set_attr "cc" "clobber")
+   (set_attr "length" "2")])
+
+;; Storing a part of HImode to QImode.
+
+(define_insn ""
+  [(set (match_operand:QI 0 "general_operand_dst" "=rm<")
+       (subreg:QI (lshiftrt:HI (match_operand:HI 1 "register_operand" "r")
+                               (const_int 8)) 1))]
+  ""
+  "mov.b\\t%t1,%R0"
+  [(set_attr "cc" "set_znv")
+   (set_attr "length" "8")])
+
+;; Storing a part of SImode to QImode.
+
+(define_insn ""
+  [(set (match_operand:QI 0 "general_operand_dst" "=rm<")
+       (subreg:QI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+                               (const_int 8)) 3))]
+  ""
+  "mov.b\\t%x1,%R0"
+  [(set_attr "cc" "set_znv")
+   (set_attr "length" "8")])
+
+(define_insn ""
+  [(set (match_operand:QI 0 "general_operand_dst" "=rm<")
+       (subreg:QI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+                               (const_int 16)) 3))
+   (clobber (match_scratch:SI 2 "=&r"))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "mov.w\\t%e1,%f2\;mov.b\\t%w2,%R0"
+  [(set_attr "cc" "set_znv")
+   (set_attr "length" "10")])
+
+(define_insn ""
+  [(set (match_operand:QI 0 "general_operand_dst" "=rm<")
+       (subreg:QI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+                               (const_int 24)) 3))
+   (clobber (match_scratch:SI 2 "=&r"))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "mov.w\\t%e1,%f2\;mov.b\\t%x2,%R0"
+  [(set_attr "cc" "set_znv")
+   (set_attr "length" "10")])
+
 (define_insn_and_split ""
   [(set (pc)
        (if_then_else (eq (zero_extract:SI (subreg:SI (match_operand:QI 0 "register_operand" "") 0)