(define_expand "ashldi3"
[(set (match_operand:DI 0 "s_register_operand")
(ashift:DI (match_operand:DI 1 "s_register_operand")
- (match_operand:SI 2 "general_operand")))]
+ (match_operand:SI 2 "reg_or_int_operand")))]
"TARGET_32BIT"
"
- if (TARGET_NEON)
- {
- /* Delay the decision whether to use NEON or core-regs until
- register allocation. */
- emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
- DONE;
- }
- else
- {
- /* Only the NEON case can handle in-memory shift counts. */
- if (!reg_or_int_operand (operands[2], SImode))
- operands[2] = force_reg (SImode, operands[2]);
- }
-
- if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
- ; /* No special preparation statements; expand pattern as above. */
- else
- {
- rtx scratch1, scratch2;
-
- /* Ideally we should use iwmmxt here if we could know that operands[1]
- ends up already living in an iwmmxt register. Otherwise it's
- cheaper to have the alternate code being generated than moving
- values to iwmmxt regs and back. */
-
- /* Expand operation using core-registers.
- 'FAIL' would achieve the same thing, but this is a bit smarter. */
- scratch1 = gen_reg_rtx (SImode);
- scratch2 = gen_reg_rtx (SImode);
- arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
- operands[2], scratch1, scratch2);
- DONE;
- }
- "
-)
+ arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
+ operands[2], gen_reg_rtx (SImode),
+ gen_reg_rtx (SImode));
+ DONE;
+")
(define_expand "ashlsi3"
[(set (match_operand:SI 0 "s_register_operand")
(match_operand:SI 2 "reg_or_int_operand")))]
"TARGET_32BIT"
"
- if (TARGET_NEON)
- {
- /* Delay the decision whether to use NEON or core-regs until
- register allocation. */
- emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
- DONE;
- }
-
- if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
- ; /* No special preparation statements; expand pattern as above. */
- else
- {
- rtx scratch1, scratch2;
-
- /* Ideally we should use iwmmxt here if we could know that operands[1]
- ends up already living in an iwmmxt register. Otherwise it's
- cheaper to have the alternate code being generated than moving
- values to iwmmxt regs and back. */
-
- /* Expand operation using core-registers.
- 'FAIL' would achieve the same thing, but this is a bit smarter. */
- scratch1 = gen_reg_rtx (SImode);
- scratch2 = gen_reg_rtx (SImode);
- arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
- operands[2], scratch1, scratch2);
- DONE;
- }
- "
-)
+ arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
+ operands[2], gen_reg_rtx (SImode),
+ gen_reg_rtx (SImode));
+ DONE;
+")
(define_expand "ashrsi3"
[(set (match_operand:SI 0 "s_register_operand")
(match_operand:SI 2 "reg_or_int_operand")))]
"TARGET_32BIT"
"
- if (TARGET_NEON)
- {
- /* Delay the decision whether to use NEON or core-regs until
- register allocation. */
- emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
- DONE;
- }
-
- if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
- ; /* No special preparation statements; expand pattern as above. */
- else
- {
- rtx scratch1, scratch2;
-
- /* Ideally we should use iwmmxt here if we could know that operands[1]
- ends up already living in an iwmmxt register. Otherwise it's
- cheaper to have the alternate code being generated than moving
- values to iwmmxt regs and back. */
-
- /* Expand operation using core-registers.
- 'FAIL' would achieve the same thing, but this is a bit smarter. */
- scratch1 = gen_reg_rtx (SImode);
- scratch2 = gen_reg_rtx (SImode);
- arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
- operands[2], scratch1, scratch2);
- DONE;
- }
- "
-)
+ arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
+ operands[2], gen_reg_rtx (SImode),
+ gen_reg_rtx (SImode));
+ DONE;
+")
(define_expand "lshrsi3"
[(set (match_operand:SI 0 "s_register_operand")
;; Zero and sign extension instructions.
(define_insn "zero_extend<mode>di2"
- [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
+ [(set (match_operand:DI 0 "s_register_operand" "=r,?r")
(zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
"<qhs_zextenddi_cstr>")))]
"TARGET_32BIT <qhs_zextenddi_cond>"
"#"
- [(set_attr "length" "8,4,8,8")
- (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
+ [(set_attr "length" "4,8")
+ (set_attr "arch" "*,*")
(set_attr "ce_count" "2")
(set_attr "predicable" "yes")
- (set_attr "type" "multiple,mov_reg,multiple,multiple")]
+ (set_attr "type" "mov_reg,multiple")]
)
(define_insn "extend<mode>di2"
- [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
+ [(set (match_operand:DI 0 "s_register_operand" "=r,?r,?r")
(sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
"<qhs_extenddi_cstr>")))]
"TARGET_32BIT <qhs_sextenddi_cond>"
"#"
- [(set_attr "length" "8,4,8,8,8")
+ [(set_attr "length" "4,8,8")
(set_attr "ce_count" "2")
(set_attr "shift" "1")
(set_attr "predicable" "yes")
- (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
- (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
+ (set_attr "arch" "*,a,t")
+ (set_attr "type" "mov_reg,multiple,multiple")]
)
;; Splits for all extensions to DImode
[(set_attr "type" "neon_load1_1reg,neon_from_gp")]
)
-(define_insn "ashldi3_neon_noclobber"
- [(set (match_operand:DI 0 "s_register_operand" "=w,w")
- (ashift:DI (match_operand:DI 1 "s_register_operand" " w,w")
- (match_operand:DI 2 "reg_or_int_operand" " i,w")))]
- "TARGET_NEON && reload_completed
- && (!CONST_INT_P (operands[2])
- || (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 64))"
- "@
- vshl.u64\t%P0, %P1, %2
- vshl.u64\t%P0, %P1, %P2"
- [(set_attr "type" "neon_shift_imm, neon_shift_reg")]
-)
-
-(define_insn_and_split "ashldi3_neon"
- [(set (match_operand:DI 0 "s_register_operand" "= w, w, &r, r, &r, ?w,?w")
- (ashift:DI (match_operand:DI 1 "s_register_operand" " 0w, w, 0r, 0, r, 0w, w")
- (match_operand:SI 2 "general_operand" "rUm, i, r, i, i,rUm, i")))
- (clobber (match_scratch:SI 3 "= X, X, &r, X, X, X, X"))
- (clobber (match_scratch:SI 4 "= X, X, &r, X, X, X, X"))
- (clobber (match_scratch:DI 5 "=&w, X, X, X, X, &w, X"))
- (clobber (reg:CC_C CC_REGNUM))]
- "TARGET_NEON"
- "#"
- "TARGET_NEON && reload_completed"
- [(const_int 0)]
- "
- {
- if (IS_VFP_REGNUM (REGNO (operands[0])))
- {
- if (CONST_INT_P (operands[2]))
- {
- if (INTVAL (operands[2]) < 1)
- {
- emit_insn (gen_movdi (operands[0], operands[1]));
- DONE;
- }
- else if (INTVAL (operands[2]) > 63)
- operands[2] = gen_rtx_CONST_INT (VOIDmode, 63);
- }
- else
- {
- emit_insn (gen_neon_load_count (operands[5], operands[2]));
- operands[2] = operands[5];
- }
-
- /* Ditch the unnecessary clobbers. */
- emit_insn (gen_ashldi3_neon_noclobber (operands[0], operands[1],
- operands[2]));
- }
- else
- {
- /* The shift expanders support either full overlap or no overlap. */
- gcc_assert (!reg_overlap_mentioned_p (operands[0], operands[1])
- || REGNO (operands[0]) == REGNO (operands[1]));
-
- arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
- operands[2], operands[3], operands[4]);
- }
- DONE;
- }"
- [(set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")
- (set_attr "opt" "*,*,speed,speed,speed,*,*")
- (set_attr "type" "multiple")]
-)
-
-; The shift amount needs to be negated for right-shifts
-(define_insn "signed_shift_di3_neon"
- [(set (match_operand:DI 0 "s_register_operand" "=w")
- (unspec:DI [(match_operand:DI 1 "s_register_operand" " w")
- (match_operand:DI 2 "s_register_operand" " w")]
- UNSPEC_ASHIFT_SIGNED))]
- "TARGET_NEON && reload_completed"
- "vshl.s64\t%P0, %P1, %P2"
- [(set_attr "type" "neon_shift_reg")]
-)
-
-; The shift amount needs to be negated for right-shifts
-(define_insn "unsigned_shift_di3_neon"
- [(set (match_operand:DI 0 "s_register_operand" "=w")
- (unspec:DI [(match_operand:DI 1 "s_register_operand" " w")
- (match_operand:DI 2 "s_register_operand" " w")]
- UNSPEC_ASHIFT_UNSIGNED))]
- "TARGET_NEON && reload_completed"
- "vshl.u64\t%P0, %P1, %P2"
- [(set_attr "type" "neon_shift_reg")]
-)
-
-(define_insn "ashrdi3_neon_imm_noclobber"
- [(set (match_operand:DI 0 "s_register_operand" "=w")
- (ashiftrt:DI (match_operand:DI 1 "s_register_operand" " w")
- (match_operand:DI 2 "const_int_operand" " i")))]
- "TARGET_NEON && reload_completed
- && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 64"
- "vshr.s64\t%P0, %P1, %2"
- [(set_attr "type" "neon_shift_imm")]
-)
-
-(define_insn "lshrdi3_neon_imm_noclobber"
- [(set (match_operand:DI 0 "s_register_operand" "=w")
- (lshiftrt:DI (match_operand:DI 1 "s_register_operand" " w")
- (match_operand:DI 2 "const_int_operand" " i")))]
- "TARGET_NEON && reload_completed
- && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 64"
- "vshr.u64\t%P0, %P1, %2"
- [(set_attr "type" "neon_shift_imm")]
-)
-
-;; ashrdi3_neon
-;; lshrdi3_neon
-(define_insn_and_split "<shift>di3_neon"
- [(set (match_operand:DI 0 "s_register_operand" "= w, w, &r, r, &r,?w,?w")
- (RSHIFTS:DI (match_operand:DI 1 "s_register_operand" " 0w, w, 0r, 0, r,0w, w")
- (match_operand:SI 2 "reg_or_int_operand" " r, i, r, i, i, r, i")))
- (clobber (match_scratch:SI 3 "=2r, X, &r, X, X,2r, X"))
- (clobber (match_scratch:SI 4 "= X, X, &r, X, X, X, X"))
- (clobber (match_scratch:DI 5 "=&w, X, X, X, X,&w, X"))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_NEON"
- "#"
- "TARGET_NEON && reload_completed"
- [(const_int 0)]
- "
- {
- if (IS_VFP_REGNUM (REGNO (operands[0])))
- {
- if (CONST_INT_P (operands[2]))
- {
- if (INTVAL (operands[2]) < 1)
- {
- emit_insn (gen_movdi (operands[0], operands[1]));
- DONE;
- }
- else if (INTVAL (operands[2]) > 64)
- operands[2] = gen_rtx_CONST_INT (VOIDmode, 64);
-
- /* Ditch the unnecessary clobbers. */
- emit_insn (gen_<shift>di3_neon_imm_noclobber (operands[0],
- operands[1],
- operands[2]));
- }
- else
- {
- /* We must use a negative left-shift. */
- emit_insn (gen_negsi2 (operands[3], operands[2]));
- emit_insn (gen_neon_load_count (operands[5], operands[3]));
- emit_insn (gen_<shifttype>_shift_di3_neon (operands[0], operands[1],
- operands[5]));
- }
- }
- else
- {
- /* The shift expanders support either full overlap or no overlap. */
- gcc_assert (!reg_overlap_mentioned_p (operands[0], operands[1])
- || REGNO (operands[0]) == REGNO (operands[1]));
-
- /* This clobbers CC (ASHIFTRT by register only). */
- arm_emit_coreregs_64bit_shift (<CODE>, operands[0], operands[1],
- operands[2], operands[3], operands[4]);
- }
-
- DONE;
- }"
- [(set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")
- (set_attr "opt" "*,*,speed,speed,speed,*,*")
- (set_attr "type" "multiple")]
-)
-
;; Widening operations
(define_expand "widen_ssum<mode>3"
"vabd.<V_if_elem> %<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set_attr "type" "neon_fp_abd_s<q>")]
)
-
-;; Copy from core-to-neon regs, then extend, not vice-versa
-
-(define_split
- [(set (match_operand:DI 0 "s_register_operand" "")
- (sign_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
- "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
- [(set (match_dup 2) (vec_duplicate:V2SI (match_dup 1)))
- (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 32)))]
- {
- operands[2] = gen_rtx_REG (V2SImode, REGNO (operands[0]));
- })
-
-(define_split
- [(set (match_operand:DI 0 "s_register_operand" "")
- (sign_extend:DI (match_operand:HI 1 "s_register_operand" "")))]
- "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
- [(set (match_dup 2) (vec_duplicate:V4HI (match_dup 1)))
- (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))]
- {
- operands[2] = gen_rtx_REG (V4HImode, REGNO (operands[0]));
- })
-
-(define_split
- [(set (match_operand:DI 0 "s_register_operand" "")
- (sign_extend:DI (match_operand:QI 1 "s_register_operand" "")))]
- "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
- [(set (match_dup 2) (vec_duplicate:V8QI (match_dup 1)))
- (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))]
- {
- operands[2] = gen_rtx_REG (V8QImode, REGNO (operands[0]));
- })
-
-(define_split
- [(set (match_operand:DI 0 "s_register_operand" "")
- (zero_extend:DI (match_operand:SI 1 "s_register_operand" "")))]
- "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
- [(set (match_dup 2) (vec_duplicate:V2SI (match_dup 1)))
- (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 32)))]
- {
- operands[2] = gen_rtx_REG (V2SImode, REGNO (operands[0]));
- })
-
-(define_split
- [(set (match_operand:DI 0 "s_register_operand" "")
- (zero_extend:DI (match_operand:HI 1 "s_register_operand" "")))]
- "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
- [(set (match_dup 2) (vec_duplicate:V4HI (match_dup 1)))
- (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))]
- {
- operands[2] = gen_rtx_REG (V4HImode, REGNO (operands[0]));
- })
-
-(define_split
- [(set (match_operand:DI 0 "s_register_operand" "")
- (zero_extend:DI (match_operand:QI 1 "s_register_operand" "")))]
- "TARGET_NEON && reload_completed && IS_VFP_REGNUM (REGNO (operands[0]))"
- [(set (match_dup 2) (vec_duplicate:V8QI (match_dup 1)))
- (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 56)))]
- {
- operands[2] = gen_rtx_REG (V8QImode, REGNO (operands[0]));
- })