--- gcc/config/a29k/a29k.c 2018/04/24 18:10:25 1.1.1.1 +++ gcc/config/a29k/a29k.c 2018/04/24 18:29:19 1.1.1.4 @@ -1,5 +1,5 @@ /* Subroutines used for code generation on AMD Am29000. - Copyright (C) 1987, 1988, 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 90-94, 1995 Free Software Foundation, Inc. Contributed by Richard Kenner (kenner@nyu.edu) This file is part of GNU CC. @@ -16,7 +16,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" @@ -220,7 +221,7 @@ spec_reg_operand (op, mode) return REGNO (op) >= R_BP && REGNO (op) <= R_CR; case MODE_INT: return REGNO (op) >= R_Q && REGNO (op) <= R_EXO; - detault: + default: return 0; } } @@ -233,7 +234,7 @@ accum_reg_operand (op, mode) enum machine_mode mode; { return (GET_CODE (op) == REG - && REGNO (op) >= R_ACC (0) && REGNO (op) <= R_ACC (3)); + && REGNO (op) >= R_ACU (0) && REGNO (op) <= R_ACU (3)); } /* Returns 1 if OP is a normal data register. */ @@ -259,7 +260,8 @@ gpc_reg_operand (op, mode) else return 0; - return regno >= FIRST_PSEUDO_REGISTER || regno < R_BP; + return (regno >= FIRST_PSEUDO_REGISTER || regno < R_BP + || (regno >= R_KR (0) && regno <= R_KR (31))); } /* Returns 1 if OP is either an 8-bit constant integer or a general register. @@ -281,6 +283,22 @@ srcb_operand (op, mode) return gpc_reg_operand (op, mode); } +int +cmplsrcb_operand (op, mode) + register rtx op; + enum machine_mode mode; +{ + if (GET_CODE (op) == CONST_INT + && (mode == QImode + || (INTVAL (op) & 0xffffff00) == 0xffffff00)) + return 1; + + if (GET_MODE (op) != mode && mode != VOIDmode) + return 0; + + return gpc_reg_operand (op, mode); +} + /* Return 1 if OP is either an immediate or a general register. This is used for the input operand of mtsr/mtrsim. */ @@ -332,7 +350,9 @@ call_operand (op, mode) { case SYMBOL_REF: return (TARGET_SMALL_MEMORY - || ! strcmp (XSTR (op, 0), current_function_name)); + || (! TARGET_LARGE_MEMORY + && ((GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_FLAG (op)) + || ! strcmp (XSTR (op, 0), current_function_name)))); case CONST_INT: return (unsigned HOST_WIDE_INT) INTVAL (op) < 0x40000; @@ -739,7 +759,10 @@ secondary_reload_class (class, mode, in) /* Otherwise, we can place anything into GENERAL_REGS and can put GENERAL_REGS into anything. */ - if (class == GENERAL_REGS || (regno != -1 && regno < R_BP)) + if (class == GENERAL_REGS + || (regno != -1 + && (regno < R_BP + || (regno >= R_KR (0) && regno <= R_KR (31))))) return NO_REGS; /* We can place 16-bit constants into a special register. */ @@ -769,9 +792,14 @@ incoming_reg (start, count) { int i; + /* We only use 16 argument registers, so truncate at the end of the + area. */ + if (start + count > 16) + count = 16 - start; + if (! TARGET_NO_REUSE_ARGS) /* Mark all the used registers as not fixed and saved over calls. */ - for (i = R_AR (start); i < R_AR (16) && i < R_AR (start + count); i++) + for (i = R_AR (start); i < R_AR (start + count); i++) { fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 0; CLEAR_HARD_REG_BIT (fixed_reg_set, i); @@ -779,8 +807,13 @@ incoming_reg (start, count) CLEAR_HARD_REG_BIT (call_fixed_reg_set, i); } - /* Shorten the maximum size of the frame. */ - for (i = R_AR (0) - start - count; i < R_AR (0) - start; i++) + /* Shorten the maximum size of the frame. + Remember that R_AR(-1,-2) are place holders for the caller's lr0,lr1. + Make sure to keep the frame rounded to an even boundary. Rounding up + to an 8 byte boundary will use a slot. Otherwise a frame with 121 local + regs and 5 arguments will overrun the stack (121+1 + 5 + 2 > 128). */ + /* ??? An alternative would be to never allocate one reg. */ + for (i = (R_AR (0) - 2 - start - count) & ~1; i < R_AR (0) - 2 - start; i++) { fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 1; SET_HARD_REG_BIT (fixed_reg_set, i); @@ -791,6 +824,33 @@ incoming_reg (start, count) return R_AR (start); } +/* Add CLOBBERs to CALL_INSN_FUNCTION_USAGE chain of INSN indicating + that LR2 up to, but not including, OP are clobbered. If OP is + zero, indicate all parameter registers are clobbered. */ + +void +a29k_clobbers_to (insn, op) + rtx insn; + rtx op; +{ + int i; + int high_regno; + + if (op == 0) + high_regno = R_LR (18); + else if (GET_CODE (op) != REG || REGNO (op) < R_LR (0) + || REGNO (op) > R_LR (18)) + abort (); + else + high_regno = REGNO (op); + + for (i = R_LR (2); i < high_regno; i++) + CALL_INSN_FUNCTION_USAGE (insn) + = gen_rtx (EXPR_LIST, VOIDmode, + gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, i)), + CALL_INSN_FUNCTION_USAGE (insn)); +} + /* These routines are used in finding insns to fill delay slots in the epilogue. */ @@ -1020,7 +1080,16 @@ print_operand (file, x, code) output_addr_const (file, x); if (dbr_sequence_length () == 0) { - if (GET_CODE (x) == SYMBOL_REF + /* If this doesn't have its delay slot filled, see if we need to + put the last insn of the prolog in it. If not, see if this is + a recursive call. If so, we can put the first insn of its + prolog in the delay slot. Otherwise, write a nop. */ + if (a29k_last_prologue_insn) + { + fprintf (file, "\n\t%s", a29k_last_prologue_insn); + a29k_last_prologue_insn = 0; + } + else if (GET_CODE (x) == SYMBOL_REF && ! strcmp (XSTR (x, 0), current_function_name)) fprintf (file, "+4\n\t%s,%d", a29k_regstack_size >= 64 ? "const gr121" : "sub gr1,gr1", @@ -1035,7 +1104,7 @@ print_operand (file, x, code) { union real_extract u; - bcopy (&CONST_DOUBLE_LOW (x), &u, sizeof u); + bcopy ((char *) &CONST_DOUBLE_LOW (x), (char *) &u, sizeof u); fprintf (file, "$double1(%.20e)", u.d); } else if (GET_CODE (x) == REG) @@ -1099,7 +1168,8 @@ print_operand (file, x, code) fprintf (file, "$float"); else fprintf (file, "$double%d", SUBREG_WORD (XEXP (x, 0))); - bcopy (&CONST_DOUBLE_LOW (SUBREG_REG (XEXP (x, 0))), &u, sizeof u); + bcopy ((char *) &CONST_DOUBLE_LOW (SUBREG_REG (XEXP (x, 0))), + (char *) &u, sizeof u); fprintf (file, "(%.20e)", u.d); } @@ -1108,7 +1178,7 @@ print_operand (file, x, code) { union real_extract u; - bcopy (&CONST_DOUBLE_LOW (x), &u, sizeof u); + bcopy ((char *) &CONST_DOUBLE_LOW (x), (char *) &u, sizeof u); fprintf (file, "$%s(%.20e)", GET_MODE (x) == SFmode ? "float" : "double0", u.d); } @@ -1184,6 +1254,16 @@ output_prolog (file, size) a29k_debug_reg_map[R_AR (i)] = R_LR (a29k_regstack_size + i + 2); } + /* If using kernel register map, swap numbers for kernel and user + registers. */ + if (TARGET_KERNEL_REGISTERS) + for (i = 0; i < 32; i++) + { + int tem = a29k_debug_reg_map[i]; + a29k_debug_reg_map[i] = a29k_debug_reg_map[R_KR (i)]; + a29k_debug_reg_map[R_KR (i)] = tem; + } + /* Compute memory stack size. Add in number of bytes that the we should push and pretend the caller did and the size of outgoing arguments. Then round to a doubleword boundary. */