diff options
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/mn10300/mn10300.c | 171 | ||||
-rw-r--r-- | gcc/config/mn10300/mn10300.h | 23 | ||||
-rw-r--r-- | gcc/config/mn10300/mn10300.md | 383 |
3 files changed, 491 insertions, 86 deletions
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c index 1ae2a27..10e7ae3 100644 --- a/gcc/config/mn10300/mn10300.c +++ b/gcc/config/mn10300/mn10300.c @@ -1,5 +1,5 @@ /* Subroutines for insn-output.c for Matsushita MN10300 series - Copyright (C) 1996 Free Software Foundation, Inc. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. Contributed by Jeff Law (law@cygnus.com). This file is part of GNU CC. @@ -36,6 +36,26 @@ Boston, MA 02111-1307, USA. */ #include "tree.h" #include "obstack.h" +/* Global registers known to hold the value zero. + + Normally we'd depend on CSE and combine to put zero into a + register and re-use it. + + However, on the mn10x00 processors we implicitly use the constant + zero in tst instructions, so we might be able to do better by + loading the value into a register in the prologue, then re-useing + that register throughout the function. + + We could perform similar optimizations for other constants, but with + gcse due soon, it doesn't seem worth the effort. + + These variables hold a rtx for a register known to hold the value + zero throughout the entire function, or NULL if no register of + the appropriate class has such a value throughout the life of the + function. */ +rtx zero_dreg; +rtx zero_areg; + void asm_file_start (file) FILE *file; @@ -339,15 +359,124 @@ can_use_return_insn () && !frame_pointer_needed); } +/* Count the number of tst insns which compare a data or address + register with zero. */ +static void +count_tst_insns (dreg_countp, areg_countp) + int *dreg_countp; + int *areg_countp; +{ + rtx insn; + + /* Assume no tst insns exist. */ + *dreg_countp = 0; + *areg_countp = 0; + + /* If not optimizing, then quit now. */ + if (!optimize) + return; + + /* Walk through all the insns. */ + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + { + rtx pat; + + /* Ignore anything that is not a normal INSN. */ + if (GET_CODE (insn) != INSN) + continue; + + /* Ignore anything that isn't a SET. */ + pat = PATTERN (insn); + if (GET_CODE (pat) != SET) + continue; + + /* Check for a tst insn. */ + if (SET_DEST (pat) == cc0_rtx + && GET_CODE (SET_SRC (pat)) == REG) + { + if (REGNO_REG_CLASS (REGNO (SET_SRC (pat))) == DATA_REGS) + (*dreg_countp)++; + + if (REGNO_REG_CLASS (REGNO (SET_SRC (pat))) == ADDRESS_REGS) + (*areg_countp)++; + } + + /* Setting an address register to zero can also be optimized, + so count it just like a tst insn. */ + if (GET_CODE (SET_DEST (pat)) == REG + && GET_CODE (SET_SRC (pat)) == CONST_INT + && INTVAL (SET_SRC (pat)) == 0 + && REGNO_REG_CLASS (REGNO (SET_DEST (pat))) == ADDRESS_REGS) + (*areg_countp)++; + } +} + void expand_prologue () { unsigned int size; - /* We have to end the current sequence so leaf_function_p will - work. We then start a new sequence to hold the prologue/epilogue. */ + /* We have to end the current sequence so leaf_function_p and + count_tst_insns will work. We then start a new sequence to + hold the prologue/epilogue. */ end_sequence (); + /* Determine if it is profitable to put the value zero into a register + for the entire function. If so, set ZERO_DREG and ZERO_AREG. */ + if (regs_ever_live[2] || regs_ever_live[3] + || regs_ever_live[6] || regs_ever_live[7] + || frame_pointer_needed) + { + int dreg_count, areg_count; + + /* Get a count of the number of tst insns which use address and + data registers. */ + count_tst_insns (&dreg_count, &areg_count); + + /* If there's more than one tst insn using a data register, then + this optimization is a win. */ + if (dreg_count > 1 + && (!regs_ever_live[2] || !regs_ever_live[3])) + { + if (!regs_ever_live[2]) + { + regs_ever_live[2] = 1; + zero_dreg = gen_rtx (REG, SImode, 2); + } + else + { + regs_ever_live[3] = 1; + zero_dreg = gen_rtx (REG, SImode, 3); + } + } + else + zero_dreg = NULL_RTX; + + /* If there's more than two tst insns using an address register, + then this optimization is a win. */ + if (areg_count > 2 + && (!regs_ever_live[6] || !regs_ever_live[7])) + { + if (!regs_ever_live[6]) + { + regs_ever_live[6] = 1; + zero_areg = gen_rtx (REG, SImode, 6); + } + else + { + regs_ever_live[7] = 1; + zero_areg = gen_rtx (REG, SImode, 7); + } + } + else + zero_areg = NULL_RTX; + } + else + { + zero_dreg = NULL_RTX; + zero_areg = NULL_RTX; + } + /* SIZE includes the fixed stack space needed for function calls. */ size = get_frame_size () + (!leaf_function_p () ? 12 : 0); @@ -384,6 +513,13 @@ expand_prologue () emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (-size))); + + /* Load zeros into registers as needed. */ + if (zero_dreg) + emit_move_insn (zero_dreg, const0_rtx); + + if (zero_areg) + emit_move_insn (zero_areg, const0_rtx); } void @@ -713,14 +849,36 @@ char * output_tst (operand, insn) rtx operand, insn; { - rtx temp; int past_call = 0; + /* If we have a data register which is known to be zero throughout + the function, then use it instead of doing a search. */ + if (zero_dreg && REGNO_REG_CLASS (REGNO (operand)) == DATA_REGS) + { + rtx xoperands[2]; + xoperands[0] = operand; + xoperands[1] = zero_dreg; + + output_asm_insn ("cmp %1,%0", xoperands); + return ""; + } + + /* Similarly for address registers. */ + if (zero_areg && REGNO_REG_CLASS (REGNO (operand)) == ADDRESS_REGS) + { + rtx xoperands[2]; + xoperands[0] = operand; + xoperands[1] = zero_areg; + + output_asm_insn ("cmp %1,%0", xoperands); + return ""; + } + /* We can save a byte if we can find a register which has the value zero in it. */ temp = PREV_INSN (insn); - while (temp) + while (optimize && temp) { rtx set; @@ -759,7 +917,8 @@ output_tst (operand, insn) if (REG_P (SET_DEST (set)) && SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set))) && !reg_set_between_p (SET_DEST (set), temp, insn) - && REGNO_REG_CLASS (REGNO (SET_DEST (set))) == DATA_REGS + && (REGNO_REG_CLASS (REGNO (SET_DEST (set))) + == REGNO_REG_CLASS (REGNO (operand))) && REGNO (SET_DEST (set)) != REGNO (operand) && (!past_call || !call_used_regs[REGNO (SET_DEST (set))])) diff --git a/gcc/config/mn10300/mn10300.h b/gcc/config/mn10300/mn10300.h index d850641..c36c6c4 100644 --- a/gcc/config/mn10300/mn10300.h +++ b/gcc/config/mn10300/mn10300.h @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler. Matsushita MN10300 series - Copyright (C) 1996 Free Software Foundation, Inc. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. Contributed by Jeff Law (law@cygnus.com). This file is part of GNU CC. @@ -37,6 +37,10 @@ Boston, MA 02111-1307, USA. */ extern int target_flags; +/* Global registers known to hold the value zero. */ +extern struct rtx_def *zero_dreg; +extern struct rtx_def *zero_areg; + /* Macros used in the machine description to test the flags. */ /* Macro to define tables used to set the flags. @@ -404,8 +408,7 @@ enum reg_class { OFFSET = initial_offset (FROM, TO) #define FRAME_POINTER_REQUIRED \ - !(leaf_function_p ()) - + !(leaf_function_p () || current_function_outgoing_args_size == 0) #define CAN_DEBUG_WITHOUT_FP /* A guess for the MN10300. */ @@ -562,6 +565,20 @@ extern struct rtx_def *function_arg (); emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 0x18)), \ (FNADDR)); \ } +/* A C expression whose value is RTL representing the value of the return + address for the frame COUNT steps up from the current frame. + + On the mn10300, the return address is not at a constant location + due to the frame layout. Luckily, it is at a constant offset from + the argument pointer, so we define RETURN_ADDR_RTX to return a + MEM using arg_pointer_rtx. Reload will replace arg_pointer_rtx + with a reference to the stack/frame pointer + an appropriate offset. */ + +#define RETURN_ADDR_RTX(COUNT, FRAME) \ + ((COUNT == 0) \ + ? gen_rtx (MEM, Pmode, arg_pointer_rtx) \ + : (rtx) 0) + /* Emit code for a call to builtin_saveregs. We must emit USE insns which reference the 2 integer arg registers. Ordinarily they are not call used registers, but they are for diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md index 98f4536..13628ecf 100644 --- a/gcc/config/mn10300/mn10300.md +++ b/gcc/config/mn10300/mn10300.md @@ -1,4 +1,4 @@ -;; GCC machine description for Matsushita MN10300 +; GCC machine description for Matsushita MN10300 ;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. ;; Contributed by Jeff Law (law@cygnus.com). @@ -59,21 +59,45 @@ }") (define_insn "" - [(set (match_operand:QI 0 "general_operand" "=d,a,d,d,a,d,a,d,m") - (match_operand:QI 1 "general_operand" "0,0,I,a,d,di,ia,m,d"))] + [(set (match_operand:QI 0 "general_operand" "=d,a,d,a,d,a,d,a,d,m") + (match_operand:QI 1 "general_operand" "0,0,I,I,a,d,di,ia,m,d"))] "register_operand (operands[0], QImode) || register_operand (operands[1], QImode)" - "@ - nop - nop - clr %0 - mov %1,%0 - mov %1,%0 - mov %1,%0 - mov %1,%0 - movbu %1,%0 - movbu %1,%0" - [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + "* +{ + switch (which_alternative) + { + case 0: + case 1: + return \"nop\"; + case 2: + return \"clr %0\"; + case 3: + if (zero_areg) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %1,%0\", xoperands); + else + output_asm_insn (\"mov %1,%0\", xoperands); + return \"\"; + } + + /* FALLTHROUGH */ + case 4: + case 5: + case 6: + case 7: + return \"mov %1,%0\"; + case 8: + case 9: + return \"movbu %1,%0\"; + } +}" + [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) ;; movhi @@ -90,21 +114,45 @@ }") (define_insn "" - [(set (match_operand:HI 0 "general_operand" "=d,a,d,d,a,d,a,d,m") - (match_operand:HI 1 "general_operand" "0,0,I,a,d,di,ia,m,d"))] + [(set (match_operand:HI 0 "general_operand" "=d,a,d,a,d,a,d,a,d,m") + (match_operand:HI 1 "general_operand" "0,0,I,I,a,d,di,ia,m,d"))] "register_operand (operands[0], HImode) || register_operand (operands[1], HImode)" - "@ - nop - nop - clr %0 - mov %1,%0 - mov %1,%0 - mov %1,%0 - mov %1,%0 - movhu %1,%0 - movhu %1,%0" - [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + "* +{ + switch (which_alternative) + { + case 0: + case 1: + return \"nop\"; + case 2: + return \"clr %0\"; + case 3: + if (zero_areg) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %1,%0\", xoperands); + else + output_asm_insn (\"mov %1,%0\", xoperands); + return \"\"; + } + + /* FALLTHROUGH */ + case 4: + case 5: + case 6: + case 7: + return \"mov %1,%0\"; + case 8: + case 9: + return \"movhu %1,%0\"; + } +}" + [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) ;; movsi and helpers @@ -121,25 +169,50 @@ }") (define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d,a,d,dm,dm,am,am,d,d,a,a,aR,x") - (match_operand:SI 1 "general_operand" "0,0,I,d,a,d,a,dim,aim,dim,aim,x,aR"))] + [(set (match_operand:SI 0 "general_operand" + "=d,a,d,a,dm,dm,am,am,d,d,a,a,aR,x") + (match_operand:SI 1 "general_operand" + "0,0,I,I,d,a,d,a,dim,aim,dim,aim,x,aR"))] "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)" - "@ - nop - nop - clr %0 - mov %1,%0 - mov %1,%0 - mov %1,%0 - mov %1,%0 - mov %1,%0 - mov %1,%0 - mov %1,%0 - mov %1,%0 - mov %1,%0 - mov %1,%0" - [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + "* +{ + switch (which_alternative) + { + case 0: + case 1: + return \"nop\"; + case 2: + return \"clr %0\"; + case 3: + if (zero_areg) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %1,%0\", xoperands); + else + output_asm_insn (\"mov %1,%0\", xoperands); + return \"\"; + } + + /* FALLTHROUGH */ + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + return \"mov %1,%0\"; + } +}" + [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) (define_expand "movsf" [(set (match_operand:SF 0 "general_operand" "") @@ -154,17 +227,40 @@ }") (define_insn "" - [(set (match_operand:SF 0 "general_operand" "=d,a,d,dam,da") - (match_operand:SF 1 "general_operand" "0,0,G,da,daim"))] + [(set (match_operand:SF 0 "general_operand" "=d,a,d,a,dam,da") + (match_operand:SF 1 "general_operand" "0,0,G,G,da,daim"))] "register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode)" - "@ - nop - nop - clr %0 - mov %1,%0 - mov %1,%0" - [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit")]) + "* +{ + switch (which_alternative) + { + case 0: + case 1: + return \"nop\"; + case 2: + return \"clr %0\"; + case 3: + if (zero_areg) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %1,%0\", xoperands); + else + output_asm_insn (\"mov %1,%0\", xoperands); + return \"\"; + } + + /* FALLTHROUGH */ + case 4: + case 5: + return \"mov %1,%0\"; + } +}" + [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit")]) (define_expand "movdi" [(set (match_operand:DI 0 "general_operand" "") @@ -179,8 +275,10 @@ }") (define_insn "" - [(set (match_operand:DI 0 "general_operand" "=d,a,d,dm,dm,am,am,d,d,a,a") - (match_operand:DI 1 "general_operand" "0,0,I,d,a,d,a,dim,aim,dim,aim"))] + [(set (match_operand:DI 0 "general_operand" + "=d,a,d,a,dm,dm,am,am,d,d,a,a") + (match_operand:DI 1 "general_operand" + "0,0,I,I,d,a,d,a,dim,aim,dim,aim"))] "register_operand (operands[0], DImode) || register_operand (operands[1], DImode)" "* @@ -198,6 +296,17 @@ return \"clr %L0\;clr %H0\"; case 3: + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg ? zero_areg : operands[1]; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %L1,%L0\;mov %L0,%H0\", xoperands); + else + output_asm_insn (\"mov %1,%L0\;mov %L0,%H0\", xoperands); + return \"\"; + } case 4: case 5: case 6: @@ -205,6 +314,7 @@ case 8: case 9: case 10: + case 11: if (GET_CODE (operands[1]) == CONST_INT) { val[0] = INTVAL (operands[1]); @@ -243,28 +353,75 @@ return \"mov %L1,%L0\;mov %H1,%H0\"; } + else if (GET_CODE (operands[1]) == MEM + && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)) + && REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = XEXP (operands[1], 0); + + output_asm_insn (\"mov %1,%L0\;mov (4,%L0),%H0\;mov (%L0),%L0\", + xoperands); + return \"\"; + } else { if ((GET_CODE (operands[1]) == CONST_INT || GET_CODE (operands[1]) == CONST_DOUBLE) - && val[0] == 0 - && REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) - output_asm_insn (\"clr %L0\", operands); + && val[0] == 0) + { + if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) + output_asm_insn (\"clr %L0\", operands); + else if (zero_areg) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %L0,%L0\", xoperands); + else + output_asm_insn (\"mov %1,%L0\", xoperands); + } + else + output_asm_insn (\"mov %L1,%L0\", operands); + } else output_asm_insn (\"mov %L1,%L0\", operands); if ((GET_CODE (operands[1]) == CONST_INT || GET_CODE (operands[1]) == CONST_DOUBLE) - && val[1] == 0 - && REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) - output_asm_insn (\"clr %H0\", operands); + && val[1] == 0) + { + if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) + output_asm_insn (\"clr %H0\", operands); + else if (zero_areg) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %H0,%H0\", xoperands); + else + output_asm_insn (\"mov %1,%H0\", xoperands); + } + else + output_asm_insn (\"mov %H1,%H0\", operands); + } + else if ((GET_CODE (operands[1]) == CONST_INT + || GET_CODE (operands[1]) == CONST_DOUBLE) + && val[0] == val[1]) + output_asm_insn (\"mov %L0,%H0\", operands); else output_asm_insn (\"mov %H1,%H0\", operands); return \"\"; } } }" - [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) (define_expand "movdf" [(set (match_operand:DF 0 "general_operand" "") @@ -279,8 +436,10 @@ }") (define_insn "" - [(set (match_operand:DF 0 "general_operand" "=d,a,d,dm,dm,am,am,d,d,a,a") - (match_operand:DF 1 "general_operand" "0,0,G,d,a,d,a,dim,aim,dim,aim"))] + [(set (match_operand:DF 0 "general_operand" + "=d,a,d,a,dm,dm,am,am,d,d,a,a") + (match_operand:DF 1 "general_operand" + "0,0,G,G,d,a,d,a,dim,aim,dim,aim"))] "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)" "* @@ -298,6 +457,17 @@ return \"clr %L0\;clr %H0\"; case 3: + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg ? zero_areg : operands[1]; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %L1,%L0\;mov %L0,%H0\", xoperands); + else + output_asm_insn (\"mov %1,%L0\;mov %L0,%H0\", xoperands); + return \"\"; + } case 4: case 5: case 6: @@ -305,6 +475,7 @@ case 8: case 9: case 10: + case 11: if (GET_CODE (operands[1]) == CONST_INT) { val[0] = INTVAL (operands[1]); @@ -343,28 +514,75 @@ return \"mov %L1,%L0\;mov %H1,%H0\"; } + else if (GET_CODE (operands[1]) == MEM + && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)) + && REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = XEXP (operands[1], 0); + + output_asm_insn (\"mov %1,%L0\;mov (4,%L0),%H0\;mov (%L0),%L0\", + xoperands); + return \"\"; + } else { if ((GET_CODE (operands[1]) == CONST_INT || GET_CODE (operands[1]) == CONST_DOUBLE) - && val[0] == 0 - && REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) - output_asm_insn (\"clr %L0\", operands); + && val[0] == 0) + { + if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) + output_asm_insn (\"clr %L0\", operands); + else if (zero_areg) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %L0,%L0\", xoperands); + else + output_asm_insn (\"mov %1,%L0\", xoperands); + } + else + output_asm_insn (\"mov %L1,%L0\", operands); + } else output_asm_insn (\"mov %L1,%L0\", operands); if ((GET_CODE (operands[1]) == CONST_INT || GET_CODE (operands[1]) == CONST_DOUBLE) - && val[1] == 0 - && REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) - output_asm_insn (\"clr %H0\", operands); + && val[1] == 0) + { + if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) + output_asm_insn (\"clr %H0\", operands); + else if (zero_areg) + { + rtx xoperands[2]; + + xoperands[0] = operands[0]; + xoperands[1] = zero_areg; + if (rtx_equal_p (xoperands[0], xoperands[1])) + output_asm_insn (\"sub %H0,%H0\", xoperands); + else + output_asm_insn (\"mov %1,%H0\", xoperands); + } + else + output_asm_insn (\"mov %H1,%H0\", operands); + } + else if ((GET_CODE (operands[1]) == CONST_INT + || GET_CODE (operands[1]) == CONST_DOUBLE) + && val[0] == val[1]) + output_asm_insn (\"mov %L0,%H0\", operands); else output_asm_insn (\"mov %H1,%H0\", operands); return \"\"; } } }" - [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) @@ -428,17 +646,18 @@ }") (define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,a,a,da,x") - (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0") - (match_operand:SI 2 "nonmemory_operand" "J,J,L,dai,i")))] + [(set (match_operand:SI 0 "register_operand" "=d,a,a,da,x,!&da") + (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,da") + (match_operand:SI 2 "nonmemory_operand" "J,J,L,dai,i,da")))] "" "@ inc %0 inc %0 inc4 %0 add %2,%0 - add %2,%0" - [(set_attr "cc" "set_zn_c0,none_0hit,none_0hit,set_zn_c0,none_0hit")]) + add %2,%0 + mov %2,%0\;add %1,%0" + [(set_attr "cc" "set_zn_c0,none_0hit,none_0hit,set_zn_c0,none_0hit,none_0hit")]) (define_expand "adddi3" [(set (reg:DI 0) (match_operand:DI 1 "register_operand" "")) @@ -1131,7 +1350,17 @@ (define_insn "return" [(return)] "can_use_return_insn ()" - "rets" + "* +{ + rtx next = next_active_insn (insn); + + if (next + && GET_CODE (next) == JUMP_INSN + && GET_CODE (PATTERN (next)) == RETURN) + return \"\"; + else + return \"rets\"; +}" [(set_attr "cc" "clobber")]) ;; Try to combine consecutive updates of the stack pointer (or any |