aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1994-03-18 17:52:27 -0500
committerRichard Kenner <kenner@gcc.gnu.org>1994-03-18 17:52:27 -0500
commit8ffd9c51e4d97ff8a7fb9a282a7cb535c51d82f1 (patch)
treee73cf78162052f81712e94c36928d87d5aa91e25 /gcc/config
parent1052937bbaaa01efe5a9ecaa574ee084812cb173 (diff)
downloadgcc-8ffd9c51e4d97ff8a7fb9a282a7cb535c51d82f1.zip
gcc-8ffd9c51e4d97ff8a7fb9a282a7cb535c51d82f1.tar.gz
gcc-8ffd9c51e4d97ff8a7fb9a282a7cb535c51d82f1.tar.bz2
(divmodsi4, udivsi3, divsi3, udivmodsi4): Add AIX common-mode cases.
(mulh_call, mull_call, divss_call, divus_call, quoss_call, quous_call): AIX common-mode call patterns. (ashlsi3): More TARGET_POWERPC to ! TARGET_POWER changes. (addsf3, subsf3, mulsf3, divsf3, etc.): Change TARGET_POWER to ! TARGET_POWERPC. (fix_truncdfsi2): Use POWER/2 and PowerPC FP convert instruction. (fpcvtsi): New pattern. (mulsidi3): Add AIX common-mode case, add imul attribute to POWER pattern, add PowerPC pattern, flag input operands as commutative. (smulsi3_highpart): Add AIX common-mode case. (movsi matcher): Add mtjmpr attribute to ! TARGET_POWER case. (movsf): Clean up load from memory or integer register test. (movdi matcher): Add FP register support. (smulsi3_highpart): New patterns. (umulsi3_highpart_power): New pattern. From-SVN: r6816
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/rs6000/rs6000.md292
1 files changed, 260 insertions, 32 deletions
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index aa55d33..316c7be 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -715,7 +715,26 @@
;; 0 and remainder to operand 3.
;; ??? At some point, see what, if anything, we can do about if (x % y == 0).
-(define_insn "divmodsi4"
+(define_expand "divmodsi4"
+ [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
+ (div:SI (match_operand:SI 1 "gpc_reg_operand" "")
+ (match_operand:SI 2 "gpc_reg_operand" "")))
+ (set (match_operand:SI 3 "gpc_reg_operand" "")
+ (mod:SI (match_dup 1) (match_dup 2)))])]
+ "TARGET_POWER || (! TARGET_POWER && ! TARGET_POWERPC)"
+ "
+{
+ if (! TARGET_POWER && ! TARGET_POWERPC)
+ {
+ emit_move_insn (gen_rtx (REG, SImode, 3), operands[1]);
+ emit_move_insn (gen_rtx (REG, SImode, 4), operands[2]);
+ emit_insn (gen_divss_call ());
+ emit_move_insn (operands[0], gen_rtx (REG, SImode, 3));
+ emit_move_insn (operands[3], gen_rtx (REG, SImode, 4));
+ DONE;
+ }
+}")
+(define_insn ""
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(div:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "gpc_reg_operand" "r")))
@@ -733,7 +752,23 @@
"divw %0, %1, %2"
[(set_attr "type" "idiv")])
-(define_insn "udivsi3"
+(define_expand "udivsi3"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "")
+ (udiv:SI (match_operand:SI 1 "gpc_reg_operand" "")
+ (match_operand:SI 2 "gpc_reg_operand" "")))]
+ "TARGET_POWERPC || (! TARGET_POWER && ! TARGET_POWERPC)"
+ "
+{
+ if (! TARGET_POWER && ! TARGET_POWERPC)
+ {
+ emit_move_insn (gen_rtx (REG, SImode, 3), operands[1]);
+ emit_move_insn (gen_rtx (REG, SImode, 4), operands[2]);
+ emit_insn (gen_quous_call ());
+ emit_move_insn (operands[0], gen_rtx (REG, SImode, 3));
+ DONE;
+ }
+}")
+(define_insn ""
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(udiv:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "gpc_reg_operand" "r")))]
@@ -743,7 +778,8 @@
;; For powers of two we can do srai/aze for divide and then adjust for
;; modulus. If it isn't a power of two, FAIL on POWER so divmodsi4 will be
-;; used; for PowerPC, force operands into register and do a normal divide.
+;; used; for PowerPC, force operands into register and do a normal divide;
+;; for AIX common-mode, use quoss call on register operands.
(define_expand "divsi3"
[(set (match_operand:SI 0 "gpc_reg_operand" "")
(div:SI (match_operand:SI 1 "gpc_reg_operand" "")
@@ -754,10 +790,18 @@
if (GET_CODE (operands[2]) == CONST_INT
&& exact_log2 (INTVAL (operands[2])) >= 0)
;
- else if (! TARGET_POWERPC)
+ else if (TARGET_POWER && ! TARGET_POWERPC)
FAIL;
else
operands[2] = force_reg (SImode, operands[2]);
+ if (! TARGET_POWER && ! TARGET_POWERPC)
+ {
+ emit_move_insn (gen_rtx (REG, SImode, 3), operands[1]);
+ emit_move_insn (gen_rtx (REG, SImode, 4), operands[2]);
+ emit_insn (gen_quoss_call ());
+ emit_move_insn (operands[0], gen_rtx (REG, SImode, 3));
+ DONE;
+ }
}")
(define_expand "modsi3"
@@ -781,7 +825,6 @@
emit_insn (gen_ashlsi3 (temp2, temp1, GEN_INT (i)));
emit_insn (gen_subsi3 (operands[0], operands[1], temp2));
DONE;
-
}")
(define_insn ""
@@ -877,11 +920,23 @@
(match_operand:SI 2 "reg_or_cint_operand" "")))
(set (match_operand:SI 3 "gpc_reg_operand" "")
(umod:SI (match_dup 1) (match_dup 2)))])]
- "TARGET_POWER"
+ ""
"
{
rtx label = 0;
+ if (! TARGET_POWER)
+ if (! TARGET_POWERPC)
+ {
+ emit_move_insn (gen_rtx (REG, SImode, 3), operands[1]);
+ emit_move_insn (gen_rtx (REG, SImode, 4), operands[2]);
+ emit_insn (gen_divus_call ());
+ emit_move_insn (operands[0], gen_rtx (REG, SImode, 3));
+ emit_move_insn (operands[3], gen_rtx (REG, SImode, 4));
+ DONE;
+ }
+ else
+ FAIL;
if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) < 0)
{
operands[2] = force_reg (SImode, operands[2]);
@@ -899,7 +954,60 @@
DONE;
}")
-
+;; AIX architecture-independent common-mode multiply (DImode),
+;; divide/modulus, and quotient subroutine calls. Input operands in R3 and
+;; R4; results in R3 and somtimes R4; link register always clobbered by bla
+;; instruction; R0 sometimes clobbered; also, MQ sometimes clobbered but
+;; assumed unused if generating common-mode, so ignore.
+(define_insn "mulh_call"
+ [(set (reg:SI 3)
+ (truncate:SI
+ (lshiftrt:DI (mult:DI (sign_extend:DI (reg:SI 3))
+ (sign_extend:DI (reg:SI 4)))
+ (const_int 32))))
+ (clobber (match_scratch:SI 0 "=l"))]
+ "! TARGET_POWER && ! TARGET_POWERPC"
+ "bla __mulh")
+(define_insn "mull_call"
+ [(set (reg:DI 3)
+ (mult:DI (sign_extend:DI (reg:SI 3))
+ (sign_extend:DI (reg:SI 4))))
+ (clobber (match_scratch:SI 0 "=l"))
+ (clobber (reg:SI 0))]
+ "! TARGET_POWER && ! TARGET_POWERPC"
+ "bla __mull")
+(define_insn "divss_call"
+ [(set (reg:SI 3)
+ (div:SI (reg:SI 3) (reg:SI 4)))
+ (set (reg:SI 4)
+ (mod:SI (reg:SI 3) (reg:SI 4)))
+ (clobber (match_scratch:SI 0 "=l"))
+ (clobber (reg:SI 0))]
+ "! TARGET_POWER && ! TARGET_POWERPC"
+ "bla __divss")
+(define_insn "divus_call"
+ [(set (reg:SI 3)
+ (udiv:SI (reg:SI 3) (reg:SI 4)))
+ (set (reg:SI 4)
+ (umod:SI (reg:SI 3) (reg:SI 4)))
+ (clobber (match_scratch:SI 0 "=l"))
+ (clobber (reg:SI 0))]
+ "! TARGET_POWER && ! TARGET_POWERPC"
+ "bla __divus")
+(define_insn "quoss_call"
+ [(set (reg:SI 3)
+ (div:SI (reg:SI 3) (reg:SI 4)))
+ (clobber (match_scratch:SI 0 "=l"))]
+ "! TARGET_POWER && ! TARGET_POWERPC"
+ "bla __quoss")
+(define_insn "quous_call"
+ [(set (reg:SI 3)
+ (udiv:SI (reg:SI 3) (reg:SI 4)))
+ (clobber (match_scratch:SI 0 "=l"))
+ (clobber (reg:SI 0))]
+ "! TARGET_POWER && ! TARGET_POWERPC"
+ "bla __quous")
+
(define_insn "andsi3"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
(and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
@@ -1603,7 +1711,7 @@
(match_operand:SI 2 "reg_or_cint_operand" "ri"))
(const_int 0)))
(clobber (match_scratch:SI 3 "=r"))]
- "TARGET_POWERPC"
+ "! TARGET_POWER"
"slw%I2. %3,%1,%2"
[(set_attr "type" "delayed_compare")])
@@ -1628,7 +1736,7 @@
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(ashift:SI (match_dup 1) (match_dup 2)))]
- "TARGET_POWERPC"
+ "! TARGET_POWER"
"slw%I2. %0,%1,%2"
[(set_attr "type" "delayed_compare")])
@@ -2114,7 +2222,7 @@
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(plus:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_POWER"
+ "! TARGET_POWERPC"
"{fa|fadd} %0,%1,%2"
[(set_attr "type" "fp")])
@@ -2137,7 +2245,7 @@
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(minus:SF (match_operand:SF 1 "gpc_reg_operand" "f")
(match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_POWER"
+ "! TARGET_POWERPC"
"{fs|fsub} %0,%1,%2"
[(set_attr "type" "fp")])
@@ -2160,7 +2268,7 @@
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_POWER"
+ "! TARGET_POWERPC"
"{fm|fmul} %0,%1,%2"
[(set_attr "type" "fp")])
@@ -2183,7 +2291,7 @@
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(div:SF (match_operand:SF 1 "gpc_reg_operand" "f")
(match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_POWER"
+ "! TARGET_POWERPC"
"{fd|fdiv} %0,%1,%2"
[(set_attr "type" "sdiv")])
@@ -2201,7 +2309,7 @@
(plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f")))]
- "TARGET_POWER"
+ "! TARGET_POWERPC"
"{fma|fmadd} %0,%1,%2,%3"
[(set_attr "type" "fp")])
@@ -2219,7 +2327,7 @@
(minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f")))]
- "TARGET_POWER"
+ "! TARGET_POWERPC"
"{fms|fmsub} %0,%1,%2,%3"
[(set_attr "type" "fp")])
@@ -2237,7 +2345,7 @@
(neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f"))))]
- "TARGET_POWER"
+ "! TARGET_POWERPC"
"{fnma|fnmadd} %0,%1,%2,%3"
[(set_attr "type" "fp")])
@@ -2255,7 +2363,7 @@
(neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f"))))]
- "TARGET_POWER"
+ "! TARGET_POWERPC"
"{fnms|fnmsub} %0,%1,%2,%3"
[(set_attr "type" "fp")])
@@ -2638,15 +2746,36 @@
""
"
{
- emit_insn (gen_trunc_call (operands[0], operands[1],
- gen_rtx (SYMBOL_REF, Pmode, RS6000_ITRUNC)));
- DONE;
+ if (TARGET_POWER2 || TARGET_POWERPC)
+ {
+ rtx stack_slot, temp = gen_reg_rtx (DImode);
+ emit_insn (gen_fpcvtsi (temp, operands[1]));
+ stack_slot = gen_rtx (MEM, DImode,
+ plus_constant (stack_pointer_rtx, 8));
+ emit_move_insn (stack_slot, temp);
+ emit_move_insn (operands[0],
+ operand_subword (stack_slot, 1, 0, DImode));
+ DONE;
+ }
+ else
+ {
+ emit_insn (gen_trunc_call (operands[0], operands[1],
+ gen_rtx (SYMBOL_REF, Pmode, RS6000_ITRUNC)));
+ DONE;
+ }
}")
+(define_insn "fpcvtsi"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=f")
+ (sign_extend:DI
+ (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))))]
+ "TARGET_POWER2 || TARGET_POWERPC"
+ "{fcirz|fctiwz} %0,%1"
+ [(set_attr "type" "fp")])
(define_expand "fixuns_truncdfsi2"
[(set (match_operand:SI 0 "gpc_reg_operand" "")
(unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))]
- ""
+ "! TARGET_POWER2 && ! TARGET_POWERPC"
"
{
emit_insn (gen_trunc_call (operands[0], operands[1],
@@ -2763,14 +2892,106 @@
"{sfi|subfic} %L0,%L1,0\;{sfze|subfze} %0,%1"
[(set_attr "length" "8")])
-(define_insn "mulsidi3"
+(define_expand "mulsidi3"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" ""))
+ (sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" ""))))]
+ ""
+ "
+{
+ if (! TARGET_POWER && ! TARGET_POWERPC)
+ {
+ emit_move_insn (gen_rtx (REG, SImode, 3), operands[1]);
+ emit_move_insn (gen_rtx (REG, SImode, 4), operands[2]);
+ emit_insn (gen_mull_call ());
+ emit_move_insn (operand_subword (operands[0], 0, 0, DImode),
+ gen_rtx (REG, SImode, 3));
+ emit_move_insn (operand_subword (operands[0], 1, 0, DImode),
+ gen_rtx (REG, SImode, 4));
+ DONE;
+ }
+ else if (TARGET_POWER)
+ {
+ emit_insn (gen_mulsidi3_mq (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+}")
+(define_insn "mulsidi3_mq"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r"))
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "%r"))
(sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r"))))
(clobber (match_scratch:SI 3 "=q"))]
"TARGET_POWER"
"mul %0,%1,%2\;mfmq %L0"
- [(set_attr "length" "8")])
+ [(set_attr "type" "imul")
+ (set_attr "length" "8")])
+(define_insn ""
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "%r"))
+ (sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r"))))]
+ "TARGET_POWERPC"
+ "mulhw %0,%1,%2\;mullw %L0,%1,%2"
+ [(set_attr "type" "imul")
+ (set_attr "length" "8")])
+(define_expand "smulsi3_highpart"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "")
+ (truncate:SI
+ (lshiftrt:DI (mult:DI (sign_extend:DI
+ (match_operand:SI 1 "gpc_reg_operand" "%r"))
+ (sign_extend:DI
+ (match_operand:SI 2 "gpc_reg_operand" "r")))
+ (const_int 32))))]
+ ""
+ "
+{
+ if (! TARGET_POWER && ! TARGET_POWERPC)
+ {
+ emit_move_insn (gen_rtx (REG, SImode, 3), operands[1]);
+ emit_move_insn (gen_rtx (REG, SImode, 4), operands[2]);
+ emit_insn (gen_mulh_call ());
+ emit_move_insn (operands[0], gen_rtx (REG, SImode, 3));
+ DONE;
+ }
+ else if (TARGET_POWER)
+ {
+ emit_insn (gen_smulsi3_highpart_mq (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+}")
+(define_insn "smulsi3_highpart_mq"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (truncate:SI
+ (lshiftrt:DI (mult:DI (sign_extend:DI
+ (match_operand:SI 1 "gpc_reg_operand" "%r"))
+ (sign_extend:DI
+ (match_operand:SI 2 "gpc_reg_operand" "r")))
+ (const_int 32))))
+ (clobber (match_scratch:SI 3 "=q"))]
+ "TARGET_POWER"
+ "mul %0,%1,%2"
+ [(set_attr "type" "imul")])
+(define_insn ""
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (truncate:SI
+ (lshiftrt:DI (mult:DI (sign_extend:DI
+ (match_operand:SI 1 "gpc_reg_operand" "%r"))
+ (sign_extend:DI
+ (match_operand:SI 2 "gpc_reg_operand" "r")))
+ (const_int 32))))]
+ "TARGET_POWERPC"
+ "mulhw %0,%1,%2"
+ [(set_attr "type" "imul")])
+(define_insn "umulsi3_highpart"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (truncate:SI
+ (lshiftrt:DI (mult:DI (zero_extend:DI
+ (match_operand:SI 1 "gpc_reg_operand" "%r"))
+ (zero_extend:DI
+ (match_operand:SI 2 "gpc_reg_operand" "r")))
+ (const_int 32))))]
+ "TARGET_POWERPC"
+ "mulhwu %0,%1,%2"
+ [(set_attr "type" "imul")])
;; If operands 0 and 2 are in the same register, we have a problem. But
;; operands 0 and 1 (the usual case) can be in the same register. That's
@@ -2914,7 +3135,7 @@
lis %0,%u1
mf%1 %0
mt%0 %1"
- [(set_attr "type" "*,load,*,*,*,*,*")])
+ [(set_attr "type" "*,load,*,*,*,*,mtjmpr")])
;; Split a load of a large constant into the appropriate two-insn
;; sequence.
@@ -3125,9 +3346,10 @@
#if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT && ! defined(REAL_IS_NOT_DOUBLE)
|| GET_CODE (operands[1]) == CONST_DOUBLE
#endif
- || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 32)
- || (reload_in_progress && GET_CODE (operands[1]) == REG
- && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER))
+ || (GET_CODE (operands[1]) == REG
+ && (REGNO (operands[1]) < 32
+ || (reload_in_progress
+ && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER))))
{
emit_move_insn (operand_subword (operands[0], 0, 0, SFmode),
operand_subword (operands[1], 0, 0, SFmode));
@@ -3286,8 +3508,8 @@
}")
(define_insn ""
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m")
- (match_operand:DI 1 "input_operand" "r,m,r"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,f,f,m")
+ (match_operand:DI 1 "input_operand" "r,m,r,f,m,f"))]
"gpc_reg_operand (operands[0], DImode)
|| gpc_reg_operand (operands[1], DImode)"
"*
@@ -3314,10 +3536,16 @@
return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
case 2:
return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
+ case 3:
+ return \"fmr %0,%1\";
+ case 4:
+ return \"lfd%U1%X1 %0,%1\";
+ case 5:
+ return \"stfd%U0%X0 %1,%0\";
}
}"
- [(set_attr "type" "*,load,*")
- (set_attr "length" "8")])
+ [(set_attr "type" "*,load,*,fp,fpload,*")
+ (set_attr "length" "8,8,8,*,*,*")])
;; TImode is similar, except that we usually want to compute the address into
;; a register and use lsi/stsi (the exception is during reload). MQ is also