diff options
Diffstat (limited to 'gcc/config/rs6000/rs6000.md')
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 72 |
1 files changed, 59 insertions, 13 deletions
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index e833863..4286d89 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -6307,8 +6307,8 @@ ;; The "??" is a kludge until we can figure out a more reasonable way ;; of handling these non-offsettable values. (define_insn "*movdf_hardfloat32" - [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,o,!r,!r,!r,f,f,m") - (match_operand:DF 1 "input_operand" "r,o,r,G,H,F,f,m,f"))] + [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,m,!r,!r,!r,f,f,m") + (match_operand:DF 1 "input_operand" "r,m,r,G,H,F,f,m,f"))] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && (gpc_reg_operand (operands[0], DFmode) || gpc_reg_operand (operands[1], DFmode))" @@ -6320,24 +6320,70 @@ abort (); case 0: /* We normally copy the low-numbered register first. However, if - the first register operand 0 is the same as the second register of - operand 1, we must copy in the opposite order. */ + the first register operand 0 is the same as the second register + of operand 1, we must copy in the opposite order. */ if (REGNO (operands[0]) == REGNO (operands[1]) + 1) return \"mr %L0,%L1\;mr %0,%1\"; else return \"mr %0,%1\;mr %L0,%L1\"; case 1: - /* If the low-address word is used in the address, we must load it - last. Otherwise, load it first. Note that we cannot have - auto-increment in that case since the address register is known to be - dead. */ - if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands [1], 0)) - return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\"; + if (offsettable_memref_p (operands[1])) + { + /* If the low-address word is used in the address, we must load + it last. Otherwise, load it first. Note that we cannot have + auto-increment in that case since the address register is + known to be dead. */ + if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, + operands[1], 0)) + return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\"; + else + return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\"; + } else - return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\"; + { + rtx addreg; + + if (GET_CODE (XEXP (operands[1], 0)) == PRE_INC + || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC) + abort (); + + addreg = find_addr_reg (XEXP (operands[1], 0)); + if (refers_to_regno_p (REGNO (operands[0]), + REGNO (operands[0]) + 1, + operands[1], 0)) + { + output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg); + output_asm_insn (\"{lx|lwzx} %L0,%1\", operands); + output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg); + return \"{lx|lwzx} %0,%1\"; + } + else + { + output_asm_insn (\"{lx|lwzx} %0,%1\", operands); + output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg); + output_asm_insn (\"{lx|lwzx} %L0,%1\", operands); + output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg); + return \"\"; + } + } case 2: - return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\"; + if (offsettable_memref_p (operands[0])) + return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\"; + else + { + rtx addreg; + + if (GET_CODE (XEXP (operands[1], 0)) == PRE_INC + || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC) + abort (); + + addreg = find_addr_reg (XEXP (operands[0], 0)); + output_asm_insn (\"{stx|stwx} %1,%0\", operands); + output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg); + output_asm_insn (\"{stx|stwx} %L1,%0\", operands); + output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg); + return \"\"; + } case 3: case 4: case 5: |