@@ -32,7 +32,6 @@ extern void arc_print_operand (FILE *, rtx, int);
extern void arc_print_operand_address (FILE *, rtx);
extern void arc_final_prescan_insn (rtx_insn *, rtx *, int);
extern const char *arc_output_libcall (const char *);
-extern int arc_output_addsi (rtx *operands, bool, bool);
extern int arc_output_commutative_cond_exec (rtx *operands, bool);
extern bool arc_expand_cpymem (rtx *operands);
extern bool prepare_move_operands (rtx *operands, machine_mode mode);
@@ -86,7 +85,6 @@ extern void arc_init_expanders (void);
extern int arc_check_millicode (rtx op, int offset, int load_p);
extern void arc_clear_unalign (void);
extern void arc_toggle_unalign (void);
-extern void split_addsi (rtx *);
extern void split_subsi (rtx *);
extern void arc_split_move (rtx *);
extern const char *arc_short_long (rtx_insn *insn, const char *, const char *);
@@ -4501,8 +4501,8 @@ static int output_sdata = 0;
/* Print operand X (an rtx) in assembler syntax to file FILE.
CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
- For `%' followed by punctuation, CODE is the punctuation and X is null. */
-/* In final.cc:output_asm_insn:
+ For `%' followed by punctuation, CODE is the punctuation and X is null.
+ In final.cc:output_asm_insn:
'l' : label
'a' : address
'c' : constant address if CONSTANT_ADDRESS_P
@@ -4512,7 +4512,10 @@ static int output_sdata = 0;
'z': log2
'M': log2(~x)
'p': bit Position of lsb
- 's': size of bit field
+ 's': scalled immediate
+ 'S': Scalled immediate, to be used in pair with 's'.
+ 'N': Negative immediate, to be used in pair with 's'.
+ 'x': size of bit field
'#': condbranch delay slot suffix
'*': jump delay slot suffix
'?' : nonjump-insn suffix for conditional execution or short instruction
@@ -4521,7 +4524,7 @@ static int output_sdata = 0;
'd'
'D'
'R': Second word
- 'S': JLI instruction
+ 'J': JLI instruction
'j': used by mov instruction to properly emit jli related labels.
'B': Branch comparison operand - suppress sda reference
'H': Most significant word
@@ -4538,6 +4541,10 @@ static int output_sdata = 0;
void
arc_print_operand (FILE *file, rtx x, int code)
{
+ HOST_WIDE_INT ival;
+ unsigned scalled = 0;
+ int sign = 1;
+
switch (code)
{
case 'Z':
@@ -4580,6 +4587,56 @@ arc_print_operand (FILE *file, rtx x, int code)
return;
case 's':
+ if (REG_P (x))
+ return;
+ if (!CONST_INT_P (x))
+ {
+ output_operand_lossage ("invalid operand for %%s code");
+ return;
+ }
+ ival = INTVAL (x);
+ if ((ival & 0x07) == 0)
+ scalled = 3;
+ else if ((ival & 0x03) == 0)
+ scalled = 2;
+ else if ((ival & 0x01) == 0)
+ scalled = 1;
+
+ if (scalled)
+ asm_fprintf (file, "%d", scalled);
+ return;
+
+ case 'N':
+ if (REG_P (x))
+ {
+ output_operand_lossage ("invalid operand for %%N code");
+ return;
+ }
+ sign = -1;
+ /* fall through */
+ case 'S':
+ if (REG_P (x))
+ {
+ asm_fprintf (file, "%s", reg_names [REGNO (x)]);
+ return;
+ }
+ if (!CONST_INT_P (x))
+ {
+ output_operand_lossage ("invalid operand for %%N or %%S code");
+ return;
+ }
+ ival = sign * INTVAL (x);
+ if ((ival & 0x07) == 0)
+ scalled = 3;
+ else if ((ival & 0x03) == 0)
+ scalled = 2;
+ else if ((ival & 0x01) == 0)
+ scalled = 1;
+
+ asm_fprintf (file, "%wd", (ival >> scalled));
+ return;
+
+ case 'x':
if (GET_CODE (x) == CONST_INT)
{
HOST_WIDE_INT i = INTVAL (x);
@@ -4738,7 +4795,7 @@ arc_print_operand (FILE *file, rtx x, int code)
output_operand_lossage ("invalid operand to %%R code");
return;
case 'j':
- case 'S' :
+ case 'J' :
if (GET_CODE (x) == SYMBOL_REF
&& arc_is_jli_call_p (x))
{
@@ -8989,7 +9046,7 @@ arc_register_move_cost (machine_mode,
Return the length of the instruction.
If OUTPUT_P is false, don't actually output the instruction, just return
its length. */
-int
+static int
arc_output_addsi (rtx *operands, bool cond_p, bool output_p)
{
char format[35];
@@ -10016,31 +10073,6 @@ arc_toggle_unalign (void)
cfun->machine->unalign ^= 2;
}
-/* Operands 0..2 are the operands of a addsi which uses a 12 bit
- constant in operand 2, but which would require a LIMM because of
- operand mismatch.
- operands 3 and 4 are new SET_SRCs for operands 0. */
-
-void
-split_addsi (rtx *operands)
-{
- int val = INTVAL (operands[2]);
-
- /* Try for two short insns first. Lengths being equal, we prefer
- expansions with shorter register lifetimes. */
- if (val > 127 && val <= 255
- && arc_check_short_reg_p (operands[0]))
- {
- operands[3] = operands[2];
- operands[4] = gen_rtx_PLUS (SImode, operands[0], operands[1]);
- }
- else
- {
- operands[3] = operands[1];
- operands[4] = gen_rtx_PLUS (SImode, operands[0], operands[2]);
- }
-}
-
/* Operands 0..2 are the operands of a subsi which uses a 12 bit
constant in operand 1, but which would require a LIMM because of
operand mismatch.
@@ -615,25 +615,53 @@ extern enum reg_class arc_regno_reg_class[];
((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
#define SMALL_INT(X) ((unsigned) ((X) + 0x100) < 0x200)
-#define SMALL_INT_RANGE(X, OFFSET, SHIFT) \
- ((unsigned) (((X) >> (SHIFT)) + 0x100) \
+#define SMALL_INT_RANGE(X, OFFSET, SHIFT) \
+ ((unsigned) (((X) >> (SHIFT)) + 0x100) \
< 0x200 - ((unsigned) (OFFSET) >> (SHIFT)))
-#define SIGNED_INT12(X) ((unsigned) ((X) + 0x800) < 0x1000)
-#define SIGNED_INT16(X) ((unsigned) ((X) + 0x8000) < 0x10000)
-#define LARGE_INT(X) \
-(((X) < 0) \
- ? (X) >= (-(HOST_WIDE_INT) 0x7fffffff - 1) \
- : (unsigned HOST_WIDE_INT) (X) <= (unsigned HOST_WIDE_INT) 0xffffffff)
-#define UNSIGNED_INT3(X) ((unsigned) (X) < 0x8)
-#define UNSIGNED_INT5(X) ((unsigned) (X) < 0x20)
-#define UNSIGNED_INT6(X) ((unsigned) (X) < 0x40)
-#define UNSIGNED_INT7(X) ((unsigned) (X) < 0x80)
-#define UNSIGNED_INT8(X) ((unsigned) (X) < 0x100)
-#define UNSIGNED_INT12(X) ((unsigned) (X) < 0x800)
-#define UNSIGNED_INT16(X) ((unsigned) (X) < 0x10000)
+#define LARGE_INT(X) \
+ (((X) < 0) \
+ ? (X) >= (-(HOST_WIDE_INT) 0x7fffffff - 1) \
+ : (unsigned HOST_WIDE_INT) (X) <= (unsigned HOST_WIDE_INT) 0xffffffff)
+
#define IS_ONE(X) ((X) == 1)
#define IS_ZERO(X) ((X) == 0)
+#define SIGNED(X,V) \
+ ((unsigned long long) ((X) + (1ULL << (V - 1))) < (1ULL << V))
+#define UNSIGNED(X,V) ((unsigned long long) (X) < (1ULL << V))
+#define VERIFY_SHIFT(X,S) ((X & ((1 << S) - 1)) == 0)
+
+#define UNSIGNED_INT3(X) (UNSIGNED(X,3))
+#define UNSIGNED_INT5(X) (UNSIGNED(X,5))
+#define UNSIGNED_INT6(X) (UNSIGNED(X,6))
+#define UNSIGNED_INT7(X) (UNSIGNED(X,7))
+#define UNSIGNED_INT8(X) (UNSIGNED(X,8))
+#define UNSIGNED_INT9(X) (UNSIGNED(X,9))
+#define UNSIGNED_INT10(X) (UNSIGNED(X,10))
+#define UNSIGNED_INT12(X) (UNSIGNED(X,12))
+#define UNSIGNED_INT16(X) (UNSIGNED(X,16))
+
+#define SIGNED_INT3(X) (SIGNED(X,3))
+#define SIGNED_INT6(X) (SIGNED(X,6))
+#define SIGNED_INT7(X) (SIGNED(X,7))
+#define SIGNED_INT8(X) (SIGNED(X,8))
+#define SIGNED_INT9(X) (SIGNED(X,9))
+#define SIGNED_INT10(X) (SIGNED(X,10))
+#define SIGNED_INT11(X) (SIGNED(X,11))
+#define SIGNED_INT12(X) (SIGNED(X,12))
+#define SIGNED_INT13(X) (SIGNED(X,13))
+#define SIGNED_INT16(X) (SIGNED(X,16))
+#define SIGNED_INT21(X) (SIGNED(X,21))
+#define SIGNED_INT25(X) (SIGNED(X,25))
+
+#define UNSIGNED_INT7_SHIFTED(X,S) (VERIFY_SHIFT(X,S) && UNSIGNED_INT6(X >> S))
+#define UNSIGNED_INT8_SHIFTED(X,S) (VERIFY_SHIFT(X,S) && UNSIGNED_INT6(X >> S))
+#define UNSIGNED_INT9_SHIFTED(X,S) (VERIFY_SHIFT(X,S) && UNSIGNED_INT6(X >> S))
+
+#define SIGNED_INT13_SHIFTED(X,S) (VERIFY_SHIFT(X,S) && SIGNED_INT12(X >> S))
+#define SIGNED_INT14_SHIFTED(X,S) (VERIFY_SHIFT(X,S) && SIGNED_INT12(X >> S))
+#define SIGNED_INT15_SHIFTED(X,S) (VERIFY_SHIFT(X,S) && SIGNED_INT12(X >> S))
+
/* Stack layout and stack pointer usage. */
/* Define this macro if pushing a word onto the stack moves the stack
@@ -242,11 +242,12 @@ (define_attr "is_sfunc" "no,yes" (const_string "no"))
; via r12.
(define_attr "type"
- "move,load,store,cmove,unary,binary,compare,shift,uncond_branch,jump,branch,
- brcc,brcc_no_delay_slot,call,sfunc,call_no_delay_slot,rtie,
- multi,umulti, two_cycle_core,lr,sr,divaw,loop_setup,loop_end,return,
- misc,spfp,dpfp_mult,dpfp_addsub,mulmac_600,cc_arith,
- simd_vload, simd_vload128, simd_vstore, simd_vmove, simd_vmove_else_zero,
+ "add,sub,bxor,move,load,store,cmove,unary,binary,compare,shift,uncond_branch,
+ jump,branch,brcc,brcc_no_delay_slot,call,sfunc,call_no_delay_slot,rtie,
+ multi,umulti,
+ two_cycle_core,lr,sr,divaw,loop_setup,loop_end,return,
+ misc,spfp,dpfp_mult,dpfp_addsub,mulmac_600,cc_arith, simd_vload,
+ simd_vload128, simd_vstore, simd_vmove, simd_vmove_else_zero,
simd_vmove_with_acc, simd_varith_1cycle, simd_varith_2cycle,
simd_varith_with_acc, simd_vlogic, simd_vlogic_with_acc,
simd_vcompare, simd_vpermute, simd_vpack, simd_vpack_with_acc,
@@ -1004,7 +1005,7 @@ (define_insn_and_split "*tst_movb"
(const_int 0)]))
(clobber (match_scratch:SI 3 "=X,X,X,X,X,X,Rrq,1,c"))]
"TARGET_NPS_BITOPS"
- "movb.f.cl %3,%1,%p2,%p2,%s2"
+ "movb.f.cl %3,%1,%p2,%p2,%x2"
"TARGET_NPS_BITOPS && reload_completed
&& (extract_constrain_insn_cached (insn), (which_alternative & ~1) != 6)"
[(set (match_dup 0) (match_dup 4))])
@@ -2018,44 +2019,40 @@ (define_insn "sminsi3"
;; Arithmetic instructions.
-; We say an insn can be conditionalized if this doesn't introduce a long
-; immediate. We set the type such that we still have good scheduling if the
-; insn is conditionalized.
-; ??? It would make sense to allow introduction of long immediates, but
-; we'd need to communicate to the ccfsm machinery the extra cost.
; The alternatives in the constraints still serve three purposes:
; - estimate insn size assuming conditional execution
; - guide reload to re-order the second and third operand to get a better fit.
; - give tentative insn type to guide scheduling
; N.B. "%" for commutativity doesn't help when there is another matching
; (but longer) alternative.
-; We avoid letting this pattern use LP_COUNT as a register by specifying
-; register class 'W' instead of 'w'.
-(define_insn_and_split "*addsi3_mixed"
- ;; 0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12
- [(set (match_operand:SI 0 "dest_reg_operand" "=q,q, h,!*Rsd, q,Rcb, q, q, q, r,r, r, W, W,W, W, q, r, W")
- (plus:SI (match_operand:SI 1 "register_operand" "%0,c, 0, q, 0, 0,Rcb, q, 0, 0,r, 0, c, c,0, 0, 0, 0, c")
- (match_operand:SI 2 "nonmemory_operand" "cL,0, Cm1, L,CL2,Csp,CM4,qK,cO,rL,0,rCca,cLCmL,Cca,I,C2a,Cal,Cal,Cal")))]
+(define_insn "*addsi3_mixed"
+ ;; 0 1 2 3 4 5 6 7 8 9 a b c d e f 10
+ [(set (match_operand:SI 0 "register_operand" "=q, h,!*Rsd,Rcb,Rcb, q, q, q, r,r, r, r, r, r, q, r, r")
+ (plus:SI (match_operand:SI 1 "register_operand" "%0, 0, q, 0, 0,Rcb, q, 0, 0,r, r, r, 0, r, 0, 0, r")
+ (match_operand:SI 2 "nonmemory_operand" "hL,Cm1, L,CP4,CM4,CM4,qK, O,rL,0,rC6u,C6n,CIs,C4p,Cal,Cal,Cal")))]
""
-{
- arc_output_addsi (operands, arc_ccfsm_cond_exec_p (), true);
- return "";
-}
- "&& reload_completed && get_attr_length (insn) == 8
- && satisfies_constraint_I (operands[2])
- && GET_CODE (PATTERN (insn)) != COND_EXEC"
- [(set (match_dup 0) (match_dup 3)) (set (match_dup 0) (match_dup 4))]
- "split_addsi (operands);"
- [(set_attr "type" "*,*,*,*,two_cycle_core,two_cycle_core,*,*,*,*,*,two_cycle_core,*,two_cycle_core,*,two_cycle_core,*,*,*")
- (set (attr "iscompact")
- (cond [(match_test "~arc_output_addsi (operands, false, false) & 2")
- (const_string "false")
- (match_operand 2 "long_immediate_operand" "")
- (const_string "maybe_limm")]
- (const_string "maybe")))
- (set_attr "length" "*,*,*,*,*,*,*,*,*,4,4,4,4,4,4,4,*,8,8")
- (set_attr "predicable" "no,no,no,no,no,no,no,no,no,yes,yes,yes,no,no,no,no,no,yes,no")
- (set_attr "cond" "canuse,nocond,nocond,nocond,canuse,canuse,nocond,nocond,nocond,canuse,canuse,canuse,nocond,nocond,canuse_limm,canuse_limm,canuse,canuse,nocond")
+ "@
+ add_s\\t%0,%1,%2 ;b,b,h
+ add_s\\t%0,%1,%2 ;h,h,s3
+ add_s\\t%0,%1,%2 ;R0/R1,b,u6
+ sub_s\\t%0,%1,%n2 ;sp,sp,u7
+ add_s\\t%0,%1,%2 ;sp,sp,u7
+ add_s\\t%0,%1,%2 ;b,sp,u7
+ add_s\\t%0,%1,%2 ;a,b,c/u3
+ add_s\\t%0,%1,%2 ;b,b,u7
+ add%?\\t%0,%1,%2 ;(p)b,b,c/u6
+ add%?\\t%0,%2,%1 ;(p)b,b,c
+ add%s2\\t%0,%1,%S2 ;a,b,c/u6
+ sub%s2\\t%0,%1,%N2 ;a,b,u6
+ add%s2\\t%0,%1,%S2 ;b,b,s12
+ bxor\\t%0,%1,31
+ add_s\\t%0,%1,%2 ;b,b,limm
+ add%?\\t%0,%1,%2 ;(p)b,b,limm
+ add\\t%0,%1,%2 ;a,b,limm"
+ [(set_attr "type" "add,add,add,sub,add,add,add,add,add,add,add,sub,add,bxor,add,add,add")
+ (set_attr "iscompact" "true,true,true,true,true,true,true,true,false,false,false,false,false,false,true_limm,false,false")
+ (set_attr "length" "2,2,2,2,2,2,2,2,4,4,4,4,4,4,6,8,8")
+ (set_attr "predicable" "no,no,no,no,no,no,no,no,yes,yes,no,no,no,no,no,yes,no")
])
;; ARCv2 MPYW and MPYUW
@@ -3236,7 +3233,7 @@ (define_insn "andsi3_i" ;0 1 2 3 4 5
? "extb%? %0,%1%&" : "ext%_%? %0,%1%&");
case 9: case 14: return \"bic%? %0,%1,%n2-1\";
case 15:
- return "movb.cl %0,%1,%p2,%p2,%s2";
+ return "movb.cl %0,%1,%p2,%p2,%x2";
case 19:
const char *tmpl;
@@ -4090,8 +4087,8 @@ (define_insn "*call_i"
"@
jl%!%* [%0]%&
jl%!%* [%0]
- jli_s %S0
- sjli %S0
+ jli_s %J0
+ sjli %J0
bl%!%* %P0
bl%!%* %P0
jl%!%* %0
@@ -4134,8 +4131,8 @@ (define_insn "*call_value_i"
"@
jl%!%* [%1]%&
jl%!%* [%1]
- jli_s %S1
- sjli %S1
+ jli_s %J1
+ sjli %J1
bl%!%* %P1;1
bl%!%* %P1;1
jl%!%* %1
@@ -46,7 +46,7 @@ (define_insn_reservation "sr" 1
(define_insn_reservation "core_insn" 1
(and (eq_attr "tune_arc700" "true")
- (eq_attr "type" "unary, move, binary"))
+ (eq_attr "type" "unary, move, binary, add, sub, bxor"))
"issue+core, nothing, write_port")
(define_insn_reservation "cmove" 1
@@ -46,7 +46,7 @@ (define_insn_reservation "hs_alu0" 4
(define_insn_reservation "hs_alu1" 4
(and (match_test "TARGET_HS")
(eq_attr "tune" "none")
- (eq_attr "type" "move, cmove, unary, binary, compare, misc"))
+ (eq_attr "type" "move, cmove, unary, binary, compare, misc, add, sub, bxor"))
"hs_issue+x1, nothing*3")
(define_insn_reservation "hs_divrem" 13
@@ -77,7 +77,7 @@ (define_insn_reservation "hs4x_adv_alul_op" 6
(define_insn_reservation "hs4x_basic_alue_op" 1
(and (match_test "TARGET_HS")
(eq_attr "tune" "archs4x, archs4xd")
- (eq_attr "type" "move, cmove, unary, binary, compare, misc"))
+ (eq_attr "type" "move, cmove, unary, binary, compare, misc, add, sub, bxor"))
"(hs4x_issue0 | hs4x_issue1) + hs4x_y1")
(define_insn_reservation "hs4x_basic_alul_op" 4
@@ -112,12 +112,6 @@ (define_constraint "CnL"
(and (match_code "const_int")
(match_test "UNSIGNED_INT6 (~ival)")))
-(define_constraint "CmL"
- "@internal
- Two's complement of a 6-bit unsigned integer constant"
- (and (match_code "const_int")
- (match_test "UNSIGNED_INT6 (-ival)")))
-
(define_constraint "C16"
"@internal
A 16-bit signed integer constant"
@@ -160,42 +154,17 @@ (define_constraint "Cn0"
(and (match_code "const_int")
(match_test "ival <= 0")))
-(define_constraint "Cca"
- "@internal
- Conditional or three-address add / sub constant"
- (and (match_code "const_int")
- (match_test "ival == (HOST_WIDE_INT)(HOST_WIDE_INT_M1U << 31)
- || (ival >= -0x1f8 && ival <= 0x1f8
- && ((ival >= 0 ? ival : -ival)
- <= 0x3f * (ival & -ival)))")))
-
-; intersection of "O" and "Cca".
-(define_constraint "CL2"
- "@internal
- A 6-bit unsigned integer constant times 2"
- (and (match_code "const_int")
- (match_test "!(ival & ~126)")))
-
(define_constraint "CM4"
"@internal
- A 5-bit unsigned integer constant times 4"
+ A valid 5-bit unsigned stack offset for a short add"
(and (match_code "const_int")
(match_test "!(ival & ~124)")))
-(define_constraint "Csp"
+(define_constraint "CP4"
"@internal
- A valid stack pointer offset for a short add"
+ A valid 5-bit unsigned stack offset for a short sub"
(and (match_code "const_int")
- (match_test "!(ival & ~124) || !(-ival & ~124)")))
-
-(define_constraint "C2a"
- "@internal
- Unconditional two-address add / sub constant"
- (and (match_code "const_int")
- (match_test "ival == (HOST_WIDE_INT) (HOST_WIDE_INT_M1U << 31)
- || (ival >= -0x4000 && ival <= 0x4000
- && ((ival >= 0 ? ival : -ival)
- <= 0x7ff * (ival & -ival)))")))
+ (match_test "!(-ival & ~124)")))
(define_constraint "C0p"
"@internal
@@ -532,3 +501,35 @@ (define_register_constraint "Rzd"
"TARGET_CODE_DENSITY ? R0_REGS : NO_REGS"
"@internal
@code{r0} register for code density instructions.")
+
+(define_constraint "C6u" "@internal
+ A 6-bit unsigned integer constant shifted by x-bit(s)"
+ (and (match_code "const_int")
+ (ior (match_test "UNSIGNED_INT9_SHIFTED (ival,3)")
+ (match_test "UNSIGNED_INT8_SHIFTED (ival,2)")
+ (match_test "UNSIGNED_INT7_SHIFTED (ival,1)")
+ (match_test "UNSIGNED_INT6 (ival)"))))
+
+(define_constraint "C6n" "@internal
+ A negative 6-bit integer constant shifted by x-bit(s) used by add."
+ (and (match_code "const_int")
+ (match_test "ival < 0")
+ (match_test "SIGNED_INT10(ival)")
+ (ior (match_test "UNSIGNED_INT9_SHIFTED (-ival,3)")
+ (match_test "UNSIGNED_INT8_SHIFTED (-ival,2)")
+ (match_test "UNSIGNED_INT7_SHIFTED (-ival,1)")
+ (match_test "UNSIGNED_INT6 (-ival)"))))
+
+(define_constraint "CIs" "@internal
+ A 12-bit signed integer constant shifted by x-bit(s)"
+ (and (match_code "const_int")
+ (ior (match_test "SIGNED_INT15_SHIFTED (ival,3)")
+ (match_test "SIGNED_INT14_SHIFTED (ival,2)")
+ (match_test "SIGNED_INT13_SHIFTED (ival,1)")
+ (match_test "SIGNED_INT12 (ival)"))))
+
+(define_constraint "C4p"
+ "@internal
+ Matches 0x8000_0000"
+ (and (match_code "const_int")
+ (match_test "ival == (HOST_WIDE_INT) (HOST_WIDE_INT_M1U << 31)")))