From f7e0e539c53fa846aa01be0aae76f165507e8187 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 3 Jul 1998 03:19:41 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 21 +++ gcc/config/sparc/linux-aout.h | 19 ++ gcc/config/sparc/linux.h | 19 ++ gcc/config/sparc/linux64.h | 19 ++ gcc/config/sparc/sol2.h | 19 ++ gcc/config/sparc/sparc.c | 405 +++--------------------------------------- gcc/config/sparc/sparc.h | 43 +++++ gcc/config/sparc/sparc.md | 49 ----- gcc/config/sparc/sun4o3.h | 21 ++- gcc/config/sparc/sunos4.h | 19 ++ 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 + + * 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 * 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)); -- 2.7.4