/* Definitions of target machine for GNU compiler, Mitsubishi M32R cpu.
- Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
#endif
#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "%{!shared:crt0.o%s crtsysc.o%s} crtinit.o%s"
+#define STARTFILE_SPEC "%{!shared:crt0.o%s} crtinit.o%s"
#undef ENDFILE_SPEC
-#define ENDFILE_SPEC "crtfini.o%s"
+#define ENDFILE_SPEC "-lgloss crtfini.o%s"
#undef LIB_SPEC
#define FIXED_REGISTERS \
{ 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 1, \
- 1, 0 }
+ 1, 1 }
/* 1 for registers not available across function calls.
(values in the range -32767 to +32768). */
/* local to this file */
-#define INT8_P(X) ((unsigned) ((X) + 0x80) < 0x100)
-#define INT16_P(X) ((unsigned) ((X) + 0x8000) < 0x10000)
-#define CMP_INT16_P(X) ((unsigned) ((X) - 1 + 0x8000) < 0x10000)
-#define UINT16_P(X) ((unsigned) (X) < 0x10000)
-#define UPPER16_P(X) (((X) & ~0xffff0000) == 0)
-#define UINT24_P(X) ((unsigned) (X) < 0x1000000)
-#define INT32_P(X) ((X) >= (-(HOST_WIDE_INT) 0x7fffffff - 1) \
- && (X) <= (unsigned HOST_WIDE_INT) 0xffffffff)
-#define UINT5_P(X) ((unsigned) (X) < 32)
-
-#define CONST_OK_FOR_LETTER_P(VALUE, C) \
-((C) == 'I' ? INT8_P (VALUE) \
- : (C) == 'J' ? INT16_P (VALUE) \
- : (C) == 'K' ? UINT16_P (VALUE) \
- : (C) == 'L' ? UPPER16_P (VALUE) \
- : (C) == 'M' ? UINT24_P (VALUE) \
- : (C) == 'N' ? INT32_P (VALUE) \
- : (C) == 'O' ? UINT5_P (VALUE) \
- : (C) == 'P' ? CMP_INT16_P (VALUE) \
+#define INT8_P(X) ((X) >= -0x80 && (X) <= 0x7f)
+#define INT16_P(X) ((X) >= -0x8000 && (X) <= 0x7fff)
+#define CMP_INT16_P(X) ((X) >= -0x7fff && (X) <= 0x8000)
+#define UINT16_P(X) ((X) >= 0 && (X) <= 0xffff)
+#define UPPER16_P(X) (((X) & 0xffff) == 0 \
+ && ((X) >> 16) >= -0x8000 \
+ && ((X) >> 16) <= 0x7fff)
+#define UINT24_P(X) ((X) >= 0 && (X) < 0x1000000)
+#define INT32_P(X) (((X) >= -(HOST_WIDE_INT) 0x80000000 \
+ && (X) <= (HOST_WIDE_INT) 0x7fffffff) \
+ || (unsigned HOST_WIDE_INT) (X) <= 0xffffffff)
+#define UINT5_P(X) ((X) >= 0 && (X) < 32)
+#define INVERTED_SIGNED_8BIT(VAL) ((VAL) >= -127 && (VAL) <= 128)
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C) \
+((C) == 'I' ? INT8_P (VALUE) \
+ : (C) == 'J' ? INT16_P (VALUE) \
+ : (C) == 'K' ? UINT16_P (VALUE) \
+ : (C) == 'L' ? UPPER16_P (VALUE) \
+ : (C) == 'M' ? UINT24_P (VALUE) \
+ : (C) == 'N' ? INVERTED_SIGNED_8BIT (VALUE) \
+ : (C) == 'O' ? UINT5_P (VALUE) \
+ : (C) == 'P' ? CMP_INT16_P (VALUE) \
: 0)
/* Similar, but for floating constants, and defining letters G and H.
For the m32r, handle a few constants inline.
??? We needn't treat DI and DF modes differently, but for now we do. */
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
-((C) == 'G' ? easy_di_const (VALUE) \
- : (C) == 'H' ? easy_df_const (VALUE) \
+((C) == 'G' ? easy_di_const (VALUE) \
+ : (C) == 'H' ? easy_df_const (VALUE) \
: 0)
/* A C expression that defines the optional machine-dependent constraint
be 0 regardless of VALUE. */
/* Q is for symbolic addresses loadable with ld24.
R is for symbolic addresses when ld24 can't be used.
- S is for an 8 bit signed integer in the range +128 to -127 */
-
-#define INVERTED_SIGNED_8BIT(VAL) ((VAL) >= -127 && (VAL) <= 128)
-
-#define EXTRA_CONSTRAINT(VALUE, C) \
-((C) == 'Q' \
- ? ((TARGET_ADDR24 && GET_CODE (VALUE) == LABEL_REF) \
- || addr24_operand (VALUE, VOIDmode)) \
- : (C) == 'R' \
- ? ((TARGET_ADDR32 && GET_CODE (VALUE) == LABEL_REF) \
- || addr32_operand (VALUE, VOIDmode)) \
- : (C) == 'S' \
- ? ((GET_CODE (VALUE) == CONST_INT) && INVERTED_SIGNED_8BIT (INTVAL (VALUE))) \
+ S is unused.
+ T is for indirect of a pointer.
+ U is for pushes and pops of the stack pointer. */
+
+#define EXTRA_CONSTRAINT(VALUE, C) \
+((C) == 'Q' \
+ ? ((TARGET_ADDR24 && GET_CODE (VALUE) == LABEL_REF) \
+ || addr24_operand (VALUE, VOIDmode)) \
+ : (C) == 'R' \
+ ? ((TARGET_ADDR32 && GET_CODE (VALUE) == LABEL_REF) \
+ || addr32_operand (VALUE, VOIDmode)) \
+ : (C) == 'S' \
+ ? 0 \
+ : (C) == 'T' \
+ ? (GET_CODE (VALUE) == MEM \
+ && memreg_operand (VALUE, GET_MODE (VALUE))) \
+ : (C) == 'U' \
+ ? (GET_CODE (VALUE) == MEM \
+ && PUSH_POP_P (GET_MODE (VALUE), XEXP (VALUE, 0))) \
: 0)
\f
/* Stack layout and stack pointer usage. */
/* The current return address is in r14. */
#if 0 /* The default value should work. */
#define RETURN_ADDR_RTX(COUNT, FRAME) \
-(((COUNT) == -1) \
- ? gen_rtx (REG, Pmode, 14) \
- : copy_to_reg (gen_rtx (MEM, Pmode, \
- memory_address (Pmode, plus_constant ((FRAME), UNITS_PER_WORD)))))
+(((COUNT) == -1) \
+ ? gen_rtx_REG (Pmode, 14) \
+ : copy_to_reg (gen_rtx_MEM (Pmode, \
+ memory_address (Pmode, \
+ plus_constant ((FRAME), \
+ UNITS_PER_WORD)))))
#endif
/* Register to use for pushing function arguments. */
/* Function argument passing. */
/* When a prototype says `char' or `short', really pass an `int'. */
-#define PROMOTE_PROTOTYPES
+#define PROMOTE_PROTOTYPES 1
/* If defined, the maximum amount of space required for outgoing
arguments will be computed and placed into the variable
SIZE is the number of bytes of arguments passed on the stack. */
#define RETURN_POPS_ARGS(DECL, FUNTYPE, SIZE) 0
+/* Nonzero if we do not know how to pass TYPE solely in registers. */
+#define MUST_PASS_IN_STACK(MODE,TYPE) \
+ ((TYPE) != 0 \
+ && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \
+ || TREE_ADDRESSABLE (TYPE)))
+
/* Define a data type for recording info about an argument list
during the scan of that argument list. This data type should
hold all necessary information about the function itself
and the rest are pushed. */
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
(PASS_IN_REG_P ((CUM), (MODE), (TYPE), (NAMED)) \
- ? gen_rtx (REG, (MODE), ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE))) \
+ ? gen_rtx_REG ((MODE), ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE))) \
: 0)
/* ??? Quick hack to try to get varargs working the normal way. */
#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
(((! current_function_varargs || (NAMED)) \
&& PASS_IN_REG_P ((CUM), (MODE), (TYPE), (NAMED))) \
- ? gen_rtx (REG, (MODE), ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE))) \
+ ? gen_rtx_REG ((MODE), ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE))) \
: 0)
/* A C expression for the number of words, at the beginning of an
: 2 * PARM_BOUNDARY)
#endif
-#if 0
-/* If defined, is a C expression that produces the machine-specific
- code for a call to `__builtin_saveregs'. This code will be moved
- to the very beginning of the function, before any parameter access
- are made. The return value of this function should be an RTX that
- contains the value to use as the return of `__builtin_saveregs'.
-
- The argument ARGS is a `tree_list' containing the arguments that
- were passed to `__builtin_saveregs'.
-
- If this macro is not defined, the compiler will output an ordinary
- call to the library function `__builtin_saveregs'. */
-extern struct rtx *m32r_expand_builtin_savergs ();
-#define EXPAND_BUILTIN_SAVEREGS(ARGS) m32r_expand_builtin_saveregs (ARGS)
-#endif
-
/* This macro offers an alternative
to using `__builtin_saveregs' and defining the macro
`EXPAND_BUILTIN_SAVEREGS'. Use it to store the anonymous register
#define SETUP_INCOMING_VARARGS(ARGS_SO_FAR, MODE, TYPE, PRETEND_SIZE, NO_RTL) \
m32r_setup_incoming_varargs (&ARGS_SO_FAR, MODE, TYPE, &PRETEND_SIZE, NO_RTL)
+
+/* Implement `va_arg'. */
+#define EXPAND_BUILTIN_VA_ARG(valist, type) \
+ m32r_va_arg (valist, type)
\f
/* Function results. */
VALTYPE is the data type of the value (as a tree).
If the precise function being called is known, FUNC is its FUNCTION_DECL;
otherwise, FUNC is 0. */
-#define FUNCTION_VALUE(VALTYPE, FUNC) gen_rtx (REG, TYPE_MODE (VALTYPE), 0)
+#define FUNCTION_VALUE(VALTYPE, FUNC) gen_rtx_REG (TYPE_MODE (VALTYPE), 0)
/* 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, 0)
+#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, 0)
/* 1 if N is a possible register number for a function value
as seen by the caller. */
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
-#define FUNCTION_PROFILER(FILE, LABELNO)
+#define FUNCTION_PROFILER(FILE, LABELNO) abort ()
\f
/* Trampolines. */
CXT is an RTX for the static chain value for the function. */
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
do { \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 0)), \
+ emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 0)), \
plus_constant ((CXT), 0xe7000000)); \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 4)), \
+ emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 4)), \
plus_constant ((FNADDR), 0xe6000000)); \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 8)), \
+ emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 8)), \
GEN_INT (0x1fc67000)); \
- emit_insn (gen_flush_icache (validize_mem (gen_rtx (MEM, SImode, TRAMP)))); \
+ emit_insn (gen_flush_icache (validize_mem (gen_rtx_MEM (SImode, TRAMP)))); \
} while (0)
\f
/* Library calls. */
/* We have post-inc load and pre-dec,pre-inc store,
but only for 4 byte vals. */
#if 0
-#define HAVE_PRE_DECREMENT
-#define HAVE_PRE_INCREMENT
-#define HAVE_POST_INCREMENT
+#define HAVE_PRE_DECREMENT 1
+#define HAVE_PRE_INCREMENT 1
+#define HAVE_POST_INCREMENT 1
#endif
/* Recognize any constant value that is a valid address. */
(GET_CODE (X) == CONST_INT && INT16_P (INTVAL (X)))
/* local to this file */
-#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X) \
-(GET_CODE (X) == PLUS \
- && RTX_OK_FOR_BASE_P (XEXP (X, 0)) \
+#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X) \
+(GET_CODE (X) == PLUS \
+ && RTX_OK_FOR_BASE_P (XEXP (X, 0)) \
&& RTX_OK_FOR_OFFSET_P (XEXP (X, 1)))
/* local to this file */
-#define LEGITIMATE_LO_SUM_ADDRESS_P(MODE, X) \
-(GET_CODE (X) == LO_SUM \
- && RTX_OK_FOR_BASE_P (XEXP (X, 0)) \
+/* For LO_SUM addresses, do not allow them if the MODE is > 1 word,
+ since more than one instruction will be required. */
+#define LEGITIMATE_LO_SUM_ADDRESS_P(MODE, X) \
+(GET_CODE (X) == LO_SUM \
+ && (MODE != BLKmode && GET_MODE_SIZE (MODE) <= UNITS_PER_WORD) \
+ && RTX_OK_FOR_BASE_P (XEXP (X, 0)) \
&& CONSTANT_P (XEXP (X, 1)))
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
-{ if (RTX_OK_FOR_BASE_P (X)) \
- goto ADDR; \
- if (LEGITIMATE_OFFSET_ADDRESS_P ((MODE), (X))) \
- goto ADDR; \
- if (LEGITIMATE_LO_SUM_ADDRESS_P ((MODE), (X))) \
- goto ADDR; \
+/* local to this file */
+/* Memory address that is a push/pop of the stack pointer. */
+#define PUSH_POP_P(MODE, X) \
+((MODE) == SImode \
+ && (GET_CODE (X) == POST_INC \
+ || GET_CODE (X) == PRE_INC \
+ || GET_CODE (X) == PRE_DEC))
+
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ if (RTX_OK_FOR_BASE_P (X)) \
+ goto ADDR; \
+ if (LEGITIMATE_OFFSET_ADDRESS_P ((MODE), (X))) \
+ goto ADDR; \
+ if (LEGITIMATE_LO_SUM_ADDRESS_P ((MODE), (X))) \
+ goto ADDR; \
+ if (PUSH_POP_P ((MODE), (X))) \
+ goto ADDR; \
}
/* Try machine-dependent ways of modifying an illegitimate address
/* Go to LABEL if ADDR (a legitimate address expression)
has an effect that depends on the machine mode it is used for. */
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \
-do { \
- if (GET_CODE (ADDR) == PRE_DEC) \
- goto LABEL; \
- if (GET_CODE (ADDR) == PRE_INC) \
- goto LABEL; \
- if (GET_CODE (ADDR) == POST_INC) \
- goto LABEL; \
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \
+do { \
+ if (GET_CODE (ADDR) == PRE_DEC \
+ || GET_CODE (ADDR) == PRE_INC \
+ || GET_CODE (ADDR) == POST_INC \
+ || GET_CODE (ADDR) == LO_SUM) \
+ goto LABEL; \
} while (0)
\f
/* Condition code usage. */
/* Compute the cost of moving data between registers and memory. */
/* Memory is 3 times as expensive as registers.
??? Is that the right way to look at it? */
-#define MEMORY_MOVE_COST(MODE,CLASS,IN) \
+#define MEMORY_MOVE_COST(MODE,CLASS,IN_P) \
(GET_MODE_SIZE (MODE) <= UNITS_PER_WORD ? 6 : 12)
/* The cost of a branch insn. */
#define HAIFA_P 0
#endif
-/* Indicate how many instructions can be issued at the same time. */
+/* Indicate how many instructions can be issued at the same time.
+ This is 1/2 of a lie. The m32r can issue only 1 long insn at
+ once, but 2. However doing so allows the scheduler to group
+ the two short insns together. */
#define ISSUE_RATE 2
/* When the `length' insn attribute is used, this macro specifies the
#undef ASM_OUTPUT_LABELREF
#define ASM_OUTPUT_LABELREF(FILE, NAME) \
do { \
- char * real_name; \
+ const char * real_name; \
STRIP_NAME_ENCODING (real_name, (NAME)); \
- fprintf (FILE, "%s%s", USER_LABEL_PREFIX, real_name); \
+ asm_fprintf (FILE, "%U%s", real_name); \
} while (0)
+/* If -Os, don't force line number labels to begin at the beginning of
+ the word; we still want the assembler to try to put things in parallel,
+ should that be possible.
+ For m32r/d, instructions are never in parallel (other than with a nop)
+ and the simulator and stub both handle a breakpoint in the middle of
+ a word so don't ever force line number labels to begin at the beginning
+ of a word. */
+
+#undef ASM_OUTPUT_SOURCE_LINE
+#define ASM_OUTPUT_SOURCE_LINE(file, line) \
+do \
+ { \
+ static int sym_lineno = 1; \
+ fprintf (file, ".stabn 68,0,%d,.LM%d-", \
+ line, sym_lineno); \
+ assemble_name (file, \
+ XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));\
+ fprintf (file, \
+ (optimize_size || TARGET_M32R) \
+ ? "\n\t.debugsym .LM%d\n" \
+ : "\n.LM%d:\n", \
+ sym_lineno); \
+ sym_lineno += 1; \
+ } \
+while (0)
+
/* Store in OUTPUT a string (made with alloca) containing
an assembler-name for a local static variable named NAME.
LABELNO is an integer which is different for each call. */
After generation of rtl, the compiler makes no further distinction
between pointers and any other objects of this machine mode. */
/* ??? The M32R doesn't have full 32 bit pointers, but making this PSImode has
- it's own problems (you have to add extendpsisi2 and truncsipsi2).
+ its own problems (you have to add extendpsisi2 and truncsipsi2).
Try to avoid it. */
#define Pmode SImode
{ "cmp_int16_operand", { CONST_INT }}, \
{ "call_address_operand", { SYMBOL_REF, LABEL_REF, CONST }}, \
{ "small_insn_p", { INSN, CALL_INSN, JUMP_INSN }}, \
+{ "m32r_block_immediate_operand",{ CONST_INT }}, \
{ "large_insn_p", { INSN, CALL_INSN, JUMP_INSN }},
/* Functions declared in m32r.c */
#endif
#endif
-#ifdef BUFSIZE /* stdio.h has been included, ok to use FILE * */
+#ifdef BUFSIZ /* stdio.h has been included, ok to use FILE * */
#define STDIO_PROTO(ARGS) PROTO(ARGS)
#else
#define STDIO_PROTO(ARGS) ()
extern int large_insn_p PROTO((Rtx, int));
extern int m32r_select_cc_mode PROTO((int, Rtx, Rtx));
extern Rtx gen_compare PROTO((int, Rtx, Rtx, int));
+extern Rtx gen_split_move_double PROTO((Rtx *));
extern int function_arg_partial_nregs PROTO((CUMULATIVE_ARGS *,
int, Tree, int));
extern void m32r_setup_incoming_varargs PROTO((CUMULATIVE_ARGS *,
int, Tree, int *,
int));
+extern struct rtx_def *m32r_va_arg PROTO((Tree, Tree));
extern int m32r_address_code PROTO((Rtx));
extern enum m32r_function_type m32r_compute_function_type
PROTO((Tree));
extern unsigned m32r_compute_frame_size PROTO((int));
extern int m32r_first_insn_address PROTO((void));
+extern void m32r_expand_prologue PROTO((void));
extern void m32r_output_function_prologue STDIO_PROTO((FILE *, int));
extern void m32r_output_function_epilogue STDIO_PROTO((FILE *, int));
extern void m32r_finalize_pic PROTO((void));
extern int carry_compare_operand PROTO((Rtx, int));
extern char *emit_cond_move PROTO((Rtx *, Rtx));
-/* Needed by a peephole optimisation. */
-#define PRESERVE_DEATH_INFO_REGNO_P(regno) (regno < FIRST_PSEUDO_REGISTER)
+extern char * m32r_output_block_move PROTO((Rtx, Rtx *));
+extern int m32r_block_immediate_operand PROTO((Rtx, int));
+extern void m32r_expand_block_move PROTO((Rtx *));