}
})
\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