Commit 45d5d09c by Hans-Peter Nilsson

cris.md: Group related constants together, with comments local.

	* gcc/config/cris/cris.md: Group related constants together, with
	comments local.
	(CRIS_UNSPEC_PLT_GOTREL, CRIS_UNSPEC_PLT_PCREL, CRIS_UNSPEC_PCREL)
	(CRIS_UNSPEC_CASESI): New constants.
	(CRIS_UNSPEC_PLT): Remove constant.
	(CRIS_ACR_REGNUM): New constant.
	("slottable"): New attr alternatives "has_return_slot" and
	"has_call_slot".
	("cc"): New attr alternatives "noov32" and "rev".
	((eq_attr "slottable" "has_call_slot"))
	((eq_attr "slottable" "has_return_slot")): New define_delays.
	("movdi", "movsi"): Adjust operands for CRIS v32.
	("tstdi", "cmpdi", "adddi3", "subdi3", "uminsi3")
	("indirect_jump"): Ditto.  Make define_expand.
	("*tstdi_non_v32", "*tstdi_v32", "*tst<mode>_cmp")
	("*tst<mode>_non_cmp", "*cmpdi_non_v32", "*cmpdi_v32")
	("*movdi_v32", "*adddi3_non_v32", "*adddi3_v32")
	("*addsi3_non_v32", "*addsi3_v32", "*addhi3_non_v32")
	("*addhi3_v32", "*addqi3_non_v32", "*addqi3_v32")
	("*subdi3_non_v32", "*subdi3_v32", "*subsi3_non_v32")
	("*subsi3_v32", "*sub<mode>3_nonv32", "*sub<mode>3_v32")
	("*andqi3_non_v32", "*andqi3_v32", "*iorsi3_non_v32")
	("*iorsi3_v32", "*iorhi3_non_v32", "*iorhi3_v32")
	("*iorqi3_non_v32", "*iorqi3_v32", "*uminsi3_non_v32")
	("*uminsi3_v32", "*indirect_jump_non_v32", "*indirect_jump_v32")
	("*expanded_call_v32", "*expanded_call_value_v32"): New patterns,
	for the corresponding standard name.
	("tst<mode>"): Limit to BW and make define_expand.
	("tstsi"): Make separate insn, adjusting for CRIS v32.
	("*cmp_swapext<mode>"): Adjust for v32.  Specify "rev" for attr "cc".
	("cmpsi", "cmp<mode>"): Remove special cases for zero.  Specify
	attr "cc".
	("*btst"): Don't match for TARGET_CCINIT.  Replace test of
	register with compatible "cmpq 0".  Specify attr "cc".
	("*movdi_insn_non_v32"): New pattern, replacing "*movdi_insn" and
	define_split.
	(define_split for DI move): Match CRIS v32 only.
	("*movsi_got_load", "*movsi_internal", "*addi"): Adjust for CRIS
	v32.
	("load_multiple", "store_multiple", "*addsbw_v32", "*addubw_v32")
	("*adds<mode>_v32", "*addu<mode>_v32", "*bound<mode>_v32")
	("*casesi_jump_v32", "*expanded_andsi_v32", "*expanded_andhi_v32")
	("*extop<mode>si_v32", "*extopqihi_v32", "*andhi_lowpart_v32")
	("*andqi_lowpart_v32", "cris_casesi_v32"): New patterns. 
	("add<mode>3"): Make addsi3, addhi3 and addqi3 define_expand.
	("sub<mode>3"): Ditto subsi3, subhi3 and subqi3.
	("ior<mode>3"): Ditto iorsi3, iorhi3 and iorqi3.
	("*extopqihi_non_v32"): Replace "*extopqihi".
	("*extop<mode>si_non_v32"): Replace "*extop<mode>si".
	("*addxqihi_swap_non_v32"): Rename from "*extopqihi_swap", make
	non-v32 only.
	("*extop<mode>si_swap_non_v32"): Ditto "*extop<mode>si_swap".
	("*expanded_andsi_non_v32"): Ditto "*expanded_andsi".
	("*expanded_andhi_non_v32"): Ditto "*expanded_andhi".
	("*andhi_lowpart_non_v32"): Ditto "*andhi_lowpart".
	("*andqi_lowpart_non_v32"): Ditto "*andqi_lowpart".
	("*expanded_call_non_v32"): Ditto "*expanded_call".  Change from
	"cris_general_operand_or_plt_symbol" to "general_operand".
	("*expanded_call_value_non_v32") Ditto "*expanded_call_value".
	("*casesi_adds_w", "mstep_shift", "mstep_mul")
	("*expanded_call_side", "*expanded_call_value_side")
	(op-extend-split, op-extend-split-rx=rz, op-extend-split-swapped)
	(op-extend-split-swapped-rx=rz, op-extend, op-split-rx=rz)
	(op-split-swapped, op-split-swapped-rx=rz): Make non-v32 only.
	("dstep_mul", "xorsi3", "one_cmplsi2", "<shlr>si3")
	("*expanded_<shlr><mode>", "*<shlr><mode>_lowpart", "ashl<mode>3")
	("*ashl<mode>_lowpart", "abssi2", "clzsi2", "bswapsi2", "cris_swap_bits"): Specify "noov32" for
	attr "cc".
	("<su>mulsi3_highpart"): Ditto.  Correct operand 0 to
	register_operand.
	("andqi3"): Make define_expand.
	("*return_expanded"): For attr "slottable", change from "has_slot"
	to "has_return_slot".
	("cris_casesi_non_v32"): New pattern, old contents of "casesi".
	("casesi"): Divert into "cris_casesi_v32" and
	"cris_casesi_non_v32".
	(moversideqi, movemsideqi, mover2side): Require
	TARGET_SIDE_EFFECT_PREFIXES.
	(gotplt-to-plt, gotplt-to-plt-side): Change from CRIS_UNSPEC_PLT
	to CRIS_UNSPEC_PLT_GOTREL.

