--- gcc/config/i860/i860.c 2018/04/24 18:10:24 1.1.1.1 +++ gcc/config/i860/i860.c 2018/04/24 18:28:47 1.1.1.4 @@ -4,7 +4,7 @@ Written by Richard Stallman (rms@ai.mit.edu). - Hacked substantially by Ron Guilmette (rfg@ncd.com) to cater + Hacked substantially by Ron Guilmette (rfg@netcom.com) to cater to the whims of the System V Release 4 assembler. This file is part of GNU CC. @@ -21,7 +21,8 @@ GNU General Public License for more deta You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ #include "config.h" @@ -99,7 +100,6 @@ safe_insn_src_p (op, mode) case AND: case IOR: case XOR: - case LSHIFT: case ASHIFT: case ASHIFTRT: case LSHIFTRT: @@ -326,7 +326,6 @@ single_insn_src_p (op, mode) || INTVAL (XEXP (op, 1)) & 0xffff == 0))) return 0; - case LSHIFT: case ASHIFT: case ASHIFTRT: case LSHIFTRT: @@ -572,6 +571,8 @@ output_move_double (operands) enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1; rtx latehalf[2]; rtx addreg0 = 0, addreg1 = 0; + int highest_first = 0; + int no_addreg1_decrement = 0; /* First classify both operands. */ @@ -680,15 +681,40 @@ output_move_double (operands) else if (optype0 == REGOP && optype1 != REGOP && reg_overlap_mentioned_p (operands[0], operands[1])) { - /* Do the late half first. */ - output_asm_insn (singlemove_string (latehalf), latehalf); - /* Then clobber. */ - return singlemove_string (operands); + /* If both halves of dest are used in the src memory address, + add the two regs and put them in the low reg (operands[0]). + Then it works to load latehalf first. */ + if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)) + && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0))) + { + rtx xops[2]; + xops[0] = latehalf[0]; + xops[1] = operands[0]; + output_asm_insn ("adds %1,%0,%1", xops); + operands[1] = gen_rtx (MEM, DImode, operands[0]); + latehalf[1] = adj_offsettable_operand (operands[1], 4); + addreg1 = 0; + highest_first = 1; + } + /* Only one register in the dest is used in the src memory address, + and this is the first register of the dest, so we want to do + the late half first here also. */ + else if (! reg_mentioned_p (latehalf[0], XEXP (operands[1], 0))) + highest_first = 1; + /* Only one register in the dest is used in the src memory address, + and this is the second register of the dest, so we want to do + the late half last. If addreg1 is set, and addreg1 is the same + register as latehalf, then we must suppress the trailing decrement, + because it would clobber the value just loaded. */ + else if (addreg1 && reg_mentioned_p (addreg1, latehalf[0])) + no_addreg1_decrement = 1; } - /* Normal case: do the two words, low-numbered first. */ + /* Normal case: do the two words, low-numbered first. + Overlap case (highest_first set): do high-numbered word first. */ - output_asm_insn (singlemove_string (operands), operands); + if (! highest_first) + output_asm_insn (singlemove_string (operands), operands); CC_STATUS_PARTIAL_INIT; /* Make any unoffsettable addresses point at high-numbered word. */ @@ -703,9 +729,12 @@ output_move_double (operands) /* Undo the adds we just did. */ if (addreg0) output_asm_insn ("adds -0x4,%0,%0", &addreg0); - if (addreg1) + if (addreg1 && !no_addreg1_decrement) output_asm_insn ("adds -0x4,%0,%0", &addreg1); + if (highest_first) + output_asm_insn (singlemove_string (operands), operands); + return ""; }