summaryrefslogtreecommitdiff
path: root/gcc/config/m68k
diff options
context:
space:
mode:
authorYamaArashi <shadow962@live.com>2016-01-06 01:47:28 -0800
committerYamaArashi <shadow962@live.com>2016-01-06 01:47:28 -0800
commitbe8b04496302184c6e8f04d6179f9c3afc50aeb6 (patch)
tree726e2468c0c07add773c0dbd86ab6386844259ae /gcc/config/m68k
initial commit
Diffstat (limited to 'gcc/config/m68k')
-rwxr-xr-xgcc/config/m68k/3b1.h513
-rwxr-xr-xgcc/config/m68k/3b1g.h64
-rwxr-xr-xgcc/config/m68k/a-ux.h206
-rwxr-xr-xgcc/config/m68k/altos3068.h135
-rwxr-xr-xgcc/config/m68k/amix.h149
-rwxr-xr-xgcc/config/m68k/apollo68.h208
-rwxr-xr-xgcc/config/m68k/atari.h106
-rwxr-xr-xgcc/config/m68k/aux-crt1.c134
-rwxr-xr-xgcc/config/m68k/aux-crt2.asm42
-rwxr-xr-xgcc/config/m68k/aux-crtn.asm26
-rwxr-xr-xgcc/config/m68k/aux-exit.c99
-rwxr-xr-xgcc/config/m68k/aux-low.gld38
-rwxr-xr-xgcc/config/m68k/aux-mcount.c69
-rwxr-xr-xgcc/config/m68k/auxas.h189
-rwxr-xr-xgcc/config/m68k/auxgas.h56
-rwxr-xr-xgcc/config/m68k/auxgld.h29
-rwxr-xr-xgcc/config/m68k/auxld.h35
-rwxr-xr-xgcc/config/m68k/ccur-GAS.h129
-rwxr-xr-xgcc/config/m68k/coff.h176
-rwxr-xr-xgcc/config/m68k/crds.h621
-rwxr-xr-xgcc/config/m68k/ctix.h48
-rwxr-xr-xgcc/config/m68k/dpx2.h822
-rwxr-xr-xgcc/config/m68k/dpx2.ifile55
-rwxr-xr-xgcc/config/m68k/dpx2cdbx.h31
-rwxr-xr-xgcc/config/m68k/dpx2g.h71
-rwxr-xr-xgcc/config/m68k/fpgnulib.c442
-rwxr-xr-xgcc/config/m68k/hp2bsd.h78
-rwxr-xr-xgcc/config/m68k/hp310.h36
-rwxr-xr-xgcc/config/m68k/hp310g.h12
-rwxr-xr-xgcc/config/m68k/hp320.h642
-rwxr-xr-xgcc/config/m68k/hp320g.h12
-rwxr-xr-xgcc/config/m68k/hp3bsd.h44
-rwxr-xr-xgcc/config/m68k/hp3bsd44.h53
-rwxr-xr-xgcc/config/m68k/hpux7.h7
-rwxr-xr-xgcc/config/m68k/isi-nfp.h9
-rwxr-xr-xgcc/config/m68k/isi.h91
-rwxr-xr-xgcc/config/m68k/lb1sf68.asm3904
-rwxr-xr-xgcc/config/m68k/lb1sun3.asm1036
-rwxr-xr-xgcc/config/m68k/linux-aout.h77
-rwxr-xr-xgcc/config/m68k/linux.h387
-rwxr-xr-xgcc/config/m68k/lynx-ng.h43
-rwxr-xr-xgcc/config/m68k/lynx.h74
-rwxr-xr-xgcc/config/m68k/m68020-elf.h53
-rwxr-xr-xgcc/config/m68k/m68360-coff.h27
-rwxr-xr-xgcc/config/m68k/m68360-none.h129
-rwxr-xr-xgcc/config/m68k/m68k-aout.h44
-rwxr-xr-xgcc/config/m68k/m68k-coff.h28
-rwxr-xr-xgcc/config/m68k/m68k-none.h197
-rwxr-xr-xgcc/config/m68k/m68k-psos.h67
-rwxr-xr-xgcc/config/m68k/m68k.c3393
-rwxr-xr-xgcc/config/m68k/m68k.h2139
-rwxr-xr-xgcc/config/m68k/m68k.md7913
-rwxr-xr-xgcc/config/m68k/m68kelf.h297
-rwxr-xr-xgcc/config/m68k/m68kemb.h55
-rwxr-xr-xgcc/config/m68k/m68kv4.h346
-rwxr-xr-xgcc/config/m68k/mot3300-crt0.S98
-rwxr-xr-xgcc/config/m68k/mot3300.h816
-rwxr-xr-xgcc/config/m68k/mot3300Mcrt0.S142
-rwxr-xr-xgcc/config/m68k/netbsd.h63
-rwxr-xr-xgcc/config/m68k/news.h552
-rwxr-xr-xgcc/config/m68k/news3.h6
-rwxr-xr-xgcc/config/m68k/news3gas.h6
-rwxr-xr-xgcc/config/m68k/newsgas.h19
-rwxr-xr-xgcc/config/m68k/next.h199
-rwxr-xr-xgcc/config/m68k/next21.h104
-rwxr-xr-xgcc/config/m68k/os68000.h81
-rwxr-xr-xgcc/config/m68k/ose68k.h45
-rwxr-xr-xgcc/config/m68k/pbb.h163
-rwxr-xr-xgcc/config/m68k/plexus.h108
-rwxr-xr-xgcc/config/m68k/rtems.h33
-rwxr-xr-xgcc/config/m68k/sgs.h446
-rwxr-xr-xgcc/config/m68k/st2000.h610
-rwxr-xr-xgcc/config/m68k/sun2.h77
-rwxr-xr-xgcc/config/m68k/sun2o4.h189
-rwxr-xr-xgcc/config/m68k/sun3.h301
-rwxr-xr-xgcc/config/m68k/sun3mach.h15
-rwxr-xr-xgcc/config/m68k/sun3n.h9
-rwxr-xr-xgcc/config/m68k/sun3n3.h5
-rwxr-xr-xgcc/config/m68k/sun3o3.h5
-rwxr-xr-xgcc/config/m68k/t-adobe9
-rwxr-xr-xgcc/config/m68k/t-aux44
-rwxr-xr-xgcc/config/m68k/t-linux2
-rwxr-xr-xgcc/config/m68k/t-linux-aout2
-rwxr-xr-xgcc/config/m68k/t-lynx6
-rwxr-xr-xgcc/config/m68k/t-m68kbare24
-rwxr-xr-xgcc/config/m68k/t-m68kelf29
-rwxr-xr-xgcc/config/m68k/t-mot330010
-rwxr-xr-xgcc/config/m68k/t-mot3300-gald13
-rwxr-xr-xgcc/config/m68k/t-mot3300-gas13
-rwxr-xr-xgcc/config/m68k/t-mot3300-gld12
-rwxr-xr-xgcc/config/m68k/t-next6
-rwxr-xr-xgcc/config/m68k/t-ose6826
-rwxr-xr-xgcc/config/m68k/t-vxworks6827
-rwxr-xr-xgcc/config/m68k/tower-as.h616
-rwxr-xr-xgcc/config/m68k/tower.h104
-rwxr-xr-xgcc/config/m68k/vxm68k.h101
-rwxr-xr-xgcc/config/m68k/x-alloca-c1
-rwxr-xr-xgcc/config/m68k/x-amix27
-rwxr-xr-xgcc/config/m68k/x-apollo6815
-rwxr-xr-xgcc/config/m68k/x-apollo68v5
-rwxr-xr-xgcc/config/m68k/x-ccur3
-rwxr-xr-xgcc/config/m68k/x-crds7
-rwxr-xr-xgcc/config/m68k/x-dpx216
-rwxr-xr-xgcc/config/m68k/x-hp2bsd4
-rwxr-xr-xgcc/config/m68k/x-hp32017
-rwxr-xr-xgcc/config/m68k/x-hp320g17
-rwxr-xr-xgcc/config/m68k/x-hp3bsd441
-rwxr-xr-xgcc/config/m68k/x-mot330015
-rwxr-xr-xgcc/config/m68k/x-mot3300-gas12
-rwxr-xr-xgcc/config/m68k/x-next13
-rwxr-xr-xgcc/config/m68k/x-sun31
-rwxr-xr-xgcc/config/m68k/x-tower9
-rwxr-xr-xgcc/config/m68k/xm-3b1.h4
-rwxr-xr-xgcc/config/m68k/xm-altos3068.h3
-rwxr-xr-xgcc/config/m68k/xm-amix.h45
-rwxr-xr-xgcc/config/m68k/xm-atari.h5
-rwxr-xr-xgcc/config/m68k/xm-aux.h9
-rwxr-xr-xgcc/config/m68k/xm-crds.h7
-rwxr-xr-xgcc/config/m68k/xm-hp320.h13
-rwxr-xr-xgcc/config/m68k/xm-linux.h4
-rwxr-xr-xgcc/config/m68k/xm-lynx.h35
-rwxr-xr-xgcc/config/m68k/xm-m68k.h41
-rwxr-xr-xgcc/config/m68k/xm-m68kv.h9
-rwxr-xr-xgcc/config/m68k/xm-mot3300.h41
-rwxr-xr-xgcc/config/m68k/xm-netbsd.h4
-rwxr-xr-xgcc/config/m68k/xm-next.h3
-rwxr-xr-xgcc/config/m68k/xm-plexus.h6
-rwxr-xr-xgcc/config/m68k/xm-sun3.h5
-rwxr-xr-xgcc/config/m68k/xm-tower.h4
129 files changed, 31223 insertions, 0 deletions
diff --git a/gcc/config/m68k/3b1.h b/gcc/config/m68k/3b1.h
new file mode 100755
index 0000000..2b6611a
--- /dev/null
+++ b/gcc/config/m68k/3b1.h
@@ -0,0 +1,513 @@
+/* Definitions of target machine for GNU compiler.
+ AT&T UNIX PC version (pc7300, 3b1)
+ Copyright (C) 1987, 1993, 1996 Free Software Foundation, Inc.
+ Contributed by Alex Crain (alex@umbc3.umd.edu).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define SGS_SWITCH_TABLES /* Different switch table handling */
+
+#include "m68k/hp320.h"
+
+/* See m68k.h. 0 means 680[01]0 with no 68881. */
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT 0
+
+/* Don't try using XFmode. */
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+/* -m68020 requires special flags to the assembler. */
+
+#undef ASM_SPEC
+#define ASM_SPEC "%{m68020:-68020}%{!m68020:-68010} %{m68881:-68881}"
+
+/* we use /lib/libp/lib* when profiling */
+
+#undef LIB_SPEC
+#define LIB_SPEC "%{!shlib:%{p:-L/lib/libp} %{pg:-L/lib/libp} -lc}"
+
+/* shared libraries need to use crt0s.o */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{!shlib:%{pg:mcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}\
+ %{shlib:crt0s.o%s shlib.ifile%s} "
+
+/* cpp has to support a #sccs directive for the /usr/include files */
+
+#define SCCS_DIRECTIVE
+
+/* Make output for SDB. */
+
+#define SDB_DEBUGGING_INFO
+
+/* The .file command should always begin the output. */
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+output_file_directive ((FILE), main_input_filename)
+
+/* Don't try to define `gcc_compiled.' since the assembler might not
+ accept symbols with periods and GDB doesn't run on this machine anyway. */
+#define ASM_IDENTIFY_GCC(FILE)
+
+/* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#undef CPP_SPEC
+#define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+/* ihnp4!lmayk!lgm@eddie.mit.edu says mc68000 and m68k should not be here. */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dmc68k -Dunix -Dunixpc -D__motorola__ -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES \
+{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp", \
+ "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7"}
+
+/* Specify how to pad function arguments.
+ Value should be `upward', `downward' or `none'.
+ Same as the default, except no padding for large or variable-size args. */
+
+#define FUNCTION_ARG_PADDING(MODE, TYPE) \
+ (((MODE) == BLKmode \
+ ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
+ && int_size_in_bytes (TYPE) < PARM_BOUNDARY / BITS_PER_UNIT) \
+ : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY) \
+ ? downward : none)
+
+/* The 3b1 does not have `atexit'. */
+
+#undef HAVE_ATEXIT
+
+/* Override parts of m68k.h to fit the SGS-3b1 assembler. */
+
+#undef TARGET_VERSION
+#undef ASM_FORMAT_PRIVATE_NAME
+#undef ASM_OUTPUT_DOUBLE
+#undef ASM_OUTPUT_FLOAT
+#undef ASM_OUTPUT_ALIGN
+#undef ASM_OUTPUT_SOURCE_FILENAME
+#undef ASM_OUTPUT_SOURCE_LINE
+#undef PRINT_OPERAND_ADDRESS
+#undef ASM_GENERATE_INTERNAL_LABEL
+#undef FUNCTION_PROFILER
+#undef ASM_OUTPUT_ADDR_VEC_ELT
+#undef ASM_OUTPUT_ADDR_DIFF_ELT
+#undef ASM_OUTPUT_INTERNAL_LABEL
+#undef ASM_OUTPUT_OPCODE
+#undef ASM_OUTPUT_LOCAL
+#undef USER_LABEL_PREFIX
+#undef ASM_OUTPUT_ASCII
+
+#define TARGET_VERSION fprintf (stderr, " (68k, SGS/AT&T unixpc syntax)");
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 12), \
+ sprintf ((OUTPUT), "%s_%%%d", (NAME), (LABELNO)))
+
+/* The unixpc doesn't know about double's and float's */
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+do { long l[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
+ fprintf (FILE, "\tlong 0x%x,0x%x\n", l[0], l[1]); \
+ } while (0)
+
+#undef ASM_OUTPUT_LONG_DOUBLE
+#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
+do { long l[3]; \
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
+ fprintf (FILE, "\tlong 0x%x,0x%x,0x%x\n", l[0], l[1], l[2]); \
+ } while (0)
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+do { long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
+ fprintf ((FILE), "\tlong 0x%x\n", l); \
+ } while (0)
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) == 1) \
+ fprintf (FILE, "\teven\n"); \
+ else if ((LOG) != 0) \
+ abort ();
+
+/* This is how to output an assembler line
+ that says to advance the location counter by SIZE bytes. */
+
+#undef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\tspace %d\n", (SIZE))
+
+/* Can't use ASM_OUTPUT_SKIP in text section; it doesn't leave 0s. */
+
+#define ASM_NO_SKIP_IN_TEXT 1
+
+/* The beginnings of sdb support... */
+
+#define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
+ do { fprintf (FILE, "\tfile\t"); \
+ output_quoted_string (FILE, FILENAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+#define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \
+ fprintf (FILE, "\tln\t%d\n", \
+ (sdb_begin_function_line \
+ ? last_linenum - sdb_begin_function_line : 1))
+
+/* Yet another null terminated string format. */
+
+#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
+ do { register int sp = 0, lp = 0; \
+ fprintf ((FILE), "\tbyte\t"); \
+ loop: \
+ if ((PTR)[sp] > ' ' && ! ((PTR)[sp] & 0x80) && (PTR)[sp] != '\\') \
+ { lp += 3; \
+ fprintf ((FILE), "'%c", (PTR)[sp]); } \
+ else \
+ { lp += 5; \
+ fprintf ((FILE), "0x%x", (PTR)[sp]); } \
+ if (++sp < (LEN)) \
+ { if (lp > 60) \
+ { lp = 0; \
+ fprintf ((FILE), "\n\t%s ", ASCII_DATA_ASM_OP); } \
+ else \
+ putc (',', (FILE)); \
+ goto loop; } \
+ putc ('\n', (FILE)); } while (0)
+
+/* Note that in the case of the movhi which fetches an element of
+ an ADDR_DIFF_VEC the offset output is too large by 2.
+ This is because the 3b1 assembler refuses to subtract 2.
+ ASM_OUTPUT_CASE_LABEL, below, compensates for this. */
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx reg1, reg2, breg, ireg; \
+ register rtx addr = ADDR; \
+ rtx offset; \
+ switch (GET_CODE (addr)) \
+ { \
+ case REG: \
+ fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
+ break; \
+ case PRE_DEC: \
+ fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case POST_INC: \
+ fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case PLUS: \
+ reg1 = 0; reg2 = 0; \
+ ireg = 0; breg = 0; \
+ offset = 0; \
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
+ { \
+ offset = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
+ { \
+ offset = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) != PLUS) ; \
+ else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
+ || GET_CODE (addr) == SIGN_EXTEND) \
+ { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
+/* for OLD_INDEXING \
+ else if (GET_CODE (addr) == PLUS) \
+ { \
+ if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg2 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg2 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ } \
+ */ \
+ if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
+ if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
+ || GET_CODE (reg1) == MULT)) \
+ || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
+ { breg = reg2; ireg = reg1; } \
+ else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
+ { breg = reg1; ireg = reg2; } \
+ if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { int scale = 1; \
+ if (GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "LD%%%d(%%pc,%s.w", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (XEXP (ireg, 0))]); \
+ else \
+ fprintf (FILE, "LD%%%d(%%pc,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ fprintf (FILE, ")"); \
+ break; } \
+ if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "LD%%%d(%%pc,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (breg)]); \
+ putc (')', FILE); \
+ break; } \
+ if (ireg != 0 || breg != 0) \
+ { int scale = 1; \
+ if (breg == 0) \
+ abort (); \
+ if (addr != 0) \
+ output_addr_const (FILE, addr); \
+ fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \
+ if (ireg != 0) \
+ putc (',', FILE); \
+ if (ireg != 0 && GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
+ else if (ireg != 0) \
+ fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; \
+ } \
+ else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "LD%%%d(%%pc,%s.w)", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (reg1)]); \
+ break; } \
+ default: \
+ if (GET_CODE (addr) == CONST_INT \
+ && INTVAL (addr) < 0x8000 \
+ && INTVAL (addr) >= -0x8000) \
+ fprintf (FILE, "%d", INTVAL (addr)); \
+ else \
+ output_addr_const (FILE, addr); \
+ }}
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
+ sprintf ((LABEL), "%s%%%d", (PREFIX), (NUM))
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, "%s%%%d:\n", PREFIX, NUM)
+
+/* Must put address in %a0 , not %d0 . -- LGM, 7/15/88 */
+#define FUNCTION_PROFILER(FILE, LABEL_NO) \
+ fprintf (FILE, "\tmov.l &LP%%%d,%%a0\n\tjsr mcount\n", (LABEL_NO))
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\tlong L%%%d\n", (VALUE))
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
+ fprintf (FILE, "\tshort L%%%d-L%%%d\n", (VALUE), (REL))
+
+/* ihnp4!lmayk!lgm says that `short 0' triggers assembler bug;
+ `short L%nn-L%nn' supposedly works. */
+#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
+ if (! RTX_INTEGRATED_P (TABLE)) \
+ fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n", \
+ XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM)); \
+ else \
+ fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n\tshort %s%%%d-%s%%%d\n", \
+ XVECLEN (PATTERN (TABLE), 1) + 1, (PREFIX), (NUM), \
+ (PREFIX), (NUM), (PREFIX), (NUM))
+
+/* At end of a switch table, define LDnnn iff the symbol LInnn was defined.
+ Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
+ fails to assemble. Luckily "LDnnn(pc,d0.l*2)" produces the results
+ we want. This difference can be accommodated by making the assembler
+ define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
+ string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
+ macro. */
+
+#define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \
+{ if (switch_table_difference_label_flag) \
+ fprintf (FILE, "\tset LD%%%d,L%%%d-LI%%%d\n", (NUM), (NUM), (NUM)); \
+ switch_table_difference_label_flag = 0; }
+
+int switch_table_difference_label_flag;
+
+#define ASM_OUTPUT_OPCODE(FILE, PTR) \
+{ if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
+ { ++(PTR); \
+ while (*(PTR) != ' ') \
+ { putc (*(PTR), (FILE)); ++(PTR); } \
+ fprintf ((FILE), ".w"); } \
+ else if ((PTR)[0] == 's') \
+ { \
+ if (!strncmp ((PTR), "swap", 4)) \
+ { fprintf ((FILE), "swap.w"); (PTR) += 4; } \
+ } \
+ else if ((PTR)[0] == 'f') \
+ { \
+ if (!strncmp ((PTR), "fmove", 5)) \
+ { fprintf ((FILE), "fmov"); (PTR) += 5; } \
+ else if (!strncmp ((PTR), "fbne", 4)) \
+ { fprintf ((FILE), "fbneq"); (PTR) += 4; } \
+ } \
+/* MOVE, MOVEA, MOVEQ, MOVEC ==> MOV */ \
+ else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
+ { fprintf ((FILE), "mov"); (PTR) += 4; \
+ if ((PTR)[0] == 'q' || (PTR)[0] == 'a' \
+ || (PTR)[0] == 'c') (PTR)++; } \
+/* SUB, SUBQ, SUBA, SUBI ==> SUB */ \
+ else if ((PTR)[0] == 's' && (PTR)[1] == 'u' \
+ && (PTR)[2] == 'b') \
+ { fprintf ((FILE), "sub"); (PTR) += 3; \
+ if ((PTR)[0] == 'q' || (PTR)[0] == 'i' \
+ || (PTR)[0] == 'a') (PTR)++; } \
+/* CMP, CMPA, CMPI, CMPM ==> CMP */ \
+ else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \
+ && (PTR)[2] == 'p') \
+ { fprintf ((FILE), "cmp"); (PTR) += 3; \
+ if ((PTR)[0] == 'a' || (PTR)[0] == 'i' \
+ || (PTR)[0] == 'm') (PTR)++; } \
+}
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\tlcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+#define USER_LABEL_PREFIX ""
+
+/* Override usual definitions of SDB output macros.
+ These definitions differ only in the absence of the period
+ at the beginning of the name of the directive
+ and in the use of `~' as the symbol for the current location. */
+
+#define PUT_SDB_SCL(a) fprintf(asm_out_file, "\tscl\t%d;", (a))
+#define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\tval\t%d;", (a))
+#define PUT_SDB_VAL(a) \
+( fputs ("\tval\t", asm_out_file), \
+ output_addr_const (asm_out_file, (a)), \
+ fputc (';', asm_out_file))
+
+#define PUT_SDB_DEF(a) \
+do { fprintf (asm_out_file, "\tdef\t"); \
+ ASM_OUTPUT_LABELREF (asm_out_file, a); \
+ fprintf (asm_out_file, ";"); } while (0)
+
+#define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\tdef\t~%s;",a)
+#define PUT_SDB_ENDEF fputs("\tendef\n", asm_out_file)
+#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\ttype\t0%o;", a)
+#define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\tsize\t%d;", a)
+#define PUT_SDB_START_DIM fprintf(asm_out_file, "\tdim\t")
+
+#define PUT_SDB_TAG(a) \
+do { fprintf (asm_out_file, "\ttag\t"); \
+ ASM_OUTPUT_LABELREF (asm_out_file, a); \
+ fprintf (asm_out_file, ";"); } while (0)
+
+#define PUT_SDB_BLOCK_START(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~bb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_BLOCK_END(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~eb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_FUNCTION_START(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~bf;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_FUNCTION_END(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~ef;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_EPILOGUE_END(NAME) \
+ fprintf (asm_out_file, \
+ "\tdef\t%s;\tval\t~;\tscl\t-1;\tendef\n", \
+ (NAME))
+
+#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
+ sprintf ((BUFFER), "~%dfake", (NUMBER));
+
+/* Define subroutines to call to handle multiply, divide, and remainder.
+ Use the subroutines that the 3b1's library provides.
+ The `*' prevents an underscore from being prepended by the compiler. */
+
+#define DIVSI3_LIBCALL "*ldiv"
+#define UDIVSI3_LIBCALL "*uldiv"
+#define MODSI3_LIBCALL "*lrem"
+#define UMODSI3_LIBCALL "*ulrem"
+#define MULSI3_LIBCALL "*lmul"
+#define UMULSI3_LIBCALL "*ulmul"
+
+/* Definitions for collect2. */
+
+#define OBJECT_FORMAT_COFF
+#define NO_SYS_SIGLIST
+#define MY_ISCOFF(magic) \
+ ((magic) == MC68KWRMAGIC || (magic) == MC68KROMAGIC || (magic) == MC68KPGMAGIC)
diff --git a/gcc/config/m68k/3b1g.h b/gcc/config/m68k/3b1g.h
new file mode 100755
index 0000000..2b1d23c
--- /dev/null
+++ b/gcc/config/m68k/3b1g.h
@@ -0,0 +1,64 @@
+/* Definitions of target machine for GNU compiler, for a 3b1 using GAS.
+ Copyright (C) 1987, 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "m68k/m68k.h"
+
+/* See m68k.h. 0 means 68000 with no 68881. */
+#define TARGET_DEFAULT 0
+
+/* Don't try using XFmode. */
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+/* Define __HAVE_68881 in preprocessor only if -m68881 is specified.
+ This will control the use of inline 68881 insns in certain macros.
+ Also inform the program which CPU this is for. */
+#define CPP_SPEC "%{m68881:-D__HAVE_68881__} \
+%{!ansi:%{m68020:-Dmc68020}%{mc68020:-Dmc68020}%{!mc68020:%{!m68020:-Dmc68010}}}"
+
+/* -m68020 requires special flags to the assembler. */
+#define ASM_SPEC \
+ "%{m68020:-mc68020}%{mc68020:-mc68020}%{!mc68020:%{!m68020:-mc68010}}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+#define CPP_PREDEFINES "-Dmc68000 -Dmc68k -Dunix -Dunixpc -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
+
+/* This is (not really) BSD, so (but) it wants DBX format. */
+#define DBX_DEBUGGING_INFO
+
+/* Brain damage. */
+#define SCCS_DIRECTIVE
+
+/* Specify how to pad function arguments.
+ Value should be `upward', `downward' or `none'.
+ Same as the default, except no padding for large or variable-size args. */
+#define FUNCTION_ARG_PADDING(MODE, TYPE) \
+ (((MODE) == BLKmode \
+ ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
+ && int_size_in_bytes (TYPE) < PARM_BOUNDARY / BITS_PER_UNIT) \
+ : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY) \
+ ? downward : none)
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* Generate calls to memcpy, memcmp and memset. */
+#define TARGET_MEM_FUNCTIONS
+
diff --git a/gcc/config/m68k/a-ux.h b/gcc/config/m68k/a-ux.h
new file mode 100755
index 0000000..69ecb53
--- /dev/null
+++ b/gcc/config/m68k/a-ux.h
@@ -0,0 +1,206 @@
+/* Definitions for Motorola 680x0 running A/UX
+ Copyright (C) 1996, 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* This file was renamed from aux.h because of MSDOS: aux.anything
+ isn't usable. Sigh. */
+
+/* Execution environment */
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020) /* 68020, 68881 */
+
+#define CPP_PREDEFINES "-Dunix -Dm68k -DAUX -DmacII \
+-Asystem(unix) -Asystem(AUX) -Acpu(m68k) -Amachine(m68k) -Amachine(macII)"
+
+#define CPP_SPEC \
+"%{!msoft-float:%{!ansi:-Dmc68881 }-D__HAVE_68881__ }\
+-Acpu(mc68000) -D__mc68000__ %{!ansi:-Dmc68000 }\
+%{!mc68000:%{!m68000:-Acpu(mc68020) -D__mc68020__ %{!ansi:-Dmc68020 }}}\
+%{m68030:-Acpu(mc68030) -D__mc68030__ %{!ansi:-Dmc68030 }}\
+%{m68040:-Acpu(mc68040) -D__mc68040__ %{!ansi:-Dmc68040 }}\
+%{!ansi:%{!traditional:-D__STDC__=2 }}\
+%{sbsd:-D_BSD_SOURCE -DBSD }%{ZB:-D_BSD_SOURCE -DBSD }\
+%{ssysv:-D_SYSV_SOURCE -DSYSV -DUSG }%{ZS:-D_SYSV_SOURCE -DSYSV -DUSG }\
+%{sposix:-D_POSIX_SOURCE -DPOSIX }%{ZP:-D_POSIX_SOURCE -DPOSIX }\
+%{sposix+:-D_POSIX_SOURCE -DPOSIX }\
+%{saux:-D_AUX_SOURCE }%{ZA:-D_AUX_SOURCE }\
+%{!sbsd:%{!ZB:%{!ssysv:%{!ZS:%{!sposix:%{!ZP:%{!snone:\
+-D_BSD_SOURCE -D_SYSV_SOURCE -D_AUX_SOURCE }}}}}}}"
+
+#define LIB_SPEC \
+"%{sbsd:-lbsd }%{ZB:-lbsd }\
+%{ssysv:-lsvid }%{ZS:-lsvid }\
+%{sposix:-lposix }%{ZP:-lposix }%{sposix+:-lposix }\
+%{!static:%{smac:-lmac_s -lat -lld -lmr }-lc_s }\
+%{static:%{smac:-lmac -lat -lld -lmr }-lc }"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+"%{pg:mcrt0.o%s }%{!pg:%{p:mcrt1.o%s }\
+%{!p:%{smac:maccrt1.o%s low.o%s }%{!smac:crt1.o%s }}}\
+crt2.o%s "
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "crtn.o%s "
+
+
+/*===================================================================*/
+/* Compilation environment -- mostly */
+
+#define NO_SYS_SIGLIST
+
+/* We provide atexit(), A/UX does not have it */
+#define HAVE_ATEXIT
+
+/* Generate calls to memcpy, memcmp and memset, as opposed to bcopy, bcmp,
+ and bzero */
+#define TARGET_MEM_FUNCTIONS
+
+/* Resize standard types */
+
+#undef SIZE_TYPE
+#define SIZE_TYPE "unsigned int"
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "int"
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "unsigned int"
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* Bits needed by collect */
+
+#define OBJECT_FORMAT_COFF
+#define MY_ISCOFF(m) ((m) == M68TVMAGIC || \
+ (m) == M68MAGIC || \
+ (m) == MC68TVMAGIC || \
+ (m) == MC68MAGIC || \
+ (m) == M68NSMAGIC)
+
+
+#ifndef USE_COLLECT2
+/* For .ctor/.dtor sections for collecting constructors */
+/* We have special start/end files for defining [cd]tor lists */
+#define CTOR_LISTS_DEFINED_EXTERNALLY
+#endif
+
+
+/*======================================================================*/
+/* Calling convention and library support changes */
+
+/* Define how to generate (in the callee) the output value of a function
+ and how to find (in the caller) the value returned by a function. VALTYPE
+ is the data type of the value (as a tree). If the precise function being
+ called is known, FUNC is its FUNCTION_DECL; otherwise, FUNC is 0.
+ For A/UX generate the result in d0, a0, or fp0 as appropriate. */
+
+#undef FUNCTION_VALUE
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ (TREE_CODE (VALTYPE) == REAL_TYPE && TARGET_68881 \
+ ? gen_rtx (REG, TYPE_MODE (VALTYPE), 16) \
+ : (POINTER_TYPE_P (VALTYPE) \
+ ? gen_rtx (REG, TYPE_MODE (VALTYPE), 8) \
+ : gen_rtx (REG, TYPE_MODE (VALTYPE), 0)))
+
+#undef LIBCALL_VALUE
+#define LIBCALL_VALUE(MODE) \
+ gen_rtx (REG, (MODE), ((TARGET_68881 && \
+ ((MODE) == SFmode || (MODE) == DFmode)) ? 16 : 0))
+
+/* 1 if N is a possible register number for a function value.
+ For A/UX allow d0, a0, or fp0 as return registers, for integral,
+ pointer, or floating types, respectively. Reject fp0 if not using a
+ 68881 coprocessor. */
+
+#undef FUNCTION_VALUE_REGNO_P
+#define FUNCTION_VALUE_REGNO_P(N) \
+ ((N) == 0 || (N) == 8 || (TARGET_68881 && (N) == 16))
+
+/* Define this to be true when FUNCTION_VALUE_REGNO_P is true for
+ more than one register. */
+
+#undef NEEDS_UNTYPED_CALL
+#define NEEDS_UNTYPED_CALL 1
+
+/* For compatibility with the large body of existing code which does not
+ always properly declare external functions returning pointer types, the
+ A/UX convention is to copy the value returned for pointer functions
+ from a0 to d0 in the function epilogue, so that callers that have
+ neglected to properly declare the callee can still find the correct return
+ value. */
+
+#define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE) \
+{ \
+ extern int current_function_returns_pointer; \
+ if ((current_function_returns_pointer) && \
+ ! find_equiv_reg (0, get_last_insn (), 0, 0, 0, 8, Pmode)) \
+ asm_fprintf (FILE, "\t%s %Ra0,%Rd0\n", ASM_MOV_INSN); \
+}
+
+/* How to call the function profiler */
+
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ asm_fprintf (FILE, "\t%Olea %LLP%d,%Ra0\n\t%Ojbsr %s\n", \
+ (LABELNO), FUNCTION_PROFILER_SYMBOL)
+
+/* Finalize the trampoline by flushing the insn cache */
+
+#undef FINALIZE_TRAMPOLINE
+#define FINALIZE_TRAMPOLINE(TRAMP) \
+ emit_library_call(gen_rtx(SYMBOL_REF, Pmode, "__clear_cache"), \
+ 0, VOIDmode, 2, TRAMP, Pmode, \
+ plus_constant(TRAMP, TRAMPOLINE_SIZE), Pmode);
+
+/* Clear the instruction cache from `beg' to `end'. This makes an
+ inline system call to SYS_sysm68k. The arguments are as follows:
+
+ sysm68k(105, addr, scope, cache, len)
+
+ 105 - the subfunction code to clear the cache
+ addr - the start address for the flush
+ scope - the scope of the flush (see the cpush insn)
+ cache - which cache to flush (see the cpush insn)
+ len - a factor relating to the number of flushes to perform :
+ len/16 lines, or len/4096 pages.
+
+ While all this is only really relevant to 040's, the system call
+ will just return an error (which we ignore) on other systems. */
+
+#define CLEAR_INSN_CACHE(beg, end) \
+{ \
+ unsigned _beg = (unsigned)(beg), _end = (unsigned)(end); \
+ unsigned _len = ((_end / 16) - (_beg / 16) + 1) * 16; \
+ __asm __volatile( \
+ ASM_MOV_INSN " %1, %-\n\t" /* nr lines */ \
+ ASM_MOV_INSN " %#3, %-\n\t" /* insn+data caches */ \
+ ASM_MOV_INSN " %#1, %-\n\t" /* clear lines */ \
+ ASM_MOV_INSN " %0, %-\n\t" /* beginning of buffer */ \
+ ASM_MOV_INSN " %#105, %-\n\t" /* cache sub-function nr */ \
+ ASM_MOV_INSN " %#0, %-\n\t" /* dummy return address */ \
+ ASM_MOV_INSN " %#38, %/d0\n\t" /* system call nr */ \
+ "trap %#0\n\t" \
+ "add%.l %#24, %/sp" \
+ : /* no outputs */ \
+ : "g"(_beg), "g"(_len) \
+ : "%d0"); \
+}
diff --git a/gcc/config/m68k/altos3068.h b/gcc/config/m68k/altos3068.h
new file mode 100755
index 0000000..5903a12
--- /dev/null
+++ b/gcc/config/m68k/altos3068.h
@@ -0,0 +1,135 @@
+/* Definitions of target machine for GNU compiler. Altos 3068 68020 version.
+ Copyright (C) 1988, 1989, 1993, 1996 Free Software Foundation, Inc.
+ Contributed by Jyrki Kuoppala <jkp@cs.hut.fi>
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+#include "m68k/m68k.h"
+
+/* See m68k.h. 7 means 68020 with 68881. */
+/* 5 is without 68881. Change to 7 if you have 68881 */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68020)
+
+/* Don't try using XFmode. */
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 64
+#endif
+
+/* Define __HAVE_68881__ in preprocessor,
+ according to the -m flags.
+ This will control the use of inline 68881 insns in certain macros.
+ Also inform the program which CPU this is for. */
+
+#if TARGET_DEFAULT & MASK_68881
+
+/* -m68881 is the default */
+#define CPP_SPEC \
+"%{!msoft-float:-D__HAVE_68881__ }\
+%{!ansi:%{m68000:-Dmc68010}%{mc68000:-Dmc68010}%{!mc68000:%{!m68000:-Dmc68020}}}"
+
+#else
+
+/* -msoft-float is the default */
+#define CPP_SPEC \
+"%{m68881:-D__HAVE_68881__ }\
+%{!ansi:%{m68000:-Dmc68010}%{mc68000:-Dmc68010}%{!mc68000:%{!m68000:-Dmc68020}}}"
+
+#endif
+
+/* -m68000 requires special flags to the assembler. */
+
+#define ASM_SPEC \
+ "%{m68000:-mc68010}%{mc68000:-mc68010}%{!mc68000:%{!m68000:-mc68020}}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dmc68000 -DPORTAR -Dmc68k32 -Uvax -Dm68k -Dunix -Asystem(unix) -Acpu(m68k) -Amachine(m68k)"
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* Generate calls to memcpy, memcmp and memset. */
+#define TARGET_MEM_FUNCTIONS
+
+/* We use gnu assembler, linker and gdb, so we want DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Tell some conditionals we will use GAS. Is this really used? */
+
+#define USE_GAS
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#undef ASM_OUTPUT_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.20e", dstr); \
+ fprintf (FILE, "\t.double 0r%s\n", dstr); \
+ } while (0)
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#undef ASM_OUTPUT_FLOAT
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.20e", dstr); \
+ fprintf (FILE, "\t.single 0r%s\n", dstr); \
+ } while (0)
+
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
+ do { \
+ if (CODE == 'f') \
+ { \
+ char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.9g", dstr); \
+ fprintf (FILE, "#0r%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)
+
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
+ fprintf (FILE, "#0r%s", dstr); \
+ } while (0)
+
+/* Return pointer values in both d0 and a0. */
+
+#undef FUNCTION_EXTRA_EPILOGUE
+#define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE) \
+{ \
+ extern int current_function_returns_pointer; \
+ if ((current_function_returns_pointer) && \
+ ! find_equiv_reg (0, get_last_insn (), 0, 0, 0, 8, Pmode))\
+ fprintf (FILE, "\tmovel d0,a0\n"); \
+}
diff --git a/gcc/config/m68k/amix.h b/gcc/config/m68k/amix.h
new file mode 100755
index 0000000..9b40a29
--- /dev/null
+++ b/gcc/config/m68k/amix.h
@@ -0,0 +1,149 @@
+/* Definitions of target machine for GNU compiler.
+ Commodore Amiga A3000UX version.
+
+ Copyright (C) 1991, 1993 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "m68k/m68kv4.h"
+
+/* rhealey@aggregate.com says dots are no good either. */
+#define NO_DOT_IN_LABEL
+
+/* Alter assembler syntax for fsgldiv and fsglmul.
+ It is highly likely that this is a generic SGS m68k assembler dependency.
+ If so, it should eventually be handled in the m68k/sgs.h ASM_OUTPUT_OPCODE
+ macro, like the other SGS assembler quirks. -fnf */
+
+#define FSGLDIV_USE_S /* Use fsgldiv.s, not fsgldiv.x */
+#define FSGLMUL_USE_S /* Use fsglmul.s, not fsglmul.x */
+
+/* Names to predefine in the preprocessor for this target machine. For the
+ Amiga, these definitions match those of the native AT&T compiler. Note
+ that we override the definition in m68kv4.h, where SVR4 is defined and
+ AMIX isn't. */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES \
+ "-Dm68k -Dunix -DAMIX -D__svr4__ -D__motorola__ \
+ -Amachine(m68k) -Acpu(m68k) -Asystem(unix) -Alint(off)"
+
+/* At end of a switch table, define LDnnn iff the symbol LInnn was defined.
+ Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
+ fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
+ we want. This difference can be accommodated by making the assembler
+ define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
+ string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
+ macro. (the Amiga assembler has this bug) */
+
+#undef ASM_OUTPUT_CASE_END
+#define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \
+do { \
+ if (switch_table_difference_label_flag) \
+ asm_fprintf ((FILE), "\t%s %LLD%d,%LL%d\n", SET_ASM_OP, (NUM), (NUM));\
+ switch_table_difference_label_flag = 0; \
+} while (0)
+
+int switch_table_difference_label_flag;
+
+/* This says how to output assembler code to declare an
+ uninitialized external linkage data object. Under SVR4,
+ the linker seems to want the alignment of data objects
+ to depend on their types. We do exactly that here.
+ [This macro overrides the one in svr4.h because the amix assembler
+ has a minimum default alignment of 4, and will not accept any
+ explicit alignment smaller than this. -fnf] */
+
+#undef ASM_OUTPUT_ALIGNED_COMMON
+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
+do { \
+ fputs ("\t.comm\t", (FILE)); \
+ assemble_name ((FILE), (NAME)); \
+ fprintf ((FILE), ",%u,%u\n", (SIZE), MAX ((ALIGN) / BITS_PER_UNIT, 4)); \
+} while (0)
+
+/* This says how to output assembler code to declare an
+ uninitialized internal linkage data object. Under SVR4,
+ the linker seems to want the alignment of data objects
+ to depend on their types. We do exactly that here.
+ [This macro overrides the one in svr4.h because the amix assembler
+ has a minimum default alignment of 4, and will not accept any
+ explicit alignment smaller than this. -fnf] */
+
+#undef ASM_OUTPUT_ALIGNED_LOCAL
+#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
+do { \
+ fprintf ((FILE), "\t%s\t%s,%u,%u\n", \
+ BSS_ASM_OP, (NAME), (SIZE), MAX ((ALIGN) / BITS_PER_UNIT, 4)); \
+} while (0)
+
+/* This definition of ASM_OUTPUT_ASCII is the same as the one in m68k/sgs.h,
+ which has been overridden by the one in svr4.h. However, we can't use
+ the one in svr4.h because the amix assembler croaks on some of the
+ strings that it emits (such as .string "\"%s\"\n"). */
+
+#undef ASM_OUTPUT_ASCII
+#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
+do { \
+ register int sp = 0, lp = 0, ch; \
+ fprintf ((FILE), "\t%s ", BYTE_ASM_OP); \
+ do { \
+ ch = (PTR)[sp]; \
+ if (ch > ' ' && ! (ch & 0x80) && ch != '\\') \
+ { \
+ fprintf ((FILE), "'%c", ch); \
+ } \
+ else \
+ { \
+ fprintf ((FILE), "0x%x", ch); \
+ } \
+ if (++sp < (LEN)) \
+ { \
+ if ((sp % 10) == 0) \
+ { \
+ fprintf ((FILE), "\n\t%s ", BYTE_ASM_OP); \
+ } \
+ else \
+ { \
+ putc (',', (FILE)); \
+ } \
+ } \
+ } while (sp < (LEN)); \
+ putc ('\n', (FILE)); \
+} while (0)
+
+/* The following should be unnecessary as a result of PIC_CASE_VECTOR_ADDRESS.
+ But rhealey@aggregate.com says they are still needed. */
+
+/* Override these for the sake of an assembler bug: the Amix
+ assembler can't handle .LC0@GOT syntax. This pollutes the final
+ table for shared librarys but what's a poor soul to do; sigh... RFH */
+
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ if (flag_pic && !strcmp(PREFIX,"LC")) \
+ sprintf (LABEL, "*%s%%%d", PREFIX, NUM); \
+ else \
+ sprintf (LABEL, "*%s%s%d", LOCAL_LABEL_PREFIX, PREFIX, NUM)
+
+#undef ASM_OUTPUT_INTERNAL_LABEL
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ if (flag_pic && !strcmp(PREFIX,"LC")) \
+ asm_fprintf (FILE, "%s%%%d:\n", PREFIX, NUM); \
+ else \
+ asm_fprintf (FILE, "%0L%s%d:\n", PREFIX, NUM)
diff --git a/gcc/config/m68k/apollo68.h b/gcc/config/m68k/apollo68.h
new file mode 100755
index 0000000..8eed141
--- /dev/null
+++ b/gcc/config/m68k/apollo68.h
@@ -0,0 +1,208 @@
+/* Definitions of target machine for GNU compiler. Apollo 680X0 version.
+ Copyright (C) 1989, 1992, 1996, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "m68k/m68k.h"
+
+/* This symbol may be tested in other files for special Apollo handling */
+
+#define TM_APOLLO
+
+/* See m68k.h. 7 means 68020 with 68881. */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
+#endif
+
+/* Target switches for the Apollo is the same as in m68k.h, except
+ there is no Sun FPA. */
+
+#undef TARGET_SWITCHES
+#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}, \
+ { "", TARGET_DEFAULT}}
+
+/* Define __HAVE_68881__ in preprocessor,
+ according to the -m flags.
+ This will control the use of inline 68881 insns in certain macros.
+ Also inform the program which CPU this is for. */
+
+#if TARGET_DEFAULT & MASK_68881
+
+/* -m68881 is the default */
+#define CPP_SPEC \
+"%{!msoft-float:%{mfpa:-D__HAVE_FPA__ }%{!mfpa:-D__HAVE_68881__ }}\
+%{!ansi:%{m68000:-Dmc68010 }%{mc68000:-Dmc68010 }%{!mc68000:%{!m68000:-Dmc68020 }}\
+%{!ansi:-D_APOLLO_SOURCE}}"
+
+#else
+
+/* -msoft-float is the default */
+#define CPP_SPEC \
+"%{m68881:-D__HAVE_68881__ }%{mfpa:-D__HAVE_FPA__ }\
+%{!ansi:%{m68000:-Dmc68010 }%{mc68000:-Dmc68010 }%{!mc68000:%{!m68000:-Dmc68020 }}\
+%{!ansi:-D_APOLLO_SOURCE}}"
+
+#endif
+
+/* Names to predefine in the preprocessor for this target machine. */
+/* These are the ones defined by Apollo, plus mc68000 for uniformity with
+ GCC on other 68000 systems. */
+
+#define CPP_PREDEFINES "-Dapollo -Daegis -Dunix -Asystem(unix) -Acpu(m68k) -Amachine(m68k)"
+
+/* cpp has to support a #sccs directive for the /usr/include files */
+
+#define SCCS_DIRECTIVE
+
+/* Allow #ident but output nothing for it. */
+
+#define IDENT_DIRECTIVE
+#define ASM_OUTPUT_IDENT(FILE, NAME)
+
+/* -m68000 requires special flags to the assembler. */
+
+#define ASM_SPEC \
+ "%{m68000:-mc68010}%{mc68000:-mc68010}%{!mc68000:%{!m68000:-mc68020}}"
+
+/* STARTFILE_SPEC
+ Note that includes knowledge of the default specs for gcc, ie. no
+ args translates to the same effect as -m68881 */
+
+#if TARGET_DEFAULT & MASK_68881
+/* -m68881 is the default */
+#define STARTFILE_SPEC \
+ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}"
+#else
+/* -msoft-float is the default */
+#define STARTFILE_SPEC \
+ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}"
+#endif
+
+/* Specify library to handle `-a' basic block profiling. */
+
+#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} \
+%{a:/usr/lib/bb_link.o} "
+
+/* Debugging is not supported yet */
+
+#undef DBX_DEBUGGING_INFO
+#undef SDB_DEBUGGING_INFO
+
+/* We have atexit(2). So C++ can use it for global destructors. */
+
+#if 0 /* troy@cbme.unsw.edu.au says people are still using sr10.2
+ and it does not support atexit. */
+#define HAVE_ATEXIT
+#endif
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* Boundary (in *bits*) on which stack pointer should be aligned. */
+#undef STACK_BOUNDARY
+#define STACK_BOUNDARY 32
+
+/* Functions which return large structures get the address
+ to place the wanted value from a hidden parameter. */
+
+#undef PCC_STATIC_STRUCT_RETURN
+#undef STRUCT_VALUE_REGNUM
+#define STRUCT_VALUE 0
+#define STRUCT_VALUE_INCOMING 0
+
+/* Specify how to pad function arguments.
+ Arguments are not padded at all; the stack is kept aligned on long
+ boundaries. */
+
+#define FUNCTION_ARG_PADDING(mode, size) none
+
+/* The definition of this macro imposes a limit on the size of
+ an aggregate object which can be treated as if it were a scalar
+ object. */
+
+#define MAX_FIXED_MODE_SIZE BITS_PER_WORD
+
+/* The definition of this macro implies that there are cases where
+ a scalar value cannot be returned in registers.
+ For Apollo, anything larger than one integer register is returned
+ using the structure-value mechanism, i.e. objects of DFmode are
+ returned that way. */
+
+#define RETURN_IN_MEMORY(type) \
+ (TYPE_MODE (type) == BLKmode \
+ || GET_MODE_SIZE (TYPE_MODE (type)) > UNITS_PER_WORD)
+
+/* In order to link with Apollo libraries, we can't prefix external
+ symbols with an underscore. */
+
+#undef USER_LABEL_PREFIX
+
+/* Use a prefix for local labels, just to be on the save side. */
+
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
+/* Use a register prefix to avoid clashes with external symbols (classic
+ example: `extern char PC;' in termcap). */
+
+#undef REGISTER_PREFIX
+#define REGISTER_PREFIX "%"
+
+/* config/m68k.md has an explicit reference to the program counter,
+ prefix this by the register prefix. */
+
+#define ASM_RETURN_CASE_JUMP \
+ do { \
+ if (TARGET_5200) \
+ return "ext%.l %0\n\tjmp %%pc@(2,%0:l)"; \
+ else \
+ return "jmp %%pc@(2,%0:w)" \
+ } while (0)
+
+/* Here are the new register names. */
+
+#undef REGISTER_NAMES
+#ifndef SUPPORT_SUN_FPA
+#define REGISTER_NAMES \
+{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%sp", \
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7" }
+#else /* SUPPORTED_SUN_FPA */
+#define REGISTER_NAMES \
+{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%sp", \
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7", \
+ "%fpa0", "%fpa1", "%fpa2", "%fpa3", "%fpa4", "%fpa5", "%fpa6", "%fpa7", \
+ "%fpa8", "%fpa9", "%fpa10", "%fpa11", "%fpa12", "%fpa13", "%fpa14", "%fpa15", \
+ "%fpa16", "%fpa17", "%fpa18", "%fpa19", "%fpa20", "%fpa21", "%fpa22", "%fpa23", \
+ "%fpa24", "%fpa25", "%fpa26", "%fpa27", "%fpa28", "%fpa29", "%fpa30", "%fpa31" }
+#endif /* defined SUPPORT_SUN_FPA */
diff --git a/gcc/config/m68k/atari.h b/gcc/config/m68k/atari.h
new file mode 100755
index 0000000..da0a803
--- /dev/null
+++ b/gcc/config/m68k/atari.h
@@ -0,0 +1,106 @@
+/* Definitions of target machine for GNU compiler.
+ Atari TT ASV version.
+ Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "m68k/m68kv4.h"
+
+/* Dollars and dots in labels are not allowed. */
+
+#define NO_DOLLAR_IN_LABEL
+#define NO_DOT_IN_LABEL
+
+/* Alter assembler syntax for fsgldiv and fsglmul.
+ It is highly likely that this is a generic SGS m68k assembler dependency.
+ If so, it should eventually be handled in the m68k/sgs.h ASM_OUTPUT_OPCODE
+ macro, like the other SGS assembler quirks. -fnf */
+
+#define FSGLDIV_USE_S /* Use fsgldiv.s, not fsgldiv.x */
+#define FSGLMUL_USE_S /* Use fsglmul.s, not fsglmul.x */
+
+/* At end of a switch table, define LDnnn iff the symbol LInnn was defined.
+ Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
+ fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
+ we want. This difference can be accommodated by making the assembler
+ define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
+ string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
+ macro. (the Amiga assembler has this bug) */
+
+#undef ASM_OUTPUT_CASE_END
+#define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \
+do { \
+ if (switch_table_difference_label_flag) \
+ asm_fprintf ((FILE), "\t%s %LLD%d,%LL%d\n", SET_ASM_OP, (NUM), (NUM));\
+ switch_table_difference_label_flag = 0; \
+} while (0)
+
+int switch_table_difference_label_flag;
+
+/* This definition of ASM_OUTPUT_ASCII is the same as the one in m68k/sgs.h,
+ which has been overridden by the one in svr4.h. However, we can't use
+ the one in svr4.h because the ASV assembler croaks on some of the
+ strings that it emits (such as .string "\"%s\"\n"). */
+
+#undef ASM_OUTPUT_ASCII
+#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
+{ \
+ register int sp = 0, lp = 0, ch; \
+ fprintf ((FILE), "\t%s ", BYTE_ASM_OP); \
+ do { \
+ ch = (PTR)[sp]; \
+ if (ch > ' ' && ! (ch & 0x80) && ch != '\\') \
+ { \
+ fprintf ((FILE), "'%c", ch); \
+ } \
+ else \
+ { \
+ fprintf ((FILE), "0x%x", ch); \
+ } \
+ if (++sp < (LEN)) \
+ { \
+ if ((sp % 10) == 0) \
+ { \
+ fprintf ((FILE), "\n\t%s ", BYTE_ASM_OP); \
+ } \
+ else \
+ { \
+ putc (',', (FILE)); \
+ } \
+ } \
+ } while (sp < (LEN)); \
+ putc ('\n', (FILE)); \
+}
+
+/* Override these for the sake of an assembler bug: the ASV
+ assembler can't handle .LC0@GOT syntax. This pollutes the final
+ table for shared librarys but what's a poor soul to do; sigh... RFH */
+
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ if (flag_pic && !strcmp(PREFIX,"LC")) \
+ sprintf (LABEL, "*%s%%%d", PREFIX, NUM); \
+ else \
+ sprintf (LABEL, "*%s%s%d", LOCAL_LABEL_PREFIX, PREFIX, NUM)
+
+#undef ASM_OUTPUT_INTERNAL_LABEL
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ if (flag_pic && !strcmp(PREFIX,"LC")) \
+ asm_fprintf (FILE, "%s%%%d:\n", PREFIX, NUM); \
+ else \
+ asm_fprintf (FILE, "%0L%s%d:\n", PREFIX, NUM)
diff --git a/gcc/config/m68k/aux-crt1.c b/gcc/config/m68k/aux-crt1.c
new file mode 100755
index 0000000..9ee529b
--- /dev/null
+++ b/gcc/config/m68k/aux-crt1.c
@@ -0,0 +1,134 @@
+/* Startup code for A/UX
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs without any restriction coming from the use of this
+file. (The General Public License restrictions do apply in other
+respects; for example, they cover modification of the file, and
+distribution when not linked into another program.)
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* As a special exception, if you link this library with files
+ compiled with GCC to produce an executable, this does not cause
+ the resulting executable to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
+
+/* This file is compiled three times to produce crt1.o, mcrt1.o, and
+ maccrt1.o. The final two are created by defining MCRT1 and MACCRT1
+ respectively. */
+
+#include <stdlib.h>
+#ifdef MCRT1
+#include <unistd.h>
+#include <mon.h>
+#endif
+
+/* Extern function declarations */
+
+extern void initfpu(void);
+extern void __istart(void);
+extern void __compatmode(void);
+extern void _cleanup(void);
+extern int main(int, char **, char **);
+extern void exit(int) __attribute__((noreturn));
+extern void _exit(int) __attribute__((noreturn));
+
+#ifdef MACCRT1
+extern void InitMac(void);
+#endif
+#ifdef MCRT1
+static void monitor_start(void);
+#endif
+
+/* Global variables */
+
+char **environ;
+char *__splimit; /* address of top of stack */
+
+
+/* Initialize system and run */
+
+void _start() __attribute__((noreturn));
+void _start()
+{
+ register int *fp __asm__("%a6");
+ register char *d0 __asm__("%d0");
+ char **argv;
+ int argc;
+
+ __splimit = d0;
+ argc = fp[1];
+ argv = (char **)&fp[2];
+ environ = &argv[argc+1];
+
+ initfpu();
+ __istart();
+ __compatmode();
+
+ atexit(_cleanup);
+#ifdef MCRT1
+ monitor_start();
+#endif
+#ifdef MACCRT1
+ InitMac();
+#endif
+
+ exit(main(argc, argv, environ));
+}
+
+
+#ifdef MCRT1
+/* Start/Stop program monitor */
+
+extern void monitor(void *, void *, WORD *, int, int);
+
+static WORD *monitor_buffer;
+
+static void monitor_cleanup(void)
+{
+ monitor(NULL, NULL, NULL, 0, 0);
+ free(monitor_buffer);
+}
+
+static void monitor_start(void)
+{
+ extern int etext;
+ extern int stext __asm__(".text");
+
+ /* Choice of buffer size should be "no more than a few times
+ smaller than the program size" -- I don't believe that there
+ are any (useful) functions smaller than two insns (4 bytes)
+ so that is the scale factor used here */
+ int len = (&etext - &stext + 1) / 4;
+
+ monitor_buffer = (WORD *)calloc(len, sizeof(WORD));
+ if (monitor_buffer == NULL)
+ {
+ static const char msg[] = "mcrt1: could not allocate monitor buffer\n";
+ write(2, msg, sizeof(msg)-1);
+ _exit(-1);
+ }
+
+ /* I'm not sure why the count cap at 600 -- but that is what A/UX does */
+ monitor(&stext, &etext, monitor_buffer, len, 600);
+
+ atexit(monitor_cleanup);
+}
+#endif /* MCRT1 */
diff --git a/gcc/config/m68k/aux-crt2.asm b/gcc/config/m68k/aux-crt2.asm
new file mode 100755
index 0000000..062c16a
--- /dev/null
+++ b/gcc/config/m68k/aux-crt2.asm
@@ -0,0 +1,42 @@
+/* More startup code for A/UX */
+
+#include "tm.h"
+
+#ifdef USE_BIN_AS
+ file "crt2.s"
+
+/* The init section is used to support shared libraries */
+ init
+ global __istart
+
+__istart:
+ link %fp,&-4
+#else
+ .file "crt2.s"
+
+/* The init section is used to support shared libraries */
+.section .init, "x"
+.even
+.globl __istart
+
+__istart:
+ link %fp,#-4
+
+#ifndef USE_COLLECT2
+/* The ctors and dtors sections are used to support COFF collection of
+ c++ constructors and destructors */
+.section .ctors, "d"
+.even
+.globl __CTOR_LIST__
+
+__CTOR_LIST__:
+ .long -1
+
+.section .dtors, "d"
+.even
+.globl __DTOR_LIST__
+
+__DTOR_LIST__:
+ .long -1
+#endif /* USE_COLLECT2 */
+#endif /* USE_BIN_AS */
diff --git a/gcc/config/m68k/aux-crtn.asm b/gcc/config/m68k/aux-crtn.asm
new file mode 100755
index 0000000..ce63d7f
--- /dev/null
+++ b/gcc/config/m68k/aux-crtn.asm
@@ -0,0 +1,26 @@
+/* More startup code for A/UX */
+
+#include "tm.h"
+
+#ifdef USE_BIN_AS
+ file "crtn.s"
+
+ init
+
+ unlk %fp
+ rts
+#else
+ .file "crtn.s"
+
+.section .init, "x"
+ unlk %fp
+ rts
+
+#ifndef USE_COLLECT2
+.section .ctors, "d"
+ .long 0
+
+.section .dtors, "d"
+ .long 0
+#endif /* USE_COLLECT2 */
+#endif /* USE_BIN_AS */
diff --git a/gcc/config/m68k/aux-exit.c b/gcc/config/m68k/aux-exit.c
new file mode 100755
index 0000000..fe06c77
--- /dev/null
+++ b/gcc/config/m68k/aux-exit.c
@@ -0,0 +1,99 @@
+/* Generic atexit()
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs without any restriction coming from the use of this
+file. (The General Public License restrictions do apply in other
+respects; for example, they cover modification of the file, and
+distribution when not linked into another program.)
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* As a special exception, if you link this library with files
+ compiled with GCC to produce an executable, this does not cause
+ the resulting executable to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
+
+/* Rather than come up with some ugly hack to make mcrt1 work, it is
+ better to just go ahead and provide atexit(). */
+
+
+#include <stdlib.h>
+
+
+void exit(int) __attribute__((noreturn));
+void _exit(int) __attribute__((noreturn));
+void _cleanup(void);
+
+
+#define FNS_PER_BLOCK 32
+
+struct atexit_fn_block
+{
+ struct atexit_fn_block *next;
+ void (*fns[FNS_PER_BLOCK])(void);
+ short used;
+};
+
+
+/* staticly allocate the first block */
+static struct atexit_fn_block atexit_fns;
+static struct atexit_fn_block *current_block = &atexit_fns;
+
+
+int atexit(void (*fn)(void))
+{
+ if (current_block->used >= FNS_PER_BLOCK)
+ {
+ struct atexit_fn_block *new_block =
+ (struct atexit_fn_block *)malloc(sizeof(struct atexit_fn_block));
+ if (new_block == NULL)
+ return -1;
+
+ new_block->used = 0;
+ new_block->next = current_block;
+ current_block = new_block;
+ }
+
+ current_block->fns[current_block->used++] = fn;
+
+ return 0;
+}
+
+
+void exit(int status)
+{
+ struct atexit_fn_block *block = current_block, *old_block;
+ short i;
+
+ while (1)
+ {
+ for (i = block->used; --i >= 0 ;)
+ (*block->fns[i])();
+ if (block == &atexit_fns)
+ break;
+ /* I know what you are thinking -- we are about to exit, why free?
+ Because it is friendly to memory leak detectors, that's why. */
+ old_block = block;
+ block = block->next;
+ free(old_block);
+ }
+
+ _exit(status);
+}
diff --git a/gcc/config/m68k/aux-low.gld b/gcc/config/m68k/aux-low.gld
new file mode 100755
index 0000000..d1bb2a9
--- /dev/null
+++ b/gcc/config/m68k/aux-low.gld
@@ -0,0 +1,38 @@
+/* GLD link script for building mac-compatible executables */
+
+OUTPUT_FORMAT("coff-m68k")
+
+SEARCH_DIR(@tooldir@/lib);
+SEARCH_DIR(@libdir@);
+SEARCH_DIR(/lib);
+SEARCH_DIR(/usr/lib);
+SEARCH_DIR(@local_prefix@/lib);
+
+ENTRY(_start)
+
+SECTIONS
+{
+ .lowmem 0 (DSECT) : {
+ /usr/lib/low.o (.data)
+ }
+ .text 0x10000000 : {
+ *(.text)
+ *(.init)
+ *(.fini)
+ etext = .;
+ _etext = .;
+ }
+ .data ALIGN(0x40000) : {
+ *(.data)
+ *(.ctors)
+ *(.dtors)
+ edata = .;
+ _edata = .;
+ }
+ .bss : {
+ *(.bss)
+ *(COMMON)
+ end = .;
+ _end = .;
+ }
+}
diff --git a/gcc/config/m68k/aux-mcount.c b/gcc/config/m68k/aux-mcount.c
new file mode 100755
index 0000000..1001c84
--- /dev/null
+++ b/gcc/config/m68k/aux-mcount.c
@@ -0,0 +1,69 @@
+/* Profiling support code for A/UX
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs without any restriction coming from the use of this
+file. (The General Public License restrictions do apply in other
+respects; for example, they cover modification of the file, and
+distribution when not linked into another program.)
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* As a special exception, if you link this library with files
+ compiled with GCC to produce an executable, this does not cause
+ the resulting executable to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
+
+/* This routine is called at the beginning of functions compiled with -p
+ or -pg. The A/UX libraries call mcount%, but gas cannot generate
+ symbols with embedded percent signs. Previous ports of GCC to A/UX
+ have done things like (1) assemble a stub routine with the native
+ assembler, or (2) assemble a stub routine with gas and edit the object
+ file. This solution has the advantage that it can interoperate with
+ the A/UX version and can be used in an eventual port of glibc to A/UX. */
+
+#ifndef __GNUC__
+#error This file uses GNU C extensions
+#endif
+
+#include <mon.h>
+
+#ifdef IN_GCC
+#include "tm.h"
+#endif
+
+struct cnt *_countbase;
+
+#ifdef FUNCTION_PROFILER_SYMBOL
+void __mcount() __asm__(FUNCTION_PROFILER_SYMBOL);
+#endif
+
+void __mcount()
+{
+ register long **pfncnt __asm__("%a0");
+ register long *fncnt = *pfncnt;
+
+ if (!fncnt)
+ {
+ struct cnt *newcnt = _countbase++;
+ newcnt->fnpc = (char *)__builtin_return_address(0);
+ *pfncnt = fncnt = &newcnt->mcnt;
+ }
+ *fncnt += 1;
+}
diff --git a/gcc/config/m68k/auxas.h b/gcc/config/m68k/auxas.h
new file mode 100755
index 0000000..794df51
--- /dev/null
+++ b/gcc/config/m68k/auxas.h
@@ -0,0 +1,189 @@
+/* Definitions for Motorola 680x0 running A/UX using /bin/as
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define USE_BIN_AS
+
+#ifndef USE_COLLECT2
+#define USE_COLLECT2
+#endif
+
+#ifndef __ASSEMBLY__
+
+#include "m68k/sgs.h"
+
+#define ASM_SPEC "%{m68030:-68030 }%{m68040:-68040 }"
+
+/* Modify AT&T SGS assembler syntax */
+/* A/UX's as doesn't do dots in pseudo-ops */
+
+#define SDB_DEBUGGING_INFO
+
+#define NO_DOLLAR_IN_LABEL
+#define NO_DOT_IN_LABEL
+
+#undef TEXT_SECTION_ASM_OP
+#define TEXT_SECTION_ASM_OP "\ttext"
+
+#undef DATA_SECTION_ASM_OP
+#define DATA_SECTION_ASM_OP "\tdata\t1"
+
+#undef BYTE_ASM_OP
+#define BYTE_ASM_OP "byte"
+
+#undef WORD_ASM_OP
+#define WORD_ASM_OP "short"
+
+#undef LONG_ASM_OP
+#define LONG_ASM_OP "long"
+
+#undef SPACE_ASM_OP
+#define SPACE_ASM_OP "space"
+
+#undef ALIGN_ASM_OP
+#define ALIGN_ASM_OP "align"
+
+#undef GLOBAL_ASM_OP
+#define GLOBAL_ASM_OP "\tglobal"
+
+#undef SWBEG_ASM_OP
+#define SWBEG_ASM_OP "swbeg"
+
+#undef SET_ASM_OP
+#define SET_ASM_OP "set"
+
+#undef ASM_PN_FORMAT
+#define ASM_PN_FORMAT "%s%%%d"
+
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "L%"
+
+#define ADDITIONAL_REGISTER_NAMES { "%a6", 14, "%a7", 15 }
+
+#undef ASM_OUTPUT_INT
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf ((FILE), "\t%s ", LONG_ASM_OP), \
+ output_addr_const ((FILE), (VALUE)), \
+ fprintf ((FILE), "\n"))
+
+#undef ASM_OUTPUT_COMMON
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\tcomm\t", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+#undef ASM_OUTPUT_LOCAL
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\tlcomm\t", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+ output_file_directive ((FILE), main_input_filename)
+
+#undef ASM_OUTPUT_SOURCE_FILENAME
+#define ASM_OUTPUT_SOURCE_FILENAME(FILE, NAME) \
+( fputs ("\tfile\t", (FILE)), \
+ output_quoted_string ((FILE), (NAME)), \
+ fputc ('\n', (FILE)) )
+
+#undef ASM_OUTPUT_CASE_FETCH
+#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname) \
+ asm_fprintf (file, "10(%Rpc,%s.", regname)
+
+#define SGS_NO_LI
+
+/* Random macros describing parts of SDB data. */
+
+#define PUT_SDB_SCL(a) \
+ fprintf(asm_out_file, "\tscl\t%d%s", (a), SDB_DELIM)
+
+#define PUT_SDB_INT_VAL(a) \
+ fprintf (asm_out_file, "\tval\t%d%s", (a), SDB_DELIM)
+
+#define PUT_SDB_VAL(a) \
+( fputs ("\tval\t", asm_out_file), \
+ output_addr_const (asm_out_file, (a)), \
+ fprintf (asm_out_file, SDB_DELIM))
+
+#define PUT_SDB_DEF(a) \
+do { fprintf (asm_out_file, "\tdef\t"); \
+ ASM_OUTPUT_LABELREF (asm_out_file, a); \
+ fprintf (asm_out_file, SDB_DELIM); } while (0)
+
+#define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\tdef\t~%s%s", a, SDB_DELIM)
+
+#define PUT_SDB_ENDEF fputs("\tendef\n", asm_out_file)
+
+#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\ttype\t0%o%s", a, SDB_DELIM)
+
+#define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\tsize\t%d%s", a, SDB_DELIM)
+
+#define PUT_SDB_START_DIM fprintf(asm_out_file, "\tdim\t")
+
+#define PUT_SDB_NEXT_DIM(a) fprintf(asm_out_file, "%d,", a)
+
+#define PUT_SDB_LAST_DIM(a) fprintf(asm_out_file, "%d%s", a, SDB_DELIM)
+
+#define PUT_SDB_TAG(a) \
+do { fprintf (asm_out_file, "\ttag\t"); \
+ ASM_OUTPUT_LABELREF (asm_out_file, a); \
+ fprintf (asm_out_file, SDB_DELIM); } while (0)
+
+#define PUT_SDB_BLOCK_START(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~bb%s\tval\t~%s\tscl\t100%s\tline\t%d%s\tendef\n", \
+ SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
+
+#define PUT_SDB_BLOCK_END(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~eb%s\tval\t~%s\tscl\t100%s\tline\t%d%s\tendef\n", \
+ SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
+
+#define PUT_SDB_FUNCTION_START(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~bf%s\tval\t~%s\tscl\t101%s\tline\t%d%s\tendef\n", \
+ SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
+
+#define PUT_SDB_FUNCTION_END(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~ef%s\tval\t~%s\tscl\t101%s\tline\t%d%s\tendef\n", \
+ SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
+
+#define PUT_SDB_EPILOGUE_END(NAME) \
+do { fprintf (asm_out_file, "\tdef\t"); \
+ ASM_OUTPUT_LABELREF (asm_out_file, NAME); \
+ fprintf (asm_out_file, \
+ "%s\tval\t~%s\tscl\t-1%s\tendef\n", \
+ SDB_DELIM, SDB_DELIM, SDB_DELIM); } while (0)
+
+#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
+ sprintf ((BUFFER), "~%dfake", (NUMBER));
+
+#define ASM_OUTPUT_SOURCE_LINE(FILE, LINE) \
+ fprintf((FILE), "\tln\t%d\n", \
+ (sdb_begin_function_line > 1 ? \
+ last_linenum - sdb_begin_function_line : 1))
+
+#define ASM_MOV_INSN "mov.l"
+
+#define FUNCTION_PROFILER_SYMBOL "mcount%"
+
+#endif /* !__ASSEMBLY__ */
diff --git a/gcc/config/m68k/auxgas.h b/gcc/config/m68k/auxgas.h
new file mode 100755
index 0000000..c2e0d56
--- /dev/null
+++ b/gcc/config/m68k/auxgas.h
@@ -0,0 +1,56 @@
+/* Definitions for Motorola 680x0 running A/UX using GAS
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define USE_GAS
+
+#ifndef __ASSEMBLY__
+
+#include "m68k/m68k.h"
+#include "m68k/coff.h"
+
+#define ASM_SPEC "%{m68000:-Am68000 }%{m68030:-Am68030 }%{m68040:-Am68040 }"
+
+/* Output #ident as a .ident. */
+#define ASM_OUTPUT_IDENT(FILE, NAME) \
+ fprintf (FILE, "\t.ident \"%s\"\n", NAME);
+
+#ifdef IDENTIFY_WITH_IDENT
+/* Put the GCC identification somewhere nicer, I think.
+ Does the COFF GDB use the "gcc2_complied." symbol anyway? */
+#define ASM_IDENTIFY_GCC(FILE) /* nothing */
+#define ASM_IDENTIFY_LANGUAGE(FILE) \
+ fprintf (FILE, "\t.ident \"GCC (%s) %s\"\n", lang_identify(), version_string)
+#endif
+
+#ifdef USE_COLLECT2
+#undef ASM_OUTPUT_CONSTRUCTOR
+#undef ASM_OUTPUT_DESTRUCTOR
+/* for the sake of link-level compatibility with /bin/as version */
+#define NO_DOLLAR_IN_LABEL
+#define NO_DOT_IN_LABEL
+#endif
+
+#define ADDITIONAL_REGISTER_NAMES { "%fp", 14, "%a7", 15 }
+
+#define ASM_MOV_INSN "movel"
+
+#define FUNCTION_PROFILER_SYMBOL "__mcount"
+
+#endif /* !__ASSEMBLY__ */
diff --git a/gcc/config/m68k/auxgld.h b/gcc/config/m68k/auxgld.h
new file mode 100755
index 0000000..12c97af
--- /dev/null
+++ b/gcc/config/m68k/auxgld.h
@@ -0,0 +1,29 @@
+/* Definitions for Motorola 680x0 running A/UX using GLD
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define USE_GNU_LD
+
+#ifndef __ASSEMBLY__
+
+#define LINK_SPEC \
+"%{p:-L/lib/libp -L/usr/lib/libp }%{pg:-L/lib/libp -L/usr/lib/libp }\
+%{smac:-T low.gld%s }"
+
+#endif /* !__ASSEMBLY__ */
diff --git a/gcc/config/m68k/auxld.h b/gcc/config/m68k/auxld.h
new file mode 100755
index 0000000..932dd6a
--- /dev/null
+++ b/gcc/config/m68k/auxld.h
@@ -0,0 +1,35 @@
+/* Definitions for Motorola 680x0 running A/UX using /bin/ld
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define USE_BIN_LD
+
+#ifndef USE_COLLECT2
+#define USE_COLLECT2
+#endif
+
+#ifndef __ASSEMBLY__
+
+#define LINK_SPEC \
+"%{p:-L/lib/libp -L/usr/lib/libp }%{pg:-L/lib/libp -L/usr/lib/libp }\
+%{smac:low.ld%s }%{!smac:shlib.ld%s }"
+
+#define SWITCHES_NEED_SPACES "o"
+
+#endif /* !__ASSEMBLY__ */
diff --git a/gcc/config/m68k/ccur-GAS.h b/gcc/config/m68k/ccur-GAS.h
new file mode 100755
index 0000000..685eb97
--- /dev/null
+++ b/gcc/config/m68k/ccur-GAS.h
@@ -0,0 +1,129 @@
+/* Definitions of target machine for GNU compiler. Concurrent 68k version.
+ Copyright (C) 1987, 1988, 1995, 1996, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifndef MASSCOMP
+#define MASSCOMP
+#endif
+
+#ifndef CONCURRENT
+#define CONCURRENT
+#endif
+
+#ifndef __mc68000__
+#define __mc68000__
+#endif
+
+#ifndef __mc68020__
+#define __mc68020__
+#endif
+
+#define USE_GAS
+#define MOVE_RATIO 100
+
+#define SPACE_AFTER_L_OPTION
+#define SWITCHES_NEED_SPACES "oL"
+
+/* See m68k.h. 7 means 68020 with 68881. */
+#define TARGET_DEFAULT (MASK_68040|MASK_BITFIELD|MASK_68881|MASK_68020)
+
+#include "m68k/m68k.h"
+
+#define SIZE_TYPE "int"
+
+/* for 68k machines this only needs to be TRUE for the 68000 */
+
+#undef STRICT_ALIGNMENT
+#define STRICT_ALIGNMENT 0
+
+/* Names to predefine in the preprocessor for this target machine. */
+#define CPP_PREDEFINES \
+ "-Dmc68000 -Dmasscomp -DMASSCOMP -Dunix -DLANGUAGE_C -Dconcurrent -DCONCURRENT"
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (68k, GNU GAS syntax)");
+
+/* Discard internal local symbols beginning with 'L'. */
+#define LINK_SPEC "-X"
+
+/* Every structure or union's size must be a multiple of 4 bytes. */
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* No data type wants to be aligned rounder than this. */
+#undef BIGGEST_ALIGNMENT
+#define BIGGEST_ALIGNMENT 32
+
+/* Allocation boundary (in *bits*) for storing pointers in memory. */
+#undef POINTER_BOUNDARY
+#define POINTER_BOUNDARY 32
+
+/* Alignment of field after `int : 0' in a structure. */
+#undef EMPTY_FIELD_BOUNDARY
+#define EMPTY_FIELD_BOUNDARY 32
+
+/* Allocation boundary in bits for the code of a function */
+#undef FUNCTION_BOUNDARY
+#define FUNCTION_BOUNDARY 32
+
+/* Make strings long-word aligned so dhrystones will run faster. */
+#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
+ (TREE_CODE (EXP) == STRING_CST \
+ && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
+
+/* Make arrays of chars word-aligned for the same reasons. */
+#define DATA_ALIGNMENT(TYPE, ALIGN) \
+ (TREE_CODE (TYPE) == ARRAY_TYPE \
+ && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
+ && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
+
+/* This is BSD, so it wants DBX format. */
+#define DBX_DEBUGGING_INFO
+
+/* Override parts of m68k.h */
+
+#undef CALL_USED_REGISTERS
+#define CALL_USED_REGISTERS \
+ {1, 1, 0, 0, 0, 0, 0, 0, \
+ 1, 1, 0, 0, 0, 0, 0, 1, \
+ 1, 1, 0, 0, 0, 0, 1, 1 }
+
+#undef REG_ALLOC_ORDER
+#define REG_ALLOC_ORDER \
+{ 0, 1, 2, 3, 4, 5, 6, 7,\
+ 8, 9, 10, 11, 12, 13, 14, 15, \
+ 16, 17, 22, 23, 18, 19, 20, 21 }
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+ fprintf (FILE, "#NO_APP\n.globl fltused\n");
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+{ int _LOG = LOG; \
+ if (_LOG == 1) \
+ fprintf (FILE, "\t.even\n"); \
+ else if (_LOG == 2) \
+ fprintf (FILE, "\t.align 4\n"); \
+ else if (_LOG != 0) \
+ fprintf (FILE, "\t.align %d\n", _LOG);\
+}
+
+/* crt0.c should use the vax-bsd style of entry, with a dummy arg. */
+
+#define CRT0_DUMMIES bogus_fp,
diff --git a/gcc/config/m68k/coff.h b/gcc/config/m68k/coff.h
new file mode 100755
index 0000000..acd45e7
--- /dev/null
+++ b/gcc/config/m68k/coff.h
@@ -0,0 +1,176 @@
+/* Definitions of target machine for GNU compiler.
+ m68k series COFF object files and debugging, version.
+ Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* This file is included after m68k.h by CPU COFF specific files. It
+ is not a complete target itself. */
+
+/* Generate sdb debugging information. */
+
+#define SDB_DEBUGGING_INFO
+
+/* Output DBX (stabs) debugging information if using -gstabs. */
+
+#include "dbxcoff.h"
+
+/* COFF symbols don't start with an underscore. */
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+
+/* Use a prefix for local labels, just to be on the save side. */
+
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
+/* Use a register prefix to avoid clashes with external symbols (classic
+ example: `extern char PC;' in termcap). */
+
+#undef REGISTER_PREFIX
+#define REGISTER_PREFIX "%"
+
+/* In the machine description we can't use %R, because it will not be seen
+ by ASM_FPRINTF. (Isn't that a design bug?). */
+
+#undef REGISTER_PREFIX_MD
+#define REGISTER_PREFIX_MD "%%"
+
+/* config/m68k.md has an explicit reference to the program counter,
+ prefix this by the register prefix. */
+
+#define ASM_RETURN_CASE_JUMP \
+ do { \
+ if (TARGET_5200) \
+ return "ext%.l %0\n\tjmp %%pc@(2,%0:l)"; \
+ else \
+ return "jmp %%pc@(2,%0:w)"; \
+ } while (0)
+
+/* Here are the new register names. */
+
+#undef REGISTER_NAMES
+#ifndef SUPPORT_SUN_FPA
+#define REGISTER_NAMES \
+{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%sp", \
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7" }
+#else /* SUPPORTED_SUN_FPA */
+#define REGISTER_NAMES \
+{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%sp", \
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7", \
+ "%fpa0", "%fpa1", "%fpa2", "%fpa3", "%fpa4", "%fpa5", "%fpa6", "%fpa7", \
+ "%fpa8", "%fpa9", "%fpa10", "%fpa11", "%fpa12", "%fpa13", "%fpa14", "%fpa15", \
+ "%fpa16", "%fpa17", "%fpa18", "%fpa19", "%fpa20", "%fpa21", "%fpa22", "%fpa23", \
+ "%fpa24", "%fpa25", "%fpa26", "%fpa27", "%fpa28", "%fpa29", "%fpa30", "%fpa31" }
+#endif /* defined SUPPORT_SUN_FPA */
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+ output_file_directive ((FILE), main_input_filename)
+
+/* If defined, a C expression whose value is a string containing the
+ assembler operation to identify the following data as uninitialized global
+ data. */
+
+#define BSS_SECTION_ASM_OP ".section\t.bss"
+
+/* A C statement (sans semicolon) to output to the stdio stream
+ FILE the assembler definition of uninitialized global DECL named
+ NAME whose size is SIZE bytes and alignment is ALIGN bytes.
+ Try to use asm_output_aligned_bss to implement this macro. */
+
+#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
+ asm_output_aligned_bss ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
+
+/* Support generic sections */
+
+#undef ASM_OUTPUT_SECTION_NAME
+#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
+ fprintf((FILE), ".section\t%s,\"%c\"\n", (NAME), \
+ (DECL) && (TREE_CODE (DECL) == FUNCTION_DECL || \
+ DECL_READONLY_SECTION (DECL, RELOC)) ? 'x' : 'd')
+
+/* Support the ctors and dtors sections for g++. */
+
+#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"x\""
+#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"x\""
+
+/* A list of other sections which the compiler might be "in" at any
+ given time. */
+
+#undef EXTRA_SECTIONS
+#define EXTRA_SECTIONS in_ctors, in_dtors
+
+/* A list of extra section function definitions. */
+
+#undef EXTRA_SECTION_FUNCTIONS
+#define EXTRA_SECTION_FUNCTIONS \
+ CTORS_SECTION_FUNCTION \
+ DTORS_SECTION_FUNCTION
+
+#define CTORS_SECTION_FUNCTION \
+void \
+ctors_section () \
+{ \
+ if (in_section != in_ctors) \
+ { \
+ fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \
+ in_section = in_ctors; \
+ } \
+}
+
+#define DTORS_SECTION_FUNCTION \
+void \
+dtors_section () \
+{ \
+ if (in_section != in_dtors) \
+ { \
+ fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \
+ in_section = in_dtors; \
+ } \
+}
+
+#define INT_ASM_OP ".long"
+
+/* A C statement (sans semicolon) to output an element in the table of
+ global constructors. */
+#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
+ do { \
+ ctors_section (); \
+ fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+/* A C statement (sans semicolon) to output an element in the table of
+ global destructors. */
+#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
+ do { \
+ dtors_section (); \
+ fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+/* Don't assume anything about startfiles. */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC ""
diff --git a/gcc/config/m68k/crds.h b/gcc/config/m68k/crds.h
new file mode 100755
index 0000000..441b285
--- /dev/null
+++ b/gcc/config/m68k/crds.h
@@ -0,0 +1,621 @@
+/* Definitions of target machine for GNU compiler;
+ Charles River Data Systems UNiverse/32.
+ Copyright (C) 1987, 1993, 1994, 1996, 1997 Free Software Foundation, Inc.
+ Contributed by Gary E. Miller (Gary_Edmunds_Miller@cup.portal.com)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define MOTOROLA /* Use Motorola syntax rather than "MIT" */
+#define SGS /* Uses SGS assembler */
+#define SGS_SWITCH_TABLES /* Different switch table handling */
+#define SGS_NO_LI /* Suppress jump table label usage */
+#define CRDS /* Charles River Data Systems assembler */
+
+#include "m68k/m68k.h"
+
+/* Without STRUCTURE_SIZE_BOUNDARY, we can't ensure that structures are
+ aligned such that we can correctly extract bitfields from them.
+ Someone should check whether the usual compiler on the crds machine
+ provides the equivalent behavior of STRUCTURE_SIZE_BOUNDARY. */
+/* Set to 16 because all other m68k targets have it so */
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* See m68k.h. 0 means 680[01]0 with no 68881. */
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT 0
+
+/* Don't try using XFmode. */
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+/* special flags to the unos assembler. */
+
+#undef ASM_SPEC
+#define ASM_SPEC "-g"
+
+#undef LIB_SPEC
+#define LIB_SPEC "%{!p:%{!pg:-lunos}}%{p:-lc_p}%{pg:-lc_p}"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{pg:gcrt0.o%s}%{!pg:%{p:mc68rt0.o%s}%{!p:c68rt0.o%s}}"
+
+/* CC1 spec */
+#if 0
+/* c.sac only used in _s_call_r() in libunos.a and malloc() in libmalloc.a */
+/* so we do not need to bother ! */
+#define CC1_SPEC "-fpcc-struct-return"
+#endif
+
+/* -O2 for MAX optimization */
+#undef CC1_SPEC
+#define CC1_SPEC "%{O2:-fstrength-reduce}"
+
+/* cpp has to support a #sccs directive for the /usr/include files */
+
+#define SCCS_DIRECTIVE
+
+/* Make output for SDB. */
+
+/* #define SDB_DEBUGGING_INFO UNOS casm has no debugging :-( */
+
+/* UNOS need stack probe :-( */
+
+#if 0
+#define HAVE_probe 1
+#define gen_probe() gen_rtx(ASM_INPUT, VOIDmode, "tstb -2048(sp)\t;probe\n")
+#else
+#undef NEED_PROBE
+#define NEED_PROBE (-2048)
+#endif
+
+/* use memcpy, memset instead of bcopy, etc. */
+
+#define TARGET_MEM_FUNCTIONS
+
+/* Don't try to define `gcc_compiled.' since the assembler might not
+ accept symbols with periods and GDB doesn't run on this machine anyway. */
+#define ASM_IDENTIFY_GCC(FILE)
+
+/* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#undef CPP_SPEC
+#define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dmc68k -DM68000 -Dmc68000 -Dunos -Dunix -D__motorola__ -Asystem(unix) -Acpu(m68k) -Amachine(m68k)"
+
+/* Register in which address to store a structure value
+ is passed to a function. */
+/* unos uses ".comm c.sac" returns &c.sac in d0 */
+/* make pointer to c.sac ?
+#undef STRUCT_VALUE_REGNUM
+#define STRUCT_VALUE gen_rtx(MEM, Pmode, gen_rtx( , , ) )
+*/
+
+#define BSS_SECTION_ASM_OP ".bss"
+
+/* Specify how to pad function arguments.
+ Value should be `upward', `downward' or `none'.
+ Same as the default, except no padding for large or variable-size args. */
+
+#define FUNCTION_ARG_PADDING(MODE, TYPE) \
+ (((MODE) == BLKmode \
+ ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
+ && int_size_in_bytes (TYPE) < PARM_BOUNDARY / BITS_PER_UNIT) \
+ : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY) \
+ ? downward : none)
+
+/* Override parts of m68k.h to fit the CRuDS assembler. */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (68k, CRDS/UNOS)");
+
+/* Specify extra dir to search for include files. */
+#define SYSTEM_INCLUDE_DIR "/include"
+
+/* Control the assembler format that we output. */
+
+/* Output at beginning of assembler file. */
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+ fprintf (FILE, ";#NO_APP\n");
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#undef ASM_APP_ON
+#define ASM_APP_ON ";#APP\n"
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#undef ASM_APP_OFF
+#define ASM_APP_OFF ";#NO_APP\n"
+
+/* The prefix for immediate operands. */
+
+#undef IMMEDIATE_PREFIX
+#define IMMEDIATE_PREFIX "$"
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#undef ASM_OUTPUT_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+do { long l[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
+ fprintf (FILE, "\t.long 0x%x, 0x%x\n", l[0], l[1]); \
+ } while (0)
+
+/*unos has no .skip :-( */
+#undef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t. = . + %u\n", (SIZE));
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+/* should use bss_section instead of data_section but this makes casm die ? */
+
+#undef ASM_OUTPUT_LOCAL
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+{ data_section (); \
+ if ((SIZE) > 1) fprintf (FILE, "\t.even\n"); \
+ assemble_name ((FILE), (NAME)); \
+ fprintf ((FILE), ":\t. = . + %u\n", (ROUNDED));}
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#undef ASM_OUTPUT_REG_PUSH
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tmovel %s,-(sp)\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#undef ASM_OUTPUT_REG_POP
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tmovel (sp)+,%s\n", reg_names[REGNO])
+
+#undef ASM_OUTPUT_ASCII
+#define ASM_OUTPUT_ASCII(FILE, P , SIZE) \
+do { int i; \
+ fprintf ((FILE), "\t.ascii \""); \
+ for (i = 0; i < (SIZE); i++) \
+ { \
+ register int c = (P)[i]; \
+ if (i != 0 && (i / 200) * 200 == i) \
+ fprintf ((FILE), "\"\n\t.ascii \""); \
+ if (c >= ' ' && c < 0177) { \
+ if (c != '\"' && c != '\\') { \
+ putc (c, (FILE)); \
+ continue; \
+ } \
+ } \
+ /* brain dead asm doesn't understand char escapes */ \
+ fprintf ((FILE), "\"\n\t.byte\t%d\n\t.ascii \"", c); \
+ } \
+ fprintf ((FILE), "\"\n"); \
+ } while (0)
+
+
+/* Change all JBxx to Bxx. Also change all DBRA to DBF.
+ Also change divs.l, etc., to divs, etc. But don't change divsl.l. */
+
+#define ASM_OUTPUT_OPCODE(FILE, PTR) \
+{ if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
+ { ++(PTR); } \
+ else if ((PTR)[0] == 'd') \
+ { \
+ if (!strncmp ((PTR), "dbra", 4)) \
+ { fprintf ((FILE), "dbf"); (PTR) += 4; } \
+ else if (!strncmp ((PTR), "div", 3) && (PTR)[5] == ' ') \
+ { fprintf ((FILE), "div%c", (PTR)[3]); (PTR) += 6; } \
+ } \
+}
+
+
+#if 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.
+ For `%' followed by punctuation, CODE is the punctuation and X is null.
+
+ On the 68000, we use several CODE characters:
+ '.' for dot needed in Motorola-style opcode names.
+ '-' for an operand pushing on the stack:
+ sp@-, -(sp) or -(%sp) depending on the style of syntax.
+ '+' for an operand pushing on the stack:
+ sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
+ '@' for a reference to the top word on the stack:
+ sp@, (sp) or (%sp) depending on the style of syntax.
+ '#' for an immediate operand prefix (# in MIT and Motorola syntax
+ but & in SGS syntax, $ in unos syntax).
+ '!' for the fpcr register (used in some float-to-fixed conversions).
+
+ 'b' for byte insn (no effect, on the Sun; this is for the ISI).
+ 'd' to force memory addressing to be absolute, not relative.
+ 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
+ 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
+ than directly). Second part of 'y' below.
+ 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
+ or print pair of registers as rx:ry.
+ 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
+ CONST_DOUBLE's as SunFPA constant RAM registers if
+ possible, so it should not be used except for the SunFPA. */
+
+#undef PRINT_OPERAND_PUNCT_VALID_P
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
+ ((CODE) == '.' || (CODE) == '#' || (CODE) == '-' \
+ || (CODE) == '+' || (CODE) == '@' || (CODE) == '!')
+
+#undef PRINT_OPERAND
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ int i; \
+ if (CODE == '.') ; \
+ else if (CODE == '#') fprintf (FILE, "$"); \
+ else if (CODE == '-') fprintf (FILE, "-(sp)"); \
+ else if (CODE == '+') fprintf (FILE, "(sp)+"); \
+ else if (CODE == '@') fprintf (FILE, "(sp)"); \
+ else if (CODE == '!') fprintf (FILE, "fpcr"); \
+ else if (CODE == '/') \
+ ; \
+ else if (GET_CODE (X) == REG) \
+ { if (REGNO (X) < 16 && (CODE == 'y' || CODE == 'x') && GET_MODE (X) == DFmode) \
+ fprintf (FILE, "%s:%s", reg_names[REGNO (X)], reg_names[REGNO (X)+1]); \
+ else \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ } \
+ else if (GET_CODE (X) == MEM) \
+ { \
+ output_address (XEXP (X, 0)); \
+ if (CODE == 'd' && ! TARGET_68020 \
+ && CONSTANT_ADDRESS_P (XEXP (X, 0))) \
+ /* fprintf (FILE, ".l") */; \
+ } \
+ else if ((CODE == 'y' || CODE == 'w') \
+ && GET_CODE(X) == CONST_DOUBLE \
+ && (i = standard_sun_fpa_constant_p (X))) \
+ fprintf (FILE, "%%%d", i & 0x1ff); \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
+ { REAL_VALUE_TYPE r; long l; \
+ REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
+ if (CODE == 'f') \
+ ASM_OUTPUT_FLOAT_OPERAND (CODE, FILE, r); \
+ else \
+ { REAL_VALUE_TO_TARGET_SINGLE (r, l); \
+ fprintf (FILE, "$0x%x", l); } } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode) \
+ { REAL_VALUE_TYPE r; \
+ REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
+ ASM_OUTPUT_DOUBLE_OPERAND (FILE, r); } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == XFmode) \
+ { REAL_VALUE_TYPE r; \
+ REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
+ ASM_OUTPUT_LONG_DOUBLE_OPERAND (FILE, r); } \
+ else { putc ('$', FILE); output_addr_const (FILE, X); }}
+#endif
+
+/* Note that this contains a kludge that knows that the only reason
+ we have an address (plus (label_ref...) (reg...))
+ is in the insn before a tablejump, and we know that m68k.md
+ generates a label LInnn: on such an insn. */
+#undef PRINT_OPERAND_ADDRESS
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx reg1, reg2, breg, ireg; \
+ register rtx addr = ADDR; \
+ rtx offset; \
+ switch (GET_CODE (addr)) \
+ { \
+ case REG: \
+ fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
+ break; \
+ case PRE_DEC: \
+ fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case POST_INC: \
+ fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case PLUS: \
+ reg1 = 0; reg2 = 0; \
+ ireg = 0; breg = 0; \
+ offset = 0; \
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
+ { \
+ offset = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
+ { \
+ offset = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) != PLUS) ; \
+ else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
+ || GET_CODE (addr) == SIGN_EXTEND) \
+ { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
+ if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
+ if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
+ || GET_CODE (reg1) == MULT)) \
+ || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
+ { breg = reg2; ireg = reg1; } \
+ else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
+ { breg = reg1; ireg = reg2; } \
+ if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { int scale = 1; \
+ if (GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "L%d-LI%d-2(pc,%s.w", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (XEXP (ireg, 0))]); \
+ else \
+ fprintf (FILE, "L%d-LI%d-2(pc,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, ":%d", scale); \
+ putc (')', FILE); \
+ break; } \
+ if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "L%d-LI%d-2(pc,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (breg)]); \
+ putc (')', FILE); \
+ break; } \
+ if (ireg != 0 || breg != 0) \
+ { int scale = 1; \
+ if (breg == 0) \
+ abort (); \
+ if (addr && GET_CODE (addr) == LABEL_REF) abort (); \
+ if (addr != 0) \
+ output_addr_const (FILE, addr); \
+ fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \
+ if (breg != 0 && ireg != 0) \
+ putc (',', FILE); \
+ if (ireg != 0 && GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
+ else if (ireg != 0) \
+ fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, ":%d", scale); \
+ putc (')', FILE); \
+ break; \
+ } \
+ else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "L%d-LI%d-2(pc,%s.l)", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (reg1)]); \
+ break; } \
+ default: \
+ if (GET_CODE (addr) == CONST_INT \
+ && INTVAL (addr) < 0x8000 \
+ && INTVAL (addr) >= -0x8000) \
+ fprintf (FILE, "%d", INTVAL (addr)); \
+ else \
+ output_addr_const (FILE, addr); \
+ }}
+
+#define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
+ do { fprintf (FILE, "\t; file\t"); \
+ output_quoted_string (FILE, FILENAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+#define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \
+ fprintf (FILE, "\t; ln\t%d\n", \
+ (sdb_begin_function_line \
+ ? last_linenum - sdb_begin_function_line : 1))
+
+/* This macro generates the assembly code for function entry.
+ FILE is a stdio stream to output the code to.
+ SIZE is an int: how many units of temporary storage to allocate.
+ Refer to the array `regs_ever_live' to determine which registers
+ to save; `regs_ever_live[I]' is nonzero if register number I
+ is ever used in the function. This macro is responsible for
+ knowing which registers should not be saved even if used. */
+
+/* Note that the order of the bit mask for fmovem is the opposite
+ of the order for movem! */
+
+#undef FUNCTION_PROLOGUE
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ register int regno; \
+ register int mask = 0; \
+ extern char call_used_regs[]; \
+ int fsize = ((SIZE) + 3) & -4; \
+ /* unos stack probe */ \
+ if ( fsize > 30000 ) { \
+ fprintf (FILE, "\tmovel sp,a0\n"); \
+ fprintf (FILE, "\taddl $-%d,a0\n", 2048 + fsize); \
+ fprintf (FILE, "\ttstb (a0)\n"); \
+ } else { \
+ fprintf (FILE, "\ttstb -%d(sp)\n", 2048 + fsize); \
+ } \
+ if (frame_pointer_needed) \
+ { if (TARGET_68020 || fsize < 0x8000) \
+ fprintf (FILE, "\tlink a6,$%d\n", -fsize); \
+ else \
+ fprintf (FILE, "\tlink a6,$0\n\tsubl $%d,sp\n", fsize); } \
+ else if (fsize) \
+ { \
+ /* Adding negative number is faster on the 68040. */ \
+ if (fsize + 4 < 0x8000) \
+ { \
+ fprintf (FILE, "\tadd.w #%d,sp\n", - (fsize + 4)); \
+ } \
+ else \
+ { \
+ fprintf (FILE, "\tadd.l #%d,sp\n", - (fsize + 4)); \
+ } \
+ } \
+ for (regno = 16; regno < 24; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ mask |= 1 << (regno - 16); \
+ if ((mask & 0xff) != 0) \
+ fprintf (FILE, "\tfmovem $0x%x,-(sp)\n", mask & 0xff); \
+ mask = 0; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ mask |= 1 << (15 - regno); \
+ if (frame_pointer_needed) \
+ mask &= ~ (1 << (15-FRAME_POINTER_REGNUM)); \
+ if (exact_log2 (mask) >= 0) \
+ fprintf (FILE, "\tmovel %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]); \
+ else if (mask) fprintf (FILE, "\tmovem $0x%x,-(sp)\n", mask); }
+
+/* Must put address in %a0 , not %d0 . -- LGM, 7/15/88 */
+/* UNOS ?? */
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(FILE, LABEL_NO) \
+ fprintf (FILE, "\tmovl &LP%%%d,%%a0\n\tjsr mcount\n", (LABEL_NO))
+
+/* This macro generates the assembly code for function exit,
+ on machines that need it. If FUNCTION_EPILOGUE is not defined
+ then individual return instructions are generated for each
+ return statement. Args are same as for FUNCTION_PROLOGUE.
+
+ The function epilogue should not depend on the current stack pointer!
+ It should use the frame pointer only. This is mandatory because
+ of alloca; we also take advantage of it to omit stack adjustments
+ before returning. */
+
+#undef FUNCTION_EPILOGUE
+#define FUNCTION_EPILOGUE(FILE, SIZE) \
+{ register int regno; \
+ register int mask, fmask; \
+ register int nregs; \
+ int offset, foffset, fpoffset; \
+ extern char call_used_regs[]; \
+ int fsize = ((SIZE) + 3) & -4; \
+ int big = 0; \
+ nregs = 0; fmask = 0; fpoffset = 0; \
+ for (regno = 16; regno < 24; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ { nregs++; fmask |= 1 << (23 - regno); } \
+ foffset = fpoffset + nregs * 12; \
+ nregs = 0; mask = 0; \
+ if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ { nregs++; mask |= 1 << regno; } \
+ offset = foffset + nregs * 4; \
+ if (offset + fsize >= 0x8000 \
+ && frame_pointer_needed \
+ && (mask || fmask || fpoffset)) \
+ { fprintf (FILE, "\tmovel $%d,a0\n", -fsize); \
+ fsize = 0, big = 1; } \
+ if (exact_log2 (mask) >= 0) { \
+ if (big) \
+ fprintf (FILE, "\tmovel -%d(a6,a0.l),%s\n", \
+ offset + fsize, reg_names[exact_log2 (mask)]); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tmovel (sp)+,%s\n", \
+ reg_names[exact_log2 (mask)]); \
+ else \
+ fprintf (FILE, "\tmovel -%d(a6),%s\n", \
+ offset + fsize, reg_names[exact_log2 (mask)]); } \
+ else if (mask) { \
+ if (big) \
+ fprintf (FILE, "\tmovem -%d(a6,a0.l),$0x%x\n", \
+ offset + fsize, mask); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tmovem (sp)+,$0x%x\n", mask); \
+ else \
+ fprintf (FILE, "\tmovem -%d(a6),$0x%x\n", \
+ offset + fsize, mask); } \
+ if (fmask) { \
+ if (big) \
+ fprintf (FILE, "\tfmovem -%d(a6,a0.l),$0x%x\n", \
+ foffset + fsize, fmask); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tfmovem (sp)+,$0x%x\n", fmask); \
+ else \
+ fprintf (FILE, "\tfmovem -%d(a6),$0x%x\n", \
+ foffset + fsize, fmask); } \
+ if (fpoffset != 0) \
+ for (regno = 55; regno >= 24; regno--) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) { \
+ if (big) \
+ fprintf(FILE, "\tfpmoved -%d(a6,a0.l), %s\n", \
+ fpoffset + fsize, reg_names[regno]); \
+ else if (! frame_pointer_needed) \
+ fprintf(FILE, "\tfpmoved (sp)+, %s\n", \
+ reg_names[regno]); \
+ else \
+ fprintf(FILE, "\tfpmoved -%d(a6), %s\n", \
+ fpoffset + fsize, reg_names[regno]); \
+ fpoffset -= 8; \
+ } \
+ if (frame_pointer_needed) \
+ fprintf (FILE, "\tunlk a6\n"); \
+ else if (fsize) \
+ { \
+ if (fsize + 4 < 0x8000) \
+ { \
+ fprintf (FILE, "\tadd.w #%d,sp\n", fsize + 4); \
+ } \
+ else \
+ { \
+ fprintf (FILE, "\tadd.l #%d,sp\n", fsize + 4); \
+ } \
+ } \
+ if (current_function_pops_args) \
+ fprintf (FILE, "\trtd $%d\n", current_function_pops_args); \
+ else fprintf (FILE, "\trts\n"); }
+
diff --git a/gcc/config/m68k/ctix.h b/gcc/config/m68k/ctix.h
new file mode 100755
index 0000000..9c213fc
--- /dev/null
+++ b/gcc/config/m68k/ctix.h
@@ -0,0 +1,48 @@
+/* Definitions of target machine for GNU compiler.
+ Convergent Technologies MiniFrame version,
+ using GAS and binutils with COFF encapsulation.
+
+ Written by Ronald Cole
+
+ Because the MiniFrame's C compiler is so completely lobotomized,
+ bootstrapping this is damn near impossible!
+ Write to me for information on obtaining the binaries...
+
+ bug reports to csusac!unify!rjc@ucdavis.edu
+
+ Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "m68k/3b1g.h"
+
+/* Names to predefine in the preprocessor for this target machine. */
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dmc68000 -Dmc68k -Dunix -Dctix -Asystem(unix) -Acpu(m68k) -Amachine(m68k)"
+
+/* Where to look for robotussinized startfiles. */
+#undef STANDARD_STARTFILE_PREFIX
+#define STANDARD_STARTFILE_PREFIX "/usr/local/lib/gnu/"
+
+/* Generate calls to the MiniFrame's library (for speed). */
+#define DIVSI3_LIBCALL "ldiv"
+#define UDIVSI3_LIBCALL "uldiv"
+#define MODSI3_LIBCALL "lrem"
+#define UMODSI3_LIBCALL "ulrem"
+#define MULSI3_LIBCALL "lmul"
+#define UMULSI3_LIBCALL "ulmul"
diff --git a/gcc/config/m68k/dpx2.h b/gcc/config/m68k/dpx2.h
new file mode 100755
index 0000000..b377974
--- /dev/null
+++ b/gcc/config/m68k/dpx2.h
@@ -0,0 +1,822 @@
+/* Definitions of target machine for GNU compiler.
+ Bull DPX/2 200 and 300 systems (m68k, SysVr3).
+ Copyright (C) 1987, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+ Contributed by Frederic Pierresteguy (F.Pierresteguy@frcl.bull.fr).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+#ifndef USE_GAS
+#define MOTOROLA /* Use Motorola syntax rather than "MIT" */
+#define SGS_NO_LI /* Suppress jump table label usage */
+#define VERSADOS /* This is the name of the assembler we have */
+#endif
+
+#include "m68k/m68k.h"
+#undef SELECT_RTX_SECTION
+#include "svr3.h"
+
+/* See m68k.h. 7 means 68020 with 68881.
+ * We really have 68030 and 68882,
+ * but this will get us going.
+ */
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
+#endif
+
+#define OBJECT_FORMAT_COFF
+#define NO_SYS_SIGLIST
+
+#ifdef CPP_PREDEFINES
+#undef CPP_PREDEFINES
+#endif
+/*
+ * define all the things the compiler should
+ */
+#ifdef ncl_mr
+# define CPP_PREDEFINES "-Dunix -Dbull -DDPX2 -DSVR3 -Dmc68000 -Dmc68020 -Dncl_mr=1 -D_BULL_SOURCE -D_POSIX_SOURCE -D_XOPEN_SOURCE -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
+#else
+# ifdef ncl_el
+# define CPP_PREDEFINES "-Dunix -Dbull -DDPX2 -DSVR3 -Dmc68000 -Dmc68020 -Dncl_el -D_BULL_SOURCE -D_POSIX_SOURCE -D_XOPEN_SOURCE -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
+# else
+# define CPP_PREDEFINES "-Dunix -Dbull -DDPX2 -DSVR3 -Dmc68000 -Dmc68020 -D_BULL_SOURCE -D_POSIX_SOURCE -D_XOPEN_SOURCE -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
+# endif
+#endif
+
+#undef CPP_SPEC
+/*
+ * you can't get a DPX/2 without a 68882 but allow it
+ * to be ignored...
+ */
+# define __HAVE_68881__ 1
+# define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__ }"
+
+#define HAVE_ATEXIT
+#undef DO_GLOBAL_CTORS_BODY /* don't use svr3.h version */
+#undef DO_GLOBAL_DTORS_BODY
+
+#ifndef USE_GAS
+/*
+ * handle the native MOTOROLA VERSAdos assembler.
+ */
+
+/* See m68k.h. 3 means 68020 with 68881 and no bitfield
+ * bitfield instructions do not seem to work a clean way.
+ */
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_68881|MASK_68020)
+
+/* The native assembler doesn't support fmovecr. */
+#define NO_ASM_FMOVECR
+
+#undef EXTRA_SECTIONS
+#undef EXTRA_SECTION_FUNCTIONS
+#undef READONLY_DATA_SECTION
+#define READONLY_DATA_SECTION data_section
+#undef SELECT_SECTION
+#undef SELECT_RTX_SECTION
+#define fini_section() while (0)
+
+#undef CTORS_SECTION_ASM_OP
+#define CTORS_SECTION_ASM_OP "\tsection 15"
+#undef DTORS_SECTION_ASM_OP
+#define DTORS_SECTION_ASM_OP "\tsection 15"
+#undef INIT_SECTION_ASM_OP
+#define BSS_SECTION_ASM_OP "\tsection 14"
+#undef TEXT_SECTION_ASM_OP
+#define TEXT_SECTION_ASM_OP "\tsection 10"
+#undef DATA_SECTION_ASM_OP
+#define DATA_SECTION_ASM_OP "\tsection 15"
+
+
+/* Don't try using XFmode. */
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+/* 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
+
+#undef ASM_OUTPUT_SOURCE_FILENAME
+#define ASM_OUTPUT_SOURCE_FILENAME(FILE, NA) \
+ do { fprintf ((FILE), "\t.file\t'%s'\n", (NA)); } while (0)
+
+/* Assembler pseudos to introduce constants of various size. */
+
+#undef ASM_BYTE_OP
+#define ASM_BYTE_OP "\tdc.b"
+#undef ASM_LONG
+#define ASM_LONG "\tdc.l"
+
+/*
+ * we don't seem to support any of:
+ * .globl
+ * .even
+ * .align
+ * .ascii
+ */
+#undef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\tdcb.b %u,0\n", (SIZE))
+
+#undef GLOBAL_ASM_OP
+#define GLOBAL_ASM_OP "\txdef"
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) >= 1) \
+ fprintf (FILE, "\tds.w 0\n");
+
+
+#define STRING_LIMIT (0)
+#undef ASM_APP_ON
+#define ASM_APP_ON ""
+#undef ASM_APP_OFF
+#define ASM_APP_OFF ""
+/*
+ * dc.b 'hello, world!'
+ * dc.b 10,0
+ * is how we have to output "hello, world!\n"
+ */
+#undef ASM_OUTPUT_ASCII
+#define ASM_OUTPUT_ASCII(asm_out_file, p, thissize) \
+ do { register int i, c, f=0, len=0; \
+ for (i = 0; i < thissize; i++) { \
+ c = p[i]; \
+ if (c == '\'' || c < ' ' || c > 127) { \
+ switch(f) { \
+ case 0: /* need to output dc.b etc */ \
+ fprintf(asm_out_file, "\tdc.b %d", c); \
+ f=1; \
+ break; \
+ case 1: \
+ fprintf(asm_out_file, ",%d", c); \
+ break; \
+ default: \
+ /* close a string */ \
+ fprintf(asm_out_file, "'\n\tdc.b %d", c); \
+ f=1; \
+ break; \
+ } \
+ } else { \
+ switch(f) { \
+ case 0: \
+ fprintf(asm_out_file, "\tdc.b '%c", c); \
+ f=2; \
+ break; \
+ case 2: \
+ if (len >= 79) { \
+ fprintf(asm_out_file, "'\n\tdc.b '%c", c); \
+ len = 0; } \
+ else \
+ fprintf(asm_out_file, "%c", c); \
+ break; \
+ default: \
+ len = 0; \
+ fprintf(asm_out_file, "\n\tdc.b '%c", c); \
+ f=2; \
+ break; \
+ } \
+ } \
+ len++; \
+ } \
+ if (f==2) \
+ putc('\'', asm_out_file); \
+ putc('\n', asm_out_file); } while (0)
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#undef ASM_OUTPUT_REG_PUSH
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tmove.l %s,-(sp)\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#undef ASM_OUTPUT_REG_POP
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tmove.l (sp)+,%s\n", reg_names[REGNO])
+
+
+#define PUT_SDB_FUNCTION_START(LINE) \
+ fprintf (asm_out_file, \
+ "\t.def\t.bf%s\t.val\t*%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
+ SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
+
+#define PUT_SDB_FUNCTION_END(LINE) \
+ fprintf (asm_out_file, \
+ "\t.def\t.ef%s\t.val\t*%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
+ SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
+
+#define PUT_SDB_BLOCK_START(LINE) \
+ fprintf (asm_out_file, \
+ "\t.def\t.bb%s\t.val\t*%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \
+ SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
+
+#define PUT_SDB_BLOCK_END(LINE) \
+ fprintf (asm_out_file, \
+ "\t.def\t.eb%s\t.val\t*%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \
+ SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
+
+#define PUT_SDB_EPILOGUE_END(NAME)
+
+/* Output type in decimal not in octal as done in sdbout.c */
+#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\t.type\t0%d%s", a, SDB_DELIM)
+
+#undef FUNCTION_PROLOGUE
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ \
+ register int regno; \
+ register int mask = 0; \
+ int num_saved_regs = 0, first = 1; \
+ extern char call_used_regs[]; \
+ int fsize = ((SIZE) + 3) & -4; \
+ \
+ \
+ if (frame_pointer_needed) \
+ { \
+ /* Adding negative number is faster on the 68040. */ \
+ if (fsize < 0x8000 && !TARGET_68040) \
+ { \
+ fprintf (FILE, "\tlink %s,#%d\n", \
+ reg_names[FRAME_POINTER_REGNUM], -fsize); \
+ } \
+ else if (TARGET_68020) \
+ { \
+ fprintf (FILE, "\tlink %s,#%d\n", \
+ reg_names[FRAME_POINTER_REGNUM], -fsize); \
+ } \
+ else \
+ { \
+ fprintf (FILE, "\tlink %s,#0\n\tadd.l #%d,sp\n", \
+ reg_names[FRAME_POINTER_REGNUM], -fsize); \
+ } \
+ } \
+ else if (fsize) \
+ { \
+ /* Adding negative number is faster on the 68040. */ \
+ if (fsize + 4 < 0x8000) \
+ { \
+ fprintf (FILE, "\tadd.w #%d,sp\n", - (fsize + 4)); \
+ } \
+ else \
+ { \
+ fprintf (FILE, "\tadd.l #%d,sp\n", - (fsize + 4)); \
+ } \
+ } \
+ for (regno = 23; regno >= 16; regno--) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ if (first) { \
+ fprintf (FILE, "\tfmovem.x %s", reg_names[regno]); \
+ first = 0; \
+ } \
+ else fprintf (FILE, "/%s", reg_names[regno]); \
+ if (!first) fprintf (FILE, ",-(sp)\n"); \
+ \
+ mask = 0; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ { \
+ mask |= 1 << (15 - regno); \
+ num_saved_regs++; \
+ } \
+ if (frame_pointer_needed) \
+ { \
+ mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM)); \
+ num_saved_regs--; \
+ } \
+ \
+ \
+ if (num_saved_regs <= 2) \
+ { \
+ /* Store each separately in the same order moveml uses. \
+ Using two movel instructions instead of a single moveml \
+ is about 15% faster for the 68020 and 68030 at no expense \
+ in code size */ \
+ \
+ int i; \
+ \
+ /* Undo the work from above. */ \
+ for (i = 0; i< 16; i++) \
+ if (mask & (1 << i)) \
+ fprintf (FILE, "\tmove.l %s,-(sp)\n", reg_names[15 - i]); \
+ } \
+ else if (mask) \
+ { \
+ first = 1; \
+ for (regno = 0; regno < 16; regno++) \
+ if (mask & (1 << regno)) \
+ if (first) { \
+ fprintf (FILE, "\tmovem.l %s", reg_names[15 - regno]); \
+ first = 0; \
+ } \
+ else fprintf (FILE, "/%s", reg_names[15 - regno]); \
+ fprintf (FILE, ",-(sp)\n"); \
+ } \
+ if (flag_pic && current_function_uses_pic_offset_table) \
+ { \
+ fprintf (FILE, "\tmove.l #__GLOBAL_OFFSET_TABLE_, %s\n", \
+ reg_names[PIC_OFFSET_TABLE_REGNUM]); \
+ fprintf (FILE, "\tlea.l (pc,%s.l),%s\n", \
+ reg_names[PIC_OFFSET_TABLE_REGNUM], \
+ reg_names[PIC_OFFSET_TABLE_REGNUM]); \
+ } \
+}
+
+
+#undef FUNCTION_EPILOGUE
+#define FUNCTION_EPILOGUE(FILE, SIZE) \
+{ \
+ register int regno; \
+ register int mask, fmask; \
+ register int nregs; \
+ int offset, foffset, fpoffset, first = 1; \
+ extern char call_used_regs[]; \
+ int fsize = ((SIZE) + 3) & -4; \
+ int big = 0; \
+ rtx insn = get_last_insn (); \
+ \
+ /* If the last insn was a BARRIER, we don't have to write any code. */ \
+ if (GET_CODE (insn) == NOTE) \
+ insn = prev_nonnote_insn (insn); \
+ if (insn && GET_CODE (insn) == BARRIER) \
+ { \
+ /* Output just a no-op so that debuggers don't get confused \
+ about which function the pc is in at this address. */ \
+ fprintf (FILE, "\tnop\n"); \
+ return; \
+ } \
+ \
+ nregs = 0; fmask = 0; fpoffset = 0; \
+ for (regno = 16; regno < 24; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ { \
+ nregs++; \
+ fmask |= 1 << (23 - regno); \
+ } \
+ foffset = fpoffset + nregs * 12; \
+ nregs = 0; mask = 0; \
+ if (frame_pointer_needed) \
+ regs_ever_live[FRAME_POINTER_REGNUM] = 0; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ { \
+ nregs++; \
+ mask |= 1 << regno; \
+ } \
+ offset = foffset + nregs * 4; \
+ if (offset + fsize >= 0x8000 \
+ && frame_pointer_needed \
+ && (mask || fmask || fpoffset)) \
+ { \
+ fprintf (FILE, "\tmove.l #%d,a0\n", -fsize); \
+ fsize = 0, big = 1; \
+ } \
+ if (nregs <= 2) \
+ { \
+ /* Restore each separately in the same order moveml does. \
+ Using two movel instructions instead of a single moveml \
+ is about 15% faster for the 68020 and 68030 at no expense \
+ in code size. */ \
+ \
+ int i; \
+ \
+ /* Undo the work from above. */ \
+ for (i = 0; i< 16; i++) \
+ if (mask & (1 << i)) \
+ { \
+ if (big) \
+ { \
+ fprintf (FILE, "\tmove.l -%d(%s,a0.l),%s\n", \
+ offset + fsize, \
+ reg_names[FRAME_POINTER_REGNUM], \
+ reg_names[i]); \
+ } \
+ else if (! frame_pointer_needed) \
+ { \
+ fprintf (FILE, "\tmove.l (sp)+,%s\n", \
+ reg_names[i]); \
+ } \
+ else \
+ { \
+ fprintf (FILE, "\tmove.l -%d(%s),%s\n", \
+ offset + fsize, \
+ reg_names[FRAME_POINTER_REGNUM], \
+ reg_names[i]); \
+ } \
+ offset = offset - 4; \
+ } \
+ } \
+ else if (mask) \
+ { \
+ first = 1; \
+ for (regno = 0; regno < 16; regno++) \
+ if (mask & (1 << regno)) \
+ if (first && big) { \
+ fprintf (FILE, "\tmovem.l -%d(%s,a0.l),%s", \
+ offset + fsize, \
+ reg_names[FRAME_POINTER_REGNUM], \
+ reg_names[regno]); \
+ first = 0; \
+ } \
+ else if (first && ! frame_pointer_needed) { \
+ fprintf (FILE, "\tmovem.l (sp)+,%s", \
+ offset + fsize, \
+ reg_names[FRAME_POINTER_REGNUM], \
+ reg_names[regno]); \
+ first = 0; \
+ } \
+ else if (first) { \
+ fprintf (FILE, "\tmovem.l -%d(%s),%s", \
+ offset + fsize, \
+ reg_names[FRAME_POINTER_REGNUM], \
+ reg_names[regno]); \
+ first = 0; \
+ } \
+ else \
+ fprintf (FILE, "/%s", reg_names[regno]); \
+ fprintf (FILE, "\n"); \
+ } \
+ if (fmask) \
+ { \
+ first = 1; \
+ for (regno = 16; regno < 24; regno++) \
+ if (fmask & (1 << (23 - regno))) \
+ if (first && big) { \
+ fprintf (FILE, "\tfmovem.x -%d(%s,a0.l),%s", \
+ foffset + fsize, \
+ reg_names[FRAME_POINTER_REGNUM], \
+ reg_names[regno]); \
+ first = 0; \
+ } \
+ else if (first && ! frame_pointer_needed) { \
+ fprintf (FILE, "\tfmovem.x (sp)+,%s", \
+ foffset + fsize, \
+ reg_names[FRAME_POINTER_REGNUM], \
+ reg_names[regno]); \
+ first = 0; \
+ } \
+ else if (first) { \
+ fprintf (FILE, "\tfmovem.x -%d(%s),%s", \
+ foffset + fsize, \
+ reg_names[FRAME_POINTER_REGNUM], \
+ reg_names[regno]); \
+ first = 0; \
+ } \
+ else fprintf (FILE, "/%s", reg_names[regno]); \
+ fprintf (FILE, "\n"); \
+ } \
+ if (frame_pointer_needed) \
+ fprintf (FILE, "\tunlk %s\n", \
+ reg_names[FRAME_POINTER_REGNUM]); \
+ else if (fsize) \
+ { \
+ if (fsize + 4 < 0x8000) \
+ { \
+ fprintf (FILE, "\tadd.w #%d,sp\n", fsize + 4); \
+ } \
+ else \
+ { \
+ fprintf (FILE, "\tadd.l #%d,sp\n", fsize + 4); \
+ } \
+ } \
+ if (current_function_pops_args) \
+ fprintf (FILE, "\trtd #%d\n", current_function_pops_args); \
+ else \
+ fprintf (FILE, "\trts\n"); \
+}
+
+/* Translate Motorola opcodes such as `jbeq'
+ into VERSAdos opcodes such as `beq'.
+ Change `fbeq' to `fbseq', `fbne' to `fbsneq'.
+*/
+
+#undef ASM_OUTPUT_OPCODE
+#define ASM_OUTPUT_OPCODE(FILE, PTR) \
+{ if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
+ { ++(PTR); \
+ while (*(PTR) != ' ') \
+ { putc (*(PTR), (FILE)); ++(PTR); } \
+ } \
+ else if ((PTR)[0] == 'f') \
+ { \
+ if (!strncmp ((PTR), "fbeq", 4)) \
+ { fprintf ((FILE), "fbseq"); (PTR) += 4; } \
+ else if (!strncmp ((PTR), "fbne", 4)) \
+ { fprintf ((FILE), "fbsneq"); (PTR) += 4; } \
+ } \
+ else if ((PTR)[0] == 'b' && (PTR)[1] == 'f') \
+ { \
+ char *s; \
+ if ((s = (char*)strchr ((PTR), '{'))) \
+ while (*s != '}') { \
+ if (*s == 'b') \
+ /* hack, I replace it with R ie nothing */ \
+ *s = '0'; \
+ s++; } \
+ } \
+}
+
+/* This is how to output a `long double' extended real constant. */
+#undef ASM_OUTPUT_LONG_DOUBLE
+#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, "\tdc.l $%x,$%x,$%x\n", l[0], l[1], l[2]); \
+ else \
+ fprintf (FILE, "\tdc.l $%lx,$%lx,$%lx\n", l[0], l[1], l[2]); \
+ } while (0)
+
+#undef ASM_OUTPUT_DOUBLE
+#if 0
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
+ fprintf (FILE, "\tdc.d %s\n", dstr); \
+ } while (0)
+#endif
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+do { long l[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
+ fprintf (FILE, "\tdc.l $%x,$%x\n", l[0], l[1]); \
+ } while (0)
+
+
+/* This is how to output an assembler line defining a `float' constant. */
+#undef ASM_OUTPUT_FLOAT
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+do { long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
+ if (sizeof (int) == sizeof (long)) \
+ fprintf (FILE, "\tdc.l $%x\n", l); \
+ else \
+ fprintf (FILE, "\tdc.l $%lx\n", l); \
+ } while (0)
+
+/* This is how to output an assembler line defining an `int' constant. */
+#undef ASM_OUTPUT_INT
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\tdc.l "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+#undef ASM_OUTPUT_SHORT
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\tdc.w "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#undef ASM_OUTPUT_CHAR
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\tdc.b "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+#undef ASM_OUTPUT_BYTE
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\tdc.b $%x\n", (VALUE))
+
+/* This is how to output an element of a case-vector that is absolute.
+ (The 68000 does not use such vectors,
+ but we must define this macro anyway.) */
+#undef ASM_OUTPUT_ADDR_VEC_ELT
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ asm_fprintf (FILE, "\tdc.l %LL%d\n", VALUE)
+
+/* This is how to output an element of a case-vector that is relative. */
+#undef ASM_OUTPUT_ADDR_DIFF_ELT
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
+ asm_fprintf (FILE, "\tdc.w %LL%d-%LL%d\n", VALUE, REL)
+
+/* Currently, JUMP_TABLES_IN_TEXT_SECTION must be defined in order to
+ keep switch tables in the text section. */
+#define JUMP_TABLES_IN_TEXT_SECTION 1
+
+/* Output a float value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#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), "%I%s", dstr); \
+ } \
+ else \
+ { \
+ long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
+ if (sizeof (int) == sizeof (long)) \
+ asm_fprintf ((FILE), "%I$%x", l); \
+ else \
+ asm_fprintf ((FILE), "%I$%lx", l); \
+ } \
+ } while (0)
+
+/* Output a double value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
+ asm_fprintf (FILE, "%I%s", dstr); \
+ } while (0)
+
+/* Note, long double immediate operands are not actually
+ generated by m68k.md. */
+#undef ASM_OUTPUT_LONG_DOUBLE_OPERAND
+#define ASM_OUTPUT_LONG_DOUBLE_OPERAND(FILE,VALUE) \
+ do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
+ asm_fprintf (FILE, "%I%s", dstr); \
+ } while (0)
+
+#undef ASM_OUTPUT_COMMON
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\t.comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+#undef ASM_OUTPUT_LOCAL
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+ do { \
+ int align = exact_log2 (ROUNDED); \
+ /*fprintf ((FILE), "\tsection 14\n"); */ \
+ data_section (); \
+ ASM_OUTPUT_ALIGN ((FILE), align) \
+ ASM_OUTPUT_LABEL ((FILE), (NAME)); \
+ fprintf ((FILE), "\tdcb.b %u,0\n", (ROUNDED)); \
+ /* fprintf ((FILE), "\tsection 10\n"); */ \
+ } while (0)
+
+#undef PRINT_OPERAND_ADDRESS
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx reg1, reg2, breg, ireg; \
+ register rtx addr = ADDR; \
+ rtx offset; \
+ switch (GET_CODE (addr)) \
+ { \
+ case REG: \
+ fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
+ break; \
+ case PRE_DEC: \
+ fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case POST_INC: \
+ fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case PLUS: \
+ reg1 = 0; reg2 = 0; \
+ ireg = 0; breg = 0; \
+ offset = 0; \
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
+ { \
+ offset = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
+ { \
+ offset = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) != PLUS) ; \
+ else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
+ || GET_CODE (addr) == SIGN_EXTEND) \
+ { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
+/* for OLD_INDEXING \
+ else if (GET_CODE (addr) == PLUS) \
+ { \
+ if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg2 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg2 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ } \
+ */ \
+ if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
+ if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
+ || GET_CODE (reg1) == MULT)) \
+ || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
+ { breg = reg2; ireg = reg1; } \
+ else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
+ { breg = reg1; ireg = reg2; } \
+ if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { int scale = 1; \
+ if (GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "(.L%d,pc,%s.w", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (XEXP (ireg, 0))]); \
+ else \
+ fprintf (FILE, "(.L%d,pc,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; } \
+ if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF \
+ && ! (flag_pic && breg == pic_offset_table_rtx)) \
+ { \
+ fprintf (FILE, "(.L%d,pc,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (breg)]); \
+ putc (')', FILE); \
+ break; } \
+ if (ireg != 0 || breg != 0) \
+ { int scale = 1; \
+ if (breg == 0) \
+ abort (); \
+ putc ('(', FILE); \
+ if (addr != 0) \
+ { \
+ output_addr_const (FILE, addr); \
+ putc (',', FILE); \
+ } \
+ fprintf (FILE, "%s", reg_names[REGNO (breg)]); \
+ if (ireg != 0) \
+ putc (',', FILE); \
+ if (ireg != 0 && GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
+ else if (ireg != 0) \
+ fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; \
+ } \
+ else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "(.L%d,pc,%s.w)", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (reg1)]); \
+ break; } \
+ default: \
+ if (GET_CODE (addr) == CONST_INT \
+ && INTVAL (addr) < 0x8000 \
+ && INTVAL (addr) >= -0x8000) \
+ fprintf (FILE, "%d.w", INTVAL (addr)); \
+ else \
+ output_addr_const (FILE, addr); \
+ }}
+
+
+#endif /* ! use gas */
diff --git a/gcc/config/m68k/dpx2.ifile b/gcc/config/m68k/dpx2.ifile
new file mode 100755
index 0000000..2c8acd8
--- /dev/null
+++ b/gcc/config/m68k/dpx2.ifile
@@ -0,0 +1,55 @@
+/*
+ * dpx2.ifile - for collectless G++ on Bull DPX/2
+ *
+ * Peter Schauer <Peter.Schauer@regent.e-technik.tu-muenchen.dbp.de>
+ *
+ * Install this file as $prefix/gcc-lib/dpx2/VERSION/gcc.ifile
+ * and comment out the lines referring to COLLECT at the top
+ * of Makefile before building GCC.
+ *
+ * This file has been tested with gcc-2.2.2 on a DPX/2 340
+ * running BOS 2.00.45, if it doesn't work for you, stick
+ * with collect.
+ * --sjg
+ */
+/*
+ * Ifile to link with memory configured at 0.
+ * BLOCK to an offset that leaves room for many headers ( the value
+ * here allows for a file header, an outheader, and up to 11 section
+ * headers on most systems.
+ * BIND to an address that excludes page 0 from being mapped. The value
+ * used for BLOCK should be or'd into this value. Here I'm setting BLOCK
+ * to 0x200 and BIND to ( 0x100000 | value_used_for(BLOCK) )
+ * If you are using shared libraries, watch that you don't overlap the
+ * address ranges assigned for shared libs.
+ *
+ * GROUP BIND to a location in the next segment. Here, the only value
+ * that you should change (I think) is that within NEXT, which I've set
+ * to my hardware segment size. You can always use a larger size, but not
+ * a smaller one.
+ */
+SECTIONS
+{
+ .text BIND(0x100200) BLOCK (0x200) :
+ {
+ /* plenty of room for headers */
+ *(.init)
+ *(.text)
+ _vfork = _fork; /* I got tired of editing peoples sloppy code */
+ *(.fini)
+ }
+ GROUP BIND( NEXT(0x100000) + (ADDR(.text) + (SIZEOF(.text)) % 0x1000)):
+ {
+ .data : {
+ ___CTOR_LIST__ = . ;
+ . += 4 ; /* leading NULL */
+ *(.ctor)
+ . += 4 ; /* trailing NULL */
+ ___DTOR_LIST__ = . ;
+ . += 4 ; /* leading NULL */
+ *(.dtor)
+ . += 4 ; /* trailing NULL */
+ }
+ .bss : { }
+ }
+}
diff --git a/gcc/config/m68k/dpx2cdbx.h b/gcc/config/m68k/dpx2cdbx.h
new file mode 100755
index 0000000..88a180e
--- /dev/null
+++ b/gcc/config/m68k/dpx2cdbx.h
@@ -0,0 +1,31 @@
+/* Definitions for Bull dpx/2 200 and 300 with gas
+ using dbx-in-coff encapsulation.
+ Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+#include "m68k/dpx2g.h"
+
+/* Use STABS debugging information inside COFF. */
+#ifndef DBX_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO
+#endif
+
+/* Let sbd debugging be the default. */
+#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG
diff --git a/gcc/config/m68k/dpx2g.h b/gcc/config/m68k/dpx2g.h
new file mode 100755
index 0000000..ea5cd13
--- /dev/null
+++ b/gcc/config/m68k/dpx2g.h
@@ -0,0 +1,71 @@
+/*
+ * dpx2g.h - Bull DPX/2 200 and 300 systems (m68k, SysVr3) with gas
+ */
+
+#define USE_GAS
+#include "m68k/dpx2.h"
+
+#if 0 /* #ifndef USE_COLLECT2 */
+
+/* We use set vectors for the constructors/destructors. */
+
+#undef ASM_OUTPUT_CONSTRUCTOR
+#undef ASM_OUTPUT_DESTRUCTOR
+
+/* Although the gas we use can create .ctor and .dtor sections from N_SETT
+ stabs, it does not support section directives, so we need to have the loader
+ define the lists.
+ */
+#define CTOR_LISTS_DEFINED_EXTERNALLY
+
+/* similar to default, but allows for the table defined by ld with gcc.ifile.
+ nptrs is always 0. So we need to instead check that __DTOR_LIST__[1] != 0.
+ The old check is left in so that the same macro can be used if and when
+ a future version of gas does support section directives. */
+
+#define DO_GLOBAL_DTORS_BODY {int nptrs = *(int *)__DTOR_LIST__; int i; \
+ if (nptrs == -1 || (__DTOR_LIST__[0] == 0 && __DTOR_LIST__[1] != 0)) \
+ for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++); \
+ for (i = nptrs; i >= 1; i--) \
+ __DTOR_LIST__[i] (); }
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{!r:gcc.ifile%s}\
+ %{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}\
+ huge.o%s"
+
+#endif /* !USE_COLLECT2 */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}\
+ huge.o%s"
+
+
+/*
+ * we are using GAS
+ */
+#undef EXTRA_SECTION_FUNCTIONS
+#undef EXTRA_SECTIONS
+/* Gas understands dollars in labels. */
+#undef NO_DOLLAR_IN_LABEL
+/* GAS does not understand .ident so don't output anything for #ident. */
+#undef ASM_OUTPUT_IDENT
+
+#undef ASM_LONG
+#define ASM_LONG "\t.long"
+
+/*
+ * put const's in the text section
+ */
+#define const_section() text_section()
+#define fini_section() while (0)
+
+#undef CTORS_SECTION_ASM_OP
+#define CTORS_SECTION_ASM_OP "\t.data"
+#undef DTORS_SECTION_ASM_OP
+#define DTORS_SECTION_ASM_OP "\t.data"
+#undef INIT_SECTION_ASM_OP
+
+/* end of dpx2g.h */
diff --git a/gcc/config/m68k/fpgnulib.c b/gcc/config/m68k/fpgnulib.c
new file mode 100755
index 0000000..0559b62
--- /dev/null
+++ b/gcc/config/m68k/fpgnulib.c
@@ -0,0 +1,442 @@
+/* This is a stripped down version of floatlib.c. It supplies only those
+ functions which exist in libgcc, but for which there is not assembly
+ language versions in m68k/lb1sf68.asm.
+
+ It also includes simplistic support for extended floats (by working in
+ double precision). You must compile this file again with -DEXTFLOAT
+ to get this support. */
+
+/*
+** gnulib support for software floating point.
+** Copyright (C) 1991 by Pipeline Associates, Inc. All rights reserved.
+** Permission is granted to do *anything* you want with this file,
+** commercial or otherwise, provided this message remains intact. So there!
+** I would appreciate receiving any updates/patches/changes that anyone
+** makes, and am willing to be the repository for said changes (am I
+** making a big mistake?).
+**
+** Pat Wood
+** Pipeline Associates, Inc.
+** pipeline!phw@motown.com or
+** sun!pipeline!phw or
+** uunet!motown!pipeline!phw
+**
+** 05/01/91 -- V1.0 -- first release to gcc mailing lists
+** 05/04/91 -- V1.1 -- added float and double prototypes and return values
+** -- fixed problems with adding and subtracting zero
+** -- fixed rounding in truncdfsf2
+** -- fixed SWAP define and tested on 386
+*/
+
+/*
+** The following are routines that replace the gnulib soft floating point
+** routines that are called automatically when -msoft-float is selected.
+** The support single and double precision IEEE format, with provisions
+** for byte-swapped machines (tested on 386). Some of the double-precision
+** routines work at full precision, but most of the hard ones simply punt
+** and call the single precision routines, producing a loss of accuracy.
+** long long support is not assumed or included.
+** Overall accuracy is close to IEEE (actually 68882) for single-precision
+** arithmetic. I think there may still be a 1 in 1000 chance of a bit
+** being rounded the wrong way during a multiply. I'm not fussy enough to
+** bother with it, but if anyone is, knock yourself out.
+**
+** Efficiency has only been addressed where it was obvious that something
+** would make a big difference. Anyone who wants to do this right for
+** best speed should go in and rewrite in assembler.
+**
+** I have tested this only on a 68030 workstation and 386/ix integrated
+** in with -msoft-float.
+*/
+
+/* the following deal with IEEE single-precision numbers */
+#define EXCESS 126L
+#define SIGNBIT 0x80000000L
+#define HIDDEN (1L << 23L)
+#define SIGN(fp) ((fp) & SIGNBIT)
+#define EXP(fp) (((fp) >> 23L) & 0xFF)
+#define MANT(fp) (((fp) & 0x7FFFFFL) | HIDDEN)
+#define PACK(s,e,m) ((s) | ((e) << 23L) | (m))
+
+/* the following deal with IEEE double-precision numbers */
+#define EXCESSD 1022
+#define HIDDEND (1L << 20L)
+#define EXPDBITS 11
+#define EXPDMASK 0x7FF
+#define EXPD(fp) (((fp.l.upper) >> 20L) & 0x7FFL)
+#define SIGND(fp) ((fp.l.upper) & SIGNBIT)
+#define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \
+ (fp.l.lower >> 22))
+#define MANTDMASK 0xFFFFF /* mask of upper part */
+
+/* the following deal with IEEE extended-precision numbers */
+#define EXCESSX 16382
+#define HIDDENX (1L << 31L)
+#define EXPXBITS 15
+#define EXPXMASK 0x7FFF
+#define EXPX(fp) (((fp.l.upper) >> 16) & EXPXMASK)
+#define SIGNX(fp) ((fp.l.upper) & SIGNBIT)
+#define MANTXMASK 0x7FFFFFFF /* mask of upper part */
+
+union double_long
+{
+ double d;
+ struct {
+ long upper;
+ unsigned long lower;
+ } l;
+};
+
+union float_long {
+ float f;
+ long l;
+};
+
+union long_double_long
+{
+ long double ld;
+ struct
+ {
+ long upper;
+ unsigned long middle;
+ unsigned long lower;
+ } l;
+};
+
+#ifndef EXTFLOAT
+
+/* convert int to double */
+double
+__floatsidf (int a1)
+{
+ long sign = 0, exp = 31 + EXCESSD;
+ union double_long dl;
+
+ if (!a1)
+ {
+ dl.l.upper = dl.l.lower = 0;
+ return dl.d;
+ }
+
+ if (a1 < 0)
+ {
+ sign = SIGNBIT;
+ a1 = -a1;
+ if (a1 < 0)
+ {
+ dl.l.upper = SIGNBIT | ((32 + EXCESSD) << 20L);
+ dl.l.lower = 0;
+ return dl.d;
+ }
+ }
+
+ while (a1 < 0x1000000)
+ {
+ a1 <<= 4;
+ exp -= 4;
+ }
+
+ while (a1 < 0x40000000)
+ {
+ a1 <<= 1;
+ exp--;
+ }
+
+ /* pack up and go home */
+ dl.l.upper = sign;
+ dl.l.upper |= exp << 20L;
+ dl.l.upper |= (a1 >> 10L) & ~HIDDEND;
+ dl.l.lower = a1 << 22L;
+
+ return dl.d;
+}
+
+/* convert int to float */
+float
+__floatsisf (int l)
+{
+ double foo = __floatsidf (l);
+ return foo;
+}
+
+/* convert float to double */
+double
+__extendsfdf2 (float a1)
+{
+ register union float_long fl1;
+ register union double_long dl;
+ register long exp;
+
+ fl1.f = a1;
+
+ if (!fl1.l)
+ {
+ dl.l.upper = dl.l.lower = 0;
+ return dl.d;
+ }
+
+ dl.l.upper = SIGN (fl1.l);
+ exp = EXP (fl1.l) - EXCESS + EXCESSD;
+ dl.l.upper |= exp << 20;
+ dl.l.upper |= (MANT (fl1.l) & ~HIDDEN) >> 3;
+ dl.l.lower = MANT (fl1.l) << 29;
+
+ return dl.d;
+}
+
+/* convert double to float */
+float
+__truncdfsf2 (double a1)
+{
+ register long exp;
+ register long mant;
+ register union float_long fl;
+ register union double_long dl1;
+
+ dl1.d = a1;
+
+ if (!dl1.l.upper && !dl1.l.lower)
+ return 0;
+
+ exp = EXPD (dl1) - EXCESSD + EXCESS;
+
+ /* shift double mantissa 6 bits so we can round */
+ mant = MANTD (dl1) >> 6;
+
+ /* now round and shift down */
+ mant += 1;
+ mant >>= 1;
+
+ /* did the round overflow? */
+ if (mant & 0xFF000000)
+ {
+ mant >>= 1;
+ exp++;
+ }
+
+ mant &= ~HIDDEN;
+
+ /* pack up and go home */
+ fl.l = PACK (SIGND (dl1), exp, mant);
+ return (fl.f);
+}
+
+/* convert double to int */
+int
+__fixdfsi (double a1)
+{
+ register union double_long dl1;
+ register long exp;
+ register long l;
+
+ dl1.d = a1;
+
+ if (!dl1.l.upper && !dl1.l.lower)
+ return 0;
+
+ exp = EXPD (dl1) - EXCESSD - 31;
+ l = MANTD (dl1);
+
+ if (exp > 0)
+ {
+ /* Return largest integer. */
+ return SIGND (dl1) ? 0x80000000 : 0x7fffffff;
+ }
+
+ if (exp <= -32)
+ return 0;
+
+ /* shift down until exp = 0 */
+ if (exp < 0)
+ l >>= -exp;
+
+ return (SIGND (dl1) ? -l : l);
+}
+
+/* convert float to int */
+int
+__fixsfsi (float a1)
+{
+ double foo = a1;
+ return __fixdfsi (foo);
+}
+
+#else /* EXTFLOAT */
+
+/* Primitive extended precision floating point support.
+
+ We assume all numbers are normalized, don't do any rounding, etc. */
+
+/* Prototypes for the above in case we use them. */
+double __floatsidf (int);
+float __floatsisf (int);
+double __extendsfdf2 (float);
+float __truncdfsf2 (double);
+int __fixdfsi (double);
+int __fixsfsi (float);
+
+/* convert double to long double */
+long double
+__extenddfxf2 (double d)
+{
+ register union double_long dl;
+ register union long_double_long ldl;
+ register long exp;
+
+ dl.d = d;
+ /*printf ("dfxf in: %g\n", d);*/
+
+ if (!dl.l.upper && !dl.l.lower)
+ return 0;
+
+ ldl.l.upper = SIGND (dl);
+ exp = EXPD (dl) - EXCESSD + EXCESSX;
+ ldl.l.upper |= exp << 16;
+ ldl.l.middle = HIDDENX;
+ /* 31-20: # mantissa bits in ldl.l.middle - # mantissa bits in dl.l.upper */
+ ldl.l.middle |= (dl.l.upper & MANTDMASK) << (31 - 20);
+ /* 1+20: explicit-integer-bit + # mantissa bits in dl.l.upper */
+ ldl.l.middle |= dl.l.lower >> (1 + 20);
+ /* 32 - 21: # bits of dl.l.lower in ldl.l.middle */
+ ldl.l.lower = dl.l.lower << (32 - 21);
+
+ /*printf ("dfxf out: %s\n", dumpxf (ldl.ld));*/
+ return ldl.ld;
+}
+
+/* convert long double to double */
+double
+__truncxfdf2 (long double ld)
+{
+ register long exp;
+ register union double_long dl;
+ register union long_double_long ldl;
+
+ ldl.ld = ld;
+ /*printf ("xfdf in: %s\n", dumpxf (ld));*/
+
+ if (!ldl.l.upper && !ldl.l.middle && !ldl.l.lower)
+ return 0;
+
+ exp = EXPX (ldl) - EXCESSX + EXCESSD;
+ /* ??? quick and dirty: keep `exp' sane */
+ if (exp >= EXPDMASK)
+ exp = EXPDMASK - 1;
+ dl.l.upper = SIGNX (ldl);
+ dl.l.upper |= exp << (32 - (EXPDBITS + 1));
+ /* +1-1: add one for sign bit, but take one off for explicit-integer-bit */
+ dl.l.upper |= (ldl.l.middle & MANTXMASK) >> (EXPDBITS + 1 - 1);
+ dl.l.lower = (ldl.l.middle & MANTXMASK) << (32 - (EXPDBITS + 1 - 1));
+ dl.l.lower |= ldl.l.lower >> (EXPDBITS + 1 - 1);
+
+ /*printf ("xfdf out: %g\n", dl.d);*/
+ return dl.d;
+}
+
+/* convert a float to a long double */
+long double
+__extendsfxf2 (float f)
+{
+ long double foo = __extenddfxf2 (__extendsfdf2 (f));
+ return foo;
+}
+
+/* convert a long double to a float */
+float
+__truncxfsf2 (long double ld)
+{
+ float foo = __truncdfsf2 (__truncxfdf2 (ld));
+ return foo;
+}
+
+/* convert an int to a long double */
+long double
+__floatsixf (int l)
+{
+ double foo = __floatsidf (l);
+ return foo;
+}
+
+/* convert a long double to an int */
+int
+__fixxfsi (long double ld)
+{
+ int foo = __fixdfsi ((double) ld);
+ return foo;
+}
+
+/* The remaining provide crude math support by working in double precision. */
+
+long double
+__addxf3 (long double x1, long double x2)
+{
+ return (double) x1 + (double) x2;
+}
+
+long double
+__subxf3 (long double x1, long double x2)
+{
+ return (double) x1 - (double) x2;
+}
+
+long double
+__mulxf3 (long double x1, long double x2)
+{
+ return (double) x1 * (double) x2;
+}
+
+long double
+__divxf3 (long double x1, long double x2)
+{
+ return (double) x1 / (double) x2;
+}
+
+long double
+__negxf2 (long double x1)
+{
+ return - (double) x1;
+}
+
+long
+__cmpxf2 (long double x1, long double x2)
+{
+ return __cmpdf2 ((double) x1, (double) x2);
+}
+
+long
+__eqxf2 (long double x1, long double x2)
+{
+ return __cmpdf2 ((double) x1, (double) x2);
+}
+
+long
+__nexf2 (long double x1, long double x2)
+{
+ return __cmpdf2 ((double) x1, (double) x2);
+}
+
+long
+__ltxf2 (long double x1, long double x2)
+{
+ return __cmpdf2 ((double) x1, (double) x2);
+}
+
+long
+__lexf2 (long double x1, long double x2)
+{
+ return __cmpdf2 ((double) x1, (double) x2);
+}
+
+long
+__gtxf2 (long double x1, long double x2)
+{
+ return __cmpdf2 ((double) x1, (double) x2);
+}
+
+long
+__gexf2 (long double x1, long double x2)
+{
+ return __cmpdf2 ((double) x1, (double) x2);
+}
+
+#endif /* EXTFLOAT */
diff --git a/gcc/config/m68k/hp2bsd.h b/gcc/config/m68k/hp2bsd.h
new file mode 100755
index 0000000..9090923
--- /dev/null
+++ b/gcc/config/m68k/hp2bsd.h
@@ -0,0 +1,78 @@
+/* Definitions of target machine for GNU compiler. HP 9000/200 68000 version.
+ Copyright (C) 1987, 1991 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "m68k/m68k.h"
+
+/* See m68k.h. 0 means 68000 with no 68881. */
+
+#define TARGET_DEFAULT 0
+
+/* Don't try using XFmode. */
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+/* Define __HAVE_68881 in preprocessor only if -m68881 is specified.
+ This will control the use of inline 68881 insns in certain macros.
+ Also inform the program which CPU this is for. */
+
+#define CPP_SPEC "%{m68881:-D__HAVE_68881__} \
+%{!ansi:%{m68020:-Dmc68020}%{mc68020:-Dmc68020}%{!mc68020:%{!m68020:-Dmc68010}}}"
+
+/* -m68020 requires special flags to the assembler. */
+
+#define ASM_SPEC \
+ "%{m68020:-mc68020}%{mc68020:-mc68020}%{!mc68020:%{!m68020:-mc68010}}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dmc68000 -Dmc68010 -Dhp200 -Dunix -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
+
+/* Link with libg.a when debugging, for dbx's sake. */
+
+#define LIB_SPEC "%{g:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} "
+
+/* Alignment of field after `int : 0' in a structure. */
+
+#undef EMPTY_FIELD_BOUNDARY
+#define EMPTY_FIELD_BOUNDARY 16
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Define subroutines to call to handle multiply, divide, and remainder.
+ These routines are built into the c-library on the hp200.
+ XXX What other routines from the c-library could we use?
+ The `*' prevents an underscore from being prepended by the compiler. */
+
+#define DIVSI3_LIBCALL "*ldiv"
+#define UDIVSI3_LIBCALL "*uldiv"
+#define MODSI3_LIBCALL "*lrem"
+#define UMODSI3_LIBCALL "*ulrem"
+#define MULSI3_LIBCALL "*lmul"
+#define UMULSI3_LIBCALL "*ulmul"
+
+/* Don't default to pcc-struct-return, because gcc is the only compiler, and
+ we want to retain compatibility with older gcc versions. */
+#define DEFAULT_PCC_STRUCT_RETURN 0
diff --git a/gcc/config/m68k/hp310.h b/gcc/config/m68k/hp310.h
new file mode 100755
index 0000000..a9d24f4
--- /dev/null
+++ b/gcc/config/m68k/hp310.h
@@ -0,0 +1,36 @@
+/* Definitions of target machine for GNU compiler. HP-UX 68010 version. */
+
+/* See m68k.h. 0 means 68000 without 68881 and no bitfields. */
+#define TARGET_DEFAULT 0
+
+#include "m68k/hp320.h"
+
+/* Don't try using XFmode. */
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+#undef CPP_SPEC
+#undef ASM_SPEC
+
+/* HP does not support a 68020 without a 68881 or a 68010 with a 68881.
+ However, -m68020 does not imply -m68881. You must specify both
+ if you want both. */
+
+#ifdef HPUX_ASM
+
+#define CPP_SPEC "-D__HPUX_ASM__ %{m68881: -D__HAVE_68881__}\
+%{m68020: -Dmc68020}%{mc68020: -Dmc68020}\
+%{!traditional:-D_INCLUDE__STDC__}"
+
+#define ASM_SPEC "%{!m68020:%{!mc68020:+X}}"
+
+#else /* not HPUX_ASM */
+
+#define CPP_SPEC "%{m68881: -D__HAVE_68881__}\
+%{m68020: -Dmc68020}%{mc68020: -Dmc68020}\
+%{!traditional:-D_INCLUDE__STDC__}"
+
+#define ASM_SPEC \
+ "%{m68000:-mc68000}%{mc68000:-mc68000}%{!mc68000:%{!m68000:-mc68020}}"
+
+#endif /* not HPUX_ASM */
diff --git a/gcc/config/m68k/hp310g.h b/gcc/config/m68k/hp310g.h
new file mode 100755
index 0000000..c07a73b
--- /dev/null
+++ b/gcc/config/m68k/hp310g.h
@@ -0,0 +1,12 @@
+/* Definitions of target machine for GNU compiler. HP-UX 68010 version.
+ Use this file if GCC is supposed to work with the GNU assembler,
+ GNU linker and GNU debugger using DBX debugging information.
+ (In other words, much of HPUX has been cast aside.) */
+
+/* This wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+#define USE_GAS
+
+#include "m68k/hp310.h"
diff --git a/gcc/config/m68k/hp320.h b/gcc/config/m68k/hp320.h
new file mode 100755
index 0000000..9816502
--- /dev/null
+++ b/gcc/config/m68k/hp320.h
@@ -0,0 +1,642 @@
+/* Definitions of target machine for GNU compiler. HP-UX 68000/68020 version.
+ Copyright (C) 1987, 88, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Define USE_GAS if GCC is supposed to work with the GNU assembler,
+ GNU linker and GNU debugger using DBX debugging information.
+ (In other words, much of HPUX has been cast aside.)
+ Undefine USE_GAS if you want GCC to feed the HP assembler. */
+
+/* #define USE_GAS */ /* Use hp320g.h if you want this. */
+
+/* Control assembler-syntax conditionals in m68k.md. */
+
+#ifndef USE_GAS
+#define MOTOROLA /* Use Motorola syntax rather than "MIT" */
+#define SGS /* Uses SGS assembler */
+#define SGS_CMP_ORDER /* Takes cmp operands in reverse order */
+#define HPUX_ASM
+
+#if !defined (CROSS_COMPILE) && !defined (NO_BUGS)
+/* The assembler on HP 9k3xx machines running HPUX 8.0 doesn't translate
+ floating point constants behind some operands. The workaround is to
+ use hex constants. Reported by Thomas Nau (nau@medizin.uni-ulm.de). */
+#define AS_BUG_FLOATING_CONSTANT
+/* The assembler on HP 9k3xx machines running HPUX 8.0 doesn't accept
+ labels followed by a text, data, or other section directive. Reported
+ by Thomas Nau (nau@medizin.uni-ulm.de). */
+#define AS_BUG_TRAILING_LABEL
+#endif
+
+#endif /* not USE_GAS */
+
+/* gcc.c should find libgcc.a itself rather than expecting linker to. */
+#define LINK_LIBGCC_SPECIAL
+/* The arguments of -L must be a separate argv element. */
+#define SPACE_AFTER_L_OPTION
+/* HP/UX doesn't have libg.a. */
+#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}"
+
+/* Be compatible with system stddef.h. */
+#define SIZE_TYPE "unsigned int"
+
+/* Use atexit for static constructors/destructors, instead of defining
+ our own exit function. */
+#define HAVE_ATEXIT
+
+#include "m68k/m68k.h"
+
+/* See m68k.h. 7 means 68020 with 68881. */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
+#endif
+
+/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#ifdef HPUX_ASM
+
+#define ASM_SPEC "%{m68000:+X}%{mc68000:+X}"
+
+#define NO_DOT_IN_LABEL
+
+#if TARGET_DEFAULT & MASK_68881 /* -m68881 is the default */
+
+/* These definitions differ from those used for GAS by defining __HPUX_ASM__.
+ This is needed because some programs, particularly GDB, need to
+ know which assembler is being used so that the correct `asm'
+ instructions can be used. */
+
+#define CPP_SPEC \
+"%{!msoft-float:-D__HAVE_68881__ }\
+%{!ansi:%{!mc68000:%{!m68000:-Dmc68020}} -D_HPUX_SOURCE} -D__HPUX_ASM__"
+
+#else /* default is -msoft-float */
+
+#define CPP_SPEC \
+"%{m68881:-D__HAVE_68881__ }\
+%{!ansi:%{!mc68000:%{!m68000:-Dmc68020}} -D_HPUX_SOURCE} -D__HPUX_ASM__"
+
+#endif /* default is -msoft-float */
+
+#else /* not HPUX_ASM */
+
+#if TARGET_DEFAULT & MASK_68881 /* -m68881 is the default */
+
+#define CPP_SPEC \
+"%{!msoft-float:-D__HAVE_68881__ }\
+%{!ansi:%{!mc68000:%{!m68000:-Dmc68020}} -D_HPUX_SOURCE}"
+
+#else /* default is -msoft-float */
+
+#define CPP_SPEC \
+"%{m68881:-D__HAVE_68881__ }\
+%{!ansi:%{!mc68000:%{!m68000:-Dmc68020}} -D_HPUX_SOURCE}"
+
+#endif /* default is -msoft-float */
+
+
+/* -m68000 requires special flags to the assembler. */
+#define ASM_SPEC \
+ "%{m68000:-mc68000}%{mc68000:-mc68000}%{!mc68000:%{!m68000:-mc68020}}"
+
+/* Tell GCC to put a space after -L when generating such options. */
+#define SPACE_AFTER_L_OPTION
+
+#endif /* Not HPUX_ASM */
+
+/* Translate -static for HPUX linker. */
+#define LINK_SPEC "%{static:-a archive}"
+
+/* Names to predefine in the preprocessor for this target machine
+ (for non-strict-ANSI programs only). */
+/* These are the ones defined by HPUX cc, plus mc68000 for uniformity with
+ GCC on other 68000 systems. */
+
+#define CPP_PREDEFINES "-Dhp9000s200 -Dhp9000s300 -DPWB -Dhpux -Dunix -D__hp9000s300 -D__hp9000s200 -D__PWB -D__hpux -D__unix -D__motorola__ -Asystem(unix) -Asystem(hpux) -Acpu(m68k) -Amachine(m68k)"
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* hpux doesn't use static area for struct returns. */
+#undef PCC_STATIC_STRUCT_RETURN
+
+/* Generate calls to memcpy, memcmp and memset. */
+#define TARGET_MEM_FUNCTIONS
+
+#if 0 /* No longer correct in HPUX version 6.5. */
+/* Function calls don't save any fp registers on hpux. */
+#undef CALL_USED_REGISTERS
+#define CALL_USED_REGISTERS \
+ {1, 1, 0, 0, 0, 0, 0, 0, \
+ 1, 1, 0, 0, 0, 0, 0, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1}
+#endif /* 0 */
+
+#ifdef HPUX_ASM
+
+/* Override parts of m68k.h to fit the HPUX assembler. */
+
+#undef TARGET_VERSION
+#undef REGISTER_NAMES
+#undef ASM_OUTPUT_REG_PUSH
+#undef ASM_OUTPUT_REG_POP
+#undef ASM_FILE_START
+#undef ASM_APP_ON
+#undef ASM_APP_OFF
+#undef TEXT_SECTION_ASM_OP
+#undef DATA_SECTION_ASM_OP
+#undef READONLY_DATA_SECTION
+#undef ASM_OUTPUT_DOUBLE
+#undef ASM_OUTPUT_FLOAT
+#undef ASM_OUTPUT_INT
+#undef ASM_OUTPUT_SHORT
+#undef ASM_OUTPUT_CHAR
+#undef ASM_OUTPUT_BYTE
+#undef ASM_OUTPUT_ADDR_VEC_ELT
+#undef ASM_OUTPUT_ADDR_DIFF_ELT
+#undef ASM_OUTPUT_ALIGN
+#undef ASM_OUTPUT_SKIP
+#undef ASM_OUTPUT_COMMON
+#undef ASM_OUTPUT_LOCAL
+#undef ASM_FORMAT_PRIVATE_NAME
+#undef FUNCTION_PROFILER
+#undef ASM_OUTPUT_INTERNAL_LABEL
+#undef GLOBAL_ASM_OP
+#undef IMMEDIATE_PREFIX
+#undef REGISTER_PREFIX
+
+#define TARGET_VERSION fprintf (stderr, " (68k, SGS/hpux syntax)");
+
+#define REGISTER_NAMES \
+{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp", \
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7"}
+
+#define IMMEDIATE_PREFIX "&"
+#define REGISTER_PREFIX "%"
+
+#define FUNCTION_PROFILER(FILE, LABEL_NO) \
+ fprintf (FILE, "\tmov.l &LP%d,%%a0\n\tjsr mcount\n", (LABEL_NO));
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tmov.l %s,-(%%sp)\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tmov.l (%%sp)+,%s\n", reg_names[REGNO])
+
+/* For HPUX versions before 6.5, define this macro as empty. */
+#define ASM_FILE_START(FILE) \
+ if (TARGET_68020) \
+ { \
+ if (TARGET_68881) \
+ fprintf (FILE, "\tversion 3\n"); /* 68020 fp regs saved */ \
+ else \
+ fprintf (FILE, "\tversion 2\n"); /* 68020 no fp regs saved */ \
+ } \
+ else \
+ fprintf (FILE, "\tversion 1\n"); /* 68010 */
+
+#define ASM_APP_ON ""
+
+#define ASM_APP_OFF ""
+
+#ifdef AS_BUG_TRAILING_LABEL
+#define TEXT_SECTION_ASM_OP "\tlalign\t1\ntext"
+#define DATA_SECTION_ASM_OP "\tlalign\t1\ndata"
+#else
+#define TEXT_SECTION_ASM_OP "text"
+#define DATA_SECTION_ASM_OP "data"
+#endif
+#define ASCII_DATA_ASM_OP "byte"
+
+/* This is the command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define GLOBAL_ASM_OP "global"
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\tcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\tlcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u,2\n", (ROUNDED)))
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 12), \
+ sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO)))
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+do{ if (PREFIX[0] == 'L' && PREFIX[1] == 'I') \
+ fprintf(FILE, "\tset %s%d,.+2\n", PREFIX, NUM); \
+ else \
+ fprintf (FILE, "%s%d:\n", PREFIX, NUM); \
+} while(0)
+
+#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \
+ do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
+ fprintf (FILE, "\tdouble 0f%s\n", dstr); \
+ } while (0)
+
+#define ASM_OUTPUT_FLOAT(FILE, VALUE) \
+ do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.9g", dstr); \
+ fprintf (FILE, "\tfloat 0f%s\n", dstr); \
+ } while (0)
+
+#undef ASM_OUTPUT_LONG_DOUBLE
+#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
+do { long l[3]; \
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
+ fprintf (FILE, "\tlong 0x%x,0x%x,0x%x\n", l[0], l[1], l[2]); \
+ } while (0)
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\tlong "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\tshort "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\tbyte "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\tbyte 0x%x\n", (VALUE))
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\tlong L%d\n", VALUE)
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
+ fprintf (FILE, "\tshort L%d-L%d\n", VALUE, REL)
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) == 1) \
+ fprintf (FILE, "\tlalign 2\n"); \
+ else if ((LOG) != 0) \
+ abort ();
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\tspace %u\n", (SIZE))
+
+#define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME)
+#define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO)
+
+/* Output a float value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#ifdef AS_BUG_FLOATING_CONSTANT
+#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
+ do { long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
+ fprintf ((FILE), "&0x%lx", l); \
+ } while (0)
+#else
+#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
+ do { \
+ if (CODE == 'f') \
+ { \
+ char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.9g", dstr); \
+ fprintf ((FILE), "&0f%s", dstr); \
+ } \
+ else \
+ { \
+ long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
+ fprintf ((FILE), "&0x%lx", l); \
+ } \
+ } while (0)
+#endif /* AS_BUG_FLOATING_CONSTANT */
+
+/* Output a double value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
+ fprintf (FILE, "&0f%s", dstr); \
+ } while (0)
+
+/* Note, long double immediate operands are not actually
+ generated by m68k.md. */
+#undef ASM_OUTPUT_LONG_DOUBLE_OPERAND
+#define ASM_OUTPUT_LONG_DOUBLE_OPERAND(FILE,VALUE) \
+ do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
+ fprintf (FILE, "&0f%s", dstr); \
+ } while (0)
+
+#if 0
+#undef PRINT_OPERAND
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (CODE == '.') fprintf (FILE, "."); \
+ else if (CODE == '#') fprintf (FILE, "&"); \
+ else if (CODE == '-') fprintf (FILE, "-(%%sp)"); \
+ else if (CODE == '+') fprintf (FILE, "(%%sp)+"); \
+ else if (CODE == '@') fprintf (FILE, "(%%sp)"); \
+ else if (CODE == '!') fprintf (FILE, "%%fpcr"); \
+ else if (CODE == '$') { if (TARGET_68040_ONLY) fprintf (FILE, "s"); } \
+ else if (CODE == '&') { if (TARGET_68040_ONLY) fprintf (FILE, "d"); } \
+ else if (CODE == '/') \
+ fprintf (FILE, "%%"); \
+ else if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if (GET_CODE (X) == MEM) \
+ output_address (XEXP (X, 0)); \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
+ { REAL_VALUE_TYPE r; long l; \
+ REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
+ PRINT_OPERAND_FLOAT (CODE, FILE, r, l); } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode) \
+ { REAL_VALUE_TYPE r; char dstr[30]; \
+ REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
+ REAL_VALUE_TO_DECIMAL (r, "%.20g", dstr); \
+ fprintf (FILE, "&0f%s", dstr); } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == XFmode) \
+ { REAL_VALUE_TYPE r; char dstr[30]; \
+ REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
+ REAL_VALUE_TO_DECIMAL (r, "%.20g", dstr); \
+ fprintf (FILE, "&0f%s", dstr); } \
+ else { putc ('&', FILE); output_addr_const (FILE, X); }}
+#endif
+
+#undef PRINT_OPERAND_ADDRESS
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx reg1, reg2, breg, ireg; \
+ register rtx addr = ADDR; \
+ rtx offset; \
+ switch (GET_CODE (addr)) \
+ { \
+ case REG: \
+ fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
+ break; \
+ case PRE_DEC: \
+ fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case POST_INC: \
+ fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case PLUS: \
+ reg1 = 0; reg2 = 0; \
+ ireg = 0; breg = 0; \
+ offset = 0; \
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
+ { \
+ offset = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
+ { \
+ offset = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) != PLUS) ; \
+ else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
+ || GET_CODE (addr) == SIGN_EXTEND) \
+ { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
+/* for OLD_INDEXING \
+ else if (GET_CODE (addr) == PLUS) \
+ { \
+ if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg2 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg2 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ } \
+ */ \
+ if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
+ if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
+ || GET_CODE (reg1) == MULT)) \
+ || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
+ { breg = reg2; ireg = reg1; } \
+ else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
+ { breg = reg1; ireg = reg2; } \
+ if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { int scale = 1; \
+ if (GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "L%d-LI%d(%%pc,%s.w", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (XEXP (ireg, 0))]); \
+ else \
+ fprintf (FILE, "L%d-LI%d(%%pc,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; } \
+ if (ireg != 0 || breg != 0) \
+ { int scale = 1; \
+ if (breg == 0) \
+ abort (); \
+ if (addr != 0) \
+ output_addr_const (FILE, addr); \
+ fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \
+ if (ireg != 0) \
+ putc (',', FILE); \
+ if (ireg != 0 && GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
+ else if (ireg != 0) \
+ fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; \
+ } \
+ else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "L%d-LI%d(%%pc,%s.w)", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (reg1)]); \
+ break; } \
+ default: \
+ if (GET_CODE (addr) == CONST_INT \
+ && INTVAL (addr) < 0x8000 \
+ && INTVAL (addr) >= -0x8000) \
+ fprintf (FILE, "%d.w", INTVAL (addr)); \
+ else \
+ output_addr_const (FILE, addr); \
+ }}
+
+#define ASM_OUTPUT_ASCII(f, p, size) \
+do { register int i; \
+ int inside; \
+ inside = FALSE; \
+ for (i = 0; i < (size); i++) { \
+ if (i % 8 == 0) { \
+ if (i != 0) { \
+ if (inside) \
+ putc('"', (f)); \
+ putc('\n', (f)); \
+ inside = FALSE; \
+ } \
+ fprintf((f), "\t%s ", ASCII_DATA_ASM_OP); \
+ } \
+ if ((p)[i] < 32 || (p)[i] == '\\' || (p)[i] == '"' || (p)[i] == 127) { \
+ if (inside) { \
+ putc('"', (f)); \
+ inside = FALSE; \
+ } \
+ if (i % 8 != 0) \
+ putc(',', (f)); \
+ fprintf((f), "%d", (p)[i]); \
+ } else { \
+ if (!inside) { \
+ if (i % 8 != 0) \
+ putc(',', (f)); \
+ putc('"', (f)); \
+ inside = TRUE; \
+ } \
+ putc((p)[i], (f)); \
+ } \
+ } \
+ if (inside) \
+ putc('"', (f)); \
+ putc('\n', (f)); \
+} while (0)
+
+/* Translate Motorola opcodes such as `jbeq'
+ into SGS opcodes such as `beq.w'.
+ Delete the `e' in `move...' and `fmove'.
+ Change `ftst' to `ftest'. */
+
+#define ASM_OUTPUT_OPCODE(FILE, PTR) \
+{ if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
+ { ++(PTR); \
+ while (*(PTR) != ' ') \
+ { putc (*(PTR), (FILE)); ++(PTR); } \
+ fprintf ((FILE), ".w"); } \
+ else if ((PTR)[0] == 'f') \
+ { \
+ if (!strncmp ((PTR), "fmove", 5)) \
+ { fprintf ((FILE), "fmov"); (PTR) += 5; } \
+ else if (!strncmp ((PTR), "ftst", 4)) \
+ { fprintf ((FILE), "ftest"); (PTR) += 4; } \
+ } \
+ else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
+ { fprintf ((FILE), "mov"); (PTR) += 4; } \
+}
+
+/* Prevent output of `gcc_compiled.:'. */
+
+#define ASM_IDENTIFY_GCC(FILE)
+
+#else /* not HPUX_ASM */
+
+#undef FUNCTION_PROFILER
+
+/* HP-UX needs the call to mcount before the link instruction.
+ Copy the return address onto the stack before the call to fake it out. */
+#define FUNCTION_PROFILER(FILE, LABEL_NO) \
+ fprintf (FILE, \
+ "\tmovel a6@(4),sp@-\n\tmovl #LP%d,a0\n\tjsr mcount\n\taddqw #4,sp\n", \
+ (LABEL_NO));
+
+#endif /* not HPUX_ASM */
+
+/* In m68k svr4, a symbol_ref rtx can be a valid PIC operand if it is an
+ operand of a function call. */
+#undef LEGITIMATE_PIC_OPERAND_P
+#define LEGITIMATE_PIC_OPERAND_P(X) \
+ ((! 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)))
+
+/* hpux8 and later have C++ compatible include files, so do not
+ pretend they are `extern "C"'. */
+#define NO_IMPLICIT_EXTERN_C
diff --git a/gcc/config/m68k/hp320g.h b/gcc/config/m68k/hp320g.h
new file mode 100755
index 0000000..1e93185
--- /dev/null
+++ b/gcc/config/m68k/hp320g.h
@@ -0,0 +1,12 @@
+/* Definitions of target machine for GNU compiler. HP-UX 68000/68020 version.
+ Use this file if GCC is supposed to work with the GNU assembler,
+ GNU linker and GNU debugger using DBX debugging information.
+ (In other words, much of HPUX has been cast aside.) */
+
+/* This wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+#define USE_GAS
+
+#include "m68k/hp320.h"
diff --git a/gcc/config/m68k/hp3bsd.h b/gcc/config/m68k/hp3bsd.h
new file mode 100755
index 0000000..34405f8
--- /dev/null
+++ b/gcc/config/m68k/hp3bsd.h
@@ -0,0 +1,44 @@
+#include "m68k/m68k.h"
+
+/* See m68k.h. 7 means 68020 with 68881. */
+
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
+
+/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__ -D__HAVE_FPU__}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dmc68000 -Dmc68020 -Dhp300 -Dhp9000 -Dunix -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
+
+/* Link with libg.a when debugging, for dbx's sake. */
+
+#define LIB_SPEC "%{g:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} "
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Do not break .stabs pseudos into continuations. */
+
+#define DBX_CONTIN_LENGTH 0
+
+/* This is the char to use for continuation (in case we need to turn
+ continuation back on). */
+
+#define DBX_CONTIN_CHAR '?'
+
+/* Don't use the `xsfoo;' construct in DBX output; this system
+ doesn't support it. */
+
+#define DBX_NO_XREFS
+
+/* Don't default to pcc-struct-return, because gcc is the only compiler, and
+ we want to retain compatibility with older gcc versions. */
+#define DEFAULT_PCC_STRUCT_RETURN 0
diff --git a/gcc/config/m68k/hp3bsd44.h b/gcc/config/m68k/hp3bsd44.h
new file mode 100755
index 0000000..a3b652f
--- /dev/null
+++ b/gcc/config/m68k/hp3bsd44.h
@@ -0,0 +1,53 @@
+#include "m68k/m68k.h"
+
+/* See m68k.h. 7 means 68020 with 68881. */
+
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
+
+/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__ -D__HAVE_FPU__}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dmc68000 -Dmc68020 -Dhp300 -Dhp9000 -Dunix -D__BSD_4_4__ -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
+
+/* No more libg.a */
+
+#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}"
+
+/* Make gcc agree with <machine/ansi.h> */
+
+#define SIZE_TYPE "unsigned int"
+#define PTRDIFF_TYPE "int"
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "short unsigned int"
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 16
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Do not break .stabs pseudos into continuations. */
+
+#define DBX_CONTIN_LENGTH 0
+
+/* This is the char to use for continuation (in case we need to turn
+ continuation back on). */
+
+#define DBX_CONTIN_CHAR '?'
+
+/* Don't use the `xsfoo;' construct in DBX output; this system
+ doesn't support it. */
+
+#define DBX_NO_XREFS
+
+/* Don't default to pcc-struct-return, because gcc is the only compiler, and
+ we want to retain compatibility with older gcc versions. */
+#define DEFAULT_PCC_STRUCT_RETURN 0
diff --git a/gcc/config/m68k/hpux7.h b/gcc/config/m68k/hpux7.h
new file mode 100755
index 0000000..ae584bd
--- /dev/null
+++ b/gcc/config/m68k/hpux7.h
@@ -0,0 +1,7 @@
+/* tm.h for m68k running HPUX version 7. */
+
+/* fletcher@cs.utexas.edu says this is needed. */
+#define NO_DOT_IN_LABEL
+#define NO_BUGS
+
+#include "m68k/hp320.h"
diff --git a/gcc/config/m68k/isi-nfp.h b/gcc/config/m68k/isi-nfp.h
new file mode 100755
index 0000000..fbded9e
--- /dev/null
+++ b/gcc/config/m68k/isi-nfp.h
@@ -0,0 +1,9 @@
+/* Define target machine as an ISI 68000/68020 with no 68881. */
+
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68020)
+
+#include "m68k/isi.h"
+
+/* Don't try using XFmode. */
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 64
diff --git a/gcc/config/m68k/isi.h b/gcc/config/m68k/isi.h
new file mode 100755
index 0000000..a458cf9
--- /dev/null
+++ b/gcc/config/m68k/isi.h
@@ -0,0 +1,91 @@
+/* Definitions of target machine for GNU compiler. ISI 68000/68020 version.
+ Intended only for use with GAS, and not ISI's assembler, which is buggy
+ Copyright (C) 1988, 1996 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "m68k/m68k.h"
+
+/* See m68k.h. 7 means 68020 with 68881. */
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
+#endif
+
+#if TARGET_DEFAULT & MASK_68881
+/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__}"
+
+/* If the 68881 is used, link must load libmc.a before libc.a. */
+
+#define LIB_SPEC "%{!msoft-float:%{!p:%{!pg:-lmc}}%{p:-lmc_p}%{pg:-lmc_p}} \
+%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} %{g:-lg}"
+
+#else
+/* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
+
+/* If the 68881 is used, link must load libmc.a instead of libc.a */
+
+#define LIB_SPEC "%{m68881:%{!p:%{!pg:-lmc}}%{p:-lmc_p}%{pg:-lmc_p}} \
+%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} %{g:-lg}"
+#endif
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dunix -Dmc68000 -Dis68k -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Override parts of m68k.h to fit the ISI 68k machine. */
+
+#undef FUNCTION_VALUE
+#undef LIBCALL_VALUE
+#undef FUNCTION_VALUE_REGNO_P
+#undef NEEDS_UNTYPED_CALL
+#undef ASM_FILE_START
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* If TARGET_68881, return SF and DF values in f0 instead of d0. */
+
+#define FUNCTION_VALUE(VALTYPE,FUNC) LIBCALL_VALUE (TYPE_MODE (VALTYPE))
+
+#define LIBCALL_VALUE(MODE) \
+ gen_rtx (REG, (MODE), ((TARGET_68881 && ((MODE) == SFmode || (MODE) == DFmode)) ? 16 : 0))
+
+/* 1 if N is a possible register number for a function value.
+ D0 may be used, and F0 as well if -m68881 is specified. */
+
+#define FUNCTION_VALUE_REGNO_P(N) \
+ ((N) == 0 || (TARGET_68881 && (N) == 16))
+
+/* Define this to be true when FUNCTION_VALUE_REGNO_P is true for
+ more than one register. */
+
+#define NEEDS_UNTYPED_CALL 1
+
+/* Also output something to cause the correct _doprnt to be loaded. */
+#define ASM_FILE_START(FILE) fprintf (FILE, "#NO_APP\n%s\n", TARGET_68881 ? ".globl fltused" : "")
diff --git a/gcc/config/m68k/lb1sf68.asm b/gcc/config/m68k/lb1sf68.asm
new file mode 100755
index 0000000..ef40a34
--- /dev/null
+++ b/gcc/config/m68k/lb1sf68.asm
@@ -0,0 +1,3904 @@
+/* libgcc1 routines for 68000 w/o floating-point hardware.
+ Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs without any restriction coming from the use of this
+file. (The General Public License restrictions do apply in other
+respects; for example, they cover modification of the file, and
+distribution when not linked into another program.)
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* As a special exception, if you link this library with files
+ compiled with GCC to produce an executable, this does not cause
+ the resulting executable to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
+
+/* Use this one for any 680x0; assumes no floating point hardware.
+ The trailing " '" appearing on some lines is for ANSI preprocessors. Yuk.
+ Some of this code comes from MINIX, via the folks at ericsson.
+ D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992
+*/
+
+/* These are predefined by new versions of GNU cpp. */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+#ifndef __IMMEDIATE_PREFIX__
+#define __IMMEDIATE_PREFIX__ #
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/* Use the right prefix for immediate values. */
+
+#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x)
+
+#define d0 REG (d0)
+#define d1 REG (d1)
+#define d2 REG (d2)
+#define d3 REG (d3)
+#define d4 REG (d4)
+#define d5 REG (d5)
+#define d6 REG (d6)
+#define d7 REG (d7)
+#define a0 REG (a0)
+#define a1 REG (a1)
+#define a2 REG (a2)
+#define a3 REG (a3)
+#define a4 REG (a4)
+#define a5 REG (a5)
+#define a6 REG (a6)
+#define fp REG (fp)
+#define sp REG (sp)
+
+#ifdef L_floatex
+
+| This is an attempt at a decent floating point (single, double and
+| extended double) code for the GNU C compiler. It should be easy to
+| adapt to other compilers (but beware of the local labels!).
+
+| Starting date: 21 October, 1990
+
+| It is convenient to introduce the notation (s,e,f) for a floating point
+| number, where s=sign, e=exponent, f=fraction. We will call a floating
+| point number fpn to abbreviate, independently of the precision.
+| Let MAX_EXP be in each case the maximum exponent (255 for floats, 1023
+| for doubles and 16383 for long doubles). We then have the following
+| different cases:
+| 1. Normalized fpns have 0 < e < MAX_EXP. They correspond to
+| (-1)^s x 1.f x 2^(e-bias-1).
+| 2. Denormalized fpns have e=0. They correspond to numbers of the form
+| (-1)^s x 0.f x 2^(-bias).
+| 3. +/-INFINITY have e=MAX_EXP, f=0.
+| 4. Quiet NaN (Not a Number) have all bits set.
+| 5. Signaling NaN (Not a Number) have s=0, e=MAX_EXP, f=1.
+
+|=============================================================================
+| exceptions
+|=============================================================================
+
+| This is the floating point condition code register (_fpCCR):
+|
+| struct {
+| short _exception_bits;
+| short _trap_enable_bits;
+| short _sticky_bits;
+| short _rounding_mode;
+| short _format;
+| short _last_operation;
+| union {
+| float sf;
+| double df;
+| } _operand1;
+| union {
+| float sf;
+| double df;
+| } _operand2;
+| } _fpCCR;
+
+ .data
+ .even
+
+ .globl SYM (_fpCCR)
+
+SYM (_fpCCR):
+__exception_bits:
+ .word 0
+__trap_enable_bits:
+ .word 0
+__sticky_bits:
+ .word 0
+__rounding_mode:
+ .word ROUND_TO_NEAREST
+__format:
+ .word NIL
+__last_operation:
+ .word NOOP
+__operand1:
+ .long 0
+ .long 0
+__operand2:
+ .long 0
+ .long 0
+
+| Offsets:
+EBITS = __exception_bits - SYM (_fpCCR)
+TRAPE = __trap_enable_bits - SYM (_fpCCR)
+STICK = __sticky_bits - SYM (_fpCCR)
+ROUND = __rounding_mode - SYM (_fpCCR)
+FORMT = __format - SYM (_fpCCR)
+LASTO = __last_operation - SYM (_fpCCR)
+OPER1 = __operand1 - SYM (_fpCCR)
+OPER2 = __operand2 - SYM (_fpCCR)
+
+| The following exception types are supported:
+INEXACT_RESULT = 0x0001
+UNDERFLOW = 0x0002
+OVERFLOW = 0x0004
+DIVIDE_BY_ZERO = 0x0008
+INVALID_OPERATION = 0x0010
+
+| The allowed rounding modes are:
+UNKNOWN = -1
+ROUND_TO_NEAREST = 0 | round result to nearest representable value
+ROUND_TO_ZERO = 1 | round result towards zero
+ROUND_TO_PLUS = 2 | round result towards plus infinity
+ROUND_TO_MINUS = 3 | round result towards minus infinity
+
+| The allowed values of format are:
+NIL = 0
+SINGLE_FLOAT = 1
+DOUBLE_FLOAT = 2
+LONG_FLOAT = 3
+
+| The allowed values for the last operation are:
+NOOP = 0
+ADD = 1
+MULTIPLY = 2
+DIVIDE = 3
+NEGATE = 4
+COMPARE = 5
+EXTENDSFDF = 6
+TRUNCDFSF = 7
+
+|=============================================================================
+| __clear_sticky_bits
+|=============================================================================
+
+| The sticky bits are normally not cleared (thus the name), whereas the
+| exception type and exception value reflect the last computation.
+| This routine is provided to clear them (you can also write to _fpCCR,
+| since it is globally visible).
+
+ .globl SYM (__clear_sticky_bit)
+
+ .text
+ .even
+
+| void __clear_sticky_bits(void);
+SYM (__clear_sticky_bit):
+ lea SYM (_fpCCR),a0
+#ifndef __mcf5200__
+ movew IMM (0),a0@(STICK)
+#else
+ clr.w a0@(STICK)
+#endif
+ rts
+
+|=============================================================================
+| $_exception_handler
+|=============================================================================
+
+ .globl $_exception_handler
+
+ .text
+ .even
+
+| This is the common exit point if an exception occurs.
+| NOTE: it is NOT callable from C!
+| It expects the exception type in d7, the format (SINGLE_FLOAT,
+| DOUBLE_FLOAT or LONG_FLOAT) in d6, and the last operation code in d5.
+| It sets the corresponding exception and sticky bits, and the format.
+| Depending on the format if fills the corresponding slots for the
+| operands which produced the exception (all this information is provided
+| so if you write your own exception handlers you have enough information
+| to deal with the problem).
+| Then checks to see if the corresponding exception is trap-enabled,
+| in which case it pushes the address of _fpCCR and traps through
+| trap FPTRAP (15 for the moment).
+
+FPTRAP = 15
+
+$_exception_handler:
+ lea SYM (_fpCCR),a0
+ movew d7,a0@(EBITS) | set __exception_bits
+#ifndef __mcf5200__
+ orw d7,a0@(STICK) | and __sticky_bits
+#else
+ movew a0@(STICK),d4
+ orl d7,d4
+ movew d4,a0@(STICK)
+#endif
+ movew d6,a0@(FORMT) | and __format
+ movew d5,a0@(LASTO) | and __last_operation
+
+| Now put the operands in place:
+#ifndef __mcf5200__
+ cmpw IMM (SINGLE_FLOAT),d6
+#else
+ cmpl IMM (SINGLE_FLOAT),d6
+#endif
+ beq 1f
+ movel a6@(8),a0@(OPER1)
+ movel a6@(12),a0@(OPER1+4)
+ movel a6@(16),a0@(OPER2)
+ movel a6@(20),a0@(OPER2+4)
+ bra 2f
+1: movel a6@(8),a0@(OPER1)
+ movel a6@(12),a0@(OPER2)
+2:
+| And check whether the exception is trap-enabled:
+#ifndef __mcf5200__
+ andw a0@(TRAPE),d7 | is exception trap-enabled?
+#else
+ clrl d6
+ movew a0@(TRAPE),d6
+ andl d6,d7
+#endif
+ beq 1f | no, exit
+ pea SYM (_fpCCR) | yes, push address of _fpCCR
+ trap IMM (FPTRAP) | and trap
+#ifndef __mcf5200__
+1: moveml sp@+,d2-d7 | restore data registers
+#else
+1: moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6 | and return
+ rts
+#endif /* L_floatex */
+
+#ifdef L_mulsi3
+ .text
+ .proc
+ .globl SYM (__mulsi3)
+SYM (__mulsi3):
+ movew sp@(4), d0 /* x0 -> d0 */
+ muluw sp@(10), d0 /* x0*y1 */
+ movew sp@(6), d1 /* x1 -> d1 */
+ muluw sp@(8), d1 /* x1*y0 */
+#ifndef __mcf5200__
+ addw d1, d0
+#else
+ addl d1, d0
+#endif
+ swap d0
+ clrw d0
+ movew sp@(6), d1 /* x1 -> d1 */
+ muluw sp@(10), d1 /* x1*y1 */
+ addl d1, d0
+
+ rts
+#endif /* L_mulsi3 */
+
+#ifdef L_udivsi3
+ .text
+ .proc
+ .globl SYM (__udivsi3)
+SYM (__udivsi3):
+#ifndef __mcf5200__
+ movel d2, sp@-
+ movel sp@(12), d1 /* d1 = divisor */
+ movel sp@(8), d0 /* d0 = dividend */
+
+ cmpl IMM (0x10000), d1 /* divisor >= 2 ^ 16 ? */
+ jcc L3 /* then try next algorithm */
+ movel d0, d2
+ clrw d2
+ swap d2
+ divu d1, d2 /* high quotient in lower word */
+ movew d2, d0 /* save high quotient */
+ swap d0
+ movew sp@(10), d2 /* get low dividend + high rest */
+ divu d1, d2 /* low quotient */
+ movew d2, d0
+ jra L6
+
+L3: movel d1, d2 /* use d2 as divisor backup */
+L4: lsrl IMM (1), d1 /* shift divisor */
+ lsrl IMM (1), d0 /* shift dividend */
+ cmpl IMM (0x10000), d1 /* still divisor >= 2 ^ 16 ? */
+ jcc L4
+ divu d1, d0 /* now we have 16 bit divisor */
+ andl IMM (0xffff), d0 /* mask out divisor, ignore remainder */
+
+/* Multiply the 16 bit tentative quotient with the 32 bit divisor. Because of
+ the operand ranges, this might give a 33 bit product. If this product is
+ greater than the dividend, the tentative quotient was too large. */
+ movel d2, d1
+ mulu d0, d1 /* low part, 32 bits */
+ swap d2
+ mulu d0, d2 /* high part, at most 17 bits */
+ swap d2 /* align high part with low part */
+ tstw d2 /* high part 17 bits? */
+ jne L5 /* if 17 bits, quotient was too large */
+ addl d2, d1 /* add parts */
+ jcs L5 /* if sum is 33 bits, quotient was too large */
+ cmpl sp@(8), d1 /* compare the sum with the dividend */
+ jls L6 /* if sum > dividend, quotient was too large */
+L5: subql IMM (1), d0 /* adjust quotient */
+
+L6: movel sp@+, d2
+ rts
+
+#else /* __mcf5200__ */
+
+/* Coldfire implementation of non-restoring division algorithm from
+ Hennessy & Patterson, Appendix A. */
+ link a6,IMM (-12)
+ moveml d2-d4,sp@
+ movel a6@(8),d0
+ movel a6@(12),d1
+ clrl d2 | clear p
+ moveq IMM (31),d4
+L1: addl d0,d0 | shift reg pair (p,a) one bit left
+ addxl d2,d2
+ movl d2,d3 | subtract b from p, store in tmp.
+ subl d1,d3
+ jcs L2 | if no carry,
+ bset IMM (0),d0 | set the low order bit of a to 1,
+ movl d3,d2 | and store tmp in p.
+L2: subql IMM (1),d4
+ jcc L1
+ moveml sp@,d2-d4 | restore data registers
+ unlk a6 | and return
+ rts
+#endif /* __mcf5200__ */
+
+#endif /* L_udivsi3 */
+
+#ifdef L_divsi3
+ .text
+ .proc
+ .globl SYM (__divsi3)
+SYM (__divsi3):
+ movel d2, sp@-
+
+ moveq IMM (1), d2 /* sign of result stored in d2 (=1 or =-1) */
+ movel sp@(12), d1 /* d1 = divisor */
+ jpl L1
+ negl d1
+#ifndef __mcf5200__
+ negb d2 /* change sign because divisor <0 */
+#else
+ negl d2 /* change sign because divisor <0 */
+#endif
+L1: movel sp@(8), d0 /* d0 = dividend */
+ jpl L2
+ negl d0
+#ifndef __mcf5200__
+ negb d2
+#else
+ negl d2
+#endif
+
+L2: movel d1, sp@-
+ movel d0, sp@-
+ jbsr SYM (__udivsi3) /* divide abs(dividend) by abs(divisor) */
+ addql IMM (8), sp
+
+ tstb d2
+ jpl L3
+ negl d0
+
+L3: movel sp@+, d2
+ rts
+#endif /* L_divsi3 */
+
+#ifdef L_umodsi3
+ .text
+ .proc
+ .globl SYM (__umodsi3)
+SYM (__umodsi3):
+ movel sp@(8), d1 /* d1 = divisor */
+ movel sp@(4), d0 /* d0 = dividend */
+ movel d1, sp@-
+ movel d0, sp@-
+ jbsr SYM (__udivsi3)
+ addql IMM (8), sp
+ movel sp@(8), d1 /* d1 = divisor */
+#ifndef __mcf5200__
+ movel d1, sp@-
+ movel d0, sp@-
+ jbsr SYM (__mulsi3) /* d0 = (a/b)*b */
+ addql IMM (8), sp
+#else
+ mulsl d1,d0
+#endif
+ movel sp@(4), d1 /* d1 = dividend */
+ subl d0, d1 /* d1 = a - (a/b)*b */
+ movel d1, d0
+ rts
+#endif /* L_umodsi3 */
+
+#ifdef L_modsi3
+ .text
+ .proc
+ .globl SYM (__modsi3)
+SYM (__modsi3):
+ movel sp@(8), d1 /* d1 = divisor */
+ movel sp@(4), d0 /* d0 = dividend */
+ movel d1, sp@-
+ movel d0, sp@-
+ jbsr SYM (__divsi3)
+ addql IMM (8), sp
+ movel sp@(8), d1 /* d1 = divisor */
+#ifndef __mcf5200__
+ movel d1, sp@-
+ movel d0, sp@-
+ jbsr SYM (__mulsi3) /* d0 = (a/b)*b */
+ addql IMM (8), sp
+#else
+ mulsl d1,d0
+#endif
+ movel sp@(4), d1 /* d1 = dividend */
+ subl d0, d1 /* d1 = a - (a/b)*b */
+ movel d1, d0
+ rts
+#endif /* L_modsi3 */
+
+
+#ifdef L_double
+
+ .globl SYM (_fpCCR)
+ .globl $_exception_handler
+
+QUIET_NaN = 0xffffffff
+
+D_MAX_EXP = 0x07ff
+D_BIAS = 1022
+DBL_MAX_EXP = D_MAX_EXP - D_BIAS
+DBL_MIN_EXP = 1 - D_BIAS
+DBL_MANT_DIG = 53
+
+INEXACT_RESULT = 0x0001
+UNDERFLOW = 0x0002
+OVERFLOW = 0x0004
+DIVIDE_BY_ZERO = 0x0008
+INVALID_OPERATION = 0x0010
+
+DOUBLE_FLOAT = 2
+
+NOOP = 0
+ADD = 1
+MULTIPLY = 2
+DIVIDE = 3
+NEGATE = 4
+COMPARE = 5
+EXTENDSFDF = 6
+TRUNCDFSF = 7
+
+UNKNOWN = -1
+ROUND_TO_NEAREST = 0 | round result to nearest representable value
+ROUND_TO_ZERO = 1 | round result towards zero
+ROUND_TO_PLUS = 2 | round result towards plus infinity
+ROUND_TO_MINUS = 3 | round result towards minus infinity
+
+| Entry points:
+
+ .globl SYM (__adddf3)
+ .globl SYM (__subdf3)
+ .globl SYM (__muldf3)
+ .globl SYM (__divdf3)
+ .globl SYM (__negdf2)
+ .globl SYM (__cmpdf2)
+
+ .text
+ .even
+
+| These are common routines to return and signal exceptions.
+
+Ld$den:
+| Return and signal a denormalized number
+ orl d7,d0
+ movew IMM (INEXACT_RESULT+UNDERFLOW),d7
+ moveq IMM (DOUBLE_FLOAT),d6
+ jmp $_exception_handler
+
+Ld$infty:
+Ld$overflow:
+| Return a properly signed INFINITY and set the exception flags
+ movel IMM (0x7ff00000),d0
+ movel IMM (0),d1
+ orl d7,d0
+ movew IMM (INEXACT_RESULT+OVERFLOW),d7
+ moveq IMM (DOUBLE_FLOAT),d6
+ jmp $_exception_handler
+
+Ld$underflow:
+| Return 0 and set the exception flags
+ movel IMM (0),d0
+ movel d0,d1
+ movew IMM (INEXACT_RESULT+UNDERFLOW),d7
+ moveq IMM (DOUBLE_FLOAT),d6
+ jmp $_exception_handler
+
+Ld$inop:
+| Return a quiet NaN and set the exception flags
+ movel IMM (QUIET_NaN),d0
+ movel d0,d1
+ movew IMM (INEXACT_RESULT+INVALID_OPERATION),d7
+ moveq IMM (DOUBLE_FLOAT),d6
+ jmp $_exception_handler
+
+Ld$div$0:
+| Return a properly signed INFINITY and set the exception flags
+ movel IMM (0x7ff00000),d0
+ movel IMM (0),d1
+ orl d7,d0
+ movew IMM (INEXACT_RESULT+DIVIDE_BY_ZERO),d7
+ moveq IMM (DOUBLE_FLOAT),d6
+ jmp $_exception_handler
+
+|=============================================================================
+|=============================================================================
+| double precision routines
+|=============================================================================
+|=============================================================================
+
+| A double precision floating point number (double) has the format:
+|
+| struct _double {
+| unsigned int sign : 1; /* sign bit */
+| unsigned int exponent : 11; /* exponent, shifted by 126 */
+| unsigned int fraction : 52; /* fraction */
+| } double;
+|
+| Thus sizeof(double) = 8 (64 bits).
+|
+| All the routines are callable from C programs, and return the result
+| in the register pair d0-d1. They also preserve all registers except
+| d0-d1 and a0-a1.
+
+|=============================================================================
+| __subdf3
+|=============================================================================
+
+| double __subdf3(double, double);
+SYM (__subdf3):
+ bchg IMM (31),sp@(12) | change sign of second operand
+ | and fall through, so we always add
+|=============================================================================
+| __adddf3
+|=============================================================================
+
+| double __adddf3(double, double);
+SYM (__adddf3):
+#ifndef __mcf5200__
+ link a6,IMM (0) | everything will be done in registers
+ moveml d2-d7,sp@- | save all data registers and a2 (but d0-d1)
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
+ movel a6@(8),d0 | get first operand
+ movel a6@(12),d1 |
+ movel a6@(16),d2 | get second operand
+ movel a6@(20),d3 |
+
+ movel d0,d7 | get d0's sign bit in d7 '
+ addl d1,d1 | check and clear sign bit of a, and gain one
+ addxl d0,d0 | bit of extra precision
+ beq Ladddf$b | if zero return second operand
+
+ movel d2,d6 | save sign in d6
+ addl d3,d3 | get rid of sign bit and gain one bit of
+ addxl d2,d2 | extra precision
+ beq Ladddf$a | if zero return first operand
+
+ andl IMM (0x80000000),d7 | isolate a's sign bit '
+ swap d6 | and also b's sign bit '
+#ifndef __mcf5200__
+ andw IMM (0x8000),d6 |
+ orw d6,d7 | and combine them into d7, so that a's sign '
+ | bit is in the high word and b's is in the '
+ | low word, so d6 is free to be used
+#else
+ andl IMM (0x8000),d6
+ orl d6,d7
+#endif
+ movel d7,a0 | now save d7 into a0, so d7 is free to
+ | be used also
+
+| Get the exponents and check for denormalized and/or infinity.
+
+ movel IMM (0x001fffff),d6 | mask for the fraction
+ movel IMM (0x00200000),d7 | mask to put hidden bit back
+
+ movel d0,d4 |
+ andl d6,d0 | get fraction in d0
+ notl d6 | make d6 into mask for the exponent
+ andl d6,d4 | get exponent in d4
+ beq Ladddf$a$den | branch if a is denormalized
+ cmpl d6,d4 | check for INFINITY or NaN
+ beq Ladddf$nf |
+ orl d7,d0 | and put hidden bit back
+Ladddf$1:
+ swap d4 | shift right exponent so that it starts
+#ifndef __mcf5200__
+ lsrw IMM (5),d4 | in bit 0 and not bit 20
+#else
+ lsrl IMM (5),d4 | in bit 0 and not bit 20
+#endif
+| Now we have a's exponent in d4 and fraction in d0-d1 '
+ movel d2,d5 | save b to get exponent
+ andl d6,d5 | get exponent in d5
+ beq Ladddf$b$den | branch if b is denormalized
+ cmpl d6,d5 | check for INFINITY or NaN
+ beq Ladddf$nf
+ notl d6 | make d6 into mask for the fraction again
+ andl d6,d2 | and get fraction in d2
+ orl d7,d2 | and put hidden bit back
+Ladddf$2:
+ swap d5 | shift right exponent so that it starts
+#ifndef __mcf5200__
+ lsrw IMM (5),d5 | in bit 0 and not bit 20
+#else
+ lsrl IMM (5),d5 | in bit 0 and not bit 20
+#endif
+
+| Now we have b's exponent in d5 and fraction in d2-d3. '
+
+| The situation now is as follows: the signs are combined in a0, the
+| numbers are in d0-d1 (a) and d2-d3 (b), and the exponents in d4 (a)
+| and d5 (b). To do the rounding correctly we need to keep all the
+| bits until the end, so we need to use d0-d1-d2-d3 for the first number
+| and d4-d5-d6-d7 for the second. To do this we store (temporarily) the
+| exponents in a2-a3.
+
+#ifndef __mcf5200__
+ moveml a2-a3,sp@- | save the address registers
+#else
+ movel a2,sp@-
+ movel a3,sp@-
+ movel a4,sp@-
+#endif
+
+ movel d4,a2 | save the exponents
+ movel d5,a3 |
+
+ movel IMM (0),d7 | and move the numbers around
+ movel d7,d6 |
+ movel d3,d5 |
+ movel d2,d4 |
+ movel d7,d3 |
+ movel d7,d2 |
+
+| Here we shift the numbers until the exponents are the same, and put
+| the largest exponent in a2.
+#ifndef __mcf5200__
+ exg d4,a2 | get exponents back
+ exg d5,a3 |
+ cmpw d4,d5 | compare the exponents
+#else
+ movel d4,a4 | get exponents back
+ movel a2,d4
+ movel a4,a2
+ movel d5,a4
+ movel a3,d5
+ movel a4,a3
+ cmpl d4,d5 | compare the exponents
+#endif
+ beq Ladddf$3 | if equal don't shift '
+ bhi 9f | branch if second exponent is higher
+
+| Here we have a's exponent larger than b's, so we have to shift b. We do
+| this by using as counter d2:
+1: movew d4,d2 | move largest exponent to d2
+#ifndef __mcf5200__
+ subw d5,d2 | and subtract second exponent
+ exg d4,a2 | get back the longs we saved
+ exg d5,a3 |
+#else
+ subl d5,d2 | and subtract second exponent
+ movel d4,a4 | get back the longs we saved
+ movel a2,d4
+ movel a4,a2
+ movel d5,a4
+ movel a3,d5
+ movel a4,a3
+#endif
+| if difference is too large we don't shift (actually, we can just exit) '
+#ifndef __mcf5200__
+ cmpw IMM (DBL_MANT_DIG+2),d2
+#else
+ cmpl IMM (DBL_MANT_DIG+2),d2
+#endif
+ bge Ladddf$b$small
+#ifndef __mcf5200__
+ cmpw IMM (32),d2 | if difference >= 32, shift by longs
+#else
+ cmpl IMM (32),d2 | if difference >= 32, shift by longs
+#endif
+ bge 5f
+2:
+#ifndef __mcf5200__
+ cmpw IMM (16),d2 | if difference >= 16, shift by words
+#else
+ cmpl IMM (16),d2 | if difference >= 16, shift by words
+#endif
+ bge 6f
+ bra 3f | enter dbra loop
+
+4:
+#ifndef __mcf5200__
+ lsrl IMM (1),d4
+ roxrl IMM (1),d5
+ roxrl IMM (1),d6
+ roxrl IMM (1),d7
+#else
+ lsrl IMM (1),d7
+ btst IMM (0),d6
+ beq 10f
+ bset IMM (31),d7
+10: lsrl IMM (1),d6
+ btst IMM (0),d5
+ beq 11f
+ bset IMM (31),d6
+11: lsrl IMM (1),d5
+ btst IMM (0),d4
+ beq 12f
+ bset IMM (31),d5
+12: lsrl IMM (1),d4
+#endif
+3:
+#ifndef __mcf5200__
+ dbra d2,4b
+#else
+ subql IMM (1),d2
+ bpl 4b
+#endif
+ movel IMM (0),d2
+ movel d2,d3
+ bra Ladddf$4
+5:
+ movel d6,d7
+ movel d5,d6
+ movel d4,d5
+ movel IMM (0),d4
+#ifndef __mcf5200__
+ subw IMM (32),d2
+#else
+ subl IMM (32),d2
+#endif
+ bra 2b
+6:
+ movew d6,d7
+ swap d7
+ movew d5,d6
+ swap d6
+ movew d4,d5
+ swap d5
+ movew IMM (0),d4
+ swap d4
+#ifndef __mcf5200__
+ subw IMM (16),d2
+#else
+ subl IMM (16),d2
+#endif
+ bra 3b
+
+9:
+#ifndef __mcf5200__
+ exg d4,d5
+ movew d4,d6
+ subw d5,d6 | keep d5 (largest exponent) in d4
+ exg d4,a2
+ exg d5,a3
+#else
+ movel d5,d6
+ movel d4,d5
+ movel d6,d4
+ subl d5,d6
+ movel d4,a4
+ movel a2,d4
+ movel a4,a2
+ movel d5,a4
+ movel a3,d5
+ movel a4,a3
+#endif
+| if difference is too large we don't shift (actually, we can just exit) '
+#ifndef __mcf5200__
+ cmpw IMM (DBL_MANT_DIG+2),d6
+#else
+ cmpl IMM (DBL_MANT_DIG+2),d6
+#endif
+ bge Ladddf$a$small
+#ifndef __mcf5200__
+ cmpw IMM (32),d6 | if difference >= 32, shift by longs
+#else
+ cmpl IMM (32),d6 | if difference >= 32, shift by longs
+#endif
+ bge 5f
+2:
+#ifndef __mcf5200__
+ cmpw IMM (16),d6 | if difference >= 16, shift by words
+#else
+ cmpl IMM (16),d6 | if difference >= 16, shift by words
+#endif
+ bge 6f
+ bra 3f | enter dbra loop
+
+4:
+#ifndef __mcf5200__
+ lsrl IMM (1),d0
+ roxrl IMM (1),d1
+ roxrl IMM (1),d2
+ roxrl IMM (1),d3
+#else
+ lsrl IMM (1),d3
+ btst IMM (0),d2
+ beq 10f
+ bset IMM (31),d3
+10: lsrl IMM (1),d2
+ btst IMM (0),d1
+ beq 11f
+ bset IMM (31),d2
+11: lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 12f
+ bset IMM (31),d1
+12: lsrl IMM (1),d0
+#endif
+3:
+#ifndef __mcf5200__
+ dbra d6,4b
+#else
+ subql IMM (1),d6
+ bpl 4b
+#endif
+ movel IMM (0),d7
+ movel d7,d6
+ bra Ladddf$4
+5:
+ movel d2,d3
+ movel d1,d2
+ movel d0,d1
+ movel IMM (0),d0
+#ifndef __mcf5200__
+ subw IMM (32),d6
+#else
+ subl IMM (32),d6
+#endif
+ bra 2b
+6:
+ movew d2,d3
+ swap d3
+ movew d1,d2
+ swap d2
+ movew d0,d1
+ swap d1
+ movew IMM (0),d0
+ swap d0
+#ifndef __mcf5200__
+ subw IMM (16),d6
+#else
+ subl IMM (16),d6
+#endif
+ bra 3b
+Ladddf$3:
+#ifndef __mcf5200__
+ exg d4,a2
+ exg d5,a3
+#else
+ movel d4,a4
+ movel a2,d4
+ movel a4,a2
+ movel d5,a4
+ movel a3,d5
+ movel a4,a3
+#endif
+Ladddf$4:
+| Now we have the numbers in d0--d3 and d4--d7, the exponent in a2, and
+| the signs in a4.
+
+| Here we have to decide whether to add or subtract the numbers:
+#ifndef __mcf5200__
+ exg d7,a0 | get the signs
+ exg d6,a3 | a3 is free to be used
+#else
+ movel d7,a4
+ movel a0,d7
+ movel a4,a0
+ movel d6,a4
+ movel a3,d6
+ movel a4,a3
+#endif
+ movel d7,d6 |
+ movew IMM (0),d7 | get a's sign in d7 '
+ swap d6 |
+ movew IMM (0),d6 | and b's sign in d6 '
+ eorl d7,d6 | compare the signs
+ bmi Lsubdf$0 | if the signs are different we have
+ | to subtract
+#ifndef __mcf5200__
+ exg d7,a0 | else we add the numbers
+ exg d6,a3 |
+#else
+ movel d7,a4
+ movel a0,d7
+ movel a4,a0
+ movel d6,a4
+ movel a3,d6
+ movel a4,a3
+#endif
+ addl d7,d3 |
+ addxl d6,d2 |
+ addxl d5,d1 |
+ addxl d4,d0 |
+
+ movel a2,d4 | return exponent to d4
+ movel a0,d7 |
+ andl IMM (0x80000000),d7 | d7 now has the sign
+
+#ifndef __mcf5200__
+ moveml sp@+,a2-a3
+#else
+ movel sp@+,a4
+ movel sp@+,a3
+ movel sp@+,a2
+#endif
+
+| Before rounding normalize so bit #DBL_MANT_DIG is set (we will consider
+| the case of denormalized numbers in the rounding routine itself).
+| As in the addition (not in the subtraction!) we could have set
+| one more bit we check this:
+ btst IMM (DBL_MANT_DIG+1),d0
+ beq 1f
+#ifndef __mcf5200__
+ lsrl IMM (1),d0
+ roxrl IMM (1),d1
+ roxrl IMM (1),d2
+ roxrl IMM (1),d3
+ addw IMM (1),d4
+#else
+ lsrl IMM (1),d3
+ btst IMM (0),d2
+ beq 10f
+ bset IMM (31),d3
+10: lsrl IMM (1),d2
+ btst IMM (0),d1
+ beq 11f
+ bset IMM (31),d2
+11: lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 12f
+ bset IMM (31),d1
+12: lsrl IMM (1),d0
+ addl IMM (1),d4
+#endif
+1:
+ lea Ladddf$5,a0 | to return from rounding routine
+ lea SYM (_fpCCR),a1 | check the rounding mode
+#ifdef __mcf5200__
+ clrl d6
+#endif
+ movew a1@(6),d6 | rounding mode in d6
+ beq Lround$to$nearest
+#ifndef __mcf5200__
+ cmpw IMM (ROUND_TO_PLUS),d6
+#else
+ cmpl IMM (ROUND_TO_PLUS),d6
+#endif
+ bhi Lround$to$minus
+ blt Lround$to$zero
+ bra Lround$to$plus
+Ladddf$5:
+| Put back the exponent and check for overflow
+#ifndef __mcf5200__
+ cmpw IMM (0x7ff),d4 | is the exponent big?
+#else
+ cmpl IMM (0x7ff),d4 | is the exponent big?
+#endif
+ bge 1f
+ bclr IMM (DBL_MANT_DIG-1),d0
+#ifndef __mcf5200__
+ lslw IMM (4),d4 | put exponent back into position
+#else
+ lsll IMM (4),d4 | put exponent back into position
+#endif
+ swap d0 |
+#ifndef __mcf5200__
+ orw d4,d0 |
+#else
+ orl d4,d0 |
+#endif
+ swap d0 |
+ bra Ladddf$ret
+1:
+ movew IMM (ADD),d5
+ bra Ld$overflow
+
+Lsubdf$0:
+| Here we do the subtraction.
+#ifndef __mcf5200__
+ exg d7,a0 | put sign back in a0
+ exg d6,a3 |
+#else
+ movel d7,a4
+ movel a0,d7
+ movel a4,a0
+ movel d6,a4
+ movel a3,d6
+ movel a4,a3
+#endif
+ subl d7,d3 |
+ subxl d6,d2 |
+ subxl d5,d1 |
+ subxl d4,d0 |
+ beq Ladddf$ret$1 | if zero just exit
+ bpl 1f | if positive skip the following
+ movel a0,d7 |
+ bchg IMM (31),d7 | change sign bit in d7
+ movel d7,a0 |
+ negl d3 |
+ negxl d2 |
+ negxl d1 | and negate result
+ negxl d0 |
+1:
+ movel a2,d4 | return exponent to d4
+ movel a0,d7
+ andl IMM (0x80000000),d7 | isolate sign bit
+#ifndef __mcf5200__
+ moveml sp@+,a2-a3 |
+#else
+ movel sp@+,a4
+ movel sp@+,a3
+ movel sp@+,a2
+#endif
+
+| Before rounding normalize so bit #DBL_MANT_DIG is set (we will consider
+| the case of denormalized numbers in the rounding routine itself).
+| As in the addition (not in the subtraction!) we could have set
+| one more bit we check this:
+ btst IMM (DBL_MANT_DIG+1),d0
+ beq 1f
+#ifndef __mcf5200__
+ lsrl IMM (1),d0
+ roxrl IMM (1),d1
+ roxrl IMM (1),d2
+ roxrl IMM (1),d3
+ addw IMM (1),d4
+#else
+ lsrl IMM (1),d3
+ btst IMM (0),d2
+ beq 10f
+ bset IMM (31),d3
+10: lsrl IMM (1),d2
+ btst IMM (0),d1
+ beq 11f
+ bset IMM (31),d2
+11: lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 12f
+ bset IMM (31),d1
+12: lsrl IMM (1),d0
+ addl IMM (1),d4
+#endif
+1:
+ lea Lsubdf$1,a0 | to return from rounding routine
+ lea SYM (_fpCCR),a1 | check the rounding mode
+#ifdef __mcf5200__
+ clrl d6
+#endif
+ movew a1@(6),d6 | rounding mode in d6
+ beq Lround$to$nearest
+#ifndef __mcf5200__
+ cmpw IMM (ROUND_TO_PLUS),d6
+#else
+ cmpl IMM (ROUND_TO_PLUS),d6
+#endif
+ bhi Lround$to$minus
+ blt Lround$to$zero
+ bra Lround$to$plus
+Lsubdf$1:
+| Put back the exponent and sign (we don't have overflow). '
+ bclr IMM (DBL_MANT_DIG-1),d0
+#ifndef __mcf5200__
+ lslw IMM (4),d4 | put exponent back into position
+#else
+ lsll IMM (4),d4 | put exponent back into position
+#endif
+ swap d0 |
+#ifndef __mcf5200__
+ orw d4,d0 |
+#else
+ orl d4,d0 |
+#endif
+ swap d0 |
+ bra Ladddf$ret
+
+| If one of the numbers was too small (difference of exponents >=
+| DBL_MANT_DIG+1) we return the other (and now we don't have to '
+| check for finiteness or zero).
+Ladddf$a$small:
+#ifndef __mcf5200__
+ moveml sp@+,a2-a3
+#else
+ movel sp@+,a4
+ movel sp@+,a3
+ movel sp@+,a2
+#endif
+ movel a6@(16),d0
+ movel a6@(20),d1
+ lea SYM (_fpCCR),a0
+ movew IMM (0),a0@
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7 | restore data registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6 | and return
+ rts
+
+Ladddf$b$small:
+#ifndef __mcf5200__
+ moveml sp@+,a2-a3
+#else
+ movel sp@+,a4
+ movel sp@+,a3
+ movel sp@+,a2
+#endif
+ movel a6@(8),d0
+ movel a6@(12),d1
+ lea SYM (_fpCCR),a0
+ movew IMM (0),a0@
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7 | restore data registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6 | and return
+ rts
+
+Ladddf$a$den:
+ movel d7,d4 | d7 contains 0x00200000
+ bra Ladddf$1
+
+Ladddf$b$den:
+ movel d7,d5 | d7 contains 0x00200000
+ notl d6
+ bra Ladddf$2
+
+Ladddf$b:
+| Return b (if a is zero)
+ movel d2,d0
+ movel d3,d1
+ bra 1f
+Ladddf$a:
+ movel a6@(8),d0
+ movel a6@(12),d1
+1:
+ movew IMM (ADD),d5
+| Check for NaN and +/-INFINITY.
+ movel d0,d7 |
+ andl IMM (0x80000000),d7 |
+ bclr IMM (31),d0 |
+ cmpl IMM (0x7ff00000),d0 |
+ bge 2f |
+ movel d0,d0 | check for zero, since we don't '
+ bne Ladddf$ret | want to return -0 by mistake
+ bclr IMM (31),d7 |
+ bra Ladddf$ret |
+2:
+ andl IMM (0x000fffff),d0 | check for NaN (nonzero fraction)
+ orl d1,d0 |
+ bne Ld$inop |
+ bra Ld$infty |
+
+Ladddf$ret$1:
+#ifndef __mcf5200__
+ moveml sp@+,a2-a3 | restore regs and exit
+#else
+ movel sp@+,a4
+ movel sp@+,a3
+ movel sp@+,a2
+#endif
+
+Ladddf$ret:
+| Normal exit.
+ lea SYM (_fpCCR),a0
+ movew IMM (0),a0@
+ orl d7,d0 | put sign bit back
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6
+ rts
+
+Ladddf$ret$den:
+| Return a denormalized number.
+#ifndef __mcf5200__
+ lsrl IMM (1),d0 | shift right once more
+ roxrl IMM (1),d1 |
+#else
+ lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 10f
+ bset IMM (31),d1
+10: lsrl IMM (1),d0
+#endif
+ bra Ladddf$ret
+
+Ladddf$nf:
+ movew IMM (ADD),d5
+| This could be faster but it is not worth the effort, since it is not
+| executed very often. We sacrifice speed for clarity here.
+ movel a6@(8),d0 | get the numbers back (remember that we
+ movel a6@(12),d1 | did some processing already)
+ movel a6@(16),d2 |
+ movel a6@(20),d3 |
+ movel IMM (0x7ff00000),d4 | useful constant (INFINITY)
+ movel d0,d7 | save sign bits
+ movel d2,d6 |
+ bclr IMM (31),d0 | clear sign bits
+ bclr IMM (31),d2 |
+| We know that one of them is either NaN of +/-INFINITY
+| Check for NaN (if either one is NaN return NaN)
+ cmpl d4,d0 | check first a (d0)
+ bhi Ld$inop | if d0 > 0x7ff00000 or equal and
+ bne 2f
+ tstl d1 | d1 > 0, a is NaN
+ bne Ld$inop |
+2: cmpl d4,d2 | check now b (d1)
+ bhi Ld$inop |
+ bne 3f
+ tstl d3 |
+ bne Ld$inop |
+3:
+| Now comes the check for +/-INFINITY. We know that both are (maybe not
+| finite) numbers, but we have to check if both are infinite whether we
+| are adding or subtracting them.
+ eorl d7,d6 | to check sign bits
+ bmi 1f
+ andl IMM (0x80000000),d7 | get (common) sign bit
+ bra Ld$infty
+1:
+| We know one (or both) are infinite, so we test for equality between the
+| two numbers (if they are equal they have to be infinite both, so we
+| return NaN).
+ cmpl d2,d0 | are both infinite?
+ bne 1f | if d0 <> d2 they are not equal
+ cmpl d3,d1 | if d0 == d2 test d3 and d1
+ beq Ld$inop | if equal return NaN
+1:
+ andl IMM (0x80000000),d7 | get a's sign bit '
+ cmpl d4,d0 | test now for infinity
+ beq Ld$infty | if a is INFINITY return with this sign
+ bchg IMM (31),d7 | else we know b is INFINITY and has
+ bra Ld$infty | the opposite sign
+
+|=============================================================================
+| __muldf3
+|=============================================================================
+
+| double __muldf3(double, double);
+SYM (__muldf3):
+#ifndef __mcf5200__
+ link a6,IMM (0)
+ moveml d2-d7,sp@-
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
+ movel a6@(8),d0 | get a into d0-d1
+ movel a6@(12),d1 |
+ movel a6@(16),d2 | and b into d2-d3
+ movel a6@(20),d3 |
+ movel d0,d7 | d7 will hold the sign of the product
+ eorl d2,d7 |
+ andl IMM (0x80000000),d7 |
+ movel d7,a0 | save sign bit into a0
+ movel IMM (0x7ff00000),d7 | useful constant (+INFINITY)
+ movel d7,d6 | another (mask for fraction)
+ notl d6 |
+ bclr IMM (31),d0 | get rid of a's sign bit '
+ movel d0,d4 |
+ orl d1,d4 |
+ beq Lmuldf$a$0 | branch if a is zero
+ movel d0,d4 |
+ bclr IMM (31),d2 | get rid of b's sign bit '
+ movel d2,d5 |
+ orl d3,d5 |
+ beq Lmuldf$b$0 | branch if b is zero
+ movel d2,d5 |
+ cmpl d7,d0 | is a big?
+ bhi Lmuldf$inop | if a is NaN return NaN
+ beq Lmuldf$a$nf | we still have to check d1 and b ...
+ cmpl d7,d2 | now compare b with INFINITY
+ bhi Lmuldf$inop | is b NaN?
+ beq Lmuldf$b$nf | we still have to check d3 ...
+| Here we have both numbers finite and nonzero (and with no sign bit).
+| Now we get the exponents into d4 and d5.
+ andl d7,d4 | isolate exponent in d4
+ beq Lmuldf$a$den | if exponent zero, have denormalized
+ andl d6,d0 | isolate fraction
+ orl IMM (0x00100000),d0 | and put hidden bit back
+ swap d4 | I like exponents in the first byte
+#ifndef __mcf5200__
+ lsrw IMM (4),d4 |
+#else
+ lsrl IMM (4),d4 |
+#endif
+Lmuldf$1:
+ andl d7,d5 |
+ beq Lmuldf$b$den |
+ andl d6,d2 |
+ orl IMM (0x00100000),d2 | and put hidden bit back
+ swap d5 |
+#ifndef __mcf5200__
+ lsrw IMM (4),d5 |
+#else
+ lsrl IMM (4),d5 |
+#endif
+Lmuldf$2: |
+#ifndef __mcf5200__
+ addw d5,d4 | add exponents
+ subw IMM (D_BIAS+1),d4 | and subtract bias (plus one)
+#else
+ addl d5,d4 | add exponents
+ subl IMM (D_BIAS+1),d4 | and subtract bias (plus one)
+#endif
+
+| We are now ready to do the multiplication. The situation is as follows:
+| both a and b have bit 52 ( bit 20 of d0 and d2) set (even if they were
+| denormalized to start with!), which means that in the product bit 104
+| (which will correspond to bit 8 of the fourth long) is set.
+
+| Here we have to do the product.
+| To do it we have to juggle the registers back and forth, as there are not
+| enough to keep everything in them. So we use the address registers to keep
+| some intermediate data.
+
+#ifndef __mcf5200__
+ moveml a2-a3,sp@- | save a2 and a3 for temporary use
+#else
+ movel a2,sp@-
+ movel a3,sp@-
+ movel a4,sp@-
+#endif
+ movel IMM (0),a2 | a2 is a null register
+ movel d4,a3 | and a3 will preserve the exponent
+
+| First, shift d2-d3 so bit 20 becomes bit 31:
+#ifndef __mcf5200__
+ rorl IMM (5),d2 | rotate d2 5 places right
+ swap d2 | and swap it
+ rorl IMM (5),d3 | do the same thing with d3
+ swap d3 |
+ movew d3,d6 | get the rightmost 11 bits of d3
+ andw IMM (0x07ff),d6 |
+ orw d6,d2 | and put them into d2
+ andw IMM (0xf800),d3 | clear those bits in d3
+#else
+ moveq IMM (11),d7 | left shift d2 11 bits
+ lsll d7,d2
+ movel d3,d6 | get a copy of d3
+ lsll d7,d3 | left shift d3 11 bits
+ andl IMM (0xffe00000),d6 | get the top 11 bits of d3
+ moveq IMM (21),d7 | right shift them 21 bits
+ lsrl d7,d6
+ orl d6,d2 | stick them at the end of d2
+#endif
+
+ movel d2,d6 | move b into d6-d7
+ movel d3,d7 | move a into d4-d5
+ movel d0,d4 | and clear d0-d1-d2-d3 (to put result)
+ movel d1,d5 |
+ movel IMM (0),d3 |
+ movel d3,d2 |
+ movel d3,d1 |
+ movel d3,d0 |
+
+| We use a1 as counter:
+ movel IMM (DBL_MANT_DIG-1),a1
+#ifndef __mcf5200__
+ exg d7,a1
+#else
+ movel d7,a4
+ movel a1,d7
+ movel a4,a1
+#endif
+
+1:
+#ifndef __mcf5200__
+ exg d7,a1 | put counter back in a1
+#else
+ movel d7,a4
+ movel a1,d7
+ movel a4,a1
+#endif
+ addl d3,d3 | shift sum once left
+ addxl d2,d2 |
+ addxl d1,d1 |
+ addxl d0,d0 |
+ addl d7,d7 |
+ addxl d6,d6 |
+ bcc 2f | if bit clear skip the following
+#ifndef __mcf5200__
+ exg d7,a2 |
+#else
+ movel d7,a4
+ movel a2,d7
+ movel a4,a2
+#endif
+ addl d5,d3 | else add a to the sum
+ addxl d4,d2 |
+ addxl d7,d1 |
+ addxl d7,d0 |
+#ifndef __mcf5200__
+ exg d7,a2 |
+#else
+ movel d7,a4
+ movel a2,d7
+ movel a4,a2
+#endif
+2:
+#ifndef __mcf5200__
+ exg d7,a1 | put counter in d7
+ dbf d7,1b | decrement and branch
+#else
+ movel d7,a4
+ movel a1,d7
+ movel a4,a1
+ subql IMM (1),d7
+ bpl 1b
+#endif
+
+ movel a3,d4 | restore exponent
+#ifndef __mcf5200__
+ moveml sp@+,a2-a3
+#else
+ movel sp@+,a4
+ movel sp@+,a3
+ movel sp@+,a2
+#endif
+
+| Now we have the product in d0-d1-d2-d3, with bit 8 of d0 set. The
+| first thing to do now is to normalize it so bit 8 becomes bit
+| DBL_MANT_DIG-32 (to do the rounding); later we will shift right.
+ swap d0
+ swap d1
+ movew d1,d0
+ swap d2
+ movew d2,d1
+ swap d3
+ movew d3,d2
+ movew IMM (0),d3
+#ifndef __mcf5200__
+ lsrl IMM (1),d0
+ roxrl IMM (1),d1
+ roxrl IMM (1),d2
+ roxrl IMM (1),d3
+ lsrl IMM (1),d0
+ roxrl IMM (1),d1
+ roxrl IMM (1),d2
+ roxrl IMM (1),d3
+ lsrl IMM (1),d0
+ roxrl IMM (1),d1
+ roxrl IMM (1),d2
+ roxrl IMM (1),d3
+#else
+ moveq IMM (29),d6
+ lsrl IMM (3),d3
+ movel d2,d7
+ lsll d6,d7
+ orl d7,d3
+ lsrl IMM (3),d2
+ movel d1,d7
+ lsll d6,d7
+ orl d7,d2
+ lsrl IMM (3),d1
+ movel d0,d7
+ lsll d6,d7
+ orl d7,d1
+ lsrl IMM (3),d0
+#endif
+
+| Now round, check for over- and underflow, and exit.
+ movel a0,d7 | get sign bit back into d7
+ movew IMM (MULTIPLY),d5
+
+ btst IMM (DBL_MANT_DIG+1-32),d0
+ beq Lround$exit
+#ifndef __mcf5200__
+ lsrl IMM (1),d0
+ roxrl IMM (1),d1
+ addw IMM (1),d4
+#else
+ lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 10f
+ bset IMM (31),d1
+10: lsrl IMM (1),d0
+ addl IMM (1),d4
+#endif
+ bra Lround$exit
+
+Lmuldf$inop:
+ movew IMM (MULTIPLY),d5
+ bra Ld$inop
+
+Lmuldf$b$nf:
+ movew IMM (MULTIPLY),d5
+ movel a0,d7 | get sign bit back into d7
+ tstl d3 | we know d2 == 0x7ff00000, so check d3
+ bne Ld$inop | if d3 <> 0 b is NaN
+ bra Ld$overflow | else we have overflow (since a is finite)
+
+Lmuldf$a$nf:
+ movew IMM (MULTIPLY),d5
+ movel a0,d7 | get sign bit back into d7
+ tstl d1 | we know d0 == 0x7ff00000, so check d1
+ bne Ld$inop | if d1 <> 0 a is NaN
+ bra Ld$overflow | else signal overflow
+
+| If either number is zero return zero, unless the other is +/-INFINITY or
+| NaN, in which case we return NaN.
+Lmuldf$b$0:
+ movew IMM (MULTIPLY),d5
+#ifndef __mcf5200__
+ exg d2,d0 | put b (==0) into d0-d1
+ exg d3,d1 | and a (with sign bit cleared) into d2-d3
+#else
+ movel d2,d7
+ movel d0,d2
+ movel d7,d0
+ movel d3,d7
+ movel d1,d3
+ movel d7,d1
+#endif
+ bra 1f
+Lmuldf$a$0:
+ movel a6@(16),d2 | put b into d2-d3 again
+ movel a6@(20),d3 |
+ bclr IMM (31),d2 | clear sign bit
+1: cmpl IMM (0x7ff00000),d2 | check for non-finiteness
+ bge Ld$inop | in case NaN or +/-INFINITY return NaN
+ lea SYM (_fpCCR),a0
+ movew IMM (0),a0@
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6
+ rts
+
+| If a number is denormalized we put an exponent of 1 but do not put the
+| hidden bit back into the fraction; instead we shift left until bit 21
+| (the hidden bit) is set, adjusting the exponent accordingly. We do this
+| to ensure that the product of the fractions is close to 1.
+Lmuldf$a$den:
+ movel IMM (1),d4
+ andl d6,d0
+1: addl d1,d1 | shift a left until bit 20 is set
+ addxl d0,d0 |
+#ifndef __mcf5200__
+ subw IMM (1),d4 | and adjust exponent
+#else
+ subl IMM (1),d4 | and adjust exponent
+#endif
+ btst IMM (20),d0 |
+ bne Lmuldf$1 |
+ bra 1b
+
+Lmuldf$b$den:
+ movel IMM (1),d5
+ andl d6,d2
+1: addl d3,d3 | shift b left until bit 20 is set
+ addxl d2,d2 |
+#ifndef __mcf5200__
+ subw IMM (1),d5 | and adjust exponent
+#else
+ subql IMM (1),d5 | and adjust exponent
+#endif
+ btst IMM (20),d2 |
+ bne Lmuldf$2 |
+ bra 1b
+
+
+|=============================================================================
+| __divdf3
+|=============================================================================
+
+| double __divdf3(double, double);
+SYM (__divdf3):
+#ifndef __mcf5200__
+ link a6,IMM (0)
+ moveml d2-d7,sp@-
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
+ movel a6@(8),d0 | get a into d0-d1
+ movel a6@(12),d1 |
+ movel a6@(16),d2 | and b into d2-d3
+ movel a6@(20),d3 |
+ movel d0,d7 | d7 will hold the sign of the result
+ eorl d2,d7 |
+ andl IMM (0x80000000),d7
+ movel d7,a0 | save sign into a0
+ movel IMM (0x7ff00000),d7 | useful constant (+INFINITY)
+ movel d7,d6 | another (mask for fraction)
+ notl d6 |
+ bclr IMM (31),d0 | get rid of a's sign bit '
+ movel d0,d4 |
+ orl d1,d4 |
+ beq Ldivdf$a$0 | branch if a is zero
+ movel d0,d4 |
+ bclr IMM (31),d2 | get rid of b's sign bit '
+ movel d2,d5 |
+ orl d3,d5 |
+ beq Ldivdf$b$0 | branch if b is zero
+ movel d2,d5
+ cmpl d7,d0 | is a big?
+ bhi Ldivdf$inop | if a is NaN return NaN
+ beq Ldivdf$a$nf | if d0 == 0x7ff00000 we check d1
+ cmpl d7,d2 | now compare b with INFINITY
+ bhi Ldivdf$inop | if b is NaN return NaN
+ beq Ldivdf$b$nf | if d2 == 0x7ff00000 we check d3
+| Here we have both numbers finite and nonzero (and with no sign bit).
+| Now we get the exponents into d4 and d5 and normalize the numbers to
+| ensure that the ratio of the fractions is around 1. We do this by
+| making sure that both numbers have bit #DBL_MANT_DIG-32-1 (hidden bit)
+| set, even if they were denormalized to start with.
+| Thus, the result will satisfy: 2 > result > 1/2.
+ andl d7,d4 | and isolate exponent in d4
+ beq Ldivdf$a$den | if exponent is zero we have a denormalized
+ andl d6,d0 | and isolate fraction
+ orl IMM (0x00100000),d0 | and put hidden bit back
+ swap d4 | I like exponents in the first byte
+#ifndef __mcf5200__
+ lsrw IMM (4),d4 |
+#else
+ lsrl IMM (4),d4 |
+#endif
+Ldivdf$1: |
+ andl d7,d5 |
+ beq Ldivdf$b$den |
+ andl d6,d2 |
+ orl IMM (0x00100000),d2
+ swap d5 |
+#ifndef __mcf5200__
+ lsrw IMM (4),d5 |
+#else
+ lsrl IMM (4),d5 |
+#endif
+Ldivdf$2: |
+#ifndef __mcf5200__
+ subw d5,d4 | subtract exponents
+ addw IMM (D_BIAS),d4 | and add bias
+#else
+ subl d5,d4 | subtract exponents
+ addl IMM (D_BIAS),d4 | and add bias
+#endif
+
+| We are now ready to do the division. We have prepared things in such a way
+| that the ratio of the fractions will be less than 2 but greater than 1/2.
+| At this point the registers in use are:
+| d0-d1 hold a (first operand, bit DBL_MANT_DIG-32=0, bit
+| DBL_MANT_DIG-1-32=1)
+| d2-d3 hold b (second operand, bit DBL_MANT_DIG-32=1)
+| d4 holds the difference of the exponents, corrected by the bias
+| a0 holds the sign of the ratio
+
+| To do the rounding correctly we need to keep information about the
+| nonsignificant bits. One way to do this would be to do the division
+| using four registers; another is to use two registers (as originally
+| I did), but use a sticky bit to preserve information about the
+| fractional part. Note that we can keep that info in a1, which is not
+| used.
+ movel IMM (0),d6 | d6-d7 will hold the result
+ movel d6,d7 |
+ movel IMM (0),a1 | and a1 will hold the sticky bit
+
+ movel IMM (DBL_MANT_DIG-32+1),d5
+
+1: cmpl d0,d2 | is a < b?
+ bhi 3f | if b > a skip the following
+ beq 4f | if d0==d2 check d1 and d3
+2: subl d3,d1 |
+ subxl d2,d0 | a <-- a - b
+ bset d5,d6 | set the corresponding bit in d6
+3: addl d1,d1 | shift a by 1
+ addxl d0,d0 |
+#ifndef __mcf5200__
+ dbra d5,1b | and branch back
+#else
+ subql IMM (1), d5
+ bpl 1b
+#endif
+ bra 5f
+4: cmpl d1,d3 | here d0==d2, so check d1 and d3
+ bhi 3b | if d1 > d2 skip the subtraction
+ bra 2b | else go do it
+5:
+| Here we have to start setting the bits in the second long.
+ movel IMM (31),d5 | again d5 is counter
+
+1: cmpl d0,d2 | is a < b?
+ bhi 3f | if b > a skip the following
+ beq 4f | if d0==d2 check d1 and d3
+2: subl d3,d1 |
+ subxl d2,d0 | a <-- a - b
+ bset d5,d7 | set the corresponding bit in d7
+3: addl d1,d1 | shift a by 1
+ addxl d0,d0 |
+#ifndef __mcf5200__
+ dbra d5,1b | and branch back
+#else
+ subql IMM (1), d5
+ bpl 1b
+#endif
+ bra 5f
+4: cmpl d1,d3 | here d0==d2, so check d1 and d3
+ bhi 3b | if d1 > d2 skip the subtraction
+ bra 2b | else go do it
+5:
+| Now go ahead checking until we hit a one, which we store in d2.
+ movel IMM (DBL_MANT_DIG),d5
+1: cmpl d2,d0 | is a < b?
+ bhi 4f | if b < a, exit
+ beq 3f | if d0==d2 check d1 and d3
+2: addl d1,d1 | shift a by 1
+ addxl d0,d0 |
+#ifndef __mcf5200__
+ dbra d5,1b | and branch back
+#else
+ subql IMM (1), d5
+ bpl 1b
+#endif
+ movel IMM (0),d2 | here no sticky bit was found
+ movel d2,d3
+ bra 5f
+3: cmpl d1,d3 | here d0==d2, so check d1 and d3
+ bhi 2b | if d1 > d2 go back
+4:
+| Here put the sticky bit in d2-d3 (in the position which actually corresponds
+| to it; if you don't do this the algorithm loses in some cases). '
+ movel IMM (0),d2
+ movel d2,d3
+#ifndef __mcf5200__
+ subw IMM (DBL_MANT_DIG),d5
+ addw IMM (63),d5
+ cmpw IMM (31),d5
+#else
+ subl IMM (DBL_MANT_DIG),d5
+ addl IMM (63),d5
+ cmpl IMM (31),d5
+#endif
+ bhi 2f
+1: bset d5,d3
+ bra 5f
+#ifndef __mcf5200__
+ subw IMM (32),d5
+#else
+ subl IMM (32),d5
+#endif
+2: bset d5,d2
+5:
+| Finally we are finished! Move the longs in the address registers to
+| their final destination:
+ movel d6,d0
+ movel d7,d1
+ movel IMM (0),d3
+
+| Here we have finished the division, with the result in d0-d1-d2-d3, with
+| 2^21 <= d6 < 2^23. Thus bit 23 is not set, but bit 22 could be set.
+| If it is not, then definitely bit 21 is set. Normalize so bit 22 is
+| not set:
+ btst IMM (DBL_MANT_DIG-32+1),d0
+ beq 1f
+#ifndef __mcf5200__
+ lsrl IMM (1),d0
+ roxrl IMM (1),d1
+ roxrl IMM (1),d2
+ roxrl IMM (1),d3
+ addw IMM (1),d4
+#else
+ lsrl IMM (1),d3
+ btst IMM (0),d2
+ beq 10f
+ bset IMM (31),d3
+10: lsrl IMM (1),d2
+ btst IMM (0),d1
+ beq 11f
+ bset IMM (31),d2
+11: lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 12f
+ bset IMM (31),d1
+12: lsrl IMM (1),d0
+ addl IMM (1),d4
+#endif
+1:
+| Now round, check for over- and underflow, and exit.
+ movel a0,d7 | restore sign bit to d7
+ movew IMM (DIVIDE),d5
+ bra Lround$exit
+
+Ldivdf$inop:
+ movew IMM (DIVIDE),d5
+ bra Ld$inop
+
+Ldivdf$a$0:
+| If a is zero check to see whether b is zero also. In that case return
+| NaN; then check if b is NaN, and return NaN also in that case. Else
+| return zero.
+ movew IMM (DIVIDE),d5
+ bclr IMM (31),d2 |
+ movel d2,d4 |
+ orl d3,d4 |
+ beq Ld$inop | if b is also zero return NaN
+ cmpl IMM (0x7ff00000),d2 | check for NaN
+ bhi Ld$inop |
+ blt 1f |
+ tstl d3 |
+ bne Ld$inop |
+1: movel IMM (0),d0 | else return zero
+ movel d0,d1 |
+ lea SYM (_fpCCR),a0 | clear exception flags
+ movew IMM (0),a0@ |
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7 |
+#else
+ moveml sp@,d2-d7 |
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6 |
+ rts |
+
+Ldivdf$b$0:
+ movew IMM (DIVIDE),d5
+| If we got here a is not zero. Check if a is NaN; in that case return NaN,
+| else return +/-INFINITY. Remember that a is in d0 with the sign bit
+| cleared already.
+ movel a0,d7 | put a's sign bit back in d7 '
+ cmpl IMM (0x7ff00000),d0 | compare d0 with INFINITY
+ bhi Ld$inop | if larger it is NaN
+ tstl d1 |
+ bne Ld$inop |
+ bra Ld$div$0 | else signal DIVIDE_BY_ZERO
+
+Ldivdf$b$nf:
+ movew IMM (DIVIDE),d5
+| If d2 == 0x7ff00000 we have to check d3.
+ tstl d3 |
+ bne Ld$inop | if d3 <> 0, b is NaN
+ bra Ld$underflow | else b is +/-INFINITY, so signal underflow
+
+Ldivdf$a$nf:
+ movew IMM (DIVIDE),d5
+| If d0 == 0x7ff00000 we have to check d1.
+ tstl d1 |
+ bne Ld$inop | if d1 <> 0, a is NaN
+| If a is INFINITY we have to check b
+ cmpl d7,d2 | compare b with INFINITY
+ bge Ld$inop | if b is NaN or INFINITY return NaN
+ tstl d3 |
+ bne Ld$inop |
+ bra Ld$overflow | else return overflow
+
+| If a number is denormalized we put an exponent of 1 but do not put the
+| bit back into the fraction.
+Ldivdf$a$den:
+ movel IMM (1),d4
+ andl d6,d0
+1: addl d1,d1 | shift a left until bit 20 is set
+ addxl d0,d0
+#ifndef __mcf5200__
+ subw IMM (1),d4 | and adjust exponent
+#else
+ subl IMM (1),d4 | and adjust exponent
+#endif
+ btst IMM (DBL_MANT_DIG-32-1),d0
+ bne Ldivdf$1
+ bra 1b
+
+Ldivdf$b$den:
+ movel IMM (1),d5
+ andl d6,d2
+1: addl d3,d3 | shift b left until bit 20 is set
+ addxl d2,d2
+#ifndef __mcf5200__
+ subw IMM (1),d5 | and adjust exponent
+#else
+ subql IMM (1),d5 | and adjust exponent
+#endif
+ btst IMM (DBL_MANT_DIG-32-1),d2
+ bne Ldivdf$2
+ bra 1b
+
+Lround$exit:
+| This is a common exit point for __muldf3 and __divdf3. When they enter
+| this point the sign of the result is in d7, the result in d0-d1, normalized
+| so that 2^21 <= d0 < 2^22, and the exponent is in the lower byte of d4.
+
+| First check for underlow in the exponent:
+#ifndef __mcf5200__
+ cmpw IMM (-DBL_MANT_DIG-1),d4
+#else
+ cmpl IMM (-DBL_MANT_DIG-1),d4
+#endif
+ blt Ld$underflow
+| It could happen that the exponent is less than 1, in which case the
+| number is denormalized. In this case we shift right and adjust the
+| exponent until it becomes 1 or the fraction is zero (in the latter case
+| we signal underflow and return zero).
+ movel d7,a0 |
+ movel IMM (0),d6 | use d6-d7 to collect bits flushed right
+ movel d6,d7 | use d6-d7 to collect bits flushed right
+#ifndef __mcf5200__
+ cmpw IMM (1),d4 | if the exponent is less than 1 we
+#else
+ cmpl IMM (1),d4 | if the exponent is less than 1 we
+#endif
+ bge 2f | have to shift right (denormalize)
+1:
+#ifndef __mcf5200__
+ addw IMM (1),d4 | adjust the exponent
+ lsrl IMM (1),d0 | shift right once
+ roxrl IMM (1),d1 |
+ roxrl IMM (1),d2 |
+ roxrl IMM (1),d3 |
+ roxrl IMM (1),d6 |
+ roxrl IMM (1),d7 |
+ cmpw IMM (1),d4 | is the exponent 1 already?
+#else
+ addl IMM (1),d4 | adjust the exponent
+ lsrl IMM (1),d7
+ btst IMM (0),d6
+ beq 13f
+ bset IMM (31),d7
+13: lsrl IMM (1),d6
+ btst IMM (0),d3
+ beq 14f
+ bset IMM (31),d6
+14: lsrl IMM (1),d3
+ btst IMM (0),d2
+ beq 10f
+ bset IMM (31),d3
+10: lsrl IMM (1),d2
+ btst IMM (0),d1
+ beq 11f
+ bset IMM (31),d2
+11: lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 12f
+ bset IMM (31),d1
+12: lsrl IMM (1),d0
+ cmpl IMM (1),d4 | is the exponent 1 already?
+#endif
+ beq 2f | if not loop back
+ bra 1b |
+ bra Ld$underflow | safety check, shouldn't execute '
+2: orl d6,d2 | this is a trick so we don't lose '
+ orl d7,d3 | the bits which were flushed right
+ movel a0,d7 | get back sign bit into d7
+| Now call the rounding routine (which takes care of denormalized numbers):
+ lea Lround$0,a0 | to return from rounding routine
+ lea SYM (_fpCCR),a1 | check the rounding mode
+#ifdef __mcf5200__
+ clrl d6
+#endif
+ movew a1@(6),d6 | rounding mode in d6
+ beq Lround$to$nearest
+#ifndef __mcf5200__
+ cmpw IMM (ROUND_TO_PLUS),d6
+#else
+ cmpl IMM (ROUND_TO_PLUS),d6
+#endif
+ bhi Lround$to$minus
+ blt Lround$to$zero
+ bra Lround$to$plus
+Lround$0:
+| Here we have a correctly rounded result (either normalized or denormalized).
+
+| Here we should have either a normalized number or a denormalized one, and
+| the exponent is necessarily larger or equal to 1 (so we don't have to '
+| check again for underflow!). We have to check for overflow or for a
+| denormalized number (which also signals underflow).
+| Check for overflow (i.e., exponent >= 0x7ff).
+#ifndef __mcf5200__
+ cmpw IMM (0x07ff),d4
+#else
+ cmpl IMM (0x07ff),d4
+#endif
+ bge Ld$overflow
+| Now check for a denormalized number (exponent==0):
+ movew d4,d4
+ beq Ld$den
+1:
+| Put back the exponents and sign and return.
+#ifndef __mcf5200__
+ lslw IMM (4),d4 | exponent back to fourth byte
+#else
+ lsll IMM (4),d4 | exponent back to fourth byte
+#endif
+ bclr IMM (DBL_MANT_DIG-32-1),d0
+ swap d0 | and put back exponent
+#ifndef __mcf5200__
+ orw d4,d0 |
+#else
+ orl d4,d0 |
+#endif
+ swap d0 |
+ orl d7,d0 | and sign also
+
+ lea SYM (_fpCCR),a0
+ movew IMM (0),a0@
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6
+ rts
+
+|=============================================================================
+| __negdf2
+|=============================================================================
+
+| double __negdf2(double, double);
+SYM (__negdf2):
+#ifndef __mcf5200__
+ link a6,IMM (0)
+ moveml d2-d7,sp@-
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
+ movew IMM (NEGATE),d5
+ movel a6@(8),d0 | get number to negate in d0-d1
+ movel a6@(12),d1 |
+ bchg IMM (31),d0 | negate
+ movel d0,d2 | make a positive copy (for the tests)
+ bclr IMM (31),d2 |
+ movel d2,d4 | check for zero
+ orl d1,d4 |
+ beq 2f | if zero (either sign) return +zero
+ cmpl IMM (0x7ff00000),d2 | compare to +INFINITY
+ blt 1f | if finite, return
+ bhi Ld$inop | if larger (fraction not zero) is NaN
+ tstl d1 | if d2 == 0x7ff00000 check d1
+ bne Ld$inop |
+ movel d0,d7 | else get sign and return INFINITY
+ andl IMM (0x80000000),d7
+ bra Ld$infty
+1: lea SYM (_fpCCR),a0
+ movew IMM (0),a0@
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6
+ rts
+2: bclr IMM (31),d0
+ bra 1b
+
+|=============================================================================
+| __cmpdf2
+|=============================================================================
+
+GREATER = 1
+LESS = -1
+EQUAL = 0
+
+| int __cmpdf2(double, double);
+SYM (__cmpdf2):
+#ifndef __mcf5200__
+ link a6,IMM (0)
+ moveml d2-d7,sp@- | save registers
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
+ movew IMM (COMPARE),d5
+ movel a6@(8),d0 | get first operand
+ movel a6@(12),d1 |
+ movel a6@(16),d2 | get second operand
+ movel a6@(20),d3 |
+| First check if a and/or b are (+/-) zero and in that case clear
+| the sign bit.
+ movel d0,d6 | copy signs into d6 (a) and d7(b)
+ bclr IMM (31),d0 | and clear signs in d0 and d2
+ movel d2,d7 |
+ bclr IMM (31),d2 |
+ cmpl IMM (0x7fff0000),d0 | check for a == NaN
+ bhi Ld$inop | if d0 > 0x7ff00000, a is NaN
+ beq Lcmpdf$a$nf | if equal can be INFINITY, so check d1
+ movel d0,d4 | copy into d4 to test for zero
+ orl d1,d4 |
+ beq Lcmpdf$a$0 |
+Lcmpdf$0:
+ cmpl IMM (0x7fff0000),d2 | check for b == NaN
+ bhi Ld$inop | if d2 > 0x7ff00000, b is NaN
+ beq Lcmpdf$b$nf | if equal can be INFINITY, so check d3
+ movel d2,d4 |
+ orl d3,d4 |
+ beq Lcmpdf$b$0 |
+Lcmpdf$1:
+| Check the signs
+ eorl d6,d7
+ bpl 1f
+| If the signs are not equal check if a >= 0
+ tstl d6
+ bpl Lcmpdf$a$gt$b | if (a >= 0 && b < 0) => a > b
+ bmi Lcmpdf$b$gt$a | if (a < 0 && b >= 0) => a < b
+1:
+| If the signs are equal check for < 0
+ tstl d6
+ bpl 1f
+| If both are negative exchange them
+#ifndef __mcf5200__
+ exg d0,d2
+ exg d1,d3
+#else
+ movel d0,d7
+ movel d2,d0
+ movel d7,d2
+ movel d1,d7
+ movel d3,d1
+ movel d7,d3
+#endif
+1:
+| Now that they are positive we just compare them as longs (does this also
+| work for denormalized numbers?).
+ cmpl d0,d2
+ bhi Lcmpdf$b$gt$a | |b| > |a|
+ bne Lcmpdf$a$gt$b | |b| < |a|
+| If we got here d0 == d2, so we compare d1 and d3.
+ cmpl d1,d3
+ bhi Lcmpdf$b$gt$a | |b| > |a|
+ bne Lcmpdf$a$gt$b | |b| < |a|
+| If we got here a == b.
+ movel IMM (EQUAL),d0
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7 | put back the registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6
+ rts
+Lcmpdf$a$gt$b:
+ movel IMM (GREATER),d0
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7 | put back the registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6
+ rts
+Lcmpdf$b$gt$a:
+ movel IMM (LESS),d0
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7 | put back the registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6
+ rts
+
+Lcmpdf$a$0:
+ bclr IMM (31),d6
+ bra Lcmpdf$0
+Lcmpdf$b$0:
+ bclr IMM (31),d7
+ bra Lcmpdf$1
+
+Lcmpdf$a$nf:
+ tstl d1
+ bne Ld$inop
+ bra Lcmpdf$0
+
+Lcmpdf$b$nf:
+ tstl d3
+ bne Ld$inop
+ bra Lcmpdf$1
+
+|=============================================================================
+| rounding routines
+|=============================================================================
+
+| The rounding routines expect the number to be normalized in registers
+| d0-d1-d2-d3, with the exponent in register d4. They assume that the
+| exponent is larger or equal to 1. They return a properly normalized number
+| if possible, and a denormalized number otherwise. The exponent is returned
+| in d4.
+
+Lround$to$nearest:
+| We now normalize as suggested by D. Knuth ("Seminumerical Algorithms"):
+| Here we assume that the exponent is not too small (this should be checked
+| before entering the rounding routine), but the number could be denormalized.
+
+| Check for denormalized numbers:
+1: btst IMM (DBL_MANT_DIG-32),d0
+ bne 2f | if set the number is normalized
+| Normalize shifting left until bit #DBL_MANT_DIG-32 is set or the exponent
+| is one (remember that a denormalized number corresponds to an
+| exponent of -D_BIAS+1).
+#ifndef __mcf5200__
+ cmpw IMM (1),d4 | remember that the exponent is at least one
+#else
+ cmpl IMM (1),d4 | remember that the exponent is at least one
+#endif
+ beq 2f | an exponent of one means denormalized
+ addl d3,d3 | else shift and adjust the exponent
+ addxl d2,d2 |
+ addxl d1,d1 |
+ addxl d0,d0 |
+#ifndef __mcf5200__
+ dbra d4,1b |
+#else
+ subql IMM (1), d4
+ bpl 1b
+#endif
+2:
+| Now round: we do it as follows: after the shifting we can write the
+| fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2.
+| If delta < 1, do nothing. If delta > 1, add 1 to f.
+| If delta == 1, we make sure the rounded number will be even (odd?)
+| (after shifting).
+ btst IMM (0),d1 | is delta < 1?
+ beq 2f | if so, do not do anything
+ orl d2,d3 | is delta == 1?
+ bne 1f | if so round to even
+ movel d1,d3 |
+ andl IMM (2),d3 | bit 1 is the last significant bit
+ movel IMM (0),d2 |
+ addl d3,d1 |
+ addxl d2,d0 |
+ bra 2f |
+1: movel IMM (1),d3 | else add 1
+ movel IMM (0),d2 |
+ addl d3,d1 |
+ addxl d2,d0
+| Shift right once (because we used bit #DBL_MANT_DIG-32!).
+2:
+#ifndef __mcf5200__
+ lsrl IMM (1),d0
+ roxrl IMM (1),d1
+#else
+ lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 10f
+ bset IMM (31),d1
+10: lsrl IMM (1),d0
+#endif
+
+| Now check again bit #DBL_MANT_DIG-32 (rounding could have produced a
+| 'fraction overflow' ...).
+ btst IMM (DBL_MANT_DIG-32),d0
+ beq 1f
+#ifndef __mcf5200__
+ lsrl IMM (1),d0
+ roxrl IMM (1),d1
+ addw IMM (1),d4
+#else
+ lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 10f
+ bset IMM (31),d1
+10: lsrl IMM (1),d0
+ addl IMM (1),d4
+#endif
+1:
+| If bit #DBL_MANT_DIG-32-1 is clear we have a denormalized number, so we
+| have to put the exponent to zero and return a denormalized number.
+ btst IMM (DBL_MANT_DIG-32-1),d0
+ beq 1f
+ jmp a0@
+1: movel IMM (0),d4
+ jmp a0@
+
+Lround$to$zero:
+Lround$to$plus:
+Lround$to$minus:
+ jmp a0@
+#endif /* L_double */
+
+#ifdef L_float
+
+ .globl SYM (_fpCCR)
+ .globl $_exception_handler
+
+QUIET_NaN = 0xffffffff
+SIGNL_NaN = 0x7f800001
+INFINITY = 0x7f800000
+
+F_MAX_EXP = 0xff
+F_BIAS = 126
+FLT_MAX_EXP = F_MAX_EXP - F_BIAS
+FLT_MIN_EXP = 1 - F_BIAS
+FLT_MANT_DIG = 24
+
+INEXACT_RESULT = 0x0001
+UNDERFLOW = 0x0002
+OVERFLOW = 0x0004
+DIVIDE_BY_ZERO = 0x0008
+INVALID_OPERATION = 0x0010
+
+SINGLE_FLOAT = 1
+
+NOOP = 0
+ADD = 1
+MULTIPLY = 2
+DIVIDE = 3
+NEGATE = 4
+COMPARE = 5
+EXTENDSFDF = 6
+TRUNCDFSF = 7
+
+UNKNOWN = -1
+ROUND_TO_NEAREST = 0 | round result to nearest representable value
+ROUND_TO_ZERO = 1 | round result towards zero
+ROUND_TO_PLUS = 2 | round result towards plus infinity
+ROUND_TO_MINUS = 3 | round result towards minus infinity
+
+| Entry points:
+
+ .globl SYM (__addsf3)
+ .globl SYM (__subsf3)
+ .globl SYM (__mulsf3)
+ .globl SYM (__divsf3)
+ .globl SYM (__negsf2)
+ .globl SYM (__cmpsf2)
+
+| These are common routines to return and signal exceptions.
+
+ .text
+ .even
+
+Lf$den:
+| Return and signal a denormalized number
+ orl d7,d0
+ movew IMM (INEXACT_RESULT+UNDERFLOW),d7
+ moveq IMM (SINGLE_FLOAT),d6
+ jmp $_exception_handler
+
+Lf$infty:
+Lf$overflow:
+| Return a properly signed INFINITY and set the exception flags
+ movel IMM (INFINITY),d0
+ orl d7,d0
+ movew IMM (INEXACT_RESULT+OVERFLOW),d7
+ moveq IMM (SINGLE_FLOAT),d6
+ jmp $_exception_handler
+
+Lf$underflow:
+| Return 0 and set the exception flags
+ movel IMM (0),d0
+ movew IMM (INEXACT_RESULT+UNDERFLOW),d7
+ moveq IMM (SINGLE_FLOAT),d6
+ jmp $_exception_handler
+
+Lf$inop:
+| Return a quiet NaN and set the exception flags
+ movel IMM (QUIET_NaN),d0
+ movew IMM (INEXACT_RESULT+INVALID_OPERATION),d7
+ moveq IMM (SINGLE_FLOAT),d6
+ jmp $_exception_handler
+
+Lf$div$0:
+| Return a properly signed INFINITY and set the exception flags
+ movel IMM (INFINITY),d0
+ orl d7,d0
+ movew IMM (INEXACT_RESULT+DIVIDE_BY_ZERO),d7
+ moveq IMM (SINGLE_FLOAT),d6
+ jmp $_exception_handler
+
+|=============================================================================
+|=============================================================================
+| single precision routines
+|=============================================================================
+|=============================================================================
+
+| A single precision floating point number (float) has the format:
+|
+| struct _float {
+| unsigned int sign : 1; /* sign bit */
+| unsigned int exponent : 8; /* exponent, shifted by 126 */
+| unsigned int fraction : 23; /* fraction */
+| } float;
+|
+| Thus sizeof(float) = 4 (32 bits).
+|
+| All the routines are callable from C programs, and return the result
+| in the single register d0. They also preserve all registers except
+| d0-d1 and a0-a1.
+
+|=============================================================================
+| __subsf3
+|=============================================================================
+
+| float __subsf3(float, float);
+SYM (__subsf3):
+ bchg IMM (31),sp@(8) | change sign of second operand
+ | and fall through
+|=============================================================================
+| __addsf3
+|=============================================================================
+
+| float __addsf3(float, float);
+SYM (__addsf3):
+#ifndef __mcf5200__
+ link a6,IMM (0) | everything will be done in registers
+ moveml d2-d7,sp@- | save all data registers but d0-d1
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
+ movel a6@(8),d0 | get first operand
+ movel a6@(12),d1 | get second operand
+ movel d0,d6 | get d0's sign bit '
+ addl d0,d0 | check and clear sign bit of a
+ beq Laddsf$b | if zero return second operand
+ movel d1,d7 | save b's sign bit '
+ addl d1,d1 | get rid of sign bit
+ beq Laddsf$a | if zero return first operand
+
+ movel d6,a0 | save signs in address registers
+ movel d7,a1 | so we can use d6 and d7
+
+| Get the exponents and check for denormalized and/or infinity.
+
+ movel IMM (0x00ffffff),d4 | mask to get fraction
+ movel IMM (0x01000000),d5 | mask to put hidden bit back
+
+ movel d0,d6 | save a to get exponent
+ andl d4,d0 | get fraction in d0
+ notl d4 | make d4 into a mask for the exponent
+ andl d4,d6 | get exponent in d6
+ beq Laddsf$a$den | branch if a is denormalized
+ cmpl d4,d6 | check for INFINITY or NaN
+ beq Laddsf$nf
+ swap d6 | put exponent into first word
+ orl d5,d0 | and put hidden bit back
+Laddsf$1:
+| Now we have a's exponent in d6 (second byte) and the mantissa in d0. '
+ movel d1,d7 | get exponent in d7
+ andl d4,d7 |
+ beq Laddsf$b$den | branch if b is denormalized
+ cmpl d4,d7 | check for INFINITY or NaN
+ beq Laddsf$nf
+ swap d7 | put exponent into first word
+ notl d4 | make d4 into a mask for the fraction
+ andl d4,d1 | get fraction in d1
+ orl d5,d1 | and put hidden bit back
+Laddsf$2:
+| Now we have b's exponent in d7 (second byte) and the mantissa in d1. '
+
+| Note that the hidden bit corresponds to bit #FLT_MANT_DIG-1, and we
+| shifted right once, so bit #FLT_MANT_DIG is set (so we have one extra
+| bit).
+
+ movel d1,d2 | move b to d2, since we want to use
+ | two registers to do the sum
+ movel IMM (0),d1 | and clear the new ones
+ movel d1,d3 |
+
+| Here we shift the numbers in registers d0 and d1 so the exponents are the
+| same, and put the largest exponent in d6. Note that we are using two
+| registers for each number (see the discussion by D. Knuth in "Seminumerical
+| Algorithms").
+#ifndef __mcf5200__
+ cmpw d6,d7 | compare exponents
+#else
+ cmpl d6,d7 | compare exponents
+#endif
+ beq Laddsf$3 | if equal don't shift '
+ bhi 5f | branch if second exponent largest
+1:
+ subl d6,d7 | keep the largest exponent
+ negl d7
+#ifndef __mcf5200__
+ lsrw IMM (8),d7 | put difference in lower byte
+#else
+ lsrl IMM (8),d7 | put difference in lower byte
+#endif
+| if difference is too large we don't shift (actually, we can just exit) '
+#ifndef __mcf5200__
+ cmpw IMM (FLT_MANT_DIG+2),d7
+#else
+ cmpl IMM (FLT_MANT_DIG+2),d7
+#endif
+ bge Laddsf$b$small
+#ifndef __mcf5200__
+ cmpw IMM (16),d7 | if difference >= 16 swap
+#else
+ cmpl IMM (16),d7 | if difference >= 16 swap
+#endif
+ bge 4f
+2:
+#ifndef __mcf5200__
+ subw IMM (1),d7
+#else
+ subql IMM (1), d7
+#endif
+3:
+#ifndef __mcf5200__
+ lsrl IMM (1),d2 | shift right second operand
+ roxrl IMM (1),d3
+ dbra d7,3b
+#else
+ lsrl IMM (1),d3
+ btst IMM (0),d2
+ beq 10f
+ bset IMM (31),d3
+10: lsrl IMM (1),d2
+ subql IMM (1), d7
+ bpl 3b
+#endif
+ bra Laddsf$3
+4:
+ movew d2,d3
+ swap d3
+ movew d3,d2
+ swap d2
+#ifndef __mcf5200__
+ subw IMM (16),d7
+#else
+ subl IMM (16),d7
+#endif
+ bne 2b | if still more bits, go back to normal case
+ bra Laddsf$3
+5:
+#ifndef __mcf5200__
+ exg d6,d7 | exchange the exponents
+#else
+ eorl d6,d7
+ eorl d7,d6
+ eorl d6,d7
+#endif
+ subl d6,d7 | keep the largest exponent
+ negl d7 |
+#ifndef __mcf5200__
+ lsrw IMM (8),d7 | put difference in lower byte
+#else
+ lsrl IMM (8),d7 | put difference in lower byte
+#endif
+| if difference is too large we don't shift (and exit!) '
+#ifndef __mcf5200__
+ cmpw IMM (FLT_MANT_DIG+2),d7
+#else
+ cmpl IMM (FLT_MANT_DIG+2),d7
+#endif
+ bge Laddsf$a$small
+#ifndef __mcf5200__
+ cmpw IMM (16),d7 | if difference >= 16 swap
+#else
+ cmpl IMM (16),d7 | if difference >= 16 swap
+#endif
+ bge 8f
+6:
+#ifndef __mcf5200__
+ subw IMM (1),d7
+#else
+ subl IMM (1),d7
+#endif
+7:
+#ifndef __mcf5200__
+ lsrl IMM (1),d0 | shift right first operand
+ roxrl IMM (1),d1
+ dbra d7,7b
+#else
+ lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 10f
+ bset IMM (31),d1
+10: lsrl IMM (1),d0
+ subql IMM (1),d7
+ bpl 7b
+#endif
+ bra Laddsf$3
+8:
+ movew d0,d1
+ swap d1
+ movew d1,d0
+ swap d0
+#ifndef __mcf5200__
+ subw IMM (16),d7
+#else
+ subl IMM (16),d7
+#endif
+ bne 6b | if still more bits, go back to normal case
+ | otherwise we fall through
+
+| Now we have a in d0-d1, b in d2-d3, and the largest exponent in d6 (the
+| signs are stored in a0 and a1).
+
+Laddsf$3:
+| Here we have to decide whether to add or subtract the numbers
+#ifndef __mcf5200__
+ exg d6,a0 | get signs back
+ exg d7,a1 | and save the exponents
+#else
+ movel d6,d4
+ movel a0,d6
+ movel d4,a0
+ movel d7,d4
+ movel a1,d7
+ movel d4,a1
+#endif
+ eorl d6,d7 | combine sign bits
+ bmi Lsubsf$0 | if negative a and b have opposite
+ | sign so we actually subtract the
+ | numbers
+
+| Here we have both positive or both negative
+#ifndef __mcf5200__
+ exg d6,a0 | now we have the exponent in d6
+#else
+ movel d6,d4
+ movel a0,d6
+ movel d4,a0
+#endif
+ movel a0,d7 | and sign in d7
+ andl IMM (0x80000000),d7
+| Here we do the addition.
+ addl d3,d1
+ addxl d2,d0
+| Note: now we have d2, d3, d4 and d5 to play with!
+
+| Put the exponent, in the first byte, in d2, to use the "standard" rounding
+| routines:
+ movel d6,d2
+#ifndef __mcf5200__
+ lsrw IMM (8),d2
+#else
+ lsrl IMM (8),d2
+#endif
+
+| Before rounding normalize so bit #FLT_MANT_DIG is set (we will consider
+| the case of denormalized numbers in the rounding routine itself).
+| As in the addition (not in the subtraction!) we could have set
+| one more bit we check this:
+ btst IMM (FLT_MANT_DIG+1),d0
+ beq 1f
+#ifndef __mcf5200__
+ lsrl IMM (1),d0
+ roxrl IMM (1),d1
+#else
+ lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 10f
+ bset IMM (31),d1
+10: lsrl IMM (1),d0
+#endif
+ addl IMM (1),d2
+1:
+ lea Laddsf$4,a0 | to return from rounding routine
+ lea SYM (_fpCCR),a1 | check the rounding mode
+#ifdef __mcf5200__
+ clrl d6
+#endif
+ movew a1@(6),d6 | rounding mode in d6
+ beq Lround$to$nearest
+#ifndef __mcf5200__
+ cmpw IMM (ROUND_TO_PLUS),d6
+#else
+ cmpl IMM (ROUND_TO_PLUS),d6
+#endif
+ bhi Lround$to$minus
+ blt Lround$to$zero
+ bra Lround$to$plus
+Laddsf$4:
+| Put back the exponent, but check for overflow.
+#ifndef __mcf5200__
+ cmpw IMM (0xff),d2
+#else
+ cmpl IMM (0xff),d2
+#endif
+ bhi 1f
+ bclr IMM (FLT_MANT_DIG-1),d0
+#ifndef __mcf5200__
+ lslw IMM (7),d2
+#else
+ lsll IMM (7),d2
+#endif
+ swap d2
+ orl d2,d0
+ bra Laddsf$ret
+1:
+ movew IMM (ADD),d5
+ bra Lf$overflow
+
+Lsubsf$0:
+| We are here if a > 0 and b < 0 (sign bits cleared).
+| Here we do the subtraction.
+ movel d6,d7 | put sign in d7
+ andl IMM (0x80000000),d7
+
+ subl d3,d1 | result in d0-d1
+ subxl d2,d0 |
+ beq Laddsf$ret | if zero just exit
+ bpl 1f | if positive skip the following
+ bchg IMM (31),d7 | change sign bit in d7
+ negl d1
+ negxl d0
+1:
+#ifndef __mcf5200__
+ exg d2,a0 | now we have the exponent in d2
+ lsrw IMM (8),d2 | put it in the first byte
+#else
+ movel d2,d4
+ movel a0,d2
+ movel d4,a0
+ lsrl IMM (8),d2 | put it in the first byte
+#endif
+
+| Now d0-d1 is positive and the sign bit is in d7.
+
+| Note that we do not have to normalize, since in the subtraction bit
+| #FLT_MANT_DIG+1 is never set, and denormalized numbers are handled by
+| the rounding routines themselves.
+ lea Lsubsf$1,a0 | to return from rounding routine
+ lea SYM (_fpCCR),a1 | check the rounding mode
+#ifdef __mcf5200__
+ clrl d6
+#endif
+ movew a1@(6),d6 | rounding mode in d6
+ beq Lround$to$nearest
+#ifndef __mcf5200__
+ cmpw IMM (ROUND_TO_PLUS),d6
+#else
+ cmpl IMM (ROUND_TO_PLUS),d6
+#endif
+ bhi Lround$to$minus
+ blt Lround$to$zero
+ bra Lround$to$plus
+Lsubsf$1:
+| Put back the exponent (we can't have overflow!). '
+ bclr IMM (FLT_MANT_DIG-1),d0
+#ifndef __mcf5200__
+ lslw IMM (7),d2
+#else
+ lsll IMM (7),d2
+#endif
+ swap d2
+ orl d2,d0
+ bra Laddsf$ret
+
+| If one of the numbers was too small (difference of exponents >=
+| FLT_MANT_DIG+2) we return the other (and now we don't have to '
+| check for finiteness or zero).
+Laddsf$a$small:
+ movel a6@(12),d0
+ lea SYM (_fpCCR),a0
+ movew IMM (0),a0@
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7 | restore data registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6 | and return
+ rts
+
+Laddsf$b$small:
+ movel a6@(8),d0
+ lea SYM (_fpCCR),a0
+ movew IMM (0),a0@
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7 | restore data registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6 | and return
+ rts
+
+| If the numbers are denormalized remember to put exponent equal to 1.
+
+Laddsf$a$den:
+ movel d5,d6 | d5 contains 0x01000000
+ swap d6
+ bra Laddsf$1
+
+Laddsf$b$den:
+ movel d5,d7
+ swap d7
+ notl d4 | make d4 into a mask for the fraction
+ | (this was not executed after the jump)
+ bra Laddsf$2
+
+| The rest is mainly code for the different results which can be
+| returned (checking always for +/-INFINITY and NaN).
+
+Laddsf$b:
+| Return b (if a is zero).
+ movel a6@(12),d0
+ bra 1f
+Laddsf$a:
+| Return a (if b is zero).
+ movel a6@(8),d0
+1:
+ movew IMM (ADD),d5
+| We have to check for NaN and +/-infty.
+ movel d0,d7
+ andl IMM (0x80000000),d7 | put sign in d7
+ bclr IMM (31),d0 | clear sign
+ cmpl IMM (INFINITY),d0 | check for infty or NaN
+ bge 2f
+ movel d0,d0 | check for zero (we do this because we don't '
+ bne Laddsf$ret | want to return -0 by mistake
+ bclr IMM (31),d7 | if zero be sure to clear sign
+ bra Laddsf$ret | if everything OK just return
+2:
+| The value to be returned is either +/-infty or NaN
+ andl IMM (0x007fffff),d0 | check for NaN
+ bne Lf$inop | if mantissa not zero is NaN
+ bra Lf$infty
+
+Laddsf$ret:
+| Normal exit (a and b nonzero, result is not NaN nor +/-infty).
+| We have to clear the exception flags (just the exception type).
+ lea SYM (_fpCCR),a0
+ movew IMM (0),a0@
+ orl d7,d0 | put sign bit
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7 | restore data registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6 | and return
+ rts
+
+Laddsf$ret$den:
+| Return a denormalized number (for addition we don't signal underflow) '
+ lsrl IMM (1),d0 | remember to shift right back once
+ bra Laddsf$ret | and return
+
+| Note: when adding two floats of the same sign if either one is
+| NaN we return NaN without regard to whether the other is finite or
+| not. When subtracting them (i.e., when adding two numbers of
+| opposite signs) things are more complicated: if both are INFINITY
+| we return NaN, if only one is INFINITY and the other is NaN we return
+| NaN, but if it is finite we return INFINITY with the corresponding sign.
+
+Laddsf$nf:
+ movew IMM (ADD),d5
+| This could be faster but it is not worth the effort, since it is not
+| executed very often. We sacrifice speed for clarity here.
+ movel a6@(8),d0 | get the numbers back (remember that we
+ movel a6@(12),d1 | did some processing already)
+ movel IMM (INFINITY),d4 | useful constant (INFINITY)
+ movel d0,d2 | save sign bits
+ movel d1,d3
+ bclr IMM (31),d0 | clear sign bits
+ bclr IMM (31),d1
+| We know that one of them is either NaN of +/-INFINITY
+| Check for NaN (if either one is NaN return NaN)
+ cmpl d4,d0 | check first a (d0)
+ bhi Lf$inop
+ cmpl d4,d1 | check now b (d1)
+ bhi Lf$inop
+| Now comes the check for +/-INFINITY. We know that both are (maybe not
+| finite) numbers, but we have to check if both are infinite whether we
+| are adding or subtracting them.
+ eorl d3,d2 | to check sign bits
+ bmi 1f
+ movel d0,d7
+ andl IMM (0x80000000),d7 | get (common) sign bit
+ bra Lf$infty
+1:
+| We know one (or both) are infinite, so we test for equality between the
+| two numbers (if they are equal they have to be infinite both, so we
+| return NaN).
+ cmpl d1,d0 | are both infinite?
+ beq Lf$inop | if so return NaN
+
+ movel d0,d7
+ andl IMM (0x80000000),d7 | get a's sign bit '
+ cmpl d4,d0 | test now for infinity
+ beq Lf$infty | if a is INFINITY return with this sign
+ bchg IMM (31),d7 | else we know b is INFINITY and has
+ bra Lf$infty | the opposite sign
+
+|=============================================================================
+| __mulsf3
+|=============================================================================
+
+| float __mulsf3(float, float);
+SYM (__mulsf3):
+#ifndef __mcf5200__
+ link a6,IMM (0)
+ moveml d2-d7,sp@-
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
+ movel a6@(8),d0 | get a into d0
+ movel a6@(12),d1 | and b into d1
+ movel d0,d7 | d7 will hold the sign of the product
+ eorl d1,d7 |
+ andl IMM (0x80000000),d7
+ movel IMM (INFINITY),d6 | useful constant (+INFINITY)
+ movel d6,d5 | another (mask for fraction)
+ notl d5 |
+ movel IMM (0x00800000),d4 | this is to put hidden bit back
+ bclr IMM (31),d0 | get rid of a's sign bit '
+ movel d0,d2 |
+ beq Lmulsf$a$0 | branch if a is zero
+ bclr IMM (31),d1 | get rid of b's sign bit '
+ movel d1,d3 |
+ beq Lmulsf$b$0 | branch if b is zero
+ cmpl d6,d0 | is a big?
+ bhi Lmulsf$inop | if a is NaN return NaN
+ beq Lmulsf$inf | if a is INFINITY we have to check b
+ cmpl d6,d1 | now compare b with INFINITY
+ bhi Lmulsf$inop | is b NaN?
+ beq Lmulsf$overflow | is b INFINITY?
+| Here we have both numbers finite and nonzero (and with no sign bit).
+| Now we get the exponents into d2 and d3.
+ andl d6,d2 | and isolate exponent in d2
+ beq Lmulsf$a$den | if exponent is zero we have a denormalized
+ andl d5,d0 | and isolate fraction
+ orl d4,d0 | and put hidden bit back
+ swap d2 | I like exponents in the first byte
+#ifndef __mcf5200__
+ lsrw IMM (7),d2 |
+#else
+ lsrl IMM (7),d2 |
+#endif
+Lmulsf$1: | number
+ andl d6,d3 |
+ beq Lmulsf$b$den |
+ andl d5,d1 |
+ orl d4,d1 |
+ swap d3 |
+#ifndef __mcf5200__
+ lsrw IMM (7),d3 |
+#else
+ lsrl IMM (7),d3 |
+#endif
+Lmulsf$2: |
+#ifndef __mcf5200__
+ addw d3,d2 | add exponents
+ subw IMM (F_BIAS+1),d2 | and subtract bias (plus one)
+#else
+ addl d3,d2 | add exponents
+ subl IMM (F_BIAS+1),d2 | and subtract bias (plus one)
+#endif
+
+| We are now ready to do the multiplication. The situation is as follows:
+| both a and b have bit FLT_MANT_DIG-1 set (even if they were
+| denormalized to start with!), which means that in the product
+| bit 2*(FLT_MANT_DIG-1) (that is, bit 2*FLT_MANT_DIG-2-32 of the
+| high long) is set.
+
+| To do the multiplication let us move the number a little bit around ...
+ movel d1,d6 | second operand in d6
+ movel d0,d5 | first operand in d4-d5
+ movel IMM (0),d4
+ movel d4,d1 | the sums will go in d0-d1
+ movel d4,d0
+
+| now bit FLT_MANT_DIG-1 becomes bit 31:
+ lsll IMM (31-FLT_MANT_DIG+1),d6
+
+| Start the loop (we loop #FLT_MANT_DIG times):
+ movew IMM (FLT_MANT_DIG-1),d3
+1: addl d1,d1 | shift sum
+ addxl d0,d0
+ lsll IMM (1),d6 | get bit bn
+ bcc 2f | if not set skip sum
+ addl d5,d1 | add a
+ addxl d4,d0
+2:
+#ifndef __mcf5200__
+ dbf d3,1b | loop back
+#else
+ subql IMM (1),d3
+ bpl 1b
+#endif
+
+| Now we have the product in d0-d1, with bit (FLT_MANT_DIG - 1) + FLT_MANT_DIG
+| (mod 32) of d0 set. The first thing to do now is to normalize it so bit
+| FLT_MANT_DIG is set (to do the rounding).
+#ifndef __mcf5200__
+ rorl IMM (6),d1
+ swap d1
+ movew d1,d3
+ andw IMM (0x03ff),d3
+ andw IMM (0xfd00),d1
+#else
+ movel d1,d3
+ lsll IMM (8),d1
+ addl d1,d1
+ addl d1,d1
+ moveq IMM (22),d5
+ lsrl d5,d3
+ orl d3,d1
+ andl IMM (0xfffffd00),d1
+#endif
+ lsll IMM (8),d0
+ addl d0,d0
+ addl d0,d0
+#ifndef __mcf5200__
+ orw d3,d0
+#else
+ orl d3,d0
+#endif
+
+ movew IMM (MULTIPLY),d5
+
+ btst IMM (FLT_MANT_DIG+1),d0
+ beq Lround$exit
+#ifndef __mcf5200__
+ lsrl IMM (1),d0
+ roxrl IMM (1),d1
+ addw IMM (1),d2
+#else
+ lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 10f
+ bset IMM (31),d1
+10: lsrl IMM (1),d0
+ addql IMM (1),d2
+#endif
+ bra Lround$exit
+
+Lmulsf$inop:
+ movew IMM (MULTIPLY),d5
+ bra Lf$inop
+
+Lmulsf$overflow:
+ movew IMM (MULTIPLY),d5
+ bra Lf$overflow
+
+Lmulsf$inf:
+ movew IMM (MULTIPLY),d5
+| If either is NaN return NaN; else both are (maybe infinite) numbers, so
+| return INFINITY with the correct sign (which is in d7).
+ cmpl d6,d1 | is b NaN?
+ bhi Lf$inop | if so return NaN
+ bra Lf$overflow | else return +/-INFINITY
+
+| If either number is zero return zero, unless the other is +/-INFINITY,
+| or NaN, in which case we return NaN.
+Lmulsf$b$0:
+| Here d1 (==b) is zero.
+ movel d1,d0 | put b into d0 (just a zero)
+ movel a6@(8),d1 | get a again to check for non-finiteness
+ bra 1f
+Lmulsf$a$0:
+ movel a6@(12),d1 | get b again to check for non-finiteness
+1: bclr IMM (31),d1 | clear sign bit
+ cmpl IMM (INFINITY),d1 | and check for a large exponent
+ bge Lf$inop | if b is +/-INFINITY or NaN return NaN
+ lea SYM (_fpCCR),a0 | else return zero
+ movew IMM (0),a0@ |
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7 |
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6 |
+ rts |
+
+| If a number is denormalized we put an exponent of 1 but do not put the
+| hidden bit back into the fraction; instead we shift left until bit 23
+| (the hidden bit) is set, adjusting the exponent accordingly. We do this
+| to ensure that the product of the fractions is close to 1.
+Lmulsf$a$den:
+ movel IMM (1),d2
+ andl d5,d0
+1: addl d0,d0 | shift a left (until bit 23 is set)
+#ifndef __mcf5200__
+ subw IMM (1),d2 | and adjust exponent
+#else
+ subql IMM (1),d2 | and adjust exponent
+#endif
+ btst IMM (FLT_MANT_DIG-1),d0
+ bne Lmulsf$1 |
+ bra 1b | else loop back
+
+Lmulsf$b$den:
+ movel IMM (1),d3
+ andl d5,d1
+1: addl d1,d1 | shift b left until bit 23 is set
+#ifndef __mcf5200__
+ subw IMM (1),d3 | and adjust exponent
+#else
+ subl IMM (1),d3 | and adjust exponent
+#endif
+ btst IMM (FLT_MANT_DIG-1),d1
+ bne Lmulsf$2 |
+ bra 1b | else loop back
+
+|=============================================================================
+| __divsf3
+|=============================================================================
+
+| float __divsf3(float, float);
+SYM (__divsf3):
+#ifndef __mcf5200__
+ link a6,IMM (0)
+ moveml d2-d7,sp@-
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
+ movel a6@(8),d0 | get a into d0
+ movel a6@(12),d1 | and b into d1
+ movel d0,d7 | d7 will hold the sign of the result
+ eorl d1,d7 |
+ andl IMM (0x80000000),d7 |
+ movel IMM (INFINITY),d6 | useful constant (+INFINITY)
+ movel d6,d5 | another (mask for fraction)
+ notl d5 |
+ movel IMM (0x00800000),d4 | this is to put hidden bit back
+ bclr IMM (31),d0 | get rid of a's sign bit '
+ movel d0,d2 |
+ beq Ldivsf$a$0 | branch if a is zero
+ bclr IMM (31),d1 | get rid of b's sign bit '
+ movel d1,d3 |
+ beq Ldivsf$b$0 | branch if b is zero
+ cmpl d6,d0 | is a big?
+ bhi Ldivsf$inop | if a is NaN return NaN
+ beq Ldivsf$inf | if a is INFINITY we have to check b
+ cmpl d6,d1 | now compare b with INFINITY
+ bhi Ldivsf$inop | if b is NaN return NaN
+ beq Ldivsf$underflow
+| Here we have both numbers finite and nonzero (and with no sign bit).
+| Now we get the exponents into d2 and d3 and normalize the numbers to
+| ensure that the ratio of the fractions is close to 1. We do this by
+| making sure that bit #FLT_MANT_DIG-1 (hidden bit) is set.
+ andl d6,d2 | and isolate exponent in d2
+ beq Ldivsf$a$den | if exponent is zero we have a denormalized
+ andl d5,d0 | and isolate fraction
+ orl d4,d0 | and put hidden bit back
+ swap d2 | I like exponents in the first byte
+#ifndef __mcf5200__
+ lsrw IMM (7),d2 |
+#else
+ lsrl IMM (7),d2 |
+#endif
+Ldivsf$1: |
+ andl d6,d3 |
+ beq Ldivsf$b$den |
+ andl d5,d1 |
+ orl d4,d1 |
+ swap d3 |
+#ifndef __mcf5200__
+ lsrw IMM (7),d3 |
+#else
+ lsrl IMM (7),d3 |
+#endif
+Ldivsf$2: |
+#ifndef __mcf5200__
+ subw d3,d2 | subtract exponents
+ addw IMM (F_BIAS),d2 | and add bias
+#else
+ subl d3,d2 | subtract exponents
+ addl IMM (F_BIAS),d2 | and add bias
+#endif
+
+| We are now ready to do the division. We have prepared things in such a way
+| that the ratio of the fractions will be less than 2 but greater than 1/2.
+| At this point the registers in use are:
+| d0 holds a (first operand, bit FLT_MANT_DIG=0, bit FLT_MANT_DIG-1=1)
+| d1 holds b (second operand, bit FLT_MANT_DIG=1)
+| d2 holds the difference of the exponents, corrected by the bias
+| d7 holds the sign of the ratio
+| d4, d5, d6 hold some constants
+ movel d7,a0 | d6-d7 will hold the ratio of the fractions
+ movel IMM (0),d6 |
+ movel d6,d7
+
+ movew IMM (FLT_MANT_DIG+1),d3
+1: cmpl d0,d1 | is a < b?
+ bhi 2f |
+ bset d3,d6 | set a bit in d6
+ subl d1,d0 | if a >= b a <-- a-b
+ beq 3f | if a is zero, exit
+2: addl d0,d0 | multiply a by 2
+#ifndef __mcf5200__
+ dbra d3,1b
+#else
+ subql IMM (1),d3
+ bpl 1b
+#endif
+
+| Now we keep going to set the sticky bit ...
+ movew IMM (FLT_MANT_DIG),d3
+1: cmpl d0,d1
+ ble 2f
+ addl d0,d0
+#ifndef __mcf5200__
+ dbra d3,1b
+#else
+ subql IMM(1),d3
+ bpl 1b
+#endif
+ movel IMM (0),d1
+ bra 3f
+2: movel IMM (0),d1
+#ifndef __mcf5200__
+ subw IMM (FLT_MANT_DIG),d3
+ addw IMM (31),d3
+#else
+ subl IMM (FLT_MANT_DIG),d3
+ addl IMM (31),d3
+#endif
+ bset d3,d1
+3:
+ movel d6,d0 | put the ratio in d0-d1
+ movel a0,d7 | get sign back
+
+| Because of the normalization we did before we are guaranteed that
+| d0 is smaller than 2^26 but larger than 2^24. Thus bit 26 is not set,
+| bit 25 could be set, and if it is not set then bit 24 is necessarily set.
+ btst IMM (FLT_MANT_DIG+1),d0
+ beq 1f | if it is not set, then bit 24 is set
+ lsrl IMM (1),d0 |
+#ifndef __mcf5200__
+ addw IMM (1),d2 |
+#else
+ addl IMM (1),d2 |
+#endif
+1:
+| Now round, check for over- and underflow, and exit.
+ movew IMM (DIVIDE),d5
+ bra Lround$exit
+
+Ldivsf$inop:
+ movew IMM (DIVIDE),d5
+ bra Lf$inop
+
+Ldivsf$overflow:
+ movew IMM (DIVIDE),d5
+ bra Lf$overflow
+
+Ldivsf$underflow:
+ movew IMM (DIVIDE),d5
+ bra Lf$underflow
+
+Ldivsf$a$0:
+ movew IMM (DIVIDE),d5
+| If a is zero check to see whether b is zero also. In that case return
+| NaN; then check if b is NaN, and return NaN also in that case. Else
+| return zero.
+ andl IMM (0x7fffffff),d1 | clear sign bit and test b
+ beq Lf$inop | if b is also zero return NaN
+ cmpl IMM (INFINITY),d1 | check for NaN
+ bhi Lf$inop |
+ movel IMM (0),d0 | else return zero
+ lea SYM (_fpCCR),a0 |
+ movew IMM (0),a0@ |
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7 |
+#else
+ moveml sp@,d2-d7 |
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6 |
+ rts |
+
+Ldivsf$b$0:
+ movew IMM (DIVIDE),d5
+| If we got here a is not zero. Check if a is NaN; in that case return NaN,
+| else return +/-INFINITY. Remember that a is in d0 with the sign bit
+| cleared already.
+ cmpl IMM (INFINITY),d0 | compare d0 with INFINITY
+ bhi Lf$inop | if larger it is NaN
+ bra Lf$div$0 | else signal DIVIDE_BY_ZERO
+
+Ldivsf$inf:
+ movew IMM (DIVIDE),d5
+| If a is INFINITY we have to check b
+ cmpl IMM (INFINITY),d1 | compare b with INFINITY
+ bge Lf$inop | if b is NaN or INFINITY return NaN
+ bra Lf$overflow | else return overflow
+
+| If a number is denormalized we put an exponent of 1 but do not put the
+| bit back into the fraction.
+Ldivsf$a$den:
+ movel IMM (1),d2
+ andl d5,d0
+1: addl d0,d0 | shift a left until bit FLT_MANT_DIG-1 is set
+#ifndef __mcf5200__
+ subw IMM (1),d2 | and adjust exponent
+#else
+ subl IMM (1),d2 | and adjust exponent
+#endif
+ btst IMM (FLT_MANT_DIG-1),d0
+ bne Ldivsf$1
+ bra 1b
+
+Ldivsf$b$den:
+ movel IMM (1),d3
+ andl d5,d1
+1: addl d1,d1 | shift b left until bit FLT_MANT_DIG is set
+#ifndef __mcf5200__
+ subw IMM (1),d3 | and adjust exponent
+#else
+ subl IMM (1),d3 | and adjust exponent
+#endif
+ btst IMM (FLT_MANT_DIG-1),d1
+ bne Ldivsf$2
+ bra 1b
+
+Lround$exit:
+| This is a common exit point for __mulsf3 and __divsf3.
+
+| First check for underlow in the exponent:
+#ifndef __mcf5200__
+ cmpw IMM (-FLT_MANT_DIG-1),d2
+#else
+ cmpl IMM (-FLT_MANT_DIG-1),d2
+#endif
+ blt Lf$underflow
+| It could happen that the exponent is less than 1, in which case the
+| number is denormalized. In this case we shift right and adjust the
+| exponent until it becomes 1 or the fraction is zero (in the latter case
+| we signal underflow and return zero).
+ movel IMM (0),d6 | d6 is used temporarily
+#ifndef __mcf5200__
+ cmpw IMM (1),d2 | if the exponent is less than 1 we
+#else
+ cmpl IMM (1),d2 | if the exponent is less than 1 we
+#endif
+ bge 2f | have to shift right (denormalize)
+1:
+#ifndef __mcf5200__
+ addw IMM (1),d2 | adjust the exponent
+ lsrl IMM (1),d0 | shift right once
+ roxrl IMM (1),d1 |
+ roxrl IMM (1),d6 | d6 collect bits we would lose otherwise
+ cmpw IMM (1),d2 | is the exponent 1 already?
+#else
+ addql IMM (1),d2 | adjust the exponent
+ lsrl IMM (1),d6
+ btst IMM (0),d1
+ beq 11f
+ bset IMM (31),d6
+11: lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 10f
+ bset IMM (31),d1
+10: lsrl IMM (1),d0
+ cmpl IMM (1),d2 | is the exponent 1 already?
+#endif
+ beq 2f | if not loop back
+ bra 1b |
+ bra Lf$underflow | safety check, shouldn't execute '
+2: orl d6,d1 | this is a trick so we don't lose '
+ | the extra bits which were flushed right
+| Now call the rounding routine (which takes care of denormalized numbers):
+ lea Lround$0,a0 | to return from rounding routine
+ lea SYM (_fpCCR),a1 | check the rounding mode
+#ifdef __mcf5200__
+ clrl d6
+#endif
+ movew a1@(6),d6 | rounding mode in d6
+ beq Lround$to$nearest
+#ifndef __mcf5200__
+ cmpw IMM (ROUND_TO_PLUS),d6
+#else
+ cmpl IMM (ROUND_TO_PLUS),d6
+#endif
+ bhi Lround$to$minus
+ blt Lround$to$zero
+ bra Lround$to$plus
+Lround$0:
+| Here we have a correctly rounded result (either normalized or denormalized).
+
+| Here we should have either a normalized number or a denormalized one, and
+| the exponent is necessarily larger or equal to 1 (so we don't have to '
+| check again for underflow!). We have to check for overflow or for a
+| denormalized number (which also signals underflow).
+| Check for overflow (i.e., exponent >= 255).
+#ifndef __mcf5200__
+ cmpw IMM (0x00ff),d2
+#else
+ cmpl IMM (0x00ff),d2
+#endif
+ bge Lf$overflow
+| Now check for a denormalized number (exponent==0).
+ movew d2,d2
+ beq Lf$den
+1:
+| Put back the exponents and sign and return.
+#ifndef __mcf5200__
+ lslw IMM (7),d2 | exponent back to fourth byte
+#else
+ lsll IMM (7),d2 | exponent back to fourth byte
+#endif
+ bclr IMM (FLT_MANT_DIG-1),d0
+ swap d0 | and put back exponent
+#ifndef __mcf5200__
+ orw d2,d0 |
+#else
+ orl d2,d0
+#endif
+ swap d0 |
+ orl d7,d0 | and sign also
+
+ lea SYM (_fpCCR),a0
+ movew IMM (0),a0@
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6
+ rts
+
+|=============================================================================
+| __negsf2
+|=============================================================================
+
+| This is trivial and could be shorter if we didn't bother checking for NaN '
+| and +/-INFINITY.
+
+| float __negsf2(float);
+SYM (__negsf2):
+#ifndef __mcf5200__
+ link a6,IMM (0)
+ moveml d2-d7,sp@-
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
+ movew IMM (NEGATE),d5
+ movel a6@(8),d0 | get number to negate in d0
+ bchg IMM (31),d0 | negate
+ movel d0,d1 | make a positive copy
+ bclr IMM (31),d1 |
+ tstl d1 | check for zero
+ beq 2f | if zero (either sign) return +zero
+ cmpl IMM (INFINITY),d1 | compare to +INFINITY
+ blt 1f |
+ bhi Lf$inop | if larger (fraction not zero) is NaN
+ movel d0,d7 | else get sign and return INFINITY
+ andl IMM (0x80000000),d7
+ bra Lf$infty
+1: lea SYM (_fpCCR),a0
+ movew IMM (0),a0@
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6
+ rts
+2: bclr IMM (31),d0
+ bra 1b
+
+|=============================================================================
+| __cmpsf2
+|=============================================================================
+
+GREATER = 1
+LESS = -1
+EQUAL = 0
+
+| int __cmpsf2(float, float);
+SYM (__cmpsf2):
+#ifndef __mcf5200__
+ link a6,IMM (0)
+ moveml d2-d7,sp@- | save registers
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
+ movew IMM (COMPARE),d5
+ movel a6@(8),d0 | get first operand
+ movel a6@(12),d1 | get second operand
+| Check if either is NaN, and in that case return garbage and signal
+| INVALID_OPERATION. Check also if either is zero, and clear the signs
+| if necessary.
+ movel d0,d6
+ andl IMM (0x7fffffff),d0
+ beq Lcmpsf$a$0
+ cmpl IMM (0x7f800000),d0
+ bhi Lf$inop
+Lcmpsf$1:
+ movel d1,d7
+ andl IMM (0x7fffffff),d1
+ beq Lcmpsf$b$0
+ cmpl IMM (0x7f800000),d1
+ bhi Lf$inop
+Lcmpsf$2:
+| Check the signs
+ eorl d6,d7
+ bpl 1f
+| If the signs are not equal check if a >= 0
+ tstl d6
+ bpl Lcmpsf$a$gt$b | if (a >= 0 && b < 0) => a > b
+ bmi Lcmpsf$b$gt$a | if (a < 0 && b >= 0) => a < b
+1:
+| If the signs are equal check for < 0
+ tstl d6
+ bpl 1f
+| If both are negative exchange them
+#ifndef __mcf5200__
+ exg d0,d1
+#else
+ movel d0,d7
+ movel d1,d0
+ movel d7,d1
+#endif
+1:
+| Now that they are positive we just compare them as longs (does this also
+| work for denormalized numbers?).
+ cmpl d0,d1
+ bhi Lcmpsf$b$gt$a | |b| > |a|
+ bne Lcmpsf$a$gt$b | |b| < |a|
+| If we got here a == b.
+ movel IMM (EQUAL),d0
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7 | put back the registers
+#else
+ moveml sp@,d2-d7
+#endif
+ unlk a6
+ rts
+Lcmpsf$a$gt$b:
+ movel IMM (GREATER),d0
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7 | put back the registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6
+ rts
+Lcmpsf$b$gt$a:
+ movel IMM (LESS),d0
+#ifndef __mcf5200__
+ moveml sp@+,d2-d7 | put back the registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
+ unlk a6
+ rts
+
+Lcmpsf$a$0:
+ bclr IMM (31),d6
+ bra Lcmpsf$1
+Lcmpsf$b$0:
+ bclr IMM (31),d7
+ bra Lcmpsf$2
+
+|=============================================================================
+| rounding routines
+|=============================================================================
+
+| The rounding routines expect the number to be normalized in registers
+| d0-d1, with the exponent in register d2. They assume that the
+| exponent is larger or equal to 1. They return a properly normalized number
+| if possible, and a denormalized number otherwise. The exponent is returned
+| in d2.
+
+Lround$to$nearest:
+| We now normalize as suggested by D. Knuth ("Seminumerical Algorithms"):
+| Here we assume that the exponent is not too small (this should be checked
+| before entering the rounding routine), but the number could be denormalized.
+
+| Check for denormalized numbers:
+1: btst IMM (FLT_MANT_DIG),d0
+ bne 2f | if set the number is normalized
+| Normalize shifting left until bit #FLT_MANT_DIG is set or the exponent
+| is one (remember that a denormalized number corresponds to an
+| exponent of -F_BIAS+1).
+#ifndef __mcf5200__
+ cmpw IMM (1),d2 | remember that the exponent is at least one
+#else
+ cmpl IMM (1),d2 | remember that the exponent is at least one
+#endif
+ beq 2f | an exponent of one means denormalized
+ addl d1,d1 | else shift and adjust the exponent
+ addxl d0,d0 |
+#ifndef __mcf5200__
+ dbra d2,1b |
+#else
+ subql IMM (1),d2
+ bpl 1b
+#endif
+2:
+| Now round: we do it as follows: after the shifting we can write the
+| fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2.
+| If delta < 1, do nothing. If delta > 1, add 1 to f.
+| If delta == 1, we make sure the rounded number will be even (odd?)
+| (after shifting).
+ btst IMM (0),d0 | is delta < 1?
+ beq 2f | if so, do not do anything
+ tstl d1 | is delta == 1?
+ bne 1f | if so round to even
+ movel d0,d1 |
+ andl IMM (2),d1 | bit 1 is the last significant bit
+ addl d1,d0 |
+ bra 2f |
+1: movel IMM (1),d1 | else add 1
+ addl d1,d0 |
+| Shift right once (because we used bit #FLT_MANT_DIG!).
+2: lsrl IMM (1),d0
+| Now check again bit #FLT_MANT_DIG (rounding could have produced a
+| 'fraction overflow' ...).
+ btst IMM (FLT_MANT_DIG),d0
+ beq 1f
+ lsrl IMM (1),d0
+#ifndef __mcf5200__
+ addw IMM (1),d2
+#else
+ addql IMM (1),d2
+#endif
+1:
+| If bit #FLT_MANT_DIG-1 is clear we have a denormalized number, so we
+| have to put the exponent to zero and return a denormalized number.
+ btst IMM (FLT_MANT_DIG-1),d0
+ beq 1f
+ jmp a0@
+1: movel IMM (0),d2
+ jmp a0@
+
+Lround$to$zero:
+Lround$to$plus:
+Lround$to$minus:
+ jmp a0@
+#endif /* L_float */
+
+| gcc expects the routines __eqdf2, __nedf2, __gtdf2, __gedf2,
+| __ledf2, __ltdf2 to all return the same value as a direct call to
+| __cmpdf2 would. In this implementation, each of these routines
+| simply calls __cmpdf2. It would be more efficient to give the
+| __cmpdf2 routine several names, but separating them out will make it
+| easier to write efficient versions of these routines someday.
+
+#ifdef L_eqdf2
+ .text
+ .proc
+ .globl SYM (__eqdf2)
+SYM (__eqdf2):
+ link a6,IMM (0)
+ movl a6@(20),sp@-
+ movl a6@(16),sp@-
+ movl a6@(12),sp@-
+ movl a6@(8),sp@-
+ jbsr SYM (__cmpdf2)
+ unlk a6
+ rts
+#endif /* L_eqdf2 */
+
+#ifdef L_nedf2
+ .text
+ .proc
+ .globl SYM (__nedf2)
+SYM (__nedf2):
+ link a6,IMM (0)
+ movl a6@(20),sp@-
+ movl a6@(16),sp@-
+ movl a6@(12),sp@-
+ movl a6@(8),sp@-
+ jbsr SYM (__cmpdf2)
+ unlk a6
+ rts
+#endif /* L_nedf2 */
+
+#ifdef L_gtdf2
+ .text
+ .proc
+ .globl SYM (__gtdf2)
+SYM (__gtdf2):
+ link a6,IMM (0)
+ movl a6@(20),sp@-
+ movl a6@(16),sp@-
+ movl a6@(12),sp@-
+ movl a6@(8),sp@-
+ jbsr SYM (__cmpdf2)
+ unlk a6
+ rts
+#endif /* L_gtdf2 */
+
+#ifdef L_gedf2
+ .text
+ .proc
+ .globl SYM (__gedf2)
+SYM (__gedf2):
+ link a6,IMM (0)
+ movl a6@(20),sp@-
+ movl a6@(16),sp@-
+ movl a6@(12),sp@-
+ movl a6@(8),sp@-
+ jbsr SYM (__cmpdf2)
+ unlk a6
+ rts
+#endif /* L_gedf2 */
+
+#ifdef L_ltdf2
+ .text
+ .proc
+ .globl SYM (__ltdf2)
+SYM (__ltdf2):
+ link a6,IMM (0)
+ movl a6@(20),sp@-
+ movl a6@(16),sp@-
+ movl a6@(12),sp@-
+ movl a6@(8),sp@-
+ jbsr SYM (__cmpdf2)
+ unlk a6
+ rts
+#endif /* L_ltdf2 */
+
+#ifdef L_ledf2
+ .text
+ .proc
+ .globl SYM (__ledf2)
+SYM (__ledf2):
+ link a6,IMM (0)
+ movl a6@(20),sp@-
+ movl a6@(16),sp@-
+ movl a6@(12),sp@-
+ movl a6@(8),sp@-
+ jbsr SYM (__cmpdf2)
+ unlk a6
+ rts
+#endif /* L_ledf2 */
+
+| The comments above about __eqdf2, et. al., also apply to __eqsf2,
+| et. al., except that the latter call __cmpsf2 rather than __cmpdf2.
+
+#ifdef L_eqsf2
+ .text
+ .proc
+ .globl SYM (__eqsf2)
+SYM (__eqsf2):
+ link a6,IMM (0)
+ movl a6@(12),sp@-
+ movl a6@(8),sp@-
+ jbsr SYM (__cmpsf2)
+ unlk a6
+ rts
+#endif /* L_eqsf2 */
+
+#ifdef L_nesf2
+ .text
+ .proc
+ .globl SYM (__nesf2)
+SYM (__nesf2):
+ link a6,IMM (0)
+ movl a6@(12),sp@-
+ movl a6@(8),sp@-
+ jbsr SYM (__cmpsf2)
+ unlk a6
+ rts
+#endif /* L_nesf2 */
+
+#ifdef L_gtsf2
+ .text
+ .proc
+ .globl SYM (__gtsf2)
+SYM (__gtsf2):
+ link a6,IMM (0)
+ movl a6@(12),sp@-
+ movl a6@(8),sp@-
+ jbsr SYM (__cmpsf2)
+ unlk a6
+ rts
+#endif /* L_gtsf2 */
+
+#ifdef L_gesf2
+ .text
+ .proc
+ .globl SYM (__gesf2)
+SYM (__gesf2):
+ link a6,IMM (0)
+ movl a6@(12),sp@-
+ movl a6@(8),sp@-
+ jbsr SYM (__cmpsf2)
+ unlk a6
+ rts
+#endif /* L_gesf2 */
+
+#ifdef L_ltsf2
+ .text
+ .proc
+ .globl SYM (__ltsf2)
+SYM (__ltsf2):
+ link a6,IMM (0)
+ movl a6@(12),sp@-
+ movl a6@(8),sp@-
+ jbsr SYM (__cmpsf2)
+ unlk a6
+ rts
+#endif /* L_ltsf2 */
+
+#ifdef L_lesf2
+ .text
+ .proc
+ .globl SYM (__lesf2)
+SYM (__lesf2):
+ link a6,IMM (0)
+ movl a6@(12),sp@-
+ movl a6@(8),sp@-
+ jbsr SYM (__cmpsf2)
+ unlk a6
+ rts
+#endif /* L_lesf2 */
diff --git a/gcc/config/m68k/lb1sun3.asm b/gcc/config/m68k/lb1sun3.asm
new file mode 100755
index 0000000..7b1854c
--- /dev/null
+++ b/gcc/config/m68k/lb1sun3.asm
@@ -0,0 +1,1036 @@
+/* libgcc1 routines for 68000 w/o floating-point hardware,
+ calling the Sun3 floating point support routines. */
+/* Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs without any restriction coming from the use of this
+file. (The General Public License restrictions do apply in other
+respects; for example, they cover modification of the file, and
+distribution when not linked into another program.)
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* As a special exception, if you link this library with files
+ compiled with GCC to produce an executable, this does not cause
+ the resulting executable to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
+
+#ifdef L_mulsi3
+ .text
+ .proc
+ .globl SYM (__mulsi3)
+SYM (__mulsi3):
+ movew sp@(4), d0 /* x0 -> d0 */
+ muluw sp@(10), d0 /* x0*y1 */
+ movew sp@(6), d1 /* x1 -> d1 */
+ muluw sp@(8), d1 /* x1*y0 */
+ addw d1, d0
+ swap d0
+ clrw d0
+ movew sp@(6), d1 /* x1 -> d1 */
+ muluw sp@(10), d1 /* x1*y1 */
+ addl d1, d0
+
+ rts
+#endif /* L_mulsi3 */
+
+#ifdef L_udivsi3
+ .text
+ .proc
+ .globl SYM (__udivsi3)
+SYM (__udivsi3):
+ movel d2, sp@-
+ movel sp@(12), d1 /* d1 = divisor */
+ movel sp@(8), d0 /* d0 = dividend */
+
+ cmpl #0x10000, d1 /* divisor >= 2 ^ 16 ? */
+ jcc L3 /* then try next algorithm */
+ movel d0, d2
+ clrw d2
+ swap d2
+ divu d1, d2 /* high quotient in lower word */
+ movew d2, d0 /* save high quotient */
+ swap d0
+ movew sp@(10), d2 /* get low dividend + high rest */
+ divu d1, d2 /* low quotient */
+ movew d2, d0
+ jra L6
+
+L3: movel d1, d2 /* use d2 as divisor backup */
+L4: lsrl #1, d1 /* shift divisor */
+ lsrl #1, d0 /* shift dividend */
+ cmpl #0x10000, d1 /* still divisor >= 2 ^ 16 ? */
+ jcc L4
+ divu d1, d0 /* now we have 16 bit divisor */
+ andl #0xffff, d0 /* mask out divisor, ignore remainder */
+
+/* Muliply the 16 bit tentative quotient with the 32 bit divisor. Because of
+ the operand ranges, this might give a 33 bit product. If this product is
+ greater than the dividend, the tentative quotient was too large. */
+ movel d2, d1
+ mulu d0, d1 /* low part, 32 bits */
+ swap d2
+ mulu d0, d2 /* high part, at most 17 bits */
+ swap d2 /* align high part with low part */
+ btst #0, d2 /* high part 17 bits? */
+ jne L5 /* if 17 bits, quotient was too large */
+ addl d2, d1 /* add parts */
+ jcs L5 /* if sum is 33 bits, quotient was too large */
+ cmpl sp@(8), d1 /* compare the sum with the dividend */
+ jls L6 /* if sum > dividend, quotient was too large */
+L5: subql #1, d0 /* adjust quotient */
+
+L6: movel sp@+, d2
+ rts
+#endif /* L_udivsi3 */
+
+#ifdef L_divsi3
+ .text
+ .proc
+ .globl SYM (__divsi3)
+SYM (__divsi3):
+ movel d2, sp@-
+
+ moveb #1, d2 /* sign of result stored in d2 (=1 or =-1) */
+ movel sp@(12), d1 /* d1 = divisor */
+ jpl L1
+ negl d1
+ negb d2 /* change sign because divisor <0 */
+L1: movel sp@(8), d0 /* d0 = dividend */
+ jpl L2
+ negl d0
+ negb d2
+
+L2: movel d1, sp@-
+ movel d0, sp@-
+ jbsr SYM (__udivsi3) /* divide abs(dividend) by abs(divisor) */
+ addql #8, sp
+
+ tstb d2
+ jpl L3
+ negl d0
+
+L3: movel sp@+, d2
+ rts
+#endif /* L_divsi3 */
+
+#ifdef L_umodsi3
+ .text
+ .proc
+ .globl SYM (__umodsi3)
+SYM (__umodsi3):
+ movel sp@(8), d1 /* d1 = divisor */
+ movel sp@(4), d0 /* d0 = dividend */
+ movel d1, sp@-
+ movel d0, sp@-
+ jbsr SYM (__udivsi3)
+ addql #8, sp
+ movel sp@(8), d1 /* d1 = divisor */
+ movel d1, sp@-
+ movel d0, sp@-
+ jbsr SYM (__mulsi3) /* d0 = (a/b)*b */
+ addql #8, sp
+ movel sp@(4), d1 /* d1 = dividend */
+ subl d0, d1 /* d1 = a - (a/b)*b */
+ movel d1, d0
+ rts
+#endif /* L_umodsi3 */
+
+#ifdef L_modsi3
+ .text
+ .proc
+ .globl SYM (__modsi3)
+SYM (__modsi3):
+ movel sp@(8), d1 /* d1 = divisor */
+ movel sp@(4), d0 /* d0 = dividend */
+ movel d1, sp@-
+ movel d0, sp@-
+ jbsr SYM (__divsi3)
+ addql #8, sp
+ movel sp@(8), d1 /* d1 = divisor */
+ movel d1, sp@-
+ movel d0, sp@-
+ jbsr SYM (__mulsi3) /* d0 = (a/b)*b */
+ addql #8, sp
+ movel sp@(4), d1 /* d1 = dividend */
+ subl d0, d1 /* d1 = a - (a/b)*b */
+ movel d1, d0
+ rts
+#endif /* L_modsi3 */
+
+
+#ifdef L_divdf3
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 07
+ LF17 = 8
+ LS17 = 0
+ LFF17 = 8
+ LSS17 = 0
+ LV17 = 8
+ .text
+ .globl ___divdf3
+___divdf3:
+|#PROLOGUE# 0
+ link a6,#-8
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ movl a6@(12),d1
+ lea a6@(16),a0
+ jbsr Fdivd
+ movl d0,a6@(-8)
+ movl d1,a6@(-4)
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_divdf3 */
+
+#ifdef L_muldf3
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 07
+ LF17 = 8
+ LS17 = 0
+ LFF17 = 8
+ LSS17 = 0
+ LV17 = 8
+ .text
+ .globl ___muldf3
+___muldf3:
+|#PROLOGUE# 0
+ link a6,#-8
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ movl a6@(12),d1
+ lea a6@(16),a0
+ jbsr Fmuld
+ movl d0,a6@(-8)
+ movl d1,a6@(-4)
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_muldf3 */
+
+#ifdef L_negdf2
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 07
+ LF17 = 8
+ LS17 = 0
+ LFF17 = 8
+ LSS17 = 0
+ LV17 = 8
+ .text
+ .globl ___negdf2
+___negdf2:
+|#PROLOGUE# 0
+ link a6,#-8
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ movl a6@(12),a6@(-4)
+ bchg #31,d0
+ movl d0,a6@(-8)
+ movl a6@(-4),d1
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_negdf2 */
+
+#ifdef L_adddf3
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 07
+ LF17 = 8
+ LS17 = 0
+ LFF17 = 8
+ LSS17 = 0
+ LV17 = 8
+ .text
+ .globl ___adddf3
+___adddf3:
+|#PROLOGUE# 0
+ link a6,#-8
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ movl a6@(12),d1
+ lea a6@(16),a0
+ jbsr Faddd
+ movl d0,a6@(-8)
+ movl d1,a6@(-4)
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_adddf3 */
+
+#ifdef L_subdf3
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 07
+ LF17 = 8
+ LS17 = 0
+ LFF17 = 8
+ LSS17 = 0
+ LV17 = 8
+ .text
+ .globl ___subdf3
+___subdf3:
+|#PROLOGUE# 0
+ link a6,#-8
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ movl a6@(12),d1
+ lea a6@(16),a0
+ jbsr Fsubd
+ movl d0,a6@(-8)
+ movl d1,a6@(-4)
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_subdf3 */
+
+#ifdef L_fixdfsi
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 4
+ LS17 = 128
+ LFF17 = 0
+ LSS17 = 0
+ LV17 = 0
+ .text
+ .globl ___fixdfsi
+___fixdfsi:
+|#PROLOGUE# 0
+ link a6,#-4
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ movl a6@(12),d1
+ jbsr Fintd
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_fixdfsi */
+
+#ifdef L_fixsfsi
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 4
+ LS17 = 128
+ LFF17 = 0
+ LSS17 = 0
+ LV17 = 0
+ .text
+ .globl ___fixsfsi
+___fixsfsi:
+|#PROLOGUE# 0
+ link a6,#-4
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ jbsr Fints
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_fixsfsi */
+
+#ifdef L_floatsidf
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 07
+ LF17 = 8
+ LS17 = 0
+ LFF17 = 8
+ LSS17 = 0
+ LV17 = 8
+ .text
+ .globl ___floatsidf
+___floatsidf:
+|#PROLOGUE# 0
+ link a6,#-8
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ jbsr Ffltd
+ movl d0,a6@(-8)
+ movl d1,a6@(-4)
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_floatsidf */
+
+#ifdef L_floatsisf
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 8
+ LS17 = 128
+ LFF17 = 4
+ LSS17 = 0
+ LV17 = 4
+ .text
+ .globl ___floatsisf
+___floatsisf:
+|#PROLOGUE# 0
+ link a6,#-8
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ jbsr Fflts
+ movl d0,a6@(-4)
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_floatsisf */
+
+#ifdef L_truncdfsf2
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 8
+ LS17 = 128
+ LFF17 = 4
+ LSS17 = 0
+ LV17 = 4
+ .text
+ .globl ___truncdfsf2
+___truncdfsf2:
+|#PROLOGUE# 0
+ link a6,#-8
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ movl a6@(12),d1
+ jbsr Fdtos
+ movl d0,a6@(-4)
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_truncdfsf2 */
+
+#ifdef L_extendsfdf2
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 07
+ LF17 = 8
+ LS17 = 0
+ LFF17 = 8
+ LSS17 = 0
+ LV17 = 8
+ .text
+ .globl ___extendsfdf2
+___extendsfdf2:
+|#PROLOGUE# 0
+ link a6,#-8
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ jbsr Fstod
+ movl d0,a6@(-8)
+ movl d1,a6@(-4)
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_extendsfdf2 */
+
+#ifdef L_addsf3
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 8
+ LS17 = 128
+ LFF17 = 4
+ LSS17 = 0
+ LV17 = 4
+ .text
+ .globl ___addsf3
+___addsf3:
+|#PROLOGUE# 0
+ link a6,#-8
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ movl a6@(12),d1
+ jbsr Fadds
+ movl d0,a6@(-4)
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_addsf3 */
+
+#ifdef L_negsf2
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 8
+ LS17 = 128
+ LFF17 = 4
+ LSS17 = 0
+ LV17 = 4
+ .text
+ .globl ___negsf2
+___negsf2:
+|#PROLOGUE# 0
+ link a6,#-8
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ bchg #31,d0
+ movl d0,a6@(-4)
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_negsf2 */
+
+#ifdef L_subsf3
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 8
+ LS17 = 128
+ LFF17 = 4
+ LSS17 = 0
+ LV17 = 4
+ .text
+ .globl ___subsf3
+___subsf3:
+|#PROLOGUE# 0
+ link a6,#-8
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ movl a6@(12),d1
+ jbsr Fsubs
+ movl d0,a6@(-4)
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_subsf3 */
+
+#ifdef L_mulsf3
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 8
+ LS17 = 128
+ LFF17 = 4
+ LSS17 = 0
+ LV17 = 4
+ .text
+ .globl ___mulsf3
+___mulsf3:
+|#PROLOGUE# 0
+ link a6,#-8
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ movl a6@(12),d1
+ jbsr Fmuls
+ movl d0,a6@(-4)
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_mulsf3 */
+
+#ifdef L_divsf3
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 8
+ LS17 = 128
+ LFF17 = 4
+ LSS17 = 0
+ LV17 = 4
+ .text
+ .globl ___divsf3
+___divsf3:
+|#PROLOGUE# 0
+ link a6,#-8
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ movl a6@(12),d1
+ jbsr Fdivs
+ movl d0,a6@(-4)
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_divsf3 */
+
+#ifdef L_eqdf2
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 4
+ LS17 = 128
+ LFF17 = 0
+ LSS17 = 0
+ LV17 = 0
+ .text
+ .globl ___eqdf2
+___eqdf2:
+|#PROLOGUE# 0
+ link a6,#-4
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ movl a6@(12),d1
+ lea a6@(16),a0
+ jbsr Fcmpd
+ jfeq L77003
+ moveq #1,d0
+ jra L77005
+L77003:
+ moveq #0,d0
+L77005:
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_eqdf2 */
+
+#ifdef L_nedf2
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 8
+ LS17 = 132
+ LFF17 = 0
+ LSS17 = 0
+ LV17 = 0
+ .text
+ .globl ___nedf2
+___nedf2:
+|#PROLOGUE# 0
+ link a6,#-8
+ movl d7,sp@
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ movl a6@(12),d1
+ moveq #0,d7
+ lea a6@(16),a0
+ jbsr Fcmpd
+ sfneq d7
+ negb d7
+ movl d7,d0
+|#PROLOGUE# 2
+ movl a6@(-8),d7
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_nedf2 */
+
+#ifdef L_gtdf2
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 8
+ LS17 = 132
+ LFF17 = 0
+ LSS17 = 0
+ LV17 = 0
+ .text
+ .globl ___gtdf2
+___gtdf2:
+|#PROLOGUE# 0
+ link a6,#-8
+ movl d7,sp@
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ movl a6@(12),d1
+ moveq #0,d7
+ lea a6@(16),a0
+ jbsr Fcmpd
+ sfgt d7
+ negb d7
+ movl d7,d0
+|#PROLOGUE# 2
+ movl a6@(-8),d7
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_gtdf2 */
+
+#ifdef L_gedf2
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 8
+ LS17 = 132
+ LFF17 = 0
+ LSS17 = 0
+ LV17 = 0
+ .text
+ .globl ___gedf2
+___gedf2:
+|#PROLOGUE# 0
+ link a6,#-8
+ movl d7,sp@
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ movl a6@(12),d1
+ moveq #0,d7
+ lea a6@(16),a0
+ jbsr Fcmpd
+ sfge d7
+ negb d7
+ subql #1,d7
+ movl d7,d0
+|#PROLOGUE# 2
+ movl a6@(-8),d7
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_gedf2 */
+
+#ifdef L_ltdf2
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 8
+ LS17 = 132
+ LFF17 = 0
+ LSS17 = 0
+ LV17 = 0
+ .text
+ .globl ___ltdf2
+___ltdf2:
+|#PROLOGUE# 0
+ link a6,#-8
+ movl d7,sp@
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ movl a6@(12),d1
+ moveq #0,d7
+ lea a6@(16),a0
+ jbsr Fcmpd
+ sflt d7
+ negb d7
+ negl d7
+ movl d7,d0
+|#PROLOGUE# 2
+ movl a6@(-8),d7
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_ltdf2 */
+
+#ifdef L_ledf2
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 8
+ LS17 = 132
+ LFF17 = 0
+ LSS17 = 0
+ LV17 = 0
+ .text
+ .globl ___ledf2
+___ledf2:
+|#PROLOGUE# 0
+ link a6,#-8
+ movl d2,sp@
+|#PROLOGUE# 1
+ movl a6@(8),d0
+ movl a6@(12),d1
+ moveq #0,d2
+ lea a6@(16),a0
+ jbsr Fcmpd
+ sfle d2
+ negb d2
+ moveq #1,d0
+ subl d2,d0
+|#PROLOGUE# 2
+ movl a6@(-8),d2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_ledf2 */
+
+#ifdef L_eqsf2
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 4
+ LS17 = 128
+ LFF17 = 0
+ LSS17 = 0
+ LV17 = 0
+ .text
+ .globl ___eqsf2
+___eqsf2:
+|#PROLOGUE# 0
+ link a6,#-4
+|#PROLOGUE# 1
+ movl a6@(12),d1
+ movl a6@(8),d0
+ jbsr Fcmps
+ jfeq L77003
+ moveq #1,d0
+ jra L77005
+L77003:
+ moveq #0,d0
+L77005:
+|#PROLOGUE# 2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_eqsf2 */
+
+#ifdef L_nesf2
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 8
+ LS17 = 132
+ LFF17 = 0
+ LSS17 = 0
+ LV17 = 0
+ .text
+ .globl ___nesf2
+___nesf2:
+|#PROLOGUE# 0
+ link a6,#-8
+ movl d7,sp@
+|#PROLOGUE# 1
+ movl a6@(12),d1
+ movl a6@(8),d0
+ moveq #0,d7
+ jbsr Fcmps
+ sfneq d7
+ negb d7
+ movl d7,d0
+|#PROLOGUE# 2
+ movl a6@(-8),d7
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_nesf2 */
+
+#ifdef L_gtsf2
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 8
+ LS17 = 132
+ LFF17 = 0
+ LSS17 = 0
+ LV17 = 0
+ .text
+ .globl ___gtsf2
+___gtsf2:
+|#PROLOGUE# 0
+ link a6,#-8
+ movl d7,sp@
+|#PROLOGUE# 1
+ movl a6@(12),d1
+ movl a6@(8),d0
+ moveq #0,d7
+ jbsr Fcmps
+ sfgt d7
+ negb d7
+ movl d7,d0
+|#PROLOGUE# 2
+ movl a6@(-8),d7
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_gtsf2 */
+
+#ifdef L_gesf2
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 8
+ LS17 = 132
+ LFF17 = 0
+ LSS17 = 0
+ LV17 = 0
+ .text
+ .globl ___gesf2
+___gesf2:
+|#PROLOGUE# 0
+ link a6,#-8
+ movl d7,sp@
+|#PROLOGUE# 1
+ movl a6@(12),d1
+ movl a6@(8),d0
+ moveq #0,d7
+ jbsr Fcmps
+ sfge d7
+ negb d7
+ subql #1,d7
+ movl d7,d0
+|#PROLOGUE# 2
+ movl a6@(-8),d7
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_gesf2 */
+
+#ifdef L_ltsf2
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 8
+ LS17 = 132
+ LFF17 = 0
+ LSS17 = 0
+ LV17 = 0
+ .text
+ .globl ___ltsf2
+___ltsf2:
+|#PROLOGUE# 0
+ link a6,#-8
+ movl d7,sp@
+|#PROLOGUE# 1
+ movl a6@(12),d1
+ movl a6@(8),d0
+ moveq #0,d7
+ jbsr Fcmps
+ sflt d7
+ negb d7
+ negl d7
+ movl d7,d0
+|#PROLOGUE# 2
+ movl a6@(-8),d7
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_ltsf2 */
+
+#ifdef L_lesf2
+LL0:
+ .data
+ .data
+ .text
+ .proc
+|#PROC# 04
+ LF17 = 8
+ LS17 = 132
+ LFF17 = 0
+ LSS17 = 0
+ LV17 = 0
+ .text
+ .globl ___lesf2
+___lesf2:
+|#PROLOGUE# 0
+ link a6,#-8
+ movl d2,sp@
+|#PROLOGUE# 1
+ movl a6@(12),d1
+ movl a6@(8),d0
+ moveq #0,d2
+ jbsr Fcmps
+ sfle d2
+ negb d2
+ moveq #1,d0
+ subl d2,d0
+|#PROLOGUE# 2
+ movl a6@(-8),d2
+ unlk a6
+|#PROLOGUE# 3
+ rts
+#endif /* L_lesf2 */
+
diff --git a/gcc/config/m68k/linux-aout.h b/gcc/config/m68k/linux-aout.h
new file mode 100755
index 0000000..692725e
--- /dev/null
+++ b/gcc/config/m68k/linux-aout.h
@@ -0,0 +1,77 @@
+/* Definitions for Motorola m68k running Linux-based GNU systems.
+ Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include <m68k/m68k.h>
+#include <linux-aout.h>
+
+/* 68020 with 68881 */
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
+
+#define DBX_DEBUGGING_INFO
+
+#define ASM_COMMENT_START "|"
+
+#define CPP_PREDEFINES \
+ "-Dunix -Dmc68000 -Dmc68020 -Dlinux -Asystem(unix) -Asystem(posix) -Acpu(m68k) -Amachine(m68k)"
+
+#undef CPP_SPEC
+#if TARGET_DEFAULT & MASK_68881
+#define CPP_SPEC \
+ "%{!msoft-float:-D__HAVE_68881__} %{posix:-D_POSIX_SOURCE}"
+#else
+#define CPP_SPEC \
+ "%{m68881:-D__HAVE_68881__} %{posix:-D_POSIX_SOURCE}"
+#endif
+
+#undef SUBTARGET_SWITCHES
+#define SUBTARGET_SWITCHES {"ieee-fp", 0},
+
+#undef ASM_SPEC
+#define ASM_SPEC \
+ "%{m68030} %{m68040} %{fpic:-k} %{fPIC:-k}"
+
+#undef LIB_SPEC
+#if 1
+/* We no longer link with libc_p.a or libg.a by default. If you want
+ to profile or debug the GNU/Linux C library, please add -lc_p or -ggdb
+ to LDFLAGS at the link time, respectively. */
+#define LIB_SPEC \
+ "%{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} %{!ggdb:-lc} %{ggdb:-lg}"
+#else
+#define LIB_SPEC \
+ "%{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}"
+#endif
+
+/* We want to pass -v to linker */
+#undef LINK_SPEC
+#define LINK_SPEC "-m m68klinux %{v:-dll-verbose}"
+
+#define SIZE_TYPE "unsigned int"
+#define PTRDIFF_TYPE "int"
+
+/* Generate calls to memcpy, memcmp and memset. */
+#define TARGET_MEM_FUNCTIONS
+
+/* Don't default to pcc-struct-return, because gcc is the only compiler. */
+#undef PCC_STATIC_STRUCT_RETURN
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* Allow folding division by zero. */
+#define REAL_INFINITY
diff --git a/gcc/config/m68k/linux.h b/gcc/config/m68k/linux.h
new file mode 100755
index 0000000..0df0bd8
--- /dev/null
+++ b/gcc/config/m68k/linux.h
@@ -0,0 +1,387 @@
+/* Definitions for Motorola 68k running Linux-based GNU systems with
+ ELF format.
+ Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define LINUX_DEFAULT_ELF
+#define MOTOROLA /* Use Motorola syntax */
+#define USE_GAS /* But GAS wants jbsr instead of jsr */
+
+#include <m68k/m68k.h>
+
+/* Make sure CC1 is undefined. */
+#undef CC1_SPEC
+
+#include <linux.h> /* some common stuff */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (68k GNU/Linux with ELF)");
+
+/* 68020 with 68881 */
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
+
+/* for 68k machines this only needs to be TRUE for the 68000 */
+
+#undef STRICT_ALIGNMENT
+#define STRICT_ALIGNMENT 0
+
+#undef SUBTARGET_SWITCHES
+#define SUBTARGET_SWITCHES {"ieee-fp", 0},
+
+/* Here are four prefixes that are used by asm_fprintf to
+ facilitate customization for alternate assembler syntaxes.
+ Machines with no likelihood of an alternate syntax need not
+ define these and need not use asm_fprintf. */
+
+/* The prefix for register names. Note that REGISTER_NAMES
+ is supposed to include this prefix. Also note that this is NOT an
+ fprintf format string, it is a literal string */
+
+#undef REGISTER_PREFIX
+#define REGISTER_PREFIX "%"
+
+/* The prefix for local (compiler generated) labels.
+ These labels will not appear in the symbol table. */
+
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
+/* The prefix to add to user-visible assembler symbols. */
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+
+#define ASM_COMMENT_START "|"
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number.
+ Motorola format uses different register names than defined in m68k.h. */
+
+#undef REGISTER_NAMES
+
+#ifndef SUPPORT_SUN_FPA
+
+#define REGISTER_NAMES \
+{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%sp", \
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7" }
+
+#else /* SUPPORTED_SUN_FPA */
+
+#define REGISTER_NAMES \
+{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%sp", \
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7", \
+ "%fpa0", "%fpa1", "%fpa2", "%fpa3", "%fpa4", "%fpa5", "%fpa6", "%fpa7", \
+ "%fpa8", "%fpa9", "%fpa10","%fpa11","%fpa12","%fpa13","%fpa14","%fpa15", \
+ "%fpa16","%fpa17","%fpa18","%fpa19","%fpa20","%fpa21","%fpa22","%fpa23", \
+ "%fpa24","%fpa25","%fpa26","%fpa27","%fpa28","%fpa29","%fpa30","%fpa31" }
+
+#endif /* defined SUPPORT_SUN_FPA */
+
+#undef SIZE_TYPE
+#define SIZE_TYPE "unsigned int"
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "int"
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "long int"
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE BITS_PER_WORD
+
+#define CPP_PREDEFINES \
+ "-D__ELF__ -Dunix -Dmc68000 -Dmc68020 -Dlinux -Asystem(unix) -Asystem(posix) -Acpu(m68k) -Amachine(m68k)"
+
+#undef CPP_SPEC
+#ifdef USE_GNULIBC_1
+#if TARGET_DEFAULT & MASK_68881
+#define CPP_SPEC \
+ "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{!msoft-float:-D__HAVE_68881__} %{posix:-D_POSIX_SOURCE}"
+#else
+#define CPP_SPEC \
+ "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{m68881:-D__HAVE_68881__} %{posix:-D_POSIX_SOURCE}"
+#endif
+#else
+#if TARGET_DEFAULT & MASK_68881
+#define CPP_SPEC \
+ "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{!msoft-float:-D__HAVE_68881__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
+#else
+#define CPP_SPEC \
+ "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{m68881:-D__HAVE_68881__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
+#endif
+#endif
+
+/* We override the ASM_SPEC from svr4.h because we must pass -m68040 down
+ to the assembler. */
+#undef ASM_SPEC
+#define ASM_SPEC \
+ "%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
+%{m68040} %{m68060:-m68040}"
+
+/* Provide a LINK_SPEC appropriate for GNU/Linux. Here we provide support
+ for the special GCC options -static and -shared, which allow us to
+ link things in one of these three modes by applying the appropriate
+ combinations of options at link-time. We like to support here for
+ as many of the other GNU linker options as possible. But I don't
+ have the time to search for those flags. I am sure how to add
+ support for -soname shared_object_name. H.J.
+
+ I took out %{v:%{!V:-V}}. It is too much :-(. They can use
+ -Wl,-V.
+
+ When the -shared link option is used a final link is not being
+ done. */
+
+/* If ELF is the default format, we should not use /lib/elf. */
+
+#undef LINK_SPEC
+#ifdef USE_GNULIBC_1
+#ifndef LINUX_DEFAULT_ELF
+#define LINK_SPEC "-m m68kelf %{shared} %{symbolic:-shared -Bsymbolic} \
+ %{!shared:%{!symbolic: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker*:-dynamic-linker /lib/elf/ld-linux.so.1} \
+ %{!rpath*:-rpath /lib/elf/}} %{static}}}"
+#else
+#define LINK_SPEC "-m m68kelf %{shared} %{symbolic:-shared -Bsymbolic} \
+ %{!shared:%{!symbolic: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker*:-dynamic-linker /lib/ld-linux.so.1}} \
+ %{static}}}"
+#endif
+#else
+#define LINK_SPEC "-m m68kelf %{shared} \
+ %{!shared: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker*:-dynamic-linker /lib/ld.so.1}} \
+ %{static}}"
+#endif
+
+/* For compatibility with linux/a.out */
+
+#undef PCC_BITFIELD_TYPE_MATTERS
+
+/* Currently, JUMP_TABLES_IN_TEXT_SECTION must be defined in order to
+ keep switch tables in the text section. */
+
+#define JUMP_TABLES_IN_TEXT_SECTION 1
+
+/* Use the default action for outputting the case label. */
+#undef ASM_OUTPUT_CASE_LABEL
+#define ASM_RETURN_CASE_JUMP \
+ do { \
+ if (TARGET_5200) \
+ return "ext%.l %0\n\tjmp %%pc@(2,%0:l)"; \
+ else \
+ return "jmp %%pc@(2,%0:w)"; \
+ } while (0)
+
+/* This is how to output an assembler line that says to advance the
+ location counter to a multiple of 2**LOG bytes. */
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) > 0) \
+ fprintf ((FILE), "\t%s \t%u\n", ALIGN_ASM_OP, 1 << (LOG));
+
+/* If defined, a C expression whose value is a string containing the
+ assembler operation to identify the following data as uninitialized global
+ data. */
+
+#define BSS_SECTION_ASM_OP ".section\t.bss"
+
+/* A C statement (sans semicolon) to output to the stdio stream
+ FILE the assembler definition of uninitialized global DECL named
+ NAME whose size is SIZE bytes and alignment is ALIGN bytes.
+ Try to use asm_output_aligned_bss to implement this macro. */
+
+#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
+ asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+{ \
+ asm_fprintf (FILE, "\tlea (%LLP%d,%Rpc),%Ra1\n", (LABELNO)); \
+ if (flag_pic) \
+ fprintf (FILE, "\tbsr.l _mcount@PLTPC\n"); \
+ else \
+ fprintf (FILE, "\tjbsr _mcount\n"); \
+}
+
+/* How to renumber registers for dbx and gdb.
+ On the Sun-3, the floating point registers have numbers
+ 18 to 25, not 16 to 23 as they do in the compiler. */
+
+#define DBX_REGISTER_NUMBER(REGNO) ((REGNO) < 16 ? (REGNO) : (REGNO) + 2)
+
+/* Do not break .stabs pseudos into continuations. */
+
+#define DBX_CONTIN_LENGTH 0
+
+/* Allow folding division by zero. */
+#define REAL_INFINITY
+
+/* 1 if N is a possible register number for a function value. For
+ m68k/SVR4 allow d0, a0, or fp0 as return registers, for integral,
+ pointer, or floating types, respectively. Reject fp0 if not using
+ a 68881 coprocessor. */
+
+#undef FUNCTION_VALUE_REGNO_P
+#define FUNCTION_VALUE_REGNO_P(N) \
+ ((N) == 0 || (N) == 8 || (TARGET_68881 && (N) == 16))
+
+/* Define this to be true when FUNCTION_VALUE_REGNO_P is true for
+ more than one register. */
+
+#undef NEEDS_UNTYPED_CALL
+#define NEEDS_UNTYPED_CALL 1
+
+/* Define how to generate (in the callee) the output value of a
+ function and how to find (in the caller) the value returned by a
+ function. VALTYPE is the data type of the value (as a tree). If
+ the precise function being called is known, FUNC is its
+ FUNCTION_DECL; otherwise, FUNC is 0. For m68k/SVR4 generate the
+ result in d0, a0, or fp0 as appropriate. */
+
+#undef FUNCTION_VALUE
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ (TREE_CODE (VALTYPE) == REAL_TYPE && TARGET_68881 \
+ ? gen_rtx_REG (TYPE_MODE (VALTYPE), 16) \
+ : (POINTER_TYPE_P (VALTYPE) \
+ ? gen_rtx_REG (TYPE_MODE (VALTYPE), 8) \
+ : gen_rtx_REG (TYPE_MODE (VALTYPE), 0)))
+
+/* For compatibility with the large body of existing code which does
+ not always properly declare external functions returning pointer
+ types, the m68k/SVR4 convention is to copy the value returned for
+ pointer functions from a0 to d0 in the function epilogue, so that
+ callers that have neglected to properly declare the callee can
+ still find the correct return value. */
+
+extern int current_function_returns_pointer;
+#define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE) \
+do { \
+ if ((current_function_returns_pointer) && \
+ ! find_equiv_reg (0, get_last_insn (), 0, 0, 0, 8, Pmode)) \
+ asm_fprintf (FILE, "\tmove.l %Ra0,%Rd0\n"); \
+} while (0);
+
+/* Define how to find the value returned by a library function
+ assuming the value has mode MODE.
+ For m68k/SVR4 look for integer values in d0, pointer values in d0
+ (returned in both d0 and a0), and floating values in fp0. */
+
+#undef LIBCALL_VALUE
+#define LIBCALL_VALUE(MODE) \
+ ((((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode) \
+ && TARGET_68881) \
+ ? gen_rtx_REG (MODE, 16) \
+ : gen_rtx_REG (MODE, 0))
+
+/* In m68k svr4, a symbol_ref rtx can be a valid PIC operand if it is
+ an operand of a function call. */
+#undef LEGITIMATE_PIC_OPERAND_P
+#define LEGITIMATE_PIC_OPERAND_P(X) \
+ ((! 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)))
+
+/* Turn off function cse if we are doing PIC. We always want function
+ call to be done as `bsr foo@PLTPC', so it will force the assembler
+ to create the PLT entry for `foo'. Doing function cse will cause
+ the address of `foo' to be loaded into a register, which is exactly
+ what we want to avoid when we are doing PIC on svr4 m68k. */
+#undef SUBTARGET_OVERRIDE_OPTIONS
+#define SUBTARGET_OVERRIDE_OPTIONS \
+ if (flag_pic) flag_no_function_cse = 1;
+
+/* For m68k SVR4, structures are returned using the reentrant
+ technique. */
+#undef PCC_STATIC_STRUCT_RETURN
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* Finalize the trampoline by flushing the insn cache. */
+
+#undef FINALIZE_TRAMPOLINE
+#define FINALIZE_TRAMPOLINE(TRAMP) \
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"), \
+ 0, VOIDmode, 2, TRAMP, Pmode, \
+ plus_constant (TRAMP, TRAMPOLINE_SIZE), Pmode);
+
+/* Clear the instruction cache from `beg' to `end'. This makes an
+ inline system call to SYS_cacheflush. The arguments are as
+ follows:
+
+ cacheflush (addr, scope, cache, len)
+
+ addr - the start address for the flush
+ scope - the scope of the flush (see the cpush insn)
+ cache - which cache to flush (see the cpush insn)
+ len - a factor relating to the number of flushes to perform:
+ len/16 lines, or len/4096 pages. */
+
+#define CLEAR_INSN_CACHE(BEG, END) \
+{ \
+ register unsigned long _beg __asm ("%d1") = (unsigned long) (BEG); \
+ unsigned long _end = (unsigned long) (END); \
+ register unsigned long _len __asm ("%d4") = (_end - _beg + 32); \
+ __asm __volatile \
+ ("move%.l %#123, %/d0\n\t" /* system call nr */ \
+ "move%.l %#1, %/d2\n\t" /* clear lines */ \
+ "move%.l %#3, %/d3\n\t" /* insn+data caches */ \
+ "trap %#0" \
+ : /* no outputs */ \
+ : "d" (_beg), "d" (_len) \
+ : "%d0", "%d2", "%d3"); \
+}
+
+/* Output code to add DELTA to the first argument, and then jump to FUNCTION.
+ Used for C++ multiple inheritance. */
+#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
+do { \
+ if (DELTA > 0 && DELTA <= 8) \
+ asm_fprintf (FILE, "\taddq.l %I%d,4(%Rsp)\n", DELTA); \
+ else if (DELTA < 0 && DELTA >= -8) \
+ asm_fprintf (FILE, "\tsubq.l %I%d,4(%Rsp)\n", -DELTA); \
+ else \
+ asm_fprintf (FILE, "\tadd.l %I%d,4(%Rsp)\n", DELTA); \
+ \
+ if (flag_pic) \
+ { \
+ fprintf (FILE, "\tbra.l "); \
+ assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
+ fprintf (FILE, "@PLTPC\n"); \
+ } \
+ else \
+ { \
+ fprintf (FILE, "\tjmp "); \
+ assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
+ fprintf (FILE, "\n"); \
+ } \
+} while (0)
diff --git a/gcc/config/m68k/lynx-ng.h b/gcc/config/m68k/lynx-ng.h
new file mode 100755
index 0000000..ac3afac
--- /dev/null
+++ b/gcc/config/m68k/lynx-ng.h
@@ -0,0 +1,43 @@
+/* Definitions for Motorola 680x0 running LynxOS, using Lynx's old as and ld.
+ Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include <m68k/m68k.h>
+#include <m68k/coff.h>
+#include <lynx-ng.h>
+
+/* See m68k.h. 7 means 68020 with 68881. */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
+#endif
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dunix -Dmc68000 -DM68K -DLynx -DIBITS32 -Asystem(unix) -Asystem(lynx) -Acpu(m68k) -Amachine(m68k)"
+
+/* Provide required defaults for linker switches. */
+
+#undef LINK_SPEC
+#define LINK_SPEC "-P1000 %{msystem-v:-V} %{mcoff:-k}"
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
diff --git a/gcc/config/m68k/lynx.h b/gcc/config/m68k/lynx.h
new file mode 100755
index 0000000..8c54b8b
--- /dev/null
+++ b/gcc/config/m68k/lynx.h
@@ -0,0 +1,74 @@
+/* Definitions for Motorola 680x0 running LynxOS.
+ Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include <m68k/m68k.h>
+#include <m68k/coff.h>
+
+#undef CTORS_SECTION_ASM_OP
+#undef DTORS_SECTION_ASM_OP
+#undef ASM_OUTPUT_DESTRUCTOR
+#undef SELECT_RTX_SECTION
+
+#define BSS_SECTION_ASM_OP ".bss"
+
+#define ASM_LONG ".long"
+
+#include <lynx.h>
+
+/* See m68k.h. 7 means 68020 with 68881. */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
+#endif
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dunix -Dmc68000 -DM68K -DLynx -DIBITS32 -Asystem(unix) -Asystem(lynx) -Acpu(m68k) -Amachine(m68k)"
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* Lynx uses d2 and d3 as scratch registers. */
+#undef CALL_USED_REGISTERS
+#define CALL_USED_REGISTERS \
+ {1, 1, 1, 1, 0, 0, 0, 0, \
+ 1, 1, 0, 0, 0, 0, 0, 1, \
+ 1, 1, 0, 0, 0, 0, 0, 0 }
+
+/* Return floating point values in a fp register. This make fp code a
+ little bit faster. It also makes -msoft-float code incompatible with
+ -m68881 code, so people have to be careful not to mix the two. */
+#undef FUNCTION_VALUE
+#define FUNCTION_VALUE(VALTYPE,FUNC) LIBCALL_VALUE (TYPE_MODE (VALTYPE))
+
+#undef LIBCALL_VALUE
+#define LIBCALL_VALUE(MODE) \
+ gen_rtx (REG, (MODE), \
+ ((TARGET_68881 \
+ && ((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode)) \
+ ? 16 : 0))
+
+#undef FUNCTION_VALUE_REGNO_P
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (TARGET_68881 && (N) == 16))
+
+#undef NEEDS_UNTYPED_CALL
+#define NEEDS_UNTYPED_CALL 1
diff --git a/gcc/config/m68k/m68020-elf.h b/gcc/config/m68k/m68020-elf.h
new file mode 100755
index 0000000..94b5d44
--- /dev/null
+++ b/gcc/config/m68k/m68020-elf.h
@@ -0,0 +1,53 @@
+/* Definitions of target machine for GNU compiler. "naked" 68020,
+ elf object files and debugging, version.
+ Copyright (C) 1987, 1988, 1992, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* This comment is here to see if it will keep Sun's cpp from dying. */
+
+#include "m68k/m68k-none.h"
+#include "m68k/m68kelf.h"
+#include "elfos.h"
+/* m68k/m68kemb.h sets some macros in ways that override the svr4 abi. */
+#include "m68k/m68kemb.h"
+
+/* We need to override the default specs from elfos.h. This suppresses the
+ loading of crt0.o by gcc's default linker spec. For embedded targets crt0
+ now comes from the linker script. */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "crtbegin.o%s"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s"
+
+#define LIB_SPEC "-lc"
+
+/* ??? Quick hack to get constructors working. Make this look more like a
+ COFF target, so the existing dejagnu/libgloss support works. A better
+ solution would be to make the necessary dejagnu and libgloss changes so
+ that we can use normal the ELF constructor mechanism. */
+#undef INIT_SECTION_ASM_OP
+#undef FINI_SECTION_ASM_OP
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC ""
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC ""
+
+/* end of m68020-elf.h */
diff --git a/gcc/config/m68k/m68360-coff.h b/gcc/config/m68k/m68360-coff.h
new file mode 100755
index 0000000..9f0c718
--- /dev/null
+++ b/gcc/config/m68k/m68360-coff.h
@@ -0,0 +1,27 @@
+/* Definitions of target machine for GNU compiler. "naked" 68360,
+ COFF object files and debugging, version.
+ Copyright (C) 1987, 1988, 1991, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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. */
+
+#define MOTOROLA /* Use Motorola syntax rather than MIT. */
+
+#include "m68k/m68360-none.h"
+#include "m68k/m68kemb.h"
+#include "m68k/coff.h"
+
+/* end of m68360-coff.h */
diff --git a/gcc/config/m68k/m68360-none.h b/gcc/config/m68k/m68360-none.h
new file mode 100755
index 0000000..27b1d60
--- /dev/null
+++ b/gcc/config/m68k/m68360-none.h
@@ -0,0 +1,129 @@
+/* Definitions of target machine for GNU compiler. "naked" 68360.
+ Copyright (C) 1987, 1988, 1992, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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. */
+
+#include "m68k/m68k.h"
+
+/* See m68k.h. 1 means 68020 without bitfield insns or 68881. */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT 1
+#endif
+
+/* Names to predefine in the preprocessor for this target machine.
+ Always define mc68000. Other definitions depend on switches given
+ to the compiler:
+
+ -m68000: define nothing else
+ -m68020, -mc68020: define mc68020
+ -m68030: define mc68030
+ -m68040: define mc68040
+ -m68020-40: define mc68020 mc68030 mc68040
+ -m68302: define mc68302
+ -m68332: define mc68332
+ default, -m68360: define mc68360
+ */
+
+#ifndef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dmc68000"
+#endif
+
+#ifndef CPP_SPEC
+
+#if TARGET_DEFAULT & 02
+
+/* -m68881 is the default */
+#define CPP_SPEC \
+"%{!mc68000:%{!m68000:%{!m68332:%{!msoft-float:%{mfpa:-D__HAVE_FPA__ }%{!mfpa:-D__HAVE_68881__ }}}}}\
+%{!ansi:%{m68010:-Dmc68010 }%{m68020:-Dmc68020 }%{mc68020:-Dmc68020 }%{m68030:-Dmc68030 }%{m68040:-Dmc68040 }%{m68020-40:-Dmc68020 -Dmc68030 -Dmc68040 }%{m68302:-Dmc68302 }%{m68332:-Dmc68332 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-Dmc68360 }}}}}}}}}}}\
+%{m68010:-D__mc68010__ -D__mc68010 }%{m68020:-D__mc68020__ -D__mc68020 }%{mc68020:-D__mc68020__ -D__mc68020 }%{m68030:-D__mc68030__ -D__mc68030 }%{m68040:-D__mc68040__ -D__mc68040 }%{m68020-40:-D__mc68020__ -D__mc68030__ -D__mc68040__ -D__mc68020 -D__mc68030 -D__mc68040 }%{m68302:-D__mc68302__ -D__mc68302 }%{m68332:-D__mc68332__ -D__mc68332 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-D__mc68360__ -D__mc68360 }}}}}}}}}}"
+
+#else
+#if TARGET_DEFAULT & 0100
+
+/* -mfpa is the default */
+#define CPP_SPEC \
+"%{!msoft-float:%{m68881:-D__HAVE_68881__ }%{!m68881:-D__HAVE_FPA__ }}\
+%{!ansi:%{m68010:-Dmc68010 }%{m68020:-Dmc68020 }%{mc68020:-Dmc68020 }%{m68030:-Dmc68030 }%{m68040:-Dmc68040 }%{m68020-40:-Dmc68020 -Dmc68030 -Dmc68040 }%{m68302:-Dmc68302 }%{m68332:-Dmc68332 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-Dmc68360 }}}}}}}}}}}\
+%{m68010:-D__mc68010__ -D__mc68010 }%{m68020:-D__mc68020__ -D__mc68020 }%{mc68020:-D__mc68020__ -D__mc68020 }%{m68030:-D__mc68030__ -D__mc68030 }%{m68040:-D__mc68040__ -D__mc68040 }%{m68020-40:-D__mc68020__ -D__mc68030__ -D__mc68040__ -D__mc68020 -D__mc68030 -D__mc68040 }%{m68302:-D__mc68302__ -D__mc68302 }%{m68332:-D__mc68332__ -D__mc68332 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-D__mc68360__ -D__mc68360 }}}}}}}}}}"
+
+#else
+
+/* -msoft-float is the default */
+#define CPP_SPEC \
+"%{m68881:-D__HAVE_68881__ }%{mfpa:-D__HAVE_FPA__ }\
+%{!ansi:%{m68010:-Dmc68010 }%{m68020:-Dmc68020 }%{mc68020:-Dmc68020 }%{m68030:-Dmc68030 }%{m68040:-Dmc68040 }%{m68020-40:-Dmc68020 -Dmc68030 -Dmc68040 }%{m68302:-Dmc68302 }%{m68332:-Dmc68332 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-Dmc68360 }}}}}}}}}}}\
+%{m68010:-D__mc68010__ -D__mc68010 }%{m68020:-D__mc68020__ -D__mc68020 }%{mc68020:-D__mc68020__ -D__mc68020 }%{m68030:-D__mc68030__ -D__mc68030 }%{m68040:-D__mc68040__ -D__mc68040 }%{m68020-40:-D__mc68020__ -D__mc68030__ -D__mc68040__ -D__mc68020 -D__mc68030 -D__mc68040 }%{m68302:-D__mc68302__ -D__mc68302 }%{m68332:-D__mc68332__ -D__mc68332 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-D__mc68360__ -D__mc68360 }}}}}}}}}}"
+
+#endif
+#endif
+
+#endif
+
+/* Pass flags to gas indicating which type of processor we have. */
+
+#ifndef ASM_SPEC
+
+#define ASM_SPEC \
+"%{m68851}%{mno-68851}%{m68881}%{mno-68881}%{msoft-float:-mno-68881 }\
+%{m68000}%{mc68000}%{m68010}%{m68020}%{mc68020}%{m68030}%{m68040}%{m68020-40:-mc68040}%{m68302}%{m68332}%{!m68000:%{!mc68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-m68360}}}}}}}}}}"
+
+#endif
+
+#ifndef CC1_SPEC
+
+#define CC1_SPEC \
+ "%{m68000:%{!m68881:-msoft-float }}%{m68302:-m68000}%{m68332:-m68020 -mnobitfield %{!m68881:-msoft-float}}%{!m68000:%{!mc68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-m68000}}}}}}}}}}"
+
+#endif
+
+#define HANDLE_SYSV_PRAGMA
+
+/* Boundary (in *bits*) on which stack pointer should be aligned.
+ The m68k/SVR4 convention is to keep the stack pointer longword aligned. */
+
+#undef STACK_BOUNDARY
+#define STACK_BOUNDARY 32
+
+/* Alignment of field after `int : 0' in a structure.
+ For m68k/SVR4, this is the next longword boundary. */
+
+#undef EMPTY_FIELD_BOUNDARY
+#define EMPTY_FIELD_BOUNDARY 32
+
+/* Make strings word-aligned so strcpy from constants will be faster. */
+#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
+ ((ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
+
+/* Make arrays of chars word-aligned for the same reasons. */
+#define DATA_ALIGNMENT(TYPE, ALIGN) \
+ ((ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
+
+/* No data type wants to be aligned rounder than this. */
+#undef BIGGEST_ALIGNMENT
+#define BIGGEST_ALIGNMENT 32
+
+/* Other 68k targets don't have a way to align to more than a two-byte
+ boundary, so we override here. */
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) == 1) \
+ fprintf (FILE, "\t.even\n"); \
+ else \
+ fprintf (FILE, "\t.align %d\n", (LOG))
+/* end of m68360-none.h */
diff --git a/gcc/config/m68k/m68k-aout.h b/gcc/config/m68k/m68k-aout.h
new file mode 100755
index 0000000..b65f9fe
--- /dev/null
+++ b/gcc/config/m68k/m68k-aout.h
@@ -0,0 +1,44 @@
+/* Definitions of target machine for GNU compiler. "naked" 68020,
+ a.out object files and debugging, version.
+ Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* This comment is here to see if it will keep Sun's cpp from dying. */
+
+#include "m68k/m68k-none.h"
+#include "m68k/m68kemb.h"
+#include "aoutos.h"
+
+#define DBX_DEBUGGING_INFO
+#undef SDB_DEBUGGING_INFO
+
+/* If defined, a C expression whose value is a string containing the
+ assembler operation to identify the following data as uninitialized global
+ data. */
+#define BSS_SECTION_ASM_OP "\t.bss"
+
+/* A C statement (sans semicolon) to output to the stdio stream
+ FILE the assembler definition of uninitialized global DECL named
+ NAME whose size is SIZE bytes. The variable ROUNDED
+ is the size rounded up to whatever alignment the caller wants.
+ Try to use asm_output_bss to implement this macro. */
+/* a.out files typically can't handle arbitrary variable alignments so
+ define ASM_OUTPUT_BSS instead of ASM_OUTPUT_ALIGNED_BSS. */
+#define ASM_OUTPUT_BSS(FILE, DECL, NAME, SIZE, ROUNDED) \
+ asm_output_bss ((FILE), (DECL), (NAME), (SIZE), (ROUNDED))
diff --git a/gcc/config/m68k/m68k-coff.h b/gcc/config/m68k/m68k-coff.h
new file mode 100755
index 0000000..085dd95
--- /dev/null
+++ b/gcc/config/m68k/m68k-coff.h
@@ -0,0 +1,28 @@
+/* Definitions of target machine for GNU compiler. "naked" 68020,
+ COFF object files and debugging, version.
+ Copyright (C) 1994 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define MOTOROLA /* Use Motorola syntax rather than MIT. */
+
+#include "m68k/m68k-none.h"
+#include "m68k/m68kemb.h"
+#include "m68k/coff.h"
+
+/* end of m68k-coff.h */
diff --git a/gcc/config/m68k/m68k-none.h b/gcc/config/m68k/m68k-none.h
new file mode 100755
index 0000000..c48ac3d
--- /dev/null
+++ b/gcc/config/m68k/m68k-none.h
@@ -0,0 +1,197 @@
+/* Definitions of target machine for GNU compiler. "naked" 68020.
+ Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "m68k/m68k.h"
+
+/* Default to m68k (m68020). */
+#ifndef TARGET_CPU_DEFAULT
+#define TARGET_CPU_DEFAULT M68K_CPU_m68k
+#endif
+
+/* These are values set by the configure script in TARGET_CPU_DEFAULT.
+ They are ((desired value for TARGET_DEFAULT) << 4) + sequential integer.
+ See m68k.h for the values (it should really define MASK_FOO so we can
+ use them). */
+#define M68K_CPU_m68k ((7 << 4) + 0)
+#define M68K_CPU_m68000 ((0 << 4) + 1)
+#define M68K_CPU_m68010 ((0 << 4) + 1) /* make same as m68000 */
+#define M68K_CPU_m68020 ((7 << 4) + 2)
+#define M68K_CPU_m68030 ((7 << 4) + 3)
+#define M68K_CPU_m68040 ((01007 << 4) + 4)
+#define M68K_CPU_m68302 ((0 << 4) + 5)
+#define M68K_CPU_m68332 ((1 << 4) + 6)
+
+/* This is tested for below, so if target wants to override this, it
+ just set this first in cover file. */
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT (TARGET_CPU_DEFAULT >> 4)
+#endif
+
+/* Defaults for the various specs below.
+ These are collected here so we only test TARGET_CPU_DEFAULT once. */
+/* ??? CC1_CPU_DEFAULT_SPEC was copied over from the earlier version of
+ this file. However, it's not used anywhere here because it doesn't
+ seem to be necessary. */
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68k || TARGET_CPU_DEFAULT == M68K_CPU_m68020
+#define CPP_CPU_DEFAULT_SPEC "%{!ansi:-Dmc68020 } -D__mc68020 -D__mc68020__"
+#define ASM_CPU_DEFAULT_SPEC "-mc68020"
+#define CC1_CPU_DEFAULT_SPEC "-m68020"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68000
+#define CPP_CPU_DEFAULT_SPEC "%{!ansi:-Dmc68000 } -D__mc68000 -D__mc68000__"
+#define ASM_CPU_DEFAULT_SPEC "-mc68000"
+#define CC1_CPU_DEFAULT_SPEC "-m68000"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68030
+#define CPP_CPU_DEFAULT_SPEC "%{!ansi:-Dmc68030 } -D__mc68030 -D__mc68030__"
+#define ASM_CPU_DEFAULT_SPEC "-mc68030"
+#define CC1_CPU_DEFAULT_SPEC "-m68030"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68040
+#define CPP_CPU_DEFAULT_SPEC "%{!ansi:-Dmc68040 } -D__mc68040 -D__mc68040__"
+#define ASM_CPU_DEFAULT_SPEC "-mc68040"
+#define CC1_CPU_DEFAULT_SPEC "-m68040"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68302
+#define CPP_CPU_DEFAULT_SPEC "%{!ansi:-Dmc68302 } -D__mc68302 -D__mc68302__"
+#define ASM_CPU_DEFAULT_SPEC "-mc68302"
+#define CC1_CPU_DEFAULT_SPEC "-m68302"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68332
+#define CPP_CPU_DEFAULT_SPEC "%{!ansi:-Dmc68332 -Dmcpu32 } -D__mc68332 -D__mc68332__ -D__mcpu32 -D__mcpu32__"
+#define ASM_CPU_DEFAULT_SPEC "-mc68332"
+#define CC1_CPU_DEFAULT_SPEC "-m68332"
+#else
+Unrecognized value in TARGET_CPU_DEFAULT.
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+/* Always define mc68000.
+ Remember that GCC will automatically add __mc68000 and __mc68000__. */
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dmc68000"
+
+/* Define one of __HAVE_68881__, __HAVE_FPA__, __HAVE_SKY__, or nothing
+ (soft float), appropriately. */
+#undef CPP_FPU_SPEC
+#if TARGET_DEFAULT & MASK_68881
+#define CPP_FPU_SPEC "\
+%{!mc68000:%{!m68000:%{!m68302:%{!mcpu32:%{!m68332:%{!m5200:%{!msoft-float:%{!mno-68881:%{!mfpa:%{!msky:-D__HAVE_68881__ }}}}}}}}}} \
+%{m68881:-D__HAVE_68881__ }%{mfpa:-D__HAVE_FPA__ }%{msky:-D__HAVE_SKY__ }"
+#else
+/* This can't currently happen, but we code it anyway to show how it's done. */
+#if TARGET_DEFAULT & MASK_FPA
+#define CPP_FPU_SPEC \
+"%{!msoft-float:%{m68881:-D__HAVE_68881__ }%{!m68881:-D__HAVE_FPA__ }}"
+#else
+#define CPP_FPU_SPEC "\
+%{m68881:-D__HAVE_68881__ }%{mfpa:-D__HAVE_FPA__ }%{msky:-D__HAVE_SKY__ }"
+#endif
+#endif
+
+/* Names to predefine in the preprocessor for this target machine.
+ Other definitions depend on what the default cpu is and switches
+ given to the compiler:
+
+ -m68000, -mc68000: define nothing else
+ -m68010: define mc68010
+ -m68020, -mc68020: define mc68020
+ -m68030: define mc68030
+ -m68040: define mc68040
+ -m68060: define mc68060
+ -m68020-40: define mc68020 mc68030 mc68040
+ -m68020-60: define mc68020 mc68030 mc68040 mc68060
+ -m68302: define mc68302
+ -m68332: define mc68332 mcpu32
+ -mcpu32: define mcpu32
+ -m5200: define mcf5200
+ default: define as above appropriately
+
+ GCC won't automatically add __'d versions, we have to mention them
+ explicitly. */
+
+#undef CPP_SPEC
+#define CPP_SPEC "\
+%(cpp_fpu)%{!ansi:%{m68302:-Dmc68302 }%{m68010:-Dmc68010 }%{m68020:-Dmc68020 }%{mc68020:-Dmc68020 }%{m68030:-Dmc68030 }%{m68040:-Dmc68040 }%{m68020-40:-Dmc68020 -Dmc68030 -Dmc68040 }%{m68020-60:-Dmc68020 -Dmc68030 -Dmc68040 -Dmc68060 }%{m68060:-Dmc68060 }%{mcpu32:-Dmcpu32 } %{m68332:-Dmc68332 -Dmcpu32 }%{m5200:-Dmcf5200 }} \
+%{m68302:-D__mc68302__ -D__mc68302 }%{m68010:-D__mc68010__ -D__mc68010 }%{m68020:-D__mc68020__ -D__mc68020 }%{mc68020:-D__mc68020__ -D__mc68020 }%{m68030:-D__mc68030__ -D__mc68030 }%{m68040:-D__mc68040__ -D__mc68040 }%{m68020-40:-D__mc68020__ -D__mc68030__ -D__mc68040__ -D__mc68020 -D__mc68030 -D__mc68040 }%{m68020-60:-D__mc68020__ -D__mc68030__ -D__mc68040__ -D__mc68020 -D__mc68030 -D__mc68040 -D__mc68060__ -D__mc68060 }%{m68060:-D__mc68060__ -D__mc68060 }%{mcpu32:-D__mcpu32__ -D__mcpu32 }%{m68332:-D__mc68332__ -D__mc68332 -D__mcpu32__ -D__mcpu32 }%{m5200:-D__mcf5200__ -D__mcf5200 } \
+%{!mc68000:%{!m68000:%{!m68302:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68020-60:%{!m68060:%{!mcpu32: %{!m68332:%{!m5200:%(cpp_cpu_default)}}}}}}}}}}}}}} \
+%(cpp_subtarget) \
+"
+
+/* Pass flags to gas indicating which type of processor we have. */
+
+#undef ASM_SPEC
+#define ASM_SPEC "\
+%{m68851}%{mno-68851}%{m68881}%{mno-68881}%{msoft-float:-mno-68881 }%{m68000}%{m68302}%{mc68000}%{m68010}%{m68020}%{mc68020}%{m68030}%{m68040}%{m68020-40:-mc68040 }%{m68020-60:-mc68040 }%{m68060}%{mcpu32}%{m68332}%{m5200}%{!mc68000:%{!m68000:%{!m68302:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68020-60:%{!m68060:%{!mcpu32:%{!m68332:%{!m5200:%(asm_cpu_default) }}}}}}}}}}}}}} \
+"
+
+/* cc1/cc1plus always receives all the -m flags. If the specs strings above
+ are consistent with the TARGET_OPTIONS flags in m68k.h, there should be no
+ need for any further cc1/cc1plus specs. */
+
+#undef CC1_SPEC
+#define CC1_SPEC ""
+
+/* This macro defines names of additional specifications to put in the specs
+ that can be used in various specifications like CC1_SPEC. Its definition
+ is an initializer with a subgrouping for each command option.
+
+ Each subgrouping contains a string constant, that defines the
+ specification name, and a string constant that used by the GNU CC driver
+ program.
+
+ Do not define this macro if it does not need to do anything. */
+
+#define EXTRA_SPECS \
+ { "cpp_cpu_default", CPP_CPU_DEFAULT_SPEC }, \
+ { "cpp_fpu", CPP_FPU_SPEC }, \
+ { "cpp_subtarget", CPP_SUBTARGET_SPEC }, \
+ { "asm_cpu_default", ASM_CPU_DEFAULT_SPEC }, \
+/*{ "cc1_cpu_default", CC1_CPU_DEFAULT__SPEC },*/ \
+ SUBTARGET_EXTRA_SPECS
+
+#define CPP_SUBTARGET_SPEC ""
+#define SUBTARGET_EXTRA_SPECS
+
+/* Avoid building multilib libraries for the defaults.
+ t-m68kbare doesn't support -mfpa in the multilib'd libraries, so we don't
+ either.
+ For targets not handled here, just build the full set of multilibs.
+ The default is m68k 99.9% of the time anyway. */
+
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68k || TARGET_CPU_DEFAULT == M68K_CPU_m68020
+#if TARGET_DEFAULT & MASK_68881
+#define MULTILIB_DEFAULTS { "m68020", "m68881" }
+#else
+#define MULTILIB_DEFAULTS { "m68020", "msoft-float" }
+#endif
+#endif
+
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68000 || TARGET_CPU_DEFAULT == M68K_CPU_m68302
+#if TARGET_DEFAULT & MASK_68881
+#define MULTILIB_DEFAULTS { "m68000", "m68881" }
+#else
+#define MULTILIB_DEFAULTS { "m68000", "msoft-float" }
+#endif
+#endif
diff --git a/gcc/config/m68k/m68k-psos.h b/gcc/config/m68k/m68k-psos.h
new file mode 100755
index 0000000..8e5b843
--- /dev/null
+++ b/gcc/config/m68k/m68k-psos.h
@@ -0,0 +1,67 @@
+/* Definitions of a target machine for the GNU compiler:
+ 68040 running pSOS, ELF object files, DBX debugging.
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+/* Use MOTOROLA assembler syntax, as gas is configured that way and
+ glibc also seems to use it. Must come BEFORE m68k.h! */
+
+#define MOTOROLA
+
+/* Get generic m68k definitions. */
+
+#include "m68k/m68k.h"
+#include "m68k/m68kemb.h"
+
+/* Default processor type is a (pure) 68040 with 68881 emulation using
+ the floating-point support package. */
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_68040_ONLY|MASK_BITFIELD|MASK_68881|MASK_68020)
+
+/* Options passed to CPP, GAS, CC1 and CC1PLUS. We override
+ m68k-none.h for consistency with TARGET_DEFAULT. */
+
+#undef CPP_SPEC
+#define CPP_SPEC \
+"%{!mc68000:%{!m68000:%{!m68332:%{!msoft-float:-D__HAVE_68881__ }}}}\
+%{!ansi:-Dmc68000 %{m68010:-Dmc68010 }%{m68020:-Dmc68020 }%{mc68020:-Dmc68020 }%{m68030:-Dmc68030 }%{m68040:-Dmc68040 }%{m68020-40:-Dmc68020 -Dmc68030 -Dmc68040 }%{m68302:-Dmc68302 }%{m68332:-Dmc68332 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-Dmc68040 }}}}}}}}}}}\
+-D__mc68000__ -D__mc68000 %{m68010:-D__mc68010__ -D__mc68010 }%{m68020:-D__mc68020__ -D__mc68020 }%{mc68020:-D__mc68020__ -D__mc68020 }%{m68030:-D__mc68030__ -D__mc68030 }%{m68040:-D__mc68040__ -D__mc68040 }%{m68020-40:-D__mc68020__ -D__mc68030__ -D__mc68040__ -D__mc68020 -D__mc68030 -D__mc68040 }%{m68302:-D__mc68302__ -D__mc68302 }%{m68332:-D__mc68332__ -D__mc68332 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-D__mc68040__ -D__mc68040 }}}}}}}}}}"
+
+#undef ASM_SPEC
+#define ASM_SPEC \
+"%{m68851}%{mno-68851}%{m68881}%{mno-68881}%{msoft-float:-mno-68881 }\
+%{m68000}%{mc68000}%{m68010}%{m68020}%{mc68020}%{m68030}%{m68040}%{m68020-40:-mc68040}%{m68302}%{m68332}%{!m68000:%{!mc68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-mc68040}}}}}}}}}}"
+
+#undef CC1_SPEC
+#define CC1_SPEC \
+ "%{m68000:%{!m68881:-msoft-float }}%{m68302:-m68000}%{m68332:-m68020 -mnobitfield %{!m68881:-msoft-float}}%{!m68000:%{!mc68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-m68040}}}}}}}}}}"
+
+#undef CC1PLUS_SPEC
+#define CC1PLUS_SPEC \
+ "%{m68000:%{!m68881:-msoft-float }}%{m68302:-m68000}%{m68332:-m68020 -mnobitfield %{!m68881:-msoft-float}}%{!m68000:%{!mc68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-m68040}}}}}}}}}}"
+
+
+/* Get processor-independent pSOS definitions. */
+
+#include "psos.h"
+
+
+/* end of m68k-psos.h */
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
new file mode 100755
index 0000000..244fa7f
--- /dev/null
+++ b/gcc/config/m68k/m68k.c
@@ -0,0 +1,3393 @@
+/* Subroutines for insn-output.c for Motorola 68000 family.
+ Copyright (C) 1987, 93-98, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+/* Some output-actions in m68k.md need these. */
+#include "config.h"
+#include "system.h"
+#include "tree.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-flags.h"
+#include "output.h"
+#include "insn-attr.h"
+#include "recog.h"
+#include "toplev.h"
+
+/* Needed for use_return_insn. */
+#include "flags.h"
+
+#ifdef SUPPORT_SUN_FPA
+
+/* Index into this array by (register number >> 3) to find the
+ smallest class which contains that register. */
+enum reg_class regno_reg_class[]
+ = { DATA_REGS, ADDR_REGS, FP_REGS,
+ LO_FPA_REGS, LO_FPA_REGS, FPA_REGS, FPA_REGS };
+
+#endif /* defined SUPPORT_SUN_FPA */
+
+/* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
+ if SGS_SWITCH_TABLE. */
+int switch_table_difference_label_flag;
+
+static rtx find_addr_reg ();
+rtx legitimize_pic_address ();
+
+
+/* Alignment to use for loops and jumps */
+/* Specify power of two alignment used for loops. */
+char *m68k_align_loops_string;
+/* Specify power of two alignment used for non-loop jumps. */
+char *m68k_align_jumps_string;
+/* Specify power of two alignment used for functions. */
+char *m68k_align_funcs_string;
+
+/* Specify power of two alignment used for loops. */
+int m68k_align_loops;
+/* Specify power of two alignment used for non-loop jumps. */
+int m68k_align_jumps;
+/* Specify power of two alignment used for functions. */
+int m68k_align_funcs;
+
+/* Nonzero if the last compare/test insn had FP operands. The
+ sCC expanders peek at this to determine what to do for the
+ 68060, which has no fsCC instructions. */
+int m68k_last_compare_had_fp_operands;
+
+/* 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. */
+
+void
+override_options ()
+{
+ int def_align;
+
+ def_align = 1;
+
+ /* Validate -malign-loops= value, or provide default */
+ if (m68k_align_loops_string)
+ {
+ m68k_align_loops = atoi (m68k_align_loops_string);
+ if (m68k_align_loops < 1 || m68k_align_loops > MAX_CODE_ALIGN)
+ fatal ("-malign-loops=%d is not between 1 and %d",
+ m68k_align_loops, MAX_CODE_ALIGN);
+ }
+ else
+ m68k_align_loops = def_align;
+
+ /* Validate -malign-jumps= value, or provide default */
+ if (m68k_align_jumps_string)
+ {
+ m68k_align_jumps = atoi (m68k_align_jumps_string);
+ if (m68k_align_jumps < 1 || m68k_align_jumps > MAX_CODE_ALIGN)
+ fatal ("-malign-jumps=%d is not between 1 and %d",
+ m68k_align_jumps, MAX_CODE_ALIGN);
+ }
+ else
+ m68k_align_jumps = def_align;
+
+ /* Validate -malign-functions= value, or provide default */
+ if (m68k_align_funcs_string)
+ {
+ m68k_align_funcs = atoi (m68k_align_funcs_string);
+ if (m68k_align_funcs < 1 || m68k_align_funcs > MAX_CODE_ALIGN)
+ fatal ("-malign-functions=%d is not between 1 and %d",
+ m68k_align_funcs, MAX_CODE_ALIGN);
+ }
+ else
+ m68k_align_funcs = def_align;
+}
+
+/* Emit a (use pic_offset_table_rtx) if we used PIC relocation in the
+ function at any time during the compilation process. In the future
+ we should try and eliminate the USE if we can easily determine that
+ all PIC references were deleted from the current function. That would
+ save an address register */
+
+void
+finalize_pic ()
+{
+ if (flag_pic && current_function_uses_pic_offset_table)
+ {
+ rtx insn = gen_rtx_USE (VOIDmode, pic_offset_table_rtx);
+ emit_insn_after (insn, get_insns ());
+ emit_insn (insn);
+ }
+}
+
+
+/* This function generates the assembly code for function entry.
+ STREAM is a stdio stream to output the code to.
+ SIZE is an int: how many units of temporary storage to allocate.
+ Refer to the array `regs_ever_live' to determine which registers
+ to save; `regs_ever_live[I]' is nonzero if register number I
+ is ever used in the function. This function is responsible for
+ knowing which registers should not be saved even if used. */
+
+
+/* Note that the order of the bit mask for fmovem is the opposite
+ of the order for movem! */
+
+
+void
+output_function_prologue (stream, size)
+ FILE *stream;
+ int size;
+{
+ register int regno;
+ register int mask = 0;
+ int num_saved_regs = 0;
+ extern char call_used_regs[];
+ int fsize = (size + 3) & -4;
+ int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset;
+
+
+ if (frame_pointer_needed)
+ {
+ if (fsize == 0 && TARGET_68040)
+ {
+ /* on the 68040, pea + move is faster than link.w 0 */
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tpea (%s)\n\tmove.l %s,%s\n",
+ reg_names[FRAME_POINTER_REGNUM], reg_names[STACK_POINTER_REGNUM],
+ reg_names[FRAME_POINTER_REGNUM]);
+#else
+ asm_fprintf (stream, "\tpea %s@\n\tmovel %s,%s\n",
+ reg_names[FRAME_POINTER_REGNUM], reg_names[STACK_POINTER_REGNUM],
+ reg_names[FRAME_POINTER_REGNUM]);
+#endif
+ }
+ else if (fsize < 0x8000)
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tlink.w %s,%0I%d\n",
+ reg_names[FRAME_POINTER_REGNUM], -fsize);
+#else
+ asm_fprintf (stream, "\tlink %s,%0I%d\n",
+ reg_names[FRAME_POINTER_REGNUM], -fsize);
+#endif
+ }
+ else if (TARGET_68020)
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tlink.l %s,%0I%d\n",
+ reg_names[FRAME_POINTER_REGNUM], -fsize);
+#else
+ asm_fprintf (stream, "\tlink %s,%0I%d\n",
+ reg_names[FRAME_POINTER_REGNUM], -fsize);
+#endif
+ }
+ else
+ {
+ /* Adding negative number is faster on the 68040. */
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",
+ reg_names[FRAME_POINTER_REGNUM], -fsize);
+#else
+ asm_fprintf (stream, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",
+ reg_names[FRAME_POINTER_REGNUM], -fsize);
+#endif
+ }
+ if (dwarf2out_do_frame ())
+ {
+ char *l;
+ l = (char *) dwarf2out_cfi_label ();
+ cfa_store_offset += 4;
+ cfa_offset = cfa_store_offset;
+ dwarf2out_def_cfa (l, FRAME_POINTER_REGNUM, cfa_offset);
+ dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, -cfa_store_offset);
+ cfa_store_offset += fsize;
+ }
+ }
+ else if (fsize)
+ {
+ if (fsize + 4 < 0x8000)
+ {
+#ifndef NO_ADDSUB_Q
+ if (fsize + 4 <= 8)
+ {
+ if (!TARGET_5200)
+ {
+ /* asm_fprintf() cannot handle %. */
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tsubq.w %0I%d,%Rsp\n", fsize + 4);
+#else
+ asm_fprintf (stream, "\tsubqw %0I%d,%Rsp\n", fsize + 4);
+#endif
+ }
+ else
+ {
+ /* asm_fprintf() cannot handle %. */
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tsubq.l %0I%d,%Rsp\n", fsize + 4);
+#else
+ asm_fprintf (stream, "\tsubql %0I%d,%Rsp\n", fsize + 4);
+#endif
+ }
+ }
+ else if (fsize + 4 <= 16 && TARGET_CPU32)
+ {
+ /* On the CPU32 it is faster to use two subqw instructions to
+ subtract a small integer (8 < N <= 16) to a register. */
+ /* asm_fprintf() cannot handle %. */
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tsubq.w %0I8,%Rsp\n\tsubq.w %0I%d,%Rsp\n",
+ fsize + 4);
+#else
+ asm_fprintf (stream, "\tsubqw %0I8,%Rsp\n\tsubqw %0I%d,%Rsp\n",
+ fsize + 4);
+#endif
+ }
+ else
+#endif /* not NO_ADDSUB_Q */
+ if (TARGET_68040)
+ {
+ /* Adding negative number is faster on the 68040. */
+ /* asm_fprintf() cannot handle %. */
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - (fsize + 4));
+#else
+ asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", - (fsize + 4));
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", - (fsize + 4));
+#else
+ asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", - (fsize + 4));
+#endif
+ }
+ }
+ else
+ {
+ /* asm_fprintf() cannot handle %. */
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", - (fsize + 4));
+#else
+ asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", - (fsize + 4));
+#endif
+ }
+ if (dwarf2out_do_frame ())
+ {
+ cfa_store_offset += fsize;
+ cfa_offset = cfa_store_offset;
+ dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset);
+ }
+ }
+#ifdef SUPPORT_SUN_FPA
+ for (regno = 24; regno < 56; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n",
+ reg_names[regno]);
+#else
+ asm_fprintf (stream, "\tfpmoved %s,%Rsp@-\n",
+ reg_names[regno]);
+#endif
+ if (dwarf2out_do_frame ())
+ {
+ char *l = dwarf2out_cfi_label ();
+
+ cfa_store_offset += 8;
+ if (! frame_pointer_needed)
+ {
+ cfa_offset = cfa_store_offset;
+ dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
+ }
+ dwarf2out_reg_save (l, regno, -cfa_store_offset);
+ }
+ }
+#endif
+ if (TARGET_68881)
+ {
+ for (regno = 16; regno < 24; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ mask |= 1 << (regno - 16);
+ num_saved_regs++;
+ }
+ if ((mask & 0xff) != 0)
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tfmovm %0I0x%x,-(%Rsp)\n", mask & 0xff);
+#else
+ asm_fprintf (stream, "\tfmovem %0I0x%x,%Rsp@-\n", mask & 0xff);
+#endif
+ if (dwarf2out_do_frame ())
+ {
+ char *l = (char *) dwarf2out_cfi_label ();
+ int n_regs;
+
+ cfa_store_offset += num_saved_regs * 12;
+ if (! frame_pointer_needed)
+ {
+ cfa_offset = cfa_store_offset;
+ dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
+ }
+ for (regno = 16, n_regs = 0; regno < 24; regno++)
+ if (mask & (1 << (regno - 16)))
+ dwarf2out_reg_save (l, regno,
+ -cfa_store_offset + n_regs++ * 12);
+ }
+ }
+ mask = 0;
+ num_saved_regs = 0;
+ }
+ for (regno = 0; regno < 16; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ mask |= 1 << (15 - regno);
+ num_saved_regs++;
+ }
+ if (frame_pointer_needed)
+ {
+ mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM));
+ num_saved_regs--;
+ }
+
+#if NEED_PROBE
+#ifdef MOTOROLA
+#ifdef CRDS
+ asm_fprintf (stream, "\ttstl %d(%Rsp)\n", NEED_PROBE - num_saved_regs * 4);
+#else
+ asm_fprintf (stream, "\ttst.l %d(%Rsp)\n", NEED_PROBE - num_saved_regs * 4);
+#endif
+#else
+ asm_fprintf (stream, "\ttstl %Rsp@(%d)\n", NEED_PROBE - num_saved_regs * 4);
+#endif
+#endif
+
+ if (num_saved_regs <= 2)
+ {
+ /* Store each separately in the same order moveml uses.
+ Using two movel instructions instead of a single moveml
+ is about 15% faster for the 68020 and 68030 at no expense
+ in code size */
+
+ int i;
+
+ /* Undo the work from above. */
+ for (i = 0; i< 16; i++)
+ if (mask & (1 << i))
+ {
+ asm_fprintf (stream,
+#ifdef MOTOROLA
+ "\t%Omove.l %s,-(%Rsp)\n",
+#else
+ "\tmovel %s,%Rsp@-\n",
+#endif
+ reg_names[15 - i]);
+ if (dwarf2out_do_frame ())
+ {
+ char *l = (char *) dwarf2out_cfi_label ();
+
+ cfa_store_offset += 4;
+ if (! frame_pointer_needed)
+ {
+ cfa_offset = cfa_store_offset;
+ dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
+ }
+ dwarf2out_reg_save (l, 15 - i, -cfa_store_offset);
+ }
+ }
+ }
+ else if (mask)
+ {
+ if (TARGET_5200)
+ {
+ /* The coldfire does not support the predecrement form of the
+ movml instruction, so we must adjust the stack pointer and
+ then use the plain address register indirect mode. We also
+ have to invert the register save mask to use the new mode.
+
+ FIXME: if num_saved_regs was calculated earlier, we could
+ combine the stack pointer adjustment with any adjustment
+ done when the initial stack frame is created. This would
+ save an instruction */
+
+ int newmask = 0;
+ int i;
+
+ for (i = 0; i < 16; i++)
+ if (mask & (1 << i))
+ newmask |= (1 << (15-i));
+
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", -num_saved_regs*4);
+ asm_fprintf (stream, "\tmovm.l %0I0x%x,(%Rsp)\n", newmask);
+#else
+ asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", -num_saved_regs*4);
+ asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@\n", newmask);
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask);
+#else
+ asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@-\n", mask);
+#endif
+ }
+ if (dwarf2out_do_frame ())
+ {
+ char *l = (char *) dwarf2out_cfi_label ();
+ int n_regs;
+
+ cfa_store_offset += num_saved_regs * 4;
+ if (! frame_pointer_needed)
+ {
+ cfa_offset = cfa_store_offset;
+ dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
+ }
+ for (regno = 0, n_regs = 0; regno < 16; regno++)
+ if (mask & (1 << (15 - regno)))
+ dwarf2out_reg_save (l, regno,
+ -cfa_store_offset + n_regs++ * 4);
+ }
+ }
+ if (flag_pic && current_function_uses_pic_offset_table)
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
+ reg_names[PIC_OFFSET_TABLE_REGNUM]);
+#else
+ asm_fprintf (stream, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",
+ reg_names[PIC_OFFSET_TABLE_REGNUM]);
+ asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n",
+ reg_names[PIC_OFFSET_TABLE_REGNUM],
+ reg_names[PIC_OFFSET_TABLE_REGNUM]);
+#endif
+ }
+}
+
+/* Return true if this function's epilogue can be output as RTL. */
+
+int
+use_return_insn ()
+{
+ int regno;
+
+ if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)
+ return 0;
+
+ /* Copied from output_function_epilogue (). We should probably create a
+ separate layout routine to perform the common work. */
+
+ for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ return 0;
+
+ return 1;
+}
+
+/* This function generates the assembly code for function exit,
+ on machines that need it. Args are same as for FUNCTION_PROLOGUE.
+
+ The function epilogue should not depend on the current stack pointer!
+ It should use the frame pointer only, if there is a frame pointer.
+ This is mandatory because of alloca; we also take advantage of it to
+ omit stack adjustments before returning. */
+
+void
+output_function_epilogue (stream, size)
+ FILE *stream;
+ int size;
+{
+ register int regno;
+ register int mask, fmask;
+ register int nregs;
+ int offset, foffset, fpoffset;
+ extern char call_used_regs[];
+ int fsize = (size + 3) & -4;
+ int big = 0;
+ rtx insn = get_last_insn ();
+ int restore_from_sp = 0;
+
+ /* If the last insn was a BARRIER, we don't have to write any code. */
+ if (GET_CODE (insn) == NOTE)
+ insn = prev_nonnote_insn (insn);
+ if (insn && GET_CODE (insn) == BARRIER)
+ {
+ /* Output just a no-op so that debuggers don't get confused
+ about which function the pc is in at this address. */
+ asm_fprintf (stream, "\tnop\n");
+ return;
+ }
+
+#ifdef FUNCTION_BLOCK_PROFILER_EXIT
+ if (profile_block_flag == 2)
+ {
+ FUNCTION_BLOCK_PROFILER_EXIT (stream);
+ }
+#endif
+
+#ifdef FUNCTION_EXTRA_EPILOGUE
+ FUNCTION_EXTRA_EPILOGUE (stream, size);
+#endif
+ nregs = 0; fmask = 0; fpoffset = 0;
+#ifdef SUPPORT_SUN_FPA
+ for (regno = 24 ; regno < 56 ; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ nregs++;
+ fpoffset = nregs * 8;
+#endif
+ nregs = 0;
+ if (TARGET_68881)
+ {
+ for (regno = 16; regno < 24; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ nregs++;
+ fmask |= 1 << (23 - regno);
+ }
+ }
+ foffset = fpoffset + nregs * 12;
+ nregs = 0; mask = 0;
+ if (frame_pointer_needed)
+ regs_ever_live[FRAME_POINTER_REGNUM] = 0;
+ for (regno = 0; regno < 16; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ nregs++;
+ mask |= 1 << regno;
+ }
+ offset = foffset + nregs * 4;
+ /* FIXME : leaf_function_p below is too strong.
+ What we really need to know there is if there could be pending
+ stack adjustment needed at that point. */
+ restore_from_sp = ! frame_pointer_needed
+ || (! current_function_calls_alloca && leaf_function_p ());
+ if (offset + fsize >= 0x8000
+ && ! restore_from_sp
+ && (mask || fmask || fpoffset))
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\t%Omove.l %0I%d,%Ra1\n", -fsize);
+#else
+ asm_fprintf (stream, "\tmovel %0I%d,%Ra1\n", -fsize);
+#endif
+ fsize = 0, big = 1;
+ }
+ if (TARGET_5200 || nregs <= 2)
+ {
+ /* Restore each separately in the same order moveml does.
+ Using two movel instructions instead of a single moveml
+ is about 15% faster for the 68020 and 68030 at no expense
+ in code size. */
+
+ int i;
+
+ /* Undo the work from above. */
+ for (i = 0; i< 16; i++)
+ if (mask & (1 << i))
+ {
+ if (big)
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\t%Omove.l -%d(%s,%Ra1.l),%s\n",
+ offset + fsize,
+ reg_names[FRAME_POINTER_REGNUM],
+ reg_names[i]);
+#else
+ asm_fprintf (stream, "\tmovel %s@(-%d,%Ra1:l),%s\n",
+ reg_names[FRAME_POINTER_REGNUM],
+ offset + fsize, reg_names[i]);
+#endif
+ }
+ else if (restore_from_sp)
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\t%Omove.l (%Rsp)+,%s\n",
+ reg_names[i]);
+#else
+ asm_fprintf (stream, "\tmovel %Rsp@+,%s\n",
+ reg_names[i]);
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\t%Omove.l -%d(%s),%s\n",
+ offset + fsize,
+ reg_names[FRAME_POINTER_REGNUM],
+ reg_names[i]);
+#else
+ asm_fprintf (stream, "\tmovel %s@(-%d),%s\n",
+ reg_names[FRAME_POINTER_REGNUM],
+ offset + fsize, reg_names[i]);
+#endif
+ }
+ offset = offset - 4;
+ }
+ }
+ else if (mask)
+ {
+ if (big)
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tmovm.l -%d(%s,%Ra1.l),%0I0x%x\n",
+ offset + fsize,
+ reg_names[FRAME_POINTER_REGNUM],
+ mask);
+#else
+ asm_fprintf (stream, "\tmoveml %s@(-%d,%Ra1:l),%0I0x%x\n",
+ reg_names[FRAME_POINTER_REGNUM],
+ offset + fsize, mask);
+#endif
+ }
+ else if (restore_from_sp)
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask);
+#else
+ asm_fprintf (stream, "\tmoveml %Rsp@+,%0I0x%x\n", mask);
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tmovm.l -%d(%s),%0I0x%x\n",
+ offset + fsize,
+ reg_names[FRAME_POINTER_REGNUM],
+ mask);
+#else
+ asm_fprintf (stream, "\tmoveml %s@(-%d),%0I0x%x\n",
+ reg_names[FRAME_POINTER_REGNUM],
+ offset + fsize, mask);
+#endif
+ }
+ }
+ if (fmask)
+ {
+ if (big)
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tfmovm -%d(%s,%Ra1.l),%0I0x%x\n",
+ foffset + fsize,
+ reg_names[FRAME_POINTER_REGNUM],
+ fmask);
+#else
+ asm_fprintf (stream, "\tfmovem %s@(-%d,%Ra1:l),%0I0x%x\n",
+ reg_names[FRAME_POINTER_REGNUM],
+ foffset + fsize, fmask);
+#endif
+ }
+ else if (restore_from_sp)
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask);
+#else
+ asm_fprintf (stream, "\tfmovem %Rsp@+,%0I0x%x\n", fmask);
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tfmovm -%d(%s),%0I0x%x\n",
+ foffset + fsize,
+ reg_names[FRAME_POINTER_REGNUM],
+ fmask);
+#else
+ asm_fprintf (stream, "\tfmovem %s@(-%d),%0I0x%x\n",
+ reg_names[FRAME_POINTER_REGNUM],
+ foffset + fsize, fmask);
+#endif
+ }
+ }
+ if (fpoffset != 0)
+ for (regno = 55; regno >= 24; regno--)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ if (big)
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tfpmovd -%d(%s,%Ra1.l), %s\n",
+ fpoffset + fsize,
+ reg_names[FRAME_POINTER_REGNUM],
+ reg_names[regno]);
+#else
+ asm_fprintf (stream, "\tfpmoved %s@(-%d,%Ra1:l), %s\n",
+ reg_names[FRAME_POINTER_REGNUM],
+ fpoffset + fsize, reg_names[regno]);
+#endif
+ }
+ else if (restore_from_sp)
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tfpmovd (%Rsp)+,%s\n",
+ reg_names[regno]);
+#else
+ asm_fprintf (stream, "\tfpmoved %Rsp@+, %s\n",
+ reg_names[regno]);
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tfpmovd -%d(%s), %s\n",
+ fpoffset + fsize,
+ reg_names[FRAME_POINTER_REGNUM],
+ reg_names[regno]);
+#else
+ asm_fprintf (stream, "\tfpmoved %s@(-%d), %s\n",
+ reg_names[FRAME_POINTER_REGNUM],
+ fpoffset + fsize, reg_names[regno]);
+#endif
+ }
+ fpoffset -= 8;
+ }
+ if (frame_pointer_needed)
+ fprintf (stream, "\tunlk %s\n",
+ reg_names[FRAME_POINTER_REGNUM]);
+ else if (fsize)
+ {
+#ifndef NO_ADDSUB_Q
+ if (fsize + 4 <= 8)
+ {
+ if (!TARGET_5200)
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\taddq.w %0I%d,%Rsp\n", fsize + 4);
+#else
+ asm_fprintf (stream, "\taddqw %0I%d,%Rsp\n", fsize + 4);
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\taddq.l %0I%d,%Rsp\n", fsize + 4);
+#else
+ asm_fprintf (stream, "\taddql %0I%d,%Rsp\n", fsize + 4);
+#endif
+ }
+ }
+ else if (fsize + 4 <= 16 && TARGET_CPU32)
+ {
+ /* On the CPU32 it is faster to use two addqw instructions to
+ add a small integer (8 < N <= 16) to a register. */
+ /* asm_fprintf() cannot handle %. */
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\taddq.w %0I8,%Rsp\n\taddq.w %0I%d,%Rsp\n",
+ fsize + 4);
+#else
+ asm_fprintf (stream, "\taddqw %0I8,%Rsp\n\taddqw %0I%d,%Rsp\n",
+ fsize + 4);
+#endif
+ }
+ else
+#endif /* not NO_ADDSUB_Q */
+ if (fsize + 4 < 0x8000)
+ {
+ if (TARGET_68040)
+ {
+ /* asm_fprintf() cannot handle %. */
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", fsize + 4);
+#else
+ asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", fsize + 4);
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", fsize + 4);
+#else
+ asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", fsize + 4);
+#endif
+ }
+ }
+ else
+ {
+ /* asm_fprintf() cannot handle %. */
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", fsize + 4);
+#else
+ asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", fsize + 4);
+#endif
+ }
+ }
+ if (current_function_pops_args)
+ asm_fprintf (stream, "\trtd %0I%d\n", current_function_pops_args);
+ else
+ fprintf (stream, "\trts\n");
+}
+
+/* Similar to general_operand, but exclude stack_pointer_rtx. */
+
+int
+not_sp_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ return op != stack_pointer_rtx && general_operand (op, mode);
+}
+
+/* Return TRUE if X is a valid comparison operator for the dbcc
+ instruction.
+
+ Note it rejects floating point comparison operators.
+ (In the future we could use Fdbcc).
+
+ It also rejects some comparisons when CC_NO_OVERFLOW is set. */
+
+int
+valid_dbcc_comparison_p (x, mode)
+ rtx x;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ switch (GET_CODE (x))
+ {
+ case EQ: case NE: case GTU: case LTU:
+ case GEU: case LEU:
+ return 1;
+
+ /* Reject some when CC_NO_OVERFLOW is set. This may be over
+ conservative */
+ case GT: case LT: case GE: case LE:
+ return ! (cc_prev_status.flags & CC_NO_OVERFLOW);
+ default:
+ return 0;
+ }
+}
+
+/* Return non-zero if flags are currently in the 68881 flag register. */
+int
+flags_in_68881 ()
+{
+ /* We could add support for these in the future */
+ return cc_status.flags & CC_IN_68881;
+}
+
+/* Output a dbCC; jCC sequence. Note we do not handle the
+ floating point version of this sequence (Fdbcc). We also
+ do not handle alternative conditions when CC_NO_OVERFLOW is
+ set. It is assumed that valid_dbcc_comparison_p and flags_in_68881 will
+ kick those out before we get here. */
+
+void
+output_dbcc_and_branch (operands)
+ rtx *operands;
+{
+ switch (GET_CODE (operands[3]))
+ {
+ case EQ:
+#ifdef MOTOROLA
+ output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands);
+#else
+ output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands);
+#endif
+ break;
+
+ case NE:
+#ifdef MOTOROLA
+ output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands);
+#else
+ output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands);
+#endif
+ break;
+
+ case GT:
+#ifdef MOTOROLA
+ output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands);
+#else
+ output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands);
+#endif
+ break;
+
+ case GTU:
+#ifdef MOTOROLA
+ output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands);
+#else
+ output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands);
+#endif
+ break;
+
+ case LT:
+#ifdef MOTOROLA
+ output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands);
+#else
+ output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands);
+#endif
+ break;
+
+ case LTU:
+#ifdef MOTOROLA
+ output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands);
+#else
+ output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands);
+#endif
+ break;
+
+ case GE:
+#ifdef MOTOROLA
+ output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands);
+#else
+ output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands);
+#endif
+ break;
+
+ case GEU:
+#ifdef MOTOROLA
+ output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands);
+#else
+ output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands);
+#endif
+ break;
+
+ case LE:
+#ifdef MOTOROLA
+ output_asm_insn ("dble %0,%l1\n\tjble %l2", operands);
+#else
+ output_asm_insn ("dble %0,%l1\n\tjle %l2", operands);
+#endif
+ break;
+
+ case LEU:
+#ifdef MOTOROLA
+ output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands);
+#else
+ output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands);
+#endif
+ break;
+
+ default:
+ abort ();
+ }
+
+ /* If the decrement is to be done in SImode, then we have
+ to compensate for the fact that dbcc decrements in HImode. */
+ switch (GET_MODE (operands[0]))
+ {
+ case SImode:
+#ifdef MOTOROLA
+ output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands);
+#else
+ output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands);
+#endif
+ break;
+
+ case HImode:
+ break;
+
+ default:
+ abort ();
+ }
+}
+
+char *
+output_scc_di(op, operand1, operand2, dest)
+ rtx op;
+ rtx operand1;
+ rtx operand2;
+ rtx dest;
+{
+ rtx loperands[7];
+ enum rtx_code op_code = GET_CODE (op);
+
+ /* This does not produce a usefull cc. */
+ CC_STATUS_INIT;
+
+ /* The m68k cmp.l instruction requires operand1 to be a reg as used
+ below. Swap the operands and change the op if these requirements
+ are not fulfilled. */
+ if (GET_CODE (operand2) == REG && GET_CODE (operand1) != REG)
+ {
+ rtx tmp = operand1;
+
+ operand1 = operand2;
+ operand2 = tmp;
+ op_code = swap_condition (op_code);
+ }
+ loperands[0] = operand1;
+ if (GET_CODE (operand1) == REG)
+ loperands[1] = gen_rtx_REG (SImode, REGNO (operand1) + 1);
+ else
+ loperands[1] = adj_offsettable_operand (operand1, 4);
+ if (operand2 != const0_rtx)
+ {
+ loperands[2] = operand2;
+ if (GET_CODE (operand2) == REG)
+ loperands[3] = gen_rtx_REG (SImode, REGNO (operand2) + 1);
+ else
+ loperands[3] = adj_offsettable_operand (operand2, 4);
+ }
+ loperands[4] = gen_label_rtx();
+ if (operand2 != const0_rtx)
+ {
+#ifdef MOTOROLA
+#ifdef SGS_CMP_ORDER
+ output_asm_insn ("cmp%.l %0,%2\n\tjbne %l4\n\tcmp%.l %1,%3", loperands);
+#else
+ output_asm_insn ("cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1", loperands);
+#endif
+#else
+#ifdef SGS_CMP_ORDER
+ output_asm_insn ("cmp%.l %0,%2\n\tjne %l4\n\tcmp%.l %1,%3", loperands);
+#else
+ output_asm_insn ("cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1", loperands);
+#endif
+#endif
+ }
+ else
+ {
+ if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (loperands[0]))
+ output_asm_insn ("tst%.l %0", loperands);
+ else
+ {
+#ifdef SGS_CMP_ORDER
+ output_asm_insn ("cmp%.w %0,%#0", loperands);
+#else
+ output_asm_insn ("cmp%.w %#0,%0", loperands);
+#endif
+ }
+
+#ifdef MOTOROLA
+ output_asm_insn ("jbne %l4", loperands);
+#else
+ output_asm_insn ("jne %l4", loperands);
+#endif
+
+ if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (loperands[1]))
+ output_asm_insn ("tst%.l %1", loperands);
+ else
+ {
+#ifdef SGS_CMP_ORDER
+ output_asm_insn ("cmp%.w %1,%#0", loperands);
+#else
+ output_asm_insn ("cmp%.w %#0,%1", loperands);
+#endif
+ }
+ }
+
+ loperands[5] = dest;
+
+ switch (op_code)
+ {
+ case EQ:
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (loperands[4]));
+ output_asm_insn ("seq %5", loperands);
+ break;
+
+ case NE:
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (loperands[4]));
+ output_asm_insn ("sne %5", loperands);
+ break;
+
+ case GT:
+ loperands[6] = gen_label_rtx();
+#ifdef MOTOROLA
+ output_asm_insn ("shi %5\n\tjbra %l6", loperands);
+#else
+ output_asm_insn ("shi %5\n\tjra %l6", loperands);
+#endif
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (loperands[4]));
+ output_asm_insn ("sgt %5", loperands);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (loperands[6]));
+ break;
+
+ case GTU:
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (loperands[4]));
+ output_asm_insn ("shi %5", loperands);
+ break;
+
+ case LT:
+ loperands[6] = gen_label_rtx();
+#ifdef MOTOROLA
+ output_asm_insn ("scs %5\n\tjbra %l6", loperands);
+#else
+ output_asm_insn ("scs %5\n\tjra %l6", loperands);
+#endif
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (loperands[4]));
+ output_asm_insn ("slt %5", loperands);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (loperands[6]));
+ break;
+
+ case LTU:
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (loperands[4]));
+ output_asm_insn ("scs %5", loperands);
+ break;
+
+ case GE:
+ loperands[6] = gen_label_rtx();
+#ifdef MOTOROLA
+ output_asm_insn ("scc %5\n\tjbra %l6", loperands);
+#else
+ output_asm_insn ("scc %5\n\tjra %l6", loperands);
+#endif
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (loperands[4]));
+ output_asm_insn ("sge %5", loperands);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (loperands[6]));
+ break;
+
+ case GEU:
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (loperands[4]));
+ output_asm_insn ("scc %5", loperands);
+ break;
+
+ case LE:
+ loperands[6] = gen_label_rtx();
+#ifdef MOTOROLA
+ output_asm_insn ("sls %5\n\tjbra %l6", loperands);
+#else
+ output_asm_insn ("sls %5\n\tjra %l6", loperands);
+#endif
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (loperands[4]));
+ output_asm_insn ("sle %5", loperands);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (loperands[6]));
+ break;
+
+ case LEU:
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (loperands[4]));
+ output_asm_insn ("sls %5", loperands);
+ break;
+
+ default:
+ abort ();
+ }
+ return "";
+}
+
+char *
+output_btst (operands, countop, dataop, insn, signpos)
+ rtx *operands;
+ rtx countop, dataop;
+ rtx insn;
+ int signpos;
+{
+ operands[0] = countop;
+ operands[1] = dataop;
+
+ if (GET_CODE (countop) == CONST_INT)
+ {
+ register int count = INTVAL (countop);
+ /* If COUNT is bigger than size of storage unit in use,
+ advance to the containing unit of same size. */
+ if (count > signpos)
+ {
+ int offset = (count & ~signpos) / 8;
+ count = count & signpos;
+ operands[1] = dataop = adj_offsettable_operand (dataop, offset);
+ }
+ if (count == signpos)
+ cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
+ else
+ cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
+
+ /* These three statements used to use next_insns_test_no...
+ but it appears that this should do the same job. */
+ if (count == 31
+ && next_insn_tests_no_inequality (insn))
+ return "tst%.l %1";
+ if (count == 15
+ && next_insn_tests_no_inequality (insn))
+ return "tst%.w %1";
+ if (count == 7
+ && next_insn_tests_no_inequality (insn))
+ return "tst%.b %1";
+
+ cc_status.flags = CC_NOT_NEGATIVE;
+ }
+ return "btst %0,%1";
+}
+
+/* Returns 1 if OP is either a symbol reference or a sum of a symbol
+ reference and a constant. */
+
+int
+symbolic_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ switch (GET_CODE (op))
+ {
+ case SYMBOL_REF:
+ case LABEL_REF:
+ return 1;
+
+ case CONST:
+ op = XEXP (op, 0);
+ return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+ || GET_CODE (XEXP (op, 0)) == LABEL_REF)
+ && GET_CODE (XEXP (op, 1)) == CONST_INT);
+
+#if 0 /* Deleted, with corresponding change in m68k.h,
+ so as to fit the specs. No CONST_DOUBLE is ever symbolic. */
+ case CONST_DOUBLE:
+ return GET_MODE (op) == mode;
+#endif
+
+ default:
+ return 0;
+ }
+}
+
+/* Check for sign_extend or zero_extend. Used for bit-count operands. */
+
+int
+extend_operator(x, mode)
+ rtx x;
+ enum machine_mode mode;
+{
+ if (mode != VOIDmode && GET_MODE(x) != mode)
+ return 0;
+ switch (GET_CODE(x))
+ {
+ case SIGN_EXTEND :
+ case ZERO_EXTEND :
+ return 1;
+ default :
+ return 0;
+ }
+}
+
+
+/* Legitimize PIC addresses. If the address is already
+ position-independent, we return ORIG. Newly generated
+ position-independent addresses go to REG. If we need more
+ than one register, we lose.
+
+ An address is legitimized by making an indirect reference
+ through the Global Offset Table with the name of the symbol
+ used as an offset.
+
+ The assembler and linker are responsible for placing the
+ address of the symbol in the GOT. The function prologue
+ is responsible for initializing a5 to the starting address
+ of the GOT.
+
+ The assembler is also responsible for translating a symbol name
+ into a constant displacement from the start of the GOT.
+
+ A quick example may make things a little clearer:
+
+ When not generating PIC code to store the value 12345 into _foo
+ we would generate the following code:
+
+ movel #12345, _foo
+
+ When generating PIC two transformations are made. First, the compiler
+ loads the address of foo into a register. So the first transformation makes:
+
+ lea _foo, a0
+ movel #12345, a0@
+
+ The code in movsi will intercept the lea instruction and call this
+ routine which will transform the instructions into:
+
+ movel a5@(_foo:w), a0
+ movel #12345, a0@
+
+
+ That (in a nutshell) is how *all* symbol and label references are
+ handled. */
+
+rtx
+legitimize_pic_address (orig, mode, reg)
+ rtx orig, reg;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ rtx pic_ref = orig;
+
+ /* First handle a simple SYMBOL_REF or LABEL_REF */
+ if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
+ {
+ if (reg == 0)
+ abort ();
+
+ pic_ref = gen_rtx_MEM (Pmode,
+ gen_rtx_PLUS (Pmode,
+ pic_offset_table_rtx, orig));
+ current_function_uses_pic_offset_table = 1;
+ if (reload_in_progress)
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+ RTX_UNCHANGING_P (pic_ref) = 1;
+ emit_move_insn (reg, pic_ref);
+ return reg;
+ }
+ else if (GET_CODE (orig) == CONST)
+ {
+ rtx base;
+
+ /* Make sure this is CONST has not already been legitimized */
+ if (GET_CODE (XEXP (orig, 0)) == PLUS
+ && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
+ return orig;
+
+ if (reg == 0)
+ abort ();
+
+ /* legitimize both operands of the PLUS */
+ if (GET_CODE (XEXP (orig, 0)) == PLUS)
+ {
+ base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
+ orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
+ base == reg ? 0 : reg);
+ }
+ else abort ();
+
+ if (GET_CODE (orig) == CONST_INT)
+ return plus_constant_for_output (base, INTVAL (orig));
+ pic_ref = gen_rtx_PLUS (Pmode, base, orig);
+ /* Likewise, should we set special REG_NOTEs here? */
+ }
+ return pic_ref;
+}
+
+
+typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ } CONST_METHOD;
+
+#define USE_MOVQ(i) ((unsigned)((i) + 128) <= 255)
+
+CONST_METHOD
+const_method (constant)
+ rtx constant;
+{
+ int i;
+ unsigned u;
+
+ i = INTVAL (constant);
+ if (USE_MOVQ (i))
+ return MOVQ;
+
+ /* The Coldfire doesn't have byte or word operations. */
+ /* FIXME: This may not be useful for the m68060 either */
+ if (!TARGET_5200)
+ {
+ /* if -256 < N < 256 but N is not in range for a moveq
+ N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */
+ if (USE_MOVQ (i ^ 0xff))
+ return NOTB;
+ /* Likewise, try with not.w */
+ if (USE_MOVQ (i ^ 0xffff))
+ return NOTW;
+ /* This is the only value where neg.w is useful */
+ if (i == -65408)
+ return NEGW;
+ /* Try also with swap */
+ u = i;
+ if (USE_MOVQ ((u >> 16) | (u << 16)))
+ return SWAP;
+ }
+ /* Otherwise, use move.l */
+ return MOVL;
+}
+
+int
+const_int_cost (constant)
+ rtx constant;
+{
+ switch (const_method (constant))
+ {
+ case MOVQ :
+ /* Constants between -128 and 127 are cheap due to moveq */
+ return 0;
+ case NOTB :
+ case NOTW :
+ case NEGW :
+ case SWAP :
+ /* Constants easily generated by moveq + not.b/not.w/neg.w/swap */
+ return 1;
+ case MOVL :
+ return 2;
+ default :
+ abort ();
+ }
+}
+
+char *
+output_move_const_into_data_reg (operands)
+ rtx *operands;
+{
+ int i;
+
+ i = INTVAL (operands[1]);
+ switch (const_method (operands[1]))
+ {
+ case MOVQ :
+#if defined (MOTOROLA) && !defined (CRDS)
+ return "moveq%.l %1,%0";
+#else
+ return "moveq %1,%0";
+#endif
+ case NOTB :
+ operands[1] = GEN_INT (i ^ 0xff);
+#if defined (MOTOROLA) && !defined (CRDS)
+ return "moveq%.l %1,%0\n\tnot%.b %0";
+#else
+ return "moveq %1,%0\n\tnot%.b %0";
+#endif
+ case NOTW :
+ operands[1] = GEN_INT (i ^ 0xffff);
+#if defined (MOTOROLA) && !defined (CRDS)
+ return "moveq%.l %1,%0\n\tnot%.w %0";
+#else
+ return "moveq %1,%0\n\tnot%.w %0";
+#endif
+ case NEGW :
+#if defined (MOTOROLA) && !defined (CRDS)
+ return "moveq%.l %#-128,%0\n\tneg%.w %0";
+#else
+ return "moveq %#-128,%0\n\tneg%.w %0";
+#endif
+ case SWAP :
+ {
+ unsigned u = i;
+
+ operands[1] = GEN_INT ((u << 16) | (u >> 16));
+#if defined (MOTOROLA) && !defined (CRDS)
+ return "moveq%.l %1,%0\n\tswap %0";
+#else
+ return "moveq %1,%0\n\tswap %0";
+#endif
+ }
+ case MOVL :
+ return "move%.l %1,%0";
+ default :
+ abort ();
+ }
+}
+
+char *
+output_move_simode_const (operands)
+ rtx *operands;
+{
+ if (operands[1] == const0_rtx
+ && (DATA_REG_P (operands[0])
+ || GET_CODE (operands[0]) == MEM)
+ /* clr insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no TARGET_68010. */
+ && ((TARGET_68020 || TARGET_5200)
+ || !(GET_CODE (operands[0]) == MEM
+ && MEM_VOLATILE_P (operands[0]))))
+ return "clr%.l %0";
+ else if (operands[1] == const0_rtx
+ && ADDRESS_REG_P (operands[0]))
+ return "sub%.l %0,%0";
+ else if (DATA_REG_P (operands[0]))
+ return output_move_const_into_data_reg (operands);
+ else if (ADDRESS_REG_P (operands[0])
+ && INTVAL (operands[1]) < 0x8000
+ && INTVAL (operands[1]) >= -0x8000)
+ return "move%.w %1,%0";
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
+ && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
+ && INTVAL (operands[1]) < 0x8000
+ && INTVAL (operands[1]) >= -0x8000)
+ return "pea %a1";
+ return "move%.l %1,%0";
+}
+
+char *
+output_move_simode (operands)
+ rtx *operands;
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return output_move_simode_const (operands);
+ else if ((GET_CODE (operands[1]) == SYMBOL_REF
+ || GET_CODE (operands[1]) == CONST)
+ && push_operand (operands[0], SImode))
+ return "pea %a1";
+ else if ((GET_CODE (operands[1]) == SYMBOL_REF
+ || GET_CODE (operands[1]) == CONST)
+ && ADDRESS_REG_P (operands[0]))
+ return "lea %a1,%0";
+ return "move%.l %1,%0";
+}
+
+char *
+output_move_himode (operands)
+ rtx *operands;
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (operands[1] == const0_rtx
+ && (DATA_REG_P (operands[0])
+ || GET_CODE (operands[0]) == MEM)
+ /* clr insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no TARGET_68010. */
+ && ((TARGET_68020 || TARGET_5200)
+ || !(GET_CODE (operands[0]) == MEM
+ && MEM_VOLATILE_P (operands[0]))))
+ return "clr%.w %0";
+ else if (operands[1] == const0_rtx
+ && ADDRESS_REG_P (operands[0]))
+ return "sub%.l %0,%0";
+ else if (DATA_REG_P (operands[0])
+ && INTVAL (operands[1]) < 128
+ && INTVAL (operands[1]) >= -128)
+ {
+#if defined(MOTOROLA) && !defined(CRDS)
+ return "moveq%.l %1,%0";
+#else
+ return "moveq %1,%0";
+#endif
+ }
+ else if (INTVAL (operands[1]) < 0x8000
+ && INTVAL (operands[1]) >= -0x8000)
+ return "move%.w %1,%0";
+ }
+ else if (CONSTANT_P (operands[1]))
+ return "move%.l %1,%0";
+#ifndef SGS_NO_LI
+ /* Recognize the insn before a tablejump, one that refers
+ to a table of offsets. Such an insn will need to refer
+ to a label on the insn. So output one. Use the label-number
+ of the table of offsets to generate this label. This code,
+ and similar code below, assumes that there will be at most one
+ reference to each table. */
+ if (GET_CODE (operands[1]) == MEM
+ && GET_CODE (XEXP (operands[1], 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS)
+ {
+ rtx labelref = XEXP (XEXP (operands[1], 0), 1);
+#if defined (MOTOROLA) && !defined (SGS_SWITCH_TABLES)
+#ifdef SGS
+ asm_fprintf (asm_out_file, "\tset %LLI%d,.+2\n",
+ CODE_LABEL_NUMBER (XEXP (labelref, 0)));
+#else /* not SGS */
+ asm_fprintf (asm_out_file, "\t.set %LLI%d,.+2\n",
+ CODE_LABEL_NUMBER (XEXP (labelref, 0)));
+#endif /* not SGS */
+#else /* SGS_SWITCH_TABLES or not MOTOROLA */
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LI",
+ CODE_LABEL_NUMBER (XEXP (labelref, 0)));
+#ifdef SGS_SWITCH_TABLES
+ /* Set flag saying we need to define the symbol
+ LD%n (with value L%n-LI%n) at the end of the switch table. */
+ switch_table_difference_label_flag = 1;
+#endif /* SGS_SWITCH_TABLES */
+#endif /* SGS_SWITCH_TABLES or not MOTOROLA */
+ }
+#endif /* SGS_NO_LI */
+ return "move%.w %1,%0";
+}
+
+char *
+output_move_qimode (operands)
+ rtx *operands;
+{
+ rtx xoperands[4];
+
+ /* This is probably useless, since it loses for pushing a struct
+ of several bytes a byte at a time. */
+ /* 68k family always modifies the stack pointer by at least 2, even for
+ byte pushes. The 5200 (coldfire) does not do this. */
+ if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
+ && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx
+ && ! ADDRESS_REG_P (operands[1])
+ && ! TARGET_5200)
+ {
+ xoperands[1] = operands[1];
+ xoperands[2]
+ = gen_rtx_MEM (QImode,
+ gen_rtx_PLUS (VOIDmode, stack_pointer_rtx, const1_rtx));
+ /* Just pushing a byte puts it in the high byte of the halfword. */
+ /* We must put it in the low-order, high-numbered byte. */
+ if (!reg_mentioned_p (stack_pointer_rtx, operands[1]))
+ {
+ xoperands[3] = stack_pointer_rtx;
+#ifndef NO_ADDSUB_Q
+ output_asm_insn ("subq%.l %#2,%3\n\tmove%.b %1,%2", xoperands);
+#else
+ output_asm_insn ("sub%.l %#2,%3\n\tmove%.b %1,%2", xoperands);
+#endif
+ }
+ else
+ output_asm_insn ("move%.b %1,%-\n\tmove%.b %@,%2", xoperands);
+ return "";
+ }
+
+ /* clr and st insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no TARGET_68010. */
+ if (!ADDRESS_REG_P (operands[0])
+ && ((TARGET_68020 || TARGET_5200)
+ || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
+ {
+ if (operands[1] == const0_rtx)
+ return "clr%.b %0";
+ if ((!TARGET_5200 || DATA_REG_P (operands[0]))
+ && GET_CODE (operands[1]) == CONST_INT
+ && (INTVAL (operands[1]) & 255) == 255)
+ {
+ CC_STATUS_INIT;
+ return "st %0";
+ }
+ }
+ if (GET_CODE (operands[1]) == CONST_INT
+ && DATA_REG_P (operands[0])
+ && INTVAL (operands[1]) < 128
+ && INTVAL (operands[1]) >= -128)
+ {
+#if defined(MOTOROLA) && !defined(CRDS)
+ return "moveq%.l %1,%0";
+#else
+ return "moveq %1,%0";
+#endif
+ }
+ if (operands[1] == const0_rtx && ADDRESS_REG_P (operands[0]))
+ return "sub%.l %0,%0";
+ if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1]))
+ return "move%.l %1,%0";
+ /* 68k family (including the 5200 coldfire) does not support byte moves to
+ from address registers. */
+ if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1]))
+ return "move%.w %1,%0";
+ return "move%.b %1,%0";
+}
+
+char *
+output_move_stricthi (operands)
+ rtx *operands;
+{
+ if (operands[1] == const0_rtx
+ /* clr insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no TARGET_68010. */
+ && ((TARGET_68020 || TARGET_5200)
+ || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
+ return "clr%.w %0";
+ return "move%.w %1,%0";
+}
+
+char *
+output_move_strictqi (operands)
+ rtx *operands;
+{
+ if (operands[1] == const0_rtx
+ /* clr insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no TARGET_68010. */
+ && ((TARGET_68020 || TARGET_5200)
+ || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
+ return "clr%.b %0";
+ return "move%.b %1,%0";
+}
+
+/* Return the best assembler insn template
+ for moving operands[1] into operands[0] as a fullword. */
+
+static char *
+singlemove_string (operands)
+ rtx *operands;
+{
+#ifdef SUPPORT_SUN_FPA
+ if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1]))
+ return "fpmoves %1,%0";
+#endif
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return output_move_simode_const (operands);
+ return "move%.l %1,%0";
+}
+
+
+/* Output assembler code to perform a doubleword move insn
+ with operands OPERANDS. */
+
+char *
+output_move_double (operands)
+ rtx *operands;
+{
+ enum
+ {
+ REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP
+ } optype0, optype1;
+ rtx latehalf[2];
+ rtx middlehalf[2];
+ rtx xops[2];
+ rtx addreg0 = 0, addreg1 = 0;
+ int dest_overlapped_low = 0;
+ int size = GET_MODE_SIZE (GET_MODE (operands[0]));
+
+ middlehalf[0] = 0;
+ middlehalf[1] = 0;
+
+ /* First classify both operands. */
+
+ if (REG_P (operands[0]))
+ optype0 = REGOP;
+ else if (offsettable_memref_p (operands[0]))
+ optype0 = OFFSOP;
+ else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ optype0 = POPOP;
+ else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ optype0 = PUSHOP;
+ else if (GET_CODE (operands[0]) == MEM)
+ optype0 = MEMOP;
+ else
+ optype0 = RNDOP;
+
+ if (REG_P (operands[1]))
+ optype1 = REGOP;
+ else if (CONSTANT_P (operands[1]))
+ optype1 = CNSTOP;
+ else if (offsettable_memref_p (operands[1]))
+ optype1 = OFFSOP;
+ else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
+ optype1 = POPOP;
+ else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
+ optype1 = PUSHOP;
+ else if (GET_CODE (operands[1]) == MEM)
+ optype1 = MEMOP;
+ else
+ optype1 = RNDOP;
+
+ /* Check for the cases that the operand constraints are not
+ supposed to allow to happen. Abort if we get one,
+ because generating code for these cases is painful. */
+
+ if (optype0 == RNDOP || optype1 == RNDOP)
+ abort ();
+
+ /* If one operand is decrementing and one is incrementing
+ decrement the former register explicitly
+ and change that operand into ordinary indexing. */
+
+ if (optype0 == PUSHOP && optype1 == POPOP)
+ {
+ operands[0] = XEXP (XEXP (operands[0], 0), 0);
+ if (size == 12)
+ output_asm_insn ("sub%.l %#12,%0", operands);
+ else
+ output_asm_insn ("subq%.l %#8,%0", operands);
+ if (GET_MODE (operands[1]) == XFmode)
+ operands[0] = gen_rtx_MEM (XFmode, operands[0]);
+ else if (GET_MODE (operands[0]) == DFmode)
+ operands[0] = gen_rtx_MEM (DFmode, operands[0]);
+ else
+ operands[0] = gen_rtx_MEM (DImode, operands[0]);
+ optype0 = OFFSOP;
+ }
+ if (optype0 == POPOP && optype1 == PUSHOP)
+ {
+ operands[1] = XEXP (XEXP (operands[1], 0), 0);
+ if (size == 12)
+ output_asm_insn ("sub%.l %#12,%1", operands);
+ else
+ output_asm_insn ("subq%.l %#8,%1", operands);
+ if (GET_MODE (operands[1]) == XFmode)
+ operands[1] = gen_rtx_MEM (XFmode, operands[1]);
+ else if (GET_MODE (operands[1]) == DFmode)
+ operands[1] = gen_rtx_MEM (DFmode, operands[1]);
+ else
+ operands[1] = gen_rtx_MEM (DImode, operands[1]);
+ optype1 = OFFSOP;
+ }
+
+ /* If an operand is an unoffsettable memory ref, find a register
+ we can increment temporarily to make it refer to the second word. */
+
+ if (optype0 == MEMOP)
+ addreg0 = find_addr_reg (XEXP (operands[0], 0));
+
+ if (optype1 == MEMOP)
+ addreg1 = find_addr_reg (XEXP (operands[1], 0));
+
+ /* Ok, we can do one word at a time.
+ Normally we do the low-numbered word first,
+ but if either operand is autodecrementing then we
+ do the high-numbered word first.
+
+ In either case, set up in LATEHALF the operands to use
+ for the high-numbered word and in some cases alter the
+ operands in OPERANDS to be suitable for the low-numbered word. */
+
+ if (size == 12)
+ {
+ if (optype0 == REGOP)
+ {
+ latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
+ middlehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ }
+ else if (optype0 == OFFSOP)
+ {
+ middlehalf[0] = adj_offsettable_operand (operands[0], 4);
+ latehalf[0] = adj_offsettable_operand (operands[0], size - 4);
+ }
+ else
+ {
+ middlehalf[0] = operands[0];
+ latehalf[0] = operands[0];
+ }
+
+ if (optype1 == REGOP)
+ {
+ latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
+ middlehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+ }
+ else if (optype1 == OFFSOP)
+ {
+ middlehalf[1] = adj_offsettable_operand (operands[1], 4);
+ latehalf[1] = adj_offsettable_operand (operands[1], size - 4);
+ }
+ else if (optype1 == CNSTOP)
+ {
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ REAL_VALUE_TYPE r;
+ long l[3];
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
+ operands[1] = GEN_INT (l[0]);
+ middlehalf[1] = GEN_INT (l[1]);
+ latehalf[1] = GEN_INT (l[2]);
+ }
+ else if (CONSTANT_P (operands[1]))
+ {
+ /* actually, no non-CONST_DOUBLE constant should ever
+ appear here. */
+ abort ();
+ if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
+ latehalf[1] = constm1_rtx;
+ else
+ latehalf[1] = const0_rtx;
+ }
+ }
+ else
+ {
+ middlehalf[1] = operands[1];
+ latehalf[1] = operands[1];
+ }
+ }
+ else
+ /* size is not 12: */
+ {
+ if (optype0 == REGOP)
+ latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ else if (optype0 == OFFSOP)
+ latehalf[0] = adj_offsettable_operand (operands[0], size - 4);
+ else
+ latehalf[0] = operands[0];
+
+ if (optype1 == REGOP)
+ latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+ else if (optype1 == OFFSOP)
+ latehalf[1] = adj_offsettable_operand (operands[1], size - 4);
+ else if (optype1 == CNSTOP)
+ split_double (operands[1], &operands[1], &latehalf[1]);
+ else
+ latehalf[1] = operands[1];
+ }
+
+ /* If insn is effectively movd N(sp),-(sp) then we will do the
+ high word first. We should use the adjusted operand 1 (which is N+4(sp))
+ for the low word as well, to compensate for the first decrement of sp. */
+ if (optype0 == PUSHOP
+ && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
+ && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
+ operands[1] = middlehalf[1] = latehalf[1];
+
+ /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
+ if the upper part of reg N does not appear in the MEM, arrange to
+ emit the move late-half first. Otherwise, compute the MEM address
+ into the upper part of N and use that as a pointer to the memory
+ operand. */
+ if (optype0 == REGOP
+ && (optype1 == OFFSOP || optype1 == MEMOP))
+ {
+ rtx testlow = gen_rtx_REG (SImode, REGNO (operands[0]));
+
+ if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
+ && reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
+ {
+ /* If both halves of dest are used in the src memory address,
+ compute the address into latehalf of dest.
+ Note that this can't happen if the dest is two data regs. */
+compadr:
+ xops[0] = latehalf[0];
+ xops[1] = XEXP (operands[1], 0);
+ output_asm_insn ("lea %a1,%0", xops);
+ if( GET_MODE (operands[1]) == XFmode )
+ {
+ operands[1] = gen_rtx_MEM (XFmode, latehalf[0]);
+ middlehalf[1] = adj_offsettable_operand (operands[1], size-8);
+ latehalf[1] = adj_offsettable_operand (operands[1], size-4);
+ }
+ else
+ {
+ operands[1] = gen_rtx_MEM (DImode, latehalf[0]);
+ latehalf[1] = adj_offsettable_operand (operands[1], size-4);
+ }
+ }
+ else if (size == 12
+ && reg_overlap_mentioned_p (middlehalf[0],
+ XEXP (operands[1], 0)))
+ {
+ /* Check for two regs used by both source and dest.
+ Note that this can't happen if the dest is all data regs.
+ It can happen if the dest is d6, d7, a0.
+ But in that case, latehalf is an addr reg, so
+ the code at compadr does ok. */
+
+ if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
+ || reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
+ goto compadr;
+
+ /* JRV says this can't happen: */
+ if (addreg0 || addreg1)
+ abort ();
+
+ /* Only the middle reg conflicts; simply put it last. */
+ output_asm_insn (singlemove_string (operands), operands);
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+ output_asm_insn (singlemove_string (middlehalf), middlehalf);
+ return "";
+ }
+ else if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0)))
+ /* If the low half of dest is mentioned in the source memory
+ address, the arrange to emit the move late half first. */
+ dest_overlapped_low = 1;
+ }
+
+ /* If one or both operands autodecrementing,
+ do the two words, high-numbered first. */
+
+ /* Likewise, the first move would clobber the source of the second one,
+ do them in the other order. This happens only for registers;
+ such overlap can't happen in memory unless the user explicitly
+ sets it up, and that is an undefined circumstance. */
+
+ if (optype0 == PUSHOP || optype1 == PUSHOP
+ || (optype0 == REGOP && optype1 == REGOP
+ && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1]))
+ || REGNO (operands[0]) == REGNO (latehalf[1])))
+ || dest_overlapped_low)
+ {
+ /* Make any unoffsettable addresses point at high-numbered word. */
+ if (addreg0)
+ {
+ if (size == 12)
+ output_asm_insn ("addq%.l %#8,%0", &addreg0);
+ else
+ output_asm_insn ("addq%.l %#4,%0", &addreg0);
+ }
+ if (addreg1)
+ {
+ if (size == 12)
+ output_asm_insn ("addq%.l %#8,%0", &addreg1);
+ else
+ output_asm_insn ("addq%.l %#4,%0", &addreg1);
+ }
+
+ /* Do that word. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Undo the adds we just did. */
+ if (addreg0)
+ output_asm_insn ("subq%.l %#4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("subq%.l %#4,%0", &addreg1);
+
+ if (size == 12)
+ {
+ output_asm_insn (singlemove_string (middlehalf), middlehalf);
+ if (addreg0)
+ output_asm_insn ("subq%.l %#4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("subq%.l %#4,%0", &addreg1);
+ }
+
+ /* Do low-numbered word. */
+ return singlemove_string (operands);
+ }
+
+ /* Normal case: do the two words, low-numbered first. */
+
+ output_asm_insn (singlemove_string (operands), operands);
+
+ /* Do the middle one of the three words for long double */
+ if (size == 12)
+ {
+ if (addreg0)
+ output_asm_insn ("addq%.l %#4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("addq%.l %#4,%0", &addreg1);
+
+ output_asm_insn (singlemove_string (middlehalf), middlehalf);
+ }
+
+ /* Make any unoffsettable addresses point at high-numbered word. */
+ if (addreg0)
+ output_asm_insn ("addq%.l %#4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("addq%.l %#4,%0", &addreg1);
+
+ /* Do that word. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Undo the adds we just did. */
+ if (addreg0)
+ {
+ if (size == 12)
+ output_asm_insn ("subq%.l %#8,%0", &addreg0);
+ else
+ output_asm_insn ("subq%.l %#4,%0", &addreg0);
+ }
+ if (addreg1)
+ {
+ if (size == 12)
+ output_asm_insn ("subq%.l %#8,%0", &addreg1);
+ else
+ output_asm_insn ("subq%.l %#4,%0", &addreg1);
+ }
+
+ return "";
+}
+
+/* Return a REG that occurs in ADDR with coefficient 1.
+ ADDR can be effectively incremented by incrementing REG. */
+
+static rtx
+find_addr_reg (addr)
+ rtx addr;
+{
+ while (GET_CODE (addr) == PLUS)
+ {
+ if (GET_CODE (XEXP (addr, 0)) == REG)
+ addr = XEXP (addr, 0);
+ else if (GET_CODE (XEXP (addr, 1)) == REG)
+ addr = XEXP (addr, 1);
+ else if (CONSTANT_P (XEXP (addr, 0)))
+ addr = XEXP (addr, 1);
+ else if (CONSTANT_P (XEXP (addr, 1)))
+ addr = XEXP (addr, 0);
+ else
+ abort ();
+ }
+ if (GET_CODE (addr) == REG)
+ return addr;
+ abort ();
+}
+
+/* Output assembler code to perform a 32 bit 3 operand add. */
+
+char *
+output_addsi3 (operands)
+ rtx *operands;
+{
+ if (! operands_match_p (operands[0], operands[1]))
+ {
+ if (!ADDRESS_REG_P (operands[1]))
+ {
+ rtx tmp = operands[1];
+
+ operands[1] = operands[2];
+ operands[2] = tmp;
+ }
+
+ /* These insns can result from reloads to access
+ stack slots over 64k from the frame pointer. */
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) + 0x8000 >= (unsigned) 0x10000)
+ return "move%.l %2,%0\n\tadd%.l %1,%0";
+#ifdef SGS
+ if (GET_CODE (operands[2]) == REG)
+ return "lea 0(%1,%2.l),%0";
+ else
+ return "lea %c2(%1),%0";
+#else /* not SGS */
+#ifdef MOTOROLA
+ if (GET_CODE (operands[2]) == REG)
+ return "lea (%1,%2.l),%0";
+ else
+ return "lea (%c2,%1),%0";
+#else /* not MOTOROLA (MIT syntax) */
+ if (GET_CODE (operands[2]) == REG)
+ return "lea %1@(0,%2:l),%0";
+ else
+ return "lea %1@(%c2),%0";
+#endif /* not MOTOROLA */
+#endif /* not SGS */
+ }
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+#ifndef NO_ADDSUB_Q
+ if (INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) <= 8)
+ return "addq%.l %2,%0";
+ if (INTVAL (operands[2]) < 0
+ && INTVAL (operands[2]) >= -8)
+ {
+ operands[2] = GEN_INT (-INTVAL (operands[2]));
+ return "subq%.l %2,%0";
+ }
+ /* On the CPU32 it is faster to use two addql instructions to
+ add a small integer (8 < N <= 16) to a register.
+ Likewise for subql. */
+ if (TARGET_CPU32 && REG_P (operands[0]))
+ {
+ if (INTVAL (operands[2]) > 8
+ && INTVAL (operands[2]) <= 16)
+ {
+ operands[2] = GEN_INT (INTVAL (operands[2]) - 8);
+ return "addq%.l %#8,%0\n\taddq%.l %2,%0";
+ }
+ if (INTVAL (operands[2]) < -8
+ && INTVAL (operands[2]) >= -16)
+ {
+ operands[2] = GEN_INT (-INTVAL (operands[2]) - 8);
+ return "subq%.l %#8,%0\n\tsubq%.l %2,%0";
+ }
+ }
+#endif
+ if (ADDRESS_REG_P (operands[0])
+ && INTVAL (operands[2]) >= -0x8000
+ && INTVAL (operands[2]) < 0x8000)
+ {
+ if (TARGET_68040)
+ return "add%.w %2,%0";
+ else
+#ifdef MOTOROLA
+ return "lea (%c2,%0),%0";
+#else
+ return "lea %0@(%c2),%0";
+#endif
+ }
+ }
+ return "add%.l %2,%0";
+}
+
+/* Store in cc_status the expressions that the condition codes will
+ describe after execution of an instruction whose pattern is EXP.
+ Do not alter them if the instruction would not alter the cc's. */
+
+/* On the 68000, all the insns to store in an address register fail to
+ set the cc's. However, in some cases these instructions can make it
+ possibly invalid to use the saved cc's. In those cases we clear out
+ some or all of the saved cc's so they won't be used. */
+
+void
+notice_update_cc (exp, insn)
+ rtx exp;
+ rtx insn;
+{
+ /* If the cc is being set from the fpa and the expression is not an
+ explicit floating point test instruction (which has code to deal with
+ this), reinit the CC. */
+ if (((cc_status.value1 && FPA_REG_P (cc_status.value1))
+ || (cc_status.value2 && FPA_REG_P (cc_status.value2)))
+ && !(GET_CODE (exp) == PARALLEL
+ && GET_CODE (XVECEXP (exp, 0, 0)) == SET
+ && XEXP (XVECEXP (exp, 0, 0), 0) == cc0_rtx))
+ {
+ CC_STATUS_INIT;
+ }
+ else if (GET_CODE (exp) == SET)
+ {
+ if (GET_CODE (SET_SRC (exp)) == CALL)
+ {
+ CC_STATUS_INIT;
+ }
+ else if (ADDRESS_REG_P (SET_DEST (exp)))
+ {
+ if (cc_status.value1 && modified_in_p (cc_status.value1, insn))
+ cc_status.value1 = 0;
+ if (cc_status.value2 && modified_in_p (cc_status.value2, insn))
+ cc_status.value2 = 0;
+ }
+ else if (!FP_REG_P (SET_DEST (exp))
+ && SET_DEST (exp) != cc0_rtx
+ && (FP_REG_P (SET_SRC (exp))
+ || GET_CODE (SET_SRC (exp)) == FIX
+ || GET_CODE (SET_SRC (exp)) == FLOAT_TRUNCATE
+ || GET_CODE (SET_SRC (exp)) == FLOAT_EXTEND))
+ {
+ CC_STATUS_INIT;
+ }
+ /* A pair of move insns doesn't produce a useful overall cc. */
+ else if (!FP_REG_P (SET_DEST (exp))
+ && !FP_REG_P (SET_SRC (exp))
+ && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
+ && (GET_CODE (SET_SRC (exp)) == REG
+ || GET_CODE (SET_SRC (exp)) == MEM
+ || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
+ {
+ CC_STATUS_INIT;
+ }
+ else if (GET_CODE (SET_SRC (exp)) == CALL)
+ {
+ CC_STATUS_INIT;
+ }
+ else if (XEXP (exp, 0) != pc_rtx)
+ {
+ cc_status.flags = 0;
+ cc_status.value1 = XEXP (exp, 0);
+ cc_status.value2 = XEXP (exp, 1);
+ }
+ }
+ else if (GET_CODE (exp) == PARALLEL
+ && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
+ {
+ if (ADDRESS_REG_P (XEXP (XVECEXP (exp, 0, 0), 0)))
+ CC_STATUS_INIT;
+ else if (XEXP (XVECEXP (exp, 0, 0), 0) != pc_rtx)
+ {
+ cc_status.flags = 0;
+ cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
+ cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1);
+ }
+ }
+ else
+ CC_STATUS_INIT;
+ if (cc_status.value2 != 0
+ && ADDRESS_REG_P (cc_status.value2)
+ && GET_MODE (cc_status.value2) == QImode)
+ CC_STATUS_INIT;
+ if (cc_status.value2 != 0
+ && !(cc_status.value1 && FPA_REG_P (cc_status.value1)))
+ switch (GET_CODE (cc_status.value2))
+ {
+ case PLUS: case MINUS: case MULT:
+ case DIV: case UDIV: case MOD: case UMOD: case NEG:
+#if 0 /* These instructions always clear the overflow bit */
+ case ASHIFT: case ASHIFTRT: case LSHIFTRT:
+ case ROTATE: case ROTATERT:
+#endif
+ if (GET_MODE (cc_status.value2) != VOIDmode)
+ cc_status.flags |= CC_NO_OVERFLOW;
+ break;
+ case ZERO_EXTEND:
+ /* (SET r1 (ZERO_EXTEND r2)) on this machine
+ ends with a move insn moving r2 in r2's mode.
+ Thus, the cc's are set for r2.
+ This can set N bit spuriously. */
+ cc_status.flags |= CC_NOT_NEGATIVE;
+
+ default:
+ break;
+ }
+ if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
+ && cc_status.value2
+ && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
+ cc_status.value2 = 0;
+ if (((cc_status.value1 && FP_REG_P (cc_status.value1))
+ || (cc_status.value2 && FP_REG_P (cc_status.value2)))
+ && !((cc_status.value1 && FPA_REG_P (cc_status.value1))
+ || (cc_status.value2 && FPA_REG_P (cc_status.value2))))
+ cc_status.flags = CC_IN_68881;
+}
+
+char *
+output_move_const_double (operands)
+ rtx *operands;
+{
+#ifdef SUPPORT_SUN_FPA
+ if (TARGET_FPA && FPA_REG_P (operands[0]))
+ {
+ int code = standard_sun_fpa_constant_p (operands[1]);
+
+ if (code != 0)
+ {
+ static char buf[40];
+
+ sprintf (buf, "fpmove%%.d %%%%%d,%%0", code & 0x1ff);
+ return buf;
+ }
+ return "fpmove%.d %1,%0";
+ }
+ else
+#endif
+ {
+ int code = standard_68881_constant_p (operands[1]);
+
+ if (code != 0)
+ {
+ static char buf[40];
+
+ sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
+ return buf;
+ }
+ return "fmove%.d %1,%0";
+ }
+}
+
+char *
+output_move_const_single (operands)
+ rtx *operands;
+{
+#ifdef SUPPORT_SUN_FPA
+ if (TARGET_FPA)
+ {
+ int code = standard_sun_fpa_constant_p (operands[1]);
+
+ if (code != 0)
+ {
+ static char buf[40];
+
+ sprintf (buf, "fpmove%%.s %%%%%d,%%0", code & 0x1ff);
+ return buf;
+ }
+ return "fpmove%.s %1,%0";
+ }
+ else
+#endif /* defined SUPPORT_SUN_FPA */
+ {
+ int code = standard_68881_constant_p (operands[1]);
+
+ if (code != 0)
+ {
+ static char buf[40];
+
+ sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
+ return buf;
+ }
+ return "fmove%.s %f1,%0";
+ }
+}
+
+/* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
+ from the "fmovecr" instruction.
+ The value, anded with 0xff, gives the code to use in fmovecr
+ to get the desired constant. */
+
+/* This code has been fixed for cross-compilation. */
+
+static int inited_68881_table = 0;
+
+char *strings_68881[7] = {
+ "0.0",
+ "1.0",
+ "10.0",
+ "100.0",
+ "10000.0",
+ "1e8",
+ "1e16"
+ };
+
+int codes_68881[7] = {
+ 0x0f,
+ 0x32,
+ 0x33,
+ 0x34,
+ 0x35,
+ 0x36,
+ 0x37
+ };
+
+REAL_VALUE_TYPE values_68881[7];
+
+/* Set up values_68881 array by converting the decimal values
+ strings_68881 to binary. */
+
+void
+init_68881_table ()
+{
+ int i;
+ REAL_VALUE_TYPE r;
+ enum machine_mode mode;
+
+ mode = SFmode;
+ for (i = 0; i < 7; i++)
+ {
+ if (i == 6)
+ mode = DFmode;
+ r = REAL_VALUE_ATOF (strings_68881[i], mode);
+ values_68881[i] = r;
+ }
+ inited_68881_table = 1;
+}
+
+int
+standard_68881_constant_p (x)
+ rtx x;
+{
+ REAL_VALUE_TYPE r;
+ int i;
+
+#ifdef NO_ASM_FMOVECR
+ return 0;
+#endif
+
+ /* fmovecr must be emulated on the 68040 and 68060, so it shouldn't be
+ used at all on those chips. */
+ if (TARGET_68040 || TARGET_68060)
+ return 0;
+
+#ifndef REAL_ARITHMETIC
+#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
+ if (! flag_pretend_float)
+ return 0;
+#endif
+#endif
+
+ if (! inited_68881_table)
+ init_68881_table ();
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+
+ for (i = 0; i < 6; i++)
+ {
+ if (REAL_VALUES_EQUAL (r, values_68881[i]))
+ return (codes_68881[i]);
+ }
+
+ if (GET_MODE (x) == SFmode)
+ return 0;
+
+ if (REAL_VALUES_EQUAL (r, values_68881[6]))
+ return (codes_68881[6]);
+
+ /* larger powers of ten in the constants ram are not used
+ because they are not equal to a `double' C constant. */
+ return 0;
+}
+
+/* If X is a floating-point constant, return the logarithm of X base 2,
+ or 0 if X is not a power of 2. */
+
+int
+floating_exact_log2 (x)
+ rtx x;
+{
+ REAL_VALUE_TYPE r, r1;
+ int i;
+
+#ifndef REAL_ARITHMETIC
+#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
+ if (! flag_pretend_float)
+ return 0;
+#endif
+#endif
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+
+ if (REAL_VALUES_LESS (r, dconst0))
+ return 0;
+
+ r1 = dconst1;
+ i = 0;
+ while (REAL_VALUES_LESS (r1, r))
+ {
+ r1 = REAL_VALUE_LDEXP (dconst1, i);
+ if (REAL_VALUES_EQUAL (r1, r))
+ return i;
+ i = i + 1;
+ }
+ return 0;
+}
+
+#ifdef SUPPORT_SUN_FPA
+/* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
+ from the Sun FPA's constant RAM.
+ The value returned, anded with 0x1ff, gives the code to use in fpmove
+ to get the desired constant. */
+
+static int inited_FPA_table = 0;
+
+char *strings_FPA[38] = {
+/* small rationals */
+ "0.0",
+ "1.0",
+ "0.5",
+ "-1.0",
+ "2.0",
+ "3.0",
+ "4.0",
+ "8.0",
+ "0.25",
+ "0.125",
+ "10.0",
+ "-0.5",
+/* Decimal equivalents of double precision values */
+ "2.718281828459045091", /* D_E */
+ "6.283185307179586477", /* 2 pi */
+ "3.141592653589793116", /* D_PI */
+ "1.570796326794896619", /* pi/2 */
+ "1.414213562373095145", /* D_SQRT2 */
+ "0.7071067811865475244", /* 1/sqrt(2) */
+ "-1.570796326794896619", /* -pi/2 */
+ "1.442695040888963387", /* D_LOG2ofE */
+ "3.321928024887362182", /* D_LOG2of10 */
+ "0.6931471805599452862", /* D_LOGEof2 */
+ "2.302585092994045901", /* D_LOGEof10 */
+ "0.3010299956639811980", /* D_LOG10of2 */
+ "0.4342944819032518167", /* D_LOG10ofE */
+/* Decimal equivalents of single precision values */
+ "2.718281745910644531", /* S_E */
+ "6.283185307179586477", /* 2 pi */
+ "3.141592741012573242", /* S_PI */
+ "1.570796326794896619", /* pi/2 */
+ "1.414213538169860840", /* S_SQRT2 */
+ "0.7071067811865475244", /* 1/sqrt(2) */
+ "-1.570796326794896619", /* -pi/2 */
+ "1.442695021629333496", /* S_LOG2ofE */
+ "3.321928024291992188", /* S_LOG2of10 */
+ "0.6931471824645996094", /* S_LOGEof2 */
+ "2.302585124969482442", /* S_LOGEof10 */
+ "0.3010300099849700928", /* S_LOG10of2 */
+ "0.4342944920063018799", /* S_LOG10ofE */
+};
+
+
+int codes_FPA[38] = {
+/* small rationals */
+ 0x200,
+ 0xe,
+ 0xf,
+ 0x10,
+ 0x11,
+ 0xb1,
+ 0x12,
+ 0x13,
+ 0x15,
+ 0x16,
+ 0x17,
+ 0x2e,
+/* double precision */
+ 0x8,
+ 0x9,
+ 0xa,
+ 0xb,
+ 0xc,
+ 0xd,
+ 0x27,
+ 0x28,
+ 0x29,
+ 0x2a,
+ 0x2b,
+ 0x2c,
+ 0x2d,
+/* single precision */
+ 0x8,
+ 0x9,
+ 0xa,
+ 0xb,
+ 0xc,
+ 0xd,
+ 0x27,
+ 0x28,
+ 0x29,
+ 0x2a,
+ 0x2b,
+ 0x2c,
+ 0x2d
+ };
+
+REAL_VALUE_TYPE values_FPA[38];
+
+/* This code has been fixed for cross-compilation. */
+
+void
+init_FPA_table ()
+{
+ enum machine_mode mode;
+ int i;
+ REAL_VALUE_TYPE r;
+
+ mode = DFmode;
+ for (i = 0; i < 38; i++)
+ {
+ if (i == 25)
+ mode = SFmode;
+ r = REAL_VALUE_ATOF (strings_FPA[i], mode);
+ values_FPA[i] = r;
+ }
+ inited_FPA_table = 1;
+}
+
+
+int
+standard_sun_fpa_constant_p (x)
+ rtx x;
+{
+ REAL_VALUE_TYPE r;
+ int i;
+
+#ifndef REAL_ARITHMETIC
+#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
+ if (! flag_pretend_float)
+ return 0;
+#endif
+#endif
+
+ if (! inited_FPA_table)
+ init_FPA_table ();
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+
+ for (i=0; i<12; i++)
+ {
+ if (REAL_VALUES_EQUAL (r, values_FPA[i]))
+ return (codes_FPA[i]);
+ }
+
+ if (GET_MODE (x) == SFmode)
+ {
+ for (i=25; i<38; i++)
+ {
+ if (REAL_VALUES_EQUAL (r, values_FPA[i]))
+ return (codes_FPA[i]);
+ }
+ }
+ else
+ {
+ for (i=12; i<25; i++)
+ {
+ if (REAL_VALUES_EQUAL (r, values_FPA[i]))
+ return (codes_FPA[i]);
+ }
+ }
+ return 0x0;
+}
+#endif /* define SUPPORT_SUN_FPA */
+
+/* A C compound statement to output to stdio stream STREAM the
+ assembler syntax for an instruction operand X. X is an RTL
+ expression.
+
+ CODE is a value that can be used to specify one of several ways
+ of printing the operand. It is used when identical operands
+ must be printed differently depending on the context. CODE
+ comes from the `%' specification that was used to request
+ printing of the operand. If the specification was just `%DIGIT'
+ then CODE is 0; if the specification was `%LTR DIGIT' then CODE
+ is the ASCII code for LTR.
+
+ If X is a register, this macro should print the register's name.
+ The names can be found in an array `reg_names' whose type is
+ `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
+
+ When the machine description has a specification `%PUNCT' (a `%'
+ followed by a punctuation character), this macro is called with
+ a null pointer for X and the punctuation character for CODE.
+
+ The m68k specific codes are:
+
+ '.' for dot needed in Motorola-style opcode names.
+ '-' for an operand pushing on the stack:
+ sp@-, -(sp) or -(%sp) depending on the style of syntax.
+ '+' for an operand pushing on the stack:
+ sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
+ '@' for a reference to the top word on the stack:
+ sp@, (sp) or (%sp) depending on the style of syntax.
+ '#' for an immediate operand prefix (# in MIT and Motorola syntax
+ but & in SGS syntax, $ in CRDS/UNOS syntax).
+ '!' for the cc register (used in an `and to cc' insn).
+ '$' 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.
+ 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
+ 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
+ than directly). Second part of 'y' below.
+ 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
+ or print pair of registers as rx:ry.
+ 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
+ CONST_DOUBLE's as SunFPA constant RAM registers if
+ possible, so it should not be used except for the SunFPA.
+
+ */
+
+void
+print_operand (file, op, letter)
+ FILE *file; /* file to write to */
+ rtx op; /* operand to print */
+ int letter; /* %<letter> or 0 */
+{
+#ifdef SUPPORT_SUN_FPA
+ int i;
+#endif
+
+ if (letter == '.')
+ {
+#if defined (MOTOROLA) && !defined (CRDS)
+ asm_fprintf (file, ".");
+#endif
+ }
+ else if (letter == '#')
+ {
+ asm_fprintf (file, "%0I");
+ }
+ else if (letter == '-')
+ {
+#ifdef MOTOROLA
+ asm_fprintf (file, "-(%Rsp)");
+#else
+ asm_fprintf (file, "%Rsp@-");
+#endif
+ }
+ else if (letter == '+')
+ {
+#ifdef MOTOROLA
+ asm_fprintf (file, "(%Rsp)+");
+#else
+ asm_fprintf (file, "%Rsp@+");
+#endif
+ }
+ else if (letter == '@')
+ {
+#ifdef MOTOROLA
+ asm_fprintf (file, "(%Rsp)");
+#else
+ asm_fprintf (file, "%Rsp@");
+#endif
+ }
+ else if (letter == '!')
+ {
+ asm_fprintf (file, "%Rfpcr");
+ }
+ else if (letter == '$')
+ {
+ if (TARGET_68040_ONLY)
+ {
+ fprintf (file, "s");
+ }
+ }
+ else if (letter == '&')
+ {
+ if (TARGET_68040_ONLY)
+ {
+ fprintf (file, "d");
+ }
+ }
+ else if (letter == '/')
+ {
+ asm_fprintf (file, "%R");
+ }
+ else if (GET_CODE (op) == REG)
+ {
+#ifdef SUPPORT_SUN_FPA
+ if (REGNO (op) < 16
+ && (letter == 'y' || letter == 'x')
+ && GET_MODE (op) == DFmode)
+ {
+ fprintf (file, "%s:%s", reg_names[REGNO (op)],
+ reg_names[REGNO (op)+1]);
+ }
+ else
+#endif
+ {
+ if (letter == 'R')
+ /* Print out the second register name of a register pair.
+ I.e., R (6) => 7. */
+ fputs (reg_names[REGNO (op) + 1], file);
+ else
+ fputs (reg_names[REGNO (op)], file);
+ }
+ }
+ else if (GET_CODE (op) == MEM)
+ {
+ output_address (XEXP (op, 0));
+ if (letter == 'd' && ! TARGET_68020
+ && CONSTANT_ADDRESS_P (XEXP (op, 0))
+ && !(GET_CODE (XEXP (op, 0)) == CONST_INT
+ && INTVAL (XEXP (op, 0)) < 0x8000
+ && INTVAL (XEXP (op, 0)) >= -0x8000))
+ {
+#ifdef MOTOROLA
+ fprintf (file, ".l");
+#else
+ fprintf (file, ":l");
+#endif
+ }
+ }
+#ifdef SUPPORT_SUN_FPA
+ else if ((letter == 'y' || letter == 'w')
+ && GET_CODE (op) == CONST_DOUBLE
+ && (i = standard_sun_fpa_constant_p (op)))
+ {
+ fprintf (file, "%%%d", i & 0x1ff);
+ }
+#endif
+ else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
+ {
+ REAL_VALUE_TYPE r;
+ REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+ ASM_OUTPUT_FLOAT_OPERAND (letter, file, r);
+ }
+ else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == XFmode)
+ {
+ REAL_VALUE_TYPE r;
+ REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+ ASM_OUTPUT_LONG_DOUBLE_OPERAND (file, r);
+ }
+ else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
+ {
+ REAL_VALUE_TYPE r;
+ REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+ ASM_OUTPUT_DOUBLE_OPERAND (file, r);
+ }
+ else
+ {
+ asm_fprintf (file, "%0I"); output_addr_const (file, op);
+ }
+}
+
+
+/* A C compound statement to output to stdio stream STREAM the
+ assembler syntax for an instruction operand that is a memory
+ reference whose address is ADDR. ADDR is an RTL expression.
+
+ Note that this contains a kludge that knows that the only reason
+ we have an address (plus (label_ref...) (reg...)) when not generating
+ PIC code is in the insn before a tablejump, and we know that m68k.md
+ generates a label LInnn: on such an insn.
+
+ It is possible for PIC to generate a (plus (label_ref...) (reg...))
+ and we handle that just like we would a (plus (symbol_ref...) (reg...)).
+
+ Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
+ fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
+ we want. This difference can be accommodated by using an assembler
+ define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
+ string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
+ macro. See m68k/sgs.h for an example; for versions without the bug.
+ Some assemblers refuse all the above solutions. The workaround is to
+ emit "K(pc,d0.l*2)" with K being a small constant known to give the
+ right behaviour.
+
+ They also do not like things like "pea 1.w", so we simple leave off
+ the .w on small constants.
+
+ This routine is responsible for distinguishing between -fpic and -fPIC
+ style relocations in an address. When generating -fpic code the
+ offset is output in word mode (eg movel a5@(_foo:w), a0). When generating
+ -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
+
+#ifndef ASM_OUTPUT_CASE_FETCH
+#ifdef MOTOROLA
+#ifdef SGS
+#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
+ asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
+#else
+#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
+ asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
+#endif
+#else
+#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
+ asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
+#endif
+#endif /* ASM_OUTPUT_CASE_FETCH */
+
+void
+print_operand_address (file, addr)
+ FILE *file;
+ rtx addr;
+{
+ register rtx reg1, reg2, breg, ireg;
+ rtx offset;
+
+ switch (GET_CODE (addr))
+ {
+ case REG:
+#ifdef MOTOROLA
+ fprintf (file, "(%s)", reg_names[REGNO (addr)]);
+#else
+ fprintf (file, "%s@", reg_names[REGNO (addr)]);
+#endif
+ break;
+ case PRE_DEC:
+#ifdef MOTOROLA
+ fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
+#else
+ fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]);
+#endif
+ break;
+ case POST_INC:
+#ifdef MOTOROLA
+ fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
+#else
+ fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]);
+#endif
+ break;
+ case PLUS:
+ reg1 = reg2 = ireg = breg = offset = 0;
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
+ {
+ offset = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
+ {
+ offset = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ if (GET_CODE (addr) != PLUS)
+ {
+ ;
+ }
+ else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
+ {
+ reg1 = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
+ {
+ reg1 = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ else if (GET_CODE (XEXP (addr, 0)) == MULT)
+ {
+ reg1 = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else if (GET_CODE (XEXP (addr, 1)) == MULT)
+ {
+ reg1 = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ else if (GET_CODE (XEXP (addr, 0)) == REG)
+ {
+ reg1 = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else if (GET_CODE (XEXP (addr, 1)) == REG)
+ {
+ reg1 = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
+ || GET_CODE (addr) == SIGN_EXTEND)
+ {
+ if (reg1 == 0)
+ {
+ reg1 = addr;
+ }
+ else
+ {
+ reg2 = addr;
+ }
+ addr = 0;
+ }
+#if 0 /* for OLD_INDEXING */
+ else if (GET_CODE (addr) == PLUS)
+ {
+ if (GET_CODE (XEXP (addr, 0)) == REG)
+ {
+ reg2 = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else if (GET_CODE (XEXP (addr, 1)) == REG)
+ {
+ reg2 = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ }
+#endif
+ if (offset != 0)
+ {
+ if (addr != 0)
+ {
+ abort ();
+ }
+ addr = offset;
+ }
+ if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
+ || GET_CODE (reg1) == MULT))
+ || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
+ {
+ breg = reg2;
+ ireg = reg1;
+ }
+ else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
+ {
+ breg = reg1;
+ ireg = reg2;
+ }
+ if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
+ && ! (flag_pic && ireg == pic_offset_table_rtx))
+ {
+ int scale = 1;
+ if (GET_CODE (ireg) == MULT)
+ {
+ scale = INTVAL (XEXP (ireg, 1));
+ ireg = XEXP (ireg, 0);
+ }
+ if (GET_CODE (ireg) == SIGN_EXTEND)
+ {
+ ASM_OUTPUT_CASE_FETCH (file,
+ CODE_LABEL_NUMBER (XEXP (addr, 0)),
+ reg_names[REGNO (XEXP (ireg, 0))]);
+ fprintf (file, "w");
+ }
+ else
+ {
+ ASM_OUTPUT_CASE_FETCH (file,
+ CODE_LABEL_NUMBER (XEXP (addr, 0)),
+ reg_names[REGNO (ireg)]);
+ fprintf (file, "l");
+ }
+ if (scale != 1)
+ {
+#ifdef MOTOROLA
+ fprintf (file, "*%d", scale);
+#else
+ fprintf (file, ":%d", scale);
+#endif
+ }
+ putc (')', file);
+ break;
+ }
+ if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
+ && ! (flag_pic && breg == pic_offset_table_rtx))
+ {
+ ASM_OUTPUT_CASE_FETCH (file,
+ CODE_LABEL_NUMBER (XEXP (addr, 0)),
+ reg_names[REGNO (breg)]);
+ fprintf (file, "l)");
+ break;
+ }
+ if (ireg != 0 || breg != 0)
+ {
+ int scale = 1;
+ if (breg == 0)
+ {
+ abort ();
+ }
+ if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
+ {
+ abort ();
+ }
+#ifdef MOTOROLA
+ if (addr != 0)
+ {
+ output_addr_const (file, addr);
+ if (flag_pic && (breg == pic_offset_table_rtx))
+ {
+ fprintf (file, "@GOT");
+ if (flag_pic == 1)
+ fprintf (file, ".w");
+ }
+ }
+ fprintf (file, "(%s", reg_names[REGNO (breg)]);
+ if (ireg != 0)
+ {
+ putc (',', file);
+ }
+#else
+ fprintf (file, "%s@(", reg_names[REGNO (breg)]);
+ if (addr != 0)
+ {
+ output_addr_const (file, addr);
+ if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
+ fprintf (file, ":w");
+ if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
+ fprintf (file, ":l");
+ }
+ if (addr != 0 && ireg != 0)
+ {
+ putc (',', file);
+ }
+#endif
+ if (ireg != 0 && GET_CODE (ireg) == MULT)
+ {
+ scale = INTVAL (XEXP (ireg, 1));
+ ireg = XEXP (ireg, 0);
+ }
+ if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
+ {
+#ifdef MOTOROLA
+ fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);
+#else
+ fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]);
+#endif
+ }
+ else if (ireg != 0)
+ {
+#ifdef MOTOROLA
+ fprintf (file, "%s.l", reg_names[REGNO (ireg)]);
+#else
+ fprintf (file, "%s:l", reg_names[REGNO (ireg)]);
+#endif
+ }
+ if (scale != 1)
+ {
+#ifdef MOTOROLA
+ fprintf (file, "*%d", scale);
+#else
+ fprintf (file, ":%d", scale);
+#endif
+ }
+ putc (')', file);
+ break;
+ }
+ else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
+ && ! (flag_pic && reg1 == pic_offset_table_rtx))
+ {
+ ASM_OUTPUT_CASE_FETCH (file,
+ CODE_LABEL_NUMBER (XEXP (addr, 0)),
+ reg_names[REGNO (reg1)]);
+ fprintf (file, "l)");
+ break;
+ }
+ /* FALL-THROUGH (is this really what we want? */
+ default:
+ if (GET_CODE (addr) == CONST_INT
+ && INTVAL (addr) < 0x8000
+ && INTVAL (addr) >= -0x8000)
+ {
+#ifdef MOTOROLA
+#ifdef SGS
+ /* Many SGS assemblers croak on size specifiers for constants. */
+ fprintf (file, "%d", INTVAL (addr));
+#else
+ fprintf (file, "%d.w", INTVAL (addr));
+#endif
+#else
+ fprintf (file, "%d:w", INTVAL (addr));
+#endif
+ }
+ else
+ {
+ output_addr_const (file, addr);
+ }
+ break;
+ }
+}
+
+/* Check for cases where a clr insns can be omitted from code using
+ strict_low_part sets. For example, the second clrl here is not needed:
+ clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
+
+ MODE is the mode of this STRICT_LOW_PART set. FIRST_INSN is the clear
+ insn we are checking for redundancy. TARGET is the register set by the
+ clear insn. */
+
+int
+strict_low_part_peephole_ok (mode, first_insn, target)
+ enum machine_mode mode;
+ rtx first_insn;
+ rtx target;
+{
+ rtx p;
+
+ p = prev_nonnote_insn (first_insn);
+
+ while (p)
+ {
+ /* If it isn't an insn, then give up. */
+ if (GET_CODE (p) != INSN)
+ return 0;
+
+ if (reg_set_p (target, p))
+ {
+ rtx set = single_set (p);
+ rtx dest;
+
+ /* If it isn't an easy to recognize insn, then give up. */
+ if (! set)
+ return 0;
+
+ dest = SET_DEST (set);
+
+ /* If this sets the entire target register to zero, then our
+ first_insn is redundant. */
+ if (rtx_equal_p (dest, target)
+ && SET_SRC (set) == const0_rtx)
+ return 1;
+ else if (GET_CODE (dest) == STRICT_LOW_PART
+ && GET_CODE (XEXP (dest, 0)) == REG
+ && REGNO (XEXP (dest, 0)) == REGNO (target)
+ && (GET_MODE_SIZE (GET_MODE (XEXP (dest, 0)))
+ <= GET_MODE_SIZE (mode)))
+ /* This is a strict low part set which modifies less than
+ we are using, so it is safe. */
+ ;
+ else
+ return 0;
+ }
+
+ p = prev_nonnote_insn (p);
+
+ }
+
+ return 0;
+}
+
+/* Accept integer operands in the range 0..0xffffffff. We have to check the
+ range carefully since this predicate is used in DImode contexts. Also, we
+ need some extra crud to make it work when hosted on 64-bit machines. */
+
+int
+const_uint32_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+#if HOST_BITS_PER_WIDE_INT > 32
+ /* All allowed constants will fit a CONST_INT. */
+ return (GET_CODE (op) == CONST_INT
+ && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
+#else
+ return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0)
+ || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
+#endif
+}
+
+/* Accept integer operands in the range -0x80000000..0x7fffffff. We have
+ to check the range carefully since this predicate is used in DImode
+ contexts. */
+
+int
+const_sint32_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ /* All allowed constants will fit a CONST_INT. */
+ return (GET_CODE (op) == CONST_INT
+ && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
+}
+
+char *
+output_andsi3 (operands)
+ rtx *operands;
+{
+ int logval;
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (INTVAL (operands[2]) | 0xffff) == 0xffffffff
+ && (DATA_REG_P (operands[0])
+ || offsettable_memref_p (operands[0]))
+ && !TARGET_5200)
+ {
+ if (GET_CODE (operands[0]) != REG)
+ operands[0] = adj_offsettable_operand (operands[0], 2);
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
+ /* Do not delete a following tstl %0 insn; that would be incorrect. */
+ CC_STATUS_INIT;
+ if (operands[2] == const0_rtx)
+ return "clr%.w %0";
+ return "and%.w %2,%0";
+ }
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (logval = exact_log2 (~ INTVAL (operands[2]))) >= 0
+ && (DATA_REG_P (operands[0])
+ || offsettable_memref_p (operands[0])))
+ {
+ if (DATA_REG_P (operands[0]))
+ {
+ operands[1] = GEN_INT (logval);
+ }
+ else
+ {
+ operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8));
+ operands[1] = GEN_INT (logval % 8);
+ }
+ /* This does not set condition codes in a standard way. */
+ CC_STATUS_INIT;
+ return "bclr %1,%0";
+ }
+ return "and%.l %2,%0";
+}
+
+char *
+output_iorsi3 (operands)
+ rtx *operands;
+{
+ register int logval;
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >> 16 == 0
+ && (DATA_REG_P (operands[0])
+ || offsettable_memref_p (operands[0]))
+ && !TARGET_5200)
+ {
+ if (GET_CODE (operands[0]) != REG)
+ operands[0] = adj_offsettable_operand (operands[0], 2);
+ /* Do not delete a following tstl %0 insn; that would be incorrect. */
+ CC_STATUS_INIT;
+ if (INTVAL (operands[2]) == 0xffff)
+ return "mov%.w %2,%0";
+ return "or%.w %2,%0";
+ }
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
+ && (DATA_REG_P (operands[0])
+ || offsettable_memref_p (operands[0])))
+ {
+ if (DATA_REG_P (operands[0]))
+ {
+ operands[1] = GEN_INT (logval);
+ }
+ else
+ {
+ operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8));
+ operands[1] = GEN_INT (logval % 8);
+ }
+ CC_STATUS_INIT;
+ return "bset %1,%0";
+ }
+ return "or%.l %2,%0";
+}
+
+char *
+output_xorsi3 (operands)
+ rtx *operands;
+{
+ register int logval;
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >> 16 == 0
+ && (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0]))
+ && !TARGET_5200)
+ {
+ if (! DATA_REG_P (operands[0]))
+ operands[0] = adj_offsettable_operand (operands[0], 2);
+ /* Do not delete a following tstl %0 insn; that would be incorrect. */
+ CC_STATUS_INIT;
+ if (INTVAL (operands[2]) == 0xffff)
+ return "not%.w %0";
+ return "eor%.w %2,%0";
+ }
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
+ && (DATA_REG_P (operands[0])
+ || offsettable_memref_p (operands[0])))
+ {
+ if (DATA_REG_P (operands[0]))
+ {
+ operands[1] = GEN_INT (logval);
+ }
+ else
+ {
+ operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8));
+ operands[1] = GEN_INT (logval % 8);
+ }
+ CC_STATUS_INIT;
+ return "bchg %1,%0";
+ }
+ return "eor%.l %2,%0";
+}
diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
new file mode 100755
index 0000000..4531908
--- /dev/null
+++ b/gcc/config/m68k/m68k.h
@@ -0,0 +1,2139 @@
+/* Definitions of target machine for GNU compiler. Sun 68000/68020 version.
+ Copyright (C) 1987, 88, 93-98, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+/* Note that some other tm.h files include this one and then override
+ many of the definitions that relate to assembler syntax. */
+
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+/* See sun3.h, sun2.h, isi.h for different CPP_PREDEFINES. */
+
+/* Print subsidiary information on the compiler version in use. */
+#ifdef MOTOROLA
+#define TARGET_VERSION fprintf (stderr, " (68k, Motorola syntax)");
+#else
+#define TARGET_VERSION fprintf (stderr, " (68k, MIT syntax)");
+#endif
+
+/* Define SUPPORT_SUN_FPA to include support for generating code for
+ the Sun Floating Point Accelerator, an optional product for Sun 3
+ machines. By default, it is not defined. Avoid defining it unless
+ you need to output code for the Sun3+FPA architecture, as it has the
+ effect of slowing down the register set operations in hard-reg-set.h
+ (total number of registers will exceed number of bits in a long,
+ if defined, causing the set operations to expand to loops).
+ SUPPORT_SUN_FPA is typically defined in sun3.h. */
+
+/* Run-time compilation parameters selecting different hardware subsets. */
+
+extern int target_flags;
+
+/* Macros used in the machine description to test the flags. */
+
+/* Compile for a 68020 (not a 68000 or 68010). */
+#define MASK_68020 1
+#define TARGET_68020 (target_flags & MASK_68020)
+
+/* Compile 68881 insns for floating point (not library calls). */
+#define MASK_68881 2
+#define TARGET_68881 (target_flags & MASK_68881)
+
+/* Compile using 68020 bitfield insns. */
+#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 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 MASK_REGPARM 16
+#define TARGET_REGPARM (target_flags & MASK_REGPARM)
+
+/* Compile with 16-bit `int'. */
+#define MASK_SHORT 32
+#define TARGET_SHORT (target_flags & MASK_SHORT)
+
+/* Compile with special insns for Sun FPA. */
+#define MASK_FPA 64
+#define TARGET_FPA (target_flags & MASK_FPA)
+
+/* Compile (actually, link) for Sun SKY board. */
+#define MASK_SKY 128
+#define TARGET_SKY (target_flags & MASK_SKY)
+
+/* 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 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)
+
+/* 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,
+ each pair being { "NAME", VALUE }
+ where VALUE is the bits to set or minus the bits to clear.
+ An empty string NAME is used to identify the default VALUE. */
+
+#define TARGET_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|MASK_68881)}, \
+ { "c68000", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY \
+ |MASK_68020|MASK_BITFIELD|MASK_68881)}, \
+ { "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|MASK_68040_ONLY)}, \
+ { "68020-40", (MASK_BITFIELD|MASK_68881|MASK_68020|MASK_68040)}, \
+ { "68020-60", -(MASK_5200|MASK_68040_ONLY)}, \
+ { "68020-60", (MASK_BITFIELD|MASK_68881|MASK_68020|MASK_68040 \
+ |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_68040_ONLY|MASK_68020 \
+ |MASK_BITFIELD|MASK_68881)}, \
+ { "5200", (MASK_5200)}, \
+ { "68851", 0}, \
+ { "no-68851", 0}, \
+ { "68302", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY \
+ |MASK_68020|MASK_BITFIELD|MASK_68881)}, \
+ { "68332", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY \
+ |MASK_BITFIELD|MASK_68881)}, \
+ { "68332", MASK_68020}, \
+ { "cpu32", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY \
+ |MASK_BITFIELD|MASK_68881)}, \
+ { "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 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; \
+}
+
+/* These are meant to be redefined in the host dependent files */
+#define SUBTARGET_SWITCHES
+#define SUBTARGET_OPTIONS
+#define SUBTARGET_OVERRIDE_OPTIONS
+
+/* 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.
+ We make it true always by avoiding using the single-bit insns
+ except in special cases with constant bit numbers. */
+#define BITS_BIG_ENDIAN 1
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+/* That is true on the 68000. */
+#define BYTES_BIG_ENDIAN 1
+
+/* Define this if most significant word of a multiword number is the lowest
+ numbered. */
+/* For 68000 we can decide arbitrarily
+ since there are no machine instructions for them.
+ So let's be consistent. */
+#define WORDS_BIG_ENDIAN 1
+
+/* number of bits in an addressable storage unit */
+#define BITS_PER_UNIT 8
+
+/* Width in bits of a "word", which is the contents of a machine register.
+ Note that this is not necessarily the width of data type `int';
+ if using 16-bit ints on a 68000, this would still be 32.
+ But on a machine with 16-bit registers, this would be 16. */
+#define BITS_PER_WORD 32
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 4
+
+/* Width in bits of a pointer.
+ See also the macro `Pmode' defined below. */
+#define POINTER_SIZE 32
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY (TARGET_SHORT ? 16 : 32)
+
+/* Boundary (in *bits*) on which stack pointer should be aligned. */
+#define STACK_BOUNDARY 16
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+#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.
+ Most published ABIs say that ints should be aligned on 16 bit
+ boundaries, but cpus with 32 bit busses get better performance
+ aligned on 32 bit boundaries. 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 LOOP_ALIGN(LABEL) (m68k_align_loops)
+
+/* This is how to align an instruction for optimal branching. */
+#define LABEL_ALIGN_AFTER_BARRIER(LABEL) (m68k_align_jumps)
+
+#define SELECT_RTX_SECTION(MODE, X) \
+{ \
+ if (!flag_pic) \
+ readonly_data_section(); \
+ else if (LEGITIMATE_PIC_OPERAND_P (X)) \
+ readonly_data_section(); \
+ else \
+ data_section(); \
+}
+
+/* Define number of bits in most basic integer type.
+ (If undefined, default is BITS_PER_WORD). */
+
+#define INT_TYPE_SIZE (TARGET_SHORT ? 16 : 32)
+
+/* Define these to avoid dependence on meaning of `int'.
+ Note that WCHAR_TYPE_SIZE is used in cexp.y,
+ where TARGET_SHORT is not available. */
+
+#define WCHAR_TYPE "long int"
+#define WCHAR_TYPE_SIZE 32
+
+/* Standard register usage. */
+
+/* Number of actual hardware registers.
+ The hardware registers are assigned numbers for the compiler
+ from 0 to just below FIRST_PSEUDO_REGISTER.
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers.
+ For the 68000, we give the data registers numbers 0-7,
+ the address registers numbers 010-017,
+ and the 68881 floating point registers numbers 020-027. */
+#ifndef SUPPORT_SUN_FPA
+#define FIRST_PSEUDO_REGISTER 24
+#else
+#define FIRST_PSEUDO_REGISTER 56
+#endif
+
+/* This defines the register which is used to hold the offset table for PIC. */
+#define PIC_OFFSET_TABLE_REGNUM 13
+
+/* Used to output a (use pic_offset_table_rtx) so that we
+ always save/restore a5 in functions that use PIC relocation
+ at *any* time during the compilation process. */
+#define FINALIZE_PIC finalize_pic()
+
+#ifndef SUPPORT_SUN_FPA
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+ On the 68000, only the stack pointer is such. */
+
+#define FIXED_REGISTERS \
+ {/* Data registers. */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ \
+ /* Address registers. */ \
+ 0, 0, 0, 0, 0, 0, 0, 1, \
+ \
+ /* Floating point registers \
+ (if available). */ \
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+
+/* 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like. */
+#define CALL_USED_REGISTERS \
+ {1, 1, 0, 0, 0, 0, 0, 0, \
+ 1, 1, 0, 0, 0, 0, 0, 1, \
+ 1, 1, 0, 0, 0, 0, 0, 0 }
+
+#else /* SUPPORT_SUN_FPA */
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+ On the 68000, only the stack pointer is such. */
+
+/* fpa0 is also reserved so that it can be used to move data back and
+ forth between high fpa regs and everything else. */
+
+#define FIXED_REGISTERS \
+ {/* Data registers. */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ \
+ /* Address registers. */ \
+ 0, 0, 0, 0, 0, 0, 0, 1, \
+ \
+ /* Floating point registers \
+ (if available). */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ \
+ /* Sun3 FPA registers. */ \
+ 1, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+
+/* 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like. */
+#define CALL_USED_REGISTERS \
+ {1, 1, 0, 0, 0, 0, 0, 0, \
+ 1, 1, 0, 0, 0, 0, 0, 1, \
+ 1, 1, 0, 0, 0, 0, 0, 0, \
+ /* FPA registers. */ \
+ 1, 1, 1, 1, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+
+#endif /* defined SUPPORT_SUN_FPA */
+
+
+/* Make sure everything's fine if we *don't* have a given processor.
+ This assumes that putting a register in fixed_regs will keep the
+ 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. */
+
+#ifdef SUPPORT_SUN_FPA
+
+#define CONDITIONAL_REGISTER_USAGE \
+{ \
+ int i; \
+ HARD_REG_SET x; \
+ if (!TARGET_FPA) \
+ { \
+ COPY_HARD_REG_SET (x, reg_class_contents[(int)FPA_REGS]); \
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++ ) \
+ if (TEST_HARD_REG_BIT (x, i)) \
+ fixed_regs[i] = call_used_regs[i] = 1; \
+ } \
+ if (TARGET_FPA) \
+ { \
+ COPY_HARD_REG_SET (x, reg_class_contents[(int)FP_REGS]); \
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++ ) \
+ if (TEST_HARD_REG_BIT (x, i)) \
+ fixed_regs[i] = call_used_regs[i] = 1; \
+ } \
+}
+
+#endif /* defined SUPPORT_SUN_FPA */
+
+/* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE.
+ This is ordinarily the length in words of a value of mode MODE
+ but can be less for certain modes in special long registers.
+
+ On the 68000, ordinary registers hold 32 bits worth;
+ for the 68881 registers, a single register is always enough for
+ anything that can be stored in them at all. */
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+ ((REGNO) >= 16 ? GET_MODE_NUNITS (MODE) \
+ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+#ifndef SUPPORT_SUN_FPA
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
+ On the 68000, the cpu registers can hold any mode but the 68881 registers
+ can hold only SFmode or DFmode. The 68881 registers can't hold anything
+ if 68881 use is disabled. */
+
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ (((REGNO) < 16 \
+ && !((REGNO) < 8 && (REGNO) + GET_MODE_SIZE (MODE) / 4 > 8)) \
+ || ((REGNO) >= 16 && (REGNO) < 24 \
+ && TARGET_68881 \
+ && (GET_MODE_CLASS (MODE) == MODE_FLOAT \
+ || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
+ && GET_MODE_UNIT_SIZE (MODE) <= 12))
+
+#else /* defined SUPPORT_SUN_FPA */
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
+ On the 68000, the cpu registers can hold any mode but the 68881 registers
+ can hold only SFmode or DFmode. And the 68881 registers can't hold anything
+ if 68881 use is disabled. However, the Sun FPA register can
+ (apparently) hold whatever you feel like putting in them.
+ If using the fpa, don't put a double in d7/a0. */
+
+/* ??? This is confused. The check to prohibit d7/a0 overlaps should always
+ be enabled regardless of whether TARGET_FPA is specified. It isn't clear
+ what the other d/a register checks are for. Every check using REGNO
+ actually needs to use a range, e.g. 24>=X<56 not <56. There is probably
+ no one using this code anymore. */
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+(((REGNO) < 16 \
+ && !(TARGET_FPA \
+ && GET_MODE_CLASS ((MODE)) != MODE_INT \
+ && GET_MODE_UNIT_SIZE ((MODE)) > 4 \
+ && (REGNO) < 8 && (REGNO) + GET_MODE_SIZE ((MODE)) / 4 > 8 \
+ && (REGNO) % (GET_MODE_UNIT_SIZE ((MODE)) / 4) != 0)) \
+ || ((REGNO) < 24 \
+ ? (TARGET_68881 \
+ && (GET_MODE_CLASS (MODE) == MODE_FLOAT \
+ || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
+ && GET_MODE_UNIT_SIZE (MODE) <= 12) \
+ : ((REGNO) < 56 ? TARGET_FPA && GET_MODE_UNIT_SIZE (MODE) <= 8 : 0)))
+
+#endif /* defined SUPPORT_SUN_FPA */
+
+/* Value is 1 if it is a good idea to tie two pseudo registers
+ when one has mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be 0 for correct output. */
+#define MODES_TIEABLE_P(MODE1, MODE2) \
+ (! TARGET_68881 \
+ || ((GET_MODE_CLASS (MODE1) == MODE_FLOAT \
+ || GET_MODE_CLASS (MODE1) == MODE_COMPLEX_FLOAT) \
+ == (GET_MODE_CLASS (MODE2) == MODE_FLOAT \
+ || GET_MODE_CLASS (MODE2) == MODE_COMPLEX_FLOAT)))
+
+/* Specify the registers used for certain standard purposes.
+ The values of these macros are register numbers. */
+
+/* m68000 pc isn't overloaded on a register. */
+/* #define PC_REGNUM */
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM 15
+
+/* Base register for access to local variables of the function. */
+#define FRAME_POINTER_REGNUM 14
+
+/* Value should be nonzero if functions must have frame pointers.
+ Zero means the frame pointer need not be set up (and parms
+ may be accessed via the stack pointer) in functions that seem suitable.
+ This is computed in `reload', in reload1.c. */
+#define FRAME_POINTER_REQUIRED 0
+
+/* Base register for access to arguments of the function. */
+#define ARG_POINTER_REGNUM 14
+
+/* Register in which static-chain is passed to a function. */
+#define STATIC_CHAIN_REGNUM 8
+
+/* Register in which address to store a structure value
+ is passed to a function. */
+#define STRUCT_VALUE_REGNUM 9
+
+/* Define the classes of registers for register constraints in the
+ machine description. Also define ranges of constants.
+
+ One of the classes must always be named ALL_REGS and include all hard regs.
+ If there is more than one class, another class must be named NO_REGS
+ and contain no registers.
+
+ The name GENERAL_REGS must be the name of a class (or an alias for
+ another name such as ALL_REGS). This is the class of registers
+ that is allowed by "g" or "r" in a register constraint.
+ Also, registers outside this class are allocated only when
+ instructions express preferences for them.
+
+ The classes must be numbered in nondecreasing order; that is,
+ a larger-numbered class must never be contained completely
+ in a smaller-numbered class.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+/* The 68000 has three kinds of registers, so eight classes would be
+ a complete set. One of them is not needed. */
+
+#ifndef SUPPORT_SUN_FPA
+
+enum reg_class {
+ NO_REGS, DATA_REGS,
+ ADDR_REGS, FP_REGS,
+ GENERAL_REGS, DATA_OR_FP_REGS,
+ ADDR_OR_FP_REGS, ALL_REGS,
+ LIM_REG_CLASSES };
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* Give names of register classes as strings for dump file. */
+
+#define REG_CLASS_NAMES \
+ { "NO_REGS", "DATA_REGS", \
+ "ADDR_REGS", "FP_REGS", \
+ "GENERAL_REGS", "DATA_OR_FP_REGS", \
+ "ADDR_OR_FP_REGS", "ALL_REGS" }
+
+/* Define which registers fit in which classes.
+ This is an initializer for a vector of HARD_REG_SET
+ of length N_REG_CLASSES. */
+
+#define REG_CLASS_CONTENTS \
+{ \
+ {0x00000000}, /* NO_REGS */ \
+ {0x000000ff}, /* DATA_REGS */ \
+ {0x0000ff00}, /* ADDR_REGS */ \
+ {0x00ff0000}, /* FP_REGS */ \
+ {0x0000ffff}, /* GENERAL_REGS */ \
+ {0x00ff00ff}, /* DATA_OR_FP_REGS */ \
+ {0x00ffff00}, /* ADDR_OR_FP_REGS */ \
+ {0x00ffffff}, /* ALL_REGS */ \
+}
+
+/* The same information, inverted:
+ Return the class number of the smallest class containing
+ reg number REGNO. This could be a conditional expression
+ or could index an array. */
+
+#define REGNO_REG_CLASS(REGNO) (((REGNO)>>3)+1)
+
+#else /* defined SUPPORT_SUN_FPA */
+
+/*
+ * Notes on final choices:
+ *
+ * 1) Didn't feel any need to union-ize LOW_FPA_REGS with anything
+ * else.
+ * 2) Removed all unions that involve address registers with
+ * floating point registers (left in unions of address and data with
+ * floating point).
+ * 3) Defined GENERAL_REGS as ADDR_OR_DATA_REGS.
+ * 4) Defined ALL_REGS as FPA_OR_FP_OR_GENERAL_REGS.
+ * 4) Left in everything else.
+ */
+enum reg_class { NO_REGS, LO_FPA_REGS, FPA_REGS, FP_REGS,
+ FP_OR_FPA_REGS, DATA_REGS, DATA_OR_FPA_REGS, DATA_OR_FP_REGS,
+ DATA_OR_FP_OR_FPA_REGS, ADDR_REGS, GENERAL_REGS,
+ GENERAL_OR_FPA_REGS, GENERAL_OR_FP_REGS, ALL_REGS,
+ LIM_REG_CLASSES };
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* Give names of register classes as strings for dump file. */
+
+#define REG_CLASS_NAMES \
+ { "NO_REGS", "LO_FPA_REGS", "FPA_REGS", "FP_REGS", \
+ "FP_OR_FPA_REGS", "DATA_REGS", "DATA_OR_FPA_REGS", "DATA_OR_FP_REGS", \
+ "DATA_OR_FP_OR_FPA_REGS", "ADDR_REGS", "GENERAL_REGS", \
+ "GENERAL_OR_FPA_REGS", "GENERAL_OR_FP_REGS", "ALL_REGS" }
+
+/* Define which registers fit in which classes.
+ This is an initializer for a vector of HARD_REG_SET
+ of length N_REG_CLASSES. */
+
+#define REG_CLASS_CONTENTS \
+{ \
+ {0, 0}, /* NO_REGS */ \
+ {0xff000000, 0x000000ff}, /* LO_FPA_REGS */ \
+ {0xff000000, 0x00ffffff}, /* FPA_REGS */ \
+ {0x00ff0000, 0x00000000}, /* FP_REGS */ \
+ {0xffff0000, 0x00ffffff}, /* FP_OR_FPA_REGS */ \
+ {0x000000ff, 0x00000000}, /* DATA_REGS */ \
+ {0xff0000ff, 0x00ffffff}, /* DATA_OR_FPA_REGS */ \
+ {0x00ff00ff, 0x00000000}, /* DATA_OR_FP_REGS */ \
+ {0xffff00ff, 0x00ffffff}, /* DATA_OR_FP_OR_FPA_REGS */\
+ {0x0000ff00, 0x00000000}, /* ADDR_REGS */ \
+ {0x0000ffff, 0x00000000}, /* GENERAL_REGS */ \
+ {0xff00ffff, 0x00ffffff}, /* GENERAL_OR_FPA_REGS */\
+ {0x00ffffff, 0x00000000}, /* GENERAL_OR_FP_REGS */\
+ {0xffffffff, 0x00ffffff}, /* ALL_REGS */ \
+}
+
+/* The same information, inverted:
+ Return the class number of the smallest class containing
+ reg number REGNO. This could be a conditional expression
+ or could index an array. */
+
+extern enum reg_class regno_reg_class[];
+#define REGNO_REG_CLASS(REGNO) (regno_reg_class[(REGNO)>>3])
+
+#endif /* SUPPORT_SUN_FPA */
+
+/* The class value for index registers, and the one for base regs. */
+
+#define INDEX_REG_CLASS GENERAL_REGS
+#define BASE_REG_CLASS ADDR_REGS
+
+/* Get reg_class from a letter such as appears in the machine description.
+ We do a trick here to modify the effective constraints on the
+ machine description; we zorch the constraint letters that aren't
+ appropriate for a specific target. This allows us to guarantee
+ that a specific kind of register will not be used for a given target
+ without fiddling with the register classes above. */
+
+#ifndef SUPPORT_SUN_FPA
+
+#define REG_CLASS_FROM_LETTER(C) \
+ ((C) == 'a' ? ADDR_REGS : \
+ ((C) == 'd' ? DATA_REGS : \
+ ((C) == 'f' ? (TARGET_68881 ? FP_REGS : \
+ NO_REGS) : \
+ NO_REGS)))
+
+#else /* defined SUPPORT_SUN_FPA */
+
+#define REG_CLASS_FROM_LETTER(C) \
+ ((C) == 'a' ? ADDR_REGS : \
+ ((C) == 'd' ? DATA_REGS : \
+ ((C) == 'f' ? (TARGET_68881 ? FP_REGS : \
+ NO_REGS) : \
+ ((C) == 'x' ? (TARGET_FPA ? FPA_REGS : \
+ NO_REGS) : \
+ ((C) == 'y' ? (TARGET_FPA ? LO_FPA_REGS : \
+ NO_REGS) : \
+ NO_REGS)))))
+
+#endif /* defined SUPPORT_SUN_FPA */
+
+/* The letters I, J, K, L and M in a register constraint string
+ can be used to stand for particular ranges of immediate operands.
+ This macro defines what the ranges are.
+ C is the letter, and VALUE is a constant value.
+ Return 1 if VALUE is in the range specified by C.
+
+ For the 68000, `I' is used for the range 1 to 8
+ 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.
+ `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:
+ * "G" defines all of the floating constants that are *NOT* 68881
+ * constants. this is so 68881 constants get reloaded and the
+ * fpmovecr is used. "H" defines *only* the class of constants that
+ * the fpa can use, because these can be gotten at in any fpa
+ * instruction and there is no need to force reloads.
+ */
+#ifndef SUPPORT_SUN_FPA
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'G' ? ! (TARGET_68881 && standard_68881_constant_p (VALUE)) : 0 )
+#else /* defined SUPPORT_SUN_FPA */
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'G' ? ! (TARGET_68881 && standard_68881_constant_p (VALUE)) : \
+ (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
+ in some cases it is preferable to use a more restrictive 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.
+ 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 \
+ && (unsigned) (INTVAL (X) + 0x80) < 0x100 \
+ && (CLASS) != ADDR_REGS) \
+ ? DATA_REGS \
+ : (GET_MODE (X) == QImode && (CLASS) != ADDR_REGS) \
+ ? DATA_REGS \
+ : (GET_CODE (X) == CONST_DOUBLE \
+ && GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \
+ ? (! CONST_DOUBLE_OK_FOR_LETTER_P (X, 'G') \
+ && (CLASS == FP_REGS || CLASS == DATA_OR_FP_REGS) \
+ ? FP_REGS : NO_REGS) \
+ : (CLASS))
+
+/* Force QImode output reloads from subregs to be allocated to data regs,
+ since QImode stores from address regs are not supported. We make the
+ assumption that if the class is not ADDR_REGS, then it must be a superset
+ of DATA_REGS. */
+
+#define LIMIT_RELOAD_CLASS(MODE, CLASS) \
+ (((MODE) == QImode && (CLASS) != ADDR_REGS) \
+ ? DATA_REGS \
+ : (CLASS))
+
+/* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS. */
+/* On the 68000, this is the size of MODE in words,
+ except in the FP regs, where a single reg is always enough. */
+#ifndef SUPPORT_SUN_FPA
+
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((CLASS) == FP_REGS ? 1 \
+ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+/* Moves between fp regs and other regs are two insns. */
+#define REGISTER_MOVE_COST(CLASS1, CLASS2) \
+ (((CLASS1) == FP_REGS && (CLASS2) != FP_REGS) \
+ || ((CLASS2) == FP_REGS && (CLASS1) != FP_REGS) \
+ ? 4 : 2)
+
+#else /* defined SUPPORT_SUN_FPA */
+
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((CLASS) == FP_REGS || (CLASS) == FPA_REGS || (CLASS) == LO_FPA_REGS ? 1 \
+ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+/* Moves between fp regs and other regs are two insns. */
+/* Likewise for high fpa regs and other regs. */
+#define REGISTER_MOVE_COST(CLASS1, CLASS2) \
+ ((((CLASS1) == FP_REGS && (CLASS2) != FP_REGS) \
+ || ((CLASS2) == FP_REGS && (CLASS1) != FP_REGS) \
+ || ((CLASS1) == FPA_REGS && (CLASS2) != FPA_REGS) \
+ || ((CLASS2) == FPA_REGS && (CLASS1) != FPA_REGS)) \
+ ? 4 : 2)
+
+#endif /* define SUPPORT_SUN_FPA */
+
+/* Stack layout; function entry, exit and calling. */
+
+/* Define this if pushing a word on the stack
+ makes the stack pointer a smaller address. */
+#define STACK_GROWS_DOWNWARD
+
+/* Nonzero if we need to generate stack-probe insns.
+ On most systems they are not needed.
+ When they are needed, define this as the stack offset to probe at. */
+#define NEED_PROBE 0
+
+/* Define this if the nominal address of the stack frame
+ is at the high-address end of the local variables;
+ that is, each additional local variable allocated
+ goes at a more negative offset in the frame. */
+#define FRAME_GROWS_DOWNWARD
+
+/* Offset within stack frame to start allocating local variables at.
+ If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
+ first local allocated. Otherwise, it is the offset to the BEGINNING
+ of the first local allocated. */
+#define STARTING_FRAME_OFFSET 0
+
+/* 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.
+ 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
+
+/* Offset of the CFA from the argument pointer register value. */
+#define ARG_POINTER_CFA_OFFSET 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.
+
+ On the 68000, the RTS insn cannot pop anything.
+ On the 68010, the RTD insn may be used to pop them if the number
+ of args is fixed, but if the number is variable then the caller
+ must pop them all. RTD can't be used for library calls now
+ because the library is compiled with the Unix compiler.
+ Use of RTD is a selectable option, since it is incompatible with
+ standard Unix calling sequences. If the option is not selected,
+ the caller must always pop the args. */
+
+#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))) \
+ ? (SIZE) : 0)
+
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+/* On the 68000 the return value is in D0 regardless. */
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ gen_rtx_REG (TYPE_MODE (VALTYPE), 0)
+
+/* Define how to find the value returned by a library function
+ assuming the value has mode MODE. */
+
+/* On the 68000 the return value is in D0 regardless. */
+
+#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, 0)
+
+/* 1 if N is a possible register number for a function value.
+ On the 68000, d0 is the only register thus used. */
+
+#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. */
+
+#define PCC_STATIC_STRUCT_RETURN
+
+/* 1 if N is a possible register number for function argument passing.
+ On the 68000, no registers are used in this way. */
+
+#define FUNCTION_ARG_REGNO_P(N) 0
+
+/* Define a data type for recording info about an argument list
+ during the scan of that argument list. This data type should
+ hold all necessary information about the function itself
+ and about the args processed so far, enough to enable macros
+ such as FUNCTION_ARG to determine where the next arg should go.
+
+ On the m68k, this is a single integer, which is a number of bytes
+ of arguments scanned so far. */
+
+#define CUMULATIVE_ARGS int
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+ For a library call, FNTYPE is 0.
+
+ On the m68k, the offset starts at 0. */
+
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
+ ((CUM) = 0)
+
+/* Update the data in CUM to advance over an argument
+ of mode MODE and data type TYPE.
+ (TYPE is null for libcalls where that information may not be available.) */
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ ((CUM) += ((MODE) != BLKmode \
+ ? (GET_MODE_SIZE (MODE) + 3) & ~3 \
+ : (int_size_in_bytes (TYPE) + 3) & ~3))
+
+/* Define where to put the arguments to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+
+/* On the 68000 all args are pushed, except if -mregparm is specified
+ then the first two words of arguments are passed in d0, d1.
+ *NOTE* -mregparm does not work.
+ It exists only to test register calling conventions. */
+
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+((TARGET_REGPARM && (CUM) < 8) ? gen_rtx_REG ((MODE), (CUM) / 4) : 0)
+
+/* For an arg passed partly in registers and partly in memory,
+ this is the number of registers used.
+ For args passed entirely in registers or entirely in memory, zero. */
+
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
+((TARGET_REGPARM && (CUM) < 8 \
+ && 8 < ((CUM) + ((MODE) == BLKmode \
+ ? int_size_in_bytes (TYPE) \
+ : GET_MODE_SIZE (MODE)))) \
+ ? 2 - (CUM) / 4 : 0)
+
+/* Generate the assembly code for function entry. */
+#define FUNCTION_PROLOGUE(FILE, SIZE) output_function_prologue(FILE, SIZE)
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ asm_fprintf (FILE, "\tlea %LLP%d,%Ra0\n\tjsr mcount\n", (LABELNO))
+
+/* 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, 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) \
+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(__mcpu32__) || defined(mcpu32)
+#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)
+#ifdef __HPUX_ASM__
+/* HPUX assembler does not accept %ccr. */
+#define MACHINE_STATE_SAVE(id) \
+ { \
+ asm ("move.w %cc,-(%sp)"); \
+ asm ("movm.l &0xc0c0,-(%sp)"); \
+ }
+#else /* ! __HPUX_ASM__ */
+#define MACHINE_STATE_SAVE(id) \
+ { \
+ asm ("move.w %ccr,-(%sp)"); \
+ asm ("movm.l &0xc0c0,-(%sp)"); \
+ }
+#endif /* __HPUX_ASM__ */
+#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__ */
+#ifdef __HPUX_ASM__
+/* HPUX assembler does not accept %ccr. */
+#define MACHINE_STATE_RESTORE(id) \
+ { \
+ asm ("movm.l (%sp)+,&0x0303"); \
+ asm ("move.w (%sp)+,%cc"); \
+ }
+#else /* ! __HPUX_ASM__ */
+#define MACHINE_STATE_RESTORE(id) \
+ { \
+ asm ("movm.l (%sp)+,&0x0303"); \
+ asm ("move.w (%sp)+,%ccr"); \
+ }
+#endif /* __HPUX_ASM__ */
+#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
+ functions that have frame pointers.
+ No definition is equivalent to always zero. */
+
+#define EXIT_IGNORE_STACK 1
+
+/* Generate the assembly code for function exit. */
+#define FUNCTION_EPILOGUE(FILE, SIZE) output_function_epilogue (FILE, SIZE)
+
+/* This is a hook for other tm files to change. */
+/* #define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE) */
+
+/* Determine if the epilogue should be output as RTL.
+ You should override this if you define FUNCTION_EXTRA_EPILOGUE. */
+#define USE_RETURN_INSN use_return_insn ()
+
+/* Store in the variable DEPTH the initial difference between the
+ frame pointer reg contents and the stack pointer reg contents,
+ as of the start of the function body. This depends on the layout
+ of the fixed parts of the stack frame and on how registers are saved.
+
+ On the 68k, if we have a frame, we must add one word to its length
+ to allow for the place that a6 is stored when we do have a frame pointer.
+ Otherwise, we would need to compute the offset from the frame pointer
+ of a local variable as a function of frame_pointer_needed, which
+ is hard. */
+
+#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \
+{ int regno; \
+ int offset = -4; \
+ for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ offset += 12; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ offset += 4; \
+ (DEPTH) = (offset + ((get_frame_size () + 3) & -4) \
+ + (get_frame_size () == 0 ? 0 : 4)); \
+}
+
+/* Output assembler code for a block containing the constant parts
+ of a trampoline, leaving space for the variable parts. */
+
+/* On the 68k, the trampoline looks like this:
+ 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 12
+
+/* Alignment required for a trampoline in bits. */
+
+#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.
+ CXT is an RTX for the static chain value for the function.
+
+ We generate a two-instructions program at address TRAMP :
+ movea.l &CXT,%a0
+ jmp FNADDR */
+
+#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
+{ \
+ 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.
+ 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. */
+/* The function name __transfer_from_trampoline is not actually used.
+ The function definition just permits use of "asm with operands"
+ (though the operand list is empty). */
+#define TRANSFER_FROM_TRAMPOLINE \
+void \
+__transfer_from_trampoline () \
+{ \
+ register char *a0 asm ("%a0"); \
+ 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])); \
+ asm ("rts":); \
+}
+
+/* Addressing modes, and classification of registers for them. */
+
+#define HAVE_POST_INCREMENT 1
+/* #define HAVE_POST_DECREMENT 0 */
+
+#define HAVE_PRE_DECREMENT 1
+/* #define HAVE_PRE_INCREMENT 0 */
+
+/* Macros to check register numbers against specific register classes. */
+
+/* These assume that REGNO is a hard or pseudo reg number.
+ They give nonzero only if REGNO is a hard reg of the suitable class
+ or a pseudo reg currently allocated to a suitable hard reg.
+ Since they use reg_renumber, they are safe only once reg_renumber
+ has been allocated, which happens in local-alloc.c. */
+
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
+((REGNO) < 16 || (unsigned) reg_renumber[REGNO] < 16)
+#define REGNO_OK_FOR_BASE_P(REGNO) \
+(((REGNO) ^ 010) < 8 || (unsigned) (reg_renumber[REGNO] ^ 010) < 8)
+#define REGNO_OK_FOR_DATA_P(REGNO) \
+((REGNO) < 8 || (unsigned) reg_renumber[REGNO] < 8)
+#define REGNO_OK_FOR_FP_P(REGNO) \
+(((REGNO) ^ 020) < 8 || (unsigned) (reg_renumber[REGNO] ^ 020) < 8)
+#ifdef SUPPORT_SUN_FPA
+#define REGNO_OK_FOR_FPA_P(REGNO) \
+(((REGNO) >= 24 && (REGNO) < 56) || (reg_renumber[REGNO] >= 24 && reg_renumber[REGNO] < 56))
+#endif
+
+/* Now macros that check whether X is a register and also,
+ strictly, whether it is in a specified class.
+
+ These macros are specific to the 68000, and may be used only
+ in code for printing assembler insns and in conditions for
+ define_optimization. */
+
+/* 1 if X is a data register. */
+
+#define DATA_REG_P(X) (REG_P (X) && REGNO_OK_FOR_DATA_P (REGNO (X)))
+
+/* 1 if X is an fp register. */
+
+#define FP_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FP_P (REGNO (X)))
+
+/* 1 if X is an address register */
+
+#define ADDRESS_REG_P(X) (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X)))
+
+#ifdef SUPPORT_SUN_FPA
+/* 1 if X is a register in the Sun FPA. */
+#define FPA_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FPA_P (REGNO (X)))
+#else
+/* Answer must be no if we don't have an FPA. */
+#define FPA_REG_P(X) 0
+#endif
+
+/* Maximum number of registers that can appear in a valid memory address. */
+
+#define MAX_REGS_PER_ADDRESS 2
+
+/* Recognize any constant value that is a valid address. */
+
+#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. */
+
+#define LEGITIMATE_CONSTANT_P(X) 1
+
+/* Nonzero if the constant value X is a legitimate general operand
+ when generating PIC code. It is given that flag_pic is on and
+ that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
+
+#define LEGITIMATE_PIC_OPERAND_P(X) \
+ ((! 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.
+ We have two alternate definitions for each of them.
+ The usual definition accepts all pseudo regs; the other rejects
+ them unless they have been allocated suitable hard regs.
+ The symbol REG_OK_STRICT causes the latter definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that
+ they will get allocated to the class that the insn wants them to be in.
+ Source files for reload pass need to be strict.
+ After reload, it makes no difference, since pseudo regs have
+ been eliminated by then. */
+
+#ifndef REG_OK_STRICT
+
+/* Nonzero if X is a hard reg that can be used as an index
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_INDEX_P(X) ((REGNO (X) ^ 020) >= 8)
+/* Nonzero if X is a hard reg that can be used as a base reg
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_BASE_P(X) ((REGNO (X) & ~027) != 0)
+
+#else
+
+/* Nonzero if X is a hard reg that can be used as an index. */
+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+/* Nonzero if X is a hard reg that can be used as a base reg. */
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+
+#endif
+
+/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
+ that is a valid memory address for an instruction.
+ The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+
+ When generating PIC, an address involving a SYMBOL_REF is legitimate
+ if and only if it is the sum of pic_offset_table_rtx and the SYMBOL_REF.
+ We use LEGITIMATE_PIC_OPERAND_P to throw out the illegitimate addresses,
+ and we explicitly check for the sum of pic_offset_table_rtx and a SYMBOL_REF.
+
+ Likewise for a LABEL_REF when generating PIC.
+
+ 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))) \
+ || LEGITIMATE_BASE_REG_P (X) \
+ || ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \
+ && LEGITIMATE_BASE_REG_P (XEXP (X, 0))) \
+ || (GET_CODE (X) == PLUS \
+ && LEGITIMATE_BASE_REG_P (XEXP (X, 0)) \
+ && GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && (TARGET_68020 \
+ || ((unsigned) INTVAL (XEXP (X, 1)) + 0x8000) < 0x10000)) \
+ || (GET_CODE (X) == PLUS && XEXP (X, 0) == pic_offset_table_rtx \
+ && flag_pic && GET_CODE (XEXP (X, 1)) == SYMBOL_REF) \
+ || (GET_CODE (X) == PLUS && XEXP (X, 0) == pic_offset_table_rtx \
+ && flag_pic && GET_CODE (XEXP (X, 1)) == LABEL_REF)) \
+
+#define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \
+{ if (INDIRECTABLE_1_ADDRESS_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))) \
+ { GO_IF_INDEXABLE_BASE (XEXP (X, 1), ADDR); } \
+ if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 1))) \
+ { GO_IF_INDEXABLE_BASE (XEXP (X, 0), ADDR); } }
+
+#define GO_IF_INDEXED_ADDRESS(X, ADDR) \
+{ GO_IF_INDEXING (X, ADDR); \
+ if (GET_CODE (X) == PLUS) \
+ { if (GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && (TARGET_68020 || (unsigned) INTVAL (XEXP (X, 1)) + 0x80 < 0x100)) \
+ { rtx go_temp = XEXP (X, 0); GO_IF_INDEXING (go_temp, ADDR); } \
+ if (GET_CODE (XEXP (X, 0)) == CONST_INT \
+ && (TARGET_68020 || (unsigned) INTVAL (XEXP (X, 0)) + 0x80 < 0x100)) \
+ { rtx go_temp = XEXP (X, 1); GO_IF_INDEXING (go_temp, ADDR); } } }
+
+/* coldfire/5200 does not allow HImode index registers. */
+#define LEGITIMATE_INDEX_REG_P(X) \
+ ((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X)) \
+ || (! TARGET_5200 \
+ && 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))) \
+ || (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 || 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 && !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
+
+/* Try machine-dependent ways of modifying an illegitimate address
+ to be legitimate. If we find one, return the new, valid address.
+ This macro is used in only one place: `memory_address' in explow.c.
+
+ OLDX is the address as it was before break_out_memory_refs was called.
+ In some cases it is useful to look at this to decide what needs to be done.
+
+ MODE and WIN are passed so that this macro can use
+ GO_IF_LEGITIMATE_ADDRESS.
+
+ It is always safe for this macro to do nothing. It exists to recognize
+ opportunities to optimize the output.
+
+ For the 68000, we handle X+REG by loading X into a register R and
+ using R+REG. R will go in an address reg and indexing will be used.
+ However, if REG is a broken-out memory address or multiplication,
+ nothing needs to be done because REG can certainly go in an address reg. */
+
+#define COPY_ONCE(Y) if (!copied) { Y = copy_rtx (Y); copied = ch = 1; }
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
+{ register int ch = (X) != (OLDX); \
+ if (GET_CODE (X) == PLUS) \
+ { int copied = 0; \
+ if (GET_CODE (XEXP (X, 0)) == MULT) \
+ { COPY_ONCE (X); XEXP (X, 0) = force_operand (XEXP (X, 0), 0);} \
+ if (GET_CODE (XEXP (X, 1)) == MULT) \
+ { COPY_ONCE (X); XEXP (X, 1) = force_operand (XEXP (X, 1), 0);} \
+ if (ch && GET_CODE (XEXP (X, 1)) == REG \
+ && GET_CODE (XEXP (X, 0)) == REG) \
+ goto WIN; \
+ if (ch) { GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); } \
+ if (GET_CODE (XEXP (X, 0)) == REG \
+ || (GET_CODE (XEXP (X, 0)) == SIGN_EXTEND \
+ && GET_CODE (XEXP (XEXP (X, 0), 0)) == REG \
+ && GET_MODE (XEXP (XEXP (X, 0), 0)) == HImode)) \
+ { register rtx temp = gen_reg_rtx (Pmode); \
+ register rtx val = force_operand (XEXP (X, 1), 0); \
+ emit_move_insn (temp, val); \
+ COPY_ONCE (X); \
+ XEXP (X, 1) = temp; \
+ goto WIN; } \
+ else if (GET_CODE (XEXP (X, 1)) == REG \
+ || (GET_CODE (XEXP (X, 1)) == SIGN_EXTEND \
+ && GET_CODE (XEXP (XEXP (X, 1), 0)) == REG \
+ && GET_MODE (XEXP (XEXP (X, 1), 0)) == HImode)) \
+ { register rtx temp = gen_reg_rtx (Pmode); \
+ register rtx val = force_operand (XEXP (X, 0), 0); \
+ emit_move_insn (temp, val); \
+ COPY_ONCE (X); \
+ XEXP (X, 0) = temp; \
+ goto WIN; }}}
+
+/* Go to LABEL if ADDR (a legitimate address expression)
+ has an effect that depends on the machine mode it is used for.
+ On the 68000, only predecrement and postincrement address depend thus
+ (the amount of decrement or increment being the length of the operand). */
+
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \
+ if (GET_CODE (ADDR) == POST_INC || GET_CODE (ADDR) == PRE_DEC) goto LABEL
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction. */
+#define CASE_VECTOR_MODE HImode
+
+/* Define as C expression which evaluates to nonzero if the tablejump
+ instruction expects the table to contain offsets from the address of the
+ table.
+ Do not define this if the table should contain absolute addresses. */
+#define CASE_VECTOR_PC_RELATIVE 1
+
+/* Specify the tree operation to be used to convert reals to integers. */
+#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
+
+/* This is the kind of divide that is easiest to do in the general case. */
+#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+#define DEFAULT_SIGNED_CHAR 1
+
+/* Don't cse the address of the function being compiled. */
+#define NO_RECURSIVE_FUNCTION_CSE
+
+/* Max number of bytes we can move from memory to memory
+ in one reasonably fast instruction. */
+#define MOVE_MAX 4
+
+/* Define this if zero-extension is slow (more than one real instruction). */
+#define SLOW_ZERO_EXTEND
+
+/* Nonzero if access to memory by bytes is slow and undesirable. */
+#define SLOW_BYTE_ACCESS 0
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* We assume that the store-condition-codes instructions store 0 for false
+ and some other value for true. This is the value stored for true. */
+
+#define STORE_FLAG_VALUE -1
+
+/* When a prototype says `char' or `short', really pass an `int'. */
+#define PROMOTE_PROTOTYPES
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+#define Pmode SImode
+
+/* A function address in a call instruction
+ is a byte address (for indexing purposes)
+ so give the MEM rtx a byte's mode. */
+#define FUNCTION_MODE QImode
+
+/* Compute the cost of computing a constant rtl expression RTX
+ whose rtx-code is CODE. The body of this macro is a portion
+ of a switch statement. If the code is computed here,
+ return it with a return statement. Otherwise, break from the switch. */
+
+#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
+ case CONST_INT: \
+ /* Constant zero is super cheap due to clr instruction. */ \
+ if (RTX == const0_rtx) return 0; \
+ /* if ((OUTER_CODE) == SET) */ \
+ return const_int_cost(RTX); \
+ case CONST: \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ return 3; \
+ case CONST_DOUBLE: \
+ return 5;
+
+/* Compute the cost of various arithmetic operations.
+ These are vaguely right for a 68020. */
+/* The costs for long multiply have been adjusted to
+ 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. */
+/* 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, 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 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 (2); /* clrw;swap */ \
+ if (GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && !(INTVAL (XEXP (X, 1)) > 0 \
+ && INTVAL (XEXP (X, 1)) <= 8)) \
+ return COSTS_N_INSNS (3); /* lsr #i,dn */ \
+ break; \
+ case MULT: \
+ 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); \
+ case DIV: \
+ case UDIV: \
+ case MOD: \
+ case UMOD: \
+ if (GET_MODE (X) == QImode || GET_MODE (X) == HImode) \
+ return COSTS_N_INSNS (DIVW_COST); /* div.w */ \
+ return COSTS_N_INSNS (43); /* div.l */
+
+/* Tell final.c how to eliminate redundant test instructions. */
+
+/* Here we define machine-dependent flags and fields in cc_status
+ (see `conditions.h'). */
+
+/* Set if the cc value is actually in the 68881, so a floating point
+ conditional branch must be output. */
+#define CC_IN_68881 04000
+
+/* Store in cc_status the expressions that the condition codes will
+ describe after execution of an instruction whose pattern is EXP.
+ Do not alter them if the instruction would not alter the cc's. */
+
+/* On the 68000, all the insns to store in an address register fail to
+ set the cc's. However, in some cases these instructions can make it
+ possibly invalid to use the saved cc's. In those cases we clear out
+ some or all of the saved cc's so they won't be used. */
+
+#define NOTICE_UPDATE_CC(EXP,INSN) notice_update_cc (EXP, INSN)
+
+#define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \
+{ if (cc_prev_status.flags & CC_IN_68881) \
+ return FLOAT; \
+ if (cc_prev_status.flags & CC_NO_OVERFLOW) \
+ return NO_OV; \
+ return NORMAL; }
+
+/* Control the assembler format that we output. */
+
+/* Output at beginning of assembler file. */
+
+#define ASM_FILE_START(FILE) \
+ fprintf (FILE, "#NO_APP\n");
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#define ASM_APP_ON "#APP\n"
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#define ASM_APP_OFF "#NO_APP\n"
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP ".text"
+
+/* Output before writable data. */
+
+#define DATA_SECTION_ASM_OP ".data"
+
+/* Here are four prefixes that are used by asm_fprintf to
+ facilitate customization for alternate assembler syntaxes.
+ Machines with no likelihood of an alternate syntax need not
+ define these and need not use asm_fprintf. */
+
+/* The prefix for register names. Note that REGISTER_NAMES
+ is supposed to include this prefix. */
+
+#define REGISTER_PREFIX ""
+
+/* The prefix for local labels. You should be able to define this as
+ an empty string, or any arbitrary string (such as ".", ".L%", etc)
+ without having to make any other changes to account for the specific
+ definition. Note it is a string literal, not interpreted by printf
+ and friends. */
+
+#define LOCAL_LABEL_PREFIX ""
+
+/* The prefix to add to user-visible assembler symbols. */
+
+#define USER_LABEL_PREFIX "_"
+
+/* The prefix for immediate operands. */
+
+#define IMMEDIATE_PREFIX "#"
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number (see above). */
+
+#ifndef SUPPORT_SUN_FPA
+
+#define REGISTER_NAMES \
+{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
+ "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp", \
+ "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7" }
+
+#else /* SUPPORTED_SUN_FPA */
+
+#define REGISTER_NAMES \
+{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
+ "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp", \
+ "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \
+ "fpa0", "fpa1", "fpa2", "fpa3", "fpa4", "fpa5", "fpa6", "fpa7", \
+ "fpa8", "fpa9", "fpa10", "fpa11", "fpa12", "fpa13", "fpa14", "fpa15", \
+ "fpa16", "fpa17", "fpa18", "fpa19", "fpa20", "fpa21", "fpa22", "fpa23", \
+ "fpa24", "fpa25", "fpa26", "fpa27", "fpa28", "fpa29", "fpa30", "fpa31" }
+
+#endif /* defined SUPPORT_SUN_FPA */
+
+/* How to renumber registers for dbx and gdb.
+ On the Sun-3, the floating point registers have numbers
+ 18 to 25, not 16 to 23 as they do in the compiler. */
+
+#define DBX_REGISTER_NUMBER(REGNO) ((REGNO) < 16 ? (REGNO) : (REGNO) + 2)
+
+/* Before the prologue, RA is at 0(%sp). */
+#define INCOMING_RETURN_ADDR_RTX \
+ gen_rtx_MEM (VOIDmode, gen_rtx_REG (VOIDmode, STACK_POINTER_REGNUM))
+
+/* We must not use the DBX register numbers for the DWARF 2 CFA column
+ numbers because that maps to numbers beyond FIRST_PSEUDO_REGISTER.
+ Instead use the identity mapping. */
+#define DWARF_FRAME_REGNUM(REG) REG
+
+/* Before the prologue, the top of the frame is at 4(%sp). */
+#define INCOMING_FRAME_SP_OFFSET 4
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME. */
+
+#define ASM_OUTPUT_LABEL(FILE,NAME) \
+ do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define GLOBAL_ASM_OP ".globl"
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ do { fprintf (FILE, "%s ", GLOBAL_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ fputs ("\n", FILE);} while (0)
+
+/* This is how to output a reference to a user-level label named NAME.
+ `assemble_name' uses this. */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ asm_fprintf (FILE, "%0U%s", NAME)
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ asm_fprintf (FILE, "%0L%s%d:\n", PREFIX, NUM)
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#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); \
+ 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) \
+ 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. */
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+do { long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
+ fprintf (FILE, "\t.long 0x%lx\n", l); \
+ } while (0)
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\t.long "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\t.word "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\t.byte "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\t.byte 0x%x\n", (VALUE))
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ asm_fprintf (FILE, "\tmovel %s,%Rsp@-\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ asm_fprintf (FILE, "\tmovel %Rsp@+,%s\n", reg_names[REGNO])
+
+/* This is how to output an element of a case-vector that is absolute.
+ (The 68000 does not use such vectors,
+ but we must define this macro anyway.) */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ asm_fprintf (FILE, "\t.long %LL%d\n", VALUE)
+
+/* This is how to output an element of a case-vector that is relative. */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
+ asm_fprintf (FILE, "\t.word %LL%d-%LL%d\n", VALUE, REL)
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+/* We don't have a way to align to more than a two-byte boundary, so do the
+ best we can and don't complain. */
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) >= 1) \
+ fprintf (FILE, "\t.even\n");
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t.skip %u\n", (SIZE))
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".lcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+/* Define the parentheses used to group arithmetic operations
+ in assembler code. */
+
+#define ASM_OPEN_PAREN "("
+#define ASM_CLOSE_PAREN ")"
+
+/* Define results of standard character escape sequences. */
+#define TARGET_BELL 007
+#define TARGET_BS 010
+#define TARGET_TAB 011
+#define TARGET_NEWLINE 012
+#define TARGET_VT 013
+#define TARGET_FF 014
+#define TARGET_CR 015
+
+/* 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(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); \
+ 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) \
+ 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.
+ For `%' followed by punctuation, CODE is the punctuation and X is null.
+
+ On the 68000, we use several CODE characters:
+ '.' for dot needed in Motorola-style opcode names.
+ '-' for an operand pushing on the stack:
+ sp@-, -(sp) or -(%sp) depending on the style of syntax.
+ '+' for an operand pushing on the stack:
+ sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
+ '@' for a reference to the top word on the stack:
+ sp@, (sp) or (%sp) depending on the style of syntax.
+ '#' for an immediate operand prefix (# in MIT and Motorola syntax
+ but & in SGS syntax).
+ '!' 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.
+ 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
+ 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
+ than directly). Second part of 'y' below.
+ 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
+ or print pair of registers as rx:ry.
+ 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
+ CONST_DOUBLE's as SunFPA constant RAM registers if
+ possible, so it should not be used except for the SunFPA. */
+
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
+ ((CODE) == '.' || (CODE) == '#' || (CODE) == '-' \
+ || (CODE) == '+' || (CODE) == '@' || (CODE) == '!' \
+ || (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
+ expression.
+
+ CODE is a value that can be used to specify one of several ways
+ of printing the operand. It is used when identical operands
+ must be printed differently depending on the context. CODE
+ comes from the `%' specification that was used to request
+ printing of the operand. If the specification was just `%DIGIT'
+ then CODE is 0; if the specification was `%LTR DIGIT' then CODE
+ is the ASCII code for LTR.
+
+ If X is a register, this macro should print the register's name.
+ The names can be found in an array `reg_names' whose type is
+ `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
+
+ When the machine description has a specification `%PUNCT' (a `%'
+ followed by a punctuation character), this macro is called with
+ a null pointer for X and the punctuation character for CODE.
+
+ See m68k.c for the m68k specific codes. */
+
+#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE)
+
+/* A C compound statement to output to stdio stream STREAM the
+ assembler syntax for an instruction operand that is a memory
+ reference whose address is ADDR. ADDR is an RTL expression.
+
+ On some machines, the syntax for a symbolic address depends on
+ the section that the address refers to. On these machines,
+ define the macro `ENCODE_SECTION_INFO' to store the information
+ into the `symbol_ref', and then check for it here. */
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
+
+/* 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 ();
+extern char *output_andsi3 ();
+extern char *output_iorsi3 ();
+extern char *output_xorsi3 ();
+extern void output_dbcc_and_branch ();
+extern int const_uint32_operand ();
+extern int const_sint32_operand ();
+extern int floating_exact_log2 ();
+extern int not_sp_operand ();
+extern int valid_dbcc_comparison_p ();
+extern int extend_operator ();
+extern int flags_in_68881 ();
+extern int strict_low_part_peephole_ok ();
+
+/* 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;
+
+/* Functions from m68k.c used in macros. */
+extern int symbolic_operand ();
+extern int const_int_cost ();
+extern int standard_68881_constant_p ();
+extern int standard_sun_fpa_constant_p ();
+extern void output_function_prologue ();
+extern void output_function_epilogue ();
+extern int use_return_insn ();
+extern void print_operand_address ();
+extern void print_operand ();
+extern void notice_update_cc ();
+extern void finalize_pic ();
+extern void override_options ();
+
+
+/*
+Local variables:
+version-control: t
+End:
+*/
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
new file mode 100755
index 0000000..87e76ef
--- /dev/null
+++ b/gcc/config/m68k/m68k.md
@@ -0,0 +1,7913 @@
+;;- Machine description for GNU compiler, Motorola 68000 Version
+;; Copyright (C) 1987, 88, 93-97, 1998 Free Software Foundation, Inc.
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; 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, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;- Information about MCF5200 port.
+
+;;- The MCF5200 "ColdFire" architecture is a reduced version of the
+;;- 68k ISA. Differences include reduced support for byte and word
+;;- operands and the removal of BCD, bitfield, rotate, and integer
+;;- divide instructions. The TARGET_5200 flag turns the use of the
+;;- removed opcodes and addressing modes off.
+;;-
+
+
+;;- instruction definitions
+
+;;- @@The original PO technology requires these to be ordered by speed,
+;;- @@ so that assigner will pick the fastest.
+
+;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
+
+;;- When naming insn's (operand 0 of define_insn) be careful about using
+;;- names from other targets machine descriptions.
+
+;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
+;;- updates for most instructions.
+
+;;- Operand classes for the register allocator:
+;;- 'a' one of the address registers can be used.
+;;- 'd' one of the data registers can be used.
+;;- 'f' one of the m68881 registers can be used
+;;- 'r' either a data or an address register can be used.
+;;- 'x' if one of the Sun FPA registers
+;;- 'y' if one of the Low Sun FPA registers (fpa0-fpa15).
+
+;;- Immediate Floating point operator constraints
+;;- 'G' a floating point constant that is *NOT* one of the standard
+;; 68881 constant values (to force calling output_move_const_double
+;; to get it from rom if it is a 68881 constant).
+;;- 'H' one of the standard FPA constant values
+;;
+;; See the functions standard_XXX_constant_p in output-m68k.c for more
+;; info.
+
+;;- Immediate integer operand constraints:
+;;- 'I' 1 .. 8
+;;- 'J' -32768 .. 32767
+;;- 'K' all integers EXCEPT -128 .. 127
+;;- 'L' -8 .. -1
+;;- 'M' all integers EXCEPT -256 .. 255
+;;- 'N' 24 .. 31
+;;- 'O' 16
+;;- 'P' 8 .. 15
+
+;;- Assembler specs:
+;;- "%." size separator ("." or "") move%.l d0,d1
+;;- "%#" immediate separator ("#" or "") move%.l %#0,d0
+;;- "%-" push operand "sp@-" move%.l d0,%-
+;;- "%+" pop operand "sp@+" move%.l d0,%+
+;;- "%@" top of stack "sp@" move%.l d0,%@
+;;- "%!" fpcr register
+;;- "%$" single-precision fp specifier ("s" or "") f%$add.x fp0,fp1
+;;- "%&" double-precision fp specifier ("d" or "") f%&add.x fp0,fp1
+
+;; UNSPEC usage:
+;; 1 This is a `sin' operation. The mode of the UNSPEC is MODE_FLOAT.
+;; operand 1 is the argument for `sin'.
+;; 2 This is a `cos' operation. The mode of the UNSPEC is MODE_FLOAT.
+;; operand 1 is the argument for `cos'.
+
+;;- Information about 68040 port.
+
+;;- The 68040 executes all 68030 and 68881/2 instructions, but some must
+;;- be emulated in software by the OS. It is faster to avoid these
+;;- instructions and issue a library call rather than trapping into
+;;- the kernel. The affected instructions are fintrz and fscale. The
+;;- TARGET_68040 flag turns the use of the opcodes off.
+
+;;- The '040 also implements a set of new floating-point instructions
+;;- which specify the rounding precision in the opcode. This finally
+;;- permit the 68k series to be truly IEEE compliant, and solves all
+;;- issues of excess precision accumulating in the extended registers.
+;;- By default, GCC does not use these instructions, since such code will
+;;- not run on an '030. To use these instructions, use the -m68040-only
+;;- switch. By changing TARGET_DEFAULT to include TARGET_68040_ONLY,
+;;- you can make these instructions the default.
+
+;;- These new instructions aren't directly in the md. They are brought
+;;- into play by defining "%$" and "%&" to expand to "s" and "d" rather
+;;- than "".
+
+;;- Information about 68060 port.
+
+;;- The 68060 executes all 68030 and 68881/2 instructions, but some must
+;;- be emulated in software by the OS. It is faster to avoid these
+;;- instructions and issue a library call rather than trapping into
+;;- the kernel. The affected instructions are: divs.l <ea>,Dr:Dq;
+;;- divu.l <ea>,Dr:Dq; muls.l <ea>,Dr:Dq; mulu.l <ea>,Dr:Dq; and
+;;- fscale. The TARGET_68060 flag turns the use of the opcodes off.
+
+;;- FPA port explanation:
+
+;;- Usage of the Sun FPA and the 68881 together
+
+;;- The current port of gcc to the sun fpa disallows use of the m68881
+;;- instructions completely if code is targeted for the fpa. This is
+;;- for the following reasons:
+
+;;- 1) Expressing the preference hierarchy (ie. use the fpa if you
+;;- can, the 68881 otherwise, and data registers only if you are
+;;- forced to it) is a bitch with the current constraint scheme,
+;;- especially since it would have to work for any combination of
+;;- -mfpa, -m68881.
+
+;;- 2) There are no instructions to move between the two types of
+;;- registers; the stack must be used as an intermediary.
+
+;;- It could indeed be done; I think the best way would be to have
+;;- separate patterns for TARGET_FPA (which implies a 68881),
+;;- TARGET_68881, and no floating point co-processor. Use
+;;- define_expands for all of the named instruction patterns, and
+;;- include code in the FPA instruction to deal with the 68881 with
+;;- preferences specifically set to favor the fpa. Some of this has
+;;- already been done:
+;;-
+;;- 1) Separation of most of the patterns out into a TARGET_FPA
+;;- case and a TARGET_68881 case (the exceptions are the patterns
+;;- which would need one define_expand and three define_insn's under
+;;- it (with a lot of duplicate code between them) to replace the
+;;- current single define_insn. These are mov{[ds]f,[ds]i} and the
+;;- first two patterns in the md.
+;;-
+;;- Some would still have to be done:
+;;-
+;;- 1) Add code to the fpa patterns which correspond to 68881
+;;- patterns to deal with the 68881 case (including preferences!).
+;;- What you might actually do here is combine the fpa and 68881 code
+;;- back together into one pattern for those instructions where it's
+;;- absolutely necessary and save yourself some duplicate code. I'm
+;;- not completely sure as to whether you could get away with doing
+;;- this only for the mov* insns, or if you'd have to do it for all
+;;- named insns.
+;;- 2) Add code to the mov{[ds]f,[ds]i} instructions to handle
+;;- moving between fpa regs and 68881 regs.
+
+;;- Since the fpa is more powerful than the 68881 and also has more
+;;- registers, and since I think the resultant md would be medium ugly
+;;- (lot's of duplicate code, ugly constraint strings), I elected not
+;;- to do this change.
+
+;;- Another reason why someone *might* want to do the change is to
+;;- control which register classes are accessed in a slightly cleaner
+;;- way than I have. See the blurb on CONDITIONAL_REGISTER_USAGE in
+;;- the internals manual.
+
+;;- Yet another reason why someone might want to do this change is to
+;;- allow use of some of the 68881 insns which have no equivalent on
+;;- the fpa. The sqrt instruction comes fairly quickly to mind.
+
+;;- If this is ever done, don't forget to change sun3.h so that
+;;- it *will* define __HAVE_68881__ when the FPA is in use.
+
+;;- Condition code hack
+
+;;- When a floating point compare is done in the fpa, the resulting
+;;- condition codes are left in the fpastatus register. The values in
+;;- this register must be moved into the 68000 cc register before any
+;;- jump is executed. Once this has been done, regular jump
+;;- instructions are fine (ie. floating point jumps are not necessary.
+;;- They are only done if the cc is in the 68881).
+
+;;- The instructions that move the fpastatus register to the 68000
+;;- register clobber a data register (the move cannot be done direct).
+;;- These instructions might be bundled either with the compare
+;;- instruction, or the branch instruction. If we were using both the
+;;- fpa and the 68881 together, we would wish to only mark the
+;;- register clobbered if we were doing the compare in the fpa, but I
+;;- think that that decision (whether to clobber the register or not)
+;;- must be done before register allocation (makes sense) and hence we
+;;- can't know if the floating point compare will be done in the fpa
+;;- or the fp. So whenever we are asked for code that uses the fpa,
+;;- we will mark a data register as clobbered. This is reasonable, as
+;;- almost all floating point compare operations done with fpa code
+;;- enabled will be done in the fpa. It's even more reasonable since
+;;- we decided to make the 68881 and the fpa mutually exclusive.
+
+;;- We place to code to move the fpastatus register inside of a
+;;- define_expand so that we can do it conditionally based on whether
+;;- we are targeting an fpa or not.
+
+;;- This still leaves us with the question of where we wish to put the
+;;- code to move the fpastatus reg. If we put it in the compare
+;;- instruction, we can restrict the clobbering of the register to
+;;- floating point compares, but we can't take advantage of floating
+;;- point subtracts & etc. that alter the fpastatus register. If we
+;;- put it in the branch instruction, all branches compiled with fpa
+;;- code enabled will clobber a data register, but we will be able to
+;;- take advantage of fpa subtracts. This balance favors putting the
+;;- code in with the compare instruction.
+
+;;- Note that if some enterprising hacker should decide to switch
+;;- this, he'll need to modify the code in NOTICE_UPDATE_CC.
+
+;;- Usage of the top 16 fpa registers
+
+;;- The only locations which we may transfer fpa registers 16-31 from
+;;- or to are the fpa registers 0-15. (68000 registers and memory
+;;- locations are impossible). This causes problems in gcc, which
+;;- assumes that mov?? instructions require no additional registers
+;;- (see section 11.7) and since floating point moves *must* be
+;;- supported into general registers (see section 12.3 under
+;;- HARD_REGNO_OK_FOR_MODE_P) from anywhere.
+
+;;- My solution was to reserve fpa0 for moves into or out of these top
+;;- 16 registers and to disparage the choice to reload into or out of
+;;- these registers as much as I could. That alternative is always
+;;- last in the list, so it will not be used unless all else fails. I
+;;- will note that according to my current information, sun's compiler
+;;- doesn't use these top 16 registers at all.
+
+;;- There is another possible way to do it. I *believe* that if you
+;;- make absolutely sure that the code will not be executed in the
+;;- reload pass, you can support the mov?? names with define_expands
+;;- which require new registers. This may be possible by the
+;;- appropriate juggling of constraints. I may come back to this later.
+
+;;- Usage of constant RAM
+
+;;- This has been handled correctly (I believe) but the way I've done
+;;- it could use a little explanation. The constant RAM can only be
+;;- accessed when the instruction is in "command register" mode.
+;;- "command register" mode means that no accessing of memory or the
+;;- 68000 registers is being done. This can be expressed easily in
+;;- constraints, so generally the mode of the instruction is
+;;- determined by a branch off of which_alternative. In outputting
+;;- instructions, a 'w' means to output an access to the constant ram
+;;- (if the arg is CONST_DOUBLE and is one of the available
+;;- constants), and 'x' means to output a register pair (if the arg is
+;;- a 68000 register) and a 'y' is the combination of the above two
+;;- processes. You use a 'y' in two operand DF instructions where you
+;;- *know* the other operand is an fpa register, you use an 'x' in DF
+;;- instructions where the arg might be a 68000 register and the
+;;- instruction is *not* in "command register" mode, and you use a 'w'
+;;- in two situations: 1) The instruction *is* in command register
+;;- mode (and hence won't be accessing 68000 registers), or 2) The
+;;- instruction is a two operand SF instruction where you know the
+;;- other operand is an fpa register.
+
+;;- Optimization issues
+
+;;- I actually think that I've included all of the fpa instructions
+;;- that should be included. Note that if someone is interested in
+;;- doing serious floating point work on the sun fpa, I would advise
+;;- the use of the "asm" instruction in gcc to allow you to use the
+;;- sin, cos, and exponential functions on the fpa board.
+
+;;- END FPA Explanation Section.
+
+
+;;- Some of these insn's are composites of several m68000 op codes.
+;;- The assembler (or final @@??) insures that the appropriate one is
+;;- selected.
+
+(define_insn ""
+ [(set (match_operand:DF 0 "push_operand" "=m")
+ (match_operand:DF 1 "general_operand" "ro<>fyE"))]
+ ""
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"fmove%.d %f1,%0\";
+ if (FPA_REG_P (operands[1]))
+ return \"fpmove%.d %1, %x0\";
+ return output_move_double (operands);
+}")
+
+(define_insn "pushdi"
+ [(set (match_operand:DI 0 "push_operand" "=m")
+ (match_operand:DI 1 "general_operand" "ro<>Fyi"))]
+ ""
+ "*
+{
+ return output_move_double (operands);
+}")
+
+;; We don't want to allow a constant operand for test insns because
+;; (set (cc0) (const_int foo)) has no mode information. Such insns will
+;; be folded while optimizing anyway.
+
+(define_expand "tstdi"
+ [(parallel [(set (cc0)
+ (match_operand:DI 0 "nonimmediate_operand" ""))
+ (clobber (match_scratch:SI 1 ""))
+ (clobber (match_scratch:DI 2 ""))])]
+ ""
+ "m68k_last_compare_had_fp_operands = 0;")
+
+(define_insn ""
+ [(set (cc0)
+ (match_operand:DI 0 "nonimmediate_operand" "am,d"))
+ (clobber (match_scratch:SI 1 "=X,d"))
+ (clobber (match_scratch:DI 2 "=d,X"))]
+ ""
+ "*
+{
+ if (which_alternative == 0)
+ {
+ rtx xoperands[2];
+
+ xoperands[0] = operands[2];
+ xoperands[1] = operands[0];
+ output_move_double (xoperands);
+ cc_status.flags |= CC_REVERSED;
+ return \"neg%.l %R2\;negx%.l %2\";
+ }
+ if (find_reg_note (insn, REG_DEAD, operands[0]))
+ {
+ cc_status.flags |= CC_REVERSED;
+ return \"neg%.l %R0\;negx%.l %0\";
+ }
+ else
+ /*
+ ** 'sub' clears %1, and also clears the X cc bit
+ ** 'tst' sets the Z cc bit according to the low part of the DImode operand
+ ** 'subx %1' (i.e. subx #0) acts as a (non-existent) tstx on the high part
+ */
+ return \"sub%.l %1,%1\;tst%.l %R0\;subx%.l %1,%0\";
+}")
+
+(define_expand "tstsi"
+ [(set (cc0)
+ (match_operand:SI 0 "nonimmediate_operand" ""))]
+ ""
+ "m68k_last_compare_had_fp_operands = 0;")
+
+(define_insn ""
+ [(set (cc0)
+ (match_operand:SI 0 "nonimmediate_operand" "rm"))]
+ ""
+ "*
+{
+#ifdef ISI_OV
+ /* ISI's assembler fails to handle tstl a0. */
+ if (! ADDRESS_REG_P (operands[0]))
+#else
+ if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (operands[0]))
+#endif
+ return \"tst%.l %0\";
+ /* If you think that the 68020 does not support tstl a0,
+ reread page B-167 of the 68020 manual more carefully. */
+ /* On an address reg, cmpw may replace cmpl. */
+#ifdef SGS_CMP_ORDER
+ return \"cmp%.w %0,%#0\";
+#else
+ return \"cmp%.w %#0,%0\";
+#endif
+}")
+
+;; This can't use an address register, because comparisons
+;; with address registers as second operand always test the whole word.
+(define_expand "tsthi"
+ [(set (cc0)
+ (match_operand:HI 0 "nonimmediate_operand" ""))]
+ ""
+ "m68k_last_compare_had_fp_operands = 0;")
+
+(define_insn ""
+ [(set (cc0)
+ (match_operand:HI 0 "nonimmediate_operand" "dm"))]
+ ""
+ "tst%.w %0")
+
+(define_expand "tstqi"
+ [(set (cc0)
+ (match_operand:QI 0 "nonimmediate_operand" ""))]
+ ""
+ "m68k_last_compare_had_fp_operands = 0;")
+
+(define_insn ""
+ [(set (cc0)
+ (match_operand:QI 0 "nonimmediate_operand" "dm"))]
+ ""
+ "tst%.b %0")
+
+(define_expand "tstsf"
+ [(set (cc0)
+ (match_operand:SF 0 "general_operand" ""))]
+ "TARGET_68881 || TARGET_FPA"
+ "
+{
+ m68k_last_compare_had_fp_operands = 1;
+ if (TARGET_FPA)
+ {
+ emit_insn (gen_tstsf_fpa (operands[0]));
+ DONE;
+ }
+}")
+
+(define_insn "tstsf_fpa"
+ [(set (cc0)
+ (match_operand:SF 0 "general_operand" "xmdF"))
+ (clobber (match_scratch:SI 1 "=d"))]
+ "TARGET_FPA"
+ "fptst%.s %x0\;fpmove fpastatus,%1\;movw %1,cc")
+
+(define_insn ""
+ [(set (cc0)
+ (match_operand:SF 0 "general_operand" "fdm"))]
+ "TARGET_68881"
+ "*
+{
+ cc_status.flags = CC_IN_68881;
+ if (FP_REG_P (operands[0]))
+ return \"ftst%.x %0\";
+ return \"ftst%.s %0\";
+}")
+
+(define_expand "tstdf"
+ [(set (cc0)
+ (match_operand:DF 0 "general_operand" ""))]
+ "TARGET_68881 || TARGET_FPA"
+ "
+{
+ m68k_last_compare_had_fp_operands = 1;
+ if (TARGET_FPA)
+ {
+ emit_insn (gen_tstsf_fpa (operands[0]));
+ DONE;
+ }
+}")
+
+(define_insn "tstdf_fpa"
+ [(set (cc0)
+ (match_operand:DF 0 "general_operand" "xrmF"))
+ (clobber (match_scratch:SI 1 "=d"))]
+ "TARGET_FPA"
+ "fptst%.d %x0\;fpmove fpastatus,%1\;movw %1,cc")
+
+(define_insn ""
+ [(set (cc0)
+ (match_operand:DF 0 "general_operand" "fm"))]
+ "TARGET_68881"
+ "*
+{
+ cc_status.flags = CC_IN_68881;
+ if (FP_REG_P (operands[0]))
+ return \"ftst%.x %0\";
+ return \"ftst%.d %0\";
+}")
+
+;; compare instructions.
+
+(define_expand "cmpdi"
+ [(parallel
+ [(set (cc0)
+ (compare (match_operand:DI 0 "nonimmediate_operand" "")
+ (match_operand:DI 1 "general_operand" "")))
+ (clobber (match_dup 2))])]
+ ""
+ "m68k_last_compare_had_fp_operands = 0; operands[2] = gen_reg_rtx (DImode);")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:DI 1 "nonimmediate_operand" "0,d")
+ (match_operand:DI 2 "general_operand" "d,0")))
+ (clobber (match_operand:DI 0 "register_operand" "=d,d"))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"sub%.l %R2,%R0\;subx%.l %2,%0\";
+ else
+ {
+ cc_status.flags |= CC_REVERSED;
+ return \"sub%.l %R1,%R0\;subx%.l %1,%0\";
+ }
+}")
+
+;; This is the second "hook" for PIC code (in addition to movsi). See
+;; comment of movsi for a description of PIC handling.
+(define_expand "cmpsi"
+ [(set (cc0)
+ (compare (match_operand:SI 0 "nonimmediate_operand" "")
+ (match_operand:SI 1 "general_operand" "")))]
+ ""
+ "
+{
+ m68k_last_compare_had_fp_operands = 0;
+ if (flag_pic && symbolic_operand (operands[1], SImode))
+ {
+ /* The source is an address which requires PIC relocation.
+ Call legitimize_pic_address with the source, mode, and a relocation
+ register (a new pseudo, or the final destination if reload_in_progress
+ is set). Then fall through normally */
+ extern rtx legitimize_pic_address();
+ rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
+ operands[1] = legitimize_pic_address (operands[1], SImode, temp);
+ }
+}")
+
+;; A composite of the cmp, cmpa, cmpi & cmpm m68000 op codes.
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:SI 0 "nonimmediate_operand" "rKs,mr,>")
+ (match_operand:SI 1 "general_operand" "mr,rKs,>")))]
+ "!TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+#ifdef SGS_CMP_ORDER
+ return \"cmpm%.l %0,%1\";
+#else
+ return \"cmpm%.l %1,%0\";
+#endif
+ if (REG_P (operands[1])
+ || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+ { cc_status.flags |= CC_REVERSED;
+#ifdef SGS_CMP_ORDER
+ return \"cmp%.l %d1,%d0\";
+#else
+ return \"cmp%.l %d0,%d1\";
+#endif
+ }
+#ifdef SGS_CMP_ORDER
+ return \"cmp%.l %d0,%d1\";
+#else
+ return \"cmp%.l %d1,%d0\";
+#endif
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:SI 0 "nonimmediate_operand" "mrKs,r")
+ (match_operand:SI 1 "general_operand" "r,mrKs")))]
+ "TARGET_5200"
+ "*
+{
+ if (REG_P (operands[1])
+ || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+ { cc_status.flags |= CC_REVERSED;
+#ifdef SGS_CMP_ORDER
+ return \"cmp%.l %d1,%d0\";
+#else
+ return \"cmp%.l %d0,%d1\";
+#endif
+ }
+#ifdef SGS_CMP_ORDER
+ return \"cmp%.l %d0,%d1\";
+#else
+ return \"cmp%.l %d1,%d0\";
+#endif
+}")
+
+(define_expand "cmphi"
+ [(set (cc0)
+ (compare (match_operand:HI 0 "nonimmediate_operand" "")
+ (match_operand:HI 1 "general_operand" "")))]
+ "!TARGET_5200"
+ "m68k_last_compare_had_fp_operands = 0;")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:HI 0 "nonimmediate_operand" "rnm,d,n,m,>")
+ (match_operand:HI 1 "general_operand" "d,rnm,m,n,>")))]
+ "!TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+#ifdef SGS_CMP_ORDER
+ return \"cmpm%.w %0,%1\";
+#else
+ return \"cmpm%.w %1,%0\";
+#endif
+ if ((REG_P (operands[1]) && !ADDRESS_REG_P (operands[1]))
+ || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+ { cc_status.flags |= CC_REVERSED;
+#ifdef SGS_CMP_ORDER
+ return \"cmp%.w %d1,%d0\";
+#else
+ return \"cmp%.w %d0,%d1\";
+#endif
+ }
+#ifdef SGS_CMP_ORDER
+ return \"cmp%.w %d0,%d1\";
+#else
+ return \"cmp%.w %d1,%d0\";
+#endif
+}")
+
+(define_expand "cmpqi"
+ [(set (cc0)
+ (compare (match_operand:QI 0 "nonimmediate_operand" "")
+ (match_operand:QI 1 "general_operand" "")))]
+ "!TARGET_5200"
+ "m68k_last_compare_had_fp_operands = 0;")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:QI 0 "nonimmediate_operand" "dn,md,>")
+ (match_operand:QI 1 "general_operand" "dm,nd,>")))]
+ "!TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+#ifdef SGS_CMP_ORDER
+ return \"cmpm%.b %0,%1\";
+#else
+ return \"cmpm%.b %1,%0\";
+#endif
+ if (REG_P (operands[1])
+ || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+ { cc_status.flags |= CC_REVERSED;
+#ifdef SGS_CMP_ORDER
+ return \"cmp%.b %d1,%d0\";
+#else
+ return \"cmp%.b %d0,%d1\";
+#endif
+ }
+#ifdef SGS_CMP_ORDER
+ return \"cmp%.b %d0,%d1\";
+#else
+ return \"cmp%.b %d1,%d0\";
+#endif
+}")
+
+(define_expand "cmpdf"
+ [(set (cc0)
+ (compare (match_operand:DF 0 "general_operand" "")
+ (match_operand:DF 1 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "
+{
+ m68k_last_compare_had_fp_operands = 1;
+ if (TARGET_FPA)
+ {
+ emit_insn (gen_cmpdf_fpa (operands[0], operands[1]));
+ DONE;
+ }
+}")
+
+(define_insn "cmpdf_fpa"
+ [(set (cc0)
+ (compare (match_operand:DF 0 "general_operand" "x,y")
+ (match_operand:DF 1 "general_operand" "xH,rmF")))
+ (clobber (match_scratch:SI 2 "=d,d"))]
+ "TARGET_FPA"
+ "fpcmp%.d %y1,%0\;fpmove fpastatus,%2\;movw %2,cc")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:DF 0 "general_operand" "f,mG")
+ (match_operand:DF 1 "general_operand" "fmG,f")))]
+ "TARGET_68881"
+ "*
+{
+ cc_status.flags = CC_IN_68881;
+#ifdef SGS_CMP_ORDER
+ if (REG_P (operands[0]))
+ {
+ if (REG_P (operands[1]))
+ return \"fcmp%.x %0,%1\";
+ else
+ return \"fcmp%.d %0,%f1\";
+ }
+ cc_status.flags |= CC_REVERSED;
+ return \"fcmp%.d %1,%f0\";
+#else
+ if (REG_P (operands[0]))
+ {
+ if (REG_P (operands[1]))
+ return \"fcmp%.x %1,%0\";
+ else
+ return \"fcmp%.d %f1,%0\";
+ }
+ cc_status.flags |= CC_REVERSED;
+ return \"fcmp%.d %f0,%1\";
+#endif
+}")
+
+(define_expand "cmpsf"
+ [(set (cc0)
+ (compare (match_operand:SF 0 "general_operand" "")
+ (match_operand:SF 1 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "
+{
+ m68k_last_compare_had_fp_operands = 1;
+ if (TARGET_FPA)
+ {
+ emit_insn (gen_cmpsf_fpa (operands[0], operands[1]));
+ DONE;
+ }
+}")
+
+(define_insn "cmpsf_fpa"
+ [(set (cc0)
+ (compare (match_operand:SF 0 "general_operand" "x,y")
+ (match_operand:SF 1 "general_operand" "xH,rmF")))
+ (clobber (match_scratch:SI 2 "=d,d"))]
+ "TARGET_FPA"
+ "fpcmp%.s %w1,%x0\;fpmove fpastatus,%2\;movw %2,cc")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:SF 0 "general_operand" "f,mdG")
+ (match_operand:SF 1 "general_operand" "fmdG,f")))]
+ "TARGET_68881"
+ "*
+{
+ cc_status.flags = CC_IN_68881;
+#ifdef SGS_CMP_ORDER
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"fcmp%.x %0,%1\";
+ else
+ return \"fcmp%.s %0,%f1\";
+ }
+ cc_status.flags |= CC_REVERSED;
+ return \"fcmp%.s %1,%f0\";
+#else
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"fcmp%.x %1,%0\";
+ else
+ return \"fcmp%.s %f1,%0\";
+ }
+ cc_status.flags |= CC_REVERSED;
+ return \"fcmp%.s %f0,%1\";
+#endif
+}")
+
+;; Recognizers for btst instructions.
+
+;; Coldfire/5200 only allows "<Q>" type addresses when the bit position is
+;; specified as a constant, so we must disable all patterns that may extract
+;; from a MEM at a constant bit position if we can't use this as a constraint.
+
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o")
+ (const_int 1)
+ (minus:SI (const_int 7)
+ (match_operand:SI 1 "general_operand" "di"))))]
+ "!TARGET_5200"
+ "* { return output_btst (operands, operands[1], operands[0], insn, 7); }")
+
+;; This is the same as the above pattern except for the constraints. The 'i'
+;; has been deleted.
+
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o")
+ (const_int 1)
+ (minus:SI (const_int 7)
+ (match_operand:SI 1 "general_operand" "d"))))]
+ "TARGET_5200"
+ "* { return output_btst (operands, operands[1], operands[0], insn, 7); }")
+
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "d")
+ (const_int 1)
+ (minus:SI (const_int 31)
+ (match_operand:SI 1 "general_operand" "di"))))]
+ ""
+ "* { return output_btst (operands, operands[1], operands[0], insn, 31); }")
+
+;; The following two patterns are like the previous two
+;; except that they use the fact that bit-number operands
+;; are automatically masked to 3 or 5 bits.
+
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o")
+ (const_int 1)
+ (minus:SI (const_int 7)
+ (and:SI
+ (match_operand:SI 1 "register_operand" "d")
+ (const_int 7)))))]
+ ""
+ "* { return output_btst (operands, operands[1], operands[0], insn, 7); }")
+
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "d")
+ (const_int 1)
+ (minus:SI (const_int 31)
+ (and:SI
+ (match_operand:SI 1 "register_operand" "d")
+ (const_int 31)))))]
+ ""
+ "* { return output_btst (operands, operands[1], operands[0], insn, 31); }")
+
+;; Nonoffsettable mem refs are ok in this one pattern
+;; since we don't try to adjust them.
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m")
+ (const_int 1)
+ (match_operand:SI 1 "const_int_operand" "n")))]
+ "(unsigned) INTVAL (operands[1]) < 8 && !TARGET_5200"
+ "*
+{
+ operands[1] = GEN_INT (7 - INTVAL (operands[1]));
+ return output_btst (operands, operands[1], operands[0], insn, 7);
+}")
+
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "do")
+ (const_int 1)
+ (match_operand:SI 1 "const_int_operand" "n")))]
+ "!TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ operands[0] = adj_offsettable_operand (operands[0],
+ INTVAL (operands[1]) / 8);
+ operands[1] = GEN_INT (7 - INTVAL (operands[1]) % 8);
+ return output_btst (operands, operands[1], operands[0], insn, 7);
+ }
+ operands[1] = GEN_INT (31 - INTVAL (operands[1]));
+ return output_btst (operands, operands[1], operands[0], insn, 31);
+}")
+
+;; This is the same as the above pattern except for the constraints.
+;; The 'o' has been replaced with 'Q'.
+
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "dQ")
+ (const_int 1)
+ (match_operand:SI 1 "const_int_operand" "n")))]
+ "TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ operands[0] = adj_offsettable_operand (operands[0],
+ INTVAL (operands[1]) / 8);
+ operands[1] = GEN_INT (7 - INTVAL (operands[1]) % 8);
+ return output_btst (operands, operands[1], operands[0], insn, 7);
+ }
+ operands[1] = GEN_INT (31 - INTVAL (operands[1]));
+ return output_btst (operands, operands[1], operands[0], insn, 31);
+}")
+
+
+;; move instructions
+
+;; A special case in which it is not desirable
+;; to reload the constant into a data register.
+(define_insn "pushexthisi_const"
+ [(set (match_operand:SI 0 "push_operand" "=m")
+ (match_operand:SI 1 "const_int_operand" "J"))]
+ "INTVAL (operands[1]) >= -0x8000 && INTVAL (operands[1]) < 0x8000"
+ "*
+{
+ if (operands[1] == const0_rtx)
+ return \"clr%.l %0\";
+ return \"pea %a1\";
+}")
+
+;This is never used.
+;(define_insn "swapsi"
+; [(set (match_operand:SI 0 "general_operand" "+r")
+; (match_operand:SI 1 "general_operand" "+r"))
+; (set (match_dup 1) (match_dup 0))]
+; ""
+; "exg %1,%0")
+
+;; Special case of fullword move when source is zero.
+;; The reason this is special is to avoid loading a zero
+;; into a data reg with moveq in order to store it elsewhere.
+
+(define_insn "movsi_const0"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (const_int 0))]
+ ;; clr insns on 68000 read before writing.
+ ;; This isn't so on the 68010, but we have no TARGET_68010.
+ "((TARGET_68020 || TARGET_5200)
+ || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))"
+ "*
+{
+ if (ADDRESS_REG_P (operands[0]))
+ {
+ /* On the '040, 'subl an,an' takes 2 clocks while lea takes only 1 */
+ if (!TARGET_68040 && !TARGET_68060)
+ return \"sub%.l %0,%0\";
+ else
+ {
+#ifdef MOTOROLA
+#ifdef SGS
+ /* Many SGS assemblers croak on size specifiers for constants. */
+ return \"lea 0,%0\";
+#else
+ return \"lea 0.w,%0\";
+#endif
+#else
+ return \"lea 0:w,%0\";
+#endif
+ }
+ }
+ /* moveq is faster on the 68000. */
+ if (DATA_REG_P (operands[0]) && (!TARGET_68020 && !TARGET_5200))
+#if defined(MOTOROLA) && !defined(CRDS)
+ return \"moveq%.l %#0,%0\";
+#else
+ return \"moveq %#0,%0\";
+#endif
+ return \"clr%.l %0\";
+}")
+
+;; General case of fullword move.
+;;
+;; This is the main "hook" for PIC code. When generating
+;; PIC, movsi is responsible for determining when the source address
+;; needs PIC relocation and appropriately calling legitimize_pic_address
+;; to perform the actual relocation.
+;;
+;; In both the PIC and non-PIC cases the patterns generated will
+;; matched by the next define_insn.
+(define_expand "movsi"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (match_operand:SI 1 "general_operand" ""))]
+ ""
+ "
+{
+ if (flag_pic && symbolic_operand (operands[1], SImode))
+ {
+ /* The source is an address which requires PIC relocation.
+ Call legitimize_pic_address with the source, mode, and a relocation
+ register (a new pseudo, or the final destination if reload_in_progress
+ is set). Then fall through normally */
+ extern rtx legitimize_pic_address();
+ rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
+ operands[1] = legitimize_pic_address (operands[1], SImode, temp);
+ }
+}")
+
+;; General case of fullword move. The register constraints
+;; force integer constants in range for a moveq to be reloaded
+;; if they are headed for memory.
+(define_insn ""
+ ;; Notes: make sure no alternative allows g vs g.
+ ;; We don't allow f-regs since fixed point cannot go in them.
+ ;; We do allow y and x regs since fixed point is allowed in them.
+ [(set (match_operand:SI 0 "general_operand" "=g,da,y,!*x*r*m")
+ (match_operand:SI 1 "general_operand" "daymKs,i,g,*x*r*m"))]
+ "!TARGET_5200"
+ "*
+{
+ if (which_alternative == 3)
+ return \"fpmove%.l %x1,fpa0\;fpmove%.l fpa0,%x0\";
+ if (FPA_REG_P (operands[1]) || FPA_REG_P (operands[0]))
+ return \"fpmove%.l %x1,%x0\";
+ return output_move_simode (operands);
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=r<Q>,g")
+ (match_operand:SI 1 "general_operand" "g,r<Q>"))]
+ "TARGET_5200"
+ "* return output_move_simode (operands);")
+
+(define_expand "movhi"
+ [(set (match_operand:HI 0 "general_operand" "")
+ (match_operand:HI 1 "general_operand" ""))]
+ ""
+ "")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (match_operand:HI 1 "general_operand" "g"))]
+ "!TARGET_5200"
+ "* return output_move_himode (operands);")
+
+ (define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=r<Q>,g")
+ (match_operand:HI 1 "general_operand" "g,r<Q>"))]
+ "TARGET_5200"
+ "* return output_move_himode (operands);")
+
+(define_expand "movstricthi"
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" ""))
+ (match_operand:HI 1 "general_operand" ""))]
+ ""
+ "")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
+ (match_operand:HI 1 "general_operand" "rmn"))]
+ "!TARGET_5200"
+ "* return output_move_stricthi (operands);")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+d,m"))
+ (match_operand:HI 1 "general_operand" "rmn,r"))]
+ "TARGET_5200"
+ "* return output_move_stricthi (operands);")
+
+(define_expand "movqi"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+ "")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=d,*a,m")
+ (match_operand:QI 1 "general_operand" "dmi*a,di*a,dmi"))]
+ "!TARGET_5200"
+ "* return output_move_qimode (operands);")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=d<Q>,dm,d*a")
+ (match_operand:QI 1 "general_operand" "dmi,d<Q>,di*a"))]
+ "TARGET_5200"
+ "* return output_move_qimode (operands);")
+
+(define_expand "movstrictqi"
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" ""))
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+ "")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
+ (match_operand:QI 1 "general_operand" "dmn"))]
+ "!TARGET_5200"
+ "* return output_move_strictqi (operands);")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+d,m"))
+ (match_operand:QI 1 "general_operand" "dmn,d"))]
+ "TARGET_5200"
+ "* return output_move_strictqi (operands);")
+
+(define_expand "movsf"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (match_operand:SF 1 "general_operand" ""))]
+ ""
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=rmf,x,y,rm,!x,!rm")
+ (match_operand:SF 1 "general_operand" "rmfF,xH,rmF,y,rm,x"))]
+; [(set (match_operand:SF 0 "general_operand" "=rmf")
+; (match_operand:SF 1 "general_operand" "rmfF"))]
+ "!TARGET_5200"
+ "*
+{
+ if (which_alternative >= 4)
+ return \"fpmove%.s %1,fpa0\;fpmove%.s fpa0,%0\";
+ if (FPA_REG_P (operands[0]))
+ {
+ if (FPA_REG_P (operands[1]))
+ return \"fpmove%.s %x1,%x0\";
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ return output_move_const_single (operands);
+ else if (FP_REG_P (operands[1]))
+ return \"fmove%.s %1,sp@-\;fpmove%.d sp@+, %0\";
+ return \"fpmove%.s %x1,%x0\";
+ }
+ if (FPA_REG_P (operands[1]))
+ {
+ if (FP_REG_P (operands[0]))
+ return \"fpmove%.s %x1,sp@-\;fmove%.s sp@+,%0\";
+ else
+ return \"fpmove%.s %x1,%x0\";
+ }
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"f%$move%.x %1,%0\";
+ else if (ADDRESS_REG_P (operands[1]))
+ return \"move%.l %1,%-\;f%$move%.s %+,%0\";
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ return output_move_const_single (operands);
+ return \"f%$move%.s %f1,%0\";
+ }
+ if (FP_REG_P (operands[1]))
+ {
+ if (ADDRESS_REG_P (operands[0]))
+ return \"fmove%.s %1,%-\;move%.l %+,%0\";
+ return \"fmove%.s %f1,%0\";
+ }
+ if (operands[1] == CONST0_RTX (SFmode)
+ /* clr insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no TARGET_68010. */
+ && ((TARGET_68020 || TARGET_5200)
+ || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
+ {
+ if (ADDRESS_REG_P (operands[0]))
+ {
+ /* On the '040, 'subl an,an' takes 2 clocks while lea takes only 1 */
+ if (!TARGET_68040 && !TARGET_68060)
+ return \"sub%.l %0,%0\";
+ else
+ {
+#ifdef MOTOROLA
+#ifdef SGS
+ /* Many SGS assemblers croak on size specifiers for constants. */
+ return \"lea 0,%0\";
+#else
+ return \"lea 0.w,%0\";
+#endif
+#else
+ return \"lea 0:w,%0\";
+#endif
+ }
+ }
+ /* moveq is faster on the 68000. */
+ if (DATA_REG_P (operands[0]) && !(TARGET_68020 || TARGET_5200))
+ {
+#if defined(MOTOROLA) && !defined(CRDS)
+ return \"moveq%.l %#0,%0\";
+#else
+ return \"moveq %#0,%0\";
+#endif
+ }
+ return \"clr%.l %0\";
+ }
+ return \"move%.l %1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=r,g")
+ (match_operand:SF 1 "general_operand" "g,r"))]
+ "TARGET_5200"
+ "* return \"move%.l %1,%0\";")
+
+(define_expand "movdf"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (match_operand:DF 1 "general_operand" ""))]
+ ""
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=rm,rf,rf,&rof<>,y,rm,x,!x,!rm")
+ (match_operand:DF 1 "general_operand" "rf,m,0,rofE<>,rmE,y,xH,rm,x"))]
+; [(set (match_operand:DF 0 "general_operand" "=rm,&rf,&rof<>")
+; (match_operand:DF 1 "general_operand" "rf,m,rofF<>"))]
+ "!TARGET_5200"
+ "*
+{
+ if (which_alternative == 7)
+ return \"fpmove%.d %x1,fpa0\;fpmove%.d fpa0,%x0\";
+ if (FPA_REG_P (operands[0]))
+ {
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ return output_move_const_double (operands);
+ if (FP_REG_P (operands[1]))
+ return \"fmove%.d %1,sp@-\;fpmove%.d sp@+,%x0\";
+ return \"fpmove%.d %x1,%x0\";
+ }
+ else if (FPA_REG_P (operands[1]))
+ {
+ if (FP_REG_P(operands[0]))
+ return \"fpmove%.d %x1,sp@-\;fmoved sp@+,%0\";
+ else
+ return \"fpmove%.d %x1,%x0\";
+ }
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"f%&move%.x %1,%0\";
+ if (REG_P (operands[1]))
+ {
+ rtx xoperands[2];
+ xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+ output_asm_insn (\"move%.l %1,%-\", xoperands);
+ output_asm_insn (\"move%.l %1,%-\", operands);
+ return \"f%&move%.d %+,%0\";
+ }
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ return output_move_const_double (operands);
+ return \"f%&move%.d %f1,%0\";
+ }
+ else if (FP_REG_P (operands[1]))
+ {
+ if (REG_P (operands[0]))
+ {
+ output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands);
+ operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ return \"move%.l %+,%0\";
+ }
+ else
+ return \"fmove%.d %f1,%0\";
+ }
+ return output_move_double (operands);
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=r,g")
+ (match_operand:DF 1 "general_operand" "g,r"))]
+ "TARGET_5200"
+ "* return output_move_double (operands);")
+
+(define_expand "movxf"
+ [(set (match_operand:XF 0 "nonimmediate_operand" "")
+ (match_operand:XF 1 "general_operand" ""))]
+ ""
+ "
+{
+ if (CONSTANT_P (operands[1]))
+ {
+ operands[1] = force_const_mem (XFmode, operands[1]);
+ if (! memory_address_p (XFmode, XEXP (operands[1], 0))
+ && ! reload_in_progress)
+ operands[1] = change_address (operands[1], XFmode,
+ XEXP (operands[1], 0));
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,!r,!f,!r")
+ (match_operand:XF 1 "nonimmediate_operand" "m,f,f,f,r,!r"))]
+ "TARGET_68881"
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"fmove%.x %1,%0\";
+ if (REG_P (operands[1]))
+ {
+ rtx xoperands[2];
+ xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
+ output_asm_insn (\"move%.l %1,%-\", xoperands);
+ xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+ output_asm_insn (\"move%.l %1,%-\", xoperands);
+ output_asm_insn (\"move%.l %1,%-\", operands);
+ return \"fmove%.x %+,%0\";
+ }
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ return \"fmove%.x %1,%0\";
+ return \"fmove%.x %f1,%0\";
+ }
+ if (FP_REG_P (operands[1]))
+ {
+ if (REG_P (operands[0]))
+ {
+ output_asm_insn (\"fmove%.x %f1,%-\;move%.l %+,%0\", operands);
+ operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ output_asm_insn (\"move%.l %+,%0\", operands);
+ operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ return \"move%.l %+,%0\";
+ }
+ /* Must be memory destination. */
+ return \"fmove%.x %f1,%0\";
+ }
+ return output_move_double (operands);
+}
+")
+
+(define_insn ""
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=rm,rf,&rof<>")
+ (match_operand:XF 1 "nonimmediate_operand" "rf,m,rof<>"))]
+ "! TARGET_68881 && ! TARGET_5200"
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"fmove%.x %1,%0\";
+ if (REG_P (operands[1]))
+ {
+ rtx xoperands[2];
+ xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
+ output_asm_insn (\"move%.l %1,%-\", xoperands);
+ xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+ output_asm_insn (\"move%.l %1,%-\", xoperands);
+ output_asm_insn (\"move%.l %1,%-\", operands);
+ return \"fmove%.x %+,%0\";
+ }
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ return \"fmove%.x %1,%0\";
+ return \"fmove%.x %f1,%0\";
+ }
+ if (FP_REG_P (operands[1]))
+ {
+ if (REG_P (operands[0]))
+ {
+ output_asm_insn (\"fmove%.x %f1,%-\;move%.l %+,%0\", operands);
+ operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ output_asm_insn (\"move%.l %+,%0\", operands);
+ operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ return \"move%.l %+,%0\";
+ }
+ else
+ return \"fmove%.x %f1,%0\";
+ }
+ return output_move_double (operands);
+}
+")
+
+(define_insn ""
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=r,g")
+ (match_operand:XF 1 "nonimmediate_operand" "g,r"))]
+ "! TARGET_68881 && TARGET_5200"
+ "* return output_move_double (operands);")
+
+(define_expand "movdi"
+ ;; Let's see if it really still needs to handle fp regs, and, if so, why.
+ [(set (match_operand:DI 0 "general_operand" "")
+ (match_operand:DI 1 "general_operand" ""))]
+ ""
+ "")
+
+;; movdi can apply to fp regs in some cases
+(define_insn ""
+ ;; Let's see if it really still needs to handle fp regs, and, if so, why.
+ [(set (match_operand:DI 0 "general_operand" "=rm,r,&ro<>,y,rm,!*x,!rm")
+ (match_operand:DI 1 "general_operand" "rF,m,roi<>F,rmiF,y,rmF,*x"))]
+; [(set (match_operand:DI 0 "general_operand" "=rm,&r,&ro<>,!&rm,!&f,y,rm,x,!x,!rm")
+; (match_operand:DI 1 "general_operand" "r,m,roi<>,fF,rfmF,rmi,y,rm,x"))]
+; [(set (match_operand:DI 0 "general_operand" "=rm,&rf,&ro<>,!&rm,!&f")
+; (match_operand:DI 1 "general_operand" "r,m,roi<>,fF,rfF"))]
+ "!TARGET_5200"
+ "*
+{
+ if (which_alternative == 8)
+ return \"fpmove%.d %x1,fpa0\;fpmove%.d fpa0,%x0\";
+ if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1]))
+ return \"fpmove%.d %x1,%x0\";
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"fmove%.x %1,%0\";
+ if (REG_P (operands[1]))
+ {
+ rtx xoperands[2];
+ xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+ output_asm_insn (\"move%.l %1,%-\", xoperands);
+ output_asm_insn (\"move%.l %1,%-\", operands);
+ return \"fmove%.d %+,%0\";
+ }
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ return output_move_const_double (operands);
+ return \"fmove%.d %f1,%0\";
+ }
+ else if (FP_REG_P (operands[1]))
+ {
+ if (REG_P (operands[0]))
+ {
+ output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands);
+ operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ return \"move%.l %+,%0\";
+ }
+ else
+ return \"fmove%.d %f1,%0\";
+ }
+ return output_move_double (operands);
+}")
+
+(define_insn ""
+ [(set (match_operand:DI 0 "general_operand" "=r,g")
+ (match_operand:DI 1 "general_operand" "g,r"))]
+ "TARGET_5200"
+ "* return output_move_double (operands);")
+
+;; Thus goes after the move instructions
+;; because the move instructions are better (require no spilling)
+;; when they can apply. It goes before the add/sub insns
+;; so we will prefer it to them.
+
+(define_insn "pushasi"
+ [(set (match_operand:SI 0 "push_operand" "=m")
+ (match_operand:SI 1 "address_operand" "p"))]
+ ""
+ "pea %a1")
+
+;; truncation instructions
+(define_insn "truncsiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm,d")
+ (truncate:QI
+ (match_operand:SI 1 "general_operand" "doJ,i")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == REG)
+ {
+ /* Must clear condition codes, since the move.l bases them on
+ the entire 32 bits, not just the desired 8 bits. */
+ CC_STATUS_INIT;
+ return \"move%.l %1,%0\";
+ }
+ if (GET_CODE (operands[1]) == MEM)
+ operands[1] = adj_offsettable_operand (operands[1], 3);
+ return \"move%.b %1,%0\";
+}")
+
+(define_insn "trunchiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm,d")
+ (truncate:QI
+ (match_operand:HI 1 "general_operand" "doJ,i")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == REG
+ && (GET_CODE (operands[1]) == MEM
+ || GET_CODE (operands[1]) == CONST_INT))
+ {
+ /* Must clear condition codes, since the move.w bases them on
+ the entire 16 bits, not just the desired 8 bits. */
+ CC_STATUS_INIT;
+ return \"move%.w %1,%0\";
+ }
+ if (GET_CODE (operands[0]) == REG)
+ {
+ /* Must clear condition codes, since the move.l bases them on
+ the entire 32 bits, not just the desired 8 bits. */
+ CC_STATUS_INIT;
+ return \"move%.l %1,%0\";
+ }
+ if (GET_CODE (operands[1]) == MEM)
+ operands[1] = adj_offsettable_operand (operands[1], 1);
+ return \"move%.b %1,%0\";
+}")
+
+(define_insn "truncsihi2"
+ [(set (match_operand:HI 0 "general_operand" "=dm,d")
+ (truncate:HI
+ (match_operand:SI 1 "general_operand" "roJ,i")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == REG)
+ {
+ /* Must clear condition codes, since the move.l bases them on
+ the entire 32 bits, not just the desired 8 bits. */
+ CC_STATUS_INIT;
+ return \"move%.l %1,%0\";
+ }
+ if (GET_CODE (operands[1]) == MEM)
+ operands[1] = adj_offsettable_operand (operands[1], 2);
+ return \"move%.w %1,%0\";
+}")
+
+;; zero extension instructions
+
+(define_insn "zero_extendqidi2"
+ [(set (match_operand:DI 0 "general_operand" "=&d")
+ (zero_extend:DI (match_operand:QI 1 "general_operand" "dm")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ return \"moveq %#0,%0\;moveq %#0,%2\;move%.b %1,%2\";
+}")
+
+(define_insn "zero_extendhidi2"
+ [(set (match_operand:DI 0 "general_operand" "=&d")
+ (zero_extend:DI (match_operand:HI 1 "general_operand" "rm")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ return \"moveq %#0,%0\;moveq %#0,%2\;move%.w %1,%2\";
+}")
+
+;; this is the canonical form for (lshiftrt:DI x 32)
+(define_insn "zero_extendsidi2"
+ [(set (match_operand:DI 0 "general_operand" "rm")
+ (zero_extend:DI (match_operand:SI 1 "general_operand" "rm")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (GET_CODE (operands[0]) == REG)
+ operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ return \"move%.l %1,%0\;clr%.l %0\";
+ else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ return \"clr%.l %0\;move%.l %1,%0\";
+ else
+ operands[2] = adj_offsettable_operand (operands[0], 4);
+ if (GET_CODE (operands[1]) != REG || GET_CODE (operands[2]) != REG
+ || REGNO (operands[1]) != REGNO (operands[2]))
+ output_asm_insn (\"move%.l %1,%2\", operands);
+ if (ADDRESS_REG_P (operands[0]))
+ return \"sub%.l %0,%0\";
+ else
+ return \"clr%.l %0\";
+}")
+
+(define_expand "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (const_int 0))
+ (set (strict_low_part (match_dup 2))
+ (match_operand:HI 1 "general_operand" ""))]
+ ""
+ "
+{
+ operands[1] = make_safe_from (operands[1], operands[0]);
+ if (GET_CODE (operands[0]) == SUBREG)
+ operands[2] = gen_rtx_SUBREG (HImode, SUBREG_REG (operands[0]),
+ SUBREG_WORD (operands[0]));
+ else
+ operands[2] = gen_rtx_SUBREG (HImode, operands[0], 0);
+}")
+
+(define_expand "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "")
+ (const_int 0))
+ (set (strict_low_part (match_dup 2))
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+ "
+{
+ operands[1] = make_safe_from (operands[1], operands[0]);
+ if (GET_CODE (operands[0]) == SUBREG)
+ operands[2] = gen_rtx_SUBREG (QImode, SUBREG_REG (operands[0]),
+ SUBREG_WORD (operands[0]));
+ else
+ operands[2] = gen_rtx_SUBREG (QImode, operands[0], 0);
+}")
+
+(define_expand "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (const_int 0))
+ (set (strict_low_part (match_dup 2))
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+ "
+{
+ operands[1] = make_safe_from (operands[1], operands[0]);
+ if (GET_CODE (operands[0]) == SUBREG)
+ operands[2] = gen_rtx_SUBREG (QImode, SUBREG_REG (operands[0]),
+ SUBREG_WORD (operands[0]));
+ else
+ operands[2] = gen_rtx_SUBREG (QImode, operands[0], 0);
+}")
+
+;; Patterns to recognize zero-extend insns produced by the combiner.
+;; We don't allow both operands in memory, because of aliasing problems.
+;; Explicitly disallow two memory operands via the condition since reloading
+;; of this case will result in worse code than the uncombined patterns.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=do<>,d<")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+ "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
+ "*
+{
+ if (DATA_REG_P (operands[0]))
+ {
+ if (GET_CODE (operands[1]) == REG
+ && REGNO (operands[0]) == REGNO (operands[1]))
+ return \"and%.l %#0xFFFF,%0\";
+ if (reg_mentioned_p (operands[0], operands[1]))
+ return \"move%.w %1,%0\;and%.l %#0xFFFF,%0\";
+ return \"clr%.l %0\;move%.w %1,%0\";
+ }
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ return \"move%.w %1,%0\;clr%.w %0\";
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ return \"clr%.w %0\;move%.w %1,%0\";
+ else
+ {
+ output_asm_insn (\"clr%.w %0\", operands);
+ operands[0] = adj_offsettable_operand (operands[0], 2);
+ return \"move%.w %1,%0\";
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=do<>,d")
+ (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+ "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
+ "*
+{
+ if (DATA_REG_P (operands[0]))
+ {
+ if (GET_CODE (operands[1]) == REG
+ && REGNO (operands[0]) == REGNO (operands[1]))
+ return (!TARGET_5200 ? \"and%.w %#0xFF,%0\" : \"and%.l %#0xFF,%0\");
+ if (reg_mentioned_p (operands[0], operands[1]))
+ return (!TARGET_5200 ? \"move%.b %1,%0\;and%.w %#0xFF,%0\"
+ : \"move%.b %1,%0\;and%.l %#0xFF,%0\");
+ return \"clr%.w %0\;move%.b %1,%0\";
+ }
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ {
+ if (REGNO (XEXP (XEXP (operands[0], 0), 0))
+ == STACK_POINTER_REGNUM)
+ {
+ output_asm_insn (\"clr%.w %-\", operands);
+ operands[0] = gen_rtx_MEM (GET_MODE (operands[0]),
+ plus_constant (stack_pointer_rtx, 1));
+ return \"move%.b %1,%0\";
+ }
+ else
+ return \"move%.b %1,%0\;clr%.b %0\";
+ }
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ return \"clr%.b %0\;move%.b %1,%0\";
+ else
+ {
+ output_asm_insn (\"clr%.b %0\", operands);
+ operands[0] = adj_offsettable_operand (operands[0], 1);
+ return \"move%.b %1,%0\";
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=do<>,d")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+ "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
+ "*
+{
+ if (DATA_REG_P (operands[0]))
+ {
+ if (GET_CODE (operands[1]) == REG
+ && REGNO (operands[0]) == REGNO (operands[1]))
+ return \"and%.l %#0xFF,%0\";
+ if (reg_mentioned_p (operands[0], operands[1]))
+ return \"move%.b %1,%0\;and%.l %#0xFF,%0\";
+ return \"clr%.l %0\;move%.b %1,%0\";
+ }
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ {
+ operands[0] = XEXP (XEXP (operands[0], 0), 0);
+#ifdef MOTOROLA
+#ifdef SGS
+ return \"clr%.l -(%0)\;move%.b %1,3(%0)\";
+#else
+ return \"clr%.l -(%0)\;move%.b %1,(3,%0)\";
+#endif
+#else
+ return \"clrl %0@-\;moveb %1,%0@(3)\";
+#endif
+ }
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ {
+ operands[0] = XEXP (XEXP (operands[0], 0), 0);
+#ifdef MOTOROLA
+#ifdef SGS
+ return \"clr%.l (%0)+\;move%.b %1,-1(%0)\";
+#else
+ return \"clr%.l (%0)+\;move%.b %1,(-1,%0)\";
+#endif
+#else
+ return \"clrl %0@+\;moveb %1,%0@(-1)\";
+#endif
+ }
+ else
+ {
+ output_asm_insn (\"clr%.l %0\", operands);
+ operands[0] = adj_offsettable_operand (operands[0], 3);
+ return \"move%.b %1,%0\";
+ }
+}")
+
+;; sign extension instructions
+
+(define_insn "extendqidi2"
+ [(set (match_operand:DI 0 "general_operand" "=d")
+ (sign_extend:DI
+ (match_operand:QI 1 "general_operand" "rm")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ if (TARGET_68020 || TARGET_5200)
+ return \"move%.b %1,%2\;extb%.l %2\;smi %0\;extb%.l %0\";
+ else
+ return \"move%.b %1,%2\;ext%.w %0\;ext%.l %2\;move%.l %2,%0\;smi %0\";
+}")
+
+(define_insn "extendhidi2"
+ [(set (match_operand:DI 0 "general_operand" "=d")
+ (sign_extend:DI
+ (match_operand:HI 1 "general_operand" "rm")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ if (TARGET_68020 || TARGET_5200)
+ return \"move%.w %1,%2\;ext%.l %2\;smi %0\;extb%.l %0\";
+ else
+ return \"move%.w %1,%2\;ext%.l %2\;smi %0\;ext%.w %0\;ext%.l %0\";
+}")
+
+(define_insn "extendsidi2"
+ [(set (match_operand:DI 0 "general_operand" "=d")
+ (sign_extend:DI
+ (match_operand:SI 1 "general_operand" "rm")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ if (TARGET_68020 || TARGET_5200)
+ return \"move%.l %1,%2\;smi %0\;extb%.l %0\";
+ else
+ return \"move%.l %1,%2\;smi %0\;ext%.w %0\;ext%.l %0\";
+}")
+
+;; Special case when one can avoid register clobbering, copy and test
+;; Maybe there is a way to make that the general case, by forcing the
+;; result of the SI tree to be in the lower register of the DI target
+
+(define_insn "extendplussidi"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (sign_extend:DI (plus:SI (match_operand:SI 1 "general_operand" "%rmn")
+ (match_operand:SI 2 "general_operand" "rmn"))))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ if (GET_CODE (operands[1]) == CONST_INT
+ && (unsigned) INTVAL (operands[1]) > 8)
+ {
+ rtx tmp = operands[1];
+
+ operands[1] = operands[2];
+ operands[2] = tmp;
+ }
+ if (GET_CODE (operands[1]) == REG
+ && REGNO (operands[1]) == REGNO (operands[3]))
+ output_asm_insn (\"add%.l %2,%3\", operands);
+ else
+ output_asm_insn (\"move%.l %2,%3\;add%.l %1,%3\", operands);
+ if (TARGET_68020 || TARGET_5200)
+ return \"smi %0\;extb%.l %0\";
+ else
+ return \"smi %0\;ext%.w %0\;ext%.l %0\";
+}")
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "general_operand" "=*d,a")
+ (sign_extend:SI
+ (match_operand:HI 1 "nonimmediate_operand" "0,rm")))]
+ ""
+ "*
+{
+ if (ADDRESS_REG_P (operands[0]))
+ return \"move%.w %1,%0\";
+ return \"ext%.l %0\";
+}")
+
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0")))]
+ ""
+ "ext%.w %0")
+
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0")))]
+ "TARGET_68020 || TARGET_5200"
+ "extb%.l %0")
+
+;; Conversions between float and double.
+
+(define_expand "extendsfdf2"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (float_extend:DF
+ (match_operand:SF 1 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=x,y")
+ (float_extend:DF
+ (match_operand:SF 1 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "fpstod %w1,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=*fdm,f")
+ (float_extend:DF
+ (match_operand:SF 1 "general_operand" "f,dmF")))]
+ "TARGET_68881"
+ "*
+{
+ if (FP_REG_P (operands[0]) && FP_REG_P (operands[1]))
+ {
+ if (REGNO (operands[0]) == REGNO (operands[1]))
+ {
+ /* Extending float to double in an fp-reg is a no-op.
+ NOTICE_UPDATE_CC has already assumed that the
+ cc will be set. So cancel what it did. */
+ cc_status = cc_prev_status;
+ return \"\";
+ }
+ return \"f%&move%.x %1,%0\";
+ }
+ if (FP_REG_P (operands[0]))
+ return \"f%&move%.s %f1,%0\";
+ if (DATA_REG_P (operands[0]) && FP_REG_P (operands[1]))
+ {
+ output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands);
+ operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ return \"move%.l %+,%0\";
+ }
+ return \"fmove%.d %f1,%0\";
+}")
+
+;; This cannot output into an f-reg because there is no way to be
+;; sure of truncating in that case.
+;; But on the Sun FPA, we can be sure.
+(define_expand "truncdfsf2"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (float_truncate:SF
+ (match_operand:DF 1 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=x,y")
+ (float_truncate:SF
+ (match_operand:DF 1 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "fpdtos %y1,%0")
+
+;; On the '040 we can truncate in a register accurately and easily.
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (float_truncate:SF
+ (match_operand:DF 1 "general_operand" "fmG")))]
+ "TARGET_68040_ONLY"
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"f%$move%.x %1,%0\";
+ return \"f%$move%.d %f1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=dm")
+ (float_truncate:SF
+ (match_operand:DF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.s %f1,%0")
+
+;; Conversion between fixed point and floating point.
+;; Note that among the fix-to-float insns
+;; the ones that start with SImode come first.
+;; That is so that an operand that is a CONST_INT
+;; (and therefore lacks a specific machine mode).
+;; will be recognized as SImode (which is always valid)
+;; rather than as QImode or HImode.
+
+(define_expand "floatsisf2"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (float:SF (match_operand:SI 1 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=y,x")
+ (float:SF (match_operand:SI 1 "general_operand" "rmi,x")))]
+ "TARGET_FPA"
+ "fpltos %1,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (float:SF (match_operand:SI 1 "general_operand" "dmi")))]
+ "TARGET_68881"
+ "f%$move%.l %1,%0")
+
+(define_expand "floatsidf2"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (float:DF (match_operand:SI 1 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=y,x")
+ (float:DF (match_operand:SI 1 "general_operand" "rmi,x")))]
+ "TARGET_FPA"
+ "fpltod %1,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (float:DF (match_operand:SI 1 "general_operand" "dmi")))]
+ "TARGET_68881"
+ "f%&move%.l %1,%0")
+
+(define_insn "floathisf2"
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (float:SF (match_operand:HI 1 "general_operand" "dmn")))]
+ "TARGET_68881"
+ "f%$move%.w %1,%0")
+
+(define_insn "floathidf2"
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (float:DF (match_operand:HI 1 "general_operand" "dmn")))]
+ "TARGET_68881"
+ "fmove%.w %1,%0")
+
+(define_insn "floatqisf2"
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (float:SF (match_operand:QI 1 "general_operand" "dmn")))]
+ "TARGET_68881"
+ "fmove%.b %1,%0")
+
+(define_insn "floatqidf2"
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (float:DF (match_operand:QI 1 "general_operand" "dmn")))]
+ "TARGET_68881"
+ "f%&move%.b %1,%0")
+
+;; New routines to convert floating-point values to integers
+;; to be used on the '040. These should be faster than trapping
+;; into the kernel to emulate fintrz. They should also be faster
+;; than calling the subroutines fixsfsi or fixdfsi.
+
+(define_insn "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=dm")
+ (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
+ (clobber (match_scratch:SI 2 "=d"))
+ (clobber (match_scratch:SI 3 "=d"))]
+ "TARGET_68881 && TARGET_68040"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"fmovem%.l %!,%2\;moveq %#16,%3\;or%.l %2,%3\;and%.w %#-33,%3\;fmovem%.l %3,%!\;fmove%.l %1,%0\;fmovem%.l %2,%!\";
+}")
+
+(define_insn "fix_truncdfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=dm")
+ (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
+ (clobber (match_scratch:SI 2 "=d"))
+ (clobber (match_scratch:SI 3 "=d"))]
+ "TARGET_68881 && TARGET_68040"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"fmovem%.l %!,%2\;moveq %#16,%3\;or%.l %2,%3\;and%.w %#-33,%3\;fmovem%.l %3,%!\;fmove%.w %1,%0\;fmovem%.l %2,%!\";
+}")
+
+(define_insn "fix_truncdfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (fix:QI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
+ (clobber (match_scratch:SI 2 "=d"))
+ (clobber (match_scratch:SI 3 "=d"))]
+ "TARGET_68881 && TARGET_68040"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"fmovem%.l %!,%2\;moveq %#16,%3\;or%.l %2,%3\;and%.w %#-33,%3\;fmovem%.l %3,%!\;fmove%.b %1,%0\;fmovem%.l %2,%!\";
+}")
+
+;; Convert a float to a float whose value is an integer.
+;; This is the first stage of converting it to an integer type.
+
+(define_insn "ftruncdf2"
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (fix:DF (match_operand:DF 1 "general_operand" "fFm")))]
+ "TARGET_68881 && !TARGET_68040"
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"fintrz%.x %f1,%0\";
+ return \"fintrz%.d %f1,%0\";
+}")
+
+(define_insn "ftruncsf2"
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (fix:SF (match_operand:SF 1 "general_operand" "dfFm")))]
+ "TARGET_68881 && !TARGET_68040"
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"fintrz%.x %f1,%0\";
+ return \"fintrz%.s %f1,%0\";
+}")
+
+;; Convert a float whose value is an integer
+;; to an actual integer. Second stage of converting float to integer type.
+(define_insn "fixsfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (fix:QI (match_operand:SF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.b %1,%0")
+
+(define_insn "fixsfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=dm")
+ (fix:HI (match_operand:SF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.w %1,%0")
+
+(define_insn "fixsfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=dm")
+ (fix:SI (match_operand:SF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.l %1,%0")
+
+(define_insn "fixdfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (fix:QI (match_operand:DF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.b %1,%0")
+
+(define_insn "fixdfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=dm")
+ (fix:HI (match_operand:DF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.w %1,%0")
+
+(define_insn "fixdfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=dm")
+ (fix:SI (match_operand:DF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.l %1,%0")
+
+;; Convert a float to an integer.
+;; On the Sun FPA, this is done in one step.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=x,y")
+ (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "xH,rmF"))))]
+ "TARGET_FPA"
+ "fpstol %w1,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=x,y")
+ (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "xH,rmF"))))]
+ "TARGET_FPA"
+ "fpdtol %y1,%0")
+
+;; add instructions
+
+(define_insn "adddi_lshrdi_63"
+ [(set (match_operand:DI 0 "general_operand" "=d")
+ (plus:DI (lshiftrt:DI (match_operand:DI 1 "general_operand" "rm")
+ (const_int 63))
+ (match_dup 1)))
+ (clobber (match_scratch:SI 2 "=d"))]
+ ""
+ "*
+{
+ operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ if (REG_P (operands[1]) && REGNO (operands[1]) == REGNO (operands[0]))
+ return
+ \"move%.l %1,%2\;add%.l %2,%2\;subx%.l %2,%2\;sub%.l %2,%3\;subx%.l %2,%0\";
+ if (GET_CODE (operands[1]) == REG)
+ operands[4] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+ else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC
+ || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
+ operands[4] = operands[1];
+ else
+ operands[4] = adj_offsettable_operand (operands[1], 4);
+ if (GET_CODE (operands[1]) == MEM
+ && GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
+ output_asm_insn (\"move%.l %4,%3\", operands);
+ output_asm_insn (\"move%.l %1,%0\;smi %2\", operands);
+ if (TARGET_68020 || TARGET_5200)
+ output_asm_insn (\"extb%.l %2\", operands);
+ else
+ output_asm_insn (\"ext%.w %2\;ext%.l %2\", operands);
+ if (GET_CODE (operands[1]) != MEM
+ || GET_CODE (XEXP (operands[1], 0)) != PRE_DEC)
+ output_asm_insn (\"move%.l %4,%3\", operands);
+ return \"sub%.l %2,%3\;subx%.l %2,%0\";
+}")
+
+(define_insn "adddi_sexthishl32"
+ [(set (match_operand:DI 0 "general_operand" "=o,a,*d,*d")
+ (plus:DI (ashift:DI (sign_extend:DI
+ (match_operand:HI 1 "general_operand" "rm,rm,rm,rm"))
+ (const_int 32))
+ (match_operand:DI 2 "general_operand" "0,0,0,0")))
+ (clobber (match_scratch:SI 3 "=&d,X,a,?d"))]
+ "!TARGET_5200"
+ "*
+{
+ CC_STATUS_INIT;
+ if (ADDRESS_REG_P (operands[0]))
+ return \"add%.w %1,%0\";
+ else if (ADDRESS_REG_P (operands[3]))
+ return \"move%.w %1,%3\;add%.l %3,%0\";
+ else
+ return \"move%.w %1,%3\;ext%.l %3\;add%.l %3,%0\";
+} ")
+
+(define_insn "adddi_dilshr32"
+ [(set (match_operand:DI 0 "general_operand" "=d,o")
+;; (plus:DI (match_operand:DI 2 "general_operand" "%0")
+;; (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro")
+;; (const_int 32))))]
+ (plus:DI (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro,r")
+ (const_int 32))
+ (match_operand:DI 2 "general_operand" "0,0")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (GET_CODE (operands[0]) == REG)
+ operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ else
+ operands[2] = adj_offsettable_operand (operands[0], 4);
+ return \"add%.l %1,%2\;negx%.l %0\;neg%.l %0\";
+} ")
+
+(define_insn "adddi_dishl32"
+ [(set (match_operand:DI 0 "general_operand" "=r,o")
+;; (plus:DI (match_operand:DI 2 "general_operand" "%0")
+;; (ashift:DI (match_operand:DI 1 "general_operand" "ro")
+;; (const_int 32))))]
+ (plus:DI (ashift:DI (match_operand:DI 1 "general_operand" "ro,r")
+ (const_int 32))
+ (match_operand:DI 2 "general_operand" "0,0")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (GET_CODE (operands[1]) == REG)
+ operands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+ else
+ operands[1] = adj_offsettable_operand (operands[1], 4);
+ return \"add%.l %1,%0\";
+} ")
+
+(define_insn "adddi3"
+ [(set (match_operand:DI 0 "general_operand" "=<,o<>,d,d,d")
+ (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0,0")
+ (match_operand:DI 2 "general_operand" "<,d,no>,d,a")))
+ (clobber (match_scratch:SI 3 "=X,&d,&d,X,&d"))]
+ ""
+ "*
+{
+ if (DATA_REG_P (operands[0]))
+ {
+ if (DATA_REG_P (operands[2]))
+ return \"add%.l %R2,%R0\;addx%.l %2,%0\";
+ else if (GET_CODE (operands[2]) == MEM
+ && GET_CODE (XEXP (operands[2], 0)) == POST_INC)
+ {
+ return \"move%.l %2,%3\;add%.l %2,%R0\;addx%.l %3,%0\";
+ }
+ else
+ {
+ rtx xoperands[2];
+ if (GET_CODE (operands[2]) == REG)
+ operands[1] = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
+ else if (GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+ operands[2] = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
+ }
+ else if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ operands[1] = operands[2];
+ operands[2] = INTVAL (operands[2]) < 0 ? constm1_rtx : const0_rtx;
+ }
+ else
+ operands[1] = adj_offsettable_operand (operands[2], 4);
+ xoperands[0] = operands[3];
+ if (GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) >= -8 && INTVAL (operands[1]) < 0)
+ xoperands[1] = GEN_INT (-INTVAL (operands[2]) - 1);
+ else
+ xoperands[1] = operands[2];
+ output_asm_insn (output_move_simode (xoperands), xoperands);
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (INTVAL (operands[1]) > 0 && INTVAL (operands[1]) <= 8)
+ {
+#ifdef NO_ADDSUB_Q
+ return \"add%.l %1,%R0\;addx%.l %3,%0\";
+#else
+ return \"addq%.l %1,%R0\;addx%.l %3,%0\";
+#endif
+ }
+ else if (INTVAL (operands[1]) >= -8 && INTVAL (operands[1]) < 0)
+ {
+ operands[1] = GEN_INT (-INTVAL (operands[1]));
+#ifdef NO_ADDSUB_Q
+ return \"sub%.l %1,%R0\;subx%.l %3,%0\";
+#else
+ return \"subq%.l %1,%R0\;subx%.l %3,%0\";
+#endif
+ }
+ }
+ return \"add%.l %1,%R0\;addx%.l %3,%0\";
+ }
+ }
+ else if (GET_CODE (operands[0]) == MEM)
+ {
+ if (GET_CODE (operands[2]) == MEM
+ && GET_CODE (XEXP (operands[2], 0)) == PRE_DEC)
+ return \"add%.l %2,%0\;addx%.l %2,%0\";
+ CC_STATUS_INIT;
+ if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ {
+ operands[1]
+ = gen_rtx_MEM (SImode,
+ gen_rtx_PLUS (VOIDmode, XEXP(operands[0], 0),
+ GEN_INT (-8)));
+ return \"move%.l %0,%3\;add%.l %R2,%0\;addx%.l %2,%3\;move%.l %3,%1\";
+ }
+ else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ {
+ operands[1] = XEXP(operands[0], 0);
+ return \"add%.l %R2,%0\;move%.l %0,%3\;addx%.l %2,%3\;move%.l %3,%1\";
+ }
+ else
+ {
+ operands[1] = adj_offsettable_operand (operands[0], 4);
+ return \"add%.l %R2,%1\;move%.l %0,%3\;addx%.l %2,%3\;move%.l %3,%0\";
+ }
+ }
+ else
+ abort ();
+} ")
+
+(define_insn "addsi_lshrsi_31"
+ [(set (match_operand:SI 0 "general_operand" "=dm")
+ (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "rm")
+ (const_int 31))
+ (match_dup 1)))]
+ ""
+ "*
+{
+ operands[2] = operands[0];
+ operands[3] = gen_label_rtx();
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ operands[0] = gen_rtx_MEM (SImode, XEXP (XEXP (operands[0], 0), 0));
+ else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ operands[2] = gen_rtx_MEM (SImode, XEXP (XEXP (operands[0], 0), 0));
+ }
+ output_asm_insn (\"move%.l %1,%0\", operands);
+#ifdef MOTOROLA
+ output_asm_insn (\"jbpl %l3\", operands);
+#else
+ output_asm_insn (\"jpl %l3\", operands);
+#endif
+#ifndef NO_ADDSUB_Q
+ output_asm_insn (\"addq%.l %#1,%2\", operands);
+#else
+ output_asm_insn (\"add%.l %#1,%2\", operands);
+#endif
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (operands[3]));
+ return \"\";
+}")
+
+(define_expand "addsi3"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (plus:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ ""
+ "")
+
+;; Note that the middle two alternatives are near-duplicates
+;; in order to handle insns generated by reload.
+;; This is needed since they are not themselves reloaded,
+;; so commutativity won't apply to them.
+(define_insn "*addsi3_internal"
+ [(set (match_operand:SI 0 "general_operand" "=m,?a,?a,r")
+ (plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0")
+ (match_operand:SI 2 "general_operand" "dIKLs,rJK,a,mrIKLs")))]
+ "! TARGET_5200"
+ "* return output_addsi3 (operands);")
+
+(define_insn "*addsi3_5200"
+ [(set (match_operand:SI 0 "general_operand" "=m,?a,?a,r")
+ (plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0")
+ (match_operand:SI 2 "general_operand" "d,rJK,a,mrIKLs")))]
+ "TARGET_5200"
+ "* return output_addsi3 (operands);")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=a")
+ (plus:SI (match_operand:SI 1 "general_operand" "0")
+ (sign_extend:SI
+ (match_operand:HI 2 "nonimmediate_operand" "rm"))))]
+ "!TARGET_5200"
+ "add%.w %2,%0")
+
+(define_insn "addhi3"
+ [(set (match_operand:HI 0 "general_operand" "=m,r")
+ (plus:HI (match_operand:HI 1 "general_operand" "%0,0")
+ (match_operand:HI 2 "general_operand" "dn,rmn")))]
+ "!TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+#ifndef NO_ADDSUB_Q
+ /* If the constant would be a negative number when interpreted as
+ HImode, make it negative. This is usually, but not always, done
+ elsewhere in the compiler. First check for constants out of range,
+ which could confuse us. */
+
+ if (INTVAL (operands[2]) >= 32768)
+ operands[2] = GEN_INT (INTVAL (operands[2]) - 65536);
+
+ if (INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) <= 8)
+ return \"addq%.w %2,%0\";
+ if (INTVAL (operands[2]) < 0
+ && INTVAL (operands[2]) >= -8)
+ {
+ operands[2] = GEN_INT (-INTVAL (operands[2]));
+ return \"subq%.w %2,%0\";
+ }
+ /* On the CPU32 it is faster to use two addqw instructions to
+ add a small integer (8 < N <= 16) to a register.
+ Likewise for subqw. */
+ if (TARGET_CPU32 && REG_P (operands[0]))
+ {
+ if (INTVAL (operands[2]) > 8
+ && INTVAL (operands[2]) <= 16)
+ {
+ operands[2] = GEN_INT (INTVAL (operands[2]) - 8);
+ return \"addq%.w %#8,%0\;addq%.w %2,%0\";
+ }
+ if (INTVAL (operands[2]) < -8
+ && INTVAL (operands[2]) >= -16)
+ {
+ operands[2] = GEN_INT (-INTVAL (operands[2]) - 8);
+ return \"subq%.w %#8,%0\;subq%.w %2,%0\";
+ }
+ }
+#endif
+ if (ADDRESS_REG_P (operands[0]) && !TARGET_68040)
+#ifdef MOTOROLA
+ return \"lea (%c2,%0),%0\";
+#else
+ return \"lea %0@(%c2),%0\";
+#endif
+ }
+ return \"add%.w %2,%0\";
+}")
+
+;; These insns must use MATCH_DUP instead of the more expected
+;; use of a matching constraint because the "output" here is also
+;; an input, so you can't use the matching constraint. That also means
+;; that you can't use the "%", so you need patterns with the matched
+;; operand in both positions.
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ (plus:HI (match_dup 0)
+ (match_operand:HI 1 "general_operand" "dn,rmn")))]
+ "!TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+#ifndef NO_ADDSUB_Q
+ /* If the constant would be a negative number when interpreted as
+ HImode, make it negative. This is usually, but not always, done
+ elsewhere in the compiler. First check for constants out of range,
+ which could confuse us. */
+
+ if (INTVAL (operands[1]) >= 32768)
+ operands[1] = GEN_INT (INTVAL (operands[1]) - 65536);
+
+ if (INTVAL (operands[1]) > 0
+ && INTVAL (operands[1]) <= 8)
+ return \"addq%.w %1,%0\";
+ if (INTVAL (operands[1]) < 0
+ && INTVAL (operands[1]) >= -8)
+ {
+ operands[1] = GEN_INT (-INTVAL (operands[1]));
+ return \"subq%.w %1,%0\";
+ }
+ /* On the CPU32 it is faster to use two addqw instructions to
+ add a small integer (8 < N <= 16) to a register.
+ Likewise for subqw. */
+ if (TARGET_CPU32 && REG_P (operands[0]))
+ {
+ if (INTVAL (operands[1]) > 8
+ && INTVAL (operands[1]) <= 16)
+ {
+ operands[1] = GEN_INT (INTVAL (operands[1]) - 8);
+ return \"addq%.w %#8,%0\;addq%.w %1,%0\";
+ }
+ if (INTVAL (operands[1]) < -8
+ && INTVAL (operands[1]) >= -16)
+ {
+ operands[1] = GEN_INT (-INTVAL (operands[1]) - 8);
+ return \"subq%.w %#8,%0\;subq%.w %1,%0\";
+ }
+ }
+#endif
+ if (ADDRESS_REG_P (operands[0]) && !TARGET_68040)
+#ifdef MOTOROLA
+ return \"lea (%c1,%0),%0\";
+#else
+ return \"lea %0@(%c1),%0\";
+#endif
+ }
+ return \"add%.w %1,%0\";
+}")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ (plus:HI (match_operand:HI 1 "general_operand" "dn,rmn")
+ (match_dup 0)))]
+ "!TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+#ifndef NO_ADDSUB_Q
+ /* If the constant would be a negative number when interpreted as
+ HImode, make it negative. This is usually, but not always, done
+ elsewhere in the compiler. First check for constants out of range,
+ which could confuse us. */
+
+ if (INTVAL (operands[1]) >= 32768)
+ operands[1] = GEN_INT (INTVAL (operands[1]) - 65536);
+
+ if (INTVAL (operands[1]) > 0
+ && INTVAL (operands[1]) <= 8)
+ return \"addq%.w %1,%0\";
+ if (INTVAL (operands[1]) < 0
+ && INTVAL (operands[1]) >= -8)
+ {
+ operands[1] = GEN_INT (-INTVAL (operands[1]));
+ return \"subq%.w %1,%0\";
+ }
+ /* On the CPU32 it is faster to use two addqw instructions to
+ add a small integer (8 < N <= 16) to a register.
+ Likewise for subqw. */
+ if (TARGET_CPU32 && REG_P (operands[0]))
+ {
+ if (INTVAL (operands[1]) > 8
+ && INTVAL (operands[1]) <= 16)
+ {
+ operands[1] = GEN_INT (INTVAL (operands[1]) - 8);
+ return \"addq%.w %#8,%0\;addq%.w %1,%0\";
+ }
+ if (INTVAL (operands[1]) < -8
+ && INTVAL (operands[1]) >= -16)
+ {
+ operands[1] = GEN_INT (-INTVAL (operands[1]) - 8);
+ return \"subq%.w %#8,%0\;subq%.w %1,%0\";
+ }
+ }
+#endif
+ if (ADDRESS_REG_P (operands[0]) && !TARGET_68040)
+#ifdef MOTOROLA
+ return \"lea (%c1,%0),%0\";
+#else
+ return \"lea %0@(%c1),%0\";
+#endif
+ }
+ return \"add%.w %1,%0\";
+}")
+
+(define_insn "addqi3"
+ [(set (match_operand:QI 0 "general_operand" "=m,d")
+ (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
+ (match_operand:QI 2 "general_operand" "dn,dmn")))]
+ "!TARGET_5200"
+ "*
+{
+#ifndef NO_ADDSUB_Q
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (INTVAL (operands[2]) >= 128)
+ operands[2] = GEN_INT (INTVAL (operands[2]) - 256);
+
+ if (INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) <= 8)
+ return \"addq%.b %2,%0\";
+ if (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) >= -8)
+ {
+ operands[2] = GEN_INT (-INTVAL (operands[2]));
+ return \"subq%.b %2,%0\";
+ }
+ }
+#endif
+ return \"add%.b %2,%0\";
+}")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ (plus:QI (match_dup 0)
+ (match_operand:QI 1 "general_operand" "dn,dmn")))]
+ "!TARGET_5200"
+ "*
+{
+#ifndef NO_ADDSUB_Q
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (INTVAL (operands[1]) >= 128)
+ operands[1] = GEN_INT (INTVAL (operands[1]) - 256);
+
+ if (INTVAL (operands[1]) > 0
+ && INTVAL (operands[1]) <= 8)
+ return \"addq%.b %1,%0\";
+ if (INTVAL (operands[1]) < 0 && INTVAL (operands[1]) >= -8)
+ {
+ operands[1] = GEN_INT (-INTVAL (operands[1]));
+ return \"subq%.b %1,%0\";
+ }
+ }
+#endif
+ return \"add%.b %1,%0\";
+}")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ (plus:QI (match_operand:QI 1 "general_operand" "dn,dmn")
+ (match_dup 0)))]
+ "!TARGET_5200"
+ "*
+{
+#ifndef NO_ADDSUB_Q
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (INTVAL (operands[1]) >= 128)
+ operands[1] = GEN_INT (INTVAL (operands[1]) - 256);
+
+ if (INTVAL (operands[1]) > 0
+ && INTVAL (operands[1]) <= 8)
+ return \"addq%.b %1,%0\";
+ if (INTVAL (operands[1]) < 0 && INTVAL (operands[1]) >= -8)
+ {
+ operands[1] = GEN_INT (-INTVAL (operands[1]));
+ return \"subq%.b %1,%0\";
+ }
+ }
+#endif
+ return \"add%.b %1,%0\";
+}")
+
+(define_expand "adddf3"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (plus:DF (match_operand:DF 1 "general_operand" "")
+ (match_operand:DF 2 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=x,y")
+ (plus:DF (match_operand:DF 1 "general_operand" "%xH,y")
+ (match_operand:DF 2 "general_operand" "xH,dmF")))]
+ "TARGET_FPA"
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"fpadd%.d %y2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"fpadd%.d %y1,%0\";
+ if (which_alternative == 0)
+ return \"fpadd3%.d %w2,%w1,%0\";
+ return \"fpadd3%.d %x2,%x1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (plus:DF (float:DF (match_operand:SI 2 "general_operand" "dmi"))
+ (match_operand:DF 1 "general_operand" "0")))]
+ "TARGET_68881"
+ "f%&add%.l %2,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (plus:DF (float:DF (match_operand:HI 2 "general_operand" "dmn"))
+ (match_operand:DF 1 "general_operand" "0")))]
+ "TARGET_68881"
+ "f%&add%.w %2,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (plus:DF (float:DF (match_operand:QI 2 "general_operand" "dmn"))
+ (match_operand:DF 1 "general_operand" "0")))]
+ "TARGET_68881"
+ "f%&add%.b %2,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (plus:DF (match_operand:DF 1 "general_operand" "%0")
+ (match_operand:DF 2 "general_operand" "fmG")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[2]))
+ return \"f%&add%.x %2,%0\";
+ return \"f%&add%.d %f2,%0\";
+}")
+
+(define_expand "addsf3"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (plus:SF (match_operand:SF 1 "general_operand" "")
+ (match_operand:SF 2 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=x,y")
+ (plus:SF (match_operand:SF 1 "general_operand" "%xH,y")
+ (match_operand:SF 2 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"fpadd%.s %w2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"fpadd%.s %w1,%0\";
+ if (which_alternative == 0)
+ return \"fpadd3%.s %w2,%w1,%0\";
+ return \"fpadd3%.s %2,%1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (plus:SF (float:SF (match_operand:SI 2 "general_operand" "dmi"))
+ (match_operand:SF 1 "general_operand" "0")))]
+ "TARGET_68881"
+ "f%$add%.l %2,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (plus:SF (float:SF (match_operand:HI 2 "general_operand" "dmn"))
+ (match_operand:SF 1 "general_operand" "0")))]
+ "TARGET_68881"
+ "f%$add%.w %2,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (plus:SF (float:SF (match_operand:QI 2 "general_operand" "dmn"))
+ (match_operand:SF 1 "general_operand" "0")))]
+ "TARGET_68881"
+ "f%$add%.b %2,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (plus:SF (match_operand:SF 1 "general_operand" "%0")
+ (match_operand:SF 2 "general_operand" "fdmF")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
+ return \"f%$add%.x %2,%0\";
+ return \"f%$add%.s %f2,%0\";
+}")
+
+;; subtract instructions
+
+(define_insn "subdi_sexthishl32"
+ [(set (match_operand:DI 0 "general_operand" "=o,a,*d,*d")
+ (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
+ (ashift:DI (sign_extend:DI (match_operand:HI 2 "general_operand" "rm,rm,rm,rm"))
+ (const_int 32))))
+ (clobber (match_scratch:SI 3 "=&d,X,a,?d"))]
+ "!TARGET_5200"
+ "*
+{
+ CC_STATUS_INIT;
+ if (ADDRESS_REG_P (operands[0]))
+ return \"sub%.w %2,%0\";
+ else if (ADDRESS_REG_P (operands[3]))
+ return \"move%.w %2,%3\;sub%.l %3,%0\";
+ else
+ return \"move%.w %2,%3\;ext%.l %3\;sub%.l %3,%0\";
+} ")
+
+(define_insn "subdi_dishl32"
+ [(set (match_operand:DI 0 "general_operand" "+ro")
+ (minus:DI (match_dup 0)
+ (ashift:DI (match_operand:DI 1 "general_operand" "ro")
+ (const_int 32))))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (GET_CODE (operands[1]) == REG)
+ operands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+ else
+ operands[1] = adj_offsettable_operand (operands[1], 4);
+ return \"sub%.l %1,%0\";
+} ")
+
+(define_insn "subdi3"
+ [(set (match_operand:DI 0 "general_operand" "=<,o<>,d,d,d")
+ (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0,0")
+ (match_operand:DI 2 "general_operand" "<,d,no>,d,a")))
+ (clobber (match_scratch:SI 3 "=X,&d,&d,X,&d"))]
+ ""
+ "*
+{
+ if (DATA_REG_P (operands[0]))
+ {
+ if (DATA_REG_P (operands[2]))
+ return \"sub%.l %R2,%R0\;subx%.l %2,%0\";
+ else if (GET_CODE (operands[2]) == MEM
+ && GET_CODE (XEXP (operands[2], 0)) == POST_INC)
+ {
+ return \"move%.l %2,%3\;sub%.l %2,%R0\;subx%.l %3,%0\";
+ }
+ else
+ {
+ rtx xoperands[2];
+ if (GET_CODE (operands[2]) == REG)
+ operands[1] = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
+ else if (GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+ operands[2] = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
+ }
+ else if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ operands[1] = operands[2];
+ operands[2] = INTVAL (operands[2]) < 0 ? constm1_rtx : const0_rtx;
+ }
+ else
+ operands[1] = adj_offsettable_operand (operands[2], 4);
+ xoperands[0] = operands[3];
+ if (GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) >= -8 && INTVAL (operands[1]) < 0)
+ xoperands[1] = GEN_INT (-INTVAL (operands[2]) - 1);
+ else
+ xoperands[1] = operands[2];
+ output_asm_insn (output_move_simode (xoperands), xoperands);
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (INTVAL (operands[1]) > 0 && INTVAL (operands[1]) <= 8)
+ {
+#ifdef NO_ADDSUB_Q
+ return \"sub%.l %1,%R0\;subx%.l %3,%0\";
+#else
+ return \"subq%.l %1,%R0\;subx%.l %3,%0\";
+#endif
+ }
+ else if (INTVAL (operands[1]) >= -8 && INTVAL (operands[1]) < 0)
+ {
+ operands[1] = GEN_INT (-INTVAL (operands[1]));
+#ifdef NO_ADDSUB_Q
+ return \"add%.l %1,%R0\;addx%.l %3,%0\";
+#else
+ return \"addq%.l %1,%R0\;addx%.l %3,%0\";
+#endif
+ }
+ }
+ return \"sub%.l %1,%R0\;subx%.l %3,%0\";
+ }
+ }
+ else if (GET_CODE (operands[0]) == MEM)
+ {
+ if (GET_CODE (operands[2]) == MEM
+ && GET_CODE (XEXP (operands[2], 0)) == PRE_DEC)
+ return \"sub%.l %2,%0\;subx%.l %2,%0\";
+ CC_STATUS_INIT;
+ if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ {
+ operands[1]
+ = gen_rtx_MEM (SImode,
+ gen_rtx_PLUS (VOIDmode, XEXP(operands[0], 0),
+ GEN_INT (-8)));
+ return \"move%.l %0,%3\;sub%.l %R2,%0\;subx%.l %2,%3\;move%.l %3,%1\";
+ }
+ else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ {
+ operands[1] = XEXP(operands[0], 0);
+ return \"sub%.l %R2,%0\;move%.l %0,%3\;subx%.l %2,%3\;move%.l %3,%1\";
+ }
+ else
+ {
+ operands[1] = adj_offsettable_operand (operands[0], 4);
+ return \"sub%.l %R2,%1\;move%.l %0,%3\;subx%.l %2,%3\;move%.l %3,%0\";
+ }
+ }
+ else
+ abort ();
+} ")
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "general_operand" "=m,r")
+ (minus:SI (match_operand:SI 1 "general_operand" "0,0")
+ (match_operand:SI 2 "general_operand" "ds,mrs")))]
+ ""
+ "sub%.l %2,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=a")
+ (minus:SI (match_operand:SI 1 "general_operand" "0")
+ (sign_extend:SI
+ (match_operand:HI 2 "nonimmediate_operand" "rm"))))]
+ "!TARGET_5200"
+ "sub%.w %2,%0")
+
+(define_insn "subhi3"
+ [(set (match_operand:HI 0 "general_operand" "=m,r")
+ (minus:HI (match_operand:HI 1 "general_operand" "0,0")
+ (match_operand:HI 2 "general_operand" "dn,rmn")))]
+ "!TARGET_5200"
+ "sub%.w %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ (minus:HI (match_dup 0)
+ (match_operand:HI 1 "general_operand" "dn,rmn")))]
+ "!TARGET_5200"
+ "sub%.w %1,%0")
+
+(define_insn "subqi3"
+ [(set (match_operand:QI 0 "general_operand" "=m,d")
+ (minus:QI (match_operand:QI 1 "general_operand" "0,0")
+ (match_operand:QI 2 "general_operand" "dn,dmn")))]
+ "!TARGET_5200"
+ "sub%.b %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ (minus:QI (match_dup 0)
+ (match_operand:QI 1 "general_operand" "dn,dmn")))]
+ "!TARGET_5200"
+ "sub%.b %1,%0")
+
+(define_expand "subdf3"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (minus:DF (match_operand:DF 1 "general_operand" "")
+ (match_operand:DF 2 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=x,y,y")
+ (minus:DF (match_operand:DF 1 "general_operand" "xH,y,dmF")
+ (match_operand:DF 2 "general_operand" "xH,dmF,0")))]
+ "TARGET_FPA"
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"fprsub%.d %y1,%0\";
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"fpsub%.d %y2,%0\";
+ if (which_alternative == 0)
+ return \"fpsub3%.d %w2,%w1,%0\";
+ return \"fpsub3%.d %x2,%x1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (minus:DF (match_operand:DF 1 "general_operand" "0")
+ (float:DF (match_operand:SI 2 "general_operand" "dmi"))))]
+ "TARGET_68881"
+ "f%&sub%.l %2,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (minus:DF (match_operand:DF 1 "general_operand" "0")
+ (float:DF (match_operand:HI 2 "general_operand" "dmn"))))]
+ "TARGET_68881"
+ "f%&sub%.w %2,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (minus:DF (match_operand:DF 1 "general_operand" "0")
+ (float:DF (match_operand:QI 2 "general_operand" "dmn"))))]
+ "TARGET_68881"
+ "f%&sub%.b %2,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (minus:DF (match_operand:DF 1 "general_operand" "0")
+ (match_operand:DF 2 "general_operand" "fmG")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[2]))
+ return \"f%&sub%.x %2,%0\";
+ return \"f%&sub%.d %f2,%0\";
+}")
+
+(define_expand "subsf3"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (minus:SF (match_operand:SF 1 "general_operand" "")
+ (match_operand:SF 2 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=x,y,y")
+ (minus:SF (match_operand:SF 1 "general_operand" "xH,y,rmF")
+ (match_operand:SF 2 "general_operand" "xH,rmF,0")))]
+ "TARGET_FPA"
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"fprsub%.s %w1,%0\";
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"fpsub%.s %w2,%0\";
+ if (which_alternative == 0)
+ return \"fpsub3%.s %w2,%w1,%0\";
+ return \"fpsub3%.s %2,%1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (minus:SF (match_operand:SF 1 "general_operand" "0")
+ (float:SF (match_operand:SI 2 "general_operand" "dmi"))))]
+ "TARGET_68881"
+ "f%$sub%.l %2,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (minus:SF (match_operand:SF 1 "general_operand" "0")
+ (float:SF (match_operand:HI 2 "general_operand" "dmn"))))]
+ "TARGET_68881"
+ "f%$sub%.w %2,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (minus:SF (match_operand:SF 1 "general_operand" "0")
+ (float:SF (match_operand:QI 2 "general_operand" "dmn"))))]
+ "TARGET_68881"
+ "f%$sub%.b %2,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (minus:SF (match_operand:SF 1 "general_operand" "0")
+ (match_operand:SF 2 "general_operand" "fdmF")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
+ return \"f%$sub%.x %2,%0\";
+ return \"f%$sub%.s %f2,%0\";
+}")
+
+;; multiply instructions
+
+(define_insn "mulhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (mult:HI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "*
+{
+#if defined(MOTOROLA) && !defined(CRDS)
+ return \"muls%.w %2,%0\";
+#else
+ return \"muls %2,%0\";
+#endif
+}")
+
+(define_insn "mulhisi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (mult:SI (sign_extend:SI
+ (match_operand:HI 1 "nonimmediate_operand" "%0"))
+ (sign_extend:SI
+ (match_operand:HI 2 "nonimmediate_operand" "dm"))))]
+ ""
+ "*
+{
+#if defined(MOTOROLA) && !defined(CRDS)
+ return \"muls%.w %2,%0\";
+#else
+ return \"muls %2,%0\";
+#endif
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (mult:SI (sign_extend:SI
+ (match_operand:HI 1 "nonimmediate_operand" "%0"))
+ (match_operand:SI 2 "const_int_operand" "n")))]
+ "INTVAL (operands[2]) >= -0x8000 && INTVAL (operands[2]) <= 0x7fff"
+ "*
+{
+#if defined(MOTOROLA) && !defined(CRDS)
+ return \"muls%.w %2,%0\";
+#else
+ return \"muls %2,%0\";
+#endif
+}")
+
+(define_expand "mulsi3"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (mult:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ "TARGET_68020 || TARGET_5200"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (mult:SI (match_operand:SI 1 "general_operand" "%0")
+ (match_operand:SI 2 "general_operand" "dmsK")))]
+ "TARGET_68020"
+ "muls%.l %2,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (mult:SI (match_operand:SI 1 "general_operand" "%0")
+ (match_operand:SI 2 "general_operand" "d<Q>")))]
+ "TARGET_5200"
+ "muls%.l %2,%0")
+
+(define_insn "umulhisi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (mult:SI (zero_extend:SI
+ (match_operand:HI 1 "nonimmediate_operand" "%0"))
+ (zero_extend:SI
+ (match_operand:HI 2 "nonimmediate_operand" "dm"))))]
+ ""
+ "*
+{
+#if defined(MOTOROLA) && !defined(CRDS)
+ return \"mulu%.w %2,%0\";
+#else
+ return \"mulu %2,%0\";
+#endif
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (mult:SI (zero_extend:SI
+ (match_operand:HI 1 "nonimmediate_operand" "%0"))
+ (match_operand:SI 2 "const_int_operand" "n")))]
+ "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 0xffff"
+ "*
+{
+#if defined(MOTOROLA) && !defined(CRDS)
+ return \"mulu%.w %2,%0\";
+#else
+ return \"mulu %2,%0\";
+#endif
+}")
+
+;; We need a separate DEFINE_EXPAND for u?mulsidi3 to be able to use the
+;; proper matching constraint. This is because the matching is between
+;; the high-numbered word of the DImode operand[0] and operand[1].
+(define_expand "umulsidi3"
+ [(parallel
+ [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 1)
+ (mult:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonimmediate_operand" "")))
+ (set (subreg:SI (match_dup 0) 0)
+ (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
+ (zero_extend:DI (match_dup 2)))
+ (const_int 32))))])]
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (mult:SI (match_operand:SI 1 "register_operand" "%0")
+ (match_operand:SI 2 "nonimmediate_operand" "dm")))
+ (set (match_operand:SI 3 "register_operand" "=d")
+ (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
+ (zero_extend:DI (match_dup 2)))
+ (const_int 32))))]
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
+ "mulu%.l %2,%3:%0")
+
+; Match immediate case. For 2.4 only match things < 2^31.
+; It's tricky with larger values in these patterns since we need to match
+; values between the two parallel multiplies, between a CONST_DOUBLE and
+; a CONST_INT.
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (mult:SI (match_operand:SI 1 "register_operand" "%0")
+ (match_operand:SI 2 "const_int_operand" "n")))
+ (set (match_operand:SI 3 "register_operand" "=d")
+ (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
+ (match_dup 2))
+ (const_int 32))))]
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200
+ && (unsigned) INTVAL (operands[2]) <= 0x7fffffff"
+ "mulu%.l %2,%3:%0")
+
+(define_expand "mulsidi3"
+ [(parallel
+ [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 1)
+ (mult:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonimmediate_operand" "")))
+ (set (subreg:SI (match_dup 0) 0)
+ (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
+ (sign_extend:DI (match_dup 2)))
+ (const_int 32))))])]
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (mult:SI (match_operand:SI 1 "register_operand" "%0")
+ (match_operand:SI 2 "nonimmediate_operand" "dm")))
+ (set (match_operand:SI 3 "register_operand" "=d")
+ (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
+ (sign_extend:DI (match_dup 2)))
+ (const_int 32))))]
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
+ "muls%.l %2,%3:%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (mult:SI (match_operand:SI 1 "register_operand" "%0")
+ (match_operand:SI 2 "const_sint32_operand" "")))
+ (set (match_operand:SI 3 "register_operand" "=d")
+ (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
+ (match_dup 2))
+ (const_int 32))))]
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
+ "muls%.l %2,%3:%0")
+
+(define_expand "umulsi3_highpart"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
+ (zero_extend:DI (match_operand:SI 2 "general_operand" "")))
+ (const_int 32))))
+ (clobber (match_dup 3))])]
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
+ "
+{
+ operands[3] = gen_reg_rtx (SImode);
+ if (GET_CODE (operands[2]) == CONST_INT
+ || GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ if (! const_uint32_operand (operands[2], VOIDmode))
+ abort ();
+ /* We have to adjust the operand order for the matching constraints. */
+ emit_insn (gen_const_umulsi3_highpart (operands[0], operands[3],
+ operands[1], operands[2]));
+ DONE;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI (zero_extend:DI (match_operand:SI 2 "register_operand" "%1"))
+ (zero_extend:DI (match_operand:SI 3 "nonimmediate_operand" "dm")))
+ (const_int 32))))
+ (clobber (match_operand:SI 1 "register_operand" "=d"))]
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
+ "mulu%.l %3,%0:%1")
+
+(define_insn "const_umulsi3_highpart"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI (zero_extend:DI (match_operand:SI 2 "register_operand" "1"))
+ (match_operand 3 "const_uint32_operand" ""))
+ (const_int 32))))
+ (clobber (match_operand:SI 1 "register_operand" "=d"))]
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
+ "mulu%.l %3,%0:%1")
+
+(define_expand "smulsi3_highpart"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
+ (sign_extend:DI (match_operand:SI 2 "general_operand" "")))
+ (const_int 32))))
+ (clobber (match_dup 3))])]
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
+ "
+{
+ operands[3] = gen_reg_rtx (SImode);
+ if (GET_CODE (operands[2]) == CONST_INT
+ || GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ if (! const_sint32_operand (operands[2], VOIDmode))
+ abort ();
+ /* We have to adjust the operand order for the matching constraints. */
+ emit_insn (gen_const_smulsi3_highpart (operands[0], operands[3],
+ operands[1], operands[2]));
+ DONE;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI (sign_extend:DI (match_operand:SI 2 "register_operand" "%1"))
+ (sign_extend:DI (match_operand:SI 3 "nonimmediate_operand" "dm")))
+ (const_int 32))))
+ (clobber (match_operand:SI 1 "register_operand" "=d"))]
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
+ "muls%.l %3,%0:%1")
+
+(define_insn "const_smulsi3_highpart"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI (sign_extend:DI (match_operand:SI 2 "register_operand" "1"))
+ (match_operand 3 "const_sint32_operand" ""))
+ (const_int 32))))
+ (clobber (match_operand:SI 1 "register_operand" "=d"))]
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
+ "muls%.l %3,%0:%1")
+
+(define_expand "muldf3"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (mult:DF (match_operand:DF 1 "general_operand" "")
+ (match_operand:DF 2 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=x,y")
+ (mult:DF (match_operand:DF 1 "general_operand" "%xH,y")
+ (match_operand:DF 2 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "*
+{
+ if (rtx_equal_p (operands[1], operands[2]))
+ return \"fpsqr%.d %y1,%0\";
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"fpmul%.d %y2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"fpmul%.d %y1,%0\";
+ if (which_alternative == 0)
+ return \"fpmul3%.d %w2,%w1,%0\";
+ return \"fpmul3%.d %x2,%x1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (mult:DF (float:DF (match_operand:SI 2 "general_operand" "dmi"))
+ (match_operand:DF 1 "general_operand" "0")))]
+ "TARGET_68881"
+ "f%&mul%.l %2,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (mult:DF (float:DF (match_operand:HI 2 "general_operand" "dmn"))
+ (match_operand:DF 1 "general_operand" "0")))]
+ "TARGET_68881"
+ "f%&mul%.w %2,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (mult:DF (float:DF (match_operand:QI 2 "general_operand" "dmn"))
+ (match_operand:DF 1 "general_operand" "0")))]
+ "TARGET_68881"
+ "f%&mul%.b %2,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (mult:DF (match_operand:DF 1 "general_operand" "%0")
+ (match_operand:DF 2 "general_operand" "fmG")))]
+ "TARGET_68881"
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_DOUBLE
+ && floating_exact_log2 (operands[2]) && !TARGET_68040 && !TARGET_68060)
+ {
+ int i = floating_exact_log2 (operands[2]);
+ operands[2] = GEN_INT (i);
+ return \"fscale%.l %2,%0\";
+ }
+ if (REG_P (operands[2]))
+ return \"f%&mul%.x %2,%0\";
+ return \"f%&mul%.d %f2,%0\";
+}")
+
+(define_expand "mulsf3"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (mult:SF (match_operand:SF 1 "general_operand" "")
+ (match_operand:SF 2 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=x,y")
+ (mult:SF (match_operand:SF 1 "general_operand" "%xH,y")
+ (match_operand:SF 2 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "*
+{
+ if (rtx_equal_p (operands[1], operands[2]))
+ return \"fpsqr%.s %w1,%0\";
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"fpmul%.s %w2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"fpmul%.s %w1,%0\";
+ if (which_alternative == 0)
+ return \"fpmul3%.s %w2,%w1,%0\";
+ return \"fpmul3%.s %2,%1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (mult:SF (float:SF (match_operand:SI 2 "general_operand" "dmi"))
+ (match_operand:SF 1 "general_operand" "0")))]
+ "TARGET_68881"
+ "*
+{
+ return (TARGET_68040_ONLY
+ ? \"fsmul%.l %2,%0\"
+ : \"fsglmul%.l %2,%0\");
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (mult:SF (float:SF (match_operand:HI 2 "general_operand" "dmn"))
+ (match_operand:SF 1 "general_operand" "0")))]
+ "TARGET_68881"
+ "*
+{
+ return (TARGET_68040_ONLY
+ ? \"fsmul%.w %2,%0\"
+ : \"fsglmul%.w %2,%0\");
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (mult:SF (float:SF (match_operand:QI 2 "general_operand" "dmn"))
+ (match_operand:SF 1 "general_operand" "0")))]
+ "TARGET_68881"
+ "*
+{
+ return (TARGET_68040_ONLY
+ ? \"fsmul%.b %2,%0\"
+ : \"fsglmul%.b %2,%0\");
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (mult:SF (match_operand:SF 1 "general_operand" "%0")
+ (match_operand:SF 2 "general_operand" "fdmF")))]
+ "TARGET_68881"
+ "*
+{
+#ifdef FSGLMUL_USE_S
+ if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
+ return (TARGET_68040_ONLY
+ ? \"fsmul%.s %2,%0\"
+ : \"fsglmul%.s %2,%0\");
+#else
+ if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
+ return (TARGET_68040_ONLY
+ ? \"fsmul%.x %2,%0\"
+ : \"fsglmul%.x %2,%0\");
+#endif
+ return (TARGET_68040_ONLY
+ ? \"fsmul%.s %f2,%0\"
+ : \"fsglmul%.s %f2,%0\");
+}")
+
+;; divide instructions
+
+(define_expand "divdf3"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (div:DF (match_operand:DF 1 "general_operand" "")
+ (match_operand:DF 2 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=x,y,y")
+ (div:DF (match_operand:DF 1 "general_operand" "xH,y,rmF")
+ (match_operand:DF 2 "general_operand" "xH,rmF,0")))]
+ "TARGET_FPA"
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"fprdiv%.d %y1,%0\";
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"fpdiv%.d %y2,%0\";
+ if (which_alternative == 0)
+ return \"fpdiv3%.d %w2,%w1,%0\";
+ return \"fpdiv3%.d %x2,%x1,%x0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (div:DF (match_operand:DF 1 "general_operand" "0")
+ (float:DF (match_operand:SI 2 "general_operand" "dmi"))))]
+ "TARGET_68881"
+ "f%&div%.l %2,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (div:DF (match_operand:DF 1 "general_operand" "0")
+ (float:DF (match_operand:HI 2 "general_operand" "dmn"))))]
+ "TARGET_68881"
+ "f%&div%.w %2,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (div:DF (match_operand:DF 1 "general_operand" "0")
+ (float:DF (match_operand:QI 2 "general_operand" "dmn"))))]
+ "TARGET_68881"
+ "f%&div%.b %2,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (div:DF (match_operand:DF 1 "general_operand" "0")
+ (match_operand:DF 2 "general_operand" "fmG")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[2]))
+ return \"f%&div%.x %2,%0\";
+ return \"f%&div%.d %f2,%0\";
+}")
+
+(define_expand "divsf3"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (div:SF (match_operand:SF 1 "general_operand" "")
+ (match_operand:SF 2 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=x,y,y")
+ (div:SF (match_operand:SF 1 "general_operand" "xH,y,rmF")
+ (match_operand:SF 2 "general_operand" "xH,rmF,0")))]
+ "TARGET_FPA"
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"fpdiv%.s %w2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"fprdiv%.s %w1,%0\";
+ if (which_alternative == 0)
+ return \"fpdiv3%.s %w2,%w1,%0\";
+ return \"fpdiv3%.s %2,%1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (div:SF (match_operand:SF 1 "general_operand" "0")
+ (float:SF (match_operand:SI 2 "general_operand" "dmi"))))]
+ "TARGET_68881"
+ "*
+{
+ return (TARGET_68040_ONLY
+ ? \"fsdiv%.l %2,%0\"
+ : \"fsgldiv%.l %2,%0\");
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (div:SF (match_operand:SF 1 "general_operand" "0")
+ (float:SF (match_operand:HI 2 "general_operand" "dmn"))))]
+ "TARGET_68881"
+ "*
+{
+ return (TARGET_68040_ONLY
+ ? \"fsdiv%.w %2,%0\"
+ : \"fsgldiv%.w %2,%0\");
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (div:SF (match_operand:SF 1 "general_operand" "0")
+ (float:SF (match_operand:QI 2 "general_operand" "dmn"))))]
+ "TARGET_68881"
+ "*
+{
+ return (TARGET_68040_ONLY
+ ? \"fsdiv%.b %2,%0\"
+ : \"fsgldiv%.b %2,%0\");
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (div:SF (match_operand:SF 1 "general_operand" "0")
+ (match_operand:SF 2 "general_operand" "fdmF")))]
+ "TARGET_68881"
+ "*
+{
+#ifdef FSGLDIV_USE_S
+ if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
+ return (TARGET_68040_ONLY
+ ? \"fsdiv%.s %2,%0\"
+ : \"fsgldiv%.s %2,%0\");
+#else
+ if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
+ return (TARGET_68040_ONLY
+ ? \"fsdiv%.x %2,%0\"
+ : \"fsgldiv%.x %2,%0\");
+#endif
+ return (TARGET_68040_ONLY
+ ? \"fsdiv%.s %f2,%0\"
+ : \"fsgldiv%.s %f2,%0\");
+}")
+
+;; Remainder instructions.
+
+(define_insn "divmodsi4"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (div:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dmsK")))
+ (set (match_operand:SI 3 "general_operand" "=d")
+ (mod:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_68020 && !TARGET_5200"
+ "*
+{
+ if (find_reg_note (insn, REG_UNUSED, operands[3]))
+ return \"divs%.l %2,%0\";
+ else
+ return \"divsl%.l %2,%3:%0\";
+}")
+
+(define_insn "udivmodsi4"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (udiv:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dmsK")))
+ (set (match_operand:SI 3 "general_operand" "=d")
+ (umod:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_68020 && !TARGET_5200"
+ "*
+{
+ if (find_reg_note (insn, REG_UNUSED, operands[3]))
+ return \"divu%.l %2,%0\";
+ else
+ return \"divul%.l %2,%3:%0\";
+}")
+
+(define_insn "divmodhi4"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (div:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmsK")))
+ (set (match_operand:HI 3 "general_operand" "=d")
+ (mod:HI (match_dup 1) (match_dup 2)))]
+ "!TARGET_5200"
+ "*
+{
+#ifdef MOTOROLA
+ output_asm_insn (\"ext%.l %0\;divs%.w %2,%0\", operands);
+#else
+ output_asm_insn (\"extl %0\;divs %2,%0\", operands);
+#endif
+ if (!find_reg_note(insn, REG_UNUSED, operands[3]))
+ {
+ CC_STATUS_INIT;
+ return \"move%.l %0,%3\;swap %3\";
+ }
+ else
+ return \"\";
+}")
+
+(define_insn "udivmodhi4"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (udiv:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmsK")))
+ (set (match_operand:HI 3 "general_operand" "=d")
+ (umod:HI (match_dup 1) (match_dup 2)))]
+ "!TARGET_5200"
+ "*
+{
+#ifdef MOTOROLA
+ output_asm_insn (\"and%.l %#0xFFFF,%0\;divu%.w %2,%0\", operands);
+#else
+ output_asm_insn (\"and%.l %#0xFFFF,%0\;divu %2,%0\", operands);
+#endif
+ if (!find_reg_note(insn, REG_UNUSED, operands[3]))
+ {
+ CC_STATUS_INIT;
+ return \"move%.l %0,%3\;swap %3\";
+ }
+ else
+ return \"\";
+}")
+
+;; logical-and instructions
+
+;; "anddi3" is mainly here to help combine().
+(define_insn "anddi3"
+ [(set (match_operand:DI 0 "general_operand" "=o,d")
+ (and:DI (match_operand:DI 1 "general_operand" "%0,0")
+ (match_operand:DI 2 "general_operand" "dn,don")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ /* We can get CONST_DOUBLE, but also const1_rtx etc. */
+ if (GET_CODE (operands[2]) == CONST_DOUBLE
+ || GET_CODE (operands[2]) == CONST_INT)
+ {
+ rtx hi, lo;
+
+ if (GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ hi = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
+ lo = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+ }
+ else
+ {
+ lo = operands[2];
+ hi = INTVAL (lo) < 0 ? constm1_rtx : const0_rtx;
+ }
+ switch (INTVAL (hi))
+ {
+ case 0 :
+ output_asm_insn (\"clr%.l %0\", operands);
+ break;
+ case -1 :
+ break;
+ default :
+ {
+ rtx xoperands[3];
+
+ xoperands[0] = operands[0];
+ xoperands[2] = hi;
+ output_asm_insn (output_andsi3 (xoperands), xoperands);
+ }
+ }
+ if (GET_CODE (operands[0]) == REG)
+ operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ else
+ operands[0] = adj_offsettable_operand (operands[0], 4);
+ switch (INTVAL (lo))
+ {
+ case 0 :
+ output_asm_insn (\"clr%.l %0\", operands);
+ break;
+ case -1 :
+ break;
+ default :
+ {
+ rtx xoperands[3];
+
+ xoperands[0] = operands[0];
+ xoperands[2] = lo;
+ output_asm_insn (output_andsi3 (xoperands), xoperands);
+ }
+ }
+ return \"\";
+ }
+ if (GET_CODE (operands[0]) != REG)
+ {
+ operands[1] = adj_offsettable_operand (operands[0], 4);
+ return \"and%.l %2,%0\;and%.l %R2,%1\";
+ }
+ if (GET_CODE (operands[2]) != REG)
+ {
+ operands[1] = adj_offsettable_operand (operands[2], 4);
+ return \"and%.l %2,%0\;and%.l %1,%R0\";
+ }
+ return \"and%.l %2,%0\;and%.l %R2,%R0\";
+}")
+
+;; Prevent AND from being made with sp. This doesn't exist in the machine
+;; and reload will cause inefficient code. Since sp is a FIXED_REG, we
+;; can't allocate pseudos into it.
+
+(define_expand "andsi3"
+ [(set (match_operand:SI 0 "not_sp_operand" "=m,d")
+ (and:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
+ ""
+ "")
+
+(define_insn "andsi3_internal"
+ [(set (match_operand:SI 0 "not_sp_operand" "=m,d")
+ (and:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
+ "!TARGET_5200"
+ "*
+{
+ return output_andsi3 (operands);
+}")
+
+(define_insn "andsi3_5200"
+ [(set (match_operand:SI 0 "not_sp_operand" "=m,d")
+ (and:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,dmsK")))]
+ "TARGET_5200"
+ "and%.l %2,%0")
+
+(define_insn "andhi3"
+ [(set (match_operand:HI 0 "general_operand" "=m,d")
+ (and:HI (match_operand:HI 1 "general_operand" "%0,0")
+ (match_operand:HI 2 "general_operand" "dn,dmn")))]
+ "!TARGET_5200"
+ "and%.w %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ (and:HI (match_dup 0)
+ (match_operand:HI 1 "general_operand" "dn,dmn")))]
+ "!TARGET_5200"
+ "and%.w %1,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ (and:HI (match_operand:HI 1 "general_operand" "dn,dmn")
+ (match_dup 0)))]
+ "!TARGET_5200"
+ "and%.w %1,%0")
+
+(define_insn "andqi3"
+ [(set (match_operand:QI 0 "general_operand" "=m,d")
+ (and:QI (match_operand:QI 1 "general_operand" "%0,0")
+ (match_operand:QI 2 "general_operand" "dn,dmn")))]
+ "!TARGET_5200"
+ "and%.b %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ (and:QI (match_dup 0)
+ (match_operand:QI 1 "general_operand" "dn,dmn")))]
+ "!TARGET_5200"
+ "and%.b %1,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ (and:QI (match_operand:QI 1 "general_operand" "dn,dmn")
+ (match_dup 0)))]
+ "!TARGET_5200"
+ "and%.b %1,%0")
+
+;; inclusive-or instructions
+
+(define_insn "iordi_zext"
+ [(set (match_operand:DI 0 "general_operand" "=o,d")
+ (ior:DI (zero_extend:DI (match_operand 1 "general_operand" "dn,dmn"))
+ (match_operand:DI 2 "general_operand" "0,0")))]
+ "!TARGET_5200"
+ "*
+{
+ int byte_mode;
+
+ CC_STATUS_INIT;
+ if (GET_CODE (operands[0]) == REG)
+ operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ else
+ operands[0] = adj_offsettable_operand (operands[0], 4);
+ if (GET_MODE (operands[1]) == SImode)
+ return \"or%.l %1,%0\";
+ byte_mode = (GET_MODE (operands[1]) == QImode);
+ if (GET_CODE (operands[0]) == MEM)
+ operands[0] = adj_offsettable_operand (operands[0], byte_mode ? 3 : 2);
+ if (byte_mode)
+ return \"or%.b %1,%0\";
+ else
+ return \"or%.w %1,%0\";
+}")
+
+;; "iordi3" is mainly here to help combine().
+(define_insn "iordi3"
+ [(set (match_operand:DI 0 "general_operand" "=o,d")
+ (ior:DI (match_operand:DI 1 "general_operand" "%0,0")
+ (match_operand:DI 2 "general_operand" "dn,don")))]
+ "!TARGET_5200"
+ "*
+{
+ CC_STATUS_INIT;
+ /* We can get CONST_DOUBLE, but also const1_rtx etc. */
+ if (GET_CODE (operands[2]) == CONST_DOUBLE
+ || GET_CODE (operands[2]) == CONST_INT)
+ {
+ rtx hi, lo;
+
+ if (GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ hi = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
+ lo = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+ }
+ else
+ {
+ lo = operands[2];
+ hi = INTVAL (lo) < 0 ? constm1_rtx : const0_rtx;
+ }
+ switch (INTVAL (hi))
+ {
+ case 0 :
+ break;
+ case -1 :
+ /* FIXME : a scratch register would be welcome here if operand[0]
+ is not a register */
+ output_asm_insn (\"move%.l %#-1,%0\", operands);
+ break;
+ default :
+ {
+ rtx xoperands[3];
+
+ xoperands[0] = operands[0];
+ xoperands[2] = hi;
+ output_asm_insn (output_iorsi3 (xoperands), xoperands);
+ }
+ }
+ if (GET_CODE (operands[0]) == REG)
+ operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ else
+ operands[0] = adj_offsettable_operand (operands[0], 4);
+ switch (INTVAL (lo))
+ {
+ case 0 :
+ break;
+ case -1 :
+ /* FIXME : a scratch register would be welcome here if operand[0]
+ is not a register */
+ output_asm_insn (\"move%.l %#-1,%R0\", operands);
+ break;
+ default :
+ {
+ rtx xoperands[3];
+
+ xoperands[0] = operands[0];
+ xoperands[2] = lo;
+ output_asm_insn (output_iorsi3 (xoperands), xoperands);
+ }
+ }
+ return \"\";
+ }
+ if (GET_CODE (operands[0]) != REG)
+ {
+ operands[1] = adj_offsettable_operand (operands[0], 4);
+ return \"or%.l %2,%0\;or%.l %R2,%1\";
+ }
+ if (GET_CODE (operands[2]) != REG)
+ {
+ operands[1] = adj_offsettable_operand (operands[2], 4);
+ return \"or%.l %2,%0\;or%.l %1,%R0\";
+ }
+ return \"or%.l %2,%0\;or%.l %R2,%R0\";
+}")
+
+(define_expand "iorsi3"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (ior:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ ""
+ "")
+
+(define_insn "iorsi3_internal"
+ [(set (match_operand:SI 0 "general_operand" "=m,d")
+ (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
+ "! TARGET_5200"
+ "*
+{
+ return output_iorsi3 (operands);
+}")
+
+(define_insn "iorsi3_5200"
+ [(set (match_operand:SI 0 "general_operand" "=m,d")
+ (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,dmsK")))]
+ "TARGET_5200"
+ "or%.l %2,%0")
+
+(define_insn "iorhi3"
+ [(set (match_operand:HI 0 "general_operand" "=m,d")
+ (ior:HI (match_operand:HI 1 "general_operand" "%0,0")
+ (match_operand:HI 2 "general_operand" "dn,dmn")))]
+ "!TARGET_5200"
+ "or%.w %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ (ior:HI (match_dup 0)
+ (match_operand:HI 1 "general_operand" "dn,dmn")))]
+ "!TARGET_5200"
+ "or%.w %1,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ (ior:HI (match_operand:HI 1 "general_operand" "dn,dmn")
+ (match_dup 0)))]
+ "!TARGET_5200"
+ "or%.w %1,%0")
+
+(define_insn "iorqi3"
+ [(set (match_operand:QI 0 "general_operand" "=m,d")
+ (ior:QI (match_operand:QI 1 "general_operand" "%0,0")
+ (match_operand:QI 2 "general_operand" "dn,dmn")))]
+ "!TARGET_5200"
+ "or%.b %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ (ior:QI (match_dup 0)
+ (match_operand:QI 1 "general_operand" "dn,dmn")))]
+ "!TARGET_5200"
+ "or%.b %1,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ (ior:QI (match_operand:QI 1 "general_operand" "dn,dmn")
+ (match_dup 0)))]
+ "!TARGET_5200"
+ "or%.b %1,%0")
+
+;; On all 68k models, this makes faster code in a special case.
+;; See also ashlsi_16, ashrsi_16 and lshrsi_16.
+
+(define_insn "iorsi_zexthi_ashl16"
+ [(set (match_operand:SI 0 "general_operand" "=&d")
+ (ior:SI (zero_extend:SI (match_operand:HI 1 "general_operand" "rmn"))
+ (ashift:SI (match_operand:SI 2 "general_operand" "or")
+ (const_int 16))))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (GET_CODE (operands[2]) != REG)
+ operands[2] = adj_offsettable_operand (operands[2], 2);
+ if (GET_CODE (operands[2]) != REG
+ || REGNO (operands[2]) != REGNO (operands[0]))
+ output_asm_insn (\"move%.w %2,%0\", operands);
+ return \"swap %0\;mov%.w %1,%0\";
+}")
+
+(define_insn "iorsi_zext"
+ [(set (match_operand:SI 0 "general_operand" "=o,d")
+ (ior:SI (zero_extend:SI (match_operand 1 "general_operand" "dn,dmn"))
+ (match_operand:SI 2 "general_operand" "0,0")))]
+ "!TARGET_5200"
+ "*
+{
+ int byte_mode;
+
+ CC_STATUS_INIT;
+ byte_mode = (GET_MODE (operands[1]) == QImode);
+ if (GET_CODE (operands[0]) == MEM)
+ operands[0] = adj_offsettable_operand (operands[0], byte_mode ? 3 : 2);
+ if (byte_mode)
+ return \"or%.b %1,%0\";
+ else
+ return \"or%.w %1,%0\";
+}")
+
+;; xor instructions
+
+;; "xordi3" is mainly here to help combine().
+(define_insn "xordi3"
+ [(set (match_operand:DI 0 "general_operand" "=od")
+ (xor:DI (match_operand:DI 1 "general_operand" "%0")
+ (match_operand:DI 2 "general_operand" "dn")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ /* We can get CONST_DOUBLE, but also const1_rtx etc. */
+ if (GET_CODE (operands[2]) == CONST_DOUBLE
+ || GET_CODE (operands[2]) == CONST_INT)
+ {
+ rtx hi, lo;
+
+ if (GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ hi = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
+ lo = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+ }
+ else
+ {
+ lo = operands[2];
+ hi = INTVAL (lo) < 0 ? constm1_rtx : const0_rtx;
+ }
+ switch (INTVAL (hi))
+ {
+ case 0 :
+ break;
+ case -1 :
+ output_asm_insn (\"not%.l %0\", operands);
+ break;
+ default :
+ /* FIXME : a scratch register would be welcome here if
+ -128 <= INTVAL (hi) < -1 */
+ {
+ rtx xoperands[3];
+
+ xoperands[0] = operands[0];
+ xoperands[2] = hi;
+ output_asm_insn (output_xorsi3 (xoperands), xoperands);
+ }
+ }
+ if (GET_CODE (operands[0]) == REG)
+ operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ else
+ operands[0] = adj_offsettable_operand (operands[0], 4);
+ switch (INTVAL (lo))
+ {
+ case 0 :
+ break;
+ case -1 :
+ output_asm_insn (\"not%.l %0\", operands);
+ break;
+ default :
+ /* FIXME : a scratch register would be welcome here if
+ -128 <= INTVAL (lo) < -1 */
+ operands[2] = lo;
+ /* FIXME : this should be merged with xorsi3 */
+ {
+ rtx xoperands[3];
+
+ xoperands[0] = operands[0];
+ xoperands[2] = lo;
+ output_asm_insn (output_xorsi3 (xoperands), xoperands);
+ }
+ }
+ return \"\";
+ }
+ if (GET_CODE (operands[0]) != REG)
+ {
+ operands[1] = adj_offsettable_operand (operands[0], 4);
+ return \"eor%.l %2,%0\;eor%.l %R2,%1\";
+ }
+ if (GET_CODE (operands[2]) != REG)
+ {
+ operands[1] = adj_offsettable_operand (operands[2], 4);
+ return \"eor%.l %2,%0\;eor%.l %1,%R0\";
+ }
+ return \"eor%.l %2,%0\;eor%.l %R2,%R0\";
+}")
+
+(define_expand "xorsi3"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (xor:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ ""
+ "")
+
+(define_insn "xorsi3_internal"
+ [(set (match_operand:SI 0 "general_operand" "=do,m")
+ (xor:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "di,dKs")))]
+ "!TARGET_5200"
+ "*
+{
+ return output_xorsi3 (operands);
+}")
+
+(define_insn "xorsi3_5200"
+ [(set (match_operand:SI 0 "general_operand" "=dm,d")
+ (xor:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,Ks")))]
+ "TARGET_5200"
+ "eor%.l %2,%0")
+
+(define_insn "xorhi3"
+ [(set (match_operand:HI 0 "general_operand" "=dm")
+ (xor:HI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "dn")))]
+ "!TARGET_5200"
+ "eor%.w %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
+ (xor:HI (match_dup 0)
+ (match_operand:HI 1 "general_operand" "dn")))]
+ "!TARGET_5200"
+ "eor%.w %1,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
+ (xor:HI (match_operand:HI 1 "general_operand" "dn")
+ (match_dup 0)))]
+ "!TARGET_5200"
+ "eor%.w %1,%0")
+
+(define_insn "xorqi3"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (xor:QI (match_operand:QI 1 "general_operand" "%0")
+ (match_operand:QI 2 "general_operand" "dn")))]
+ "!TARGET_5200"
+ "eor%.b %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
+ (xor:QI (match_dup 0)
+ (match_operand:QI 1 "general_operand" "dn")))]
+ "!TARGET_5200"
+ "eor%.b %1,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
+ (xor:QI (match_operand:QI 1 "general_operand" "dn")
+ (match_dup 0)))]
+ "!TARGET_5200"
+ "eor%.b %1,%0")
+
+;; negation instructions
+
+(define_expand "negdi2"
+ [(set (match_operand:DI 0 "general_operand" "")
+ (neg:DI (match_operand:DI 1 "general_operand" "")))]
+ ""
+ "
+{
+ if (TARGET_5200)
+ emit_insn (gen_negdi2_5200 (operands[0], operands[1]));
+ else
+ emit_insn (gen_negdi2_internal (operands[0], operands[1]));
+ DONE;
+}")
+
+(define_insn "negdi2_internal"
+ [(set (match_operand:DI 0 "general_operand" "=<,do,!*a")
+ (neg:DI (match_operand:DI 1 "general_operand" "0,0,0")))]
+ "!TARGET_5200"
+ "*
+{
+ if (which_alternative == 0)
+ return \"neg%.l %0\;negx%.l %0\";
+ if (GET_CODE (operands[0]) == REG)
+ operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ else
+ operands[1] = adj_offsettable_operand (operands[0], 4);
+ if (ADDRESS_REG_P (operands[0]))
+ return \"exg %/d0,%1\;neg%.l %/d0\;exg %/d0,%1\;exg %/d0,%0\;negx%.l %/d0\;exg %/d0,%0\";
+ else
+ return \"neg%.l %1\;negx%.l %0\";
+} ")
+
+(define_insn "negdi2_5200"
+ [(set (match_operand:DI 0 "general_operand" "=d")
+ (neg:DI (match_operand:DI 1 "general_operand" "0")))]
+ "TARGET_5200"
+ "*
+{
+ operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ return \"neg%.l %1\;negx%.l %0\";
+} ")
+
+(define_expand "negsi2"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (neg:SI (match_operand:SI 1 "general_operand" "")))]
+ ""
+ "
+{
+ if (TARGET_5200)
+ emit_insn (gen_negsi2_5200 (operands[0], operands[1]));
+ else
+ emit_insn (gen_negsi2_internal (operands[0], operands[1]));
+ DONE;
+}")
+
+(define_insn "negsi2_internal"
+ [(set (match_operand:SI 0 "general_operand" "=dm")
+ (neg:SI (match_operand:SI 1 "general_operand" "0")))]
+ "!TARGET_5200"
+ "neg%.l %0")
+
+(define_insn "negsi2_5200"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (neg:SI (match_operand:SI 1 "general_operand" "0")))]
+ "TARGET_5200"
+ "neg%.l %0")
+
+(define_insn "neghi2"
+ [(set (match_operand:HI 0 "general_operand" "=dm")
+ (neg:HI (match_operand:HI 1 "general_operand" "0")))]
+ "!TARGET_5200"
+ "neg%.w %0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
+ (neg:HI (match_dup 0)))]
+ "!TARGET_5200"
+ "neg%.w %0")
+
+(define_insn "negqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (neg:QI (match_operand:QI 1 "general_operand" "0")))]
+ "!TARGET_5200"
+ "neg%.b %0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
+ (neg:QI (match_dup 0)))]
+ "!TARGET_5200"
+ "neg%.b %0")
+
+;; If using software floating point, just flip the sign bit.
+
+(define_expand "negsf2"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (neg:SF (match_operand:SF 1 "general_operand" "")))]
+ ""
+ "
+{
+ if (!TARGET_FPA && !TARGET_68881)
+ {
+ rtx result;
+ rtx target;
+
+ target = operand_subword_force (operands[0], 0, SFmode);
+ result = expand_binop (SImode, xor_optab,
+ operand_subword_force (operands[1], 0, SFmode),
+ GEN_INT(0x80000000), target, 0, OPTAB_WIDEN);
+ if (result == 0)
+ abort ();
+
+ if (result != target)
+ emit_move_insn (result, target);
+
+ /* Make a place for REG_EQUAL. */
+ emit_move_insn (operands[0], operands[0]);
+ DONE;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=x,y")
+ (neg:SF (match_operand:SF 1 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "fpneg%.s %w1,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f,d")
+ (neg:SF (match_operand:SF 1 "general_operand" "fdmF,0")))]
+ "TARGET_68881"
+ "*
+{
+ if (DATA_REG_P (operands[0]))
+ {
+ operands[1] = GEN_INT (31);
+ return \"bchg %1,%0\";
+ }
+ if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
+ return \"f%$neg%.x %1,%0\";
+ return \"f%$neg%.s %f1,%0\";
+}")
+
+(define_expand "negdf2"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (neg:DF (match_operand:DF 1 "general_operand" "")))]
+ ""
+ "
+{
+ if (!TARGET_FPA && !TARGET_68881)
+ {
+ rtx result;
+ rtx target;
+ rtx insns;
+
+ start_sequence ();
+ target = operand_subword (operands[0], 0, 1, DFmode);
+ result = expand_binop (SImode, xor_optab,
+ operand_subword_force (operands[1], 0, DFmode),
+ GEN_INT(0x80000000), target, 0, OPTAB_WIDEN);
+ if (result == 0)
+ abort ();
+
+ if (result != target)
+ emit_move_insn (result, target);
+
+ emit_move_insn (operand_subword (operands[0], 1, 1, DFmode),
+ operand_subword_force (operands[1], 1, DFmode));
+
+ insns = get_insns ();
+ end_sequence ();
+
+ emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
+ DONE;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=x,y")
+ (neg:DF (match_operand:DF 1 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "fpneg%.d %y1, %0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f,d")
+ (neg:DF (match_operand:DF 1 "general_operand" "fmF,0")))]
+ "TARGET_68881"
+ "*
+{
+ if (DATA_REG_P (operands[0]))
+ {
+ operands[1] = GEN_INT (31);
+ return \"bchg %1,%0\";
+ }
+ if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
+ return \"f%&neg%.x %1,%0\";
+ return \"f%&neg%.d %f1,%0\";
+}")
+
+;; Sqrt instruction for the 68881
+
+(define_insn "sqrtsf2"
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (sqrt:SF (match_operand:SF 1 "general_operand" "fm")))]
+ "TARGET_68881"
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"f%$sqrt%.x %1,%0\";
+ else
+ return \"f%$sqrt%.s %1,%0\";
+}")
+
+(define_insn "sqrtdf2"
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (sqrt:DF (match_operand:DF 1 "general_operand" "fm")))]
+ "TARGET_68881"
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"f%&sqrt%.x %1,%0\";
+ else
+ return \"f%&sqrt%.d %1,%0\";
+}")
+
+;; Absolute value instructions
+;; If using software floating point, just zero the sign bit.
+
+(define_expand "abssf2"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (abs:SF (match_operand:SF 1 "general_operand" "")))]
+ ""
+ "
+{
+ if (!TARGET_FPA && !TARGET_68881)
+ {
+ rtx result;
+ rtx target;
+
+ target = operand_subword_force (operands[0], 0, SFmode);
+ result = expand_binop (SImode, and_optab,
+ operand_subword_force (operands[1], 0, SFmode),
+ GEN_INT(0x7fffffff), target, 0, OPTAB_WIDEN);
+ if (result == 0)
+ abort ();
+
+ if (result != target)
+ emit_move_insn (result, target);
+
+ /* Make a place for REG_EQUAL. */
+ emit_move_insn (operands[0], operands[0]);
+ DONE;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=x,y")
+ (abs:SF (match_operand:SF 1 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "fpabs%.s %y1,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (abs:SF (match_operand:SF 1 "general_operand" "fdmF")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
+ return \"f%$abs%.x %1,%0\";
+ return \"f%$abs%.s %f1,%0\";
+}")
+
+(define_expand "absdf2"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (abs:DF (match_operand:DF 1 "general_operand" "")))]
+ ""
+ "
+{
+ if (!TARGET_FPA && !TARGET_68881)
+ {
+ rtx result;
+ rtx target;
+ rtx insns;
+
+ start_sequence ();
+ target = operand_subword (operands[0], 0, 1, DFmode);
+ result = expand_binop (SImode, and_optab,
+ operand_subword_force (operands[1], 0, DFmode),
+ GEN_INT(0x7fffffff), target, 0, OPTAB_WIDEN);
+ if (result == 0)
+ abort ();
+
+ if (result != target)
+ emit_move_insn (result, target);
+
+ emit_move_insn (operand_subword (operands[0], 1, 1, DFmode),
+ operand_subword_force (operands[1], 1, DFmode));
+
+ insns = get_insns ();
+ end_sequence ();
+
+ emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
+ DONE;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=x,y")
+ (abs:DF (match_operand:DF 1 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "fpabs%.d %y1,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (abs:DF (match_operand:DF 1 "general_operand" "fmF")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
+ return \"f%&abs%.x %1,%0\";
+ return \"f%&abs%.d %f1,%0\";
+}")
+
+;; one complement instructions
+
+;; "one_cmpldi2" is mainly here to help combine().
+(define_insn "one_cmpldi2"
+ [(set (match_operand:DI 0 "general_operand" "=dm")
+ (not:DI (match_operand:DI 1 "general_operand" "0")))]
+ "!TARGET_5200"
+ "*
+{
+ CC_STATUS_INIT;
+ if (GET_CODE (operands[0]) == REG)
+ operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC
+ || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ operands[1] = operands[0];
+ else
+ operands[1] = adj_offsettable_operand (operands[0], 4);
+ return \"not%.l %1\;not%.l %0\";
+}")
+
+(define_expand "one_cmplsi2"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (not:SI (match_operand:SI 1 "general_operand" "")))]
+ ""
+ "
+{
+ if (TARGET_5200)
+ emit_insn (gen_one_cmplsi2_5200 (operands[0], operands[1]));
+ else
+ emit_insn (gen_one_cmplsi2_internal (operands[0], operands[1]));
+ DONE;
+}")
+
+(define_insn "one_cmplsi2_internal"
+ [(set (match_operand:SI 0 "general_operand" "=dm")
+ (not:SI (match_operand:SI 1 "general_operand" "0")))]
+ "!TARGET_5200"
+ "not%.l %0")
+
+(define_insn "one_cmplsi2_5200"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (not:SI (match_operand:SI 1 "general_operand" "0")))]
+ "TARGET_5200"
+ "not%.l %0")
+
+(define_insn "one_cmplhi2"
+ [(set (match_operand:HI 0 "general_operand" "=dm")
+ (not:HI (match_operand:HI 1 "general_operand" "0")))]
+ "!TARGET_5200"
+ "not%.w %0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
+ (not:HI (match_dup 0)))]
+ "!TARGET_5200"
+ "not%.w %0")
+
+(define_insn "one_cmplqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (not:QI (match_operand:QI 1 "general_operand" "0")))]
+ "!TARGET_5200"
+ "not%.b %0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
+ (not:QI (match_dup 0)))]
+ "!TARGET_5200"
+ "not%.b %0")
+
+;; arithmetic shift instructions
+;; We don't need the shift memory by 1 bit instruction
+
+(define_insn "ashldi_extsi"
+ [(set (match_operand:DI 0 "general_operand" "=ro")
+ (ashift:DI
+ (match_operator:DI 2 "extend_operator"
+ [(match_operand:SI 1 "general_operand" "rm")])
+ (const_int 32)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (GET_CODE (operands[0]) == REG)
+ operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ else
+ operands[2] = adj_offsettable_operand (operands[0], 4);
+ if (ADDRESS_REG_P (operands[0]))
+ return \"move%.l %1,%0\;sub%.l %2,%2\";
+ else
+ return \"move%.l %1,%0\;clr%.l %2\";
+} ")
+
+(define_insn "ashldi_sexthi"
+ [(set (match_operand:DI 0 "general_operand" "=m,a*d")
+ (ashift:DI (sign_extend:DI (match_operand:HI 1 "general_operand" "rm,rm"))
+ (const_int 32)))
+ (clobber (match_scratch:SI 2 "=a,X"))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ return \"clr%.l %0\;move%.w %1,%2\;move%.l %2,%0\";
+ else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ return \"move%.w %1,%2\;move%.l %2,%0\;clr%.l %0\";
+ else
+ {
+ operands[3] = adj_offsettable_operand (operands[0], 4);
+ return \"move%.w %1,%2\;move%.l %2,%0\;clr%.l %3\";
+ }
+ }
+ else if (DATA_REG_P (operands[0]))
+ return \"move%.w %1,%0\;ext%.l %0\;clr%.l %R0\";
+ else
+ return \"move%.w %1,%0\;sub%.l %R0,%R0\";
+} ")
+
+(define_insn "ashldi_const32"
+ [(set (match_operand:DI 0 "general_operand" "=rm")
+ (ashift:DI (match_operand:DI 1 "general_operand" "ro")
+ (const_int 32)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (GET_CODE (operands[1]) == REG)
+ operands[3] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+ else
+ operands[3] = adj_offsettable_operand (operands[1], 4);
+ if (GET_CODE (operands[0]) == REG)
+ operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ return \"clr%.l %0\;move%.l %3,%0\";
+ else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ return \"move%.l %3,%0\;clr%.l %0\";
+ else
+ operands[2] = adj_offsettable_operand (operands[0], 4);
+ if (ADDRESS_REG_P (operands[2]))
+ return \"move%.l %3,%0\;sub%.l %2,%2\";
+ else
+ return \"move%.l %3,%0\;clr%.l %2\";
+} ")
+
+;; The predicate below must be general_operand, because ashldi3 allows that
+(define_insn "ashldi_const"
+ [(set (match_operand:DI 0 "general_operand" "=d")
+ (ashift:DI (match_operand:DI 1 "general_operand" "0")
+ (match_operand 2 "const_int_operand" "n")))]
+ "(!TARGET_5200
+ && ((INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 3)
+ || INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16
+ || (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63)))"
+ "*
+{
+ operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ if (INTVAL (operands[2]) == 1)
+ return \"add%.l %1,%1\;addx%.l %0,%0\";
+ else if (INTVAL (operands[2]) == 8)
+ return \"rol%.l %#8,%1\;rol%.l %#8,%0\;move%.b %1,%0\;clr%.b %1\";
+ else if (INTVAL (operands[2]) == 16)
+ return \"swap %1\;swap %0\;move%.w %1,%0\;clr%.w %1\";
+ else if (INTVAL (operands[2]) == 48)
+ return \"mov%.l %1,%0\;swap %0\;clr%.l %1\;clr%.w %0\";
+ else if (INTVAL (operands[2]) == 2)
+ return \"add%.l %1,%1\;addx%.l %0,%0\;add%.l %1,%1\;addx%.l %0,%0\";
+ else if (INTVAL (operands[2]) == 3)
+ return \"add%.l %1,%1\;addx%.l %0,%0\;add%.l %1,%1\;addx%.l %0,%0\;add%.l %1,%1\;addx%.l %0,%0\";
+ else /* 32 < INTVAL (operands[2]) <= 63 */
+ {
+ operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
+ output_asm_insn (INTVAL (operands[2]) <= 8 ? \"asl%.l %2,%1\" :
+ \"moveq %2,%0\;asl%.l %0,%1\", operands);
+ return \"mov%.l %1,%0\;moveq %#0,%1\";
+ }
+} ")
+
+(define_expand "ashldi3"
+ [(set (match_operand:DI 0 "general_operand" "")
+ (ashift:DI (match_operand:DI 1 "general_operand" "")
+ (match_operand 2 "const_int_operand" "")))]
+ "!TARGET_5200"
+ "
+{
+ /* ??? This is a named pattern like this is not allowed to FAIL based
+ on its operands. */
+ if (GET_CODE (operands[2]) != CONST_INT
+ || ((INTVAL (operands[2]) < 1 || INTVAL (operands[2]) > 3)
+ && INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16
+ && (INTVAL (operands[2]) < 32 || INTVAL (operands[2]) > 63)))
+ FAIL;
+} ")
+
+;; On most 68k models, this makes faster code in a special case.
+
+(define_insn "ashlsi_16"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (ashift:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 16)))]
+ "!TARGET_68060"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"swap %0\;clr%.w %0\";
+}")
+
+;; ashift patterns : use lsl instead of asl, because lsl always clears the
+;; overflow bit, so we must not set CC_NO_OVERFLOW.
+
+;; On the 68000, this makes faster code in a special case.
+
+(define_insn "ashlsi_17_24"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (ashift:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_int_operand" "n")))]
+ "(! TARGET_68020 && !TARGET_5200
+ && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)"
+ "*
+{
+ CC_STATUS_INIT;
+
+ operands[2] = GEN_INT (INTVAL (operands[2]) - 16);
+ return \"lsl%.w %2,%0\;swap %0\;clr%.w %0\";
+}")
+
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (ashift:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "general_operand" "dI")))]
+ ""
+ "*
+{
+ if (operands[2] == const1_rtx)
+ {
+ cc_status.flags = CC_NO_OVERFLOW;
+ return \"add%.l %0,%0\";
+ }
+ return \"lsl%.l %2,%0\";
+}")
+
+(define_insn "ashlhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (ashift:HI (match_operand:HI 1 "register_operand" "0")
+ (match_operand:HI 2 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "lsl%.w %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
+ (ashift:HI (match_dup 0)
+ (match_operand:HI 1 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "lsl%.w %1,%0")
+
+(define_insn "ashlqi3"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (ashift:QI (match_operand:QI 1 "register_operand" "0")
+ (match_operand:QI 2 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "lsl%.b %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
+ (ashift:QI (match_dup 0)
+ (match_operand:QI 1 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "lsl%.b %1,%0")
+
+;; On most 68k models, this makes faster code in a special case.
+
+(define_insn "ashrsi_16"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 16)))]
+ "!TARGET_68060"
+ "swap %0\;ext%.l %0")
+
+;; On the 68000, this makes faster code in a special case.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_int_operand" "n")))]
+ "(! TARGET_68020 && !TARGET_5200
+ && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)"
+ "*
+{
+ operands[2] = GEN_INT (INTVAL (operands[2]) - 16);
+ return \"swap %0\;asr%.w %2,%0\;ext%.l %0\";
+}")
+
+(define_insn "subreghi1ashrdi_const32"
+ [(set (match_operand:HI 0 "general_operand" "=rm")
+ (subreg:HI (ashiftrt:DI (match_operand:DI 1 "general_operand" "ro")
+ (const_int 32)) 1))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) != REG)
+ operands[1] = adj_offsettable_operand (operands[1], 2);
+ return \"move%.w %1,%0\";
+} ")
+
+(define_insn "subregsi1ashrdi_const32"
+ [(set (match_operand:SI 0 "general_operand" "=rm")
+ (subreg:SI (ashiftrt:DI (match_operand:DI 1 "general_operand" "ro")
+ (const_int 32)) 1))]
+ ""
+ "*
+{
+ return \"move%.l %1,%0\";
+} ")
+
+(define_insn "ashrdi_const32"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (ashiftrt:DI (match_operand:DI 1 "general_operand" "ro")
+ (const_int 32)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ if (TARGET_68020)
+ return \"move%.l %1,%2\;smi %0\;extb%.l %0\";
+ else
+ return \"move%.l %1,%2\;smi %0\;ext%.w %0\;ext%.l %0\";
+} ")
+
+(define_insn "ashrdi_const32_mem"
+ [(set (match_operand:DI 0 "general_operand" "=o,<")
+ (ashiftrt:DI (match_operand:DI 1 "general_operand" "ro,ro")
+ (const_int 32)))
+ (clobber (match_scratch:SI 2 "=d,d"))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (which_alternative == 1)
+ operands[3] = operands[0];
+ else
+ operands[3] = adj_offsettable_operand (operands[0], 4);
+ if (TARGET_68020)
+ return \"move%.l %1,%3\;smi %2\;extb%.l %2\;move%.l %2,%0\";
+ else
+ return \"move%.l %1,%3\;smi %2\;ext%.w %2\;ext%.l %2\;move%.l %2,%0\";
+} ")
+
+;; The predicate below must be general_operand, because ashrdi3 allows that
+(define_insn "ashrdi_const"
+ [(set (match_operand:DI 0 "general_operand" "=d")
+ (ashiftrt:DI (match_operand:DI 1 "general_operand" "0")
+ (match_operand 2 "const_int_operand" "n")))]
+ "!TARGET_5200
+ && ((INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 3)
+ || INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16
+ || INTVAL (operands[2]) == 31
+ || (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63))"
+ "*
+{
+ operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ if (INTVAL (operands[2]) == 63)
+ return \"add%.l %0,%0\;subx%.l %0,%0\;move%.l %0,%1\";
+ CC_STATUS_INIT;
+ if (INTVAL (operands[2]) == 1)
+ return \"asr%.l %#1,%0\;roxr%.l %#1,%1\";
+ else if (INTVAL (operands[2]) == 8)
+ return \"move%.b %0,%1\;asr%.l %#8,%0\;ror%.l %#8,%1\";
+ else if (INTVAL (operands[2]) == 16)
+ return \"move%.w %0,%1\;clr%.w %0\;swap %1\;ext%.l %0\";
+ else if (INTVAL (operands[2]) == 48)
+ return \"swap %0\;ext%.l %0\;move%.l %0,%1\;smi %0\;ext%.w %0\";
+ else if (INTVAL (operands[2]) == 31)
+ return \"add%.l %1,%1\;addx%.l %0,%0\;move%.l %0,%1\;subx%.l %0,%0\";
+ else if (INTVAL (operands[2]) == 2)
+ return \"asr%.l %#1,%0\;roxr%.l %#1,%1\;asr%.l %#1,%0\;roxr%.l %#1,%1\";
+ else if (INTVAL (operands[2]) == 3)
+ return \"asr%.l %#1,%0\;roxr%.l %#1,%1\;asr%.l %#1,%0\;roxr%.l %#1,%1\;asr%.l %#1,%0\;roxr%.l %#1,%1\";
+ else /* 32 < INTVAL (operands[2]) <= 63 */
+ {
+ operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
+ output_asm_insn (INTVAL (operands[2]) <= 8 ? \"asr%.l %2,%0\" :
+ \"moveq %2,%1\;asr%.l %1,%0\", operands);
+ output_asm_insn (\"mov%.l %0,%1\;smi %0\", operands);
+ return INTVAL (operands[2]) >= 15 ? \"ext%.w %d0\" :
+ TARGET_68020 ? \"extb%.l %0\" : \"ext%.w %0\;ext%.l %0\";
+ }
+} ")
+
+(define_expand "ashrdi3"
+ [(set (match_operand:DI 0 "general_operand" "")
+ (ashiftrt:DI (match_operand:DI 1 "general_operand" "")
+ (match_operand 2 "const_int_operand" "")))]
+ "!TARGET_5200"
+ "
+{
+ if (GET_CODE (operands[2]) != CONST_INT
+ || ((INTVAL (operands[2]) < 1 || INTVAL (operands[2]) > 3)
+ && INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16
+ && (INTVAL (operands[2]) < 31 || INTVAL (operands[2]) > 63)))
+ FAIL;
+} ")
+
+;; On all 68k models, this makes faster code in a special case.
+
+(define_insn "ashrsi_31"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 31)))]
+ ""
+ "*
+{
+ return \"add%.l %0,%0\;subx%.l %0,%0\";
+}")
+
+(define_insn "ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "general_operand" "dI")))]
+ ""
+ "asr%.l %2,%0")
+
+(define_insn "ashrhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
+ (match_operand:HI 2 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "asr%.w %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
+ (ashiftrt:HI (match_dup 0)
+ (match_operand:HI 1 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "asr%.w %1,%0")
+
+(define_insn "ashrqi3"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
+ (match_operand:QI 2 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "asr%.b %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
+ (ashiftrt:QI (match_dup 0)
+ (match_operand:QI 1 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "asr%.b %1,%0")
+
+;; logical shift instructions
+
+;; commented out because of reload problems in 950612-1.c
+;;(define_insn ""
+;; [(set (cc0)
+;; (subreg:SI (lshiftrt:DI (match_operand:DI 0 "general_operand" "ro")
+;; (const_int 32)) 1))
+;; (set (match_operand:SI 1 "general_operand" "=dm")
+;; (subreg:SI (lshiftrt:DI (match_dup 0)
+;; (const_int 32)) 1))]
+;; ""
+;; "*
+;;{
+;; return \"move%.l %0,%1\";
+;;} ")
+;;
+;;(define_insn ""
+;; [(set (cc0)
+;; (subreg:SI (lshiftrt:DI (match_operand:DI 0 "general_operand" "ro")
+;; (const_int 32)) 0))
+;; (set (match_operand:DI 1 "general_operand" "=do")
+;; (lshiftrt:DI (match_dup 0)
+;; (const_int 32)))]
+;; ""
+;; "*
+;;{
+;; if (GET_CODE (operands[1]) == REG)
+;; operands[2] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+;; else
+;; operands[2] = adj_offsettable_operand (operands[1], 4);
+;; return \"move%.l %0,%2\;clr%.l %1\";
+;;} ")
+
+(define_insn "subreg1lshrdi_const32"
+ [(set (match_operand:SI 0 "general_operand" "=rm")
+ (subreg:SI (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro")
+ (const_int 32)) 1))]
+ ""
+ "*
+{
+ return \"move%.l %1,%0\";
+} ")
+
+(define_insn "lshrdi_const32"
+ [(set (match_operand:DI 0 "general_operand" "=ro,<,>")
+ (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro,ro,ro")
+ (const_int 32)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (which_alternative == 1)
+ return \"move%.l %1,%0\;clr%.l %0\";
+ if (which_alternative == 2)
+ return \"clr%.l %0\;move%.l %1,%0\";
+ if (GET_CODE (operands[0]) == REG)
+ operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ else
+ operands[2] = adj_offsettable_operand (operands[0], 4);
+ if (GET_CODE (operands[1]) == REG)
+ operands[3] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+ else
+ operands[3] = adj_offsettable_operand (operands[1], 4);
+ if (ADDRESS_REG_P (operands[0]))
+ return \"move%.l %1,%2\;sub%.l %0,%0\";
+ else
+ return \"move%.l %1,%2\;clr%.l %0\";
+} ")
+
+;; The predicate below must be general_operand, because lshrdi3 allows that
+(define_insn "lshrdi_const"
+ [(set (match_operand:DI 0 "general_operand" "=d")
+ (lshiftrt:DI (match_operand:DI 1 "general_operand" "0")
+ (match_operand 2 "const_int_operand" "n")))]
+ "!TARGET_5200
+ && ((INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 3)
+ || INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16
+ || (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63))"
+ "*
+{
+ operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ if (INTVAL (operands[2]) == 63)
+ return \"add%.l %0,%0\;clr%.l %0\;clr%.l %1\;addx%.l %1,%1\";
+ CC_STATUS_INIT;
+ if (INTVAL (operands[2]) == 1)
+ return \"lsr%.l %#1,%0\;roxr%.l %#1,%1\";
+ else if (INTVAL (operands[2]) == 8)
+ return \"move%.b %0,%1\;lsr%.l %#8,%0\;ror%.l %#8,%1\";
+ else if (INTVAL (operands[2]) == 16)
+ return \"move%.w %0,%1\;clr%.w %0\;swap %1\;swap %0\";
+ else if (INTVAL (operands[2]) == 48)
+ return \"move%.l %0,%1\;clr%.w %1\;clr%.l %0\;swap %1\";
+ else if (INTVAL (operands[2]) == 2)
+ return \"lsr%.l %#1,%0\;roxr%.l %#1,%1\;lsr%.l %#1,%0\;roxr%.l %#1,%1\";
+ else if (INTVAL (operands[2]) == 3)
+ return \"lsr%.l %#1,%0\;roxr%.l %#1,%1\;lsr%.l %#1,%0\;roxr%.l %#1,%1\;lsr%.l %#1,%0\;roxr%.l %#1,%1\";
+ else /* 32 < INTVAL (operands[2]) <= 63 */
+ {
+ operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
+ output_asm_insn (INTVAL (operands[2]) <= 8 ? \"lsr%.l %2,%0\" :
+ \"moveq %2,%1\;lsr%.l %1,%0\", operands);
+ return \"mov%.l %0,%1\;moveq %#0,%0\";
+ }
+} ")
+
+(define_expand "lshrdi3"
+ [(set (match_operand:DI 0 "general_operand" "")
+ (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
+ (match_operand 2 "const_int_operand" "")))]
+ "!TARGET_5200"
+ "
+{
+ if (GET_CODE (operands[2]) != CONST_INT
+ || ((INTVAL (operands[2]) < 1 || INTVAL (operands[2]) > 3)
+ && INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16
+ && (INTVAL (operands[2]) < 32 || INTVAL (operands[2]) > 63)))
+ FAIL;
+} ")
+
+;; On all 68k models, this makes faster code in a special case.
+
+(define_insn "lshrsi_31"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 31)))]
+ ""
+ "*
+{
+ return \"add%.l %0,%0\;subx%.l %0,%0\;neg%.l %0\";
+}")
+
+;; On most 68k models, this makes faster code in a special case.
+
+(define_insn "lshrsi_16"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 16)))]
+ "!TARGET_68060"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"clr%.w %0\;swap %0\";
+}")
+
+;; On the 68000, this makes faster code in a special case.
+
+(define_insn "lshrsi_17_24"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_int_operand" "n")))]
+ "(! TARGET_68020 && !TARGET_5200
+ && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)"
+ "*
+{
+ /* I think lsr%.w sets the CC properly. */
+ operands[2] = GEN_INT (INTVAL (operands[2]) - 16);
+ return \"clr%.w %0\;swap %0\;lsr%.w %2,%0\";
+}")
+
+(define_insn "lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "general_operand" "dI")))]
+ ""
+ "lsr%.l %2,%0")
+
+(define_insn "lshrhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
+ (match_operand:HI 2 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "lsr%.w %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
+ (lshiftrt:HI (match_dup 0)
+ (match_operand:HI 1 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "lsr%.w %1,%0")
+
+(define_insn "lshrqi3"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
+ (match_operand:QI 2 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "lsr%.b %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
+ (lshiftrt:QI (match_dup 0)
+ (match_operand:QI 1 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "lsr%.b %1,%0")
+
+;; rotate instructions
+
+(define_insn "rotlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (rotate:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "general_operand" "dINO")))]
+ "!TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 16)
+ return \"swap %0\";
+ else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 16)
+ {
+ operands[2] = GEN_INT (32 - INTVAL (operands[2]));
+ return \"ror%.l %2,%0\";
+ }
+ else
+ return \"rol%.l %2,%0\";
+}")
+
+(define_insn "rotlhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (rotate:HI (match_operand:HI 1 "register_operand" "0")
+ (match_operand:HI 2 "general_operand" "dIP")))]
+ "!TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 8)
+ {
+ operands[2] = GEN_INT (16 - INTVAL (operands[2]));
+ return \"ror%.w %2,%0\";
+ }
+ else
+ return \"rol%.w %2,%0\";
+}")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
+ (rotate:HI (match_dup 0)
+ (match_operand:HI 1 "general_operand" "dIP")))]
+ "!TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 8)
+ {
+ operands[2] = GEN_INT (16 - INTVAL (operands[2]));
+ return \"ror%.w %2,%0\";
+ }
+ else
+ return \"rol%.w %2,%0\";
+}")
+
+(define_insn "rotlqi3"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (rotate:QI (match_operand:QI 1 "register_operand" "0")
+ (match_operand:QI 2 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 4)
+ {
+ operands[2] = GEN_INT (8 - INTVAL (operands[2]));
+ return \"ror%.b %2,%0\";
+ }
+ else
+ return \"rol%.b %2,%0\";
+}")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
+ (rotate:QI (match_dup 0)
+ (match_operand:QI 1 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 4)
+ {
+ operands[2] = GEN_INT (8 - INTVAL (operands[2]));
+ return \"ror%.b %2,%0\";
+ }
+ else
+ return \"rol%.b %2,%0\";
+}")
+
+(define_insn "rotrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (rotatert:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "ror%.l %2,%0")
+
+(define_insn "rotrhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (rotatert:HI (match_operand:HI 1 "register_operand" "0")
+ (match_operand:HI 2 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "ror%.w %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
+ (rotatert:HI (match_dup 0)
+ (match_operand:HI 1 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "ror%.w %1,%0")
+
+(define_insn "rotrqi3"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (rotatert:QI (match_operand:QI 1 "register_operand" "0")
+ (match_operand:QI 2 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "ror%.b %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
+ (rotatert:QI (match_dup 0)
+ (match_operand:QI 1 "general_operand" "dI")))]
+ "!TARGET_5200"
+ "ror%.b %1,%0")
+
+
+;; Bit set/clear in memory byte.
+
+;; set bit, bit number is int
+(define_insn "bsetmemqi"
+ [(set (match_operand:QI 0 "memory_operand" "+m")
+ (ior:QI (subreg:QI (ashift:SI (const_int 1)
+ (match_operand:SI 1 "general_operand" "d")) 0)
+ (match_dup 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bset %1,%0\";
+}")
+
+;; set bit, bit number is (sign/zero)_extended from HImode/QImode
+(define_insn ""
+ [(set (match_operand:QI 0 "memory_operand" "+m")
+ (ior:QI (subreg:QI (ashift:SI (const_int 1)
+ (match_operator:SI 2 "extend_operator"
+ [(match_operand 1 "general_operand" "d")])) 0)
+ (match_dup 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bset %1,%0\";
+}")
+
+;; clear bit, bit number is int
+(define_insn "bclrmemqi"
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+m")
+ (const_int 1)
+ (minus:SI (const_int 7)
+ (match_operand:SI 1 "general_operand" "d")))
+ (const_int 0))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bclr %1,%0\";
+}")
+
+;; clear bit, bit number is (sign/zero)_extended from HImode/QImode
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+m")
+ (const_int 1)
+ (minus:SI (const_int 7)
+ (match_operator:SI 2 "extend_operator"
+ [(match_operand 1 "general_operand" "d")])))
+ (const_int 0))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bclr %1,%0\";
+}")
+
+;; Special cases of bit-field insns which we should
+;; recognize in preference to the general case.
+;; These handle aligned 8-bit and 16-bit fields,
+;; which can usually be done with move instructions.
+
+;
+; Special case for 32-bit field in memory. This only occurs when 32-bit
+; alignment of structure members is specified.
+;
+; The move is allowed to be odd byte aligned, because that's still faster
+; than an odd byte aligned bit field instruction.
+;
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
+ (const_int 32)
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "general_operand" "rmi"))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && (INTVAL (operands[2]) % 8) == 0
+ && ! mode_dependent_address_p (XEXP (operands[0], 0))"
+ "*
+{
+ operands[0]
+ = adj_offsettable_operand (operands[0], INTVAL (operands[2]) / 8);
+
+ return \"move%.l %3,%0\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+do")
+ (match_operand:SI 1 "const_int_operand" "n")
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "register_operand" "d"))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && (INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
+ && INTVAL (operands[2]) % INTVAL (operands[1]) == 0
+ && (GET_CODE (operands[0]) == REG
+ || ! mode_dependent_address_p (XEXP (operands[0], 0)))"
+ "*
+{
+ if (REG_P (operands[0]))
+ {
+ if (INTVAL (operands[1]) + INTVAL (operands[2]) != 32)
+ return \"bfins %3,%0{%b2:%b1}\";
+ }
+ else
+ operands[0]
+ = adj_offsettable_operand (operands[0], INTVAL (operands[2]) / 8);
+
+ if (GET_CODE (operands[3]) == MEM)
+ operands[3] = adj_offsettable_operand (operands[3],
+ (32 - INTVAL (operands[1])) / 8);
+ if (INTVAL (operands[1]) == 8)
+ return \"move%.b %3,%0\";
+ return \"move%.w %3,%0\";
+}")
+
+
+;
+; Special case for 32-bit field in memory. This only occurs when 32-bit
+; alignment of structure members is specified.
+;
+; The move is allowed to be odd byte aligned, because that's still faster
+; than an odd byte aligned bit field instruction.
+;
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=rm")
+ (zero_extract:SI (match_operand:QI 1 "memory_operand" "o")
+ (const_int 32)
+ (match_operand:SI 3 "const_int_operand" "n")))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && (INTVAL (operands[3]) % 8) == 0
+ && ! mode_dependent_address_p (XEXP (operands[1], 0))"
+ "*
+{
+ operands[1]
+ = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+
+ return \"move%.l %1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=&d")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "do")
+ (match_operand:SI 2 "const_int_operand" "n")
+ (match_operand:SI 3 "const_int_operand" "n")))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+ && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
+ && (GET_CODE (operands[1]) == REG
+ || ! mode_dependent_address_p (XEXP (operands[1], 0)))"
+ "*
+{
+ cc_status.flags |= CC_NOT_NEGATIVE;
+ if (REG_P (operands[1]))
+ {
+ if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32)
+ return \"bfextu %1{%b3:%b2},%0\";
+ }
+ else
+ operands[1]
+ = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+
+ output_asm_insn (\"clr%.l %0\", operands);
+ if (GET_CODE (operands[0]) == MEM)
+ operands[0] = adj_offsettable_operand (operands[0],
+ (32 - INTVAL (operands[1])) / 8);
+ if (INTVAL (operands[2]) == 8)
+ return \"move%.b %1,%0\";
+ return \"move%.w %1,%0\";
+}")
+
+;
+; Special case for 32-bit field in memory. This only occurs when 32-bit
+; alignment of structure members is specified.
+;
+; The move is allowed to be odd byte aligned, because that's still faster
+; than an odd byte aligned bit field instruction.
+;
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=rm")
+ (sign_extract:SI (match_operand:QI 1 "memory_operand" "o")
+ (const_int 32)
+ (match_operand:SI 3 "const_int_operand" "n")))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && (INTVAL (operands[3]) % 8) == 0
+ && ! mode_dependent_address_p (XEXP (operands[1], 0))"
+ "*
+{
+ operands[1]
+ = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+
+ return \"move%.l %1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (sign_extract:SI (match_operand:SI 1 "register_operand" "do")
+ (match_operand:SI 2 "const_int_operand" "n")
+ (match_operand:SI 3 "const_int_operand" "n")))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+ && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
+ && (GET_CODE (operands[1]) == REG
+ || ! mode_dependent_address_p (XEXP (operands[1], 0)))"
+ "*
+{
+ if (REG_P (operands[1]))
+ {
+ if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32)
+ return \"bfexts %1{%b3:%b2},%0\";
+ }
+ else
+ operands[1]
+ = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+
+ if (INTVAL (operands[2]) == 8)
+ return \"move%.b %1,%0\;extb%.l %0\";
+ return \"move%.w %1,%0\;ext%.l %0\";
+}")
+
+;; Bit field instructions, general cases.
+;; "o,d" constraint causes a nonoffsettable memref to match the "o"
+;; so that its address is reloaded.
+
+(define_expand "extv"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (sign_extract:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")
+ (match_operand:SI 3 "general_operand" "")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (sign_extract:SI (match_operand:QI 1 "memory_operand" "o")
+ (match_operand:SI 2 "general_operand" "di")
+ (match_operand:SI 3 "general_operand" "di")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "bfexts %1{%b3:%b2},%0")
+
+(define_expand "extzv"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (zero_extract:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")
+ (match_operand:SI 3 "general_operand" "")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d,d")
+ (zero_extract:SI (match_operand:QI 1 "memory_operand" "o,d")
+ (match_operand:SI 2 "general_operand" "di,di")
+ (match_operand:SI 3 "general_operand" "di,di")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (INTVAL (operands[2]) != 32)
+ cc_status.flags |= CC_NOT_NEGATIVE;
+ }
+ else
+ {
+ CC_STATUS_INIT;
+ }
+ return \"bfextu %1{%b3:%b2},%0\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ (xor:SI (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2))
+ (match_operand 3 "const_int_operand" "n")))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && (INTVAL (operands[3]) == -1
+ || (GET_CODE (operands[1]) == CONST_INT
+ && (~ INTVAL (operands[3]) & ((1 << INTVAL (operands[1]))- 1)) == 0))"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bfchg %0{%b2:%b1}\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ (const_int 0))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bfclr %0{%b2:%b1}\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ (const_int -1))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bfset %0{%b2:%b1}\";
+}")
+
+(define_expand "insv"
+ [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "")
+ (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" ""))
+ (match_operand:SI 3 "register_operand" ""))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ (match_operand:SI 3 "register_operand" "d"))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "bfins %3,%0{%b2:%b1}")
+
+;; Now recognize bit field insns that operate on registers
+;; (or at least were intended to do so).
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (sign_extract:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "general_operand" "di")
+ (match_operand:SI 3 "general_operand" "di")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "bfexts %1{%b3:%b2},%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "general_operand" "di")
+ (match_operand:SI 3 "general_operand" "di")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (INTVAL (operands[2]) != 32)
+ cc_status.flags |= CC_NOT_NEGATIVE;
+ }
+ else
+ {
+ CC_STATUS_INIT;
+ }
+ return \"bfextu %1{%b3:%b2},%0\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ (const_int 0))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bfclr %0{%b2:%b1}\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ (const_int -1))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bfset %0{%b2:%b1}\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ (match_operand:SI 3 "register_operand" "d"))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+#if 0
+ /* These special cases are now recognized by a specific pattern. */
+ if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[1]) == 16 && INTVAL (operands[2]) == 16)
+ return \"move%.w %3,%0\";
+ if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[1]) == 24 && INTVAL (operands[2]) == 8)
+ return \"move%.b %3,%0\";
+#endif
+ return \"bfins %3,%0{%b2:%b1}\";
+}")
+
+;; Special patterns for optimizing bit-field instructions.
+
+(define_insn ""
+ [(set (cc0)
+ (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
+ (match_operand:SI 1 "const_int_operand" "n")
+ (match_operand:SI 2 "general_operand" "di")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ if (operands[1] == const1_rtx
+ && GET_CODE (operands[2]) == CONST_INT)
+ {
+ int width = GET_CODE (operands[0]) == REG ? 31 : 7;
+ return output_btst (operands,
+ GEN_INT (width - INTVAL (operands[2])),
+ operands[0],
+ insn, 1000);
+ /* Pass 1000 as SIGNPOS argument so that btst will
+ not think we are testing the sign bit for an `and'
+ and assume that nonzero implies a negative result. */
+ }
+ if (INTVAL (operands[1]) != 32)
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return \"bftst %0{%b2:%b1}\";
+}")
+
+
+;;; now handle the register cases
+(define_insn ""
+ [(set (cc0)
+ (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
+ (match_operand:SI 1 "const_int_operand" "n")
+ (match_operand:SI 2 "general_operand" "di")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ if (operands[1] == const1_rtx
+ && GET_CODE (operands[2]) == CONST_INT)
+ {
+ int width = GET_CODE (operands[0]) == REG ? 31 : 7;
+ return output_btst (operands,
+ GEN_INT (width - INTVAL (operands[2])),
+ operands[0],
+ insn, 1000);
+ /* Pass 1000 as SIGNPOS argument so that btst will
+ not think we are testing the sign bit for an `and'
+ and assume that nonzero implies a negative result. */
+ }
+ if (INTVAL (operands[1]) != 32)
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return \"bftst %0{%b2:%b1}\";
+}")
+
+(define_insn "scc0_di"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (match_operator 1 "valid_dbcc_comparison_p"
+ [(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))]
+ "! TARGET_5200"
+ "*
+{
+ return output_scc_di (operands[1], operands[2], const0_rtx, operands[0]);
+} ")
+
+(define_insn "scc0_di_5200"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (match_operator 1 "valid_dbcc_comparison_p"
+ [(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))]
+ "TARGET_5200"
+ "*
+{
+ return output_scc_di (operands[1], operands[2], const0_rtx, operands[0]);
+} ")
+
+(define_insn "scc_di"
+ [(set (match_operand:QI 0 "general_operand" "=dm,dm")
+ (match_operator 1 "valid_dbcc_comparison_p"
+ [(match_operand:DI 2 "general_operand" "ro,r")
+ (match_operand:DI 3 "general_operand" "r,ro")]))]
+ "! TARGET_5200"
+ "*
+{
+ return output_scc_di (operands[1], operands[2], operands[3], operands[0]);
+} ")
+
+(define_insn "scc_di_5200"
+ [(set (match_operand:QI 0 "general_operand" "=d,d")
+ (match_operator 1 "valid_dbcc_comparison_p"
+ [(match_operand:DI 2 "general_operand" "ro,r")
+ (match_operand:DI 3 "general_operand" "r,ro")]))]
+ "TARGET_5200"
+ "*
+{
+ return output_scc_di (operands[1], operands[2], operands[3], operands[0]);
+} ")
+
+(define_expand "seq"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (eq:QI (cc0) (const_int 0)))]
+ ""
+ "
+{
+ if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+ {
+ m68k_last_compare_had_fp_operands = 0;
+ FAIL;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (eq:QI (cc0) (const_int 0)))]
+ "! TARGET_5200"
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"seq %0\", \"fseq %0\", \"seq %0\");
+")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (eq:QI (cc0) (const_int 0)))]
+ "TARGET_5200"
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"seq %0\", \"fseq %0\", \"seq %0\");
+")
+
+(define_expand "sne"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (ne:QI (cc0) (const_int 0)))]
+ ""
+ "
+{
+ if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+ {
+ m68k_last_compare_had_fp_operands = 0;
+ FAIL;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (ne:QI (cc0) (const_int 0)))]
+ "! TARGET_5200"
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"sne %0\", \"fsne %0\", \"sne %0\");
+")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (ne:QI (cc0) (const_int 0)))]
+ "TARGET_5200"
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"sne %0\", \"fsne %0\", \"sne %0\");
+")
+
+(define_expand "sgt"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (gt:QI (cc0) (const_int 0)))]
+ ""
+ "
+{
+ if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+ {
+ m68k_last_compare_had_fp_operands = 0;
+ FAIL;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (gt:QI (cc0) (const_int 0)))]
+ "! TARGET_5200"
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"sgt %0\", \"fsgt %0\", 0);
+")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (gt:QI (cc0) (const_int 0)))]
+ "TARGET_5200"
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"sgt %0\", \"fsgt %0\", 0);
+")
+
+(define_expand "sgtu"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (gtu:QI (cc0) (const_int 0)))]
+ ""
+ "")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (gtu:QI (cc0) (const_int 0)))]
+ "! TARGET_5200"
+ "* cc_status = cc_prev_status;
+ return \"shi %0\"; ")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (gtu:QI (cc0) (const_int 0)))]
+ "TARGET_5200"
+ "* cc_status = cc_prev_status;
+ return \"shi %0\"; ")
+
+(define_expand "slt"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (lt:QI (cc0) (const_int 0)))]
+ ""
+ "
+{
+ if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+ {
+ m68k_last_compare_had_fp_operands = 0;
+ FAIL;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (lt:QI (cc0) (const_int 0)))]
+ "! TARGET_5200"
+ "* cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"slt %0\", \"fslt %0\", \"smi %0\"); ")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (lt:QI (cc0) (const_int 0)))]
+ "TARGET_5200"
+ "* cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"slt %0\", \"fslt %0\", \"smi %0\"); ")
+
+(define_expand "sltu"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (ltu:QI (cc0) (const_int 0)))]
+ ""
+ "")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (ltu:QI (cc0) (const_int 0)))]
+ "! TARGET_5200"
+ "* cc_status = cc_prev_status;
+ return \"scs %0\"; ")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (ltu:QI (cc0) (const_int 0)))]
+ "TARGET_5200"
+ "* cc_status = cc_prev_status;
+ return \"scs %0\"; ")
+
+(define_expand "sge"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (ge:QI (cc0) (const_int 0)))]
+ ""
+ "
+{
+ if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+ {
+ m68k_last_compare_had_fp_operands = 0;
+ FAIL;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (ge:QI (cc0) (const_int 0)))]
+ "! TARGET_5200"
+ "* cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"sge %0\", \"fsge %0\", \"spl %0\"); ")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (ge:QI (cc0) (const_int 0)))]
+ "TARGET_5200"
+ "* cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"sge %0\", \"fsge %0\", \"spl %0\"); ")
+
+(define_expand "sgeu"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (geu:QI (cc0) (const_int 0)))]
+ ""
+ "")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (geu:QI (cc0) (const_int 0)))]
+ "! TARGET_5200"
+ "* cc_status = cc_prev_status;
+ return \"scc %0\"; ")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (geu:QI (cc0) (const_int 0)))]
+ "TARGET_5200"
+ "* cc_status = cc_prev_status;
+ return \"scc %0\"; ")
+
+(define_expand "sle"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (le:QI (cc0) (const_int 0)))]
+ ""
+ "
+{
+ if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+ {
+ m68k_last_compare_had_fp_operands = 0;
+ FAIL;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (le:QI (cc0) (const_int 0)))]
+ "! TARGET_5200"
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"sle %0\", \"fsle %0\", 0);
+")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (le:QI (cc0) (const_int 0)))]
+ "TARGET_5200"
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"sle %0\", \"fsle %0\", 0);
+")
+
+(define_expand "sleu"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (leu:QI (cc0) (const_int 0)))]
+ ""
+ "")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (leu:QI (cc0) (const_int 0)))]
+ "! TARGET_5200"
+ "* cc_status = cc_prev_status;
+ return \"sls %0\"; ")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (leu:QI (cc0) (const_int 0)))]
+ "TARGET_5200"
+ "* cc_status = cc_prev_status;
+ return \"sls %0\"; ")
+
+;; Basic conditional jump instructions.
+
+(define_insn "beq0_di"
+ [(set (pc)
+ (if_then_else (eq (match_operand:DI 0 "general_operand" "d*ao,<>")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ","))
+ (pc)))
+ (clobber (match_scratch:SI 2 "=d,d"))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (which_alternative == 1)
+#ifdef MOTOROLA
+ return \"move%.l %0,%2\;or%.l %0,%2\;jbeq %l1\";
+#else
+ return \"move%.l %0,%2\;or%.l %0,%2\;jeq %l1\";
+#endif
+ if ((cc_prev_status.value1
+ && rtx_equal_p (cc_prev_status.value1, operands[0]))
+ || (cc_prev_status.value2
+ && rtx_equal_p (cc_prev_status.value2, operands[0])))
+ {
+ cc_status = cc_prev_status;
+#ifdef MOTOROLA
+ return \"jbeq %l1\";
+#else
+ return \"jeq %l1\";
+#endif
+ }
+ if (GET_CODE (operands[0]) == REG)
+ operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ else
+ operands[3] = adj_offsettable_operand (operands[0], 4);
+ if (! ADDRESS_REG_P (operands[0]))
+ {
+ if (reg_overlap_mentioned_p (operands[2], operands[0]))
+ {
+ if (reg_overlap_mentioned_p (operands[2], operands[3]))
+ {
+#ifdef MOTOROLA
+ return \"or%.l %0,%2\;jbeq %l1\";
+#else
+ return \"or%.l %0,%2\;jeq %l1\";
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ return \"or%.l %3,%2\;jbeq %l1\";
+#else
+ return \"or%.l %3,%2\;jeq %l1\";
+#endif
+ }
+ }
+#ifdef MOTOROLA
+ return \"move%.l %0,%2\;or%.l %3,%2\;jbeq %l1\";
+#else
+ return \"move%.l %0,%2\;or%.l %3,%2\;jeq %l1\";
+#endif
+ }
+ operands[4] = gen_label_rtx();
+ if (TARGET_68020 || TARGET_5200)
+ {
+#ifdef MOTOROLA
+ output_asm_insn (\"tst%.l %0\;jbne %l4\;tst%.l %3\;jbeq %l1\", operands);
+#else
+ output_asm_insn (\"tst%.l %0\;jne %l4\;tst%.l %3\;jeq %l1\", operands);
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+#ifdef SGS_CMP_ORDER
+ output_asm_insn (\"cmp%.w %0,%#0\;jbne %l4\;cmp%.w %3,%#0\;jbeq %l1\", operands);
+#else
+ output_asm_insn (\"cmp%.w %#0,%0\;jbne %l4\;cmp%.w %#0,%3\;jbeq %l1\", operands);
+#endif
+#else
+ output_asm_insn (\"cmp%.w %#0,%0\;jne %l4\;cmp%.w %#0,%3\;jeq %l1\", operands);
+#endif
+ }
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (operands[4]));
+ return \"\";
+} ")
+
+(define_insn "bne0_di"
+ [(set (pc)
+ (if_then_else (ne (match_operand:DI 0 "general_operand" "do,*a")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ","))
+ (pc)))
+ (clobber (match_scratch:SI 2 "=d,X"))]
+ ""
+ "*
+{
+ if ((cc_prev_status.value1
+ && rtx_equal_p (cc_prev_status.value1, operands[0]))
+ || (cc_prev_status.value2
+ && rtx_equal_p (cc_prev_status.value2, operands[0])))
+ {
+ cc_status = cc_prev_status;
+#ifdef MOTOROLA
+ return \"jbne %l1\";
+#else
+ return \"jne %l1\";
+#endif
+ }
+ CC_STATUS_INIT;
+ if (GET_CODE (operands[0]) == REG)
+ operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ else
+ operands[3] = adj_offsettable_operand (operands[0], 4);
+ if (!ADDRESS_REG_P (operands[0]))
+ {
+ if (reg_overlap_mentioned_p (operands[2], operands[0]))
+ {
+ if (reg_overlap_mentioned_p (operands[2], operands[3]))
+ {
+#ifdef MOTOROLA
+ return \"or%.l %0,%2\;jbne %l1\";
+#else
+ return \"or%.l %0,%2\;jne %l1\";
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ return \"or%.l %3,%2\;jbne %l1\";
+#else
+ return \"or%.l %3,%2\;jne %l1\";
+#endif
+ }
+ }
+#ifdef MOTOROLA
+ return \"move%.l %0,%2\;or%.l %3,%2\;jbne %l1\";
+#else
+ return \"move%.l %0,%2\;or%.l %3,%2\;jne %l1\";
+#endif
+ }
+ if (TARGET_68020 || TARGET_5200)
+ {
+#ifdef MOTOROLA
+ return \"tst%.l %0\;jbne %l1\;tst%.l %3\;jbne %l1\";
+#else
+ return \"tst%.l %0\;jne %l1\;tst%.l %3\;jne %l1\";
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+#ifdef SGS_CMP_ORDER
+ return \"cmp%.w %0,%#0\;jbne %l1\;cmp%.w %3,%#0\;jbne %l1\";
+#else
+ return \"cmp%.w %#0,%0\;jbne %l1\;cmp%.w %#0,%3\;jbne %l1\";
+#endif
+#else
+ return \"cmp%.w %#0,%0\;jne %l1\;cmp%.w %#0,%3\;jne %l1\";
+#endif
+ }
+} ")
+
+(define_insn "bge0_di"
+ [(set (pc)
+ (if_then_else (ge (match_operand:DI 0 "general_operand" "ro")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ if ((cc_prev_status.value1
+ && rtx_equal_p (cc_prev_status.value1, operands[0]))
+ || (cc_prev_status.value2
+ && rtx_equal_p (cc_prev_status.value2, operands[0])))
+ {
+ cc_status = cc_prev_status;
+ if (cc_status.flags & CC_REVERSED)
+ {
+#ifdef MOTOROLA
+ return \"jble %l1\";
+#else
+ return \"jle %l1\";
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ return \"jbpl %l1\";
+#else
+ return \"jpl %l1\";
+#endif
+ }
+ }
+ CC_STATUS_INIT;
+ if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (operands[0]))
+ output_asm_insn(\"tst%.l %0\", operands);
+ else
+ {
+ /* On an address reg, cmpw may replace cmpl. */
+#ifdef SGS_CMP_ORDER
+ output_asm_insn(\"cmp%.w %0,%#0\", operands);
+#else
+ output_asm_insn(\"cmp%.w %#0,%0\", operands);
+#endif
+ }
+
+#ifdef MOTOROLA
+ return \"jbpl %l1\";
+#else
+ return \"jpl %l1\";
+#endif
+} ")
+
+(define_insn "blt0_di"
+ [(set (pc)
+ (if_then_else (lt (match_operand:DI 0 "general_operand" "ro")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ if ((cc_prev_status.value1
+ && rtx_equal_p (cc_prev_status.value1, operands[0]))
+ || (cc_prev_status.value2
+ && rtx_equal_p (cc_prev_status.value2, operands[0])))
+ {
+ cc_status = cc_prev_status;
+ if (cc_status.flags & CC_REVERSED)
+ {
+#ifdef MOTOROLA
+ return \"jbgt %l1\";
+#else
+ return \"jgt %l1\";
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ return \"jbmi %l1\";
+#else
+ return \"jmi %l1\";
+#endif
+ }
+ }
+ CC_STATUS_INIT;
+ if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (operands[0]))
+ output_asm_insn(\"tst%.l %0\", operands);
+ else
+ {
+ /* On an address reg, cmpw may replace cmpl. */
+#ifdef SGS_CMP_ORDER
+ output_asm_insn(\"cmp%.w %0,%#0\", operands);
+#else
+ output_asm_insn(\"cmp%.w %#0,%0\", operands);
+#endif
+ }
+
+#ifdef MOTOROLA
+ return \"jbmi %l1\";
+#else
+ return \"jmi %l1\";
+#endif
+} ")
+
+(define_insn "beq"
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jbeq %l0\", \"fbeq %l0\", \"jbeq %l0\");
+#else
+ OUTPUT_JUMP (\"jeq %l0\", \"fjeq %l0\", \"jeq %l0\");
+#endif
+}")
+
+(define_insn "bne"
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jbne %l0\", \"fbne %l0\", \"jbne %l0\");
+#else
+ OUTPUT_JUMP (\"jne %l0\", \"fjne %l0\", \"jne %l0\");
+#endif
+}")
+
+(define_insn "bgt"
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jbgt %l0\", \"fbgt %l0\", 0);
+#else
+ OUTPUT_JUMP (\"jgt %l0\", \"fjgt %l0\", 0);
+#endif
+")
+
+(define_insn "bgtu"
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbhi %l0\";
+#else
+ return \"jhi %l0\";
+#endif
+")
+
+(define_insn "blt"
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jblt %l0\", \"fblt %l0\", \"jbmi %l0\");
+#else
+ OUTPUT_JUMP (\"jlt %l0\", \"fjlt %l0\", \"jmi %l0\");
+#endif
+")
+
+(define_insn "bltu"
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbcs %l0\";
+#else
+ return \"jcs %l0\";
+#endif
+")
+
+(define_insn "bge"
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jbge %l0\", \"fbge %l0\", \"jbpl %l0\");
+#else
+ OUTPUT_JUMP (\"jge %l0\", \"fjge %l0\", \"jpl %l0\");
+#endif
+")
+
+(define_insn "bgeu"
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbcc %l0\";
+#else
+ return \"jcc %l0\";
+#endif
+")
+
+(define_insn "ble"
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jble %l0\", \"fble %l0\", 0);
+#else
+ OUTPUT_JUMP (\"jle %l0\", \"fjle %l0\", 0);
+#endif
+")
+
+(define_insn "bleu"
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbls %l0\";
+#else
+ return \"jls %l0\";
+#endif
+")
+
+;; Negated conditional jump instructions.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jbne %l0\", \"fbne %l0\", \"jbne %l0\");
+#else
+ OUTPUT_JUMP (\"jne %l0\", \"fjne %l0\", \"jne %l0\");
+#endif
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jbeq %l0\", \"fbeq %l0\", \"jbeq %l0\");
+#else
+ OUTPUT_JUMP (\"jeq %l0\", \"fjeq %l0\", \"jeq %l0\");
+#endif
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jble %l0\", \"fbngt %l0\", 0);
+#else
+ OUTPUT_JUMP (\"jle %l0\", \"fjngt %l0\", 0);
+#endif
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbls %l0\";
+#else
+ return \"jls %l0\";
+#endif
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jbge %l0\", \"fbnlt %l0\", \"jbpl %l0\");
+#else
+ OUTPUT_JUMP (\"jge %l0\", \"fjnlt %l0\", \"jpl %l0\");
+#endif
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbcc %l0\";
+#else
+ return \"jcc %l0\";
+#endif
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jblt %l0\", \"fbnge %l0\", \"jbmi %l0\");
+#else
+ OUTPUT_JUMP (\"jlt %l0\", \"fjnge %l0\", \"jmi %l0\");
+#endif
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbcs %l0\";
+#else
+ return \"jcs %l0\";
+#endif
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jbgt %l0\", \"fbnle %l0\", 0);
+#else
+ OUTPUT_JUMP (\"jgt %l0\", \"fjnle %l0\", 0);
+#endif
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbhi %l0\";
+#else
+ return \"jhi %l0\";
+#endif
+")
+
+;; Unconditional and other jump instructions
+(define_insn "jump"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbra %l0\";
+#else
+ return \"jra %l0\";
+#endif
+")
+
+;; We support two different ways of handling dispatch tables.
+;; The NeXT uses absolute tables, and other machines use relative.
+;; This define_expand can generate either kind.
+(define_expand "tablejump"
+ [(parallel [(set (pc) (match_operand 0 "" ""))
+ (use (label_ref (match_operand 1 "" "")))])]
+ ""
+ "
+{
+#ifdef CASE_VECTOR_PC_RELATIVE
+ operands[0] = gen_rtx_PLUS (SImode, pc_rtx,
+ gen_rtx_SIGN_EXTEND (SImode, operands[0]));
+#endif
+}")
+
+;; Jump to variable address from dispatch table of absolute addresses.
+(define_insn ""
+ [(set (pc) (match_operand:SI 0 "register_operand" "a"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jmp (%0)\";
+#else
+ return \"jmp %0@\";
+#endif
+")
+
+;; Jump to variable address from dispatch table of relative addresses.
+(define_insn ""
+ [(set (pc)
+ (plus:SI (pc)
+ (sign_extend:SI (match_operand:HI 0 "register_operand" "r"))))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "*
+#ifdef ASM_RETURN_CASE_JUMP
+ ASM_RETURN_CASE_JUMP;
+#else
+#ifdef SGS
+#ifdef ASM_OUTPUT_CASE_LABEL
+ if (TARGET_5200)
+ return \"ext%.l %0\;jmp 6(%%pc,%0.l)\";
+ else
+ return \"jmp 6(%%pc,%0.w)\";
+#else
+ if (TARGET_5200)
+ {
+#ifdef CRDS
+ return \"ext%.l %0\;jmp 2(pc,%0.l)\";
+#else
+ return \"extl %0\;jmp 2(%%pc,%0.l)\";
+#endif /* end !CRDS */
+ }
+ else
+ {
+#ifdef CRDS
+ return \"jmp 2(pc,%0.w)\";
+#else
+ return \"jmp 2(%%pc,%0.w)\";
+#endif /* end !CRDS */
+ }
+#endif
+#else /* not SGS */
+ if (TARGET_5200)
+ {
+#ifdef MOTOROLA
+ return \"ext%.l %0\;jmp (2,pc,%0.l)\";
+#else
+ return \"extl %0\;jmp pc@(2,%0:l)\";
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ return \"jmp (2,pc,%0.w)\";
+#else
+ return \"jmp pc@(2,%0:w)\";
+#endif
+ }
+#endif
+#endif
+")
+
+;; Decrement-and-branch insns.
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (match_operand:HI 0 "general_operand" "+d*g")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:HI (match_dup 0)
+ (const_int -1)))]
+ "!TARGET_5200"
+ "*
+{
+ CC_STATUS_INIT;
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ {
+#ifdef MOTOROLA
+#ifdef NO_ADDSUB_Q
+ return \"sub%.w %#1,%0\;jbcc %l1\";
+#else
+ return \"subq%.w %#1,%0\;jbcc %l1\";
+#endif
+#else /* not MOTOROLA */
+ return \"subqw %#1,%0\;jcc %l1\";
+#endif
+ }
+#ifdef MOTOROLA
+#ifdef SGS_CMP_ORDER
+#ifdef NO_ADDSUB_Q
+ return \"sub%.w %#1,%0\;cmp%.w %0,%#-1\;jbne %l1\";
+#else
+ return \"subq%.w %#1,%0\;cmp%.w %0,%#-1\;jbne %l1\";
+#endif
+#else /* not SGS_CMP_ORDER */
+ return \"subq%.w %#1,%0\;cmp%.w %#-1,%0\;jbne %l1\";
+#endif
+#else /* not MOTOROLA */
+ return \"subqw %#1,%0\;cmpw %#-1,%0\;jne %l1\";
+#endif
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (match_operand:SI 0 "general_operand" "+d*g")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))]
+ "!TARGET_5200"
+ "*
+{
+ CC_STATUS_INIT;
+#ifdef MOTOROLA
+#ifdef NO_ADDSUB_Q
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\;clr%.w %0\;sub%.l %#1,%0\;jbcc %l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ return \"sub%.l %#1,%0\;jbcc %l1\";
+#else
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\;clr%.w %0\;subq%.l %#1,%0\;jbcc %l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ return \"subq%.l %#1,%0\;jbcc %l1\";
+#endif /* NO_ADDSUB_Q */
+#ifdef SGS_CMP_ORDER
+#ifdef NO_ADDSUB_Q
+ return \"sub.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\";
+#else
+ return \"subq.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\";
+#endif
+#else /* not SGS_CMP_ORDER */
+ return \"subq.l %#1,%0\;cmp.l %#-1,%0\;jbne %l1\";
+#endif /* not SGS_CMP_ORDER */
+#else /* not MOTOROLA */
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\;clr%.w %0\;subql %#1,%0\;jcc %l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ return \"subql %#1,%0\;jcc %l1\";
+ return \"subql %#1,%0\;cmpl %#-1,%0\;jne %l1\";
+#endif /* not MOTOROLA */
+}")
+
+;; Two dbra patterns that use REG_NOTES info generated by strength_reduce.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ge (plus:HI (match_operand:HI 0 "general_operand" "+d*am")
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:HI (match_dup 0)
+ (const_int -1)))]
+ "!TARGET_5200 && find_reg_note (insn, REG_NONNEG, 0)"
+ "*
+{
+ CC_STATUS_INIT;
+#ifdef MOTOROLA
+#ifdef NO_ADDSUB_Q
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ return \"sub%.w %#1,%0\;jbcc %l1\";
+#else
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ return \"subq%.w %#1,%0\;jbcc %l1\";
+#endif
+#ifdef SGS_CMP_ORDER
+#ifdef NO_ADDSUB_Q
+ return \"sub.w %#1,%0\;cmp.w %0,%#-1\;jbne %l1\";
+#else
+ return \"subq.w %#1,%0\;cmp.w %0,%#-1\;jbne %l1\";
+#endif
+#else /* not SGS_CMP_ORDER */
+ return \"subq.w %#1,%0\;cmp.w %#-1,%0\;jbne %l1\";
+#endif /* not SGS_CMP_ORDER */
+#else /* not MOTOROLA */
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ return \"subqw %#1,%0\;jcc %l1\";
+ return \"subqw %#1,%0\;cmpw %#-1,%0\;jne %l1\";
+#endif /* not MOTOROLA */
+}")
+
+(define_expand "decrement_and_branch_until_zero"
+ [(parallel [(set (pc)
+ (if_then_else
+ (ge (plus:SI (match_operand:SI 0 "general_operand" "")
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))])]
+ ""
+ "")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ge (plus:SI (match_operand:SI 0 "general_operand" "+d*am")
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))]
+ "!TARGET_5200 && find_reg_note (insn, REG_NONNEG, 0)"
+ "*
+{
+ CC_STATUS_INIT;
+#ifdef MOTOROLA
+#ifdef NO_ADDSUB_Q
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\;clr%.w %0\;sub%.l %#1,%0\;jbcc %l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ return \"sub%.l %#1,%0\;jbcc %l1\";
+#else
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\;clr%.w %0\;subq%.l %#1,%0\;jbcc %l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ return \"subq%.l %#1,%0\;jbcc %l1\";
+#endif
+#ifdef SGS_CMP_ORDER
+#ifdef NO_ADDSUB_Q
+ return \"sub.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\";
+#else
+ return \"subq.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\";
+#endif
+#else /* not SGS_CMP_ORDER */
+ return \"subq.l %#1,%0\;cmp.l %#-1,%0\;jbne %l1\";
+#endif /* not SGS_CMP_ORDER */
+#else /* not MOTOROLA */
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\;clr%.w %0\;subql %#1,%0\;jcc %l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ return \"subql %#1,%0\;jcc %l1\";
+ return \"subql %#1,%0\;cmpl %#-1,%0\;jne %l1\";
+#endif /* not MOTOROLA */
+}")
+
+
+;; For PIC calls, in order to be able to support
+;; dynamic linker LAZY BINDING, all the procedure calls need to go
+;; through the PLT (Procedure Linkage Table) section in PIC mode.
+;;
+;; PIC calls are handled by loading the address of the function into a
+;; register (via movsi), then emitting a register indirect call using
+;; the "jsr" function call syntax.
+;;
+;; When outputting MIT syntax (e.g. on Suns), we add a bogus extra
+;; operand to the jbsr statement to indicate that this call should
+;; go through the PLT (why? because this is the way that Sun does it).
+;;
+;; We have different patterns for PIC calls and non-PIC calls. The
+;; different patterns are only used to choose the right syntax.
+;;
+;; The svr4 m68k assembler recognizes this syntax: `bsr FUNC@PLTPC' and it
+;; will create the correct relocation entry (R_68K_PLT32) for `FUNC',
+;; that tells the linker editor to create an entry for `FUNC' in PLT
+;; section at link time. However, all global objects reference are still
+;; done by using `OBJ@GOT'. So, the goal here is to output the function
+;; call operand as `FUNC@PLTPC', but output object operand as `OBJ@GOT'.
+;; We need to have a way to differentiate these two different operands.
+;;
+;; The strategy I use here is to use SYMBOL_REF_FLAG to differentiate
+;; these two different operands. The macro LEGITIMATE_PIC_OPERAND_P needs
+;; to be changed to recognize function calls symbol_ref operand as a valid
+;; PIC operand (by checking whether SYMBOL_REF_FLAG is set). This will
+;; avoid the compiler to load this symbol_ref operand into a register.
+;; Remember, the operand "foo@PLTPC" cannot be called via jsr directly
+;; since the value is a PC relative offset, not a real address.
+;;
+;; All global objects are treated in the similar way as in SUN3. The only
+;; difference is: on m68k svr4, the reference of such global object needs
+;; to end with a suffix "@GOT" so the assembler and linker know to create
+;; an entry for it in GOT (Global Offset Table) section. This is done in
+;; m68k.c.
+
+;; Call subroutine with no return value.
+(define_expand "call"
+ [(call (match_operand:QI 0 "memory_operand" "")
+ (match_operand:SI 1 "general_operand" ""))]
+ ;; Operand 1 not really used on the m68000.
+
+ ""
+ "
+{
+ if (flag_pic && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
+ SYMBOL_REF_FLAG (XEXP (operands[0], 0)) = 1;
+}")
+
+;; This is a normal call sequence.
+(define_insn ""
+ [(call (match_operand:QI 0 "memory_operand" "o")
+ (match_operand:SI 1 "general_operand" "g"))]
+ ;; Operand 1 not really used on the m68000.
+
+ "! flag_pic"
+ "*
+#if defined (MOTOROLA) && !defined (USE_GAS)
+#ifdef MOTOROLA_BSR
+ if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
+ return \"bsr %0\";
+#endif
+ return \"jsr %0\";
+#else
+ return \"jbsr %0\";
+#endif
+")
+
+;; This is a PIC call sequence.
+(define_insn ""
+ [(call (match_operand:QI 0 "memory_operand" "o")
+ (match_operand:SI 1 "general_operand" "g"))]
+ ;; Operand 1 not really used on the m68000.
+
+ "flag_pic"
+ "*
+ if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
+#ifdef MOTOROLA
+#ifdef HPUX_ASM
+ return \"bsr.l %0\";
+#else
+#ifdef USE_GAS
+ return \"bsr.l %0@PLTPC\";
+#else
+ return \"bsr %0@PLTPC\";
+#endif
+#endif
+#else
+ /* The ',a1' is a dummy argument telling the Sun assembler we want PIC,
+ GAS just plain ignores it. */
+ return \"jbsr %0,a1\";
+#endif
+ return \"jsr %0\";
+")
+
+;; Call subroutine, returning value in operand 0
+;; (which must be a hard register).
+;; See comments before "call" regarding PIC calls.
+(define_expand "call_value"
+ [(set (match_operand 0 "" "")
+ (call (match_operand:QI 1 "memory_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ ;; Operand 2 not really used on the m68000.
+ ""
+ "
+{
+ if (flag_pic && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
+ SYMBOL_REF_FLAG (XEXP (operands[1], 0)) = 1;
+}")
+
+;; This is a normal call_value
+(define_insn ""
+ [(set (match_operand 0 "" "=rf")
+ (call (match_operand:QI 1 "memory_operand" "o")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ;; Operand 2 not really used on the m68000.
+ "! flag_pic"
+ "*
+#if defined (MOTOROLA) && !defined (USE_GAS)
+#ifdef MOTOROLA_BSR
+ if (GET_CODE (operands[1]) == MEM
+ && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
+ return \"bsr %1\";
+#endif
+ return \"jsr %1\";
+#else
+ return \"jbsr %1\";
+#endif
+")
+
+;; This is a PIC call_value
+(define_insn ""
+ [(set (match_operand 0 "" "=rf")
+ (call (match_operand:QI 1 "memory_operand" "o")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ;; Operand 2 not really used on the m68000.
+ "flag_pic"
+ "*
+ if (GET_CODE (operands[1]) == MEM
+ && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
+ {
+#ifdef MOTOROLA
+#ifdef HPUX_ASM
+ return \"bsr.l %1\";
+#else
+#ifdef USE_GAS
+ return \"bsr.l %1@PLTPC\";
+#else
+ return \"bsr %1@PLTPC\";
+#endif
+#endif
+#else
+ /* The ',a1' is a dummy argument telling the Sun assembler we want PIC
+ GAS just plain ignores it. */
+ return \"jbsr %1,a1\";
+#endif
+ }
+ return \"jsr %1\";
+")
+
+;; Call subroutine returning any type.
+
+(define_expand "untyped_call"
+ [(parallel [(call (match_operand 0 "" "")
+ (const_int 0))
+ (match_operand 1 "" "")
+ (match_operand 2 "" "")])]
+ "NEEDS_UNTYPED_CALL"
+ "
+{
+ int i;
+
+ emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
+
+ for (i = 0; i < XVECLEN (operands[2], 0); i++)
+ {
+ rtx set = XVECEXP (operands[2], 0, i);
+ emit_move_insn (SET_DEST (set), SET_SRC (set));
+ }
+
+ /* The optimizer does not know that the call sets the function value
+ registers we stored in the result block. We avoid problems by
+ claiming that all hard registers are used and clobbered at this
+ point. */
+ emit_insn (gen_blockage ());
+
+ DONE;
+}")
+
+;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
+;; all of memory. This blocks insns from being moved across this point.
+
+(define_insn "blockage"
+ [(unspec_volatile [(const_int 0)] 0)]
+ ""
+ "")
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop")
+
+(define_insn "probe"
+ [(reg:SI 15)]
+ "NEED_PROBE"
+ "*
+{
+ operands[0] = gen_rtx_PLUS (SImode, stack_pointer_rtx,
+ GEN_INT (NEED_PROBE));
+ return \"tstl %a0\";
+}")
+
+;; Used for frameless functions which save no regs and allocate no locals.
+(define_insn "return"
+ [(return)]
+ "USE_RETURN_INSN"
+ "*
+{
+ if (current_function_pops_args == 0)
+ return \"rts\";
+ operands[0] = GEN_INT (current_function_pops_args);
+ return \"rtd %0\";
+}")
+
+(define_insn "indirect_jump"
+ [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
+ ""
+ "jmp %a0")
+
+;; This should not be used unless the add/sub insns can't be.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=a")
+ (match_operand:QI 1 "address_operand" "p"))]
+ ""
+ "*
+{
+#ifndef SGS_NO_LI
+ /* Recognize an insn that refers to a table of offsets. Such an insn will
+ need to refer to a label on the insn. So output one. Use the
+ label-number of the table of offsets to generate this label. This code,
+ and similar code above, assumes that there will be at most one reference
+ to each table. */
+ if (GET_CODE (operands[1]) == PLUS
+ && GET_CODE (XEXP (operands[1], 1)) == LABEL_REF
+ && GET_CODE (XEXP (operands[1], 0)) != PLUS)
+ {
+ rtx labelref = XEXP (operands[1], 1);
+#if defined (MOTOROLA) && !defined (SGS_SWITCH_TABLES)
+#ifdef SGS
+ asm_fprintf (asm_out_file, \"\\tset %LLI%d,.+2\\n\",
+ CODE_LABEL_NUMBER (XEXP (labelref, 0)));
+#else /* not SGS */
+ asm_fprintf (asm_out_file, \"\\t.set %LLI%d,.+2\\n\",
+ CODE_LABEL_NUMBER (XEXP (labelref, 0)));
+#endif /* not SGS */
+#else /* SGS_SWITCH_TABLES or not MOTOROLA */
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"LI\",
+ CODE_LABEL_NUMBER (XEXP (labelref, 0)));
+#ifdef SGS_SWITCH_TABLES
+ /* Set flag saying we need to define the symbol
+ LD%n (with value L%n-LI%n) at the end of the switch table. */
+ switch_table_difference_label_flag = 1;
+#endif /* SGS_SWITCH_TABLES */
+#endif /* SGS_SWITCH_TABLES or not MOTOROLA */
+ }
+#endif /* SGS_NO_LI */
+
+ return \"lea %a1,%0\";
+}")
+
+;; This is the first machine-dependent peephole optimization.
+;; It is useful when a floating value is returned from a function call
+;; and then is moved into an FP register.
+;; But it is mainly intended to test the support for these optimizations.
+
+(define_peephole
+ [(set (reg:SI 15) (plus:SI (reg:SI 15) (const_int 4)))
+ (set (match_operand:DF 0 "register_operand" "=f")
+ (match_operand:DF 1 "register_operand" "ad"))]
+ "FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
+ "*
+{
+ rtx xoperands[2];
+ xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+ output_asm_insn (\"move%.l %1,%@\", xoperands);
+ output_asm_insn (\"move%.l %1,%-\", operands);
+ return \"fmove%.d %+,%0\";
+}
+")
+
+;; Optimize a stack-adjust followed by a push of an argument.
+;; This is said to happen frequently with -msoft-float
+;; when there are consecutive library calls.
+
+(define_peephole
+ [(set (reg:SI 15) (plus:SI (reg:SI 15)
+ (match_operand:SI 0 "const_int_operand" "n")))
+ (set (match_operand:SF 1 "push_operand" "=m")
+ (match_operand:SF 2 "general_operand" "rmfF"))]
+ "INTVAL (operands[0]) >= 4
+ && ! reg_mentioned_p (stack_pointer_rtx, operands[2])"
+ "*
+{
+ if (INTVAL (operands[0]) > 4)
+ {
+ rtx xoperands[2];
+ xoperands[0] = stack_pointer_rtx;
+ xoperands[1] = GEN_INT (INTVAL (operands[0]) - 4);
+#ifndef NO_ADDSUB_Q
+ if (INTVAL (xoperands[1]) <= 8)
+ {
+ if (!TARGET_5200)
+ output_asm_insn (\"addq%.w %1,%0\", xoperands);
+ else
+ output_asm_insn (\"addq%.l %1,%0\", xoperands);
+ }
+ else if (TARGET_CPU32 && INTVAL (xoperands[1]) <= 16)
+ {
+ xoperands[1] = GEN_INT (INTVAL (xoperands[1]) - 8);
+ output_asm_insn (\"addq%.w %#8,%0\;addq%.w %1,%0\", xoperands);
+ }
+ else
+#endif
+ if (INTVAL (xoperands[1]) <= 0x7FFF)
+ {
+ if (TARGET_68040)
+ output_asm_insn (\"add%.w %1,%0\", xoperands);
+ else
+#ifdef MOTOROLA
+ output_asm_insn (\"lea (%c1,%0),%0\", xoperands);
+#else
+ output_asm_insn (\"lea %0@(%c1),%0\", xoperands);
+#endif
+ }
+ else
+ output_asm_insn (\"add%.l %1,%0\", xoperands);
+ }
+ if (FP_REG_P (operands[2]))
+ return \"fmove%.s %2,%@\";
+ return \"move%.l %2,%@\";
+}")
+
+;; Speed up stack adjust followed by a fullword fixedpoint push.
+
+(define_peephole
+ [(set (reg:SI 15) (plus:SI (reg:SI 15)
+ (match_operand:SI 0 "const_int_operand" "n")))
+ (set (match_operand:SI 1 "push_operand" "=m")
+ (match_operand:SI 2 "general_operand" "g"))]
+ "INTVAL (operands[0]) >= 4
+ && ! reg_mentioned_p (stack_pointer_rtx, operands[2])"
+ "*
+{
+ if (INTVAL (operands[0]) > 4)
+ {
+ rtx xoperands[2];
+ xoperands[0] = stack_pointer_rtx;
+ xoperands[1] = GEN_INT (INTVAL (operands[0]) - 4);
+#ifndef NO_ADDSUB_Q
+ if (INTVAL (xoperands[1]) <= 8)
+ {
+ if (!TARGET_5200)
+ output_asm_insn (\"addq%.w %1,%0\", xoperands);
+ else
+ output_asm_insn (\"addq%.l %1,%0\", xoperands);
+ }
+ else if (TARGET_CPU32 && INTVAL (xoperands[1]) <= 16)
+ {
+ xoperands[1] = GEN_INT (INTVAL (xoperands[1]) - 8);
+ output_asm_insn (\"addq%.w %#8,%0\;addq%.w %1,%0\", xoperands);
+ }
+ else
+#endif
+ if (INTVAL (xoperands[1]) <= 0x7FFF)
+ {
+ if (TARGET_68040)
+ output_asm_insn (\"add%.w %1,%0\", xoperands);
+ else
+ {
+#ifdef MOTOROLA
+ output_asm_insn (\"lea (%c1,%0),%0\", xoperands);
+#else
+ output_asm_insn (\"lea %0@(%c1),%0\", xoperands);
+#endif
+ }
+ }
+ else
+ output_asm_insn (\"add%.l %1,%0\", xoperands);
+ }
+ if (operands[2] == const0_rtx)
+ return \"clr%.l %@\";
+ return \"move%.l %2,%@\";
+}")
+
+;; Speed up pushing a single byte but leaving four bytes of space.
+
+(define_peephole
+ [(set (mem:QI (pre_dec:SI (reg:SI 15)))
+ (match_operand:QI 1 "general_operand" "dami"))
+ (set (reg:SI 15) (minus:SI (reg:SI 15) (const_int 2)))]
+ "! reg_mentioned_p (stack_pointer_rtx, operands[1])"
+ "*
+{
+ rtx xoperands[4];
+
+ if (GET_CODE (operands[1]) == REG)
+ return \"move%.l %1,%-\";
+
+ xoperands[1] = operands[1];
+ xoperands[2]
+ = gen_rtx_MEM (QImode,
+ gen_rtx_PLUS (VOIDmode, stack_pointer_rtx,
+ GEN_INT (3)));
+ xoperands[3] = stack_pointer_rtx;
+ if (!TARGET_5200)
+ output_asm_insn (\"subq%.w %#4,%3\;move%.b %1,%2\", xoperands);
+ else
+ output_asm_insn (\"subq%.l %#4,%3\;move%.b %1,%2\", xoperands);
+ return \"\";
+}")
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (const_int 0))
+ (set (strict_low_part (subreg:HI (match_dup 0) 0))
+ (match_operand:HI 1 "general_operand" "rmn"))]
+ "strict_low_part_peephole_ok (HImode, prev_nonnote_insn (insn), operands[0])"
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (operands[1] == const0_rtx
+ && (DATA_REG_P (operands[0])
+ || GET_CODE (operands[0]) == MEM)
+ /* clr insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no TARGET_68010. */
+ && ((TARGET_68020 || TARGET_5200)
+ || !(GET_CODE (operands[0]) == MEM
+ && MEM_VOLATILE_P (operands[0]))))
+ return \"clr%.w %0\";
+ }
+ return \"move%.w %1,%0\";
+}")
+
+;; dbCC peepholes
+;;
+;; Turns
+;; loop:
+;; [ ... ]
+;; jCC label ; abnormal loop termination
+;; dbra dN, loop ; normal loop termination
+;;
+;; Into
+;; loop:
+;; [ ... ]
+;; dbCC dN, loop
+;; jCC label
+;;
+;; Which moves the jCC condition outside the inner loop for free.
+;;
+(define_peephole
+ [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (parallel
+ [(set (pc)
+ (if_then_else
+ (ge (plus:HI (match_operand:HI 0 "register_operand" "+d")
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:HI (match_dup 0)
+ (const_int -1)))])]
+ "!TARGET_5200 && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
+ "*
+{
+ CC_STATUS_INIT;
+ output_dbcc_and_branch (operands);
+ return \"\";
+}")
+
+(define_peephole
+ [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (parallel
+ [(set (pc)
+ (if_then_else
+ (ge (plus:SI (match_operand:SI 0 "register_operand" "+d")
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))])]
+ "!TARGET_5200 && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
+ "*
+{
+ CC_STATUS_INIT;
+ output_dbcc_and_branch (operands);
+ return \"\";
+}")
+
+
+;; FPA multiply and add.
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=x,y,y")
+ (plus:DF (mult:DF (match_operand:DF 1 "general_operand" "%x,dmF,y")
+ (match_operand:DF 2 "general_operand" "xH,y,y"))
+ (match_operand:DF 3 "general_operand" "xH,y,dmF")))]
+ "TARGET_FPA"
+ "@
+ fpma%.d %1,%w2,%w3,%0
+ fpma%.d %x1,%x2,%x3,%0
+ fpma%.d %x1,%x2,%x3,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=x,y,y")
+ (plus:SF (mult:SF (match_operand:SF 1 "general_operand" "%x,ydmF,y")
+ (match_operand:SF 2 "general_operand" "xH,y,ydmF"))
+ (match_operand:SF 3 "general_operand" "xH,ydmF,ydmF")))]
+ "TARGET_FPA"
+ "@
+ fpma%.s %1,%w2,%w3,%0
+ fpma%.s %1,%2,%3,%0
+ fpma%.s %1,%2,%3,%0")
+
+;; FPA Multiply and subtract
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=x,y,y")
+ (minus:DF (match_operand:DF 1 "general_operand" "xH,rmF,y")
+ (mult:DF (match_operand:DF 2 "general_operand" "%xH,y,y")
+ (match_operand:DF 3 "general_operand" "x,y,rmF"))))]
+ "TARGET_FPA"
+ "@
+ fpms%.d %3,%w2,%w1,%0
+ fpms%.d %x3,%2,%x1,%0
+ fpms%.d %x3,%2,%x1,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=x,y,y")
+ (minus:SF (match_operand:SF 1 "general_operand" "xH,rmF,yrmF")
+ (mult:SF (match_operand:SF 2 "general_operand" "%xH,rmF,y")
+ (match_operand:SF 3 "general_operand" "x,y,yrmF"))))]
+ "TARGET_FPA"
+ "@
+ fpms%.s %3,%w2,%w1,%0
+ fpms%.s %3,%2,%1,%0
+ fpms%.s %3,%2,%1,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=x,y,y")
+ (minus:DF (mult:DF (match_operand:DF 1 "general_operand" "%xH,y,y")
+ (match_operand:DF 2 "general_operand" "x,y,rmF"))
+ (match_operand:DF 3 "general_operand" "xH,rmF,y")))]
+ "TARGET_FPA"
+ "@
+ fpmr%.d %2,%w1,%w3,%0
+ fpmr%.d %x2,%1,%x3,%0
+ fpmr%.d %x2,%1,%x3,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=x,y,y")
+ (minus:SF (mult:SF (match_operand:SF 1 "general_operand" "%xH,rmF,y")
+ (match_operand:SF 2 "general_operand" "x,y,yrmF"))
+ (match_operand:SF 3 "general_operand" "xH,rmF,yrmF")))]
+ "TARGET_FPA"
+ "@
+ fpmr%.s %2,%w1,%w3,%0
+ fpmr%.s %x2,%1,%x3,%0
+ fpmr%.s %x2,%1,%x3,%0")
+
+;; FPA Add and multiply
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=x,y,y")
+ (mult:DF (plus:DF (match_operand:DF 1 "general_operand" "%xH,y,y")
+ (match_operand:DF 2 "general_operand" "x,y,rmF"))
+ (match_operand:DF 3 "general_operand" "xH,rmF,y")))]
+ "TARGET_FPA"
+ "@
+ fpam%.d %2,%w1,%w3,%0
+ fpam%.d %x2,%1,%x3,%0
+ fpam%.d %x2,%1,%x3,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=x,y,y")
+ (mult:SF (plus:SF (match_operand:SF 1 "general_operand" "%xH,rmF,y")
+ (match_operand:SF 2 "general_operand" "x,y,yrmF"))
+ (match_operand:SF 3 "general_operand" "xH,rmF,yrmF")))]
+ "TARGET_FPA"
+ "@
+ fpam%.s %2,%w1,%w3,%0
+ fpam%.s %x2,%1,%x3,%0
+ fpam%.s %x2,%1,%x3,%0")
+
+;;FPA Subtract and multiply
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=x,y,y")
+ (mult:DF (minus:DF (match_operand:DF 1 "general_operand" "xH,y,y")
+ (match_operand:DF 2 "general_operand" "x,y,rmF"))
+ (match_operand:DF 3 "general_operand" "xH,rmF,y")))]
+ "TARGET_FPA"
+ "@
+ fpsm%.d %2,%w1,%w3,%0
+ fpsm%.d %x2,%1,%x3,%0
+ fpsm%.d %x2,%1,%x3,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=x,y,y")
+ (mult:DF (match_operand:DF 1 "general_operand" "xH,rmF,y")
+ (minus:DF (match_operand:DF 2 "general_operand" "xH,y,y")
+ (match_operand:DF 3 "general_operand" "x,y,rmF"))))]
+ "TARGET_FPA"
+ "@
+ fpsm%.d %3,%w2,%w1,%0
+ fpsm%.d %x3,%2,%x1,%0
+ fpsm%.d %x3,%2,%x1,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=x,y,y")
+ (mult:SF (minus:SF (match_operand:SF 1 "general_operand" "xH,rmF,y")
+ (match_operand:SF 2 "general_operand" "x,y,yrmF"))
+ (match_operand:SF 3 "general_operand" "xH,rmF,yrmF")))]
+ "TARGET_FPA"
+ "@
+ fpsm%.s %2,%w1,%w3,%0
+ fpsm%.s %x2,%1,%x3,%0
+ fpsm%.s %x2,%1,%x3,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=x,y,y")
+ (mult:SF (match_operand:SF 1 "general_operand" "xH,rmF,yrmF")
+ (minus:SF (match_operand:SF 2 "general_operand" "xH,rmF,y")
+ (match_operand:SF 3 "general_operand" "x,y,yrmF"))))]
+ "TARGET_FPA"
+ "@
+ fpsm%.s %3,%w2,%w1,%0
+ fpsm%.s %x3,%2,%x1,%0
+ fpsm%.s %x3,%2,%x1,%0")
+
+(define_expand "tstxf"
+ [(set (cc0)
+ (match_operand:XF 0 "nonimmediate_operand" ""))]
+ "TARGET_68881"
+ "m68k_last_compare_had_fp_operands = 1;")
+
+(define_insn ""
+ [(set (cc0)
+ (match_operand:XF 0 "nonimmediate_operand" "fm"))]
+ "TARGET_68881"
+ "*
+{
+ cc_status.flags = CC_IN_68881;
+ return \"ftst%.x %0\";
+}")
+
+(define_expand "cmpxf"
+ [(set (cc0)
+ (compare (match_operand:XF 0 "nonimmediate_operand" "")
+ (match_operand:XF 1 "nonimmediate_operand" "")))]
+ "TARGET_68881"
+ "m68k_last_compare_had_fp_operands = 1;")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:XF 0 "nonimmediate_operand" "f,m")
+ (match_operand:XF 1 "nonimmediate_operand" "fm,f")))]
+ "TARGET_68881"
+ "*
+{
+ cc_status.flags = CC_IN_68881;
+#ifdef SGS_CMP_ORDER
+ if (REG_P (operands[0]))
+ {
+ if (REG_P (operands[1]))
+ return \"fcmp%.x %0,%1\";
+ else
+ return \"fcmp%.x %0,%f1\";
+ }
+ cc_status.flags |= CC_REVERSED;
+ return \"fcmp%.x %1,%f0\";
+#else
+ if (REG_P (operands[0]))
+ {
+ if (REG_P (operands[1]))
+ return \"fcmp%.x %1,%0\";
+ else
+ return \"fcmp%.x %f1,%0\";
+ }
+ cc_status.flags |= CC_REVERSED;
+ return \"fcmp%.x %f0,%1\";
+#endif
+}")
+
+(define_insn "extendsfxf2"
+ [(set (match_operand:XF 0 "general_operand" "=fm,f")
+ (float_extend:XF (match_operand:SF 1 "general_operand" "f,m")))]
+ "TARGET_68881"
+ "*
+{
+ if (FP_REG_P (operands[0]) && FP_REG_P (operands[1]))
+ {
+ if (REGNO (operands[0]) == REGNO (operands[1]))
+ {
+ /* Extending float to double in an fp-reg is a no-op.
+ NOTICE_UPDATE_CC has already assumed that the
+ cc will be set. So cancel what it did. */
+ cc_status = cc_prev_status;
+ return \"\";
+ }
+ return \"f%$move%.x %1,%0\";
+ }
+ if (FP_REG_P (operands[0]))
+ return \"f%$move%.s %f1,%0\";
+ return \"fmove%.x %f1,%0\";
+}")
+
+
+(define_insn "extenddfxf2"
+ [(set (match_operand:XF 0 "general_operand" "=fm,f")
+ (float_extend:XF
+ (match_operand:DF 1 "general_operand" "f,m")))]
+ "TARGET_68881"
+ "*
+{
+ if (FP_REG_P (operands[0]) && FP_REG_P (operands[1]))
+ {
+ if (REGNO (operands[0]) == REGNO (operands[1]))
+ {
+ /* Extending float to double in an fp-reg is a no-op.
+ NOTICE_UPDATE_CC has already assumed that the
+ cc will be set. So cancel what it did. */
+ cc_status = cc_prev_status;
+ return \"\";
+ }
+ return \"fmove%.x %1,%0\";
+ }
+ if (FP_REG_P (operands[0]))
+ return \"f%&move%.d %f1,%0\";
+ return \"fmove%.x %f1,%0\";
+}")
+
+(define_insn "truncxfdf2"
+ [(set (match_operand:DF 0 "general_operand" "=m,!r")
+ (float_truncate:DF
+ (match_operand:XF 1 "general_operand" "f,f")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[0]))
+ {
+ output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands);
+ operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ return \"move%.l %+,%0\";
+ }
+ return \"fmove%.d %f1,%0\";
+}")
+
+(define_insn "truncxfsf2"
+ [(set (match_operand:SF 0 "general_operand" "=dm")
+ (float_truncate:SF
+ (match_operand:XF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.s %f1,%0")
+
+(define_insn "floatsixf2"
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (float:XF (match_operand:SI 1 "general_operand" "dmi")))]
+ "TARGET_68881"
+ "fmove%.l %1,%0")
+
+(define_insn "floathixf2"
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (float:XF (match_operand:HI 1 "general_operand" "dmn")))]
+ "TARGET_68881"
+ "fmove%.w %1,%0")
+
+(define_insn "floatqixf2"
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (float:XF (match_operand:QI 1 "general_operand" "dmn")))]
+ "TARGET_68881"
+ "fmove%.b %1,%0")
+
+(define_insn "ftruncxf2"
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (fix:XF (match_operand:XF 1 "general_operand" "fFm")))]
+ "TARGET_68881"
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"fintrz%.x %f1,%0\";
+ return \"fintrz%.x %f1,%0\";
+}")
+
+(define_insn "fixxfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (fix:QI (match_operand:XF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.b %1,%0")
+
+(define_insn "fixxfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=dm")
+ (fix:HI (match_operand:XF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.w %1,%0")
+
+(define_insn "fixxfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=dm")
+ (fix:SI (match_operand:XF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.l %1,%0")
+
+(define_insn ""
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (plus:XF (float:XF (match_operand:SI 2 "general_operand" "dmi"))
+ (match_operand:XF 1 "nonimmediate_operand" "0")))]
+ "TARGET_68881"
+ "fadd%.l %2,%0")
+
+(define_insn ""
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (plus:XF (float:XF (match_operand:HI 2 "general_operand" "dmn"))
+ (match_operand:XF 1 "nonimmediate_operand" "0")))]
+ "TARGET_68881"
+ "fadd%.w %2,%0")
+
+(define_insn ""
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (plus:XF (float:XF (match_operand:QI 2 "general_operand" "dmn"))
+ (match_operand:XF 1 "general_operand" "0")))]
+ "TARGET_68881"
+ "fadd%.b %2,%0")
+
+(define_insn "addxf3"
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (plus:XF (match_operand:XF 1 "nonimmediate_operand" "%0")
+ (match_operand:XF 2 "nonimmediate_operand" "fm")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[2]))
+ return \"fadd%.x %2,%0\";
+ return \"fadd%.x %f2,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (minus:XF (match_operand:XF 1 "nonimmediate_operand" "0")
+ (float:XF (match_operand:SI 2 "general_operand" "dmi"))))]
+ "TARGET_68881"
+ "fsub%.l %2,%0")
+
+(define_insn ""
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (minus:XF (match_operand:XF 1 "nonimmediate_operand" "0")
+ (float:XF (match_operand:HI 2 "general_operand" "dmn"))))]
+ "TARGET_68881"
+ "fsub%.w %2,%0")
+
+(define_insn ""
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (minus:XF (match_operand:XF 1 "nonimmediate_operand" "0")
+ (float:XF (match_operand:QI 2 "general_operand" "dmn"))))]
+ "TARGET_68881"
+ "fsub%.b %2,%0")
+
+(define_insn "subxf3"
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (minus:XF (match_operand:XF 1 "nonimmediate_operand" "0")
+ (match_operand:XF 2 "nonimmediate_operand" "fm")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[2]))
+ return \"fsub%.x %2,%0\";
+ return \"fsub%.x %f2,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (mult:XF (float:XF (match_operand:SI 2 "general_operand" "dmi"))
+ (match_operand:XF 1 "nonimmediate_operand" "0")))]
+ "TARGET_68881"
+ "fmul%.l %2,%0")
+
+(define_insn ""
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (mult:XF (float:XF (match_operand:HI 2 "general_operand" "dmn"))
+ (match_operand:XF 1 "nonimmediate_operand" "0")))]
+ "TARGET_68881"
+ "fmul%.w %2,%0")
+
+(define_insn ""
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (mult:XF (float:XF (match_operand:QI 2 "general_operand" "dmn"))
+ (match_operand:XF 1 "nonimmediate_operand" "0")))]
+ "TARGET_68881"
+ "fmul%.b %2,%0")
+
+(define_insn "mulxf3"
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (mult:XF (match_operand:XF 1 "nonimmediate_operand" "%0")
+ (match_operand:XF 2 "nonimmediate_operand" "fm")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[2]))
+ return \"fmul%.x %2,%0\";
+ return \"fmul%.x %f2,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (div:XF (match_operand:XF 1 "nonimmediate_operand" "0")
+ (float:XF (match_operand:SI 2 "general_operand" "dmi"))))]
+ "TARGET_68881"
+ "fdiv%.l %2,%0")
+
+(define_insn ""
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (div:XF (match_operand:XF 1 "nonimmediate_operand" "0")
+ (float:XF (match_operand:HI 2 "general_operand" "dmn"))))]
+ "TARGET_68881"
+ "fdiv%.w %2,%0")
+
+(define_insn ""
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (div:XF (match_operand:XF 1 "nonimmediate_operand" "0")
+ (float:XF (match_operand:QI 2 "general_operand" "dmn"))))]
+ "TARGET_68881"
+ "fdiv%.b %2,%0")
+
+(define_insn "divxf3"
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (div:XF (match_operand:XF 1 "nonimmediate_operand" "0")
+ (match_operand:XF 2 "nonimmediate_operand" "fm")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[2]))
+ return \"fdiv%.x %2,%0\";
+ return \"fdiv%.x %f2,%0\";
+}")
+
+(define_expand "negxf2"
+ [(set (match_operand:XF 0 "general_operand" "")
+ (neg:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
+ ""
+ "
+{
+ /* ??? There isn't an FPA define_insn so we could handle it here too.
+ For now we don't (paranoia). */
+ if (!TARGET_68881)
+ {
+ rtx result;
+ rtx target;
+ rtx insns;
+
+ start_sequence ();
+ target = operand_subword (operands[0], 0, 1, XFmode);
+ result = expand_binop (SImode, xor_optab,
+ operand_subword_force (operands[1], 0, XFmode),
+ GEN_INT(0x80000000), target, 0, OPTAB_WIDEN);
+ if (result == 0)
+ abort ();
+
+ if (result != target)
+ emit_move_insn (result, target);
+
+ emit_move_insn (operand_subword (operands[0], 1, 1, XFmode),
+ operand_subword_force (operands[1], 1, XFmode));
+ emit_move_insn (operand_subword (operands[0], 2, 1, XFmode),
+ operand_subword_force (operands[1], 2, XFmode));
+
+ insns = get_insns ();
+ end_sequence ();
+
+ emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
+ DONE;
+ }
+}")
+
+(define_insn "negxf2_68881"
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (neg:XF (match_operand:XF 1 "nonimmediate_operand" "fm")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
+ return \"fneg%.x %1,%0\";
+ return \"fneg%.x %f1,%0\";
+}")
+
+(define_expand "absxf2"
+ [(set (match_operand:XF 0 "general_operand" "")
+ (abs:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
+ ""
+ "
+{
+ /* ??? There isn't an FPA define_insn so we could handle it here too.
+ For now we don't (paranoia). */
+ if (!TARGET_68881)
+ {
+ rtx result;
+ rtx target;
+ rtx insns;
+
+ start_sequence ();
+ target = operand_subword (operands[0], 0, 1, XFmode);
+ result = expand_binop (SImode, and_optab,
+ operand_subword_force (operands[1], 0, XFmode),
+ GEN_INT(0x7fffffff), target, 0, OPTAB_WIDEN);
+ if (result == 0)
+ abort ();
+
+ if (result != target)
+ emit_move_insn (result, target);
+
+ emit_move_insn (operand_subword (operands[0], 1, 1, XFmode),
+ operand_subword_force (operands[1], 1, XFmode));
+ emit_move_insn (operand_subword (operands[0], 2, 1, XFmode),
+ operand_subword_force (operands[1], 2, XFmode));
+
+ insns = get_insns ();
+ end_sequence ();
+
+ emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
+ DONE;
+ }
+}")
+
+(define_insn "absxf2_68881"
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (abs:XF (match_operand:XF 1 "nonimmediate_operand" "fm")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
+ return \"fabs%.x %1,%0\";
+ return \"fabs%.x %f1,%0\";
+}")
+
+(define_insn "sqrtxf2"
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (sqrt:XF (match_operand:XF 1 "nonimmediate_operand" "fm")))]
+ "TARGET_68881"
+ "fsqrt%.x %1,%0")
+
+(define_insn "sinsf2"
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (unspec:SF [(match_operand:SF 1 "general_operand" "fm")] 1))]
+ "TARGET_68881 && flag_fast_math"
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"fsin%.x %1,%0\";
+ else
+ return \"fsin%.s %1,%0\";
+}")
+
+(define_insn "sindf2"
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "general_operand" "fm")] 1))]
+ "TARGET_68881 && flag_fast_math"
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"fsin%.x %1,%0\";
+ else
+ return \"fsin%.d %1,%0\";
+}")
+
+(define_insn "sinxf2"
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] 1))]
+ "TARGET_68881 && flag_fast_math"
+ "fsin%.x %1,%0")
+
+(define_insn "cossf2"
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (unspec:SF [(match_operand:SF 1 "general_operand" "fm")] 2))]
+ "TARGET_68881 && flag_fast_math"
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"fcos%.x %1,%0\";
+ else
+ return \"fcos%.s %1,%0\";
+}")
+
+(define_insn "cosdf2"
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "general_operand" "fm")] 2))]
+ "TARGET_68881 && flag_fast_math"
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"fcos%.x %1,%0\";
+ else
+ return \"fcos%.d %1,%0\";
+}")
+
+(define_insn "cosxf2"
+ [(set (match_operand:XF 0 "general_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] 2))]
+ "TARGET_68881 && flag_fast_math"
+ "fcos%.x %1,%0")
diff --git a/gcc/config/m68k/m68kelf.h b/gcc/config/m68k/m68kelf.h
new file mode 100755
index 0000000..0257d1b
--- /dev/null
+++ b/gcc/config/m68k/m68kelf.h
@@ -0,0 +1,297 @@
+/* m68kelf support, derived from m68kv4.h */
+
+/* Target definitions for GNU compiler for mc680x0 running System V.4
+ Copyright (C) 1991, 1993 Free Software Foundation, Inc.
+
+ Written by Ron Guilmette (rfg@netcom.com) and Fred Fish (fnf@cygnus.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* #notinclude "m68k/sgs.h" /* The m68k/SVR4 assembler is SGS based */
+
+/* These are necessary for -fpic/-fPIC to work correctly. */
+#ifndef MOTOROLA
+#define MOTOROLA /* Use MOTOROLA syntax. */
+#endif
+#ifdef USE_GAS /* when present, forces jsbr instead of jsr. */
+#undef USE_GAS
+#endif
+
+#ifndef SWBEG_ASM_OP
+#define SWBEG_ASM_OP ".swbeg"
+#endif
+
+/* Here are four prefixes that are used by asm_fprintf to
+ facilitate customization for alternate assembler syntaxes.
+ Machines with no likelihood of an alternate syntax need not
+ define these and need not use asm_fprintf. */
+
+/* The prefix for register names. Note that REGISTER_NAMES
+ is supposed to include this prefix. Also note that this is NOT an
+ fprintf format string, it is a literal string */
+
+#undef REGISTER_PREFIX
+#define REGISTER_PREFIX "%"
+
+/* The prefix for local (compiler generated) labels.
+ These labels will not appear in the symbol table. */
+
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
+/* The prefix to add to user-visible assembler symbols. */
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+
+/* The prefix for immediate operands. */
+
+#undef IMMEDIATE_PREFIX
+#define IMMEDIATE_PREFIX "#"
+
+/* In the machine description we can't use %R, because it will not be seen
+ by ASM_FPRINTF. (Isn't that a design bug?). */
+
+#undef REGISTER_PREFIX_MD
+#define REGISTER_PREFIX_MD "%%"
+
+/* config/m68k.md has an explicit reference to the program counter,
+ prefix this by the register prefix. */
+
+#define ASM_RETURN_CASE_JUMP \
+ do { \
+ if (TARGET_5200) \
+ return "ext%.l %0\n\tjmp %%pc@(2,%0:l)"; \
+ else \
+ return "jmp %%pc@(2,%0:w)"; \
+ } while (0)
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number.
+ Motorola format uses different register names than defined
+ in m68k.h. */
+
+#undef REGISTER_NAMES
+
+#define REGISTER_NAMES \
+{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%sp", \
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7" }
+
+/* This is how to output an assembler line that says to advance the
+ location counter to a multiple of 2**LOG bytes. */
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) > 0) \
+ fprintf ((FILE), "\t%s \t%u\n", ALIGN_ASM_OP, 1 << (LOG)); \
+ else if ((LOG) > 31) \
+ abort ();
+
+/* Use proper assembler syntax for these macros. */
+#undef ASM_OUTPUT_REG_PUSH
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ asm_fprintf (FILE, "\t%Omove.l %s,-(%Rsp)\n", reg_names[REGNO])
+
+#undef ASM_OUTPUT_REG_POP
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ asm_fprintf (FILE, "\t%Omove.l (%Rsp)+,%s\n", reg_names[REGNO])
+
+/* Override the definition of NO_DOLLAR_IN_LABEL in svr4.h, for special
+ g++ assembler names. When this is defined, g++ uses embedded '.'
+ characters and some m68k assemblers have problems with this. The
+ chances are much greater that any particular assembler will permit
+ embedded '$' characters. */
+
+#undef NO_DOLLAR_IN_LABEL
+
+/* Define PCC_STATIC_STRUCT_RETURN if the convention on the target machine
+ is to use the nonreentrant technique for returning structure and union
+ values, as commonly implemented by the AT&T Portable C Compiler (PCC).
+ When defined, the gcc option -fpcc-struct-return can be used to cause
+ this form to be generated. When undefined, the option does nothing.
+ For m68k SVR4, the convention is to use a reentrant technique compatible
+ with the gcc default, so override the definition of this macro in m68k.h */
+
+#undef PCC_STATIC_STRUCT_RETURN
+
+/* Local common symbols are declared to the assembler with ".lcomm" rather
+ than ".bss", so override the definition in svr4.h */
+
+#undef BSS_ASM_OP
+#define BSS_ASM_OP ".lcomm"
+
+/* Register in which address to store a structure value is passed to a
+ function. The default in m68k.h is a1. For m68k/SVR4 it is a0. */
+
+#undef STRUCT_VALUE_REGNUM
+#define STRUCT_VALUE_REGNUM 8
+
+#define ASM_COMMENT_START "|"
+
+#undef TYPE_OPERAND_FMT
+#define TYPE_OPERAND_FMT "@%s"
+
+/* Define how the m68k registers should be numbered for Dwarf output.
+ The numbering provided here should be compatible with the native
+ SVR4 SDB debugger in the m68k/SVR4 reference port, where d0-d7
+ are 0-7, a0-a8 are 8-15, and fp0-fp7 are 16-23. */
+
+#undef DBX_REGISTER_NUMBER
+#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
+
+/* The ASM_OUTPUT_SKIP macro is first defined in m68k.h, using ".skip".
+ It is then overridden by m68k/sgs.h to use ".space", and again by svr4.h
+ to use ".zero". The m68k/SVR4 assembler uses ".space", so repeat the
+ definition from m68k/sgs.h here. Note that ASM_NO_SKIP_IN_TEXT is
+ defined in m68k/sgs.h, so we don't have to repeat it here. */
+
+#undef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t%s %u\n", SPACE_ASM_OP, (SIZE))
+
+#if 0
+/* SVR4 m68k assembler is bitching on the `comm i,1,1' which askes for
+ 1 byte alignment. Don't generate alignment for COMMON seems to be
+ safer until we the assembler is fixed. */
+#undef ASM_OUTPUT_ALIGNED_COMMON
+/* Same problem with this one. */
+#undef ASM_OUTPUT_ALIGNED_LOCAL
+#endif
+
+/* The `string' directive on m68k svr4 does not handle string with
+ escape char (ie., `\') right. Use normal way to output ASCII bytes
+ seems to be safer. */
+#undef ASM_OUTPUT_ASCII
+#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
+do { \
+ register int sp = 0, lp = 0, ch; \
+ fprintf ((FILE), "\t%s ", BYTE_ASM_OP); \
+ do { \
+ ch = (PTR)[sp]; \
+ if (ch > ' ' && ! (ch & 0x80) && ch != '\\') \
+ { \
+ fprintf ((FILE), "'%c", ch); \
+ } \
+ else \
+ { \
+ fprintf ((FILE), "0x%x", ch); \
+ } \
+ if (++sp < (LEN)) \
+ { \
+ if ((sp % 10) == 0) \
+ { \
+ fprintf ((FILE), "\n\t%s ", BYTE_ASM_OP); \
+ } \
+ else \
+ { \
+ putc (',', (FILE)); \
+ } \
+ } \
+ } while (sp < (LEN)); \
+ putc ('\n', (FILE)); \
+} while (0)
+
+/* SVR4 m68k assembler is bitching on the syntax `2.b'.
+ So use the "LLDnnn-LLnnn" format. Define LLDnnn after the table. */
+
+#undef ASM_OUTPUT_CASE_END
+#define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \
+do { \
+ if (switch_table_difference_label_flag) \
+ asm_fprintf ((FILE), "\t%s %LLD%d,%LL%d\n", SET_ASM_OP, (NUM), (NUM));\
+ switch_table_difference_label_flag = 0; \
+} while (0)
+
+extern int switch_table_difference_label_flag;
+
+#undef ASM_OUTPUT_COMMON
+#undef ASM_OUTPUT_LOCAL
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (SIZE)))
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".lcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (SIZE)))
+
+/* Currently, JUMP_TABLES_IN_TEXT_SECTION must be defined in order to
+ keep switch tables in the text section. */
+
+#define JUMP_TABLES_IN_TEXT_SECTION 1
+
+/* Override the definition in svr4.h. In m68k svr4, using swbeg is the
+ standard way to do switch table. */
+#undef ASM_OUTPUT_BEFORE_CASE_LABEL
+#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
+ fprintf ((FILE), "\t%s &%d\n", SWBEG_ASM_OP, XVECLEN (PATTERN (TABLE), 1));
+
+/* In m68k svr4, a symbol_ref rtx can be a valid PIC operand if it is an
+ operand of a function call. */
+#undef LEGITIMATE_PIC_OPERAND_P
+#define LEGITIMATE_PIC_OPERAND_P(X) \
+ (! symbolic_operand (X, VOIDmode) \
+ || ((GET_CODE(X) == SYMBOL_REF) && SYMBOL_REF_FLAG(X)))
+
+/* Turn off function cse if we are doing PIC. We always want function call
+ to be done as `bsr foo@PLTPC', so it will force the assembler to create
+ the PLT entry for `foo'. Doing function cse will cause the address of `foo'
+ to be loaded into a register, which is exactly what we want to avoid when
+ we are doing PIC on svr4 m68k. */
+#undef OVERRIDE_OPTIONS
+#define OVERRIDE_OPTIONS \
+{ \
+ if (flag_pic) flag_no_function_cse = 1; \
+ if (! TARGET_68020 && flag_pic == 2) \
+ error("-fPIC is not currently supported on the 68000 or 68010\n"); \
+}
+/* end of stuff from m68kv4.h */
+
+#undef SGS_CMP_ORDER
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "crtbegin.o%s"
+
+/* If defined, a C expression whose value is a string containing the
+ assembler operation to identify the following data as
+ uninitialized global data. If not defined, and neither
+ `ASM_OUTPUT_BSS' nor `ASM_OUTPUT_ALIGNED_BSS' are defined,
+ uninitialized global data will be output in the data section if
+ `-fno-common' is passed, otherwise `ASM_OUTPUT_COMMON' will be
+ used. */
+#ifndef BSS_SECTION_ASM_OP
+#define BSS_SECTION_ASM_OP ".section\t.bss"
+#endif
+
+/* Like `ASM_OUTPUT_BSS' except takes the required alignment as a
+ separate, explicit argument. If you define this macro, it is used
+ in place of `ASM_OUTPUT_BSS', and gives you more flexibility in
+ handling the required alignment of the variable. The alignment is
+ specified as the number of bits.
+
+ Try to use function `asm_output_aligned_bss' defined in file
+ `varasm.c' when defining this macro. */
+#ifndef ASM_OUTPUT_ALIGNED_BSS
+#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
+ asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
+#endif
diff --git a/gcc/config/m68k/m68kemb.h b/gcc/config/m68k/m68kemb.h
new file mode 100755
index 0000000..9fa0c69
--- /dev/null
+++ b/gcc/config/m68k/m68kemb.h
@@ -0,0 +1,55 @@
+/* Definitions of target machine for GNU compiler. "embedded" 68XXX.
+ This is meant to be included after m68k.h.
+ Copyright (C) 1994, 1995 Free Software Foundation, Inc. */
+
+#define PTRDIFF_TYPE "long int"
+#define SIZE_TYPE "long unsigned int"
+
+/* In order for bitfields to work on a 68000, or with -mnobitfield, we must
+ define either PCC_BITFIELD_TYPE_MATTERS or STRUCTURE_SIZE_BOUNDARY.
+ Defining STRUCTURE_SIZE_BOUNDARY results in structure packing problems,
+ so we define PCC_BITFIELD_TYPE_MATTERS. */
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* Undef PCC_STATIC_STRUCT_RETURN so that we get a re-entrant calling
+ convention. */
+#undef PCC_STATIC_STRUCT_RETURN
+
+/* Don't default to pcc-struct-return, so that we can return small structures
+ and unions in registers, which is slightly more efficient. */
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* Return floating point values in a fp register. This make fp code a
+ little bit faster. It also makes -msoft-float code incompatible with
+ -m68881 code, so people have to be careful not to mix the two. */
+#undef FUNCTION_VALUE
+#define FUNCTION_VALUE(VALTYPE,FUNC) LIBCALL_VALUE (TYPE_MODE (VALTYPE))
+
+#undef LIBCALL_VALUE
+#define LIBCALL_VALUE(MODE) \
+ gen_rtx (REG, (MODE), \
+ ((TARGET_68881 \
+ && ((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode)) \
+ ? 16 : 0))
+
+#undef FUNCTION_VALUE_REGNO_P
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (TARGET_68881 && (N) == 16))
+
+#undef NEEDS_UNTYPED_CALL
+#define NEEDS_UNTYPED_CALL 1
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dmc68000 -D__embedded__ -Asystem(embedded) \
+ -Amachine(mc68000)"
+
+/* Override the default LIB_SPEC from gcc.c. We don't currently support
+ profiling, or libg.a. */
+
+#undef LIB_SPEC
+#define LIB_SPEC "-lc"
+
+/* Make this be null, since we want the crt0.o to come from the linker
+ script */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC ""
diff --git a/gcc/config/m68k/m68kv4.h b/gcc/config/m68k/m68kv4.h
new file mode 100755
index 0000000..16cc1c9
--- /dev/null
+++ b/gcc/config/m68k/m68kv4.h
@@ -0,0 +1,346 @@
+/* Target definitions for GNU compiler for mc680x0 running System V.4
+ Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+ Contributed by Ron Guilmette (rfg@monkeys.com) and
+ Fred Fish (fnf@cygnus.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Use SGS_* macros to control compilation in m68k.md */
+
+#define SGS_SWITCH_TABLES /* Different switch table handling */
+
+#include "m68k/sgs.h" /* The m68k/SVR4 assembler is SGS based */
+
+/* The SGS assembler requires a special definition of
+ ASM_IDENTIFY_GCC. We combine the m68k/sgs.h and the svr4.h
+ definitions below. */
+#undef ASM_IDENTIFY_GCC
+
+#include "svr4.h" /* Pick up the generic SVR4 macros */
+
+/* See m68k.h. 7 means 68020 with 68881. */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
+#endif
+
+/* When using an SGS assembler, modify the name of the artificial label which
+ identifies this file as having been compiled with gcc, and the macro that
+ emits such a label in the assembly output, to use '%' rather than '.' */
+
+#undef ASM_IDENTIFY_GCC
+#define ASM_IDENTIFY_GCC(FILE) \
+do \
+ { \
+ if (write_symbols != DBX_DEBUG) \
+ fputs ("gcc2_compiled%:\n", FILE); \
+ } \
+while (0)
+
+/* Override the definition of NO_DOLLAR_IN_LABEL in svr4.h, for special
+ g++ assembler names. When this is defined, g++ uses embedded '.'
+ characters and some m68k assemblers have problems with this. The
+ chances are much greater that any particular assembler will permit
+ embedded '$' characters. */
+
+#undef NO_DOLLAR_IN_LABEL
+
+/* Define PCC_STATIC_STRUCT_RETURN if the convention on the target machine
+ is to use the nonreentrant technique for returning structure and union
+ values, as commonly implemented by the AT&T Portable C Compiler (PCC).
+ When defined, the gcc option -fpcc-struct-return can be used to cause
+ this form to be generated. When undefined, the option does nothing.
+ For m68k SVR4, the convention is to use a reentrant technique compatible
+ with the gcc default, so override the definition of this macro in m68k.h */
+
+#undef PCC_STATIC_STRUCT_RETURN
+
+/* Provide a set of pre-definitions and pre-assertions appropriate for
+ the m68k running svr4. __svr4__ is our extension. */
+
+#define CPP_PREDEFINES \
+ "-Dm68k -Dunix -D__svr4__ -D__motorola__ \
+ -Asystem(unix) -Asystem(svr4) -Acpu(m68k) -Amachine(m68k)"
+
+/* Test to see if the target includes a 68881 by default, and use CPP_SPEC
+ to control whether or not __HAVE_68881__ is defined by default or not.
+ If a 68881 is the default, gcc will use inline 68881 instructions, by
+ predefining __HAVE_68881__, unless -msoft-float is specified.
+ If a 68881 is not the default, gcc will only define __HAVE_68881__ if
+ -m68881 is specified. */
+
+#if TARGET_DEFAULT & MASK_68881
+#define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__}"
+#else
+#define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
+#endif
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. We override the definition in m68k.h
+ and match the way the native m68k/SVR4 compiler does profiling, with the
+ address of the profile counter in a1, not a0, and using bsr rather
+ than jsr. */
+
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ asm_fprintf ((FILE), "\tlea.l\t(%LLP%d,%Rpc),%Ra1\n\tbsr\t_mcount\n", \
+ (LABELNO))
+
+/* Local common symbols are declared to the assembler with ".lcomm" rather
+ than ".bss", so override the definition in svr4.h */
+/* ??? svr4.h no longer defines this, and this is only used by m68k/amix.h. */
+
+#undef BSS_ASM_OP
+#define BSS_ASM_OP ".lcomm"
+
+/* Register in which address to store a structure value is passed to a
+ function. The default in m68k.h is a1. For m68k/SVR4 it is a0. */
+
+#undef STRUCT_VALUE_REGNUM
+#define STRUCT_VALUE_REGNUM 8
+
+/* Register in which static-chain is passed to a function. The
+ default in m68k.h is a0, but that is already the struct value
+ regnum. Make it a1 instead. */
+
+#undef STATIC_CHAIN_REGNUM
+#define STATIC_CHAIN_REGNUM 9
+
+#define ASM_COMMENT_START "#"
+
+#undef TYPE_OPERAND_FMT
+#define TYPE_OPERAND_FMT "@%s"
+
+/* Define how the m68k registers should be numbered for Dwarf output.
+ The numbering provided here should be compatible with the native
+ SVR4 SDB debugger in the m68k/SVR4 reference port, where d0-d7
+ are 0-7, a0-a8 are 8-15, and fp0-fp7 are 16-23. */
+
+#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
+
+/* The ASM_OUTPUT_SKIP macro is first defined in m68k.h, using ".skip".
+ It is then overridden by m68k/sgs.h to use ".space", and again by svr4.h
+ to use ".zero". The m68k/SVR4 assembler uses ".space", so repeat the
+ definition from m68k/sgs.h here. Note that ASM_NO_SKIP_IN_TEXT is
+ defined in m68k/sgs.h, so we don't have to repeat it here. */
+
+#undef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t%s %u\n", SPACE_ASM_OP, (SIZE))
+
+/* 1 if N is a possible register number for a function value.
+ For m68k/SVR4 allow d0, a0, or fp0 as return registers, for integral,
+ pointer, or floating types, respectively. Reject fp0 if not using a
+ 68881 coprocessor. */
+
+#undef FUNCTION_VALUE_REGNO_P
+#define FUNCTION_VALUE_REGNO_P(N) \
+ ((N) == 0 || (N) == 8 || (TARGET_68881 && (N) == 16))
+
+/* Define this to be true when FUNCTION_VALUE_REGNO_P is true for
+ more than one register. */
+
+#undef NEEDS_UNTYPED_CALL
+#define NEEDS_UNTYPED_CALL 1
+
+/* Define how to generate (in the callee) the output value of a function
+ and how to find (in the caller) the value returned by a function. VALTYPE
+ is the data type of the value (as a tree). If the precise function being
+ called is known, FUNC is its FUNCTION_DECL; otherwise, FUNC is 0.
+ For m68k/SVR4 generate the result in d0, a0, or fp0 as appropriate. */
+
+#undef FUNCTION_VALUE
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ (TREE_CODE (VALTYPE) == REAL_TYPE && TARGET_68881 \
+ ? gen_rtx (REG, TYPE_MODE (VALTYPE), 16) \
+ : (POINTER_TYPE_P (VALTYPE) \
+ ? gen_rtx (REG, TYPE_MODE (VALTYPE), 8) \
+ : gen_rtx (REG, TYPE_MODE (VALTYPE), 0)))
+
+/* For compatibility with the large body of existing code which does not
+ always properly declare external functions returning pointer types, the
+ m68k/SVR4 convention is to copy the value returned for pointer functions
+ from a0 to d0 in the function epilogue, so that callers that have
+ neglected to properly declare the callee can still find the correct return
+ value. */
+
+extern int current_function_returns_pointer;
+#define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE) \
+do { \
+ if ((current_function_returns_pointer) && \
+ ! find_equiv_reg (0, get_last_insn (), 0, 0, 0, 8, Pmode)) \
+ asm_fprintf (FILE, "\tmov.l %Ra0,%Rd0\n"); \
+} while (0);
+
+/* Define how to find the value returned by a library function assuming the
+ value has mode MODE.
+ For m68k/SVR4 look for integer values in d0, pointer values in d0
+ (returned in both d0 and a0), and floating values in fp0. */
+
+#undef LIBCALL_VALUE
+#define LIBCALL_VALUE(MODE) \
+ ((((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode) \
+ && TARGET_68881) \
+ ? gen_rtx (REG, (MODE), 16) \
+ : gen_rtx (REG, (MODE), 0))
+
+/* Boundary (in *bits*) on which stack pointer should be aligned.
+ The m68k/SVR4 convention is to keep the stack pointer longword aligned. */
+
+#undef STACK_BOUNDARY
+#define STACK_BOUNDARY 32
+
+/* Alignment of field after `int : 0' in a structure.
+ For m68k/SVR4, this is the next longword boundary. */
+
+#undef EMPTY_FIELD_BOUNDARY
+#define EMPTY_FIELD_BOUNDARY 32
+
+/* No data type wants to be aligned rounder than this.
+ For m68k/SVR4, some types (doubles for example) are aligned on 8 byte
+ boundaries */
+
+#undef BIGGEST_ALIGNMENT
+#define BIGGEST_ALIGNMENT 64
+
+/* SVR4 m68k assembler is bitching on the `comm i,1,1' which asks for
+ 1 byte alignment. Don't generate alignment for COMMON seems to be
+ safer until we the assembler is fixed. */
+#undef ASM_OUTPUT_ALIGNED_COMMON
+/* Same problem with this one. */
+#undef ASM_OUTPUT_ALIGNED_LOCAL
+
+/* The `string' directive on m68k svr4 does not handle string with
+ escape char (ie., `\') right. Use normal way to output ASCII bytes
+ seems to be safer. */
+#undef ASM_OUTPUT_ASCII
+#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
+do { \
+ register int sp = 0, lp = 0, ch; \
+ fprintf ((FILE), "\t%s ", BYTE_ASM_OP); \
+ do { \
+ ch = (PTR)[sp]; \
+ if (ch > ' ' && ! (ch & 0x80) && ch != '\\') \
+ { \
+ fprintf ((FILE), "'%c", ch); \
+ } \
+ else \
+ { \
+ fprintf ((FILE), "0x%x", ch); \
+ } \
+ if (++sp < (LEN)) \
+ { \
+ if ((sp % 10) == 0) \
+ { \
+ fprintf ((FILE), "\n\t%s ", BYTE_ASM_OP); \
+ } \
+ else \
+ { \
+ putc (',', (FILE)); \
+ } \
+ } \
+ } while (sp < (LEN)); \
+ putc ('\n', (FILE)); \
+} while (0)
+
+/* SVR4 m68k assembler is bitching on the syntax `2.b'.
+ So use the "LLDnnn-LLnnn" format. Define LLDnnn after the table. */
+
+#undef ASM_OUTPUT_CASE_END
+#define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \
+do { \
+ if (switch_table_difference_label_flag) \
+ asm_fprintf ((FILE), "\t%s %LLD%d,%LL%d\n", SET_ASM_OP, (NUM), (NUM));\
+ switch_table_difference_label_flag = 0; \
+} while (0)
+
+int switch_table_difference_label_flag;
+
+#undef ASM_OUTPUT_COMMON
+#undef ASM_OUTPUT_LOCAL
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (SIZE)))
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".lcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (SIZE)))
+
+/* Override the definition in svr4.h. In m68k svr4, using swbeg is the
+ standard way to do switch table. */
+#undef ASM_OUTPUT_BEFORE_CASE_LABEL
+#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
+ fprintf ((FILE), "\t%s &%d\n", SWBEG_ASM_OP, XVECLEN (PATTERN (TABLE), 1));
+
+/* In m68k svr4, a symbol_ref rtx can be a valid PIC operand if it is an
+ operand of a function call. */
+#undef LEGITIMATE_PIC_OPERAND_P
+#define LEGITIMATE_PIC_OPERAND_P(X) \
+ ((! 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)))
+
+/* Turn off function cse if we are doing PIC. We always want function call
+ to be done as `bsr foo@PLTPC', so it will force the assembler to create
+ the PLT entry for `foo'. Doing function cse will cause the address of `foo'
+ to be loaded into a register, which is exactly what we want to avoid when
+ we are doing PIC on svr4 m68k. */
+#undef OVERRIDE_OPTIONS
+#define OVERRIDE_OPTIONS \
+{ \
+ if (flag_pic) flag_no_function_cse = 1; \
+ if (! TARGET_68020 && flag_pic == 2) \
+ error("-fPIC is not currently supported on the 68000 or 68010\n"); \
+}
+
+/* Output assembler code for a block containing the constant parts
+ of a trampoline, leaving space for the variable parts. */
+
+/* On m68k svr4, the trampoline is different from the generic version
+ in that we use a1 as the static call chain. */
+
+#undef TRAMPOLINE_TEMPLATE
+#define TRAMPOLINE_TEMPLATE(FILE) \
+{ \
+ ASM_OUTPUT_SHORT (FILE, GEN_INT (0x227a)); \
+ ASM_OUTPUT_SHORT (FILE, GEN_INT (8)); \
+ ASM_OUTPUT_SHORT (FILE, GEN_INT (0x2f3a)); \
+ ASM_OUTPUT_SHORT (FILE, GEN_INT (8)); \
+ ASM_OUTPUT_SHORT (FILE, GEN_INT (0x4e75)); \
+ ASM_OUTPUT_INT (FILE, const0_rtx); \
+ ASM_OUTPUT_INT (FILE, const0_rtx); \
+}
+
+/* Redefine since we are using a different trampoline */
+#undef TRAMPOLINE_SIZE
+#define TRAMPOLINE_SIZE 18
+
+/* Emit RTL insns to initialize the variable parts of a trampoline.
+ FNADDR is an RTX for the address of the function's pure code.
+ CXT is an RTX for the static chain value for the function. */
+
+#undef INITIALIZE_TRAMPOLINE
+#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
+{ \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 10)), CXT); \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 14)), FNADDR); \
+}
diff --git a/gcc/config/m68k/mot3300-crt0.S b/gcc/config/m68k/mot3300-crt0.S
new file mode 100755
index 0000000..6a32dc2
--- /dev/null
+++ b/gcc/config/m68k/mot3300-crt0.S
@@ -0,0 +1,98 @@
+/* The start module crt0.s for the SysV68 Motorola 3300 Delta Series.
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Contributed by Manfred Hollstein (manfred@lts.sel.alcatel.de).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifdef MOTOROLA
+# define COMM comm
+# define DATA data
+# define EVEN even
+# define FILE(n) file n
+# define GLOBAL_SYM(s) global s
+# define LOCAL_LABEL(l) L%##l
+# define IDENT(s) ident s
+# define TEXT text
+#else /* Assume we are using GNU as. */
+# define COMM .comm
+# define DATA .data
+# define EVEN .even
+# define FILE(name) .file name
+# define GLOBAL_SYM(s) .globl s
+# define LOCAL_LABEL(l) .L.##l
+# define IDENT(s) .section .comment;.asciz s
+# define TEXT .text
+#endif
+
+ FILE ("crt0.s")
+ TEXT
+ GLOBAL_SYM (_start)
+_start: mov.l %d0,splimit%
+ subq.w &8,%sp
+ mov.l 8(%sp),(%sp)
+ lea 12(%sp),%a0
+ mov.l %a0,4(%sp)
+ mov.l %a0,%a1
+LOCAL_LABEL(0):
+ tst.l (%a0)+
+ bne.b LOCAL_LABEL(0)
+#ifdef SGS_CMP_ORDER
+ cmpa.l %a0,(%a1)
+#else
+ cmpa.l (%a1),%a0
+#endif
+ blt.b LOCAL_LABEL(1)
+ subq.w &4,%a0
+LOCAL_LABEL(1):
+ mov.l %a0,8(%sp)
+ mov.l %a0,environ
+ jsr initfpu
+
+ subq.w &8,%sp
+ clr.l %d0 /* if (! isatty (fileno (stderr))) */
+ mov.b _iob+27,%d0
+ mov.l %d0,-(%sp)
+ jsr isatty
+ addq.w &4,%sp
+ tst.l %d0
+ bne.b LOCAL_LABEL(isatty)
+ clr.l -(%sp) /* setbuf (stderr, NULL) */
+ pea _iob+28
+ jsr setbuf
+ addq.w &8,%sp
+LOCAL_LABEL(isatty):
+ addq.w &8,%sp
+
+ jsr main
+ mov.l %d0,(%sp)
+ jsr exit
+ moveq.l &1,%d0
+ trap &0
+ nop
+
+ GLOBAL_SYM (__stop_monitor)
+__stop_monitor:
+ rts
+ EVEN
+
+ COMM splimit%,4
+ COMM environ,4
+
+ IDENT ("$Id: mot3300-crt0.S,v 1.23 1999/01/15 07:37:19 law Exp $")
+ IDENT ("Contributed by Manfred Hollstein (manfred@lts.sel.alcatel.de)")
+ IDENT ("Corrections by Philippe De Muyter (phdm@macqel.be)")
diff --git a/gcc/config/m68k/mot3300.h b/gcc/config/m68k/mot3300.h
new file mode 100755
index 0000000..e1b4060
--- /dev/null
+++ b/gcc/config/m68k/mot3300.h
@@ -0,0 +1,816 @@
+/* Definitions of target machine for GNU compiler,
+ SysV68 Motorola 3300 Delta Series.
+ Copyright (C) 1987, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+ Contributed by Abramo and Roberto Bagnara (bagnara@dipisa.di.unipi.it)
+ based on Alex Crain's 3B1 definitions.
+ Maintained by Philippe De Muyter (phdm@info.ucl.ac.be).
+ Support for GAS added by merging mot3300g.h into this file by
+ Manfred Hollstein (manfred@lts.sel.alcatel.de).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifndef USE_GAS
+#define MOTOROLA /* Use Motorola syntax rather than "MIT" */
+#define MOTOROLA_BSR /* Use Span-dependent optimized bsr */
+#define SGS /* Uses SGS assembler */
+#define SGS_CMP_ORDER /* Takes cmp operands in reverse order */
+#define SGS_SWAP_W /* Use swap.w rather than just plain swap */
+#endif /* USE_GAS */
+
+#define NO_DOLLAR_IN_LABEL
+#define NO_DOT_IN_LABEL
+
+#include "m68k/m68k.h"
+
+/* See m68k.h. 0407 means 68020-68040. */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_68040|MASK_BITFIELD|MASK_68881|MASK_68020)
+#endif
+
+/* -m[c]6800 requires special flag to the assembler. */
+
+#undef ASM_SPEC
+#ifndef USE_GAS
+#define ASM_SPEC "%{m68000:-p 000}%{mc68000:-p 000}"
+#else /* USE_GAS */
+#define ASM_SPEC \
+ "%{v:-v} %{m68000:-mc68000}%{mc68000:-mc68000}%{!mc68000:%{!m68000:-mc68020}}"
+#endif /* USE_GAS */
+
+/* NYI: FP= is equivalent to -msoft-float */
+
+/* We use /lib/libp/lib* when profiling. */
+
+/* NYI: if FP=M68881U library is -lc881u */
+/* NYI: if FP= library is -lc. */
+/* Default for us: FP=M68881 library is -lc881 */
+#undef LIB_SPEC
+#define LIB_SPEC "%{!shlib:%{!msoft-float:-lc881}%{msoft-float:-lc}}"
+#ifdef CROSS_COMPILE
+#ifndef USE_GLD
+#define DEFAULT_A_OUT_NAME "m68ka.out"
+#endif
+#endif
+
+#ifdef USE_GLD
+#undef LINK_SPEC
+#define LINK_SPEC "%{v:-v}"
+#endif /* defined (USE_GLD) */
+
+#define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__}\
+%{!mc68000:%{!m68000: -D__mc68020__}}"
+
+/* Shared libraries need to use crt0s.o */
+
+#undef STARTFILE_SPEC
+#ifdef CROSS_COMPILE
+#define STARTFILE_SPEC \
+ "%{!shlib:%{pg:mcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}\
+ %{shlib:crt0s.o%s shlib.ifile%s} %{p:-L"TOOLDIR_BASE_PREFIX DEFAULT_TARGET_MACHINE"/lib/libp} %{pg:-L"TOOLDIR_BASE_PREFIX DEFAULT_TARGET_MACHINE"/lib/libp} "
+#else /* CROSS_COMPILE */
+#define STARTFILE_SPEC \
+ "%{!shlib:%{pg:mcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}\
+ %{shlib:crt0s.o%s shlib.ifile%s} %{p:-L/usr/lib/libp} %{pg:-L/usr/lib/libp} "
+#endif /* CROSS_COMPILE */
+
+/* Generate calls to memcpy, memcmp and memset. */
+
+#define TARGET_MEM_FUNCTIONS
+
+/* size_t is unsigned int. */
+
+#define SIZE_TYPE "unsigned int"
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* Follow sysV68 cc regarding alignment imposed by char:0; */
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+/* Be compatible with native compiler. */
+#undef PARM_BOUNDARY
+#define PARM_BOUNDARY 16
+
+/* cpp has to support a #sccs directive for the /usr/include files */
+
+#define SCCS_DIRECTIVE
+
+/* Make output for SDB. */
+
+#define SDB_DEBUGGING_INFO
+
+#undef REGISTER_PREFIX
+#define REGISTER_PREFIX "%"
+
+#undef LOCAL_LABEL_PREFIX
+#ifdef USE_GAS
+#define LOCAL_LABEL_PREFIX ".L"
+#else
+#define LOCAL_LABEL_PREFIX "L%"
+#endif
+
+#undef USER_LABEL_PREFIX
+
+#undef IMMEDIATE_PREFIX
+#define IMMEDIATE_PREFIX "&"
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES \
+{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp", \
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7"}
+
+#undef FUNCTION_EXTRA_EPILOGUE
+#define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE) \
+ { extern int current_function_returns_pointer; \
+ if ((current_function_returns_pointer) && \
+ ! find_equiv_reg (0, get_last_insn (), 0, 0, 0, 8, Pmode)) \
+ asm_fprintf (FILE, "\tmov.l %Ra0,%Rd0\n"); }
+
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(FILE, LABEL_NO) \
+ asm_fprintf (FILE, "\tmov.l %I%LLP%d,%Ra0\n\tjsr mcount%%\n", (LABEL_NO))
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#undef ASM_OUTPUT_REG_PUSH
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tmov.l %s,-(%%sp)\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#undef ASM_OUTPUT_REG_POP
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tmov.l (%%sp)+,%s\n", reg_names[REGNO])
+
+#ifndef USE_GAS
+
+#undef ASM_APP_ON
+#define ASM_APP_ON ""
+
+#undef ASM_APP_OFF
+#define ASM_APP_OFF ""
+
+#undef TEXT_SECTION_ASM_OP
+#define TEXT_SECTION_ASM_OP "text"
+#undef DATA_SECTION_ASM_OP
+#define DATA_SECTION_ASM_OP "data"
+#undef ASCII_DATA_ASM_OP
+#define ASCII_DATA_ASM_OP "byte"
+
+#undef SET_ASM_OP
+#define SET_ASM_OP "set"
+
+#endif /* USE_GAS */
+
+#ifdef USE_GLD
+/* Support the ctors and dtors sections for g++. */
+
+#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"x\""
+#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"x\""
+
+/* A list of other sections which the compiler might be "in" at any
+ given time. */
+
+#undef EXTRA_SECTIONS
+#define EXTRA_SECTIONS in_ctors, in_dtors
+
+/* A list of extra section function definitions. */
+
+#undef EXTRA_SECTION_FUNCTIONS
+#define EXTRA_SECTION_FUNCTIONS \
+ CTORS_SECTION_FUNCTION \
+ DTORS_SECTION_FUNCTION
+
+#define CTORS_SECTION_FUNCTION \
+void \
+ctors_section () \
+{ \
+ if (in_section != in_ctors) \
+ { \
+ fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \
+ in_section = in_ctors; \
+ } \
+}
+
+#define DTORS_SECTION_FUNCTION \
+void \
+dtors_section () \
+{ \
+ if (in_section != in_dtors) \
+ { \
+ fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \
+ in_section = in_dtors; \
+ } \
+}
+
+/* A C statement (sans semicolon) to output an element in the table of
+ global constructors. */
+#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
+ do { \
+ ctors_section (); \
+ fprintf (FILE, "\t%s\t ", ASM_LONG); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+/* A C statement (sans semicolon) to output an element in the table of
+ global destructors. */
+#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
+ do { \
+ dtors_section (); \
+ fprintf (FILE, "\t%s\t ", ASM_LONG); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+#endif /* defined (USE_GLD) */
+
+/* The file command should always begin the output. */
+
+#undef ASM_FILE_START
+#ifndef USE_GAS
+#define ASM_FILE_START(FILE) \
+ output_file_directive ((FILE), main_input_filename)
+#else /* USE_GAS */
+#define ASM_FILE_START(FILE) \
+ { \
+ fprintf (FILE, "%s", ASM_APP_OFF); \
+ output_file_directive ((FILE), main_input_filename); \
+ }
+#endif /* USE_GAS */
+
+/* The sysV68 assembler does not accept dots in labels.
+ Let's use percent instead */
+
+#define ASM_IDENTIFY_GCC(FILE) fputs("gcc2_compiled%:\n", FILE)
+
+/* Names to predefine in the preprocessor for this target machine. */
+/* ihnp4!lmayk!lgm@eddie.mit.edu says mc68000 and m68k should not be here,
+ on the other hand I don't care what he says. */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dm68k -Dunix -DsysV68 -D__motorola__ -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
+
+#undef TARGET_VERSION
+#ifndef USE_GAS
+#define TARGET_VERSION fprintf (stderr, " (68k, SGS/AT&T sysV68 syntax)");
+#endif /* USE_GAS */
+
+/* This will return small structs in d0. */
+#define RETURN_IN_MEMORY(type) \
+ ((TYPE_MODE (type) == BLKmode) \
+ || (AGGREGATE_TYPE_P (type) \
+ && GET_MODE_SIZE (TYPE_MODE (type)) > UNITS_PER_WORD))
+
+/* Don't default to pcc-struct-return, because we have already specified
+ exactly how to return structures in the RETURN_IN_MEMORY macro. */
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* If TARGET_68881, return SF and DF values in fp0 instead of d0. */
+/* NYI: If FP=M68881U return SF and DF values in d0. */
+/* NYI: If -mold return pointer in a0 and d0 */
+
+#undef FUNCTION_VALUE
+/* sysV68 (brain damaged) cc convention support. */
+#define FUNCTION_VALUE(VALTYPE,FUNC) \
+ (TREE_CODE (VALTYPE) == REAL_TYPE && TARGET_68881 \
+ ? gen_rtx (REG, TYPE_MODE (VALTYPE), 16) \
+ : (POINTER_TYPE_P (VALTYPE) \
+ ? gen_rtx (REG, TYPE_MODE (VALTYPE), 8) \
+ : gen_rtx (REG, TYPE_MODE (VALTYPE), 0)))
+
+/* If TARGET_68881, SF and DF values are returned in fp0 instead of d0. */
+
+/* Is LIBCALL_VALUE never called with a pointer ? */
+#undef LIBCALL_VALUE
+#define LIBCALL_VALUE(MODE) \
+ gen_rtx (REG, (MODE), \
+ ((TARGET_68881 \
+ && ((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode)) \
+ ? 16 : 0))
+
+/* 1 if N is a possible register number for a function value.
+ d0 may be used, and fp0 as well if -msoft-float is not specified. */
+
+#undef FUNCTION_VALUE_REGNO_P
+/* sysV68 (brain damaged) cc convention support. */
+#define FUNCTION_VALUE_REGNO_P(N) \
+ ((N) == 0 || (N) == 8 || (TARGET_68881 && (N) == 16))
+
+/* Define this to be true when FUNCTION_VALUE_REGNO_P is true for
+ more than one register. */
+
+#undef NEEDS_UNTYPED_CALL
+#define NEEDS_UNTYPED_CALL 1
+
+#ifndef USE_GAS
+/* This is the command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#undef GLOBAL_ASM_OP
+#define GLOBAL_ASM_OP "global"
+#endif /* USE_GAS */
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#undef ASM_FORMAT_PRIVATE_NAME
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 12), \
+ sprintf ((OUTPUT), "%s_%%%d", (NAME), (LABELNO)))
+
+#ifdef USE_GAS
+#undef ASM_LONG
+#define ASM_LONG ".long"
+#undef ASM_SHORT
+#define ASM_SHORT ".short"
+#undef ASM_CHAR
+#define ASM_CHAR ".byte"
+#undef ASM_BYTE
+#define ASM_BYTE ".byte"
+#undef ASM_BYTE_OP
+#define ASM_BYTE_OP ".byte"
+#else
+#undef ASM_LONG
+#define ASM_LONG "long"
+#undef ASM_SHORT
+#define ASM_SHORT "short"
+#undef ASM_CHAR
+#define ASM_CHAR "byte"
+#undef ASM_BYTE
+#define ASM_BYTE "byte"
+#undef ASM_BYTE_OP
+#define ASM_BYTE_OP "byte"
+#endif /* USE_GAS */
+
+/* The sysV68 as doesn't know about double's and float's. */
+/* This is how to output an assembler line defining a `double' constant. */
+
+#undef ASM_OUTPUT_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+do { long l[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
+ fprintf (FILE, "\t%s 0x%x,0x%x\n", ASM_LONG, l[0], l[1]); \
+ } while (0)
+
+#undef ASM_OUTPUT_LONG_DOUBLE
+#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
+do { long l[3]; \
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
+ fprintf (FILE, "\t%s 0x%x,0x%x,0x%x\n", ASM_LONG, l[0], l[1], l[2]); \
+ } while (0)
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#undef ASM_OUTPUT_FLOAT
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+do { long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
+ fprintf ((FILE), "\t%s 0x%x\n", ASM_LONG, l); \
+ } while (0)
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#undef ASM_OUTPUT_INT
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\t%s ", ASM_LONG), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#undef ASM_OUTPUT_SHORT
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\t%s ", ASM_SHORT), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#undef ASM_OUTPUT_CHAR
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\t%s ", ASM_CHAR), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#undef ASM_OUTPUT_BYTE
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\t%s 0x%x\n", ASM_BYTE, (VALUE))
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#ifndef USE_GAS
+#define ALIGN_ASM_OP "even"
+#else /* USE_GAS */
+#define ALIGN_ASM_OP ".even"
+#endif /* USE_GAS */
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) >= 1) \
+ fprintf (FILE, "\t%s\n", ALIGN_ASM_OP);
+
+#ifndef USE_GAS
+#define SKIP_ASM_OP "space"
+#else /* USE_GAS */
+#define SKIP_ASM_OP ".skip"
+#endif /* USE_GAS */
+
+#undef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t%s %u\n", SKIP_ASM_OP, (SIZE))
+
+/* Can't use ASM_OUTPUT_SKIP in text section. */
+
+#define ASM_NO_SKIP_IN_TEXT 1
+
+/* The beginnings of sdb support... */
+
+/* Undefining these will allow `output_file_directive' (in toplev.c)
+ to default to the right thing. */
+#undef ASM_OUTPUT_MAIN_SOURCE_FILENAME
+#ifndef USE_GAS
+#define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
+ do { fprintf (FILE, "\tfile\t"); \
+ output_quoted_string (FILE, FILENAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+#undef ASM_OUTPUT_SOURCE_LINE
+#define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \
+ fprintf (FILE, "\tln\t%d\n", \
+ (sdb_begin_function_line \
+ ? last_linenum - sdb_begin_function_line : 1))
+
+/* Yet another null terminated string format. */
+
+#undef ASM_OUTPUT_ASCII
+#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
+ do { register int sp = 0, lp = 0; \
+ fprintf ((FILE), "\t%s\t", ASM_BYTE_OP); \
+ loop: \
+ if ((PTR)[sp] > ' ' && ! ((PTR)[sp] & 0x80) && (PTR)[sp] != '\\') \
+ { lp += 3; \
+ fprintf ((FILE), "'%c", (PTR)[sp]); } \
+ else \
+ { lp += 5; \
+ fprintf ((FILE), "0x%x", (PTR)[sp]); } \
+ if (++sp < (LEN)) \
+ { if (lp > 60) \
+ { lp = 0; \
+ fprintf ((FILE), "\n\t%s ", ASCII_DATA_ASM_OP); } \
+ else \
+ putc (',', (FILE)); \
+ goto loop; } \
+ putc ('\n', (FILE)); } while (0)
+#endif /* USE_GAS */
+
+#ifndef USE_GAS
+/* Output a float value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
+ do { long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (r, l); \
+ /* Use hex representation even if CODE is f. as needs it. */ \
+ fprintf ((FILE), "&0x%lx", l); \
+ } while (0)
+
+/* Output a double value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ do { long l[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
+ fprintf ((FILE), "&0x%lx%08lx", l[0], l[1]); \
+ } while (0)
+#endif /* USE_GAS */
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
+ sprintf ((LABEL), "%s%s%d", LOCAL_LABEL_PREFIX, (PREFIX), (NUM))
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#undef ASM_OUTPUT_INTERNAL_LABEL
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ asm_fprintf (FILE, "%L%s%d:\n", PREFIX, NUM)
+
+/* The prefix to add to user-visible assembler symbols. */
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+
+/* This is how to output an element of a case-vector that is absolute.
+ (The 68000 does not use such vectors,
+ but we must define this macro anyway.) */
+/* The L after the local prefix is the "L" prefix for the normal labels
+ generated by gcc; why are ASM_OUTPUT_ADDR_VEC_ELT and
+ ASM_OUTPUT_ADDR_DIFF_ELT not called with a PREFIX parameter, like
+ ASM_OUTPUT_INTERNAL_LABEL ? */
+
+#undef ASM_OUTPUT_ADDR_VEC_ELT
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ asm_fprintf (FILE, "\t%s %LL%d\n", ASM_LONG, (VALUE))
+
+/* This is how to output an element of a case-vector that is relative. */
+
+#undef ASM_OUTPUT_ADDR_DIFF_ELT
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
+ asm_fprintf (FILE, "\t%s %LL%d-%LL%d\n", ASM_SHORT, (VALUE), (REL))
+
+#ifndef USE_GAS
+
+#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
+ asm_fprintf (FILE, "\tswbeg &%d\n%L%s%d:\n", \
+ XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM))
+
+/* sysV68 as cannot handle LD%n(%pc,%reg) */
+#define SGS_NO_LI
+
+/* labelno is not used here */
+#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
+ asm_fprintf (file, "12(%Rpc,%s.", regname)
+
+#define ASM_RETURN_CASE_JUMP \
+ do { \
+ if (TARGET_5200) \
+ return "ext%.l %0\n\tjmp 8(%%pc,%0.l)"; \
+ else \
+ return "jmp 8(%%pc,%0.w)"; \
+ } while (0)
+
+#else /* USE_GAS */
+
+/* labelno is not used here */
+#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
+ asm_fprintf (file, "%Rpc@(6,%s:", regname)
+
+#define ASM_RETURN_CASE_JUMP return "jmp %%pc@(2,%0:w)"
+
+#endif /* USE_GAS */
+
+#ifndef USE_GAS
+
+/* Translate some opcodes to fit the sysV68 assembler syntax. */
+/* The opcodes fdmov and fsmov are guesses. */
+
+/* cliffm@netcom.com says no need for .w suffix on jumps. */
+#undef ASM_OUTPUT_OPCODE
+#define ASM_OUTPUT_OPCODE(FILE, PTR) \
+{ if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
+ { ++(PTR); \
+ while (*(PTR) != ' ') \
+ { putc (*(PTR), (FILE)); ++(PTR); } \
+ } \
+ else if ((PTR)[0] == 's') \
+ { \
+ if (!strncmp ((PTR), "swap", 4)) \
+ { fprintf ((FILE), "swap.w"); (PTR) += 4; } \
+ } \
+ else if ((PTR)[0] == 'f') \
+ { \
+ if (!strncmp ((PTR), "fmove", 5)) \
+ { fprintf ((FILE), "fmov"); (PTR) += 5; } \
+ else if (!strncmp ((PTR), "f%$move", 7)) \
+ { if (TARGET_68040_ONLY) \
+ { fprintf ((FILE), "fsmov"); (PTR) += 7; } \
+ else \
+ { fprintf ((FILE), "fmov"); (PTR) += 7; } } \
+ else if (!strncmp ((PTR), "f%&move", 7)) \
+ { if (TARGET_68040_ONLY) \
+ { fprintf ((FILE), "fdmov"); (PTR) += 7; } \
+ else \
+ { fprintf ((FILE), "fmov"); (PTR) += 7; } } \
+ else if (!strncmp ((PTR), "ftst", 4)) \
+ { fprintf ((FILE), "ftest"); (PTR) += 4; } \
+ else if (!strncmp ((PTR), "fbne", 4)) \
+ { fprintf ((FILE), "fbneq"); (PTR) += 4; } \
+ else if (!strncmp ((PTR), "fsne", 4)) \
+ { fprintf ((FILE), "fsneq"); (PTR) += 4; } \
+ } \
+/* MOVE, MOVEA, MOVEQ, MOVEC ==> MOV */ \
+ else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
+ { fprintf ((FILE), "mov"); (PTR) += 4; \
+ if ((PTR)[0] == 'q' || (PTR)[0] == 'a' \
+ || (PTR)[0] == 'c') (PTR)++; } \
+/* SUB, SUBQ, SUBA, SUBI ==> SUB */ \
+ else if ((PTR)[0] == 's' && (PTR)[1] == 'u' \
+ && (PTR)[2] == 'b') \
+ { fprintf ((FILE), "sub"); (PTR) += 3; \
+ if ((PTR)[0] == 'q' || (PTR)[0] == 'i' \
+ || (PTR)[0] == 'a') (PTR)++; } \
+/* CMP, CMPA, CMPI, CMPM ==> CMP */ \
+ else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \
+ && (PTR)[2] == 'p') \
+ { fprintf ((FILE), "cmp"); (PTR) += 3; \
+ if ((PTR)[0] == 'a' || (PTR)[0] == 'i' \
+ || (PTR)[0] == 'm') (PTR)++; } \
+}
+#endif /* USE_GAS */
+
+/* phdm@info.ucl.ac.be says to pass SIZE, not ROUNDED. */
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#undef ASM_OUTPUT_COMMON
+#ifndef USE_GAS
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\tcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (SIZE)))
+#else /* USE_GAS */
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\t.comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (SIZE)))
+#endif /* USE_GAS */
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#undef ASM_OUTPUT_LOCAL
+#ifndef USE_GAS
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\tlcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (SIZE)))
+#else /* USE_GAS */
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\t.lcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (SIZE)))
+#endif /* USE_GAS */
+
+#ifndef USE_GAS
+/* Override usual definitions of SDB output macros.
+ These definitions differ only in the absence of the period
+ at the beginning of the name of the directive
+ and in the use of `~' as the symbol for the current location. */
+
+#define PUT_SDB_SCL(a) fprintf(asm_out_file, "\tscl\t%d;", (a))
+#define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\tval\t%d;", (a))
+#define PUT_SDB_VAL(a) \
+( fputs ("\tval\t", asm_out_file), \
+ output_addr_const (asm_out_file, (a)), \
+ fputc (';', asm_out_file))
+
+#define PUT_SDB_DEF(a) \
+do { fprintf (asm_out_file, "\tdef\t"); \
+ ASM_OUTPUT_LABELREF (asm_out_file, a); \
+ fprintf (asm_out_file, ";"); } while (0)
+
+#define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\tdef\t~%s;",a)
+#define PUT_SDB_ENDEF fputs("\tendef\n", asm_out_file)
+#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\ttype\t0%o;", a)
+#define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\tsize\t%d;", a)
+#define PUT_SDB_START_DIM fprintf(asm_out_file, "\tdim\t")
+#define PUT_SDB_NEXT_DIM(a) fprintf(asm_out_file, "%d,", a)
+#define PUT_SDB_LAST_DIM(a) fprintf(asm_out_file, "%d;", a)
+
+#define PUT_SDB_TAG(a) \
+do { fprintf (asm_out_file, "\ttag\t"); \
+ ASM_OUTPUT_LABELREF (asm_out_file, a); \
+ fprintf (asm_out_file, ";"); } while (0)
+
+#define PUT_SDB_BLOCK_START(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~bb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_BLOCK_END(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~eb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_FUNCTION_START(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~bf;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_FUNCTION_END(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~ef;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_EPILOGUE_END(NAME) \
+ fprintf (asm_out_file, \
+ "\tdef\t%s;\tval\t~;\tscl\t-1;\tendef\n", \
+ (NAME))
+
+#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
+ sprintf ((BUFFER), "~%dfake", (NUMBER));
+
+#endif /* USE_GAS */
+
+/* Define subroutines to call to handle multiply, divide, and remainder.
+ Use the subroutines that the sysV68's library provides.
+ The `*' prevents an underscore from being prepended by the compiler. */
+/* The '*' is also used by INIT_CUMULATIVE_ARGS */
+
+#define DIVSI3_LIBCALL "*ldiv%%"
+#define UDIVSI3_LIBCALL "*uldiv%%"
+#define MODSI3_LIBCALL "*lrem%%"
+#define UMODSI3_LIBCALL "*ulrem%%"
+#define MULSI3_LIBCALL "*lmul%%"
+
+struct sysV68_cumulative_args
+ {
+ int offset;
+ int libcall;
+ };
+
+#undef CUMULATIVE_ARGS
+#define CUMULATIVE_ARGS struct sysV68_cumulative_args
+
+#undef INIT_CUMULATIVE_ARGS
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
+do {(CUM).offset = 0;\
+(CUM).libcall = (LIBNAME) && (*XSTR((LIBNAME), 0) == '*');} while(0)
+
+#undef FUNCTION_ARG_ADVANCE
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ ((CUM).offset += ((MODE) != BLKmode \
+ ? (GET_MODE_SIZE (MODE) + 3) & ~3 \
+ : (int_size_in_bytes (TYPE) + 3) & ~3))
+
+#undef FUNCTION_ARG
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+(((CUM).libcall && (CUM).offset == 0) ? gen_rtx(REG, (MODE), 0)\
+: (TARGET_REGPARM && (CUM).offset < 8) ? gen_rtx (REG, (MODE), (CUM).offset / 4) : 0)
+
+#undef FUNCTION_ARG_PARTIAL_NREGS
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
+((TARGET_REGPARM && (CUM).offset < 8 \
+ && 8 < ((CUM).offset + ((MODE) == BLKmode \
+ ? int_size_in_bytes (TYPE) \
+ : GET_MODE_SIZE (MODE)))) \
+ ? 2 - (CUM).offset / 4 : 0)
+
+#undef FUNCTION_ARG_REGNO_P
+#define FUNCTION_ARG_REGNO_P(N) (TARGET_68020 ? 0 : (N) == 0)
+
+/* manfred@lts.sel.alcatel.de: I believe that most delta machines are configured to have
+ a 6888[12] FPU for which we need to link -lm881 instead of -lm; define ALT_LIBM to
+ tell g++.c about that. */
+#define ALT_LIBM "-lm881"
+
+#if (TARGET_DEFAULT & MASK_68881) /* The default configuration has a 6888[12] FPU. */
+#define MATH_LIBRARY "-lm881"
+#endif
+
+/* Currently we do not have the atexit() function,
+ so take that from libgcc2.c */
+
+#define NEED_ATEXIT 1
+#define HAVE_ATEXIT 1
+
+#define EXIT_BODY \
+ do \
+ { \
+ __stop_monitor (); \
+ _cleanup (); \
+ } while (0)
+
+/* FINALIZE_TRAMPOLINE clears the instruction cache. */
+
+#undef FINALIZE_TRAMPOLINE
+#define FINALIZE_TRAMPOLINE(TRAMP) \
+ if (!TARGET_68040) \
+ ; \
+ else \
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__clear_insn_cache"), \
+ 0, VOIDmode, 0)
diff --git a/gcc/config/m68k/mot3300Mcrt0.S b/gcc/config/m68k/mot3300Mcrt0.S
new file mode 100755
index 0000000..539fe8e
--- /dev/null
+++ b/gcc/config/m68k/mot3300Mcrt0.S
@@ -0,0 +1,142 @@
+/* The start module mcrt0.s for the SysV68 Motorola 3300 Delta Series.
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Contributed by Manfred Hollstein (manfred@lts.sel.alcatel.de).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifdef MOTOROLA
+# define COMM comm
+# define DATA data
+# define EVEN even
+# define FILE(n) file n
+# define GLOBAL_SYM(s) global s
+# define LOCAL_LABEL(l) L%##l
+# define IDENT(s) ident s
+# define TEXT text
+#else /* Assume we are using GNU as. */
+# define COMM .comm
+# define DATA .data
+# define EVEN .even
+# define FILE(name) .file name
+# define GLOBAL_SYM(s) .globl s
+# define LOCAL_LABEL(l) .L.##l
+# define IDENT(s) .section .comment;.asciz s
+# define TEXT .text
+#endif
+
+ FILE ("mcrt0.s")
+ TEXT
+ GLOBAL_SYM (_start)
+_start: mov.l %d0,splimit%
+ subq.w &8,%sp
+ mov.l 8(%sp),(%sp)
+ lea 12(%sp),%a0
+ mov.l %a0,___Argv
+ mov.l %a0,4(%sp)
+ mov.l %a0,%a1
+LOCAL_LABEL(0):
+ tst.l (%a0)+
+ bne.b LOCAL_LABEL(0)
+#ifdef SGS_CMP_ORDER
+ cmpa.l %a0,(%a1)
+#else
+ cmpa.l (%a1),%a0
+#endif
+ blt.b LOCAL_LABEL(1)
+ subq.w &4,%a0
+LOCAL_LABEL(1):
+ mov.l %a0,8(%sp)
+ mov.l %a0,environ
+ jsr initfpu
+
+ sub &8,%sp
+ clr.l %d0 /* if (! isatty (fileno (stderr))) */
+ mov.b _iob+27,%d0
+ mov.l %d0,-(%sp)
+ jsr isatty
+ addq.w &4,%sp
+ tst.l %d0
+ bne.b LOCAL_LABEL(isatty)
+ clr.l -(%sp) /* setbuf (stderr, NULL) */
+ pea _iob+28
+ jsr setbuf
+ addq.w &8,%sp
+LOCAL_LABEL(isatty):
+ addq.w &8,%sp
+
+ mov.l &600,-(%sp)
+ mov.l &etext,%d1
+ subi.l &LOCAL_LABEL(endofstart),%d1
+ addq.l &1,%d1
+ bclr &0,%d1
+ addi.l &4812,%d1
+ asr.l &1,%d1
+ mov.l %d1,-(%sp)
+ add.l %d1,%d1
+ mov.l %d1,-(%sp)
+ jsr sbrk
+ addq.w &4,%sp
+#ifdef SGS_CMP_ORDER
+ cmpa.l %a0,&-1
+#else
+ cmpa.l &-1,%a0
+#endif
+ beq.b LOCAL_LABEL(3)
+ mov.l %a0,-(%sp)
+ add.l &12,%a0
+ mov.l %a0,_countbase
+ mov.l &etext,-(%sp)
+ mov.l &LOCAL_LABEL(endofstart),-(%sp)
+ jsr monitor
+ lea 20(%sp),%sp
+ jsr main
+ mov.l %d0,(%sp)
+ jsr exit
+_exit: moveq &1,%d0
+ trap &0
+
+ GLOBAL_SYM (__stop_monitor)
+__stop_monitor:
+ clr.l -(%sp)
+ jsr monitor
+ add.w &4,%sp
+ rts
+
+LOCAL_LABEL(errtxt):
+ byte 'N,'o,' ,'s,'p,'a,'c,'e,' ,'f,'o,'r,' ,'m,'o,'n
+ byte 'i,'t,'o,'r,' ,'b,'u,'f,'f,'e,'r,'\n
+LOCAL_LABEL(errtxt_end):
+
+ EVEN
+LOCAL_LABEL(3):
+ pea LOCAL_LABEL(errtxt_end)-LOCAL_LABEL(errtxt)
+ pea LOCAL_LABEL(errtxt)(%pc)
+ pea 2
+ jsr write
+ bra.b _exit
+LOCAL_LABEL(endofstart):
+
+ EVEN
+
+ COMM splimit%,4
+ COMM environ,4
+ COMM _countbase,4
+
+ IDENT ("$Id: mot3300Mcrt0.S,v 1.23 1999/01/15 07:37:19 law Exp $")
+ IDENT ("Contributed by Manfred Hollstein (manfred@lts.sel.alcatel.de)")
+ IDENT ("Corrections by Philippe De Muyter (phdm@macqel.be)")
diff --git a/gcc/config/m68k/netbsd.h b/gcc/config/m68k/netbsd.h
new file mode 100755
index 0000000..6bd9161
--- /dev/null
+++ b/gcc/config/m68k/netbsd.h
@@ -0,0 +1,63 @@
+#include <m68k/m68k.h>
+
+/* Get generic NetBSD definitions. */
+
+#include <netbsd.h>
+
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
+
+/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#undef CPP_SPEC
+#define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__ -D__HAVE_FPU__} %{posix:-D_POSIX_SOURCE}"
+
+#undef ASM_SPEC
+#define ASM_SPEC " %| %{m68030} %{m68040} %{m68060} %{fpic:-k} %{fPIC:-k -K}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dunix -Dm68k -Dmc68000 -Dmc68020 -D__NetBSD__ -Asystem(unix) -Asystem(NetBSD) -Acpu(m68k) -Amachine(m68k)"
+
+/* Make gcc agree with <machine/ansi.h> */
+
+#undef SIZE_TYPE
+#define SIZE_TYPE "unsigned int"
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "int"
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+
+#undef WCHAR_UNSIGNED
+#define WCHAR_UNSIGNED 0
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Do not break .stabs pseudos into continuations. */
+
+#define DBX_CONTIN_LENGTH 0
+
+/* This is the char to use for continuation (in case we need to turn
+ continuation back on). */
+
+#define DBX_CONTIN_CHAR '?'
+
+/* Don't default to pcc-struct-return, because gcc is the only compiler, and
+ we want to retain compatibility with older gcc versions. */
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* Until they use ELF or something that handles dwarf2 unwinds
+ and initialization stuff better. */
+#define DWARF2_UNWIND_INFO 0
+
diff --git a/gcc/config/m68k/news.h b/gcc/config/m68k/news.h
new file mode 100755
index 0000000..f83524c
--- /dev/null
+++ b/gcc/config/m68k/news.h
@@ -0,0 +1,552 @@
+/* Definitions of target machine for GNU compiler. SONY NEWS-OS 4 version.
+ Copyright (C) 1987, 89, 93, 94, 96, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifndef USE_GAS
+/* This controls conditionals in m68k.h. */
+#define MOTOROLA /* Use Motorola syntax rather than "MIT" */
+#define SGS_NO_LI /* Suppress jump table label usage */
+#endif
+
+#define NO_DOLLAR_IN_LABEL
+#define NO_DOT_IN_LABEL
+
+#include "m68k/m68k.h"
+
+/* See m68k.h. 7 means 68020 with 68881. */
+
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
+
+/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+/* These are the ones defined by Sony, plus mc68000 for uniformity with
+ GCC on other 68000 systems. */
+
+#ifdef MOTOROLA
+#define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dnews700 -D__motorola__ -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
+#else
+#define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dnews700 -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
+#endif
+
+/* These conditionals tested for different submodels,
+ but they were incorrect since they tested the host rather than the target.
+ The choice of model shouldn't actually matter. */
+
+#if 0
+#ifdef news800
+#define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dnews800 -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
+#endif
+#ifdef news900
+#define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dnews900 -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
+#endif
+#ifdef news1500
+#define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dmc68030 -Dnews1500 -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
+#endif
+#ifdef news1700
+#define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dmc68030 -Dnews1700 -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
+#endif
+#ifdef news1800
+#define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dmc68030 -Dnews1800 -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
+#endif
+#ifdef news1900
+#define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dmc68030 -Dnews1900 -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
+#endif
+#endif
+
+/* Link with libg.a when debugging, for dbx's sake. */
+
+#define LIB_SPEC "%{g:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} "
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+#if 0
+/* This is to be compatible with types.h.
+ It was found to be necessary with Newsos 3. */
+
+#define SIZE_TYPE "long int"
+#endif
+
+/* Override parts of m68k.h to fit Sony's assembler syntax. */
+
+#undef BIGGEST_ALIGNMENT
+#undef CALL_USED_REGISTERS
+#undef FUNCTION_VALUE
+#undef LIBCALL_VALUE
+#undef FUNCTION_PROFILER
+
+#ifdef MOTOROLA
+#undef FUNCTION_PROLOGUE
+#undef FUNCTION_EPILOGUE
+#undef REGISTER_NAMES
+#undef ASM_OUTPUT_REG_PUSH
+#undef ASM_OUTPUT_REG_POP
+#undef ASM_OUTPUT_DOUBLE
+#undef ASM_OUTPUT_SKIP
+#undef ASM_FORMAT_PRIVATE_NAME
+#endif
+
+#undef ASM_OUTPUT_ALIGN
+
+/* There is no point aligning anything to a rounder boundary than this. */
+#define BIGGEST_ALIGNMENT 32
+
+/* A bitfield declared as `int' forces `int' alignment for the struct. */
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* NEWS makes d2, d3, fp2 and fp3 unsaved registers, unlike the Sun system. */
+
+#define CALL_USED_REGISTERS \
+ {1, 1, 1, 1, 0, 0, 0, 0, \
+ 1, 1, 0, 0, 0, 0, 0, 1, \
+ 1, 1, 1, 1, 0, 0, 0, 0}
+
+/* NEWS returns floats and doubles in fp0, not d0/d1. */
+
+#define FUNCTION_VALUE(VALTYPE,FUNC) LIBCALL_VALUE (TYPE_MODE (VALTYPE))
+
+#define LIBCALL_VALUE(MODE) \
+ gen_rtx (REG, (MODE), \
+ ((TARGET_68881 \
+ && ((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode)) \
+ ? 16 : 0))
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ fprintf (FILE, "\t.align %d\n", (LOG))
+
+#ifdef MOTOROLA
+
+/* Don't try to define `gcc_compiled.' since the assembler does not
+ accept symbols with periods. This is no real loss since GDB only
+ really needs it for parms passed in registers. */
+#define ASM_IDENTIFY_GCC(FILE)
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ register int regno; \
+ register int mask = 0; \
+ extern char call_used_regs[]; \
+ int fsize = ((SIZE) + 3) & -4; \
+ if (frame_pointer_needed) \
+ { if (fsize < 0x8000) \
+ fprintf (FILE, "\tlink fp,#%d\n", -fsize); \
+ else if (TARGET_68020) \
+ fprintf (FILE, "\tlink.l fp,#%d\n", -fsize); \
+ else \
+ fprintf (FILE, "\tlink fp,#0\n\tsub.l #%d,sp\n", fsize);\
+ } \
+ else if (fsize) \
+ { \
+ int amt = fsize + 4; \
+ /* Adding negative number is faster on the 68040. */ \
+ if (fsize + 4 < 0x8000) \
+ asm_fprintf (FILE, "\tadd.w %0I%d,%Rsp\n", - amt); \
+ else \
+ asm_fprintf (FILE, "\tadd.l %0I%d,%Rsp\n", - amt); \
+ } \
+ for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ mask |= 1 << (regno - 16); \
+ if (mask != 0) \
+ fprintf (FILE, "\tfmovem.x #0x%x,-(sp)\n", mask & 0xff); \
+ mask = 0; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ mask |= 1 << (15 - regno); \
+ if (frame_pointer_needed) \
+ mask &= ~ (1 << (15-FRAME_POINTER_REGNUM)); \
+ if (exact_log2 (mask) >= 0) \
+ fprintf (FILE, "\tmove.l %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]); \
+ else if (mask) fprintf (FILE, "\tmovem.l #0x%x,-(sp)\n", mask); }
+
+#define FUNCTION_PROFILER(FILE, LABEL_NO) \
+ fprintf (FILE, "\tmove.l #LP%d,d0\n\tjsr mcount\n", (LABEL_NO));
+
+#define FUNCTION_EPILOGUE(FILE, SIZE) \
+{ register int regno; \
+ register int mask, fmask; \
+ register int nregs; \
+ int offset, foffset; \
+ extern char call_used_regs[]; \
+ int fsize = ((SIZE) + 3) & -4; \
+ int big = 0; \
+ nregs = 0; fmask = 0; \
+ for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ { nregs++; fmask |= 1 << (23 - regno); } \
+ foffset = nregs * 12; \
+ nregs = 0; mask = 0; \
+ if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ { nregs++; mask |= 1 << regno; } \
+ offset = foffset + nregs * 4; \
+ if (offset + fsize >= 0x8000 \
+ && frame_pointer_needed \
+ && (mask || fmask)) \
+ { fprintf (FILE, "\tmove.l #%d,a0\n", -fsize); \
+ fsize = 0, big = 1; } \
+ if (exact_log2 (mask) >= 0) { \
+ if (big) \
+ fprintf (FILE, "\tmove.l (-%d,fp,a0.l),%s\n", \
+ offset + fsize, reg_names[exact_log2 (mask)]); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tmove.l (sp)+,%s\n", \
+ reg_names[exact_log2 (mask)]); \
+ else \
+ fprintf (FILE, "\tmove.l (-%d,fp),%s\n", \
+ offset + fsize, reg_names[exact_log2 (mask)]); } \
+ else if (mask) { \
+ if (big) \
+ fprintf (FILE, "\tmovem.l (-%d,fp,a0.l),#0x%x\n", \
+ offset + fsize, mask); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tmovem.l (sp)+,#0x%x\n", mask); \
+ else \
+ fprintf (FILE, "\tmovem.l (-%d,fp),#0x%x\n", \
+ offset + fsize, mask); } \
+ if (fmask) { \
+ if (big) \
+ fprintf (FILE, "\tfmovem.x (-%d,fp,a0.l),#0x%x\n", \
+ foffset + fsize, fmask); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tfmovem.x (sp)+,#0x%x\n", fmask); \
+ else \
+ fprintf (FILE, "\tfmovem.x (-%d,fp),#0x%x\n", \
+ foffset + fsize, fmask); } \
+ if (frame_pointer_needed) \
+ fprintf (FILE, "\tunlk fp\n"); \
+ else if (fsize) \
+ { \
+ if (fsize + 4 < 0x8000) \
+ fprintf (FILE, "\tadd.w #%d,sp\n", fsize + 4); \
+ else \
+ fprintf (FILE, "\tadd.l #%d,sp\n", fsize + 4); \
+ } \
+ if (current_function_pops_args) \
+ fprintf (FILE, "\trtd #%d\n", current_function_pops_args); \
+ else fprintf (FILE, "\trts\n"); }
+
+/* Difference from m68k.h is in `fp' instead of `a6'. */
+
+#define REGISTER_NAMES \
+{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
+ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \
+ "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7"}
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tmove.l %s,-(sp)\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tmove.l (sp)+,%s\n", reg_names[REGNO])
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \
+ fprintf (FILE, "\t.double 0d%s\n", dstr); \
+ } while (0)
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t.space %u\n", (SIZE))
+
+#if 0
+/* The NEWS assembler in version 3.4 complains about fmove.d, but this
+ macro proved not to work right. 3.4 is old, so forget about it. */
+#define ASM_OUTPUT_OPCODE(FILE, STRING) \
+{ \
+ if (!strncmp (STRING, "fmove.d", 7) \
+ && CONSTANT_P (operands[1])) \
+ { \
+ fprintf (FILE, "fmove.x"); \
+ STRING += 7; \
+ } \
+}
+#endif
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 13), \
+ sprintf ((OUTPUT), "%s$$$%d", (NAME), (LABELNO)))
+
+/* Output a float value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
+ do { \
+ if (CODE == 'f') \
+ { \
+ char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.9e", dstr); \
+ if (REAL_VALUE_ISINF (VALUE) || REAL_VALUE_ISNAN (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "#0f-99e999"); \
+ else \
+ fprintf (FILE, "#0f99e999"); \
+ } \
+ else if (REAL_VALUE_MINUS_ZERO (VALUE)) \
+ fprintf (FILE, "#0f-0.0"); \
+ else \
+ fprintf (FILE, "#0f%s", dstr); \
+ } \
+ else \
+ { \
+ long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
+ fprintf (FILE, "#0x%lx", l); \
+ } \
+ } while (0)
+
+/* Output a double value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.20e", dstr ); \
+ if (REAL_VALUE_ISINF (VALUE) || REAL_VALUE_ISNAN (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "#0d-99e999"); \
+ else \
+ fprintf (FILE, "#0d99e999"); \
+ } \
+ else if (REAL_VALUE_MINUS_ZERO (VALUE)) \
+ fprintf (FILE, "#0d-0.0"); \
+ else \
+ fprintf (FILE, "#0d%s", dstr); \
+ } while (0)
+
+/* Note, long double immediate operands are not actually
+ generated by m68k.md. */
+#undef ASM_OUTPUT_LONG_DOUBLE_OPERAND
+#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)
+
+#if 0
+#undef PRINT_OPERAND
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (CODE == '.') fprintf (FILE, "."); \
+ else if (CODE == '#') fprintf (FILE, "#"); \
+ else if (CODE == '-') fprintf (FILE, "-(sp)"); \
+ else if (CODE == '+') fprintf (FILE, "(sp)+"); \
+ else if (CODE == '@') fprintf (FILE, "(sp)"); \
+ else if (CODE == '!') fprintf (FILE, "fpcr"); \
+ else if (CODE == '$') {if (TARGET_68040_ONLY) fprintf (FILE, "s");} \
+ else if (CODE == '&') {if (TARGET_68040_ONLY) fprintf (FILE, "d");} \
+ else if (CODE == '/') \
+ ; \
+ else if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if (GET_CODE (X) == MEM) \
+ output_address (XEXP (X, 0)); \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
+ { REAL_VALUE_TYPE r; \
+ REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
+ if (CODE == 'f') \
+ { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (r, "%.9e", dstr); \
+ if (REAL_VALUE_ISINF (r) || REAL_VALUE_ISNAN (r)) { \
+ if (REAL_VALUE_NEGATIVE (r)) \
+ fprintf (FILE, "#0f-99e999"); \
+ else \
+ fprintf (FILE, "#0f99e999"); } \
+ else if (REAL_VALUE_MINUS_ZERO (r)) \
+ fprintf (FILE, "#0f-0.0"); \
+ else \
+ fprintf (FILE, "#0f%s", dstr); \
+ } \
+ else \
+ { long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (r, l); \
+ fprintf (FILE, "#0x%x", l); \
+ }} \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == XFmode) \
+ { REAL_VALUE_TYPE r; \
+ REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
+ ASM_OUTPUT_LONG_DOUBLE_OPERAND (FILE, r); } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode) \
+ { REAL_VALUE_TYPE r; char dstr[30]; \
+ REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
+ REAL_VALUE_TO_DECIMAL (r, "%.20e", dstr ); \
+ if (REAL_VALUE_ISINF (r) || REAL_VALUE_ISNAN (r)) { \
+ if (REAL_VALUE_NEGATIVE (r)) \
+ fprintf (FILE, "#0d-99e999"); \
+ else \
+ fprintf (FILE, "#0d99e999"); } \
+ else if (REAL_VALUE_MINUS_ZERO (r)) \
+ fprintf (FILE, "#0d-0.0"); \
+ else \
+ fprintf (FILE, "#0d%s", dstr); } \
+ else if (CODE == 'b') output_addr_const (FILE, X); \
+ else { putc ('#', FILE); output_addr_const (FILE, X); }}
+#endif
+
+#undef PRINT_OPERAND_ADDRESS
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx reg1, reg2, breg, ireg; \
+ register rtx addr = ADDR; \
+ rtx offset; \
+ switch (GET_CODE (addr)) \
+ { \
+ case REG: \
+ fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
+ break; \
+ case PRE_DEC: \
+ fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case POST_INC: \
+ fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case PLUS: \
+ reg1 = 0; reg2 = 0; \
+ ireg = 0; breg = 0; \
+ offset = 0; \
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
+ { \
+ offset = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
+ { \
+ offset = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) != PLUS) ; \
+ else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
+ || GET_CODE (addr) == SIGN_EXTEND) \
+ { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
+ if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
+ if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
+ || GET_CODE (reg1) == MULT)) \
+ || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
+ { breg = reg2; ireg = reg1; } \
+ else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
+ { breg = reg1; ireg = reg2; } \
+ if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { int scale = 1; \
+ if (GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "(L%d.b,pc,%s.w", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (XEXP (ireg, 0))]); \
+ else \
+ fprintf (FILE, "(L%d.b,pc,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; } \
+ if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "(L%d.b,pc,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (breg)]); \
+ putc (')', FILE); \
+ break; } \
+ if (ireg != 0 || breg != 0) \
+ { int scale = 1; \
+ if (breg == 0) \
+ abort (); \
+ if (addr && GET_CODE (addr) == LABEL_REF) abort (); \
+ fprintf (FILE, "("); \
+ if (addr != 0) { \
+ output_addr_const (FILE, addr); \
+ putc (',', FILE); } \
+ fprintf (FILE, "%s", reg_names[REGNO (breg)]); \
+ if (ireg != 0) \
+ putc (',', FILE); \
+ if (ireg != 0 && GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
+ else if (ireg != 0) \
+ fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; \
+ } \
+ else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "(L%d.b,pc,%s.l)", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (reg1)]); \
+ break; } \
+ default: \
+ if (GET_CODE (addr) == CONST_INT \
+ && INTVAL (addr) < 0x8000 \
+ && INTVAL (addr) >= -0x8000) \
+ fprintf (FILE, "%d.w", INTVAL (addr)); \
+ else \
+ output_addr_const (FILE, addr); \
+ }}
+
+#else /* Using GAS, which uses the MIT assembler syntax, like a Sun. */
+
+#define FUNCTION_PROFILER(FILE, LABEL_NO) \
+ fprintf (FILE, "\tmovl #LP%d,d0\n\tjsr mcount\n", (LABEL_NO));
+
+#endif /* MOTOROLA */
diff --git a/gcc/config/m68k/news3.h b/gcc/config/m68k/news3.h
new file mode 100755
index 0000000..b4a3f41
--- /dev/null
+++ b/gcc/config/m68k/news3.h
@@ -0,0 +1,6 @@
+#include "m68k/news.h"
+
+/* This is to be compatible with types.h.
+ It was found to be necessary with Newsos 3. */
+
+#define SIZE_TYPE "long int"
diff --git a/gcc/config/m68k/news3gas.h b/gcc/config/m68k/news3gas.h
new file mode 100755
index 0000000..7c2d2b0
--- /dev/null
+++ b/gcc/config/m68k/news3gas.h
@@ -0,0 +1,6 @@
+#include "m68k/newsgas.h"
+
+/* This is to be compatible with types.h.
+ It was found to be necessary with Newsos 3. */
+
+#define SIZE_TYPE "long int"
diff --git a/gcc/config/m68k/newsgas.h b/gcc/config/m68k/newsgas.h
new file mode 100755
index 0000000..8dc7801
--- /dev/null
+++ b/gcc/config/m68k/newsgas.h
@@ -0,0 +1,19 @@
+/* In Sony versions before 3.0, use the GNU Assembler, because the
+ system's assembler has no way to assemble the difference of two
+ labels for the displacement in a switch-dispatch instruction. */
+
+#define USE_GAS
+
+/* This is the assembler directive to equate two values. */
+
+#undef SET_ASM_OP
+#define SET_ASM_OP ".set"
+
+/* This is how we tell the assembler that a symbol is weak. */
+
+#undef ASM_WEAKEN_LABEL
+#define ASM_WEAKEN_LABEL(FILE,NAME) \
+ do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
+ fputc ('\n', FILE); } while (0)
+
+#include "m68k/news.h"
diff --git a/gcc/config/m68k/next.h b/gcc/config/m68k/next.h
new file mode 100755
index 0000000..8391ab5
--- /dev/null
+++ b/gcc/config/m68k/next.h
@@ -0,0 +1,199 @@
+/* Target definitions for GNU compiler for mc680x0 running NeXTSTEP
+ Copyright (C) 1989, 90-94, 96, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "m68k/m68k.h"
+#include "nextstep.h"
+
+/* See m68k.h. 0407 means 68040 (or 68030 or 68020, with 68881/2). */
+
+#define TARGET_DEFAULT (MASK_68040|MASK_BITFIELD|MASK_68881|MASK_68020)
+
+/* Boundary (in *bits*) on which stack pointer should be aligned. */
+
+#undef STACK_BOUNDARY
+#define STACK_BOUNDARY 32
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dmc68000 -Dm68k -DNeXT -Dunix -D__MACH__ -D__BIG_ENDIAN__ -D__ARCHITECTURE__=\"m68k\" -Asystem(unix) -Asystem(mach) -Acpu(m68k) -Amachine(m68k) -D_NEXT_SOURCE"
+
+/* Every structure or union's size must be a multiple of 2 bytes.
+ (Why isn't this in m68k.h?) */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+/* This is how to output an assembler line defining a `double' constant. */
+
+#undef ASM_OUTPUT_DOUBLE
+#ifdef REAL_VALUE_TO_TARGET_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ do { \
+ long hex[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE (VALUE, hex); \
+ fprintf (FILE, "\t.long 0x%x\n\t.long 0x%x\n", hex[0], hex[1]); \
+ } while (0)
+#else
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ do { if (REAL_VALUE_ISINF (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "\t.double 0r-99e999\n"); \
+ else \
+ fprintf (FILE, "\t.double 0r99e999\n"); \
+ } \
+ else \
+ { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \
+ fprintf (FILE, "\t.double 0r%s\n", dstr); \
+ } \
+ } while (0)
+#endif
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#undef ASM_OUTPUT_FLOAT
+#ifdef REAL_VALUE_TO_TARGET_SINGLE
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ do { \
+ long hex; \
+ REAL_VALUE_TO_TARGET_SINGLE (VALUE, hex); \
+ fprintf (FILE, "\t.long 0x%x\n", hex); \
+ } while (0)
+#else
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ do { if (REAL_VALUE_ISINF (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "\t.single 0r-99e999\n"); \
+ else \
+ fprintf (FILE, "\t.single 0r99e999\n"); \
+ } \
+ else \
+ { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \
+ fprintf (FILE, "\t.single 0r%s\n", dstr); \
+ } \
+ } while (0)
+#endif
+
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#ifdef REAL_VALUE_TO_TARGET_SINGLE
+#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
+ do { \
+ long hex; \
+ REAL_VALUE_TO_TARGET_SINGLE (VALUE, hex); \
+ fprintf (FILE, "#0%c%x", (CODE) == 'f' ? 'b' : 'x', hex); \
+ } while (0)
+#else
+#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
+ do{ \
+ if (CODE != 'f') \
+ { \
+ 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); \
+ } \
+ else if (REAL_VALUE_ISINF (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "#0r-99e999"); \
+ else \
+ fprintf (FILE, "#0r99e999"); \
+ } \
+ else \
+ { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.9g", dstr); \
+ fprintf (FILE, "#0r%s", dstr); \
+ } \
+ } while (0)
+#endif
+
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#ifdef REAL_VALUE_TO_TARGET_DOUBLE
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ do { \
+ long hex[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE (VALUE, hex); \
+ fprintf (FILE, "#0b%x%08x", hex[0], hex[1]); \
+ } while (0)
+#else
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ do { if (REAL_VALUE_ISINF (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "#0r-99e999"); \
+ else \
+ fprintf (FILE, "#0r99e999"); \
+ } \
+ else \
+ { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.20g", dstr); \
+ fprintf (FILE, "#0r%s", dstr); \
+ } \
+ } while (0)
+#endif
+
+/* We do not define JUMP_TABLES_IN_TEXT_SECTION, since we wish to keep
+ the text section pure. There is no point in addressing the jump
+ tables using pc relative addressing, since they are not in the text
+ section, so we undefine CASE_VECTOR_PC_RELATIVE. This also
+ causes the compiler to use absolute addresses in the jump table,
+ so we redefine CASE_VECTOR_MODE to be SImode. */
+
+#undef CASE_VECTOR_MODE
+#define CASE_VECTOR_MODE SImode
+#undef CASE_VECTOR_PC_RELATIVE
+
+/* Make sure jump tables have the same alignment as other pointers. */
+
+#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLEINSN) \
+{ ASM_OUTPUT_ALIGN (FILE, 1); ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); }
+
+/* Don't treat addresses involving labels differently from symbol names.
+ Previously, references to labels generated pc-relative addressing modes
+ while references to symbol names generated absolute addressing modes. */
+
+#undef GO_IF_INDEXABLE_BASE
+#define GO_IF_INDEXABLE_BASE(X, ADDR) \
+{ if (LEGITIMATE_BASE_REG_P (X)) goto ADDR; }
+
+/* This accounts for the return pc and saved fp on the m68k. */
+
+#define OBJC_FORWARDING_STACK_OFFSET 8
+#define OBJC_FORWARDING_MIN_OFFSET 8
+
+/* FINALIZE_TRAMPOLINE enables executable stack. The
+ __enable_execute_stack also clears the insn cache. */
+
+#undef FINALIZE_TRAMPOLINE
+#define FINALIZE_TRAMPOLINE(TRAMP) \
+ emit_library_call(gen_rtx(SYMBOL_REF, Pmode, "__enable_execute_stack"), \
+ 0, VOIDmode, 1, memory_address(SImode, (TRAMP)), Pmode)
+
+/* A C expression used to clear the instruction cache from
+ address BEG to address END. On NeXTSTEP this i a system trap. */
+
+#define CLEAR_INSN_CACHE(BEG, END) \
+ asm volatile ("trap #2")
+
+/* GCC is the primary compiler for NeXTSTEP, so we don't need this. */
+#undef PCC_STATIC_STRUCT_RETURN
diff --git a/gcc/config/m68k/next21.h b/gcc/config/m68k/next21.h
new file mode 100755
index 0000000..5d18c4e
--- /dev/null
+++ b/gcc/config/m68k/next21.h
@@ -0,0 +1,104 @@
+/* Target definitions for GNU compiler for mc680x0 running NeXTSTEP 2.1
+ Copyright (C) 1989, 90, 91, 92, 93, 1994 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Changed for NeXTStep2.1, Ch. Kranz, 2/94, 3/94 */
+
+#include "m68k/next.h"
+#include "nextstep21.h"
+
+/* for #include <mach.h> in libgcc2.c */
+#define NeXTStep21
+
+#undef ASM_OUTPUT_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ do { if (REAL_VALUE_ISINF (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "#0r-99e999"); \
+ else \
+ fprintf (FILE, "#0r99e999"); \
+ } \
+ else \
+ { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \
+ fprintf (FILE, "\t.double 0r%s\n", dstr); \
+ } \
+ } while (0)
+
+/* This is how to output an assembler line defining a `float' constant. */
+#undef ASM_OUTPUT_FLOAT
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ do { if (REAL_VALUE_ISINF (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "\t.single 0r-99e999\n"); \
+ else \
+ fprintf (FILE, "\t.single 0r99e999\n"); \
+ } \
+ else \
+ { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \
+ fprintf (FILE, "\t.single 0r%s\n", dstr); \
+ } \
+ } while (0)
+
+/* called from m68k.c line 1881 */
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
+ do{ \
+ if (CODE != 'f') \
+ { \
+ 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); \
+ } \
+ else if (REAL_VALUE_ISINF (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "#0r-99e999"); \
+ else \
+ fprintf (FILE, "#0r99e999"); \
+ } \
+ else \
+ { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.9g", dstr); \
+ fprintf (FILE, "#0r%s", dstr); \
+ } \
+ } while (0)
+
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ do { if (REAL_VALUE_ISINF (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "#0r-99e999"); \
+ else \
+ fprintf (FILE, "#0r99e999"); \
+ } \
+ else \
+ { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.20g", dstr); \
+ fprintf (FILE, "#0r%s", dstr); \
+ } \
+ } while (0)
+
diff --git a/gcc/config/m68k/os68000.h b/gcc/config/m68k/os68000.h
new file mode 100755
index 0000000..8f88769
--- /dev/null
+++ b/gcc/config/m68k/os68000.h
@@ -0,0 +1,81 @@
+/* CYGNUS LOCAL ericsson */
+/* Definitions of target machine for GNU compiler. Vxworks 68010 version.
+ Copyright 1987, 1988, 1992 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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. */
+
+
+#include "m68k/m68k.h"
+#include "aoutos.h"
+
+/* See m68k.h. 0 means 68000 with no 68881. */
+
+#define TARGET_DEFAULT 0
+
+/* Define __HAVE_68881 in preprocessor only if -m68881 is specified.
+ This will control the use of inline 68881 insns in certain macros.
+ Also inform the program which CPU this is for. */
+
+#define CPP_SPEC "%{m68881:-D__HAVE_68881__} \
+%{!ansi:%{m68020:-Dmc68020}%{mc68020:-Dmc68020}%{!mc68020:%{!m68020:-Dmc68010}}}"
+
+/* -m68020 requires special flags to the assembler. */
+
+#define ASM_SPEC \
+ "%{m68020:-mc68020}%{mc68020:-mc68020}%{!mc68020:%{!m68020:-mc68000}}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dmc68000"
+
+/* Prevent error on `-sun2' and `-target sun2' options. */
+
+#define CC1_SPEC "%{sun2:} %{target:}"
+
+#define PTRDIFF_TYPE "int"
+#define SIZE_TYPE "unsigned int"
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "short unsigned int"
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 16
+
+/* Specify what to link with. */
+
+/* VxWorks does all the library stuff itself. */
+
+#define LIB_SPEC ""
+
+/* Provide required defaults for linker -e. */
+
+#define LINK_SPEC "%{!nostdlib:%{!r*:%{!e*:-e start}}}"
+
+/* VxWorks provides the functionality of crt0.o and friends itself. */
+
+#define STARTFILE_SPEC ""
+
+/* Alignment of field after `int : 0' in a structure. */
+
+#undef EMPTY_FIELD_BOUNDARY
+#define EMPTY_FIELD_BOUNDARY 16
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
diff --git a/gcc/config/m68k/ose68k.h b/gcc/config/m68k/ose68k.h
new file mode 100755
index 0000000..ebe8846
--- /dev/null
+++ b/gcc/config/m68k/ose68k.h
@@ -0,0 +1,45 @@
+/* CYGNUS LOCAL ericsson */
+/* Definitions of target machine for GNU compiler. OSE ^68000/68020 version.
+ Copyright 1987, 1988, 1992, 1996 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* See m68k.h for the macro values */
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
+
+#include "m68k/m68k-none.h"
+#include "aoutos.h"
+
+#define DBX_DEBUGGING_INFO
+#undef SDB_DEBUGGING_INFO
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "short unsigned int"
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 16
+
+/* Provide required defaults for linker -e. */
+#define LINK_SPEC "%{!nostdlib:%{!r*:%{!e*:-e start}}}"
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* User must provide startfile if desired. */
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC ""
diff --git a/gcc/config/m68k/pbb.h b/gcc/config/m68k/pbb.h
new file mode 100755
index 0000000..41319c2
--- /dev/null
+++ b/gcc/config/m68k/pbb.h
@@ -0,0 +1,163 @@
+/* Definitions of target machine for GNU compiler.
+ Citicorp/TTI Unicom PBB version (using GAS with a %-register prefix)
+ Copyright (C) 1987, 1988, 1990, 1996, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Note: This config uses a version of gas with a postprocessing stage that
+ converts the output of gas to coff containing stab debug symbols.
+ (See vasta@apollo.com or mb@soldev.tti.com) */
+
+#include "m68k/m68k.h"
+
+/* See m68k.h. 5 means 68020 without 68881. */
+
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68020)
+
+/* Don't try using XFmode. */
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dm68k -Dunix -DUnicomPBB -Dmc68k -Dmc68020 -Dmc68k32 -Asystem(unix) -Acpu(m68k) -Amachine(m68k)"
+
+/* We want DBX format for use with gdb under COFF. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Generate calls to memcpy, memcmp and memset. */
+
+#define TARGET_MEM_FUNCTIONS
+
+/* -m68000 requires special flags to the assembler. */
+
+#define ASM_SPEC \
+ " %{m68000:-mc68010}%{mc68000:-mc68010}"
+
+/* we use /lib/libp/lib* when profiling */
+
+#define LIB_SPEC "%{p:-L/usr/lib/libp} %{pg:-L/usr/lib/libp} -lc"
+
+
+/* Use crt1.o as a startup file and crtn.o as a closing file. */
+/*
+ * The loader directive file gcc.ifile defines how to merge the constructor
+ * sections into the data section. Also, since gas only puts out those
+ * sections in response to N_SETT stabs, and does not (yet) have a
+ * ".sections" directive, gcc.ifile also defines the list symbols
+ * __DTOR_LIST__ and __CTOR_LIST__.
+ *
+ * Finally, we must explicitly specify the file from libgcc.a that defines
+ * exit(), otherwise if the user specifies (for example) "-lc_s" on the
+ * command line, the wrong exit() will be used and global destructors will
+ * not get called .
+ */
+
+#define STARTFILE_SPEC \
+"%{!r: gcc.ifile%s} %{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}} \
+%{!r:_exit.o%s}"
+
+#define ENDFILE_SPEC "crtn.o%s"
+
+/* cpp has to support a #sccs directive for the /usr/include files */
+
+#define SCCS_DIRECTIVE
+
+/* GAS register prefix assembly syntax: */
+
+/* User labels have no prefix */
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+
+/* local labels are prefixed with ".L" */
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
+/* registers are prefixed with "%" */
+#undef REGISTER_PREFIX
+#define REGISTER_PREFIX "%"
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES \
+{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%sp", \
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7"}
+
+#undef FUNCTION_EXTRA_EPILOGUE
+#define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE) \
+ { extern int current_function_returns_pointer; \
+ if ((current_function_returns_pointer) && \
+ ! find_equiv_reg (0, get_last_insn (), 0, 0, 0, 8, Pmode)) \
+ asm_fprintf (FILE, "\tmovl %Rd0,%Ra0\n"); }
+
+#define ASM_RETURN_CASE_JUMP \
+ do { \
+ if (TARGET_5200) \
+ return "ext%.l %0\n\tjmp %%pc@(2,%0:l)"; \
+ else \
+ return "jmp %%pc@(2,%0:w)"; \
+ } while (0)
+
+/* Although the gas we use can create .ctor and .dtor sections from N_SETT
+ stabs, it does not support section directives, so we need to have the loader
+ define the lists.
+ */
+#define CTOR_LISTS_DEFINED_EXTERNALLY
+
+/* similar to default, but allows for the table defined by ld with gcc.ifile.
+ nptrs is always 0. So we need to instead check that __DTOR_LIST__[1] != 0.
+ The old check is left in so that the same macro can be used if and when
+ a future version of gas does support section directives. */
+
+#define DO_GLOBAL_DTORS_BODY {int nptrs = *(int *)__DTOR_LIST__; int i; \
+ if (nptrs == -1 || (__DTOR_LIST__[0] == 0 && __DTOR_LIST__[1] != 0)) \
+ for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++); \
+ for (i = nptrs; i >= 1; i--) \
+ __DTOR_LIST__[i] (); }
+
+/*
+ * Here is an example gcc.ifile. I've tested it on PBB 68k and on sco 386
+ * systems. The NEXT(0x200000) works on just about all 386 and m68k systems,
+ * but can be reduced to any power of 2 that is >= NBPS (0x10000 on a pbb).
+
+ SECTIONS {
+ .text BIND(0x200200) BLOCK (0x200) :
+ { *(.init) *(.text) vfork = fork; *(.fini) }
+
+ GROUP BIND( NEXT(0x200000) + ADDR(.text) + SIZEOF(.text)):
+ { .data : { __CTOR_LIST__ = . ; . += 4; *(.ctor) . += 4 ;
+ __DTOR_LIST__ = . ; . += 4; *(.dtor) . += 4 ; }
+ .bss : { }
+ }
+ }
+ */
+
+/*
+Local variables:
+version-control: t
+End:
+*/
diff --git a/gcc/config/m68k/plexus.h b/gcc/config/m68k/plexus.h
new file mode 100755
index 0000000..3ca99fd
--- /dev/null
+++ b/gcc/config/m68k/plexus.h
@@ -0,0 +1,108 @@
+/* Definitions of target machine for GNU compiler, for 680X0 based Plexus
+ Computers running SYSVR2
+ Copyright (C) 1990, 1994, 1996 Free Software Foundation, Inc.
+ Contributed by Randy Welch (rwelch@netcom.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+/* The Plexus port of gcc requires you to use gas ( either 1.3X with COFF
+ patches or 2.X ), If you use gas 2.X you have to use binutils-2.X.
+
+ With using gas-2.X the Plexus gcc port is now capable of generating
+ output suitable for use by gdb-4.X ( send mail to above address for
+ info on getting gdb patches or other GNU items for the Plexus )
+
+ This is configured for label output default by gas as LXXX instead of
+ plexus cc/as combination requires .LXXX */
+
+#include "m68k/m68k.h"
+
+/* Define __HAVE_68881 in preprocessor only if -m68881 is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68020)
+
+/* Don't try using XFmode. */
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+#define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
+#define CPP_PREDEFINES "-Dm68 -Dunix -Dplexus -Asystem(unix) -Acpu(m68k) -Amachine(m68k)"
+
+#if TARGET_DEFAULT & MASK_68020
+#define ASM_SPEC\
+"%{m68000:-mc68000}%{mc68000:-mc68000}%{!mc68000:%{!m68000:-mc68020}}"
+#undef STRICT_ALIGNMENT
+#define STRICT_ALIGNMENT 0
+#else
+#define ASM_SPEC\
+"%{m68020:-mc68020}%{mc68020:-mc68020}%{!mc68020:%{!mc68020:-mc68000}}"
+#endif
+
+/***************************************************************************/
+/* Un comment the following if you want adb to be able to follow a core */
+/* file if you compile a program with -O */
+/***************************************************************************/
+/* #define FRAME_POINTER_REQUIRED */
+
+/* Let's be compatible with the Plexus C compiler by default. Why not? */
+#define PLEXUS_CC_COMPAT
+
+#ifdef PLEXUS_CC_COMPAT
+#define STRUCTURE_SIZE_BOUNDARY 16 /* for compatibility with cc */
+#undef STACK_BOUNDARY
+#define STACK_BOUNDARY 32 /* ditto */
+#endif
+
+#undef NEED_PROBE
+#define NEED_PROBE -132 /* plexus needs a stack probe */
+
+/***********************************************************************/
+/* if you have binutils-2.X and gas-2.X running you can generate code */
+/* that gdb can understand ( gdb support available for 4.11 ) */
+/* */
+/* If you use gas-1.3X don't define this as the version of the coff */
+/* patches for gas-1.3x ( stabs in coff ) does not generate coff debug */
+/* syms */
+/***********************************************************************/
+#define HAVE_GAS_2_X
+
+#ifdef HAVE_GAS_2_X
+#undef DBX_DEBUGGING_INFO
+#define SDB_DEBUGGING_INFO
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+ output_file_directive((FILE), main_input_filename)
+
+#else
+#undef DBX_DEBUGGING_INFO /* no real debugger */
+#undef SDB_DEBUGGING_INFO
+#endif
+#define TARGET_MEM_FUNCTIONS
+
+/***********************************************************************/
+/* items for collect2 */
+/***********************************************************************/
+
+#define NM_FLAGS ""
+#define NO_SYS_SIGLIST
+#define NO_DUP2
+
+#define SIZE_TYPE "int"
diff --git a/gcc/config/m68k/rtems.h b/gcc/config/m68k/rtems.h
new file mode 100755
index 0000000..20e623e
--- /dev/null
+++ b/gcc/config/m68k/rtems.h
@@ -0,0 +1,33 @@
+/* Definitions for rtems targeting a Motorola m68k using coff.
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Contributed by Joel Sherrill (joel@OARcorp.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "m68k/m68k-coff.h"
+
+/* Specify predefined symbols in preprocessor. */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dmc68000 -Drtems -D__rtems__ \
+ -Asystem(rtems) -Acpu(mc68000) -Acpu(m68k) -Amachine(m68k)"
+
+/* Generate calls to memcpy, memcmp and memset. */
+#ifndef TARGET_MEM_FUNCTIONS
+#define TARGET_MEM_FUNCTIONS
+#endif
diff --git a/gcc/config/m68k/sgs.h b/gcc/config/m68k/sgs.h
new file mode 100755
index 0000000..62d2336
--- /dev/null
+++ b/gcc/config/m68k/sgs.h
@@ -0,0 +1,446 @@
+/* Definitions of target machine for GNU compiler for m68k targets using
+ assemblers derived from AT&T "SGS" releases.
+ Copyright (C) 1991, 1993, 1996 Free Software Foundation, Inc.
+ Written by Fred Fish (fnf@cygnus.com)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Control assembler-syntax conditionals in m68k.md and conditionals in
+ m68k.h. Note that some systems may also require SGS_SWAP_W and/or
+ SGS_SWITCH_TABLES to be defined as well. */
+
+#define MOTOROLA /* Use Motorola syntax rather than "MIT" */
+#define SGS /* Uses SGS assembler */
+#define SGS_CMP_ORDER /* Takes cmp operands in reverse order */
+
+#include "m68k/m68k.h"
+
+/* SGS specific assembler pseudo ops. */
+
+#define BYTE_ASM_OP ".byte"
+#define WORD_ASM_OP ".short"
+#define LONG_ASM_OP ".long"
+#define SPACE_ASM_OP ".space"
+#define ALIGN_ASM_OP ".align"
+#undef GLOBAL_ASM_OP
+#define GLOBAL_ASM_OP ".global"
+#define SWBEG_ASM_OP ".swbeg"
+#define SET_ASM_OP ".set"
+
+#define UNALIGNED_SHORT_ASM_OP ".short" /* Used in dwarfout.c */
+#define UNALIGNED_INT_ASM_OP ".long" /* Used in dwarfout.c */
+
+#define ASM_PN_FORMAT "%s_%d" /* Format for private names */
+
+/* Here are four prefixes that are used by asm_fprintf to
+ facilitate customization for alternate assembler syntaxes.
+ Machines with no likelihood of an alternate syntax need not
+ define these and need not use asm_fprintf. */
+
+/* The prefix for register names. Note that REGISTER_NAMES
+ is supposed to include this prefix. Also note that this is NOT an
+ fprintf format string, it is a literal string */
+
+#undef REGISTER_PREFIX
+#define REGISTER_PREFIX "%"
+
+/* The prefix for local (compiler generated) labels.
+ These labels will not appear in the symbol table. */
+
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
+/* The prefix to add to user-visible assembler symbols. */
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+
+/* The prefix for immediate operands. */
+
+#undef IMMEDIATE_PREFIX
+#define IMMEDIATE_PREFIX "&"
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number.
+ Motorola format uses different register names than defined in m68k.h.
+ We also take this chance to convert 'a6' to 'fp' */
+
+#undef REGISTER_NAMES
+
+#ifndef SUPPORT_SUN_FPA
+
+#define REGISTER_NAMES \
+{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp", \
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7" }
+
+#else /* SUPPORTED_SUN_FPA */
+
+#define REGISTER_NAMES \
+{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp", \
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7", \
+ "%fpa0", "%fpa1", "%fpa2", "%fpa3", "%fpa4", "%fpa5", "%fpa6","%fpa7", \
+ "%fpa8", "%fpa9", "%fpa10","%fpa11","%fpa12","%fpa13","%fpa14","%fpa15", \
+ "%fpa16","%fpa17","%fpa18","%fpa19","%fpa20","%fpa21","%fpa22","%fpa23", \
+ "%fpa24","%fpa25","%fpa26","%fpa27","%fpa28","%fpa29","%fpa30","%fpa31" }
+
+#endif /* defined SUPPORT_SUN_FPA */
+
+/* When using an SGS assembler, modify the name of the artificial label which
+ identifies this file as having been compiled with gcc, and the macro that
+ emits such a label in the assembly output, to use '%' rather than '.' */
+
+#define ASM_IDENTIFY_GCC(FILE) \
+ { fprintf ((FILE), "%s:\n", "gcc2_compiled%"); }
+
+/* This is how to output an assembler line defining an `int' constant. */
+/* The SGS assembler doesn't understand ".word". */
+
+#undef ASM_OUTPUT_SHORT
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf ((FILE), "\t%s ", WORD_ASM_OP), \
+ output_addr_const ((FILE), (VALUE)), \
+ fprintf ((FILE), "\n"))
+
+#undef ASM_OUTPUT_LONG_DOUBLE
+#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
+do { long l[3]; \
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
+ fprintf ((FILE), "\t%s 0x%x,0x%x,0x%x\n", LONG_ASM_OP, \
+ l[0], l[1], l[2]); \
+ } while (0)
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#undef ASM_OUTPUT_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+do { long l[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
+ fprintf ((FILE), "\t%s 0x%x,0x%x\n", LONG_ASM_OP, \
+ l[0], l[1]); \
+ } while (0)
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#undef ASM_OUTPUT_FLOAT
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+do { long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
+ fprintf ((FILE), "\t%s 0x%x\n", LONG_ASM_OP, l); \
+ } while (0)
+
+/* This is how to output an assembler line that says to advance the
+ location counter to a multiple of 2**LOG bytes. */
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) > 0) \
+ fprintf ((FILE), "\t%s \t%u\n", ALIGN_ASM_OP, 1 << (LOG)); \
+ else if ((LOG) > 31) \
+ abort ();
+
+/* The routine used to output null terminated string literals. We cannot
+ use the ".string" pseudo op, because it silently truncates strings to
+ 1023 bytes. There is no "partial string op" which works like ".string"
+ but doesn't append a null byte, so we can't chop the input string up
+ into small pieces and use that. Our only remaining alternative is to
+ output the string one byte at a time. */
+
+#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
+do { \
+ register int sp = 0, lp = 0, ch; \
+ fprintf ((FILE), "\t%s ", BYTE_ASM_OP); \
+ do { \
+ ch = (PTR)[sp]; \
+ if (ch > ' ' && ! (ch & 0x80) && ch != '\\') \
+ { \
+ fprintf ((FILE), "'%c", ch); \
+ } \
+ else \
+ { \
+ fprintf ((FILE), "0x%x", ch); \
+ } \
+ if (++sp < (LEN)) \
+ { \
+ if ((sp % 10) == 0) \
+ { \
+ fprintf ((FILE), "\n\t%s ", BYTE_ASM_OP); \
+ } \
+ else \
+ { \
+ putc (',', (FILE)); \
+ } \
+ } \
+ } while (sp < (LEN)); \
+ putc ('\n', (FILE)); \
+} while (0)
+
+
+/* SGS based assemblers don't understand #NO_APP and #APP, so just don't
+ bother emitting them. */
+
+#undef ASM_APP_ON
+#define ASM_APP_ON ""
+
+#undef ASM_APP_OFF
+#define ASM_APP_OFF ""
+
+/* When using SGS derived assemblers, change the "MIT" or "MOTOROLA"
+ to "SGS/AT&T" */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (68k, SGS/AT&T syntax)");
+
+/* Use proper assembler syntax for these macros. */
+#undef ASM_OUTPUT_REG_PUSH
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ asm_fprintf (FILE, "\t%Omove.l %s,-(%Rsp)\n", reg_names[REGNO])
+
+#undef ASM_OUTPUT_REG_POP
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ asm_fprintf (FILE, "\t%Omove.l (%Rsp)+,%s\n", reg_names[REGNO])
+
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
+ do { long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
+ asm_fprintf ((FILE), "%I0x%x", l); \
+ } while (0)
+
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ do { long l[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
+ asm_fprintf ((FILE), "%I0x%x%08x", l[0], l[1]); \
+ } while (0)
+
+/* How to output a block of SIZE zero bytes. Note that the `space' pseudo,
+ when used in the text segment, causes SGS assemblers to output nop insns
+ rather than 0s, so we set ASM_NO_SKIP_IN_TEXT to prevent this. */
+
+#define ASM_NO_SKIP_IN_TEXT 1
+
+#undef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t%s %u\n", SPACE_ASM_OP, (SIZE))
+
+/* Translate Motorola opcodes such as `jbeq' into SGS opcodes such
+ as `beq.w'.
+ Delete the `e' in `move...' and `fmove'.
+ Change `ftst' to `ftest'.
+ Change `fbne' to `fbneq'
+ Change `fsne' to `fsneq'
+ Change `divsl' to `tdivs' (32/32 -> 32r:32q)
+ Change `divul' to `tdivu' (32/32 -> 32r:32q)
+ Optionally change swap to swap.w.
+ */
+
+#ifdef SGS_SWAP_W
+#define ASM_OUTPUT_OPCODE(FILE, PTR) \
+{ \
+ extern int flag_pic; \
+ if (!strncmp ((PTR), "jbsr", 4)) \
+ { if (flag_pic) \
+ fprintf ((FILE), "bsr"); \
+ else \
+ fprintf ((FILE), "jsr"); \
+ (PTR) += 4; } \
+ else if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
+ { ++(PTR); \
+ while (*(PTR) != ' ') \
+ { putc (*(PTR), (FILE)); ++(PTR); } \
+ fprintf ((FILE), ".w"); } \
+ else if ((PTR)[0] == 's') \
+ { \
+ if (!strncmp ((PTR), "swap", 4)) \
+ { fprintf ((FILE), "swap.w"); (PTR) += 4; } \
+ } \
+/* FMOVE ==> FMOV, (and F%& F%$ translations) */ \
+ else if ((PTR)[0] == 'f') \
+ { \
+ if (!strncmp ((PTR), "fmove", 5)) \
+ { fprintf ((FILE), "fmov"); (PTR) += 5; } \
+ else if (!strncmp ((PTR), "ftst", 4)) \
+ { fprintf ((FILE), "ftest"); (PTR) += 4; } \
+ else if (!strncmp ((PTR), "fbne", 4)) \
+ { fprintf ((FILE), "fbneq"); (PTR) += 4; } \
+ else if (!strncmp ((PTR), "fsne", 4)) \
+ { fprintf ((FILE), "fsneq"); (PTR) += 4; } \
+ else if (!strncmp ((PTR), "f%$move", 7)) \
+ { (PTR) += 7; \
+ if (TARGET_68040_ONLY) \
+ fprintf ((FILE), "fsmov"); \
+ else fprintf ((FILE), "fmov"); } \
+ else if (!strncmp ((PTR), "f%&move", 7)) \
+ { (PTR) += 7; \
+ if (TARGET_68040_ONLY) \
+ fprintf ((FILE), "fdmov"); \
+ else fprintf ((FILE), "fmov"); } \
+ } \
+/* MOVE, MOVEA, MOVEQ, MOVEC ==> MOV */ \
+ else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
+ { fprintf ((FILE), "mov"); (PTR) += 4; \
+ if ((PTR)[0] == 'q' || (PTR)[0] == 'a' \
+ || (PTR)[0] == 'c') (PTR)++; } \
+/* SUB, SUBQ, SUBA, SUBI ==> SUB */ \
+ else if ((PTR)[0] == 's' && (PTR)[1] == 'u' \
+ && (PTR)[2] == 'b') \
+ { fprintf ((FILE), "sub"); (PTR) += 3; \
+ if ((PTR)[0] == 'q' || (PTR)[0] == 'i' \
+ || (PTR)[0] == 'a') (PTR)++; } \
+/* CMP, CMPA, CMPI, CMPM ==> CMP */ \
+ else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \
+ && (PTR)[2] == 'p') \
+ { fprintf ((FILE), "cmp"); (PTR) += 3; \
+ if ((PTR)[0] == 'a' || (PTR)[0] == 'i' \
+ || (PTR)[0] == 'm') (PTR)++; } \
+/* DIVSL ==> TDIVS */ \
+ else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 's' \
+ && (PTR)[4] == 'l') \
+ { fprintf ((FILE), "tdivs"); (PTR) += 5; } \
+/* DIVUL ==> TDIVU */ \
+ else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 'u' \
+ && (PTR)[4] == 'l') \
+ { fprintf ((FILE), "tdivu"); (PTR) += 5; } \
+}
+
+#else /* not SGS_SWAP_W */
+
+#define ASM_OUTPUT_OPCODE(FILE, PTR) \
+{ \
+ extern int flag_pic; \
+ if (!strncmp ((PTR), "jbsr", 4)) \
+ { if (flag_pic) \
+ fprintf ((FILE), "bsr"); \
+ else \
+ fprintf ((FILE), "jsr"); \
+ (PTR) += 4; } \
+ else if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
+ { ++(PTR); \
+ while (*(PTR) != ' ') \
+ { putc (*(PTR), (FILE)); ++(PTR); } \
+ fprintf ((FILE), ".w"); } \
+/* FMOVE ==> FMOV, (and F%& F%$ translations) */ \
+ else if ((PTR)[0] == 'f') \
+ { \
+ if (!strncmp ((PTR), "fmove", 5)) \
+ { fprintf ((FILE), "fmov"); (PTR) += 5; } \
+ else if (!strncmp ((PTR), "ftst", 4)) \
+ { fprintf ((FILE), "ftest"); (PTR) += 4; } \
+ else if (!strncmp ((PTR), "fbne", 4)) \
+ { fprintf ((FILE), "fbneq"); (PTR) += 4; } \
+ else if (!strncmp ((PTR), "fsne", 4)) \
+ { fprintf ((FILE), "fsneq"); (PTR) += 4; } \
+ else if (!strncmp ((PTR), "f%$move", 7)) \
+ { (PTR) += 7; \
+ if (TARGET_68040_ONLY) \
+ fprintf ((FILE), "fsmov"); \
+ else fprintf ((FILE), "fmov"); } \
+ else if (!strncmp ((PTR), "f%&move", 7)) \
+ { (PTR) += 7; \
+ if (TARGET_68040_ONLY) \
+ fprintf ((FILE), "fdmov"); \
+ else fprintf ((FILE), "fmov"); } \
+ } \
+/* MOVE, MOVEA, MOVEQ, MOVEC ==> MOV */ \
+ else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
+ { fprintf ((FILE), "mov"); (PTR) += 4; \
+ if ((PTR)[0] == 'q' || (PTR)[0] == 'a' \
+ || (PTR)[0] == 'c') (PTR)++; } \
+/* SUB, SUBQ, SUBA, SUBI ==> SUB */ \
+ else if ((PTR)[0] == 's' && (PTR)[1] == 'u' \
+ && (PTR)[2] == 'b') \
+ { fprintf ((FILE), "sub"); (PTR) += 3; \
+ if ((PTR)[0] == 'q' || (PTR)[0] == 'i' \
+ || (PTR)[0] == 'a') (PTR)++; } \
+/* CMP, CMPA, CMPI, CMPM ==> CMP */ \
+ else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \
+ && (PTR)[2] == 'p') \
+ { fprintf ((FILE), "cmp"); (PTR) += 3; \
+ if ((PTR)[0] == 'a' || (PTR)[0] == 'i' \
+ || (PTR)[0] == 'm') (PTR)++; } \
+/* DIVSL ==> TDIVS */ \
+ else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 's' \
+ && (PTR)[4] == 'l') \
+ { fprintf ((FILE), "tdivs"); (PTR) += 5; } \
+/* DIVUL ==> TDIVU */ \
+ else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 'u' \
+ && (PTR)[4] == 'l') \
+ { fprintf ((FILE), "tdivu"); (PTR) += 5; } \
+}
+
+#endif /* not SGS_SWAP_W */
+
+/* This macro outputs the label at the start of a switch table. The
+ ".swbeg <N>" is an assembler directive that causes the switch table
+ size to be inserted into the object code so that disassemblers, for
+ example, can identify that it is the start of a switch table. */
+
+#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
+ fprintf ((FILE), "\t%s &%d\n", SWBEG_ASM_OP, XVECLEN (PATTERN (TABLE), 1));
+
+#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
+ do { \
+ ASM_OUTPUT_BEFORE_CASE_LABEL((FILE),(PREFIX),(NUM),(TABLE)); \
+ ASM_OUTPUT_INTERNAL_LABEL((FILE),(PREFIX),(NUM)); \
+ } while (0)
+
+/* At end of a switch table, define LDnnn iff the symbol LInnn was defined.
+ Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
+ fails to assemble. Luckily "LDnnn(pc,d0.l*2)" produces the results
+ we want. This difference can be accommodated by making the assembler
+ define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
+ string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
+ macro. */
+
+#undef ASM_OUTPUT_CASE_END
+#define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \
+{ if (switch_table_difference_label_flag) \
+ asm_fprintf (FILE, "\t%s %LLD%d,%LL%d-%LLI%d-2.b\n",\
+ SET_ASM_OP, (NUM), (NUM), (NUM)); \
+ switch_table_difference_label_flag = 0; }
+
+extern int switch_table_difference_label_flag;
+
+/* This is how to output an element of a case-vector that is relative. */
+
+#undef ASM_OUTPUT_ADDR_DIFF_ELT
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
+ asm_fprintf (FILE, "\t%s %LL%d-%LL%d\n", WORD_ASM_OP, VALUE, REL)
+
+/* Currently, JUMP_TABLES_IN_TEXT_SECTION must be defined in order to
+ keep switch tables in the text section. */
+
+#define JUMP_TABLES_IN_TEXT_SECTION 1
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#undef ASM_FORMAT_PRIVATE_NAME
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), ASM_PN_FORMAT, (NAME), (LABELNO)))
+
diff --git a/gcc/config/m68k/st2000.h b/gcc/config/m68k/st2000.h
new file mode 100755
index 0000000..3aea439
--- /dev/null
+++ b/gcc/config/m68k/st2000.h
@@ -0,0 +1,610 @@
+/* Definitions of target machine for GNU compiler.
+ Tandem ST-2000 version
+ Copyright 1992 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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. */
+
+/*
+ Contributed by Steve Chamberlain
+ sac@cygnus.com
+ */
+
+
+
+/* This controls conditionals in m68k.h. */
+#define MOTOROLA /* Use Motorola syntax rather than "MIT" */
+#define SGS_NO_LI /* Suppress jump table label usage */
+
+#include "aoutos.h"
+#undef ASM_OUTPUT_LABELREF
+#include "m68k/m68k.h"
+
+
+#undef TARGET_SWITCHES
+#undef USER_LABEL_PREFIX
+#undef ASM_OUTPUT_LABEL
+#undef ASM_GLOBALIZE_LABEL
+#undef ASM_OUTPUT_INTERNAL_LABEL
+#undef ASM_OUTPUT_DOUBLE
+#undef ASM_OUTPUT_FLOAT
+#undef ASM_OUTPUT_INT
+#undef ASM_OUTPUT_SHORT
+#undef ASM_OUTPUT_CHAR
+#undef ASM_OUTPUT_BYTE
+#undef ASM_OUTPUT_REG_PUSH
+#undef ASM_OUTPUT_REG_POP
+#undef ASM_OUTPUT_ADDR_VEC_ELT
+#undef ASM_OUTPUT_ADDR_DIFF_ELT
+#undef ASM_OUTPUT_ALIGN
+#undef ASM_OUTPUT_SKIP
+#undef ASM_OUTPUT_COMMON
+#undef ASM_OUTPUT_LOCAL
+#undef ASM_FORMAT_PRIVATE_NAME
+#undef TEXT_SECTION_ASM_OP
+#undef DATA_SECTION_ASM_OP
+#undef ASM_FILE_START
+#undef FUNCTION_PROLOGUE
+#undef FUNCTION_EPILOGUE
+#undef ASM_OUTPUT_LABELREF
+#undef REGISTER_NAMES
+#undef PRINT_OPERAND
+#undef PRINT_OPERAND_ADDRESS
+#undef ASM_OUTPUT_ALIGN
+
+/* See m68k.h. 7 means 68020 with 68881. */
+
+#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}, \
+ { "no-prefix", 02000}, \
+ { "", TARGET_DEFAULT}}
+
+#define TARGET_DEFAULT 7
+
+#define USER_LABEL_PREFIX (target_flags & 02000) ? "" : "_"
+
+/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+/* These are the ones defined by Sony, plus mc68000 for uniformity with
+ GCC on other 68000 systems. */
+
+#define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dnews700"
+
+/* These conditionals tested for different submodels,
+ but they were incorrect since they tested the host rather than the target.
+ The choice of model shouldn't actually matter. */
+
+
+/* Link with libg.a when debugging, for dbx's sake. */
+
+#define LIB_SPEC "%{g:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} "
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Override parts of m68k.h to fit Sony's assembler syntax. */
+
+#undef BIGGEST_ALIGNMENT
+#undef CALL_USED_REGISTERS
+#undef FUNCTION_VALUE
+#undef LIBCALL_VALUE
+#undef FUNCTION_PROFILER
+
+
+#undef ASM_OUTPUT_ALIGN
+
+/* There is no point aligning anything to a rounder boundary than this. */
+#define BIGGEST_ALIGNMENT 32
+
+/* A bitfield declared as `int' forces `int' alignment for the struct. */
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* NEWS makes d2, d3, fp2 and fp3 unsaved registers, unlike the Sun system. */
+
+#define CALL_USED_REGISTERS \
+ {1, 1, 1, 1, 0, 0, 0, 0, \
+ 1, 1, 0, 0, 0, 0, 0, 1, \
+ 1, 1, 1, 1, 0, 0, 0, 0}
+
+/* NEWS returns floats and doubles in fp0, not d0/d1. */
+
+#define FUNCTION_VALUE(VALTYPE,FUNC) LIBCALL_VALUE (TYPE_MODE (VALTYPE))
+
+#define LIBCALL_VALUE(MODE) \
+ gen_rtx (REG, (MODE), ((TARGET_68881 && ((MODE) == SFmode || (MODE) == DFmode)) ? 16 : 0))
+
+
+
+
+/* Don't try to define `gcc_compiled.' since the assembler does not
+ accept symbols with periods. This is no real loss since GDB only
+ really needs it for parms passed in registers. */
+#define ASM_IDENTIFY_GCC(FILE)
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ register int regno; \
+ register int mask = 0; \
+ extern char call_used_regs[]; \
+ int fsize = ((SIZE) + 3) & -4; \
+ if (frame_pointer_needed) \
+ { if (fsize < 0x8000) \
+ fprintf (FILE, "\tlink fp,#%d\n", -fsize); \
+ else if (TARGET_68020) \
+ fprintf (FILE, "\tlink.l fp,#%d\n", -fsize); \
+ else \
+ fprintf (FILE, "\tlink fp,#0\n\tsub.l #%d,sp\n", fsize); } \
+ for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ mask |= 1 << (regno - 16); \
+ if (mask != 0) \
+ fprintf (FILE, "\tfmovem.x #0x%x,-(sp)\n", mask & 0xff); \
+ mask = 0; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ mask |= 1 << (15 - regno); \
+ if (frame_pointer_needed) \
+ mask &= ~ (1 << (15-FRAME_POINTER_REGNUM)); \
+ if (exact_log2 (mask) >= 0) \
+ fprintf (FILE, "\tmove.l %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]); \
+ else if (mask) fprintf (FILE, "\tmovem.l #0x%x,-(sp)\n", mask); }
+
+#define FUNCTION_PROFILER(FILE, LABEL_NO) \
+ fprintf (FILE, "\tmove.l #LP%d,d0\n\tjsr mcount\n", (LABEL_NO));
+
+#define FUNCTION_EPILOGUE(FILE, SIZE) \
+{ register int regno; \
+ register int mask, fmask; \
+ register int nregs; \
+ int offset, foffset; \
+ extern char call_used_regs[]; \
+ int fsize = ((SIZE) + 3) & -4; \
+ int big = 0; \
+ nregs = 0; fmask = 0; \
+ for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ { nregs++; fmask |= 1 << (23 - regno); } \
+ foffset = nregs * 12; \
+ nregs = 0; mask = 0; \
+ if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ { nregs++; mask |= 1 << regno; } \
+ offset = foffset + nregs * 4; \
+ if (offset + fsize >= 0x8000 \
+ && frame_pointer_needed \
+ && (mask || fmask)) \
+ { fprintf (FILE, "\tmove.l #%d,a0\n", -fsize); \
+ fsize = 0, big = 1; } \
+ if (exact_log2 (mask) >= 0) { \
+ if (big) \
+ fprintf (FILE, "\tmove.l (-%d,fp,a0.l),%s\n", \
+ offset + fsize, reg_names[exact_log2 (mask)]); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tmove.l (sp)+,%s\n", \
+ reg_names[exact_log2 (mask)]); \
+ else \
+ fprintf (FILE, "\tmove.l (-%d,fp),%s\n", \
+ offset + fsize, reg_names[exact_log2 (mask)]); } \
+ else if (mask) { \
+ if (big) \
+ fprintf (FILE, "\tmovem.l (-%d,fp,a0.l),#0x%x\n", \
+ offset + fsize, mask); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tmovem.l (sp)+,#0x%x\n", mask); \
+ else \
+ fprintf (FILE, "\tmovem.l (-%d,fp),#0x%x\n", \
+ offset + fsize, mask); } \
+ if (fmask) { \
+ if (big) \
+ fprintf (FILE, "\tfmovem.x (-%d,fp,a0.l),#0x%x\n", \
+ foffset + fsize, fmask); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tfmovem.x (sp)+,#0x%x\n", fmask); \
+ else \
+ fprintf (FILE, "\tfmovem.x (-%d,fp),#0x%x\n", \
+ foffset + fsize, fmask); } \
+ if (frame_pointer_needed) \
+ fprintf (FILE, "\tunlk fp\n"); \
+ if (current_function_pops_args) \
+ fprintf (FILE, "\trtd #%d\n", current_function_pops_args); \
+ else fprintf (FILE, "\trts\n"); }
+
+/* Difference from m68k.h is in `fp' instead of `a6'. */
+
+#define REGISTER_NAMES \
+{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
+ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \
+ "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7"}
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tmove.l\t%s,-(sp)\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tmove.l\t(sp)+,%s\n", reg_names[REGNO])
+
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (CODE == '.') fprintf (FILE, "."); \
+ else if (CODE == '#') fprintf (FILE, "#"); \
+ else if (CODE == '-') fprintf (FILE, "-(sp)"); \
+ else if (CODE == '+') fprintf (FILE, "(sp)+"); \
+ else if (CODE == '@') fprintf (FILE, "(sp)"); \
+ else if (CODE == '!') fprintf (FILE, "ccr"); \
+ else if (CODE == '$') {if (TARGET_68040_ONLY) fprintf (FILE, "s");} \
+ else if (CODE == '&') {if (TARGET_68040_ONLY) fprintf (FILE, "d");} \
+ else if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if (GET_CODE (X) == MEM) \
+ output_address (XEXP (X, 0)); \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
+ { union { double d; int i[2]; } u; \
+ union { float f; int i; } u1; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ u1.f = u.d; \
+ if (CODE == 'f') \
+ fprintf (FILE, "#0f%.9e", u1.f); \
+ else \
+ fprintf (FILE, "#0x%x", u1.i); } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \
+ { union { double d; int i[2]; } u; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ fprintf (FILE, "#0d%.20e", u.d); } \
+ else if (CODE == 'b') { putc('#', FILE); output_addr_const (FILE, X);}\
+ else { putc ('#', FILE); output_addr_const (FILE, X); }}
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx reg1, reg2, breg, ireg; \
+ register rtx addr = ADDR; \
+ rtx offset; \
+ switch (GET_CODE (addr)) \
+ { \
+ case REG: \
+ fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
+ break; \
+ case PRE_DEC: \
+ fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case POST_INC: \
+ fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case PLUS: \
+ reg1 = 0; reg2 = 0; \
+ ireg = 0; breg = 0; \
+ offset = 0; \
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
+ { \
+ offset = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
+ { \
+ offset = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) != PLUS) ; \
+ else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
+ || GET_CODE (addr) == SIGN_EXTEND) \
+ { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
+ if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
+ if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
+ || GET_CODE (reg1) == MULT)) \
+ || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
+ { breg = reg2; ireg = reg1; } \
+ else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
+ { breg = reg1; ireg = reg2; } \
+ if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { int scale = 1; \
+ if (GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "(L%d.b,pc,%s.w", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (XEXP (ireg, 0))]); \
+ else \
+ fprintf (FILE, "(L%d.b,pc,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; } \
+ if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "(L%d.b,pc,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (breg)]); \
+ putc (')', FILE); \
+ break; } \
+ if (ireg != 0 || breg != 0) \
+ { int scale = 1; \
+ if (breg == 0) \
+ abort (); \
+ if (addr && GET_CODE (addr) == LABEL_REF) abort (); \
+ fprintf (FILE, "("); \
+ if (addr != 0) { \
+ output_addr_const (FILE, addr); \
+ putc (',', FILE); } \
+ fprintf (FILE, "%s", reg_names[REGNO (breg)]); \
+ if (ireg != 0) \
+ putc (',', FILE); \
+ if (ireg != 0 && GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
+ else if (ireg != 0) \
+ fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; \
+ } \
+ else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "(L%d.b,pc,%s.l)", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (reg1)]); \
+ break; } \
+ default: \
+ if (GET_CODE (addr) == CONST_INT \
+ && INTVAL (addr) < 0x8000 \
+ && INTVAL (addr) >= -0x8000) \
+ fprintf (FILE, "%d.w", INTVAL (addr)); \
+ else \
+ output_addr_const (FILE, addr); \
+ }}
+
+
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME. */
+
+#define ASM_OUTPUT_LABEL(FILE,NAME) \
+ do { assemble_name (FILE, NAME); fputs ("\n", FILE); } while (0)
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ do { fputs ("\tXDEF\t", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
+
+/* This is how to output a reference to a user-level label named NAME.
+ `assemble_name' uses this. */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ asm_fprintf (FILE, "%U%s", NAME)
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ asm_fprintf (FILE, "%s%d\n", PREFIX, NUM)
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf (LABEL, "*%s%s%d", LOCAL_LABEL_PREFIX, PREFIX, NUM)
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ fprintf (FILE, "\tDC.D\t0r%.20g\n", (VALUE))
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ fprintf (FILE, "\tDC.S\t0r%.20g\n", (VALUE))
+
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\tDC.L\t"), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\tDC.W\t"), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\tDC.B\t"), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\tDC.B\t0x%x\n", (VALUE))
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+
+/* This is how to output an element of a case-vector that is absolute.
+ (The 68000 does not use such vectors,
+ but we must define this macro anyway.) */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ asm_fprintf (FILE, "\tDC.L\t%LL%d\n", VALUE)
+
+/* This is how to output an element of a case-vector that is relative. */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
+ asm_fprintf (FILE, "\tDC.W\t%LL%d-%LL%d\n", VALUE, REL)
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ fprintf (FILE, "\tALIGN\t%d\n", 1<<LOG);
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\tDS.B\t%u\n", (SIZE))
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\tXCOM\t", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+/* There doesn't seem to be a way to say this in MRI way */
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( data_section(), assemble_name ((FILE), (NAME)), fputs ("\n\tDS.B ", (FILE)), \
+ fprintf ((FILE), "%u\n", (ROUNDED)))
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s__%d", (NAME), (LABELNO)))
+
+#define TEXT_SECTION_ASM_OP "\tSECT\t.text"
+#define DATA_SECTION_ASM_OP "\tSECT\t.data"
+#define BSS_SECTION_ASM_OP "\tSECT\t.bss"
+
+#define MAX_TEXT_ALIGN 32
+
+#define ASM_FILE_START(FILE) \
+ fprintf (FILE, "* TANDEM ST-2000 M68K GCC\n"); \
+ fprintf (FILE, "* Cygnus Support (415) 322-3811\n"); \
+ fprintf (FILE, "* bugs@cygnus.com\n\n");
+
+
+#define SECTION_ASM_OP "\tSECT\t"
+
+#define EXTRA_SECTIONS in_user
+
+#undef SELECT_SECTION
+
+#define SELECT_SECTION(DECL,RELOC) \
+do { \
+ if (TREE_CODE (DECL) == VAR_DECL || TREE_CODE (DECL) == FUNCTION_DECL)\
+ { \
+ if (GET_CODE (DECL_RTL (DECL)) == MEM \
+ && GET_CODE (XEXP (DECL_RTL (DECL), 0)) == SYMBOL_REF \
+ && SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0))) \
+ { \
+ rtx sym = XEXP (DECL_RTL (DECL), 0); \
+ int len = (char *) index (XEXP (sym, 0), ' ') - XSTR (sym, 0); \
+ char *section_name = (char *)alloca (len+1); \
+ strncpy (section_name, XEXP (sym, 0), len); \
+ section_name[len] = '\0'; \
+ in_section = in_user; \
+ fprintf (asm_out_file, "\tSECT\t%s\n", section_name); \
+ break; \
+ } \
+ } \
+ if (TREE_CODE (DECL) == VAR_DECL) \
+ { \
+ if (TREE_READONLY (DECL) && ! TREE_SIDE_EFFECTS (DECL) \
+ && DECL_ALIGN (DECL) <= MAX_TEXT_ALIGN \
+ && ! (flag_pic && RELOC)) \
+ text_section (); \
+ else \
+ data_section (); \
+ } \
+ else if (TREE_CODE (DECL) == CONSTRUCTOR) \
+ { \
+ if (flag_pic != 0 && RELOC != 0) \
+ data_section (); \
+ else \
+ text_section (); \
+ } \
+ else if (*tree_code_type[(int) TREE_CODE (DECL)] == 'c') \
+ { \
+ if ((TREE_CODE (DECL) == STRING_CST && flag_writable_strings) \
+ || TYPE_ALIGN (TREE_TYPE (DECL)) > MAX_TEXT_ALIGN) \
+ data_section (); \
+ else \
+ text_section (); \
+ } \
+ else text_section() ;\
+} while (0)
diff --git a/gcc/config/m68k/sun2.h b/gcc/config/m68k/sun2.h
new file mode 100755
index 0000000..679e57a
--- /dev/null
+++ b/gcc/config/m68k/sun2.h
@@ -0,0 +1,77 @@
+/* Definitions of target machine for GNU compiler. Sun 68010 version.
+ Copyright (C) 1987, 1988, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+#include "m68k/m68k.h"
+
+/* See m68k.h. 0 means 68000 with no 68881. */
+
+#define TARGET_DEFAULT 0
+
+/* Don't try using XFmode. */
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+/* Define __HAVE_68881 in preprocessor only if -m68881 is specified.
+ This will control the use of inline 68881 insns in certain macros.
+ Also inform the program which CPU this is for. */
+
+#define CPP_SPEC "%{m68881:-D__HAVE_68881__} \
+%{!ansi:%{m68020:-Dmc68020}%{mc68020:-Dmc68020}%{!mc68020:%{!m68020:-Dmc68010}}}"
+
+/* -m68020 requires special flags to the assembler. */
+
+#define ASM_SPEC \
+ "%{m68020:-mc68020}%{mc68020:-mc68020}%{!mc68020:%{!m68020:-mc68010}} \
+ %{fpic:-k} %{fPIC:-k} %{R} %{j} %{J} %{h} %{d2} %{keep-local-as-symbols:-L}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dmc68000 -Dsun -Dunix -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
+
+/* Prevent error on `-sun2' and `-target sun2' options. */
+
+#define CC1_SPEC "%{sun2:} %{target:}"
+
+/* These compiler options take an argument. We ignore -target for now. */
+
+#define WORD_SWITCH_TAKES_ARG(STR) \
+ (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \
+ || !strcmp (STR, "target") || !strcmp (STR, "assert"))
+
+/* Specify what to link with. */
+
+/* Link with libg.a when debugging, for dbx's sake. */
+/* Include the support for -a when appropriate. */
+#define LIB_SPEC "%{g:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} \
+%{a:/usr/lib/bb_link.o -lc} "
+
+/* Alignment of field after `int : 0' in a structure. */
+
+#undef EMPTY_FIELD_BOUNDARY
+#define EMPTY_FIELD_BOUNDARY 16
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
diff --git a/gcc/config/m68k/sun2o4.h b/gcc/config/m68k/sun2o4.h
new file mode 100755
index 0000000..da722cf
--- /dev/null
+++ b/gcc/config/m68k/sun2o4.h
@@ -0,0 +1,189 @@
+/* Definitions of target machine for GNU compiler. Sun 2 running SunOS 4.
+ Copyright (C) 1987, 1988, 1993, 1996, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "m68k/sun2.h"
+
+
+/* Define __HAVE_SKY__ in preprocessor, according to the -m flags.
+ Also inform the program which CPU this is for. */
+
+#undef CPP_SPEC
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "int"
+#undef SIZE_TYPE
+#define SIZE_TYPE "int"
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "short unsigned int"
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 16
+
+#if TARGET_DEFAULT & MASK_SKY
+
+/* -msky is the default */
+#define CPP_SPEC \
+"%{!msoft-float:-D__HAVE_SKY__}\
+%{!ansi:%{m68020:-Dmc68020}%{mc68020:-Dmc68020}%{!mc68020:%{!m68020:-Dmc68010}}}"
+
+#else
+
+/* -msoft-float is the default */
+#define CPP_SPEC \
+"%{msky:-D__HAVE_SKY__ }\
+%{!ansi:%{m68020:-Dmc68020}%{mc68020:-Dmc68020}%{!mc68020:%{!m68020:-Dmc68010}}}"
+
+#endif
+
+/* STARTFILE_SPEC to include sun floating point initialization
+ This is necessary (tr: Sun does it) for the sky routines.
+ I'm not sure what would happen below if people gave contradictory
+ arguments (eg. -msoft-float -mfpa) */
+
+#undef STARTFILE_SPEC
+
+#if TARGET_DEFAULT & MASK_SKY
+/* -msky is the default */
+#define STARTFILE_SPEC \
+ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}} \
+ %{msoft-float:Fcrt1.o%s} \
+ %{!msoft-float:Scrt1.o%s}"
+#else
+/* -msoft-float is the default */
+#define STARTFILE_SPEC \
+ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}} \
+ %{msky:Scrt1.o%s} \
+ %{!msky:Fcrt1.o%s}"
+#endif
+
+/* Specify library to handle `-a' basic block profiling.
+ Control choice of libm.a (if user says -lm)
+ based on fp arith default and options. */
+
+#undef LIB_SPEC
+
+#if TARGET_DEFAULT & MASK_SKY
+/* -msky is the default */
+#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} \
+%{a:/usr/lib/bb_link.o -lc} %{g:-lg} \
+%{msoft-float:-L/usr/lib/fsoft} \
+%{!msoft_float:-L/usr/lib/fsky}"
+#else
+/* -msoft-float is the default */
+#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} \
+%{a:/usr/lib/bb_link.o -lc} %{g:-lg} \
+%{!msky:-L/usr/lib/fsoft} \
+%{msky:-L/usr/lib/ffpa}"
+#endif
+
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{static:-Bstatic}"
+
+#undef ASM_OUTPUT_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ do { if (REAL_VALUE_ISINF (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "\t.double 0r-99e999\n"); \
+ else \
+ fprintf (FILE, "\t.double 0r99e999\n"); \
+ } \
+ else if (REAL_VALUE_MINUS_ZERO (VALUE)) \
+ { \
+ fprintf (FILE, "\t.long 0x80000000,0\n"); \
+ } \
+ else \
+ { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \
+ fprintf (FILE, "\t.double 0r%s\n", dstr); \
+ } \
+ } while (0)
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#undef ASM_OUTPUT_FLOAT
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ do { if (REAL_VALUE_ISINF (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "\t.single 0r-99e999\n"); \
+ else \
+ fprintf (FILE, "\t.single 0r99e999\n"); \
+ } \
+ else if (REAL_VALUE_MINUS_ZERO (VALUE)) \
+ { \
+ fprintf (FILE, "\t.long 0x80000000\n"); \
+ } \
+ else \
+ { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \
+ fprintf (FILE, "\t.single 0r%s\n", dstr); \
+ } \
+ } while (0)
+
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
+ do { \
+ if (CODE != 'f') \
+ { \
+ 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); \
+ } \
+ else if (REAL_VALUE_ISINF (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "#0r-99e999"); \
+ else \
+ fprintf (FILE, "#0r99e999"); \
+ } \
+ else if (REAL_VALUE_MINUS_ZERO (VALUE)) \
+ { \
+ fprintf (FILE, "#0r-0.0"); \
+ } \
+ else \
+ { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.9g", dstr); \
+ fprintf (FILE, "#0r%s", dstr); \
+ } \
+ } while (0)
+
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ do { if (REAL_VALUE_ISINF (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "#0r-99e999"); \
+ else \
+ fprintf (FILE, "#0r99e999"); \
+ } \
+ else if (REAL_VALUE_MINUS_ZERO (VALUE)) \
+ { \
+ fprintf (FILE, "#0r-0.0"); \
+ } \
+ else \
+ { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.20g", dstr); \
+ fprintf (FILE, "#0r%s", dstr); \
+ } \
+ } while (0)
diff --git a/gcc/config/m68k/sun3.h b/gcc/config/m68k/sun3.h
new file mode 100755
index 0000000..13e927e
--- /dev/null
+++ b/gcc/config/m68k/sun3.h
@@ -0,0 +1,301 @@
+/* Definitions of target machine for GNU compiler. Sun 68000/68020 version.
+ Copyright (C) 1987, 1988, 1993, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* This comment is here to see if it will keep Sun's cpp from dying. */
+
+/* If you do not need to generate floating point code for the optional
+ Sun FPA board, you can safely comment out the SUPPORT_SUN_FPA define
+ to gain a little speed and code size. */
+
+#define SUPPORT_SUN_FPA
+
+#include "m68k/m68k.h"
+
+/* See m68k.h. 7 means 68020 with 68881. */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
+#endif
+
+/* Define __HAVE_FPA__ or __HAVE_68881__ in preprocessor,
+ according to the -m flags.
+ This will control the use of inline 68881 insns in certain macros.
+ Also inform the program which CPU this is for. */
+
+#if TARGET_DEFAULT & MASK_68881
+
+/* -m68881 is the default */
+#define CPP_SPEC \
+"%{!msoft-float:%{mfpa:-D__HAVE_FPA__ }%{!mfpa:-D__HAVE_68881__ }}\
+%{m68000:-D__mc68010__}%{mc68000:-D__mc68010__}%{!mc68000:%{!m68000:-D__mc68020__}} \
+%{!ansi:%{m68000:-Dmc68010}%{mc68000:-Dmc68010}%{!mc68000:%{!m68000:-Dmc68020}}}"
+
+#else
+
+/* -msoft-float is the default */
+#define CPP_SPEC \
+"%{m68881:-D__HAVE_68881__ }%{mfpa:-D__HAVE_FPA__ }\
+%{m68000:-D__mc68010__}%{mc68000:-D__mc68010__}%{!mc68000:%{!m68000:-D__mc68020__}} \
+%{!ansi:%{m68000:-Dmc68010}%{mc68000:-Dmc68010}%{!mc68000:%{!m68000:-Dmc68020}}}"
+
+#endif
+
+/* Prevent error on `-sun3' and `-target sun3' options. */
+
+#define CC1_SPEC "%{sun3:} %{target:}"
+
+#define PTRDIFF_TYPE "int"
+
+/* We must override m68k.h. */
+#undef WCHAR_TYPE
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE "short unsigned int"
+#define WCHAR_TYPE_SIZE 16
+
+/* These compiler options take an argument. We ignore -target for now. */
+
+#define WORD_SWITCH_TAKES_ARG(STR) \
+ (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \
+ || !strcmp (STR, "target") || !strcmp (STR, "assert"))
+
+/* -m68000 requires special flags to the assembler. */
+
+#define ASM_SPEC \
+ "%{m68000:-mc68010}%{mc68000:-mc68010}%{!mc68000:%{!m68000:-mc68020}} \
+ %{fpic:-k} %{fPIC:-k} %{R} %{j} %{J} %{h} %{d2} %{keep-local-as-symbols:-L}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+/* For a while, -D_CROSS_TARGET_ARCH=SUN3 was included here,
+ but it doesn't work, partly because SUN3 etc. aren't defined
+ (and shouldn't be). It seems that on a native compiler _CROSS_TARGET_ARCH
+ should not be defined. For cross compilers, let's do things as we
+ normally do in GCC. -- rms. */
+
+#define CPP_PREDEFINES "-Dmc68000 -Dsun -Dunix -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
+
+/* STARTFILE_SPEC to include sun floating point initialization
+ This is necessary (tr: Sun does it) for both the m68881 and the fpa
+ routines.
+ Note that includes knowledge of the default specs for gcc, ie. no
+ args translates to the same effect as -m68881
+ I'm not sure what would happen below if people gave contradictory
+ arguments (eg. -msoft-float -mfpa) */
+
+#if TARGET_DEFAULT & MASK_FPA
+/* -mfpa is the default */
+#define STARTFILE_SPEC \
+ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}} \
+ %{m68881:Mcrt1.o%s} \
+ %{msoft-float:Fcrt1.o%s} \
+ %{!m68881:%{!msoft-float:Wcrt1.o%s}}"
+#else
+#if TARGET_DEFAULT & MASK_68881
+/* -m68881 is the default */
+#define STARTFILE_SPEC \
+ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}} \
+ %{mfpa:Wcrt1.o%s} \
+ %{msoft-float:Fcrt1.o%s} \
+ %{!mfpa:%{!msoft-float:Mcrt1.o%s}}"
+#else
+/* -msoft-float is the default */
+#define STARTFILE_SPEC \
+ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}} \
+ %{m68881:Mcrt1.o%s} \
+ %{mfpa:Wcrt1.o%s} \
+ %{!m68881:%{!mfpa:Fcrt1.o%s}}"
+#endif
+#endif
+
+/* Specify library to handle `-a' basic block profiling.
+ Control choice of libm.a (if user says -lm)
+ based on fp arith default and options. */
+
+#if TARGET_DEFAULT & MASK_FPA
+/* -mfpa is the default */
+#define LIB_SPEC "%{g:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} \
+%{g:-lg} \
+%{msoft-float:-L/usr/lib/fsoft}%{m68881:-L/usr/lib/f68881}\
+%{!msoft_float:%{!m68881:-L/usr/lib/ffpa}}"
+#else
+#if TARGET_DEFAULT & MASK_68881
+/* -m68881 is the default */
+#define LIB_SPEC "%{g:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} \
+%{g:-lg} \
+%{msoft-float:-L/usr/lib/fsoft}%{!msoft-float:%{!mfpa:-L/usr/lib/f68881}}\
+%{mfpa:-L/usr/lib/ffpa}"
+#else
+/* -msoft-float is the default */
+#define LIB_SPEC "%{g:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} \
+%{g:-lg} \
+%{!m68881:%{!mfpa:-L/usr/lib/fsoft}}%{m68881:-L/usr/lib/f68881}\
+%{mfpa:-L/usr/lib/ffpa}"
+#endif
+#endif
+
+/* Provide required defaults for linker -e and -d switches. */
+
+#define LINK_SPEC \
+ "%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{static:-Bstatic} %{assert*}"
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Allow folding division by zero. */
+#define REAL_INFINITY
+
+/* Generate calls to memcpy, memcmp and memset. */
+#define TARGET_MEM_FUNCTIONS
+
+/* This is not a good idea. It prevents interoperation between
+ files compiled with -m68881 and those compiled with -msoft-float. */
+#if 0
+#define FUNCTION_VALUEX(MODE) \
+ gen_rtx (REG, (MODE), \
+ ((TARGET_68881 \
+ && ((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode)) \
+ ? 16 : 0))
+
+#undef FUNCTION_VALUE
+#define FUNCTION_VALUE(VALTYPE,FUNC) FUNCTION_VALUEX (TYPE_MODE (VALTYPE))
+#endif /* 0 */
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#undef ASM_OUTPUT_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ { \
+ if (REAL_VALUE_ISINF (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "\t.double 0r-99e999\n"); \
+ else \
+ fprintf (FILE, "\t.double 0r99e999\n"); \
+ } \
+ else if (REAL_VALUE_ISNAN (VALUE)) \
+ { long l[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), l); \
+ fprintf (FILE, "\t.long 0x%lx\n\t.long 0x%lx\n", l[0], l[1]); \
+ } \
+ else \
+ { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.17g", dstr); \
+ fprintf (FILE, "\t.double 0r%s\n", dstr); \
+ } \
+ }
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#undef ASM_OUTPUT_FLOAT
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ { \
+ if (REAL_VALUE_ISINF (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "\t.single 0r-99e999\n"); \
+ else \
+ fprintf (FILE, "\t.single 0r99e999\n"); \
+ } \
+ else if (REAL_VALUE_ISNAN (VALUE)) \
+ { long l; \
+ REAL_VALUE_TO_TARGET_SINGLE ((VALUE), l); \
+ fprintf (FILE, "\t.long 0x%lx\n", l); \
+ } \
+ else \
+ { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.9g", dstr); \
+ fprintf (FILE, "\t.single 0r%s\n", dstr); \
+ } \
+ }
+
+/* This is how to output an assembler lines defining floating operands.
+ There's no way to output a NaN's fraction, so we lose it. */
+
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
+ do { \
+ if (CODE != 'f') \
+ { \
+ 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); \
+ } \
+ else if (REAL_VALUE_ISINF (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ asm_fprintf (FILE, "%I0r-99e999"); \
+ else \
+ asm_fprintf (FILE, "%I0r99e999"); \
+ } \
+ else if (REAL_VALUE_MINUS_ZERO (VALUE)) \
+ { \
+ asm_fprintf (FILE, "%I0r-0.0"); \
+ } \
+ else \
+ { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.9g", dstr); \
+ asm_fprintf (FILE, "%I0r%s", dstr); \
+ } \
+ } while (0)
+
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ do { if (REAL_VALUE_ISINF (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ asm_fprintf (FILE, "%I0r-99e999"); \
+ else \
+ asm_fprintf (FILE, "%I0r99e999"); \
+ } \
+ else if (REAL_VALUE_MINUS_ZERO (VALUE)) \
+ { \
+ asm_fprintf (FILE, "%I0r-0.0"); \
+ } \
+ else \
+ { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.17g", dstr); \
+ asm_fprintf (FILE, "%I0r%s", dstr); \
+ } \
+ } while (0)
+
+#if 0
+/* This was turned off as it caused linking errors on sunos4.1.
+ `gcc -a' links in /usr/lib/bb_link.o which does not provide __bb_link
+ but its own version of __bb_init_func. */
+#undef BLOCK_PROFILER_CODE
+#define BLOCK_PROFILER_CODE \
+extern int ___tcov_init; \
+ \
+__bb_init_func (blocks) \
+ struct bb *blocks; \
+{ \
+ if (! ___tcov_init) \
+ ___tcov_init_func (); \
+ \
+ ___bb_link (blocks->filename, blocks->counts, blocks->ncounts); \
+}
+#endif
diff --git a/gcc/config/m68k/sun3mach.h b/gcc/config/m68k/sun3mach.h
new file mode 100755
index 0000000..1c76cc4
--- /dev/null
+++ b/gcc/config/m68k/sun3mach.h
@@ -0,0 +1,15 @@
+#include "m68k/sun3.h"
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dmc68000 -Dsun -Dsun3 -Dunix -DMACH -DCMU -DMTXINU -DBIT_MSF -DBYTE_MSF -Asystem(unix) -Asystem(mach) -Acpu(m68k) -Amachine(m68k)"
+
+/* Specify extra dir to search for include files. */
+#define SYSTEM_INCLUDE_DIR "/usr/mach/include"
+
+/* LINK_SPEC is needed only for SunOS 4. */
+
+#undef LINK_SPEC
+
+/* Don't default to pcc-struct-return, because gcc is the only compiler, and
+ we want to retain compatibility with older gcc versions. */
+#define DEFAULT_PCC_STRUCT_RETURN 0
diff --git a/gcc/config/m68k/sun3n.h b/gcc/config/m68k/sun3n.h
new file mode 100755
index 0000000..32f5f65
--- /dev/null
+++ b/gcc/config/m68k/sun3n.h
@@ -0,0 +1,9 @@
+/* Define target machine as a Sun 3 with no 68881. */
+
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68020)
+
+#include "m68k/sun3.h"
+
+/* Don't try using XFmode. */
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 64
diff --git a/gcc/config/m68k/sun3n3.h b/gcc/config/m68k/sun3n3.h
new file mode 100755
index 0000000..38680d8
--- /dev/null
+++ b/gcc/config/m68k/sun3n3.h
@@ -0,0 +1,5 @@
+#include "m68k/sun3n.h"
+
+/* LINK_SPEC is needed only for SunOS 4. */
+
+#undef LINK_SPEC
diff --git a/gcc/config/m68k/sun3o3.h b/gcc/config/m68k/sun3o3.h
new file mode 100755
index 0000000..95f1ff6
--- /dev/null
+++ b/gcc/config/m68k/sun3o3.h
@@ -0,0 +1,5 @@
+#include "m68k/sun3.h"
+
+/* LINK_SPEC is needed only for SunOS 4. */
+
+#undef LINK_SPEC
diff --git a/gcc/config/m68k/t-adobe b/gcc/config/m68k/t-adobe
new file mode 100755
index 0000000..c46960c
--- /dev/null
+++ b/gcc/config/m68k/t-adobe
@@ -0,0 +1,9 @@
+CROSS_LIBGCC1 = libgcc1-asm.a
+LIB1ASMSRC = m68k/lb1sun3.asm
+
+LIB1ASMFUNCS = _mulsi3 _udivsi3 _divsi3 _umodsi3 _modsi3 \
+ _divdf3 _muldf3 _negdf2 _adddf3 _subdf3 \
+ _fixdfsi _fixsfsi _floatsidf _floatsisf _truncdfsf2 _extendsfdf2 \
+ _addsf3 _negsf2 _subsf3 _mulsf3 _divsf3 \
+ _eqdf2 _nedf2 _gtdf2 _gedf2 _ltdf2 _ledf2 \
+ _eqsf2 _nesf2 _gtsf2 _gesf2 _ltsf2 _lesf2
diff --git a/gcc/config/m68k/t-aux b/gcc/config/m68k/t-aux
new file mode 100755
index 0000000..3d59d67
--- /dev/null
+++ b/gcc/config/m68k/t-aux
@@ -0,0 +1,44 @@
+# Makefile additions for A/UX
+
+LIB2FUNCS_EXTRA=aux-mcount.c aux-exit.c
+
+FIXPROTO_DEFINES=-D_POSIX_SOURCE
+
+# Only really needed for collect2
+CLIB=-lld
+
+# Needed to support builds for multiple versions of A/UX
+# LDFLAGS=-static
+
+# Make sure we get the right assembler by letting gcc choose
+AS = $(GCC_FOR_TARGET) -xassembler-with-cpp -D__ASSEMBLY__ $(INCLUDES) -c
+
+aux-mcount.c: $(srcdir)/config/m68k/aux-mcount.c
+ cp $(srcdir)/config/m68k/aux-mcount.c aux-mcount.c
+
+aux-exit.c: $(srcdir)/config/m68k/aux-exit.c
+ cp $(srcdir)/config/m68k/aux-exit.c aux-exit.c
+
+crt1.o: $(srcdir)/config/m68k/aux-crt1.c $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) -o crt1.o -c \
+ -fno-omit-frame-pointer $(srcdir)/config/m68k/aux-crt1.c
+
+mcrt1.o: $(srcdir)/config/m68k/aux-crt1.c $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) -o mcrt1.o -c \
+ -fno-omit-frame-pointer -DMCRT1 $(srcdir)/config/m68k/aux-crt1.c
+
+maccrt1.o: $(srcdir)/config/m68k/aux-crt1.c $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) -o maccrt1.o -c \
+ -fno-omit-frame-pointer -DMACCRT1 $(srcdir)/config/m68k/aux-crt1.c
+
+crt2.o: $(srcdir)/config/m68k/aux-crt2.asm $(GCC_PASSES)
+ $(AS) -o crt2.o $(srcdir)/config/m68k/aux-crt2.asm
+
+crtn.o: $(srcdir)/config/m68k/aux-crtn.asm $(GCC_PASSES)
+ $(AS) -o crtn.o $(srcdir)/config/m68k/aux-crtn.asm
+
+low.gld: $(srcdir)/config/m68k/aux-low.gld
+ sed -e 's|@libdir@|$(libdir)|' -e 's|@tooldir@|$(tooldir)|' \
+ -e 's|@local_prefix@|$(local_prefix)|' \
+ $(srcdir)/config/m68k/aux-low.gld > tmp-low.gld
+ mv tmp-low.gld low.gld
diff --git a/gcc/config/m68k/t-linux b/gcc/config/m68k/t-linux
new file mode 100755
index 0000000..99dc452
--- /dev/null
+++ b/gcc/config/m68k/t-linux
@@ -0,0 +1,2 @@
+# On GNU/Linux we can print long double
+ENQUIRE_CFLAGS = -DNO_MEM -O0
diff --git a/gcc/config/m68k/t-linux-aout b/gcc/config/m68k/t-linux-aout
new file mode 100755
index 0000000..99dc452
--- /dev/null
+++ b/gcc/config/m68k/t-linux-aout
@@ -0,0 +1,2 @@
+# On GNU/Linux we can print long double
+ENQUIRE_CFLAGS = -DNO_MEM -O0
diff --git a/gcc/config/m68k/t-lynx b/gcc/config/m68k/t-lynx
new file mode 100755
index 0000000..6f2caba
--- /dev/null
+++ b/gcc/config/m68k/t-lynx
@@ -0,0 +1,6 @@
+CROSS_LIBGCC1 = libgcc1-asm.a
+LIB1ASMSRC = m68k/lb1sf68.asm
+LIB1ASMFUNCS = _mulsi3 _udivsi3 _divsi3 _umodsi3 _modsi3 \
+ _double _float _floatex \
+ _eqdf2 _nedf2 _gtdf2 _gedf2 _ltdf2 _ledf2 \
+ _eqsf2 _nesf2 _gtsf2 _gesf2 _ltsf2 _lesf2
diff --git a/gcc/config/m68k/t-m68kbare b/gcc/config/m68k/t-m68kbare
new file mode 100755
index 0000000..d334eab
--- /dev/null
+++ b/gcc/config/m68k/t-m68kbare
@@ -0,0 +1,24 @@
+CROSS_LIBGCC1 = libgcc1-asm.a
+LIB1ASMSRC = m68k/lb1sf68.asm
+LIB1ASMFUNCS = _mulsi3 _udivsi3 _divsi3 _umodsi3 _modsi3 \
+ _double _float _floatex \
+ _eqdf2 _nedf2 _gtdf2 _gedf2 _ltdf2 _ledf2 \
+ _eqsf2 _nesf2 _gtsf2 _gesf2 _ltsf2 _lesf2
+
+# These are really part of libgcc1, but this will cause them to be
+# built correctly, so...
+LIB2FUNCS_EXTRA = fpgnulib.c xfgnulib.c
+
+fpgnulib.c: $(srcdir)/config/m68k/fpgnulib.c
+ cp $(srcdir)/config/m68k/fpgnulib.c fpgnulib.c
+xfgnulib.c: $(srcdir)/config/m68k/fpgnulib.c
+ echo '#define EXTFLOAT' > xfgnulib.c
+ cat $(srcdir)/config/m68k/fpgnulib.c >> xfgnulib.c
+
+MULTILIB_OPTIONS = m68000/m68020/m5200/mcpu32 m68881/msoft-float
+MULTILIB_DIRNAMES =
+MULTILIB_MATCHES = m68000=mc68000 m68000=m68302 mcpu32=m68332 m68020=mc68020 m68020=m68040 m68020=m68060
+MULTILIB_EXCEPTIONS = m68000/msoft-float m5200/m68881 m5200/msoft-float mcpu32/m68881 mcpu32/msoft-float
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/m68k/t-m68kelf b/gcc/config/m68k/t-m68kelf
new file mode 100755
index 0000000..d0f857a
--- /dev/null
+++ b/gcc/config/m68k/t-m68kelf
@@ -0,0 +1,29 @@
+CROSS_LIBGCC1 = libgcc1-asm.a
+LIB1ASMSRC = m68k/lb1sf68.asm
+LIB1ASMFUNCS = _mulsi3 _udivsi3 _divsi3 _umodsi3 _modsi3 \
+ _double _float _floatex \
+ _eqdf2 _nedf2 _gtdf2 _gedf2 _ltdf2 _ledf2 \
+ _eqsf2 _nesf2 _gtsf2 _gesf2 _ltsf2 _lesf2
+
+# These are really part of libgcc1, but this will cause them to be
+# built correctly, so...
+LIB2FUNCS_EXTRA = fpgnulib.c xfgnulib.c
+
+fpgnulib.c: $(srcdir)/config/m68k/fpgnulib.c
+ cp $(srcdir)/config/m68k/fpgnulib.c fpgnulib.c
+xfgnulib.c: $(srcdir)/config/m68k/fpgnulib.c
+ echo '#define EXTFLOAT' > xfgnulib.c
+ cat $(srcdir)/config/m68k/fpgnulib.c >> xfgnulib.c
+
+MULTILIB_OPTIONS = m68000/m68020/m5200/mcpu32 m68881/msoft-float
+MULTILIB_DIRNAMES =
+MULTILIB_MATCHES = m68000=mc68000 m68000=m68302 mcpu32=m68332 m68020=mc68020 m68020=m68040 m68020=m68060
+MULTILIB_EXCEPTIONS = m68000/msoft-float m5200/m68881 m5200/msoft-float mcpu32/m68881 mcpu32/msoft-float
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+# from ../t-svr4
+EXTRA_PARTS=crtbegin.o crtend.o
+# no pic for now
+#CRTSTUFF_T_CFLAGS=-fpic
diff --git a/gcc/config/m68k/t-mot3300 b/gcc/config/m68k/t-mot3300
new file mode 100755
index 0000000..2fc1185
--- /dev/null
+++ b/gcc/config/m68k/t-mot3300
@@ -0,0 +1,10 @@
+MULTILIB_OPTIONS=m68000/m68020 msoft-float
+MULTILIB_DIRNAMES=
+MULTILIB_MATCHES=m68000=mc68000 m68000=m68302 m68000=m68332 m68020=mc68020 m68020=m68040
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+CRT0_S = $(srcdir)/config/m68k/mot3300-crt0.S
+MCRT0_S = $(srcdir)/config/m68k/mot3300Mcrt0.S
+CRT0STUFF_T_CFLAGS = -DMOTOROLA -DSGS_CMP_ORDER
diff --git a/gcc/config/m68k/t-mot3300-gald b/gcc/config/m68k/t-mot3300-gald
new file mode 100755
index 0000000..435afc4
--- /dev/null
+++ b/gcc/config/m68k/t-mot3300-gald
@@ -0,0 +1,13 @@
+T_CPPFLAGS = -DUSE_GAS -DUSE_GLD
+TARGET_LIBGCC2_CFLAGS = -DUSE_GAS
+
+MULTILIB_OPTIONS=m68000/m68020 msoft-float
+MULTILIB_DIRNAMES=
+MULTILIB_MATCHES=m68000=mc68000 m68000=m68302 m68000=m68332 m68020=mc68020 m68020=m68040
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+CRT0_S = $(srcdir)/config/m68k/mot3300-crt0.S
+MCRT0_S = $(srcdir)/config/m68k/mot3300Mcrt0.S
+CRT0STUFF_T_CFLAGS =
diff --git a/gcc/config/m68k/t-mot3300-gas b/gcc/config/m68k/t-mot3300-gas
new file mode 100755
index 0000000..5256674
--- /dev/null
+++ b/gcc/config/m68k/t-mot3300-gas
@@ -0,0 +1,13 @@
+T_CPPFLAGS = -DUSE_GAS
+TARGET_LIBGCC2_CFLAGS = -DUSE_GAS
+
+MULTILIB_OPTIONS=m68000/m68020 msoft-float
+MULTILIB_DIRNAMES=
+MULTILIB_MATCHES=m68000=mc68000 m68000=m68302 m68000=m68332 m68020=mc68020 m68020=m68040
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+CRT0_S = $(srcdir)/config/m68k/mot3300-crt0.S
+MCRT0_S = $(srcdir)/config/m68k/mot3300Mcrt0.S
+CRT0STUFF_T_CFLAGS =
diff --git a/gcc/config/m68k/t-mot3300-gld b/gcc/config/m68k/t-mot3300-gld
new file mode 100755
index 0000000..8cc3ed6
--- /dev/null
+++ b/gcc/config/m68k/t-mot3300-gld
@@ -0,0 +1,12 @@
+T_CPPFLAGS = -DUSE_GLD
+
+MULTILIB_OPTIONS=m68000/m68020 msoft-float
+MULTILIB_DIRNAMES=
+MULTILIB_MATCHES=m68000=mc68000 m68000=m68302 m68000=m68332 m68020=mc68020 m68020=m68040
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+CRT0_S = $(srcdir)/config/m68k/mot3300-crt0.S
+MCRT0_S = $(srcdir)/config/m68k/mot3300Mcrt0.S
+CRT0STUFF_T_CFLAGS = -DMOTOROLA -DSGS_CMP_ORDER
diff --git a/gcc/config/m68k/t-next b/gcc/config/m68k/t-next
new file mode 100755
index 0000000..787ee79
--- /dev/null
+++ b/gcc/config/m68k/t-next
@@ -0,0 +1,6 @@
+# libgcc1.c is not needed, since the standard library has these functions.
+LIBGCC1=
+CROSS_LIBGCC1=
+
+nextstep.o: $(srcdir)/config/nextstep.c $(CONFIG_H) flags.h tree.h
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gcc/config/m68k/t-ose68 b/gcc/config/m68k/t-ose68
new file mode 100755
index 0000000..5f9cba2
--- /dev/null
+++ b/gcc/config/m68k/t-ose68
@@ -0,0 +1,26 @@
+# CYGNUS LOCAL ericsson
+
+CROSS_LIBGCC1 = libgcc1-asm.a
+LIB1ASMSRC = m68k/lb1sf68.asm
+LIB1ASMFUNCS = _mulsi3 _udivsi3 _divsi3 _umodsi3 _modsi3 \
+ _double _float _floatex \
+ _eqdf2 _nedf2 _gtdf2 _gedf2 _ltdf2 _ledf2 \
+ _eqsf2 _nesf2 _gtsf2 _gesf2 _ltsf2 _lesf2
+
+# These are really part of libgcc1, but this will cause them to be
+# built correctly, so...
+LIB2FUNCS_EXTRA = fpgnulib.c xfgnulib.c
+
+fpgnulib.c: $(srcdir)/config/m68k/fpgnulib.c
+ cp $(srcdir)/config/m68k/fpgnulib.c fpgnulib.c
+xfgnulib.c: $(srcdir)/config/m68k/fpgnulib.c
+ echo '#define EXTFLOAT' > xfgnulib.c
+ cat $(srcdir)/config/m68k/fpgnulib.c >> xfgnulib.c
+
+MULTILIB_OPTIONS= m68000/m68020 m68881/msoft-float
+MULTILIB_DIRNAMES =
+MULTILIB_MATCHES = m68000=mc68000 m68000=m68302 m68000=m68332 m68020=mc68020 m68020=m68040
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
diff --git a/gcc/config/m68k/t-vxworks68 b/gcc/config/m68k/t-vxworks68
new file mode 100755
index 0000000..7fa5943
--- /dev/null
+++ b/gcc/config/m68k/t-vxworks68
@@ -0,0 +1,27 @@
+CROSS_LIBGCC1 = libgcc1-asm.a
+LIB1ASMSRC = m68k/lb1sf68.asm
+LIB1ASMFUNCS = _mulsi3 _udivsi3 _divsi3 _umodsi3 _modsi3 \
+ _double _float _floatex \
+ _eqdf2 _nedf2 _gtdf2 _gedf2 _ltdf2 _ledf2 \
+ _eqsf2 _nesf2 _gtsf2 _gesf2 _ltsf2 _lesf2
+
+# We don't want to put exit in libgcc.a for VxWorks, because VxWorks
+# does not have _exit.
+TARGET_LIBGCC2_CFLAGS = -Dexit=unused_exit
+
+# These are really part of libgcc1, but this will cause them to be
+# built correctly, so...
+LIB2FUNCS_EXTRA = fpgnulib.c xfgnulib.c
+
+fpgnulib.c: $(srcdir)/config/m68k/fpgnulib.c
+ cp $(srcdir)/config/m68k/fpgnulib.c fpgnulib.c
+xfgnulib.c: $(srcdir)/config/m68k/fpgnulib.c
+ echo '#define EXTFLOAT' > xfgnulib.c
+ cat $(srcdir)/config/m68k/fpgnulib.c >> xfgnulib.c
+
+MULTILIB_OPTIONS = m68000/m68020 m68881/msoft-float
+MULTILIB_DIRNAMES =
+MULTILIB_MATCHES = m68000=mc68000 m68000=m68302 m68000=m68332 m68020=mc68020 m68020=m68040
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/m68k/tower-as.h b/gcc/config/m68k/tower-as.h
new file mode 100755
index 0000000..7b5771a
--- /dev/null
+++ b/gcc/config/m68k/tower-as.h
@@ -0,0 +1,616 @@
+/* Definitions of target machine for GNU compiler.
+ For NCR Tower 32/4x0 and 32/6x0 running System V Release 3.
+ Copyright (C) 1990, 1993, 1994, 1996, 1997 Free Software Foundation, Inc.
+ Contributed by Robert Andersson (ra@intsys.no), International Systems,
+ Oslo, Norway.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+/* This file outputs assembler source suitable for the native Tower as
+ and with sdb debugging symbols. See tower.h for more comments.
+
+ This file was based on m68k.h, hp320.h and 3b1.h as of the
+ 1.37.1 version. */
+
+#include "m68k/tower.h"
+#undef SELECT_RTX_SECTION
+
+/* Use default settings for system V.3. */
+
+#include "svr3.h"
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dunix -Dtower32 -Dtower32_600 -D__motorola__ -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
+
+/* Define __HAVE_68881 in preprocessor only if -m68881 is specified.
+ This will control the use of inline 68881 insns in certain macros.
+ Also, define special define used to identify the Tower assembler. */
+
+#define CPP_SPEC "-D__TOWER_ASM__ %{m68881:-D__HAVE_68881__}"
+
+/* We don't want local labels to start with period.
+ See ASM_OUTPUT_INTERNAL_LABEL. */
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX ""
+
+/* The prefix to add to user-visible assembler symbols. */
+/* We do not want leading underscores. */
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+
+/* These four macros control how m68k.md is expanded. */
+
+#define MOTOROLA /* Use Motorola syntax rather than "MIT" */
+#define SGS /* Uses SGS assembler */
+#define SGS_CMP_ORDER /* Takes cmp operands in reverse order */
+#define SGS_NO_LI /* Suppress jump table label usage */
+
+/* Turn on SDB debugging info. */
+
+#define SDB_DEBUGGING_INFO
+
+/* This is only useful if gdb is changed, but doesn't harm anyway. */
+
+#define ASM_IDENTIFY_GCC(FILE) \
+ fprintf (FILE, "gcc2_compiled%%:\n")
+
+/* All the ASM_OUTPUT macros need to conform to the Tower as syntax. */
+
+#define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
+ do { \
+ fprintf (FILE, "\tfile\t"); \
+ output_quoted_string (FILE, FILENAME); \
+ fprintf (FILE, "\n"); \
+ fprintf (FILE, "section ~init,\"x\"\n"); \
+ fprintf (FILE, "section ~fini,\"x\"\n"); \
+ fprintf (FILE, "section ~rodata,\"x\"\n"); \
+ fprintf (FILE, "text\n"); \
+ } while (0)
+
+#define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \
+ fprintf (FILE, "\tln\t%d\n", \
+ (sdb_begin_function_line \
+ ? last_linenum - sdb_begin_function_line : 1))
+
+#undef ASM_OUTPUT_IDENT
+#define ASM_OUTPUT_IDENT(FILE, NAME) \
+ fprintf (FILE, "\tident\t\"%s\" \n", NAME)
+
+#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
+ do { register int sp = 0, lp = 0; \
+ fprintf ((FILE), "\tbyte\t"); \
+ loop: \
+ if ((PTR)[sp] > ' ' && ! ((PTR)[sp] & 0x80) && (PTR)[sp] != '\\') \
+ { lp += 3; \
+ fprintf ((FILE), "'%c", (PTR)[sp]); } \
+ else \
+ { lp += 5; \
+ fprintf ((FILE), "0x%x", (PTR)[sp]); } \
+ if (++sp < (LEN)) \
+ { if (lp > 60) \
+ { lp = 0; \
+ fprintf ((FILE), "\n\tbyte\t"); } \
+ else \
+ putc (',', (FILE)); \
+ goto loop; } \
+ putc ('\n', (FILE)); } while (0)
+
+/* Translate Motorola opcodes such as `jbeq'
+ into SGS/Tower opcodes such as `beq.w'.
+ Change `move' to `mov'.
+ Change `cmpm' to `cmp'.
+ Change `divsl' to `tdivs'.
+ Change `divul' to `tdivu'.
+ Change `ftst' to `ftest'.
+ Change `fmove' to `fmov'. */
+
+#define ASM_OUTPUT_OPCODE(FILE, PTR) \
+{ if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
+ { ++(PTR); \
+ while (*(PTR) != ' ') \
+ { putc (*(PTR), (FILE)); ++(PTR); } \
+ fprintf ((FILE), ".w"); } \
+ else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
+ { fprintf ((FILE), "mov"); (PTR) += 4; } \
+ else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \
+ && (PTR)[2] == 'p' && (PTR)[3] == 'm') \
+ { fprintf ((FILE), "cmp"); (PTR) += 4; } \
+ else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 's' \
+ && (PTR)[4] == 'l') \
+ { fprintf ((FILE), "tdivs"); (PTR) += 5; } \
+ else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 'u' \
+ && (PTR)[4] == 'l') \
+ { fprintf ((FILE), "tdivu"); (PTR) += 5; } \
+ else if ((PTR)[0] == 'f' && (PTR)[1] == 't' \
+ && (PTR)[2] == 's' && (PTR)[3] == 't') \
+ { fprintf ((FILE), "ftest"); (PTR) += 4; } \
+ else if ((PTR)[0] == 'f' && (PTR)[1] == 'm' \
+ && (PTR)[2] == 'o' && (PTR)[3] == 'v' \
+ && (PTR)[4] == 'e') \
+ { fprintf ((FILE), "fmov"); (PTR) += 5; } \
+}
+
+
+
+/* Override parts of m68k.h to fit the Tower assembler.
+ This section needs to track changes done to m68k.h in the future. */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (68k, Motorola/SGS/Tower32 syntax)");
+
+#undef FUNCTION_BLOCK_PROFILER
+#define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) \
+ do { \
+ char label1[20], label2[20]; \
+ ASM_GENERATE_INTERNAL_LABEL (label1, "LPBX", 0); \
+ ASM_GENERATE_INTERNAL_LABEL (label2, "LPI", LABELNO); \
+ fprintf (FILE, "\ttst.l %s\n\tbne %s\n\tpea %s\n\tjsr __bb_init_func\n\taddq.l &4,%%sp\n", \
+ label1, label2, label1); \
+ ASM_OUTPUT_INTERNAL_LABEL (FILE, "LPI", LABELNO); \
+ putc ('\n', FILE); \
+ } while (0)
+
+#undef BLOCK_PROFILER
+#define BLOCK_PROFILER(FILE, BLOCKNO) \
+ do { \
+ char label[20]; \
+ ASM_GENERATE_INTERNAL_LABEL (label, "LPBX", 2); \
+ fprintf (FILE, "\taddq.l &1,%s+%d\n", label, 4 * BLOCKNO); \
+ } while (0)
+
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(FILE, LABEL_NO) \
+ fprintf (FILE, "\tmov.l &LP%%%d,%%a0\n\tjsr mcount%%\n", (LABEL_NO))
+
+#undef FUNCTION_EXTRA_EPILOGUE
+#define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE) \
+ { extern int current_function_returns_pointer; \
+ if ((current_function_returns_pointer) && \
+ ! find_equiv_reg (0, get_last_insn (), 0, 0, 0, 8, Pmode)) \
+ asm_fprintf (FILE, "\tmov.l %Rd0,%Ra0\n"); }
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#undef ASM_OUTPUT_REG_PUSH
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tmov.l %s,-(%%sp)\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#undef ASM_OUTPUT_REG_POP
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tmov.l (%%sp)+,%s\n", reg_names[REGNO])
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+( fprintf (FILE, "#NO_APP\n"), \
+ output_file_directive ((FILE), main_input_filename))
+
+#undef TEXT_SECTION_ASM_OP
+#define TEXT_SECTION_ASM_OP "text"
+
+#undef DATA_SECTION_ASM_OP
+#define DATA_SECTION_ASM_OP "data"
+
+/* This says how to output an assembler line to define a global common symbol.
+ We use SIZE rather than ROUNDED, as this is what the native cc does. */
+
+#undef ASM_OUTPUT_COMMON
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\tcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%d\n", ((SIZE) == 0) ? (ROUNDED) : (SIZE)))
+
+/* This says how to output an assembler line to define a local common symbol.
+ We use SIZE rather than ROUNDED, as this is what the native cc does. */
+
+#undef ASM_OUTPUT_LOCAL
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\tlcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%d\n", ((SIZE) == 0) ? (ROUNDED) : (SIZE)))
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#undef ASM_FORMAT_PRIVATE_NAME
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 11), \
+ sprintf ((OUTPUT), "%s%%%%%d", (NAME), (LABELNO)))
+
+/* This is the command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#undef GLOBAL_ASM_OP
+#define GLOBAL_ASM_OP "global"
+
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
+ sprintf ((LABEL), "%s%%%d", (PREFIX), (NUM))
+
+#undef ASM_OUTPUT_INTERNAL_LABEL
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf ((FILE), "%s%%%d:\n", (PREFIX), (NUM))
+
+#undef ASM_OUTPUT_CASE_LABEL
+#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
+ fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n", \
+ XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM)); \
+
+#undef ASM_OUTPUT_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+do { long l[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
+ fprintf (FILE, "\tlong 0x%x,0x%x\n", l[0], l[1]); \
+ } while (0)
+
+#undef ASM_OUTPUT_LONG_DOUBLE
+#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
+do { long l[3]; \
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
+ fprintf (FILE, "\tlong 0x%x,0x%x,0x%x\n", l[0], l[1], l[2]); \
+ } while (0)
+
+#undef ASM_OUTPUT_FLOAT
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+do { long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
+ fprintf ((FILE), "\tlong 0x%x\n", l); \
+ } while (0)
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#undef ASM_OUTPUT_INT
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\tlong "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#undef ASM_OUTPUT_SHORT
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\tshort "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#undef ASM_OUTPUT_CHAR
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\tbyte "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#undef ASM_OUTPUT_BYTE
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\tbyte 0x%x\n", (VALUE))
+
+#undef ASM_OUTPUT_ADDR_VEC_ELT
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\tlong L%%%d\n", (VALUE))
+
+#undef ASM_OUTPUT_ADDR_DIFF_ELT
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
+ fprintf (FILE, "\tshort L%%%d-L%%%d\n", (VALUE), (REL))
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) == 1) \
+ fprintf (FILE, "\teven\n"); \
+ else if ((LOG) != 0) \
+ abort ();
+
+#undef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\tspace %d\n", (SIZE))
+
+/* Output a float value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
+ do { long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (r, l); \
+ /* Use hex representation even if CODE is f. as needs it. */ \
+ fprintf ((FILE), "&0x%lx", l); \
+ } while (0)
+
+/* Output a double value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ do { long l[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
+ fprintf ((FILE), "&0x%lx%08lx", l[0], l[1]); \
+ } while (0)
+
+#if 0
+#undef PRINT_OPERAND
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (CODE == '.') fprintf (FILE, "."); \
+ else if (CODE == '#') fprintf (FILE, "&"); \
+ else if (CODE == '-') fprintf (FILE, "-(%%sp)"); \
+ else if (CODE == '+') fprintf (FILE, "(%%sp)+"); \
+ else if (CODE == '@') fprintf (FILE, "(%%sp)"); \
+ else if (CODE == '!') fprintf (FILE, "%%fpcr"); \
+ else if (CODE == '/') \
+ fprintf (FILE, "%%"); \
+ else if (CODE == '$') { if (TARGET_68040_ONLY) fprintf (FILE, "s"); } \
+ else if (CODE == '&') { if (TARGET_68040_ONLY) fprintf (FILE, "d"); } \
+ else if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if (GET_CODE (X) == MEM) \
+ output_address (XEXP (X, 0)); \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
+ { REAL_VALUE_TYPE r; long l; \
+ REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
+ REAL_VALUE_TO_TARGET_SINGLE (r, l); \
+ fprintf (FILE, "&0x%x", l); } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode) \
+ { REAL_VALUE_TYPE r; int i[2]; \
+ REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
+ REAL_VALUE_TO_TARGET_DOUBLE (r, i); \
+ fprintf (FILE, "&0x%x%08x", i[0], i[1]); } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == XFmode) \
+ { REAL_VALUE_TYPE r; \
+ REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
+ ASM_OUTPUT_LONG_DOUBLE_OPERAND (FILE, r); } \
+ else { putc ('&', FILE); output_addr_const (FILE, X); }}
+#endif
+
+/* Note that this contains a kludge that knows that the only reason
+ we have an address (plus (label_ref...) (reg...))
+ is in the insn before a tablejump, and we know that the table is
+ exactly 10 bytes away. */
+
+#undef PRINT_OPERAND_ADDRESS
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx reg1, reg2, breg, ireg; \
+ register rtx addr = ADDR; \
+ rtx offset; \
+ switch (GET_CODE (addr)) \
+ { \
+ case REG: \
+ fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
+ break; \
+ case PRE_DEC: \
+ fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case POST_INC: \
+ fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case PLUS: \
+ reg1 = 0; reg2 = 0; \
+ ireg = 0; breg = 0; \
+ offset = 0; \
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
+ { \
+ offset = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
+ { \
+ offset = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) != PLUS) ; \
+ else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
+ || GET_CODE (addr) == SIGN_EXTEND) \
+ { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
+/* for OLD_INDEXING \
+ else if (GET_CODE (addr) == PLUS) \
+ { \
+ if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg2 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg2 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ } \
+ */ \
+ if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
+ if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
+ || GET_CODE (reg1) == MULT)) \
+ || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
+ { breg = reg2; ireg = reg1; } \
+ else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
+ { breg = reg1; ireg = reg2; } \
+ if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { int scale = 1; \
+ if (GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "10(%%pc,%s.w", \
+ reg_names[REGNO (XEXP (ireg, 0))]); \
+ else \
+ fprintf (FILE, "10(%%pc,%s.l", \
+ reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; } \
+ if (ireg != 0 || breg != 0) \
+ { int scale = 1; \
+ if (breg == 0) \
+ abort (); \
+ if (addr != 0) \
+ output_addr_const (FILE, addr); \
+ fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \
+ if (ireg != 0) \
+ putc (',', FILE); \
+ if (ireg != 0 && GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
+ else if (ireg != 0) \
+ fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; \
+ } \
+ else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "10(%%pc,%s.w)", \
+ reg_names[REGNO (reg1)]); \
+ break; } \
+ default: \
+ output_addr_const (FILE, addr); \
+ }}
+
+
+
+/* Override usual definitions of SDB output macros.
+ These definitions differ only in the absence of the period
+ at the beginning of the name of the directive
+ and in the use of `~' as the symbol for the current location. */
+
+#define PUT_SDB_SCL(a) fprintf(asm_out_file, "\tscl\t%d;", (a))
+#define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\tval\t%d;", (a))
+#define PUT_SDB_VAL(a) \
+( fputs ("\tval\t", asm_out_file), \
+ output_addr_const (asm_out_file, (a)), \
+ fputc (';', asm_out_file))
+
+#define PUT_SDB_DEF(a) \
+do { fprintf (asm_out_file, "\tdef\t"); \
+ ASM_OUTPUT_LABELREF (asm_out_file, a); \
+ fprintf (asm_out_file, ";"); } while (0)
+
+#define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\tdef\t~%s;",a)
+#define PUT_SDB_ENDEF fputs("\tendef\n", asm_out_file)
+#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\ttype\t0%o;", a)
+#define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\tsize\t%d;", a)
+#define PUT_SDB_START_DIM fprintf(asm_out_file, "\tdim\t")
+#define PUT_SDB_NEXT_DIM(a) fprintf(asm_out_file, "%d,", a)
+#define PUT_SDB_LAST_DIM(a) fprintf(asm_out_file, "%d;", a)
+
+#define PUT_SDB_TAG(a) \
+do { fprintf (asm_out_file, "\ttag\t"); \
+ ASM_OUTPUT_LABELREF (asm_out_file, a); \
+ fprintf (asm_out_file, ";"); } while (0)
+
+#define PUT_SDB_BLOCK_START(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~bb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_BLOCK_END(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~eb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_FUNCTION_START(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~bf;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_FUNCTION_END(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~ef;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_EPILOGUE_END(NAME) \
+ fprintf (asm_out_file, \
+ "\tdef\t%s;\tval\t~;\tscl\t-1;\tendef\n", \
+ (NAME))
+
+#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
+ sprintf ((BUFFER), "~%dfake", (NUMBER));
+
+#define NO_DOLLAR_IN_LABEL
+#define NO_DOT_IN_LABEL
+
+/* The usual definitions don't work because neither $ nor . is allowed. */
+#define CONSTRUCTOR_NAME_FORMAT "_GLOBAL_%%I\%%%s"
+
+/* Define a few machine-specific details
+ of the implementation of constructors.
+
+ The __CTORS_LIST__ goes in the .init section. Define CTOR_LIST_BEGIN
+ and CTOR_LIST_END to contribute to the .init section an instruction to
+ push a word containing 0 (or some equivalent of that).
+
+ ASM_OUTPUT_CONSTRUCTOR should be defined
+ to push the address of the constructor. */
+
+#define ASM_LONG "\tlong"
+#undef INIT_SECTION_ASM_OP
+#define INIT_SECTION_ASM_OP "section\t~init"
+#undef FINI_SECTION_ASM_OP
+#define FINI_SECTION_ASM_OP "section\t~fini"
+#undef CONST_SECTION_ASM_OP
+#define CONST_SECTION_ASM_OP "section\t~rodata"
+
+#define CTOR_LIST_BEGIN \
+ asm (INIT_SECTION_ASM_OP); \
+ asm ("clr.l -(%sp)")
+#define CTOR_LIST_END CTOR_LIST_BEGIN
+
+#define BSS_SECTION_ASM_OP "section\t~bss"
+
+#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
+ do { \
+ init_section (); \
+ fprintf (FILE, "\tmov.l &"); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, ",-(%%sp)\n"); \
+ } while (0)
diff --git a/gcc/config/m68k/tower.h b/gcc/config/m68k/tower.h
new file mode 100755
index 0000000..73faedb
--- /dev/null
+++ b/gcc/config/m68k/tower.h
@@ -0,0 +1,104 @@
+/* Definitions of target machine for GNU compiler.
+ Copyright (C) 1990, 1994, 1996 Free Software Foundation, Inc.
+ Contributed by Robert Andersson, International Systems, Oslo, ra@intsys.no.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* For NCR Tower 32/4x0 and 32/6x0 running System V Release 3. I don't have
+ access to 200/700/800/850 machines, so I don't know if it works on those
+ as well. It shouldn't be far from it however. The hardware floating point
+ support is completely untested, as I do not have access to a machine with
+ a 6888x FPU in it. It does not work on the System V Release 2 based OS
+ releases. Making it work will not be easy, due to the silly way in which
+ stack expansion is implemented in the OS.
+
+ This file is included in tower-as.h.
+ Do *NOT* include this file directly. */
+
+
+#include "m68k/m68k.h"
+
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68020)
+
+/* Don't try using XFmode. */
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dunix -Dtower32 -Dtower32_200 -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
+
+#if 0 /* It is incorrect to test these symbols.
+ They describe the host, not the target.
+ It should not matter which model is specified. */
+#ifdef tower32_600
+#define CPP_PREDEFINES "-Dunix -Dtower32 -Dtower32_600 -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
+#endif
+#ifdef tower32_700
+#define CPP_PREDEFINES "-Dunix -Dtower32 -Dtower32_700 -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
+#endif
+#ifdef tower32_800
+#define CPP_PREDEFINES "-Dunix -Dtower32 -Dtower32_800 -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
+#endif
+#ifdef tower32_850
+#define CPP_PREDEFINES "-Dunix -Dtower32 -Dtower32_850 -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
+#endif
+#endif
+
+/* The startfiles and libraries depend on the -p and -m68881 options.
+ The Tower does not support the -pg option. */
+
+#define LINK_SPEC \
+"%{p:%{m68881:-L/usr/lib/fp/libp} -L/usr/lib/libp} \
+ %{m68881:-L/usr/lib/fp}"
+
+#define LIB_SPEC \
+"%{shlib:-lc_s} -lc crtend.o%s crtn.o%s"
+
+#define STARTFILE_SPEC \
+"%{p:mcrt1.o%s} %{!p:crt1.o%s} crtbegin.o%s"
+
+/* Use mem* functions, recognize #ident lines. */
+
+#define TARGET_MEM_FUNCTIONS
+#define IDENT_DIRECTIVE
+
+/* Every structure and union's size must be a multiple of two bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* All register names should have a leading % character. */
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES \
+{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%sp", \
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7"};
+
+#undef REGISTER_PREFIX
+#define REGISTER_PREFIX "%"
+
+#undef IMMEDIATE_PREFIX
+#define IMMEDIATE_PREFIX "&"
+
+/* The prefix to add to user-visible assembler symbols. */
+
+/* We do not want leading underscores. */
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
diff --git a/gcc/config/m68k/vxm68k.h b/gcc/config/m68k/vxm68k.h
new file mode 100755
index 0000000..063ded8
--- /dev/null
+++ b/gcc/config/m68k/vxm68k.h
@@ -0,0 +1,101 @@
+/* Definitions of target machine for GNU compiler. Vxworks m68k version.
+ Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* This comment is here to see if it will keep Sun's cpp from dying. */
+
+#include "m68k/m68k-none.h"
+#include "aoutos.h"
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dmc68000 -D__vxworks -D__vxworks_5 -Acpu(m68k) -Amachine(m68k)"
+
+/* The default value for -DCPU=. */
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68k || TARGET_CPU_DEFAULT == M68K_CPU_m68020
+#define CPP_SUBTARGET_CPU_DEFAULT_SPEC "-DCPU=MC68020"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68000
+#define CPP_SUBTARGET_CPU_DEFAULT_SPEC "-DCPU=MC68000"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68030
+#define CPP_SUBTARGET_CPU_DEFAULT_SPEC "-DCPU=MC68030"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68040
+#define CPP_SUBTARGET_CPU_DEFAULT_SPEC "-DCPU=MC68040"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68302
+#define CPP_SUBTARGET_CPU_DEFAULT_SPEC "-DCPU=MC68302"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68332
+#define CPP_SUBTARGET_CPU_DEFAULT_SPEC "-DCPU=MC68332"
+#else
+Unrecognized value in TARGET_CPU_DEFAULT.
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+{ "cpp_subtarget_cpu_default", CPP_SUBTARGET_CPU_DEFAULT_SPEC }
+
+/* Vxworks header files require that the macro CPU be set. */
+/* ??? The previous code didn't set CPU if -ansi. */
+#undef CPP_SUBTARGET_SPEC
+#define CPP_SUBTARGET_SPEC "\
+%{m68000:-DCPU=MC68000 }%{m68010:-DCPU=MC68010 }%{m68020:-DCPU=MC68020 }%{mc68020:-DCPU=MC68020 }%{m68030:-DCPU=MC68030 }%{m68040:-DCPU=MC68040 }%{m68020-40:-DCPU=MC68020 }%{m68302:-DCPU=MC68000 }%{m68332:-DCPU=CPU32 } \
+%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:%(cpp_subtarget_cpu_default) }}}}}}}}}} \
+"
+
+#define DBX_DEBUGGING_INFO
+#undef SDB_DEBUGGING_INFO
+
+/* These are the official values from WRS. */
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "char"
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 8
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "long int"
+#undef SIZE_TYPE
+#define SIZE_TYPE "unsigned int"
+
+/* VxWorks does all the library stuff itself. */
+
+#define LIB_SPEC ""
+
+/* Provide required defaults for linker -e. */
+
+#define LINK_SPEC "%{!nostdlib:%{!r*:%{!e*:-e start}}}"
+
+/* VxWorks provides the functionality of crt0.o and friends itself. */
+
+#define STARTFILE_SPEC ""
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* Allow folding division by zero. */
+#define REAL_INFINITY
+
+/* GCC is the primary compiler for VxWorks, so we don't need this. */
+#undef PCC_STATIC_STRUCT_RETURN
diff --git a/gcc/config/m68k/x-alloca-c b/gcc/config/m68k/x-alloca-c
new file mode 100755
index 0000000..3375d42
--- /dev/null
+++ b/gcc/config/m68k/x-alloca-c
@@ -0,0 +1 @@
+ALLOCA=alloca.o
diff --git a/gcc/config/m68k/x-amix b/gcc/config/m68k/x-amix
new file mode 100755
index 0000000..6ec4f63
--- /dev/null
+++ b/gcc/config/m68k/x-amix
@@ -0,0 +1,27 @@
+# Makefile configuration for Commodore Amiga running SVR4.
+# (configure amiga-amix)
+
+# The Amiga ships with gcc installed, so use it as the default CC.
+
+CC = /usr/public/bin/gcc
+
+# The AT&T compiler is still available in /usr/ccs/bin/cc and should
+# be used to compile the things that should not be compiled with gcc.
+
+OLDCC = /usr/ccs/bin/cc
+
+# Link the executables with -ansi to get ANSI floating point ranges.
+# Otherwise the values returned on overflow or underflow will be wrong.
+# NOTE: some early releases of Amiga Unix contained a bug in ptod.o
+# that prevents the correct values being returned from strtod/atof, even
+# when linked with -ansi. Sometimes -static will fix this since at least
+# one version had a fixed copy in the static libc.a.
+
+LDFLAGS = -ansi
+
+# The manual pages go in /usr/man/1l (section 1, local) without any filename
+# extension. The man command will automatically create the /usr/catman/1l
+# entry.
+
+mandir = /usr/man/1l
+manext =
diff --git a/gcc/config/m68k/x-apollo68 b/gcc/config/m68k/x-apollo68
new file mode 100755
index 0000000..4c809f9
--- /dev/null
+++ b/gcc/config/m68k/x-apollo68
@@ -0,0 +1,15 @@
+# x-apollo68 -- 680x0 based Apollos as host system
+
+# vasta@apollo.com says this is how to compile on an Apollo (SR10.x).
+# Use a Berkeley environment.
+CC=cc -g -A nansi -A cpu,3000 -A runtype,bsd4.3 -A systype,any -DSHORT_ENUM_BUG
+OLDCC=cc -g -A nansi -A cpu,3000 -A runtype,bsd4.3 -A systype,any -DSHORT_ENUM_BUG
+
+# This used to redefine CFLAGS and LIBGCC2_CFLAGS to eliminate the unsupported
+# -g flag from both macros. This gives an undebuggable stage1 compiler which
+# is bad, and it also does the wrong thing if we are cross compiling to a
+# target which does support debugging. There is currently no way to avoid
+# the -g option that doesn't break something else.
+
+# Apollo does not have B option.
+TAROUTOPTS=xpf
diff --git a/gcc/config/m68k/x-apollo68v b/gcc/config/m68k/x-apollo68v
new file mode 100755
index 0000000..ccb76c1
--- /dev/null
+++ b/gcc/config/m68k/x-apollo68v
@@ -0,0 +1,5 @@
+# vasta@apollo.com says this is how to compile on an Apollo (SR10.x).
+# Use a Berkeley environment.
+CC=cc -g -A nansi -A cpu,3000 -A runtype,any -A systype,any -DSHORT_ENUM_BUG -DUSG -U__STDC__
+OLDCC=cc -g -A nansi -A cpu,3000 -A runtype,bsd4.3 -A systype,any -DSHORT_ENUM_BUG -DUSG -U__STDC__
+
diff --git a/gcc/config/m68k/x-ccur b/gcc/config/m68k/x-ccur
new file mode 100755
index 0000000..0f94e9d
--- /dev/null
+++ b/gcc/config/m68k/x-ccur
@@ -0,0 +1,3 @@
+# Specify the jobs library when building in the ATT universe.
+CLIB = -ljobs
+X_CFLAGS = -O0 -DSHORT_ENUM_BUG -Dregister=
diff --git a/gcc/config/m68k/x-crds b/gcc/config/m68k/x-crds
new file mode 100755
index 0000000..172909c
--- /dev/null
+++ b/gcc/config/m68k/x-crds
@@ -0,0 +1,7 @@
+CC = cc -Wx,-X23
+
+# The following line might be necessary as well or instead of the above.
+# If you find out that it is necessary,
+# or if you find out that it is not necessary,
+# please inform bug-gcc@prep.ai.mit.edu.
+# ALLOCA = alloca.o
diff --git a/gcc/config/m68k/x-dpx2 b/gcc/config/m68k/x-dpx2
new file mode 100755
index 0000000..a4a8c1b
--- /dev/null
+++ b/gcc/config/m68k/x-dpx2
@@ -0,0 +1,16 @@
+# need this when using cc
+ALLOCA = alloca.o
+# avoid lossage assembling alloca.
+ALLOCA_FLAGS=-S
+ALLOCA_FINISH = $(AS) -o alloca.o alloca.s
+# be sure not to confuse ./as with /bin/as
+AS=`if [ x$(OLDCC) = x$(CC) ] ; then echo /bin/as; else echo $(GAS); fi`
+GAS = gas
+#
+# as of gcc-2.2.1 gcc -g produces too many .stabd's for /bin/ld
+# to link cc1plus, so use -g with /bin/cc, but -O with gcc
+CFLAGS=`if [ x$(OLDCC) = x$(CC) ] ; then echo -g; else echo -O; fi`
+#
+CLIB=-lmalloc -lld -lm
+# tell CC whether we are a 200 or 300
+X_CFLAGS=-D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BULL_SOURCE -D__DPX2__ `if [ -d /makesys/kernel/cf/ncl_mr ]; then echo -Dncl_mr=1; else echo -Dncl_el; fi`
diff --git a/gcc/config/m68k/x-hp2bsd b/gcc/config/m68k/x-hp2bsd
new file mode 100755
index 0000000..7dd651c
--- /dev/null
+++ b/gcc/config/m68k/x-hp2bsd
@@ -0,0 +1,4 @@
+# Make assignments for compilation for hp200 running 4.3bsd
+CC=gcc
+OLDCC=oldcc
+# You must have a previous version of gcc for bootstrapping
diff --git a/gcc/config/m68k/x-hp320 b/gcc/config/m68k/x-hp320
new file mode 100755
index 0000000..46f68e6
--- /dev/null
+++ b/gcc/config/m68k/x-hp320
@@ -0,0 +1,17 @@
+# Make assignments for compilation on HPUX with their C compiler.
+CC=cc -Wc,-Nw2000 -Wc,-Ns2000 -Wc,-Ne700 -Wc,-Np300
+OLDCC=cc -Wc,-Nw2000 -Wc,-Ns2000 -Wc,-Ne700 -Wc,-Np300
+ALLOCA=alloca.o
+# B option not supported on hpux.
+TAROUTOPTS = xpf
+
+# For CCLIBFLAGS you might want to specify the switch that
+# forces only 68000 instructions to be used.
+
+# Version 5 of HPUX had a compiler bug that made it crash with -g.
+# You must set CFLAGS to empty on version 5.
+
+# You must get alloca.c from GNU Emacs.
+
+# So putenv and other functions get seen by fixproto.
+FIXPROTO_DEFINES = -D_HPUX_SOURCE
diff --git a/gcc/config/m68k/x-hp320g b/gcc/config/m68k/x-hp320g
new file mode 100755
index 0000000..38f201e
--- /dev/null
+++ b/gcc/config/m68k/x-hp320g
@@ -0,0 +1,17 @@
+# Make assignments for compilation on HPUX with their C compiler.
+CC=cc -Wc,-Nw2000 -Wc,-Ns2000 -Wc,-Ne700 -Wc,-Np300
+OLDCC=cc -Wc,-Nw2000 -Wc,-Ns2000 -Wc,-Ne700 -Wc,-Np300
+ALLOCA=alloca.o
+# B option not supported on hpux.
+TAROUTOPTS = xpf
+
+# For CCLIBFLAGS you might want to specify the switch that
+# forces only 68000 instructions to be used.
+
+X_CFLAGS= -I../hp-include
+
+# Version 5 of HPUX had a compiler bug that made it crash with -g.
+# You must set CFLAGS to empty on version 5.
+
+# So putenv and other functions get seen by fixproto.
+FIXPROTO_DEFINES = -D_HPUX_SOURCE
diff --git a/gcc/config/m68k/x-hp3bsd44 b/gcc/config/m68k/x-hp3bsd44
new file mode 100755
index 0000000..b8dffd0
--- /dev/null
+++ b/gcc/config/m68k/x-hp3bsd44
@@ -0,0 +1 @@
+USER_H = $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS)
diff --git a/gcc/config/m68k/x-mot3300 b/gcc/config/m68k/x-mot3300
new file mode 100755
index 0000000..3d7e3c3
--- /dev/null
+++ b/gcc/config/m68k/x-mot3300
@@ -0,0 +1,15 @@
+ALLOCA=alloca.o
+
+# This disables the long/short jump optimization.
+# I use sysV68 R3V7.1 RM04 (phdm@info.ucl.ac.be)
+# Since ss-950318, with jump optimization enabled, "as" issues a warning
+# when assembling combine.s :
+# aline nnnnn : Warning: Table overflow: some optimizations lost (SDIs)
+# but later "ld" complains with
+# ld: relocation entry found for non-relocatable symbol in combine.o
+# and the produced "cc1" fails with SIGSEGV
+# Another possible fix would be to split combine.c.
+# Since ss-961013, the same happens for expr.c compiled by gcc, but not by cc;
+# and for cp/decl.c; aren't those files too big ?
+# With egcs-970910, this also happens for f/expr.o and f/stb.o
+XCFLAGS=`case $@ in combine.o|expr.o|decl.o|f/expr.o|f/stb.o) echo -Wa,-j;;esac`
diff --git a/gcc/config/m68k/x-mot3300-gas b/gcc/config/m68k/x-mot3300-gas
new file mode 100755
index 0000000..cf27977
--- /dev/null
+++ b/gcc/config/m68k/x-mot3300-gas
@@ -0,0 +1,12 @@
+ALLOCA=alloca.o
+
+# This disables the long/short jump optimization.
+# I use sysV68 R3V7.1 RM04 (phdm@info.ucl.ac.be)
+# Since ss-950318, with jump optimization enabled, "as" issues a warning
+# when assembling combine.s :
+# aline nnnnn : Warning: Table overflow: some optimizations lost (SDIs)
+# but later "ld" complains with
+# ld: relocation entry found for non-relocatable symbol in combine.o
+# and the produced "cc1" fails with SIGSEGV
+# Another possible fix would be to split combine.c.
+XCFLAGS=`if [ x$@ = xcombine.o -a "${CC}" = "${OLDCC}" ]; then echo -Wa,-j; fi`
diff --git a/gcc/config/m68k/x-next b/gcc/config/m68k/x-next
new file mode 100755
index 0000000..f1a9836
--- /dev/null
+++ b/gcc/config/m68k/x-next
@@ -0,0 +1,13 @@
+# Make assignments for compiling on NeXT with their compiler version.
+CC=cc -traditional-cpp
+OLDCC=CC -traditional-cpp
+
+# Specify other dirs of system header files to be fixed.
+OTHER_FIXINCLUDES_DIRS= /LocalDeveloper/Headers
+
+# <limits.h> is sometimes in /usr/include/ansi/limits.h.
+LIMITS_H_TEST = [ -f $(SYSTEM_HEADER_DIR)/limits.h -o -f $(SYSTEM_HEADER_DIR)/ansi/limits.h ]
+
+# f771 is so big, we need to tell linker on m68k-next-nextstep* to
+# make enough room for it.
+BOOT_LDFLAGS=-segaddr __DATA 6000000
diff --git a/gcc/config/m68k/x-sun3 b/gcc/config/m68k/x-sun3
new file mode 100755
index 0000000..b3ee2ce
--- /dev/null
+++ b/gcc/config/m68k/x-sun3
@@ -0,0 +1 @@
+INSTALL_FLOAT_H =
diff --git a/gcc/config/m68k/x-tower b/gcc/config/m68k/x-tower
new file mode 100755
index 0000000..995e72b
--- /dev/null
+++ b/gcc/config/m68k/x-tower
@@ -0,0 +1,9 @@
+# On the NCR Tower 32 running SVR3, says ra@intsys.no :
+# Do *not* enable optimization in CFLAGS when using the native cc, because:
+# a) The optimizer seems to loop when invoked with -O2.
+# b) The -O1 level does stack/frame pointer optimizations that make the
+# assembler alloca in libPW.a fail, and the C alloca eats *lots* of memory.
+# c) gcc will eventually be recompiled with itself, so all this doesn't matter.
+X_CFLAGS = -O0
+CCLIBFLAGS = -O2
+CLIB = -lmalloc -lPW
diff --git a/gcc/config/m68k/xm-3b1.h b/gcc/config/m68k/xm-3b1.h
new file mode 100755
index 0000000..035004f
--- /dev/null
+++ b/gcc/config/m68k/xm-3b1.h
@@ -0,0 +1,4 @@
+/* Override part of the obstack macros. */
+
+#define __PTR_TO_INT(P) ((int)(P))
+#define __INT_TO_PTR(P) ((char *)(P))
diff --git a/gcc/config/m68k/xm-altos3068.h b/gcc/config/m68k/xm-altos3068.h
new file mode 100755
index 0000000..f540924
--- /dev/null
+++ b/gcc/config/m68k/xm-altos3068.h
@@ -0,0 +1,3 @@
+#define USG
+
+#include "m68k/xm-m68k.h"
diff --git a/gcc/config/m68k/xm-amix.h b/gcc/config/m68k/xm-amix.h
new file mode 100755
index 0000000..c28ed78
--- /dev/null
+++ b/gcc/config/m68k/xm-amix.h
@@ -0,0 +1,45 @@
+/* Definitions of host machine for GNU compiler.
+ Commodore Amiga A3000UX version.
+ Copyright (C) 1991, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "m68k/xm-m68kv.h" /* Use the System V flavor of m68k host */
+
+#define rindex strrchr
+#define index strchr
+
+/* Define FULL_PROTOTYPES for protoize.c, to get <unistd.h> included.
+ We need this file for things like R_OK, not necessarily prototypes. */
+
+#define FULL_PROTOTYPES
+
+#if defined (__GNUC__) && __GNUC__ == 1
+#define alloca __builtin_alloca
+#endif
+
+#if 0 /* I don't want individual ports to be inconsistent about this.
+ I regard fancy_abort as a half-solution and not the right way
+ to do things. --rms. */
+/* The m88k and mips ports make use of fancy_abort to give possibly helpful
+ abort information rather than just dumping core. They do it in their
+ tm-* files. It seems more logical that this is a characteristic of
+ the host machine and not the target machine, so we do it here. */
+
+#define abort fancy_abort /* give possibly helpful abort info */
+#endif
diff --git a/gcc/config/m68k/xm-atari.h b/gcc/config/m68k/xm-atari.h
new file mode 100755
index 0000000..59f4664
--- /dev/null
+++ b/gcc/config/m68k/xm-atari.h
@@ -0,0 +1,5 @@
+/* Add HZ define if missing */
+
+#ifndef HZ
+#define HZ 100 /* System clock */
+#endif
diff --git a/gcc/config/m68k/xm-aux.h b/gcc/config/m68k/xm-aux.h
new file mode 100755
index 0000000..5ac1f46
--- /dev/null
+++ b/gcc/config/m68k/xm-aux.h
@@ -0,0 +1,9 @@
+#ifndef USG
+#define USG
+#endif
+
+#ifndef AUX
+#define AUX
+#endif
+
+#include "m68k/xm-m68k.h"
diff --git a/gcc/config/m68k/xm-crds.h b/gcc/config/m68k/xm-crds.h
new file mode 100755
index 0000000..2bf1bdb
--- /dev/null
+++ b/gcc/config/m68k/xm-crds.h
@@ -0,0 +1,7 @@
+/* Avoid conflict with C library by changing name of this symbol. */
+#define gettime gcc_gettime
+
+/* Override part of the obstack macros. */
+
+#define __PTR_TO_INT(P) ((int)(P))
+#define __INT_TO_PTR(P) ((char *)(P))
diff --git a/gcc/config/m68k/xm-hp320.h b/gcc/config/m68k/xm-hp320.h
new file mode 100755
index 0000000..f3009a6
--- /dev/null
+++ b/gcc/config/m68k/xm-hp320.h
@@ -0,0 +1,13 @@
+/* USG is needed to prevent trying to use getrusage and getwd. */
+#define USG
+
+#include "m68k/xm-m68k.h"
+
+/* If compiling with HPUX compiler, we are probably using alloca.c,
+ so help it work right. */
+#ifndef __GNUC__
+#define USE_C_ALLOCA
+#endif
+
+/* Don't try to use sys_siglist. */
+#define NO_SYS_SIGLIST
diff --git a/gcc/config/m68k/xm-linux.h b/gcc/config/m68k/xm-linux.h
new file mode 100755
index 0000000..bfac3ae
--- /dev/null
+++ b/gcc/config/m68k/xm-linux.h
@@ -0,0 +1,4 @@
+/* Configuration for GCC for Motorola m68k running Linux-based GNU systems. */
+
+#include <m68k/xm-m68k.h>
+#include <xm-linux.h>
diff --git a/gcc/config/m68k/xm-lynx.h b/gcc/config/m68k/xm-lynx.h
new file mode 100755
index 0000000..78762b3
--- /dev/null
+++ b/gcc/config/m68k/xm-lynx.h
@@ -0,0 +1,35 @@
+/* Configuration for GNU C-compiler for all platforms running LynxOS.
+ Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include <xm-lynx.h>
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+#define HOST_BITS_PER_LONGLONG 64
+
+#define HOST_WORDS_BIG_ENDIAN 1
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+
+#include "tm.h"
diff --git a/gcc/config/m68k/xm-m68k.h b/gcc/config/m68k/xm-m68k.h
new file mode 100755
index 0000000..757c9af
--- /dev/null
+++ b/gcc/config/m68k/xm-m68k.h
@@ -0,0 +1,41 @@
+/* Configuration for GNU C-compiler for Motorola 68000 family.
+ Copyright (C) 1987, 1993 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+/* #defines that need visibility everywhere. */
+#define FALSE 0
+#define TRUE 1
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+#define HOST_BITS_PER_LONGLONG 64
+
+#define HOST_WORDS_BIG_ENDIAN
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+#include "tm.h"
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
diff --git a/gcc/config/m68k/xm-m68kv.h b/gcc/config/m68k/xm-m68kv.h
new file mode 100755
index 0000000..d0931f0
--- /dev/null
+++ b/gcc/config/m68k/xm-m68kv.h
@@ -0,0 +1,9 @@
+/* Host environment for 68000's running System V. */
+
+#include "m68k/xm-m68k.h"
+
+#define USG
+
+#ifndef __GNUC__
+#define USE_C_ALLOCA
+#endif
diff --git a/gcc/config/m68k/xm-mot3300.h b/gcc/config/m68k/xm-mot3300.h
new file mode 100755
index 0000000..ea3b558
--- /dev/null
+++ b/gcc/config/m68k/xm-mot3300.h
@@ -0,0 +1,41 @@
+/* Configuration for GNU C-compiler for Motorola 68000 family.
+ SysV68 Motorola 3300 Delta Series
+ Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+#define USG 1
+
+/* do not use alloca from -lPW with cc, because function epilogues use %sp */
+#ifndef __GNUC__
+#ifdef __STDC__
+extern void *alloca ();
+#else
+extern char *alloca ();
+#endif
+#endif
+
+/* Override part of the obstack macros. */
+
+#define __PTR_TO_INT(P) ((int)(P))
+#define __INT_TO_PTR(P) ((char *)(P))
+
+/* We need POSIX/XOPEN symbols; otherwise make check will fail. */
+#define ADD_MISSING_POSIX 1
+#define ADD_MISSING_XOPEN 1
diff --git a/gcc/config/m68k/xm-netbsd.h b/gcc/config/m68k/xm-netbsd.h
new file mode 100755
index 0000000..27a33cd
--- /dev/null
+++ b/gcc/config/m68k/xm-netbsd.h
@@ -0,0 +1,4 @@
+/* Configuration for GCC for Motorola 68k running NetBSD as host. */
+
+#include <m68k/xm-m68k.h>
+#include <xm-netbsd.h>
diff --git a/gcc/config/m68k/xm-next.h b/gcc/config/m68k/xm-next.h
new file mode 100755
index 0000000..e0b53f2
--- /dev/null
+++ b/gcc/config/m68k/xm-next.h
@@ -0,0 +1,3 @@
+/* malloc does better with chunks the size of a page. */
+
+#define OBSTACK_CHUNK_SIZE (getpagesize ())
diff --git a/gcc/config/m68k/xm-plexus.h b/gcc/config/m68k/xm-plexus.h
new file mode 100755
index 0000000..8498198
--- /dev/null
+++ b/gcc/config/m68k/xm-plexus.h
@@ -0,0 +1,6 @@
+/* Host environment for 68000's running System V. */
+
+#ifndef _SIZE_T_
+typedef int size_t;
+#define _SIZE_T_
+#endif
diff --git a/gcc/config/m68k/xm-sun3.h b/gcc/config/m68k/xm-sun3.h
new file mode 100755
index 0000000..eafe716
--- /dev/null
+++ b/gcc/config/m68k/xm-sun3.h
@@ -0,0 +1,5 @@
+/* Configuration for GCC for Motorola m68k on sun3. */
+
+#define HAVE_POPEN
+
+#include "m68k/xm-m68k.h"
diff --git a/gcc/config/m68k/xm-tower.h b/gcc/config/m68k/xm-tower.h
new file mode 100755
index 0000000..fcb456f
--- /dev/null
+++ b/gcc/config/m68k/xm-tower.h
@@ -0,0 +1,4 @@
+#include "m68k/xm-m68k.h"
+#include "xm-svr3.h"
+
+#define HAVE_VPRINTF