From-SVN: r130971
parent 6725c402
......@@ -54,23 +54,48 @@
;; [rX=gotless_symbol].
;; The movsi for a gotless symbol could be split (post reload).
;; UNSPEC Usage:
;; 0 PLT reference from call expansion: operand 0 is the address,
;; the mode is VOIDmode. Always wrapped in CONST.
;; 1 Stack frame deallocation barrier.
;; 2 The address of the global offset table as a source operand.
;; 3 The address of a global-offset-table-relative symbol + offset.
;; 4 The offset within GOT of a symbol.
;; 5 The offset within GOT of a symbol that has a PLT.
(define_constants ; FIXME: reorder sanely.
[(CRIS_UNSPEC_PLT 0)
(CRIS_UNSPEC_FRAME_DEALLOC 1)
(define_constants
[
;; PLT reference from call expansion: operand 0 is the address,
;; the mode is VOIDmode. Always wrapped in CONST.
;; The value is relative to the GOT.
(CRIS_UNSPEC_PLT_GOTREL 0)
;; PLT reference from call expansion: operand 0 is the address,
;; the mode is VOIDmode. Always wrapped in CONST.
;; The value is relative to the PC. It's arch-dependent whether
;; the offset counts from the start or the end of the current item.
(CRIS_UNSPEC_PLT_PCREL 1)
;; The address of the global offset table as a source operand.
(CRIS_UNSPEC_GOT 2)
;; The offset from the global offset table to the operand.
(CRIS_UNSPEC_GOTREL 3)
(CRIS_UNSPEC_GOTREAD 4)
(CRIS_UNSPEC_PLTGOTREAD 5)
(CRIS_UNSPEC_SWAP_BITS 6)])
;; The PC-relative offset to the operand. It's arch-dependent whether
;; the offset counts from the start or the end of the current item.
(CRIS_UNSPEC_PCREL 4)
;; The index into the global offset table of a symbol, while
;; also generating a GOT entry for the symbol.
(CRIS_UNSPEC_GOTREAD 5)
;; Similar to CRIS_UNSPEC_GOTREAD, but also generating a PLT entry.
(CRIS_UNSPEC_PLTGOTREAD 6)
;; Condition for v32 casesi jump, since it needs to have if_then_else
;; form with register as one branch and default label as other.
;; Operand 0 is const_int 0.
(CRIS_UNSPEC_CASESI 7)
;; Stack frame deallocation barrier.
(CRIS_UNSPEC_FRAME_DEALLOC 8)
;; Swap all 32 bits of the operand; 31 <=> 0, 30 <=> 1...
(CRIS_UNSPEC_SWAP_BITS 9)
])
;; Register numbers.
(define_constants
......@@ -78,6 +103,7 @@
(CRIS_STATIC_CHAIN_REGNUM 7)
(CRIS_FP_REGNUM 8)
(CRIS_SP_REGNUM 14)
(CRIS_ACR_REGNUM 15)
(CRIS_SRP_REGNUM 16)
(CRIS_MOF_REGNUM 17)
(CRIS_AP_REGNUM 18)
......@@ -100,14 +126,21 @@
;; In short, any "slottable" instruction must be 16 bit and not refer
;; to pc, or alter it.
;;
;; The possible values are "yes", "no" and "has_slot". Yes/no means if
;; the insn is slottable or not. Has_slot means that the insn is a
;; return insn or branch insn (which are not considered slottable since
;; that is generally true). Having the seemingly illogical value
;; "has_slot" means we do not have to add another attribute just to say
;; that an insn has a delay-slot, since it also infers that it is not
;; slottable. Better names for the attribute were found to be longer and
;; not add readability to the machine description.
;; The possible values are "yes", "no", "has_slot", "has_return_slot"
;; and "has_call_slot".
;; Yes/no tells whether the insn is slottable or not. Has_call_slot means
;; that the insn is a call insn, which for CRIS v32 has a delay-slot.
;; Of special concern is that no RTX_FRAME_RELATED insn must go in that
;; call delay slot, as it's located in the address *after* the call insn,
;; and the unwind machinery doesn't know about delay slots.
;; Has_slot means that the insn is a branch insn (which are
;; not considered slottable since that is generally true). Having the
;; seemingly illogical value "has_slot" means we do not have to add
;; another attribute just to say that an insn has a delay-slot, since it
;; also infers that it is not slottable. Better names for the attribute
;; were found to be longer and not add readability to the machine
;; description.
;; Has_return_slot is similar, for the return insn.
;;
;; The default that is defined here for this attribute is "no", not
;; slottable, not having a delay-slot, so there's no need to worry about
......@@ -125,19 +158,20 @@
;; constraint pattern for the slottable pattern. An alternative using
;; only "r" constraints is most often slottable.
(define_attr "slottable" "no,yes,has_slot" (const_string "no"))
(define_attr "slottable" "no,yes,has_slot,has_return_slot,has_call_slot"
(const_string "no"))
;; We also need attributes to sanely determine the condition code
;; state. See cris_notice_update_cc for how this is used.
(define_attr "cc" "none,clobber,normal" (const_string "normal"))
(define_attr "cc" "none,clobber,normal,noov32,rev" (const_string "normal"))
;; At the moment, this attribute is just used to help bb-reorder do its
;; work; the default 0 doesn't help it. Many insns have other lengths,
;; though none are shorter.
(define_attr "length" "" (const_int 2))
;; A branch or return has one delay-slot. The instruction in the
;; A branch has one delay-slot. The instruction in the
;; delay-slot is always executed, independent of whether the branch is
;; taken or not. Note that besides setting "slottable" to "has_slot",
;; there also has to be a "%#" at the end of a "delayed" instruction
......@@ -147,6 +181,33 @@
(define_delay (eq_attr "slottable" "has_slot")
[(eq_attr "slottable" "yes") (nil) (nil)])
;; We can't put prologue insns in call-insn delay-slots when
;; DWARF2 unwind info is emitted, because the unwinder matches the
;; address after the insn. It must see the return address of a call at
;; a position at least *one byte after* the insn, or it'll think that
;; the insn hasn't been executed. If the insn is in a delay-slot of a
;; call, it's just *exactly* after the insn.
(define_delay (eq_attr "slottable" "has_call_slot")
[(and (eq_attr "slottable" "yes")
(ior (eq (symbol_ref "RTX_FRAME_RELATED_P (insn)")
(const_int 0))
(eq (symbol_ref "flag_exceptions")
(const_int 0))))
(nil) (nil)])
;; The insn in the return insn slot must not be the
;; return-address-register restore. FIXME: Use has_slot and express
;; as a parallel with a use of the return-address-register (currently
;; only SRP). However, this requires an amount of fixing tests for
;; naked RETURN in middle-end.
(define_delay (eq_attr "slottable" "has_return_slot")
[(and (eq_attr "slottable" "yes")
(eq (symbol_ref "dead_or_set_regno_p (insn, CRIS_SRP_REGNUM)")
(const_int 0)))
(nil) (nil)])
;; Iterator definitions.
......@@ -192,26 +253,70 @@
;; Allow register and offsettable mem operands only; post-increment is
;; not worth the trouble.
(define_insn "tstdi"
(define_expand "tstdi"
[(set (cc0) (match_operand:DI 0 "nonimmediate_operand"))]
""
{
if (TARGET_V32 && MEM_P (operands[0]))
operands[0] = force_reg (DImode, operands[0]);
})
(define_insn "*tstdi_non_v32"
[(set (cc0)
(match_operand:DI 0 "nonimmediate_operand" "r,o"))]
""
"!TARGET_V32"
"test.d %M0\;ax\;test.d %H0")
(define_insn "*tstdi_v32"
[(set (cc0)
(match_operand:DI 0 "register_operand" "r"))]
"TARGET_V32"
"cmpq 0,%M0\;ax\;cmpq 0,%H0")
;; No test insns with side-effect on the mem addressing.
;;
;; See note on cmp-insns with side-effects (or lack of them)
;; Normal named test patterns from SI on.
;; FIXME: Seems they should change to be in order smallest..largest.
(define_insn "tst<mode>"
(define_insn "tstsi"
[(set (cc0)
(match_operand:BWD 0 "nonimmediate_operand" "r,Q>,m"))]
(match_operand:SI 0 "nonimmediate_operand" "r,Q>,m"))]
""
"test<m> %0"
{
if (which_alternative == 0 && TARGET_V32)
return "cmpq 0,%0";
return "test.d %0";
}
[(set_attr "slottable" "yes,yes,no")])
(define_expand "tst<mode>"
[(set (cc0)
(match_operand:BW 0 "nonimmediate_operand"))]
""
"")
(define_insn "*tst<mode>_cmp"
[(set (cc0)
(match_operand:BW 0 "nonimmediate_operand" "r,Q>,m"))]
"cris_cc0_user_requires_cmp (insn)"
"@
cmp<m> 0,%0
test<m> %0
test<m> %0"
[(set_attr "slottable" "no,yes,no")])
(define_insn "*tst<mode>_non_cmp"
[(set (cc0)
(match_operand:BW 0 "nonimmediate_operand" "r,Q>,m"))]
"!cris_cc0_user_requires_cmp (insn)"
"@
move<m> %0,%0
test<m> %0
test<m> %0"
[(set_attr "slottable" "yes,yes,no")
(set_attr "cc" "noov32,*,*")])
;; It seems that the position of the sign-bit and the fact that 0.0 is
;; all 0-bits would make "tstsf" a straight-forward implementation;
;; either "test.d" it for positive/negative or "btstq 30,r" it for
......@@ -227,11 +332,23 @@
;; DImode for anything else but a structure/block-mode. Just do the
;; obvious stuff for the straight-forward constraint letters.
(define_insn "cmpdi"
(define_expand "cmpdi"
[(set (cc0)
(compare (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" "")))]
""
{
if (TARGET_V32 && !REG_P (operands[0]))
operands[0] = force_reg (DImode, operands[0]);
if (TARGET_V32 && MEM_P (operands[1]))
operands[1] = force_reg (DImode, operands[1]);
})
(define_insn "*cmpdi_non_v32"
[(set (cc0)
(compare (match_operand:DI 0 "nonimmediate_operand" "r,r,r,r,r,r,o")
(match_operand:DI 1 "general_operand" "K,I,P,n,r,o,r")))]
""
"!TARGET_V32"
"@
cmpq %1,%M0\;ax\;cmpq 0,%H0
cmpq %1,%M0\;ax\;cmpq -1,%H0
......@@ -241,6 +358,18 @@
cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0
cmp.d %M0,%M1\;ax\;cmp.d %H0,%H1")
(define_insn "*cmpdi_v32"
[(set (cc0)
(compare (match_operand:DI 0 "register_operand" "r,r,r,r,r")
(match_operand:DI 1 "nonmemory_operand" "K,I,P,n,r")))]
"TARGET_V32"
"@
cmpq %1,%M0\;ax\;cmpq 0,%H0
cmpq %1,%M0\;ax\;cmpq -1,%H0
cmp%e1.%z1 %1,%M0\;ax\;cmpq %H1,%H0
cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0
cmp.d %M1,%M0\;ax\;cmp.d %H1,%H0")
;; Note that compare insns with side effect addressing mode (e.g.):
;;
;; cmp.S [rx=ry+i],rz;
......@@ -281,47 +410,43 @@
[(match_operand:BW 0 "memory_operand" "Q>,m")])
(match_operand:SI 1 "register_operand" "r,r")))]
""
"cmp%e2<m> %0,%1" ; The function cris_notice_update_cc knows about
; swapped operands to compares.
[(set_attr "slottable" "yes,no")])
"cmp%e2<m> %0,%1"
[(set_attr "slottable" "yes,no")
(set_attr "cc" "rev")])
;; The "normal" compare patterns, from SI on.
;; The "normal" compare patterns, from SI on. Special-cases with zero
;; should not happen.
(define_insn "cmpsi"
[(set (cc0)
(compare
(match_operand:SI 0 "nonimmediate_operand" "r,r,r, r,Q>,Q>,r,r,m,m")
(match_operand:SI 1 "general_operand" "I,r,Q>,M,M, r, P,g,M,r")))]
(match_operand:SI 0 "nonimmediate_operand" "r,r,r, Q>,r,r,m")
(match_operand:SI 1 "general_operand" "I,r,Q>,r, P,g,r")))]
""
"@
cmpq %1,%0
cmp.d %1,%0
cmp.d %1,%0
test.d %0
test.d %0
cmp.d %0,%1
cmp%e1.%z1 %1,%0
cmp.d %1,%0
test.d %0
cmp.d %0,%1"
[(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,no,no")])
[(set_attr "slottable" "yes,yes,yes,yes,no,no,no")
(set_attr "cc" "normal,normal,normal,rev,normal,normal,rev")])
(define_insn "cmp<mode>"
[(set (cc0)
(compare
(match_operand:BW 0 "nonimmediate_operand" "r,r, r,Q>,Q>,r,m,m")
(match_operand:BW 1 "general_operand" "r,Q>,M,M, r, g,M,r")))]
(compare (match_operand:BW 0 "nonimmediate_operand" "r,r, Q>,r,m")
(match_operand:BW 1 "general_operand" "r,Q>,r, g,r")))]
""
"@
cmp<m> %1,%0
cmp<m> %1,%0
test<m> %0
test<m> %0
cmp<m> %0,%1
cmp<m> %1,%0
test<m> %0
cmp<m> %0,%1"
[(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no")])
[(set_attr "slottable" "yes,yes,yes,no,no")
(set_attr "cc" "normal,normal,rev,normal,rev")])
;; Pattern matching the BTST insn.
;; It is useful for "if (i & val)" constructs, where val is an exact
......@@ -337,15 +462,17 @@
(match_operand:SI 1 "const_int_operand" "K,n,K,n,K,n,n")
(match_operand:SI 2 "nonmemory_operand" "M,M,K,n,r,r,r")))]
;; Either it is a single bit, or consecutive ones starting at 0.
;; The btst ones depend on stuff in NOTICE_UPDATE_CC.
"CONST_INT_P (operands[1])
&& (operands[1] == const1_rtx || operands[2] == const0_rtx)
&& (REG_S_P (operands[0])
|| (operands[1] == const1_rtx
&& REG_S_P (operands[2])
&& CONST_INT_P (operands[0])
&& exact_log2 (INTVAL (operands[0])) >= 0))"
&& exact_log2 (INTVAL (operands[0])) >= 0))
&& !TARGET_CCINIT"
;; The last "&&" condition above should be caught by some kind of
;; The next-to-last "&&" condition above should be caught by some kind of
;; canonicalization in gcc, but we can easily help with it here.
;; It results from expressions of the type
;; "power_of_2_value & (1 << y)".
......@@ -357,13 +484,14 @@
"@
btstq (%1-1),%0
test.d %0
cmpq 0,%0
btstq %2,%0
clearf nz
btst %2,%0
clearf nz
cmpq %p0,%2"
[(set_attr "slottable" "yes")])
[(set_attr "slottable" "yes")
(set_attr "cc" "noov32")])
;; Move insns.
......@@ -409,7 +537,9 @@
(match_operand:DI 1 "general_operand" ""))]
""
{
if (MEM_P (operands[0]) && operands[1] != const0_rtx)
if (MEM_P (operands[0])
&& operands[1] != const0_rtx
&& (!TARGET_V32 || (!REG_P (operands[1]) && can_create_pseudo_p ())))
operands[1] = copy_to_mode_reg (DImode, operands[1]);
/* Some other ports (as of 2001-09-10 for example mcore and romp) also
......@@ -441,18 +571,64 @@
}
})
(define_insn "*movdi_insn"
(define_insn_and_split "*movdi_insn_non_v32"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,rx,m")
(match_operand:DI 1 "general_operand" "rx,g,rxM"))]
"register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode)
|| operands[1] == const0_rtx"
"#")
(match_operand:DI 1 "general_operand" "rx,g,rxM"))]
"(register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode)
|| operands[1] == const0_rtx)
&& !TARGET_V32"
"#"
"&& reload_completed"
[(match_dup 2)]
"operands[2] = cris_split_movdx (operands);")
;; Overlapping (but non-identical) source memory address and destination
;; register would be a compiler bug, so we don't have to specify that.
(define_insn "*movdi_v32"
[(set
(match_operand:DI 0 "nonimmediate_operand" "=r,rx,&r,>, m,r,x,m")
(match_operand:DI 1 "general_operand" "rxi,r>,m, rx,r,m,m,x"))]
"TARGET_V32"
{
switch (which_alternative)
{
/* FIXME: 1) Use autoincrement where possible. 2) Have peephole2,
particularly for cases where the address register is dead. */
case 5:
if (REGNO (operands[0]) == REGNO (XEXP (operands[1], 0)))
return "addq 4,%L1\;move.d %1,%H0\;subq 4,%L1\;move.d %1,%M0";
gcc_assert (REGNO (operands[0]) + 1 == REGNO (XEXP (operands[1], 0)));
return "move.d [%L1+],%M0\;move.d [%L1],%H0";
case 2:
/* We could do away with the addq if we knew the address-register
isn't ACR. If we knew the address-register is dead, we could do
away with the subq too. */
return "move.d [%L1],%M0\;addq 4,%L1\;move.d [%L1],%H0\;subq 4,%L1";
case 4:
return "move.d %M1,[%L0]\;addq 4,%L0\;move.d %H1,[%L0]\;subq 4,%L0";
case 6:
return "move [%L1],%M0\;addq 4,%L1\;move [%L1],%H0\;subq 4,%L1";
case 7:
return "move %M1,[%L0]\;addq 4,%L0\;move %H1,[%L0]\;subq 4,%L0";
default:
return "#";
}
}
;; The non-split cases clobber cc0 because of their adds and subs.
;; Beware that NOTICE_UPDATE_CC is called before the forced split happens.
[(set_attr "cc" "*,*,clobber,*,clobber,clobber,*,*")])
;; Much like "*movdi_insn_non_v32". Overlapping registers and constants
;; is handled so much better in cris_split_movdx.
(define_split
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" ""))]
"reload_completed"
"TARGET_V32
&& reload_completed
&& (!MEM_P (operands[0]) || !REG_P (XEXP (operands[0], 0)))
&& (!MEM_P (operands[1]) || !REG_P (XEXP (operands[1], 0)))"
[(match_dup 2)]
"operands[2] = cris_split_movdx (operands);")
......@@ -462,6 +638,7 @@
;;
;; move.S1 [rx=ry+rz.S],rw avoiding when rx is ry, or rw is rx
;; FIXME: These could have anonymous mode for operand 0.
;; FIXME: Special registers' alternatives too.
(define_insn "*mov_side<mode>_biap"
[(set (match_operand:BW 0 "register_operand" "=r,r")
......@@ -800,7 +977,7 @@
offset? */
if (flag_pic
&& CONSTANT_ADDRESS_P (operands[1])
&& !cris_valid_pic_const (operands[1]))
&& !cris_valid_pic_const (operands[1], false))
{
enum cris_pic_symbol_type t = cris_pic_symbol_type_of (operands[1]);
......@@ -819,26 +996,46 @@
destination register for the symbol. It might not be
worth it. Measure. */
current_function_uses_pic_offset_table = 1;
if (t == cris_gotrel_symbol)
if (t == cris_rel_symbol)
{
/* Change a "move.d sym(+offs),rN" into (allocate register rM)
for pre-v32:
"move.d (const (plus (unspec [sym]
CRIS_UNSPEC_GOTREL) offs)),rM" "add.d rPIC,rM,rN"
and for v32:
"move.d (const (plus (unspec [sym]
CRIS_UNSPEC_GOTREL) offs)),rM" "add.d rPIC,rM,rN" */
CRIS_UNSPEC_PCREL) offs)),rN". */
rtx tem, rm, rn = operands[0];
rtx sym = GET_CODE (operands[1]) != CONST
? operands[1] : get_related_value (operands[1]);
HOST_WIDE_INT offs = get_integer_term (operands[1]);
gcc_assert (can_create_pseudo_p ());
tem = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym),
CRIS_UNSPEC_GOTREL);
if (offs != 0)
tem = plus_constant (tem, offs);
rm = gen_reg_rtx (Pmode);
emit_move_insn (rm, gen_rtx_CONST (Pmode, tem));
if (expand_binop (Pmode, add_optab, rm, pic_offset_table_rtx,
rn, 0, OPTAB_LIB_WIDEN) != rn)
internal_error ("expand_binop failed in movsi gotrel");
if (TARGET_V32)
{
tem = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym),
CRIS_UNSPEC_PCREL);
if (offs != 0)
tem = plus_constant (tem, offs);
rm = rn;
emit_move_insn (rm, gen_rtx_CONST (Pmode, tem));
}
else
{
/* We still uses GOT-relative addressing for
pre-v32. */
current_function_uses_pic_offset_table = 1;
tem = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym),
CRIS_UNSPEC_GOTREL);
if (offs != 0)
tem = plus_constant (tem, offs);
rm = gen_reg_rtx (Pmode);
emit_move_insn (rm, gen_rtx_CONST (Pmode, tem));
if (expand_binop (Pmode, add_optab, rm, pic_offset_table_rtx,
rn, 0, OPTAB_LIB_WIDEN) != rn)
internal_error ("expand_binop failed in movsi gotrel");
}
DONE;
}
else if (t == cris_got_symbol)
......@@ -863,6 +1060,12 @@
aliases other same symbols is unimportant. */
set_mem_alias_set (mem, new_alias_set ());
MEM_NOTRAP_P (mem) = 1;
/* We can set the GOT memory read of a non-called symbol
to readonly, but not that of a call symbol, as those
are subject to lazy evaluation and usually have the value
changed from the first call to the second (but
constant thereafter). */
MEM_READONLY_P (mem) = 1;
emit_move_insn (rn, mem);
DONE;
......@@ -897,15 +1100,21 @@
(define_insn "*movsi_got_load"
[(set (reg:SI CRIS_GOT_REGNUM) (unspec:SI [(const_int 0)] CRIS_UNSPEC_GOT))]
"flag_pic"
"move.d $pc,%:\;sub.d .:GOTOFF,%:"
{
return TARGET_V32
? "lapc _GLOBAL_OFFSET_TABLE_,%:"
: "move.d $pc,%:\;sub.d .:GOTOFF,%:";
}
[(set_attr "cc" "clobber")])
(define_insn "*movsi_internal"
[(set
(match_operand:SI 0 "nonimmediate_operand" "=r,r, r,Q>,r,Q>,g,r,r, r,g,rQ>,x, m,x")
(match_operand:SI 0 "nonimmediate_operand"
"=r,r, r,Q>,r,Q>,g,r,r, r,g,rQ>,x, m,x")
(match_operand:SI 1 "cris_general_operand_or_pic_source"
"r,Q>,M,M, I,r, M,n,!S,g,r,x, rQ>,x,gi"))]
;; Note that we prefer not to use the S alternative (if for some reason
;; it competes with others), but g matches S.
(match_operand:SI 1 "general_operand" "r,Q>,M,M, I,r, M,n,!S,g,r,x, rQ>,x,gi"))]
;; it competes with others) above, but g matches S.
""
{
/* Better to have c-switch here; it is worth it to optimize the size of
......@@ -913,10 +1122,31 @@
letters. FIXME: Check again. It seems this could shrink a bit. */
switch (which_alternative)
{
case 9:
if (TARGET_V32)
{
if (!flag_pic
&& (GET_CODE (operands[1]) == SYMBOL_REF
|| GET_CODE (operands[1]) == LABEL_REF
|| GET_CODE (operands[1]) == CONST))
{
/* FIXME: Express this through (set_attr cc none) instead,
since we can't express the ``none'' at this point. FIXME:
Use lapc for everything except const_int and when next cc0
user would want the flag setting. */
CC_STATUS_INIT;
return "lapc %1,%0";
}
if (flag_pic == 1
&& GET_CODE (operands[1]) == CONST
&& GET_CODE (XEXP (operands[1], 0)) == UNSPEC
&& XINT (XEXP (operands[1], 0), 1) == CRIS_UNSPEC_GOTREAD)
return "movu.w %1,%0";
}
/* FALLTHROUGH */
case 0:
case 1:
case 5:
case 9:
case 10:
return "move.d %1,%0";
......@@ -958,7 +1188,8 @@
tem = XEXP (tem, 0);
if (GET_CODE (tem) == PLUS
&& GET_CODE (XEXP (tem, 0)) == UNSPEC
&& XINT (XEXP (tem, 0), 1) == CRIS_UNSPEC_GOTREL
&& (XINT (XEXP (tem, 0), 1) == CRIS_UNSPEC_GOTREL
|| XINT (XEXP (tem, 0), 1) == CRIS_UNSPEC_PCREL)
&& CONST_INT_P (XEXP (tem, 1)))
tem = XEXP (tem, 0);
gcc_assert (GET_CODE (tem) == UNSPEC);
......@@ -970,10 +1201,18 @@
indexed addressing mode. */
if (flag_pic == 1)
return "movs.w %1,%0";
return "move.d %1,%0";
case CRIS_UNSPEC_GOTREL:
case CRIS_UNSPEC_PLT:
case CRIS_UNSPEC_PLT_GOTREL:
gcc_assert (!TARGET_V32);
return "move.d %1,%0";
case CRIS_UNSPEC_PCREL:
case CRIS_UNSPEC_PLT_PCREL:
gcc_assert (TARGET_V32);
return "lapc %1,%0";
default:
gcc_unreachable ();
}
......@@ -1218,9 +1457,69 @@
move %1,%0
move %1,%0"
[(set_attr "slottable" "yes,yes,yes,yes,yes,no,no,no,yes,yes,yes,no,yes,no")])
;; Movem patterns. Primarily for use in function prologue and epilogue.
;; The V32 variants have an ordering matching the expectations of the
;; standard names "load_multiple" and "store_multiple"; pre-v32 movem
;; store R0 in the highest memory location.
(define_expand "load_multiple"
[(match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "memory_operand" "")
(match_operand:SI 2 "const_int_operand" "")]
"TARGET_V32"
{
rtx indreg;
/* Apparently the predicate isn't checked, so we need to do so
manually. Once happened for libstdc++-v3 locale_facets.tcc. */
if (!MEM_P (operands[1]))
FAIL;
indreg = XEXP (operands[1], 0);
if (GET_CODE (indreg) == POST_INC)
indreg = XEXP (indreg, 0);
if (!REG_P (indreg)
|| GET_CODE (operands[2]) != CONST_INT
|| !REG_P (operands[0])
|| REGNO (operands[0]) != 0
|| INTVAL (operands[2]) > CRIS_SP_REGNUM
|| (int) REGNO (indreg) < INTVAL (operands[2]))
FAIL;
gcc_unreachable ();
emit_insn (cris_gen_movem_load (operands[1], operands[2], 0));
DONE;
})
(define_expand "store_multiple"
[(match_operand:SI 0 "memory_operand" "")
(match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "const_int_operand" "")]
"TARGET_V32"
{
rtx indreg;
/* See load_multiple. */
if (!MEM_P (operands[0]))
FAIL;
indreg = XEXP (operands[0], 0);
if (GET_CODE (indreg) == POST_INC)
indreg = XEXP (indreg, 0);
if (!REG_P (indreg)
|| GET_CODE (operands[2]) != CONST_INT
|| !REG_P (operands[1])
|| REGNO (operands[1]) != 0
|| INTVAL (operands[2]) > CRIS_SP_REGNUM
|| (int) REGNO (indreg) < INTVAL (operands[2]))
FAIL;
gcc_unreachable ();
cris_emit_movem_store (operands[0], operands[2], 0, false);
DONE;
})
;; Note that the memory layout of the registers is the reverse of that
;; of the standard patterns "load_multiple" and "store_multiple".
(define_insn "*cris_load_multiple"
[(match_parallel 0 "cris_load_multiple_op"
[(set (match_operand:SI 1 "register_operand" "=r,r")
......@@ -1421,11 +1720,21 @@
;; Note that for the 'P' constraint, the high part can be -1 or 0. We
;; output the insn through the 'A' output modifier as "adds.w" and "addq",
;; respectively.
(define_insn "adddi3"
(define_expand "adddi3"
[(set (match_operand:DI 0 "register_operand")
(plus:DI (match_operand:DI 1 "register_operand")
(match_operand:DI 2 "general_operand")))]
""
{
if (MEM_P (operands[2]) && TARGET_V32)
operands[2] = force_reg (DImode, operands[2]);
})
(define_insn "*adddi3_non_v32"
[(set (match_operand:DI 0 "register_operand" "=r,r,r,&r,&r")
(plus:DI (match_operand:DI 1 "register_operand" "%0,0,0,0,r")
(match_operand:DI 2 "general_operand" "J,N,P,g,!To")))]
""
"!TARGET_V32"
"@
addq %2,%M0\;ax\;addq 0,%H0
subq %n2,%M0\;ax\;subq 0,%H0
......@@ -1433,7 +1742,29 @@
add.d %M2,%M0\;ax\;add.d %H2,%H0
add.d %M2,%M1,%M0\;ax\;add.d %H2,%H1,%H0")
(define_insn "addsi3"
; It seems no use allowing a memory operand for this one, because we'd
; need a scratch register for incrementing the address.
(define_insn "*adddi3_v32"
[(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r")
(plus:DI (match_operand:DI 1 "register_operand" "%0,0,0,0,0")
(match_operand:DI 2 "nonmemory_operand" "J,N,P,r,n")))]
"TARGET_V32"
"@
addq %2,%M0\;addc 0,%H0
subq %n2,%M0\;ax\;subq 0,%H0
add%e2.%z2 %2,%M0\;addc %H2,%H0
add.d %M2,%M0\;addc %H2,%H0
add.d %M2,%M0\;addc %H2,%H0")
(define_expand "add<mode>3"
[(set (match_operand:BWD 0 "register_operand")
(plus:BWD
(match_operand:BWD 1 "register_operand")
(match_operand:BWD 2 "general_operand")))]
""
"")
(define_insn "*addsi3_non_v32"
[(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r, r,r, r")
(plus:SI
(match_operand:SI 1 "register_operand" "%0,0, 0,0,0,0, 0,r, r")
......@@ -1444,7 +1775,7 @@
;; register as in destination. This will happen after insn splitting.
;; gcc <= 2.7.2. FIXME: Check for gcc-2.9x
""
"!TARGET_V32"
{
switch (which_alternative)
{
......@@ -1480,6 +1811,8 @@
tem = XEXP (tem, 0);
if (GET_CODE (tem) == PLUS
&& GET_CODE (XEXP (tem, 0)) == UNSPEC
/* We don't allow CRIS_UNSPEC_PCREL here; we can't have a
pc-relative operand in an add insn. */
&& XINT (XEXP (tem, 0), 1) == CRIS_UNSPEC_GOTREL
&& CONST_INT_P (XEXP (tem, 1)))
tem = XEXP (tem, 0);
......@@ -1492,8 +1825,9 @@
indexed addressing mode. */
if (flag_pic == 1)
return "adds.w %2,%0";
/* Fall through. */
case CRIS_UNSPEC_PLT:
return "add.d %2,%0";
case CRIS_UNSPEC_PLT_GOTREL:
case CRIS_UNSPEC_GOTREL:
return "add.d %2,%0";
default:
......@@ -1501,7 +1835,7 @@
}
}
case 6:
return "add.d %2,%0";
return "add%u2 %2,%0";
case 7:
return "add.d %2,%1,%0";
case 8:
......@@ -1511,12 +1845,38 @@
}
}
[(set_attr "slottable" "yes,yes,yes,yes,no,no,no,no,yes")])
; FIXME: Check what's best: having the three-operand ACR alternative
; before or after the corresponding-operand2 alternative. Check for
; *all* insns. FIXME: constant constraint letter for -128..127.
(define_insn "*addsi3_v32"
[(set (match_operand:SI 0 "register_operand" "=r,!a,r,!a, r,r,!a,r,!a,r,r,r,!a")
(plus:SI
(match_operand:SI 1 "register_operand" "%0,r, 0, r, 0,0,r, 0,r, 0,0,0,r")
(match_operand:SI 2 "general_operand" "r, r, Q>,Q>,J,N,NJ,L,L, P,n,g,g")))]
"TARGET_V32"
"@
add.d %2,%0
addi %2.b,%1,%0
add.d %2,%0
addo.d %2,%1,%0
addq %2,%0
subq %n2,%0
addoq %2,%1,%0
adds.w %2,%0
addo %2,%1,%0
addu.w %2,%0
add.d %2,%0
add%u2 %2,%0
addo.%Z2 %2,%1,%0"
[(set_attr "slottable" "yes,yes,yes,yes,yes,yes,yes,no,no,no,no,no,no")
(set_attr "cc" "*,none,*,none,*,*,none,*,*,*,*,*,none")])
(define_insn "addhi3"
(define_insn "*addhi3_non_v32"
[(set (match_operand:HI 0 "register_operand" "=r,r, r,r,r,r")
(plus:HI (match_operand:HI 1 "register_operand" "%0,0, 0,0,0,r")
(match_operand:HI 2 "general_operand" "r,Q>,J,N,g,!To")))]
""
"!TARGET_V32"
"@
add.w %2,%0
add.w %2,%0
......@@ -1527,11 +1887,30 @@
[(set_attr "slottable" "yes,yes,yes,yes,no,no")
(set_attr "cc" "normal,normal,clobber,clobber,normal,normal")])
(define_insn "addqi3"
(define_insn "*addhi3_v32"
[(set (match_operand:HI 0 "register_operand" "=r, !a,r,!a, r,r,!a,r,!a")
(plus:HI
(match_operand:HI 1 "register_operand" "%0,r, 0, r, 0,0,r, 0,r")
(match_operand:HI 2 "general_operand" "r, r, Q>,Q>,J,N,NJ,g,g")))]
"TARGET_V32"
"@
add.w %2,%0
addi %2.b,%1,%0
add.w %2,%0
addo.w %2,%1,%0
addq %2,%0
subq %n2,%0
addoq %2,%1,%0
add.w %2,%0
addo.w %2,%1,%0"
[(set_attr "slottable" "yes,yes,yes,yes,yes,yes,yes,no,no")
(set_attr "cc" "*,none,*,none,clobber,clobber,none,*,none")])
(define_insn "*addqi3_non_v32"
[(set (match_operand:QI 0 "register_operand" "=r,r, r,r,r,r,r")
(plus:QI (match_operand:QI 1 "register_operand" "%0,0, 0,0,0,0,r")
(match_operand:QI 2 "general_operand" "r,Q>,J,N,O,g,!To")))]
""
"!TARGET_V32"
"@
add.b %2,%0
add.b %2,%0
......@@ -1542,6 +1921,26 @@
add.b %2,%1,%0"
[(set_attr "slottable" "yes,yes,yes,yes,yes,no,no")
(set_attr "cc" "normal,normal,clobber,clobber,clobber,normal,normal")])
(define_insn "*addqi3_v32"
[(set (match_operand:QI 0 "register_operand" "=r,!a,r,!a, r,r,!a,r,r,!a")
(plus:QI
(match_operand:QI 1 "register_operand" "%0,r, 0, r, 0,0,r, 0,0,r")
(match_operand:QI 2 "general_operand" "r,r, Q>,Q>,J,N,NJ,O,g,g")))]
"TARGET_V32"
"@
add.b %2,%0
addi %2.b,%1,%0
add.b %2,%0
addo.b %2,%1,%0
addq %2,%0
subq %n2,%0
addoq %2,%1,%0
subQ -%b2,%0
add.b %2,%0
addo.b %2,%1,%0"
[(set_attr "slottable" "yes,yes,yes,yes,yes,yes,yes,yes,no,no")
(set_attr "cc" "*,none,*,none,clobber,clobber,none,clobber,*,none")])
;; Subtract.
;;
......@@ -1551,11 +1950,21 @@
;; Note that for the 'P' constraint, the high part can be -1 or 0. We
;; output the insn through the 'D' output modifier as "subs.w" and "subq",
;; respectively.
(define_insn "subdi3"
(define_expand "subdi3"
[(set (match_operand:DI 0 "register_operand")
(minus:DI (match_operand:DI 1 "register_operand")
(match_operand:DI 2 "general_operand")))]
""
{
if (TARGET_V32 && MEM_P (operands[2]))
operands[2] = force_reg (DImode, operands[2]);
})
(define_insn "*subdi3_non_v32"
[(set (match_operand:DI 0 "register_operand" "=r,r,r,&r,&r")
(minus:DI (match_operand:DI 1 "register_operand" "0,0,0,0,r")
(match_operand:DI 2 "general_operand" "J,N,P,g,!To")))]
""
"!TARGET_V32"
"@
subq %2,%M0\;ax\;subq 0,%H0
addq %n2,%M0\;ax\;addq 0,%H0
......@@ -1563,12 +1972,31 @@
sub.d %M2,%M0\;ax\;sub.d %H2,%H0
sub.d %M2,%M1,%M0\;ax\;sub.d %H2,%H1,%H0")
(define_insn "subsi3"
(define_insn "*subdi3_v32"
[(set (match_operand:DI 0 "register_operand" "=r,r,r,&r")
(minus:DI (match_operand:DI 1 "register_operand" "0,0,0,0")
(match_operand:DI 2 "nonmemory_operand" "J,N,P,r")))]
"TARGET_V32"
"@
subq %2,%M0\;ax\;subq 0,%H0
addq %n2,%M0\;ax\;addq 0,%H0
sub%e2.%z2 %2,%M0\;ax\;%D2 %H2,%H0
sub.d %M2,%M0\;ax\;sub.d %H2,%H0")
(define_expand "sub<mode>3"
[(set (match_operand:BWD 0 "register_operand")
(minus:BWD
(match_operand:BWD 1 "register_operand")
(match_operand:BWD 2 "general_operand")))]
""
"")
(define_insn "*subsi3_non_v32"
[(set (match_operand:SI 0 "register_operand" "=r,r, r,r,r,r,r,r")
(minus:SI
(match_operand:SI 1 "register_operand" "0,0, 0,0,0,0,0,r")
(match_operand:SI 2 "general_operand" "r,Q>,J,N,P,n,g,!To")))]
""
"!TARGET_V32"
;; This does not do the optimal: "addu.w 65535,r0" when %2 is negative.
;; But then again, %2 should not be negative.
......@@ -1583,12 +2011,28 @@
sub.d %2,%0
sub.d %2,%1,%0"
[(set_attr "slottable" "yes,yes,yes,yes,no,no,no,no")])
(define_insn "*subsi3_v32"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r")
(minus:SI
(match_operand:SI 1 "register_operand" "0,0,0,0,0,0,0")
(match_operand:SI 2 "general_operand" "r,Q>,J,N,P,n,g")))]
"TARGET_V32"
"@
sub.d %2,%0
sub.d %2,%0
subq %2,%0
addq %n2,%0
sub%e2.%z2 %2,%0
sub.d %2,%0
sub.d %2,%0"
[(set_attr "slottable" "yes,yes,yes,yes,no,no,no")])
(define_insn "sub<mode>3"
(define_insn "*sub<mode>3_nonv32"
[(set (match_operand:BW 0 "register_operand" "=r,r, r,r,r,r")
(minus:BW (match_operand:BW 1 "register_operand" "0,0, 0,0,0,r")
(match_operand:BW 2 "general_operand" "r,Q>,J,N,g,!To")))]
""
"!TARGET_V32"
"@
sub<m> %2,%0
sub<m> %2,%0
......@@ -1598,6 +2042,20 @@
sub<m> %2,%1,%0"
[(set_attr "slottable" "yes,yes,yes,yes,no,no")
(set_attr "cc" "normal,normal,clobber,clobber,normal,normal")])
(define_insn "*sub<mode>3_v32"
[(set (match_operand:BW 0 "register_operand" "=r,r,r,r,r")
(minus:BW (match_operand:BW 1 "register_operand" "0,0,0,0,0")
(match_operand:BW 2 "general_operand" "r,Q>,J,N,g")))]
"TARGET_V32"
"@
sub<m> %2,%0
sub<m> %2,%0
subq %2,%0
addq %n2,%0
sub<m> %2,%0"
[(set_attr "slottable" "yes,yes,yes,yes,no")
(set_attr "cc" "normal,normal,clobber,clobber,normal")])
;; CRIS has some add/sub-with-sign/zero-extend instructions.
;; Although these perform sign/zero-extension to SImode, they are
......@@ -1720,7 +2178,7 @@
;; As with op.S we may have to add special pattern to match commuted
;; operands to adds/addu and bound
;; operands to adds/addu and bound
;;
;; adds/addu/bound [rx=ry+rz.S]
......@@ -1831,7 +2289,7 @@
;; QImode to HImode
;; FIXME: GCC should widen.
(define_insn "*extopqihi"
(define_insn "*extopqihi_non_v32"
[(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
(match_operator:HI
3 "cris_additive_operand_extend_operator"
......@@ -1839,7 +2297,7 @@
(match_operator:HI
4 "cris_extend_operator"
[(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")])]))]
"GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
"!TARGET_V32 && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
&& (operands[1] != frame_pointer_rtx || GET_CODE (operands[3]) != PLUS)"
"@
%x3%E4.%m4 %2,%0
......@@ -1849,9 +2307,22 @@
[(set_attr "slottable" "yes,yes,no,no")
(set_attr "cc" "clobber")])
(define_insn "*extopqihi_v32"
[(set (match_operand:HI 0 "register_operand" "=r,r")
(match_operator:HI
3 "cris_additive_operand_extend_operator"
[(match_operand:HI 1 "register_operand" "0,0")
(match_operator:HI
4 "cris_extend_operator"
[(match_operand:QI 2 "nonimmediate_operand" "r,m")])]))]
"TARGET_V32"
"%x3%e4.%m4 %2,%0"
[(set_attr "slottable" "yes")
(set_attr "cc" "clobber")])
;; QImode to SImode
(define_insn "*extop<mode>si"
(define_insn "*extop<mode>si_non_v32"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
(match_operator:SI
3 "cris_operand_extend_operator"
......@@ -1859,7 +2330,8 @@
(match_operator:SI
4 "cris_extend_operator"
[(match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")])]))]
"(GET_CODE (operands[3]) != UMIN || GET_CODE (operands[4]) == ZERO_EXTEND)
"!TARGET_V32
&& (GET_CODE (operands[3]) != UMIN || GET_CODE (operands[4]) == ZERO_EXTEND)
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
&& (operands[1] != frame_pointer_rtx || GET_CODE (operands[3]) != PLUS)"
"@
......@@ -1868,21 +2340,32 @@
%x3%E4<m> %2,%0
%x3%E4<m> %2,%1,%0"
[(set_attr "slottable" "yes,yes,no,no")])
(define_insn "*extop<mode>si_v32"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(match_operator:SI
3 "cris_additive_operand_extend_operator"
[(match_operand:SI 1 "register_operand" "0,0")
(match_operator:SI
4 "cris_extend_operator"
[(match_operand:BW 2 "nonimmediate_operand" "r,m")])]))]
"TARGET_V32"
"%x3%e4.%m4 %2,%0"
[(set_attr "slottable" "yes")])
;; As with the side-effect patterns, may have to have swapped operands for add.
;; FIXME: *should* be redundant to gcc.
;; For commutative operands, these are the canonical forms.
;; QImode to HImode
(define_insn "*extopqihi_swap"
(define_insn "*addxqihi_swap_non_v32"
[(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
(plus:HI
(match_operator:HI
3 "cris_extend_operator"
[(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")])
(match_operand:HI 1 "register_operand" "0,0,0,r")))]
"operands[1] != frame_pointer_rtx"
"!TARGET_V32 && operands[1] != frame_pointer_rtx"
"@
add%e3.b %2,%0
add%e3.b %2,%0
......@@ -1891,7 +2374,35 @@
[(set_attr "slottable" "yes,yes,no,no")
(set_attr "cc" "clobber")])
(define_insn "*extop<mode>si_swap"
;; A case for v32, to catch the "addo" insn in addition to "adds". We
;; only care to match the canonical form; there should be no other.
(define_insn "*addsbw_v32"
[(set (match_operand:HI 0 "register_operand" "=r,r,!a")
(plus:HI
(sign_extend:HI
(match_operand:QI 2 "nonimmediate_operand" "r,m,m"))
(match_operand:HI 1 "register_operand" "0,0,r")))]
"TARGET_V32"
"@
adds.b %2,%0
adds.b %2,%0
addo.b %2,%1,%0"
[(set_attr "slottable" "yes")
(set_attr "cc" "clobber,clobber,none")])
(define_insn "*addubw_v32"
[(set (match_operand:HI 0 "register_operand" "=r,r")
(plus:HI
(zero_extend:HI
(match_operand:QI 2 "nonimmediate_operand" "r,m"))
(match_operand:HI 1 "register_operand" "0,0")))]
"TARGET_V32"
"addu.b %2,%0"
[(set_attr "slottable" "yes")
(set_attr "cc" "clobber")])
(define_insn "*extop<mode>si_swap_non_v32"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
(match_operator:SI
4 "cris_plus_or_bound_operator"
......@@ -1899,7 +2410,8 @@
3 "cris_extend_operator"
[(match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")])
(match_operand:SI 1 "register_operand" "0,0,0,r")]))]
"(GET_CODE (operands[4]) != UMIN || GET_CODE (operands[3]) == ZERO_EXTEND)
"!TARGET_V32
&& (GET_CODE (operands[4]) != UMIN || GET_CODE (operands[3]) == ZERO_EXTEND)
&& operands[1] != frame_pointer_rtx"
"@
%x4%E3<m> %2,%0
......@@ -1907,6 +2419,40 @@
%x4%E3<m> %2,%0
%x4%E3<m> %2,%1,%0"
[(set_attr "slottable" "yes,yes,no,no")])
(define_insn "*adds<mode>_v32"
[(set (match_operand:SI 0 "register_operand" "=r,r,!a")
(plus:SI
(sign_extend:SI
(match_operand:BW 2 "nonimmediate_operand" "r,m,m"))
(match_operand:SI 1 "register_operand" "0,0,r")))]
"TARGET_V32"
"@
adds<m> %2,%0
adds<m> %2,%0
addo<m> %2,%1,%0"
[(set_attr "slottable" "yes")
(set_attr "cc" "*,*,none")])
(define_insn "*addu<mode>_v32"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(plus:SI
(zero_extend:SI
(match_operand:BW 2 "nonimmediate_operand" "r,m"))
(match_operand:SI 1 "register_operand" "0,0")))]
"TARGET_V32 && operands[1] != frame_pointer_rtx"
"addu<m> %2,%0"
[(set_attr "slottable" "yes")])
(define_insn "*bound<mode>_v32"
[(set (match_operand:SI 0 "register_operand" "=r")
(umin:SI
(zero_extend:SI
(match_operand:BW 2 "register_operand" "r"))
(match_operand:SI 1 "register_operand" "0")))]
"TARGET_V32 && operands[1] != frame_pointer_rtx"
"bound<m> %2,%0"
[(set_attr "slottable" "yes")])
;; This is the special case when we use what corresponds to the
;; instruction above in "casesi". Do *not* change it to use the generic
......@@ -1940,11 +2486,29 @@
(pc))
(label_ref (match_operand 2 "" ""))))
(use (label_ref (match_operand 3 "" "")))]
"operands[0] != frame_pointer_rtx"
"!TARGET_V32 && operands[0] != frame_pointer_rtx"
"adds.w [$pc+%0.w],$pc"
[(set_attr "cc" "clobber")])
;; For V32, we just have a jump, but we need to mark the table as used,
;; and the jump insn must have the if_then_else form expected by core
;; GCC. Since we don't want to prolong the lifetime of the original
;; index value, we compare against "unspec 0". It's a pity we have to
;; jump through to get the default label in place and to keep the jump
;; table around. FIXME: Look into it some time.
(define_insn "*casesi_jump_v32"
[(set (pc)
(if_then_else
(ltu (unspec [(const_int 0)] CRIS_UNSPEC_CASESI)
(match_operand:SI 0 "const_int_operand" "n"))
(match_operand:SI 1 "register_operand" "r")
(label_ref (match_operand 2 "" ""))))
(use (label_ref (match_operand 3 "" "")))]
"TARGET_V32"
"jump %1%#"
[(set_attr "cc" "clobber")
(set_attr "slottable" "has_slot")])
;; Multiply instructions.
......@@ -1984,18 +2548,24 @@
;; The addi insn as it is normally used.
;; Make the the ACR alternative taste bad enough to not choose it as a
;; preference to avoid spilling problems (unwind-dw2-fde.c at build).
;; FIXME: Revisit for new register allocator.
(define_insn "*addi"
[(set (match_operand:SI 0 "register_operand" "=r")
[(set (match_operand:SI 0 "register_operand" "=r,!a")
(plus:SI
(mult:SI (match_operand:SI 2 "register_operand" "r")
(match_operand:SI 3 "const_int_operand" "n"))
(match_operand:SI 1 "register_operand" "0")))]
(mult:SI (match_operand:SI 2 "register_operand" "r,r")
(match_operand:SI 3 "const_int_operand" "n,n"))
(match_operand:SI 1 "register_operand" "0,r")))]
"operands[0] != frame_pointer_rtx
&& operands[1] != frame_pointer_rtx
&& CONST_INT_P (operands[3])
&& (INTVAL (operands[3]) == 1
|| INTVAL (operands[3]) == 2 || INTVAL (operands[3]) == 4)"
"addi %2%T3,%0"
"@
addi %2%T3,%0
addi %2%T3,%1,%0"
[(set_attr "slottable" "yes")
(set_attr "cc" "none")])
......@@ -2012,7 +2582,7 @@
(match_operand:SI 2 "register_operand" "r"))
(ashift:SI (match_operand:SI 3 "register_operand" "0")
(const_int 1))))]
""
"!TARGET_V32"
"mstep %2,%0"
[(set_attr "slottable" "yes")])
......@@ -2030,7 +2600,8 @@
(match_operand:SI 2 "register_operand" "r"))
(mult:SI (match_operand:SI 3 "register_operand" "0")
(const_int 2))))]
"operands[0] != frame_pointer_rtx
"!TARGET_V32
&& operands[0] != frame_pointer_rtx
&& operands[1] != frame_pointer_rtx
&& operands[2] != frame_pointer_rtx
&& operands[3] != frame_pointer_rtx"
......@@ -2107,7 +2678,7 @@
;; a / 1000;}" and unsigned. FIXME: Comment above was for 3.2, revisit.
(define_insn "<su>mulsi3_highpart"
[(set (match_operand:SI 0 "nonimmediate_operand" "=h,h,?r,?r")
[(set (match_operand:SI 0 "register_operand" "=h,h,?r,?r")
(truncate:SI
(lshiftrt:DI
(mult:DI
......@@ -2139,7 +2710,8 @@
(const_int 1))))]
""
"dstep %2,%0"
[(set_attr "slottable" "yes")])
[(set_attr "slottable" "yes")
(set_attr "cc" "noov32")])
;; Here's a variant with mult instead of ashift.
;;
......@@ -2161,7 +2733,8 @@
&& operands[2] != frame_pointer_rtx
&& operands[3] != frame_pointer_rtx"
"dstep %2,%0"
[(set_attr "slottable" "yes")])
[(set_attr "slottable" "yes")
(set_attr "cc" "noov32")])
;; Logical operators.
......@@ -2256,11 +2829,11 @@
;; pressure (worse code). That will hopefully change with an
;; improved reload pass.
(define_insn "*expanded_andsi"
(define_insn "*expanded_andsi_non_v32"
[(set (match_operand:SI 0 "register_operand" "=r,r,r, r,r")
(and:SI (match_operand:SI 1 "register_operand" "%0,0,0, 0,r")
(match_operand:SI 2 "general_operand" "I,r,Q>,g,!To")))]
""
"!TARGET_V32"
"@
andq %2,%0
and.d %2,%0
......@@ -2268,6 +2841,19 @@
and.d %2,%0
and.d %2,%1,%0"
[(set_attr "slottable" "yes,yes,yes,no,no")])
(define_insn "*expanded_andsi_v32"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
(and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
(match_operand:SI 2 "general_operand" "I,r,Q>,g")))]
"TARGET_V32"
"@
andq %2,%0
and.d %2,%0
and.d %2,%0
and.d %2,%0"
[(set_attr "slottable" "yes,yes,yes,no")
(set_attr "cc" "noov32")])
;; For both QI and HI we may use the quick patterns. This results in
;; useless condition codes, but that is used rarely enough for it to
......@@ -2331,7 +2917,7 @@
;; Catch-all andhi3 pattern.
(define_insn "*expanded_andhi"
(define_insn "*expanded_andhi_non_v32"
[(set (match_operand:HI 0 "register_operand" "=r,r,r, r,r,r,r")
(and:HI (match_operand:HI 1 "register_operand" "%0,0,0, 0,0,0,r")
(match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g,!To")))]
......@@ -2341,7 +2927,7 @@
;; pressure (worse code). That will hopefully change with an
;; improved reload pass.
""
"!TARGET_V32"
"@
andq %2,%0
and.w %2,%0
......@@ -2353,14 +2939,29 @@
[(set_attr "slottable" "yes,yes,yes,no,yes,no,no")
(set_attr "cc" "clobber,normal,normal,normal,clobber,normal,normal")])
(define_insn "*expanded_andhi_v32"
[(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r")
(and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0")
(match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g")))]
"TARGET_V32"
"@
andq %2,%0
and.w %2,%0
and.w %2,%0
and.w %2,%0
anDq %b2,%0
and.w %2,%0"
[(set_attr "slottable" "yes,yes,yes,no,yes,no")
(set_attr "cc" "clobber,noov32,noov32,noov32,clobber,noov32")])
;; A strict_low_part pattern.
(define_insn "*andhi_lowpart"
(define_insn "*andhi_lowpart_non_v32"
[(set (strict_low_part
(match_operand:HI 0 "register_operand" "=r,r, r,r,r,r"))
(and:HI (match_operand:HI 1 "register_operand" "%0,0, 0,0,0,r")
(match_operand:HI 2 "general_operand" "r,Q>,L,O,g,!To")))]
""
"!TARGET_V32"
"@
and.w %2,%0
and.w %2,%0
......@@ -2370,12 +2971,34 @@
and.w %2,%1,%0"
[(set_attr "slottable" "yes,yes,no,yes,no,no")
(set_attr "cc" "normal,normal,normal,clobber,normal,normal")])
(define_insn "*andhi_lowpart_v32"
[(set (strict_low_part
(match_operand:HI 0 "register_operand" "=r,r,r,r,r"))
(and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0")
(match_operand:HI 2 "general_operand" "r,Q>,L,O,g")))]
"TARGET_V32"
"@
and.w %2,%0
and.w %2,%0
and.w %2,%0
anDq %b2,%0
and.w %2,%0"
[(set_attr "slottable" "yes,yes,no,yes,no")
(set_attr "cc" "noov32,noov32,noov32,clobber,noov32")])
(define_insn "andqi3"
(define_expand "andqi3"
[(set (match_operand:QI 0 "register_operand")
(and:QI (match_operand:QI 1 "register_operand")
(match_operand:QI 2 "general_operand")))]
""
"")
(define_insn "*andqi3_non_v32"
[(set (match_operand:QI 0 "register_operand" "=r,r,r, r,r,r")
(and:QI (match_operand:QI 1 "register_operand" "%0,0,0, 0,0,r")
(match_operand:QI 2 "general_operand" "I,r,Q>,O,g,!To")))]
""
"!TARGET_V32"
"@
andq %2,%0
and.b %2,%0
......@@ -2386,12 +3009,26 @@
[(set_attr "slottable" "yes,yes,yes,yes,no,no")
(set_attr "cc" "clobber,normal,normal,clobber,normal,normal")])
(define_insn "*andqi_lowpart"
(define_insn "*andqi3_v32"
[(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r")
(and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0")
(match_operand:QI 2 "general_operand" "I,r,Q>,O,g")))]
"TARGET_V32"
"@
andq %2,%0
and.b %2,%0
and.b %2,%0
andQ %b2,%0
and.b %2,%0"
[(set_attr "slottable" "yes,yes,yes,yes,no")
(set_attr "cc" "clobber,noov32,noov32,clobber,noov32")])
(define_insn "*andqi_lowpart_non_v32"
[(set (strict_low_part
(match_operand:QI 0 "register_operand" "=r,r, r,r,r"))
(and:QI (match_operand:QI 1 "register_operand" "%0,0, 0,0,r")
(match_operand:QI 2 "general_operand" "r,Q>,O,g,!To")))]
""
"!TARGET_V32"
"@
and.b %2,%0
and.b %2,%0
......@@ -2400,6 +3037,20 @@
and.b %2,%1,%0"
[(set_attr "slottable" "yes,yes,yes,no,no")
(set_attr "cc" "normal,normal,clobber,normal,normal")])
(define_insn "*andqi_lowpart_v32"
[(set (strict_low_part
(match_operand:QI 0 "register_operand" "=r,r,r,r"))
(and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0")
(match_operand:QI 2 "general_operand" "r,Q>,O,g")))]
"TARGET_V32"
"@
and.b %2,%0
and.b %2,%0
andQ %b2,%0
and.b %2,%0"
[(set_attr "slottable" "yes,yes,yes,no")
(set_attr "cc" "noov32,noov32,clobber,noov32")])
;; Bitwise or.
......@@ -2408,11 +3059,18 @@
;; It seems there's no need to jump through hoops to get good code such as
;; with andsi3.
(define_insn "iorsi3"
(define_expand "ior<mode>3"
[(set (match_operand:BWD 0 "register_operand")
(ior:BWD (match_operand:BWD 1 "register_operand")
(match_operand:BWD 2 "general_operand")))]
""
"")
(define_insn "*iorsi3_non_v32"
[(set (match_operand:SI 0 "register_operand" "=r,r,r, r,r,r")
(ior:SI (match_operand:SI 1 "register_operand" "%0,0,0, 0,0,r")
(match_operand:SI 2 "general_operand" "I, r,Q>,n,g,!To")))]
""
"!TARGET_V32"
"@
orq %2,%0
or.d %2,%0
......@@ -2423,11 +3081,25 @@
[(set_attr "slottable" "yes,yes,yes,no,no,no")
(set_attr "cc" "normal,normal,normal,clobber,normal,normal")])
(define_insn "iorhi3"
(define_insn "*iorsi3_v32"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
(ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0")
(match_operand:SI 2 "general_operand" "I,r,Q>,n,g")))]
"TARGET_V32"
"@
orq %2,%0
or.d %2,%0
or.d %2,%0
oR.%s2 %2,%0
or.d %2,%0"
[(set_attr "slottable" "yes,yes,yes,no,no")
(set_attr "cc" "noov32,noov32,noov32,clobber,noov32")])
(define_insn "*iorhi3_non_v32"
[(set (match_operand:HI 0 "register_operand" "=r,r,r, r,r,r,r")
(ior:HI (match_operand:HI 1 "register_operand" "%0,0,0, 0,0,0,r")
(match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g,!To")))]
""
"!TARGET_V32"
"@
orq %2,%0
or.w %2,%0
......@@ -2439,11 +3111,26 @@
[(set_attr "slottable" "yes,yes,yes,no,yes,no,no")
(set_attr "cc" "clobber,normal,normal,normal,clobber,normal,normal")])
(define_insn "iorqi3"
(define_insn "*iorhi3_v32"
[(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r")
(ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0")
(match_operand:HI 2 "general_operand" "I,r,Q>,L,O,g")))]
"TARGET_V32"
"@
orq %2,%0
or.w %2,%0
or.w %2,%0
or.w %2,%0
oRq %b2,%0
or.w %2,%0"
[(set_attr "slottable" "yes,yes,yes,no,yes,no")
(set_attr "cc" "clobber,noov32,noov32,noov32,clobber,noov32")])
(define_insn "*iorqi3_non_v32"
[(set (match_operand:QI 0 "register_operand" "=r,r,r, r,r,r")
(ior:QI (match_operand:QI 1 "register_operand" "%0,0,0, 0,0,r")
(match_operand:QI 2 "general_operand" "I,r,Q>,O,g,!To")))]
""
"!TARGET_V32"
"@
orq %2,%0
or.b %2,%0
......@@ -2453,6 +3140,20 @@
or.b %2,%1,%0"
[(set_attr "slottable" "yes,yes,yes,yes,no,no")
(set_attr "cc" "clobber,normal,normal,clobber,normal,normal")])
(define_insn "*iorqi3_v32"
[(set (match_operand:QI 0 "register_operand" "=r,r,r,r,r")
(ior:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0")
(match_operand:QI 2 "general_operand" "I,r,Q>,O,g")))]
"TARGET_V32"
"@
orq %2,%0
or.b %2,%0
or.b %2,%0
orQ %b2,%0
or.b %2,%0"
[(set_attr "slottable" "yes,yes,yes,yes,no")
(set_attr "cc" "clobber,noov32,noov32,clobber,noov32")])
;; Exclusive-or
......@@ -2465,7 +3166,8 @@
(match_operand:SI 2 "register_operand" "r")))]
""
"xor %2,%0"
[(set_attr "slottable" "yes")])
[(set_attr "slottable" "yes")
(set_attr "cc" "noov32")])
(define_insn "xor<mode>3"
[(set (match_operand:BW 0 "register_operand" "=r")
......@@ -2522,7 +3224,8 @@
(not:SI (match_operand:SI 1 "register_operand" "0")))]
""
"not %0"
[(set_attr "slottable" "yes")])
[(set_attr "slottable" "yes")
(set_attr "cc" "noov32")])
(define_insn "one_cmpl<mode>2"
[(set (match_operand:BW 0 "register_operand" "=r")
......@@ -2545,7 +3248,8 @@
return "<slr>q %2,%0";
}
[(set_attr "slottable" "yes")])
[(set_attr "slottable" "yes")
(set_attr "cc" "noov32")])
;; Since gcc gets lost, and forgets to zero-extend the source (or mask
;; the destination) when it changes shifts of lower modes into SImode,
......@@ -2595,7 +3299,8 @@
(match_operand:BW 2 "register_operand" "r")))]
""
"<slr><m> %2,%0"
[(set_attr "slottable" "yes")])
[(set_attr "slottable" "yes")
(set_attr "cc" "noov32")])
(define_insn "*<shlr><mode>_lowpart"
[(set (strict_low_part (match_operand:BW 0 "register_operand" "+r"))
......@@ -2603,7 +3308,8 @@
(match_operand:BW 1 "register_operand" "r")))]
""
"<slr><m> %1,%0"
[(set_attr "slottable" "yes")])
[(set_attr "slottable" "yes")
(set_attr "cc" "noov32")])
;; Arithmetic/logical shift left.
......@@ -2624,7 +3330,7 @@
? "lslq %2,%0" : "lsl<m> %2,%0");
}
[(set_attr "slottable" "yes")
(set_attr "cc" "normal,clobber")])
(set_attr "cc" "noov32,clobber")])
;; A strict_low_part matcher.
......@@ -2634,7 +3340,8 @@
(match_operand:HI 1 "register_operand" "r")))]
""
"lsl<m> %1,%0"
[(set_attr "slottable" "yes")])
[(set_attr "slottable" "yes")
(set_attr "cc" "noov32")])
;; Various strange insns that gcc likes.
......@@ -2652,7 +3359,8 @@
(abs:SI (match_operand:SI 1 "register_operand" "r")))]
""
"abs %1,%0"
[(set_attr "slottable" "yes")])
[(set_attr "slottable" "yes")
(set_attr "cc" "noov32")])
;; FIXME: GCC should be able to do these expansions itself.
......@@ -2670,14 +3378,16 @@
(clz:SI (match_operand:SI 1 "register_operand" "r")))]
"TARGET_HAS_LZ"
"lz %1,%0"
[(set_attr "slottable" "yes")])
[(set_attr "slottable" "yes")
(set_attr "cc" "noov32")])
(define_insn "bswapsi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(bswap:SI (match_operand:SI 1 "register_operand" "0")))]
"TARGET_HAS_SWAP"
"swapwb %0"
[(set_attr "slottable" "yes")])
[(set_attr "slottable" "yes")
(set_attr "cc" "noov32")])
;; This instruction swaps all bits in a register.
;; That means that the most significant bit is put in the place
......@@ -2689,7 +3399,8 @@
CRIS_UNSPEC_SWAP_BITS))]
"TARGET_HAS_SWAP"
"swapwbr %0"
[(set_attr "slottable" "yes")])
[(set_attr "slottable" "yes")
(set_attr "cc" "noov32")])
;; Implement ctz using two instructions, one for bit swap and one for clz.
;; Defines a scratch register to avoid clobbering input.
......@@ -2708,11 +3419,21 @@
;; operation supported by gcc. Used in casesi, but used now and then in
;; normal code too.
(define_insn "uminsi3"
(define_expand "uminsi3"
[(set (match_operand:SI 0 "register_operand" "")
(umin:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "general_operand" "")))]
""
{
if (MEM_P (operands[2]) && TARGET_V32)
operands[2] = force_reg (SImode, operands[2]);
})
(define_insn "*uminsi3_non_v32"
[(set (match_operand:SI 0 "register_operand" "=r,r, r,r")
(umin:SI (match_operand:SI 1 "register_operand" "%0,0, 0,r")
(match_operand:SI 2 "general_operand" "r,Q>,g,!To")))]
""
"!TARGET_V32"
{
if (CONST_INT_P (operands[2]))
{
......@@ -2733,6 +3454,30 @@
return "bound.d %2,%0";
}
[(set_attr "slottable" "yes,yes,no,no")])
(define_insn "*uminsi3_v32"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(umin:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "r,i")))]
"TARGET_V32"
{
if (GET_CODE (operands[2]) == CONST_INT)
{
/* Constant operands are zero-extended, so only 32-bit operands
may be negative. */
if (INTVAL (operands[2]) >= 0)
{
if (INTVAL (operands[2]) < 256)
return "bound.b %2,%0";
if (INTVAL (operands[2]) < 65536)
return "bound.w %2,%0";
}
}
return "bound.d %2,%0";
}
[(set_attr "slottable" "yes,no")])
;; Jump and branch insns.
......@@ -2748,11 +3493,25 @@
;; jmp_uses_reg_or_mem used by computed_jump_p. Perhaps it is a kludge to
;; change from general_operand to nonimmediate_operand (at least the docs
;; should be changed), but then again the pattern is called indirect_jump.
(define_insn "indirect_jump"
[(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))]
(define_expand "indirect_jump"
[(set (pc) (match_operand:SI 0 "nonimmediate_operand"))]
""
{
if (TARGET_V32 && MEM_P (operands[0]))
operands[0] = force_reg (SImode, operands[0]);
})
(define_insn "*indirect_jump_non_v32"
[(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))]
"!TARGET_V32"
"jump %0")
(define_insn "*indirect_jump_v32"
[(set (pc) (match_operand:SI 0 "register_operand" "r"))]
"TARGET_V32"
"jump %0%#"
[(set_attr "slottable" "has_slot")])
;; Return insn. Used whenever the epilogue is very simple; if it is only
;; a single ret or jump [sp+]. No allocated stack space or saved
;; registers are allowed.
......@@ -2777,7 +3536,7 @@
"(cris_return_address_on_stack_for_return ())")
(const_int 0))
(const_string "no")
(const_string "has_slot")))])
(const_string "has_return_slot")))])
(define_expand "prologue"
[(const_int 0)]
......@@ -2935,14 +3694,27 @@
;; Accept *anything* as operand 1. Accept operands for operand 0 in
;; order of preference.
(define_insn "*expanded_call"
[(call (mem:QI (match_operand:SI
0 "cris_general_operand_or_plt_symbol" "r,Q>,g"))
(define_insn "*expanded_call_non_v32"
[(call (mem:QI (match_operand:SI 0 "general_operand" "r,Q>,g"))
(match_operand 1 "" ""))
(clobber (reg:SI CRIS_SRP_REGNUM))]
""
"!TARGET_V32"
"jsr %0")
(define_insn "*expanded_call_v32"
[(call
(mem:QI
(match_operand:SI 0 "cris_nonmemory_operand_or_callable_symbol" "n,r,U,i"))
(match_operand 1 "" ""))
(clobber (reg:SI CRIS_SRP_REGNUM))]
"TARGET_V32"
"@
jsr %0%#
jsr %0%#
bsr %0%#
bsr %0%#"
[(set_attr "slottable" "has_call_slot")])
;; Parallel when calculating and reusing address of indirect pointer
;; with simple offset. (Makes most sense with PIC.) It looks a bit
;; wrong not to have the clobber last, but that's the way combine
......@@ -2958,7 +3730,7 @@
(set (match_operand:SI 3 "register_operand" "=*0,r,r")
(plus:SI (match_dup 0)
(match_dup 1)))]
"! TARGET_AVOID_GOTPLT"
"!TARGET_AVOID_GOTPLT && !TARGET_V32"
"jsr [%3=%0%S1]")
(define_expand "call_value"
......@@ -2979,13 +3751,12 @@
;; We also accept a PLT symbol. We output it as [rPIC+sym:GOTPLT] rather
;; than requiring getting rPIC + sym:PLT into a register.
(define_insn "*expanded_call_value"
(define_insn "*expanded_call_value_non_v32"
[(set (match_operand 0 "nonimmediate_operand" "=g,g,g")
(call (mem:QI (match_operand:SI
1 "cris_general_operand_or_plt_symbol" "r,Q>,g"))
(call (mem:QI (match_operand:SI 1 "general_operand" "r,Q>,g"))
(match_operand 2 "" "")))
(clobber (reg:SI CRIS_SRP_REGNUM))]
""
"!TARGET_V32"
"Jsr %1"
[(set_attr "cc" "clobber")])
......@@ -3002,10 +3773,27 @@
(set (match_operand:SI 4 "register_operand" "=*1,r,r")
(plus:SI (match_dup 1)
(match_dup 2)))]
"! TARGET_AVOID_GOTPLT"
"!TARGET_AVOID_GOTPLT && !TARGET_V32"
"Jsr [%4=%1%S2]"
[(set_attr "cc" "clobber")])
(define_insn "*expanded_call_value_v32"
[(set
(match_operand 0 "nonimmediate_operand" "=g,g,g,g")
(call
(mem:QI
(match_operand:SI 1 "cris_nonmemory_operand_or_callable_symbol" "n,r,U,i"))
(match_operand 2 "" "")))
(clobber (reg:SI 16))]
"TARGET_V32"
"@
Jsr %1%#
Jsr %1%#
Bsr %1%#
Bsr %1%#"
[(set_attr "cc" "clobber")
(set_attr "slottable" "has_call_slot")])
;; Used in debugging. No use for the direct pattern; unfilled
;; delayed-branches are taken care of by other means.
......@@ -3036,7 +3824,7 @@
;; this expansion, you must change the macro ASM_OUTPUT_CASE_END
;; accordingly, to add the default case at the end of the jump-table.
(define_expand "casesi"
(define_expand "cris_casesi_non_v32"
[(set (match_dup 5) (match_operand:SI 0 "general_operand" ""))
(set (match_dup 6)
(minus:SI (match_dup 5)
......@@ -3062,6 +3850,62 @@
operands[6] = gen_reg_rtx (SImode);
operands[7] = gen_reg_rtx (SImode);
})
;; FIXME: Check effect of not JUMP_TABLES_IN_TEXT_SECTION.
(define_expand "cris_casesi_v32"
[(set (match_dup 5) (match_operand:SI 0 "general_operand"))
(set (match_dup 6)
(minus:SI (match_dup 5)
(match_operand:SI 1 "const_int_operand")))
(set (match_dup 7)
(umin:SI (match_dup 6)
(match_operand:SI 2 "const_int_operand")))
(set (match_dup 8) (match_dup 11))
(set (match_dup 9)
(plus:SI (mult:SI (match_dup 7) (const_int 2))
(match_dup 8)))
(set (match_dup 10)
(plus:SI (sign_extend:SI (mem:HI (match_dup 9)))
(match_dup 9)))
(parallel
[(set (pc)
(if_then_else
(ltu (unspec [(const_int 0)] CRIS_UNSPEC_CASESI) (match_dup 2))
(match_dup 10)
(label_ref (match_operand 4 "" ""))))
(use (label_ref (match_dup 3)))])]
"TARGET_V32"
{
int i;
rtx xlabel = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
for (i = 5; i <= 10; i++)
operands[i] = gen_reg_rtx (SImode);
operands[2] = plus_constant (operands[2], 1);
/* Don't forget to decorate labels too, for PIC. */
operands[11] = flag_pic
? gen_rtx_CONST (Pmode,
gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xlabel),
CRIS_UNSPEC_PCREL))
: xlabel;
})
(define_expand "casesi"
[(match_operand:SI 0 "general_operand")
(match_operand:SI 1 "const_int_operand")
(match_operand:SI 2 "const_int_operand")
(match_operand 3 "" "")
(match_operand 4 "" "")]
""
{
if (TARGET_V32)
emit_insn (gen_cris_casesi_v32 (operands[0], operands[1], operands[2],
operands[3], operands[4]));
else
emit_insn (gen_cris_casesi_non_v32 (operands[0], operands[1], operands[2],
operands[3], operands[4]));
DONE;
})
;; Split-patterns. Some of them have modes unspecified. This
;; should always be ok; if for no other reason sparc.md has it as
......@@ -3081,7 +3925,9 @@
;; move ry,rz
;; op [rx],rz
;; Lose if rz=ry or rx=rz.
;; Call this op-extend-split
;; Call this op-extend-split.
;; Do not match for V32; the addo and addi shouldn't be split
;; up.
(define_split
[(set (match_operand 0 "register_operand" "")
......@@ -3091,7 +3937,8 @@
(match_operator
3 "cris_extend_operator"
[(match_operand 2 "memory_operand" "")])]))]
"REG_P (operands[0])
"!TARGET_V32
&& REG_P (operands[0])
&& REG_P (operands[1])
&& REGNO (operands[1]) != REGNO (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
......@@ -3120,7 +3967,8 @@
(match_operator
3 "cris_extend_operator"
[(match_operand 2 "memory_operand" "")])]))]
"REG_P (operands[0])
"!TARGET_V32
&& REG_P (operands[0])
&& REG_P (operands[1])
&& REGNO (operands[1]) != REGNO (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
......@@ -3147,7 +3995,8 @@
3 "cris_extend_operator"
[(match_operand 2 "memory_operand" "")])
(match_operand 1 "register_operand" "")]))]
"REG_P (operands[0])
"!TARGET_V32
&& REG_P (operands[0])
&& REG_P (operands[1])
&& REGNO (operands[1]) != REGNO (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
......@@ -3172,7 +4021,8 @@
3 "cris_extend_operator"
[(match_operand 2 "memory_operand" "")])
(match_operand 1 "register_operand" "")]))]
"REG_P (operands[0])
"!TARGET_V32
&& REG_P (operands[0])
&& REG_P (operands[1])
&& REGNO (operands[1]) != REGNO (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
......@@ -3200,7 +4050,8 @@
3 "cris_orthogonal_operator"
[(match_operand 1 "register_operand" "")
(match_operand 2 "memory_operand" "")]))]
"REG_P (operands[0])
"!TARGET_V32
&& REG_P (operands[0])
&& REG_P (operands[1])
&& REGNO (operands[1]) != REGNO (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
......@@ -3223,7 +4074,8 @@
3 "cris_commutative_orth_op"
[(match_operand 2 "memory_operand" "")
(match_operand 1 "register_operand" "")]))]
"REG_P (operands[0])
"!TARGET_V32
&& REG_P (operands[0])
&& REG_P (operands[1])
&& REGNO (operands[1]) != REGNO (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
......@@ -3246,7 +4098,8 @@
3 "cris_commutative_orth_op"
[(match_operand 1 "register_operand" "")
(match_operand 2 "memory_operand" "")]))]
"REG_P (operands[0]) && REG_P (operands[1])
"!TARGET_V32
&& REG_P (operands[0]) && REG_P (operands[1])
&& REGNO (operands[1]) != REGNO (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
&& REG_P (XEXP (operands[2], 0))
......@@ -3268,7 +4121,8 @@
3 "cris_orthogonal_operator"
[(match_operand 2 "memory_operand" "")
(match_operand 1 "register_operand" "")]))]
"REG_P (operands[0]) && REG_P (operands[1])
"!TARGET_V32
&& REG_P (operands[0]) && REG_P (operands[1])
&& REGNO (operands[1]) != REGNO (operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD
&& REG_P (XEXP (operands[2], 0))
......@@ -3818,7 +4672,8 @@
&& (BASE_P (operands[1]) || BASE_P (operands[2]))
&& ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
&& ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
&& (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)"
&& (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)
&& TARGET_SIDE_EFFECT_PREFIXES"
[(parallel
[(set (match_dup 3) (match_dup 5))
(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])]
......@@ -3853,7 +4708,8 @@
&& (BASE_P (operands[1]) || BASE_P (operands[2]))
&& ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
&& ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
&& (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)"
&& (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)
&& TARGET_SIDE_EFFECT_PREFIXES"
[(parallel
[(set (match_dup 5) (match_dup 4))
(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])]
......@@ -3891,7 +4747,8 @@
&& ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
&& ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
&& INTVAL (operands[2]) >= -128
&& INTVAL (operands[2]) <= 127"
&& INTVAL (operands[2]) <= 127
&& TARGET_SIDE_EFFECT_PREFIXES"
[(parallel
[(set (match_dup 3) (match_op_dup 4 [(match_dup 3) (match_dup 6)]))
(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])]
......@@ -4121,9 +4978,9 @@
(unspec:SI [(match_operand:SI 2 "cris_general_operand_or_symbol" "")]
CRIS_UNSPEC_PLTGOTREAD)))]))]
"flag_pic
&& cris_valid_pic_const (XEXP (XEXP (operands[1], 0), 1))
&& cris_valid_pic_const (XEXP (XEXP (operands[1], 0), 1), true)
&& REGNO_REG_CLASS (REGNO (operands[0])) == REGNO_REG_CLASS (0)"
[(set (match_dup 0) (const:SI (unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLT)))
[(set (match_dup 0) (const:SI (unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLT_GOTREL)))
(set (match_dup 0) (plus:SI (match_dup 0) (reg:SI CRIS_GOT_REGNUM)))]
"")
......@@ -4150,7 +5007,7 @@
(match_operand 4 "" ""))
(clobber (reg:SI CRIS_SRP_REGNUM))])]
"flag_pic
&& cris_valid_pic_const (XEXP (XEXP (operands[1], 0), 1))
&& cris_valid_pic_const (XEXP (XEXP (operands[1], 0), 1), true)
&& peep2_reg_dead_p (2, operands[0])"
[(parallel [(call (mem:QI (match_dup 1))
(match_dup 4))
......@@ -4183,7 +5040,7 @@
(match_operand 4 "" "")))
(clobber (reg:SI CRIS_SRP_REGNUM))])]
"flag_pic
&& cris_valid_pic_const (XEXP (XEXP (operands[1], 0), 1))
&& cris_valid_pic_const (XEXP (XEXP (operands[1], 0), 1), true)
&& peep2_reg_dead_p (2, operands[0])"
[(parallel [(set (match_dup 5)
(call (mem:QI (match_dup 1))
......@@ -4213,12 +5070,13 @@
(const:SI
(unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLTGOTREAD))))])]
"flag_pic
&& cris_valid_pic_const (XEXP (XEXP (operands[1], 0), 1))
&& cris_valid_pic_const (XEXP (XEXP (operands[1], 0), 1), true)
&& REGNO_REG_CLASS (REGNO (operands[0])) == REGNO_REG_CLASS (0)"
[(set (match_dup 3)
(const:SI (unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLTGOTREAD)))
(set (match_dup 3) (plus:SI (match_dup 3) (reg:SI CRIS_GOT_REGNUM)))
(set (match_dup 0) (const:SI (unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLT)))
(set (match_dup 0)
(const:SI (unspec:SI [(match_dup 2)] CRIS_UNSPEC_PLT_GOTREL)))
(set (match_dup 0) (plus:SI (match_dup 0) (reg:SI CRIS_GOT_REGNUM)))]
"")
......
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