/* Definitions of target machine for GNU compiler. Sun 68000/68020 version.
- Copyright (C) 1987, 88, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
of them must be emulated in software by the OS. When TARGET_68040 is
turned on, these instructions won't be used. This code will still
run on a 68030 and 68881/2. */
-#define MASK_68040 (256|512)
+#define MASK_68040 256
#define TARGET_68040 (target_flags & MASK_68040)
/* Use the 68040-only fp instructions (-m68040 or -m68060). */
#define TARGET_68040_ONLY (target_flags & MASK_68040_ONLY)
/* Optimize for 68060, but still allow execution on 68020
- (-m68060).
+ (-m68020-60 or -m68060).
The 68060 will execute all 68030 and 68881/2 instructions, but some
of them must be emulated in software by the OS. When TARGET_68060 is
turned on, these instructions won't be used. This code will still
#define MASK_5200 2048
#define TARGET_5200 (target_flags & MASK_5200)
+/* Align ints to a word boundary. This breaks compatibility with the
+ published ABI's for structures containing ints, but produces faster
+ code on cpus with 32 bit busses (020, 030, 040, 060, CPU32+, coldfire).
+ It's required for coldfire cpus without a misalignment module. */
+#define MASK_ALIGN_INT 4096
+#define TARGET_ALIGN_INT (target_flags & MASK_ALIGN_INT)
+
+/* Compile for a CPU32 */
+ /* A 68020 without bitfields is a good heuristic for a CPU32 */
+#define TARGET_CPU32 (TARGET_68020 && !TARGET_BITFIELD)
+
/* Macro to define tables used to set the flags.
This is a list in braces of pairs in braces,
each pair being { "NAME", VALUE }
An empty string NAME is used to identify the default VALUE. */
#define TARGET_SWITCHES \
- { { "68020", - (MASK_68060|MASK_68040)}, \
- { "c68020", - (MASK_68060|MASK_68040)}, \
+ { { "68020", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY)}, \
+ { "c68020", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY)}, \
{ "68020", (MASK_68020|MASK_BITFIELD)}, \
{ "c68020", (MASK_68020|MASK_BITFIELD)}, \
- { "68000", - (MASK_68060|MASK_68040|MASK_68020|MASK_BITFIELD)}, \
- { "c68000", - (MASK_68060|MASK_68040|MASK_68020|MASK_BITFIELD)}, \
+ { "68000", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY \
+ |MASK_68020|MASK_BITFIELD)}, \
+ { "c68000", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY \
+ |MASK_68020|MASK_BITFIELD)}, \
{ "bitfield", MASK_BITFIELD}, \
{ "nobitfield", - MASK_BITFIELD}, \
{ "rtd", MASK_RTD}, \
{ "68881" - (MASK_FPA|MASK_SKY)}, \
{ "68881", MASK_68881}, \
{ "soft-float", - (MASK_FPA|MASK_SKY|MASK_68040_ONLY|MASK_68881)}, \
- { "68020-40", (MASK_BITFIELD|MASK_68881|MASK_68020)}, \
- { "68030", - (MASK_68040|MASK_68060)}, \
+ { "68020-40", -(MASK_5200|MASK_68060)}, \
+ { "68020-40", (MASK_BITFIELD|MASK_68881|MASK_68020|MASK_68040)}, \
+ { "68020-60", -(MASK_5200|MASK_68040)}, \
+ { "68020-60", (MASK_BITFIELD|MASK_68881|MASK_68020|MASK_68060)}, \
+ { "68030", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY)}, \
{ "68030", (MASK_68020|MASK_BITFIELD)}, \
- { "68040", (MASK_68020|MASK_68881|MASK_BITFIELD|MASK_68040_ONLY)}, \
+ { "68040", - (MASK_5200|MASK_68060)}, \
+ { "68040", (MASK_68020|MASK_68881|MASK_BITFIELD \
+ |MASK_68040_ONLY|MASK_68040)}, \
+ { "68060", - (MASK_5200|MASK_68040)}, \
{ "68060", (MASK_68020|MASK_68881|MASK_BITFIELD \
|MASK_68040_ONLY|MASK_68060)}, \
{ "5200", - (MASK_68060|MASK_68040|MASK_68020|MASK_BITFIELD|MASK_68881)}, \
{ "5200", (MASK_5200)}, \
{ "68851", 0}, \
{ "no-68851", 0}, \
- { "68302", - (MASK_68060|MASK_68040|MASK_68020|MASK_BITFIELD)}, \
- { "68332", - (MASK_68060|MASK_68040|MASK_BITFIELD)}, \
+ { "68302", - (MASK_5200|MASK_68060|MASK_68040|MASK_68020|MASK_BITFIELD)}, \
+ { "68332", - (MASK_5200|MASK_68060|MASK_68040|MASK_BITFIELD)}, \
{ "68332", MASK_68020}, \
+ { "cpu32", - (MASK_5200|MASK_68060|MASK_68040|MASK_BITFIELD)}, \
+ { "cpu32", MASK_68020}, \
+ { "align-int", MASK_ALIGN_INT }, \
+ { "no-align-int", -MASK_ALIGN_INT }, \
SUBTARGET_SWITCHES \
{ "", TARGET_DEFAULT}}
/* TARGET_DEFAULT is defined in sun*.h and isi.h, etc. */
-/* This is meant to be redefined in the host dependent files */
-#define SUBTARGET_SWITCHES
+/* This macro is similar to `TARGET_SWITCHES' but defines names of
+ command options that have values. Its definition is an
+ initializer with a subgrouping for each command option.
+
+ Each subgrouping contains a string constant, that defines the
+ fixed part of the option name, and the address of a variable. The
+ variable, type `char *', is set to the variable part of the given
+ option if the fixed part matches. The actual option name is made
+ by appending `-m' to the specified name. */
+#define TARGET_OPTIONS \
+{ { "align-loops=", &m68k_align_loops_string }, \
+ { "align-jumps=", &m68k_align_jumps_string }, \
+ { "align-functions=", &m68k_align_funcs_string }, \
+ SUBTARGET_OPTIONS \
+}
+
+/* Sometimes certain combinations of command options do not make
+ sense on a particular target machine. You can define a macro
+ `OVERRIDE_OPTIONS' to take account of this. This macro, if
+ defined, is executed once just after all the command options have
+ been parsed.
+
+ Don't use this macro to turn on various extra optimizations for
+ `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
#define OVERRIDE_OPTIONS \
{ \
+ override_options(); \
if (! TARGET_68020 && flag_pic == 2) \
error("-fPIC is not currently supported on the 68000 or 68010\n"); \
SUBTARGET_OVERRIDE_OPTIONS; \
}
-/* This is meant to be redefined in the host dependent files */
+/* These are meant to be redefined in the host dependent files */
+#define SUBTARGET_SWITCHES
+#define SUBTARGET_OPTIONS
#define SUBTARGET_OVERRIDE_OPTIONS
\f
/* target machine storage layout */
#define STACK_BOUNDARY 16
/* Allocation boundary (in *bits*) for the code of a function. */
-#define FUNCTION_BOUNDARY 16
+#define FUNCTION_BOUNDARY (1 << (m68k_align_funcs + 3))
/* Alignment of field after `int : 0' in a structure. */
#define EMPTY_FIELD_BOUNDARY 16
-/* No data type wants to be aligned rounder than this. */
-#define BIGGEST_ALIGNMENT 16
+/* No data type wants to be aligned rounder than this.
+ Most published ABIs say that ints should be aligned on 16 bit
+ boundries, but cpus with 32 bit busses get better performance
+ aligned on 32 bit boundries. Coldfires without a misalignment
+ module require 32 bit alignment. */
+#define BIGGEST_ALIGNMENT (TARGET_ALIGN_INT ? 32 : 16)
/* Set this nonzero if move instructions will actually fail to work
when given unaligned data. */
#define STRICT_ALIGNMENT 1
+/* Maximum power of 2 that code can be aligned to. */
+#define MAX_CODE_ALIGN 2 /* 4 byte alignment */
+
+/* Align loop starts for optimal branching. */
+#define ASM_OUTPUT_LOOP_ALIGN(FILE) ASM_OUTPUT_ALIGN ((FILE), m68k_align_loops)
+
+/* This is how to align an instruction for optimal branching. */
+#define ASM_OUTPUT_ALIGN_CODE(FILE) ASM_OUTPUT_ALIGN ((FILE), m68k_align_jumps)
+
#define SELECT_RTX_SECTION(MODE, X) \
{ \
if (!flag_pic) \
`J' is used for the range of signed numbers that fit in 16 bits.
`K' is for numbers that moveq can't handle.
`L' is for range -8 to -1, range of values that can be added with subq.
- `M' is for numbers that moveq+notb can't handle. */
+ `M' is for numbers that moveq+notb can't handle.
+ 'N' is for range 24 to 31, rotatert:SI 8 to 1 expressed as rotate.
+ 'O' is for 16 (for rotate using swap).
+ 'P' is for range 8 to 15, rotatert:HI 8 to 1 expressed as rotate. */
#define CONST_OK_FOR_LETTER_P(VALUE, C) \
((C) == 'I' ? (VALUE) > 0 && (VALUE) <= 8 : \
(C) == 'J' ? (VALUE) >= -0x8000 && (VALUE) <= 0x7FFF : \
(C) == 'K' ? (VALUE) < -0x80 || (VALUE) >= 0x80 : \
(C) == 'L' ? (VALUE) < 0 && (VALUE) >= -8 : \
- (C) == 'M' ? (VALUE) < -0x100 && (VALUE) >= 0x100 : 0)
+ (C) == 'M' ? (VALUE) < -0x100 && (VALUE) >= 0x100 : \
+ (C) == 'N' ? (VALUE) >= 24 && (VALUE) <= 31 : \
+ (C) == 'O' ? (VALUE) == 16 : \
+ (C) == 'P' ? (VALUE) >= 8 && (VALUE) <= 15 : 0)
/*
* A small bit of explanation:
(C) == 'H' ? (TARGET_FPA && standard_sun_fpa_constant_p (VALUE)) : 0)
#endif /* defined SUPPORT_SUN_FPA */
+/* A C expression that defines the optional machine-dependent constraint
+ letters that can be used to segregate specific types of operands,
+ usually memory references, for the target machine. It should return 1 if
+ VALUE corresponds to the operand type represented by the constraint letter
+ C. If C is not defined as an extra constraint, the value returned should
+ be 0 regardless of VALUE. */
+
+/* For the m68k, `Q' means address register indirect addressing mode. */
+
+#define EXTRA_CONSTRAINT(OP, C) \
+ ((C) == 'Q' ? (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG) : \
+ 0 )
+
/* Given an rtx X being reloaded into a reg required to be
in class CLASS, return the class of reg to actually use.
In general this is just CLASS; but on some machines
/* If we generate an insn to push BYTES bytes,
this says how many the stack pointer really advances by.
- On the 68000, sp@- in a byte insn really pushes a word. */
-#define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1)
+ On the 68000, sp@- in a byte insn really pushes a word.
+ On the 5200 (coldfire), sp@- in a byte insn pushes just a byte. */
+#define PUSH_ROUNDING(BYTES) (TARGET_5200 ? BYTES : ((BYTES) + 1) & ~1)
/* Offset of first parameter from the argument pointer register value. */
#define FIRST_PARM_OFFSET(FNDECL) 8
the caller must always pop the args. */
#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \
- ((TARGET_RTD && TREE_CODE (FUNTYPE) != IDENTIFIER_NODE \
+ ((TARGET_RTD && (!(FUNDECL) || TREE_CODE (FUNDECL) != IDENTIFIER_NODE) \
&& (TYPE_ARG_TYPES (FUNTYPE) == 0 \
|| (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \
== void_type_node))) \
#define FUNCTION_BLOCK_PROFILER_EXIT(FILE) \
asm_fprintf (FILE, "\tjsr %U__bb_trace_ret\n");
-/* Save all registers which may be clobbered by a function call. */
+/* Save all registers which may be clobbered by a function call.
+ MACHINE_STATE_SAVE and MACHINE_STATE_RESTORE are target-code macros,
+ used in libgcc2.c. They may not refer to TARGET_* macros !!! */
+#if defined (__mc68010__) || defined(mc68010) \
+ || defined(__mc68020__) || defined(mc68020) \
+ || defined(__mc68030__) || defined(mc68030) \
+ || defined(__mc68040__) || defined(mc68040) \
+ || defined(__mc68332__) || defined(mc68332)
+#define MACHINE_STATE_m68010_up
+#endif
#ifdef MOTOROLA
+#if defined(__mcf5200__)
#define MACHINE_STATE_SAVE(id) \
- asm ("move.w %ccr,-(%sp)"); \
- asm ("movm.l &0xc0c0,-(%sp)");
-#else
+ { \
+ asm ("sub.l 20,%sp"); \
+ asm ("movm.l &0x0303,4(%sp)"); \
+ asm ("move.w %ccr,%d0"); \
+ asm ("movm.l &0x0001,(%sp)"); \
+ }
+#else /* !__mcf5200__ */
+#if defined(MACHINE_STATE_m68010_up)
#define MACHINE_STATE_SAVE(id) \
- asm ("movew cc,sp@-"); \
- asm ("moveml d0/d1/a0/a1,sp@-");
-#endif
+ { \
+ asm ("move.w %ccr,-(%sp)"); \
+ asm ("movm.l &0xc0c0,-(%sp)"); \
+ }
+#else /* !MACHINE_STATE_m68010_up */
+#define MACHINE_STATE_SAVE(id) \
+ { \
+ asm ("move.w %sr,-(%sp)"); \
+ asm ("movm.l &0xc0c0,-(%sp)"); \
+ }
+#endif /* MACHINE_STATE_m68010_up */
+#endif /* __mcf5200__ */
+#else /* !MOTOROLA */
+#if defined(__mcf5200__)
+#define MACHINE_STATE_SAVE(id) \
+ { \
+ asm ("subl 20,sp"); \
+ asm ("movml d0/d1/a0/a1,sp@(4)"); \
+ asm ("movew cc,d0"); \
+ asm ("movml d0,sp@"); \
+ }
+#else /* !__mcf5200__ */
+#if defined(MACHINE_STATE_m68010_up)
+#define MACHINE_STATE_SAVE(id) \
+ { \
+ asm ("movew cc,sp@-"); \
+ asm ("moveml d0/d1/a0/a1,sp@-"); \
+ }
+#else /* !MACHINE_STATE_m68010_up */
+#define MACHINE_STATE_SAVE(id) \
+ { \
+ asm ("movew sr,sp@-"); \
+ asm ("moveml d0/d1/a0/a1,sp@-"); \
+ }
+#endif /* MACHINE_STATE_m68010_up */
+#endif /* __mcf5200__ */
+#endif /* MOTOROLA */
/* Restore all registers saved by MACHINE_STATE_SAVE. */
#ifdef MOTOROLA
+#if defined(__mcf5200__)
#define MACHINE_STATE_RESTORE(id) \
- asm ("movm.l (%sp)+,&0x0303"); \
- asm ("move.w (%sp)+,%ccr");
-#else
+ { \
+ asm ("movm.l (%sp),&0x0001"); \
+ asm ("move.w %d0,%ccr"); \
+ asm ("movm.l 4(%sp),&0x0303"); \
+ asm ("add.l 20,%sp"); \
+ }
+#else /* !__mcf5200__ */
#define MACHINE_STATE_RESTORE(id) \
- asm ("moveml sp@+,d0/d1/a0/a1"); \
- asm ("movew sp@+,cc");
-#endif
+ { \
+ asm ("movm.l (%sp)+,&0x0303"); \
+ asm ("move.w (%sp)+,%ccr"); \
+ }
+#endif /* __mcf5200__ */
+#else /* !MOTOROLA */
+#if defined(__mcf5200__)
+#define MACHINE_STATE_RESTORE(id) \
+ { \
+ asm ("movml sp@,d0"); \
+ asm ("movew d0,cc"); \
+ asm ("movml sp@(4),d0/d1/a0/a1"); \
+ asm ("addl 20,sp"); \
+ }
+#else /* !__mcf5200__ */
+#define MACHINE_STATE_RESTORE(id) \
+ { \
+ asm ("moveml sp@+,d0/d1/a0/a1"); \
+ asm ("movew sp@+,cc"); \
+ }
+#endif /* __mcf5200__ */
+#endif /* MOTOROLA */
/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
the stack pointer does not matter. The value is tested only in
case PLUS: \
/* An lea costs about three times as much as a simple add. */ \
if (GET_MODE (X) == SImode \
- && GET_CODE (XEXP (X, 0)) == REG \
- && GET_CODE (XEXP (X, 1)) == MULT \
- && GET_CODE (XEXP (XEXP (X, 1), 0)) == REG \
- && GET_CODE (XEXP (XEXP (X, 1), 1)) == CONST_INT \
- && (INTVAL (XEXP (XEXP (X, 1), 1)) == 2 \
- || INTVAL (XEXP (XEXP (X, 1), 1)) == 4 \
- || INTVAL (XEXP (XEXP (X, 1), 1)) == 8)) \
+ && GET_CODE (XEXP (X, 1)) == REG \
+ && GET_CODE (XEXP (X, 0)) == MULT \
+ && GET_CODE (XEXP (XEXP (X, 0), 0)) == REG \
+ && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
+ && (INTVAL (XEXP (XEXP (X, 0), 1)) == 2 \
+ || INTVAL (XEXP (XEXP (X, 0), 1)) == 4 \
+ || INTVAL (XEXP (XEXP (X, 0), 1)) == 8)) \
return COSTS_N_INSNS (3); /* lea an@(dx:l:i),am */ \
break; \
case ASHIFT: \
extern char *output_move_const_into_data_reg ();
extern char *output_move_simode_const ();
+extern char *output_move_simode ();
+extern char *output_move_himode ();
+extern char *output_move_qimode ();
+extern char *output_move_stricthi ();
+extern char *output_move_strictqi ();
extern char *output_move_double ();
extern char *output_move_const_single ();
extern char *output_move_const_double ();
extern char *output_btst ();
extern char *output_scc_di ();
+extern char *output_addsi3 ();
+
+/* Variables in m68k.c */
+extern char *m68k_align_loops_string;
+extern char *m68k_align_jumps_string;
+extern char *m68k_align_funcs_string;
+extern int m68k_align_loops;
+extern int m68k_align_jumps;
+extern int m68k_align_funcs;
+extern int m68k_last_compare_had_fp_operands;
+
\f
/*
Local variables: