OSDN Git Service

(output_addsi3): Add declaration.
[pf3gnuchains/gcc-fork.git] / gcc / config / m68k / m68k.h
index 44a1b73..ba728bc 100644 (file)
@@ -1,5 +1,5 @@
 /* Definitions of target machine for GNU compiler.  Sun 68000/68020 version.
-   Copyright (C) 1987, 1988 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -15,7 +15,8 @@ GNU General Public License for more details.
 
 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
@@ -49,47 +50,72 @@ extern int target_flags;
 /* 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.
+/* Optimize for 68040, but still allow execution on 68020
+   (-m68020-40 or -m68040).
    The 68040 will execute all 68030 and 68881/2 instructions, but some
    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 & 0400)
+#define MASK_68040_ALSO (256)
+#define MASK_68040     (256|512)
+#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
+   (-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)
+
+/* Compile for mcf5200 */
+#define MASK_5200      2048
+#define TARGET_5200 (target_flags & MASK_5200)
 
-/* Support 68040 fp instructions.  */
-#define TARGET_68040_ONLY (target_flags & 01000)
+/* 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,
@@ -98,48 +124,93 @@ extern int target_flags;
    An empty string NAME is used to identify the default VALUE.  */
 
 #define TARGET_SWITCHES  \
-  { { "68020", 5},                             \
-    { "c68020", 5},                            \
-    { "68881", 2},                             \
-    { "bitfield", 4},                          \
-    { "68000", -5},                            \
-    { "c68000", -5},                           \
-    { "soft-float", -0102},                    \
-    { "nobitfield", -4},                       \
-    { "rtd", 8},                               \
-    { "nortd", -8},                            \
-    { "short", 040},                           \
-    { "noshort", -040},                                \
-    { "fpa", 0100},                            \
-    { "nofpa", -0100},                         \
-    { "sky", 0200},                            \
-    { "nosky", -0200},                         \
-    { "68040", 0407},                          \
-    { "68030", -01400},                                \
-    { "68030", 7},                             \
-    { "68040-only", 01000},                    \
+  { { "68020", - (MASK_68060|MASK_68040)},                             \
+    { "c68020", - (MASK_68060|MASK_68040)},                            \
+    { "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)},   \
+    { "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_BITFIELD|MASK_68881|MASK_68020|MASK_68040_ALSO)}, \
+    { "68030", - (MASK_68040|MASK_68060)},                             \
+    { "68030", (MASK_68020|MASK_BITFIELD)},                            \
+    { "68040", (MASK_68020|MASK_68881|MASK_BITFIELD|MASK_68040_ONLY)}, \
+    { "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)},               \
+    { "68332", MASK_68020},                                            \
+    SUBTARGET_SWITCHES                                                 \
     { "", TARGET_DEFAULT}}
 /* TARGET_DEFAULT is defined in sun*.h and isi.h, etc.  */
 
-#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"); \
+/* 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;          \
 }
-#endif /* defined SUPPORT_SUN_FPA */
+
+/* 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 for XFmode extended real floating point support.
+   This will automatically cause REAL_ARITHMETIC to be defined.  */
+#define LONG_DOUBLE_TYPE_SIZE 96
+
+/* Define if you don't want extended real, but do want to use the
+   software floating point emulator for REAL_ARITHMETIC and
+   decimal <-> binary conversion. */
+/* #define REAL_ARITHMETIC */
+
 /* Define this if most significant bit is lowest numbered
    in instructions that operate on numbered bit-fields.
    This is true for 68020 insns such as bfins and bfexts.
@@ -181,7 +252,7 @@ extern int target_flags;
 #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
@@ -193,6 +264,15 @@ extern int target_flags;
    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)                                                       \
@@ -317,21 +397,9 @@ extern int target_flags;
    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.  
-
-   Reserve PIC_OFFSET_TABLE_REGNUM (a5) for doing PIC relocation if
-   position independent code is being generated by making it a 
-   fixed register */
+   registers will be valid.  */
 
-#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 \
 {                                              \
@@ -351,8 +419,6 @@ extern int target_flags;
        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 */
@@ -377,7 +443,8 @@ extern int target_flags;
    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         \
@@ -618,13 +685,21 @@ extern enum reg_class regno_reg_class[];
    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:
@@ -650,8 +725,9 @@ extern enum reg_class regno_reg_class[];
    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                  \
@@ -662,7 +738,9 @@ extern enum reg_class regno_reg_class[];
    ? 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
@@ -731,6 +809,7 @@ extern enum reg_class regno_reg_class[];
 
 /* 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.
@@ -744,8 +823,8 @@ extern enum reg_class regno_reg_class[];
    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)))                                \
@@ -773,6 +852,11 @@ extern enum reg_class regno_reg_class[];
 
 #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0)
 
+/* Define this to be true when FUNCTION_VALUE_REGNO_P is true for
+   more than one register.  */
+
+#define NEEDS_UNTYPED_CALL 0
+
 /* Define this if PCC uses the nonreentrant convention for returning
    structure and union values.  */
 
@@ -800,7 +884,7 @@ extern enum reg_class regno_reg_class[];
 
    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
@@ -856,15 +940,73 @@ extern enum reg_class regno_reg_class[];
 /* 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. */
+
+#ifdef MOTOROLA
+#define MACHINE_STATE_SAVE(id)         \
+  asm ("move.w %ccr,-(%sp)");          \
+  asm ("movm.l &0xc0c0,-(%sp)");
+#else
+#define MACHINE_STATE_SAVE(id)         \
+  asm ("movew cc,sp@-");               \
+  asm ("moveml d0/d1/a0/a1,sp@-");
+#endif
+
+/* Restore all registers saved by MACHINE_STATE_SAVE. */
+
+#ifdef MOTOROLA
+#define MACHINE_STATE_RESTORE(id)      \
+  asm ("movm.l (%sp)+,&0x0303");       \
+  asm ("move.w (%sp)+,%ccr");
+#else
+#define MACHINE_STATE_RESTORE(id)      \
+  asm ("moveml sp@+,d0/d1/a0/a1");     \
+  asm ("movew sp@+,cc");
+#endif
 
 /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
    the stack pointer does not matter.  The value is tested only in
@@ -911,41 +1053,36 @@ extern enum reg_class regno_reg_class[];
    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.  16 is used to find the
-   beginning of a line in the instruction cache.  */
+/* Alignment required for a trampoline in bits.  */
 
-#define TRAMPOLINE_ALIGN 16
+#define TRAMPOLINE_ALIGNMENT 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.
@@ -953,14 +1090,20 @@ regardless of whether the system adds underscores.  */
 
 #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.  */
@@ -972,7 +1115,7 @@ void                                                               \
 __transfer_from_trampoline ()                                  \
 {                                                              \
   register char *a0 asm ("%a0");                               \
-  asm (GLOBAL_ASM_OP, " ___trampoline");                       \
+  asm (GLOBAL_ASM_OP " ___trampoline");                                \
   asm ("___trampoline:");                                      \
   asm volatile ("move%.l %0,%@" : : "m" (a0[22]));             \
   asm volatile ("move%.l %1,%0" : "=a" (a0) : "m" (a0[18]));   \
@@ -1041,7 +1184,10 @@ __transfer_from_trampoline ()                                    \
 
 /* Recognize any constant value that is a valid address.  */
 
-#define CONSTANT_ADDRESS_P(X)  CONSTANT_P (X)
+#define CONSTANT_ADDRESS_P(X)   \
+  (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF             \
+   || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST               \
+   || GET_CODE (X) == HIGH)
 
 /* Nonzero if the constant value X is a legitimate general operand.
    It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
@@ -1053,7 +1199,12 @@ __transfer_from_trampoline ()                                    \
    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.
@@ -1100,14 +1251,23 @@ __transfer_from_trampoline ()                                   \
 
    The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS.  */
 
+/* Allow SUBREG everywhere we allow REG.  This results in better code.  It
+   also makes function inlining work when inline functions are called with
+   arguments that are SUBREGs.  */
+
+#define LEGITIMATE_BASE_REG_P(X)   \
+  ((GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X))      \
+   || (GET_CODE (X) == SUBREG                          \
+       && GET_CODE (SUBREG_REG (X)) == REG             \
+       && REG_OK_FOR_BASE_P (SUBREG_REG (X))))
+
 #define INDIRECTABLE_1_ADDRESS_P(X)  \
   ((CONSTANT_ADDRESS_P (X) && (!flag_pic || LEGITIMATE_PIC_OPERAND_P (X))) \
-   || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X))                   \
+   || LEGITIMATE_BASE_REG_P (X)                                                \
    || ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC)           \
-       && REG_P (XEXP (X, 0))                                          \
-       && REG_OK_FOR_BASE_P (XEXP (X, 0)))                             \
+       && LEGITIMATE_BASE_REG_P (XEXP (X, 0)))                         \
    || (GET_CODE (X) == PLUS                                            \
-       && REG_P (XEXP (X, 0)) && REG_OK_FOR_BASE_P (XEXP (X, 0))       \
+       && LEGITIMATE_BASE_REG_P (XEXP (X, 0))                          \
        && GET_CODE (XEXP (X, 1)) == CONST_INT                          \
        && ((unsigned) INTVAL (XEXP (X, 1)) + 0x8000) < 0x10000)                \
    || (GET_CODE (X) == PLUS && XEXP (X, 0) == pic_offset_table_rtx     \
@@ -1127,9 +1287,16 @@ __transfer_from_trampoline ()                                    \
 #define GO_IF_NONINDEXED_ADDRESS(X, ADDR)  \
 { if (INDIRECTABLE_1_ADDRESS_P (X)) goto ADDR; }
 
-#define GO_IF_INDEXABLE_BASE(X, ADDR)  \
-{ if (GET_CODE (X) == LABEL_REF) goto ADDR;                            \
-  if (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) goto ADDR; }
+/* Only labels on dispatch tables are valid for indexing from.  */
+#define GO_IF_INDEXABLE_BASE(X, ADDR)                          \
+{ rtx temp;                                                    \
+  if (GET_CODE (X) == LABEL_REF                                        \
+      && (temp = next_nonnote_insn (XEXP (X, 0))) != 0         \
+      && GET_CODE (temp) == JUMP_INSN                          \
+      && (GET_CODE (PATTERN (temp)) == ADDR_VEC                        \
+         || GET_CODE (PATTERN (temp)) == ADDR_DIFF_VEC))       \
+    goto ADDR;                                                 \
+  if (LEGITIMATE_BASE_REG_P (X)) goto ADDR; }
 
 #define GO_IF_INDEXING(X, ADDR)        \
 { if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 0)))                \
