A large number of changes to enable PIC support and shared libraries
for NetBSD/vax.
This commit is contained in:
parent
aca741cc61
commit
40b1bb9563
3
gnu/dist/gcc/config/vax/netbsd.h
vendored
3
gnu/dist/gcc/config/vax/netbsd.h
vendored
@ -24,3 +24,6 @@
|
||||
/* Until they use ELF or something that handles dwarf2 unwinds
|
||||
and initialization stuff better. */
|
||||
#undef DWARF2_UNWIND_INFO
|
||||
|
||||
#undef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT 16 /* default to half-pic mode */
|
||||
|
374
gnu/dist/gcc/config/vax/vax.c
vendored
374
gnu/dist/gcc/config/vax/vax.c
vendored
@ -18,8 +18,9 @@ along with GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "rtl.h"
|
||||
#include "regs.h"
|
||||
#include "hard-reg-set.h"
|
||||
@ -139,7 +140,10 @@ print_operand_address (file, addr)
|
||||
addr = XEXP (addr, 1);
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
{
|
||||
debug_rtx(addr);
|
||||
abort ();
|
||||
}
|
||||
|
||||
if (GET_CODE (addr) == REG)
|
||||
{
|
||||
@ -162,7 +166,10 @@ print_operand_address (file, addr)
|
||||
else if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
|
||||
offset = plus_constant (offset, INTVAL (XEXP (addr, 0)));
|
||||
else
|
||||
abort ();
|
||||
{
|
||||
debug_rtx(addr);
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
offset = XEXP (addr, 0);
|
||||
}
|
||||
@ -210,10 +217,16 @@ print_operand_address (file, addr)
|
||||
ireg = XEXP (addr, 1);
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
{
|
||||
debug_rtx(addr);
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
{
|
||||
debug_rtx(addr);
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* If REG1 is non-zero, figure out if it is a base or index register. */
|
||||
if (reg1)
|
||||
@ -651,6 +664,357 @@ check_float_value (mode, d, overflow)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Nonzero if X is a hard reg that can be used as an index. */
|
||||
#define XREG_OK_FOR_INDEX_P(X, STRICT) (!(STRICT) || REGNO_OK_FOR_INDEX_P (REGNO (X)))
|
||||
/* Nonzero if X is a hard reg that can be used as a base reg. */
|
||||
#define XREG_OK_FOR_BASE_P(X, STRICT) (!(STRICT) || REGNO_OK_FOR_BASE_P (REGNO (X)))
|
||||
|
||||
#ifdef NO_EXTERNAL_INDIRECT_ADDRESS
|
||||
|
||||
/* Zero if this contains a (CONST (PLUS (SYMBOL_REF) (...))) and the
|
||||
symbol in the SYMBOL_REF is an external symbol. */
|
||||
|
||||
#define INDIRECTABLE_CONSTANT_P(X) \
|
||||
(! (GET_CODE ((X)) == CONST \
|
||||
&& GET_CODE (XEXP ((X), 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP ((X), 0), 0)) == SYMBOL_REF \
|
||||
&& SYMBOL_REF_FLAG (XEXP (XEXP ((X), 0), 0))))
|
||||
|
||||
/* Re-definition of CONSTANT_ADDRESS_P, which is true only when there
|
||||
are no SYMBOL_REFs for external symbols present. */
|
||||
|
||||
#define INDIRECTABLE_CONSTANT_ADDRESS_P(X) \
|
||||
(GET_CODE (X) == LABEL_REF \
|
||||
|| (GET_CODE (X) == SYMBOL_REF && !SYMBOL_REF_FLAG (X)) \
|
||||
|| (GET_CODE (X) == CONST && INDIRECTABLE_CONSTANT_P(X)) \
|
||||
|| GET_CODE (X) == CONST_INT)
|
||||
|
||||
|
||||
/* Non-zero if X is an address which can be indirected. External symbols
|
||||
could be in a sharable image library, so we disallow those. */
|
||||
|
||||
#define INDIRECTABLE_ADDRESS_P(X, STRICT) \
|
||||
(INDIRECTABLE_CONSTANT_ADDRESS_P (X) \
|
||||
|| (GET_CODE (X) == REG && XREG_OK_FOR_BASE_P (X, STRICT)) \
|
||||
|| (GET_CODE (X) == PLUS \
|
||||
&& GET_CODE (XEXP (X, 0)) == REG \
|
||||
&& XREG_OK_FOR_BASE_P (XEXP (X, 0), STRICT) \
|
||||
&& INDIRECTABLE_CONSTANT_ADDRESS_P (XEXP (X, 1))))
|
||||
|
||||
#else /* not NO_EXTERNAL_INDIRECT_ADDRESS */
|
||||
|
||||
#define INDIRECTABLE_CONSTANT_P(X) \
|
||||
(! (GET_CODE ((X)) == CONST \
|
||||
&& GET_CODE (XEXP ((X), 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP ((X), 0), 0)) == SYMBOL_REF))
|
||||
|
||||
#define INDIRECTABLE_CONSTANT_ADDRESS_P(X) \
|
||||
(!(flag_pic || TARGET_HALFPIC) ? CONSTANT_ADDRESS_P(X) \
|
||||
: (GET_CODE (X) == LABEL_REF \
|
||||
|| GET_CODE (X) == SYMBOL_REF \
|
||||
|| (GET_CODE (X) == CONST && INDIRECTABLE_CONSTANT_P (X)) \
|
||||
|| GET_CODE (X) == CONST_INT))
|
||||
|
||||
/* Non-zero if X is an address which can be indirected. */
|
||||
#define INDIRECTABLE_ADDRESS_P(X, STRICT) \
|
||||
(INDIRECTABLE_CONSTANT_ADDRESS_P (X) \
|
||||
|| (GET_CODE (X) == REG && XREG_OK_FOR_BASE_P (X, STRICT)) \
|
||||
|| (GET_CODE (X) == PLUS \
|
||||
&& GET_CODE (XEXP (X, 0)) == REG \
|
||||
&& XREG_OK_FOR_BASE_P (XEXP (X, 0), STRICT) \
|
||||
&& GET_CODE (XEXP (X, 1)) != SYMBOL_REF \
|
||||
&& ((flag_pic || TARGET_HALFPIC) \
|
||||
? GET_CODE (XEXP (X, 1)) == CONST_INT \
|
||||
: INDIRECTABLE_CONSTANT_ADDRESS_P (XEXP (X, 1)))) \
|
||||
|| (GET_CODE (X) == PLUS \
|
||||
&& GET_CODE (XEXP (X, 1)) == REG \
|
||||
&& XREG_OK_FOR_BASE_P (XEXP (X, 1), STRICT) \
|
||||
&& GET_CODE (XEXP (X, 0)) != SYMBOL_REF \
|
||||
&& ((flag_pic || TARGET_HALFPIC) \
|
||||
? GET_CODE (XEXP (X, 0)) == CONST_INT \
|
||||
: INDIRECTABLE_CONSTANT_ADDRESS_P (XEXP (X, 1)))))
|
||||
|
||||
#endif /* not NO_EXTERNAL_INDIRECT_ADDRESS */
|
||||
|
||||
/* Go to ADDR if X is a valid address not using indexing.
|
||||
(This much is the easy part.) */
|
||||
#define GO_IF_NONINDEXED_ADDRESS(X, ADDR, STRICT) \
|
||||
{ register rtx xfoob = (X); \
|
||||
if (GET_CODE (X) == REG) \
|
||||
{ \
|
||||
extern rtx *reg_equiv_mem; \
|
||||
if (! reload_in_progress \
|
||||
|| (xfoob = reg_equiv_mem[REGNO (X)]) == 0 \
|
||||
|| INDIRECTABLE_ADDRESS_P (xfoob, STRICT)) \
|
||||
goto ADDR; \
|
||||
} \
|
||||
if (INDIRECTABLE_CONSTANT_ADDRESS_P (X)) goto ADDR; \
|
||||
if (INDIRECTABLE_ADDRESS_P (X, STRICT)) goto ADDR; \
|
||||
xfoob = XEXP (X, 0); \
|
||||
if (GET_CODE (X) == MEM && INDIRECTABLE_ADDRESS_P (xfoob, STRICT)) \
|
||||
goto ADDR; \
|
||||
if ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \
|
||||
&& GET_CODE (xfoob) == REG \
|
||||
&& XREG_OK_FOR_BASE_P (xfoob, STRICT)) \
|
||||
goto ADDR; }
|
||||
|
||||
/* 1 if PROD is either a reg times size of mode MODE
|
||||
or just a reg, if MODE is just one byte.
|
||||
This macro's expansion uses the temporary variables xfoo0 and xfoo1
|
||||
that must be declared in the surrounding context. */
|
||||
#define INDEX_TERM_P(PROD, MODE, STRICT) \
|
||||
(GET_MODE_SIZE (MODE) == 1 \
|
||||
? (GET_CODE (PROD) == REG && XREG_OK_FOR_BASE_P (PROD, STRICT)) \
|
||||
: (GET_CODE (PROD) == MULT \
|
||||
&& \
|
||||
(xfoo0 = XEXP (PROD, 0), xfoo1 = XEXP (PROD, 1), \
|
||||
((GET_CODE (xfoo0) == CONST_INT \
|
||||
&& INTVAL (xfoo0) == GET_MODE_SIZE (MODE) \
|
||||
&& GET_CODE (xfoo1) == REG \
|
||||
&& XREG_OK_FOR_INDEX_P (xfoo1, STRICT)) \
|
||||
|| \
|
||||
(GET_CODE (xfoo1) == CONST_INT \
|
||||
&& INTVAL (xfoo1) == GET_MODE_SIZE (MODE) \
|
||||
&& GET_CODE (xfoo0) == REG \
|
||||
&& XREG_OK_FOR_INDEX_P (xfoo0, STRICT))))))
|
||||
|
||||
/* Go to ADDR if X is the sum of a register
|
||||
and a valid index term for mode MODE. */
|
||||
#define GO_IF_REG_PLUS_INDEX(X, MODE, ADDR, STRICT) \
|
||||
{ register rtx xfooa; \
|
||||
if (GET_CODE (X) == PLUS) \
|
||||
{ if (GET_CODE (XEXP (X, 0)) == REG \
|
||||
&& XREG_OK_FOR_BASE_P (XEXP (X, 0), STRICT) \
|
||||
&& (xfooa = XEXP (X, 1), \
|
||||
INDEX_TERM_P (xfooa, MODE, STRICT))) \
|
||||
goto ADDR; \
|
||||
if (GET_CODE (XEXP (X, 1)) == REG \
|
||||
&& XREG_OK_FOR_BASE_P (XEXP (X, 1), STRICT) \
|
||||
&& (xfooa = XEXP (X, 0), \
|
||||
INDEX_TERM_P (xfooa, MODE, STRICT))) \
|
||||
goto ADDR; } }
|
||||
|
||||
#define GO_IF_LEGITIMATE_ADDRESS2(MODE, X, ADDR, STRICT) \
|
||||
{ register rtx xfoo, xfoo0, xfoo1; \
|
||||
GO_IF_NONINDEXED_ADDRESS (X, ADDR, STRICT); \
|
||||
if (GET_CODE (X) == PLUS) \
|
||||
{ /* Handle <address>[index] represented with index-sum outermost */\
|
||||
xfoo = XEXP (X, 0); \
|
||||
if (INDEX_TERM_P (xfoo, MODE, STRICT)) \
|
||||
{ GO_IF_NONINDEXED_ADDRESS (XEXP (X, 1), ADDR, STRICT); } \
|
||||
xfoo = XEXP (X, 1); \
|
||||
if (INDEX_TERM_P (xfoo, MODE, STRICT)) \
|
||||
{ GO_IF_NONINDEXED_ADDRESS (XEXP (X, 0), ADDR, STRICT); } \
|
||||
/* Handle offset(reg)[index] with offset added outermost */ \
|
||||
if (INDIRECTABLE_CONSTANT_ADDRESS_P (XEXP (X, 0))) \
|
||||
{ if (GET_CODE (XEXP (X, 1)) == REG \
|
||||
&& XREG_OK_FOR_BASE_P (XEXP (X, 1), STRICT)) \
|
||||
goto ADDR; \
|
||||
GO_IF_REG_PLUS_INDEX (XEXP (X, 1), MODE, ADDR, STRICT); } \
|
||||
if (INDIRECTABLE_CONSTANT_ADDRESS_P (XEXP (X, 1))) \
|
||||
{ if (GET_CODE (XEXP (X, 0)) == REG \
|
||||
&& XREG_OK_FOR_BASE_P (XEXP (X, 0), STRICT)) \
|
||||
goto ADDR; \
|
||||
GO_IF_REG_PLUS_INDEX (XEXP (X, 0), MODE, ADDR, STRICT); } } }
|
||||
|
||||
|
||||
int
|
||||
legitimate_pic_operand_p(xbar, strict)
|
||||
register rtx xbar;
|
||||
int strict;
|
||||
{
|
||||
if (GET_CODE (xbar) == PLUS
|
||||
&& ((GET_CODE (XEXP (xbar, 1)) == SYMBOL_REF
|
||||
&& GET_CODE (XEXP (xbar, 0)) == REG)
|
||||
|| (GET_CODE (XEXP (xbar, 0)) == SYMBOL_REF
|
||||
&& GET_CODE (XEXP (xbar, 1)) == REG)
|
||||
|| (GET_CODE (XEXP (xbar, 0)) == MULT
|
||||
&& GET_CODE (XEXP (xbar, 1)) == MEM)))
|
||||
return 0;
|
||||
return INDIRECTABLE_CONSTANT_P (xbar);
|
||||
}
|
||||
/*
|
||||
* reg
|
||||
* plus( reg , const_int )
|
||||
* plus( reg , plus (const_int, reg))
|
||||
*/
|
||||
int
|
||||
legitimate_address_p(mode, xbar, strict)
|
||||
enum machine_mode mode;
|
||||
register rtx xbar;
|
||||
int strict;
|
||||
{
|
||||
if (flag_pic && !legitimate_pic_operand_p(xbar, mode))
|
||||
return 0;
|
||||
GO_IF_LEGITIMATE_ADDRESS2(mode, xbar, win, strict);
|
||||
return 0;
|
||||
win:
|
||||
if (flag_pic)
|
||||
{
|
||||
if (GET_CODE (xbar) == PLUS
|
||||
&& ((GET_CODE (XEXP (xbar, 1)) == SYMBOL_REF
|
||||
&& GET_CODE (XEXP (xbar, 0)) == REG)
|
||||
|| (GET_CODE (XEXP (xbar, 0)) == SYMBOL_REF
|
||||
&& GET_CODE (XEXP (xbar, 1)) == REG)))
|
||||
return 0;
|
||||
}
|
||||
if (TARGET_DEBUGADDR
|
||||
&& GET_CODE (xbar) != REG
|
||||
&& GET_CODE (xbar) != PRE_DEC
|
||||
&& GET_CODE (xbar) != POST_INC
|
||||
&& GET_CODE (xbar) != SYMBOL_REF
|
||||
&& !(GET_CODE (xbar) == PLUS
|
||||
&& ((GET_CODE (XEXP (xbar, 1)) == CONST_INT
|
||||
&& (GET_CODE (XEXP (xbar, 0)) == REG
|
||||
|| (GET_CODE (XEXP (xbar, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (xbar, 0), 0)) == REG
|
||||
&& GET_CODE (XEXP (XEXP (xbar, 0), 1)) == REG)))
|
||||
|| (GET_CODE (XEXP (xbar, 1)) == REG
|
||||
&& GET_CODE (XEXP (xbar, 0)) == CONST_INT))))
|
||||
{
|
||||
fprintf(stderr, "===== Legitimate Address Operand\n");
|
||||
debug_rtx(xbar);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Like memory_operand exit when pic where
|
||||
* we can't allow a double derefernce.
|
||||
*/
|
||||
int
|
||||
call_operand (op, mode)
|
||||
register rtx op;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
if (!memory_operand (op, mode))
|
||||
return 0;
|
||||
if ((flag_pic || TARGET_HALFPIC) && GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == MEM)
|
||||
return 0;
|
||||
if (TARGET_DEBUGADDR)
|
||||
{
|
||||
fprintf(stderr, "===== Call Operand\n");
|
||||
debug_rtx(op);
|
||||
}
|
||||
#if 0
|
||||
debug_rtx(op);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
compare_operand (op, mode)
|
||||
register rtx op;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
if (!general_operand (op, mode))
|
||||
return 0;
|
||||
if (!(flag_pic || TARGET_HALFPIC))
|
||||
return 1;
|
||||
if (GET_CODE (op) == PLUS
|
||||
&& ((GET_CODE (XEXP (op, 1)) == SYMBOL_REF
|
||||
&& GET_CODE (XEXP (op, 0)) == REG)
|
||||
|| (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
|
||||
&& GET_CODE (XEXP (op, 1)) == REG)))
|
||||
return 0;
|
||||
if (!INDIRECTABLE_CONSTANT_P (op))
|
||||
return 0;
|
||||
if (TARGET_DEBUGADDR)
|
||||
{
|
||||
fprintf(stderr, "===== Compare Operand\n");
|
||||
debug_rtx(op);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Returns 1 if OP is a sum of a symbol reference and a constant. */
|
||||
|
||||
int
|
||||
symbolic_operand (op, mode)
|
||||
register rtx op;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
return !INDIRECTABLE_CONSTANT_P (op);
|
||||
}
|
||||
|
||||
/* Legitimize PIC addresses. If the address is already
|
||||
position-independent, we return ORIG. Newly generated
|
||||
position-independent addresses go to REG. If we need more
|
||||
than one register, we lose.
|
||||
|
||||
An address is legitimized by making an indirect reference
|
||||
through the Global Offset Table with the name of the symbol
|
||||
used as an offset.
|
||||
|
||||
The assembler/loader are responsible for translating a symbol name
|
||||
into a PC-relative displacement.
|
||||
|
||||
A quick example may make things a little clearer:
|
||||
|
||||
When not generating PIC code to store the value 12345 into _foo+4
|
||||
we would generate the following code:
|
||||
|
||||
movl $12345, _foo+4
|
||||
|
||||
When generating PIC a transformation is made. First, the compiler
|
||||
loads the address of foo into a register. So the transformation makes:
|
||||
|
||||
movab _foo, r0
|
||||
movl $12345, 4(r0)
|
||||
|
||||
That (in a nutshell) is how *all* symbol references are handled. */
|
||||
|
||||
rtx
|
||||
legitimize_pic_address (orig, mode, reg)
|
||||
rtx orig, reg;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
rtx pic_ref = orig;
|
||||
|
||||
/* fprintf(stderr, "before: "); debug_rtx(orig); */
|
||||
if (GET_CODE (orig) == SYMBOL_REF)
|
||||
{
|
||||
emit_move_insn (reg, orig);
|
||||
pic_ref = reg;
|
||||
}
|
||||
else if (GET_CODE (orig) == CONST)
|
||||
{
|
||||
rtx base;
|
||||
|
||||
if (reg == 0)
|
||||
abort ();
|
||||
|
||||
/* legitimize both operands of the PLUS */
|
||||
if (GET_CODE (XEXP (orig, 0)) == PLUS)
|
||||
{
|
||||
base = XEXP (XEXP (orig, 0), 0);
|
||||
if (GET_CODE (base) == SYMBOL_REF)
|
||||
{
|
||||
emit_move_insn (reg, base);
|
||||
base = reg;
|
||||
}
|
||||
orig = XEXP (XEXP (orig, 0), 1);
|
||||
if (GET_CODE (orig) == SYMBOL_REF)
|
||||
{
|
||||
if (base == reg)
|
||||
abort();
|
||||
emit_move_insn (reg, orig);
|
||||
orig = reg;
|
||||
}
|
||||
}
|
||||
else abort ();
|
||||
|
||||
if (GET_CODE (orig) == CONST_INT)
|
||||
pic_ref = plus_constant_for_output (base, INTVAL (orig));
|
||||
else
|
||||
pic_ref = gen_rtx_PLUS (Pmode, base, orig);
|
||||
/* Likewise, should we set special REG_NOTEs here? */
|
||||
}
|
||||
/* fprintf(stderr, "after: "); debug_rtx(pic_ref); */
|
||||
return pic_ref;
|
||||
}
|
||||
|
||||
#ifdef VMS_TARGET
|
||||
/* Additional support code for VMS target. */
|
||||
|
||||
|
163
gnu/dist/gcc/config/vax/vax.h
vendored
163
gnu/dist/gcc/config/vax/vax.h
vendored
@ -59,6 +59,15 @@ extern int target_flags;
|
||||
/* Nonzero if compiling with `G'-format floating point */
|
||||
#define TARGET_G_FLOAT (target_flags & 4)
|
||||
|
||||
/* Nonzero if compiling for a CVAX or later */
|
||||
#define TARGET_CVAX (target_flags & 8)
|
||||
|
||||
/* Nonzero if compiling in half-pic mode */
|
||||
#define TARGET_HALFPIC (target_flags & 16)
|
||||
|
||||
/* printout debugging info */
|
||||
#define TARGET_DEBUGADDR (target_flags & 32)
|
||||
|
||||
/* Macro to define tables used to set the flags.
|
||||
This is a list in braces of pairs in braces,
|
||||
each pair being { "NAME", VALUE }
|
||||
@ -73,6 +82,10 @@ extern int target_flags;
|
||||
{"g-float", 4}, \
|
||||
{"d", -4}, \
|
||||
{"d-float", -4}, \
|
||||
{"cvax", 8}, \
|
||||
{"half-pic", 16}, \
|
||||
{"no-pic", -16}, \
|
||||
{"debug-addr", 32}, \
|
||||
{ "", TARGET_DEFAULT}}
|
||||
|
||||
/* Default target_flags if no switches specified. */
|
||||
@ -614,6 +627,9 @@ gen_rtx (PLUS, Pmode, frame, GEN_INT (12))
|
||||
|
||||
#define LEGITIMATE_CONSTANT_P(X) 1
|
||||
|
||||
extern int legitimate_pic_operand_p();
|
||||
extern int legitimate_address_p();
|
||||
|
||||
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
|
||||
and check its validity for a certain class.
|
||||
We have two alternate definitions for each of them.
|
||||
@ -632,154 +648,31 @@ gen_rtx (PLUS, Pmode, frame, GEN_INT (12))
|
||||
/* Nonzero if X is a hard reg that can be used as an index
|
||||
or if it is a pseudo reg. */
|
||||
#define REG_OK_FOR_INDEX_P(X) 1
|
||||
|
||||
/* Nonzero if X is a hard reg that can be used as a base reg
|
||||
or if it is a pseudo reg. */
|
||||
#define REG_OK_FOR_BASE_P(X) 1
|
||||
|
||||
#define LEGITIMATE_PIC_OPERAND_P(X) (legitimate_pic_operand_p (X, 0))
|
||||
|
||||
#define GO_IF_LEGITIMATE_ADDRESS(ZMODE, XOP, LABEL) \
|
||||
{ if (legitimate_address_p(ZMODE, XOP, 0)) goto LABEL; }
|
||||
|
||||
#else
|
||||
|
||||
/* Nonzero if X is a hard reg that can be used as an index. */
|
||||
#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
|
||||
|
||||
/* Nonzero if X is a hard reg that can be used as a base reg. */
|
||||
#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
|
||||
|
||||
#define LEGITIMATE_PIC_OPERAND_P(X) (legitimate_pic_operand_p (X, 1))
|
||||
|
||||
#define GO_IF_LEGITIMATE_ADDRESS(ZMODE, XOP, LABEL) \
|
||||
{ if (legitimate_address_p(ZMODE, XOP, 1)) goto LABEL; }
|
||||
|
||||
#endif
|
||||
|
||||
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
|
||||
that is a valid memory address for an instruction.
|
||||
The MODE argument is the machine mode for the MEM expression
|
||||
that wants to use this address.
|
||||
|
||||
The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS,
|
||||
except for CONSTANT_ADDRESS_P which is actually machine-independent. */
|
||||
|
||||
#ifdef NO_EXTERNAL_INDIRECT_ADDRESS
|
||||
|
||||
/* Zero if this contains a (CONST (PLUS (SYMBOL_REF) (...))) and the
|
||||
symbol in the SYMBOL_REF is an external symbol. */
|
||||
|
||||
#define INDIRECTABLE_CONSTANT_P(X) \
|
||||
(! (GET_CODE ((X)) == CONST \
|
||||
&& GET_CODE (XEXP ((X), 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP ((X), 0), 0)) == SYMBOL_REF \
|
||||
&& SYMBOL_REF_FLAG (XEXP (XEXP ((X), 0), 0))))
|
||||
|
||||
/* Re-definition of CONSTANT_ADDRESS_P, which is true only when there
|
||||
are no SYMBOL_REFs for external symbols present. */
|
||||
|
||||
#define INDIRECTABLE_CONSTANT_ADDRESS_P(X) \
|
||||
(GET_CODE (X) == LABEL_REF \
|
||||
|| (GET_CODE (X) == SYMBOL_REF && !SYMBOL_REF_FLAG (X)) \
|
||||
|| (GET_CODE (X) == CONST && INDIRECTABLE_CONSTANT_P(X)) \
|
||||
|| GET_CODE (X) == CONST_INT)
|
||||
|
||||
|
||||
/* Non-zero if X is an address which can be indirected. External symbols
|
||||
could be in a sharable image library, so we disallow those. */
|
||||
|
||||
#define INDIRECTABLE_ADDRESS_P(X) \
|
||||
(INDIRECTABLE_CONSTANT_ADDRESS_P (X) \
|
||||
|| (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
|
||||
|| (GET_CODE (X) == PLUS \
|
||||
&& GET_CODE (XEXP (X, 0)) == REG \
|
||||
&& REG_OK_FOR_BASE_P (XEXP (X, 0)) \
|
||||
&& INDIRECTABLE_CONSTANT_ADDRESS_P (XEXP (X, 1))))
|
||||
|
||||
#else /* not NO_EXTERNAL_INDIRECT_ADDRESS */
|
||||
|
||||
#define INDIRECTABLE_CONSTANT_ADDRESS_P(X) CONSTANT_ADDRESS_P(X)
|
||||
|
||||
/* Non-zero if X is an address which can be indirected. */
|
||||
#define INDIRECTABLE_ADDRESS_P(X) \
|
||||
(CONSTANT_ADDRESS_P (X) \
|
||||
|| (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
|
||||
|| (GET_CODE (X) == PLUS \
|
||||
&& GET_CODE (XEXP (X, 0)) == REG \
|
||||
&& REG_OK_FOR_BASE_P (XEXP (X, 0)) \
|
||||
&& CONSTANT_ADDRESS_P (XEXP (X, 1))))
|
||||
|
||||
#endif /* not NO_EXTERNAL_INDIRECT_ADDRESS */
|
||||
|
||||
/* Go to ADDR if X is a valid address not using indexing.
|
||||
(This much is the easy part.) */
|
||||
#define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \
|
||||
{ register rtx xfoob = (X); \
|
||||
if (GET_CODE (xfoob) == REG) \
|
||||
{ \
|
||||
extern rtx *reg_equiv_mem; \
|
||||
if (! reload_in_progress \
|
||||
|| reg_equiv_mem[REGNO (xfoob)] == 0 \
|
||||
|| INDIRECTABLE_ADDRESS_P (reg_equiv_mem[REGNO (xfoob)])) \
|
||||
goto ADDR; \
|
||||
} \
|
||||
if (CONSTANT_ADDRESS_P (xfoob)) goto ADDR; \
|
||||
if (INDIRECTABLE_ADDRESS_P (xfoob)) goto ADDR; \
|
||||
xfoob = XEXP (X, 0); \
|
||||
if (GET_CODE (X) == MEM && INDIRECTABLE_ADDRESS_P (xfoob)) \
|
||||
goto ADDR; \
|
||||
if ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \
|
||||
&& GET_CODE (xfoob) == REG && REG_OK_FOR_BASE_P (xfoob)) \
|
||||
goto ADDR; }
|
||||
|
||||
/* 1 if PROD is either a reg times size of mode MODE
|
||||
or just a reg, if MODE is just one byte.
|
||||
This macro's expansion uses the temporary variables xfoo0 and xfoo1
|
||||
that must be declared in the surrounding context. */
|
||||
#define INDEX_TERM_P(PROD, MODE) \
|
||||
(GET_MODE_SIZE (MODE) == 1 \
|
||||
? (GET_CODE (PROD) == REG && REG_OK_FOR_BASE_P (PROD)) \
|
||||
: (GET_CODE (PROD) == MULT \
|
||||
&& \
|
||||
(xfoo0 = XEXP (PROD, 0), xfoo1 = XEXP (PROD, 1), \
|
||||
((GET_CODE (xfoo0) == CONST_INT \
|
||||
&& INTVAL (xfoo0) == GET_MODE_SIZE (MODE) \
|
||||
&& GET_CODE (xfoo1) == REG \
|
||||
&& REG_OK_FOR_INDEX_P (xfoo1)) \
|
||||
|| \
|
||||
(GET_CODE (xfoo1) == CONST_INT \
|
||||
&& INTVAL (xfoo1) == GET_MODE_SIZE (MODE) \
|
||||
&& GET_CODE (xfoo0) == REG \
|
||||
&& REG_OK_FOR_INDEX_P (xfoo0))))))
|
||||
|
||||
/* Go to ADDR if X is the sum of a register
|
||||
and a valid index term for mode MODE. */
|
||||
#define GO_IF_REG_PLUS_INDEX(X, MODE, ADDR) \
|
||||
{ register rtx xfooa; \
|
||||
if (GET_CODE (X) == PLUS) \
|
||||
{ if (GET_CODE (XEXP (X, 0)) == REG \
|
||||
&& REG_OK_FOR_BASE_P (XEXP (X, 0)) \
|
||||
&& (xfooa = XEXP (X, 1), \
|
||||
INDEX_TERM_P (xfooa, MODE))) \
|
||||
goto ADDR; \
|
||||
if (GET_CODE (XEXP (X, 1)) == REG \
|
||||
&& REG_OK_FOR_BASE_P (XEXP (X, 1)) \
|
||||
&& (xfooa = XEXP (X, 0), \
|
||||
INDEX_TERM_P (xfooa, MODE))) \
|
||||
goto ADDR; } }
|
||||
|
||||
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
|
||||
{ register rtx xfoo, xfoo0, xfoo1; \
|
||||
GO_IF_NONINDEXED_ADDRESS (X, ADDR); \
|
||||
if (GET_CODE (X) == PLUS) \
|
||||
{ /* Handle <address>[index] represented with index-sum outermost */\
|
||||
xfoo = XEXP (X, 0); \
|
||||
if (INDEX_TERM_P (xfoo, MODE)) \
|
||||
{ GO_IF_NONINDEXED_ADDRESS (XEXP (X, 1), ADDR); } \
|
||||
xfoo = XEXP (X, 1); \
|
||||
if (INDEX_TERM_P (xfoo, MODE)) \
|
||||
{ GO_IF_NONINDEXED_ADDRESS (XEXP (X, 0), ADDR); } \
|
||||
/* Handle offset(reg)[index] with offset added outermost */ \
|
||||
if (INDIRECTABLE_CONSTANT_ADDRESS_P (XEXP (X, 0))) \
|
||||
{ if (GET_CODE (XEXP (X, 1)) == REG \
|
||||
&& REG_OK_FOR_BASE_P (XEXP (X, 1))) \
|
||||
goto ADDR; \
|
||||
GO_IF_REG_PLUS_INDEX (XEXP (X, 1), MODE, ADDR); } \
|
||||
if (INDIRECTABLE_CONSTANT_ADDRESS_P (XEXP (X, 1))) \
|
||||
{ if (GET_CODE (XEXP (X, 0)) == REG \
|
||||
&& REG_OK_FOR_BASE_P (XEXP (X, 0))) \
|
||||
goto ADDR; \
|
||||
GO_IF_REG_PLUS_INDEX (XEXP (X, 0), MODE, ADDR); } } }
|
||||
|
||||
/* Try machine-dependent ways of modifying an illegitimate address
|
||||
to be legitimate. If we find one, return the new, valid address.
|
||||
This macro is used in only one place: `memory_address' in explow.c.
|
||||
|
116
gnu/dist/gcc/config/vax/vax.md
vendored
116
gnu/dist/gcc/config/vax/vax.md
vendored
@ -61,12 +61,36 @@
|
||||
""
|
||||
"tstf %0")
|
||||
|
||||
(define_insn "cmpsi"
|
||||
(define_expand "cmpsi"
|
||||
[(set (cc0)
|
||||
(compare (match_operand:SI 0 "nonimmediate_operand" "g")
|
||||
(match_operand:SI 1 "general_operand" "g")))]
|
||||
(match_operand:SI 1 "compare_operand" "g")))]
|
||||
""
|
||||
"cmpl %0,%1")
|
||||
"
|
||||
{
|
||||
if ((TARGET_HALFPIC || flag_pic) && symbolic_operand (operands[1], SImode))
|
||||
{
|
||||
/* The source is an address which requires PIC relocation.
|
||||
Call legitimize_pic_address with the source, mode, and a relocation
|
||||
register (a new pseudo, or the final destination if reload_in_progress
|
||||
is set). Then fall through normally */
|
||||
extern rtx legitimize_pic_address();
|
||||
rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
|
||||
operands[1] = legitimize_pic_address (operands[1], SImode, temp);
|
||||
}
|
||||
}")
|
||||
|
||||
(define_insn ""
|
||||
[(set (cc0)
|
||||
(compare (match_operand:SI 0 "nonimmediate_operand" "g")
|
||||
(match_operand:SI 1 "compare_operand" "g")))]
|
||||
""
|
||||
"*
|
||||
{
|
||||
if (!(/*TARGET_HALFPIC || */flag_pic) || GET_CODE (operands[1]) != SYMBOL_REF)
|
||||
return \"cmpl %0,%1\";
|
||||
return \"pushab %a1;cmpl %0,(sp)+\";
|
||||
}")
|
||||
|
||||
(define_insn "cmphi"
|
||||
[(set (cc0)
|
||||
@ -178,6 +202,34 @@
|
||||
clrq %0
|
||||
movq %D1,%0")
|
||||
|
||||
|
||||
;; General case of fullword move.
|
||||
;;
|
||||
;; This is the main "hook" for PIC code. When generating
|
||||
;; PIC, movsi is responsible for determining when the source address
|
||||
;; needs PIC relocation and appropriately calling legitimize_pic_address
|
||||
;; to perform the actual relocation.
|
||||
;;
|
||||
;; In both the PIC and non-PIC cases the patterns generated will
|
||||
;; matched by the next define_insn.
|
||||
(define_expand "movsi"
|
||||
[(set (match_operand:SI 0 "general_operand" "")
|
||||
(match_operand:SI 1 "general_operand" ""))]
|
||||
""
|
||||
"
|
||||
{
|
||||
if ((TARGET_HALFPIC || flag_pic) && symbolic_operand (operands[1], SImode))
|
||||
{
|
||||
/* The source is an address which requires PIC relocation.
|
||||
Call legitimize_pic_address with the source, mode, and a relocation
|
||||
register (a new pseudo, or the final destination if reload_in_progress
|
||||
is set). Then fall through normally */
|
||||
extern rtx legitimize_pic_address();
|
||||
rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
|
||||
operands[1] = legitimize_pic_address (operands[1], SImode, temp);
|
||||
}
|
||||
}")
|
||||
|
||||
;; The VAX move instructions have space-time tradeoffs. On a microVAX
|
||||
;; register-register mov instructions take 3 bytes and 2 CPU cycles. clrl
|
||||
;; takes 2 bytes and 3 cycles. mov from constant to register takes 2 cycles
|
||||
@ -194,8 +246,7 @@
|
||||
|
||||
;; Loads of constants between 64 and 128 used to be done with
|
||||
;; "addl3 $63,#,dst" but this is slower than movzbl and takes as much space.
|
||||
|
||||
(define_insn "movsi"
|
||||
(define_insn ""
|
||||
[(set (match_operand:SI 0 "general_operand" "=g")
|
||||
(match_operand:SI 1 "general_operand" "g"))]
|
||||
""
|
||||
@ -571,10 +622,18 @@
|
||||
&& ((INTVAL (operands[2]) < 32767 && INTVAL (operands[2]) > -32768)
|
||||
|| REGNO (operands[1]) > 11))
|
||||
return \"movab %c2(%1),%0\";
|
||||
if (GET_CODE (operands[2]) == SYMBOL_REF
|
||||
&& GET_CODE (operands[1]) == REG)
|
||||
return \"movab %a2[%1],%0\";
|
||||
return \"addl2 %2,%0\";
|
||||
}
|
||||
if (rtx_equal_p (operands[0], operands[2]))
|
||||
return \"addl2 %1,%0\";
|
||||
{
|
||||
if (GET_CODE (operands[1]) == SYMBOL_REF
|
||||
&& GET_CODE (operands[2]) == REG)
|
||||
return \"movab %a1[%2],%0\";
|
||||
return \"addl2 %1,%0\";
|
||||
}
|
||||
|
||||
if (GET_CODE (operands[2]) == CONST_INT
|
||||
&& INTVAL (operands[2]) < 32767
|
||||
@ -594,10 +653,41 @@
|
||||
|| REGNO (operands[1]) > 11))
|
||||
return \"movab %c2(%1),%0\";
|
||||
|
||||
/* Add this if using gcc on a VAX 3xxx:
|
||||
if (REG_P (operands[1]) && REG_P (operands[2]))
|
||||
if (TARGET_CVAX && REG_P (operands[1]) && REG_P (operands[2]))
|
||||
return \"movab (%1)[%2],%0\";
|
||||
*/
|
||||
|
||||
if ((TARGET_HALFPIC || flag_pic) && GET_CODE (operands[1]) == SYMBOL_REF)
|
||||
{
|
||||
if (push_operand(operands[0], SImode))
|
||||
{
|
||||
if (REG_P (operands[2]))
|
||||
return \"pushab %a1[%2]\";
|
||||
return \"pushab %a1;addl2 %2,(sp)\";
|
||||
}
|
||||
if (GET_CODE (operands[2]) == REG)
|
||||
return \"movab %a1[%2],%0\";
|
||||
if (GET_CODE (operands[0]) != POST_INC
|
||||
&& GET_CODE (operands[0]) != PRE_DEC)
|
||||
return \"movab %a1,%0;addl2 %2,%0\";
|
||||
return \"nop;addl3 %1,%2,%0\";
|
||||
}
|
||||
|
||||
if ((TARGET_HALFPIC || flag_pic) && GET_CODE (operands[2]) == SYMBOL_REF)
|
||||
{
|
||||
if (push_operand(operands[0], SImode))
|
||||
{
|
||||
if (REG_P (operands[1]))
|
||||
return \"pushab %a2[%1]\";
|
||||
return \"pushab %a2;addl2 %1,(sp)\";
|
||||
}
|
||||
if (GET_CODE (operands[1]) == REG)
|
||||
return \"movab %a2[%1],%0\";
|
||||
if (GET_CODE (operands[0]) != POST_INC
|
||||
&& GET_CODE (operands[0]) != PRE_DEC)
|
||||
return \"movab %a2,%0;addl2 %1,%0\";
|
||||
return \"nop;addl3 %1,%2,%0\";
|
||||
}
|
||||
|
||||
return \"addl3 %1,%2,%0\";
|
||||
}")
|
||||
|
||||
@ -1841,7 +1931,7 @@
|
||||
;; a word. Since the only time we actually use it in the call instruction
|
||||
;; is when it is a constant, SImode (for addl2) is the proper mode.
|
||||
(define_insn "call_pop"
|
||||
[(call (match_operand:QI 0 "memory_operand" "m")
|
||||
[(call (match_operand:QI 0 "call_operand" "m")
|
||||
(match_operand:SI 1 "const_int_operand" "n"))
|
||||
(set (reg:SI 14) (plus:SI (reg:SI 14)
|
||||
(match_operand:SI 3 "immediate_operand" "i")))]
|
||||
@ -1856,7 +1946,7 @@
|
||||
|
||||
(define_insn "call_value_pop"
|
||||
[(set (match_operand 0 "" "=g")
|
||||
(call (match_operand:QI 1 "memory_operand" "m")
|
||||
(call (match_operand:QI 1 "call_operand" "m")
|
||||
(match_operand:SI 2 "const_int_operand" "n")))
|
||||
(set (reg:SI 14) (plus:SI (reg:SI 14)
|
||||
(match_operand:SI 4 "immediate_operand" "i")))]
|
||||
@ -1872,7 +1962,7 @@
|
||||
;; Define another set of these for the case of functions with no
|
||||
;; operands. In that case, combine may simplify the adjustment of sp.
|
||||
(define_insn ""
|
||||
[(call (match_operand:QI 0 "memory_operand" "m")
|
||||
[(call (match_operand:QI 0 "call_operand" "m")
|
||||
(match_operand:SI 1 "const_int_operand" "n"))
|
||||
(set (reg:SI 14) (reg:SI 14))]
|
||||
""
|
||||
@ -1886,7 +1976,7 @@
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand 0 "" "=g")
|
||||
(call (match_operand:QI 1 "memory_operand" "m")
|
||||
(call (match_operand:QI 1 "call_operand" "m")
|
||||
(match_operand:SI 2 "const_int_operand" "n")))
|
||||
(set (reg:SI 14) (reg:SI 14))]
|
||||
""
|
||||
|
Loading…
x
Reference in New Issue
Block a user