diff options
Diffstat (limited to 'contrib/gcc/config/arm')
-rw-r--r-- | contrib/gcc/config/arm/arm-protos.h | 4 | ||||
-rw-r--r-- | contrib/gcc/config/arm/arm.c | 40 | ||||
-rw-r--r-- | contrib/gcc/config/arm/arm.h | 2 | ||||
-rw-r--r-- | contrib/gcc/config/arm/arm.md | 20 | ||||
-rw-r--r-- | contrib/gcc/config/arm/t-netbsd | 6 | ||||
-rw-r--r-- | contrib/gcc/config/arm/t-rtems | 10 |
6 files changed, 59 insertions, 23 deletions
diff --git a/contrib/gcc/config/arm/arm-protos.h b/contrib/gcc/config/arm/arm-protos.h index 471254efe4e1..2da99b82d677 100644 --- a/contrib/gcc/config/arm/arm-protos.h +++ b/contrib/gcc/config/arm/arm-protos.h @@ -1,5 +1,6 @@ /* Prototypes for exported functions defined in arm.c and pe.c - Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005 + Free Software Foundation, Inc. Contributed by Richard Earnshaw (rearnsha@arm.com) Minor hacks by Nick Clifton (nickc@cygnus.com) @@ -138,6 +139,7 @@ extern int arm_debugger_arg_offset (int, rtx); extern int arm_is_longcall_p (rtx, int, int); extern int arm_emit_vector_const (FILE *, rtx); extern const char * arm_output_load_gr (rtx *); +extern int arm_eliminable_register (rtx); #if defined TREE_CODE extern rtx arm_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int); diff --git a/contrib/gcc/config/arm/arm.c b/contrib/gcc/config/arm/arm.c index 91e4486d0bbb..95188944be3d 100644 --- a/contrib/gcc/config/arm/arm.c +++ b/contrib/gcc/config/arm/arm.c @@ -1,6 +1,6 @@ /* Output routines for GCC for ARM. Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004 Free Software Foundation, Inc. + 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) and Martin Simmons (@harleqn.co.uk). More major hacks by Richard Earnshaw (rearnsha@arm.com). @@ -4056,6 +4056,16 @@ cirrus_shift_const (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) && INTVAL (op) < 64); } +/* Return true if X is a register that will be eliminated later on. */ +int +arm_eliminable_register (rtx x) +{ + return REG_P (x) && (REGNO (x) == FRAME_POINTER_REGNUM + || REGNO (x) == ARG_POINTER_REGNUM + || (REGNO (x) >= FIRST_VIRTUAL_REGISTER + && REGNO (x) <= LAST_VIRTUAL_REGISTER)); +} + /* Returns TRUE if INSN is an "LDR REG, ADDR" instruction. Use by the Cirrus Maverick code which has to workaround a hardware bug triggered by such instructions. */ @@ -4569,33 +4579,42 @@ adjacent_mem_locations (rtx a, rtx b) || (GET_CODE (XEXP (b, 0)) == PLUS && GET_CODE (XEXP (XEXP (b, 0), 1)) == CONST_INT))) { - int val0 = 0, val1 = 0; - int reg0, reg1; - + HOST_WIDE_INT val0 = 0, val1 = 0; + rtx reg0, reg1; + int val_diff; + if (GET_CODE (XEXP (a, 0)) == PLUS) { - reg0 = REGNO (XEXP (XEXP (a, 0), 0)); + reg0 = XEXP (XEXP (a, 0), 0); val0 = INTVAL (XEXP (XEXP (a, 0), 1)); } else - reg0 = REGNO (XEXP (a, 0)); + reg0 = XEXP (a, 0); if (GET_CODE (XEXP (b, 0)) == PLUS) { - reg1 = REGNO (XEXP (XEXP (b, 0), 0)); + reg1 = XEXP (XEXP (b, 0), 0); val1 = INTVAL (XEXP (XEXP (b, 0), 1)); } else - reg1 = REGNO (XEXP (b, 0)); + reg1 = XEXP (b, 0); /* Don't accept any offset that will require multiple instructions to handle, since this would cause the arith_adjacentmem pattern to output an overlong sequence. */ if (!const_ok_for_op (PLUS, val0) || !const_ok_for_op (PLUS, val1)) return 0; - - return (reg0 == reg1) && ((val1 - val0) == 4 || (val0 - val1) == 4); + + /* Don't allow an eliminable register: register elimination can make + the offset too large. */ + if (arm_eliminable_register (reg0)) + return 0; + + val_diff = val1 - val0; + return ((REGNO (reg0) == REGNO (reg1)) + && (val_diff == 4 || val_diff == -4)); } + return 0; } @@ -7301,7 +7320,6 @@ output_call_mem (rtx *operands) return ""; } - /* Output a move from arm registers to an fpa registers. OPERANDS[0] is an fpa register. OPERANDS[1] is the first registers of an arm register pair. */ diff --git a/contrib/gcc/config/arm/arm.h b/contrib/gcc/config/arm/arm.h index 3a13d919243b..94d8b943b410 100644 --- a/contrib/gcc/config/arm/arm.h +++ b/contrib/gcc/config/arm/arm.h @@ -1396,7 +1396,7 @@ enum reg_class : NO_REGS) #define THUMB_SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \ - ((CLASS) != LO_REGS \ + ((CLASS) != LO_REGS && (CLASS) != BASE_REGS \ ? ((true_regnum (X) == -1 ? LO_REGS \ : (true_regnum (X) + HARD_REGNO_NREGS (0, MODE) > 8) ? LO_REGS \ : NO_REGS)) \ diff --git a/contrib/gcc/config/arm/arm.md b/contrib/gcc/config/arm/arm.md index 9f10d1063dfa..57926ba6b9bc 100644 --- a/contrib/gcc/config/arm/arm.md +++ b/contrib/gcc/config/arm/arm.md @@ -5960,22 +5960,24 @@ [(set (pc) (if_then_else (match_operator 5 "equality_operator" - [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l")) - (match_operand:SI 2 "s_register_operand" "0,1,1,1")) + [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l")) + (match_operand:SI 2 "s_register_operand" "0,1,1,1,1")) (const_int 0)]) (label_ref (match_operand 4 "" "")) (pc))) - (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") + (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m") (and:SI (not:SI (match_dup 3)) (match_dup 2))) - (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] + (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))] "TARGET_THUMB" "* { if (which_alternative == 0) output_asm_insn (\"bic\\t%0, %3\", operands); - else if (which_alternative == 1) + else if (which_alternative <= 2) { output_asm_insn (\"bic\\t%1, %3\", operands); + /* It's ok if OP0 is a lo-reg, even though the mov will set the + conditions again, since we're only testing for equality. */ output_asm_insn (\"mov\\t%0, %1\", operands); } else @@ -6234,10 +6236,10 @@ case 1: output_asm_insn (\"cmn\t%1, %2\", operands); break; - case 3: + case 2: output_asm_insn (\"add\t%0, %1, %2\", operands); break; - case 4: + case 3: output_asm_insn (\"add\t%0, %0, %2\", operands); break; } @@ -7128,8 +7130,8 @@ (const_string "no"))) (set (attr "length") (if_then_else - (and (ge (minus (match_dup 0) (pc)) (const_int -2048)) - (le (minus (match_dup 0) (pc)) (const_int 2044))) + (and (ge (minus (match_dup 0) (pc)) (const_int -2044)) + (le (minus (match_dup 0) (pc)) (const_int 2048))) (const_int 2) (const_int 4)))] ) diff --git a/contrib/gcc/config/arm/t-netbsd b/contrib/gcc/config/arm/t-netbsd index 77e622716f25..533fab947a1c 100644 --- a/contrib/gcc/config/arm/t-netbsd +++ b/contrib/gcc/config/arm/t-netbsd @@ -11,8 +11,12 @@ SHLIB_OBJS = @shlib_objs@ SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \ -Wl,-soname,$(SHLIB_SONAME) \ - -o $(SHLIB_NAME) @multilib_flags@ $(SHLIB_OBJS) -lc && \ + -o $(SHLIB_NAME).tmp @multilib_flags@ $(SHLIB_OBJS) -lc && \ rm -f $(SHLIB_SONAME) && \ + if [ -f $(SHLIB_NAME) ]; then \ + mv -f $(SHLIB_NAME) $(SHLIB_NAME).backup; \ + else true; fi && \ + mv $(SHLIB_NAME).tmp $(SHLIB_NAME) && \ $(LN_S) $(SHLIB_NAME) $(SHLIB_SONAME) # $(slibdir) double quoted to protect it from expansion while building # libgcc.mk. We want this delayed until actual install time. diff --git a/contrib/gcc/config/arm/t-rtems b/contrib/gcc/config/arm/t-rtems new file mode 100644 index 000000000000..52d14bab08f6 --- /dev/null +++ b/contrib/gcc/config/arm/t-rtems @@ -0,0 +1,10 @@ +# Custom rtems multilibs + +MULTILIB_OPTIONS = marm/mthumb +MULTILIB_DIRNAMES = arm thumb +MULTILIB_EXCEPTIONS = +MULTILIB_MATCHES = marm=mno-thumb + +MULTILIB_OPTIONS += msoft-float/mhard-float +MULTILIB_DIRNAMES += soft fpu +MULTILIB_EXCEPTIONS += *mthumb/*mhard-float* |