--- gcc/config/sparc/sparc.c 2018/04/24 18:21:33 1.1.1.3 +++ gcc/config/sparc/sparc.c 2018/04/24 18:28:58 1.1.1.4 @@ -1,5 +1,5 @@ /* Subroutines for insn-output.c for Sun SPARC. - Copyright (C) 1987, 88, 89, 92, 93, 1994 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) 64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans, at Cygnus Support. @@ -18,7 +18,8 @@ GNU General Public License for more deta You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ #include #include "config.h" @@ -187,6 +188,21 @@ sparc64_fpconv_stack_temp () return fpconv_stack_temp; } +/* Miscellaneous utilities. */ + +/* Nonzero if CODE, a comparison, is suitable for use in v9 conditional move + or branch on register contents instructions. */ + +int +v9_regcmp_p (code) + enum rtx_code code; +{ + return (code == EQ || code == NE || code == GE || code == LT + || code == LE || code == GT); +} + +/* Operand constraints. */ + /* Return non-zero only if OP is a register of mode MODE, or const0_rtx. */ int @@ -453,13 +469,27 @@ move_pic_label (op, mode) } int -memop (op, mode) +splittable_symbolic_memory_operand (op, mode) rtx op; enum machine_mode mode; { - if (GET_CODE (op) == MEM) - return (mode == VOIDmode || mode == GET_MODE (op)); - return 0; + if (GET_CODE (op) != MEM) + return 0; + if (! symbolic_operand (XEXP (op, 0), Pmode)) + return 0; + return 1; +} + +int +splittable_immediate_memory_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) != MEM) + return 0; + if (! immediate_operand (XEXP (op, 0), Pmode)) + return 0; + return 1; } /* Return truth value of whether OP is EQ or NE. */ @@ -524,8 +554,7 @@ v9_regcmp_op (op, mode) if (GET_RTX_CLASS (code) != '<') return 0; - return (code == EQ || code == NE || code == GE || code == LT - || code == LE || code == GT); + return v9_regcmp_p (code); } /* Return 1 if this is a SIGN_EXTEND or ZERO_EXTEND operation. */ @@ -752,7 +781,7 @@ gen_compare_reg (code, x, y) we need the movcc patterns). It is possible to provide the movcc patterns by using the ldxfsr/stxfsr v9 insns. I tried it: you need two registers (say %g1,%g5) and it takes about 6 insns. A better fix would be - to tell cse that CCFPE mode registers (even pseudoes) are call + to tell cse that CCFPE mode registers (even pseudos) are call clobbered. */ /* ??? This is an experiment. Rather than making changes to cse which may @@ -1924,7 +1953,7 @@ output_move_quad (operands) abort (); } - /* Normal case: move the four words in lowest to higest address order. */ + /* Normal case: move the four words in lowest to highest address order. */ output_asm_insn (singlemove_string (wordpart[0]), wordpart[0]); @@ -3517,8 +3546,8 @@ order_regs_for_local_alloc () if (regs_ever_live[15] != last_order_nonleaf) { last_order_nonleaf = !last_order_nonleaf; - bcopy (reg_alloc_orders[last_order_nonleaf], reg_alloc_order, - FIRST_PSEUDO_REGISTER * sizeof (int)); + bcopy ((char *) reg_alloc_orders[last_order_nonleaf], + (char *) reg_alloc_order, FIRST_PSEUDO_REGISTER * sizeof (int)); } } @@ -3779,6 +3808,13 @@ print_operand (file, x, code) return; } + case 'f': + /* Operand must be a MEM; write its address. */ + if (GET_CODE (x) != MEM) + output_operand_lossage ("Invalid %%f operand"); + output_address (XEXP (x, 0)); + return; + case 0: /* Do nothing special. */ break; @@ -3923,7 +3959,7 @@ sparc_type_code (type) register unsigned long qualifiers = 0; register unsigned shift = 6; - /* Only the first 30 bits of the qualifer are valid. We must refrain from + /* Only the first 30 bits of the qualifier are valid. We must refrain from setting more, since some assemblers will give an error for this. Also, we must be careful to avoid shifts of 32 bits or more to avoid getting unpredictable results. */ @@ -4044,10 +4080,7 @@ sparc_type_code (type) (to store insns). This is a bit excessive. Perhaps a different mechanism would be better here. - Emit 3 FLUSH instructions (UNSPEC_VOLATILE 3) to synchonize the data - and instruction caches. - - ??? v9: We assume the top 32 bits of function addresses are 0. */ + Emit enough FLUSH insns to synchronize the data and instruction caches. */ void sparc_initialize_trampoline (tramp, fnaddr, cxt) @@ -4080,63 +4113,32 @@ sparc_initialize_trampoline (tramp, fnad emit_move_insn (tem, g2_ori); emit_insn (gen_iorsi3 (low_cxt, low_cxt, tem)); emit_move_insn (gen_rtx (MEM, SImode, plus_constant (tramp, 16)), low_cxt); - emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, - gen_rtvec (1, plus_constant (tramp, 0)), - 3)); - emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, - gen_rtvec (1, plus_constant (tramp, 8)), - 3)); - emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, - gen_rtvec (1, plus_constant (tramp, 16)), - 3)); + emit_insn (gen_flush (validize_mem (gen_rtx (MEM, SImode, tramp)))); + emit_insn (gen_flush (validize_mem (gen_rtx (MEM, SImode, + plus_constant (tramp, 8))))); + emit_insn (gen_flush (validize_mem (gen_rtx (MEM, SImode, + plus_constant (tramp, 16))))); } +/* The 64 bit version is simpler because it makes more sense to load the + values as "immediate" data out of the trampoline. It's also easier since + we can read the PC without clobbering a register. */ + void sparc64_initialize_trampoline (tramp, fnaddr, cxt) rtx tramp, fnaddr, cxt; { - rtx fnaddrdi = gen_reg_rtx (Pmode); - rtx fnaddrsi = (emit_move_insn (fnaddrdi, fnaddr), - gen_rtx (SUBREG, SImode, fnaddrdi, 0)); - rtx cxtdi = gen_reg_rtx (Pmode); - rtx cxtsi = (emit_move_insn (cxtdi, cxt), - gen_rtx (SUBREG, SImode, cxtdi, 0)); - rtx high_cxt = expand_shift (RSHIFT_EXPR, SImode, cxtsi, - size_int (10), 0, 1); - rtx high_fn = expand_shift (RSHIFT_EXPR, SImode, fnaddrsi, - size_int (10), 0, 1); - rtx low_cxt = expand_and (cxtsi, gen_rtx (CONST_INT, VOIDmode, 0x3ff), 0); - rtx low_fn = expand_and (fnaddrsi, gen_rtx (CONST_INT, VOIDmode, 0x3ff), 0); - rtx g1_sethi = gen_rtx (HIGH, SImode, - gen_rtx (CONST_INT, VOIDmode, 0x03000000)); - rtx g2_sethi = gen_rtx (HIGH, SImode, - gen_rtx (CONST_INT, VOIDmode, 0x05000000)); - rtx g1_ori = gen_rtx (HIGH, SImode, - gen_rtx (CONST_INT, VOIDmode, 0x82106000)); - rtx g2_ori = gen_rtx (HIGH, SImode, - gen_rtx (CONST_INT, VOIDmode, 0x8410A000)); - rtx tem = gen_reg_rtx (SImode); - emit_move_insn (tem, g2_sethi); - emit_insn (gen_iorsi3 (high_fn, high_fn, tem)); - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (tramp, 0)), high_fn); - emit_move_insn (tem, g2_ori); - emit_insn (gen_iorsi3 (low_fn, low_fn, tem)); - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (tramp, 4)), low_fn); - emit_move_insn (tem, g1_sethi); - emit_insn (gen_iorsi3 (high_cxt, high_cxt, tem)); - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (tramp, 8)), high_cxt); - emit_move_insn (tem, g1_ori); - emit_insn (gen_iorsi3 (low_cxt, low_cxt, tem)); - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (tramp, 16)), low_cxt); - emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, - gen_rtvec (1, plus_constant (tramp, 0)), - 3)); - emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, - gen_rtvec (1, plus_constant (tramp, 8)), - 3)); - emit_insn (gen_rtx (UNSPEC_VOLATILE, VOIDmode, - gen_rtvec (1, plus_constant (tramp, 16)), - 3)); + emit_move_insn (gen_rtx (MEM, DImode, plus_constant (tramp, 24)), cxt); + emit_move_insn (gen_rtx (MEM, DImode, plus_constant (tramp, 32)), fnaddr); + emit_insn (gen_flush (validize_mem (gen_rtx (MEM, DImode, tramp)))); + emit_insn (gen_flush (validize_mem (gen_rtx (MEM, DImode, + plus_constant (tramp, 8))))); + emit_insn (gen_flush (validize_mem (gen_rtx (MEM, DImode, + plus_constant (tramp, 16))))); + emit_insn (gen_flush (validize_mem (gen_rtx (MEM, DImode, + plus_constant (tramp, 24))))); + emit_insn (gen_flush (validize_mem (gen_rtx (MEM, DImode, + plus_constant (tramp, 32))))); } /* Subroutines to support a flat (single) register window calling @@ -4487,7 +4489,7 @@ sparc_flat_output_function_prologue (fil Don't change the order of insns emitted here without checking with the gdb folk first. */ - /* Is the entire register save area offsetable from %sp? */ + /* Is the entire register save area offsettable from %sp? */ if (reg_offset < 4096 - 64 * UNITS_PER_WORD) { if (size <= 4096) @@ -4637,7 +4639,7 @@ sparc_flat_output_function_epilogue (fil fp_str, size, sp_str); } - /* Is the entire register save area offsetable from %sp? */ + /* Is the entire register save area offsettable from %sp? */ if (reg_offset < 4096 - 64 * UNITS_PER_WORD) { size1 = 0;