diff options
author | Michael Meissner <meissner@gcc.gnu.org> | 1994-09-26 10:44:49 +0000 |
---|---|---|
committer | Michael Meissner <meissner@gcc.gnu.org> | 1994-09-26 10:44:49 +0000 |
commit | 96f218bb2aa467606a31c67b3f64c0ac04457f25 (patch) | |
tree | 6d15d6b09c65eb9db9ca892939a52b048242cd94 /gcc | |
parent | 68c1e17399798b38c22e7f20bfc4b7a5612e5f09 (diff) | |
download | gcc-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.md | 107 |
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); |