aboutsummaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch')
-rw-r--r--meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch675
1 files changed, 675 insertions, 0 deletions
diff --git a/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch b/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch
new file mode 100644
index 0000000000..95907eeb87
--- /dev/null
+++ b/meta-oe/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch
@@ -0,0 +1,675 @@
+ 2010-07-02 Daniel Jacobowitz <dan@codesourcery.com>
+ Julian Brown <julian@codesourcery.com>
+ Sandra Loosemore <sandra@codesourcery.com>
+
+ gcc/
+ * config/arm/arm.c (arm_canonicalize_comparison): Canonicalize DImode
+ comparisons. Adjust to take both operands.
+ (arm_select_cc_mode): Handle DImode comparisons.
+ (arm_gen_compare_reg): Generate a scratch register for DImode
+ comparisons which require one. Use xor for Thumb equality checks.
+ (arm_const_double_by_immediates): New.
+ (arm_print_operand): Allow 'Q' and 'R' for constants.
+ (get_arm_condition_code): Handle new CC_CZmode and CC_NCVmode.
+ * config/arm/arm.h (CANONICALIZE_COMPARISON): Always use
+ arm_canonicalize_comparison.
+ * config/arm/arm-modes.def: Add CC_CZmode and CC_NCVmode.
+ * config/arm/arm-protos.h (arm_canonicalize_comparison): Update
+ prototype.
+ (arm_const_double_by_immediates): Declare.
+ * config/arm/constraints.md (Di): New constraint.
+ * config/arm/predicates.md (arm_immediate_di_operand)
+ (arm_di_operand, cmpdi_operand): New.
+ * config/arm/arm.md (cbranchdi4): Handle non-Cirrus also.
+ (*arm_cmpdi_insn, *arm_cmpdi_unsigned)
+ (*arm_cmpdi_zero, *thumb_cmpdi_zero): New insns.
+ (cstoredi4): Handle non-Cirrus also.
+
+ gcc/testsuite/
+ * gcc.c-torture/execute/20100416-1.c: New test case.
+
+2010-07-08 Sandra Loosemore <sandra@codesourcery.com>
+
+ Backport from upstream (originally from Sourcery G++ 4.4):
+
+ 2010-07-02 Sandra Loosemore <sandra@codesourcery.com>
+
+ gcc/
+
+=== modified file 'gcc/config/arm/arm-modes.def'
+--- old/gcc/config/arm/arm-modes.def 2009-06-18 11:24:10 +0000
++++ new/gcc/config/arm/arm-modes.def 2010-07-29 16:58:56 +0000
+@@ -35,10 +35,16 @@
+ CC_NOOVmode should be used with SImode integer equalities.
+ CC_Zmode should be used if only the Z flag is set correctly
+ CC_Nmode should be used if only the N (sign) flag is set correctly
++ CC_CZmode should be used if only the C and Z flags are correct
++ (used for DImode unsigned comparisons).
++ CC_NCVmode should be used if only the N, C, and V flags are correct
++ (used for DImode signed comparisons).
+ CCmode should be used otherwise. */
+
+ CC_MODE (CC_NOOV);
+ CC_MODE (CC_Z);
++CC_MODE (CC_CZ);
++CC_MODE (CC_NCV);
+ CC_MODE (CC_SWP);
+ CC_MODE (CCFP);
+ CC_MODE (CCFPE);
+
+=== modified file 'gcc/config/arm/arm-protos.h'
+--- old/gcc/config/arm/arm-protos.h 2009-11-11 14:23:03 +0000
++++ new/gcc/config/arm/arm-protos.h 2010-07-29 16:58:56 +0000
+@@ -49,8 +49,7 @@
+ extern int const_ok_for_arm (HOST_WIDE_INT);
+ extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
+ HOST_WIDE_INT, rtx, rtx, int);
+-extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, enum machine_mode,
+- rtx *);
++extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *, rtx *);
+ extern int legitimate_pic_operand_p (rtx);
+ extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
+ extern rtx legitimize_tls_address (rtx, rtx);
+@@ -116,6 +115,7 @@
+ extern void arm_reload_out_hi (rtx *);
+ extern int arm_const_double_inline_cost (rtx);
+ extern bool arm_const_double_by_parts (rtx);
++extern bool arm_const_double_by_immediates (rtx);
+ extern const char *fp_immediate_constant (rtx);
+ extern void arm_emit_call_insn (rtx, rtx);
+ extern const char *output_call (rtx *);
+
+=== modified file 'gcc/config/arm/arm.c'
+--- old/gcc/config/arm/arm.c 2010-07-29 15:59:12 +0000
++++ new/gcc/config/arm/arm.c 2010-07-29 16:58:56 +0000
+@@ -3190,13 +3190,82 @@
+ immediate value easier to load. */
+
+ enum rtx_code
+-arm_canonicalize_comparison (enum rtx_code code, enum machine_mode mode,
+- rtx * op1)
++arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1)
+ {
+- unsigned HOST_WIDE_INT i = INTVAL (*op1);
+- unsigned HOST_WIDE_INT maxval;
++ enum machine_mode mode;
++ unsigned HOST_WIDE_INT i, maxval;
++
++ mode = GET_MODE (*op0);
++ if (mode == VOIDmode)
++ mode = GET_MODE (*op1);
++
+ maxval = (((unsigned HOST_WIDE_INT) 1) << (GET_MODE_BITSIZE(mode) - 1)) - 1;
+
++ /* For DImode, we have GE/LT/GEU/LTU comparisons. In ARM mode
++ we can also use cmp/cmpeq for GTU/LEU. GT/LE must be either
++ reversed or (for constant OP1) adjusted to GE/LT. Similarly
++ for GTU/LEU in Thumb mode. */
++ if (mode == DImode)
++ {
++ rtx tem;
++
++ /* To keep things simple, always use the Cirrus cfcmp64 if it is
++ available. */
++ if (TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK)
++ return code;
++
++ if (code == GT || code == LE
++ || (!TARGET_ARM && (code == GTU || code == LEU)))
++ {
++ /* Missing comparison. First try to use an available
++ comparison. */
++ if (GET_CODE (*op1) == CONST_INT)
++ {
++ i = INTVAL (*op1);
++ switch (code)
++ {
++ case GT:
++ case LE:
++ if (i != maxval
++ && arm_const_double_by_immediates (GEN_INT (i + 1)))
++ {
++ *op1 = GEN_INT (i + 1);
++ return code == GT ? GE : LT;
++ }
++ break;
++ case GTU:
++ case LEU:
++ if (i != ~((unsigned HOST_WIDE_INT) 0)
++ && arm_const_double_by_immediates (GEN_INT (i + 1)))
++ {
++ *op1 = GEN_INT (i + 1);
++ return code == GTU ? GEU : LTU;
++ }
++ break;
++ default:
++ gcc_unreachable ();
++ }
++ }
++
++ /* If that did not work, reverse the condition. */
++ tem = *op0;
++ *op0 = *op1;
++ *op1 = tem;
++ return swap_condition (code);
++ }
++
++ return code;
++ }
++
++ /* Comparisons smaller than DImode. Only adjust comparisons against
++ an out-of-range constant. */
++ if (GET_CODE (*op1) != CONST_INT
++ || const_ok_for_arm (INTVAL (*op1))
++ || const_ok_for_arm (- INTVAL (*op1)))
++ return code;
++
++ i = INTVAL (*op1);
++
+ switch (code)
+ {
+ case EQ:
+@@ -9912,6 +9981,55 @@
+ && (rtx_equal_p (XEXP (x, 0), y) || rtx_equal_p (XEXP (x, 1), y)))
+ return CC_Cmode;
+
++ if (GET_MODE (x) == DImode || GET_MODE (y) == DImode)
++ {
++ /* To keep things simple, always use the Cirrus cfcmp64 if it is
++ available. */
++ if (TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK)
++ return CCmode;
++
++ switch (op)
++ {
++ case EQ:
++ case NE:
++ /* A DImode comparison against zero can be implemented by
++ or'ing the two halves together. */
++ if (y == const0_rtx)
++ return CC_Zmode;
++
++ /* We can do an equality test in three Thumb instructions. */
++ if (!TARGET_ARM)
++ return CC_Zmode;
++
++ /* FALLTHROUGH */
++
++ case LTU:
++ case LEU:
++ case GTU:
++ case GEU:
++ /* DImode unsigned comparisons can be implemented by cmp +
++ cmpeq without a scratch register. Not worth doing in
++ Thumb-2. */
++ if (TARGET_ARM)
++ return CC_CZmode;
++
++ /* FALLTHROUGH */
++
++ case LT:
++ case LE:
++ case GT:
++ case GE:
++ /* DImode signed and unsigned comparisons can be implemented
++ by cmp + sbcs with a scratch register, but that does not
++ set the Z flag - we must reverse GT/LE/GTU/LEU. */
++ gcc_assert (op != EQ && op != NE);
++ return CC_NCVmode;
++
++ default:
++ gcc_unreachable ();
++ }
++ }
++
+ return CCmode;
+ }
+
+@@ -9921,10 +10039,39 @@
+ rtx
+ arm_gen_compare_reg (enum rtx_code code, rtx x, rtx y)
+ {
+- enum machine_mode mode = SELECT_CC_MODE (code, x, y);
+- rtx cc_reg = gen_rtx_REG (mode, CC_REGNUM);
+-
+- emit_set_insn (cc_reg, gen_rtx_COMPARE (mode, x, y));
++ enum machine_mode mode;
++ rtx cc_reg;
++ int dimode_comparison = GET_MODE (x) == DImode || GET_MODE (y) == DImode;
++
++ /* We might have X as a constant, Y as a register because of the predicates
++ used for cmpdi. If so, force X to a register here. */
++ if (dimode_comparison && !REG_P (x))
++ x = force_reg (DImode, x);
++
++ mode = SELECT_CC_MODE (code, x, y);
++ cc_reg = gen_rtx_REG (mode, CC_REGNUM);
++
++ if (dimode_comparison
++ && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
++ && mode != CC_CZmode)
++ {
++ rtx clobber, set;
++
++ /* To compare two non-zero values for equality, XOR them and
++ then compare against zero. Not used for ARM mode; there
++ CC_CZmode is cheaper. */
++ if (mode == CC_Zmode && y != const0_rtx)
++ {
++ x = expand_binop (DImode, xor_optab, x, y, NULL_RTX, 0, OPTAB_WIDEN);
++ y = const0_rtx;
++ }
++ /* A scratch register is required. */
++ clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode));
++ set = gen_rtx_SET (VOIDmode, cc_reg, gen_rtx_COMPARE (mode, x, y));
++ emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber)));
++ }
++ else
++ emit_set_insn (cc_reg, gen_rtx_COMPARE (mode, x, y));
+
+ return cc_reg;
+ }
+@@ -11253,6 +11400,34 @@
+ return false;
+ }
+
++/* Return true if it is possible to inline both the high and low parts
++ of a 64-bit constant into 32-bit data processing instructions. */
++bool
++arm_const_double_by_immediates (rtx val)
++{
++ enum machine_mode mode = GET_MODE (val);
++ rtx part;
++
++ if (mode == VOIDmode)
++ mode = DImode;
++
++ part = gen_highpart_mode (SImode, mode, val);
++
++ gcc_assert (GET_CODE (part) == CONST_INT);
++
++ if (!const_ok_for_arm (INTVAL (part)))
++ return false;
++
++ part = gen_lowpart (SImode, val);
++
++ gcc_assert (GET_CODE (part) == CONST_INT);
++
++ if (!const_ok_for_arm (INTVAL (part)))
++ return false;
++
++ return true;
++}
++
+ /* Scan INSN and note any of its operands that need fixing.
+ If DO_PUSHES is false we do not actually push any of the fixups
+ needed. The function returns TRUE if any fixups were needed/pushed.
+@@ -15097,8 +15272,18 @@
+ the value being loaded is big-wordian or little-wordian. The
+ order of the two register loads can matter however, if the address
+ of the memory location is actually held in one of the registers
+- being overwritten by the load. */
++ being overwritten by the load.
++
++ The 'Q' and 'R' constraints are also available for 64-bit
++ constants. */
+ case 'Q':
++ if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
++ {
++ rtx part = gen_lowpart (SImode, x);
++ fprintf (stream, "#" HOST_WIDE_INT_PRINT_DEC, INTVAL (part));
++ return;
++ }
++
+ if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM)
+ {
+ output_operand_lossage ("invalid operand for code '%c'", code);
+@@ -15109,6 +15294,18 @@
+ return;
+
+ case 'R':
++ if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
++ {
++ enum machine_mode mode = GET_MODE (x);
++ rtx part;
++
++ if (mode == VOIDmode)
++ mode = DImode;
++ part = gen_highpart_mode (SImode, mode, x);
++ fprintf (stream, "#" HOST_WIDE_INT_PRINT_DEC, INTVAL (part));
++ return;
++ }
++
+ if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM)
+ {
+ output_operand_lossage ("invalid operand for code '%c'", code);
+@@ -15801,6 +15998,28 @@
+ default: gcc_unreachable ();
+ }
+
++ case CC_CZmode:
++ switch (comp_code)
++ {
++ case NE: return ARM_NE;
++ case EQ: return ARM_EQ;
++ case GEU: return ARM_CS;
++ case GTU: return ARM_HI;
++ case LEU: return ARM_LS;
++ case LTU: return ARM_CC;
++ default: gcc_unreachable ();
++ }
++
++ case CC_NCVmode:
++ switch (comp_code)
++ {
++ case GE: return ARM_GE;
++ case LT: return ARM_LT;
++ case GEU: return ARM_CS;
++ case LTU: return ARM_CC;
++ default: gcc_unreachable ();
++ }
++
+ case CCmode:
+ switch (comp_code)
+ {
+
+=== modified file 'gcc/config/arm/arm.h'
+--- old/gcc/config/arm/arm.h 2009-12-23 16:36:40 +0000
++++ new/gcc/config/arm/arm.h 2010-07-29 16:58:56 +0000
+@@ -2253,19 +2253,7 @@
+ : reverse_condition (code))
+
+ #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
+- do \
+- { \
+- if (GET_CODE (OP1) == CONST_INT \
+- && ! (const_ok_for_arm (INTVAL (OP1)) \
+- || (const_ok_for_arm (- INTVAL (OP1))))) \
+- { \
+- rtx const_op = OP1; \
+- CODE = arm_canonicalize_comparison ((CODE), GET_MODE (OP0), \
+- &const_op); \
+- OP1 = const_op; \
+- } \
+- } \
+- while (0)
++ (CODE) = arm_canonicalize_comparison (CODE, &(OP0), &(OP1))
+
+ /* The arm5 clz instruction returns 32. */
+ #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
+
+=== modified file 'gcc/config/arm/arm.md'
+--- old/gcc/config/arm/arm.md 2010-07-29 15:59:12 +0000
++++ new/gcc/config/arm/arm.md 2010-07-29 16:58:56 +0000
+@@ -6718,17 +6718,45 @@
+ operands[3])); DONE;"
+ )
+
+-;; this uses the Cirrus DI compare instruction
+ (define_expand "cbranchdi4"
+ [(set (pc) (if_then_else
+ (match_operator 0 "arm_comparison_operator"
+- [(match_operand:DI 1 "cirrus_fp_register" "")
+- (match_operand:DI 2 "cirrus_fp_register" "")])
++ [(match_operand:DI 1 "cmpdi_operand" "")
++ (match_operand:DI 2 "cmpdi_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+- "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
+- operands[3])); DONE;"
++ "TARGET_32BIT"
++ "{
++ rtx swap = NULL_RTX;
++ enum rtx_code code = GET_CODE (operands[0]);
++
++ /* We should not have two constants. */
++ gcc_assert (GET_MODE (operands[1]) == DImode
++ || GET_MODE (operands[2]) == DImode);
++
++ /* Flip unimplemented DImode comparisons to a form that
++ arm_gen_compare_reg can handle. */
++ switch (code)
++ {
++ case GT:
++ swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
++ case LE:
++ swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
++ case GTU:
++ swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
++ case LEU:
++ swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
++ default:
++ break;
++ }
++ if (swap)
++ emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
++ operands[3]));
++ else
++ emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
++ operands[3]));
++ DONE;
++ }"
+ )
+
+ (define_insn "*cbranchsi4_insn"
+@@ -7880,6 +7908,52 @@
+ (const_string "alu_shift_reg")))]
+ )
+
++;; DImode comparisons. The generic code generates branches that
++;; if-conversion can not reduce to a conditional compare, so we do
++;; that directly.
++
++(define_insn "*arm_cmpdi_insn"
++ [(set (reg:CC_NCV CC_REGNUM)
++ (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
++ (match_operand:DI 1 "arm_di_operand" "rDi")))
++ (clobber (match_scratch:SI 2 "=r"))]
++ "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
++ "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
++ [(set_attr "conds" "set")
++ (set_attr "length" "8")]
++)
++
++(define_insn "*arm_cmpdi_unsigned"
++ [(set (reg:CC_CZ CC_REGNUM)
++ (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
++ (match_operand:DI 1 "arm_di_operand" "rDi")))]
++ "TARGET_ARM"
++ "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1"
++ [(set_attr "conds" "set")
++ (set_attr "length" "8")]
++)
++
++(define_insn "*arm_cmpdi_zero"
++ [(set (reg:CC_Z CC_REGNUM)
++ (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
++ (const_int 0)))
++ (clobber (match_scratch:SI 1 "=r"))]
++ "TARGET_32BIT"
++ "orr%.\\t%1, %Q0, %R0"
++ [(set_attr "conds" "set")]
++)
++
++(define_insn "*thumb_cmpdi_zero"
++ [(set (reg:CC_Z CC_REGNUM)
++ (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
++ (const_int 0)))
++ (clobber (match_scratch:SI 1 "=l"))]
++ "TARGET_THUMB1"
++ "orr\\t%1, %Q0, %R0"
++ [(set_attr "conds" "set")
++ (set_attr "length" "2")]
++)
++
+ ;; Cirrus SF compare instruction
+ (define_insn "*cirrus_cmpsf"
+ [(set (reg:CCFP CC_REGNUM)
+@@ -8183,18 +8257,45 @@
+ operands[2], operands[3])); DONE;"
+ )
+
+-;; this uses the Cirrus DI compare instruction
+ (define_expand "cstoredi4"
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (match_operator:SI 1 "arm_comparison_operator"
+- [(match_operand:DI 2 "cirrus_fp_register" "")
+- (match_operand:DI 3 "cirrus_fp_register" "")]))]
+- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
+- "emit_insn (gen_cstore_cc (operands[0], operands[1],
+- operands[2], operands[3])); DONE;"
++ [(match_operand:DI 2 "cmpdi_operand" "")
++ (match_operand:DI 3 "cmpdi_operand" "")]))]
++ "TARGET_32BIT"
++ "{
++ rtx swap = NULL_RTX;
++ enum rtx_code code = GET_CODE (operands[1]);
++
++ /* We should not have two constants. */
++ gcc_assert (GET_MODE (operands[2]) == DImode
++ || GET_MODE (operands[3]) == DImode);
++
++ /* Flip unimplemented DImode comparisons to a form that
++ arm_gen_compare_reg can handle. */
++ switch (code)
++ {
++ case GT:
++ swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
++ case LE:
++ swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
++ case GTU:
++ swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
++ case LEU:
++ swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
++ default:
++ break;
++ }
++ if (swap)
++ emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
++ operands[2]));
++ else
++ emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
++ operands[3]));
++ DONE;
++ }"
+ )
+
+-
+ (define_expand "cstoresi_eq0_thumb1"
+ [(parallel
+ [(set (match_operand:SI 0 "s_register_operand" "")
+
+=== modified file 'gcc/config/arm/constraints.md'
+--- old/gcc/config/arm/constraints.md 2009-12-07 20:34:53 +0000
++++ new/gcc/config/arm/constraints.md 2010-07-29 16:58:56 +0000
+@@ -29,7 +29,7 @@
+ ;; in Thumb-1 state: I, J, K, L, M, N, O
+
+ ;; The following multi-letter normal constraints have been used:
+-;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv, Dy
++;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv, Dy, Di
+ ;; in Thumb-1 state: Pa, Pb
+ ;; in Thumb-2 state: Ps, Pt
+
+@@ -191,6 +191,13 @@
+ (match_test "TARGET_32BIT && arm_const_double_inline_cost (op) == 4
+ && !(optimize_size || arm_ld_sched)")))
+
++(define_constraint "Di"
++ "@internal
++ In ARM/Thumb-2 state a const_int or const_double where both the high
++ and low SImode words can be generated as immediates in 32-bit instructions."
++ (and (match_code "const_double,const_int")
++ (match_test "TARGET_32BIT && arm_const_double_by_immediates (op)")))
++
+ (define_constraint "Dn"
+ "@internal
+ In ARM/Thumb-2 state a const_vector which can be loaded with a Neon vmov
+
+=== modified file 'gcc/config/arm/predicates.md'
+--- old/gcc/config/arm/predicates.md 2010-07-29 15:59:12 +0000
++++ new/gcc/config/arm/predicates.md 2010-07-29 16:58:56 +0000
+@@ -86,6 +86,12 @@
+ (and (match_code "const_int")
+ (match_test "const_ok_for_arm (INTVAL (op))")))
+
++;; A constant value which fits into two instructions, each taking
++;; an arithmetic constant operand for one of the words.
++(define_predicate "arm_immediate_di_operand"
++ (and (match_code "const_int,const_double")
++ (match_test "arm_const_double_by_immediates (op)")))
++
+ (define_predicate "arm_neg_immediate_operand"
+ (and (match_code "const_int")
+ (match_test "const_ok_for_arm (-INTVAL (op))")))
+@@ -115,6 +121,10 @@
+ (ior (match_operand 0 "arm_rhs_operand")
+ (match_operand 0 "arm_not_immediate_operand")))
+
++(define_predicate "arm_di_operand"
++ (ior (match_operand 0 "s_register_operand")
++ (match_operand 0 "arm_immediate_di_operand")))
++
+ ;; True if the operand is a memory reference which contains an
+ ;; offsettable address.
+ (define_predicate "offsettable_memory_operand"
+@@ -522,4 +532,12 @@
+ (define_predicate "neon_lane_number"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 7")))
++;; Predicates for named expanders that overlap multiple ISAs.
++
++(define_predicate "cmpdi_operand"
++ (if_then_else (match_test "TARGET_HARD_FLOAT && TARGET_MAVERICK")
++ (and (match_test "TARGET_ARM")
++ (match_operand 0 "cirrus_fp_register"))
++ (and (match_test "TARGET_32BIT")
++ (match_operand 0 "arm_di_operand"))))
+
+
+=== added file 'gcc/testsuite/gcc.c-torture/execute/20100416-1.c'
+--- old/gcc/testsuite/gcc.c-torture/execute/20100416-1.c 1970-01-01 00:00:00 +0000
++++ new/gcc/testsuite/gcc.c-torture/execute/20100416-1.c 2010-07-29 16:58:56 +0000
+@@ -0,0 +1,40 @@
++void abort(void);
++
++int
++movegt(int x, int y, long long a)
++{
++ int i;
++ int ret = 0;
++ for (i = 0; i < y; i++)
++ {
++ if (a >= (long long) 0xf000000000000000LL)
++ ret = x;
++ else
++ ret = y;
++ }
++ return ret;
++}
++
++struct test
++{
++ long long val;
++ int ret;
++} tests[] = {
++ { 0xf000000000000000LL, -1 },
++ { 0xefffffffffffffffLL, 1 },
++ { 0xf000000000000001LL, -1 },
++ { 0x0000000000000000LL, -1 },
++ { 0x8000000000000000LL, 1 },
++};
++
++int
++main()
++{
++ int i;
++ for (i = 0; i < sizeof (tests) / sizeof (tests[0]); i++)
++ {
++ if (movegt (-1, 1, tests[i].val) != tests[i].ret)
++ abort ();
++ }
++ return 0;
++}
+