Commit ceaaa9fe by Joern Rennecke Committed by Joern Rennecke

arc.h (SYMBOL_FLAG_CMEM): Define.

2016-04-28  Joern Rennecke  <joern.rennecke@embecosm.com>
            Andrew Burgess  <andrew.burgess@embecosm.com>
gcc:
        * config/arc/arc.h (SYMBOL_FLAG_CMEM): Define.
        (TARGET_NPS_CMEM_DEFAULT): Provide default definition.
        * config/arc/arc.c (arc_address_cost): Return 0 for cmem_address.
        (arc_encode_section_info): Set SYMBOL_FLAG_CMEM where indicated.
        * config/arc/arc.opt (mcmem): New option.
        * config/arc/arc.md (*extendqihi2_i): Add r/Uex alternative,
        supply length for r/m alternative.
        (*extendqisi2_ac): Likewise.
        (*extendhisi2_i): Add r/Uex alternative, supply length for r/m and
        r/Uex alternative.
        (movqi_insn): Add r/Ucm and Ucm/?Rac alternatives.
        (movhi_insn): Likewise.
        (movsi_insn): Add r/Ucm,Ucm/w alternatives.
        (*zero_extendqihi2_i): Add r/Ucm alternative.
        (*zero_extendqisi2_ac): Likewise.
        (*zero_extendhisi2_i): Likewise.
        * config/arc/constraints.md (Uex): New memory constraint.
        (Ucm): New define_constraint.
        * config/arc/predicates.md (long_immediate_loadstore_operand):
        Return 0 for MEM with cmem_address address.
        (cmem_address_0): New predicates.
        (cmem_address_1): Likewise.
        (cmem_address_2): Likewise.
        (cmem_address): Likewise.
gcc/testsuite:
        * gcc.target/arc/cmem-1.c: New file.
        * gcc.target/arc/cmem-2.c: New file.
        * gcc.target/arc/cmem-3.c: New file.
        * gcc.target/arc/cmem-4.c: New file.
        * gcc.target/arc/cmem-5.c: New file.
        * gcc.target/arc/cmem-6.c: New file.
        * gcc.target/arc/cmem-7.c: New file.
        * gcc.target/arc/cmem-ld.inc: New file.
        * gcc.target/arc/cmem-st.inc: New file.

Co-Authored-By: Andrew Burgess <andrew.burgess@embecosm.com>