@@ -1152,20 +1319,33 @@ __transfer_from_trampoline ()                                   \
    || (GET_CODE (X) == SIGN_EXTEND                     \
        && GET_CODE (XEXP (X, 0)) == REG                        \
        && GET_MODE (XEXP (X, 0)) == HImode             \
-       && REG_OK_FOR_INDEX_P (XEXP (X, 0))))
+       && REG_OK_FOR_INDEX_P (XEXP (X, 0)))            \
+   || (GET_CODE (X) == SUBREG                          \
+       && GET_CODE (SUBREG_REG (X)) == REG             \
+       && REG_OK_FOR_INDEX_P (SUBREG_REG (X))))
 
 #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)))
-
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)  \
-{ GO_IF_NONINDEXED_ADDRESS (X, ADDR);                  \
-  GO_IF_INDEXED_ADDRESS (X, ADDR); }
+           || (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)                                \
+{ GO_IF_NONINDEXED_ADDRESS (X, ADDR);                                  \
+  GO_IF_INDEXED_ADDRESS (X, ADDR);                                     \
+  if (flag_pic && MODE == CASE_VECTOR_MODE && GET_CODE (X) == PLUS     \
+      && LEGITIMATE_INDEX_P (XEXP (X, 0))                              \
+      && GET_CODE (XEXP (X, 1)) == LABEL_REF)                          \
+    goto ADDR; }
+
+/* Don't call memory_address_noforce for the address to fetch
+   the switch offset.  This address is ok as it stands (see above),
+   but memory_address_noforce would alter it.  */
+#define PIC_CASE_VECTOR_ADDRESS(index) index
 \f
 /* Try machine-dependent ways of modifying an illegitimate address
    to be legitimate.  If we find one, return the new, valid address.
@@ -1289,12 +1469,8 @@ __transfer_from_trampoline ()                                    \
   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:                                             \
@@ -1308,26 +1484,41 @@ __transfer_from_trampoline ()                                   \
    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))                        \
@@ -1338,30 +1529,20 @@ __transfer_from_trampoline ()                                   \
       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.  */
