From fba942c46dad90bc02695e422b89c4145b59419e Mon Sep 17 00:00:00 2001 From: Richard Kenner Date: Tue, 13 Oct 1992 19:07:05 -0400 Subject: [PATCH] Now includes reload.h. (spec_reg_operand): Validate mode and know that some regs support MODE_PARTIAL_INT and some MODE_INT. (call_operand, reload_memory_operand, a29k_get_reloaded_address) New functions. (in_operand): Allow constants with MODE_PARTIAL_INT. (out_operand): Allow special registers with any mode. Any MEM a word or wider is valid. (extend_operator): Deleted. (secondary_reload_class): A pseudo is the same as memory; we need BP_REGS for multi-word memory or for bytes and halfword if -mndw. (print_operand): Delete %X; add %m. (print_operand, case 'F'): Check for SYMBOL_REF. From-SVN: r2443 --- gcc/config/a29k/a29k.c | 127 +++++++++++++++++++++++++++++++++-------- 1 file changed, 102 insertions(+), 25 deletions(-) diff --git a/gcc/config/a29k/a29k.c b/gcc/config/a29k/a29k.c index 8f73f4f9529..ad1a62035ec 100644 --- a/gcc/config/a29k/a29k.c +++ b/gcc/config/a29k/a29k.c @@ -1,5 +1,5 @@ /* Subroutines used for code generation on AMD Am29000. - Copyright (C) 1987, 1988, 1990, 1991 Free Software Foundation, Inc. + Copyright (C) 1987, 1988, 1990, 1991, 1992 Free Software Foundation, Inc. Contributed by Richard Kenner (kenner@nyu.edu) This file is part of GNU CC. @@ -34,6 +34,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "expr.h" #include "obstack.h" #include "tree.h" +#include "reload.h" #define min(A,B) ((A) < (B) ? (A) : (B)) @@ -99,7 +100,7 @@ cint_16_operand (op, mode) return GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff0000) == 0; } -/* Returns 1 if OP cannot be moved in a single insn. */ +/* Returns 1 if OP is a constant that cannot be moved in a single insn. */ int long_const_operand (op, mode) @@ -210,8 +211,18 @@ spec_reg_operand (op, mode) rtx op; enum machine_mode mode; { - return GET_MODE (op) == SImode && GET_CODE (op) == REG - && REGNO (op) >= R_BP && REGNO (op) <= R_EXO; + if (GET_CODE (op) != REG || GET_MODE (op) != mode) + return 0; + + switch (GET_MODE_CLASS (mode)) + { + case MODE_PARTIAL_INT: + return REGNO (op) >= R_BP && REGNO (op) <= R_CR; + case MODE_INT: + return REGNO (op) >= R_Q && REGNO (op) <= R_EXO; + detault: + return 0; + } } /* Returns 1 if OP is an accumulator register. */ @@ -307,6 +318,29 @@ add_operand (op, mode) || (GET_CODE (op) == CONST_INT && ((unsigned) ((- INTVAL (op)) & GET_MODE_MASK (mode)) < 256))); } + +/* Return 1 if OP is a valid address in a CALL_INSN. These are a SYMBOL_REF + to the current function, all SYMBOL_REFs if TARGET_SMALL_MEMORY, or + a sufficiently-small constant. */ + +int +call_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + switch (GET_CODE (op)) + { + case SYMBOL_REF: + return (TARGET_SMALL_MEMORY + || ! strcmp (XSTR (op, 0), current_function_name)); + + case CONST_INT: + return (unsigned HOST_WIDE_INT) INTVAL (op) < 0x40000; + + default: + return 0; + } +} /* Return 1 if OP can be used as the input operand for a move insn. */ @@ -332,7 +366,8 @@ in_operand (op, mode) return (GET_MODE_SIZE (mode) >= UNITS_PER_WORD || TARGET_DW_ENABLE); case CONST_INT: - if (GET_MODE_CLASS (mode) != MODE_INT) + if (GET_MODE_CLASS (mode) != MODE_INT + && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) return 0; return 1; @@ -370,26 +405,51 @@ out_operand (op, mode) op = SUBREG_REG (op); if (GET_CODE (op) == REG) - return (mode == SImode || gpc_reg_operand (orig_op, mode) + return (gpc_reg_operand (orig_op, mode) + || spec_reg_operand (orig_op, mode) || (GET_MODE_CLASS (mode) == MODE_FLOAT && accum_reg_operand (orig_op, mode))); else if (GET_CODE (op) == MEM) - return mode == SImode || mode == SFmode || TARGET_DW_ENABLE; - + return (GET_MODE_SIZE (mode) >= UNITS_PER_WORD || TARGET_DW_ENABLE); else return 0; } -/* Return 1 if OP is some extension operator. */ +/* Return 1 if OP is an item in memory, given that we are in reload. */ int -extend_operator (op, mode) +reload_memory_operand (op, mode) rtx op; enum machine_mode mode; { - return ((mode == VOIDmode || GET_MODE (op) == mode) - && (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)); + int regno = true_regnum (op); + + return (! CONSTANT_P (op) + && (regno == -1 + || (GET_CODE (op) == REG + && REGNO (op) >= FIRST_PSEUDO_REGISTER))); +} + +/* Given an object for which reload_memory_operand is true, return the address + of the operand, taking into account anything that reload may do. */ + +rtx +a29k_get_reloaded_address (op) + rtx op; +{ + if (GET_CODE (op) == SUBREG) + { + if (SUBREG_WORD (op) != 0) + abort (); + + op = SUBREG_REG (op); + } + + if (GET_CODE (op) == REG) + op = reg_equiv_mem[REGNO (op)]; + + return find_replacement (&XEXP (op, 0)); } /* Return 1 if OP is a comparison operator that we have in floating-point. */ @@ -591,19 +651,34 @@ secondary_reload_class (class, mode, in) rtx in; { int regno = -1; + enum rtx_code code = GET_CODE (in); + + if (! CONSTANT_P (in)) + { + regno = true_regnum (in); - if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG) - regno = true_regnum (in); + /* A pseudo is the same as memory. */ + if (regno == -1 || regno >= FIRST_PSEUDO_REGISTER) + code = MEM; + } + + /* If we are transferring between memory and a multi-word mode or between + memory and a mode smaller than a word without DW being enabled, we need + BP. */ + + if (code == MEM + && (GET_MODE_SIZE (mode) > UNITS_PER_WORD + || (! TARGET_DW_ENABLE && GET_MODE_SIZE (mode) < UNITS_PER_WORD))) + return BP_REGS; - /* We can place anything into GENERAL_REGS and can put GENERAL_REGS - into anything. */ + /* Otherwise, we can place anything into GENERAL_REGS and can put + GENERAL_REGS into anything. */ if (class == GENERAL_REGS || (regno != -1 && regno < R_BP)) return NO_REGS; /* We can place 16-bit constants into a special register. */ - if (GET_CODE (in) == CONST_INT - && (GET_MODE_BITSIZE (mode) <= 16 - || (unsigned) INTVAL (in) <= 65535) + if (code == CONST_INT + && (GET_MODE_BITSIZE (mode) <= 16 || (unsigned) INTVAL (in) <= 65535) && (class == BP_REGS || class == Q_REGS || class == SPECIAL_REGS)) return NO_REGS; @@ -739,8 +814,8 @@ null_epilogue () %N means write the low-order 8 bits of the negative of the constant %Q means write a QImode operand (truncate constants to 8 bits) %M means write the low-order 16 bits of the constant + %m means write the low-order 16 bits shifted left 16 bits %C means write the low-order 8 bits of the complement of the constant - %X means write the cntl values for LOAD with operand an extension op %b means write `f' is this is a reversed condition, `t' otherwise %B means write `t' is this is a reversed condition, `f' otherwise %J means write the 29k opcode part for a comparison operation @@ -807,11 +882,12 @@ print_operand (file, x, code) fprintf (file, "%d", INT_LOWPART (x) & 0xffff); return; - case 'X': - fprintf (file, "%d", ((GET_MODE (XEXP (x, 0)) == QImode ? 1 : 2) - + (GET_CODE (x) == SIGN_EXTEND ? 16 : 0))); + case 'm': + if (! INT_P (x)) + output_operand_lossage ("invalid %%m value"); + fprintf (file, "%d", (INT_LOWPART (x) & 0xffff) << 16); return; - + case 'b': if (GET_CODE (x) == GE) fprintf (file, "f"); @@ -878,7 +954,8 @@ print_operand (file, x, code) output_addr_const (file, x); if (dbr_sequence_length () == 0) { - if (! strcmp (XSTR (x, 0), current_function_name)) + 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", a29k_regstack_size * 4); -- 2.30.2