summaryrefslogtreecommitdiffstats
path: root/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch
diff options
context:
space:
mode:
Diffstat (limited to 'toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch')
-rw-r--r--toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch674
1 files changed, 0 insertions, 674 deletions
diff --git a/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch b/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch
deleted file mode 100644
index 0943130de6..0000000000
--- a/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch
+++ /dev/null
@@ -1,674 +0,0 @@
1 2010-07-02 Daniel Jacobowitz <dan@codesourcery.com>
2 Julian Brown <julian@codesourcery.com>
3 Sandra Loosemore <sandra@codesourcery.com>
4
5 gcc/
6 * config/arm/arm.c (arm_canonicalize_comparison): Canonicalize DImode
7 comparisons. Adjust to take both operands.
8 (arm_select_cc_mode): Handle DImode comparisons.
9 (arm_gen_compare_reg): Generate a scratch register for DImode
10 comparisons which require one. Use xor for Thumb equality checks.
11 (arm_const_double_by_immediates): New.
12 (arm_print_operand): Allow 'Q' and 'R' for constants.
13 (get_arm_condition_code): Handle new CC_CZmode and CC_NCVmode.
14 * config/arm/arm.h (CANONICALIZE_COMPARISON): Always use
15 arm_canonicalize_comparison.
16 * config/arm/arm-modes.def: Add CC_CZmode and CC_NCVmode.
17 * config/arm/arm-protos.h (arm_canonicalize_comparison): Update
18 prototype.
19 (arm_const_double_by_immediates): Declare.
20 * config/arm/constraints.md (Di): New constraint.
21 * config/arm/predicates.md (arm_immediate_di_operand)
22 (arm_di_operand, cmpdi_operand): New.
23 * config/arm/arm.md (cbranchdi4): Handle non-Cirrus also.
24 (*arm_cmpdi_insn, *arm_cmpdi_unsigned)
25 (*arm_cmpdi_zero, *thumb_cmpdi_zero): New insns.
26 (cstoredi4): Handle non-Cirrus also.
27
28 gcc/testsuite/
29 * gcc.c-torture/execute/20100416-1.c: New test case.
30
312010-07-08 Sandra Loosemore <sandra@codesourcery.com>
32
33 Backport from upstream (originally from Sourcery G++ 4.4):
34
35 2010-07-02 Sandra Loosemore <sandra@codesourcery.com>
36
37 gcc/
38
39=== modified file 'gcc/config/arm/arm-modes.def'
40Index: gcc-4.5.3/gcc/config/arm/arm-modes.def
41===================================================================
42--- gcc-4.5.3.orig/gcc/config/arm/arm-modes.def
43+++ gcc-4.5.3/gcc/config/arm/arm-modes.def
44@@ -35,10 +35,16 @@ ADJUST_FLOAT_FORMAT (HF, ((arm_fp16_form
45 CC_NOOVmode should be used with SImode integer equalities.
46 CC_Zmode should be used if only the Z flag is set correctly
47 CC_Nmode should be used if only the N (sign) flag is set correctly
48+ CC_CZmode should be used if only the C and Z flags are correct
49+ (used for DImode unsigned comparisons).
50+ CC_NCVmode should be used if only the N, C, and V flags are correct
51+ (used for DImode signed comparisons).
52 CCmode should be used otherwise. */
53
54 CC_MODE (CC_NOOV);
55 CC_MODE (CC_Z);
56+CC_MODE (CC_CZ);
57+CC_MODE (CC_NCV);
58 CC_MODE (CC_SWP);
59 CC_MODE (CCFP);
60 CC_MODE (CCFPE);
61Index: gcc-4.5.3/gcc/config/arm/arm-protos.h
62===================================================================
63--- gcc-4.5.3.orig/gcc/config/arm/arm-protos.h
64+++ gcc-4.5.3/gcc/config/arm/arm-protos.h
65@@ -49,8 +49,7 @@ extern int arm_hard_regno_mode_ok (unsig
66 extern int const_ok_for_arm (HOST_WIDE_INT);
67 extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
68 HOST_WIDE_INT, rtx, rtx, int);
69-extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, enum machine_mode,
70- rtx *);
71+extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *, rtx *);
72 extern int legitimate_pic_operand_p (rtx);
73 extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
74 extern rtx legitimize_tls_address (rtx, rtx);
75@@ -116,6 +115,7 @@ extern void arm_reload_in_hi (rtx *);
76 extern void arm_reload_out_hi (rtx *);
77 extern int arm_const_double_inline_cost (rtx);
78 extern bool arm_const_double_by_parts (rtx);
79+extern bool arm_const_double_by_immediates (rtx);
80 extern const char *fp_immediate_constant (rtx);
81 extern void arm_emit_call_insn (rtx, rtx);
82 extern const char *output_call (rtx *);
83Index: gcc-4.5.3/gcc/config/arm/arm.c
84===================================================================
85--- gcc-4.5.3.orig/gcc/config/arm/arm.c
86+++ gcc-4.5.3/gcc/config/arm/arm.c
87@@ -3191,13 +3191,82 @@ arm_gen_constant (enum rtx_code code, en
88 immediate value easier to load. */
89
90 enum rtx_code
91-arm_canonicalize_comparison (enum rtx_code code, enum machine_mode mode,
92- rtx * op1)
93+arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1)
94 {
95- unsigned HOST_WIDE_INT i = INTVAL (*op1);
96- unsigned HOST_WIDE_INT maxval;
97+ enum machine_mode mode;
98+ unsigned HOST_WIDE_INT i, maxval;
99+
100+ mode = GET_MODE (*op0);
101+ if (mode == VOIDmode)
102+ mode = GET_MODE (*op1);
103+
104 maxval = (((unsigned HOST_WIDE_INT) 1) << (GET_MODE_BITSIZE(mode) - 1)) - 1;
105
106+ /* For DImode, we have GE/LT/GEU/LTU comparisons. In ARM mode
107+ we can also use cmp/cmpeq for GTU/LEU. GT/LE must be either
108+ reversed or (for constant OP1) adjusted to GE/LT. Similarly
109+ for GTU/LEU in Thumb mode. */
110+ if (mode == DImode)
111+ {
112+ rtx tem;
113+
114+ /* To keep things simple, always use the Cirrus cfcmp64 if it is
115+ available. */
116+ if (TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK)
117+ return code;
118+
119+ if (code == GT || code == LE
120+ || (!TARGET_ARM && (code == GTU || code == LEU)))
121+ {
122+ /* Missing comparison. First try to use an available
123+ comparison. */
124+ if (GET_CODE (*op1) == CONST_INT)
125+ {
126+ i = INTVAL (*op1);
127+ switch (code)
128+ {
129+ case GT:
130+ case LE:
131+ if (i != maxval
132+ && arm_const_double_by_immediates (GEN_INT (i + 1)))
133+ {
134+ *op1 = GEN_INT (i + 1);
135+ return code == GT ? GE : LT;
136+ }
137+ break;
138+ case GTU:
139+ case LEU:
140+ if (i != ~((unsigned HOST_WIDE_INT) 0)
141+ && arm_const_double_by_immediates (GEN_INT (i + 1)))
142+ {
143+ *op1 = GEN_INT (i + 1);
144+ return code == GTU ? GEU : LTU;
145+ }
146+ break;
147+ default:
148+ gcc_unreachable ();
149+ }
150+ }
151+
152+ /* If that did not work, reverse the condition. */
153+ tem = *op0;
154+ *op0 = *op1;
155+ *op1 = tem;
156+ return swap_condition (code);
157+ }
158+
159+ return code;
160+ }
161+
162+ /* Comparisons smaller than DImode. Only adjust comparisons against
163+ an out-of-range constant. */
164+ if (GET_CODE (*op1) != CONST_INT
165+ || const_ok_for_arm (INTVAL (*op1))
166+ || const_ok_for_arm (- INTVAL (*op1)))
167+ return code;
168+
169+ i = INTVAL (*op1);
170+
171 switch (code)
172 {
173 case EQ:
174@@ -9913,6 +9982,55 @@ arm_select_cc_mode (enum rtx_code op, rt
175 && (rtx_equal_p (XEXP (x, 0), y) || rtx_equal_p (XEXP (x, 1), y)))
176 return CC_Cmode;
177
178+ if (GET_MODE (x) == DImode || GET_MODE (y) == DImode)
179+ {
180+ /* To keep things simple, always use the Cirrus cfcmp64 if it is
181+ available. */
182+ if (TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK)
183+ return CCmode;
184+
185+ switch (op)
186+ {
187+ case EQ:
188+ case NE:
189+ /* A DImode comparison against zero can be implemented by
190+ or'ing the two halves together. */
191+ if (y == const0_rtx)
192+ return CC_Zmode;
193+
194+ /* We can do an equality test in three Thumb instructions. */
195+ if (!TARGET_ARM)
196+ return CC_Zmode;
197+
198+ /* FALLTHROUGH */
199+
200+ case LTU:
201+ case LEU:
202+ case GTU:
203+ case GEU:
204+ /* DImode unsigned comparisons can be implemented by cmp +
205+ cmpeq without a scratch register. Not worth doing in
206+ Thumb-2. */
207+ if (TARGET_ARM)
208+ return CC_CZmode;
209+
210+ /* FALLTHROUGH */
211+
212+ case LT:
213+ case LE:
214+ case GT:
215+ case GE:
216+ /* DImode signed and unsigned comparisons can be implemented
217+ by cmp + sbcs with a scratch register, but that does not
218+ set the Z flag - we must reverse GT/LE/GTU/LEU. */
219+ gcc_assert (op != EQ && op != NE);
220+ return CC_NCVmode;
221+
222+ default:
223+ gcc_unreachable ();
224+ }
225+ }
226+
227 return CCmode;
228 }
229
230@@ -9922,10 +10040,39 @@ arm_select_cc_mode (enum rtx_code op, rt
231 rtx
232 arm_gen_compare_reg (enum rtx_code code, rtx x, rtx y)
233 {
234- enum machine_mode mode = SELECT_CC_MODE (code, x, y);
235- rtx cc_reg = gen_rtx_REG (mode, CC_REGNUM);
236+ enum machine_mode mode;
237+ rtx cc_reg;
238+ int dimode_comparison = GET_MODE (x) == DImode || GET_MODE (y) == DImode;
239
240- emit_set_insn (cc_reg, gen_rtx_COMPARE (mode, x, y));
241+ /* We might have X as a constant, Y as a register because of the predicates
242+ used for cmpdi. If so, force X to a register here. */
243+ if (dimode_comparison && !REG_P (x))
244+ x = force_reg (DImode, x);
245+
246+ mode = SELECT_CC_MODE (code, x, y);
247+ cc_reg = gen_rtx_REG (mode, CC_REGNUM);
248+
249+ if (dimode_comparison
250+ && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
251+ && mode != CC_CZmode)
252+ {
253+ rtx clobber, set;
254+
255+ /* To compare two non-zero values for equality, XOR them and
256+ then compare against zero. Not used for ARM mode; there
257+ CC_CZmode is cheaper. */
258+ if (mode == CC_Zmode && y != const0_rtx)
259+ {
260+ x = expand_binop (DImode, xor_optab, x, y, NULL_RTX, 0, OPTAB_WIDEN);
261+ y = const0_rtx;
262+ }
263+ /* A scratch register is required. */
264+ clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode));
265+ set = gen_rtx_SET (VOIDmode, cc_reg, gen_rtx_COMPARE (mode, x, y));
266+ emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber)));
267+ }
268+ else
269+ emit_set_insn (cc_reg, gen_rtx_COMPARE (mode, x, y));
270
271 return cc_reg;
272 }
273@@ -11254,6 +11401,34 @@ arm_const_double_by_parts (rtx val)
274 return false;
275 }
276
277+/* Return true if it is possible to inline both the high and low parts
278+ of a 64-bit constant into 32-bit data processing instructions. */
279+bool
280+arm_const_double_by_immediates (rtx val)
281+{
282+ enum machine_mode mode = GET_MODE (val);
283+ rtx part;
284+
285+ if (mode == VOIDmode)
286+ mode = DImode;
287+
288+ part = gen_highpart_mode (SImode, mode, val);
289+
290+ gcc_assert (GET_CODE (part) == CONST_INT);
291+
292+ if (!const_ok_for_arm (INTVAL (part)))
293+ return false;
294+
295+ part = gen_lowpart (SImode, val);
296+
297+ gcc_assert (GET_CODE (part) == CONST_INT);
298+
299+ if (!const_ok_for_arm (INTVAL (part)))
300+ return false;
301+
302+ return true;
303+}
304+
305 /* Scan INSN and note any of its operands that need fixing.
306 If DO_PUSHES is false we do not actually push any of the fixups
307 needed. The function returns TRUE if any fixups were needed/pushed.
308@@ -15150,8 +15325,18 @@ arm_print_operand (FILE *stream, rtx x,
309 the value being loaded is big-wordian or little-wordian. The
310 order of the two register loads can matter however, if the address
311 of the memory location is actually held in one of the registers
312- being overwritten by the load. */
313+ being overwritten by the load.
314+
315+ The 'Q' and 'R' constraints are also available for 64-bit
316+ constants. */
317 case 'Q':
318+ if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
319+ {
320+ rtx part = gen_lowpart (SImode, x);
321+ fprintf (stream, "#" HOST_WIDE_INT_PRINT_DEC, INTVAL (part));
322+ return;
323+ }
324+
325 if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM)
326 {
327 output_operand_lossage ("invalid operand for code '%c'", code);
328@@ -15162,6 +15347,18 @@ arm_print_operand (FILE *stream, rtx x,
329 return;
330
331 case 'R':
332+ if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
333+ {
334+ enum machine_mode mode = GET_MODE (x);
335+ rtx part;
336+
337+ if (mode == VOIDmode)
338+ mode = DImode;
339+ part = gen_highpart_mode (SImode, mode, x);
340+ fprintf (stream, "#" HOST_WIDE_INT_PRINT_DEC, INTVAL (part));
341+ return;
342+ }
343+
344 if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM)
345 {
346 output_operand_lossage ("invalid operand for code '%c'", code);
347@@ -15854,6 +16051,28 @@ get_arm_condition_code (rtx comparison)
348 default: gcc_unreachable ();
349 }
350
351+ case CC_CZmode:
352+ switch (comp_code)
353+ {
354+ case NE: return ARM_NE;
355+ case EQ: return ARM_EQ;
356+ case GEU: return ARM_CS;
357+ case GTU: return ARM_HI;
358+ case LEU: return ARM_LS;
359+ case LTU: return ARM_CC;
360+ default: gcc_unreachable ();
361+ }
362+
363+ case CC_NCVmode:
364+ switch (comp_code)
365+ {
366+ case GE: return ARM_GE;
367+ case LT: return ARM_LT;
368+ case GEU: return ARM_CS;
369+ case LTU: return ARM_CC;
370+ default: gcc_unreachable ();
371+ }
372+
373 case CCmode:
374 switch (comp_code)
375 {
376Index: gcc-4.5.3/gcc/config/arm/arm.h
377===================================================================
378--- gcc-4.5.3.orig/gcc/config/arm/arm.h
379+++ gcc-4.5.3/gcc/config/arm/arm.h
380@@ -2253,19 +2253,7 @@ extern int making_const_table;
381 : reverse_condition (code))
382
383 #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
384- do \
385- { \
386- if (GET_CODE (OP1) == CONST_INT \
387- && ! (const_ok_for_arm (INTVAL (OP1)) \
388- || (const_ok_for_arm (- INTVAL (OP1))))) \
389- { \
390- rtx const_op = OP1; \
391- CODE = arm_canonicalize_comparison ((CODE), GET_MODE (OP0), \
392- &const_op); \
393- OP1 = const_op; \
394- } \
395- } \
396- while (0)
397+ (CODE) = arm_canonicalize_comparison (CODE, &(OP0), &(OP1))
398
399 /* The arm5 clz instruction returns 32. */
400 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1)
401Index: gcc-4.5.3/gcc/config/arm/arm.md
402===================================================================
403--- gcc-4.5.3.orig/gcc/config/arm/arm.md
404+++ gcc-4.5.3/gcc/config/arm/arm.md
405@@ -6718,17 +6718,45 @@
406 operands[3])); DONE;"
407 )
408
409-;; this uses the Cirrus DI compare instruction
410 (define_expand "cbranchdi4"
411 [(set (pc) (if_then_else
412 (match_operator 0 "arm_comparison_operator"
413- [(match_operand:DI 1 "cirrus_fp_register" "")
414- (match_operand:DI 2 "cirrus_fp_register" "")])
415+ [(match_operand:DI 1 "cmpdi_operand" "")
416+ (match_operand:DI 2 "cmpdi_operand" "")])
417 (label_ref (match_operand 3 "" ""))
418 (pc)))]
419- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
420- "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
421- operands[3])); DONE;"
422+ "TARGET_32BIT"
423+ "{
424+ rtx swap = NULL_RTX;
425+ enum rtx_code code = GET_CODE (operands[0]);
426+
427+ /* We should not have two constants. */
428+ gcc_assert (GET_MODE (operands[1]) == DImode
429+ || GET_MODE (operands[2]) == DImode);
430+
431+ /* Flip unimplemented DImode comparisons to a form that
432+ arm_gen_compare_reg can handle. */
433+ switch (code)
434+ {
435+ case GT:
436+ swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
437+ case LE:
438+ swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
439+ case GTU:
440+ swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
441+ case LEU:
442+ swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
443+ default:
444+ break;
445+ }
446+ if (swap)
447+ emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
448+ operands[3]));
449+ else
450+ emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
451+ operands[3]));
452+ DONE;
453+ }"
454 )
455
456 (define_insn "*cbranchsi4_insn"
457@@ -7880,6 +7908,52 @@
458 (const_string "alu_shift_reg")))]
459 )
460
461+;; DImode comparisons. The generic code generates branches that
462+;; if-conversion can not reduce to a conditional compare, so we do
463+;; that directly.
464+
465+(define_insn "*arm_cmpdi_insn"
466+ [(set (reg:CC_NCV CC_REGNUM)
467+ (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
468+ (match_operand:DI 1 "arm_di_operand" "rDi")))
469+ (clobber (match_scratch:SI 2 "=r"))]
470+ "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
471+ "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
472+ [(set_attr "conds" "set")
473+ (set_attr "length" "8")]
474+)
475+
476+(define_insn "*arm_cmpdi_unsigned"
477+ [(set (reg:CC_CZ CC_REGNUM)
478+ (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
479+ (match_operand:DI 1 "arm_di_operand" "rDi")))]
480+ "TARGET_ARM"
481+ "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1"
482+ [(set_attr "conds" "set")
483+ (set_attr "length" "8")]
484+)
485+
486+(define_insn "*arm_cmpdi_zero"
487+ [(set (reg:CC_Z CC_REGNUM)
488+ (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
489+ (const_int 0)))
490+ (clobber (match_scratch:SI 1 "=r"))]
491+ "TARGET_32BIT"
492+ "orr%.\\t%1, %Q0, %R0"
493+ [(set_attr "conds" "set")]
494+)
495+
496+(define_insn "*thumb_cmpdi_zero"
497+ [(set (reg:CC_Z CC_REGNUM)
498+ (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
499+ (const_int 0)))
500+ (clobber (match_scratch:SI 1 "=l"))]
501+ "TARGET_THUMB1"
502+ "orr\\t%1, %Q0, %R0"
503+ [(set_attr "conds" "set")
504+ (set_attr "length" "2")]
505+)
506+
507 ;; Cirrus SF compare instruction
508 (define_insn "*cirrus_cmpsf"
509 [(set (reg:CCFP CC_REGNUM)
510@@ -8183,17 +8257,44 @@
511 operands[2], operands[3])); DONE;"
512 )
513
514-;; this uses the Cirrus DI compare instruction
515 (define_expand "cstoredi4"
516 [(set (match_operand:SI 0 "s_register_operand" "")
517 (match_operator:SI 1 "arm_comparison_operator"
518- [(match_operand:DI 2 "cirrus_fp_register" "")
519- (match_operand:DI 3 "cirrus_fp_register" "")]))]
520- "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
521- "emit_insn (gen_cstore_cc (operands[0], operands[1],
522- operands[2], operands[3])); DONE;"
523-)
524+ [(match_operand:DI 2 "cmpdi_operand" "")
525+ (match_operand:DI 3 "cmpdi_operand" "")]))]
526+ "TARGET_32BIT"
527+ "{
528+ rtx swap = NULL_RTX;
529+ enum rtx_code code = GET_CODE (operands[1]);
530
531+ /* We should not have two constants. */
532+ gcc_assert (GET_MODE (operands[2]) == DImode
533+ || GET_MODE (operands[3]) == DImode);
534+
535+ /* Flip unimplemented DImode comparisons to a form that
536+ arm_gen_compare_reg can handle. */
537+ switch (code)
538+ {
539+ case GT:
540+ swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
541+ case LE:
542+ swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
543+ case GTU:
544+ swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
545+ case LEU:
546+ swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
547+ default:
548+ break;
549+ }
550+ if (swap)
551+ emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
552+ operands[2]));
553+ else
554+ emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
555+ operands[3]));
556+ DONE;
557+ }"
558+)
559
560 (define_expand "cstoresi_eq0_thumb1"
561 [(parallel
562Index: gcc-4.5.3/gcc/config/arm/constraints.md
563===================================================================
564--- gcc-4.5.3.orig/gcc/config/arm/constraints.md
565+++ gcc-4.5.3/gcc/config/arm/constraints.md
566@@ -29,7 +29,7 @@
567 ;; in Thumb-1 state: I, J, K, L, M, N, O
568
569 ;; The following multi-letter normal constraints have been used:
570-;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv, Dy
571+;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv, Dy, Di
572 ;; in Thumb-1 state: Pa, Pb
573 ;; in Thumb-2 state: Ps, Pt
574
575@@ -191,6 +191,13 @@
576 (match_test "TARGET_32BIT && arm_const_double_inline_cost (op) == 4
577 && !(optimize_size || arm_ld_sched)")))
578
579+(define_constraint "Di"
580+ "@internal
581+ In ARM/Thumb-2 state a const_int or const_double where both the high
582+ and low SImode words can be generated as immediates in 32-bit instructions."
583+ (and (match_code "const_double,const_int")
584+ (match_test "TARGET_32BIT && arm_const_double_by_immediates (op)")))
585+
586 (define_constraint "Dn"
587 "@internal
588 In ARM/Thumb-2 state a const_vector which can be loaded with a Neon vmov
589Index: gcc-4.5.3/gcc/config/arm/predicates.md
590===================================================================
591--- gcc-4.5.3.orig/gcc/config/arm/predicates.md
592+++ gcc-4.5.3/gcc/config/arm/predicates.md
593@@ -101,6 +101,12 @@
594 (and (match_code "const_int")
595 (match_test "const_ok_for_arm (INTVAL (op))")))
596
597+;; A constant value which fits into two instructions, each taking
598+;; an arithmetic constant operand for one of the words.
599+(define_predicate "arm_immediate_di_operand"
600+ (and (match_code "const_int,const_double")
601+ (match_test "arm_const_double_by_immediates (op)")))
602+
603 (define_predicate "arm_neg_immediate_operand"
604 (and (match_code "const_int")
605 (match_test "const_ok_for_arm (-INTVAL (op))")))
606@@ -130,6 +136,10 @@
607 (ior (match_operand 0 "arm_rhs_operand")
608 (match_operand 0 "arm_not_immediate_operand")))
609
610+(define_predicate "arm_di_operand"
611+ (ior (match_operand 0 "s_register_operand")
612+ (match_operand 0 "arm_immediate_di_operand")))
613+
614 ;; True if the operand is a memory reference which contains an
615 ;; offsettable address.
616 (define_predicate "offsettable_memory_operand"
617@@ -538,3 +548,12 @@
618 (and (match_code "const_int")
619 (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 15")))
620
621+;; Predicates for named expanders that overlap multiple ISAs.
622+
623+(define_predicate "cmpdi_operand"
624+ (if_then_else (match_test "TARGET_HARD_FLOAT && TARGET_MAVERICK")
625+ (and (match_test "TARGET_ARM")
626+ (match_operand 0 "cirrus_fp_register"))
627+ (and (match_test "TARGET_32BIT")
628+ (match_operand 0 "arm_di_operand"))))
629+
630Index: gcc-4.5.3/gcc/testsuite/gcc.c-torture/execute/20100416-1.c
631===================================================================
632--- /dev/null
633+++ gcc-4.5.3/gcc/testsuite/gcc.c-torture/execute/20100416-1.c
634@@ -0,0 +1,40 @@
635+void abort(void);
636+
637+int
638+movegt(int x, int y, long long a)
639+{
640+ int i;
641+ int ret = 0;
642+ for (i = 0; i < y; i++)
643+ {
644+ if (a >= (long long) 0xf000000000000000LL)
645+ ret = x;
646+ else
647+ ret = y;
648+ }
649+ return ret;
650+}
651+
652+struct test
653+{
654+ long long val;
655+ int ret;
656+} tests[] = {
657+ { 0xf000000000000000LL, -1 },
658+ { 0xefffffffffffffffLL, 1 },
659+ { 0xf000000000000001LL, -1 },
660+ { 0x0000000000000000LL, -1 },
661+ { 0x8000000000000000LL, 1 },
662+};
663+
664+int
665+main()
666+{
667+ int i;
668+ for (i = 0; i < sizeof (tests) / sizeof (tests[0]); i++)
669+ {
670+ if (movegt (-1, 1, tests[i].val) != tests[i].ret)
671+ abort ();
672+ }
673+ return 0;
674+}