/* Definitions of target machine for GNU compiler, for AMD Am29000 CPU.
- Copyright (C) 1988, 1990, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@nyu.edu)
This file is part of GNU CC.
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. */
/* Names to predefine in the preprocessor for this target machine. */
-#define CPP_PREDEFINES "-D_AM29K -D_AM29000 -D_EPI"
+#define CPP_PREDEFINES "-D_AM29K -D_AM29000 -D_EPI -Acpu=a29k -Amachine=a29k"
/* Print subsidiary information on the compiler version in use. */
#define TARGET_VERSION
#define TARGET_SMALL_MEMORY (target_flags & 4)
+/* This means that we must always used on indirect call, even when
+ calling a function in the same file, since the file might be > 256KB. */
+
+#define TARGET_LARGE_MEMORY (target_flags & 8)
+
/* This means that we are compiling for a 29050. */
-#define TARGET_29050 (target_flags & 8)
+#define TARGET_29050 (target_flags & 16)
/* This means that we are compiling for the kernel which means that we use
gr64-gr95 instead of gr96-126. */
-#define TARGET_KERNEL_REGISTERS (target_flags & 16)
+#define TARGET_KERNEL_REGISTERS (target_flags & 32)
/* This means that a call to "__msp_check" should be inserted after each stack
adjustment to check for stack overflow. */
-#define TARGET_STACK_CHECK (target_flags & 32)
+#define TARGET_STACK_CHECK (target_flags & 64)
/* This handles 29k processors which cannot handle the separation
of a mtsrim insns and a storem insn (most 29000 chips to date, but
not the 29050. */
-#define TARGET_NO_STOREM_BUG (target_flags & 64)
+#define TARGET_NO_STOREM_BUG (target_flags & 128)
/* This forces the compiler not to use incoming argument registers except
for copying out arguments. It helps detect problems when a function is
called with fewer arguments than it is declared with. */
-#define TARGET_NO_REUSE_ARGS (target_flags & 128)
+#define TARGET_NO_REUSE_ARGS (target_flags & 256)
+
+/* This means that neither builtin nor emulated float operations are
+ available, and that GCC should generate libcalls instead. */
+
+#define TARGET_SOFT_FLOAT (target_flags & 512)
+
+/* This means that we should not emit the multm or mutmu instructions
+ that some embedded systems' trap handlers don't support. */
+
+#define TARGET_MULTM ((target_flags & 1024) == 0)
#define TARGET_SWITCHES \
- { {"dw", 1}, \
- {"ndw", -1}, \
- {"bw", 2}, \
- {"nbw", - (1|2)}, \
- {"small", 4}, \
- {"large", -4}, \
- {"29050", 8+64}, \
- {"29000", -8}, \
- {"kernel-registers", 16}, \
- {"user-registers", -16}, \
- {"stack-check", 32}, \
- {"no-storem-bug", 64}, \
- {"reuse-arg-regs", -128}, \
- {"no-reuse-arg-regs", 128}, \
- {"", TARGET_DEFAULT}}
+ { {"dw", 1, N_("Generate code assuming DW bit is set")}, \
+ {"ndw", -1, N_("Generate code assuming DW bit is not set")}, \
+ {"bw", 2, N_("Generate code using byte writes")}, \
+ {"nbw", - (1|2), N_("Do not generate byte writes")}, \
+ {"small", 4, N_("Use small memory model")}, \
+ {"normal", - (4|8), N_("Use normal memory model")}, \
+ {"large", 8, N_("Use large memory model")}, \
+ {"29050", 16+128, N_("Generate 29050 code")}, \
+ {"29000", -16, N_("Generate 29000 code")}, \
+ {"kernel-registers", 32, N_("Use kernel global registers")}, \
+ {"user-registers", -32, N_("Use user global registers")}, \
+ {"stack-check", 64, N_("Emit stack checking code")}, \
+ {"no-stack-check", - 74, N_("Do not emit stack checking code")}, \
+ {"storem-bug", -128, N_("Work around storem hardware bug")}, \
+ {"no-storem-bug", 128, N_("Do not work around storem hardware bug")}, \
+ {"reuse-arg-regs", -256, N_("Store locals in argument registers")}, \
+ {"no-reuse-arg-regs", 256, N_("Do not store locals in arg registers")}, \
+ {"soft-float", 512, N_("Use software floating point")}, \
+ {"no-multm", 1024, N_("Do not generate multm instructions")}, \
+ {"", TARGET_DEFAULT, NULL}}
#define TARGET_DEFAULT 3
-/* Define this to change the optimizations peformed by default. */
-
-#define OPTIMIZATION_OPTIONS(LEVEL) \
-{ \
- if ((LEVEL) > 0) \
- { \
- flag_force_addr = 1; \
- flag_force_mem = 1; \
- flag_omit_frame_pointer = 1; \
- } \
-}
+/* Show we can debug even without a frame pointer. */
+#define CAN_DEBUG_WITHOUT_FP
\f
/* target machine storage layout */
#define WCHAR_TYPE "char"
#define WCHAR_TYPE_SIZE BITS_PER_UNIT
+/* Define this macro if it is advisable to hold scalars in registers
+ in a wider mode than that declared by the program. In such cases,
+ the value is constrained to be within the bounds of the declared
+ type, but kept valid in the wider mode. The signedness of the
+ extension may differ from that of the type. */
+
+#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \
+ if (GET_MODE_CLASS (MODE) == MODE_INT \
+ && GET_MODE_SIZE (MODE) < 4) \
+ (MODE) = SImode;
+
/* Define this if most significant bit is lowest numbered
in instructions that operate on numbered bit-fields.
This is arbitrary on the 29k since it has no actual bit-field insns.
numbered.
For 29k we can decide arbitrarily since there are no machine instructions
- for them. Might as well be consistent with bytes. */
+ for them. Might as well be consistent with bytes. */
#define WORDS_BIG_ENDIAN 1
-/* number of bits in an addressible storage unit */
-#define BITS_PER_UNIT 8
-
/* Width in bits of a "word", which is the contents of a machine register.
Note that this is not necessarily the width of data type `int';
if using 16-bit ints on a 68000, this would still be 32.
/* Every structure's size must be a multiple of this. */
#define STRUCTURE_SIZE_BOUNDARY 8
+/* A bitfield declared as `int' forces `int' alignment for the struct. */
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
/* No data type wants to be aligned rounder than this. */
#define BIGGEST_ALIGNMENT 32
&& TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
&& (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
-/* Define this if move instructions will actually fail to work
+/* Set this non-zero if move instructions will actually fail to work
when given unaligned data. */
-/* #define STRICT_ALIGNMENT */
+#define STRICT_ALIGNMENT 0
-/* Define this if unaligned move instructions are extremely slow.
+/* Set this non-zero if unaligned move instructions are extremely slow.
On the 29k, they trap. */
-#define SLOW_UNALIGNED_ACCESS
+#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) 1
\f
/* Standard register usage. */
Registers 200-203 are the four floating-point accumulator register in
the 29050.
+ Registers 204-235 are the 32 global registers for kernel mode when
+ -mkernel-registers is not specified, and the 32 global user registers
+ when it is.
+
When -mkernel-registers is specified, we still use the same register
map but change the names so 0-31 print as gr64-gr95. */
-#define FIRST_PSEUDO_REGISTER 204
+#define FIRST_PSEUDO_REGISTER 236
/* Because of the large number of registers on the 29k, we define macros
to refer to each group of registers and then define the number for some
#define R_LR(N) ((N) + 32) /* lr0 is register number 32 */
#define R_FP 176 /* frame pointer is register 176 */
#define R_AR(N) ((N) + 160) /* first incoming arg reg is 160 */
+#define R_KR(N) ((N) + 204) /* kernel registers (gr64 to gr95) */
/* Define the numbers of the special registers. */
#define R_BP 177
#define R_EXO 199
/* Define the number for floating-point accumulator N. */
-#define R_ACC(N) ((N) + 200)
+#define R_ACU(N) ((N) + 200)
/* Now define the registers used in the calling sequence. */
#define R_TAV R_GR (121)
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, \
- 0, 0, 0, 0 }
+ 0, 0, 0, 0, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
#define CALL_USED_REGISTERS \
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
- 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1 }
+ 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
/* List the order in which to allocate registers. Each register must be
listed once, even those in FIXED_REGISTERS.
R_LR (117), R_LR (118), R_LR (119), R_LR (120), R_LR (121), \
R_LR (122), R_LR (123), R_LR (124), R_LR (124), R_LR (126), \
R_LR (127), \
- R_ACC (3), R_ACC (2), R_ACC (1), R_ACC (0), \
+ R_ACU (3), R_ACU (2), R_ACU (1), R_ACU (0), \
R_GR (112), R_GR (113), R_GR (114), R_GR (115), R_GR (121), \
R_GR (122), R_GR (123), R_GR (124), R_GR (125), R_GR (126), \
R_GR (127), \
R_FP, R_BP, R_FC, R_CR, R_Q, \
R_VAB, R_OPS, R_CPS, R_CFG, R_CHA, R_CHD, R_CHC, R_RBP, R_TMC, \
R_TMR, R_PC0, R_PC1, R_PC2, R_MMU, R_LRU, R_FPE, R_INT, R_FPS, \
- R_EXO }
+ R_EXO, \
+ R_KR (0), R_KR (1), R_KR (2), R_KR (3), R_KR (4), R_KR (5), \
+ R_KR (6), R_KR (7), R_KR (8), R_KR (9), R_KR (10), R_KR (11), \
+ R_KR (12), R_KR (13), R_KR (14), R_KR (15), R_KR (16), R_KR (17), \
+ R_KR (18), R_KR (19), R_KR (20), R_KR (21), R_KR (22), R_KR (23), \
+ R_KR (24), R_KR (25), R_KR (26), R_KR (27), R_KR (28), R_KR (29), \
+ R_KR (30), R_KR (31) }
/* Return number of consecutive hard regs needed starting at reg REGNO
to hold something of mode MODE.
but can be less for certain modes in special long registers. */
#define HARD_REGNO_NREGS(REGNO, MODE) \
- ((REGNO) >= R_ACC (0) ? 1 \
+ ((REGNO) >= R_ACU (0) && (REGNO) <= R_ACU (3)? 1 \
: (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
On 29k, the cpu registers can hold any mode. But a double-precision
floating-point value should start at an even register. The special
- registers cannot hold floating-point values and the accumulators cannot
+ registers cannot hold floating-point values, BP, CR, and FC cannot
+ hold integer or floating-point values, and the accumulators cannot
hold integer values.
+ DImode and larger values should start at an even register just like
+ DFmode values, even though the instruction set doesn't require it, in order
+ to prevent reload from aborting due to a modes_equiv_for_class_p failure.
+
(I'd like to use the "?:" syntax to make this more readable, but Sun's
compiler doesn't seem to accept it.) */
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
- (((REGNO) >= R_ACC (0) \
+(((REGNO) >= R_ACU (0) && (REGNO) <= R_ACU (3) \
&& (GET_MODE_CLASS (MODE) == MODE_FLOAT \
|| GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)) \
- || ((REGNO) >= R_BP && (REGNO) < R_ACC (0) \
+ || ((REGNO) >= R_BP && (REGNO) <= R_CR \
+ && GET_MODE_CLASS (MODE) == MODE_PARTIAL_INT) \
+ || ((REGNO) >= R_Q && (REGNO) < R_ACU (0) \
&& GET_MODE_CLASS (MODE) != MODE_FLOAT \
&& GET_MODE_CLASS (MODE) != MODE_COMPLEX_FLOAT) \
- || ((REGNO) < R_BP \
- && ((((REGNO) & 1) == 0) || GET_MODE_CLASS (MODE) == MODE_INT \
- || GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT \
+ || (((REGNO) < R_BP || (REGNO) >= R_KR (0)) \
+ && ((((REGNO) & 1) == 0) \
|| GET_MODE_UNIT_SIZE (MODE) <= UNITS_PER_WORD)))
/* Value is 1 if it is a good idea to tie two pseudo registers
the special register's restriction to non-floating and the floating-point
accumulator's restriction to only floating. This probably won't
cause any great inefficiencies in practice. */
+
#define MODES_TIEABLE_P(MODE1, MODE2) \
((MODE1) == (MODE2) \
- || (GET_MODE_CLASS (MODE1) != MODE_FLOAT \
- && GET_MODE_CLASS (MODE1) != MODE_COMPLEX_FLOAT \
- && GET_MODE_CLASS (MODE2) != MODE_FLOAT \
- && GET_MODE_CLASS (MODE2) != MODE_COMPLEX_FLOAT))
+ || (GET_MODE_CLASS (MODE1) == MODE_INT \
+ && GET_MODE_CLASS (MODE2) == MODE_INT))
/* Specify the registers used for certain standard purposes.
The values of these macros are register numbers. */
For any two classes, it is very desirable that there be another
class that represents their union.
- The 29k has six registers classes: GENERAL_REGS, SPECIAL_REGS,
- BP_REGS, Q_REGS, ACCUM_REGS, and ACCUM0_REGS. BP_REGS contains just BP and
- is used for the extract and insert operations to allow combinations; Q
- contains just the Q register. The latter two classes are used to represent
- the floating-point accumulator registers in the 29050. We also define the
- union class FLOAT_REGS to represent any register that can be used to hold a
+ The 29k has nine registers classes: LR0_REGS, GENERAL_REGS, SPECIAL_REGS,
+ BP_REGS, FC_REGS, CR_REGS, Q_REGS, ACCUM_REGS, and ACCUM0_REGS.
+ LR0_REGS, BP_REGS, FC_REGS, CR_REGS, and Q_REGS contain just the single
+ register. The latter two classes are used to represent the floating-point
+ accumulator registers in the 29050. We also define the union class
+ FLOAT_REGS to represent any register that can be used to hold a
floating-point value. The union of SPECIAL_REGS and ACCUM_REGS isn't
useful as the former cannot contain floating-point and the latter can only
contain floating-point. */
-enum reg_class { NO_REGS, GENERAL_REGS, BP_REGS, Q_REGS, SPECIAL_REGS,
- ACCUM0_REGS, ACCUM_REGS, FLOAT_REGS, ALL_REGS,
- LIM_REG_CLASSES };
+enum reg_class { NO_REGS, LR0_REGS, GENERAL_REGS, BP_REGS, FC_REGS, CR_REGS,
+ Q_REGS, SPECIAL_REGS, ACCUM0_REGS, ACCUM_REGS, FLOAT_REGS,
+ ALL_REGS, LIM_REG_CLASSES };
#define N_REG_CLASSES (int) LIM_REG_CLASSES
-/* Give names of register classes as strings for dump file. */
+/* Give names of register classes as strings for dump file. */
#define REG_CLASS_NAMES \
- {"NO_REGS", "GENERAL_REGS", "BP_REGS", "Q_REGS", "SPECIAL_REGS", \
- "ACCUM0_REGS", "ACCUM_REGS", "FLOAT_REGS", "ALL_REGS" }
+ {"NO_REGS", "LR0_REGS", "GENERAL_REGS", "BP_REGS", "FC_REGS", "CR_REGS", \
+ "Q_REGS", "SPECIAL_REGS", "ACCUM0_REGS", "ACCUM_REGS", "FLOAT_REGS", \
+ "ALL_REGS" }
/* Define which registers fit in which classes.
This is an initializer for a vector of HARD_REG_SET
of length N_REG_CLASSES. */
#define REG_CLASS_CONTENTS \
- { {0, 0, 0, 0, 0, 0, 0}, \
- {~0, ~0, ~0, ~0, ~0, ~ 0xfffe0000, 0}, \
- {0, 0, 0, 0, 0, 0x20000, 0}, \
- {0, 0, 0, 0, 0, 0x100000, 0}, \
- {0, 0, 0, 0, 0, 0xfffe0000, 0xff}, \
- {0, 0, 0, 0, 0, 0, 0x100}, \
- {0, 0, 0, 0, 0, 0, 0xf00}, \
- {~0, ~0, ~0, ~0, ~0, ~ 0xfffe0000, 0xf00}, \
- {~0, ~0, ~0, ~0, ~0, ~0, ~0} }
+ { {0, 0, 0, 0, 0, 0, 0, 0}, \
+ {0, 1, 0, 0, 0, 0, 0, 0}, \
+ {~0, ~0, ~0, ~0, ~0, ~ 0xfffe0000, ~ 0xfff, 0xfff}, \
+ {0, 0, 0, 0, 0, 0x20000, 0, 0}, \
+ {0, 0, 0, 0, 0, 0x40000, 0, 0}, \
+ {0, 0, 0, 0, 0, 0x80000, 0, 0}, \
+ {0, 0, 0, 0, 0, 0x100000, 0, 0}, \
+ {0, 0, 0, 0, 0, 0xfffe0000, 0xff, 0}, \
+ {0, 0, 0, 0, 0, 0, 0x100, 0}, \
+ {0, 0, 0, 0, 0, 0, 0xf00, 0}, \
+ {~0, ~0, ~0, ~0, ~0, ~ 0xfffe0000, ~ 0xff, 0xfff}, \
+ {~0, ~0, ~0, ~0, ~0, ~0, ~0, 0xfff} }
/* The same information, inverted:
Return the class number of the smallest class containing
#define REGNO_REG_CLASS(REGNO) \
((REGNO) == R_BP ? BP_REGS \
+ : (REGNO) == R_FC ? FC_REGS \
+ : (REGNO) == R_CR ? CR_REGS \
: (REGNO) == R_Q ? Q_REGS \
: (REGNO) > R_BP && (REGNO) <= R_EXO ? SPECIAL_REGS \
- : (REGNO) == R_ACC (0) ? ACCUM0_REGS \
- : (REGNO) > R_ACC (0) ? ACCUM_REGS \
+ : (REGNO) == R_ACU (0) ? ACCUM0_REGS \
+ : (REGNO) >= R_KR (0) ? GENERAL_REGS \
+ : (REGNO) > R_ACU (0) ? ACCUM_REGS \
+ : (REGNO) == R_LR (0) ? LR0_REGS \
: GENERAL_REGS)
/* The class value for index registers, and the one for base regs. */
#define REG_CLASS_FROM_LETTER(C) \
((C) == 'r' ? GENERAL_REGS \
+ : (C) == 'l' ? LR0_REGS \
: (C) == 'b' ? BP_REGS \
+ : (C) == 'f' ? FC_REGS \
+ : (C) == 'c' ? CR_REGS \
: (C) == 'q' ? Q_REGS \
: (C) == 'h' ? SPECIAL_REGS \
: (C) == 'a' ? ACCUM_REGS \
On the 29k, we use this to change the register names for kernel mapping. */
-#define CONDITIONAL_REGISTER_USAGE \
- { \
- static char *kernel_names[] = {"gr64", "gr65", "gr66", "gr67", \
- "gr68", "gr69", "gr70", "gr71", \
- "gr72", "gr73", "gr74", "gr75", \
- "gr76", "gr77", "gr78", "gr79", \
- "gr80", "gr81", "gr82", "gr83", \
- "gr84", "gr85", "gr86", "gr87", \
- "gr88", "gr89", "gr90", "gr91", \
- "gr92", "gr93", "gr94", "gr95"}; \
- int i; \
- \
- if (TARGET_KERNEL_REGISTERS) \
- for (i = 0; i < 32; i++) \
- reg_names[i] = kernel_names[i]; \
+#define CONDITIONAL_REGISTER_USAGE \
+ { \
+ const char *p; \
+ int i; \
+ \
+ if (TARGET_KERNEL_REGISTERS) \
+ for (i = 0; i < 32; i++) \
+ { \
+ p = reg_names[i]; \
+ reg_names[i] = reg_names[R_KR (i)]; \
+ reg_names[R_KR (i)] = p; \
+ } \
}
/* The letters I, J, K, L, M, N, O, and P in a register constraint string
involving a general register is cheap, but moving between the other types
(even within a class) is two insns. */
-#define REGISTER_MOVE_COST(CLASS1, CLASS2) \
+#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
((CLASS1) == GENERAL_REGS || (CLASS2) == GENERAL_REGS ? 2 : 4)
+
+/* A C expressions returning the cost of moving data of MODE from a register to
+ or from memory.
+
+ It takes extra insns on the 29k to form addresses, so we want to make
+ this higher. In addition, we need to keep it more expensive than the
+ most expensive register-register copy. */
+
+#define MEMORY_MOVE_COST(MODE,CLASS,IN) 6
\f
/* Stack layout; function entry, exit and calling. */
/* Define this if the maximum size of all the outgoing args is to be
accumulated and pushed during the prologue. The amount can be
found in the variable current_function_outgoing_args_size. */
-#define ACCUMULATE_OUTGOING_ARGS
+#define ACCUMULATE_OUTGOING_ARGS 1
/* Offset of first parameter from the argument pointer register value. */
/* Value is the number of bytes of arguments automatically
popped when returning from a subroutine call.
+ FUNDECL is the declaration node of the function (as a tree),
FUNTYPE is the data type of the function (as a tree),
or for a library call it is an identifier node for the subroutine name.
SIZE is the number of bytes of arguments passed on the stack. */
-#define RETURN_POPS_ARGS(FUNTYPE,SIZE) 0
+#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
/* Define how to find the value returned by a function.
VALTYPE is the data type of the value (as a tree).
On 29k the value is found in gr96. */
#define FUNCTION_VALUE(VALTYPE, FUNC) \
- gen_rtx (REG, TYPE_MODE (VALTYPE), R_GR (96))
+ gen_rtx_REG (TYPE_MODE (VALTYPE), R_GR (96))
/* Define how to find the value returned by a library function
assuming the value has mode MODE. */
-#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, R_GR (96))
+#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, R_GR (96))
/* 1 if N is a possible register number for a function value
as seen by the caller.
On 29k, gr96-gr111 are used. */
-#define FUNCTION_VALUE_REGNO_P(N) ((N) < R_GR (112))
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == R_GR (96))
/* 1 if N is a possible register number for function argument passing.
On 29k, these are lr2-lr17. */
for a call to a function whose data type is FNTYPE.
For a library call, FNTYPE is 0. */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) (CUM) = 0
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) (CUM) = 0
/* Same, but called for incoming args.
On the 29k, we use this to set all argument registers to fixed and
- set the last 16 local regs (lr112-lr127) to available. Some
- will later be changed to call-saved by FUNCTION_INCOMING_ARG. */
+ set the last 16 local regs, less two, (lr110-lr125) to available. Some
+ will later be changed to call-saved by FUNCTION_INCOMING_ARG.
+ lr126,lr127 are always fixed, they are place holders for the caller's
+ lr0,lr1. */
-#define INIT_CUMULATIVE_INCOMING_ARGS(CUM,FNTYPE,IGNORE) \
+#define INIT_CUMULATIVE_INCOMING_ARGS(CUM,FNTYPE,IGNORE) \
{ int i; \
- for (i = R_AR (0); i < R_AR (16); i++) \
+ for (i = R_AR (0) - 2; i < R_AR (16); i++) \
{ \
fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 1; \
SET_HARD_REG_BIT (fixed_reg_set, i); \
SET_HARD_REG_BIT (call_used_reg_set, i); \
SET_HARD_REG_BIT (call_fixed_reg_set, i); \
} \
- for (i = R_LR (112); i < R_LR (128); i++) \
+ for (i = R_LR (110); i < R_LR (126); i++) \
{ \
fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 0; \
CLEAR_HARD_REG_BIT (fixed_reg_set, i); \
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
((CUM) < 16 && (NAMED) && ! MUST_PASS_IN_STACK (MODE, TYPE) \
- ? gen_rtx(REG, (MODE), R_LR (2) + (CUM)) : 0)
+ ? gen_rtx_REG ((MODE), R_LR (2) + (CUM)) : 0)
/* Define where a function finds its arguments.
This is different from FUNCTION_ARG because of register windows.
#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
((CUM) < 16 && (NAMED) && ! MUST_PASS_IN_STACK (MODE, TYPE) \
- ? gen_rtx (REG, MODE, \
- incoming_reg (CUM, A29K_ARG_SIZE (MODE, TYPE, NAMED))) \
+ ? gen_rtx_REG (MODE, \
+ incoming_reg (CUM, A29K_ARG_SIZE (MODE, TYPE, NAMED))) \
: 0)
/* This indicates that an argument is to be passed with an invisible reference
if (! (NO_RTL) && first_reg_offset != 16) \
move_block_from_reg \
(R_AR (0) + first_reg_offset, \
- gen_rtx (MEM, BLKmode, virtual_incoming_args_rtx), \
- 16 - first_reg_offset); \
+ gen_rtx_MEM (BLKmode, virtual_incoming_args_rtx), \
+ 16 - first_reg_offset, (16 - first_reg_offset) * UNITS_PER_WORD); \
PRETEND_SIZE = (16 - first_reg_offset) * UNITS_PER_WORD; \
} \
}
For the 29k, we need the prolog to contain one or two words prior to
the declaration of the function name. So just store away the name and
- write it as part of the prolog. */
+ write it as part of the prolog. This also computes the register names,
+ which can't be done until after register allocation, but must be done
+ before final_start_function is called. */
-extern char *a29k_function_name;
+extern const char *a29k_function_name;
#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \
- a29k_function_name = NAME;
-
-/* This macro generates the assembly code for function entry.
- FILE is a stdio stream to output the code to.
- SIZE is an int: how many units of temporary storage to allocate.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) output_prolog (FILE, SIZE)
+ a29k_function_name = NAME; \
+ a29k_compute_reg_names ();
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
#define EXIT_IGNORE_STACK 1
-/* This macro generates the assembly code for function exit,
- on machines that need it. If FUNCTION_EPILOGUE is not defined
- then individual return instructions are generated for each
- return statement. Args are same as for FUNCTION_PROLOGUE.
-
- The function epilogue should not depend on the current stack pointer!
- It should use the frame pointer only. This is mandatory because
- of alloca; we also take advantage of it to omit stack adjustments
- before returning. */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) output_epilog (FILE, SIZE)
-
/* Define the number of delay slots needed for the function epilogue.
On the 29k, we need a slot except when we have a register stack adjustment,
On the 29k, we must be able to place it in a delay slot, it must
not use sp if the frame pointer cannot be eliminated, and it cannot
- use local regs if we need to push the register stack. */
+ use local regs if we need to push the register stack.
+ If this is a SET with a memory as source, it might load from
+ a stack slot, unless the address is constant. */
#define ELIGIBLE_FOR_EPILOGUE_DELAY(INSN,N) \
(get_attr_in_delay_slot (INSN) == IN_DELAY_SLOT_YES \
&& ! (frame_pointer_needed \
&& reg_mentioned_p (stack_pointer_rtx, PATTERN (INSN))) \
- && ! (needs_regstack_p () && uses_local_reg_p (PATTERN (INSN))))
+ && ! (needs_regstack_p () && uses_local_reg_p (PATTERN (INSN))) \
+ && (GET_CODE (PATTERN (INSN)) != SET \
+ || GET_CODE (SET_SRC (PATTERN (INSN))) != MEM \
+ || ! rtx_varies_p (XEXP (SET_SRC (PATTERN (INSN)), 0), 0)))
\f
/* Output assembler code for a block containing the constant parts
of a trampoline, leaving space for the variable parts.
rtx _val = force_reg (SImode, VALUE); \
\
_addr = memory_address (QImode, plus_constant (TRAMP, (CONST) + 3)); \
- emit_move_insn (gen_rtx (MEM, QImode, _addr), \
+ emit_move_insn (gen_rtx_MEM (QImode, _addr), \
gen_lowpart (QImode, _val)); \
\
_temp = expand_shift (RSHIFT_EXPR, SImode, _val, \
build_int_2 (8, 0), 0, 1); \
_addr = memory_address (QImode, plus_constant (TRAMP, (CONST) + 1)); \
- emit_move_insn (gen_rtx (MEM, QImode, _addr), \
+ emit_move_insn (gen_rtx_MEM (QImode, _addr), \
gen_lowpart (QImode, _temp)); \
\
_temp = expand_shift (RSHIFT_EXPR, SImode, _temp, \
build_int_2 (8, 0), _temp, 1); \
_addr = memory_address (QImode, plus_constant (TRAMP, (CONSTH) + 3)); \
- emit_move_insn (gen_rtx (MEM, QImode, _addr), \
+ emit_move_insn (gen_rtx_MEM (QImode, _addr), \
gen_lowpart (QImode, _temp)); \
\
_temp = expand_shift (RSHIFT_EXPR, SImode, _temp, \
build_int_2 (8, 0), _temp, 1); \
_addr = memory_address (QImode, plus_constant (TRAMP, (CONSTH) + 1)); \
- emit_move_insn (gen_rtx (MEM, QImode, _addr), \
+ emit_move_insn (gen_rtx_MEM (QImode, _addr), \
gen_lowpart (QImode, _temp)); \
}
\f
/* Addressing modes, and classification of registers for them. */
-/* #define HAVE_POST_INCREMENT */
-/* #define HAVE_POST_DECREMENT */
+/* #define HAVE_POST_INCREMENT 0 */
+/* #define HAVE_POST_DECREMENT 0 */
-/* #define HAVE_PRE_DECREMENT */
-/* #define HAVE_PRE_INCREMENT */
+/* #define HAVE_PRE_DECREMENT 0 */
+/* #define HAVE_PRE_INCREMENT 0 */
/* Macros to check register numbers against specific register classes. */
/* Maximum number of registers that can appear in a valid memory address. */
#define MAX_REGS_PER_ADDRESS 1
-/* Recognize any constant value that is a valid address.
+/* Recognize any constant value that is a valid address. */
- None are on the 29K. */
-#define CONSTANT_ADDRESS_P(X) 0
+#define CONSTANT_ADDRESS_P(X) \
+(GET_CODE (X) == CONST_INT && (unsigned) INTVAL (X) < 0x100)
/* Include all constant integers and constant doubles */
#define LEGITIMATE_CONSTANT_P(X) 1
for the index in the tablejump instruction. */
#define CASE_VECTOR_MODE SImode
-/* Define this if the tablejump instruction expects the table
- to contain offsets from the address of the table.
+/* Define as C expression which evaluates to nonzero if the tablejump
+ instruction expects the table to contain offsets from the address of the
+ table.
Do not define this if the table should contain absolute addresses. */
-/* #define CASE_VECTOR_PC_RELATIVE */
-
-/* Specify the tree operation to be used to convert reals to integers. */
-#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
-
-/* This is the kind of divide that is easiest to do in the general case. */
-#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+/* #define CASE_VECTOR_PC_RELATIVE 1 */
/* Define this as 1 if `char' should by default be signed; else as 0. */
#define DEFAULT_SIGNED_CHAR 0
manipulate fields. */
#define SLOW_BYTE_ACCESS 0
-/* Define if normal loads of shorter-than-word items from memory clears
- the rest of the bigs in the register. */
-#define BYTE_LOADS_ZERO_EXTEND
+/* Define if operations between registers always perform the operation
+ on the full register even if a narrower mode is specified. */
+#define WORD_REGISTER_OPERATIONS
+
+/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD
+ will either zero-extend or sign-extend. The value of this macro should
+ be the code that says which one of the two operations is implicitly
+ done, NIL if none. */
+#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
+
+/* Define if the object format being used is COFF or a superset. */
+#define OBJECT_FORMAT_COFF
/* This uses COFF, so it wants SDB format. */
#define SDB_DEBUGGING_INFO
#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
/* We assume that the store-condition-codes instructions store 0 for false
- and some other value for true. This is the value stored for true. */
+ and some other value for true. This is the value stored for true, which
+ is just the sign bit. */
-#define STORE_FLAG_VALUE 0x80000000
+#define STORE_FLAG_VALUE (-2147483647 - 1)
/* Specify the machine mode that pointers have.
After generation of rtl, the compiler makes no further distinction
but a CALL with constant address is cheap. */
#define NO_FUNCTION_CSE
-/* Define this if shift instructions ignore all but the low-order
- few bits. */
-#define SHIFT_COUNT_TRUNCATED
+/* Define this to be nonzero if shift instructions ignore all but the low-order
+ few bits. */
+#define SHIFT_COUNT_TRUNCATED 1
/* Compute the cost of computing a constant rtl expression RTX
whose rtx-code is CODE. The body of this macro is a portion
instruction are those involving floating-point or address. So
only these need be expensive. */
-#define CONST_COSTS(RTX,CODE) \
+#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
case CONST_INT: \
return 0; \
case CONST: \
The multiply cost depends on whether this is a 29050 or not. */
-#define RTX_COSTS(X,CODE) \
+#define RTX_COSTS(X,CODE,OUTER_CODE) \
case MULT: \
return TARGET_29050 ? COSTS_N_INSNS (2) : COSTS_N_INSNS (40); \
case DIV: \
/* Output at beginning of assembler file. */
#define ASM_FILE_START(FILE) \
-{ char *p, *after_dir = main_input_filename; \
+{ const char *p, *after_dir = main_input_filename; \
if (TARGET_29050) \
fprintf (FILE, "\t.cputype 29050\n"); \
for (p = main_input_filename; *p; p++) \
if (*p == '/') \
after_dir = p + 1; \
- fprintf (FILE, "\t.file \"%s\"\n", after_dir); \
+ fprintf (FILE, "\t.file "); \
+ output_quoted_string (FILE, after_dir); \
+ fprintf (FILE, "\n"); \
fprintf (FILE, "\t.sect .lit,lit\n"); }
/* Output to assembler file text saying following lines
#define ASM_APP_OFF ""
+/* The next few macros don't have tabs on most machines, but
+ at least one 29K assembler wants them. */
+
/* Output before instructions. */
#define TEXT_SECTION_ASM_OP "\t.text"
#define READONLY_DATA_SECTION literal_section
+/* If we are referencing a function that is static or is known to be
+ in this file, make the SYMBOL_REF special. We can use this to indicate
+ that we can branch to this function without emitting a no-op after the
+ call. */
+
+#define ENCODE_SECTION_INFO(DECL, FIRST) \
+ if (TREE_CODE (DECL) == FUNCTION_DECL \
+ && (TREE_ASM_WRITTEN (DECL) || ! TREE_PUBLIC (DECL))) \
+ SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1;
+
/* How to refer to registers in assembler output.
This sequence is indexed by compiler's hard-register-number (see above). */
"bp", "fc", "cr", "q", \
"vab", "ops", "cps", "cfg", "cha", "chd", "chc", "rbp", "tmc", "tmr", \
"pc0", "pc1", "pc2", "mmu", "lru", "fpe", "int", "fps", "exo", \
- "0", "1", "2", "3" }
+ "0", "1", "2", "3", \
+ "gr64", "gr65", "gr66", "gr67", "gr68", "gr69", "gr70", "gr71", \
+ "gr72", "gr73", "gr74", "gr75", "gr76", "gr77", "gr78", "gr79", \
+ "gr80", "gr81", "gr82", "gr83", "gr84", "gr85", "gr86", "gr87", \
+ "gr88", "gr89", "gr90", "gr91", "gr92", "gr93", "gr94", "gr95" }
/* How to renumber registers for dbx and gdb. */
-extern int a29k_debug_reg_map[];
+extern int a29k_debug_reg_map[FIRST_PSEUDO_REGISTER];
#define DBX_REGISTER_NUMBER(REGNO) a29k_debug_reg_map[REGNO]
+/* Switch into a generic section. */
+#define TARGET_ASM_NAMED_SECTION a29k_asm_named_section
+
/* This is how to output the definition of a user-level label named NAME,
such as the label on a static function or variable NAME. */
#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
do { fputs ("\t.global ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
-/* This is how to output a reference to a user-level label named NAME.
- `assemble_name' uses this. */
+/* The prefix to add to user-visible assembler symbols. */
-#define ASM_OUTPUT_LABELREF(FILE,NAME) \
- fprintf (FILE, "_%s", NAME)
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX "_"
/* This is how to output an internal numbered label where
PREFIX is the class of label and NUM is the number within the class. */
/* This is how to output a label for a jump table. Arguments are the same as
for ASM_OUTPUT_INTERNAL_LABEL, except the insn for the jump table is
- passed. */
+ passed. */
#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLEINSN) \
{ ASM_OUTPUT_ALIGN (FILE, 2); ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); }
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
sprintf (LABEL, "*%s%d", PREFIX, NUM)
-/* This is how to output an assembler line defining a `double' constant. */
-
-#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
- fprintf (FILE, "\t.double %.20e\n", (VALUE))
-
-/* This is how to output an assembler line defining a `float' constant. */
-
-#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
- fprintf (FILE, "\t.float %.20e\n", (VALUE))
-
-/* This is how to output an assembler line defining an `int' constant. */
-
-#define ASM_OUTPUT_INT(FILE,VALUE) \
-( fprintf (FILE, "\t.word "), \
- output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
-
-/* Likewise for `char' and `short' constants. */
-
-#define ASM_OUTPUT_SHORT(FILE,VALUE) \
-( fprintf (FILE, "\t.hword "), \
- output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
-
-#define ASM_OUTPUT_CHAR(FILE,VALUE) \
-( fprintf (FILE, "\t.byte "), \
- output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
-
/* This is how to output an insn to push a register on the stack.
It need not be very fast code. */
reg_names[REGNO], reg_names[R_MSP], reg_names[R_MSP], \
reg_names[R_MSP]);
-/* This is how to output an assembler line for a numeric constant byte. */
-
-#define ASM_OUTPUT_BYTE(FILE,VALUE) \
- fprintf (FILE, "\t.byte 0x%x\n", (VALUE))
-
/* This is how to output an element of a case-vector that is absolute. */
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
fprintf (FILE, "\t.word L%d\n", VALUE)
/* This is how to output an element of a case-vector that is relative.
- (29k does not use such vectors,
- but we must define this macro anyway.) */
+ Don't define this if it is not supported. */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) abort ()
+/* #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) */
/* This is how to output an assembler line
that says to advance the location counter
( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
-/* Define the parentheses used to group arithmetic operations
- in assembler code. */
-
-#define ASM_OPEN_PAREN "("
-#define ASM_CLOSE_PAREN ")"
-
-/* Define results of standard character escape sequences. */
-#define TARGET_BELL 007
-#define TARGET_BS 010
-#define TARGET_TAB 011
-#define TARGET_NEWLINE 012
-#define TARGET_VT 013
-#define TARGET_FF 014
-#define TARGET_CR 015
-
/* Print operand X (an rtx) in assembler syntax to file FILE.
CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
For `%' followed by punctuation, CODE is the punctuation and X is null. */
{"cint_16_operand", {CONST_INT}}, \
{"long_const_operand", {CONST_INT, CONST, CONST_DOUBLE, \
LABEL_REF, SYMBOL_REF}}, \
- {"shift_constant_operand", {CONST_INT, ASHIFT}}, \
- {"const_0__operand", {CONST_INT, ASHIFT}}, \
- {"const_8__operand", {CONST_INT, ASHIFT}}, \
- {"const_16__operand", {CONST_INT, ASHIFT}}, \
- {"const_24__operand", {CONST_INT, ASHIFT}}, \
+ {"const_0_operand", {CONST_INT, ASHIFT}}, \
+ {"const_8_operand", {CONST_INT, ASHIFT}}, \
+ {"const_16_operand", {CONST_INT, ASHIFT}}, \
+ {"const_24_operand", {CONST_INT, ASHIFT}}, \
{"float_const_operand", {CONST_DOUBLE}}, \
- {"gen_reg_operand", {SUBREG, REG}}, \
- {"gen_reg_or_float_constant_operand", {SUBREG, REG, CONST_DOUBLE}}, \
- {"gen_reg_or_integer_constant_operand", {SUBREG, REG, \
+ {"gpc_reg_operand", {SUBREG, REG}}, \
+ {"gpc_reg_or_float_constant_operand", {SUBREG, REG, CONST_DOUBLE}}, \
+ {"gpc_reg_or_integer_constant_operand", {SUBREG, REG, \
CONST_INT, CONST_DOUBLE}}, \
+ {"gpc_reg_or_immediate_operand", {SUBREG, REG, CONST_INT, \
+ CONST_DOUBLE, CONST, \
+ SYMBOL_REF, LABEL_REF}}, \
{"spec_reg_operand", {REG}}, \
{"accum_reg_operand", {REG}}, \
{"srcb_operand", {SUBREG, REG, CONST_INT}}, \
+ {"cmplsrcb_operand", {SUBREG, REG, CONST_INT}}, \
{"reg_or_immediate_operand", {SUBREG, REG, CONST_INT, CONST, \
CONST_DOUBLE, CONST, SYMBOL_REF, LABEL_REF}}, \
{"reg_or_u_short_operand", {SUBREG, REG, CONST_INT}}, \
{"and_operand", {SUBREG, REG, CONST_INT}}, \
{"add_operand", {SUBREG, REG, CONST_INT}}, \
+ {"call_operand", {SYMBOL_REF, CONST_INT}}, \
{"in_operand", {SUBREG, MEM, REG, CONST_INT, CONST, SYMBOL_REF, \
LABEL_REF, CONST_DOUBLE}}, \
{"out_operand", {SUBREG, REG, MEM}}, \
- {"extend_operator", {ZERO_EXTEND, SIGN_EXTEND}}, \
+ {"reload_memory_operand", {SUBREG, REG, MEM}}, \
{"fp_comparison_operator", {EQ, GT, GE}}, \
{"branch_operator", {GE, LT}}, \
+ {"load_multiple_operation", {PARALLEL}}, \
+ {"store_multiple_operation", {PARALLEL}}, \
{"epilogue_operand", {CODE_LABEL}},