OSDN Git Service

* config/i386/i386.md (divmod<mode>4) Macroize expander from
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / i386.md
index 5c2564e..2780080 100644 (file)
     }
 })
 \f
-;; Remainder instructions.
-
-(define_expand "divmoddi4"
-  [(parallel [(set (match_operand:DI 0 "register_operand" "")
-                  (div:DI (match_operand:DI 1 "register_operand" "")
-                          (match_operand:DI 2 "nonimmediate_operand" "")))
-             (set (match_operand:DI 3 "register_operand" "")
-                  (mod:DI (match_dup 1) (match_dup 2)))
+;; Divmod instructions.
+
+(define_expand "divmod<mode>4"
+  [(parallel [(set (match_operand:SWI248 0 "register_operand" "")
+                  (div:SWI248
+                    (match_operand:SWI248 1 "register_operand" "")
+                    (match_operand:SWI248 2 "nonimmediate_operand" "")))
+             (set (match_operand:SWI248 3 "register_operand" "")
+                  (mod:SWI248 (match_dup 1) (match_dup 2)))
              (clobber (reg:CC FLAGS_REG))])]
-  "TARGET_64BIT"
+  "(<MODE>mode != HImode) || TARGET_HIMODE_MATH"
   "")
 
-;; Allow to come the parameter in eax or edx to avoid extra moves.
-;; Penalize eax case slightly because it results in worse scheduling
-;; of code.
-(define_insn "*divmoddi4_nocltd_rex64"
-  [(set (match_operand:DI 0 "register_operand" "=&a,?a")
-       (div:DI (match_operand:DI 2 "register_operand" "1,0")
-               (match_operand:DI 3 "nonimmediate_operand" "rm,rm")))
-   (set (match_operand:DI 1 "register_operand" "=&d,&d")
-       (mod:DI (match_dup 2) (match_dup 3)))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT && optimize_function_for_speed_p (cfun) && !TARGET_USE_CLTD"
-  "#"
-  [(set_attr "type" "multi")])
-
-(define_insn "*divmoddi4_cltd_rex64"
-  [(set (match_operand:DI 0 "register_operand" "=a")
-       (div:DI (match_operand:DI 2 "register_operand" "a")
-               (match_operand:DI 3 "nonimmediate_operand" "rm")))
-   (set (match_operand:DI 1 "register_operand" "=&d")
-       (mod:DI (match_dup 2) (match_dup 3)))
+(define_insn_and_split "*divmod<mode>4"
+  [(set (match_operand:SWI248 0 "register_operand" "=a")
+       (div:SWI248 (match_operand:SWI248 2 "register_operand" "0")
+                   (match_operand:SWI248 3 "nonimmediate_operand" "rm")))
+   (set (match_operand:SWI248 1 "register_operand" "=&d")
+       (mod:SWI248 (match_dup 2) (match_dup 3)))
    (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT && (optimize_function_for_size_p (cfun) || TARGET_USE_CLTD)"
+  "(<MODE>mode != HImode) || TARGET_HIMODE_MATH"
   "#"
-  [(set_attr "type" "multi")])
-
-(define_insn "*divmoddi_noext_rex64"
-  [(set (match_operand:DI 0 "register_operand" "=a")
-       (div:DI (match_operand:DI 1 "register_operand" "0")
-               (match_operand:DI 2 "nonimmediate_operand" "rm")))
-   (set (match_operand:DI 3 "register_operand" "=d")
-       (mod:DI (match_dup 1) (match_dup 2)))
-   (use (match_operand:DI 4 "register_operand" "3"))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT"
-  "idiv{q}\t%2"
-  [(set_attr "type" "idiv")
-   (set_attr "mode" "DI")])
-
-(define_split
-  [(set (match_operand:DI 0 "register_operand" "")
-       (div:DI (match_operand:DI 1 "register_operand" "")
-               (match_operand:DI 2 "nonimmediate_operand" "")))
-   (set (match_operand:DI 3 "register_operand" "")
-       (mod:DI (match_dup 1) (match_dup 2)))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT && reload_completed"
-  [(parallel [(set (match_dup 3)
-                  (ashiftrt:DI (match_dup 4) (const_int 63)))
+  "&& reload_completed"
+  [(parallel [(set (match_dup 1)
+                  (ashiftrt:SWI248 (match_dup 4) (match_dup 5)))
              (clobber (reg:CC FLAGS_REG))])
    (parallel [(set (match_dup 0)
-                  (div:DI (reg:DI 0) (match_dup 2)))
-             (set (match_dup 3)
-                  (mod:DI (reg:DI 0) (match_dup 2)))
-             (use (match_dup 3))
+                  (div:SWI248 (match_dup 2) (match_dup 3)))
+             (set (match_dup 1)
+                  (mod:SWI248 (match_dup 2) (match_dup 3)))
+             (use (match_dup 1))
              (clobber (reg:CC FLAGS_REG))])]
 {
-  /* Avoid use of cltd in favor of a mov+shift.  */
-  if (!TARGET_USE_CLTD && optimize_function_for_speed_p (cfun))
-    {
-      if (true_regnum (operands[1]))
-        emit_move_insn (operands[0], operands[1]);
-      else
-       emit_move_insn (operands[3], operands[1]);
-      operands[4] = operands[3];
-    }
-  else
-    {
-      gcc_assert (!true_regnum (operands[1]));
-      operands[4] = operands[1];
-    }
-})
+  operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - 1);
 
-
-(define_expand "divmodsi4"
-  [(parallel [(set (match_operand:SI 0 "register_operand" "")
-                  (div:SI (match_operand:SI 1 "register_operand" "")
-                          (match_operand:SI 2 "nonimmediate_operand" "")))
-             (set (match_operand:SI 3 "register_operand" "")
-                  (mod:SI (match_dup 1) (match_dup 2)))
-             (clobber (reg:CC FLAGS_REG))])]
-  ""
-  "")
-
-;; Allow to come the parameter in eax or edx to avoid extra moves.
-;; Penalize eax case slightly because it results in worse scheduling
-;; of code.
-(define_insn "*divmodsi4_nocltd"
-  [(set (match_operand:SI 0 "register_operand" "=&a,?a")
-       (div:SI (match_operand:SI 2 "register_operand" "1,0")
-               (match_operand:SI 3 "nonimmediate_operand" "rm,rm")))
-   (set (match_operand:SI 1 "register_operand" "=&d,&d")
-       (mod:SI (match_dup 2) (match_dup 3)))
-   (clobber (reg:CC FLAGS_REG))]
-  "optimize_function_for_speed_p (cfun) && !TARGET_USE_CLTD"
-  "#"
-  [(set_attr "type" "multi")])
-
-(define_insn "*divmodsi4_cltd"
-  [(set (match_operand:SI 0 "register_operand" "=a")
-       (div:SI (match_operand:SI 2 "register_operand" "a")
-               (match_operand:SI 3 "nonimmediate_operand" "rm")))
-   (set (match_operand:SI 1 "register_operand" "=&d")
-       (mod:SI (match_dup 2) (match_dup 3)))
-   (clobber (reg:CC FLAGS_REG))]
-  "optimize_function_for_size_p (cfun) || TARGET_USE_CLTD"
-  "#"
-  [(set_attr "type" "multi")])
-
-(define_insn "*divmodsi_noext"
-  [(set (match_operand:SI 0 "register_operand" "=a")
-       (div:SI (match_operand:SI 1 "register_operand" "0")
-               (match_operand:SI 2 "nonimmediate_operand" "rm")))
-   (set (match_operand:SI 3 "register_operand" "=d")
-       (mod:SI (match_dup 1) (match_dup 2)))
-   (use (match_operand:SI 4 "register_operand" "3"))
-   (clobber (reg:CC FLAGS_REG))]
-  ""
-  "idiv{l}\t%2"
-  [(set_attr "type" "idiv")
-   (set_attr "mode" "SI")])
-
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (div:SI (match_operand:SI 1 "register_operand" "")
-               (match_operand:SI 2 "nonimmediate_operand" "")))
-   (set (match_operand:SI 3 "register_operand" "")
-       (mod:SI (match_dup 1) (match_dup 2)))
-   (clobber (reg:CC FLAGS_REG))]
-  "reload_completed"
-  [(parallel [(set (match_dup 3)
-                  (ashiftrt:SI (match_dup 4) (const_int 31)))
-             (clobber (reg:CC FLAGS_REG))])
-   (parallel [(set (match_dup 0)
-                  (div:SI (reg:SI 0) (match_dup 2)))
-             (set (match_dup 3)
-                  (mod:SI (reg:SI 0) (match_dup 2)))
-             (use (match_dup 3))
-             (clobber (reg:CC FLAGS_REG))])]
-{
-  /* Avoid use of cltd in favor of a mov+shift.  */
-  if (!TARGET_USE_CLTD && optimize_function_for_speed_p (cfun))
-    {
-      if (true_regnum (operands[1]))
-        emit_move_insn (operands[0], operands[1]);
-      else
-       emit_move_insn (operands[3], operands[1]);
-      operands[4] = operands[3];
-    }
+  if (<MODE>mode != HImode
+      && (optimize_function_for_size_p (cfun) || TARGET_USE_CLTD))
+    operands[4] = operands[2];
   else
     {
-      gcc_assert (!true_regnum (operands[1]));
+      /* Avoid use of cltd in favor of a mov+shift.  */
+      emit_move_insn (operands[1], operands[2]);
       operands[4] = operands[1];
     }
-})
-;; %%% Split me.
-(define_insn "divmodhi4"
-  [(set (match_operand:HI 0 "register_operand" "=a")
-       (div:HI (match_operand:HI 1 "register_operand" "0")
-               (match_operand:HI 2 "nonimmediate_operand" "rm")))
-   (set (match_operand:HI 3 "register_operand" "=&d")
-       (mod:HI (match_dup 1) (match_dup 2)))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_HIMODE_MATH"
-  "cwtd\;idiv{w}\t%2"
-  [(set_attr "type" "multi")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "SI")])
-
-(define_insn "udivmoddi4"
-  [(set (match_operand:DI 0 "register_operand" "=a")
-       (udiv:DI (match_operand:DI 1 "register_operand" "0")
-                (match_operand:DI 2 "nonimmediate_operand" "rm")))
-   (set (match_operand:DI 3 "register_operand" "=&d")
-       (umod:DI (match_dup 1) (match_dup 2)))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT"
-  "xor{q}\t%3, %3\;div{q}\t%2"
+}
   [(set_attr "type" "multi")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "DI")])
+   (set_attr "mode" "<MODE>")])
 
-(define_insn "*udivmoddi4_noext"
-  [(set (match_operand:DI 0 "register_operand" "=a")
-       (udiv:DI (match_operand:DI 1 "register_operand" "0")
-                (match_operand:DI 2 "nonimmediate_operand" "rm")))
-   (set (match_operand:DI 3 "register_operand" "=d")
-       (umod:DI (match_dup 1) (match_dup 2)))
-   (use (match_dup 3))
+(define_insn "*divmod<mode>4_noext"
+  [(set (match_operand:SWI248 0 "register_operand" "=a")
+       (div:SWI248 (match_operand:SWI248 2 "register_operand" "0")
+                   (match_operand:SWI248 3 "nonimmediate_operand" "rm")))
+   (set (match_operand:SWI248 1 "register_operand" "=d")
+       (mod:SWI248 (match_dup 2) (match_dup 3)))
+   (use (match_operand:SWI248 4 "register_operand" "1"))
    (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT"
-  "div{q}\t%2"
+  ""
+  "idiv{<imodesuffix>}\t%3"
   [(set_attr "type" "idiv")
-   (set_attr "mode" "DI")])
+   (set_attr "mode" "<MODE>")])
 
-(define_split
-  [(set (match_operand:DI 0 "register_operand" "")
-       (udiv:DI (match_operand:DI 1 "register_operand" "")
-                (match_operand:DI 2 "nonimmediate_operand" "")))
-   (set (match_operand:DI 3 "register_operand" "")
-       (umod:DI (match_dup 1) (match_dup 2)))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT && reload_completed"
-  [(set (match_dup 3) (const_int 0))
-   (parallel [(set (match_dup 0)
-                  (udiv:DI (match_dup 1) (match_dup 2)))
-             (set (match_dup 3)
-                  (umod:DI (match_dup 1) (match_dup 2)))
-             (use (match_dup 3))
+(define_expand "udivmod<mode>4"
+  [(parallel [(set (match_operand:SWI248 0 "register_operand" "")
+                  (udiv:SWI248
+                    (match_operand:SWI248 1 "register_operand" "")
+                    (match_operand:SWI248 2 "nonimmediate_operand" "")))
+             (set (match_operand:SWI248 3 "register_operand" "")
+                  (umod:SWI248 (match_dup 1) (match_dup 2)))
              (clobber (reg:CC FLAGS_REG))])]
+  "(<MODE>mode != HImode) || TARGET_HIMODE_MATH"
   "")
 
-(define_insn "udivmodsi4"
-  [(set (match_operand:SI 0 "register_operand" "=a")
-       (udiv:SI (match_operand:SI 1 "register_operand" "0")
-                (match_operand:SI 2 "nonimmediate_operand" "rm")))
-   (set (match_operand:SI 3 "register_operand" "=&d")
-       (umod:SI (match_dup 1) (match_dup 2)))
+(define_insn_and_split "*udivmod<mode>4"
+  [(set (match_operand:SWI248 0 "register_operand" "=a")
+       (udiv:SWI248 (match_operand:SWI248 2 "register_operand" "0")
+                    (match_operand:SWI248 3 "nonimmediate_operand" "rm")))
+   (set (match_operand:SWI248 1 "register_operand" "=&d")
+       (umod:SWI248 (match_dup 2) (match_dup 3)))
    (clobber (reg:CC FLAGS_REG))]
-  ""
-  "xor{l}\t%3, %3\;div{l}\t%2"
-  [(set_attr "type" "multi")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "SI")])
-
-(define_insn "*udivmodsi4_noext"
-  [(set (match_operand:SI 0 "register_operand" "=a")
-       (udiv:SI (match_operand:SI 1 "register_operand" "0")
-                (match_operand:SI 2 "nonimmediate_operand" "rm")))
-   (set (match_operand:SI 3 "register_operand" "=d")
-       (umod:SI (match_dup 1) (match_dup 2)))
-   (use (match_dup 3))
-   (clobber (reg:CC FLAGS_REG))]
-  ""
-  "div{l}\t%2"
-  [(set_attr "type" "idiv")
-   (set_attr "mode" "SI")])
-
-(define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (udiv:SI (match_operand:SI 1 "register_operand" "")
-                (match_operand:SI 2 "nonimmediate_operand" "")))
-   (set (match_operand:SI 3 "register_operand" "")
-       (umod:SI (match_dup 1) (match_dup 2)))
-   (clobber (reg:CC FLAGS_REG))]
-  "reload_completed"
-  [(set (match_dup 3) (const_int 0))
+  "(<MODE>mode != HImode) || TARGET_HIMODE_MATH"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 1) (const_int 0))
    (parallel [(set (match_dup 0)
-                  (udiv:SI (match_dup 1) (match_dup 2)))
-             (set (match_dup 3)
-                  (umod:SI (match_dup 1) (match_dup 2)))
-             (use (match_dup 3))
-             (clobber (reg:CC FLAGS_REG))])]
-  "")
-
-(define_expand "udivmodhi4"
-  [(set (match_dup 4) (const_int 0))
-   (parallel [(set (match_operand:HI 0 "register_operand" "")
-                  (udiv:HI (match_operand:HI 1 "register_operand" "")
-                           (match_operand:HI 2 "nonimmediate_operand" "")))
-             (set (match_operand:HI 3 "register_operand" "")
-                  (umod:HI (match_dup 1) (match_dup 2)))
-             (use (match_dup 4))
+                  (udiv:SWI248 (match_dup 2) (match_dup 3)))
+             (set (match_dup 1)
+                  (umod:SWI248 (match_dup 2) (match_dup 3)))
+             (use (match_dup 1))
              (clobber (reg:CC FLAGS_REG))])]
-  "TARGET_HIMODE_MATH"
-  "operands[4] = gen_reg_rtx (HImode);")
+  ""
+  [(set_attr "type" "multi")
+   (set_attr "mode" "<MODE>")])
 
-(define_insn "*udivmodhi_noext"
-  [(set (match_operand:HI 0 "register_operand" "=a")
-       (udiv:HI (match_operand:HI 1 "register_operand" "0")
-                (match_operand:HI 2 "nonimmediate_operand" "rm")))
-   (set (match_operand:HI 3 "register_operand" "=d")
-       (umod:HI (match_dup 1) (match_dup 2)))
-   (use (match_operand:HI 4 "register_operand" "3"))
+(define_insn "*udivmod<mode>4_noext"
+  [(set (match_operand:SWI248 0 "register_operand" "=a")
+       (udiv:SWI248 (match_operand:SWI248 2 "register_operand" "0")
+                    (match_operand:SWI248 3 "nonimmediate_operand" "rm")))
+   (set (match_operand:SWI248 1 "register_operand" "=d")
+       (umod:SWI248 (match_dup 2) (match_dup 3)))
+   (use (match_operand:SWI248 4 "register_operand" "1"))
    (clobber (reg:CC FLAGS_REG))]
-  ""
-  "div{w}\t%2"
+  "(<MODE>mode != HImode) || TARGET_HIMODE_MATH"
+  "div{<imodesuffix>}\t%3"
   [(set_attr "type" "idiv")
-   (set_attr "mode" "HI")])
+   (set_attr "mode" "<MODE>")])
 
 ;; We cannot use div/idiv for double division, because it causes
 ;; "division by zero" on the overflow and that's not what we expect