@@ -1506,31 +1687,36 @@ __transfer_from_trampoline ()                                   \
 #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM)  \
   sprintf (LABEL, "*%s%s%d", LOCAL_LABEL_PREFIX, PREFIX, NUM)
 
+/* This is how to output a `long double' extended real constant. */
+  
+#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE)                             \
+do { long l[3];                                                                \
+     REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l);                      \
+     if (sizeof (int) == sizeof (long))                                        \
+       fprintf (FILE, "\t.long 0x%x,0x%x,0x%x\n", l[0], l[1], l[2]);   \
+     else                                                              \
+       fprintf (FILE, "\t.long 0x%lx,0x%lx,0x%lx\n", l[0], l[1], l[2]);        \
+   } while (0)
+  
 /* This is how to output an assembler line defining a `double' constant.  */
 
-#define ASM_OUTPUT_DOUBLE(FILE,VALUE)  \
-  fprintf (FILE, "\t.double 0r%.20g\n", (VALUE))
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE)                          \
+  do { char dstr[30];                                          \
+       REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr);           \
+       fprintf (FILE, "\t.double 0r%s\n", dstr);               \
+     } while (0)
 
 /* This is how to output an assembler line defining a `float' constant.  */
 
-/* Sun's assembler can't handle floating constants written as floating.
-   However, when cross-compiling, always use that in case format differs.  */
-
-#ifdef CROSS_COMPILE
-
-#define ASM_OUTPUT_FLOAT(FILE,VALUE)  \
-  fprintf (FILE, "\t.float 0r%.10g\n", (VALUE))
-
-#else
-
-#define ASM_OUTPUT_FLOAT(FILE,VALUE)  \
-do { union { float f; long l;} tem;                    \
-     tem.f = (VALUE);                                  \
-     fprintf (FILE, "\t.long 0x%x\n", tem.l);  \
+#define ASM_OUTPUT_FLOAT(FILE,VALUE)                   \
+do { long l;                                           \
+     REAL_VALUE_TO_TARGET_SINGLE (VALUE, l);           \
+     if (sizeof (int) == sizeof (long))                        \
+       fprintf (FILE, "\t.long 0x%x\n", l);            \
+     else                                              \
+       fprintf (FILE, "\t.long 0x%lx\n", l);           \
    } while (0)
 
-#endif /* not CROSS_COMPILE */
-
 /* This is how to output an assembler line defining an `int' constant.  */
 
 #define ASM_OUTPUT_INT(FILE,VALUE)  \
@@ -1633,13 +1819,41 @@ do { union { float f; long l;} tem;                     \
 
 /* Output a float value (represented as a C double) as an immediate operand.
    This macro is a 68k-specific macro.  */
-#define ASM_OUTPUT_FLOAT_OPERAND(FILE,VALUE)                           \
-  asm_fprintf (FILE, "%I0r%.9g", (VALUE))
+
+#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE)              \
+ do {                                                          \
+      if (CODE == 'f')                                         \
+        {                                                      \
+          char dstr[30];                                       \
+          REAL_VALUE_TO_DECIMAL (VALUE, "%.9g", dstr);         \
+          asm_fprintf ((FILE), "%I0r%s", dstr);                        \
+        }                                                      \
+      else                                                     \
+        {                                                      \
+          long l;                                              \
+          REAL_VALUE_TO_TARGET_SINGLE (VALUE, l);              \
+          if (sizeof (int) == sizeof (long))                   \
+            asm_fprintf ((FILE), "%I0x%x", l);                 \
+          else                                                 \
+            asm_fprintf ((FILE), "%I0x%lx", l);                        \
+        }                                                      \
+     } while (0)
 
 /* Output a double value (represented as a C double) as an immediate operand.
    This macro is a 68k-specific macro.  */
 #define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE)                          \
-  asm_fprintf (FILE, "%I0r%.20g", (VALUE))
+ do { char dstr[30];                                                   \
+      REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr);                    \
+      asm_fprintf (FILE, "%I0r%s", dstr);                              \
+    } while (0)
+
+/* Note, long double immediate operands are not actually
+   generated by m68k.md.  */
+#define ASM_OUTPUT_LONG_DOUBLE_OPERAND(FILE,VALUE)                     \
+ do { char dstr[30];                                                   \
+      REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr);                    \
+      asm_fprintf (FILE, "%I0r%s", dstr);                              \
+    } while (0)
 
 /* 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.
@@ -1658,6 +1872,7 @@ do { union { float f; long l;} tem;                       \
    '!' for the fpcr register (used in some float-to-fixed conversions).
    '$' for the letter `s' in an op code, but only on the 68040.
    '&' for the letter `d' in an op code, but only on the 68040.
+   '/' for register prefix needed by longlong.h.
 
    'b' for byte insn (no effect, on the Sun; this is for the ISI).
    'd' to force memory addressing to be absolute, not relative.
@@ -1673,26 +1888,7 @@ do { union { float f; long l;} tem;                      \
 #define PRINT_OPERAND_PUNCT_VALID_P(CODE)                              \
   ((CODE) == '.' || (CODE) == '#' || (CODE) == '-'                     \
    || (CODE) == '+' || (CODE) == '@' || (CODE) == '!'                  \
-   || (CODE) == '$' || (CODE) == '&')
-
-#ifdef HOST_WORDS_BIG_ENDIAN
-#define PRINT_OPERAND_EXTRACT_FLOAT(X)                                 \
-      u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X);
-#else
-#define PRINT_OPERAND_EXTRACT_FLOAT(X)                                 \
-      u.i[0] = CONST_DOUBLE_HIGH (X); u.i[1] = CONST_DOUBLE_LOW (X);
-#endif
-
-#ifdef CROSS_COMPILE
-#define PRINT_OPERAND_PRINT_FLOAT(CODE, FILE)   \
-  ASM_OUTPUT_FLOAT_OPERAND (FILE, u1.f);
-#else
-#define PRINT_OPERAND_PRINT_FLOAT(CODE, FILE)   \
-{ if (CODE == 'f')                                                     \
-    ASM_OUTPUT_FLOAT_OPERAND (FILE, u1.f);                             \
-  else                                                                 \
-    asm_fprintf (FILE, "%I0x%x", u1.i); }
-#endif
+   || (CODE) == '$' || (CODE) == '&' || (CODE) == '/')
 
 /* A C compound statement to output to stdio stream STREAM the
    assembler syntax for an instruction operand X.  X is an RTL
@@ -1730,12 +1926,180 @@ do { union { float f; long l;} tem;                    \
 #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_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: