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
This commit is contained in:
Richard Sandiford 2008-06-09 20:45:56 +00:00 committed by Richard Sandiford
parent 0e462a951b
commit 21dfc6dc74
28 changed files with 915 additions and 541 deletions

View File

@ -1,3 +1,80 @@
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>
* config.gcc (i[34567]86-*-*): Put test in quotes to prevent

View File

@ -29,14 +29,16 @@
(define_register_constraint "f" "TARGET_HARD_FLOAT ? FP_REGS : NO_REGS"
"A floating-point register (if available).")
(define_register_constraint "h" "TARGET_BIG_ENDIAN ? MD0_REG : MD1_REG"
"The @code{hi} register.")
(define_register_constraint "h" "NO_REGS"
"Formerly the @code{hi} register. This constraint is no longer supported.")
(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"
"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"
"@internal")

View File

@ -2675,23 +2675,6 @@ mips_legitimize_move (enum machine_mode mode, rtx dest, rtx src)
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
immediate_operands but aren't legitimate move_operands. */
if (CONSTANT_P (src) && !move_operand (src, mode))
@ -3488,7 +3471,7 @@ mips_subword (rtx op, bool high_p)
mode = GET_MODE (op);
if (mode == VOIDmode)
mode = DImode;
mode = TARGET_64BIT ? TImode : DImode;
if (TARGET_BIG_ENDIAN ? !high_p : high_p)
byte = UNITS_PER_WORD;
@ -3539,6 +3522,8 @@ mips_split_64bit_move_p (rtx dest, rtx src)
void
mips_split_doubleword_move (rtx dest, rtx src)
{
rtx low_dest;
if (FP_REG_RTX_P (dest) || FP_REG_RTX_P (src))
{
if (!TARGET_64BIT && GET_MODE (dest) == DImode)
@ -3552,12 +3537,27 @@ mips_split_doubleword_move (rtx dest, rtx src)
else
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
{
/* The operation can be split into two normal moves. Decide in
which order to do them. */
rtx low_dest;
low_dest = mips_subword (dest, false);
if (REG_P (low_dest)
&& reg_overlap_mentioned_p (low_dest, src))
@ -3600,8 +3600,9 @@ mips_output_move (rtx dest, rtx src)
if (GP_REG_P (REGNO (dest)))
return "move\t%0,%z1";
if (MD_REG_P (REGNO (dest)))
return "mt%0\t%z1";
/* Moves to HI are handled by special .md insns. */
if (REGNO (dest) == LO_REGNUM)
return "mtlo\t%z1";
if (DSP_ACC_REG_P (REGNO (dest)))
{
@ -3624,14 +3625,29 @@ mips_output_move (rtx dest, rtx src)
}
}
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 (src_code == REG)
{
/* Handled by separate patterns. */
gcc_assert (!MD_REG_P (REGNO (src)));
/* Moves from HI are handled by special .md insns. */
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)))
{
@ -3658,7 +3674,13 @@ mips_output_move (rtx dest, rtx src)
}
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)
{
@ -8954,13 +8976,30 @@ mips_hard_regno_mode_ok_p (unsigned int regno, enum machine_mode mode)
if (ACC_REG_P (regno)
&& (INTEGRAL_MODE_P (mode) || ALL_FIXED_POINT_MODE_P (mode)))
{
if (size <= UNITS_PER_WORD)
return true;
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.
if (size <= UNITS_PER_WORD * 2)
return (DSP_ACC_REG_P (regno)
? ((regno - DSP_ACC_REG_FIRST) & 1) == 0
: regno == MD_REG_FIRST);
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)
return true;
if (size <= UNITS_PER_WORD * 2
&& ((regno - DSP_ACC_REG_FIRST) & 1) == 0)
return true;
}
}
if (ALL_COP_REG_P (regno))

File diff suppressed because it is too large Load Diff

View File

@ -76,9 +76,11 @@
(ior (match_test "op == CONST0_RTX (GET_MODE (op))")
(match_test "op == CONST1_RTX (GET_MODE (op))"))))
(define_predicate "fpr_operand"
(define_predicate "d_operand"
(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"
(and (match_code "reg")

View File

@ -2469,13 +2469,15 @@ generating MIPS16 code.
A floating-point register (if available).
@item h
The @code{hi} register.
Formerly the @code{hi} register. This constraint is no longer supported.
@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
The @code{hi} and @code{lo} registers.
The concatenated @code{hi} and @code{lo} registers. Use this register
to store doubleword values.
@item c
A register suitable for use in an indirect jump. This will always be

View File

@ -623,12 +623,12 @@ UDItype __umulsidi3 (USItype, USItype);
#endif /* __m88000__ */
#if defined (__mips__) && W_TYPE_SIZE == 32
#define umul_ppmm(w1, w0, u, v) \
__asm__ ("multu %2,%3" \
: "=l" ((USItype) (w0)), \
"=h" ((USItype) (w1)) \
: "d" ((USItype) (u)), \
"d" ((USItype) (v)))
#define umul_ppmm(w1, w0, u, v) \
do { \
UDItype __x = (UDItype) (USItype) (u) * (USItype) (v); \
(w1) = (USItype) (__x >> 32); \
(w0) = (USItype) (__x); \
} while (0)
#define UMUL_TIME 10
#define UDIV_TIME 100

View File

@ -1,3 +1,26 @@
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>
* gnat.dg/specs/pack3.ads: New test.

View File

@ -1,73 +0,0 @@
/* 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);
}

View File

@ -0,0 +1,6 @@
/* { 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 } } */

View File

@ -0,0 +1,8 @@
/* ??? 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}]" } } */

View File

@ -0,0 +1,4 @@
/* { 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}]" } } */

View File

@ -0,0 +1,4 @@
/* { 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}]" } } */

View File

@ -0,0 +1,7 @@
/* { 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}]" } } */

View File

@ -0,0 +1,7 @@
/* { 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}]" } } */

View File

@ -0,0 +1,8 @@
/* ??? 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}]" } } */

View File

@ -0,0 +1,8 @@
/* ??? 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}]" } } */

View File

@ -0,0 +1,6 @@
/* { 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 } } */

View File

@ -0,0 +1,7 @@
/* { 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}]" } } */

View File

@ -0,0 +1,7 @@
/* { 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}]" } } */

View File

@ -0,0 +1,8 @@
/* ??? 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}]" } } */

View File

@ -1,4 +1,8 @@
/* { dg-do compile } */
/* { 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" } } */

View File

@ -1,10 +1,8 @@
/* { dg-do compile } */
/* { dg-mips-options "-march=vr4130 -mgp64 -mfix-vr4130" } */
NOMIPS16 long long
foo (void)
NOMIPS16 unsigned long long
foo (unsigned long long x, unsigned long long y)
{
long long r;
asm ("# foo" : "=h" (r));
return r;
return x % y;
}
/* { dg-final { scan-assembler "\tdmacchi\t" } } */

View File

@ -0,0 +1,40 @@
/* { 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);
}

View File

@ -0,0 +1,40 @@
/* { 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);
}

View File

@ -1,17 +0,0 @@
/* { 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;
}

View File

@ -0,0 +1,65 @@
/* { 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" } } */

View File

@ -0,0 +1,64 @@
/* { 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;
}