Commit e95cfa3b by Paul Woegerer

crx.c: Implemented crx_decompose_address (like in the i386 port) so that...

	* config/crx/crx.c: Implemented crx_decompose_address (like in the
	  i386 port) so that crx_legitimate_address_p, crx_address_cost
	  and crx_print_operand_address are using the same code for adress
	  handling. Using symbolic displacements now gets rejected since
	  the CRX register relative adressing mode can't handle unsigned
	  32-bit values as displacements.
	* config/crx/crx.h: Simplified definitions for REG_OK_FOR_BASE_P,
	  removed redundant parenthesis and obsolete macros.
	* config/crx/crx.opt: Added a new switch for debugging of address
	  handling.
	* config/crx/crx-protos.h: Added new declarations for above.

From-SVN: r103269
parent 1581a9a1
...@@ -42,6 +42,18 @@ extern rtx crx_function_arg (struct cumulative_args *, enum machine_mode, tree, ...@@ -42,6 +42,18 @@ extern rtx crx_function_arg (struct cumulative_args *, enum machine_mode, tree,
#ifdef RTX_CODE #ifdef RTX_CODE
/* Addressing Modes. */ /* Addressing Modes. */
struct crx_address
{
rtx base, index, disp, side_effect;
int scale;
};
enum crx_addrtype
{
CRX_INVALID, CRX_REG_REL, CRX_POST_INC, CRX_SCALED_INDX, CRX_ABSOLUTE
};
extern enum crx_addrtype crx_decompose_address (rtx addr, struct crx_address *out);
extern int crx_legitimate_address_p (enum machine_mode, rtx, int); extern int crx_legitimate_address_p (enum machine_mode, rtx, int);
extern int crx_const_double_ok (rtx op); extern int crx_const_double_ok (rtx op);
......
...@@ -65,32 +65,29 @@ ...@@ -65,32 +65,29 @@
/* Predicate is true if the current function is a 'noreturn' function, i.e. it /* Predicate is true if the current function is a 'noreturn' function, i.e. it
* is qualified as volatile. */ * is qualified as volatile. */
#define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl)) #define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
/* The following 3 macros are used in crx_legitimate_address_p() */ /* The following macros are used in crx_decompose_address () */
/* Returns 1 if the scale factor of an index address is valid. */ /* Returns the factor of a scaled index address or -1 if invalid. */
#define SCALE_FOR_INDEX_P(X) \ #define SCALE_FOR_INDEX_P(X) \
(GET_CODE (X) == CONST_INT \ (GET_CODE (X) == CONST_INT ? \
&& (INTVAL (X) == 1 || INTVAL (X) == 2 \ (INTVAL (X) == 1 ? 1 : \
|| INTVAL(X) == 4 || INTVAL (X) == 8)) INTVAL (X) == 2 ? 2 : \
INTVAL (X) == 4 ? 4 : \
INTVAL (X) == 8 ? 8 : \
-1) : \
-1)
/* Nonzero if the rtx X is a signed const int of n bits */ /* Nonzero if the rtx X is a signed const int of n bits */
#define RTX_SIGNED_INT_FITS_N_BITS(X,n) \ #define RTX_SIGNED_INT_FITS_N_BITS(X,n) \
((GET_CODE(X) == CONST_INT \ ((GET_CODE (X) == CONST_INT \
&& SIGNED_INT_FITS_N_BITS(INTVAL(X),n)) ? 1 : 0) && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
/* Nonzero if the rtx X is an unsigned const int of n bits. */ /* Nonzero if the rtx X is an unsigned const int of n bits. */
#define RTX_UNSIGNED_INT_FITS_N_BITS(X,n) \ #define RTX_UNSIGNED_INT_FITS_N_BITS(X, n) \
((GET_CODE(X) == CONST_INT \ ((GET_CODE (X) == CONST_INT \
&& UNSIGNED_INT_FITS_N_BITS(INTVAL(X),n)) ? 1 : 0) && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
/* Register relative legal displacement */
#define CRX_REGISTER_RELATIVE_DISP_P(X) \
(CONSTANT_ADDRESS_P(X) \
&& (GET_CODE (X) != CONST_INT \
|| RTX_SIGNED_INT_FITS_N_BITS(X, GET_MODE_BITSIZE (Pmode))))
/*****************************************************************************/ /*****************************************************************************/
/* STATIC VARIABLES */ /* STATIC VARIABLES */
...@@ -114,7 +111,7 @@ static int sum_regs = 0; ...@@ -114,7 +111,7 @@ static int sum_regs = 0;
static int local_vars_size; static int local_vars_size;
/* The sum of 2 sizes: locals vars and padding byte for saving the registers. /* The sum of 2 sizes: locals vars and padding byte for saving the registers.
* Used in expand_prologue() and expand_epilogue(). */ * Used in expand_prologue () and expand_epilogue (). */
static int size_for_adjusting_sp; static int size_for_adjusting_sp;
/* In case of a POST_INC or POST_DEC memory reference, we must report the mode /* In case of a POST_INC or POST_DEC memory reference, we must report the mode
...@@ -140,6 +137,7 @@ static bool crx_fixed_condition_code_regs (unsigned int *, unsigned int *); ...@@ -140,6 +137,7 @@ static bool crx_fixed_condition_code_regs (unsigned int *, unsigned int *);
static rtx crx_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED, static rtx crx_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
int incoming ATTRIBUTE_UNUSED); int incoming ATTRIBUTE_UNUSED);
static bool crx_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED); static bool crx_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED);
static int crx_address_cost (rtx);
/*****************************************************************************/ /*****************************************************************************/
/* STACK LAYOUT AND CALLING CONVENTIONS */ /* STACK LAYOUT AND CALLING CONVENTIONS */
...@@ -155,6 +153,13 @@ static bool crx_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED); ...@@ -155,6 +153,13 @@ static bool crx_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED);
#define TARGET_RETURN_IN_MEMORY crx_return_in_memory #define TARGET_RETURN_IN_MEMORY crx_return_in_memory
/*****************************************************************************/ /*****************************************************************************/
/* RELATIVE COSTS OF OPERATIONS */
/*****************************************************************************/
#undef TARGET_ADDRESS_COST
#define TARGET_ADDRESS_COST crx_address_cost
/*****************************************************************************/
/* TARGET-SPECIFIC USES OF `__attribute__' */ /* TARGET-SPECIFIC USES OF `__attribute__' */
/*****************************************************************************/ /*****************************************************************************/
...@@ -260,7 +265,7 @@ crx_compute_save_regs (void) ...@@ -260,7 +265,7 @@ crx_compute_save_regs (void)
} }
/* If this reg is used and not call-used (except RA), save it. */ /* If this reg is used and not call-used (except RA), save it. */
if (crx_interrupt_function_p()) if (crx_interrupt_function_p ())
{ {
if (!current_function_is_leaf && call_used_regs[regno]) if (!current_function_is_leaf && call_used_regs[regno])
/* this is a volatile reg in a non-leaf interrupt routine - save it /* this is a volatile reg in a non-leaf interrupt routine - save it
...@@ -353,10 +358,13 @@ crx_regno_reg_class (int regno) ...@@ -353,10 +358,13 @@ crx_regno_reg_class (int regno)
if (regno >= 0 && regno < SP_REGNUM) if (regno >= 0 && regno < SP_REGNUM)
return NOSP_REGS; return NOSP_REGS;
if (regno == SP_REGNUM) return GENERAL_REGS; if (regno == SP_REGNUM)
return GENERAL_REGS;
if (regno == LO_REGNUM) return LO_REGS; if (regno == LO_REGNUM)
if (regno == HI_REGNUM) return HI_REGS; return LO_REGS;
if (regno == HI_REGNUM)
return HI_REGS;
return NO_REGS; return NO_REGS;
} }
...@@ -429,7 +437,7 @@ crx_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode, tree type, ...@@ -429,7 +437,7 @@ crx_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode, tree type,
{ {
last_parm_in_reg = 0; last_parm_in_reg = 0;
/* Function_arg() is called with this type just after all the args have had /* Function_arg () is called with this type just after all the args have had
* their registers assigned. The rtx that function_arg returns from this type * their registers assigned. The rtx that function_arg returns from this type
* is supposed to pass to 'gen_call' but currently it is not implemented (see * is supposed to pass to 'gen_call' but currently it is not implemented (see
* macro GEN_CALL). */ * macro GEN_CALL). */
...@@ -535,7 +543,7 @@ crx_function_arg_regno_p (int n) ...@@ -535,7 +543,7 @@ crx_function_arg_regno_p (int n)
/* ---------------- */ /* ---------------- */
/* Implements the macro GO_IF_LEGITIMATE_ADDRESS defined in crx.h. /* Implements the macro GO_IF_LEGITIMATE_ADDRESS defined in crx.h.
* The legitimate addressing modes for the CRX are: * The following addressing modes are supported on CRX:
* *
* Relocations --> const | symbol_ref | label_ref * Relocations --> const | symbol_ref | label_ref
* Absolute address --> 32 bit absolute * Absolute address --> 32 bit absolute
...@@ -545,125 +553,283 @@ crx_function_arg_regno_p (int n) ...@@ -545,125 +553,283 @@ crx_function_arg_regno_p (int n)
* Scaled index --> reg + reg | 22 bit disp. + reg + reg | * Scaled index --> reg + reg | 22 bit disp. + reg + reg |
* 22 disp. + reg + reg + (2 | 4 | 8) */ * 22 disp. + reg + reg + (2 | 4 | 8) */
int static int crx_addr_reg_p (rtx addr_reg)
crx_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
rtx x, int strict)
{ {
/* Absolute address */ rtx reg;
if (RTX_UNSIGNED_INT_FITS_N_BITS(x, GET_MODE_BITSIZE(Pmode)))
return 1; if (REG_P (addr_reg))
/* Label */
if (GET_CODE (x) == CONST
|| GET_CODE (x) == SYMBOL_REF
|| GET_CODE (x) == LABEL_REF
|| (GET_CODE (x) == REG && (strict ? STRICT_REG_OK_FOR_BASE_P (x)
: NONSTRICT_REG_OK_FOR_BASE_P (x))))
return 1;
/* Post increment - The first argument is a register and the second is
* 12-bit long int. */
if (GET_CODE (x) == POST_INC || GET_CODE (x) == POST_DEC)
{ {
/* Don't allow modes to be referenced through post autoinc/dec that reg = addr_reg;
* cannot be loaded/stored with a single instruction */ }
if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) else if ((GET_CODE (addr_reg) == SUBREG
return 0; && REG_P (SUBREG_REG (addr_reg))
&& GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg)))
<= UNITS_PER_WORD))
{
reg = SUBREG_REG (addr_reg);
}
else
return FALSE;
if((GET_CODE (XEXP (x, 0)) == REG) if (GET_MODE (addr_reg) != Pmode)
&& (strict ? STRICT_REG_OK_FOR_BASE_P (XEXP (x, 0)) {
: NONSTRICT_REG_OK_FOR_BASE_P (XEXP (x, 0)))) return FALSE;
return 1;
} }
/* Post modify */ return TRUE;
if (GET_CODE (x) == POST_MODIFY) }
enum crx_addrtype
crx_decompose_address (rtx addr, struct crx_address *out)
{
rtx base = NULL_RTX, index = NULL_RTX, disp = NULL_RTX;
rtx scale_rtx = NULL_RTX, side_effect = NULL_RTX;
int scale = -1;
enum crx_addrtype retval = CRX_INVALID;
switch (GET_CODE (addr))
{ {
/* Don't allow modes to be referenced through post autoinc/dec that case CONST_INT:
* cannot be loaded/stored with a single instruction */ /* Absolute address (known at compile time) */
if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) retval = CRX_ABSOLUTE;
return 0; disp = addr;
if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), GET_MODE_BITSIZE (Pmode)))
return CRX_INVALID;
break;
case CONST:
case SYMBOL_REF:
case LABEL_REF:
/* Absolute address (known at link time) */
retval = CRX_ABSOLUTE;
disp = addr;
break;
if (!(GET_CODE (XEXP (x, 0)) == REG case REG:
&& (strict ? STRICT_REG_OK_FOR_BASE_P (XEXP (x, 0)) case SUBREG:
: NONSTRICT_REG_OK_FOR_BASE_P (XEXP (x, 0))) /* Register relative address */
&& RTX_SIGNED_INT_FITS_N_BITS(XEXP (XEXP (x, 1), 1), 12))) retval = CRX_REG_REL;
return 0; base = addr;
break;
if(!(GET_CODE (XEXP (x, 1)) == PLUS || GET_CODE (XEXP (x, 1)) == MINUS)) case PLUS:
return 0; switch (GET_CODE (XEXP (addr, 0)))
{
case REG:
case SUBREG:
if (REG_P (XEXP (addr, 1)))
{
/* Scaled index with scale = 1 and disp. = 0 */
retval = CRX_SCALED_INDX;
base = XEXP (addr, 1);
index = XEXP (addr, 0);
scale = 1;
}
else if (RTX_SIGNED_INT_FITS_N_BITS (XEXP (addr, 1), 28))
{
/* Register relative address and <= 28-bit disp. */
retval = CRX_REG_REL;
base = XEXP (addr, 0);
disp = XEXP (addr, 1);
}
else
return CRX_INVALID;
break;
if(!rtx_equal_p(XEXP (x, 0), XEXP (XEXP (x, 1), 0))) case PLUS:
return 0; /* Scaled index and <= 22-bit disp. */
retval = CRX_SCALED_INDX;
base = XEXP (XEXP (addr, 0), 1);
disp = XEXP (addr, 1);
if (!RTX_SIGNED_INT_FITS_N_BITS (disp, 22))
return CRX_INVALID;
switch (GET_CODE (XEXP (XEXP (addr, 0), 0)))
{
case REG:
/* Scaled index with scale = 0 and <= 22-bit disp. */
index = XEXP (XEXP (addr, 0), 0);
scale = 1;
break;
case MULT:
/* Scaled index with scale >= 0 and <= 22-bit disp. */
index = XEXP (XEXP (XEXP (addr, 0), 0), 0);
scale_rtx = XEXP (XEXP (XEXP (addr, 0), 0), 1);
if ((scale = SCALE_FOR_INDEX_P (scale_rtx)) == -1)
return CRX_INVALID;
break;
return 1; default:
return CRX_INVALID;
}
break;
case MULT:
/* Scaled index with scale >= 0 */
retval = CRX_SCALED_INDX;
base = XEXP (addr, 1);
index = XEXP (XEXP (addr, 0), 0);
scale_rtx = XEXP (XEXP (addr, 0), 1);
/* Scaled index with scale >= 0 and <= 22-bit disp. */
if ((scale = SCALE_FOR_INDEX_P (scale_rtx)) == -1)
return CRX_INVALID;
break;
default:
return CRX_INVALID;
}
break;
case POST_INC:
case POST_DEC:
/* Simple post-increment */
retval = CRX_POST_INC;
base = XEXP (addr, 0);
side_effect = addr;
break;
case POST_MODIFY:
/* Generic post-increment with <= 12-bit disp. */
retval = CRX_POST_INC;
base = XEXP (addr, 0);
side_effect = XEXP (addr, 1);
if (base != XEXP (side_effect, 0))
return CRX_INVALID;
switch (GET_CODE (side_effect))
{
case PLUS:
case MINUS:
disp = XEXP (side_effect, 1);
if (!RTX_SIGNED_INT_FITS_N_BITS (disp, 12))
return CRX_INVALID;
break;
default:
/* CRX only supports PLUS and MINUS */
return CRX_INVALID;
}
break;
default:
return CRX_INVALID;
} }
if (GET_CODE (x) == PLUS) if (base && !crx_addr_reg_p (base)) return CRX_INVALID;
if (index && !crx_addr_reg_p (index)) return CRX_INVALID;
out->base = base;
out->index = index;
out->disp = disp;
out->scale = scale;
out->side_effect = side_effect;
return retval;
}
int
crx_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
rtx addr, int strict)
{
enum crx_addrtype addrtype;
struct crx_address address;
if (TARGET_DEBUG_ADDR)
{
fprintf (stderr,
"\n======\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n",
GET_MODE_NAME (mode), strict);
debug_rtx (addr);
}
addrtype = crx_decompose_address (addr, &address);
if (addrtype == CRX_POST_INC && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
return FALSE;
if (TARGET_DEBUG_ADDR)
{ {
/* Register relative */ const char *typestr;
if (GET_CODE (XEXP (x, 0)) == REG switch (addrtype)
&& (strict ? STRICT_REG_OK_FOR_BASE_P (XEXP (x, 0))
: NONSTRICT_REG_OK_FOR_BASE_P (XEXP (x, 0)))
&& (CRX_REGISTER_RELATIVE_DISP_P (XEXP (x, 1))))
return 1;
/* Scaled index with factor 1 */
/* 1a. reg + reg */
if (GET_CODE (XEXP (x, 0)) == REG
&& (strict ? STRICT_REG_OK_FOR_BASE_P (XEXP (x, 0))
: REG_OK_FOR_INDEX_P (XEXP (x, 0)))
&& GET_CODE (XEXP (x, 1)) == REG
&& (strict ? STRICT_REG_OK_FOR_BASE_P (XEXP (x, 1))
: REG_OK_FOR_INDEXED_BASE_P (XEXP (x, 1))))
return 1;
/* Scaled index with different factor */
/* 1b. reg * scale + reg */
if (GET_CODE (XEXP (x, 0)) == MULT
&& GET_CODE (XEXP( XEXP (x, 0), 0)) == REG
&& (strict ? STRICT_REG_OK_FOR_INDEX_P (XEXP( XEXP (x, 0), 0))
: NONSTRICT_REG_OK_FOR_INDEX_P (XEXP( XEXP (x, 0), 0)))
&& (SCALE_FOR_INDEX_P (XEXP( XEXP (x, 0), 1)))
&& GET_CODE (XEXP (x, 1)) == REG
&& (strict ? STRICT_REG_OK_FOR_BASE_P (XEXP (x, 1))
: NONSTRICT_REG_OK_FOR_BASE_P (XEXP (x, 1))))
return 1;
if (GET_CODE (XEXP (x, 0)) == PLUS)
{ {
/* 2. reg + reg + 22 bit disp. */ case CRX_INVALID:
if (GET_CODE (XEXP (XEXP (x, 0), 0)) == REG typestr = "Invalid";
&& (strict ? STRICT_REG_OK_FOR_BASE_P (XEXP (XEXP (x, 0), 0)) break;
: REG_OK_FOR_INDEX_P (XEXP (XEXP (x, 0), 0))) case CRX_REG_REL:
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == REG typestr = "Register relative";
&& (strict ? STRICT_REG_OK_FOR_BASE_P (XEXP (XEXP (x, 0), 1)) break;
: REG_OK_FOR_INDEXED_BASE_P (XEXP (XEXP (x, 0), 1))) case CRX_POST_INC:
&& (RTX_SIGNED_INT_FITS_N_BITS(XEXP (x, 1), 22))) typestr = "Post-increment";
return 1; break;
case CRX_SCALED_INDX:
/* 3. reg * scale + reg + 22 bit disp. */ typestr = "Scaled index";
if ((GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT) break;
&& (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == REG) case CRX_ABSOLUTE:
&& (strict ? typestr = "Absolute";
STRICT_REG_OK_FOR_BASE_P (XEXP (XEXP (XEXP (x, 0), 0), 0)) break;
: default:
REG_OK_FOR_INDEXED_BASE_P (XEXP (XEXP (XEXP (x, 0), 0), 0))) abort ();
&& (SCALE_FOR_INDEX_P (XEXP (XEXP (XEXP (x, 0), 0), 1)))
&& (GET_CODE (XEXP (XEXP (x, 0), 1)) == REG)
&& (strict ? STRICT_REG_OK_FOR_BASE_P (XEXP (XEXP (x, 0), 1)) :
REG_OK_FOR_INDEX_P (XEXP (XEXP (x, 0), 1)))
&& (RTX_SIGNED_INT_FITS_N_BITS(XEXP (x, 1), 22)))
return 1;
} }
fprintf (stderr, "CRX Address type: %s\n", typestr);
} }
if (addrtype == CRX_INVALID)
return FALSE;
return 0; if (strict)
{
if (address.base && !REGNO_OK_FOR_BASE_P (REGNO (address.base)))
{
if (TARGET_DEBUG_ADDR)
fprintf (stderr, "Base register not strict\n");
return FALSE;
}
if (address.index && !REGNO_OK_FOR_INDEX_P (REGNO (address.index)))
{
if (TARGET_DEBUG_ADDR)
fprintf (stderr, "Index register not strict\n");
return FALSE;
}
}
return TRUE;
} }
/* ROUTINES TO COMPUTE COSTS */ /* ROUTINES TO COMPUTE COSTS */
/* ------------------------- */ /* ------------------------- */
/* Return cost of the memory address x. */
static int
crx_address_cost (rtx addr)
{
enum crx_addrtype addrtype;
struct crx_address address;
int cost = 2;
addrtype = crx_decompose_address (addr, &address);
gcc_assert (addrtype != CRX_INVALID);
/* An absolute address causes a 3-word instruction */
if (addrtype == CRX_ABSOLUTE)
cost+=2;
/* Post-modifying addresses are more powerfull. */
if (addrtype == CRX_POST_INC)
cost-=2;
/* Attempt to minimize number of registers in the address. */
if (address.base)
cost++;
if (address.index && address.scale == 1)
cost+=5;
return cost;
}
/* Return the cost of moving data of mode MODE between a register of class /* Return the cost of moving data of mode MODE between a register of class
* CLASS and memory; IN is zero if the value is to be written to memory, * CLASS and memory; IN is zero if the value is to be written to memory,
* nonzero if it is to be read in. This cost is relative to those in * nonzero if it is to be read in. This cost is relative to those in
...@@ -677,25 +843,25 @@ crx_memory_move_cost (enum machine_mode mode, ...@@ -677,25 +843,25 @@ crx_memory_move_cost (enum machine_mode mode,
/* One LD or ST takes twice the time of a simple reg-reg move */ /* One LD or ST takes twice the time of a simple reg-reg move */
if (reg_classes_intersect_p (class, GENERAL_REGS)) if (reg_classes_intersect_p (class, GENERAL_REGS))
{ {
/* printf("GENERAL_REGS LD/ST = %d\n", 4 * HARD_REGNO_NREGS (0, mode));*/ /* printf ("GENERAL_REGS LD/ST = %d\n", 4 * HARD_REGNO_NREGS (0, mode));*/
return 4 * HARD_REGNO_NREGS (0, mode); return 4 * HARD_REGNO_NREGS (0, mode);
} }
else if (reg_classes_intersect_p (class, HILO_REGS)) else if (reg_classes_intersect_p (class, HILO_REGS))
{ {
/* HILO to memory and vice versa */ /* HILO to memory and vice versa */
/* printf("HILO_REGS %s = %d\n",in ? "LD" : "ST", /* printf ("HILO_REGS %s = %d\n", in ? "LD" : "ST",
(REGISTER_MOVE_COST(mode, (REGISTER_MOVE_COST (mode,
in ? GENERAL_REGS : HILO_REGS, in ? GENERAL_REGS : HILO_REGS,
in ? HILO_REGS : GENERAL_REGS) + 4) in ? HILO_REGS : GENERAL_REGS) + 4)
* HARD_REGNO_NREGS (0, mode)); */ * HARD_REGNO_NREGS (0, mode)); */
return (REGISTER_MOVE_COST(mode, return (REGISTER_MOVE_COST (mode,
in ? GENERAL_REGS : HILO_REGS, in ? GENERAL_REGS : HILO_REGS,
in ? HILO_REGS : GENERAL_REGS) + 4) in ? HILO_REGS : GENERAL_REGS) + 4)
* HARD_REGNO_NREGS (0, mode); * HARD_REGNO_NREGS (0, mode);
} }
else /* default (like in i386) */ else /* default (like in i386) */
{ {
/* printf("ANYREGS = 100\n"); */ /* printf ("ANYREGS = 100\n"); */
return 100; return 100;
} }
} }
...@@ -703,80 +869,6 @@ crx_memory_move_cost (enum machine_mode mode, ...@@ -703,80 +869,6 @@ crx_memory_move_cost (enum machine_mode mode,
/* INSTRUCTION OUTPUT */ /* INSTRUCTION OUTPUT */
/* ------------------ */ /* ------------------ */
/* Print to FILE addr expression of the form post_inc/dec (in this case
* post_offset is zero) or post_inc/dec + post_offset */
static void
print_post_operand_address (FILE * file, rtx addr, int post_offset)
{
int displmnt;
if (GET_CODE (addr) == POST_MODIFY)
{
displmnt = INTVAL(XEXP( XEXP (addr, 1), 1));
if (GET_CODE (XEXP (addr, 1)) == MINUS) displmnt = (-1) * displmnt;
}
else
{
displmnt = GET_MODE_SIZE (output_memory_reference_mode);
/* Make the displacement negative for POST_DEC */
if (GET_CODE (addr) == POST_DEC) displmnt = (-1) * displmnt;
}
if (GET_CODE (XEXP (addr, 0)) != REG)
abort ();
displmnt += post_offset;
fprintf (file, "%d(%s)+", displmnt, reg_names[REGNO (XEXP (addr, 0))]);
}
/* Check if constant rtx contains label_ref. */
static rtx
const_and_contains_label_ref (rtx x)
{
if (!x)
return NULL_RTX;
if (GET_CODE (x) == LABEL_REF)
return x;
/* Check within enclosing const. */
if (GET_CODE (x) == CONST)
x = XEXP (x, 0);
if ((GET_CODE (x) == PLUS || GET_CODE (x) == MINUS)
&& GET_CODE (XEXP (x, 1)) == CONST_INT
&& GET_CODE (XEXP (x, 0)) == LABEL_REF)
return XEXP (x, 0);
return NULL_RTX;
}
/* Check if rtx contains symbol_ref. */
static rtx
const_and_contains_symbol_ref (rtx x)
{
if (!x)
return NULL_RTX;
if (GET_CODE (x) == SYMBOL_REF)
return x;
/* Check within enclosing const. */
if (GET_CODE (x) == CONST)
x = XEXP (x, 0);
if ((GET_CODE (x) == PLUS || GET_CODE (x) == MINUS)
&& GET_CODE (XEXP (x, 1)) == CONST_INT
&& GET_CODE (XEXP (x, 0)) == SYMBOL_REF)
return XEXP (x, 0);
return NULL_RTX;
}
/* Check if a const_double is ok for crx store-immediate instructions */ /* Check if a const_double is ok for crx store-immediate instructions */
int int
...@@ -788,8 +880,8 @@ crx_const_double_ok (rtx op) ...@@ -788,8 +880,8 @@ crx_const_double_ok (rtx op)
long l[2]; long l[2];
REAL_VALUE_FROM_CONST_DOUBLE (r, op); REAL_VALUE_FROM_CONST_DOUBLE (r, op);
REAL_VALUE_TO_TARGET_DOUBLE (r, l); REAL_VALUE_TO_TARGET_DOUBLE (r, l);
return (UNSIGNED_INT_FITS_N_BITS(l[0], 4) && return (UNSIGNED_INT_FITS_N_BITS (l[0], 4) &&
UNSIGNED_INT_FITS_N_BITS(l[1], 4)) ? 1 : 0; UNSIGNED_INT_FITS_N_BITS (l[1], 4)) ? 1 : 0;
} }
if (GET_MODE (op) == SFmode) if (GET_MODE (op) == SFmode)
...@@ -798,7 +890,7 @@ crx_const_double_ok (rtx op) ...@@ -798,7 +890,7 @@ crx_const_double_ok (rtx op)
long l; long l;
REAL_VALUE_FROM_CONST_DOUBLE (r, op); REAL_VALUE_FROM_CONST_DOUBLE (r, op);
REAL_VALUE_TO_TARGET_SINGLE (r, l); REAL_VALUE_TO_TARGET_SINGLE (r, l);
return UNSIGNED_INT_FITS_N_BITS(l, 4) ? 1 : 0; return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0;
} }
return (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4) && return (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4) &&
...@@ -833,7 +925,7 @@ crx_print_operand (FILE * file, rtx x, int code) ...@@ -833,7 +925,7 @@ crx_print_operand (FILE * file, rtx x, int code)
{ {
const char *crx_cmp_str; const char *crx_cmp_str;
switch (GET_CODE (x)) switch (GET_CODE (x))
{ /* MD: compare(reg, reg or imm) but CRX: cmp(reg or imm, reg) { /* MD: compare (reg, reg or imm) but CRX: cmp (reg or imm, reg)
* -> swap all non symmetric ops */ * -> swap all non symmetric ops */
case EQ : crx_cmp_str = "eq"; break; case EQ : crx_cmp_str = "eq"; break;
case NE : crx_cmp_str = "ne"; break; case NE : crx_cmp_str = "ne"; break;
...@@ -945,7 +1037,7 @@ crx_print_operand (FILE * file, rtx x, int code) ...@@ -945,7 +1037,7 @@ crx_print_operand (FILE * file, rtx x, int code)
} }
case 0 : /* default */ case 0 : /* default */
switch (GET_CODE(x)) switch (GET_CODE (x))
{ {
case REG: case REG:
fprintf (file, "%s", reg_names[REGNO (x)]); fprintf (file, "%s", reg_names[REGNO (x)]);
...@@ -962,7 +1054,7 @@ crx_print_operand (FILE * file, rtx x, int code) ...@@ -962,7 +1054,7 @@ crx_print_operand (FILE * file, rtx x, int code)
long l; long l;
/* Always use H and L for double precision - see above */ /* Always use H and L for double precision - see above */
gcc_assert(GET_MODE (x) == SFmode); gcc_assert (GET_MODE (x) == SFmode);
REAL_VALUE_FROM_CONST_DOUBLE (r, x); REAL_VALUE_FROM_CONST_DOUBLE (r, x);
REAL_VALUE_TO_TARGET_SINGLE (r, l); REAL_VALUE_TO_TARGET_SINGLE (r, l);
...@@ -989,172 +1081,56 @@ crx_print_operand (FILE * file, rtx x, int code) ...@@ -989,172 +1081,56 @@ crx_print_operand (FILE * file, rtx x, int code)
void void
crx_print_operand_address (FILE * file, rtx addr) crx_print_operand_address (FILE * file, rtx addr)
{ {
rtx breg = 0, ireg = 0; enum crx_addrtype addrtype;
rtx offset = 0; struct crx_address address;
rtx post_offset = 0;
rtx scale = 0; int offset;
int mem = 0;
addrtype = crx_decompose_address (addr, &address);
if (address.disp)
offset = INTVAL (address.disp);
else
offset = 0;
retry: switch (addrtype)
switch (GET_CODE (addr))
{ {
case MEM: case CRX_REG_REL:
fprintf (file, "0("); fprintf (file, "%d(%s)", offset, reg_names[REGNO (address.base)]);
addr = XEXP (addr, 0); return;
mem = 1;
goto retry; case CRX_POST_INC:
case REG: switch (GET_CODE (address.side_effect))
fprintf (file, "0(%s)", reg_names[REGNO (addr)]);
break;
case MULT:
abort ();
break;
case PLUS:
switch (GET_CODE (XEXP (addr, 0)))
{ {
case REG: case PLUS:
if (GET_CODE (XEXP (addr, 1)) == REG)
{
ireg = XEXP (addr, 0);
breg = XEXP (addr, 1);
}
else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
{
if (REG_OK_FOR_BASE_P (XEXP (addr, 0))
&& ((GET_CODE (XEXP (addr, 1)) == CONST_INT)
|| (const_and_contains_symbol_ref (XEXP (addr, 1)))
|| (const_and_contains_label_ref (XEXP (addr, 1)))))
ireg = XEXP (addr, 0);
else
breg = XEXP (addr, 0);
offset = XEXP (addr, 1);
}
else
abort ();
break; break;
case MULT: case MINUS:
ireg = XEXP (XEXP (addr, 0), 0); offset = -offset;
scale = XEXP (XEXP (addr, 0), 1);
breg = XEXP (addr, 1);
break; break;
case PLUS: case POST_INC:
if ((GET_CODE (XEXP (XEXP (addr, 0), 0)) == MULT) offset = GET_MODE_SIZE (output_memory_reference_mode);
&& (GET_CODE (XEXP (XEXP (XEXP (addr, 0), 0), 0)) == REG)
&& (SCALE_FOR_INDEX_P (XEXP (XEXP (XEXP (addr, 0), 0), 1)))
&& (GET_CODE (XEXP (XEXP (addr, 0), 1)) == REG)
&& (GET_CODE (XEXP (addr, 1)) == CONST_INT))
{
ireg = XEXP (XEXP (XEXP (addr, 0), 0), 0);
breg = XEXP (XEXP (addr, 0), 1);
scale = (XEXP (XEXP (XEXP (addr, 0), 0), 1));
offset = XEXP (addr, 1);
}
else if (GET_CODE (XEXP (XEXP (addr, 0), 0)) == REG
&& GET_CODE (XEXP (XEXP (addr, 0), 1)) == REG
&& CONSTANT_ADDRESS_P (XEXP (addr, 1)))
{
ireg = XEXP (XEXP (addr, 0), 0);
breg = XEXP (XEXP (addr, 0), 1);
offset = XEXP (addr, 1);
}
else if (GET_CODE (XEXP (XEXP (addr, 0), 0)) == REG
&& GET_CODE (XEXP (addr, 1)) == REG
&& CONSTANT_ADDRESS_P (XEXP (XEXP (addr, 0), 1)))
{
ireg = XEXP (XEXP (addr, 0), 0);
breg = XEXP (addr, 1);
offset = XEXP (XEXP (addr, 0), 1);
}
else
abort ();
break; break;
default: case POST_DEC:
if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) offset = -GET_MODE_SIZE (output_memory_reference_mode);
{
if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
offset = addr;
else if (GET_CODE (XEXP (addr, 0)) == POST_INC
|| GET_CODE (XEXP (addr, 0)) == POST_DEC)
post_offset = XEXP (addr, 1);
else
abort ();
}
break; break;
default:
abort ();
} }
fprintf (file, "%d(%s)+", offset, reg_names[REGNO (address.base)]);
if (scale) return;
{
fprintf (file, "%ld(%s,%s,%ld)", offset ? INTVAL (offset) : 0, case CRX_SCALED_INDX:
reg_names[REGNO (breg)], reg_names[REGNO (ireg)], fprintf (file, "%d(%s, %s, %d)", offset, reg_names[REGNO (address.base)],
INTVAL (scale)); reg_names[REGNO (address.index)], address.scale);
} return;
else
{ case CRX_ABSOLUTE:
/* If this is (POST_DEC/INC expression + post_offset) make addr = output_addr_const (file, address.disp);
* POST_DEC/INC expression */ return;
if (post_offset != 0)
{
addr = XEXP (addr, 0);
print_post_operand_address (file, addr, INTVAL (post_offset));
break;
}
if (ireg != 0)
{
if (offset != 0)
{
output_addr_const (file, offset);
/* Print modifier if relevant. */
}
else
{
fprintf (file, "0");
}
/* Print address string */
if (breg != 0)
{
fprintf (file, "(%s,%s)", reg_names[REGNO (breg)],
reg_names[REGNO (ireg)]);
}
else
fprintf (file, "(%s)", reg_names[REGNO (ireg)]);
}
else
{
if (offset != 0)
{
output_addr_const (file, offset);
}
else
{
fprintf (file, "0");
}
if (breg != 0)
{
if (offset == 0)
fprintf (file, "0");
fprintf (file, "(%s)", reg_names[REGNO (breg)]);
}
}
}
break;
case POST_DEC:
case POST_INC:
case POST_MODIFY:
print_post_operand_address (file, addr, 0);
break;
default: default:
abort ();
output_addr_const (file, addr);
} }
if (mem)
fprintf (file, ")");
} }
...@@ -1193,16 +1169,18 @@ crx_expand_movmem (rtx dstbase, rtx srcbase, rtx count_exp, rtx align_exp) ...@@ -1193,16 +1169,18 @@ crx_expand_movmem (rtx dstbase, rtx srcbase, rtx count_exp, rtx align_exp)
if (GET_CODE (align_exp) == CONST_INT) if (GET_CODE (align_exp) == CONST_INT)
{ /* Only if aligned */ { /* Only if aligned */
align = INTVAL (align_exp); align = INTVAL (align_exp);
if (align & 3) return 0; if (align & 3)
return 0;
} }
if (GET_CODE (count_exp) == CONST_INT) if (GET_CODE (count_exp) == CONST_INT)
{ /* No more than 16 SImode moves */ { /* No more than 16 SImode moves */
count = INTVAL (count_exp); count = INTVAL (count_exp);
if (count > 64) return 0; if (count > 64)
return 0;
} }
tmp_reg = gen_reg_rtx(SImode); tmp_reg = gen_reg_rtx (SImode);
/* Create psrs for the src and dest pointers */ /* Create psrs for the src and dest pointers */
dst = copy_to_mode_reg (Pmode, XEXP (dstbase, 0)); dst = copy_to_mode_reg (Pmode, XEXP (dstbase, 0));
...@@ -1271,7 +1249,7 @@ crx_expand_scond (enum rtx_code code, rtx dest) ...@@ -1271,7 +1249,7 @@ crx_expand_scond (enum rtx_code code, rtx dest)
static void static void
mpushpop_str (char *stringbuffer, const char *mnemonic, char *mask) mpushpop_str (char *stringbuffer, const char *mnemonic, char *mask)
{ {
if(strlen(mask) > 2 || crx_interrupt_function_p ()) /* needs 2-word instr. */ if (strlen (mask) > 2 || crx_interrupt_function_p ()) /* needs 2-word instr. */
sprintf (stringbuffer, "\n\t%s\tsp, {%s}", mnemonic, mask); sprintf (stringbuffer, "\n\t%s\tsp, {%s}", mnemonic, mask);
else /* single word instruction */ else /* single word instruction */
sprintf (stringbuffer, "\n\t%s\t%s", mnemonic, mask); sprintf (stringbuffer, "\n\t%s\t%s", mnemonic, mask);
...@@ -1346,7 +1324,7 @@ crx_prepare_push_pop_string (int push_or_pop) ...@@ -1346,7 +1324,7 @@ crx_prepare_push_pop_string (int push_or_pop)
} }
} }
if (strlen(mask_str) == 0) continue; if (strlen (mask_str) == 0) continue;
if (push_or_pop == 1) if (push_or_pop == 1)
{ {
...@@ -1438,7 +1416,7 @@ crx_expand_prologue (void) ...@@ -1438,7 +1416,7 @@ crx_expand_prologue (void)
if (size_for_adjusting_sp > 0) if (size_for_adjusting_sp > 0)
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (-(size_for_adjusting_sp)))); GEN_INT (-size_for_adjusting_sp)));
if (frame_pointer_needed) if (frame_pointer_needed)
/* Initialize the frame pointer with the value of the stack pointer /* Initialize the frame pointer with the value of the stack pointer
......
...@@ -223,7 +223,6 @@ enum reg_class ...@@ -223,7 +223,6 @@ enum reg_class
|| (reg_renumber && (unsigned)reg_renumber[REGNO] < 16)) || (reg_renumber && (unsigned)reg_renumber[REGNO] < 16))
#define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO) #define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO)
#define REGNO_OK_FOR_INDEXED_BASE_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO)
#define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS
...@@ -329,7 +328,7 @@ struct cumulative_args ...@@ -329,7 +328,7 @@ struct cumulative_args
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
crx_function_arg_advance(&(CUM), (MODE), (TYPE), (NAMED)) crx_function_arg_advance(&(CUM), (MODE), (TYPE), (NAMED))
#define FUNCTION_ARG_REGNO_P(REGNO) crx_function_arg_regno_p((REGNO)) #define FUNCTION_ARG_REGNO_P(REGNO) crx_function_arg_regno_p(REGNO)
/*****************************************************************************/ /*****************************************************************************/
/* RETURNING FUNCTION VALUE */ /* RETURNING FUNCTION VALUE */
...@@ -384,22 +383,12 @@ struct cumulative_args ...@@ -384,22 +383,12 @@ struct cumulative_args
#define HAVE_POST_MODIFY_DISP 1 #define HAVE_POST_MODIFY_DISP 1
#define HAVE_POST_MODIFY_REG 0 #define HAVE_POST_MODIFY_REG 0
#define STRICT_REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
#define STRICT_REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P(REGNO(X))
#define STRICT_REG_OK_FOR_INDEXED_BASE_P(X) REGNO_OK_FOR_INDEXED_BASE_P(REGNO(X))
#define NONSTRICT_REG_OK_FOR_BASE_P(X) 1
#define NONSTRICT_REG_OK_FOR_INDEX_P(X) 1
#define NONSTRICT_REG_OK_FOR_INDEXED_BASE_P(X) 1
#ifdef REG_OK_STRICT #ifdef REG_OK_STRICT
#define REG_OK_FOR_BASE_P(X) STRICT_REG_OK_FOR_BASE_P(X) #define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
#define REG_OK_FOR_INDEX_P(X) STRICT_REG_OK_FOR_INDEX_P(X) #define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
#define REG_OK_FOR_INDEXED_BASE_P(X) STRICT_REG_OK_FOR_INDEXED_BASE_P(X)
#else #else
#define REG_OK_FOR_BASE_P(X) NONSTRICT_REG_OK_FOR_BASE_P(X) #define REG_OK_FOR_BASE_P(X) 1
#define REG_OK_FOR_INDEX_P(X) NONSTRICT_REG_OK_FOR_INDEX_P(X) #define REG_OK_FOR_INDEX_P(X) 1
#define REG_OK_FOR_INDEXED_BASE_P(X) NONSTRICT_REG_OK_FOR_INDEXED_BASE_P(X)
#endif /* REG_OK_STRICT */ #endif /* REG_OK_STRICT */
#ifdef REG_OK_STRICT #ifdef REG_OK_STRICT
...@@ -414,9 +403,7 @@ struct cumulative_args ...@@ -414,9 +403,7 @@ struct cumulative_args
if (crx_legitimate_address_p (MODE, X, 0)) \ if (crx_legitimate_address_p (MODE, X, 0)) \
goto LABEL; \ goto LABEL; \
} }
#endif #endif /* REG_OK_STRICT */
#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) {}
#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \ #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \
{ \ { \
......
...@@ -26,3 +26,6 @@ Support multiply accumulate instructions ...@@ -26,3 +26,6 @@ Support multiply accumulate instructions
mno-push-args mno-push-args
Target Report RejectNegative Mask(NO_PUSH_ARGS) Target Report RejectNegative Mask(NO_PUSH_ARGS)
Do not use push to store function arguments Do not use push to store function arguments
mdebug-addr
Target RejectNegative Var(TARGET_DEBUG_ADDR) Undocumented
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment