diff options
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.patch | 674 |
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 | |||
31 | 2010-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' | ||
40 | Index: 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); | ||
61 | Index: 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 *); | ||
83 | Index: 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 | { | ||
376 | Index: 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) | ||
401 | Index: 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 | ||
562 | Index: 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 | ||
589 | Index: 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 | + | ||
630 | Index: 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 | +} | ||