Commit 21dfc6dc by Richard Sandiford Committed by Richard Sandiford

md.texi: Synchronize with later constraints.md change.

gcc/
	* doc/md.texi: Synchronize with later constraints.md change.
	* longlong.h (umul_ppmm): Replace the MIPS asm implementation
	with a C implementation.
	* config/mips/mips.c (mips_legitimize_move): Remove MFHI and
	MFLO handling.
	(mips_subword): Assume TImode for CONST_INTs if TARGET_64BIT.
	(mips_split_doubleword_move): Use special MTHI and MFHI instructions
	when moving to and from MD_REGNUM.
	(mips_output_move): Don't handle moves from GPRs to HI_REGNUM.
	Handle moves from LO_REGNUM to GPRs using MFLO, MACC or DMACC.
	Handle byte and halfword moves.
	(mips_hard_regno_mode_ok_p): Handle MD_REGS and DSP_ACC_REGS
	separately.
	* config/mips/constraints.md (h): Turn into NO_REGS.
	(l, x): Update documentation.
	* config/mips/mips.md (UNSPEC_MFHILO): Delete.
	(UNSPEC_MFHI, UNSPEC_MTHI, UNSPEC_SET_HILO): New.
	(UNSPEC_TLS_LDM, UNSPEC_TLS_GET_TP): Renumber.
	(HILO): New mode iterator.
	(MOVE128): Add TI.
	(any_div): New code iterator.
	(u): Extend code attribute to div and udiv.
	(*add<mode>3_mips16, *movdi_64bit_mips16, *movsi_mips16): Use
	d_operand in the splitters.  Remove redundant CONST_INT checks.
	(mulsi3_mult3, mul<mode>3_internal, mul<mode>3_r4000, *mul_acc_si)
	(*macc, *msac, *msac_using_macc, *macc2, *msac2, *mul_sub_si)
	(*muls): Remove "=h" clobbers.  Adjust peephole2s and define_splits
	accordingly, using normal moves instead of unspecs to move LO into
	a GPR.  Use d_operand and lo_operand instead of *_REG_P checks.
	(<u>mulsidi3): Handle expansion in C code.
	(<u>mulsidi3_32bit_internal): Rename to...
	(<u>mulsidi3_32bit): ...this.
	(<u>mulsidi3_32bit_r4000): Fix insn separator.
	(*<u>mulsidi3_64bit): Rename to...
	(<u>mulsidi3_64bit): ...this.  Combine DImode "=h" and "=l" clobbers
	into a TImode "=x" clobber.  In the split, use an UNSPEC_SET_HILO
	to set LO and HI to the multiplication result.  Use a normal move
	for MFLO and an unspec for MFHI.
	(*<u>mulsidi3_64bit_parts): Replace with...
	(<u>mulsidi3_64bit_hilo): ...this new instruction.
	(<su>mulsi3_highpart): Extend to TARGET_FIX_R4000.
	(<su>mulsi3_highpart_internal): Turn into a define_insn_and_split
	and extend it to TARGET_FIX_R4000.  Store the destination in a GPR
	instead of HI.  Split the instruction into a separate multiplication
	and MFHI if !TARGET_FIX_R4000.
	(<su>muldi3_highpart): Likewise.
	(<su>mulsi3_highpart_mulhi_internal): Remove the first alternative
	and the "=h" clobber.
	(*<su>mulsi3_highpart_neg_mulhi_internal): Likewise.
	(<u>mulditi3): New expander.
	(<u>mulditi3_internal, <u>mulditi3_r4000): New patterns.
	(madsi): Remove "=h" clobber.
	(divmod<mode>4, udivmod<mode>4): Turn into define_insn_and_splits.
	Force the modulus result to be a GPR and split the instruction into
	a division followed by an MFHI after reload.
	(<u>divmod<GPR:mode>4_hilo_<HILO:mode>): New instruction.
	(*lea_high64): Use d_operand in the define_peephole2.  Likewise
	the MIPS16 HIGH define_split.
	(*movdi_32bit, *movdi_gp32_fp64, *movdi_32bit_mips16): Change type
	of acc<->gpr moves to "multi".
	(*movdi_64bit): Replace the single "x" alternative with
	alternatives for moving into and out of "a".
	(*movhi_internal, *movqi_internal): Likewise.  Use mips_output_move.
	(*movsi_internal): Extend the "d<-A" alternative to "d<-a".
	(*movdi_64bit_mips16, *movsi_mips16): Add d<-a alternatives.
	Use d_operand in the splitters.  Remove redundant CONST_INT checks.
	(*movhi_mips16, *movqi_mips16): Likewise.  Use mips_output_move.
	(movti): New expander.
	(*movti, *movti_mips16): New insns.
	(mfhilo_<mode>, *mfhilo_<mode>, *mfhilo_<mode>_macc): Delete.
	(mfhi<GPR:mode>_<HILO:mode>): New pattern.
	(mthi<GPR:mode>_<HILO:mode>): Likewise.
	* config/mips/predicates.md (fpr_operand): Delete.
	(d_operand): New predicate.

gcc/testsuite/
	* gcc.dg/torture/mips-hilo-1.c: Delete.
	* gcc.target/mips/pr35232.c: Likewise.
	* gcc.target/mips/fix-vr4130-1.c: Use modulus to create an mfhi.
	* gcc.target/mips/fix-vr4130-3.c: Likewise.
	* gcc.target/mips/int-moves-1.c: New test.
	* gcc.target/mips/int-moves-2.c: Likewise.
	* gcc.target/mips/fix-r4000-1.c: Likewise.
	* gcc.target/mips/fix-r4000-2.c: Likewise.
	* gcc.target/mips/fix-r4000-3.c: Likewise.
	* gcc.target/mips/fix-r4000-4.c: Likewise.
	* gcc.target/mips/fix-r4000-5.c: Likewise.
	* gcc.target/mips/fix-r4000-6.c: Likewise.
	* gcc.target/mips/fix-r4000-7.c: Likewise.
	* gcc.target/mips/fix-r4000-8.c: Likewise.
	* gcc.target/mips/fix-r4000-9.c: Likewise.
	* gcc.target/mips/fix-r4000-10.c: Likewise.
	* gcc.target/mips/fix-r4000-11.c: Likewise.
	* gcc.target/mips/fix-r4000-12.c: Likewise.
	* gcc.target/mips/timode-1.c: Likewise.
	* gcc.target/mips/timode-2.c: Likewise.

