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 | |||
