; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
-; arm_arch6. "v6t2" for Thumb-2 with arm_arch6. This attribute is
-; used to compute attribute "enabled", use type "any" to enable an
-; alternative in all cases.
-(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,v6t2,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2,armv6_or_vfpv3,neon"
+; arm_arch6. "v6t2" for Thumb-2 with arm_arch6 and "v8mb" for ARMv8-M
+; Baseline. This attribute is used to compute attribute "enabled",
+; use type "any" to enable an alternative in all cases.
+(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,v6t2,v8mb,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2,armv6_or_vfpv3,neon"
(const_string "any"))
(define_attr "arch_enabled" "no,yes"
(match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2"))
(const_string "yes")
+ (and (eq_attr "arch" "v8mb")
+ (match_test "TARGET_THUMB1 && arm_arch8"))
+ (const_string "yes")
+
(and (eq_attr "arch" "avoid_neon_for_64bits")
(match_test "TARGET_NEON")
(not (match_test "TARGET_PREFER_NEON_64BITS")))
;; LO_SUM adds in the high bits. Fortunately these are opaque operations
;; so this does not matter.
(define_insn "*arm_movt"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
- (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
- (match_operand:SI 2 "general_operand" "i")))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
+ (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
+ (match_operand:SI 2 "general_operand" "i,i")))]
"TARGET_HAVE_MOVT && arm_valid_symbolic_address_p (operands[2])"
- "movt%?\t%0, #:upper16:%c2"
- [(set_attr "predicable" "yes")
+ "@
+ movt%?\t%0, #:upper16:%c2
+ movt\t%0, #:upper16:%c2"
+ [(set_attr "arch" "32,v8mb")
+ (set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")
(set_attr "length" "4")
(set_attr "type" "alu_sreg")]
;; We only care about the lower 16 bits of the constant
;; being inserted into the upper 16 bits of the register.
(define_insn "*arm_movtas_ze"
- [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
+ [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r,r")
(const_int 16)
(const_int 16))
(match_operand:SI 1 "const_int_operand" ""))]
"TARGET_HAVE_MOVT"
- "movt%?\t%0, %L1"
- [(set_attr "predicable" "yes")
+ "@
+ movt%?\t%0, %L1
+ movt\t%0, %L1"
+ [(set_attr "arch" "32,v8mb")
+ (set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")
(set_attr "length" "4")
(set_attr "type" "alu_sreg")]
;;; ??? The 'i' constraint looks funny, but it should always be replaced by
;;; thumb_reorg with a memory reference.
(define_insn "*thumb1_movdi_insn"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
- (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,r,l,>,l, m,*r")
+ (match_operand:DI 1 "general_operand" "l, I,J,j,>,l,mi,l,*r"))]
"TARGET_THUMB1
&& ( register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode))"
operands[1] = GEN_INT (- INTVAL (operands[1]));
return \"movs\\t%Q0, %1\;rsbs\\t%Q0, %Q0, #0\;asrs\\t%R0, %Q0, #31\";
case 3:
- return \"ldmia\\t%1, {%0, %H0}\";
+ gcc_assert (TARGET_HAVE_MOVT);
+ return \"movw\\t%Q0, %L1\;movs\\tR0, #0\";
case 4:
- return \"stmia\\t%0, {%1, %H1}\";
+ return \"ldmia\\t%1, {%0, %H0}\";
case 5:
- return thumb_load_double_from_address (operands);
+ return \"stmia\\t%0, {%1, %H1}\";
case 6:
+ return thumb_load_double_from_address (operands);
+ case 7:
operands[2] = gen_rtx_MEM (SImode,
plus_constant (Pmode, XEXP (operands[0], 0), 4));
output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
return \"\";
- case 7:
+ case 8:
if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
}
}"
- [(set_attr "length" "4,4,6,2,2,6,4,4")
- (set_attr "type" "multiple,multiple,multiple,load2,store2,load2,store2,multiple")
- (set_attr "pool_range" "*,*,*,*,*,1018,*,*")]
+ [(set_attr "length" "4,4,6,6,2,2,6,4,4")
+ (set_attr "type" "multiple,multiple,multiple,multiple,load2,store2,load2,store2,multiple")
+ (set_attr "arch" "t1,t1,t1,v8mb,t1,t1,t1,t1,t1")
+ (set_attr "pool_range" "*,*,*,*,*,*,1018,*,*")]
)
(define_insn "*thumb1_movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
- (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*l*h*k"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,r,l,l,l,>,l, m,*l*h*k")
+ (match_operand:SI 1 "general_operand" "l, I,j,J,K,>,l,mi,l,*l*h*k"))]
"TARGET_THUMB1
&& ( register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
"@
movs %0, %1
movs %0, %1
+ movw %0, %1
#
#
ldmia\\t%1, {%0}
ldr\\t%0, %1
str\\t%1, %0
mov\\t%0, %1"
- [(set_attr "length" "2,2,4,4,2,2,2,2,2")
- (set_attr "type" "mov_reg,mov_imm,multiple,multiple,load1,store1,load1,store1,mov_reg")
- (set_attr "pool_range" "*,*,*,*,*,*,1018,*,*")
- (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
+ [(set_attr "length" "2,2,4,4,4,2,2,2,2,2")
+ (set_attr "type" "mov_reg,mov_imm,mov_imm,multiple,multiple,load1,store1,load1,store1,mov_reg")
+ (set_attr "pool_range" "*,*,*,*,*,*,*,1018,*,*")
+ (set_attr "arch" "t1,t1,v8mb,t1,t1,t1,t1,t1,t1,t1")
+ (set_attr "conds" "set,clob,nocond,*,*,nocond,nocond,nocond,nocond,nocond")])
; Split the load of 64-bit constant into two loads for high and low 32-bit parts respectively
; to see if we can load them in fewer instructions or fewer cycles.
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "const_int_operand" ""))]
- "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
+ "TARGET_THUMB1 && satisfies_constraint_K (operands[1])
+ && !(TARGET_HAVE_MOVT && satisfies_constraint_j (operands[1]))"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
"
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "const_int_operand" ""))]
- "TARGET_THUMB1 && satisfies_constraint_Pe (operands[1])"
+ "TARGET_THUMB1 && satisfies_constraint_Pe (operands[1])
+ && !(TARGET_HAVE_MOVT && satisfies_constraint_j (operands[1]))"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 3)))]
"
)
(define_insn "*thumb1_movhi_insn"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,l*r,*h,l")
- (match_operand:HI 1 "general_operand" "l,m,l,k*h,*r,I"))]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,l*r,*h,l,r")
+ (match_operand:HI 1 "general_operand" "l,m,l,k*h,*r,I,n"))]
"TARGET_THUMB1
&& ( register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode))"
case 3: return \"mov %0, %1\";
case 4: return \"mov %0, %1\";
case 5: return \"movs %0, %1\";
+ case 6: gcc_assert (TARGET_HAVE_MOVT);
+ return \"movw %0, %L1\";
default: gcc_unreachable ();
case 1:
/* The stack pointer can end up being taken as an index register.
}
return \"ldrh %0, %1\";
}"
- [(set_attr "length" "2,4,2,2,2,2")
- (set_attr "type" "alus_imm,load1,store1,mov_reg,mov_reg,mov_imm")
- (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
+ [(set_attr "length" "2,4,2,2,2,2,4")
+ (set_attr "type" "alus_imm,load1,store1,mov_reg,mov_reg,mov_imm,mov_imm")
+ (set_attr "arch" "t1,t1,t1,t1,t1,t1,v8mb")
+ (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob,nocond")])
(define_expand "thumb_movhi_clobber"
[(set (match_operand:HI 0 "memory_operand" "")