/* Definitions of target machine for GNU compiler. Sun 68000/68020 version.
- Copyright (C) 1987, 1988, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
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. */
/* Note that some other tm.h files include this one and then override
/* Macros used in the machine description to test the flags. */
/* Compile for a 68020 (not a 68000 or 68010). */
-#define TARGET_68020 (target_flags & 1)
+#define MASK_68020 1
+#define TARGET_68020 (target_flags & MASK_68020)
/* Compile 68881 insns for floating point (not library calls). */
-#define TARGET_68881 (target_flags & 2)
+#define MASK_68881 2
+#define TARGET_68881 (target_flags & MASK_68881)
/* Compile using 68020 bitfield insns. */
-#define TARGET_BITFIELD (target_flags & 4)
+#define MASK_BITFIELD 4
+#define TARGET_BITFIELD (target_flags & MASK_BITFIELD)
/* Compile using rtd insn calling sequence.
This will not work unless you use prototypes at least
for all functions that can take varying numbers of args. */
-#define TARGET_RTD (target_flags & 8)
+#define MASK_RTD 8
+#define TARGET_RTD (target_flags & MASK_RTD)
/* Compile passing first two args in regs 0 and 1.
This exists only to test compiler features that will
be needed for RISC chips. It is not usable
and is not intended to be usable on this cpu. */
-#define TARGET_REGPARM (target_flags & 020)
+#define MASK_REGPARM 16
+#define TARGET_REGPARM (target_flags & MASK_REGPARM)
/* Compile with 16-bit `int'. */
-#define TARGET_SHORT (target_flags & 040)
+#define MASK_SHORT 32
+#define TARGET_SHORT (target_flags & MASK_SHORT)
/* Compile with special insns for Sun FPA. */
-#ifdef SUPPORT_SUN_FPA
-#define TARGET_FPA (target_flags & 0100)
-#else
-#define TARGET_FPA 0
-#endif
+#define MASK_FPA 64
+#define TARGET_FPA (target_flags & MASK_FPA)
/* Compile (actually, link) for Sun SKY board. */
-#define TARGET_SKY (target_flags & 0200)
+#define MASK_SKY 128
+#define TARGET_SKY (target_flags & MASK_SKY)
/* Optimize for 68040, but still allow execution on 68020
(-m68020-40 or -m68040).
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 TARGET_68040 (target_flags & 01400)
+#define MASK_68040 256
+#define TARGET_68040 (target_flags & MASK_68040)
+
+/* Use the 68040-only fp instructions (-m68040 or -m68060). */
+#define MASK_68040_ONLY 512
+#define TARGET_68040_ONLY (target_flags & MASK_68040_ONLY)
+
+/* Optimize for 68060, but still allow execution on 68020
+ (-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
+ run on a 68030 and 68881/2. */
+#define MASK_68060 1024
+#define TARGET_68060 (target_flags & MASK_68060)
-/* Use the 68040-only fp instructions (-m68040). */
-#define TARGET_68040_ONLY (target_flags & 01000)
+/* Compile for mcf5200 */
+#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,
An empty string NAME is used to identify the default VALUE. */
#define TARGET_SWITCHES \
- { { "68020", -01400}, \
- { "c68020", -01400}, \
- { "68020", 5}, \
- { "c68020", 5}, \
- { "68881", 2}, \
- { "bitfield", 4}, \
- { "68000", -01405}, \
- { "c68000", -01405}, \
- { "soft-float", -01102}, \
- { "nobitfield", -4}, \
- { "rtd", 8}, \
- { "nortd", -8}, \
- { "short", 040}, \
- { "noshort", -040}, \
- { "fpa", 0100}, \
- { "nofpa", -0100}, \
- { "sky", 0200}, \
- { "nosky", -0200}, \
- { "68020-40", 0407}, \
- { "68030", -01400}, \
- { "68030", 5}, \
- { "68040", 01007}, \
- { "68851", 0}, /* Affects *_SPEC and/or GAS. */ \
- { "no-68851", 0}, /* Affects *_SPEC and/or GAS. */ \
- { "68302", 0}, /* Affects *_SPEC and/or GAS. */ \
- { "no-68302", 0}, /* Affects *_SPEC and/or GAS. */ \
- { "68332", 0}, /* Affects *_SPEC and/or GAS. */ \
- { "no-68332", 0}, /* Affects *_SPEC and/or GAS. */ \
- SUBTARGET_SWITCHES \
+ { { "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_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}, \
+ { "nortd", - MASK_RTD}, \
+ { "short", MASK_SHORT}, \
+ { "noshort", - MASK_SHORT}, \
+ { "fpa", -(MASK_SKY|MASK_68040_ONLY|MASK_68881)}, \
+ { "fpa", MASK_FPA}, \
+ { "nofpa", - MASK_FPA}, \
+ { "sky", -(MASK_FPA|MASK_68040_ONLY|MASK_68881)}, \
+ { "sky", MASK_SKY}, \
+ { "nosky", - MASK_SKY}, \
+ { "68881" - (MASK_FPA|MASK_SKY)}, \
+ { "68881", MASK_68881}, \
+ { "soft-float", - (MASK_FPA|MASK_SKY|MASK_68040_ONLY|MASK_68881)}, \
+ { "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_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_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
-
-#ifdef SUPPORT_SUN_FPA
-/* Blow away 68881 flag silently on TARGET_FPA (since we can't clear
- any bits in TARGET_SWITCHES above) */
-#define OVERRIDE_OPTIONS \
-{ \
- if (TARGET_FPA) target_flags &= ~2; \
- if (! TARGET_68020 && flag_pic == 2) \
- error("-fPIC is not currently supported on the 68000 or 68010\n"); \
- SUBTARGET_OVERRIDE_OPTIONS \
+/* 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 \
}
-#else
+
+/* 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 \
+ SUBTARGET_OVERRIDE_OPTIONS; \
}
-#endif /* defined SUPPORT_SUN_FPA */
-/* 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) \
compiler's mitts completely off it. We don't bother to zero it out
of register classes. If neither TARGET_FPA or TARGET_68881 is set,
the compiler won't touch since no instructions that use these
- registers will be valid.
+ registers will be valid. */
- Reserve PIC_OFFSET_TABLE_REGNUM (a5) for doing PIC relocation if
- position independent code is being generated by making it a
- fixed register */
-
-#ifndef SUPPORT_SUN_FPA
-
-#define CONDITIONAL_REGISTER_USAGE \
-{ \
- if (flag_pic) \
- fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
-}
-
-#else /* defined SUPPORT_SUN_FPA */
+#ifdef SUPPORT_SUN_FPA
#define CONDITIONAL_REGISTER_USAGE \
{ \
if (TEST_HARD_REG_BIT (x, i)) \
fixed_regs[i] = call_used_regs[i] = 1; \
} \
- if (flag_pic) \
- fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
}
#endif /* defined SUPPORT_SUN_FPA */
if 68881 use is disabled. */
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
- (((REGNO) < 16) \
+ (((REGNO) < 16 \
+ && !((REGNO) < 8 && (REGNO) + GET_MODE_SIZE ((MODE)) / 4 > 8)) \
|| ((REGNO) < 24 \
&& TARGET_68881 \
&& (GET_MODE_CLASS (MODE) == MODE_FLOAT \
allowed as immediate shift counts and in addq.
`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. */
-
-#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 : 0)
+ `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.
+ '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 : \
+ (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
On the 68000 series, use a data reg if possible when the
value is a constant in the range where moveq could be used
and we ensure that QImodes are reloaded into data regs.
- Also, if a floating constant needs reloading, put it in memory
- if possible. */
+ Also, if a floating constant needs reloading, put it in memory.
+ Don't do this for !G constants, since all patterns in the md file
+ expect them to be loaded into a register via fpmovecr. See above. */
#define PREFERRED_RELOAD_CLASS(X,CLASS) \
((GET_CODE (X) == CONST_INT \
? DATA_REGS \
: (GET_CODE (X) == CONST_DOUBLE \
&& GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \
- ? NO_REGS \
+ ? (! CONST_DOUBLE_OK_FOR_LETTER_P (X, 'G') \
+ && (CLASS == FP_REGS || CLASS == DATA_OR_FP_REGS) \
+ ? FP_REGS : NO_REGS) \
: (CLASS))
/* Return the maximum number of consecutive registers
/* 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
/* Value is the number of byte 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.
standard Unix calling sequences. If the option is not selected,
the caller must always pop the args. */
-#define RETURN_POPS_ARGS(FUNTYPE,SIZE) \
- ((TARGET_RTD && TREE_CODE (FUNTYPE) != IDENTIFIER_NODE \
+#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \
+ ((TARGET_RTD && (!(FUNDECL) || TREE_CODE (FUNDECL) != IDENTIFIER_NODE) \
&& (TYPE_ARG_TYPES (FUNTYPE) == 0 \
|| (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \
== void_type_node))) \
On the m68k, the offset starts at 0. */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
((CUM) = 0)
/* Update the data in CUM to advance over an argument
/* Output assembler code to FILE to initialize this source file's
basic block profiling info, if that has not already been done. */
-#define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) \
- asm_fprintf (FILE, "\ttstl %LLPBX0\n\tbne %LLPI%d\n\tpea %LLPBX0\n\tjsr %U__bb_init_func\n\taddql %I4,%Rsp\n%LLPI%d:\n", \
- LABELNO, LABELNO);
-
-/* Output assembler code to FILE to increment the entry-count for
+#define FUNCTION_BLOCK_PROFILER(FILE, BLOCK_OR_LABEL) \
+do \
+ { \
+ switch (profile_block_flag) \
+ { \
+ case 2: \
+ asm_fprintf (FILE, "\tpea %d\n\tpea %LLPBX0\n\tjsr %U__bb_init_trace_func\n\taddql %I8,%Rsp\n", \
+ (BLOCK_OR_LABEL)); \
+ break; \
+ \
+ default: \
+ asm_fprintf (FILE, "\ttstl %LLPBX0\n\tbne %LLPI%d\n\tpea %LLPBX0\n\tjsr %U__bb_init_func\n\taddql %I4,%Rsp\n%LLPI%d:\n", \
+ (BLOCK_OR_LABEL), (BLOCK_OR_LABEL)); \
+ break; \
+ } \
+ } \
+while(0)
+
+/* Output assembler code to FILE to increment the counter for
the BLOCKNO'th basic block in this source file. */
#define BLOCK_PROFILER(FILE, BLOCKNO) \
- asm_fprintf (FILE, "\taddql %I1,%LLPBX2+%d\n", 4 * BLOCKNO)
+do \
+ { \
+ switch (profile_block_flag) \
+ { \
+ case 2: \
+ asm_fprintf (FILE, "\tmovel %Ra1,%Rsp@-\n\tlea ___bb,%Ra1\n\tmovel %I%d,%Ra1@(0)\n\tmovel %I%LLPBX0,%Ra1@(4)\n\tmovel %Rsp@+,%Ra1\n\tjsr %U__bb_trace_func\n", \
+ BLOCKNO); \
+ break; \
+ \
+ default: \
+ asm_fprintf (FILE, "\taddql %I1,%LLPBX2+%d\n", 4 * BLOCKNO); \
+ break; \
+ } \
+ } \
+while(0)
+
+/* Output assembler code to FILE to indicate return from
+ a function during basic block profiling. */
+
+#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.
+ 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 ("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 ("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),&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 ("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
of a trampoline, leaving space for the variable parts. */
/* On the 68k, the trampoline looks like this:
- mov @#.,a0
- jsr @#___trampoline
- jsr @#___trampoline
- .long STATIC
- .long FUNCTION
-The reason for having three jsr insns is so that an entire line
-of the instruction cache is filled in a predictable way
-that will always be the same.
-
-We always use the assembler label ___trampoline
-regardless of whether the system adds underscores. */
-
-#define TRAMPOLINE_TEMPLATE(FILE) \
-{ \
- ASM_OUTPUT_SHORT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x207c)); \
- ASM_OUTPUT_SHORT (FILE, const0_rtx); \
- ASM_OUTPUT_SHORT (FILE, const0_rtx); \
- ASM_OUTPUT_SHORT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x4eb9)); \
- ASM_OUTPUT_INT (FILE, gen_rtx (SYMBOL_REF, SImode, "*___trampoline"));\
- ASM_OUTPUT_SHORT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x4eb9)); \
- ASM_OUTPUT_INT (FILE, gen_rtx (SYMBOL_REF, SImode, "*___trampoline"));\
- ASM_OUTPUT_SHORT (FILE, const0_rtx); \
- ASM_OUTPUT_SHORT (FILE, const0_rtx); \
- ASM_OUTPUT_SHORT (FILE, const0_rtx); \
- ASM_OUTPUT_SHORT (FILE, const0_rtx); \
-}
+ movl #STATIC,a0
+ jmp FUNCTION
+
+ WARNING: Targets that may run on 68040+ cpus must arrange for
+ the instruction cache to be flushed. Previous incarnations of
+ the m68k trampoline code attempted to get around this by either
+ using an out-of-line transfer function or pc-relative data, but
+ the fact remains that the code to jump to the transfer function
+ or the code to load the pc-relative data needs to be flushed
+ just as much as the "variable" portion of the trampoline.
+ Recognizing that a cache flush is going to be required anyway,
+ dispense with such notions and build a smaller trampoline. */
+
+/* Since more instructions are required to move a template into
+ place than to create it on the spot, don't use a template. */
/* Length in units of the trampoline for entering a nested function. */
-#define TRAMPOLINE_SIZE 26
+#define TRAMPOLINE_SIZE 12
+
+/* Alignment required for a trampoline in bits. */
-/* Alignment required for a trampoline. 16 is used to find the
- beginning of a line in the instruction cache. */
+#define TRAMPOLINE_ALIGNMENT 16
-#define TRAMPOLINE_ALIGN 16
+/* Targets redefine this to invoke code to either flush the cache,
+ or enable stack execution (or both). */
+
+#ifndef FINALIZE_TRAMPOLINE
+#define FINALIZE_TRAMPOLINE(TRAMP)
+#endif
/* Emit RTL insns to initialize the variable parts of a trampoline.
FNADDR is an RTX for the address of the function's pure code.
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
{ \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 2)), TRAMP); \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 18)), CXT); \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 22)), FNADDR); \
+ emit_move_insn (gen_rtx (MEM, HImode, TRAMP), GEN_INT(0x207C)); \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 2)), CXT); \
+ emit_move_insn (gen_rtx (MEM, HImode, plus_constant (TRAMP, 6)), \
+ GEN_INT(0x4EF9)); \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 8)), FNADDR); \
+ FINALIZE_TRAMPOLINE(TRAMP); \
}
/* This is the library routine that is used
to transfer control from the trampoline
- to the actual nested function. */
+ to the actual nested function.
+ It is defined for backward compatibility,
+ for linking with object code that used the old
+ trampoline definition. */
/* A colon is used with no explicit operands
to cause the template string to be scanned for %-constructs. */
that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
#define LEGITIMATE_PIC_OPERAND_P(X) \
- (! symbolic_operand (X, VOIDmode))
+ ((! symbolic_operand (X, VOIDmode) \
+ && ! (GET_CODE (X) == CONST_DOUBLE && CONST_DOUBLE_MEM (X) \
+ && GET_CODE (CONST_DOUBLE_MEM (X)) == MEM \
+ && symbolic_operand (XEXP (CONST_DOUBLE_MEM (X), 0), \
+ VOIDmode))) \
+ || (GET_CODE (X) == SYMBOL_REF && SYMBOL_REF_FLAG (X)))
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class.
#define LEGITIMATE_INDEX_P(X) \
(LEGITIMATE_INDEX_REG_P (X) \
- || (TARGET_68020 && GET_CODE (X) == MULT \
+ || ((TARGET_68020 || TARGET_5200) && GET_CODE (X) == MULT \
&& LEGITIMATE_INDEX_REG_P (XEXP (X, 0)) \
&& GET_CODE (XEXP (X, 1)) == CONST_INT \
&& (INTVAL (XEXP (X, 1)) == 2 \
|| INTVAL (XEXP (X, 1)) == 4 \
- || INTVAL (XEXP (X, 1)) == 8)))
+ || (INTVAL (XEXP (X, 1)) == 8 && !TARGET_5200))))
/* If pic, we accept INDEX+LABEL, which is what do_tablejump makes. */
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
case CONST_INT: \
/* Constant zero is super cheap due to clr instruction. */ \
if (RTX == const0_rtx) return 0; \
- /* Constants between -128 and 127 are cheap due to moveq */ \
- if (INTVAL (RTX) >= -128 && INTVAL (RTX) <= 127) return 1; \
- /* Constants between -136 and 254 are easily generated */ \
- /* by intelligent uses of moveq, add[q], and subq */ \
- if ((OUTER_CODE) == SET && INTVAL (RTX) >= -136 \
- && INTVAL (RTX) <= 254) return 2; \
+ /* if ((OUTER_CODE) == SET) */ \
+ return const_int_cost(RTX); \
case CONST: \
case LABEL_REF: \
case SYMBOL_REF: \
work properly in synth_mult on the 68020,
relative to an average of the time for add and the time for shift,
taking away a little more because sometimes move insns are needed. */
-#define MULL_COST (TARGET_68040 ? 5 : 13)
-#define MULW_COST (TARGET_68040 ? 3 : 8)
+/* div?.w is relatively cheaper on 68000 counted in COSTS_N_INSNS terms. */
+#define MULL_COST (TARGET_68060 ? 2 : TARGET_68040 ? 5 : 13)
+#define MULW_COST (TARGET_68060 ? 2 : TARGET_68040 ? 3 : TARGET_68020 ? 8 : 5)
+#define DIVW_COST (TARGET_68020 ? 27 : 12)
#define RTX_COSTS(X,CODE,OUTER_CODE) \
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: \
case ASHIFTRT: \
- case LSHIFT: \
case LSHIFTRT: \
+ if (TARGET_68060) \
+ return COSTS_N_INSNS(1); \
+ if (! TARGET_68020) \
+ { \
+ if (GET_CODE (XEXP (X, 1)) == CONST_INT) \
+ { \
+ if (INTVAL (XEXP (X, 1)) < 16) \
+ return COSTS_N_INSNS (2) + INTVAL (XEXP (X, 1)) / 2; \
+ else \
+ /* We're using clrw + swap for these cases. */ \
+ return COSTS_N_INSNS (4) + (INTVAL (XEXP (X, 1)) - 16) / 2; \
+ } \
+ return COSTS_N_INSNS (10); /* worst case */ \
+ } \
/* A shift by a big integer takes an extra instruction. */ \
if (GET_CODE (XEXP (X, 1)) == CONST_INT \
&& (INTVAL (XEXP (X, 1)) == 16)) \
return COSTS_N_INSNS (3); /* lsr #i,dn */ \
break; \
case MULT: \
- if (GET_CODE (XEXP (x, 1)) == CONST_INT \
- && exact_log2 (INTVAL (XEXP (x, 1))) >= 0) \
- { \
- /* A shift by a big integer takes an extra instruction. */ \
- if (GET_CODE (XEXP (X, 1)) == CONST_INT \
- && (INTVAL (XEXP (X, 1)) == (1 << 16))) \
- return COSTS_N_INSNS (2); /* clrw;swap */ \
- if (GET_CODE (XEXP (X, 1)) == CONST_INT \
- && !(INTVAL (XEXP (X, 1)) > 1 \
- && INTVAL (XEXP (X, 1)) <= 256)) \
- return COSTS_N_INSNS (3); /* lsr #i,dn */ \
- break; \
- } \
- else if (GET_MODE (X) == QImode || GET_MODE (X) == HImode) \
+ if ((GET_CODE (XEXP (X, 0)) == ZERO_EXTEND \
+ || GET_CODE (XEXP (X, 0)) == SIGN_EXTEND) \
+ && GET_MODE (X) == SImode) \
+ return COSTS_N_INSNS (MULW_COST); \
+ if (GET_MODE (X) == QImode || GET_MODE (X) == HImode) \
return COSTS_N_INSNS (MULW_COST); \
else \
return COSTS_N_INSNS (MULL_COST); \
- break; \
case DIV: \
case UDIV: \
case MOD: \
case UMOD: \
if (GET_MODE (X) == QImode || GET_MODE (X) == HImode) \
- return COSTS_N_INSNS (27); /* div.w */ \
+ return COSTS_N_INSNS (DIVW_COST); /* div.w */ \
return COSTS_N_INSNS (43); /* div.l */
\f
/* Tell final.c how to eliminate redundant test instructions. */
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
+/* Definitions for generating bytecode */
+
+/* Just so it's known this target is supported by the bytecode generator.
+ If this define isn't found anywhere in the target config files, then
+ dummy stubs are supplied by bytecode.h, and any attempt to use
+ -fbytecode will result in an error message. */
+
+#define TARGET_SUPPORTS_BYTECODE
+
+/* Minimal segment alignment within sections is 8 units. */
+#define MACHINE_SEG_ALIGN 3
+
+/* Integer alignment is two units. */
+#define INT_ALIGN 2
+
+/* Pointer alignment is eight units. */
+#define PTR_ALIGN 3
+
+/* Global symbols begin with `_' */
+#define NAMES_HAVE_UNDERSCORES
+
+/* BC_xxx below are similar to their ASM_xxx counterparts above. */
+#define BC_GLOBALIZE_LABEL(FP, NAME) bc_globalize_label(NAME)
+
+#define BC_OUTPUT_COMMON(FP, NAME, SIZE, ROUNDED) \
+ do { bc_emit_common(NAME, ROUNDED); bc_globalize_label(NAME); } while (0)
+
+#define BC_OUTPUT_BSS(FP, NAME, SIZE, ROUNDED) \
+ do { bc_data (); bc_emit_labeldef(NAME); bc_emit_skip (SIZE); } while (0)
+
+#define BC_OUTPUT_LOCAL(FP, NAME, SIZE, ROUNDED) \
+ bc_emit_common(NAME, ROUNDED)
+
+#define BC_OUTPUT_ALIGN(FP, ALIGN) bc_align(ALIGN)
+
+#define BC_OUTPUT_LABEL(FP, NAME) bc_emit_labeldef(NAME)
+
+#define BC_OUTPUT_SKIP(FP, SIZE) bc_emit_skip(SIZE)
+
+#define BC_OUTPUT_LABELREF(FP, NAME) \
+ do { \
+ char *foo = (char *) xmalloc(strlen(NAME) + 2); \
+ strcpy(foo, "_"); \
+ strcat(foo, NAME); \
+ bc_emit_labelref (foo); \
+ free (foo); \
+ } while (0)
+
+#define BC_OUTPUT_FLOAT(FP, VAL) \
+ do { \
+ float F = VAL; \
+ bc_emit ((char *) &F, sizeof F); \
+ } while (0)
+
+#define BC_OUTPUT_DOUBLE(FP, VAL) \
+ do { \
+ double D = VAL; \
+ bc_emit ((char *) &D, sizeof D); \
+ } while (0)
+
+#define BC_OUTPUT_BYTE(FP, VAL) \
+ do { \
+ char C = VAL; \
+ bc_emit (&C, 1); \
+ } while (0)
+
+
+#define BC_OUTPUT_FILE ASM_OUTPUT_FILE
+#define BC_OUTPUT_ASCII ASM_OUTPUT_ASCII
+#define BC_OUTPUT_IDENT ASM_OUTPUT_IDENT
+
+/* Same as XSTR, but for bytecode */
+#define BCXSTR(RTX) ((RTX)->bc_label)
+
+
+/* Flush bytecode buffer onto file */
+#define BC_WRITE_FILE(FP) \
+{ \
+ fprintf (FP, ".text\n"); \
+ bc_seg_write (bc_text_seg, FP); \
+ fprintf(FP, "\n.data\n"); \
+ bc_seg_write (bc_data_seg, FP); \
+ bc_sym_write (FP); /* do .globl, .bss, etc. */ \
+}
+
+/* Write one symbol */
+#define BC_WRITE_SEGSYM(SEGSYM, FP) \
+{ \
+ prsym (FP, (SEGSYM)->sym->name); \
+ fprintf (FP, ":\n"); \
+}
+
+
+/* Write one reloc entry */
+#define BC_WRITE_RELOC_ENTRY(SEGRELOC, FP, OFFSET) \
+{ \
+ fprintf (FP, "\t.long "); \
+ prsym (FP, (SEGRELOC)->sym->name); \
+ fprintf (FP, " + %d\n", OFFSET); \
+}
+
+/* Start new line of bytecodes */
+#define BC_START_BYTECODE_LINE(FP) \
+{ \
+ fprintf (FP, "\t.byte"); \
+}
+
+/* Write one bytecode */
+#define BC_WRITE_BYTECODE(SEP, VAL, FP) \
+{ \
+ fprintf (FP, "%c0x%02X", (SEP), (VAL) & 0xff); \
+}
+
+/* Write one bytecode RTL entry */
+#define BC_WRITE_RTL(R, FP) \
+{ \
+ fprintf (FP, "%s+%d/0x%08X\n", (R)->label, (R)->offset, (R)->bc_label); \
+}
+
+
+/* Emit function entry trampoline */
+#define BC_EMIT_TRAMPOLINE(TRAMPSEG, CALLINFO) \
+{ \
+ short insn; \
+ \
+ /* Push a reference to the callinfo structure. */ \
+ insn = 0x4879; /* pea xxx.L */ \
+ seg_data (TRAMPSEG, (char *) &insn, sizeof insn); \
+ seg_refsym (TRAMPSEG, CALLINFO, 0); \
+ \
+ /* Call __interp, pop arguments, and return. */ \
+ insn = 0x4eb9; /* jsr xxx.L */ \
+ seg_data (TRAMPSEG, (char *) &insn, sizeof insn); \
+ seg_refsym (TRAMPSEG, "__callint", 0); \
+ insn = 0x588f; /* addql #4, sp */ \
+ seg_data (TRAMPSEG, (char *) &insn, sizeof insn); \
+ insn = 0x4e75; /* rts */ \
+ seg_data (TRAMPSEG, (char *) &insn, sizeof insn); \
+}
+
+
+
+#if 0
+#define VALIDATE_STACK() if (stack_depth < 0) abort ();
+#else
+#if 0
+#define VALIDATE_STACK() \
+ fprintf (stderr, " %%%d%%", stack_depth);
+#endif
+#endif
+
/* Define functions defined in aux-output.c and used in templates. */
+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: