/* Definitions of target machine for GNU compiler, for AMD Am29000 CPU.
- Copyright (C) 1988, 90-94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 2000 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 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}, \
- {"normal", - (4|8)}, \
- {"large", 8}, \
- {"29050", 16+128}, \
- {"29000", -16}, \
- {"kernel-registers", 32}, \
- {"user-registers", -32}, \
- {"stack-check", 64}, \
- {"no-stack-check", - 74}, \
- {"storem-bug", -128}, \
- {"no-storem-bug", 128}, \
- {"reuse-arg-regs", -256}, \
- {"no-reuse-arg-regs", 256}, \
- {"soft-float", 512}, \
- {"", TARGET_DEFAULT}}
+ { {"dw", 1, "Generate code assuming DW bit is set"}, \
+ {"ndw", -1, "Generate code assuming DW bit is not set"}, \
+ {"bw", 2, "Generate code using byte writes"}, \
+ {"nbw", - (1|2), "Do not generate byte writes"}, \
+ {"small", 4, "Use small memory model"}, \
+ {"normal", - (4|8), "Use normal memory model"}, \
+ {"large", 8, "Use large memory model"}, \
+ {"29050", 16+128, "Generate 29050 code"}, \
+ {"29000", -16, "Generate 29000 code"}, \
+ {"kernel-registers", 32, "Use kernel global registers"}, \
+ {"user-registers", -32, "Use user global registers"}, \
+ {"stack-check", 64, "Emit stack checking code"}, \
+ {"no-stack-check", - 74, "Do not emit stack checking code"}, \
+ {"storem-bug", -128, "Work around storem hardware bug"}, \
+ {"no-storem-bug", 128, "Do not work around storem hardware bug"}, \
+ {"reuse-arg-regs", -256, "Store locals in argument registers"}, \
+ {"no-reuse-arg-regs", 256, "Do not store locals in arg registers"}, \
+ {"soft-float", 512, "Use software floating point"}, \
+ {"no-multm", 1024, "Do not generate multm instructions"}, \
+ {"", TARGET_DEFAULT, NULL}}
#define TARGET_DEFAULT 3
/* Set this non-zero if unaligned move instructions are extremely slow.
On the 29k, they trap. */
-#define SLOW_UNALIGNED_ACCESS 1
+#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) 1
\f
/* Standard register usage. */
#define CONDITIONAL_REGISTER_USAGE \
{ \
- char *p; \
+ const char *p; \
int i; \
\
if (TARGET_KERNEL_REGISTERS) \
#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
secondary_reload_class (CLASS, MODE, IN)
-/* This function is used to get the address of an object. */
-
-extern struct rtx_def *a29k_get_reloaded_address ();
-
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS.
this higher. In addition, we need to keep it more expensive than the
most expensive register-register copy. */
-#define MEMORY_MOVE_COST(MODE) 6
+#define MEMORY_MOVE_COST(MODE,CLASS,IN) 6
/* A C statement (sans semicolon) to update the integer variable COST
based on the relationship between INSN that is dependent on
/* 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.
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.
#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), \
+ 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;
+ a29k_function_name = NAME; \
+ a29k_compute_reg_names ();
/* This macro generates the assembly code for function entry.
FILE is a stdio stream to output the code to.
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))))
\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.
- Do not define this if the table should contain absolute addresses. */
-/* #define CASE_VECTOR_PC_RELATIVE */
+/* 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 1 */
/* Specify the tree operation to be used to convert reals to integers. */
#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
#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
extern int a29k_debug_reg_map[];
#define DBX_REGISTER_NUMBER(REGNO) a29k_debug_reg_map[REGNO]
+/* This how to write an assembler directive to FILE to switch to
+ section NAME for DECL. */
+
+#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
+ fprintf (FILE, "\t.sect %s, bss\n\t.use %s\n", NAME, NAME)
+
/* 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. */
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