From-SVN: r235595
parent dc236a9d
2016-04-28 Joern Rennecke <joern.rennecke@embecosm.com>
Andrew Burgess <andrew.burgess@embecosm.com>
* config/arc/arc.c (arc_conditional_register_usage): Take
TARGET_RRQ_CLASS into account.
(arc_print_operand): Support printing 'p' and 's' operands.
* config/arc/arc.h (TARGET_NPS_BITOPS_DEFAULT): Provide default
as 0.
(TARGET_RRQ_CLASS): Define.
(IS_POWEROF2_OR_0_P): Define.
* config/arc/arc.md (*movsi_insn): Add w/Clo, w/Chi, and w/Cbi
alternatives.
(*tst_movb): New define_insn.
(*tst): Avoid recognition if it could prevent '*tst_movb'
combination; replace c/CnL with c/Chs alternative.
(*tst_bitfield_tst): New define_insn.
(*tst_bitfield_asr): New define_insn.
(*tst_bitfield): New define_insn.
(andsi3_i): Add Rrq variant.
(extzv): New define_expand.
(insv): New define_expand.
(*insv_i): New define_insn.
(*movb): New define_insn.
(*movb_signed): New define_insn.
(*movb_high): New define_insn.
(*movb_high_signed): New define_insn.
(*movb_high_signed + 1): New define_split pattern.
(*mrgb): New define_insn.
(*mrgb + 1): New define_peephole2 pattern.
(*mrgb + 2): New define_peephole2 pattern.
* config/arc/arc.opt (mbitops): New option for nps400, uses
TARGET_NPS_BITOPS_DEFAULT.
* config/arc/constraints.md (q): Make register class conditional.
(Rrq): New register constraint.
(Chs): New constraint.
(Clo): New constraint.
(Chi): New constraint.
(Cbf): New constraint.
(Cbn): New constraint.
(C18): New constraint.
(Cbi): New constraint.
2016-04-28 Segher Boessenkool <segher@kernel.crashing.org>
* cfganal.c (bitmap_intersection_of_succs): Delete assert checking
......
......@@ -1430,7 +1430,8 @@ arc_conditional_register_usage (void)
{
if (i < 29)
{
if (TARGET_Q_CLASS && ((i <= 3) || ((i >= 12) && (i <= 15))))
if ((TARGET_Q_CLASS || TARGET_RRQ_CLASS)
&& ((i <= 3) || ((i >= 12) && (i <= 15))))
arc_regno_reg_class[i] = ARCOMPACT16_REGS;
else
arc_regno_reg_class[i] = GENERAL_REGS;
......@@ -1447,12 +1448,12 @@ arc_conditional_register_usage (void)
arc_regno_reg_class[i] = NO_REGS;
}
/* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS has not been activated. */
/* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS / TARGET_RRQ_CLASS
has not been activated. */
if (!TARGET_Q_CLASS && !TARGET_RRQ_CLASS)
CLEAR_HARD_REG_SET(reg_class_contents [ARCOMPACT16_REGS]);
if (!TARGET_Q_CLASS)
{
CLEAR_HARD_REG_SET(reg_class_contents [ARCOMPACT16_REGS]);
CLEAR_HARD_REG_SET(reg_class_contents [AC16_BASE_REGS]);
}
CLEAR_HARD_REG_SET(reg_class_contents [AC16_BASE_REGS]);
gcc_assert (FIRST_PSEUDO_REGISTER >= 144);
......@@ -2994,6 +2995,8 @@ static int output_scaled = 0;
'Z': log2(x+1)-1
'z': log2
'M': log2(~x)
'p': bit Position of lsb
's': size of bit field
'#': condbranch delay slot suffix
'*': jump delay slot suffix
'?' : nonjump-insn suffix for conditional execution or short instruction
......@@ -3044,6 +3047,24 @@ arc_print_operand (FILE *file, rtx x, int code)
return;
case 'p':
if (GET_CODE (x) == CONST_INT)
fprintf (file, "%d", exact_log2 (INTVAL (x) & -INTVAL (x)));
else
output_operand_lossage ("invalid operand to %%p code");
return;
case 's':
if (GET_CODE (x) == CONST_INT)
{
HOST_WIDE_INT i = INTVAL (x);
HOST_WIDE_INT s = exact_log2 (i & -i);
fprintf (file, "%d", exact_log2 (((0xffffffffUL & i) >> s) + 1));
}
else
output_operand_lossage ("invalid operand to %%s code");
return;
case '#' :
/* Conditional branches depending on condition codes.
Note that this is only for branches that were known to depend on
......
......@@ -326,10 +326,18 @@ along with GCC; see the file COPYING3. If not see
#define UNALIGNED_ACCESS_DEFAULT 0
#endif
#ifndef TARGET_NPS_BITOPS_DEFAULT
#define TARGET_NPS_BITOPS_DEFAULT 0
#endif
#ifndef TARGET_NPS_CMEM_DEFAULT
#define TARGET_NPS_CMEM_DEFAULT 0
#endif
/* Enable the RRQ instruction alternatives. */
#define TARGET_RRQ_CLASS TARGET_NPS_BITOPS
/* Target machine storage layout. */
/* We want zero_extract to mean the same
......@@ -1033,6 +1041,7 @@ extern int arc_initial_elimination_offset(int from, int to);
/* Is the argument a const_int rtx, containing an exact power of 2 */
#define IS_POWEROF2_P(X) (! ( (X) & ((X) - 1)) && (X))
#define IS_POWEROF2_OR_0_P(X) (! ( (X) & ((X) - 1)))
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class.
......
......@@ -700,8 +700,8 @@
; insns it should lengthen the return insn.
; N.B. operand 1 of alternative 7 expands into pcl,symbol@gotpc .
(define_insn "*movsi_insn"
[(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,w, w,w, w,???w, ?w, w,Rcq#q, w,Rcq, S,Us<,RcqRck,!*x,r,r,Ucm,m,???m,VUsc")
(match_operand:SI 1 "move_src_operand" " cL,cP,Rcq#q,cL,I,Crr,?Rac,Cpc,Clb,?Cal,?Cal,T,Rcq,RcqRck,Us>,Usd,Ucm,m,w,c,?Rac,C32"))]
[(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,w,w,w,w,w,w,w,???w,?w,w,Rcq#q,w,Rcq,S,Us<,RcqRck,!*x,r,r,Ucm,m,???m,VUsc")
(match_operand:SI 1 "move_src_operand" "cL,cP,Rcq#q,cL,I,Crr,Clo,Chi,Cbi,?Rac,Cpc,Clb,?Cal,?Cal,T,Rcq,RcqRck,Us>,Usd,Ucm,m,w,c,?Rac,C32"))]
"register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)
|| (CONSTANT_P (operands[1])
......@@ -716,29 +716,32 @@
mov%? %0,%1 ;3
mov%? %0,%1 ;4
ror %0,((%1*2+1) & 0x3f) ;5
mov%? %0,%1 ;6
add %0,%S1 ;7
movl.cl %0,%1 ;6
movh.cl %0,%L1>>16 ;7
* return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl %0,%1 >> %p1,%p1,8;8\" : \"movbi.cl %0,%L1 >> 24,24,8;9\";
mov%? %0,%1 ;9
add %0,%S1 ;10
* return arc_get_unalign () ? \"add %0,pcl,%1-.+2\" : \"add %0,pcl,%1-.\";
mov%? %0,%S1%& ;9
mov%? %0,%S1 ;10
ld%? %0,%1%& ;11
st%? %1,%0%& ;12
mov%? %0,%S1%& ;12
mov%? %0,%S1 ;13
ld%? %0,%1%& ;14
st%? %1,%0%& ;15
* return arc_short_long (insn, \"push%? %1%&\", \"st%U0 %1,%0%&\");
* return arc_short_long (insn, \"pop%? %0%&\", \"ld%U1 %0,%1%&\");
ld%? %0,%1%& ;15
xld%U1 %0,%1 ;16
ld%U1%V1 %0,%1 ;17
xst%U0 %1,%0 ;18
st%U0%V0 %1,%0 ;19
st%U0%V0 %1,%0 ;20
st%U0%V0 %S1,%0 ;21"
[(set_attr "type" "move,move,move,move,move,two_cycle_core,move,binary,binary,move,move,load,store,store,load,load,load,load,store,store,store,store")
(set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,maybe_limm,false,true,true,true,true,true,false,false,false,false,false,false")
ld%? %0,%1%& ;18
xld%U1 %0,%1 ;19
ld%U1%V1 %0,%1 ;20
xst%U0 %1,%0 ;21
st%U0%V0 %1,%0 ;22
st%U0%V0 %1,%0 ;23
st%U0%V0 %S1,%0 ;24"
[(set_attr "type" "move,move,move,move,move,two_cycle_core,shift,shift,shift,move,binary,binary,move,move,load,store,store,load,load,load,load,store,store,store,store")
(set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,false,false,false,maybe_limm,false,true,true,true,true,true,false,false,false,false,false,false")
; Use default length for iscompact to allow for COND_EXEC. But set length
; of Crr to 4.
(set_attr "length" "*,*,*,4,4,4,4,8,8,*,8,*,*,*,*,*,4,*,4,*,*,8")
(set_attr "predicable" "yes,no,yes,yes,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
(set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
(set_attr "length" "*,*,*,4,4,4,4,4,4,4,8,8,*,8,*,*,*,*,*,4,*,4,*,*,8")
(set_attr "predicable" "yes,no,yes,yes,no,no,no,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
(set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
;; Sometimes generated by the epilogue code. We don't want to
;; recognize these addresses in general, because the limm is costly,
......@@ -809,6 +812,24 @@
(set_attr "cond" "set_zn")
(set_attr "length" "4")])
; reload is too stingy with reloads for Rrq/Cbf/Rrq when it sees
; a c/???Cal/X alternative, so we say it's c/???Cal/c instead,
; even if we don't need the clobber.
(define_insn_and_split "*tst_movb"
[(set
(match_operand 0 "cc_register" "")
(match_operator 4 "zn_compare_operator"
[(and:SI
(match_operand:SI 1 "register_operand" "%Rcq,Rcq, c, c, c, c,Rrq, 3, c")
(match_operand:SI 2 "nonmemory_operand" "Rcq,C0p,cI,C1p,Ccp,Chs,Cbf,Cbf,???Cal"))
(const_int 0)]))
(clobber (match_scratch:SI 3 "=X,X,X,X,X,X,Rrq,Rrq,c"))]
"TARGET_NPS_BITOPS"
"movb.f.cl %3,%1,%p2,%p2,%s2"
"reload_completed
&& (extract_constrain_insn_cached (insn), (which_alternative & ~1) != 6)"
[(set (match_dup 0) (match_dup 4))])
(define_insn "*tst"
[(set
(match_operand 0 "cc_register" "")
......@@ -817,12 +838,14 @@
(match_operand:SI 1 "register_operand"
"%Rcq,Rcq, c, c, c, c, c, c")
(match_operand:SI 2 "nonmemory_operand"
" Rcq,C0p,cI,cL,C1p,Ccp,CnL,Cal"))
" Rcq,C0p,cI,cL,C1p,Ccp,Chs,Cal"))
(const_int 0)]))]
"(register_operand (operands[1], SImode)
&& nonmemory_operand (operands[2], SImode))
|| (memory_operand (operands[1], SImode)
&& satisfies_constraint_Cux (operands[2]))"
"reload_completed
|| !satisfies_constraint_Cbf (operands[2])
|| satisfies_constraint_C0p (operands[2])
|| satisfies_constraint_I (operands[2])
|| satisfies_constraint_C1p (operands[2])
|| satisfies_constraint_Chs (operands[2])"
"*
switch (which_alternative)
{
......@@ -835,17 +858,79 @@
case 5:
return \"bclr%?.f 0,%1,%M2%&\";
case 6:
return \"bic%?.f 0,%1,%n2-1\";
return \"asr.f 0,%1,%p2\";
default:
gcc_unreachable ();
}
"
[(set_attr "iscompact" "maybe,maybe,false,false,false,false,false,false")
(set_attr "type" "compare")
(set_attr "type" "compare,compare,compare,compare,compare,compare,shift,compare")
(set_attr "length" "*,*,4,4,4,4,4,8")
(set_attr "predicable" "no,yes,no,yes,no,no,no,yes")
(set_attr "cond" "set_zn")])
; ??? Sometimes, if an AND with a constant can be expressed as a zero_extract,
; combine will do that and not try the AND.
; It would take 66 constraint combinations to describe the zero_extract
; constants that are covered by the 12-bit signed constant for tst
; (excluding the ones that are better done by mov or btst).
; so we rather use an extra pattern for tst;
; since this is about constants, reload shouldn't care.
(define_insn "*tst_bitfield_tst"
[(set (match_operand:CC_ZN 0 "cc_set_register" "")
(match_operator 4 "zn_compare_operator"
[(zero_extract:SI
(match_operand:SI 1 "register_operand" "c")
(match_operand:SI 2 "const_int_operand" "n")
(match_operand:SI 3 "const_int_operand" "n"))
(const_int 0)]))]
"INTVAL (operands[2]) > 1
&& (INTVAL (operands[3]) + INTVAL (operands[2]) <= 11
|| (INTVAL (operands[3]) <= 11
&& INTVAL (operands[3]) + INTVAL (operands[2]) == 32))"
"tst %1,(1<<%2)-1<<%3"
[(set_attr "type" "compare")
(set_attr "cond" "set_zn")
(set_attr "length" "4")])
; Likewise for asr.f.
(define_insn "*tst_bitfield_asr"
[(set (match_operand:CC_ZN 0 "cc_set_register" "")
(match_operator 4 "zn_compare_operator"
[(zero_extract:SI
(match_operand:SI 1 "register_operand" "c")
(match_operand:SI 2 "const_int_operand" "n")
(match_operand:SI 3 "const_int_operand" "n"))
(const_int 0)]))]
"INTVAL (operands[2]) > 1
&& INTVAL (operands[3]) + INTVAL (operands[2]) == 32"
"asr.f 0,%1,%3"
[(set_attr "type" "shift")
(set_attr "cond" "set_zn")
(set_attr "length" "4")])
(define_insn "*tst_bitfield"
[(set (match_operand:CC_ZN 0 "cc_set_register" "")
(match_operator 5 "zn_compare_operator"
[(zero_extract:SI
(match_operand:SI 1 "register_operand" "%Rcqq,c, c,Rrq,c")
(match_operand:SI 2 "const_int_operand" "N,N, n,Cbn,n")
(match_operand:SI 3 "const_int_operand" "n,n,C_0,Cbn,n"))
(const_int 0)]))
(clobber (match_scratch:SI 4 "=X,X,X,Rrq,X"))]
""
"@
btst%? %1,%3
btst %1,%3
bmsk.f 0,%1,%2-1
movb.f.cl %4,%1,%3,%3,%2
and.f 0,%1,((1<<%2)-1)<<%3"
[(set_attr "iscompact" "maybe,false,false,false,false")
(set_attr "type" "compare,compare,compare,shift,compare")
(set_attr "cond" "set_zn")
(set_attr "length" "*,4,4,4,8")])
(define_insn "*commutative_binary_comparison"
[(set (match_operand:CC_ZN 0 "cc_set_register" "")
(match_operator:CC_ZN 5 "zn_compare_operator"
......@@ -2956,30 +3041,40 @@
operands[1] = arc_rewrite_small_data (operands[1]);")
(define_insn "andsi3_i"
[(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcqq,Rcqq,Rcqq,Rcw,Rcw,Rcw,Rcw,Rcw,Rcw, w, w, w, w,w,Rcw, w, W")
(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,Rcq, 0, 0,Rcqq, 0, c, 0, 0, 0, 0, c, c, c, c,0, 0, c, o")
(match_operand:SI 2 "nonmemory_operand" " Rcqq, 0, C1p, Ccp, Cux, cL, 0,C1p,Ccp,CnL, I, Lc,C1p,Ccp,CnL,I,Cal,Cal,Cux")))]
[(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcqq,Rcqq,Rcqq,Rcw,Rcw,Rcw,Rcw,Rcw,Rcw,w,w,w,w,Rrq,w,Rcw,w,W")
(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,Rcq,0,0,Rcqq,0,c,0,0,0,0,c,c,c,c,Rrq,0,0,c,o")
(match_operand:SI 2 "nonmemory_operand" "Rcqq,0,C1p,Ccp,Cux,cL,0,C1p,Ccp,CnL,I,Lc,C1p,Ccp,CnL,Cbf,I,Cal,Cal,Cux")))]
"(register_operand (operands[1], SImode)
&& nonmemory_operand (operands[2], SImode))
|| (memory_operand (operands[1], SImode)
&& satisfies_constraint_Cux (operands[2]))"
"*
{
switch (which_alternative)
{
case 0: case 5: case 10: case 11: case 15: case 16: case 17:
return \"and%? %0,%1,%2%&\";
case 0: case 5: case 10: case 11: case 16: case 17: case 18:
return "and%? %0,%1,%2%&";
case 1: case 6:
return \"and%? %0,%2,%1%&\";
return "and%? %0,%2,%1%&";
case 2: case 7: case 12:
return \"bmsk%? %0,%1,%Z2%&\";
return "bmsk%? %0,%1,%Z2%&";
case 3: case 8: case 13:
return \"bclr%? %0,%1,%M2%&\";
return "bclr%? %0,%1,%M2%&";
case 4:
return (INTVAL (operands[2]) == 0xff
? \"extb%? %0,%1%&\" : \"ext%_%? %0,%1%&\");
? "extb%? %0,%1%&" : "ext%_%? %0,%1%&");
case 9: case 14: return \"bic%? %0,%1,%n2-1\";
case 18:
case 15:
return "movb.cl %0,%1,%p2,%p2,%s2";
case 19:
const char *tmpl;
if (satisfies_constraint_Ucm (operands[1]))
tmpl = (INTVAL (operands[2]) == 0xff
? "xldb%U1 %0,%1" : "xld%_%U1 %0,%1");
else
tmpl = INTVAL (operands[2]) == 0xff ? "ldb %0,%1" : "ld%_ %0,%1";
if (TARGET_BIG_ENDIAN)
{
rtx xop[2];
......@@ -2987,21 +3082,19 @@
xop[0] = operands[0];
xop[1] = adjust_address (operands[1], QImode,
INTVAL (operands[2]) == 0xff ? 3 : 2);
output_asm_insn (INTVAL (operands[2]) == 0xff
? \"ldb %0,%1\" : \"ld%_ %0,%1\",
xop);
return \"\";
output_asm_insn (tmpl, xop);
return "";
}
return INTVAL (operands[2]) == 0xff ? \"ldb %0,%1\" : \"ld%_ %0,%1\";
return tmpl;
default:
gcc_unreachable ();
}
}"
[(set_attr "iscompact" "maybe,maybe,maybe,maybe,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false")
(set_attr "type" "binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,load")
(set_attr "length" "*,*,*,*,*,4,4,4,4,4,4,4,4,4,4,4,8,8,*")
(set_attr "predicable" "no,no,no,no,no,yes,yes,yes,yes,yes,no,no,no,no,no,no,yes,no,no")
(set_attr "cond" "canuse,canuse,canuse,canuse,nocond,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,nocond,nocond,canuse_limm,canuse,nocond,nocond")])
}
[(set_attr "iscompact" "maybe,maybe,maybe,maybe,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false")
(set_attr "type" "binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,shift,binary,binary,binary,load")
(set_attr "length" "*,*,*,*,*,4,4,4,4,4,4,4,4,4,4,4,4,8,8,*")
(set_attr "predicable" "no,no,no,no,no,yes,yes,yes,yes,yes,no,no,no,no,no,no,no,yes,no,no")
(set_attr "cond" "canuse,canuse,canuse,canuse,nocond,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,nocond,nocond,nocond,canuse_limm,canuse,nocond,nocond")])
; combiner splitter, pattern found in ldtoa.c .
; and op3,op0,op1 / cmp op3,op2 -> add op3,op0,op4 / bmsk.f 0,op3,op1
......@@ -5717,7 +5810,6 @@
[(set_attr "length" "4")
(set_attr "type" "misc")])
;; FPU/FPX expands
;;add
......@@ -5862,6 +5954,196 @@
gcc_unreachable ();
")
(define_expand "extzv"
[(set (match_operand:SI 0 "register_operand" "")
(zero_extract:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "const_int_operand" "")
(match_operand:SI 3 "const_int_operand" "")))]
"TARGET_NPS_BITOPS")
; We need a sanity check in the instuction predicate because combine
; will throw any old rubbish at us and see what sticks.
(define_insn "*extzv_i"
[(set (match_operand:SI 0 "register_operand" "=Rrq")
(zero_extract:SI (match_operand:SI 1 "register_operand" "Rrq")
(match_operand:SI 2 "const_int_operand" "n")
(match_operand:SI 3 "const_int_operand" "n")))]
"TARGET_NPS_BITOPS && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32"
"movb.cl %0,%1,0,%3,%2"
[(set_attr "type" "shift")
(set_attr "length" "4")])
(define_expand "insv"
[(set (zero_extract:SI (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "const_int_operand" "")
(match_operand:SI 2 "const_int_operand" ""))
(match_operand:SI 3 "nonmemory_operand" ""))]
"TARGET_NPS_BITOPS"
{
int size = INTVAL (operands[1]);
if (size != 1 && size != 2 && size != 4 && size != 8)
operands[3] = force_reg (SImode, operands[3]);
})
(define_insn "*insv_i"
[(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+w,Rrq")
(match_operand:SI 1 "const_int_operand" "C18,n")
(match_operand:SI 2 "const_int_operand" "n,n"))
(match_operand:SI 3 "nonmemory_operand" "P,Rrq"))]
"TARGET_NPS_BITOPS
&& (register_operand (operands[3], SImode)
|| satisfies_constraint_C18 (operands[1]))"
"@
movbi %0,%0,%3,%2,%1
movb %0,%0,%3,%2,0,%1"
[(set_attr "type" "shift")
(set_attr "length" "4")])
(define_insn "*movb"
[(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
(match_operand:SI 1 "const_int_operand" "n")
(match_operand:SI 2 "const_int_operand" "n"))
(zero_extract:SI (match_operand:SI 3 "register_operand" "Rrq")
(match_dup 1)
(match_operand:SI 4 "const_int_operand" "n")))]
"TARGET_NPS_BITOPS"
"movb %0,%0,%3,%2,%4,%1"
[(set_attr "type" "shift")
(set_attr "length" "4")])
(define_insn "*movb_signed"
[(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
(match_operand:SI 1 "const_int_operand" "n")
(match_operand:SI 2 "const_int_operand" "n"))
(sign_extract:SI (match_operand:SI 3 "register_operand" "Rrq")
(match_dup 1)
(match_operand:SI 4 "const_int_operand" "n")))]
"TARGET_NPS_BITOPS"
"movb %0,%0,%3,%2,%4,%1"
[(set_attr "type" "shift")
(set_attr "length" "4")])
(define_insn "*movb_high"
[(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
(match_operand:SI 1 "const_int_operand" "n")
(match_operand:SI 2 "const_int_operand" "n"))
(lshiftrt:SI (match_operand:SI 3 "register_operand" "Rrq")
(match_operand:SI 4 "const_int_operand" "n")))]
"TARGET_NPS_BITOPS
&& INTVAL (operands[4]) + INTVAL (operands[1]) <= 32"
"movb %0,%0,%3,%2,%4,%1"
[(set_attr "type" "shift")
(set_attr "length" "4")])
; N.B.: when processing signed bitfields that fit in the top half of
; a word, gcc will use a narrow sign extending load, and in this case
; we will see INTVAL (operands[4]) + INTVAL (operands[1]) == 16 (or 8)
(define_insn "*movb_high_signed"
[(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
(match_operand:SI 1 "const_int_operand" "n")
(match_operand:SI 2 "const_int_operand" "n"))
(ashiftrt:SI (match_operand:SI 3 "register_operand" "Rrq")
(match_operand:SI 4 "const_int_operand" "n")))]
"TARGET_NPS_BITOPS
&& INTVAL (operands[4]) + INTVAL (operands[1]) <= 32"
"movb %0,%0,%3,%2,%4,%1"
[(set_attr "type" "shift")
(set_attr "length" "4")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "const_int_operand" ""))
(subreg:SI (match_operand 3 "") 0)))]
"TARGET_NPS_BITOPS
&& GET_MODE_BITSIZE (GET_MODE (operands[3])) <= INTVAL (operands[2])
&& !reg_overlap_mentioned_p (operands[0], operands[1])"
[(set (match_dup 0) (zero_extend:SI (match_dup 3)))
(set (zero_extract:SI (match_dup 0) (match_dup 4) (match_dup 2))
(match_dup 1))]
"operands[4] = GEN_INT (32 - INTVAL (operands[2]));")
(define_insn "*mrgb"
[(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
(match_operand:SI 1 "const_int_operand" "n")
(match_operand:SI 2 "const_int_operand" "n"))
(zero_extract:SI (match_dup 0) (match_dup 1)
(match_operand:SI 3 "const_int_operand" "n")))
(set (zero_extract:SI (match_dup 0)
(match_operand:SI 4 "const_int_operand" "n")
(match_operand:SI 5 "const_int_operand" "n"))
(zero_extract:SI (match_operand:SI 6 "register_operand" "Rrq")
(match_dup 4)
(match_operand:SI 7 "const_int_operand" "n")))]
"TARGET_NPS_BITOPS"
{
output_asm_insn ("mrgb %0,%0,%6,%2,%3,%1,%5,%7,%4", operands);
/* The ;%? updates the known unalignment. */
return arc_short_long (insn, ";%?", "nop_s");
}
[(set_attr "type" "shift")
(set_attr "length" "6")
(set_attr "iscompact" "true")])
;; combine fumbles combination of two movb patterns, and then the
;; combination is rejected by combinable_i3pat.
;; Thus, we can only use a peephole2 to combine two such insns.
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "register_operand" ""))
(set (zero_extract:SI (match_dup 0)
(match_operand:SI 2 "const_int_operand" "")
(match_operand:SI 3 "const_int_operand" ""))
(zero_extract:SI (match_dup 1)
(match_dup 2)
(match_operand:SI 4 "const_int_operand" "")))
(match_operand 9) ; unrelated insn scheduled here
(set (zero_extract:SI (match_dup 0)
(match_operand:SI 5 "const_int_operand" "")
(match_operand:SI 6 "const_int_operand" ""))
(zero_extract:SI (match_operand:SI 7 "register_operand" "")
(match_dup 5)
(match_operand:SI 8 "const_int_operand" "")))]
"TARGET_NPS_BITOPS
// Check that the second movb doesn't clobber an input of the extra insn.
&& !reg_overlap_mentioned_p (operands[0], operands[9])
// And vice versa.
&& !reg_set_p (operands[0], operands[9])
&& !reg_set_p (operands[7], operands[9])"
[(set (match_dup 0) (match_dup 1))
(parallel [(set (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2))
(zero_extract:SI (match_dup 3) (match_dup 1) (match_dup 4)))
(set (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2))
(zero_extract:SI (match_dup 3) (match_dup 1) (match_dup 4)))])
(match_dup 9)])
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "register_operand" ""))
(set (zero_extract:SI (match_dup 0)
(match_operand:SI 2 "const_int_operand" "")
(match_operand:SI 3 "const_int_operand" ""))
(zero_extract:SI (match_dup 1)
(match_dup 2)
(match_operand:SI 4 "const_int_operand" "")))
(set (match_dup 1) (match_operand 8))
(set (zero_extract:SI (match_dup 0)
(match_operand:SI 5 "const_int_operand" "")
(match_operand:SI 6 "const_int_operand" ""))
(zero_extract:SI (match_dup 1) (match_dup 5)
(match_operand:SI 7 "const_int_operand" "")))]
"TARGET_NPS_BITOPS
&& !reg_overlap_mentioned_p (operands[0], operands[8])"
[(set (match_dup 0) (match_dup 1))
(set (match_dup 1) (match_dup 8))
(parallel [(set (zero_extract:SI (match_dup 0) (match_dup 2) (match_dup 3))
(zero_extract:SI (match_dup 0) (match_dup 2) (match_dup 4)))
(set (zero_extract:SI (match_dup 0) (match_dup 5) (match_dup 6))
(zero_extract:SI (match_dup 1) (match_dup 5) (match_dup 7)))])
(match_dup 1)])
;; include the arc-FPX instructions
(include "fpx.md")
......
......@@ -470,6 +470,10 @@ Specify thread pointer register number
mtp-regno=none
Target RejectNegative Var(arc_tp_regno,-1)
mbitops
Target Report Var(TARGET_NPS_BITOPS) Init(TARGET_NPS_BITOPS_DEFAULT)
Enable use of NPS400 bit operations.
mcmem
Target Report Var(TARGET_NPS_CMEM) Init(TARGET_NPS_CMEM_DEFAULT)
Enable use of NPS400 xld/xst extension.
......
......@@ -66,10 +66,18 @@
Link Registers @code{ilink1}:@code{r29}, @code{ilink2}:@code{r30},
@code{blink}:@code{r31},")
(define_register_constraint "q" "ARCOMPACT16_REGS"
(define_register_constraint "q" "TARGET_Q_CLASS ? ARCOMPACT16_REGS : NO_REGS"
"Registers usable in ARCompact 16-bit instructions: @code{r0}-@code{r3},
@code{r12}-@code{r15}")
; NPS400 bitfield instructions require registers from the r0-r3,r12-r15
; range, and thus we need a register class and constraint that works
; independently of size optimization.
(define_register_constraint
"Rrq" "TARGET_RRQ_CLASS ? ARCOMPACT16_REGS : NO_REGS"
"Registers usable in NPS400 bitfield instructions: @code{r0}-@code{r3},
@code{r12}-@code{r15}")
(define_register_constraint "e" "AC16_BASE_REGS"
"Registers usable as base-regs of memory addresses in ARCompact 16-bit memory
instructions: @code{r0}-@code{r3}, @code{r12}-@code{r15}, @code{sp}")
......@@ -236,12 +244,60 @@
(and (match_code "const_int")
(match_test "ival == 0xff || ival == 0xffff")))
(define_constraint "Chs"
"@internal
constant for a highpart that can be checked with a shift (asr.f 0,rn,m)"
(and (match_code "const_int")
(match_test "IS_POWEROF2_P (-ival)")))
(define_constraint "Clo"
"@internal
constant that fits into 16 lower bits, for movl"
(and (match_code "const_int")
(match_test "TARGET_NPS_BITOPS")
(match_test "(ival & ~0xffffU) == 0")))
(define_constraint "Chi"
"@internal
constant that fits into 16 higher bits, for movh_i"
(and (match_code "const_int")
(match_test "TARGET_NPS_BITOPS")
(match_test "trunc_int_for_mode (ival >> 16, HImode) << 16 == ival")))
(define_constraint "Cbf"
"@internal
a mask for a bit field, for AND using movb_i"
(and (match_code "const_int")
(match_test "TARGET_NPS_BITOPS")
(match_test "IS_POWEROF2_OR_0_P (ival + (ival & -ival))")))
(define_constraint "Cbn"
"@internal
a constant integer, valid only if TARGET_NPS_BITOPS is true"
(and (match_code "const_int")
(match_test "TARGET_NPS_BITOPS")))
(define_constraint "C18"
"@internal
1,2,4 or 8"
(and (match_code "const_int")
(match_test "ival == 1 || ival == 2 || ival == 4 || ival == 8")))
(define_constraint "Crr"
"@internal
constant that can be loaded with ror b,u6"
(and (match_code "const_int")
(match_test "(ival & ~0x8000001f) == 0 && !arc_ccfsm_cond_exec_p ()")))
(define_constraint "Cbi"
"@internal
constant that can be loaded with movbi.cl"
(and (match_code "const_int")
(match_test "TARGET_NPS_BITOPS")
(match_test "!ival
|| ((ival & 0xffffffffUL) >> exact_log2 (ival & -ival)
<= 0xff)")))
;; Floating-point constraints
(define_constraint "G"
......
2016-04-28 Joern Rennecke <joern.rennecke@embecosm.com>
Andrew Burgess <andrew.burgess@embecosm.com>
* gcc.target/arc/extzv-1.c: New file.
* gcc.target/arc/insv-1.c: New file.
* gcc.target/arc/insv-2.c: New file.
* gcc.target/arc/movb-1.c: New file.
* gcc.target/arc/movb-2.c: New file.
* gcc.target/arc/movb-3.c: New file.
* gcc.target/arc/movb-4.c: New file.
* gcc.target/arc/movb-5.c: New file.
* gcc.target/arc/movb_cl-1.c: New file.
* gcc.target/arc/movb_cl-2.c: New file.
* gcc.target/arc/movbi_cl-1.c: New file.
* gcc.target/arc/movl-1.c: New file.
2016-04-28 Joern Rennecke <joern.rennecke@embecosm.com>
Andrew Burgess <andrew.burgess@embecosm.com>
* gcc.target/arc/cmem-1.c: New file.
* gcc.target/arc/cmem-2.c: New file.
* gcc.target/arc/cmem-3.c: New file.
......
/* { dg-do compile } */
/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
struct foo { unsigned a: 3, b: 5, c: 24; };
int
f (struct foo i)
{
return i.b;
}
/* { dg-final { scan-assembler "movb\.cl" } } */
/* { dg-do compile } */
/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
/* ??? Irrespective of insn set, generated code for this is a mess. */
struct foo { unsigned a: 3, b: 8, c: 21; };
struct foo
f (struct foo i)
{
i.b = 42;
return i;
}
struct foo
g (struct foo i, int j)
{
i.b = j;
return i;
}
/* { dg-final { scan-assembler "movbi\[ \t\]" } } */
/* { dg-final { scan-assembler "movb\[ \t\]" } } */
/* { dg-do compile } */
/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
struct foo { unsigned a: 3, b: 8, c: 21; } bar;
void
f (void)
{
bar.b = 42;
}
void
g (int j)
{
bar.b = j;
}
/* { dg-final { scan-assembler "movbi\[ \t\]" } } */
/* { dg-final { scan-assembler "movb\[ \t\]" } } */
/* { dg-do compile } */
/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
struct { unsigned a: 5, b: 8, c: 19; } foo;
struct { unsigned a: 3, b: 8, c: 21; } bar;
void
f (void)
{
bar.b = foo.b;
}
/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *5, *3, *8" { target arceb-*-* } } } */
/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *19, *21, *8" { target arc-*-* } } } */
/* { dg-do compile } */
/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
struct { unsigned a: 23, b: 9; } foo;
struct { unsigned a: 23, b: 9; } bar;
void
f (void)
{
bar.b = foo.b;
}
/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *23, *23, *9" { target arc-*-* } } } */
/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *0, *0, *9" { target arceb-*-* } } } */
/* { dg-do compile } */
/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
struct { int a: 23, b: 9; } foo;
struct { int a: 23, b: 9; } bar;
void
f (void)
{
bar.a = foo.a;
}
/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *0, *0, *23" { target arc-*-* } } } */
/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *9, *9, *23" { target arceb-*-* } } } */
/* { dg-do compile } */
/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
struct { int a: 13, b: 19; } foo;
struct { int a: 13, b: 19; } bar;
void
f (void)
{
bar.b = foo.b;
}
/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *13, *13, *19" { target arc-*-* } } } */
/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *0, *0, *19" { target arceb-*-* } } } */
/* { dg-do compile } */
/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
struct { int a: 23, b: 9; } foo;
struct { int a: 23, b: 9; } bar;
void
f (void)
{
bar.b = foo.b;
}
/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *23, *(23|7), *9" { target arc-*-* } } } */
/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *0, *0, *9" { target arceb-*-* } } } */
/* { dg-do compile } */
/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
int
f (int i)
{
return i & 0x0ffff000;
}
/* { dg-final { scan-assembler "movb\.cl" } } */
/* { dg-do compile } */
/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
extern void g (void);
int
f (int i)
{
if (i & 0x0ffff000)
g ();
}
/* { dg-final { scan-assembler "movb\.f\.cl" } } */
/* { dg-do compile } */
/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
int
f (int i)
{
return 0x6e00;
}
/* { dg-final { scan-assembler "mov(bi|l)\.cl" } } */
/* { dg-do compile } */
/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
int
f (void)
{
return 0xd00d;
}
int
g (void)
{
return 0x7ff00000;
}
/* { dg-final { scan-assembler "movl\.cl\[ \t\]" } } */
/* { dg-final { scan-assembler "movh\.cl\[ \t\]" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment