diff options
Diffstat (limited to 'contrib/gcc/config/arm/arm.md')
-rw-r--r-- | contrib/gcc/config/arm/arm.md | 321 |
1 files changed, 137 insertions, 184 deletions
diff --git a/contrib/gcc/config/arm/arm.md b/contrib/gcc/config/arm/arm.md index 5180c75..0e60712 100644 --- a/contrib/gcc/config/arm/arm.md +++ b/contrib/gcc/config/arm/arm.md @@ -59,7 +59,11 @@ (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic ; usage, that is, we will add the pic_register ; value to it before trying to dereference it. - (UNSPEC_PRLG_STK 4) ; A special barrier that prevents frame accesses + (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the + ; GLOBAL_OFFSET_TABLE. The operation is fully + ; described by the RTL but must be wrapped to + ; prevent combine from trying to rip it apart. + (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses ; being scheduled before the stack adjustment insn. (UNSPEC_CLZ 5) ; `clz' instruction, count leading zeros (SImode): ; operand 0 is the result, @@ -69,6 +73,7 @@ ; instructions setting registers for EH handling ; and stack frame generation. Operand 0 is the ; register to "use". + (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode. ] ) @@ -179,7 +184,7 @@ (const_string "normal")) ; Load scheduling, set from the arm_ld_sched variable -; initialised by arm_override_options() +; initialized by arm_override_options() (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched"))) ; condition codes: this one is used by final_prescan_insn to speed up @@ -600,10 +605,10 @@ ;; Reloading and elimination of the frame pointer can ;; sometimes cause this optimization to be missed. (define_peephole2 - [(set (match_operand:SI 0 "register_operand" "=l") - (match_operand:SI 1 "const_int_operand" "M")) + [(set (match_operand:SI 0 "register_operand" "") + (match_operand:SI 1 "const_int_operand" "")) (set (match_dup 0) - (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))] + (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))] "TARGET_THUMB && REGNO (operands[2]) == STACK_POINTER_REGNUM && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024 @@ -1857,9 +1862,9 @@ ;;; ??? This pattern is bogus. If operand3 has bits outside the range ;;; represented by the bitfield, then this will produce incorrect results. ;;; Somewhere, the value needs to be truncated. On targets like the m68k, -;;; which have a real bitfield insert instruction, the truncation happens -;;; in the bitfield insert instruction itself. Since arm does not have a -;;; bitfield insert instruction, we would have to emit code here to truncate +;;; which have a real bit-field insert instruction, the truncation happens +;;; in the bit-field insert instruction itself. Since arm does not have a +;;; bit-field insert instruction, we would have to emit code here to truncate ;;; the value before we insert. This loses some of the advantage of having ;;; this insv pattern, so this pattern needs to be reevalutated. @@ -1867,7 +1872,7 @@ [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "") (match_operand:SI 1 "general_operand" "") (match_operand:SI 2 "general_operand" "")) - (match_operand:SI 3 "nonmemory_operand" ""))] + (match_operand:SI 3 "reg_or_int_operand" ""))] "TARGET_ARM" " { @@ -2035,7 +2040,7 @@ "TARGET_ARM && reload_completed && operands[0] != operands[1]" - [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2))) + [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1))) (set (match_dup 3) (match_dup 4))] " { @@ -2052,11 +2057,11 @@ [(set (match_operand:DI 0 "s_register_operand" "=&r,&r") (and:DI (not:DI (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r"))) - (match_operand:DI 1 "s_register_operand" "?r,0")))] + (match_operand:DI 1 "s_register_operand" "0,r")))] "TARGET_ARM" "#" "TARGET_ARM && reload_completed" - [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2))) + [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1))) (set (match_dup 3) (and:SI (not:SI (ashiftrt:SI (match_dup 2) (const_int 31))) (match_dup 4)))] @@ -2339,11 +2344,11 @@ ; insns. (define_split - [(set (match_operand:SI 0 "s_register_operand" "=r") - (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r")) - (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI"))) - (match_operand:SI 3 "arm_rhs_operand" "rI"))) - (clobber (match_operand:SI 4 "s_register_operand" "=r"))] + [(set (match_operand:SI 0 "s_register_operand" "") + (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "")) + (not:SI (match_operand:SI 2 "arm_rhs_operand" ""))) + (match_operand:SI 3 "arm_rhs_operand" ""))) + (clobber (match_operand:SI 4 "s_register_operand" ""))] "TARGET_ARM" [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2)) (not:SI (match_dup 3)))) @@ -3913,7 +3918,7 @@ ;; DONE; ;;}") -;; Recognise garbage generated above. +;; Recognize garbage generated above. ;;(define_insn "" ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m") @@ -4129,6 +4134,7 @@ if ((val & (mask << i)) == val) break; + /* Shouldn't happen, but we don't want to split if the shift is zero. */ if (i == 0) FAIL; @@ -4200,7 +4206,9 @@ (define_insn "pic_add_dot_plus_four" [(set (match_operand:SI 0 "register_operand" "+r") - (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4))))) + (unspec:SI [(plus:SI (match_dup 0) + (const (plus:SI (pc) (const_int 4))))] + UNSPEC_PIC_BASE)) (use (label_ref (match_operand 1 "" "")))] "TARGET_THUMB && flag_pic" "* @@ -4213,7 +4221,9 @@ (define_insn "pic_add_dot_plus_eight" [(set (match_operand:SI 0 "register_operand" "+r") - (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8))))) + (unspec:SI [(plus:SI (match_dup 0) + (const (plus:SI (pc) (const_int 8))))] + UNSPEC_PIC_BASE)) (use (label_ref (match_operand 1 "" "")))] "TARGET_ARM && flag_pic" "* @@ -4417,6 +4427,14 @@ emit_insn (gen_movsi (reg, GEN_INT (val))); operands[1] = gen_lowpart (HImode, reg); } + else if (arm_arch4 && !no_new_pseudos && optimize > 0 + && GET_CODE (operands[1]) == MEM) + { + rtx reg = gen_reg_rtx (SImode); + + emit_insn (gen_zero_extendhisi2 (reg, operands[1])); + operands[1] = gen_lowpart (HImode, reg); + } else if (!arm_arch4) { /* Note: We do not have to worry about TARGET_MMU_TRAPS @@ -4673,7 +4691,7 @@ " ) -;; Pattern to recognise insn generated default case above +;; Pattern to recognize insn generated default case above (define_insn "*movhi_insn_arch4" [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r") (match_operand:HI 1 "general_operand" "rI,K,r,m"))] @@ -4814,9 +4832,16 @@ emit_insn (gen_movsi (reg, operands[1])); operands[1] = gen_lowpart (QImode, reg); } - if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (QImode, operands[1]); - } + if (GET_CODE (operands[1]) == MEM && optimize > 0) + { + rtx reg = gen_reg_rtx (SImode); + + emit_insn (gen_zero_extendqisi2 (reg, operands[1])); + operands[1] = gen_lowpart (QImode, reg); + } + if (GET_CODE (operands[0]) == MEM) + operands[1] = force_reg (QImode, operands[1]); + } } else /* TARGET_THUMB */ { @@ -6014,7 +6039,7 @@ if (arm_ccfsm_state != 0) abort (); - return \"bvs\\t%l0;beq\\t%l0\"; + return \"bvs\\t%l0\;beq\\t%l0\"; " [(set_attr "conds" "jump_clob") (set_attr "length" "8")] @@ -6031,7 +6056,7 @@ if (arm_ccfsm_state != 0) abort (); - return \"bmi\\t%l0;bgt\\t%l0\"; + return \"bmi\\t%l0\;bgt\\t%l0\"; " [(set_attr "conds" "jump_clob") (set_attr "length" "8")] @@ -6066,7 +6091,7 @@ if (arm_ccfsm_state != 0) abort (); - return \"bmi\\t%l0;bgt\\t%l0\"; + return \"bmi\\t%l0\;bgt\\t%l0\"; " [(set_attr "conds" "jump_clob") (set_attr "length" "8")] @@ -6083,7 +6108,7 @@ if (arm_ccfsm_state != 0) abort (); - return \"bvs\\t%l0;beq\\t%l0\"; + return \"bvs\\t%l0\;beq\\t%l0\"; " [(set_attr "conds" "jump_clob") (set_attr "length" "8")] @@ -6288,8 +6313,12 @@ " { enum rtx_code code = GET_CODE (operands[1]); - rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); + rtx ccreg; + + if (code == UNEQ || code == LTGT) + FAIL; + ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); }" ) @@ -6305,6 +6334,9 @@ enum rtx_code code = GET_CODE (operands[1]); rtx ccreg; + if (code == UNEQ || code == LTGT) + FAIL; + /* When compiling for SOFT_FLOAT, ensure both arms are in registers. Otherwise, ensure it is a valid FP add operand */ if ((!TARGET_HARD_FLOAT) @@ -6325,8 +6357,12 @@ " { enum rtx_code code = GET_CODE (operands[1]); - rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); + rtx ccreg; + if (code == UNEQ || code == LTGT) + FAIL; + + ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1); operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx); }" ) @@ -6665,8 +6701,8 @@ (define_expand "sibcall" [(parallel [(call (match_operand 0 "memory_operand" "") (match_operand 1 "general_operand" "")) - (use (match_operand 2 "" "")) - (use (reg:SI LR_REGNUM))])] + (return) + (use (match_operand 2 "" ""))])] "TARGET_ARM" " { @@ -6679,8 +6715,8 @@ [(parallel [(set (match_operand 0 "register_operand" "") (call (match_operand 1 "memory_operand" "") (match_operand 2 "general_operand" ""))) - (use (match_operand 3 "" "")) - (use (reg:SI LR_REGNUM))])] + (return) + (use (match_operand 3 "" ""))])] "TARGET_ARM" " { @@ -6692,8 +6728,8 @@ (define_insn "*sibcall_insn" [(call (mem:SI (match_operand:SI 0 "" "X")) (match_operand 1 "" "")) - (use (match_operand 2 "" "")) - (use (reg:SI LR_REGNUM))] + (return) + (use (match_operand 2 "" ""))] "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF" "* return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\"; @@ -6705,8 +6741,8 @@ [(set (match_operand 0 "s_register_operand" "=r,f") (call (mem:SI (match_operand:SI 1 "" "X,X")) (match_operand 2 "" ""))) - (use (match_operand 3 "" "")) - (use (reg:SI LR_REGNUM))] + (return) + (use (match_operand 3 "" ""))] "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF" "* return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\"; @@ -6725,7 +6761,7 @@ arm_ccfsm_state += 2; return \"\"; } - return output_return_instruction (NULL, TRUE, FALSE); + return output_return_instruction (const_true_rtx, TRUE, FALSE); }" [(set_attr "type" "load") (set_attr "predicable" "yes")] @@ -6771,6 +6807,33 @@ (set_attr "type" "load")] ) +;; Generate a sequence of instructions to determine if the processor is +;; in 26-bit or 32-bit mode, and return the appropriate return address +;; mask. + +(define_expand "return_addr_mask" + [(set (match_dup 1) + (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH) + (const_int 0))) + (set (match_operand:SI 0 "s_register_operand" "") + (if_then_else:SI (eq (match_dup 1) (const_int 0)) + (const_int -1) + (const_int 67108860)))] ; 0x03fffffc + "TARGET_ARM" + " + operands[1] = gen_rtx_REG (CC_NOOVmode, 24); + ") + +(define_insn "*check_arch2" + [(set (match_operand:CC_NOOV 0 "cc_register" "") + (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH) + (const_int 0)))] + "TARGET_ARM" + "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc" + [(set_attr "length" "8") + (set_attr "conds" "set")] +) + ;; Call subroutine returning any type. (define_expand "untyped_call" @@ -7015,139 +7078,6 @@ ] ) -;; These variants of the above insns can occur if the first operand is the -;; frame pointer and we eliminate that. This is a kludge, but there doesn't -;; seem to be a way around it. Most of the predicates have to be null -;; because the format can be generated part way through reload, so -;; if we don't match it as soon as it becomes available, reload doesn't know -;; how to reload pseudos that haven't got hard registers; the constraints will -;; sort everything out. - -(define_insn "*reload_mulsi3" - [(set (match_operand:SI 0 "" "=&r") - (plus:SI (plus:SI (match_operator:SI 5 "shift_operator" - [(match_operand:SI 3 "" "r") - (match_operand:SI 4 "" "rM")]) - (match_operand:SI 2 "" "r")) - (match_operand:SI 1 "const_int_operand" "n")))] - "TARGET_ARM && reload_in_progress" - "* - output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands); - operands[2] = operands[1]; - operands[1] = operands[0]; - return output_add_immediate (operands); - " - [ - ; we have no idea how long the add_immediate is, it could be up to 4. - (set_attr "length" "20")] -) - -(define_insn "*reload_mulsi_compare0" - [(set (reg:CC_NOOV CC_REGNUM) - (compare:CC_NOOV (plus:SI - (plus:SI - (match_operator:SI 5 "shift_operator" - [(match_operand:SI 3 "" "r") - (match_operand:SI 4 "" "rM")]) - (match_operand:SI 1 "" "r")) - (match_operand:SI 2 "const_int_operand" "n")) - (const_int 0))) - (set (match_operand:SI 0 "" "=&r") - (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)]) - (match_dup 1)) - (match_dup 2)))] - "TARGET_ARM && reload_in_progress && !arm_is_xscale" - "* - output_add_immediate (operands); - return \"add%?s\\t%0, %0, %3%S5\"; - " - [(set_attr "conds" "set") - (set_attr "shift" "3") - (set_attr "length" "20")] -) - -(define_insn "*reload_mulsi_compare0_scratch" - [(set (reg:CC_NOOV CC_REGNUM) - (compare:CC_NOOV (plus:SI - (plus:SI - (match_operator:SI 5 "shift_operator" - [(match_operand:SI 3 "" "r") - (match_operand:SI 4 "" "rM")]) - (match_operand:SI 1 "" "r")) - (match_operand:SI 2 "const_int_operand" "n")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=&r"))] - "TARGET_ARM && reload_in_progress && !arm_is_xscale" - "* - output_add_immediate (operands); - return \"add%?s\\t%0, %0, %3%S5\"; - " - [(set_attr "conds" "set") - (set_attr "shift" "3") - (set_attr "length" "20")] -) - -;; These are similar, but are needed when the mla pattern contains the -;; eliminated register as operand 3. - -(define_insn "*reload_muladdsi" - [(set (match_operand:SI 0 "" "=&r,&r") - (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r") - (match_operand:SI 2 "" "r,r")) - (match_operand:SI 3 "" "r,r")) - (match_operand:SI 4 "const_int_operand" "n,n")))] - "TARGET_ARM && reload_in_progress" - "* - output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands); - operands[2] = operands[4]; - operands[1] = operands[0]; - return output_add_immediate (operands); - " - [(set_attr "length" "20") - (set_attr "type" "mult")] -) - -(define_insn "*reload_muladdsi_compare0" - [(set (reg:CC_NOOV CC_REGNUM) - (compare:CC_NOOV (plus:SI (plus:SI (mult:SI - (match_operand:SI 3 "" "r") - (match_operand:SI 4 "" "r")) - (match_operand:SI 1 "" "r")) - (match_operand:SI 2 "const_int_operand" "n")) - (const_int 0))) - (set (match_operand:SI 0 "" "=&r") - (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1)) - (match_dup 2)))] - "TARGET_ARM && reload_in_progress && !arm_is_xscale" - "* - output_add_immediate (operands); - output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands); - return \"\"; - " - [(set_attr "length" "20") - (set_attr "conds" "set") - (set_attr "type" "mult")] -) - -(define_insn "*reload_muladdsi_compare0_scratch" - [(set (reg:CC_NOOV CC_REGNUM) - (compare:CC_NOOV (plus:SI (plus:SI (mult:SI - (match_operand:SI 3 "" "r") - (match_operand:SI 4 "" "r")) - (match_operand:SI 1 "" "r")) - (match_operand:SI 2 "const_int_operand" "n")) - (const_int 0))) - (clobber (match_scratch:SI 0 "=&r"))] - "TARGET_ARM && reload_in_progress" - "* - output_add_immediate (operands); - return \"mla%?s\\t%0, %3, %4, %0\"; - " - [(set_attr "length" "20") - (set_attr "conds" "set") - (set_attr "type" "mult")] -) - (define_insn "*and_scc" @@ -8506,7 +8436,7 @@ ; We must watch to see that the source/destination register isn't also the ; same as the base address register, and that if the index is a register, ; that it is not the same as the base address register. In such cases the -; instruction that we would generate would have UNPREDICTABLE behaviour so +; instruction that we would generate would have UNPREDICTABLE behavior so ; we cannot use it. (define_peephole @@ -8759,18 +8689,27 @@ " ) +;; Note - although unspec_volatile's USE all hard registers, +;; USEs are ignored after relaod has completed. Thus we need +;; to add an unspec of the link register to ensure that flow +;; does not think that it is unused by the sibcall branch that +;; will replace the standard function epilogue. (define_insn "sibcall_epilogue" - [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)] + [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE) + (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])] "TARGET_ARM" "* - output_asm_insn (\"%@ Sibcall epilogue\", operands); if (USE_RETURN_INSN (FALSE)) - return output_return_instruction (NULL, FALSE, FALSE); + return output_return_instruction (const_true_rtx, FALSE, FALSE); return arm_output_epilogue (FALSE); " ;; Length is absolute worst case [(set_attr "length" "44") - (set_attr "type" "block")] + (set_attr "type" "block") + ;; We don't clobber the conditions, but the potential length of this + ;; operation is sufficient to make conditionalizing the sequence + ;; unlikely to be profitable. + (set_attr "conds" "clob")] ) (define_insn "*epilogue_insns" @@ -8784,7 +8723,11 @@ " ; Length is absolute worst case [(set_attr "length" "44") - (set_attr "type" "block")] + (set_attr "type" "block") + ;; We don't clobber the conditions, but the potential length of this + ;; operation is sufficient to make conditionalizing the sequence + ;; unlikely to be profitable. + (set_attr "conds" "clob")] ) (define_expand "eh_epilogue" @@ -9018,6 +8961,16 @@ [(set_attr "type" "store4")] ) +(define_insn "stack_tie" + [(set (mem:BLK (scratch)) + (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r") + (match_operand:SI 1 "s_register_operand" "r")] + UNSPEC_PRLG_STK))] + "" + "" + [(set_attr "length" "0")] +) + ;; Similarly for the floating point registers (define_insn "*push_fp_multi" [(match_parallel 2 "multi_register_push" @@ -9090,9 +9043,9 @@ { case MODE_FLOAT: { - union real_extract u; - memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u); - assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD); + REAL_VALUE_TYPE r; + REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]); + assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD); break; } default: @@ -9114,9 +9067,9 @@ { case MODE_FLOAT: { - union real_extract u; - memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u); - assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD); + REAL_VALUE_TYPE r; + REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]); + assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD); break; } default: |