aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid S. Miller <davem@pierdol.cobaltmicro.com>1998-07-03 03:19:41 +0000
committerDavid S. Miller <davem@gcc.gnu.org>1998-07-02 20:19:41 -0700
commitf7e0e539c53fa846aa01be0aae76f165507e8187 (patch)
tree3e187973b234063596a26c4c08018efa835ac893 /gcc
parentd420e567dc52d4c7c384ffdcefe4bd4ae8f4e30b (diff)
downloadgcc-f7e0e539c53fa846aa01be0aae76f165507e8187.zip
gcc-f7e0e539c53fa846aa01be0aae76f165507e8187.tar.gz
gcc-f7e0e539c53fa846aa01be0aae76f165507e8187.tar.bz2
sparc.c (sparc_operand, [...]): Recognize CONSTANT_P_RTX.
* sparc.c (sparc_operand, move_operand, arith_operand, arith11_operand, arith10_operand, arith_double_operand, arith11_double_operand, arith10_double_operand, small_int, uns_small_int): Recognize CONSTANT_P_RTX. (output_sized_memop, output_move_with_extension, output_load_address, output_size_for_block_move, output_block_move, delay_operand): Remove, has not been enabled or referenced for years. * sparc.md (movstrsi, block_move_insn): Likewise. * sparc.h (PREDICATE_CODES): Define. * linux-aout.h (MACHINE_STATE_{SAVE,RESTORE}): Override with version which uses getcc/setcc traps to save/restore condition codes. * linux64.h: Likewise. * sunos4.h: Likewise. * linux.h: Likewise. * sol2.h: Likewise. * sun4o3.h: Likewise. From-SVN: r20917
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog21
-rw-r--r--gcc/config/sparc/linux-aout.h19
-rw-r--r--gcc/config/sparc/linux.h19
-rw-r--r--gcc/config/sparc/linux64.h19
-rw-r--r--gcc/config/sparc/sol2.h19
-rw-r--r--gcc/config/sparc/sparc.c405
-rw-r--r--gcc/config/sparc/sparc.h43
-rw-r--r--gcc/config/sparc/sparc.md49
-rw-r--r--gcc/config/sparc/sun4o3.h21
-rw-r--r--gcc/config/sparc/sunos4.h19
10 files changed, 202 insertions, 432 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0f21f63..17f45c1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,24 @@
+Fri Jul 3 02:33:35 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+
+ * sparc.c (sparc_operand, move_operand, arith_operand,
+ arith11_operand, arith10_operand, arith_double_operand,
+ arith11_double_operand, arith10_double_operand, small_int,
+ uns_small_int): Recognize CONSTANT_P_RTX.
+ (output_sized_memop, output_move_with_extension,
+ output_load_address, output_size_for_block_move,
+ output_block_move, delay_operand): Remove, has not been
+ enabled or referenced for years.
+ * sparc.md (movstrsi, block_move_insn): Likewise.
+ * sparc.h (PREDICATE_CODES): Define.
+ * linux-aout.h (MACHINE_STATE_{SAVE,RESTORE}): Override with
+ version which uses getcc/setcc traps to save/restore condition
+ codes.
+ * linux64.h: Likewise.
+ * sunos4.h: Likewise.
+ * linux.h: Likewise.
+ * sol2.h: Likewise.
+ * sun4o3.h: Likewise.
+
Fri Jul 3 02:28:05 1998 Richard Henderson <rth@cygnus.com>
* alpha.c (alpha_initialize_trampoline): Hack around Pmode/ptr_mode
diff --git a/gcc/config/sparc/linux-aout.h b/gcc/config/sparc/linux-aout.h
index 7075b5f..76d7653 100644
--- a/gcc/config/sparc/linux-aout.h
+++ b/gcc/config/sparc/linux-aout.h
@@ -109,3 +109,22 @@ Boston, MA 02111-1307, USA. */
long double yet. */
#define LONG_DOUBLE_TYPE_SIZE 128
#endif
+
+/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special
+ traps available which can get and set the condition codes
+ reliably. */
+#undef MACHINE_STATE_SAVE
+#define MACHINE_STATE_SAVE(ID) \
+ unsigned long int ms_flags, ms_saveret; \
+ asm volatile("ta 0x20\n\t" \
+ "mov %%g1, %0\n\t" \
+ "mov %%g2, %1\n\t" \
+ : "=r" (ms_flags), "=r" (ms_saveret));
+
+#undef MACHINE_STATE_RESTORE
+#define MACHINE_STATE_RESTORE(ID) \
+ asm volatile("mov %0, %%g1\n\t" \
+ "mov %1, %%g2\n\t" \
+ "ta 0x21\n\t" \
+ : /* no outputs */ \
+ : "r" (ms_flags), "r" (ms_saveret));
diff --git a/gcc/config/sparc/linux.h b/gcc/config/sparc/linux.h
index a5807ec..fe6bf6a 100644
--- a/gcc/config/sparc/linux.h
+++ b/gcc/config/sparc/linux.h
@@ -238,3 +238,22 @@ do { \
long double yet. */
#define LONG_DOUBLE_TYPE_SIZE 128
#endif
+
+/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special
+ traps available which can get and set the condition codes
+ reliably. */
+#undef MACHINE_STATE_SAVE
+#define MACHINE_STATE_SAVE(ID) \
+ unsigned long int ms_flags, ms_saveret; \
+ asm volatile("ta 0x20\n\t" \
+ "mov %%g1, %0\n\t" \
+ "mov %%g2, %1\n\t" \
+ : "=r" (ms_flags), "=r" (ms_saveret));
+
+#undef MACHINE_STATE_RESTORE
+#define MACHINE_STATE_RESTORE(ID) \
+ asm volatile("mov %0, %%g1\n\t" \
+ "mov %1, %%g2\n\t" \
+ "ta 0x21\n\t" \
+ : /* no outputs */ \
+ : "r" (ms_flags), "r" (ms_saveret));
diff --git a/gcc/config/sparc/linux64.h b/gcc/config/sparc/linux64.h
index 3f35936..866d357 100644
--- a/gcc/config/sparc/linux64.h
+++ b/gcc/config/sparc/linux64.h
@@ -224,3 +224,22 @@ do { \
RELATIVE relocations. */
/* #define DWARF_OFFSET_SIZE PTR_SIZE */
+
+/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special
+ traps available which can get and set the condition codes
+ reliably. */
+#undef MACHINE_STATE_SAVE
+#define MACHINE_STATE_SAVE(ID) \
+ unsigned long int ms_flags, ms_saveret; \
+ asm volatile("ta 0x20\n\t" \
+ "mov %%g1, %0\n\t" \
+ "mov %%g2, %1\n\t" \
+ : "=r" (ms_flags), "=r" (ms_saveret));
+
+#undef MACHINE_STATE_RESTORE
+#define MACHINE_STATE_RESTORE(ID) \
+ asm volatile("mov %0, %%g1\n\t" \
+ "mov %1, %%g2\n\t" \
+ "ta 0x21\n\t" \
+ : /* no outputs */ \
+ : "r" (ms_flags), "r" (ms_saveret));
diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h
index dfcb3b9..a0fa4a8 100644
--- a/gcc/config/sparc/sol2.h
+++ b/gcc/config/sparc/sol2.h
@@ -210,4 +210,23 @@ Boston, MA 02111-1307, USA. */
sparc_override_options will disable V8+ if not generating V9 code. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU + MASK_V8PLUS)
+
+/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special
+ traps available which can get and set the condition codes
+ reliably. */
+#undef MACHINE_STATE_SAVE
+#define MACHINE_STATE_SAVE(ID) \
+ unsigned long int ms_flags, ms_saveret; \
+ asm volatile("ta 0x20\n\t" \
+ "mov %%g1, %0\n\t" \
+ "mov %%g2, %1\n\t" \
+ : "=r" (ms_flags), "=r" (ms_saveret));
+
+#undef MACHINE_STATE_RESTORE
+#define MACHINE_STATE_RESTORE(ID) \
+ asm volatile("mov %0, %%g1\n\t" \
+ "mov %1, %%g2\n\t" \
+ "ta 0x21\n\t" \
+ : /* no outputs */ \
+ : "r" (ms_flags), "r" (ms_saveret));
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 92b2049..62be726 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -641,7 +641,8 @@ sparc_operand (op, mode)
rtx op;
enum machine_mode mode;
{
- if (register_operand (op, mode))
+ if (register_operand (op, mode)
+ || GET_CODE (op) == CONSTANT_P_RTX)
return 1;
if (GET_CODE (op) == CONST_INT)
return SMALL_INT (op);
@@ -666,7 +667,8 @@ move_operand (op, mode)
{
if (mode == DImode && arith_double_operand (op, mode))
return 1;
- if (register_operand (op, mode))
+ if (register_operand (op, mode)
+ || GET_CODE (op) == CONSTANT_P_RTX)
return 1;
if (GET_CODE (op) == CONST_INT)
return SMALL_INT (op) || SPARC_SETHI_P (INTVAL (op));
@@ -773,6 +775,7 @@ v9_regcmp_op (op, mode)
return v9_regcmp_p (code);
}
+/* ??? Same as eq_or_neq. */
int
v8plus_regcmp_op (op, mode)
register rtx op;
@@ -834,7 +837,8 @@ arith_operand (op, mode)
enum machine_mode mode;
{
int val;
- if (register_operand (op, mode))
+ if (register_operand (op, mode)
+ || GET_CODE (op) == CONSTANT_P_RTX)
return 1;
if (GET_CODE (op) != CONST_INT)
return 0;
@@ -852,6 +856,7 @@ arith11_operand (op, mode)
enum machine_mode mode;
{
return (register_operand (op, mode)
+ || GET_CODE (op) == CONSTANT_P_RTX
|| (GET_CODE (op) == CONST_INT && SPARC_SIMM11_P (INTVAL (op))));
}
@@ -865,6 +870,7 @@ arith10_operand (op, mode)
enum machine_mode mode;
{
return (register_operand (op, mode)
+ || GET_CODE (op) == CONSTANT_P_RTX
|| (GET_CODE (op) == CONST_INT && SPARC_SIMM10_P (INTVAL (op))));
}
@@ -881,6 +887,7 @@ arith_double_operand (op, mode)
enum machine_mode mode;
{
return (register_operand (op, mode)
+ || GET_CODE (op) == CONSTANT_P_RTX
|| (GET_CODE (op) == CONST_INT && SMALL_INT (op))
|| (! TARGET_ARCH64
&& GET_CODE (op) == CONST_DOUBLE
@@ -906,6 +913,7 @@ arith11_double_operand (op, mode)
enum machine_mode mode;
{
return (register_operand (op, mode)
+ || GET_CODE (op) == CONSTANT_P_RTX
|| (GET_CODE (op) == CONST_DOUBLE
&& (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
&& (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x400) < 0x800
@@ -929,6 +937,7 @@ arith10_double_operand (op, mode)
enum machine_mode mode;
{
return (register_operand (op, mode)
+ || GET_CODE (op) == CONSTANT_P_RTX
|| (GET_CODE (op) == CONST_DOUBLE
&& (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
&& (unsigned) (CONST_DOUBLE_LOW (op) + 0x200) < 0x400
@@ -950,7 +959,8 @@ small_int (op, mode)
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
- return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
+ return ((GET_CODE (op) == CONST_INT && SMALL_INT (op))
+ || GET_CODE (op) == CONSTANT_P_RTX);
}
/* Recognize operand values for the umul instruction. That instruction sign
@@ -964,14 +974,16 @@ uns_small_int (op, mode)
{
#if HOST_BITS_PER_WIDE_INT > 32
/* All allowed constants will fit a CONST_INT. */
- return (GET_CODE (op) == CONST_INT
- && ((INTVAL (op) >= 0 && INTVAL (op) < 0x1000)
- || (INTVAL (op) >= 0xFFFFF000 && INTVAL (op) < 0x100000000L)));
+ return ((GET_CODE (op) == CONST_INT
+ && ((INTVAL (op) >= 0 && INTVAL (op) < 0x1000)
+ || (INTVAL (op) >= 0xFFFFF000 && INTVAL (op) < 0x100000000L)))
+ || GET_CODE (op) == CONSTANT_P_RTX);
#else
- return ((GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 0x1000)
- || (GET_CODE (op) == CONST_DOUBLE
- && CONST_DOUBLE_HIGH (op) == 0
- && (unsigned) CONST_DOUBLE_LOW (op) - 0xFFFFF000 < 0x1000));
+ return (((GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 0x1000)
+ || (GET_CODE (op) == CONST_DOUBLE
+ && CONST_DOUBLE_HIGH (op) == 0
+ && (unsigned) CONST_DOUBLE_LOW (op) - 0xFFFFF000 < 0x1000))
+ || GET_CODE (op) == CONSTANT_P_RTX);
#endif
}
@@ -2685,350 +2697,6 @@ find_addr_reg (addr)
return addr;
abort ();
}
-
-#if 0 /* not currently used */
-
-void
-output_sized_memop (opname, mode, signedp)
- char *opname;
- enum machine_mode mode;
- int signedp;
-{
- static char *ld_size_suffix_u[] = { "ub", "uh", "", "?", "d" };
- static char *ld_size_suffix_s[] = { "sb", "sh", "", "?", "d" };
- static char *st_size_suffix[] = { "b", "h", "", "?", "d" };
- char **opnametab, *modename;
-
- if (opname[0] == 'l')
- if (signedp)
- opnametab = ld_size_suffix_s;
- else
- opnametab = ld_size_suffix_u;
- else
- opnametab = st_size_suffix;
- modename = opnametab[GET_MODE_SIZE (mode) >> 1];
-
- fprintf (asm_out_file, "\t%s%s", opname, modename);
-}
-
-void
-output_move_with_extension (operands)
- rtx *operands;
-{
- if (GET_MODE (operands[2]) == HImode)
- output_asm_insn ("sll %2,0x10,%0", operands);
- else if (GET_MODE (operands[2]) == QImode)
- output_asm_insn ("sll %2,0x18,%0", operands);
- else
- abort ();
-}
-#endif /* not currently used */
-
-#if 0
-/* ??? These are only used by the movstrsi pattern, but we get better code
- in general without that, because emit_block_move can do just as good a
- job as this function does when alignment and size are known. When they
- aren't known, a call to strcpy may be faster anyways, because it is
- likely to be carefully crafted assembly language code, and below we just
- do a byte-wise copy.
-
- Also, emit_block_move expands into multiple read/write RTL insns, which
- can then be optimized, whereas our movstrsi pattern can not be optimized
- at all. */
-
-/* Load the address specified by OPERANDS[3] into the register
- specified by OPERANDS[0].
-
- OPERANDS[3] may be the result of a sum, hence it could either be:
-
- (1) CONST
- (2) REG
- (2) REG + CONST_INT
- (3) REG + REG + CONST_INT
- (4) REG + REG (special case of 3).
-
- Note that (3) is not a legitimate address.
- All cases are handled here. */
-
-void
-output_load_address (operands)
- rtx *operands;
-{
- rtx base, offset;
-
- if (CONSTANT_P (operands[3]))
- {
- output_asm_insn ("set %3,%0", operands);
- return;
- }
-
- if (REG_P (operands[3]))
- {
- if (REGNO (operands[0]) != REGNO (operands[3]))
- output_asm_insn ("mov %3,%0", operands);
- return;
- }
-
- if (GET_CODE (operands[3]) != PLUS)
- abort ();
-
- base = XEXP (operands[3], 0);
- offset = XEXP (operands[3], 1);
-
- if (GET_CODE (base) == CONST_INT)
- {
- rtx tmp = base;
- base = offset;
- offset = tmp;
- }
-
- if (GET_CODE (offset) != CONST_INT)
- {
- /* Operand is (PLUS (REG) (REG)). */
- base = operands[3];
- offset = const0_rtx;
- }
-
- if (REG_P (base))
- {
- operands[6] = base;
- operands[7] = offset;
- if (SMALL_INT (offset))
- output_asm_insn ("add %6,%7,%0", operands);
- else
- output_asm_insn ("set %7,%0\n\tadd %0,%6,%0", operands);
- }
- else if (GET_CODE (base) == PLUS)
- {
- operands[6] = XEXP (base, 0);
- operands[7] = XEXP (base, 1);
- operands[8] = offset;
-
- if (SMALL_INT (offset))
- output_asm_insn ("add %6,%7,%0\n\tadd %0,%8,%0", operands);
- else
- output_asm_insn ("set %8,%0\n\tadd %0,%6,%0\n\tadd %0,%7,%0", operands);
- }
- else
- abort ();
-}
-
-/* Output code to place a size count SIZE in register REG.
- ALIGN is the size of the unit of transfer.
-
- Because block moves are pipelined, we don't include the
- first element in the transfer of SIZE to REG. */
-
-static void
-output_size_for_block_move (size, reg, align)
- rtx size, reg;
- rtx align;
-{
- rtx xoperands[3];
-
- xoperands[0] = reg;
- xoperands[1] = size;
- xoperands[2] = align;
- if (GET_CODE (size) == REG)
- output_asm_insn ("sub %1,%2,%0", xoperands);
- else
- {
- xoperands[1]
- = GEN_INT (INTVAL (size) - INTVAL (align));
- output_asm_insn ("set %1,%0", xoperands);
- }
-}
-
-/* Emit code to perform a block move.
-
- OPERANDS[0] is the destination.
- OPERANDS[1] is the source.
- OPERANDS[2] is the size.
- OPERANDS[3] is the alignment safe to use.
- OPERANDS[4] is a register we can safely clobber as a temp. */
-
-char *
-output_block_move (operands)
- rtx *operands;
-{
- /* A vector for our computed operands. Note that load_output_address
- makes use of (and can clobber) up to the 8th element of this vector. */
- rtx xoperands[10];
- rtx zoperands[10];
- static int movstrsi_label = 0;
- int i;
- rtx temp1 = operands[4];
- rtx sizertx = operands[2];
- rtx alignrtx = operands[3];
- int align = INTVAL (alignrtx);
- char label3[30], label5[30];
-
- xoperands[0] = operands[0];
- xoperands[1] = operands[1];
- xoperands[2] = temp1;
-
- /* We can't move more than this many bytes at a time because we have only
- one register, %g1, to move them through. */
- if (align > UNITS_PER_WORD)
- {
- align = UNITS_PER_WORD;
- alignrtx = GEN_INT (UNITS_PER_WORD);
- }
-
- /* We consider 8 ld/st pairs, for a total of 16 inline insns to be
- reasonable here. (Actually will emit a maximum of 18 inline insns for
- the case of size == 31 and align == 4). */
-
- if (GET_CODE (sizertx) == CONST_INT && (INTVAL (sizertx) / align) <= 8
- && memory_address_p (QImode, plus_constant_for_output (xoperands[0],
- INTVAL (sizertx)))
- && memory_address_p (QImode, plus_constant_for_output (xoperands[1],
- INTVAL (sizertx))))
- {
- int size = INTVAL (sizertx);
- int offset = 0;
-
- /* We will store different integers into this particular RTX. */
- xoperands[2] = rtx_alloc (CONST_INT);
- PUT_MODE (xoperands[2], VOIDmode);
-
- /* This case is currently not handled. Abort instead of generating
- bad code. */
- if (align > UNITS_PER_WORD)
- abort ();
-
- if (TARGET_ARCH64 && align >= 8)
- {
- for (i = (size >> 3) - 1; i >= 0; i--)
- {
- INTVAL (xoperands[2]) = (i << 3) + offset;
- output_asm_insn ("ldx [%a1+%2],%%g1\n\tstx %%g1,[%a0+%2]",
- xoperands);
- }
- offset += (size & ~0x7);
- size = size & 0x7;
- if (size == 0)
- return "";
- }
-
- if (align >= 4)
- {
- for (i = (size >> 2) - 1; i >= 0; i--)
- {
- INTVAL (xoperands[2]) = (i << 2) + offset;
- output_asm_insn ("ld [%a1+%2],%%g1\n\tst %%g1,[%a0+%2]",
- xoperands);
- }
- offset += (size & ~0x3);
- size = size & 0x3;
- if (size == 0)
- return "";
- }
-
- if (align >= 2)
- {
- for (i = (size >> 1) - 1; i >= 0; i--)
- {
- INTVAL (xoperands[2]) = (i << 1) + offset;
- output_asm_insn ("lduh [%a1+%2],%%g1\n\tsth %%g1,[%a0+%2]",
- xoperands);
- }
- offset += (size & ~0x1);
- size = size & 0x1;
- if (size == 0)
- return "";
- }
-
- if (align >= 1)
- {
- for (i = size - 1; i >= 0; i--)
- {
- INTVAL (xoperands[2]) = i + offset;
- output_asm_insn ("ldub [%a1+%2],%%g1\n\tstb %%g1,[%a0+%2]",
- xoperands);
- }
- return "";
- }
-
- /* We should never reach here. */
- abort ();
- }
-
- /* If the size isn't known to be a multiple of the alignment,
- we have to do it in smaller pieces. If we could determine that
- the size was a multiple of 2 (or whatever), we could be smarter
- about this. */
- if (GET_CODE (sizertx) != CONST_INT)
- align = 1;
- else
- {
- int size = INTVAL (sizertx);
- while (size % align)
- align >>= 1;
- }
-
- if (align != INTVAL (alignrtx))
- alignrtx = GEN_INT (align);
-
- xoperands[3] = GEN_INT (movstrsi_label++);
- xoperands[4] = GEN_INT (align);
- xoperands[5] = GEN_INT (movstrsi_label++);
-
- ASM_GENERATE_INTERNAL_LABEL (label3, "Lm", INTVAL (xoperands[3]));
- ASM_GENERATE_INTERNAL_LABEL (label5, "Lm", INTVAL (xoperands[5]));
-
- /* This is the size of the transfer. Emit code to decrement the size
- value by ALIGN, and store the result in the temp1 register. */
- output_size_for_block_move (sizertx, temp1, alignrtx);
-
- /* Must handle the case when the size is zero or negative, so the first thing
- we do is compare the size against zero, and only copy bytes if it is
- zero or greater. Note that we have already subtracted off the alignment
- once, so we must copy 1 alignment worth of bytes if the size is zero
- here.
-
- The SUN assembler complains about labels in branch delay slots, so we
- do this before outputting the load address, so that there will always
- be a harmless insn between the branch here and the next label emitted
- below. */
-
- {
- char pattern[100];
-
- sprintf (pattern, "cmp %%2,0\n\tbl %s", &label5[1]);
- output_asm_insn (pattern, xoperands);
- }
-
- zoperands[0] = operands[0];
- zoperands[3] = plus_constant_for_output (operands[0], align);
- output_load_address (zoperands);
-
- /* ??? This might be much faster if the loops below were preconditioned
- and unrolled.
-
- That is, at run time, copy enough bytes one at a time to ensure that the
- target and source addresses are aligned to the largest possible
- alignment. Then use a preconditioned unrolled loop to copy say 16
- bytes at a time. Then copy bytes one at a time until finish the rest. */
-
- /* Output the first label separately, so that it is spaced properly. */
-
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "Lm", INTVAL (xoperands[3]));
-
- {
- char pattern[200];
- register char *ld_suffix = ((align == 1) ? "ub" : (align == 2) ? "uh"
- : (align == 8 && TARGET_ARCH64) ? "x" : "");
- register char *st_suffix = ((align == 1) ? "b" : (align == 2) ? "h"
- : (align == 8 && TARGET_ARCH64) ? "x" : "");
-
- sprintf (pattern, "ld%s [%%1+%%2],%%%%g1\n\tsubcc %%2,%%4,%%2\n\tbge %s\n\tst%s %%%%g1,[%%0+%%2]\n%s:", ld_suffix, &label3[1], st_suffix, &label5[1]);
- output_asm_insn (pattern, xoperands);
- }
-
- return "";
-}
-#endif
/* Output reasonable peephole for set-on-condition-code insns.
Note that these insns assume a particular way of defining
@@ -6798,30 +6466,3 @@ sparc_return_peephole_ok (dest, src)
return 0;
return IN_OR_GLOBAL_P (dest);
}
-
-int
-delay_operand (op, mode)
- rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- switch (GET_CODE (op))
- {
- case CONST:
- case CONST_INT:
- case SYMBOL_REF:
- case LABEL_REF:
- return 1;
-
- case MEM:
- return delay_operand (XEXP (op, 0), Pmode);
-
- case REG:
- return IN_OR_GLOBAL_P (op);
-
- case PLUS:
- return delay_operand (XEXP (op, 0), Pmode) && delay_operand (XEXP (op, 1), Pmode);
-
- default:
- return 0;
- }
-}
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index 77bae75..1e0c644 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -3186,6 +3186,49 @@ do { \
} \
}
+/* Define the codes that are matched by predicates in sparc.c. */
+
+#define PREDICATE_CODES \
+{"reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
+{"fp_zero_operand", {CONST_DOUBLE}}, \
+{"intreg_operand", {SUBREG, REG}}, \
+{"fcc_reg_operand", {REG}}, \
+{"icc_or_fcc_reg_operand", {REG}}, \
+{"restore_operand", {REG}}, \
+{"call_operand", {MEM}}, \
+{"call_operand_address", {SYMBOL_REF, LABEL_REF, CONST, CONST_DOUBLE, ADDRESSOF, \
+ SUBREG, REG, PLUS, LO_SUM, CONST_INT}}, \
+{"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST, CONST_DOUBLE}}, \
+{"symbolic_memory_operand", {SUBREG, MEM}}, \
+{"label_ref_operand", {LABEL_REF}}, \
+{"sp64_medium_pic_operand", {CONST}}, \
+{"data_segment_operand", {SYMBOL_REF, PLUS, CONST}}, \
+{"text_segment_operand", {LABEL_REF, SYMBOL_REF, PLUS, CONST}}, \
+{"reg_or_nonsymb_mem_operand", {SUBREG, REG, MEM}}, \
+{"sparc_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, MEM}}, \
+{"move_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, CONST_DOUBLE, MEM}}, \
+{"splittable_symbolic_memory_operand", {MEM}}, \
+{"splittable_immediate_memory_operand", {MEM}}, \
+{"eq_or_neq", {EQ, NE}}, \
+{"normal_comp_operator", {GE, GT, LE, LT, GTU, LEU}}, \
+{"noov_compare_op", {NE, EQ, GE, GT, LE, LT, GEU, GTU, LEU, LTU}}, \
+{"v9_regcmp_op", {EQ, NE, GE, LT, LE, GT}}, \
+{"v8plus_regcmp_op", {EQ, NE}}, \
+{"extend_op", {SIGN_EXTEND, ZERO_EXTEND}}, \
+{"cc_arithop", {AND, IOR, XOR}}, \
+{"cc_arithopn", {AND, IOR}}, \
+{"arith_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT}}, \
+{"arith11_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT}}, \
+{"arith10_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT}}, \
+{"arith_double_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, CONST_DOUBLE}}, \
+{"arith11_double_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, CONST_DOUBLE}}, \
+{"arith10_double_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, CONST_DOUBLE}}, \
+{"small_int", {CONST_INT, CONSTANT_P_RTX}}, \
+{"uns_small_int", {CONST_INT, CONSTANT_P_RTX}}, \
+{"uns_arith_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
+{"clobbered_register", {REG}},
+
+
/* The number of Pmode words for the setjmp buffer. */
#define JMP_BUF_SIZE 12
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index ff77c99..ca8de61 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -2314,55 +2314,6 @@
;; ??? There's no symbolic (set (mem:DI ...) ...).
;; Experimentation with v9 suggested one isn't needed.
-;; Block move insns.
-
-;; ??? We get better code without it. See output_block_move in sparc.c.
-
-;; The definition of this insn does not really explain what it does,
-;; but it should suffice
-;; that anything generated as this insn will be recognized as one
-;; and that it will not successfully combine with anything.
-;(define_expand "movstrsi"
-; [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
-; (mem:BLK (match_operand:BLK 1 "general_operand" "")))
-; (use (match_operand:SI 2 "nonmemory_operand" ""))
-; (use (match_operand:SI 3 "immediate_operand" ""))
-; (clobber (match_dup 0))
-; (clobber (match_dup 1))
-; (clobber (match_scratch:SI 4 ""))
-; (clobber (reg:SI 100))
-; (clobber (reg:SI 1))])]
-; ""
-; "
-;{
-; /* If the size isn't known, don't emit inline code. output_block_move
-; would output code that's much slower than the library function.
-; Also don't output code for large blocks. */
-; if (GET_CODE (operands[2]) != CONST_INT
-; || GET_CODE (operands[3]) != CONST_INT
-; || INTVAL (operands[2]) / INTVAL (operands[3]) > 16)
-; FAIL;
-;
-; operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
-; operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
-; operands[2] = force_not_mem (operands[2]);
-;}")
-
-;(define_insn "*block_move_insn"
-; [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r"))
-; (mem:BLK (match_operand:SI 1 "register_operand" "+r")))
-; (use (match_operand:SI 2 "nonmemory_operand" "rn"))
-; (use (match_operand:SI 3 "immediate_operand" "i"))
-; (clobber (match_dup 0))
-; (clobber (match_dup 1))
-; (clobber (match_scratch:SI 4 "=&r"))
-; (clobber (reg:SI 100))
-; (clobber (reg:SI 1))]
-; ""
-; "* return output_block_move (operands);"
-; [(set_attr "type" "multi")
-; (set_attr "length" "6")])
-
;; Floating point move insns
;; This pattern forces (set (reg:SF ...) (const_double ...))
diff --git a/gcc/config/sparc/sun4o3.h b/gcc/config/sparc/sun4o3.h
index 5fcb72f..10c7391 100644
--- a/gcc/config/sparc/sun4o3.h
+++ b/gcc/config/sparc/sun4o3.h
@@ -5,6 +5,25 @@
fprintf (FILE, "\tsethi %%hi(LP%d),%%o0\n\tcall .mcount\n\tor %%lo(LP%d),%%o0,%%o0\n", \
(LABELNO), (LABELNO))
-/* LINK_SPEC is needed only for Sunos 4. */
+/* LINK_SPEC is needed only for SunOS 4. */
#undef LINK_SPEC
+
+/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special
+ traps available which can get and set the condition codes
+ reliably. */
+#undef MACHINE_STATE_SAVE
+#define MACHINE_STATE_SAVE(ID) \
+ unsigned long int ms_flags, ms_saveret; \
+ asm volatile("ta 0x20\n\t" \
+ "mov %%g1, %0\n\t" \
+ "mov %%g2, %1\n\t" \
+ : "=r" (ms_flags), "=r" (ms_saveret));
+
+#undef MACHINE_STATE_RESTORE
+#define MACHINE_STATE_RESTORE(ID) \
+ asm volatile("mov %0, %%g1\n\t" \
+ "mov %1, %%g2\n\t" \
+ "ta 0x21\n\t" \
+ : /* no outputs */ \
+ : "r" (ms_flags), "r" (ms_saveret));
diff --git a/gcc/config/sparc/sunos4.h b/gcc/config/sparc/sunos4.h
index 070f41a..14c7a43 100644
--- a/gcc/config/sparc/sunos4.h
+++ b/gcc/config/sparc/sunos4.h
@@ -28,3 +28,22 @@ Boston, MA 02111-1307, USA. */
/* The Sun as doesn't like unaligned data. */
#define DWARF2_UNWIND_INFO 0
+
+/* Override MACHINE_STATE_{SAVE,RESTORE} because we have special
+ traps available which can get and set the condition codes
+ reliably. */
+#undef MACHINE_STATE_SAVE
+#define MACHINE_STATE_SAVE(ID) \
+ unsigned long int ms_flags, ms_saveret; \
+ asm volatile("ta 0x20\n\t" \
+ "mov %%g1, %0\n\t" \
+ "mov %%g2, %1\n\t" \
+ : "=r" (ms_flags), "=r" (ms_saveret));
+
+#undef MACHINE_STATE_RESTORE
+#define MACHINE_STATE_RESTORE(ID) \
+ asm volatile("mov %0, %%g1\n\t" \
+ "mov %1, %%g2\n\t" \
+ "ta 0x21\n\t" \
+ : /* no outputs */ \
+ : "r" (ms_flags), "r" (ms_saveret));