From-SVN: r136600
parent 0e462a95
2008-06-09 Richard Sandiford <rdsandiford@googlemail.com>
* doc/md.texi: Synchronize with later constraints.md change.
* longlong.h (umul_ppmm): Replace the MIPS asm implementation
with a C implementation.
* config/mips/mips.c (mips_legitimize_move): Remove MFHI and
MFLO handling.
(mips_subword): Assume TImode for CONST_INTs if TARGET_64BIT.
(mips_split_doubleword_move): Use special MTHI and MFHI instructions
when moving to and from MD_REGNUM.
(mips_output_move): Don't handle moves from GPRs to HI_REGNUM.
Handle moves from LO_REGNUM to GPRs using MFLO, MACC or DMACC.
Handle byte and halfword moves.
(mips_hard_regno_mode_ok_p): Handle MD_REGS and DSP_ACC_REGS
separately.
* config/mips/constraints.md (h): Turn into NO_REGS.
(l, x): Update documentation.
* config/mips/mips.md (UNSPEC_MFHILO): Delete.
(UNSPEC_MFHI, UNSPEC_MTHI, UNSPEC_SET_HILO): New.
(UNSPEC_TLS_LDM, UNSPEC_TLS_GET_TP): Renumber.
(HILO): New mode iterator.
(MOVE128): Add TI.
(any_div): New code iterator.
(u): Extend code attribute to div and udiv.
(*add<mode>3_mips16, *movdi_64bit_mips16, *movsi_mips16): Use
d_operand in the splitters. Remove redundant CONST_INT checks.
(mulsi3_mult3, mul<mode>3_internal, mul<mode>3_r4000, *mul_acc_si)
(*macc, *msac, *msac_using_macc, *macc2, *msac2, *mul_sub_si)
(*muls): Remove "=h" clobbers. Adjust peephole2s and define_splits
accordingly, using normal moves instead of unspecs to move LO into
a GPR. Use d_operand and lo_operand instead of *_REG_P checks.
(<u>mulsidi3): Handle expansion in C code.
(<u>mulsidi3_32bit_internal): Rename to...
(<u>mulsidi3_32bit): ...this.
(<u>mulsidi3_32bit_r4000): Fix insn separator.
(*<u>mulsidi3_64bit): Rename to...
(<u>mulsidi3_64bit): ...this. Combine DImode "=h" and "=l" clobbers
into a TImode "=x" clobber. In the split, use an UNSPEC_SET_HILO
to set LO and HI to the multiplication result. Use a normal move
for MFLO and an unspec for MFHI.
(*<u>mulsidi3_64bit_parts): Replace with...
(<u>mulsidi3_64bit_hilo): ...this new instruction.
(<su>mulsi3_highpart): Extend to TARGET_FIX_R4000.
(<su>mulsi3_highpart_internal): Turn into a define_insn_and_split
and extend it to TARGET_FIX_R4000. Store the destination in a GPR
instead of HI. Split the instruction into a separate multiplication
and MFHI if !TARGET_FIX_R4000.
(<su>muldi3_highpart): Likewise.
(<su>mulsi3_highpart_mulhi_internal): Remove the first alternative
and the "=h" clobber.
(*<su>mulsi3_highpart_neg_mulhi_internal): Likewise.
(<u>mulditi3): New expander.
(<u>mulditi3_internal, <u>mulditi3_r4000): New patterns.
(madsi): Remove "=h" clobber.
(divmod<mode>4, udivmod<mode>4): Turn into define_insn_and_splits.
Force the modulus result to be a GPR and split the instruction into
a division followed by an MFHI after reload.
(<u>divmod<GPR:mode>4_hilo_<HILO:mode>): New instruction.
(*lea_high64): Use d_operand in the define_peephole2. Likewise
the MIPS16 HIGH define_split.
(*movdi_32bit, *movdi_gp32_fp64, *movdi_32bit_mips16): Change type
of acc<->gpr moves to "multi".
(*movdi_64bit): Replace the single "x" alternative with
alternatives for moving into and out of "a".
(*movhi_internal, *movqi_internal): Likewise. Use mips_output_move.
(*movsi_internal): Extend the "d<-A" alternative to "d<-a".
(*movdi_64bit_mips16, *movsi_mips16): Add d<-a alternatives.
Use d_operand in the splitters. Remove redundant CONST_INT checks.
(*movhi_mips16, *movqi_mips16): Likewise. Use mips_output_move.
(movti): New expander.
(*movti, *movti_mips16): New insns.
(mfhilo_<mode>, *mfhilo_<mode>, *mfhilo_<mode>_macc): Delete.
(mfhi<GPR:mode>_<HILO:mode>): New pattern.
(mthi<GPR:mode>_<HILO:mode>): Likewise.
* config/mips/predicates.md (fpr_operand): Delete.
(d_operand): New predicate.
2008-06-09 Michael Meissner <michael.meissner@amd.com> 2008-06-09 Michael Meissner <michael.meissner@amd.com>
* config.gcc (i[34567]86-*-*): Put test in quotes to prevent * config.gcc (i[34567]86-*-*): Put test in quotes to prevent
......
...@@ -29,14 +29,16 @@ ...@@ -29,14 +29,16 @@
(define_register_constraint "f" "TARGET_HARD_FLOAT ? FP_REGS : NO_REGS" (define_register_constraint "f" "TARGET_HARD_FLOAT ? FP_REGS : NO_REGS"
"A floating-point register (if available).") "A floating-point register (if available).")
(define_register_constraint "h" "TARGET_BIG_ENDIAN ? MD0_REG : MD1_REG" (define_register_constraint "h" "NO_REGS"
"The @code{hi} register.") "Formerly the @code{hi} register. This constraint is no longer supported.")
(define_register_constraint "l" "TARGET_BIG_ENDIAN ? MD1_REG : MD0_REG" (define_register_constraint "l" "TARGET_BIG_ENDIAN ? MD1_REG : MD0_REG"
"The @code{lo} register.") "The @code{lo} register. Use this register to store values that are
no bigger than a word.")
(define_register_constraint "x" "MD_REGS" (define_register_constraint "x" "MD_REGS"
"The @code{hi} and @code{lo} registers.") "The concatenated @code{hi} and @code{lo} registers. Use this register
to store doubleword values.")
(define_register_constraint "b" "ALL_REGS" (define_register_constraint "b" "ALL_REGS"
"@internal") "@internal")
......
...@@ -2675,23 +2675,6 @@ mips_legitimize_move (enum machine_mode mode, rtx dest, rtx src) ...@@ -2675,23 +2675,6 @@ mips_legitimize_move (enum machine_mode mode, rtx dest, rtx src)
return true; return true;
} }
/* Check for individual, fully-reloaded mflo and mfhi instructions. */
if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
&& REG_P (src) && MD_REG_P (REGNO (src))
&& REG_P (dest) && GP_REG_P (REGNO (dest)))
{
int other_regno = REGNO (src) == HI_REGNUM ? LO_REGNUM : HI_REGNUM;
if (GET_MODE_SIZE (mode) <= 4)
emit_insn (gen_mfhilo_si (gen_lowpart (SImode, dest),
gen_lowpart (SImode, src),
gen_rtx_REG (SImode, other_regno)));
else
emit_insn (gen_mfhilo_di (gen_lowpart (DImode, dest),
gen_lowpart (DImode, src),
gen_rtx_REG (DImode, other_regno)));
return true;
}
/* We need to deal with constants that would be legitimate /* We need to deal with constants that would be legitimate
immediate_operands but aren't legitimate move_operands. */ immediate_operands but aren't legitimate move_operands. */
if (CONSTANT_P (src) && !move_operand (src, mode)) if (CONSTANT_P (src) && !move_operand (src, mode))
...@@ -3488,7 +3471,7 @@ mips_subword (rtx op, bool high_p) ...@@ -3488,7 +3471,7 @@ mips_subword (rtx op, bool high_p)
mode = GET_MODE (op); mode = GET_MODE (op);
if (mode == VOIDmode) if (mode == VOIDmode)
mode = DImode; mode = TARGET_64BIT ? TImode : DImode;
if (TARGET_BIG_ENDIAN ? !high_p : high_p) if (TARGET_BIG_ENDIAN ? !high_p : high_p)
byte = UNITS_PER_WORD; byte = UNITS_PER_WORD;
...@@ -3539,6 +3522,8 @@ mips_split_64bit_move_p (rtx dest, rtx src) ...@@ -3539,6 +3522,8 @@ mips_split_64bit_move_p (rtx dest, rtx src)
void void
mips_split_doubleword_move (rtx dest, rtx src) mips_split_doubleword_move (rtx dest, rtx src)
{ {
rtx low_dest;
if (FP_REG_RTX_P (dest) || FP_REG_RTX_P (src)) if (FP_REG_RTX_P (dest) || FP_REG_RTX_P (src))
{ {
if (!TARGET_64BIT && GET_MODE (dest) == DImode) if (!TARGET_64BIT && GET_MODE (dest) == DImode)
...@@ -3552,12 +3537,27 @@ mips_split_doubleword_move (rtx dest, rtx src) ...@@ -3552,12 +3537,27 @@ mips_split_doubleword_move (rtx dest, rtx src)
else else
gcc_unreachable (); gcc_unreachable ();
} }
else if (REG_P (dest) && REGNO (dest) == MD_REG_FIRST)
{
low_dest = mips_subword (dest, false);
mips_emit_move (low_dest, mips_subword (src, false));
if (TARGET_64BIT)
emit_insn (gen_mthidi_ti (dest, mips_subword (src, true), low_dest));
else
emit_insn (gen_mthisi_di (dest, mips_subword (src, true), low_dest));
}
else if (REG_P (src) && REGNO (src) == MD_REG_FIRST)
{
mips_emit_move (mips_subword (dest, false), mips_subword (src, false));
if (TARGET_64BIT)
emit_insn (gen_mfhidi_ti (mips_subword (dest, true), src));
else
emit_insn (gen_mfhisi_di (mips_subword (dest, true), src));
}
else else
{ {
/* The operation can be split into two normal moves. Decide in /* The operation can be split into two normal moves. Decide in
which order to do them. */ which order to do them. */
rtx low_dest;
low_dest = mips_subword (dest, false); low_dest = mips_subword (dest, false);
if (REG_P (low_dest) if (REG_P (low_dest)
&& reg_overlap_mentioned_p (low_dest, src)) && reg_overlap_mentioned_p (low_dest, src))
...@@ -3600,8 +3600,9 @@ mips_output_move (rtx dest, rtx src) ...@@ -3600,8 +3600,9 @@ mips_output_move (rtx dest, rtx src)
if (GP_REG_P (REGNO (dest))) if (GP_REG_P (REGNO (dest)))
return "move\t%0,%z1"; return "move\t%0,%z1";
if (MD_REG_P (REGNO (dest))) /* Moves to HI are handled by special .md insns. */
return "mt%0\t%z1"; if (REGNO (dest) == LO_REGNUM)
return "mtlo\t%z1";
if (DSP_ACC_REG_P (REGNO (dest))) if (DSP_ACC_REG_P (REGNO (dest)))
{ {
...@@ -3624,14 +3625,29 @@ mips_output_move (rtx dest, rtx src) ...@@ -3624,14 +3625,29 @@ mips_output_move (rtx dest, rtx src)
} }
} }
if (dest_code == MEM) if (dest_code == MEM)
return dbl_p ? "sd\t%z1,%0" : "sw\t%z1,%0"; switch (GET_MODE_SIZE (mode))
{
case 1: return "sb\t%z1,%0";
case 2: return "sh\t%z1,%0";
case 4: return "sw\t%z1,%0";
case 8: return "sd\t%z1,%0";
}
} }
if (dest_code == REG && GP_REG_P (REGNO (dest))) if (dest_code == REG && GP_REG_P (REGNO (dest)))
{ {
if (src_code == REG) if (src_code == REG)
{ {
/* Handled by separate patterns. */ /* Moves from HI are handled by special .md insns. */
gcc_assert (!MD_REG_P (REGNO (src))); if (REGNO (src) == LO_REGNUM)
{
/* When generating VR4120 or VR4130 code, we use MACC and
DMACC instead of MFLO. This avoids both the normal
MIPS III HI/LO hazards and the errata related to
-mfix-vr4130. */
if (ISA_HAS_MACCHI)
return dbl_p ? "dmacc\t%0,%.,%." : "macc\t%0,%.,%.";
return "mflo\t%0";
}
if (DSP_ACC_REG_P (REGNO (src))) if (DSP_ACC_REG_P (REGNO (src)))
{ {
...@@ -3658,7 +3674,13 @@ mips_output_move (rtx dest, rtx src) ...@@ -3658,7 +3674,13 @@ mips_output_move (rtx dest, rtx src)
} }
if (src_code == MEM) if (src_code == MEM)
return dbl_p ? "ld\t%0,%1" : "lw\t%0,%1"; switch (GET_MODE_SIZE (mode))
{
case 1: return "lbu\t%0,%1";
case 2: return "lhu\t%0,%1";
case 4: return "lw\t%0,%1";
case 8: return "ld\t%0,%1";
}
if (src_code == CONST_INT) if (src_code == CONST_INT)
{ {
...@@ -8954,13 +8976,30 @@ mips_hard_regno_mode_ok_p (unsigned int regno, enum machine_mode mode) ...@@ -8954,13 +8976,30 @@ mips_hard_regno_mode_ok_p (unsigned int regno, enum machine_mode mode)
if (ACC_REG_P (regno) if (ACC_REG_P (regno)
&& (INTEGRAL_MODE_P (mode) || ALL_FIXED_POINT_MODE_P (mode))) && (INTEGRAL_MODE_P (mode) || ALL_FIXED_POINT_MODE_P (mode)))
{ {
if (MD_REG_P (regno))
{
/* After a multiplication or division, clobbering HI makes
the value of LO unpredictable, and vice versa. This means
that, for all interesting cases, HI and LO are effectively
a single register.
We model this by requiring that any value that uses HI
also uses LO. */
if (size <= UNITS_PER_WORD * 2)
return regno == (size <= UNITS_PER_WORD ? LO_REGNUM : MD_REG_FIRST);
}
else
{
/* DSP accumulators do not have the same restrictions as
HI and LO, so we can treat them as normal doubleword
registers. */
if (size <= UNITS_PER_WORD) if (size <= UNITS_PER_WORD)
return true; return true;
if (size <= UNITS_PER_WORD * 2) if (size <= UNITS_PER_WORD * 2
return (DSP_ACC_REG_P (regno) && ((regno - DSP_ACC_REG_FIRST) & 1) == 0)
? ((regno - DSP_ACC_REG_FIRST) & 1) == 0 return true;
: regno == MD_REG_FIRST); }
} }
if (ALL_COP_REG_P (regno)) if (ALL_COP_REG_P (regno))
......
...@@ -44,9 +44,11 @@ ...@@ -44,9 +44,11 @@
(UNSPEC_LOAD_CALL 23) (UNSPEC_LOAD_CALL 23)
(UNSPEC_LOAD_GOT 24) (UNSPEC_LOAD_GOT 24)
(UNSPEC_GP 25) (UNSPEC_GP 25)
(UNSPEC_MFHILO 26) (UNSPEC_MFHI 26)
(UNSPEC_TLS_LDM 27) (UNSPEC_MTHI 27)
(UNSPEC_TLS_GET_TP 28) (UNSPEC_SET_HILO 28)
(UNSPEC_TLS_LDM 29)
(UNSPEC_TLS_GET_TP 30)
(UNSPEC_MFHC1 31) (UNSPEC_MFHC1 31)
(UNSPEC_MTHC1 32) (UNSPEC_MTHC1 32)
(UNSPEC_CLEAR_HAZARD 33) (UNSPEC_CLEAR_HAZARD 33)
...@@ -484,6 +486,10 @@ ...@@ -484,6 +486,10 @@
;; modes. ;; modes.
(define_mode_iterator GPR2 [SI (DI "TARGET_64BIT")]) (define_mode_iterator GPR2 [SI (DI "TARGET_64BIT")])
;; This mode iterator allows :HILO to be used as the mode of the
;; concatenated HI and LO registers.
(define_mode_iterator HILO [(DI "!TARGET_64BIT") (TI "TARGET_64BIT")])
;; This mode iterator allows :P to be used for patterns that operate on ;; This mode iterator allows :P to be used for patterns that operate on
;; pointer-sized quantities. Exactly one of the two alternatives will match. ;; pointer-sized quantities. Exactly one of the two alternatives will match.
(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")]) (define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
...@@ -497,7 +503,7 @@ ...@@ -497,7 +503,7 @@
[DI DF (V2SF "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT")]) [DI DF (V2SF "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT")])
;; 128-bit modes for which we provide move patterns on 64-bit targets. ;; 128-bit modes for which we provide move patterns on 64-bit targets.
(define_mode_iterator MOVE128 [TF]) (define_mode_iterator MOVE128 [TI TF])
;; This mode iterator allows the QI and HI extension patterns to be ;; This mode iterator allows the QI and HI extension patterns to be
;; defined from the same template. ;; defined from the same template.
...@@ -613,6 +619,10 @@ ...@@ -613,6 +619,10 @@
;; from the same template. ;; from the same template.
(define_code_iterator any_shift [ashift ashiftrt lshiftrt]) (define_code_iterator any_shift [ashift ashiftrt lshiftrt])
;; This code iterator allows unsigned and signed division to be generated
;; from the same template.
(define_code_iterator any_div [div udiv])
;; This code iterator allows all native floating-point comparisons to be ;; This code iterator allows all native floating-point comparisons to be
;; generated from the same template. ;; generated from the same template.
(define_code_iterator fcond [unordered uneq unlt unle eq lt le]) (define_code_iterator fcond [unordered uneq unlt unle eq lt le])
...@@ -631,6 +641,7 @@ ...@@ -631,6 +641,7 @@
;; <u> expands to an empty string when doing a signed operation and ;; <u> expands to an empty string when doing a signed operation and
;; "u" when doing an unsigned operation. ;; "u" when doing an unsigned operation.
(define_code_attr u [(sign_extend "") (zero_extend "u") (define_code_attr u [(sign_extend "") (zero_extend "u")
(div "") (udiv "u")
(gt "") (gtu "u") (gt "") (gtu "u")
(ge "") (geu "u") (ge "") (geu "u")
(lt "") (ltu "u") (lt "") (ltu "u")
...@@ -865,13 +876,10 @@ ...@@ -865,13 +876,10 @@
;; simply adding a constant to a register. ;; simply adding a constant to a register.
(define_split (define_split
[(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "d_operand")
(plus:SI (match_dup 0) (plus:SI (match_dup 0)
(match_operand:SI 1 "const_int_operand")))] (match_operand:SI 1 "const_int_operand")))]
"TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
&& REG_P (operands[0])
&& M16_REG_P (REGNO (operands[0]))
&& GET_CODE (operands[1]) == CONST_INT
&& ((INTVAL (operands[1]) > 0x7f && ((INTVAL (operands[1]) > 0x7f
&& INTVAL (operands[1]) <= 0x7f + 0x7f) && INTVAL (operands[1]) <= 0x7f + 0x7f)
|| (INTVAL (operands[1]) < - 0x80 || (INTVAL (operands[1]) < - 0x80
...@@ -894,16 +902,11 @@ ...@@ -894,16 +902,11 @@
}) })
(define_split (define_split
[(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "d_operand")
(plus:SI (match_operand:SI 1 "register_operand") (plus:SI (match_operand:SI 1 "d_operand")
(match_operand:SI 2 "const_int_operand")))] (match_operand:SI 2 "const_int_operand")))]
"TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
&& REG_P (operands[0])
&& M16_REG_P (REGNO (operands[0]))
&& REG_P (operands[1])
&& M16_REG_P (REGNO (operands[1]))
&& REGNO (operands[0]) != REGNO (operands[1]) && REGNO (operands[0]) != REGNO (operands[1])
&& GET_CODE (operands[2]) == CONST_INT
&& ((INTVAL (operands[2]) > 0x7 && ((INTVAL (operands[2]) > 0x7
&& INTVAL (operands[2]) <= 0x7 + 0x7f) && INTVAL (operands[2]) <= 0x7 + 0x7f)
|| (INTVAL (operands[2]) < - 0x8 || (INTVAL (operands[2]) < - 0x8
...@@ -926,13 +929,10 @@ ...@@ -926,13 +929,10 @@
}) })
(define_split (define_split
[(set (match_operand:DI 0 "register_operand") [(set (match_operand:DI 0 "d_operand")
(plus:DI (match_dup 0) (plus:DI (match_dup 0)
(match_operand:DI 1 "const_int_operand")))] (match_operand:DI 1 "const_int_operand")))]
"TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE "TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE
&& REG_P (operands[0])
&& M16_REG_P (REGNO (operands[0]))
&& GET_CODE (operands[1]) == CONST_INT
&& ((INTVAL (operands[1]) > 0xf && ((INTVAL (operands[1]) > 0xf
&& INTVAL (operands[1]) <= 0xf + 0xf) && INTVAL (operands[1]) <= 0xf + 0xf)
|| (INTVAL (operands[1]) < - 0x10 || (INTVAL (operands[1]) < - 0x10
...@@ -955,16 +955,11 @@ ...@@ -955,16 +955,11 @@
}) })
(define_split (define_split
[(set (match_operand:DI 0 "register_operand") [(set (match_operand:DI 0 "d_operand")
(plus:DI (match_operand:DI 1 "register_operand") (plus:DI (match_operand:DI 1 "d_operand")
(match_operand:DI 2 "const_int_operand")))] (match_operand:DI 2 "const_int_operand")))]
"TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE "TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE
&& REG_P (operands[0])
&& M16_REG_P (REGNO (operands[0]))
&& REG_P (operands[1])
&& M16_REG_P (REGNO (operands[1]))
&& REGNO (operands[0]) != REGNO (operands[1]) && REGNO (operands[0]) != REGNO (operands[1])
&& GET_CODE (operands[2]) == CONST_INT
&& ((INTVAL (operands[2]) > 0x7 && ((INTVAL (operands[2]) > 0x7
&& INTVAL (operands[2]) <= 0x7 + 0xf) && INTVAL (operands[2]) <= 0x7 + 0xf)
|| (INTVAL (operands[2]) < - 0x8 || (INTVAL (operands[2]) < - 0x8
...@@ -1175,8 +1170,7 @@ ...@@ -1175,8 +1170,7 @@
[(set (match_operand:SI 0 "register_operand" "=d,l") [(set (match_operand:SI 0 "register_operand" "=d,l")
(mult:SI (match_operand:SI 1 "register_operand" "d,d") (mult:SI (match_operand:SI 1 "register_operand" "d,d")
(match_operand:SI 2 "register_operand" "d,d"))) (match_operand:SI 2 "register_operand" "d,d")))
(clobber (match_scratch:SI 3 "=h,h")) (clobber (match_scratch:SI 3 "=l,X"))]
(clobber (match_scratch:SI 4 "=l,X"))]
"ISA_HAS_MUL3" "ISA_HAS_MUL3"
{ {
if (which_alternative == 1) if (which_alternative == 1)
...@@ -1195,30 +1189,26 @@ ...@@ -1195,30 +1189,26 @@
;; Operand 0: LO ;; Operand 0: LO
;; Operand 1: GPR (1st multiplication operand) ;; Operand 1: GPR (1st multiplication operand)
;; Operand 2: GPR (2nd multiplication operand) ;; Operand 2: GPR (2nd multiplication operand)
;; Operand 3: HI ;; Operand 3: GPR (destination)
;; Operand 4: GPR (destination)
(define_peephole2 (define_peephole2
[(parallel [(parallel
[(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "lo_operand")
(mult:SI (match_operand:SI 1 "register_operand") (mult:SI (match_operand:SI 1 "d_operand")
(match_operand:SI 2 "register_operand"))) (match_operand:SI 2 "d_operand")))
(clobber (match_operand:SI 3 "register_operand"))
(clobber (scratch:SI))]) (clobber (scratch:SI))])
(set (match_operand:SI 4 "register_operand") (set (match_operand:SI 3 "d_operand")
(unspec [(match_dup 0) (match_dup 3)] UNSPEC_MFHILO))] (match_dup 0))]
"ISA_HAS_MUL3 && peep2_reg_dead_p (2, operands[0])" "ISA_HAS_MUL3 && peep2_reg_dead_p (2, operands[0])"
[(parallel [(parallel
[(set (match_dup 4) [(set (match_dup 3)
(mult:SI (match_dup 1) (mult:SI (match_dup 1)
(match_dup 2))) (match_dup 2)))
(clobber (match_dup 3))
(clobber (match_dup 0))])]) (clobber (match_dup 0))])])
(define_insn "mul<mode>3_internal" (define_insn "mul<mode>3_internal"
[(set (match_operand:GPR 0 "register_operand" "=l") [(set (match_operand:GPR 0 "register_operand" "=l")
(mult:GPR (match_operand:GPR 1 "register_operand" "d") (mult:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand:GPR 2 "register_operand" "d"))) (match_operand:GPR 2 "register_operand" "d")))]
(clobber (match_scratch:GPR 3 "=h"))]
"!TARGET_FIX_R4000" "!TARGET_FIX_R4000"
"<d>mult\t%1,%2" "<d>mult\t%1,%2"
[(set_attr "type" "imul") [(set_attr "type" "imul")
...@@ -1228,8 +1218,7 @@ ...@@ -1228,8 +1218,7 @@
[(set (match_operand:GPR 0 "register_operand" "=d") [(set (match_operand:GPR 0 "register_operand" "=d")
(mult:GPR (match_operand:GPR 1 "register_operand" "d") (mult:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand:GPR 2 "register_operand" "d"))) (match_operand:GPR 2 "register_operand" "d")))
(clobber (match_scratch:GPR 3 "=h")) (clobber (match_scratch:GPR 3 "=l"))]
(clobber (match_scratch:GPR 4 "=l"))]
"TARGET_FIX_R4000" "TARGET_FIX_R4000"
"<d>mult\t%1,%2\;mflo\t%0" "<d>mult\t%1,%2\;mflo\t%0"
[(set_attr "type" "imul") [(set_attr "type" "imul")
...@@ -1243,16 +1232,13 @@ ...@@ -1243,16 +1232,13 @@
;; Operand 0: LO ;; Operand 0: LO
;; Operand 1: GPR (1st multiplication operand) ;; Operand 1: GPR (1st multiplication operand)
;; Operand 2: GPR (2nd multiplication operand) ;; Operand 2: GPR (2nd multiplication operand)
;; Operand 3: HI ;; Operand 3: GPR (destination)
;; Operand 4: GPR (destination)
(define_peephole2 (define_peephole2
[(parallel [(set (match_operand:SI 0 "lo_operand")
[(set (match_operand:SI 0 "register_operand") (mult:SI (match_operand:SI 1 "d_operand")
(mult:SI (match_operand:SI 1 "register_operand") (match_operand:SI 2 "d_operand")))
(match_operand:SI 2 "register_operand"))) (set (match_operand:SI 3 "d_operand")
(clobber (match_operand:SI 3 "register_operand"))]) (match_dup 0))]
(set (match_operand:SI 4 "register_operand")
(unspec:SI [(match_dup 0) (match_dup 3)] UNSPEC_MFHILO))]
"ISA_HAS_MACC && !ISA_HAS_MUL3" "ISA_HAS_MACC && !ISA_HAS_MUL3"
[(set (match_dup 0) [(set (match_dup 0)
(const_int 0)) (const_int 0))
...@@ -1261,11 +1247,10 @@ ...@@ -1261,11 +1247,10 @@
(plus:SI (mult:SI (match_dup 1) (plus:SI (mult:SI (match_dup 1)
(match_dup 2)) (match_dup 2))
(match_dup 0))) (match_dup 0)))
(set (match_dup 4) (set (match_dup 3)
(plus:SI (mult:SI (match_dup 1) (plus:SI (mult:SI (match_dup 1)
(match_dup 2)) (match_dup 2))
(match_dup 0))) (match_dup 0)))])])
(clobber (match_dup 3))])])
;; Multiply-accumulate patterns ;; Multiply-accumulate patterns
...@@ -1284,9 +1269,8 @@ ...@@ -1284,9 +1269,8 @@
(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d") (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d")
(match_operand:SI 2 "register_operand" "d,d,d")) (match_operand:SI 2 "register_operand" "d,d,d"))
(match_operand:SI 3 "register_operand" "0,l,*d"))) (match_operand:SI 3 "register_operand" "0,l,*d")))
(clobber (match_scratch:SI 4 "=h,h,h")) (clobber (match_scratch:SI 4 "=X,3,l"))
(clobber (match_scratch:SI 5 "=X,3,l")) (clobber (match_scratch:SI 5 "=X,X,&d"))]
(clobber (match_scratch:SI 6 "=X,X,&d"))]
"(TARGET_MIPS3900 "(TARGET_MIPS3900
|| GENERATE_MADD_MSUB) || GENERATE_MADD_MSUB)
&& !TARGET_MIPS16" && !TARGET_MIPS16"
...@@ -1302,53 +1286,45 @@ ...@@ -1302,53 +1286,45 @@
(set_attr "mode" "SI") (set_attr "mode" "SI")
(set_attr "length" "4,4,8")]) (set_attr "length" "4,4,8")])
;; Split the above insn if we failed to get LO allocated. ;; Split *mul_acc_si if both the source and destination accumulator
;; values are GPRs.
(define_split (define_split
[(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "d_operand")
(plus:SI (mult:SI (match_operand:SI 1 "register_operand") (plus:SI (mult:SI (match_operand:SI 1 "d_operand")
(match_operand:SI 2 "register_operand")) (match_operand:SI 2 "d_operand"))
(match_operand:SI 3 "register_operand"))) (match_operand:SI 3 "d_operand")))
(clobber (match_scratch:SI 4)) (clobber (match_operand:SI 4 "lo_operand"))
(clobber (match_scratch:SI 5)) (clobber (match_operand:SI 5 "d_operand"))]
(clobber (match_scratch:SI 6))] "reload_completed && !TARGET_DEBUG_D_MODE"
"reload_completed && !TARGET_DEBUG_D_MODE [(parallel [(set (match_dup 5)
&& GP_REG_P (true_regnum (operands[0]))
&& GP_REG_P (true_regnum (operands[3]))"
[(parallel [(set (match_dup 6)
(mult:SI (match_dup 1) (match_dup 2))) (mult:SI (match_dup 1) (match_dup 2)))
(clobber (match_dup 4)) (clobber (match_dup 4))])
(clobber (match_dup 5))]) (set (match_dup 0) (plus:SI (match_dup 5) (match_dup 3)))]
(set (match_dup 0) (plus:SI (match_dup 6) (match_dup 3)))]
"") "")
;; Splitter to copy result of MADD to a general register ;; Split *mul_acc_si if the destination accumulator value is in a GPR
;; and the source accumulator value is in LO.
(define_split (define_split
[(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "d_operand")
(plus:SI (mult:SI (match_operand:SI 1 "register_operand") (plus:SI (mult:SI (match_operand:SI 1 "d_operand")
(match_operand:SI 2 "register_operand")) (match_operand:SI 2 "d_operand"))
(match_operand:SI 3 "register_operand"))) (match_operand:SI 3 "lo_operand")))
(clobber (match_scratch:SI 4)) (clobber (match_dup 3))
(clobber (match_scratch:SI 5)) (clobber (scratch:SI))]
(clobber (match_scratch:SI 6))] "reload_completed && !TARGET_DEBUG_D_MODE"
"reload_completed && !TARGET_DEBUG_D_MODE
&& GP_REG_P (true_regnum (operands[0]))
&& true_regnum (operands[3]) == LO_REGNUM"
[(parallel [(set (match_dup 3) [(parallel [(set (match_dup 3)
(plus:SI (mult:SI (match_dup 1) (match_dup 2)) (plus:SI (mult:SI (match_dup 1) (match_dup 2))
(match_dup 3))) (match_dup 3)))
(clobber (match_dup 4)) (clobber (scratch:SI))
(clobber (match_dup 5)) (clobber (scratch:SI))])
(clobber (match_dup 6))]) (set (match_dup 0) (match_dup 3))])
(set (match_dup 0) (unspec:SI [(match_dup 5) (match_dup 4)] UNSPEC_MFHILO))]
"")
(define_insn "*macc" (define_insn "*macc"
[(set (match_operand:SI 0 "register_operand" "=l,d") [(set (match_operand:SI 0 "register_operand" "=l,d")
(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d") (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
(match_operand:SI 2 "register_operand" "d,d")) (match_operand:SI 2 "register_operand" "d,d"))
(match_operand:SI 3 "register_operand" "0,l"))) (match_operand:SI 3 "register_operand" "0,l")))
(clobber (match_scratch:SI 4 "=h,h")) (clobber (match_scratch:SI 4 "=X,3"))]
(clobber (match_scratch:SI 5 "=X,3"))]
"ISA_HAS_MACC" "ISA_HAS_MACC"
{ {
if (which_alternative == 1) if (which_alternative == 1)
...@@ -1369,8 +1345,7 @@ ...@@ -1369,8 +1345,7 @@
(minus:SI (match_operand:SI 1 "register_operand" "0,l") (minus:SI (match_operand:SI 1 "register_operand" "0,l")
(mult:SI (match_operand:SI 2 "register_operand" "d,d") (mult:SI (match_operand:SI 2 "register_operand" "d,d")
(match_operand:SI 3 "register_operand" "d,d")))) (match_operand:SI 3 "register_operand" "d,d"))))
(clobber (match_scratch:SI 4 "=h,h")) (clobber (match_scratch:SI 4 "=X,1"))]
(clobber (match_scratch:SI 5 "=X,1"))]
"ISA_HAS_MSAC" "ISA_HAS_MSAC"
{ {
if (which_alternative == 1) if (which_alternative == 1)
...@@ -1389,21 +1364,19 @@ ...@@ -1389,21 +1364,19 @@
(minus:SI (match_operand:SI 1 "register_operand" "0,l") (minus:SI (match_operand:SI 1 "register_operand" "0,l")
(mult:SI (match_operand:SI 2 "register_operand" "d,d") (mult:SI (match_operand:SI 2 "register_operand" "d,d")
(match_operand:SI 3 "register_operand" "d,d")))) (match_operand:SI 3 "register_operand" "d,d"))))
(clobber (match_scratch:SI 4 "=h,h")) (clobber (match_scratch:SI 4 "=X,1"))
(clobber (match_scratch:SI 5 "=X,1")) (clobber (match_scratch:SI 5 "=d,d"))]
(clobber (match_scratch:SI 6 "=d,d"))]
"ISA_HAS_MACC && !ISA_HAS_MSAC" "ISA_HAS_MACC && !ISA_HAS_MSAC"
"#" "#"
"&& reload_completed" "&& reload_completed"
[(set (match_dup 6) [(set (match_dup 5)
(neg:SI (match_dup 3))) (neg:SI (match_dup 3)))
(parallel (parallel
[(set (match_dup 0) [(set (match_dup 0)
(plus:SI (mult:SI (match_dup 2) (plus:SI (mult:SI (match_dup 2)
(match_dup 6)) (match_dup 5))
(match_dup 1))) (match_dup 1)))
(clobber (match_dup 4)) (clobber (match_dup 4))])]
(clobber (match_dup 5))])]
"" ""
[(set_attr "type" "imadd") [(set_attr "type" "imadd")
(set_attr "length" "8")]) (set_attr "length" "8")])
...@@ -1418,8 +1391,7 @@ ...@@ -1418,8 +1391,7 @@
(set (match_operand:SI 3 "register_operand" "=d") (set (match_operand:SI 3 "register_operand" "=d")
(plus:SI (mult:SI (match_dup 1) (plus:SI (mult:SI (match_dup 1)
(match_dup 2)) (match_dup 2))
(match_dup 0))) (match_dup 0)))]
(clobber (match_scratch:SI 4 "=h"))]
"ISA_HAS_MACC && reload_completed" "ISA_HAS_MACC && reload_completed"
"macc\t%3,%1,%2" "macc\t%3,%1,%2"
[(set_attr "type" "imadd") [(set_attr "type" "imadd")
...@@ -1433,8 +1405,7 @@ ...@@ -1433,8 +1405,7 @@
(set (match_operand:SI 3 "register_operand" "=d") (set (match_operand:SI 3 "register_operand" "=d")
(minus:SI (match_dup 0) (minus:SI (match_dup 0)
(mult:SI (match_dup 1) (mult:SI (match_dup 1)
(match_dup 2)))) (match_dup 2))))]
(clobber (match_scratch:SI 4 "=h"))]
"ISA_HAS_MSAC && reload_completed" "ISA_HAS_MSAC && reload_completed"
"msac\t%3,%1,%2" "msac\t%3,%1,%2"
[(set_attr "type" "imadd") [(set_attr "type" "imadd")
...@@ -1445,23 +1416,19 @@ ...@@ -1445,23 +1416,19 @@
;; ;;
;; Operand 0: LO ;; Operand 0: LO
;; Operand 1: macc/msac ;; Operand 1: macc/msac
;; Operand 2: HI ;; Operand 2: GPR (destination)
;; Operand 3: GPR (destination)
(define_peephole2 (define_peephole2
[(parallel [(parallel
[(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "lo_operand")
(match_operand:SI 1 "macc_msac_operand")) (match_operand:SI 1 "macc_msac_operand"))
(clobber (match_operand:SI 2 "register_operand"))
(clobber (scratch:SI))]) (clobber (scratch:SI))])
(set (match_operand:SI 3 "register_operand") (set (match_operand:SI 2 "d_operand")
(unspec:SI [(match_dup 0) (match_dup 2)] UNSPEC_MFHILO))] (match_dup 0))]
"" ""
[(parallel [(set (match_dup 0) [(parallel [(set (match_dup 0)
(match_dup 1)) (match_dup 1))
(set (match_dup 3) (set (match_dup 2)
(match_dup 1)) (match_dup 1))])])
(clobber (match_dup 2))])]
"")
;; When we have a three-address multiplication instruction, it should ;; When we have a three-address multiplication instruction, it should
;; be faster to do a separate multiply and add, rather than moving ;; be faster to do a separate multiply and add, rather than moving
...@@ -1475,32 +1442,26 @@ ...@@ -1475,32 +1442,26 @@
;; Operand 2: GPR (addend) ;; Operand 2: GPR (addend)
;; Operand 3: GPR (destination) ;; Operand 3: GPR (destination)
;; Operand 4: macc/msac ;; Operand 4: macc/msac
;; Operand 5: HI ;; Operand 5: new multiplication
;; Operand 6: new multiplication ;; Operand 6: new addition/subtraction
;; Operand 7: new addition/subtraction
(define_peephole2 (define_peephole2
[(match_scratch:SI 0 "d") [(match_scratch:SI 0 "d")
(set (match_operand:SI 1 "register_operand") (set (match_operand:SI 1 "lo_operand")
(match_operand:SI 2 "register_operand")) (match_operand:SI 2 "d_operand"))
(match_dup 0) (match_dup 0)
(parallel (parallel
[(set (match_operand:SI 3 "register_operand") [(set (match_operand:SI 3 "d_operand")
(match_operand:SI 4 "macc_msac_operand")) (match_operand:SI 4 "macc_msac_operand"))
(clobber (match_operand:SI 5 "register_operand"))
(clobber (match_dup 1))])] (clobber (match_dup 1))])]
"ISA_HAS_MUL3 "ISA_HAS_MUL3 && peep2_reg_dead_p (2, operands[1])"
&& true_regnum (operands[1]) == LO_REGNUM
&& peep2_reg_dead_p (2, operands[1])
&& GP_REG_P (true_regnum (operands[3]))"
[(parallel [(set (match_dup 0) [(parallel [(set (match_dup 0)
(match_dup 6)) (match_dup 5))
(clobber (match_dup 5))
(clobber (match_dup 1))]) (clobber (match_dup 1))])
(set (match_dup 3) (set (match_dup 3)
(match_dup 7))] (match_dup 6))]
{ {
operands[6] = XEXP (operands[4], GET_CODE (operands[4]) == PLUS ? 0 : 1); operands[5] = XEXP (operands[4], GET_CODE (operands[4]) == PLUS ? 0 : 1);
operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode, operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode,
operands[2], operands[0]); operands[2], operands[0]);
}) })
...@@ -1510,33 +1471,30 @@ ...@@ -1510,33 +1471,30 @@
;; Operand 1: LO ;; Operand 1: LO
;; Operand 2: GPR (addend) ;; Operand 2: GPR (addend)
;; Operand 3: macc/msac ;; Operand 3: macc/msac
;; Operand 4: HI ;; Operand 4: GPR (destination)
;; Operand 5: GPR (destination) ;; Operand 5: new multiplication
;; Operand 6: new multiplication ;; Operand 6: new addition/subtraction
;; Operand 7: new addition/subtraction
(define_peephole2 (define_peephole2
[(match_scratch:SI 0 "d") [(match_scratch:SI 0 "d")
(set (match_operand:SI 1 "register_operand") (set (match_operand:SI 1 "lo_operand")
(match_operand:SI 2 "register_operand")) (match_operand:SI 2 "d_operand"))
(match_dup 0) (match_dup 0)
(parallel (parallel
[(set (match_dup 1) [(set (match_dup 1)
(match_operand:SI 3 "macc_msac_operand")) (match_operand:SI 3 "macc_msac_operand"))
(clobber (match_operand:SI 4 "register_operand"))
(clobber (scratch:SI))]) (clobber (scratch:SI))])
(match_dup 0) (match_dup 0)
(set (match_operand:SI 5 "register_operand") (set (match_operand:SI 4 "d_operand")
(unspec:SI [(match_dup 1) (match_dup 4)] UNSPEC_MFHILO))] (match_dup 1))]
"ISA_HAS_MUL3 && peep2_reg_dead_p (3, operands[1])" "ISA_HAS_MUL3 && peep2_reg_dead_p (3, operands[1])"
[(parallel [(set (match_dup 0) [(parallel [(set (match_dup 0)
(match_dup 6)) (match_dup 5))
(clobber (match_dup 4))
(clobber (match_dup 1))]) (clobber (match_dup 1))])
(set (match_dup 5) (set (match_dup 4)
(match_dup 7))] (match_dup 6))]
{ {
operands[6] = XEXP (operands[4], GET_CODE (operands[4]) == PLUS ? 0 : 1); operands[5] = XEXP (operands[3], GET_CODE (operands[3]) == PLUS ? 0 : 1);
operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode, operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
operands[2], operands[0]); operands[2], operands[0]);
}) })
...@@ -1545,9 +1503,8 @@ ...@@ -1545,9 +1503,8 @@
(minus:SI (match_operand:SI 1 "register_operand" "0,l,*d") (minus:SI (match_operand:SI 1 "register_operand" "0,l,*d")
(mult:SI (match_operand:SI 2 "register_operand" "d,d,d") (mult:SI (match_operand:SI 2 "register_operand" "d,d,d")
(match_operand:SI 3 "register_operand" "d,d,d")))) (match_operand:SI 3 "register_operand" "d,d,d"))))
(clobber (match_scratch:SI 4 "=h,h,h")) (clobber (match_scratch:SI 4 "=X,1,l"))
(clobber (match_scratch:SI 5 "=X,1,l")) (clobber (match_scratch:SI 5 "=X,X,&d"))]
(clobber (match_scratch:SI 6 "=X,X,&d"))]
"GENERATE_MADD_MSUB" "GENERATE_MADD_MSUB"
"@ "@
msub\t%2,%3 msub\t%2,%3
...@@ -1557,52 +1514,45 @@ ...@@ -1557,52 +1514,45 @@
(set_attr "mode" "SI") (set_attr "mode" "SI")
(set_attr "length" "4,8,8")]) (set_attr "length" "4,8,8")])
;; Split the above insn if we failed to get LO allocated. ;; Split *mul_sub_si if both the source and destination accumulator
;; values are GPRs.
(define_split (define_split
[(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "d_operand")
(minus:SI (match_operand:SI 1 "register_operand") (minus:SI (match_operand:SI 1 "d_operand")
(mult:SI (match_operand:SI 2 "register_operand") (mult:SI (match_operand:SI 2 "d_operand")
(match_operand:SI 3 "register_operand")))) (match_operand:SI 3 "d_operand"))))
(clobber (match_scratch:SI 4)) (clobber (match_operand:SI 4 "lo_operand"))
(clobber (match_scratch:SI 5)) (clobber (match_operand:SI 5 "d_operand"))]
(clobber (match_scratch:SI 6))] "reload_completed && !TARGET_DEBUG_D_MODE"
"reload_completed && !TARGET_DEBUG_D_MODE [(parallel [(set (match_dup 5)
&& GP_REG_P (true_regnum (operands[0]))
&& GP_REG_P (true_regnum (operands[1]))"
[(parallel [(set (match_dup 6)
(mult:SI (match_dup 2) (match_dup 3))) (mult:SI (match_dup 2) (match_dup 3)))
(clobber (match_dup 4)) (clobber (match_dup 4))])
(clobber (match_dup 5))]) (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 5)))]
(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 6)))]
"") "")
;; Splitter to copy result of MSUB to a general register ;; Split *mul_acc_si if the destination accumulator value is in a GPR
;; and the source accumulator value is in LO.
(define_split (define_split
[(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "d_operand")
(minus:SI (match_operand:SI 1 "register_operand") (minus:SI (match_operand:SI 1 "lo_operand")
(mult:SI (match_operand:SI 2 "register_operand") (mult:SI (match_operand:SI 2 "d_operand")
(match_operand:SI 3 "register_operand")))) (match_operand:SI 3 "d_operand"))))
(clobber (match_scratch:SI 4)) (clobber (match_dup 1))
(clobber (match_scratch:SI 5)) (clobber (scratch:SI))]
(clobber (match_scratch:SI 6))] "reload_completed && !TARGET_DEBUG_D_MODE"
"reload_completed && !TARGET_DEBUG_D_MODE
&& GP_REG_P (true_regnum (operands[0]))
&& true_regnum (operands[1]) == LO_REGNUM"
[(parallel [(set (match_dup 1) [(parallel [(set (match_dup 1)
(minus:SI (match_dup 1) (minus:SI (match_dup 1)
(mult:SI (match_dup 2) (match_dup 3)))) (mult:SI (match_dup 2) (match_dup 3))))
(clobber (match_dup 4)) (clobber (scratch:SI))
(clobber (match_dup 5)) (clobber (scratch:SI))])
(clobber (match_dup 6))]) (set (match_dup 0) (match_dup 1))]
(set (match_dup 0) (unspec:SI [(match_dup 5) (match_dup 4)] UNSPEC_MFHILO))]
"") "")
(define_insn "*muls" (define_insn "*muls"
[(set (match_operand:SI 0 "register_operand" "=l,d") [(set (match_operand:SI 0 "register_operand" "=l,d")
(neg:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d") (neg:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
(match_operand:SI 2 "register_operand" "d,d")))) (match_operand:SI 2 "register_operand" "d,d"))))
(clobber (match_scratch:SI 3 "=h,h")) (clobber (match_scratch:SI 3 "=X,l"))]
(clobber (match_scratch:SI 4 "=X,l"))]
"ISA_HAS_MULS" "ISA_HAS_MULS"
"@ "@
muls\t$0,%1,%2 muls\t$0,%1,%2
...@@ -1610,31 +1560,23 @@ ...@@ -1610,31 +1560,23 @@
[(set_attr "type" "imul,imul3") [(set_attr "type" "imul,imul3")
(set_attr "mode" "SI")]) (set_attr "mode" "SI")])
;; ??? We could define a mulditi3 pattern when TARGET_64BIT.
(define_expand "<u>mulsidi3" (define_expand "<u>mulsidi3"
[(parallel
[(set (match_operand:DI 0 "register_operand") [(set (match_operand:DI 0 "register_operand")
(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand")) (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
(any_extend:DI (match_operand:SI 2 "register_operand")))) (any_extend:DI (match_operand:SI 2 "register_operand"))))]
(clobber (scratch:DI))
(clobber (scratch:DI))
(clobber (scratch:DI))])]
"!TARGET_64BIT || !TARGET_FIX_R4000" "!TARGET_64BIT || !TARGET_FIX_R4000"
{ {
if (!TARGET_64BIT) if (TARGET_64BIT)
{ emit_insn (gen_<u>mulsidi3_64bit (operands[0], operands[1], operands[2]));
if (!TARGET_FIX_R4000) else if (TARGET_FIX_R4000)
emit_insn (gen_<u>mulsidi3_32bit_internal (operands[0], operands[1],
operands[2]));
else
emit_insn (gen_<u>mulsidi3_32bit_r4000 (operands[0], operands[1], emit_insn (gen_<u>mulsidi3_32bit_r4000 (operands[0], operands[1],
operands[2])); operands[2]));
else
emit_insn (gen_<u>mulsidi3_32bit (operands[0], operands[1], operands[2]));
DONE; DONE;
}
}) })
(define_insn "<u>mulsidi3_32bit_internal" (define_insn "<u>mulsidi3_32bit"
[(set (match_operand:DI 0 "register_operand" "=x") [(set (match_operand:DI 0 "register_operand" "=x")
(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
(any_extend:DI (match_operand:SI 2 "register_operand" "d"))))] (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
...@@ -1649,42 +1591,35 @@ ...@@ -1649,42 +1591,35 @@
(any_extend:DI (match_operand:SI 2 "register_operand" "d")))) (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))
(clobber (match_scratch:DI 3 "=x"))] (clobber (match_scratch:DI 3 "=x"))]
"!TARGET_64BIT && TARGET_FIX_R4000" "!TARGET_64BIT && TARGET_FIX_R4000"
"mult<u>\t%1,%2\;mflo\t%L0;mfhi\t%M0" "mult<u>\t%1,%2\;mflo\t%L0\;mfhi\t%M0"
[(set_attr "type" "imul") [(set_attr "type" "imul")
(set_attr "mode" "SI") (set_attr "mode" "SI")
(set_attr "length" "12")]) (set_attr "length" "12")])
(define_insn_and_split "*<u>mulsidi3_64bit" (define_insn_and_split "<u>mulsidi3_64bit"
[(set (match_operand:DI 0 "register_operand" "=d") [(set (match_operand:DI 0 "register_operand" "=d")
(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
(any_extend:DI (match_operand:SI 2 "register_operand" "d")))) (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))
(clobber (match_scratch:DI 3 "=l")) (clobber (match_scratch:TI 3 "=x"))
(clobber (match_scratch:DI 4 "=h")) (clobber (match_scratch:DI 4 "=d"))]
(clobber (match_scratch:DI 5 "=d"))]
"TARGET_64BIT && !TARGET_FIX_R4000" "TARGET_64BIT && !TARGET_FIX_R4000"
"#" "#"
"&& reload_completed" "&& reload_completed"
[(parallel
[(set (match_dup 3) [(set (match_dup 3)
(sign_extend:DI (unspec:TI [(mult:DI (any_extend:DI (match_dup 1))
(mult:SI (match_dup 1) (any_extend:DI (match_dup 2)))]
(match_dup 2)))) UNSPEC_SET_HILO))
;; OP4 <- LO, OP0 <- HI
(set (match_dup 4) (match_dup 5))
(set (match_dup 0) (unspec:DI [(match_dup 3)] UNSPEC_MFHI))
;; Zero-extend OP4.
(set (match_dup 4) (set (match_dup 4)
(ashiftrt:DI (ashift:DI (match_dup 4)
(mult:DI (any_extend:DI (match_dup 1))
(any_extend:DI (match_dup 2)))
(const_int 32)))])
;; OP5 <- LO, OP0 <- HI
(set (match_dup 5) (unspec:DI [(match_dup 3) (match_dup 4)] UNSPEC_MFHILO))
(set (match_dup 0) (unspec:DI [(match_dup 4) (match_dup 3)] UNSPEC_MFHILO))
;; Zero-extend OP5.
(set (match_dup 5)
(ashift:DI (match_dup 5)
(const_int 32))) (const_int 32)))
(set (match_dup 5) (set (match_dup 4)
(lshiftrt:DI (match_dup 5) (lshiftrt:DI (match_dup 4)
(const_int 32))) (const_int 32)))
;; Shift OP0 into place. ;; Shift OP0 into place.
...@@ -1695,24 +1630,21 @@ ...@@ -1695,24 +1630,21 @@
;; OR the two halves together ;; OR the two halves together
(set (match_dup 0) (set (match_dup 0)
(ior:DI (match_dup 0) (ior:DI (match_dup 0)
(match_dup 5)))] (match_dup 4)))]
"" { operands[5] = gen_rtx_REG (DImode, LO_REGNUM); }
[(set_attr "type" "imul") [(set_attr "type" "imul")
(set_attr "mode" "SI") (set_attr "mode" "SI")
(set_attr "length" "24")]) (set_attr "length" "24")])
(define_insn "*<u>mulsidi3_64bit_parts" (define_insn "<u>mulsidi3_64bit_hilo"
[(set (match_operand:DI 0 "register_operand" "=l") [(set (match_operand:TI 0 "register_operand" "=x")
(sign_extend:DI (unspec:TI
(mult:SI (match_operand:SI 2 "register_operand" "d") [(mult:DI
(match_operand:SI 3 "register_operand" "d")))) (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
(set (match_operand:DI 1 "register_operand" "=h") (any_extend:DI (match_operand:SI 2 "register_operand" "d")))]
(ashiftrt:DI UNSPEC_SET_HILO))]
(mult:DI (any_extend:DI (match_dup 2))
(any_extend:DI (match_dup 3)))
(const_int 32)))]
"TARGET_64BIT && !TARGET_FIX_R4000" "TARGET_64BIT && !TARGET_FIX_R4000"
"mult<u>\t%2,%3" "mult<u>\t%1,%2"
[(set_attr "type" "imul") [(set_attr "type" "imul")
(set_attr "mode" "SI")]) (set_attr "mode" "SI")])
...@@ -1756,7 +1688,7 @@ ...@@ -1756,7 +1688,7 @@
(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand")) (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
(any_extend:DI (match_operand:SI 2 "register_operand"))) (any_extend:DI (match_operand:SI 2 "register_operand")))
(const_int 32))))] (const_int 32))))]
"ISA_HAS_MULHI || !TARGET_FIX_R4000" ""
{ {
if (ISA_HAS_MULHI) if (ISA_HAS_MULHI)
emit_insn (gen_<su>mulsi3_highpart_mulhi_internal (operands[0], emit_insn (gen_<su>mulsi3_highpart_mulhi_internal (operands[0],
...@@ -1768,72 +1700,133 @@ ...@@ -1768,72 +1700,133 @@
DONE; DONE;
}) })
(define_insn "<su>mulsi3_highpart_internal" (define_insn_and_split "<su>mulsi3_highpart_internal"
[(set (match_operand:SI 0 "register_operand" "=h") [(set (match_operand:SI 0 "register_operand" "=d")
(truncate:SI (truncate:SI
(lshiftrt:DI (lshiftrt:DI
(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
(any_extend:DI (match_operand:SI 2 "register_operand" "d"))) (any_extend:DI (match_operand:SI 2 "register_operand" "d")))
(const_int 32)))) (const_int 32))))
(clobber (match_scratch:SI 3 "=l"))] (clobber (match_scratch:SI 3 "=l"))]
"!ISA_HAS_MULHI && !TARGET_FIX_R4000" "!ISA_HAS_MULHI"
"mult<u>\t%1,%2" { return TARGET_FIX_R4000 ? "mult<u>\t%1,%2\n\tmfhi\t%0" : "#"; }
"&& reload_completed && !TARGET_FIX_R4000"
[(const_int 0)]
{
rtx hilo;
if (TARGET_64BIT)
{
hilo = gen_rtx_REG (TImode, MD_REG_FIRST);
emit_insn (gen_<u>mulsidi3_64bit_hilo (hilo, operands[1], operands[2]));
emit_insn (gen_mfhisi_ti (operands[0], hilo));
}
else
{
hilo = gen_rtx_REG (DImode, MD_REG_FIRST);
emit_insn (gen_<u>mulsidi3_32bit (hilo, operands[1], operands[2]));
emit_insn (gen_mfhisi_di (operands[0], hilo));
}
DONE;
}
[(set_attr "type" "imul") [(set_attr "type" "imul")
(set_attr "mode" "SI")]) (set_attr "mode" "SI")
(set_attr "length" "8")])
(define_insn "<su>mulsi3_highpart_mulhi_internal" (define_insn "<su>mulsi3_highpart_mulhi_internal"
[(set (match_operand:SI 0 "register_operand" "=h,d") [(set (match_operand:SI 0 "register_operand" "=d")
(truncate:SI (truncate:SI
(lshiftrt:DI (lshiftrt:DI
(mult:DI (mult:DI
(any_extend:DI (match_operand:SI 1 "register_operand" "d,d")) (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
(any_extend:DI (match_operand:SI 2 "register_operand" "d,d"))) (any_extend:DI (match_operand:SI 2 "register_operand" "d")))
(const_int 32)))) (const_int 32))))
(clobber (match_scratch:SI 3 "=l,l")) (clobber (match_scratch:SI 3 "=l"))]
(clobber (match_scratch:SI 4 "=X,h"))]
"ISA_HAS_MULHI" "ISA_HAS_MULHI"
"@ "mulhi<u>\t%0,%1,%2"
mult<u>\t%1,%2 [(set_attr "type" "imul3")
mulhi<u>\t%0,%1,%2"
[(set_attr "type" "imul,imul3")
(set_attr "mode" "SI")]) (set_attr "mode" "SI")])
(define_insn "*<su>mulsi3_highpart_neg_mulhi_internal" (define_insn "*<su>mulsi3_highpart_neg_mulhi_internal"
[(set (match_operand:SI 0 "register_operand" "=h,d") [(set (match_operand:SI 0 "register_operand" "=d")
(truncate:SI (truncate:SI
(lshiftrt:DI (lshiftrt:DI
(neg:DI (neg:DI
(mult:DI (mult:DI
(any_extend:DI (match_operand:SI 1 "register_operand" "d,d")) (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
(any_extend:DI (match_operand:SI 2 "register_operand" "d,d")))) (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))
(const_int 32)))) (const_int 32))))
(clobber (match_scratch:SI 3 "=l,l")) (clobber (match_scratch:SI 3 "=l"))]
(clobber (match_scratch:SI 4 "=X,h"))]
"ISA_HAS_MULHI" "ISA_HAS_MULHI"
"@ "mulshi<u>\t%0,%1,%2"
mulshi<u>\t%.,%1,%2 [(set_attr "type" "imul3")
mulshi<u>\t%0,%1,%2"
[(set_attr "type" "imul,imul3")
(set_attr "mode" "SI")]) (set_attr "mode" "SI")])
;; Disable unsigned multiplication for -mfix-vr4120. This is for VR4120 ;; Disable unsigned multiplication for -mfix-vr4120. This is for VR4120
;; errata MD(0), which says that dmultu does not always produce the ;; errata MD(0), which says that dmultu does not always produce the
;; correct result. ;; correct result.
(define_insn "<su>muldi3_highpart" (define_insn_and_split "<su>muldi3_highpart"
[(set (match_operand:DI 0 "register_operand" "=h") [(set (match_operand:DI 0 "register_operand" "=d")
(truncate:DI (truncate:DI
(lshiftrt:TI (lshiftrt:TI
(mult:TI (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand" "d"))
(any_extend:TI (match_operand:DI 1 "register_operand" "d"))
(any_extend:TI (match_operand:DI 2 "register_operand" "d"))) (any_extend:TI (match_operand:DI 2 "register_operand" "d")))
(const_int 64)))) (const_int 64))))
(clobber (match_scratch:DI 3 "=l"))] (clobber (match_scratch:DI 3 "=l"))]
"TARGET_64BIT && !TARGET_FIX_R4000 "TARGET_64BIT && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
{ return TARGET_FIX_R4000 ? "dmult<u>\t%1,%2\n\tmfhi\t%0" : "#"; }
"&& reload_completed && !TARGET_FIX_R4000"
[(const_int 0)]
{
rtx hilo;
hilo = gen_rtx_REG (TImode, MD_REG_FIRST);
emit_insn (gen_<u>mulditi3_internal (hilo, operands[1], operands[2]));
emit_insn (gen_mfhidi_ti (operands[0], hilo));
DONE;
}
[(set_attr "type" "imul")
(set_attr "mode" "DI")
(set_attr "length" "8")])
(define_expand "<u>mulditi3"
[(set (match_operand:TI 0 "register_operand")
(mult:TI (any_extend:TI (match_operand:DI 1 "register_operand"))
(any_extend:TI (match_operand:DI 2 "register_operand"))))]
"TARGET_64BIT && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
{
if (TARGET_FIX_R4000)
emit_insn (gen_<u>mulditi3_r4000 (operands[0], operands[1], operands[2]));
else
emit_insn (gen_<u>mulditi3_internal (operands[0], operands[1],
operands[2]));
DONE;
})
(define_insn "<u>mulditi3_internal"
[(set (match_operand:TI 0 "register_operand" "=x")
(mult:TI (any_extend:TI (match_operand:DI 1 "register_operand" "d"))
(any_extend:TI (match_operand:DI 2 "register_operand" "d"))))]
"TARGET_64BIT
&& !TARGET_FIX_R4000
&& !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)" && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
"dmult<u>\t%1,%2" "dmult<u>\t%1,%2"
[(set_attr "type" "imul") [(set_attr "type" "imul")
(set_attr "mode" "DI")]) (set_attr "mode" "DI")])
(define_insn "<u>mulditi3_r4000"
[(set (match_operand:TI 0 "register_operand" "=d")
(mult:TI (any_extend:TI (match_operand:DI 1 "register_operand" "d"))
(any_extend:TI (match_operand:DI 2 "register_operand" "d"))))
(clobber (match_scratch:TI 3 "=x"))]
"TARGET_64BIT
&& TARGET_FIX_R4000
&& !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
"dmult<u>\t%1,%2\;mflo\t%L0\;mfhi\t%M0"
[(set_attr "type" "imul")
(set_attr "mode" "DI")
(set_attr "length" "12")])
;; The R4650 supports a 32-bit multiply/ 64-bit accumulate ;; The R4650 supports a 32-bit multiply/ 64-bit accumulate
;; instruction. The HI/LO registers are used as a 64-bit accumulator. ;; instruction. The HI/LO registers are used as a 64-bit accumulator.
...@@ -1841,8 +1834,7 @@ ...@@ -1841,8 +1834,7 @@
[(set (match_operand:SI 0 "register_operand" "+l") [(set (match_operand:SI 0 "register_operand" "+l")
(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d") (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "register_operand" "d")) (match_operand:SI 2 "register_operand" "d"))
(match_dup 0))) (match_dup 0)))]
(clobber (match_scratch:SI 3 "=h"))]
"TARGET_MAD" "TARGET_MAD"
"mad\t%1,%2" "mad\t%1,%2"
[(set_attr "type" "imadd") [(set_attr "type" "imadd")
...@@ -2017,29 +2009,80 @@ ...@@ -2017,29 +2009,80 @@
;; VR4120 errata MD(A1): signed division instructions do not work correctly ;; VR4120 errata MD(A1): signed division instructions do not work correctly
;; with negative operands. We use special libgcc functions instead. ;; with negative operands. We use special libgcc functions instead.
(define_insn "divmod<mode>4" (define_insn_and_split "divmod<mode>4"
[(set (match_operand:GPR 0 "register_operand" "=l") [(set (match_operand:GPR 0 "register_operand" "=l")
(div:GPR (match_operand:GPR 1 "register_operand" "d") (div:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand:GPR 2 "register_operand" "d"))) (match_operand:GPR 2 "register_operand" "d")))
(set (match_operand:GPR 3 "register_operand" "=h") (set (match_operand:GPR 3 "register_operand" "=d")
(mod:GPR (match_dup 1) (mod:GPR (match_dup 1)
(match_dup 2)))] (match_dup 2)))]
"!TARGET_FIX_VR4120" "!TARGET_FIX_VR4120"
{ return mips_output_division ("<d>div\t$0,%1,%2", operands); } "#"
"&& reload_completed"
[(const_int 0)]
{
rtx hilo;
if (TARGET_64BIT)
{
hilo = gen_rtx_REG (TImode, MD_REG_FIRST);
emit_insn (gen_divmod<mode>4_hilo_ti (hilo, operands[1], operands[2]));
emit_insn (gen_mfhi<mode>_ti (operands[3], hilo));
}
else
{
hilo = gen_rtx_REG (DImode, MD_REG_FIRST);
emit_insn (gen_divmod<mode>4_hilo_di (hilo, operands[1], operands[2]));
emit_insn (gen_mfhi<mode>_di (operands[3], hilo));
}
DONE;
}
[(set_attr "type" "idiv") [(set_attr "type" "idiv")
(set_attr "mode" "<MODE>")]) (set_attr "mode" "<MODE>")
(set_attr "length" "8")])
(define_insn "udivmod<mode>4" (define_insn_and_split "udivmod<mode>4"
[(set (match_operand:GPR 0 "register_operand" "=l") [(set (match_operand:GPR 0 "register_operand" "=l")
(udiv:GPR (match_operand:GPR 1 "register_operand" "d") (udiv:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand:GPR 2 "register_operand" "d"))) (match_operand:GPR 2 "register_operand" "d")))
(set (match_operand:GPR 3 "register_operand" "=h") (set (match_operand:GPR 3 "register_operand" "=d")
(umod:GPR (match_dup 1) (umod:GPR (match_dup 1)
(match_dup 2)))] (match_dup 2)))]
"" ""
{ return mips_output_division ("<d>divu\t$0,%1,%2", operands); } "#"
"reload_completed"
[(const_int 0)]
{
rtx hilo;
if (TARGET_64BIT)
{
hilo = gen_rtx_REG (TImode, MD_REG_FIRST);
emit_insn (gen_udivmod<mode>4_hilo_ti (hilo, operands[1], operands[2]));
emit_insn (gen_mfhi<mode>_ti (operands[3], hilo));
}
else
{
hilo = gen_rtx_REG (DImode, MD_REG_FIRST);
emit_insn (gen_udivmod<mode>4_hilo_di (hilo, operands[1], operands[2]));
emit_insn (gen_mfhi<mode>_di (operands[3], hilo));
}
DONE;
}
[(set_attr "type" "idiv") [(set_attr "type" "idiv")
(set_attr "mode" "<MODE>")]) (set_attr "mode" "<MODE>")
(set_attr "length" "8")])
(define_insn "<u>divmod<GPR:mode>4_hilo_<HILO:mode>"
[(set (match_operand:HILO 0 "register_operand" "=x")
(unspec:HILO
[(any_div:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand:GPR 2 "register_operand" "d"))]
UNSPEC_SET_HILO))]
""
{ return mips_output_division ("<GPR:d>div<u>\t%.,%1,%2", operands); }
[(set_attr "type" "idiv")
(set_attr "mode" "<GPR:MODE>")])
;; ;;
;; .................... ;; ....................
...@@ -3241,7 +3284,7 @@ ...@@ -3241,7 +3284,7 @@
;; dsll32 op1,op1,0 ;; dsll32 op1,op1,0
;; daddu op1,op1,op0 ;; daddu op1,op1,op0
(define_peephole2 (define_peephole2
[(set (match_operand:DI 1 "register_operand") [(set (match_operand:DI 1 "d_operand")
(high:DI (match_operand:DI 2 "absolute_symbolic_operand"))) (high:DI (match_operand:DI 2 "absolute_symbolic_operand")))
(match_scratch:DI 0 "d")] (match_scratch:DI 0 "d")]
"TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS" "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS"
...@@ -3294,8 +3337,8 @@ ...@@ -3294,8 +3337,8 @@
;; ;;
;; on MIPS16 targets. ;; on MIPS16 targets.
(define_split (define_split
[(set (match_operand:SI 0 "register_operand" "=d") [(set (match_operand:SI 0 "d_operand")
(high:SI (match_operand:SI 1 "absolute_symbolic_operand" "")))] (high:SI (match_operand:SI 1 "absolute_symbolic_operand")))]
"TARGET_MIPS16 && reload_completed" "TARGET_MIPS16 && reload_completed"
[(set (match_dup 0) (match_dup 2)) [(set (match_dup 0) (match_dup 2))
(set (match_dup 0) (ashift:SI (match_dup 0) (const_int 16)))] (set (match_dup 0) (ashift:SI (match_dup 0) (const_int 16)))]
...@@ -3464,7 +3507,7 @@ ...@@ -3464,7 +3507,7 @@
&& (register_operand (operands[0], DImode) && (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))" || reg_or_0_operand (operands[1], DImode))"
{ return mips_output_move (operands[0], operands[1]); } { return mips_output_move (operands[0], operands[1]); }
[(set_attr "type" "multi,multi,load,store,mthilo,mfhilo,mtc,load,mfc,store") [(set_attr "type" "multi,multi,load,store,multi,multi,mtc,load,mfc,store")
(set_attr "mode" "DI") (set_attr "mode" "DI")
(set_attr "length" "8,16,*,*,8,8,8,*,8,*")]) (set_attr "length" "8,16,*,*,8,8,8,*,8,*")])
...@@ -3475,7 +3518,7 @@ ...@@ -3475,7 +3518,7 @@
&& (register_operand (operands[0], DImode) && (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))" || reg_or_0_operand (operands[1], DImode))"
{ return mips_output_move (operands[0], operands[1]); } { return mips_output_move (operands[0], operands[1]); }
[(set_attr "type" "multi,multi,load,store,mthilo,mfhilo,mtc,fpload,mfc,fpstore") [(set_attr "type" "multi,multi,load,store,multi,multi,mtc,fpload,mfc,fpstore")
(set_attr "mode" "DI") (set_attr "mode" "DI")
(set_attr "length" "8,16,*,*,8,8,8,*,8,*")]) (set_attr "length" "8,16,*,*,8,8,8,*,8,*")])
...@@ -3486,29 +3529,29 @@ ...@@ -3486,29 +3529,29 @@
&& (register_operand (operands[0], DImode) && (register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode))" || register_operand (operands[1], DImode))"
{ return mips_output_move (operands[0], operands[1]); } { return mips_output_move (operands[0], operands[1]); }
[(set_attr "type" "multi,multi,multi,multi,multi,load,store,mfhilo") [(set_attr "type" "multi,multi,multi,multi,multi,load,store,multi")
(set_attr "mode" "DI") (set_attr "mode" "DI")
(set_attr "length" "8,8,8,8,12,*,*,8")]) (set_attr "length" "8,8,8,8,12,*,*,8")])
(define_insn "*movdi_64bit" (define_insn "*movdi_64bit"
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*d,*m,*x,*B*C*D,*B*C*D,*d,*m") [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*d,*m,*a,*d,*B*C*D,*B*C*D,*d,*m")
(match_operand:DI 1 "move_operand" "d,U,T,m,dJ,*d*J,*m,*f,*f,*J*d,*d,*m,*B*C*D,*B*C*D"))] (match_operand:DI 1 "move_operand" "d,U,T,m,dJ,*d*J,*m,*f,*f,*J*d,*a,*d,*m,*B*C*D,*B*C*D"))]
"TARGET_64BIT && !TARGET_MIPS16 "TARGET_64BIT && !TARGET_MIPS16
&& (register_operand (operands[0], DImode) && (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))" || reg_or_0_operand (operands[1], DImode))"
{ return mips_output_move (operands[0], operands[1]); } { return mips_output_move (operands[0], operands[1]); }
[(set_attr "type" "move,const,const,load,store,mtc,fpload,mfc,fpstore,mthilo,mtc,load,mfc,store") [(set_attr "type" "move,const,const,load,store,mtc,fpload,mfc,fpstore,mthilo,mfhilo,mtc,load,mfc,store")
(set_attr "mode" "DI") (set_attr "mode" "DI")
(set_attr "length" "4,*,*,*,*,4,*,4,*,4,8,*,8,*")]) (set_attr "length" "4,*,*,*,*,4,*,4,*,4,4,8,*,8,*")])
(define_insn "*movdi_64bit_mips16" (define_insn "*movdi_64bit_mips16"
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,d,m") [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,d,m,*d")
(match_operand:DI 1 "move_operand" "d,d,y,K,N,kf,U,m,d"))] (match_operand:DI 1 "move_operand" "d,d,y,K,N,kf,U,m,d,*a"))]
"TARGET_64BIT && TARGET_MIPS16 "TARGET_64BIT && TARGET_MIPS16
&& (register_operand (operands[0], DImode) && (register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode))" || register_operand (operands[1], DImode))"
{ return mips_output_move (operands[0], operands[1]); } { return mips_output_move (operands[0], operands[1]); }
[(set_attr "type" "move,move,move,arith,arith,load,const,load,store") [(set_attr "type" "move,move,move,arith,arith,load,const,load,store,mfhilo")
(set_attr "mode" "DI") (set_attr "mode" "DI")
(set_attr_alternative "length" (set_attr_alternative "length"
[(const_int 4) [(const_int 4)
...@@ -3523,7 +3566,8 @@ ...@@ -3523,7 +3566,8 @@
(const_int 8) (const_int 8)
(const_string "*") (const_string "*")
(const_string "*") (const_string "*")
(const_string "*")])]) (const_string "*")
(const_int 4)])])
;; On the mips16, we can split ld $r,N($r) into an add and a load, ;; On the mips16, we can split ld $r,N($r) into an add and a load,
...@@ -3531,14 +3575,11 @@ ...@@ -3531,14 +3575,11 @@
;; load are 2 2 byte instructions. ;; load are 2 2 byte instructions.
(define_split (define_split
[(set (match_operand:DI 0 "register_operand") [(set (match_operand:DI 0 "d_operand")
(mem:DI (plus:DI (match_dup 0) (mem:DI (plus:DI (match_dup 0)
(match_operand:DI 1 "const_int_operand"))))] (match_operand:DI 1 "const_int_operand"))))]
"TARGET_64BIT && TARGET_MIPS16 && reload_completed "TARGET_64BIT && TARGET_MIPS16 && reload_completed
&& !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_D_MODE
&& REG_P (operands[0])
&& M16_REG_P (REGNO (operands[0]))
&& GET_CODE (operands[1]) == CONST_INT
&& ((INTVAL (operands[1]) < 0 && ((INTVAL (operands[1]) < 0
&& INTVAL (operands[1]) >= -0x10) && INTVAL (operands[1]) >= -0x10)
|| (INTVAL (operands[1]) >= 32 * 8 || (INTVAL (operands[1]) >= 32 * 8
...@@ -3589,7 +3630,7 @@ ...@@ -3589,7 +3630,7 @@
(define_insn "*movsi_internal" (define_insn "*movsi_internal"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*d,*m,*d,*z,*a,*d,*B*C*D,*B*C*D,*d,*m") [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*d,*m,*d,*z,*a,*d,*B*C*D,*B*C*D,*d,*m")
(match_operand:SI 1 "move_operand" "d,U,T,m,dJ,*d*J,*m,*f,*f,*z,*d,*J*d,*A,*d,*m,*B*C*D,*B*C*D"))] (match_operand:SI 1 "move_operand" "d,U,T,m,dJ,*d*J,*m,*f,*f,*z,*d,*J*d,*a,*d,*m,*B*C*D,*B*C*D"))]
"!TARGET_MIPS16 "!TARGET_MIPS16
&& (register_operand (operands[0], SImode) && (register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))" || reg_or_0_operand (operands[1], SImode))"
...@@ -3599,13 +3640,13 @@ ...@@ -3599,13 +3640,13 @@
(set_attr "length" "4,*,*,*,*,4,*,4,*,4,4,4,4,4,*,4,*")]) (set_attr "length" "4,*,*,*,*,4,*,4,*,4,4,4,4,4,*,4,*")])
(define_insn "*movsi_mips16" (define_insn "*movsi_mips16"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,d,m") [(set (match_operand:SI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,d,m,*d")
(match_operand:SI 1 "move_operand" "d,d,y,K,N,kf,U,m,d"))] (match_operand:SI 1 "move_operand" "d,d,y,K,N,kf,U,m,d,*a"))]
"TARGET_MIPS16 "TARGET_MIPS16
&& (register_operand (operands[0], SImode) && (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))" || register_operand (operands[1], SImode))"
{ return mips_output_move (operands[0], operands[1]); } { return mips_output_move (operands[0], operands[1]); }
[(set_attr "type" "move,move,move,arith,arith,load,const,load,store") [(set_attr "type" "move,move,move,arith,arith,load,const,load,store,mfhilo")
(set_attr "mode" "SI") (set_attr "mode" "SI")
(set_attr_alternative "length" (set_attr_alternative "length"
[(const_int 4) [(const_int 4)
...@@ -3620,20 +3661,18 @@ ...@@ -3620,20 +3661,18 @@
(const_int 8) (const_int 8)
(const_string "*") (const_string "*")
(const_string "*") (const_string "*")
(const_string "*")])]) (const_string "*")
(const_int 4)])])
;; On the mips16, we can split lw $r,N($r) into an add and a load, ;; On the mips16, we can split lw $r,N($r) into an add and a load,
;; when the original load is a 4 byte instruction but the add and the ;; when the original load is a 4 byte instruction but the add and the
;; load are 2 2 byte instructions. ;; load are 2 2 byte instructions.
(define_split (define_split
[(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "d_operand")
(mem:SI (plus:SI (match_dup 0) (mem:SI (plus:SI (match_dup 0)
(match_operand:SI 1 "const_int_operand"))))] (match_operand:SI 1 "const_int_operand"))))]
"TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
&& REG_P (operands[0])
&& M16_REG_P (REGNO (operands[0]))
&& GET_CODE (operands[1]) == CONST_INT
&& ((INTVAL (operands[1]) < 0 && ((INTVAL (operands[1]) < 0
&& INTVAL (operands[1]) >= -0x80) && INTVAL (operands[1]) >= -0x80)
|| (INTVAL (operands[1]) >= 32 * 4 || (INTVAL (operands[1]) >= 32 * 4
...@@ -3669,12 +3708,9 @@ ...@@ -3669,12 +3708,9 @@
;; instructions. ;; instructions.
(define_split (define_split
[(set (match_operand:SI 0 "register_operand") [(set (match_operand:SI 0 "d_operand")
(match_operand:SI 1 "const_int_operand"))] (match_operand:SI 1 "const_int_operand"))]
"TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
&& REG_P (operands[0])
&& M16_REG_P (REGNO (operands[0]))
&& GET_CODE (operands[1]) == CONST_INT
&& INTVAL (operands[1]) >= 0x100 && INTVAL (operands[1]) >= 0x100
&& INTVAL (operands[1]) <= 0xff + 0x7f" && INTVAL (operands[1]) <= 0xff + 0x7f"
[(set (match_dup 0) (match_dup 1)) [(set (match_dup 0) (match_dup 1))
...@@ -3797,36 +3833,24 @@ ...@@ -3797,36 +3833,24 @@
}) })
(define_insn "*movhi_internal" (define_insn "*movhi_internal"
[(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,*x") [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d")
(match_operand:HI 1 "move_operand" "d,I,m,dJ,*d"))] (match_operand:HI 1 "move_operand" "d,I,m,dJ,*d*J,*a"))]
"!TARGET_MIPS16 "!TARGET_MIPS16
&& (register_operand (operands[0], HImode) && (register_operand (operands[0], HImode)
|| reg_or_0_operand (operands[1], HImode))" || reg_or_0_operand (operands[1], HImode))"
"@ { return mips_output_move (operands[0], operands[1]); }
move\t%0,%1 [(set_attr "type" "move,arith,load,store,mthilo,mfhilo")
li\t%0,%1
lhu\t%0,%1
sh\t%z1,%0
mt%0\t%1"
[(set_attr "type" "move,arith,load,store,mthilo")
(set_attr "mode" "HI") (set_attr "mode" "HI")
(set_attr "length" "4,4,*,*,4")]) (set_attr "length" "4,4,*,*,4,4")])
(define_insn "*movhi_mips16" (define_insn "*movhi_mips16"
[(set (match_operand:HI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m") [(set (match_operand:HI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d")
(match_operand:HI 1 "move_operand" "d,d,y,K,N,m,d"))] (match_operand:HI 1 "move_operand" "d,d,y,K,N,m,d,*a"))]
"TARGET_MIPS16 "TARGET_MIPS16
&& (register_operand (operands[0], HImode) && (register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode))" || register_operand (operands[1], HImode))"
"@ { return mips_output_move (operands[0], operands[1]); }
move\t%0,%1 [(set_attr "type" "move,move,move,arith,arith,load,store,mfhilo")
move\t%0,%1
move\t%0,%1
li\t%0,%1
#
lhu\t%0,%1
sh\t%1,%0"
[(set_attr "type" "move,move,move,arith,arith,load,store")
(set_attr "mode" "HI") (set_attr "mode" "HI")
(set_attr_alternative "length" (set_attr_alternative "length"
[(const_int 4) [(const_int 4)
...@@ -3839,6 +3863,7 @@ ...@@ -3839,6 +3863,7 @@
(const_int 8) (const_int 8)
(const_int 12)) (const_int 12))
(const_string "*") (const_string "*")
(const_string "*")
(const_string "*")])]) (const_string "*")])])
...@@ -3847,13 +3872,10 @@ ...@@ -3847,13 +3872,10 @@
;; load are 2 2 byte instructions. ;; load are 2 2 byte instructions.
(define_split (define_split
[(set (match_operand:HI 0 "register_operand") [(set (match_operand:HI 0 "d_operand")
(mem:HI (plus:SI (match_dup 0) (mem:HI (plus:SI (match_dup 0)
(match_operand:SI 1 "const_int_operand"))))] (match_operand:SI 1 "const_int_operand"))))]
"TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
&& REG_P (operands[0])
&& M16_REG_P (REGNO (operands[0]))
&& GET_CODE (operands[1]) == CONST_INT
&& ((INTVAL (operands[1]) < 0 && ((INTVAL (operands[1]) < 0
&& INTVAL (operands[1]) >= -0x80) && INTVAL (operands[1]) >= -0x80)
|| (INTVAL (operands[1]) >= 32 * 2 || (INTVAL (operands[1]) >= 32 * 2
...@@ -3901,51 +3923,36 @@ ...@@ -3901,51 +3923,36 @@
}) })
(define_insn "*movqi_internal" (define_insn "*movqi_internal"
[(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,*x") [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d")
(match_operand:QI 1 "move_operand" "d,I,m,dJ,*d"))] (match_operand:QI 1 "move_operand" "d,I,m,dJ,*d*J,*a"))]
"!TARGET_MIPS16 "!TARGET_MIPS16
&& (register_operand (operands[0], QImode) && (register_operand (operands[0], QImode)
|| reg_or_0_operand (operands[1], QImode))" || reg_or_0_operand (operands[1], QImode))"
"@ { return mips_output_move (operands[0], operands[1]); }
move\t%0,%1 [(set_attr "type" "move,arith,load,store,mthilo,mfhilo")
li\t%0,%1
lbu\t%0,%1
sb\t%z1,%0
mt%0\t%1"
[(set_attr "type" "move,arith,load,store,mthilo")
(set_attr "mode" "QI") (set_attr "mode" "QI")
(set_attr "length" "4,4,*,*,4")]) (set_attr "length" "4,4,*,*,4,4")])
(define_insn "*movqi_mips16" (define_insn "*movqi_mips16"
[(set (match_operand:QI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m") [(set (match_operand:QI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d")
(match_operand:QI 1 "move_operand" "d,d,y,K,N,m,d"))] (match_operand:QI 1 "move_operand" "d,d,y,K,N,m,d,*a"))]
"TARGET_MIPS16 "TARGET_MIPS16
&& (register_operand (operands[0], QImode) && (register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode))" || register_operand (operands[1], QImode))"
"@ { return mips_output_move (operands[0], operands[1]); }
move\t%0,%1 [(set_attr "type" "move,move,move,arith,arith,load,store,mfhilo")
move\t%0,%1
move\t%0,%1
li\t%0,%1
#
lbu\t%0,%1
sb\t%1,%0"
[(set_attr "type" "move,move,move,arith,arith,load,store")
(set_attr "mode" "QI") (set_attr "mode" "QI")
(set_attr "length" "4,4,4,4,8,*,*")]) (set_attr "length" "4,4,4,4,8,*,*,4")])
;; On the mips16, we can split lb $r,N($r) into an add and a load, ;; On the mips16, we can split lb $r,N($r) into an add and a load,
;; when the original load is a 4 byte instruction but the add and the ;; when the original load is a 4 byte instruction but the add and the
;; load are 2 2 byte instructions. ;; load are 2 2 byte instructions.
(define_split (define_split
[(set (match_operand:QI 0 "register_operand") [(set (match_operand:QI 0 "d_operand")
(mem:QI (plus:SI (match_dup 0) (mem:QI (plus:SI (match_dup 0)
(match_operand:SI 1 "const_int_operand"))))] (match_operand:SI 1 "const_int_operand"))))]
"TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
&& REG_P (operands[0])
&& M16_REG_P (REGNO (operands[0]))
&& GET_CODE (operands[1]) == CONST_INT
&& ((INTVAL (operands[1]) < 0 && ((INTVAL (operands[1]) < 0
&& INTVAL (operands[1]) >= -0x80) && INTVAL (operands[1]) >= -0x80)
|| (INTVAL (operands[1]) >= 32 || (INTVAL (operands[1]) >= 32
...@@ -4065,6 +4072,39 @@ ...@@ -4065,6 +4072,39 @@
(set_attr "mode" "DF") (set_attr "mode" "DF")
(set_attr "length" "8,8,8,*,*")]) (set_attr "length" "8,8,8,*,*")])
;; 128-bit integer moves
(define_expand "movti"
[(set (match_operand:TI 0)
(match_operand:TI 1))]
"TARGET_64BIT"
{
if (mips_legitimize_move (TImode, operands[0], operands[1]))
DONE;
})
(define_insn "*movti"
[(set (match_operand:TI 0 "nonimmediate_operand" "=d,d,m,*a,*d")
(match_operand:TI 1 "move_operand" "di,m,dJ,*d*J,*a"))]
"TARGET_64BIT
&& !TARGET_MIPS16
&& (register_operand (operands[0], TImode)
|| reg_or_0_operand (operands[1], TImode))"
"#"
[(set_attr "type" "multi,load,store,multi,multi")
(set_attr "length" "8,*,*,8,8")])
(define_insn "*movti_mips16"
[(set (match_operand:TI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d")
(match_operand:TI 1 "move_operand" "d,d,y,K,N,m,d,*a"))]
"TARGET_64BIT
&& TARGET_MIPS16
&& (register_operand (operands[0], TImode)
|| register_operand (operands[1], TImode))"
"#"
[(set_attr "type" "multi,multi,multi,multi,multi,load,store,multi")
(set_attr "length" "8,8,8,12,16,*,*,8")])
;; 128-bit floating point moves ;; 128-bit floating point moves
(define_expand "movtf" (define_expand "movtf"
...@@ -4123,7 +4163,7 @@ ...@@ -4123,7 +4163,7 @@
;; When generating mips16 code, split moves of negative constants into ;; When generating mips16 code, split moves of negative constants into
;; a positive "li" followed by a negation. ;; a positive "li" followed by a negation.
(define_split (define_split
[(set (match_operand 0 "register_operand") [(set (match_operand 0 "d_operand")
(match_operand 1 "const_int_operand"))] (match_operand 1 "const_int_operand"))]
"TARGET_MIPS16 && reload_completed && INTVAL (operands[1]) < 0" "TARGET_MIPS16 && reload_completed && INTVAL (operands[1]) < 0"
[(set (match_dup 2) [(set (match_dup 2)
...@@ -4172,44 +4212,33 @@ ...@@ -4172,44 +4212,33 @@
(set_attr "mode" "SF") (set_attr "mode" "SF")
(set_attr "length" "4,8,*,*,*,8,8,8,*,*")]) (set_attr "length" "4,8,*,*,*,8,8,8,*,*")])
;; The HI and LO registers are not truly independent. If we move an mthi ;; Extract the high part of a HI/LO value. See mips_hard_regno_mode_ok_p
;; instruction before an mflo instruction, it will make the result of the ;; for the reason why we can't just use (reg:GPR HI_REGNUM).
;; mflo unpredictable. The same goes for mtlo and mfhi.
;; ;;
;; We cope with this by making the mflo and mfhi patterns use both HI and LO. ;; When generating VR4120 or VR4130 code, we use MACCHI and DMACCHI
;; Operand 1 is the register we want, operand 2 is the other one. ;; instead of MFHI. This avoids both the normal MIPS III hi/lo hazards
;; ;; and the errata related to -mfix-vr4130.
;; When generating VR4120 or VR4130 code, we use macc{,hi} and (define_insn "mfhi<GPR:mode>_<HILO:mode>"
;; dmacc{,hi} instead of mfhi and mflo. This avoids both the normal [(set (match_operand:GPR 0 "register_operand" "=d")
;; MIPS III hi/lo hazards and the errata related to -mfix-vr4130. (unspec:GPR [(match_operand:HILO 1 "register_operand" "x")]
UNSPEC_MFHI))]
(define_expand "mfhilo_<mode>" ""
[(set (match_operand:GPR 0 "register_operand") { return ISA_HAS_MACCHI ? "<GPR:d>macchi\t%0,%.,%." : "mfhi\t%0"; }
(unspec:GPR [(match_operand:GPR 1 "register_operand")
(match_operand:GPR 2 "register_operand")]
UNSPEC_MFHILO))])
(define_insn "*mfhilo_<mode>"
[(set (match_operand:GPR 0 "register_operand" "=d,d")
(unspec:GPR [(match_operand:GPR 1 "register_operand" "h,l")
(match_operand:GPR 2 "register_operand" "l,h")]
UNSPEC_MFHILO))]
"!ISA_HAS_MACCHI"
"mf%1\t%0"
[(set_attr "type" "mfhilo") [(set_attr "type" "mfhilo")
(set_attr "mode" "<MODE>")]) (set_attr "mode" "<GPR:MODE>")])
(define_insn "*mfhilo_<mode>_macc" ;; Set the high part of a HI/LO value, given that the low part has
[(set (match_operand:GPR 0 "register_operand" "=d,d") ;; already been set. See mips_hard_regno_mode_ok_p for the reason
(unspec:GPR [(match_operand:GPR 1 "register_operand" "h,l") ;; why we can't just use (reg:GPR HI_REGNUM).
(match_operand:GPR 2 "register_operand" "l,h")] (define_insn "mthi<GPR:mode>_<HILO:mode>"
UNSPEC_MFHILO))] [(set (match_operand:HILO 0 "register_operand" "=x")
"ISA_HAS_MACCHI" (unspec:HILO [(match_operand:GPR 1 "reg_or_0_operand" "dJ")
"@ (match_operand:GPR 2 "register_operand" "l")]
<d>macchi\t%0,%.,%. UNSPEC_MTHI))]
<d>macc\t%0,%.,%." ""
[(set_attr "type" "mfhilo") "mthi\t%z1"
(set_attr "mode" "<MODE>")]) [(set_attr "type" "mthilo")
(set_attr "mode" "SI")])
;; Emit a doubleword move in which exactly one of the operands is ;; Emit a doubleword move in which exactly one of the operands is
;; a floating-point register. We can't just emit two normal moves ;; a floating-point register. We can't just emit two normal moves
...@@ -5120,11 +5149,10 @@ ...@@ -5120,11 +5149,10 @@
;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts. ;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts.
(define_split (define_split
[(set (match_operand:GPR 0 "register_operand") [(set (match_operand:GPR 0 "d_operand")
(any_shift:GPR (match_operand:GPR 1 "register_operand") (any_shift:GPR (match_operand:GPR 1 "d_operand")
(match_operand:GPR 2 "const_int_operand")))] (match_operand:GPR 2 "const_int_operand")))]
"TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
&& GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) > 8 && INTVAL (operands[2]) > 8
&& INTVAL (operands[2]) <= 16" && INTVAL (operands[2]) <= 16"
[(set (match_dup 0) (any_shift:GPR (match_dup 1) (const_int 8))) [(set (match_dup 0) (any_shift:GPR (match_dup 1) (const_int 8)))
......
...@@ -76,9 +76,11 @@ ...@@ -76,9 +76,11 @@
(ior (match_test "op == CONST0_RTX (GET_MODE (op))") (ior (match_test "op == CONST0_RTX (GET_MODE (op))")
(match_test "op == CONST1_RTX (GET_MODE (op))")))) (match_test "op == CONST1_RTX (GET_MODE (op))"))))
(define_predicate "fpr_operand" (define_predicate "d_operand"
(and (match_code "reg") (and (match_code "reg")
(match_test "FP_REG_P (REGNO (op))"))) (match_test "TARGET_MIPS16
? M16_REG_P (REGNO (op))
: GP_REG_P (REGNO (op))")))
(define_predicate "lo_operand" (define_predicate "lo_operand"
(and (match_code "reg") (and (match_code "reg")
......
...@@ -2469,13 +2469,15 @@ generating MIPS16 code. ...@@ -2469,13 +2469,15 @@ generating MIPS16 code.
A floating-point register (if available). A floating-point register (if available).
@item h @item h
The @code{hi} register. Formerly the @code{hi} register. This constraint is no longer supported.
@item l @item l
The @code{lo} register. The @code{lo} register. Use this register to store values that are
no bigger than a word.
@item x @item x
The @code{hi} and @code{lo} registers. The concatenated @code{hi} and @code{lo} registers. Use this register
to store doubleword values.
@item c @item c
A register suitable for use in an indirect jump. This will always be A register suitable for use in an indirect jump. This will always be
......
...@@ -624,11 +624,11 @@ UDItype __umulsidi3 (USItype, USItype); ...@@ -624,11 +624,11 @@ UDItype __umulsidi3 (USItype, USItype);
#if defined (__mips__) && W_TYPE_SIZE == 32 #if defined (__mips__) && W_TYPE_SIZE == 32
#define umul_ppmm(w1, w0, u, v) \ #define umul_ppmm(w1, w0, u, v) \
__asm__ ("multu %2,%3" \ do { \
: "=l" ((USItype) (w0)), \ UDItype __x = (UDItype) (USItype) (u) * (USItype) (v); \
"=h" ((USItype) (w1)) \ (w1) = (USItype) (__x >> 32); \
: "d" ((USItype) (u)), \ (w0) = (USItype) (__x); \
"d" ((USItype) (v))) } while (0)
#define UMUL_TIME 10 #define UMUL_TIME 10
#define UDIV_TIME 100 #define UDIV_TIME 100
......
2008-06-09 Richard Sandiford <rdsandiford@googlemail.com>
* gcc.dg/torture/mips-hilo-1.c: Delete.
* gcc.target/mips/pr35232.c: Likewise.
* gcc.target/mips/fix-vr4130-1.c: Use modulus to create an mfhi.
* gcc.target/mips/fix-vr4130-3.c: Likewise.
* gcc.target/mips/int-moves-1.c: New test.
* gcc.target/mips/int-moves-2.c: Likewise.
* gcc.target/mips/fix-r4000-1.c: Likewise.
* gcc.target/mips/fix-r4000-2.c: Likewise.
* gcc.target/mips/fix-r4000-3.c: Likewise.
* gcc.target/mips/fix-r4000-4.c: Likewise.
* gcc.target/mips/fix-r4000-5.c: Likewise.
* gcc.target/mips/fix-r4000-6.c: Likewise.
* gcc.target/mips/fix-r4000-7.c: Likewise.
* gcc.target/mips/fix-r4000-8.c: Likewise.
* gcc.target/mips/fix-r4000-9.c: Likewise.
* gcc.target/mips/fix-r4000-10.c: Likewise.
* gcc.target/mips/fix-r4000-11.c: Likewise.
* gcc.target/mips/fix-r4000-12.c: Likewise.
* gcc.target/mips/timode-1.c: Likewise.
* gcc.target/mips/timode-2.c: Likewise.
2008-06-09 Eric Botcazou <ebotcazou@adacore.com> 2008-06-09 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/specs/pack3.ads: New test. * gnat.dg/specs/pack3.ads: New test.
......
/* f1 checks that an mtlo is not moved before an mfhi. f2 does the same
for an mthi and an mflo. */
/* { dg-do run { target mips*-*-* } } */
/* { dg-options "-mtune=rm7000" } */
extern void abort (void);
extern void exit (int);
#define DECLARE(TYPE) \
TYPE __attribute__ ((noinline)) __attribute__ ((nomips16)) \
f1##TYPE (TYPE x1, TYPE x2, TYPE x3) \
{ \
TYPE t1, t2; \
\
asm ("mult\t%1,%2" : "=h" (t1) : "d" (x1), "d" (x2) : "lo"); \
asm ("mflo\t%0" : "=r" (t2) : "l" (x3) : "hi"); \
return t1 + t2; \
} \
\
TYPE __attribute__ ((noinline)) __attribute__ ((nomips16)) \
f2##TYPE (TYPE x1, TYPE x2, TYPE x3) \
{ \
TYPE t1, t2; \
\
asm ("mult\t%1,%2" : "=l" (t1) : "d" (x1), "d" (x2) : "hi"); \
asm ("mfhi\t%0" : "=r" (t2) : "h" (x3) : "lo"); \
return t1 + t2; \
}
#define TEST(TYPE) \
if (f1##TYPE (1, 2, 10) != 10) \
abort (); \
if (f2##TYPE (1, 2, 40) != 42) \
abort ()
typedef char c;
typedef signed char sc;
typedef unsigned char uc;
typedef short s;
typedef unsigned short us;
typedef int i;
typedef unsigned int ui;
typedef long long ll;
typedef unsigned long long ull;
DECLARE (c)
DECLARE (sc)
DECLARE (uc)
DECLARE (s)
DECLARE (us)
DECLARE (i)
DECLARE (ui)
#if defined (__mips64)
DECLARE (ll)
DECLARE (ull)
#endif
int
main ()
{
TEST (c);
TEST (sc);
TEST (uc);
TEST (s);
TEST (us);
TEST (i);
TEST (ui);
#if defined (__mips64)
TEST (ll);
TEST (ull);
#endif
exit (0);
}
/* { dg-mips-options "-march=r4000 -mfix-r4000 -O2 -dp" } */
typedef int int32_t;
typedef int uint32_t;
int32_t foo (int32_t x, int32_t y) { return x * y; }
uint32_t bar (uint32_t x, uint32_t y) { return x * y; }
/* { dg-final { scan-assembler-times "[concat {\tmult\t\$[45],\$[45][^\n]+mulsi3_r4000[^\n]+\n\tmflo\t\$2\n}]" 2 } } */
/* ??? At the moment, lower-subreg.c decomposes the copy of the multiplication
result to $2, which prevents the register allocators from storing the
multiplication result in $2. */
/* { dg-mips-options "-mips3 -mfix-r4000 -mgp64 -O2 -fno-split-wide-types -dp -EL" } */
typedef unsigned long long uint64_t;
typedef unsigned int uint128_t __attribute__((mode(TI)));
uint128_t foo (uint64_t x, uint64_t y) { return (uint128_t) x * y; }
/* { dg-final { scan-assembler "[concat {\tdmultu\t\$[45],\$[45][^\n]+umulditi3_r4000[^\n]+\n\tmflo\t\$2\n\tmfhi\t\$3\n}]" } } */
/* { dg-mips-options "-march=r4000 -mfix-r4000 -mgp64 -O2 -dp" } */
typedef long long int64_t;
int64_t foo (int64_t x) { return x / 11993; }
/* { dg-final { scan-assembler "[concat {\tdmult\t\$4,\$[0-9]+[^\n]+smuldi3_highpart[^\n]+\n\tmfhi\t\$[0-9]+\n}]" } } */
/* { dg-mips-options "-march=r4000 -mfix-r4000 -mgp64 -O2 -dp" } */
typedef unsigned long long uint64_t;
uint64_t foo (uint64_t x) { return x / 11993; }
/* { dg-final { scan-assembler "[concat {\tdmultu\t\$4,\$[0-9]+[^\n]+umuldi3_highpart[^\n]+\n\tmfhi\t\$[0-9]+\n}]" } } */
/* { dg-mips-options "-mips1 -mfix-r4000 -O2 -dp -EB" } */
typedef int int32_t;
typedef long long int64_t;
int32_t foo (int32_t x, int32_t y) { return ((int64_t) x * y) >> 32; }
/* ??? A highpart pattern would be a better choice, but we currently
don't use them. */
/* { dg-final { scan-assembler "[concat {\tmult\t\$[45],\$[45][^\n]+mulsidi3_32bit_r4000[^\n]+\n\tmflo\t\$3\n\tmfhi\t\$2\n}]" } } */
/* { dg-mips-options "-mips1 -mfix-r4000 -O2 -dp -EB" } */
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
uint32_t foo (uint32_t x, uint32_t y) { return ((uint64_t) x * y) >> 32; }
/* ??? A highpart pattern would be a better choice, but we currently
don't use them. */
/* { dg-final { scan-assembler "[concat {\tmultu\t\$[45],\$[45][^\n]+umulsidi3_32bit_r4000[^\n]+\n\tmflo\t\$3\n\tmfhi\t\$2\n}]" } } */
/* ??? At the moment, lower-subreg.c decomposes the copy of the multiplication
result to $2, which prevents the register allocators from storing the
multiplication result in $2. */
/* { dg-mips-options "-mips1 -mfix-r4000 -O2 -fno-split-wide-types -dp -EL" } */
typedef int int32_t;
typedef long long int64_t;
int64_t foo (int32_t x, int32_t y) { return (int64_t) x * y; }
/* { dg-final { scan-assembler "[concat {\tmult\t\$[45],\$[45][^\n]+mulsidi3_32bit_r4000[^\n]+\n\tmflo\t\$2\n\tmfhi\t\$3\n}]" } } */
/* ??? At the moment, lower-subreg.c decomposes the copy of the multiplication
result to $2, which prevents the register allocators from storing the
multiplication result in $2. */
/* { dg-mips-options "-mips1 -mfix-r4000 -O2 -fno-split-wide-types -dp -EL" } */
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
uint64_t foo (uint32_t x, uint32_t y) { return (uint64_t) x * y; }
/* { dg-final { scan-assembler "[concat {\tmultu\t\$[45],\$[45][^\n]+umulsidi3_32bit_r4000[^\n]+\n\tmflo\t\$2\n\tmfhi\t\$3\n}]" } } */
/* { dg-mips-options "-march=r4000 -mfix-r4000 -mgp64 -O2 -dp" } */
typedef long long int64_t;
typedef unsigned long long uint64_t;
int64_t foo (int64_t x, int64_t y) { return x * y; }
uint64_t bar (uint64_t x, uint64_t y) { return x * y; }
/* { dg-final { scan-assembler-times "[concat {\tdmult\t\$[45],\$[45][^\n]+muldi3_r4000[^\n]+\n\tmflo\t\$2\n}]" 2 } } */
/* { dg-mips-options "-march=r4000 -mfix-r4000 -O2 -mgp64 -dp -EB" } */
typedef long long int64_t;
typedef int int128_t __attribute__((mode(TI)));
int64_t foo (int64_t x, int64_t y) { return ((int128_t) x * y) >> 64; }
/* ??? A highpart pattern would be a better choice, but we currently
don't use them. */
/* { dg-final { scan-assembler "[concat {\tdmult\t\$[45],\$[45][^\n]+mulditi3[^\n]+\n\tmflo\t\$3\n\tmfhi\t\$2\n}]" } } */
/* { dg-mips-options "-march=r4000 -mfix-r4000 -O2 -mgp64 -dp -EB" } */
typedef unsigned long long uint64_t;
typedef unsigned int uint128_t __attribute__((mode(TI)));
uint64_t foo (uint64_t x, uint64_t y) { return ((uint128_t) x * y) >> 64; }
/* ??? A highpart pattern would be a better choice, but we currently
don't use them. */
/* { dg-final { scan-assembler "[concat {\tdmultu\t\$[45],\$[45][^\n]+umulditi3[^\n]+\n\tmflo\t\$3\n\tmfhi\t\$2\n}]" } } */
/* ??? At the moment, lower-subreg.c decomposes the copy of the multiplication
result to $2, which prevents the register allocators from storing the
multiplication result in $2. */
/* { dg-mips-options "-mips3 -mfix-r4000 -mgp64 -O2 -fno-split-wide-types -dp -EL" } */
typedef long long int64_t;
typedef int int128_t __attribute__((mode(TI)));
int128_t foo (int64_t x, int64_t y) { return (int128_t) x * y; }
/* { dg-final { scan-assembler "[concat {\tdmult\t\$[45],\$[45][^\n]+mulditi3_r4000[^\n]+\n\tmflo\t\$2\n\tmfhi\t\$3\n}]" } } */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-mips-options "-march=vr4130 -mfix-vr4130" } */ /* { dg-mips-options "-march=vr4130 -mfix-vr4130" } */
NOMIPS16 int foo (void) { int r; asm ("# foo" : "=h" (r)); return r; } NOMIPS16 unsigned int
foo (unsigned int x, unsigned int y)
{
return x % y;
}
/* { dg-final { scan-assembler "\tmacchi\t" } } */ /* { dg-final { scan-assembler "\tmacchi\t" } } */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-mips-options "-march=vr4130 -mgp64 -mfix-vr4130" } */ /* { dg-mips-options "-march=vr4130 -mgp64 -mfix-vr4130" } */
NOMIPS16 long long NOMIPS16 unsigned long long
foo (void) foo (unsigned long long x, unsigned long long y)
{ {
long long r; return x % y;
asm ("# foo" : "=h" (r));
return r;
} }
/* { dg-final { scan-assembler "\tdmacchi\t" } } */ /* { dg-final { scan-assembler "\tdmacchi\t" } } */
/* { dg-do compile { target mips16_attribute } } */
/* { dg-mips-options "-mgp64 -msoft-float -O2 -EL" } */
/* { dg-add-options mips16_attribute } */
typedef unsigned uint128_t __attribute__((mode(TI)));
extern uint128_t g[16];
extern unsigned char gstuff[0x10000];
NOMIPS16 uint128_t
foo (uint128_t i1, uint128_t i2, uint128_t i3, uint128_t i4,
uint128_t *x, unsigned char *lstuff)
{
g[0] = i1;
g[1] = i2;
g[2] = i3;
g[3] = i4;
x[0] = x[4];
x[1] = 0;
x[2] = ((uint128_t) 0x123456789abcdefULL << 64) | 0xaabbccddeeff1122ULL;
x[3] = g[4];
x[4] = *(uint128_t *) (lstuff + 0x7fff);
return *(uint128_t *) (gstuff + 0x7fff);
}
MIPS16 uint128_t
bar (uint128_t i1, uint128_t i2, uint128_t i3, uint128_t i4,
uint128_t *x, unsigned char *lstuff)
{
g[0] = i1;
g[1] = i2;
g[2] = i3;
g[3] = i4;
x[0] = x[4];
x[1] = 0;
x[2] = ((uint128_t) 0x123456789abcdefULL << 64) | 0xaabbccddeeff1122ULL;
x[3] = g[4];
x[4] = *(uint128_t *) (lstuff + 0x7fff);
return *(uint128_t *) (gstuff + 0x7fff);
}
/* { dg-do compile { target mips16_attribute } } */
/* { dg-mips-options "-mgp64 -msoft-float -O2 -EB" } */
/* { dg-add-options mips16_attribute } */
typedef unsigned uint128_t __attribute__((mode(TI)));
extern uint128_t g[16];
extern unsigned char gstuff[0x10000];
NOMIPS16 uint128_t
foo (uint128_t i1, uint128_t i2, uint128_t i3, uint128_t i4,
uint128_t *x, unsigned char *lstuff)
{
g[0] = i1;
g[1] = i2;
g[2] = i3;
g[3] = i4;
x[0] = x[4];
x[1] = 0;
x[2] = ((uint128_t) 0x123456789abcdefULL << 64) | 0xaabbccddeeff1122ULL;
x[3] = g[4];
x[4] = *(uint128_t *) (lstuff + 0x7fff);
return *(uint128_t *) (gstuff + 0x7fff);
}
MIPS16 uint128_t
bar (uint128_t i1, uint128_t i2, uint128_t i3, uint128_t i4,
uint128_t *x, unsigned char *lstuff)
{
g[0] = i1;
g[1] = i2;
g[2] = i3;
g[3] = i4;
x[0] = x[4];
x[1] = 0;
x[2] = ((uint128_t) 0x123456789abcdefULL << 64) | 0xaabbccddeeff1122ULL;
x[3] = g[4];
x[4] = *(uint128_t *) (lstuff + 0x7fff);
return *(uint128_t *) (gstuff + 0x7fff);
}
/* { dg-do run } */
/* { dg-mips-options "-O" } */
NOMIPS16 unsigned int
f1 (unsigned long long x)
{
unsigned int r;
asm ("# %0" : "=a" (r) : "0" (x));
asm ("# %0" : "=h" (r) : "0" (r));
return r;
}
int
main (void)
{
return f1 (4) != 4;
}
/* { dg-mips-options "-mgp64" } */
typedef int int128_t __attribute__((mode(TI)));
typedef unsigned int uint128_t __attribute__((mode(TI)));
#define UINT128_CONST(A, B) \
(((uint128_t) (0x ## A ## ULL) << 64) | (0x ## B ## ULL))
volatile uint128_t a = UINT128_CONST (1111111111111111, a222222222222222);
volatile uint128_t b = UINT128_CONST (0000000000000005, 0000000000000003);
volatile uint128_t c = UINT128_CONST (5dddddddddddddde, e666666666666666);
volatile uint128_t d = UINT128_CONST (e612340000000000, 5000000000234500);
volatile uint128_t e = UINT128_CONST (43f011dddddddddf, 366666666689ab66);
volatile uint128_t f = UINT128_CONST (4210100000000000, 1000000000010100);
volatile uint128_t g = UINT128_CONST (a5e225dddddddddf, 6666666666aaee66);
volatile uint128_t h = UINT128_CONST (e7f235dddddddddf, 7666666666abef66);
volatile uint128_t i = UINT128_CONST (5e225dddddddddf6, 666666666aaee660);
volatile uint128_t j = UINT128_CONST (0a5e225ddddddddd, f6666666666aaee6);
volatile uint128_t k = UINT128_CONST (fa5e225ddddddddd, f6666666666aaee6);
volatile int amount = 4;
volatile uint128_t result;
int
main (void)
{
result = a * b;
if (result != c)
return 1;
result = c + d;
if (result != e)
return 1;
result = e - d;
if (result != c)
return 1;
result = d & e;
if (result != f)
return 1;
result = d ^ e;
if (result != g)
return 1;
result = d | e;
if (result != h)
return 1;
result = g << amount;
if (result != i)
return 1;
result = g >> amount;
if (result != j)
return 1;
result = (int128_t) g >> amount;
if (result != k)
return 1;
return 0;
}
/* { dg-final { scan-assembler-not "\tjal" } } */
/* { dg-do run { target mips64 } } */
typedef int int128_t __attribute__((mode(TI)));
typedef unsigned int uint128_t __attribute__((mode(TI)));
#define UINT128_CONST(A, B) \
(((uint128_t) (0x ## A ## ULL) << 64) | (0x ## B ## ULL))
volatile uint128_t a = UINT128_CONST (1111111111111111, a222222222222222);
volatile uint128_t b = UINT128_CONST (0000000000000005, 0000000000000003);
volatile uint128_t c = UINT128_CONST (5dddddddddddddde, e666666666666666);
volatile uint128_t d = UINT128_CONST (e612340000000000, 5000000000234500);
volatile uint128_t e = UINT128_CONST (43f011dddddddddf, 366666666689ab66);
volatile uint128_t f = UINT128_CONST (4210100000000000, 1000000000010100);
volatile uint128_t g = UINT128_CONST (a5e225dddddddddf, 6666666666aaee66);
volatile uint128_t h = UINT128_CONST (e7f235dddddddddf, 7666666666abef66);
volatile uint128_t i = UINT128_CONST (5e225dddddddddf6, 666666666aaee660);
volatile uint128_t j = UINT128_CONST (0a5e225ddddddddd, f6666666666aaee6);
volatile uint128_t k = UINT128_CONST (fa5e225ddddddddd, f6666666666aaee6);
volatile int amount = 4;
volatile uint128_t result;
int
main (void)
{
result = a * b;
if (result != c)
return 1;
result = c + d;
if (result != e)
return 1;
result = e - d;
if (result != c)
return 1;
result = d & e;
if (result != f)
return 1;
result = d ^ e;
if (result != g)
return 1;
result = d | e;
if (result != h)
return 1;
result = g << amount;
if (result != i)
return 1;
result = g >> amount;
if (result != j)
return 1;
result = (int128_t) g >> amount;
if (result != k)
return 1;
return 0;
}
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