aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMichael Meissner <meissner@gcc.gnu.org>1994-09-26 10:44:49 +0000
committerMichael Meissner <meissner@gcc.gnu.org>1994-09-26 10:44:49 +0000
commit96f218bb2aa467606a31c67b3f64c0ac04457f25 (patch)
tree6d15d6b09c65eb9db9ca892939a52b048242cd94 /gcc
parent68c1e17399798b38c22e7f20bfc4b7a5612e5f09 (diff)
downloadgcc-96f218bb2aa467606a31c67b3f64c0ac04457f25.zip
gcc-96f218bb2aa467606a31c67b3f64c0ac04457f25.tar.gz
gcc-96f218bb2aa467606a31c67b3f64c0ac04457f25.tar.bz2
Allow memory/memory DImode add/subtract.
From-SVN: r8128
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/i386/i386.md107
1 files changed, 97 insertions, 10 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 0c1c31c..131ab7c 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -2345,25 +2345,69 @@
;;- add instructions
(define_insn "adddi3"
- [(set (match_operand:DI 0 "general_operand" "=&r,ro")
- (plus:DI (match_operand:DI 1 "general_operand" "%0,0")
- (match_operand:DI 2 "general_operand" "o,riF")))]
+ [(set (match_operand:DI 0 "general_operand" "=&r,ro,o,&r,o,o,o")
+ (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,or,riF,riF,o")
+ (match_operand:DI 2 "general_operand" "o,riF,o,oriF,riF,o,o")))
+ (clobber (match_scratch:SI 3 "=X,X,&r,X,X,&r,&r"))]
""
"*
{
- rtx low[3], high[3];
+ rtx low[3], high[3], xops[7];
CC_STATUS_INIT;
split_di (operands, 3, low, high);
- if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
+ if (!rtx_equal_p (operands[0], operands[1]))
+ {
+ xops[0] = high[0];
+ xops[1] = low[0];
+ xops[2] = high[1];
+ xops[3] = low[1];
+
+ if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
+ {
+ output_asm_insn (AS2 (mov%L1,%3,%1), xops);
+ output_asm_insn (AS2 (mov%L0,%2,%0), xops);
+ }
+ else
+ {
+ xops[4] = high[2];
+ xops[5] = low[2];
+ xops[6] = operands[3];
+ output_asm_insn (AS2 (mov%L6,%3,%6), xops);
+ output_asm_insn (AS2 (add%L6,%5,%6), xops);
+ output_asm_insn (AS2 (mov%L1,%6,%1), xops);
+ output_asm_insn (AS2 (mov%L6,%2,%6), xops);
+ output_asm_insn (AS2 (adc%L6,%4,%6), xops);
+ output_asm_insn (AS2 (mov%L0,%6,%0), xops);
+ RET;
+ }
+ }
+
+ if (GET_CODE (operands[3]) == REG)
+ {
+ xops[0] = high[0];
+ xops[1] = low[0];
+ xops[2] = high[2];
+ xops[3] = low[2];
+ xops[4] = operands[3];
+
+ output_asm_insn (AS2 (mov%L4,%3,%4), xops);
+ output_asm_insn (AS2 (add%L1,%4,%1), xops);
+ output_asm_insn (AS2 (mov%L4,%2,%4), xops);
+ output_asm_insn (AS2 (adc%L0,%4,%0), xops);
+ }
+
+ else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
{
output_asm_insn (AS2 (add%L0,%2,%0), low);
output_asm_insn (AS2 (adc%L0,%2,%0), high);
}
+
else
output_asm_insn (AS2 (add%L0,%2,%0), high);
+
RET;
}")
@@ -2546,23 +2590,66 @@
;;- subtract instructions
(define_insn "subdi3"
- [(set (match_operand:DI 0 "general_operand" "=&r,ro")
- (minus:DI (match_operand:DI 1 "general_operand" "0,0")
- (match_operand:DI 2 "general_operand" "o,riF")))]
+ [(set (match_operand:DI 0 "general_operand" "=&r,ro,&r,o,o")
+ (minus:DI (match_operand:DI 1 "general_operand" "0,0,roiF,riF,o")
+ (match_operand:DI 2 "general_operand" "o,riF,roiF,riF,o")))
+ (clobber (match_scratch:SI 3 "=X,X,X,X,&r"))]
""
"*
{
- rtx low[3], high[3];
+ rtx low[3], high[3], xops[7];
CC_STATUS_INIT;
split_di (operands, 3, low, high);
- if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
+ if (!rtx_equal_p (operands[0], operands[1]))
+ {
+ xops[0] = high[0];
+ xops[1] = low[0];
+ xops[2] = high[1];
+ xops[3] = low[1];
+
+ if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
+ {
+ output_asm_insn (AS2 (mov%L1,%3,%1), xops);
+ output_asm_insn (AS2 (mov%L0,%2,%0), xops);
+ }
+ else
+ {
+ xops[4] = high[2];
+ xops[5] = low[2];
+ xops[6] = operands[3];
+ output_asm_insn (AS2 (mov%L6,%3,%6), xops);
+ output_asm_insn (AS2 (sub%L6,%5,%6), xops);
+ output_asm_insn (AS2 (mov%L1,%6,%1), xops);
+ output_asm_insn (AS2 (mov%L6,%2,%6), xops);
+ output_asm_insn (AS2 (sbb%L6,%4,%6), xops);
+ output_asm_insn (AS2 (mov%L0,%6,%0), xops);
+ RET;
+ }
+ }
+
+ if (GET_CODE (operands[3]) == REG)
+ {
+ xops[0] = high[0];
+ xops[1] = low[0];
+ xops[2] = high[2];
+ xops[3] = low[2];
+ xops[4] = operands[3];
+
+ output_asm_insn (AS2 (mov%L4,%3,%4), xops);
+ output_asm_insn (AS2 (sub%L1,%4,%1), xops);
+ output_asm_insn (AS2 (mov%L4,%2,%4), xops);
+ output_asm_insn (AS2 (sbb%L0,%4,%0), xops);
+ }
+
+ else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
{
output_asm_insn (AS2 (sub%L0,%2,%0), low);
output_asm_insn (AS2 (sbb%L0,%2,%0), high);
}
+
else
output_asm_insn (AS2 (sub%L0,%2,%0), high);