diff options
author | Koen Kooi <koen@dominion.thruhere.net> | 2010-11-02 22:03:58 +0100 |
---|---|---|
committer | Koen Kooi <koen@dominion.thruhere.net> | 2010-11-02 22:12:02 +0100 |
commit | be10a6b1321f250b1034c7d9d0a8ef18b296eef1 (patch) | |
tree | 9249025cbfbfbee4cc430d62b27f75301dd4dfde /recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch | |
parent | 93b28937ac67ba46d65f55637e42552e224aa7e2 (diff) | |
download | meta-openembedded-be10a6b1321f250b1034c7d9d0a8ef18b296eef1.tar.gz |
angstrom-layers: meta-openembedded: replace poky gcc 4.5 sources with OE ones
This needs further investigation, but for now we can get the tested sources into the poky gcc harness
Signed-off-by: Koen Kooi <k-kooi@ti.com>
Diffstat (limited to 'recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch')
-rw-r--r-- | recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch | 675 |
1 files changed, 675 insertions, 0 deletions
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch new file mode 100644 index 0000000000..95907eeb87 --- /dev/null +++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99301.patch | |||
@@ -0,0 +1,675 @@ | |||
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 | --- old/gcc/config/arm/arm-modes.def 2009-06-18 11:24:10 +0000 | ||
41 | +++ new/gcc/config/arm/arm-modes.def 2010-07-29 16:58:56 +0000 | ||
42 | @@ -35,10 +35,16 @@ | ||
43 | CC_NOOVmode should be used with SImode integer equalities. | ||
44 | CC_Zmode should be used if only the Z flag is set correctly | ||
45 | CC_Nmode should be used if only the N (sign) flag is set correctly | ||
46 | + CC_CZmode should be used if only the C and Z flags are correct | ||
47 | + (used for DImode unsigned comparisons). | ||
48 | + CC_NCVmode should be used if only the N, C, and V flags are correct | ||
49 | + (used for DImode signed comparisons). | ||
50 | CCmode should be used otherwise. */ | ||
51 | |||
52 | CC_MODE (CC_NOOV); | ||
53 | CC_MODE (CC_Z); | ||
54 | +CC_MODE (CC_CZ); | ||
55 | +CC_MODE (CC_NCV); | ||
56 | CC_MODE (CC_SWP); | ||
57 | CC_MODE (CCFP); | ||
58 | CC_MODE (CCFPE); | ||
59 | |||
60 | === modified file 'gcc/config/arm/arm-protos.h' | ||
61 | --- old/gcc/config/arm/arm-protos.h 2009-11-11 14:23:03 +0000 | ||
62 | +++ new/gcc/config/arm/arm-protos.h 2010-07-29 16:58:56 +0000 | ||
63 | @@ -49,8 +49,7 @@ | ||
64 | extern int const_ok_for_arm (HOST_WIDE_INT); | ||
65 | extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx, | ||
66 | HOST_WIDE_INT, rtx, rtx, int); | ||
67 | -extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, enum machine_mode, | ||
68 | - rtx *); | ||
69 | +extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *, rtx *); | ||
70 | extern int legitimate_pic_operand_p (rtx); | ||
71 | extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx); | ||
72 | extern rtx legitimize_tls_address (rtx, rtx); | ||
73 | @@ -116,6 +115,7 @@ | ||
74 | extern void arm_reload_out_hi (rtx *); | ||
75 | extern int arm_const_double_inline_cost (rtx); | ||
76 | extern bool arm_const_double_by_parts (rtx); | ||
77 | +extern bool arm_const_double_by_immediates (rtx); | ||
78 | extern const char *fp_immediate_constant (rtx); | ||
79 | extern void arm_emit_call_insn (rtx, rtx); | ||
80 | extern const char *output_call (rtx *); | ||
81 | |||
82 | === modified file 'gcc/config/arm/arm.c' | ||
83 | --- old/gcc/config/arm/arm.c 2010-07-29 15:59:12 +0000 | ||
84 | +++ new/gcc/config/arm/arm.c 2010-07-29 16:58:56 +0000 | ||
85 | @@ -3190,13 +3190,82 @@ | ||
86 | immediate value easier to load. */ | ||
87 | |||
88 | enum rtx_code | ||
89 | -arm_canonicalize_comparison (enum rtx_code code, enum machine_mode mode, | ||
90 | - rtx * op1) | ||
91 | +arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1) | ||
92 | { | ||
93 | - unsigned HOST_WIDE_INT i = INTVAL (*op1); | ||
94 | - unsigned HOST_WIDE_INT maxval; | ||
95 | + enum machine_mode mode; | ||
96 | + unsigned HOST_WIDE_INT i, maxval; | ||
97 | + | ||
98 | + mode = GET_MODE (*op0); | ||
99 | + if (mode == VOIDmode) | ||
100 | + mode = GET_MODE (*op1); | ||
101 | + | ||
102 | maxval = (((unsigned HOST_WIDE_INT) 1) << (GET_MODE_BITSIZE(mode) - 1)) - 1; | ||
103 | |||
104 | + /* For DImode, we have GE/LT/GEU/LTU comparisons. In ARM mode | ||
105 | + we can also use cmp/cmpeq for GTU/LEU. GT/LE must be either | ||
106 | + reversed or (for constant OP1) adjusted to GE/LT. Similarly | ||
107 | + for GTU/LEU in Thumb mode. */ | ||
108 | + if (mode == DImode) | ||
109 | + { | ||
110 | + rtx tem; | ||
111 | + | ||
112 | + /* To keep things simple, always use the Cirrus cfcmp64 if it is | ||
113 | + available. */ | ||
114 | + if (TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK) | ||
115 | + return code; | ||
116 | + | ||
117 | + if (code == GT || code == LE | ||
118 | + || (!TARGET_ARM && (code == GTU || code == LEU))) | ||
119 | + { | ||
120 | + /* Missing comparison. First try to use an available | ||
121 | + comparison. */ | ||
122 | + if (GET_CODE (*op1) == CONST_INT) | ||
123 | + { | ||
124 | + i = INTVAL (*op1); | ||
125 | + switch (code) | ||
126 | + { | ||
127 | + case GT: | ||
128 | + case LE: | ||
129 | + if (i != maxval | ||
130 | + && arm_const_double_by_immediates (GEN_INT (i + 1))) | ||
131 | + { | ||
132 | + *op1 = GEN_INT (i + 1); | ||
133 | + return code == GT ? GE : LT; | ||
134 | + } | ||
135 | + break; | ||
136 | + case GTU: | ||
137 | + case LEU: | ||
138 | + if (i != ~((unsigned HOST_WIDE_INT) 0) | ||
139 | + && arm_const_double_by_immediates (GEN_INT (i + 1))) | ||
140 | + { | ||
141 | + *op1 = GEN_INT (i + 1); | ||
142 | + return code == GTU ? GEU : LTU; | ||
143 | + } | ||
144 | + break; | ||
145 | + default: | ||
146 | + gcc_unreachable (); | ||
147 | + } | ||
148 | + } | ||
149 | + | ||
150 | + /* If that did not work, reverse the condition. */ | ||
151 | + tem = *op0; | ||
152 | + *op0 = *op1; | ||
153 | + *op1 = tem; | ||
154 | + return swap_condition (code); | ||
155 | + } | ||
156 | + | ||
157 | + return code; | ||
158 | + } | ||
159 | + | ||
160 | + /* Comparisons smaller than DImode. Only adjust comparisons against | ||
161 | + an out-of-range constant. */ | ||
162 | + if (GET_CODE (*op1) != CONST_INT | ||
163 | + || const_ok_for_arm (INTVAL (*op1)) | ||
164 | + || const_ok_for_arm (- INTVAL (*op1))) | ||
165 | + return code; | ||
166 | + | ||
167 | + i = INTVAL (*op1); | ||
168 | + | ||
169 | switch (code) | ||
170 | { | ||
171 | case EQ: | ||
172 | @@ -9912,6 +9981,55 @@ | ||
173 | && (rtx_equal_p (XEXP (x, 0), y) || rtx_equal_p (XEXP (x, 1), y))) | ||
174 | return CC_Cmode; | ||
175 | |||
176 | + if (GET_MODE (x) == DImode || GET_MODE (y) == DImode) | ||
177 | + { | ||
178 | + /* To keep things simple, always use the Cirrus cfcmp64 if it is | ||
179 | + available. */ | ||
180 | + if (TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK) | ||
181 | + return CCmode; | ||
182 | + | ||
183 | + switch (op) | ||
184 | + { | ||
185 | + case EQ: | ||
186 | + case NE: | ||
187 | + /* A DImode comparison against zero can be implemented by | ||
188 | + or'ing the two halves together. */ | ||
189 | + if (y == const0_rtx) | ||
190 | + return CC_Zmode; | ||
191 | + | ||
192 | + /* We can do an equality test in three Thumb instructions. */ | ||
193 | + if (!TARGET_ARM) | ||
194 | + return CC_Zmode; | ||
195 | + | ||
196 | + /* FALLTHROUGH */ | ||
197 | + | ||
198 | + case LTU: | ||
199 | + case LEU: | ||
200 | + case GTU: | ||
201 | + case GEU: | ||
202 | + /* DImode unsigned comparisons can be implemented by cmp + | ||
203 | + cmpeq without a scratch register. Not worth doing in | ||
204 | + Thumb-2. */ | ||
205 | + if (TARGET_ARM) | ||
206 | + return CC_CZmode; | ||
207 | + | ||
208 | + /* FALLTHROUGH */ | ||
209 | + | ||
210 | + case LT: | ||
211 | + case LE: | ||
212 | + case GT: | ||
213 | + case GE: | ||
214 | + /* DImode signed and unsigned comparisons can be implemented | ||
215 | + by cmp + sbcs with a scratch register, but that does not | ||
216 | + set the Z flag - we must reverse GT/LE/GTU/LEU. */ | ||
217 | + gcc_assert (op != EQ && op != NE); | ||
218 | + return CC_NCVmode; | ||
219 | + | ||
220 | + default: | ||
221 | + gcc_unreachable (); | ||
222 | + } | ||
223 | + } | ||
224 | + | ||
225 | return CCmode; | ||
226 | } | ||
227 | |||
228 | @@ -9921,10 +10039,39 @@ | ||
229 | rtx | ||
230 | arm_gen_compare_reg (enum rtx_code code, rtx x, rtx y) | ||
231 | { | ||
232 | - enum machine_mode mode = SELECT_CC_MODE (code, x, y); | ||
233 | - rtx cc_reg = gen_rtx_REG (mode, CC_REGNUM); | ||
234 | - | ||
235 | - emit_set_insn (cc_reg, gen_rtx_COMPARE (mode, x, y)); | ||
236 | + enum machine_mode mode; | ||
237 | + rtx cc_reg; | ||
238 | + int dimode_comparison = GET_MODE (x) == DImode || GET_MODE (y) == DImode; | ||
239 | + | ||
240 | + /* We might have X as a constant, Y as a register because of the predicates | ||
241 | + used for cmpdi. If so, force X to a register here. */ | ||
242 | + if (dimode_comparison && !REG_P (x)) | ||
243 | + x = force_reg (DImode, x); | ||
244 | + | ||
245 | + mode = SELECT_CC_MODE (code, x, y); | ||
246 | + cc_reg = gen_rtx_REG (mode, CC_REGNUM); | ||
247 | + | ||
248 | + if (dimode_comparison | ||
249 | + && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) | ||
250 | + && mode != CC_CZmode) | ||
251 | + { | ||
252 | + rtx clobber, set; | ||
253 | + | ||
254 | + /* To compare two non-zero values for equality, XOR them and | ||
255 | + then compare against zero. Not used for ARM mode; there | ||
256 | + CC_CZmode is cheaper. */ | ||
257 | + if (mode == CC_Zmode && y != const0_rtx) | ||
258 | + { | ||
259 | + x = expand_binop (DImode, xor_optab, x, y, NULL_RTX, 0, OPTAB_WIDEN); | ||
260 | + y = const0_rtx; | ||
261 | + } | ||
262 | + /* A scratch register is required. */ | ||
263 | + clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)); | ||
264 | + set = gen_rtx_SET (VOIDmode, cc_reg, gen_rtx_COMPARE (mode, x, y)); | ||
265 | + emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber))); | ||
266 | + } | ||
267 | + else | ||
268 | + emit_set_insn (cc_reg, gen_rtx_COMPARE (mode, x, y)); | ||
269 | |||
270 | return cc_reg; | ||
271 | } | ||
272 | @@ -11253,6 +11400,34 @@ | ||
273 | return false; | ||
274 | } | ||
275 | |||
276 | +/* Return true if it is possible to inline both the high and low parts | ||
277 | + of a 64-bit constant into 32-bit data processing instructions. */ | ||
278 | +bool | ||
279 | +arm_const_double_by_immediates (rtx val) | ||
280 | +{ | ||
281 | + enum machine_mode mode = GET_MODE (val); | ||
282 | + rtx part; | ||
283 | + | ||
284 | + if (mode == VOIDmode) | ||
285 | + mode = DImode; | ||
286 | + | ||
287 | + part = gen_highpart_mode (SImode, mode, val); | ||
288 | + | ||
289 | + gcc_assert (GET_CODE (part) == CONST_INT); | ||
290 | + | ||
291 | + if (!const_ok_for_arm (INTVAL (part))) | ||
292 | + return false; | ||
293 | + | ||
294 | + part = gen_lowpart (SImode, val); | ||
295 | + | ||
296 | + gcc_assert (GET_CODE (part) == CONST_INT); | ||
297 | + | ||
298 | + if (!const_ok_for_arm (INTVAL (part))) | ||
299 | + return false; | ||
300 | + | ||
301 | + return true; | ||
302 | +} | ||
303 | + | ||
304 | /* Scan INSN and note any of its operands that need fixing. | ||
305 | If DO_PUSHES is false we do not actually push any of the fixups | ||
306 | needed. The function returns TRUE if any fixups were needed/pushed. | ||
307 | @@ -15097,8 +15272,18 @@ | ||
308 | the value being loaded is big-wordian or little-wordian. The | ||
309 | order of the two register loads can matter however, if the address | ||
310 | of the memory location is actually held in one of the registers | ||
311 | - being overwritten by the load. */ | ||
312 | + being overwritten by the load. | ||
313 | + | ||
314 | + The 'Q' and 'R' constraints are also available for 64-bit | ||
315 | + constants. */ | ||
316 | case 'Q': | ||
317 | + if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE) | ||
318 | + { | ||
319 | + rtx part = gen_lowpart (SImode, x); | ||
320 | + fprintf (stream, "#" HOST_WIDE_INT_PRINT_DEC, INTVAL (part)); | ||
321 | + return; | ||
322 | + } | ||
323 | + | ||
324 | if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM) | ||
325 | { | ||
326 | output_operand_lossage ("invalid operand for code '%c'", code); | ||
327 | @@ -15109,6 +15294,18 @@ | ||
328 | return; | ||
329 | |||
330 | case 'R': | ||
331 | + if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE) | ||
332 | + { | ||
333 | + enum machine_mode mode = GET_MODE (x); | ||
334 | + rtx part; | ||
335 | + | ||
336 | + if (mode == VOIDmode) | ||
337 | + mode = DImode; | ||
338 | + part = gen_highpart_mode (SImode, mode, x); | ||
339 | + fprintf (stream, "#" HOST_WIDE_INT_PRINT_DEC, INTVAL (part)); | ||
340 | + return; | ||
341 | + } | ||
342 | + | ||
343 | if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM) | ||
344 | { | ||
345 | output_operand_lossage ("invalid operand for code '%c'", code); | ||
346 | @@ -15801,6 +15998,28 @@ | ||
347 | default: gcc_unreachable (); | ||
348 | } | ||
349 | |||
350 | + case CC_CZmode: | ||
351 | + switch (comp_code) | ||
352 | + { | ||
353 | + case NE: return ARM_NE; | ||
354 | + case EQ: return ARM_EQ; | ||
355 | + case GEU: return ARM_CS; | ||
356 | + case GTU: return ARM_HI; | ||
357 | + case LEU: return ARM_LS; | ||
358 | + case LTU: return ARM_CC; | ||
359 | + default: gcc_unreachable (); | ||
360 | + } | ||
361 | + | ||
362 | + case CC_NCVmode: | ||
363 | + switch (comp_code) | ||
364 | + { | ||
365 | + case GE: return ARM_GE; | ||
366 | + case LT: return ARM_LT; | ||
367 | + case GEU: return ARM_CS; | ||
368 | + case LTU: return ARM_CC; | ||
369 | + default: gcc_unreachable (); | ||
370 | + } | ||
371 | + | ||
372 | case CCmode: | ||
373 | switch (comp_code) | ||
374 | { | ||
375 | |||
376 | === modified file 'gcc/config/arm/arm.h' | ||
377 | --- old/gcc/config/arm/arm.h 2009-12-23 16:36:40 +0000 | ||
378 | +++ new/gcc/config/arm/arm.h 2010-07-29 16:58:56 +0000 | ||
379 | @@ -2253,19 +2253,7 @@ | ||
380 | : reverse_condition (code)) | ||
381 | |||
382 | #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \ | ||
383 | - do \ | ||
384 | - { \ | ||
385 | - if (GET_CODE (OP1) == CONST_INT \ | ||
386 | - && ! (const_ok_for_arm (INTVAL (OP1)) \ | ||
387 | - || (const_ok_for_arm (- INTVAL (OP1))))) \ | ||
388 | - { \ | ||
389 | - rtx const_op = OP1; \ | ||
390 | - CODE = arm_canonicalize_comparison ((CODE), GET_MODE (OP0), \ | ||
391 | - &const_op); \ | ||
392 | - OP1 = const_op; \ | ||
393 | - } \ | ||
394 | - } \ | ||
395 | - while (0) | ||
396 | + (CODE) = arm_canonicalize_comparison (CODE, &(OP0), &(OP1)) | ||
397 | |||
398 | /* The arm5 clz instruction returns 32. */ | ||
399 | #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1) | ||
400 | |||
401 | === modified file 'gcc/config/arm/arm.md' | ||
402 | --- old/gcc/config/arm/arm.md 2010-07-29 15:59:12 +0000 | ||
403 | +++ new/gcc/config/arm/arm.md 2010-07-29 16:58:56 +0000 | ||
404 | @@ -6718,17 +6718,45 @@ | ||
405 | operands[3])); DONE;" | ||
406 | ) | ||
407 | |||
408 | -;; this uses the Cirrus DI compare instruction | ||
409 | (define_expand "cbranchdi4" | ||
410 | [(set (pc) (if_then_else | ||
411 | (match_operator 0 "arm_comparison_operator" | ||
412 | - [(match_operand:DI 1 "cirrus_fp_register" "") | ||
413 | - (match_operand:DI 2 "cirrus_fp_register" "")]) | ||
414 | + [(match_operand:DI 1 "cmpdi_operand" "") | ||
415 | + (match_operand:DI 2 "cmpdi_operand" "")]) | ||
416 | (label_ref (match_operand 3 "" "")) | ||
417 | (pc)))] | ||
418 | - "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" | ||
419 | - "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2], | ||
420 | - operands[3])); DONE;" | ||
421 | + "TARGET_32BIT" | ||
422 | + "{ | ||
423 | + rtx swap = NULL_RTX; | ||
424 | + enum rtx_code code = GET_CODE (operands[0]); | ||
425 | + | ||
426 | + /* We should not have two constants. */ | ||
427 | + gcc_assert (GET_MODE (operands[1]) == DImode | ||
428 | + || GET_MODE (operands[2]) == DImode); | ||
429 | + | ||
430 | + /* Flip unimplemented DImode comparisons to a form that | ||
431 | + arm_gen_compare_reg can handle. */ | ||
432 | + switch (code) | ||
433 | + { | ||
434 | + case GT: | ||
435 | + swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break; | ||
436 | + case LE: | ||
437 | + swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break; | ||
438 | + case GTU: | ||
439 | + swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break; | ||
440 | + case LEU: | ||
441 | + swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break; | ||
442 | + default: | ||
443 | + break; | ||
444 | + } | ||
445 | + if (swap) | ||
446 | + emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1], | ||
447 | + operands[3])); | ||
448 | + else | ||
449 | + emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2], | ||
450 | + operands[3])); | ||
451 | + DONE; | ||
452 | + }" | ||
453 | ) | ||
454 | |||
455 | (define_insn "*cbranchsi4_insn" | ||
456 | @@ -7880,6 +7908,52 @@ | ||
457 | (const_string "alu_shift_reg")))] | ||
458 | ) | ||
459 | |||
460 | +;; DImode comparisons. The generic code generates branches that | ||
461 | +;; if-conversion can not reduce to a conditional compare, so we do | ||
462 | +;; that directly. | ||
463 | + | ||
464 | +(define_insn "*arm_cmpdi_insn" | ||
465 | + [(set (reg:CC_NCV CC_REGNUM) | ||
466 | + (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r") | ||
467 | + (match_operand:DI 1 "arm_di_operand" "rDi"))) | ||
468 | + (clobber (match_scratch:SI 2 "=r"))] | ||
469 | + "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)" | ||
470 | + "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1" | ||
471 | + [(set_attr "conds" "set") | ||
472 | + (set_attr "length" "8")] | ||
473 | +) | ||
474 | + | ||
475 | +(define_insn "*arm_cmpdi_unsigned" | ||
476 | + [(set (reg:CC_CZ CC_REGNUM) | ||
477 | + (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r") | ||
478 | + (match_operand:DI 1 "arm_di_operand" "rDi")))] | ||
479 | + "TARGET_ARM" | ||
480 | + "cmp%?\\t%R0, %R1\;cmpeq\\t%Q0, %Q1" | ||
481 | + [(set_attr "conds" "set") | ||
482 | + (set_attr "length" "8")] | ||
483 | +) | ||
484 | + | ||
485 | +(define_insn "*arm_cmpdi_zero" | ||
486 | + [(set (reg:CC_Z CC_REGNUM) | ||
487 | + (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r") | ||
488 | + (const_int 0))) | ||
489 | + (clobber (match_scratch:SI 1 "=r"))] | ||
490 | + "TARGET_32BIT" | ||
491 | + "orr%.\\t%1, %Q0, %R0" | ||
492 | + [(set_attr "conds" "set")] | ||
493 | +) | ||
494 | + | ||
495 | +(define_insn "*thumb_cmpdi_zero" | ||
496 | + [(set (reg:CC_Z CC_REGNUM) | ||
497 | + (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l") | ||
498 | + (const_int 0))) | ||
499 | + (clobber (match_scratch:SI 1 "=l"))] | ||
500 | + "TARGET_THUMB1" | ||
501 | + "orr\\t%1, %Q0, %R0" | ||
502 | + [(set_attr "conds" "set") | ||
503 | + (set_attr "length" "2")] | ||
504 | +) | ||
505 | + | ||
506 | ;; Cirrus SF compare instruction | ||
507 | (define_insn "*cirrus_cmpsf" | ||
508 | [(set (reg:CCFP CC_REGNUM) | ||
509 | @@ -8183,18 +8257,45 @@ | ||
510 | operands[2], operands[3])); DONE;" | ||
511 | ) | ||
512 | |||
513 | -;; this uses the Cirrus DI compare instruction | ||
514 | (define_expand "cstoredi4" | ||
515 | [(set (match_operand:SI 0 "s_register_operand" "") | ||
516 | (match_operator:SI 1 "arm_comparison_operator" | ||
517 | - [(match_operand:DI 2 "cirrus_fp_register" "") | ||
518 | - (match_operand:DI 3 "cirrus_fp_register" "")]))] | ||
519 | - "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK" | ||
520 | - "emit_insn (gen_cstore_cc (operands[0], operands[1], | ||
521 | - operands[2], operands[3])); DONE;" | ||
522 | + [(match_operand:DI 2 "cmpdi_operand" "") | ||
523 | + (match_operand:DI 3 "cmpdi_operand" "")]))] | ||
524 | + "TARGET_32BIT" | ||
525 | + "{ | ||
526 | + rtx swap = NULL_RTX; | ||
527 | + enum rtx_code code = GET_CODE (operands[1]); | ||
528 | + | ||
529 | + /* We should not have two constants. */ | ||
530 | + gcc_assert (GET_MODE (operands[2]) == DImode | ||
531 | + || GET_MODE (operands[3]) == DImode); | ||
532 | + | ||
533 | + /* Flip unimplemented DImode comparisons to a form that | ||
534 | + arm_gen_compare_reg can handle. */ | ||
535 | + switch (code) | ||
536 | + { | ||
537 | + case GT: | ||
538 | + swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break; | ||
539 | + case LE: | ||
540 | + swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break; | ||
541 | + case GTU: | ||
542 | + swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break; | ||
543 | + case LEU: | ||
544 | + swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break; | ||
545 | + default: | ||
546 | + break; | ||
547 | + } | ||
548 | + if (swap) | ||
549 | + emit_insn (gen_cstore_cc (operands[0], swap, operands[3], | ||
550 | + operands[2])); | ||
551 | + else | ||
552 | + emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2], | ||
553 | + operands[3])); | ||
554 | + DONE; | ||
555 | + }" | ||
556 | ) | ||
557 | |||
558 | - | ||
559 | (define_expand "cstoresi_eq0_thumb1" | ||
560 | [(parallel | ||
561 | [(set (match_operand:SI 0 "s_register_operand" "") | ||
562 | |||
563 | === modified file 'gcc/config/arm/constraints.md' | ||
564 | --- old/gcc/config/arm/constraints.md 2009-12-07 20:34:53 +0000 | ||
565 | +++ new/gcc/config/arm/constraints.md 2010-07-29 16:58:56 +0000 | ||
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 | |||
590 | === modified file 'gcc/config/arm/predicates.md' | ||
591 | --- old/gcc/config/arm/predicates.md 2010-07-29 15:59:12 +0000 | ||
592 | +++ new/gcc/config/arm/predicates.md 2010-07-29 16:58:56 +0000 | ||
593 | @@ -86,6 +86,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 | @@ -115,6 +121,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 | @@ -522,4 +532,12 @@ | ||
618 | (define_predicate "neon_lane_number" | ||
619 | (and (match_code "const_int") | ||
620 | (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 7"))) | ||
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 | |||
631 | === added file 'gcc/testsuite/gcc.c-torture/execute/20100416-1.c' | ||
632 | --- old/gcc/testsuite/gcc.c-torture/execute/20100416-1.c 1970-01-01 00:00:00 +0000 | ||
633 | +++ new/gcc/testsuite/gcc.c-torture/execute/20100416-1.c 2010-07-29 16:58:56 +0000 | ||
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 | +} | ||
675 | |||